mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-17 23:39:18 +02:00
Enable instancing
This commit is contained in:
@@ -14,6 +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" +
|
||||
R"STRING(
|
||||
const uint LIGHT_SPOT = 0U;
|
||||
const uint LIGHT_POINT = 1U;
|
||||
@@ -78,5 +79,31 @@ 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
|
||||
{
|
||||
mat4 instance_modelview[MAX_INSTANCES_PER_BATCH];
|
||||
};
|
||||
|
||||
#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;
|
||||
}
|
||||
mat3 effective_modelviewnormal() {
|
||||
// instance_modelview is rotation+translation only (no scale), so its
|
||||
// upper-3x3 is its own inverse-transpose (rotation matrix).
|
||||
return mat3(instance_modelview[gl_InstanceID]) * modelviewnormal;
|
||||
}
|
||||
#endif
|
||||
|
||||
)STRING";
|
||||
}
|
||||
|
||||
@@ -106,6 +106,12 @@ std::pair<GLuint, std::string> gl::shader::process_source(const std::string &fil
|
||||
str += "precision highp sampler2DShadow;\n";
|
||||
str += "precision highp sampler2DArrayShadow;\n";
|
||||
}
|
||||
// expose the shader stage to glsl_common so vertex-only built-ins
|
||||
// (gl_InstanceID, effective_modelview, etc.) can be guarded out of
|
||||
// fragment/geometry compilations.
|
||||
if (type == GL_VERTEX_SHADER) str += "#define STAGE_VERTEX 1\n";
|
||||
else if (type == GL_FRAGMENT_SHADER) str += "#define STAGE_FRAGMENT 1\n";
|
||||
else if (type == GL_GEOMETRY_SHADER) str += "#define STAGE_GEOMETRY 1\n";
|
||||
str += "vec4 FBOUT(vec4 x) { return " + (Global.gfx_shadergamma ? std::string("vec4(pow(x.rgb, vec3(1.0 / 2.2)), x.a)") : std::string("x")) + "; }\n";
|
||||
|
||||
str += read_file(basedir + filename);
|
||||
@@ -293,6 +299,9 @@ void gl::program::init()
|
||||
|
||||
if ((index = glGetUniformBlockIndex(*this, "light_ubo")) != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(*this, index, 2);
|
||||
|
||||
if ((index = glGetUniformBlockIndex(*this, "instance_ubo")) != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(*this, index, 3);
|
||||
}
|
||||
|
||||
gl::program::program()
|
||||
|
||||
11
gl/ubo.h
11
gl/ubo.h
@@ -87,6 +87,17 @@ 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");
|
||||
|
||||
struct light_element_ubs
|
||||
{
|
||||
enum type_e
|
||||
|
||||
Reference in New Issue
Block a user