Java OpenGL ES 2.0 vbo白屏
我一直在尝试让我的游戏引擎在android上运行,但我被顶点缓冲阵列卡住了。它使用FloatBuffer工作,但当我尝试使用VBOs渲染时,我只得到了一个白色屏幕。所以我想知道我的代码是否有问题 以下是我创建VBO的方式:Java OpenGL ES 2.0 vbo白屏,java,android,opengl-es,opengl-es-2.0,vbo,Java,Android,Opengl Es,Opengl Es 2.0,Vbo,我一直在尝试让我的游戏引擎在android上运行,但我被顶点缓冲阵列卡住了。它使用FloatBuffer工作,但当我尝试使用VBOs渲染时,我只得到了一个白色屏幕。所以我想知道我的代码是否有问题 以下是我创建VBO的方式: private int[] vbo = new int[1]; private int[] ibo = new int[1]; private void setUpVBO() { short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; /
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)根据您发布的代码,似乎您用纹理坐标覆盖了位置坐标。通常情况下,需要的缓冲区与数组的数量相同,因此在本例中,纹理坐标需要单独的缓冲区。更优雅的解决方案是将上述2个数组合并为1个交错数组,将其推送到单个VBO,并在设置顶点和纹理坐标指针时使用步长 这完全是不可能的:
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);
当您绑定同一个缓冲区两次并将数据推送到GPU时,最后只剩下纹理坐标(实际上,代码可能会根据矩阵在屏幕上的某个位置生成一个单像素图像)这看起来很糟糕
ByteBuffer.allocateDirect(bb.order(ByteOrder.nativeOrder())
,你应该改用字节大小吗?嗯……在添加vbo之前,它工作正常,所以我认为问题不存在。我唯一更改的是:添加vbo,在渲染类中更改为:bindBuffer。这就是所有更改的内容。哦,我并不完全希望这样可以解决问题,但更奇怪的是它可以编译:)我知道这会更优雅,但我真的不知道如何在java中做到这一点。在我用C++编写的桌面版本中,我刚刚创建了一个包含所有信息的结构,然后我只调用“4×sieof(DavaBuffER)”。也许你能给我一些提示。顺便说一句,我尝试了两个缓冲区,它就像一个符咒,只是没有看到一个正方形,我看到了三角形。我更改的是:glGenBuffers(2,vbo,0)和:glBindBuffer(gl_array_buffer,vbo[0])-用于顶点,vbo[1]用于纹理坐标,我在创建vbo时更改了,在渲染时您可以创建一个带交错坐标的浮点数组,并将其放入1个vbo中,设置跨步。或者,您可以将两个数组放入1字节缓冲区,将其放入单个VBO中,并为第二个设置偏移量。此外,您可以创建一些顶点对象,并使用它与C++相同或更多。至于三角形问题,你似乎有一个奇怪的组合指数和三角形带。您使用6个索引和三角形带,这使4个三角形。使用无索引或设置三角形(无条带)我从三角形条带更改为三角形扇形,现在它在2个vbo中运行良好,但我仍尝试将顶点和纹理坐标放在同一个vbo中,但我无法获得纹理坐标的正确偏移。物体被画在它们应该在的地方,但是纹理被搅乱了,这让我觉得它没有得到正确的纹理坐标。我用新添加的代码进行了编辑。顺便问一下,android opengl es 2.0中有顶点数组对象吗?我在网上搜索,只找到了iOS。如果有,你能给我指一个教程或什么吗?嗯,偏移量可能必须以字节为单位,所以在那里尝试length*4(如4=sizeof(float))。对不起,我不知道如何在android上进行VAO。