我正在尝试使用统一缓冲区对象在我的引擎中实现几何实例化。这个想法很简单。我将所有可见实体状态填充到当前场景的单个 UBO。然后在命令排序之后:
- 如果没有实例化 - 我绑定当前实例的 InstancingUBO 范围(glBindBufferRange)
- 使用实例化 - 我绑定了 2 个缓冲区:全范围内的 InstancingUBO 和全范围内的第二个动态缓冲区 InstancingIndexesUBO。
由于对齐要求,一个实例条目具有精确的 256 字节大小。
顶点伪着色器如下所示:
"
#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
"
不确定这里的问题是什么,但事实证明代码在不同的设备/平台上的工作方式完全不同。
例如,提供的代码在 GL4.5 Core OpenGL 中完美运行。它也适用于 WebGL2:FireFox、Mac Chrome 和 Mac Safary。但它不适用于 Windows Chrome 和所有 Windows Chromium 浏览器(Edge、Opera)。(只是缺少实例对象)。
为了使其在 Windows Chromium 中工作,我必须以这种方式更改 Instancing UBO 声明:
layout (std140) uniform InstancingUBO {
SInstance instances[2];
} objectUniformsInstances;
layout (std140) uniform InstancingIndexesUBO {
uvec4 instances[2];
} instancesUniforms;
所以我为两个实例化 UBO 而不是 128 贴了 2 个实例。但在这种情况下,它在 Windows FireFox、Mac Chrome 和 Mac Safary 中停止工作。它仍然无法在 Mobile iOS Safari 中运行。
看起来问题与 InstancingUBO 的动态索引有关。WebGL2 标准不支持吗?
如何使用 UBO 在包括移动设备在内的所有平台/浏览器上进行实例化?