0

我的用户报告了在某些具有 Mali GPU 的设备(华为荣耀 9 和三星 Galaxy S10+ 分别带有 Mali G71 和 G76)上渲染半浮点数据的问题。

在 Adreno 和 PowerVR GPU 上正常工作时,它会导致这些设备上的渲染出现乱码。

我已经仔细检查了代码,它似乎是正确的:

...
     if (model.hasHalfFloats()) {
         GLES20.glVertexAttribPointer(shaderOutline.getRm_Vertex(), 3, GLES20.GL_FLOAT, false, 18, 0);
         GLES20.glVertexAttribPointer(shaderOutline.getRm_Normal(), 3, getGL_HALF_FLOAT(), false, 18, 12);
     } else {
         GLES20.glVertexAttribPointer(shaderOutline.getRm_Vertex(), 3, GLES20.GL_FLOAT, false, 24, 0);
         GLES20.glVertexAttribPointer(shaderOutline.getRm_Normal(), 3, GLES20.GL_FLOAT, false, 24, 12);
     }
...

/**
 * Returns either OES extension for GL 16-bit floats (if used in ES 2.0) or ES 3.0 constant.
 */
protected int getGL_HALF_FLOAT() {
    if(isES3()) {
        return GLES30.GL_HALF_FLOAT;
    } else {
        return GL_HALF_FLOAT_OES;
    }
}

代码似乎可以正确检测 OpenGL ES 3 并使用GLES30.GL_HALF_FLOAT.getGL_HALF_FLOAT()

示例着色器代码:

    vertexShaderCode = "attribute vec4 rm_Vertex;\r\n" + 
            "attribute mediump vec3 rm_Normal;\r\n" +
            "uniform mat4 view_proj_matrix;\r\n" + 
            "uniform float uThickness1;\r\n" + 
            "void main( void )\r\n" + 
            "{\r\n" + 
            "   vec4 pos = vec4(rm_Vertex.xyz, 1.0);\r\n" + 
            "   float dist = (view_proj_matrix * pos).w;\r\n" + 
            "   vec4 normal = vec4(rm_Normal, 0.0);\r\n" + 
            "   pos += normal * uThickness1 * dist;\r\n" + 
            "   gl_Position = view_proj_matrix * pos;\r\n" + 
            "}";

    fragmentShaderCode = "precision mediump float;\r\n" + 
            "uniform vec4 uColor;\r\n" + 
            "void main( void )\r\n" + 
            "{\r\n" + 
            "    gl_FragColor = uColor;\r\n" + 
            "}";
4

1 回答 1

1

我认为你有一个对齐问题。从这个片段(和你的顶点着色器):

GLES20.glVertexAttribPointer(shaderOutline.getRm_Normal(), 3, getGL_HALF_FLOAT(), false, 18, 12);

我可以推断您正在尝试这样的顶点结构:

float fPos[3];
half fNormal[3];

您已经提出了 18 的顶点步幅,这大概是通过将元素的各个大小相加得出的(3*sizeof(float))+(3*sizeof(half)) = 12 + 6 = 18

但是,步幅应为 20,否则您的顶点未对齐。4 字节浮点数必须从 4 字节边界开始,但事实并非如此。

来自 GLES3 规范:

客户端必须将数据元素与客户端平台的要求保持一致,并附加一个基本级别的要求,即缓冲区内与包含 N 个基本机器单元的数据的偏移量是 N 的倍数

于 2019-03-10T15:04:09.673 回答