Android glDrainElements()仅绘制前两个面
已解决。问题解决方案:Android glDrainElements()仅绘制前两个面,android,opengl-es,opengl-es-2.0,google-cardboard,Android,Opengl Es,Opengl Es 2.0,Google Cardboard,已解决。问题解决方案:attribStride未正确设置 我正在编写一个小的谷歌纸板应用程序,它可以加载和渲染任何Wavefront.obj文件,并在链接的.mtl文件中显示其表面的材质属性。对于渲染,我使用VBO和IBO。对于表面和闪电的材质属性,我使用phong着色 我的问题是,glpaurements()只渲染立方体的前两个三角形,立方体由12个三角形组成 构成立方体的所有三角形都是逆时针设置的 通过解析.obj文件生成的顶点数组和索引数组数据是有效的 VBO的客户端FloatBuffe
attribStride
未正确设置
我正在编写一个小的谷歌纸板应用程序,它可以加载和渲染任何Wavefront.obj文件,并在链接的.mtl文件中显示其表面的材质属性。对于渲染,我使用VBO和IBO。对于表面和闪电的材质属性,我使用phong着色
我的问题是,glpaurements()
只渲染立方体的前两个三角形,立方体由12个三角形组成
- 构成立方体的所有三角形都是逆时针设置的
- 通过解析.obj文件生成的顶点数组和索引数组数据是有效的
- VBO的客户端FloatBuffer和IBO的客户端ShortBuffer的数据和长度有效
设置的VBO和IBO的长度有效glBufferData()
- 着色器已正确编译和附着
- 通过
和glGetAttriblLocation()
为着色器设置的所有属性和统一位置均有效glGetUniformLocation()
private void initializeGL() {
Log.i(TAG, "initializeGL()");
// Set camera matrix.
Matrix.setLookAtM(camera, OFFSET, EYE_POINT_X, EYE_POINT_Y, EYE_POINT_Z, CENTER_OF_VIEW_X, CENTER_OF_VIEW_Y, CENTER_OF_VIEW_Z, UP_VECTOR_X, UP_VECTOR_Y, UP_VECTOR_Z);
// Initialize shader program.
shaderProgram.init();
shaderProgramHandle = shaderProgram.getProgramHandle();
// Initialize object information.
objectInformation.init();
vboHandle = objectInformation.getVbo().getVboHandle();
vboLength = objectInformation.getVbo().getVboLength();
iboHandle = objectInformation.getIbo().getIboHandle();
iboLength = objectInformation.getIbo().getIboLength();
uniforms = objectInformation.getUniformArray();
numOfUniforms = objectInformation.getNumOfUniforms();
Log.i(TAG, "initializeGL(): Number of uniforms = " + numOfUniforms);
textures = objectInformation.getTextureArray();
numOfTextures = objectInformation.getNumOfTextures();
Log.i(TAG, "initializeGL(): Number of textures = " + numOfTextures);
// Get vertex shader uniform locations.
modelViewProjectionParam = GLES20.glGetUniformLocation(shaderProgramHandle, "u_ModelViewProjection");
Log.i(TAG, "initializeGL(): modelViewProjectionParam = " + modelViewProjectionParam);
modelViewParam = GLES20.glGetUniformLocation(shaderProgramHandle, "u_ModelView");
Log.i(TAG, "initializeGL(): modelViewParam = " + modelViewParam);
normalMatrixParam = GLES20.glGetUniformLocation(shaderProgramHandle, "u_NormalMatrix");
Log.i(TAG, "initializeGL(): normalMatrixParam = " + normalMatrixParam);
// Get vertex shader attribute locations.
positionParam = GLES20.glGetAttribLocation(shaderProgramHandle, "a_Position");
Log.i(TAG, "initializeGL(): positionParam = " + positionParam);
if(boolTexCoords) {
attribStride += 4 * BYTES_PER_FLOAT;
texCoordParam = GLES20.glGetAttribLocation(shaderProgramHandle, "a_TexCoord");
Log.i(TAG, "initializeGL(): texCoordParam = " + texCoordParam);
}
normalParam = GLES20.glGetAttribLocation(shaderProgramHandle, "a_Normal");
Log.i(TAG, "initializeGL(): normalParam = " + normalParam);
// Get fragment shader phong uniform locations.
if(boolPhongLightning) {
lightPosParam = GLES20.glGetUniformLocation(shaderProgramHandle, "lightPosition");
Log.i(TAG, "initializeGL(): lightPosParam = " + lightPosParam);
IaParam = GLES20.glGetUniformLocation(shaderProgramHandle, "Ia");
Log.i(TAG, "initializeGL(): IaParam = " + IaParam);
IpParam = GLES20.glGetUniformLocation(shaderProgramHandle, "Ip");
Log.i(TAG, "initializeGL(): IpParam = " + IpParam);
}
// Set fragment shader material uniforms.
GLES20.glUseProgram(shaderProgramHandle);
for(int i = 0; i < numOfUniforms; i++) {
String unifName = uniforms[i].getUnifName();
location = GLES20.glGetUniformLocation(shaderProgramHandle, unifName);
checkGLError(TAG, "initializeGL(): " + unifName + " shader location");
vec = uniforms[i].getArray();
if(vec != null) {
GLES20.glUniform3fv(location, 1, vec, 0);
Log.i(TAG, "initializeGL(): " + unifName + "_Param = " + location);
} else {
float value = uniforms[i].getValue();
GLES20.glUniform1f(location, value);
Log.i(TAG, "initializeGL(): " + unifName + "_Param = " + location);
}
}
// Set fragment shader phong uniforms.
if(boolPhongLightning) {
GLES20.glUniform3fv(IaParam, 1, Ia, 0);
GLES20.glUniform3fv(IpParam, 1, Ip, 0);
}
// Set fragment shader textures.
for(int i = 0; i < numOfTextures; i++) {
// Set active texture unit.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);
// Bind texture to active texture unit.
int texHandle = textures[i].getTextureHandle();
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texHandle);
// Assign texture unit to uniform in fragment shader.
String unifName = textures[i].getUnifName();
location = GLES20.glGetUniformLocation(shaderProgramHandle, unifName);
GLES20.glUniform1i(location, i);
checkGLError(TAG, "initializeGL(): glUniform1i()");
Log.i(TAG, "initializeGL(): " + unifName + "Param = " + location);
}
GLES20.glUseProgram(0);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthFunc(GLES20.GL_LESS);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glFrontFace(GLES20.GL_CCW);
GLES20.glCullFace(GLES20.GL_BACK);
GLES20.glClearColor(0.3f, 0.3f, 0.3f, 0.1f);
}
私人作废提款():
编辑:
类RPVBO和RPIBO。有趣的部分是init()方法:
公共最终类RPVBO{
私有静态最终字符串TAG=“RPVBO”;
私有静态最终整数字节/FLOAT=4;
私有int[]VBO句柄;
私有向量顶点;
专用的国际标准长度;
公共RPVBO(){
Log.i(标记“Constructor()”);
vboHandles=null;
顶点=新向量();
vboLength=0;
}
公共void init(){
Log.i(标记“init()”);
如果((vboHandles!=null)和&(vboHandles[0]!=0)){
返回;
}
vboHandles=新整数[1];
GLES20.glGenBuffers(1,vboHandles,0);
如果(vboHandles[0]!=0){
float[]vertexArray=getVertexArray();
FloatBuffer clientSideBuffer=ByteBuffer.allocateDirect(vertexArray.length*字节/浮点数).order(ByteOrder.nativeOrder()).asFloatBuffer();
clientSideBuffer.position(0);
clientSideBuffer.put(vertexArray);
clientSideBuffer.position(0);
if(clientSideBuffer.capacity()!=vertexArray.length){
e(标记“init():创建客户端浮动缓冲区时出错”);
抛出新的RuntimeException(“错误:“+TAG+”init():创建客户端浮动缓冲区时出错”);
}
GLES20.glBindBuffer(GLES20.GL_数组_BUFFER,vboHandles[0]);
GLES20.glBufferData(GLES20.GL_数组_BUFFER,clientSideBuffer.capacity()*字节/u浮点,clientSideBuffer,GLES20.GL_静态_DRAW);
checkleror(标记,“init():glBufferData()”;
int[]参数=新的int[2];
GLES20.glGetBufferParameteriv(GLES20.GL_数组_BUFFER,GLES20.GL_BUFFER_SIZE,params,0);
checkelError(标记,“init():glGetBufferParameteriv()”;
GLES20.glGetBufferParameteriv(GLES20.GL_数组_BUFFER,GLES20.GL_BUFFER_用法,参数,1);
checkelError(标记,“init():glGetBufferParameteriv()”;
GLES20.glBindBuffer(GLES20.GL_数组_BUFFER,0);
if(参数[0]!=(clientSideBuffer.capacity()*字节/浮点数)){
e(标记“init():设置OpenGL VBO数据时出错”);
抛出新的运行时异常(“错误:“+TAG+”:init():设置OpenGL VBO数据时出错”);
}
i(标记“init():OpenGL VBO句柄:”+vboHandles[0]);
Log.i(标记“init():OpenGL VBO大小(字节):+params[0]);
开关(参数[1]){
案例GLES20.GL_流_图:
i(标记“init():OpenGL VBO用法:GL_STREAM_DRAW”);
打破
案例20.GL\U静态\U绘图:
i(标记“init():OpenGL VBO用法:GL_STATIC_DRAW”);
打破
案例20.GL\u动态\u绘图:
i(标记,“init():OpenGL VBO用法:GL_DYNAMIC_DRAW”);
}
顶点。清除();
}
if(vboHandles[0]==0){
e(标记“init():在OpenGL中创建VBO时出错”);
抛出新的RuntimeException(“错误:“+TAG+”init():在OpenGL中创建VBO时出错”);
}
}
公共无效附加值(最终浮动值){
顶点。添加(值);
++vboLength;
}
公共无效附加值(最终浮动值){
顶点。添加(值);
++vboLength;
}
公共void addArray(最终浮点[]数组){
最终整数数组长度=array.length;
对于(int i=0;i
公共最终类RPIBO{
私有静态最终字符串TAG=“RPIBO”;
私有静态最终整型字节\u每\u短=
@Override
public void onDrawEye(Eye eye) {
Log.i(TAG, "onDrawEye()");
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
projection = eye.getPerspective(Z_NEAR, Z_FAR);
Matrix.multiplyMM(view, 0, eye.getEyeView(), 0, camera, 0);
Matrix.multiplyMM(modelView, 0, view, 0, modelMatrix, 0);
Matrix.multiplyMM(modelViewProjection, 0, projection, 0, modelView, 0);
Matrix.multiplyMV(lightPosInEyeSpace, 0, view, 0, lightPosInWorldSpace, 0);
normalMatrix = RPMath.getNormalMatrix3x3(modelView);
draw();
}
private void draw() {
Log.i(TAG, "draw()");
// Bind shader program, VBO and IBO.
GLES20.glUseProgram(shaderProgramHandle);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboHandle);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, iboHandle);
// Set vertex shader uniforms.
GLES20.glUniformMatrix4fv(modelViewProjectionParam, 1, false, modelViewProjection, 0);
GLES20.glUniformMatrix4fv(modelViewParam, 1, false, modelView, 0);
GLES20.glUniformMatrix3fv(normalMatrixParam, 1, false, normalMatrix, 0);
if(boolPhongLightning) { // fragment shader uniforms.
vec = new float[3];
vec[0] = lightPosInEyeSpace[0];
vec[1] = lightPosInEyeSpace[1];
vec[2] = lightPosInEyeSpace[2];
GLES20.glUniform3fv(lightPosParam, 1, vec, 0);
}
// Set vertex attribute pointers.
attribOffset = 0;
GLES20.glVertexAttribPointer(positionParam, 4, GLES20.GL_FLOAT, false, attribStride, attribOffset);
if(boolTexCoords) {
attribOffset += 4 * BYTES_PER_FLOAT;
GLES20.glVertexAttribPointer(texCoordParam, 4, GLES20.GL_FLOAT, false, attribStride, attribOffset);
}
attribOffset += 4 * BYTES_PER_FLOAT;
GLES20.glVertexAttribPointer(normalParam, 4, GLES20.GL_FLOAT, false, attribStride, attribOffset);
// Enable vertex attribute arrays.
GLES20.glEnableVertexAttribArray(positionParam);
if(boolTexCoords) {
GLES20.glEnableVertexAttribArray(texCoordParam);
}
GLES20.glEnableVertexAttribArray(normalParam);
// Draw.
GLES20.glDrawElements(GLES20.GL_TRIANGLES, iboLength, GLES20.GL_UNSIGNED_SHORT, 0);
// Disable vertex attribute arrays.
GLES20.glDisableVertexAttribArray(positionParam);
if(boolTexCoords) {
GLES20.glDisableVertexAttribArray(texCoordParam);
}
GLES20.glDisableVertexAttribArray(normalParam);
// Unbind shader program, VBO and IBO.
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
GLES20.glUseProgram(0);
}
public final class RPVBO {
private static final String TAG = "RPVBO";
private static final int BYTES_PER_FLOAT = 4;
private int[] vboHandles;
private Vector<Float> vertices;
private int vboLength;
public RPVBO() {
Log.i(TAG, "Constructor()");
vboHandles = null;
vertices = new Vector();
vboLength = 0;
}
public void init() {
Log.i(TAG, "init()");
if((vboHandles != null) && (vboHandles[0] != 0)) {
return;
}
vboHandles = new int[1];
GLES20.glGenBuffers(1, vboHandles, 0);
if(vboHandles[0] != 0) {
float[] vertexArray = getVertexArray();
FloatBuffer clientSideBuffer = ByteBuffer.allocateDirect(vertexArray.length * BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
clientSideBuffer.position(0);
clientSideBuffer.put(vertexArray);
clientSideBuffer.position(0);
if(clientSideBuffer.capacity() != vertexArray.length) {
Log.e(TAG, "init(): Error creating client side Floatbuffer.");
throw new RuntimeException("Error: " + TAG + "init(): Error creating client side Floatbuffer.");
}
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboHandles[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, clientSideBuffer.capacity() * BYTES_PER_FLOAT, clientSideBuffer, GLES20.GL_STATIC_DRAW);
MainActivity.checkGLError(TAG, "init(): glBufferData()");
int[] params = new int[2];
GLES20.glGetBufferParameteriv(GLES20.GL_ARRAY_BUFFER, GLES20.GL_BUFFER_SIZE, params, 0);
MainActivity.checkGLError(TAG, "init(): glGetBufferParameteriv()");
GLES20.glGetBufferParameteriv(GLES20.GL_ARRAY_BUFFER, GLES20.GL_BUFFER_USAGE, params, 1);
MainActivity.checkGLError(TAG, "init(): glGetBufferParameteriv()");
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
if(params[0] != (clientSideBuffer.capacity() * BYTES_PER_FLOAT)) {
Log.e(TAG, "init(): Error setting OpenGL VBO data.");
throw new RuntimeException("Error: " + TAG + ": init(): Error setting OpenGL VBO data.");
}
Log.i(TAG, "init(): OpenGL VBO handle: " + vboHandles[0]);
Log.i(TAG, "init(): OpenGL VBO size in Bytes: " + params[0]);
switch(params[1]) {
case GLES20.GL_STREAM_DRAW:
Log.i(TAG, "init(): OpenGL VBO usage: GL_STREAM_DRAW.");
break;
case GLES20.GL_STATIC_DRAW:
Log.i(TAG, "init(): OpenGL VBO usage: GL_STATIC_DRAW.");
break;
case GLES20.GL_DYNAMIC_DRAW:
Log.i(TAG, "init(): OpenGL VBO usage: GL_DYNAMIC_DRAW.");
}
vertices.clear();
}
if(vboHandles[0] == 0) {
Log.e(TAG, "init(): Error creating VBO in OpenGL.");
throw new RuntimeException("Error: " + TAG + "init(): Error creating VBO in OpenGL.");
}
}
public void addValue(final float value) {
vertices.add(value);
++vboLength;
}
public void addValue(final Float value) {
vertices.add(value);
++vboLength;
}
public void addArray(final float[] array) {
final int arrayLength = array.length;
for(int i = 0; i < arrayLength; i++) {
vertices.add(array[i]);
++vboLength;
}
}
public void addArray(final Float[] array) {
final int arrayLength = array.length;
for(int i = 0; i < arrayLength; i++) {
vertices.add(array[i]);
++vboLength;
}
}
public int getVboHandle() {
if(vboHandles == null) {
return 0;
}
return vboHandles[0];
}
@Nullable
public float[] getVertexArray() {
float[] array = new float[vertices.size()];
for(int i = 0; i < vertices.size(); i++) {
array[i] = vertices.get(i);
}
return array;
}
public int getVboLength() {
return vboLength;
}
}
public final class RPIBO {
private static final String TAG = "RPIBO";
private static final int BYTES_PER_SHORT = 2;
private int[] iboHandles;
private Vector<Short> indices;
private int iboLength;
public RPIBO() {
Log.i(TAG, "Constructor()");
iboHandles = null;
indices = new Vector();
iboLength = 0;
}
public void init() {
Log.i(TAG, "init()");
if((iboHandles != null) && (iboHandles[0] != 0)) {
return;
}
iboHandles = new int[1];
GLES20.glGenBuffers(1, iboHandles, 0);
if(iboHandles[0] != 0) {
short[] indexArray = getIndexArray();
ShortBuffer clientSideBuffer = ByteBuffer.allocateDirect(indexArray.length * BYTES_PER_SHORT).order(ByteOrder.nativeOrder()).asShortBuffer();
clientSideBuffer.position(0);
clientSideBuffer.put(indexArray);
clientSideBuffer.position(0);
if(clientSideBuffer.capacity() != indexArray.length) {
Log.e(TAG, "init(): Error creating client side Shortbuffer.");
throw new RuntimeException("Error: " + TAG + "init(): Error creating client side Shortbuffer.");
}
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, iboHandles[0]);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, clientSideBuffer.capacity() * BYTES_PER_SHORT, clientSideBuffer, GLES20.GL_STATIC_DRAW);
MainActivity.checkGLError(TAG, "init(): glBufferData()");
int[] params = new int[2];
GLES20.glGetBufferParameteriv(GLES20.GL_ELEMENT_ARRAY_BUFFER, GLES20.GL_BUFFER_SIZE, params, 0);
MainActivity.checkGLError(TAG, "init(): glGetBufferParameteriv()");
GLES20.glGetBufferParameteriv(GLES20.GL_ELEMENT_ARRAY_BUFFER, GLES20.GL_BUFFER_USAGE, params, 1);
MainActivity.checkGLError(TAG, "init(): glGetBufferParameteriv()");
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
if(params[0] != (clientSideBuffer.capacity() * BYTES_PER_SHORT)) {
Log.e(TAG, "init(): Error setting OpenGL IBO data.");
throw new RuntimeException("Error: " + TAG + ": init(): Error setting OpenGL IBO data.");
}
Log.i(TAG, "init(): OpenGL IBO handle: " + iboHandles[0]);
Log.i(TAG, "init(): OpenGL IBO size in Bytes: " + params[0]);
switch(params[1]) {
case GLES20.GL_STREAM_DRAW:
Log.i(TAG, "init(): OpenGL IBO usage: GL_STREAM_DRAW.");
break;
case GLES20.GL_STATIC_DRAW:
Log.i(TAG, "init(): OpenGL IBO usage: GL_STATIC_DRAW.");
break;
case GLES20.GL_DYNAMIC_DRAW:
Log.i(TAG, "init(): OpenGL IBO usage: GL_DYNAMIC_DRAW.");
}
indices.clear();
}
if(iboHandles[0] == 0) {
Log.e(TAG, "init(): Error creating IBO in OpenGL.");
throw new RuntimeException("Error: " + TAG + "init(): Error creating IBO in OpenGL.");
}
}
public void addValue(final short value) {
indices.add(value);
++iboLength;
}
public void addValue(final Short value) {
indices.add(value);
++iboLength;
}
public void addArray(final short[] array) {
final int arrayLength = array.length;
for(int i = 0; i < arrayLength; i++) {
indices.add(array[i]);
++iboLength;
}
}
public void addArray(final Short[] array) {
final int arrayLength = array.length;
for(int i = 0; i < arrayLength; i++) {
indices.add(array[i]);
++iboLength;
}
}
public int getIboHandle() {
if(iboHandles == null) {
return 0;
}
return iboHandles[0];
}
@Nullable
public short[] getIndexArray() {
short[] array = new short[indices.size()];
for(int i = 0; i < indices.size(); i++) {
array[i] = indices.get(i);
}
return array;
}
public int getIboLength() {
return iboLength;
}
}
vx, vy, vz, 1.0, s, t, 0.0, 1.0, nx, ny, nz, 1.0