Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a debug draw mode for displaying UV2 (lightmap) texel density #96814

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1809,6 +1809,14 @@
Sets the lightmap GI instance to use for the specified 3D geometry instance. The lightmap UV scale for the specified instance (equivalent to [member GeometryInstance3D.gi_lightmap_scale]) and lightmap atlas slice must also be specified.
</description>
</method>
<method name="instance_geometry_set_lightmap_scale">
<return type="void" />
<param index="0" name="instance" type="RID" />
<param index="1" name="lightmap_scale" type="float" />
<description>
Sets the lightmap scale for the given geometry instance.
</description>
</method>
<method name="instance_geometry_set_lod_bias">
<return type="void" />
<param index="0" name="instance" type="RID" />
Expand Down Expand Up @@ -2373,6 +2381,14 @@
Sets a mesh's custom aabb.
</description>
</method>
<method name="mesh_set_lightmap_size_hint">
<return type="void" />
<param index="0" name="mesh" type="RID" />
<param index="1" name="size" type="Vector2" />
<description>
Sets a mesh's lightmap size hint.
</description>
</method>
<method name="mesh_set_shadow_mesh">
<return type="void" />
<param index="0" name="mesh" type="RID" />
Expand Down Expand Up @@ -5003,24 +5019,27 @@
<constant name="VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION" value="8" enum="ViewportDebugDraw">
Objects are displayed with only the emission color from [VoxelGI]s.
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS" value="9" enum="ViewportDebugDraw">
<constant name="VIEWPORT_DEBUG_DRAW_UV2_TEXEL_DENSITY" value="9" enum="ViewportDebugDraw">
Objects are displayed with a checkerboard pattern indicative of their UV2 texel density. Each square of the checkerboard pattern is 10 texels by 10 texels in size.
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS" value="10" enum="ViewportDebugDraw">
Draws the shadow atlas that stores shadows from [OmniLight3D]s and [SpotLight3D]s in the upper left quadrant of the [Viewport].
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS" value="10" enum="ViewportDebugDraw">
<constant name="VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS" value="11" enum="ViewportDebugDraw">
Draws the shadow atlas that stores shadows from [DirectionalLight3D]s in the upper left quadrant of the [Viewport].
The slice of the camera frustum related to the shadow map cascade is superimposed to visualize coverage. The color of each slice matches the colors used for [constant VIEWPORT_DEBUG_DRAW_PSSM_SPLITS]. When shadow cascades are blended the overlap is taken into account when drawing the frustum slices.
The last cascade shows all frustum slices to illustrate the coverage of all slices.
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE" value="11" enum="ViewportDebugDraw">
Draws the estimated scene luminance. This is a 1×1 texture that is generated when autoexposure is enabled to control the scene's exposure.
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_SSAO" value="12" enum="ViewportDebugDraw">
<constant name="VIEWPORT_DEBUG_DRAW_SSAO" value="13" enum="ViewportDebugDraw">
Draws the screen space ambient occlusion texture instead of the scene so that you can clearly see how it is affecting objects. In order for this display mode to work, you must have [member Environment.ssao_enabled] set in your [WorldEnvironment].
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_SSIL" value="13" enum="ViewportDebugDraw">
<constant name="VIEWPORT_DEBUG_DRAW_SSIL" value="14" enum="ViewportDebugDraw">
Draws the screen space indirect lighting texture instead of the scene so that you can clearly see how it is affecting objects. In order for this display mode to work, you must have [member Environment.ssil_enabled] set in your [WorldEnvironment].
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_PSSM_SPLITS" value="14" enum="ViewportDebugDraw">
<constant name="VIEWPORT_DEBUG_DRAW_PSSM_SPLITS" value="15" enum="ViewportDebugDraw">
Colors each PSSM split for the [DirectionalLight3D]s in the scene a different color so you can see where the splits are. In order they will be colored red, green, blue, yellow.
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_DECAL_ATLAS" value="15" enum="ViewportDebugDraw">
Expand Down
15 changes: 9 additions & 6 deletions doc/classes/Viewport.xml
Original file line number Diff line number Diff line change
Expand Up @@ -551,25 +551,28 @@
<constant name="DEBUG_DRAW_VOXEL_GI_EMISSION" value="8" enum="DebugDraw">
Objects are displayed with only the emission color from [VoxelGI]s.
</constant>
<constant name="DEBUG_DRAW_SHADOW_ATLAS" value="9" enum="DebugDraw">
<constant name="DEBUG_DRAW_UV2_TEXEL_DENSITY" value="9" enum="DebugDraw">
Objects are displayed with a checkerboard pattern indicative of their UV2 texel density. Each square of the checkerboard pattern is 10 texels by 10 texels in size.
</constant>
<constant name="DEBUG_DRAW_SHADOW_ATLAS" value="10" enum="DebugDraw">
Draws the shadow atlas that stores shadows from [OmniLight3D]s and [SpotLight3D]s in the upper left quadrant of the [Viewport].
</constant>
<constant name="DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS" value="10" enum="DebugDraw">
<constant name="DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS" value="11" enum="DebugDraw">
Draws the shadow atlas that stores shadows from [DirectionalLight3D]s in the upper left quadrant of the [Viewport].
</constant>
<constant name="DEBUG_DRAW_SCENE_LUMINANCE" value="11" enum="DebugDraw">
Draws the scene luminance buffer (if available) in the upper left quadrant of the [Viewport].
</constant>
<constant name="DEBUG_DRAW_SSAO" value="12" enum="DebugDraw">
<constant name="DEBUG_DRAW_SSAO" value="13" enum="DebugDraw">
Draws the screen-space ambient occlusion texture instead of the scene so that you can clearly see how it is affecting objects. In order for this display mode to work, you must have [member Environment.ssao_enabled] set in your [WorldEnvironment].
</constant>
<constant name="DEBUG_DRAW_SSIL" value="13" enum="DebugDraw">
<constant name="DEBUG_DRAW_SSIL" value="14" enum="DebugDraw">
Draws the screen-space indirect lighting texture instead of the scene so that you can clearly see how it is affecting objects. In order for this display mode to work, you must have [member Environment.ssil_enabled] set in your [WorldEnvironment].
</constant>
<constant name="DEBUG_DRAW_PSSM_SPLITS" value="14" enum="DebugDraw">
<constant name="DEBUG_DRAW_PSSM_SPLITS" value="15" enum="DebugDraw">
Colors each PSSM split for the [DirectionalLight3D]s in the scene a different color so you can see where the splits are. In order, they will be colored red, green, blue, and yellow.
</constant>
<constant name="DEBUG_DRAW_DECAL_ATLAS" value="15" enum="DebugDraw">
<constant name="DEBUG_DRAW_DECAL_ATLAS" value="16" enum="DebugDraw">
Draws the decal atlas used by [Decal]s and light projector textures in the upper left quadrant of the [Viewport].
</constant>
<constant name="DEBUG_DRAW_SDFGI" value="16" enum="DebugDraw">
Expand Down
79 changes: 79 additions & 0 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,33 @@
}
}
}

#ifdef DEBUG_ENABLED
if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UV2_TEXEL_DENSITY)) {
if (inst->data->base_type == RS::INSTANCE_MESH && inst->data->use_baked_light && inst->lightmap_instance.is_valid()) {
GLES3::LightStorage *light_storage = GLES3::LightStorage::get_singleton();

Check failure on line 1364 in drivers/gles3/rasterizer_scene_gles3.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor w/ Mono (target=editor)

declaration of 'light_storage' shadows a previous local [-Werror=shadow]

Check failure on line 1364 in drivers/gles3/rasterizer_scene_gles3.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with doubles and GCC sanitizers (target=editor, tests=yes, dev_build=yes, scu_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=gold)

declaration of 'light_storage' shadows a previous local [-Werror=shadow]

Check failure on line 1364 in drivers/gles3/rasterizer_scene_gles3.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Editor (target=editor, tests=yes)

the following warning is treated as an error

Check warning on line 1364 in drivers/gles3/rasterizer_scene_gles3.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Editor (target=editor, tests=yes)

declaration of 'light_storage' hides previous local declaration

RID lightmap = light_storage->lightmap_instance_get_lightmap(inst->lightmap_instance);
Vector2i lightmap_atlas_size = light_storage->lightmap_get_light_texture_size(lightmap);

Size2 lightmap_size = inst->lightmap_uv_scale.size * Size2(lightmap_atlas_size);

if (inst->data->lightmap_size_global_uniform_pos == -2) {
// Not allocated, try to allocate.
inst->data->lightmap_size_global_uniform_pos = RSG::material_storage->global_shader_parameters_unit_variable_allocate();
}

if (inst->data->lightmap_size_global_uniform_pos >= 0) {
RSG::material_storage->global_shader_parameters_unit_variable_update(inst->data->lightmap_size_global_uniform_pos, lightmap_size);
}
}
} else if (unlikely(inst->data->lightmap_size_global_uniform_pos != -2)) {
if (inst->data->lightmap_size_global_uniform_pos >= 0) {
RSG::material_storage->global_shader_parameters_unit_variable_free(inst->data->lightmap_size_global_uniform_pos);
}
inst->data->lightmap_size_global_uniform_pos = -2;
}
#endif
}

inst->flags_cache = flags;
Expand Down Expand Up @@ -2959,6 +2986,9 @@
} else if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING)) {
material_data = default_material_data_ptr;
shader = material_data->shader_data;
} else if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UV2_TEXEL_DENSITY)) {
material_data = uv2_texel_density_material_data_ptr;
shader = material_data->shader_data;
} else {
shader = surf->shader;
material_data = surf->material;
Expand Down Expand Up @@ -3453,6 +3483,13 @@
}

material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::MODEL_FLAGS, inst->flags_cache, shader->version, instance_variant, spec_constants);
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::INSTANCE_OFFSET, uint32_t(inst->shader_uniforms_offset), shader->version, instance_variant, spec_constants);

#ifdef DEBUG_ENABLED
if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UV2_TEXEL_DENSITY && inst->data->use_baked_light && inst->data->lightmap_size_global_uniform_pos >= 0)) {
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::INSTANCE_OFFSET, uint32_t(inst->data->lightmap_size_global_uniform_pos), shader->version, instance_variant, spec_constants);
}
#endif

if (p_pass_mode == PASS_MODE_MATERIAL) {
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::UV_OFFSET, p_params->uv_offset, shader->version, instance_variant, spec_constants);
Expand Down Expand Up @@ -4187,6 +4224,43 @@
overdraw_material_data_ptr = static_cast<GLES3::SceneMaterialData *>(GLES3::MaterialStorage::get_singleton()->material_get_data(scene_globals.overdraw_material, RS::SHADER_SPATIAL));
}

{
// UV2 debug shader.
scene_globals.uv2_texel_density_material_shader = material_storage->shader_allocate();
material_storage->shader_initialize(scene_globals.uv2_texel_density_material_shader);
material_storage->shader_set_code(scene_globals.uv2_texel_density_material_shader, R"(
// 3D editor UV2 texel density debug draw mode shader (clustered).

shader_type spatial;

instance uniform vec2 lightmap_size : instance_index(0);

void fragment() {
vec2 lightmap_pos = UV2 * lightmap_size;

vec2 ddx = dFdx(UV2);
vec2 ddy = dFdy(UV2);

vec2 w = max(abs(ddx), abs(ddy)) + 0.01;

vec2 s = 2.0 * (abs(fract((lightmap_pos - 0.5 * w) / 2.0) - 0.5) - abs(fract((lightmap_pos + 0.5 * w) / 2.0) - 0.5)) / w;

// Do a larger scale checkerboard as well.
lightmap_pos /= 10.0;
vec2 s2 = 2.0 * (abs(fract((lightmap_pos - 0.5 * w) / 2.0) - 0.5) - abs(fract((lightmap_pos + 0.5 * w) / 2.0) - 0.5)) / w;

float checkerboard_pattern = mix(0.85, 1.15, 0.5 - 0.5 * s2.x * s2.y);
checkerboard_pattern = checkerboard_pattern - mix(0.25, 0.5, 0.5 - 0.5 * s.x * s.y * sign(s2.x * s2.y)) ;

ALBEDO *= checkerboard_pattern;
}
)");
scene_globals.uv2_texel_density_material = material_storage->material_allocate();
material_storage->material_initialize(scene_globals.uv2_texel_density_material);
material_storage->material_set_shader(scene_globals.uv2_texel_density_material, scene_globals.uv2_texel_density_material_shader);
uv2_texel_density_material_data_ptr = static_cast<GLES3::SceneMaterialData *>(GLES3::MaterialStorage::get_singleton()->material_get_data(scene_globals.uv2_texel_density_material, RS::SHADER_SPATIAL));
}

{
// Initialize Sky stuff
sky_globals.roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers");
Expand Down Expand Up @@ -4294,6 +4368,11 @@
RSG::material_storage->material_free(scene_globals.overdraw_material);
RSG::material_storage->shader_free(scene_globals.overdraw_shader);

// UV2 Debug Shader.
// Overdraw Shader
RSG::material_storage->material_free(scene_globals.uv2_texel_density_material);
RSG::material_storage->shader_free(scene_globals.uv2_texel_density_material_shader);

// Sky Shader
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_free(sky_globals.shader_default_version);
RSG::material_storage->material_free(sky_globals.default_material);
Expand Down
3 changes: 3 additions & 0 deletions drivers/gles3/rasterizer_scene_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,13 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
RID default_shader;
RID overdraw_material;
RID overdraw_shader;
RID uv2_texel_density_material_shader;
RID uv2_texel_density_material;
} scene_globals;

GLES3::SceneMaterialData *default_material_data_ptr = nullptr;
GLES3::SceneMaterialData *overdraw_material_data_ptr = nullptr;
GLES3::SceneMaterialData *uv2_texel_density_material_data_ptr = nullptr;

/* LIGHT INSTANCE */

Expand Down
2 changes: 2 additions & 0 deletions drivers/gles3/shaders/scene.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ uniform highp mat4 world_transform;
uniform highp vec3 compressed_aabb_position;
uniform highp vec3 compressed_aabb_size;
uniform highp vec4 uv_scale;
uniform highp uint instance_offset;

uniform highp uint model_flags;

Expand Down Expand Up @@ -965,6 +966,7 @@ ivec2 multiview_uv(ivec2 uv) {
uniform highp mat4 world_transform;
uniform mediump float opaque_prepass_threshold;
uniform highp uint model_flags;
uniform highp uint instance_offset;

#if defined(RENDER_MATERIAL)
layout(location = 0) out vec4 albedo_output_buffer;
Expand Down
10 changes: 10 additions & 0 deletions drivers/gles3/storage/light_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,11 @@ class LightStorage : public RendererLightStorage {
virtual void lightmap_set_probe_capture_update_speed(float p_speed) override;
virtual float lightmap_get_probe_capture_update_speed() const override;

_FORCE_INLINE_ Vector2i lightmap_get_light_texture_size(RID p_lightmap) const {
const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
return lm->light_texture_size;
}

/* LIGHTMAP INSTANCE */

LightmapInstance *get_lightmap_instance(RID p_rid) { return lightmap_instance_owner.get_or_null(p_rid); };
Expand All @@ -743,6 +748,11 @@ class LightStorage : public RendererLightStorage {
virtual void lightmap_instance_free(RID p_lightmap) override;
virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override;

_FORCE_INLINE_ RID lightmap_instance_get_lightmap(RID p_lightmap_instance) {
LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap_instance);
return li->lightmap;
}

/* SHADOW ATLAS API */
bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); };

Expand Down
52 changes: 52 additions & 0 deletions drivers/gles3/storage/material_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1371,6 +1371,7 @@ MaterialStorage::MaterialStorage() {

actions.check_multiview_samplers = RasterizerGLES3::get_singleton()->is_xr_enabled();
actions.global_buffer_array_variable = "global_shader_uniforms";
actions.instance_uniform_index_variable = "instance_offset";

shaders.compiler_scene.initialize(actions);
}
Expand Down Expand Up @@ -1993,6 +1994,57 @@ GLuint MaterialStorage::global_shader_parameters_get_uniform_buffer() const {
return global_shader_uniforms.buffer;
}

//An alternative way of allocating global shader uniforms.
//Allocates a single variable and returns its position in the global shader uniform buffer.
//Intended to be used for debug drawing purposes and should not be used for anything substantial.
int32_t MaterialStorage::global_shader_parameters_unit_variable_allocate() {
int32_t pos = _global_shader_uniform_allocate(1);
ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
global_shader_uniforms.buffer_usage[pos].elements = 1;
return pos;
}

void MaterialStorage::global_shader_parameters_unit_variable_free(int32_t p_pos) {
ERR_FAIL_COND(p_pos < 0);
global_shader_uniforms.buffer_usage[p_pos].elements = 0;
}

void MaterialStorage::global_shader_parameters_unit_variable_update(int32_t p_pos, const Variant &p_value) {
ERR_FAIL_COND(p_pos < 0);
ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type."); //anything greater not supported

const ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = {
ShaderLanguage::TYPE_MAX, //nil
ShaderLanguage::TYPE_BOOL, //bool
ShaderLanguage::TYPE_INT, //int
ShaderLanguage::TYPE_FLOAT, //float
ShaderLanguage::TYPE_MAX, //string
ShaderLanguage::TYPE_VEC2, //vec2
ShaderLanguage::TYPE_IVEC2, //vec2i
ShaderLanguage::TYPE_VEC4, //rect2
ShaderLanguage::TYPE_IVEC4, //rect2i
ShaderLanguage::TYPE_VEC3, // vec3
ShaderLanguage::TYPE_IVEC3, //vec3i
ShaderLanguage::TYPE_MAX, //xform2d not supported here
ShaderLanguage::TYPE_VEC4, //vec4
ShaderLanguage::TYPE_IVEC4, //vec4i
ShaderLanguage::TYPE_VEC4, //plane
ShaderLanguage::TYPE_VEC4, //quat
ShaderLanguage::TYPE_MAX, //aabb not supported here
ShaderLanguage::TYPE_MAX, //basis not supported here
ShaderLanguage::TYPE_MAX, //xform not supported here
ShaderLanguage::TYPE_MAX, //projection not supported here
ShaderLanguage::TYPE_VEC4 //color
};

ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()];

ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type.");

_fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_shader_uniforms.buffer_values[p_pos]);
_global_shader_uniform_mark_buffer_dirty(p_pos, 1);
}

int32_t MaterialStorage::global_shader_parameters_instance_allocate(RID p_instance) {
ERR_FAIL_COND_V(global_shader_uniforms.instance_buffer_pos.has(p_instance), -1);
int32_t pos = _global_shader_uniform_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
Expand Down
4 changes: 4 additions & 0 deletions drivers/gles3/storage/material_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,10 @@ class MaterialStorage : public RendererMaterialStorage {
virtual void global_shader_parameters_load_settings(bool p_load_textures = true) override;
virtual void global_shader_parameters_clear() override;

virtual int32_t global_shader_parameters_unit_variable_allocate() override;
virtual void global_shader_parameters_unit_variable_free(int32_t p_pos) override;
virtual void global_shader_parameters_unit_variable_update(int32_t p_pos, const Variant &p_value) override;

virtual int32_t global_shader_parameters_instance_allocate(RID p_instance) override;
virtual void global_shader_parameters_instance_free(RID p_instance) override;
virtual void global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value, int p_flags_count = 0) override;
Expand Down
1 change: 1 addition & 0 deletions drivers/gles3/storage/mesh_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ class MeshStorage : public RendererMeshStorage {
virtual String mesh_get_path(RID p_mesh) const override;

virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override;

virtual void mesh_clear(RID p_mesh) override;

_FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) {
Expand Down
Loading
Loading