0

我正在尝试使用统一缓冲区对象在我的引擎中实现几何实例化。这个想法很简单。我将所有可见实体状态填充到当前场景的单个 UBO。然后在命令排序之后:

  1. 如果没有实例化 - 我绑定当前实例的 InstancingUBO 范围(glBindBufferRange)
  2. 使用实例化 - 我绑定了 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 在包括移动设备在内的所有平台/浏览器上进行实例化?

4

0 回答 0