GPULightmapper's triangles and their bounding box will be in-sync

Previously the bounding boxes and triangles were maintained in two separate
arrays (Vectors). As the triangle vector was sorted and the bounding-box array
was not , the order of both arrays differed. This meant that the index in one
was different than the other, which caused lookup issues.

To prevent this, the bounding-box is now part of the triangle structure so that
there is a single structure that cannot become out-of-sync anymore.
This commit is contained in:
William Deurwaarder 2021-09-11 14:02:37 +02:00
parent 43e96e0c65
commit e11dd6500a
5 changed files with 42 additions and 65 deletions

View File

@ -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")

View File

@ -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);
}

View File

@ -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:

View File

@ -16,6 +16,10 @@ vertices;
struct Triangle {
uvec3 indices;
uint slice;
vec3 min_bounds;
uint pad0;
vec3 max_bounds;
uint pad1;
};
layout(set = 0, binding = 2, std430) restrict readonly buffer Triangles {
@ -23,19 +27,7 @@ layout(set = 0, binding = 2, std430) restrict readonly buffer Triangles {
}
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[];
}
boxes;
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;

View File

@ -160,18 +160,19 @@ bool trace_ray(vec3 p_from, vec3 p_to
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;
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)
vec3 normal = -normalize(cross((vtx0 - vtx1), (vtx0 - vtx2)));