Merge pull request #114907 from clayjohn/RD-env-filter

Fix downsampled radiance map generation
This commit is contained in:
Rémi Verschelde
2026-01-13 22:20:55 +01:00
4 changed files with 26 additions and 52 deletions

View File

@@ -166,27 +166,15 @@ CopyEffects::CopyEffects(BitField<RasterEffects> p_raster_effects) {
{
// Initialize octmap downsampler.
Vector<String> downsampler_modes;
if (raster_effects.has_flag(RASTER_EFFECT_OCTMAP)) {
for (int i = 0; i < DOWNSAMPLER_MODE_RASTER_MAX; i++) {
String mode;
if (i & DOWNSAMPLER_MODE_FLAG_HIGH_QUALITY) {
mode += "\n#define USE_HIGH_QUALITY\n";
}
downsampler_modes.push_back(mode);
}
octmap_downsampler.raster_shader.initialize(downsampler_modes);
if (raster_effects.has_flag(RASTER_EFFECT_OCTMAP)) {
octmap_downsampler.raster_shader.initialize({ "" });
octmap_downsampler.shader_version = octmap_downsampler.raster_shader.version_create();
for (int i = 0; i < DOWNSAMPLER_MODE_RASTER_MAX; i++) {
octmap_downsampler.raster_pipelines[i].setup(octmap_downsampler.raster_shader.version_get_shader(octmap_downsampler.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
}
octmap_downsampler.raster_pipeline.setup(octmap_downsampler.raster_shader.version_get_shader(octmap_downsampler.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
} else {
Vector<String> downsampler_modes;
for (int i = 0; i < DOWNSAMPLER_MODE_COMPUTE_MAX; i++) {
String mode;
if (i & DOWNSAMPLER_MODE_FLAG_HIGH_QUALITY) {
mode += "\n#define USE_HIGH_QUALITY\n";
}
if (i & DOWNSAMPLER_MODE_FLAG_RGB10_A2) {
mode += "\n#define OCTMAP_FORMAT rgb10_a2\n";
} else {
@@ -1152,7 +1140,7 @@ void CopyEffects::copy_cubemap_to_octmap(RID p_source_rd_texture, RID p_dst_fram
RD::get_singleton()->draw_list_end();
}
void CopyEffects::octmap_downsample(RID p_source_octmap, RID p_dest_octmap, const Size2i &p_size, bool p_use_filter_quality, float p_border_size) {
void CopyEffects::octmap_downsample(RID p_source_octmap, RID p_dest_octmap, const Size2i &p_size, float p_border_size) {
ERR_FAIL_COND_MSG(raster_effects.has_flag(RASTER_EFFECT_OCTMAP), "Can't use compute based octmap downsample.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -1170,9 +1158,6 @@ void CopyEffects::octmap_downsample(RID p_source_octmap, RID p_dest_octmap, cons
RD::Uniform u_dest_octmap(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_dest_octmap }));
int mode = 0;
if (!p_use_filter_quality || filter.use_high_quality) {
mode |= DOWNSAMPLER_MODE_FLAG_HIGH_QUALITY;
}
RD::TextureFormat texture_format = RD::get_singleton()->texture_get_format(p_dest_octmap);
switch (texture_format.format) {
@@ -1205,7 +1190,7 @@ void CopyEffects::octmap_downsample(RID p_source_octmap, RID p_dest_octmap, cons
RD::get_singleton()->compute_list_end();
}
void CopyEffects::octmap_downsample_raster(RID p_source_octmap, RID p_dest_framebuffer, const Size2i &p_size, bool p_use_filter_quality, float p_border_size) {
void CopyEffects::octmap_downsample_raster(RID p_source_octmap, RID p_dest_framebuffer, const Size2i &p_size, float p_border_size) {
ERR_FAIL_COND_MSG(!raster_effects.has_flag(RASTER_EFFECT_OCTMAP), "Can't use raster based octmap downsample.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -1221,16 +1206,11 @@ void CopyEffects::octmap_downsample_raster(RID p_source_octmap, RID p_dest_frame
RD::Uniform u_source_cubemap(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_octmap }));
int mode = 0;
if (!p_use_filter_quality || filter.use_high_quality) {
mode |= DOWNSAMPLER_MODE_FLAG_HIGH_QUALITY;
}
RID shader = octmap_downsampler.raster_shader.version_get_shader(octmap_downsampler.shader_version, mode);
RID shader = octmap_downsampler.raster_shader.version_get_shader(octmap_downsampler.shader_version, 0);
ERR_FAIL_COND(shader.is_null());
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::DRAW_IGNORE_COLOR_ALL);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, octmap_downsampler.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, octmap_downsampler.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
RD::get_singleton()->draw_list_set_push_constant(draw_list, &octmap_downsampler.push_constant, sizeof(OctmapDownsamplerPushConstant));

View File

@@ -256,11 +256,10 @@ private:
};
enum OctmapDownsamplerMode {
DOWNSAMPLER_MODE_FLAG_HIGH_QUALITY = (1 << 0),
DOWNSAMPLER_MODE_FLAG_RGB10_A2 = (1 << 1),
DOWNSAMPLER_MODE_FLAG_RGB10_A2 = (1 << 0),
DOWNSAMPLER_MODE_COMPUTE_MAX = ((DOWNSAMPLER_MODE_FLAG_HIGH_QUALITY | DOWNSAMPLER_MODE_FLAG_RGB10_A2) + 1),
DOWNSAMPLER_MODE_RASTER_MAX = (DOWNSAMPLER_MODE_FLAG_HIGH_QUALITY + 1),
DOWNSAMPLER_MODE_COMPUTE_MAX = (DOWNSAMPLER_MODE_FLAG_RGB10_A2 + 1),
DOWNSAMPLER_MODE_RASTER_MAX = 1,
};
struct OctmapDownsampler {
@@ -269,7 +268,7 @@ private:
OctmapDownsamplerRasterShaderRD raster_shader;
RID shader_version;
PipelineDeferredRD compute_pipelines[DOWNSAMPLER_MODE_COMPUTE_MAX];
PipelineCacheRD raster_pipelines[DOWNSAMPLER_MODE_RASTER_MAX];
PipelineCacheRD raster_pipeline;
} octmap_downsampler;
enum OctmapFilterMode {
@@ -393,8 +392,8 @@ public:
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip);
void copy_cubemap_to_octmap(RID p_source_rd_texture, RID p_dst_framebuffer, float p_border_size);
void octmap_downsample(RID p_source_octmap, RID p_dest_octmap, const Size2i &p_size, bool p_use_filter_quality, float p_border_size);
void octmap_downsample_raster(RID p_source_octmap, RID p_dest_framebuffer, const Size2i &p_size, bool p_use_filter_quality, float p_border_size);
void octmap_downsample(RID p_source_octmap, RID p_dest_octmap, const Size2i &p_size, float p_border_size);
void octmap_downsample_raster(RID p_source_octmap, RID p_dest_framebuffer, const Size2i &p_size, float p_border_size);
void octmap_filter(RID p_source_octmap, const Vector<RID> &p_dest_octmap, bool p_use_array, float p_border_size);
void octmap_filter_raster(RID p_source_octmap, RID p_dest_framebuffer, uint32_t p_mip_level, float p_border_size);
void octmap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_sample_count, float p_roughness, uint32_t p_source_size, uint32_t p_dest_size, float p_border_size);

View File

@@ -340,7 +340,7 @@ void SkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bo
tf.format = p_texture_format;
tf.width = p_low_quality ? 160 : p_size >> 1; // Always 160x160 when using REALTIME.
tf.height = p_low_quality ? 160 : p_size >> 1;
tf.mipmaps = p_low_quality ? 7 : mipmaps - 1;
tf.mipmaps = p_low_quality ? 5 : mipmaps - 1;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
if (!use_raster_effect) {
tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT;
@@ -378,10 +378,10 @@ void SkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) {
if (use_raster_effect) {
RD::get_singleton()->draw_command_begin_label("Downsample Radiance Map");
copy_effects->octmap_downsample_raster(radiance_base_octmap, downsampled_layer.mipmaps[0].framebuffer, downsampled_layer.mipmaps[0].size, true, uv_border_size);
copy_effects->octmap_downsample_raster(radiance_base_octmap, downsampled_layer.mipmaps[0].framebuffer, downsampled_layer.mipmaps[0].size, uv_border_size);
for (uint32_t i = 1; i < downsampled_layer.mipmaps.size(); i++) {
copy_effects->octmap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffer, downsampled_layer.mipmaps[i].size, true, uv_border_size);
copy_effects->octmap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffer, downsampled_layer.mipmaps[i].size, uv_border_size);
}
RD::get_singleton()->draw_command_end_label(); // Downsample Radiance
@@ -399,10 +399,10 @@ void SkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) {
RD::get_singleton()->draw_command_end_label(); // Filter radiance
} else {
RD::get_singleton()->draw_command_begin_label("Downsample Radiance Map");
copy_effects->octmap_downsample(radiance_base_octmap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size, true, uv_border_size);
copy_effects->octmap_downsample(radiance_base_octmap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size, uv_border_size);
for (uint32_t i = 1; i < downsampled_layer.mipmaps.size(); i++) {
copy_effects->octmap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size, true, uv_border_size);
copy_effects->octmap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size, uv_border_size);
}
RD::get_singleton()->draw_command_end_label(); // Downsample Radiance
Vector<RID> views;
@@ -429,10 +429,10 @@ void SkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_array
if (use_raster_effect) {
if (p_base_layer == 1) {
RD::get_singleton()->draw_command_begin_label("Downsample Radiance Map");
copy_effects->octmap_downsample_raster(radiance_base_octmap, downsampled_layer.mipmaps[0].framebuffer, downsampled_layer.mipmaps[0].size, false, uv_border_size);
copy_effects->octmap_downsample_raster(radiance_base_octmap, downsampled_layer.mipmaps[0].framebuffer, downsampled_layer.mipmaps[0].size, uv_border_size);
for (uint32_t i = 1; i < downsampled_layer.mipmaps.size(); i++) {
copy_effects->octmap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffer, downsampled_layer.mipmaps[i].size, false, uv_border_size);
copy_effects->octmap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffer, downsampled_layer.mipmaps[i].size, uv_border_size);
}
RD::get_singleton()->draw_command_end_label(); // Downsample Radiance
}
@@ -460,10 +460,10 @@ void SkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_array
} else {
if (p_base_layer == 1) {
RD::get_singleton()->draw_command_begin_label("Downsample Radiance Map");
copy_effects->octmap_downsample(radiance_base_octmap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size, false, uv_border_size);
copy_effects->octmap_downsample(radiance_base_octmap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size, uv_border_size);
for (uint32_t i = 1; i < downsampled_layer.mipmaps.size(); i++) {
copy_effects->octmap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size, false, uv_border_size);
copy_effects->octmap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size, uv_border_size);
}
RD::get_singleton()->draw_command_end_label(); // Downsample Radiance
}
@@ -490,10 +490,10 @@ void SkyRD::ReflectionData::update_reflection_mipmaps(int p_start, int p_end) {
Size2i size = layers[i].mipmaps[j + 1].size;
if (use_raster_effect) {
RID framebuffer = layers[i].mipmaps[j + 1].framebuffer;
copy_effects->octmap_downsample_raster(view, framebuffer, size, false, uv_border_size);
copy_effects->octmap_downsample_raster(view, framebuffer, size, uv_border_size);
} else {
RID texture = layers[i].mipmaps[j + 1].view;
copy_effects->octmap_downsample(view, texture, size, false, uv_border_size);
copy_effects->octmap_downsample(view, texture, size, uv_border_size);
}
}
}

View File

@@ -44,7 +44,7 @@ params;
// Use an approximation of the Jacobian.
float calcWeight(float u, float v) {
vec3 d = oct_to_vec3_with_border(vec2(u, v), params.border_size);
vec3 d = oct_to_vec3_with_border(vec2(u, v) * 0.5 + 0.5, params.border_size);
return 1.0 / pow(abs(d.z) + 1.0, 3.0);
}
@@ -54,7 +54,6 @@ void main() {
float inv_size = 1.0 / float(params.size);
uvec2 sample_id = id;
#ifdef USE_HIGH_QUALITY
float u0 = (float(sample_id.x) * 2.0f + 1.0f - 0.75f) * inv_size - 1.0f;
float u1 = (float(sample_id.x) * 2.0f + 1.0f + 0.75f) * inv_size - 1.0f;
float v0 = (float(sample_id.y) * 2.0f + 1.0f - 0.75f) * inv_size - 1.0f;
@@ -75,9 +74,5 @@ void main() {
color += textureLod(source_octmap, vec2(u0, v1) * 0.5f + 0.5f, 0.0) * weights[2];
color += textureLod(source_octmap, vec2(u1, v1) * 0.5f + 0.5f, 0.0) * weights[3];
imageStore(dest_octmap, ivec2(id), color);
#else
vec2 uv = (vec2(sample_id.xy) + 0.5) * inv_size;
imageStore(dest_octmap, ivec2(id), textureLod(source_octmap, uv, 0.0));
#endif
}
}