diff options
Diffstat (limited to 'modules/lightmapper_rd')
-rw-r--r-- | modules/lightmapper_rd/SCsub | 3 | ||||
-rw-r--r-- | modules/lightmapper_rd/lightmapper_rd.cpp | 48 | ||||
-rw-r--r-- | modules/lightmapper_rd/lightmapper_rd.h | 11 | ||||
-rw-r--r-- | modules/lightmapper_rd/lm_common_inc.glsl | 30 | ||||
-rw-r--r-- | modules/lightmapper_rd/lm_compute.glsl | 86 |
5 files changed, 78 insertions, 100 deletions
diff --git a/modules/lightmapper_rd/SCsub b/modules/lightmapper_rd/SCsub index 2f04f1833e..5cc9d8ee8b 100644 --- a/modules/lightmapper_rd/SCsub +++ b/modules/lightmapper_rd/SCsub @@ -7,6 +7,9 @@ env_lightmapper_rd = env_modules.Clone() env_lightmapper_rd.GLSL_HEADER("lm_raster.glsl") env_lightmapper_rd.GLSL_HEADER("lm_compute.glsl") env_lightmapper_rd.GLSL_HEADER("lm_blendseams.glsl") +env_lightmapper_rd.Depends("lm_raster.glsl.gen.h", "lm_common_inc.glsl") +env_lightmapper_rd.Depends("lm_compute.glsl.gen.h", "lm_common_inc.glsl") +env_lightmapper_rd.Depends("lm_blendseams.glsl.gen.h", "lm_common_inc.glsl") # Godot source files env_lightmapper_rd.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index fe941e25e7..ba4ef3be8d 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -274,13 +274,12 @@ Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_ return BAKE_OK; } -void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_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 &box_buffer, RID &lights_buffer, RID &triangle_cell_indices_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata) { +void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_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 &triangle_cell_indices_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata) { HashMap<Vertex, uint32_t, VertexHash> vertex_map; //fill triangles array and vertex array LocalVector<Triangle> triangles; LocalVector<Vertex> vertex_array; - LocalVector<Box> box_array; LocalVector<Seam> seams; slice_triangle_count.resize(atlas_slices); @@ -387,16 +386,13 @@ void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i } } - Box box; - box.min_bounds[0] = taabb.position.x; - box.min_bounds[1] = taabb.position.y; - box.min_bounds[2] = taabb.position.z; - box.max_bounds[0] = taabb.position.x + MAX(taabb.size.x, 0.0001); - box.max_bounds[1] = taabb.position.y + MAX(taabb.size.y, 0.0001); - box.max_bounds[2] = taabb.position.z + MAX(taabb.size.z, 0.0001); - box.pad0 = box.pad1 = 0; //make valgrind not complain - box_array.push_back(box); - + t.min_bounds[0] = taabb.position.x; + t.min_bounds[1] = taabb.position.y; + t.min_bounds[2] = taabb.position.z; + t.max_bounds[0] = taabb.position.x + MAX(taabb.size.x, 0.0001); + t.max_bounds[1] = taabb.position.y + MAX(taabb.size.y, 0.0001); + t.max_bounds[2] = taabb.position.z + MAX(taabb.size.z, 0.0001); + t.pad0 = t.pad1 = 0; //make valgrind not complain triangles.push_back(t); slice_triangle_count.write[t.slice]++; } @@ -505,9 +501,6 @@ void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i Vector<uint8_t> tb = triangles.to_byte_array(); triangle_buffer = rd->storage_buffer_create(tb.size(), tb); - Vector<uint8_t> bb = box_array.to_byte_array(); - box_buffer = rd->storage_buffer_create(bb.size(), bb); - Vector<uint8_t> tib = triangle_indices.to_byte_array(); triangle_cell_indices_buffer = rd->storage_buffer_create(tib.size(), tib); @@ -755,7 +748,6 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d Vector<int> slice_triangle_count; RID vertex_buffer; RID triangle_buffer; - RID box_buffer; RID lights_buffer; RID triangle_cell_indices_buffer; RID grid_texture; @@ -767,14 +759,13 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d #define FREE_BUFFERS \ rd->free(vertex_buffer); \ rd->free(triangle_buffer); \ - rd->free(box_buffer); \ rd->free(lights_buffer); \ rd->free(triangle_cell_indices_buffer); \ rd->free(grid_texture); \ rd->free(seams_buffer); \ rd->free(probe_positions_buffer); - _create_acceleration_structures(rd, atlas_size, atlas_slices, bounds, grid_size, probe_positions, p_generate_probes, slice_triangle_count, slice_seam_count, vertex_buffer, triangle_buffer, box_buffer, lights_buffer, triangle_cell_indices_buffer, probe_positions_buffer, grid_texture, seams_buffer, p_step_function, p_bake_userdata); + _create_acceleration_structures(rd, atlas_size, atlas_slices, bounds, grid_size, probe_positions, p_generate_probes, slice_triangle_count, slice_seam_count, vertex_buffer, triangle_buffer, lights_buffer, triangle_cell_indices_buffer, probe_positions_buffer, grid_texture, seams_buffer, p_step_function, p_bake_userdata); if (p_step_function) { p_step_function(0.47, TTR("Preparing shaders"), p_bake_userdata, true); @@ -828,62 +819,55 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 3; - u.ids.push_back(box_buffer); - base_uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 4; u.ids.push_back(triangle_cell_indices_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 5; + u.binding = 4; u.ids.push_back(lights_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 6; + u.binding = 5; u.ids.push_back(seams_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 7; + u.binding = 6; u.ids.push_back(probe_positions_buffer); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 8; + u.binding = 7; u.ids.push_back(grid_texture); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 9; + u.binding = 8; u.ids.push_back(albedo_array_tex); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 10; + u.binding = 9; u.ids.push_back(emission_array_tex); base_uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 11; + u.binding = 10; u.ids.push_back(sampler); base_uniforms.push_back(u); } diff --git a/modules/lightmapper_rd/lightmapper_rd.h b/modules/lightmapper_rd/lightmapper_rd.h index 7ab7f34464..a6a3740051 100644 --- a/modules/lightmapper_rd/lightmapper_rd.h +++ b/modules/lightmapper_rd/lightmapper_rd.h @@ -157,16 +157,13 @@ class LightmapperRD : public Lightmapper { } }; - struct Box { + struct Triangle { + uint32_t indices[3] = {}; + uint32_t slice = 0; float min_bounds[3] = {}; float pad0 = 0.0; float max_bounds[3] = {}; float pad1 = 0.0; - }; - - struct Triangle { - uint32_t indices[3] = {}; - uint32_t slice = 0; bool operator<(const Triangle &p_triangle) const { return slice < p_triangle.slice; } @@ -231,7 +228,7 @@ class LightmapperRD : public Lightmapper { Vector<Color> probe_values; BakeError _blit_meshes_into_atlas(int p_max_texture_size, 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); - void _create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_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 &box_buffer, RID &lights_buffer, RID &triangle_cell_indices_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &seams_buffer, 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, 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 &triangle_cell_indices_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); public: diff --git a/modules/lightmapper_rd/lm_common_inc.glsl b/modules/lightmapper_rd/lm_common_inc.glsl index 1581639036..22172d50e4 100644 --- a/modules/lightmapper_rd/lm_common_inc.glsl +++ b/modules/lightmapper_rd/lm_common_inc.glsl @@ -16,26 +16,18 @@ vertices; struct Triangle { uvec3 indices; uint slice; -}; - -layout(set = 0, binding = 2, std430) restrict readonly buffer Triangles { - Triangle data[]; -} -triangles; - -struct Box { vec3 min_bounds; uint pad0; vec3 max_bounds; uint pad1; }; -layout(set = 0, binding = 3, std430) restrict readonly buffer Boxes { - Box data[]; +layout(set = 0, binding = 2, std430) restrict readonly buffer Triangles { + Triangle data[]; } -boxes; +triangles; -layout(set = 0, binding = 4, std430) restrict readonly buffer GridIndices { +layout(set = 0, binding = 3, std430) restrict readonly buffer GridIndices { uint data[]; } grid_indices; @@ -63,7 +55,7 @@ struct Light { uint pad[3]; }; -layout(set = 0, binding = 5, std430) restrict readonly buffer Lights { +layout(set = 0, binding = 4, std430) restrict readonly buffer Lights { Light data[]; } lights; @@ -73,19 +65,19 @@ struct Seam { uvec2 b; }; -layout(set = 0, binding = 6, std430) restrict readonly buffer Seams { +layout(set = 0, binding = 5, std430) restrict readonly buffer Seams { Seam data[]; } seams; -layout(set = 0, binding = 7, std430) restrict readonly buffer Probes { +layout(set = 0, binding = 6, std430) restrict readonly buffer Probes { vec4 data[]; } probe_positions; -layout(set = 0, binding = 8) uniform utexture3D grid; +layout(set = 0, binding = 7) uniform utexture3D grid; -layout(set = 0, binding = 9) uniform texture2DArray albedo_tex; -layout(set = 0, binding = 10) uniform texture2DArray emission_tex; +layout(set = 0, binding = 8) uniform texture2DArray albedo_tex; +layout(set = 0, binding = 9) uniform texture2DArray emission_tex; -layout(set = 0, binding = 11) uniform sampler linear_sampler; +layout(set = 0, binding = 10) uniform sampler linear_sampler; diff --git a/modules/lightmapper_rd/lm_compute.glsl b/modules/lightmapper_rd/lm_compute.glsl index 9ca40535f9..25b334c5eb 100644 --- a/modules/lightmapper_rd/lm_compute.glsl +++ b/modules/lightmapper_rd/lm_compute.glsl @@ -115,7 +115,12 @@ bool ray_hits_triangle(vec3 from, vec3 dir, float max_dist, vec3 p0, vec3 p1, ve return (r_distance > params.bias) && (r_distance < max_dist) && all(greaterThanEqual(r_barycentric, vec3(0.0))); } -bool trace_ray(vec3 p_from, vec3 p_to +const uint RAY_MISS = 0; +const uint RAY_FRONT = 1; +const uint RAY_BACK = 2; +const uint RAY_ANY = 3; + +uint trace_ray(vec3 p_from, vec3 p_to #if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) , out uint r_triangle, out vec3 r_barycentric @@ -125,6 +130,7 @@ bool trace_ray(vec3 p_from, vec3 p_to out float r_distance, out vec3 r_normal #endif ) { + /* world coords */ vec3 rel = p_to - p_from; @@ -150,79 +156,66 @@ bool trace_ray(vec3 p_from, vec3 p_to while (all(greaterThanEqual(icell, ivec3(0))) && all(lessThan(icell, ivec3(params.grid_size))) && iters < 1000) { uvec2 cell_data = texelFetch(usampler3D(grid, linear_sampler), icell, 0).xy; if (cell_data.x > 0) { //triangles here - bool hit = false; -#if defined(MODE_UNOCCLUDE) - bool hit_backface = false; -#endif + uint hit = RAY_MISS; float best_distance = 1e20; for (uint i = 0; i < cell_data.x; i++) { uint tidx = grid_indices.data[cell_data.y + i]; //Ray-Box test - vec3 t0 = (boxes.data[tidx].min_bounds - p_from) * inv_dir; - vec3 t1 = (boxes.data[tidx].max_bounds - p_from) * inv_dir; + Triangle triangle = triangles.data[tidx]; + vec3 t0 = (triangle.min_bounds - p_from) * inv_dir; + vec3 t1 = (triangle.max_bounds - p_from) * inv_dir; vec3 tmin = min(t0, t1), tmax = max(t0, t1); - if (max(tmin.x, max(tmin.y, tmin.z)) <= min(tmax.x, min(tmax.y, tmax.z))) { + if (max(tmin.x, max(tmin.y, tmin.z)) > min(tmax.x, min(tmax.y, tmax.z))) { continue; //ray box failed } //prepare triangle vertices - vec3 vtx0 = vertices.data[triangles.data[tidx].indices.x].position; - vec3 vtx1 = vertices.data[triangles.data[tidx].indices.y].position; - vec3 vtx2 = vertices.data[triangles.data[tidx].indices.z].position; -#if defined(MODE_UNOCCLUDE) + vec3 vtx0 = vertices.data[triangle.indices.x].position; + vec3 vtx1 = vertices.data[triangle.indices.y].position; + vec3 vtx2 = vertices.data[triangle.indices.z].position; +#if defined(MODE_UNOCCLUDE) || defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) vec3 normal = -normalize(cross((vtx0 - vtx1), (vtx0 - vtx2))); bool backface = dot(normal, dir) >= 0.0; #endif + float distance; vec3 barycentric; if (ray_hits_triangle(p_from, dir, rel_len, vtx0, vtx1, vtx2, distance, barycentric)) { #ifdef MODE_DIRECT_LIGHT - return true; //any hit good + return RAY_ANY; //any hit good #endif -#if defined(MODE_UNOCCLUDE) +#if defined(MODE_UNOCCLUDE) || defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) if (!backface) { // the case of meshes having both a front and back face in the same plane is more common than // expected, so if this is a front-face, bias it closer to the ray origin, so it always wins over the back-face distance = max(params.bias, distance - params.bias); } - hit = true; - if (distance < best_distance) { - hit_backface = backface; + hit = backface ? RAY_BACK : RAY_FRONT; best_distance = distance; +#if defined(MODE_UNOCCLUDE) r_distance = distance; r_normal = normal; - } - #endif - #if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) - - hit = true; - if (distance < best_distance) { - best_distance = distance; r_triangle = tidx; r_barycentric = barycentric; +#endif } #endif } } -#if defined(MODE_UNOCCLUDE) +#if defined(MODE_UNOCCLUDE) || defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) - if (hit) { - return hit_backface; - } -#endif -#if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) - if (hit) { - return true; + if (hit != RAY_MISS) { + return hit; } #endif } @@ -238,7 +231,7 @@ bool trace_ray(vec3 p_from, vec3 p_to iters++; } - return false; + return RAY_MISS; } const float PI = 3.14159265f; @@ -338,7 +331,7 @@ void main() { continue; //no need to do anything } - if (!trace_ray(position + light_dir * params.bias, light_pos)) { + if (trace_ray(position + light_dir * params.bias, light_pos) == RAY_MISS) { vec3 light = lights.data[i].color * lights.data[i].energy * attenuation; if (lights.data[i].static_bake) { static_light += light; @@ -409,6 +402,7 @@ void main() { vec4(0.0, 0.0, 0.0, 1.0)); #endif vec3 light_average = vec3(0.0); + float active_rays = 0.0; for (uint i = params.ray_from; i < params.ray_to; i++) { vec3 ray_dir = normal_mat * vogel_hemisphere(i, params.ray_count, quick_hash(vec2(atlas_pos))); @@ -416,7 +410,8 @@ void main() { vec3 barycentric; vec3 light = vec3(0.0); - if (trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric)) { + uint trace_result = trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric); + if (trace_result == RAY_FRONT) { //hit a triangle vec2 uv0 = vertices.data[triangles.data[tidx].indices.x].uv; vec2 uv1 = vertices.data[triangles.data[tidx].indices.y].uv; @@ -424,7 +419,8 @@ void main() { vec3 uvw = vec3(barycentric.x * uv0 + barycentric.y * uv1 + barycentric.z * uv2, float(triangles.data[tidx].slice)); light = textureLod(sampler2DArray(source_light, linear_sampler), uvw, 0.0).rgb; - } else if (params.env_transform[0][3] == 0.0) { // Use env_transform[0][3] to indicate when we are computing the first bounce + active_rays += 1.0; + } else if (trace_result == RAY_MISS && params.env_transform[0][3] == 0.0) { // Use env_transform[0][3] to indicate when we are computing the first bounce // Did not hit a triangle, reach out for the sky vec3 sky_dir = normalize(mat3(params.env_transform) * ray_dir); @@ -438,6 +434,7 @@ void main() { st /= vec2(PI * 2.0, PI); light = textureLod(sampler2D(environment, linear_sampler), st, 0.0).rgb; + active_rays += 1.0; } light_average += light; @@ -461,7 +458,9 @@ void main() { if (params.ray_from == 0) { light_total = vec3(0.0); } else { - light_total = imageLoad(bounce_accum, ivec3(atlas_pos, params.atlas_slice)).rgb; + vec4 accum = imageLoad(bounce_accum, ivec3(atlas_pos, params.atlas_slice)); + light_total = accum.rgb; + active_rays += accum.a; } light_total += light_average; @@ -476,7 +475,9 @@ void main() { #endif if (params.ray_to == params.ray_count) { - light_total /= float(params.ray_count); + if (active_rays > 0) { + light_total /= active_rays; + } imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), vec4(light_total, 1.0)); #ifndef USE_SH_LIGHTMAPS vec4 accum = imageLoad(accum_light, ivec3(atlas_pos, params.atlas_slice)); @@ -484,7 +485,7 @@ void main() { imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice), accum); #endif } else { - imageStore(bounce_accum, ivec3(atlas_pos, params.atlas_slice), vec4(light_total, 1.0)); + imageStore(bounce_accum, ivec3(atlas_pos, params.atlas_slice), vec4(light_total, active_rays)); } #endif @@ -517,7 +518,7 @@ void main() { float d; vec3 norm; - if (trace_ray(base_pos, ray_to, d, norm)) { + if (trace_ray(base_pos, ray_to, d, norm) == RAY_BACK) { if (d < min_d) { vertex_pos = base_pos + rays[i] * d + norm * params.bias * 10.0; //this bias needs to be greater than the regular bias, because otherwise later, rays will go the other side when pointing back. min_d = d; @@ -557,7 +558,8 @@ void main() { vec3 barycentric; vec3 light; - if (trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric)) { + uint trace_result = trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric); + if (trace_result == RAY_FRONT) { vec2 uv0 = vertices.data[triangles.data[tidx].indices.x].uv; vec2 uv1 = vertices.data[triangles.data[tidx].indices.y].uv; vec2 uv2 = vertices.data[triangles.data[tidx].indices.z].uv; @@ -565,7 +567,7 @@ void main() { light = textureLod(sampler2DArray(source_light, linear_sampler), uvw, 0.0).rgb; light += textureLod(sampler2DArray(source_direct_light, linear_sampler), uvw, 0.0).rgb; - } else { + } else if (trace_result == RAY_MISS) { //did not hit a triangle, reach out for the sky vec3 sky_dir = normalize(mat3(params.env_transform) * ray_dir); |