如何解决使用 GLES30 的 VAO 渲染:偏移量 / len 错误!!!!!!错误
在 Android 上尝试在 GLES30 中使用 VAO 渲染立方体时,我收到以下错误消息:
D/emuglGLESv2_enc: sendVertexAttributes: bad offset / len!!!!!
有人知道这是什么意思以及如何解决吗?我在任何地方都找不到它的任何文档,并且函数的行为不像它们在普通 java 中的 lwjgl 中所做的那样。这是我的渲染类:
/**
* renders an object
* @param object - the mesh object to be rendered
*/
public void renderMesh(MeshObject object) {
// bind the vertex array
GLES30.glBindVertexArray(object.getMesh().getVAO()[0]);
// get the attrib pointers
int pAttrib = GLES30.glGetAttribLocation(shaderProgramID,"vPosition");
int nAttrib = GLES30.glGetAttribLocation(shaderProgramID,"vnormal");
int tAttrib = GLES30.glGetAttribLocation(shaderProgramID,"vTextureCoords");
// enable the attributes
GLES30.glEnabLevertexAttribArray(pAttrib); // position attribute
GLES30.glEnabLevertexAttribArray(nAttrib); // normal attribute
GLES30.glEnabLevertexAttribArray(tAttrib); // texture attribute
// send empty data
GLES30.glVertexAttribPointer(pAttrib,3,GLES30.GL_FLOAT,false,3 * 4,0);
GLES30.glVertexAttribPointer(nAttrib,0);
GLES30.glVertexAttribPointer(tAttrib,2,2 * 4,0);
// bind the index buffer
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,object.getMesh().getIBO()[0]);
// bind the shader
GLES30.gluseProgram(shaderProgramID);
// bind the texture
GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D,object.getMesh().getTextureID());
// get pointers to the uniform locations
int viewPositionHandle = GLES30.glGetUniformlocation(shaderProgramID,"viewPos");
int mHandle = GLES30.glGetUniformlocation(shaderProgramID,"vModel");
int vHandle = GLES30.glGetUniformlocation(shaderProgramID,"vView");
int pHandle = GLES30.glGetUniformlocation(shaderProgramID,"vProjection");
// set the uniforms
GLES30.gluniform3fv(viewPositionHandle,1,camera.getPosition().toFloatArray(),0);
GLES30.gluniformMatrix4fv(mHandle,object.getModelMatrix(),0);
GLES30.gluniformMatrix4fv(vHandle,camera.getViewMatrix(),0);
GLES30.gluniformMatrix4fv(pHandle,surfaceRenderer.getProjectionMatrix(),0);
// draw the triangles specified by the index buffer
GLES30.glDrawElements(GLES30.GL_TRIANGLES,object.getMesh().getIndices().length,GLES30.GL_UNSIGNED_INT,0);
// unbind the shader
GLES30.gluseProgram(0);
// unbind the index buffer
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,0);
// disable the vertex attributes
GLES30.gldisabLevertexAttribArray(pAttrib); // position attribute
GLES30.gldisabLevertexAttribArray(nAttrib); // normal attribute
GLES30.gldisabLevertexAttribArray(tAttrib); // texture attribute
// unbind the vertex array
GLES30.glBindVertexArray(0);
}
这是我的网格类:
package com.bramerlabs.productivitree.graphics_engine.graphics;
import android.opengl.GLES30;
import com.bramerlabs.productivitree.graphics_engine.math.Vertex;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
public class Mesh {
// the vertex array object
private final int[] vao = new int[1];
// the buffer objects
private final int[] pbo = new int[1]; // position buffer object
private final int[] nbo = new int[1]; // normal buffer object
private final int[] tbo = new int[1]; // texture buffer object
private final int[] ibo = new int[1]; // index buffer object
private final Vertex[] vertices;
private final int[] indices;
private final int textureID;
/**
* default constructor
*
* @param vertices - a list of vertices in the mesh
* @param indices - the order in which the vertices should be drawn
*/
public Mesh(Vertex[] vertices,int[] indices,int textureID) {
this.vertices = vertices;
this.indices = indices;
this.textureID = textureID;
}
/**
* creates the mesh
*/
public void create() {
// generate and bind the vertex array
GLES30.glGenVertexArrays(1,vao,0);
GLES30.glBindVertexArray(vao[0]);
// generate the data arrays
// generate the position buffer object
float[] positionData = new float[vertices.length * 3];
for (int i = 0; i < vertices.length; i++) {
positionData[3 * i] = vertices[i].getPosition().getX();
positionData[3 * i + 1] = vertices[i].getPosition().getY();
positionData[3 * i + 2] = vertices[i].getPosition().getZ();
}
FloatBuffer positionBuffer = createFloatBuffer(positionData,3);
// generate the normal buffer object
float[] normalData = new float[vertices.length * 3];
for (int i = 0; i < vertices.length; i++) {
positionData[3 * i] = vertices[i].getnormal().getX();
positionData[3 * i + 1] = vertices[i].getnormal().getY();
positionData[3 * i + 2] = vertices[i].getnormal().getZ();
}
FloatBuffer normalBuffer = createFloatBuffer(normalData,3);
// generate the texture buffer object
float[] textureData = new float[vertices.length * 2];
for (int i = 0; i < vertices.length; i++) {
textureData[2 * i] = vertices[i].getTextureCoord().getX();
textureData[2 * i + 1] = vertices[i].getTextureCoord().getY();
}
FloatBuffer textureBuffer = createFloatBuffer(textureData,2);
// generate the index buffer object
ByteBuffer bb = ByteBuffer.allocateDirect(indices.length * 4);
bb.order(ByteOrder.nativeOrder());
IntBuffer indexBuffer = bb.asIntBuffer();
indexBuffer.put(indices).flip();
indexBuffer.position(0);
// store the data
storeData(pbo,positionBuffer,3);
storeData(nbo,normalBuffer,3);
storeData(tbo,textureBuffer,2);
// create the index buffer
GLES30.glGenBuffers(1,ibo,0);
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,ibo[0]);
GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,indexBuffer.capacity(),indexBuffer,GLES30.GL_STATIC_DRAW);
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,0);
}
/**
* stores buffer data in an index
*/
private void storeData(int[] location,FloatBuffer buffer,int index,int size) {
// generate a buffer at the location
GLES30.glGenBuffers(1,location,0);
// bind the buffer
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,location[0]);
// add the data to the buffer
GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,buffer.capacity(),buffer,GLES30.GL_STATIC_DRAW);
// set the data type attribute
GLES30.glVertexAttribPointer(index,size,0);
// unbind the buffer
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,0);
}
/**
* creates a buffer
* @param data - a float array of data
* @param stride - the stride of the data
* @return - a float buffer containing the data
*/
private FloatBuffer createFloatBuffer(float[] data,int stride) {
// initialize empty float buffer
ByteBuffer bb = ByteBuffer.allocateDirect(data.length * stride * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer dataBuffer = bb.asFloatBuffer();
// add the data to the float buffer and flip it
dataBuffer.put(data).flip();
// seek to the first position
dataBuffer.position(0);
return dataBuffer;
}
/**
* getter method
* @return - the position buffer object
*/
public int[] getPBO() {
return this.pbo;
}
/**
* getter method
* @return - the normal buffer object
*/
public int[] getNBO() {
return this.nbo;
}
/**
* getter method
* @return - the texture buffer object
*/
public int[] getTBO() {
return this.tbo;
}
/**
* getter method
* @return - the index buffer object
*/
public int[] getIBO() {
return this.ibo;
}
/**
* getter method
* @return - the vertex array object
*/
public int[] getVAO() {
return this.vao;
}
/**
* getter method
* @return - the draw order
*/
public int[] getIndices() {
return this.indices;
}
/**
* getter method
* @return - the vertices
*/
public Vertex[] getVertices() {
return this.vertices;
}
public int getTextureID() {
return this.textureID;
}
}
解决方法
glBufferData
的第二个参数是缓冲区的大小以字节为单位,但不是数组中元素的数量。FloatBuffer
或 IntBuffer
中元素的字节大小为 4:
GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,buffer.capacity(),buffer,GLES30.GL_STATIC_DRAW);
GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,buffer.capacity() * 4,GLES30.GL_STATIC_DRAW);
GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,indexBuffer.capacity(),indexBuffer,indexBuffer.capacity() * 4,GLES30.GL_STATIC_DRAW);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。