I have this problem with the display of my textured VBOs on OpenGLES20 (testing on an android motorola Xoom), where textures would appear as if they were taken from a single dot of the texture instead of the whole thing: some will appear solid gray (this texture of a wall that I use) while others will appear solid white (the android robot.png).
The shader program compiles and links successfully. The model is displayed successfully at the right position, but the textures are not. The buffer that is sent as VBO seems to work well enough, I tested it as a static float[] on the SampleGLSurface tutorial to replace the triangle, and the texture is displayed well with both the robot.png and my with own.
There is no glError message.
I removed pretty much everything in the onSurfaceCreated() and onSurfaceChanged() and narrowed down to a single pack of consecutive GLES20 instructions in the draw frame for the purpose of this question.
The shader is loaded with a
GLES20.glUseProgram(_program);
at the start of the drawFrame() method and does not raise any error.
The vertex shader:
uniform mat4 uMVPMatrix;
attribute vec4 aPosition;
attribute vec2 textureCoord;
varying vec2 tCoord;
void main() {
tCoord = textureCoord;
gl_Position = uMVPMatrix * aPosition;
}
The fragment shader:
precision mediump float;
uniform sampler2D texture0;
varying vec2 tCoord;
void main() {
gl_FragC开发者_JAVA百科olor = texture2D(texture0, tCoord);
}
Rendering code:
if(textureId==null){
textureId = new int[1];
Bitmap img = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.texture0);
GLES20.glGenTextures(1, textureId, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, img, 0);
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
img.recycle();
}
if(!meshisloaded){
objectLoaderVBO = new ObjectLoaderVBO(mesh.getModelName(), mContext);
meshisloaded = true;
}
int vboId = objectLoaderVBO.getVboId();
int iboId = objectLoaderVBO.getIboId();
int sizeInFaces = objectLoaderVBO.getSizeInFaces();
int facesSize = 3;
int FLOAT_SIZE_BYTES = 4;
int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 8 * FLOAT_SIZE_BYTES;
int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
int TRIANGLE_VERTICES_DATA_TEX_OFFSET = 6; // normals are at 3,
// but we don't care about normals
// just for simple texture display
// without culling, right?
int vertexLoc = GLES20.glGetAttribLocation(shaderProgram, "aPosition");
int texCoordLoc = GLES20.glGetAttribLocation(shaderProgram, "textureCoord");
int mMVPMatrixLoc = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix");
int[] textureLocs = null;
textureLocs = new int[1];
textureLocs[0] = GLES20.glGetUniformLocation(shaderProgram, "texture0");
GLES20.glUniformMatrix4fv(mMVPMatrixLoc, 1, false, mMVPMatrix, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId[0]);
GLES20.glUniform1i(textureLocs[0], 0);
GLES20.glEnableVertexAttribArray(vertexLoc);
GLES20.glEnableVertexAttribArray(texCoordLoc);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
GLES20.glVertexAttribPointer(vertexLoc, 3, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES,TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(texCoordLoc, 2, GLES20.GL_FLOAT, true, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, TRIANGLE_VERTICES_DATA_TEX_OFFSET);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, iboId);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, sizeInFaces*facesSize, GLES20.GL_UNSIGNED_SHORT, 0);
GLES20.glDisableVertexAttribArray(vertexLoc);
GLES20.glDisableVertexAttribArray(texCoordLoc);
I've tried a lot of things already, but I'm out of ideas!
The texture coordinate offset you give in glVertexAttribPointer
has to be in bytes, not in components (floats), so it should be 24
, or better 6 * FLOAT_SIZE_BYTES
. So your texture coordinates are just rubbish (taken part from position and part from normal).
And by the way, the normalized flag of glVertexAttribPointer
is only used when supplying integer data, so no need to set it to true
for the texCoords.
精彩评论