[英]Android OpenGL ES 2.0 VBO
我花了幾天時間嘗試使用OpenGL ES 2.0在Android上運行VBO,但似乎無法正常工作。
這是我正在使用的代碼:
/* The Android shader code */
private static final String[] androidVertexShaderCode = new String[] {
"attribute vec4 vertexPosition;",
"void main() {",
" gl_Position = vertexPosition;",
"}" };
private static final String[] androidFragmentShaderCode = new String[] {
"precision mediump float;",
"uniform vec4 colour;",
"void main() {",
" gl_FragColor = colour;",
"}" };
/* The Android shader */
public Shader androidShader;
/* The constructor with the render mode and the
* number of vertex values given */
public AndroidRenderer(int renderMode, int vertexValuesCount) {
super(renderMode, vertexValuesCount);
//Add this renderer to the list
allRenderers.add(this);
usage = GLES20.GL_STATIC_DRAW;
//Setup the Android shader
this.androidShader = new AndroidShader();
this.androidShader.vertexShader = ShaderUtils.createShader(ArrayUtils.toStringList(androidVertexShaderCode), Shader.VERTEX_SHADER);
this.androidShader.fragmentShader = ShaderUtils.createShader(ArrayUtils.toStringList(androidFragmentShaderCode), Shader.FRAGMENT_SHADER);
this.androidShader.create();
}
/* The method used to setup the buffers,
* assumes the vertices have already been set */
public void setupBuffers() {
//Create the vertices buffer
this.verticesBuffer = BufferUtils.createFlippedBuffer(this.verticesData);
int[] vh = new int[1];
GLES20.glGenBuffers(1, vh, 0);
//Setup the vertices handle
this.verticesHandle = vh[0];
//Bind the vertices buffer and give OpenGL the data
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.verticesHandle);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, Float.BYTES * verticesData.length, this.verticesBuffer, this.usage);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
//Check to see whether the normals have been set
if (this.normalsData != null) {
//Create the normals buffer
this.normalsBuffer = BufferUtils.createFlippedBuffer(this.normalsData);
int[] nh = new int[1];
GLES20.glGenBuffers(1, nh, 0);
//Setup the normals handle
this.normalsHandle = nh[0];
//Bind the normals buffer and give OpenGL the data
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.normalsHandle);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, Float.BYTES * verticesData.length, this.normalsBuffer, this.usage);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
//Check to see whether the colours have been set
if (this.colourData!= null) {
//Create the colours buffer
this.coloursBuffer = BufferUtils.createFlippedBuffer(this.colourData);
int[] ch = new int[1];
GLES20.glGenBuffers(1, ch, 0);
//Setup the colours handle
this.coloursHandle = ch[0];
//Bind the colours buffer and give OpenGL the data
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.coloursHandle);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, Float.BYTES * colourData.length, this.coloursBuffer, this.usage);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
//Check to see whether the texture coordinates have been set
if (this.textureData != null) {
//Create the texture coordinates buffer
this.texturesBuffer = BufferUtils.createFlippedBuffer(this.textureData);
int[] th = new int[1];
GLES20.glGenBuffers(1, th, 0);
//Setup the texture coordinates handle
this.texturesHandle = th[0];
//Bind the texture coordinates buffer and give OpenGL the data
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.texturesHandle);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, Float.BYTES * textureData.length, this.texturesBuffer, this.usage);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
}
/* The method used to draw the object */
public void render() {
this.androidShader.use();
short[] indices = new short[this.verticesData.length];
for (short a = 0; a < indices.length; a++)
indices[a] = a;
ShortBuffer indicesBuffer = BufferUtils.createFlippedBuffer(indices);
//Enable the arrays as needed
int vertexPositionAttribute = GLES20.glGetAttribLocation(this.androidShader.program, "vertexPosition");
int normalAttribute = 0;
int colourAttribute = 0;
int texturesAttribute = 0;
GLES20.glEnableVertexAttribArray(vertexPositionAttribute);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.verticesHandle);
GLES20.glVertexAttribPointer(vertexPositionAttribute, this.vertexValuesCount, GLES20.GL_FLOAT, false, 0, 0);
if (this.normalsData != null) {
GLES20.glEnableVertexAttribArray(normalAttribute);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.normalsHandle);
GLES20.glVertexAttribPointer(normalAttribute, 2, GLES20.GL_FLOAT, false, 0, 0);
}
if (this.colourData != null) {
colourAttribute = GLES20.glGetAttribLocation(this.androidShader.program, "colour");
Log.d("HELLO", "" + colourAttribute);
GLES20.glEnableVertexAttribArray(colourAttribute);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.coloursHandle);
GLES20.glVertexAttribPointer(colourAttribute, this.colourValuesCount, GLES20.GL_FLOAT, false, 0, 0);
}
if (this.textureData != null) {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.texturesHandle);
GLES20.glEnableVertexAttribArray(texturesAttribute);
GLES20.glVertexAttribPointer(texturesAttribute, this.textureValuesCount, GLES20.GL_FLOAT, false, 0, 0);
}
//Draw the arrays
GLES20.glDrawElements(this.renderMode, indices.length, GLES20.GL_UNSIGNED_SHORT, indicesBuffer);
//Disable the arrays as needed
if (this.normalsData != null)
GLES20.glDisableVertexAttribArray(normalAttribute);
if (this.textureData != null)
GLES20.glDisableVertexAttribArray(texturesAttribute);
if (this.colourData != null)
GLES20.glDisableVertexAttribArray(colourAttribute);
GLES20.glDisableVertexAttribArray(vertexPositionAttribute);
this.androidShader.stopUsing();
}
目前,我還沒有實現法線或紋理的使用,因為我只是想繪制一個三角形,每個頂點的顏色不同。 我知道着色器應該可以正常工作,只要使用相同的着色器僅使用一種顏色以及頂點/顏色數據進行渲染即可。
當我查看LogCat時,消息:GL_INVALID_VALUE已被打印出來。 然后,我決定打印出使用glGetAttribLocation找到的colourAttribute的值,事實證明這是-1。 經過進一步研究,我發現了這一點: https : //www.opengl.org/sdk/docs/man/html/glGetAttribLocation.xhtml ,它指出返回值-1“如果命名屬性變量不是活動屬性在指定的程序對象中”。
搜索Google之后,我還沒有找到解決三角形不渲染問題的方法,因此不勝感激。
謝謝。
它表明vertexAttributePointer方法的跨度始終為0。這意味着您使用顏色值覆蓋了頂點緩沖區中的頂點位置。
GLES20.glVertexAttribPointer(colourAttribute, this.colourValuesCount, GLES20.GL_FLOAT, false, **0**, 0);
您必須將步幅增加之前頂點屬性大小之和的偏移量。 在您的情況4中,由於vertexPosition向量的vec4。 稍后,紋理和法線也是如此。
在這里查看glVertexAttribPointer的定義: http : //androidbook.com/akc/display? url=displaynoteimpurl&ownerUserId=android&reportId= 4229
另外,您可以嘗試向片段着色器添加固定的顏色,例如:
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
因此,可以避免colorHandle對渲染過程產生任何影響。
此外,嘗試避免先使用IndexBuffer而不使用
glDrawElements(.. , ..)
方法只需將vertexBufferObject與
glDrawArrays(.., .., )
方法。
如果可行,您當然可以切換回IndexBuffer方法。
由於評論而更新
我現在看到另一個問題。 您錯過了鏈接着色器並使用glLinkProgram和glUseProgram啟用它的鏈接。 在這里看看: 適用於Android OpenGL ES的着色器
這篇文章還向您展示了如何輸出着色器程序的編譯錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.