mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 05:09:20 +02:00
Cull instances by compact records and draw them from a shader storage buffer
This commit is contained in:
@@ -14,7 +14,7 @@ void gl::glsl_common_setup()
|
||||
"#define MAX_LIGHTS " + std::to_string(MAX_LIGHTS) + "U\n" +
|
||||
"#define MAX_CASCADES " + std::to_string(MAX_CASCADES) + "U\n" +
|
||||
"#define MAX_PARAMS " + std::to_string(MAX_PARAMS) + "U\n" +
|
||||
"#define MAX_INSTANCES_PER_BATCH " + std::to_string(MAX_INSTANCES_PER_BATCH) + "U\n" +
|
||||
"#define INSTANCE_SSBO_BINDING " + std::to_string(INSTANCE_SSBO_BINDING) + "\n" +
|
||||
"#define LIGHT_SSBO_BINDING " + std::to_string(LIGHT_SSBO_BINDING) + "\n" +
|
||||
"#define CLUSTER_GRID_X " + std::to_string(CLUSTER_GRID_X) + "\n" +
|
||||
"#define CLUSTER_GRID_Y " + std::to_string(CLUSTER_GRID_Y) + "\n" +
|
||||
@@ -184,24 +184,21 @@ void gl::glsl_common_setup()
|
||||
vec4 wiper_timer_return;
|
||||
};
|
||||
|
||||
// Per-instance modelview matrices for GPU-instanced draws.
|
||||
// The UBO itself is declared in every stage so the binding stays valid,
|
||||
// but the helper functions reference gl_InstanceID which is vertex-only,
|
||||
// so they are guarded behind STAGE_VERTEX.
|
||||
layout (std140) uniform instance_ubo
|
||||
#ifdef STAGE_VERTEX
|
||||
// Per-instance modelview matrices for GPU-instanced draws, element 0 is identity.
|
||||
// Draws which aren't instanced have gl_BaseInstance == 0 and gl_InstanceID == 0,
|
||||
// so effective_modelview() reduces to model_ubo.modelview. For instanced draws
|
||||
// the C++ side uploads camera-space root transforms of the instances and draws
|
||||
// them from base instance onwards, with model_ubo.modelview set to the submodel-local
|
||||
// chain (computed from identity, NOT from the camera/instance), so the product
|
||||
// gives the correct final transform per instance per submodel.
|
||||
layout(std430, binding = INSTANCE_SSBO_BINDING) readonly buffer instance_ssbo
|
||||
{
|
||||
mat4 instance_modelview[MAX_INSTANCES_PER_BATCH];
|
||||
mat4 instance_modelview[];
|
||||
};
|
||||
|
||||
#ifdef STAGE_VERTEX
|
||||
// For non-instanced draws gl_InstanceID == 0 and slot 0 is permanently set
|
||||
// to identity, so effective_modelview() reduces to model_ubo.modelview.
|
||||
// For instanced draws the C++ side uploads camera-space root transforms for
|
||||
// instances 0..N-1 and sets model_ubo.modelview to the submodel-local chain
|
||||
// (computed from identity, NOT from the camera/instance), so the product
|
||||
// gives the correct final transform per instance per submodel.
|
||||
mat4 effective_modelview() {
|
||||
return instance_modelview[gl_InstanceID] * modelview;
|
||||
return instance_modelview[gl_BaseInstance + gl_InstanceID] * modelview;
|
||||
}
|
||||
mat3 effective_modelviewnormal() {
|
||||
// instance_modelview can include per-instance scale (uniform or per-axis),
|
||||
@@ -209,7 +206,7 @@ void gl::glsl_common_setup()
|
||||
// case. Compute the correct normal matrix via transpose(inverse(...)).
|
||||
// For pure rotation+translation this still produces the rotation matrix
|
||||
// (one extra mat3 inverse per vertex — modern GPUs handle it cheaply).
|
||||
mat3 instance_mv3 = mat3(instance_modelview[gl_InstanceID]);
|
||||
mat3 instance_mv3 = mat3(instance_modelview[gl_BaseInstance + gl_InstanceID]);
|
||||
mat3 instance_normal = transpose(inverse(instance_mv3));
|
||||
return instance_normal * modelviewnormal;
|
||||
}
|
||||
|
||||
@@ -281,9 +281,6 @@ void gl::program::init()
|
||||
|
||||
if ((index = glGetUniformBlockIndex(*this, "model_ubo")) != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(*this, index, 1);
|
||||
|
||||
if ((index = glGetUniformBlockIndex(*this, "instance_ubo")) != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(*this, index, 3);
|
||||
}
|
||||
|
||||
gl::program::program()
|
||||
|
||||
15
gl/ubo.h
15
gl/ubo.h
@@ -104,17 +104,6 @@ namespace gl
|
||||
|
||||
static_assert(sizeof(model_ubs) == 208 + 16 * MAX_PARAMS, "bad size of ubs");
|
||||
|
||||
// maximum number of instances per single GPU-instanced draw call.
|
||||
// 256 mat4 = 16 KiB, the guaranteed minimum UBO size. Bigger batches must split.
|
||||
const size_t MAX_INSTANCES_PER_BATCH = 256;
|
||||
|
||||
struct instance_ubs
|
||||
{
|
||||
glm::mat4 instance_modelview[MAX_INSTANCES_PER_BATCH];
|
||||
};
|
||||
|
||||
static_assert(sizeof(instance_ubs) == 64 * MAX_INSTANCES_PER_BATCH, "bad size of instance_ubs");
|
||||
|
||||
// layout std430 (shader storage buffers)
|
||||
// structs must match with GLSL, offsets checked below
|
||||
|
||||
@@ -295,6 +284,10 @@ namespace gl
|
||||
const GLuint ATMOSPHERE_RESULT_SSBO_BINDING = 7;
|
||||
const GLuint ATMOSPHERE_UBO_BINDING = 4;
|
||||
|
||||
// binding point of the per-instance modelview matrices of instanced draws (glsl: instance_ssbo, mat4 per instance).
|
||||
// element 0 is identity, the matrix of every draw which isn't instanced
|
||||
const GLuint INSTANCE_SSBO_BINDING = 8;
|
||||
|
||||
// number of coefficients of the spherical harmonics of order 2 (bands 0..2)
|
||||
const size_t SKY_SH_COEFFICIENTS = 9;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user