Merge pull request #100765 from Geometror/lightmapgi-add-downsampling
Add a supersampling option to LightmapGI
This commit is contained in:
@@ -234,14 +234,14 @@ void LightmapperRD::_sort_triangle_clusters(uint32_t p_cluster_size, uint32_t p_
|
||||
}
|
||||
}
|
||||
|
||||
Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_size, int p_denoiser_range, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, BakeStepFunc p_step_function, void *p_bake_userdata) {
|
||||
Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_size, int p_denoiser_range, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, float p_supersampling_factor, BakeStepFunc p_step_function, void *p_bake_userdata) {
|
||||
Vector<Size2i> sizes;
|
||||
|
||||
for (int m_i = 0; m_i < mesh_instances.size(); m_i++) {
|
||||
MeshInstance &mi = mesh_instances.write[m_i];
|
||||
Size2i s = Size2i(mi.data.albedo_on_uv2->get_width(), mi.data.albedo_on_uv2->get_height());
|
||||
sizes.push_back(s);
|
||||
atlas_size = atlas_size.max(s + Size2i(2, 2).maxi(p_denoiser_range));
|
||||
atlas_size = atlas_size.max(s + Size2i(2, 2).maxi(p_denoiser_range) * p_supersampling_factor);
|
||||
}
|
||||
|
||||
int max = nearest_power_of_2_templated(atlas_size.width);
|
||||
@@ -271,7 +271,10 @@ Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_
|
||||
source_sizes.resize(sizes.size());
|
||||
source_indices.resize(sizes.size());
|
||||
for (int i = 0; i < source_indices.size(); i++) {
|
||||
source_sizes.write[i] = sizes[i] + Vector2i(2, 2).maxi(p_denoiser_range); // Add padding between lightmaps.
|
||||
// Add padding between lightmaps.
|
||||
// Scale the padding if the lightmap will be downsampled at the end of the baking process
|
||||
// Otherwise the padding would be insufficient.
|
||||
source_sizes.write[i] = sizes[i] + Vector2i(2, 2).maxi(p_denoiser_range) * p_supersampling_factor;
|
||||
source_indices.write[i] = i;
|
||||
}
|
||||
Vector<Vector3i> atlas_offsets;
|
||||
@@ -1041,7 +1044,7 @@ LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDSh
|
||||
return BAKE_OK;
|
||||
}
|
||||
|
||||
LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_denoiser, float p_denoiser_strength, int p_denoiser_range, int p_bounces, float p_bounce_indirect_energy, float p_bias, int p_max_texture_size, bool p_bake_sh, bool p_bake_shadowmask, bool p_texture_for_bounces, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function, void *p_bake_userdata, float p_exposure_normalization) {
|
||||
LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_denoiser, float p_denoiser_strength, int p_denoiser_range, int p_bounces, float p_bounce_indirect_energy, float p_bias, int p_max_texture_size, bool p_bake_sh, bool p_bake_shadowmask, bool p_texture_for_bounces, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function, void *p_bake_userdata, float p_exposure_normalization, float p_supersampling_factor) {
|
||||
int denoiser = GLOBAL_GET("rendering/lightmapping/denoising/denoiser");
|
||||
String oidn_path = EDITOR_GET("filesystem/tools/oidn/oidn_denoise_path");
|
||||
|
||||
@@ -1074,7 +1077,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
|
||||
Vector<Ref<Image>> albedo_images;
|
||||
Vector<Ref<Image>> emission_images;
|
||||
|
||||
BakeError bake_error = _blit_meshes_into_atlas(p_max_texture_size, p_denoiser_range, albedo_images, emission_images, bounds, atlas_size, atlas_slices, p_step_function, p_bake_userdata);
|
||||
BakeError bake_error = _blit_meshes_into_atlas(p_max_texture_size, p_denoiser_range, albedo_images, emission_images, bounds, atlas_size, atlas_slices, p_supersampling_factor, p_step_function, p_bake_userdata);
|
||||
if (bake_error != BAKE_OK) {
|
||||
return bake_error;
|
||||
}
|
||||
@@ -1330,6 +1333,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
|
||||
bake_parameters.shadowmask_light_idx = shadowmask_light_idx;
|
||||
// Same number of rays for transparency regardless of quality (it's more of a retry rather than shooting new ones).
|
||||
bake_parameters.transparency_rays = GLOBAL_GET("rendering/lightmapping/bake_performance/max_transparency_rays");
|
||||
bake_parameters.supersampling_factor = p_supersampling_factor;
|
||||
|
||||
bake_parameters_buffer = rd->uniform_buffer_create(sizeof(BakeParameters));
|
||||
rd->buffer_update(bake_parameters_buffer, 0, sizeof(BakeParameters), &bake_parameters);
|
||||
|
||||
@@ -59,7 +59,7 @@ class LightmapperRD : public Lightmapper {
|
||||
float bounce_indirect_energy = 0.0f;
|
||||
uint32_t shadowmask_light_idx = 0;
|
||||
uint32_t transparency_rays = 0;
|
||||
uint32_t pad[1] = {};
|
||||
float supersampling_factor = 0.0f;
|
||||
};
|
||||
|
||||
struct MeshInstance {
|
||||
@@ -260,6 +260,11 @@ class LightmapperRD : public Lightmapper {
|
||||
Vector<Ref<Image>> shadowmask_textures;
|
||||
Vector<Color> probe_values;
|
||||
|
||||
struct DilateParams {
|
||||
uint32_t radius;
|
||||
uint32_t pad[3];
|
||||
};
|
||||
|
||||
struct DenoiseParams {
|
||||
float spatial_bandwidth;
|
||||
float light_bandwidth;
|
||||
@@ -271,7 +276,7 @@ class LightmapperRD : public Lightmapper {
|
||||
float pad[2];
|
||||
};
|
||||
|
||||
BakeError _blit_meshes_into_atlas(int p_max_texture_size, int p_denoiser_range, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, BakeStepFunc p_step_function, void *p_bake_userdata);
|
||||
BakeError _blit_meshes_into_atlas(int p_max_texture_size, int p_denoiser_range, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, float p_supersampling_factor, BakeStepFunc p_step_function, void *p_bake_userdata);
|
||||
void _create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, uint32_t p_cluster_size, Vector<Probe> &probe_positions, GenerateProbes p_generate_probes, Vector<int> &slice_triangle_count, Vector<int> &slice_seam_count, RID &vertex_buffer, RID &triangle_buffer, RID &lights_buffer, RID &r_triangle_indices_buffer, RID &r_cluster_indices_buffer, RID &r_cluster_aabbs_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata);
|
||||
void _raster_geometry(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, int grid_size, AABB bounds, float p_bias, Vector<int> slice_triangle_count, RID position_tex, RID unocclude_tex, RID normal_tex, RID raster_depth_buffer, RID rasterize_shader, RID raster_base_uniform);
|
||||
|
||||
@@ -289,7 +294,7 @@ public:
|
||||
virtual void add_omni_light(const String &p_name, bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_energy, float p_range, float p_attenuation, float p_size, float p_shadow_blur) override;
|
||||
virtual void add_spot_light(const String &p_name, bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size, float p_shadow_blur) override;
|
||||
virtual void add_probe(const Vector3 &p_position) override;
|
||||
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, float p_denoiser_strength, int p_denoiser_range, int p_bounces, float p_bounce_indirect_energy, float p_bias, int p_max_texture_size, bool p_bake_sh, bool p_bake_shadowmask, bool p_texture_for_bounces, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr, float p_exposure_normalization = 1.0) override;
|
||||
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, float p_denoiser_strength, int p_denoiser_range, int p_bounces, float p_bounce_indirect_energy, float p_bias, int p_max_texture_size, bool p_bake_sh, bool p_bake_shadowmask, bool p_texture_for_bounces, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr, float p_exposure_normalization = 1.0, float p_supersampling_factor = 1.0f) override;
|
||||
|
||||
int get_bake_texture_count() const override;
|
||||
Ref<Image> get_bake_texture(int p_index) const override;
|
||||
|
||||
@@ -18,7 +18,7 @@ layout(set = 0, binding = 0) uniform BakeParameters {
|
||||
float bounce_indirect_energy;
|
||||
int shadowmask_light_idx;
|
||||
uint transparency_rays;
|
||||
uint pad0;
|
||||
float supersampling_factor;
|
||||
}
|
||||
bake_params;
|
||||
|
||||
|
||||
@@ -832,7 +832,7 @@ void main() {
|
||||
// Empty texel, try again.
|
||||
neighbor_position.xyz = texelFetch(sampler2DArray(source_position, linear_sampler), ivec3(atlas_pos + ivec2(-1, 0), params.atlas_slice), 0).xyz;
|
||||
}
|
||||
float texel_size_world_space = distance(position, neighbor_position.xyz);
|
||||
float texel_size_world_space = distance(position, neighbor_position.xyz) * bake_params.supersampling_factor;
|
||||
|
||||
vec3 light_for_texture = vec3(0.0);
|
||||
vec3 light_for_bounces = vec3(0.0);
|
||||
@@ -1071,43 +1071,35 @@ void main() {
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DILATE)
|
||||
#ifdef MODE_DILATE
|
||||
|
||||
vec4 c = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0);
|
||||
//sides first, as they are closer
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, 0), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, 1), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, 0), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, -1), params.atlas_slice), 0);
|
||||
//endpoints second
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, -1), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, 1), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, -1), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, 1), params.atlas_slice), 0);
|
||||
const int max_radius = int(4.0 * bake_params.supersampling_factor);
|
||||
const ivec2 directions[8] = ivec2[8](ivec2(-1, 0), ivec2(0, 1), ivec2(1, 0), ivec2(0, -1), ivec2(-1, -1), ivec2(-1, 1), ivec2(1, -1), ivec2(1, 1));
|
||||
|
||||
//far sides third
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, 0), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, 2), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, 0), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, -2), params.atlas_slice), 0);
|
||||
vec4 texel_color = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0);
|
||||
|
||||
//far-mid endpoints
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, -1), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, 1), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, -1), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, 1), params.atlas_slice), 0);
|
||||
for (int radius = 1; radius <= max_radius; radius++) {
|
||||
for (uint i = 0; i < 8; i++) {
|
||||
const ivec2 sample_pos = atlas_pos + directions[i] * radius;
|
||||
// Texture bounds check for robustness.
|
||||
if (any(lessThan(sample_pos, ivec2(0))) ||
|
||||
any(greaterThanEqual(sample_pos, textureSize(source_light, 0).xy))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, -2), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, 2), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, -2), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, 2), params.atlas_slice), 0);
|
||||
//far endpoints
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, -2), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, 2), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, -2), params.atlas_slice), 0);
|
||||
c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, 2), params.atlas_slice), 0);
|
||||
vec4 neighbor_color = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(sample_pos, params.atlas_slice), 0);
|
||||
if (neighbor_color.a > 0.5) {
|
||||
texel_color = neighbor_color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), c);
|
||||
if (texel_color.a > 0.5) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), texel_color);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user