Reputation: 41
I'm trying to implement geometry instancing in my engine using Uniform Buffer Objects. The idea is simple. I fill all visible entities states to single UBO for current scene. And then after commands sorting:
Due to alignment requirements one instance entry has exact 256 bytes size.
Vertex pseudo shader looks like this:
"
#version 300 es
layout(location = LOCATION_POSITION) in vec4 mesh_position;
layout(location = LOCATION_NORMAL) in vec3 mesh_normal;
LAYOUT_LOCATION(4) out highp vec3 vertex_worldPosition;
LAYOUT_LOCATION(5) out mediump vec3 vertex_worldNormal;
#define MAX_INSTANCES 128
struct SInstance {
mat4 modelMatrix;
mat3 modelNormalMatrix;
vec4 weights;
uint features
uint layers;
uint Id;
float parameter;
vec4 _padding[7];
};
layout (std140) uniform InstanceUBO {
SInstance instance;
} objectUniforms;
layout (std140) uniform InstancingUBO {
SInstance instances[MAX_INSTANCES];
} objectUniformsInstances;
layout (std140) uniform InstancingIndexesUBO {
uvec4 instances[MAX_INSTANCES/4];
} instancesUniforms;
#ifdef HAS_INSTANCING
uint getInstanceIndex()
{
int inst = gl_InstanceID;
uint instIdx = instancesUniforms.instances[inst >> 2][inst & 3];
return instIdx;
}
mat4 getModelMatrix()
{
uint instance = getInstanceIndex();
return objectUniformsInstances.instances[instance].worldFromModelMatrix;
}
mat3 getNormalMatrix()
{
uint instance = getInstanceIndex();
return objectUniformsInstances.instances[instance].worldFromModelNormalMatrix;
}
#else
mat4 getModelMatrix()
{
return objectUniforms.instance.worldFromModelMatrix;
}
mat3 getNormalMatrix()
{
return objectUniforms.instance.worldFromModelNormalMatrix;
}
void main()
{
vertex_worldNormal = mesh_normal * getNormalMatrix();
vertex_worldPos = mesh_pos * getModelMatrix();
gl_Position = viewUniforms.viewProjMatrix * vertex_worldPos;
}
#endif
"
Not sure what the problem is here but it turned out the code is working completely different on different devices / platforms.
For example provided code works perfectly in GL4.5 Core OpenGL. It also work in WebGL2: FireFox, Mac Chrome and Mac Safary. But it doesn't work in Windows Chrome and all Windows Chromium browsers (Edge, Opera). (Just missing instanced objects).
To make it working in Windows Chromium I have to change Instancing UBO declarations this way:
layout (std140) uniform InstancingUBO {
SInstance instances[2];
} objectUniformsInstances;
layout (std140) uniform InstancingIndexesUBO {
uvec4 instances[2];
} instancesUniforms;
So I decalre 2 instances for both instancing UBO's instead of 128. But in this cases it stops working in Windows FireFox, Mac Chrome and Mac Safary. And it still doesn't work in Mobile iOS Safary.
Looks like the problem is related to dynamic indexing of InstancingUBO. Is this unsupported by the WebGL2 standard?
How to make instancing using UBO working on all platforms / browsers including mobile?
Upvotes: 1
Views: 304