顶点着色器不应用第二个属性数组

时间:2017-03-30 13:04:51

标签: android opengl-es

考虑一个包含两类物体(球和墙)的简单游戏。教程我发现建议使用单个顶点数据数组,方式如下:

[...初始化...]

vdata = new float[ENOUGH_FOR_ALL];
vertexData = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
aPositionLocation = glGetAttribLocation(programId, "a_Position");
glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT, false, 0, vertexData);
glEnableVertexAttribArray(aPositionLocation);

[...图...]

vertexData.position(0);
vertexData.put(vdata);
glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 1.0f); // ball is red
glDrawArrays(GL_TRIANGLE_FAN, 0, BALL_VERTICES + 2);
glUniform4f(uColorLocation, 0.0f, 1.0f, 0.0f, 1.0f); // wall is green
glDrawArrays(GL_LINES, BALL_VERTICES + 2, 2); // wall as a single line

并且,顶点着色器很简单:

attribute vec4 a_Position;

void main() {
    gl_Position = a_Position;
}

这可行,但需要在单个缓冲区中进行繁琐的偏移计算,当某个对象大小发生变化时移动...

考虑以下顶点着色器

attribute vec4 a_Ball;
attribute vec4 a_Wall;
uniform float u_WhatDraw;

void main() {
    if (u_WhatDraw == 1.0) {
        gl_Position = a_Ball;
    }
    else if (u_WhatDraw == 2.0) {
        gl_Position = a_Wall;
    }
}

准备的数据为:

ball_data = new float[BALL_VERTICES + 2];
wall_data = new float[4]; // a single line
ballVertexData = ByteBuffer.allocateDirect(ball_data.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
wallVertexData = ByteBuffer.allocateDirect(wall_data.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
aBallLocation = glGetAttribLocation(programId, "a_Ball");
glVertexAttribPointer(aBallLocation, 2, GL_FLOAT, false, 0, ballVertexData);
glEnableVertexAttribArray(aBallLocation);
aWallLocation = glGetAttribLocation(programId, "a_Wall");
glVertexAttribPointer(aWallLocation, 2, GL_FLOAT, false, 0, wallVertexData);
glEnableVertexAttribArray(aWallLocation);

[...生成静态wall_data跳过...]

[...图...]

ballVertexData.position(0);
ballVertexData.put(ball_data);
glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 1.0f); // ball is red
glUniform1f(uWhatDrawLocation, 1.0f);
glDrawArrays(GL_TRIANGLE_FAN, 0, BALL_VERTICES + 2);
glUniform4f(uColorLocation, 0.0f, 1.0f, 0.0f, 1.0f); // wall is green
glUniform1f(uWhatDrawLocation, 2.0f);
glDrawArrays(GL_LINES, 0, 2); // wall as a single line

尽管球被拉了,但这根本不会画墙。

请建议使用2阵列方法解决此问题或解释为什么我应该为所有活动坚持使用单个阵列。

1 个答案:

答案 0 :(得分:1)

  

这可行,但需要在单个缓冲区中进行繁琐的偏移计算,当某个对象大小发生变化时移动...

如果对象大小发生变化,则需要重新上载新的网格数据,因此计算偏移量似乎是问题中的最小值。

  

或解释为什么我应该为所有活动坚持使用单个数组。

添加第三个对象或第四个或第五个对象时会发生什么?

您正在优化错误的问题。

每当您需要使用if (<insert uniform>) ...生成着色器时,您做错了 - 当应用程序只执行一次时,永远不要让GPU为每个顶点做出控制平面决策。