我一直在尝试让我的游戏引擎在 android 上运行,但我陷入了顶点缓冲区数组。它使用 FloatBuffer 工作,但是当我尝试使用 VBO 进行渲染时,我只得到一个白屏。所以我想知道我的代码是否有问题。
这就是我创建 VBO 的方式:
private int[] vbo = new int[1];
private int[] ibo = new int[1];
private void setUpVBO()
{
short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
float TextureCoords[] =
{
0.0f, 0.0f, // bottom left
0.0f, 1.0f, // top left
1.0f, 1.0f, // top right
1.0f, 0.0f, // bottom right
};
float squareCoords[] = {
-width / 2.f - 0.015f / 2.f, height / 2.f + 0.015f / 2.f, 0.0f, // top left
-width / 2.f - 0.015f / 2.f, -height / 2.f - 0.015f / 2.f, 0.0f, // bottom left
width / 2.f + 0.015f / 2.f, -height / 2.f - 0.015f / 2.f, 0.0f, // bottom right
width / 2.f + 0.015f / 2.f, height / 2.f + 0.015f / 2.f, 0.0f }; // top right
ByteBuffer bb = ByteBuffer.allocateDirect(bb.order(ByteOrder.nativeOrder());
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
// initialize vertex byte buffer for shape coordinates
ByteBuffer tc = ByteBuffer.allocateDirect(TextureCoords.length * 4);
tc.order(ByteOrder.nativeOrder());
FloatBuffer TextureCoordinateBuffer = tc.asFloatBuffer();
TextureCoordinateBuffer.put(TextureCoords);
TextureCoordinateBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
ShortBuffer drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
GLES20.glGenBuffers(1, vbo, 0);
GLES20.glGenBuffers(1, ibo, 0);
if (vbo[0] > 0 && ibo[0] > 0)
{
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * 4,
vertexBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, TextureCoordinateBuffer.capacity() * 4,
TextureCoordinateBuffer, GLES20.GL_DYNAMIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, drawListBuffer.capacity()
* 2, drawListBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
}
}
这就是我渲染的方式:
public void render(float[] mMVPMatrix)
{
if (vbo[0] > 0 && ibo[0] > 0)
{
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
GLES20.glEnableVertexAttribArray(Values.mPositionHandle);
GLES20.glVertexAttribPointer(Values.mPositionHandle, Values.COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
Values.fullStride, 0);
GLES20.glEnableVertexAttribArray(Values.mTextureCoordinateHandle);
GLES20.glVertexAttribPointer(Values.mTextureCoordinateHandle, Values.COORDS_PER_VERTEX_TEXTURE,
GLES20.GL_FLOAT, false,
Values.fullStride, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureOfBody);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
GLES20.glUniform1i(Values.mTheActualTexture, 0);
GLES20.glUniform4fv(Values.mColorHandle, 1, colorOfBody, 0);
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(Values.mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Draw the square
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, 0);
// Disable vertex array
GLES20.glDisableVertexAttribArray(Values.mTextureCoordinateHandle);
GLES20.glDisableVertexAttribArray(Values.mPositionHandle);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
}
}
着色器已正确加载。这是我的着色器:
顶点:
uniform mat4 uMVPMatrix;
attribute vec4 vPosition;
attribute vec2 TexCoordinate;
varying vec2 TexCoordinateGLFS;
void main()
{
TexCoordinateGLFS = TexCoordinate;
gl_Position = uMVPMatrix * newPosition ;
}
分段:
precision mediump float;
uniform sampler2D theActualTexture;
uniform vec4 vColor;
varying vec2 TexCoordinateGLFS;
void main()
{
gl_FragColor = texture2D(theActualTexture, TexCoordinateGLFS) * vColor;
}
一些变量:
public static final int COORDS_PER_VERTEX = 3;
public static final int COORDS_PER_VERTEX_TEXTURE = 2;
public static final int vertexStride = COORDS_PER_VERTEX * 4;
public static final int textureStride = COORDS_PER_VERTEX_TEXTURE * 4;
public static final int fullStride = (COORDS_PER_VERTEX + COORDS_PER_VERTEX_TEXTURE) * 4;
编辑:这是新的 VBO 构造:
ByteBuffer bb = ByteBuffer.allocateDirect((squareCoords.length + TextureCoords.length) * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.put(TextureCoords);
vertexBuffer.position(0);
GLES20.glGenBuffers(1, vbo, 0);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * BYTES_PER_FLOAT,
vertexBuffer, GLES20.GL_DYNAMIC_DRAW);
我在这里画:
GLES20.glVertexAttribPointer(Values.mPositionHandle, Values.COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
Values.vertexStride, 0);
GLES20.glVertexAttribPointer(Values.mTextureCoordinateHandle, Values.COORDS_PER_VERTEX_TEXTURE,
GLES20.GL_FLOAT, false,
Values.textureStride, squareCoords.length);
squareCoords.length == 12; (每个顶点 3 个坐标(x,y,z)-> 4 * 3 = 12)