Reputation: 4582
Consider a simple game with two classes of objects (ball and wall). Tutorials I've found suggests using a single vertex data array in the manner like:
[... initializing ...]
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);
[...drawing...]
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
and, the vertex shader is trivial:
attribute vec4 a_Position;
void main() {
gl_Position = a_Position;
}
This works but requires cumbersome calculation of offsets in a single buffer, moving when some object size changes...
Consider the following vertex shader
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;
}
}
data prepared as:
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);
[...generation of static wall_data skipped...]
[...drawing...]
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
This does not draw wall at all, despite the ball is drawn.
Please suggest in fixing this with 2-array approach or explain a limitation why I should stick with a single array for all activity.
Upvotes: 0
Views: 32
Reputation: 12229
This works but requires cumbersome calculation of offsets in a single buffer, moving when some object size changes...
If object size changes you need to reupload new mesh data, so computing offsets seems to be the least of the problems.
or explain a limitation why I should stick with a single array for all activity.
What happens when you add a third object, or a fourth, or a fifth?
You're optimizing the wrong problem.
Any time you are required to generate shaders with if (<insert uniform>) ...
you're doing it wrong - never make the GPU make control plane decisions for every vertex when the application can just do it once.
Upvotes: 1