2015-04-12 159 views
0

我正在使用OpenGL ES 2.0并尝试获取基本纹理立方体.obj以作为Blender模型的导入测试的一部分进行渲染。OpenGL ES 2.0纹理映射问题

这里是.OBJ:

# Blender v2.63 (sub 0) OBJ File: 'testCube.blend' 
# www.blender.org 
mtllib testCube.mtl 
o Cube 
v -1.000000 -1.000000 1.000000 
v -1.000000 -1.000000 -1.000000 
v 1.000000 -1.000000 -1.000000 
v 1.000000 -1.000000 1.000000 
v -1.000000 1.000000 1.000000 
v -1.000000 1.000000 -1.000000 
v 1.000000 1.000000 -1.000000 
v 1.000000 1.000000 1.000000 
vt 0.250043 0.500000 
vt 0.500000 0.500000 
vt 0.499999 0.749957 
vt 0.250043 0.749956 
vt 0.000087 0.000087 
vt 0.250043 0.000087 
vt 0.250043 0.250043 
vt 0.000087 0.250043 
vt 0.500000 0.000087 
vt 0.500000 0.250043 
vt 0.749956 0.250043 
vt 0.749956 0.000087 
vt 0.499999 0.999913 
vt 0.250042 0.999913 
vn -1.000000 -0.000000 0.000000 
vn 0.000000 0.000000 -1.000000 
vn 1.000000 -0.000000 0.000000 
vn 0.000000 0.000000 1.000000 
vn -0.000000 -1.000000 0.000000 
vn -0.000000 1.000000 0.000000 
usemtl Material 
s off 
f 2/1/1 1/2/1 5/3/1 
f 2/1/1 5/3/1 6/4/1 
f 6/5/2 7/6/2 3/7/2 
f 6/5/2 3/7/2 2/8/2 
f 7/6/3 8/9/3 4/10/3 
f 7/6/3 4/10/3 3/7/3 
f 1/11/4 4/10/4 8/9/4 
f 1/11/4 8/9/4 5/12/4 
f 1/2/5 2/1/5 3/7/5 
f 1/2/5 3/7/5 4/10/5 
f 8/13/6 7/14/6 6/4/6 
f 8/13/6 6/4/6 5/3/6 

这里是质地: http://i1273.photobucket.com/albums/y409/Gamer_217/testcube_zpsf2hhxszq.png

这里是渲染结果: http://i1273.photobucket.com/albums/y409/Gamer_217/TextureBug_zpsjpkb6egv.png

下面是来自同一个Java类代码片段:

全局变量:

private int[] mTextureHandle; 
private int mTextureUniformHandle; 
private int mTextureCoordinateHandle; 
private final int mTextureCoordinateDataSize = 2; 
private float uv[]; 

从OBJ读取UV贴图:

else if(type.compareTo("vt") == 0) 
{ 
    uv[u]=Float.valueOf(line[1]); 
    u++; 
    uv[u]=1.0f-Float.valueOf(line[2]); 
    u++; 
} 

纹理坐标缓冲器和加载BMP:

ByteBuffer tb = ByteBuffer.allocateDirect(uv.length*4); 
tb.order(ByteOrder.nativeOrder()); 
texBuffer = tb.asFloatBuffer(); 
texBuffer.put(uv); 
texBuffer.position(0); 

mTextureHandle = new int[1]; 
GLES20.glGenTextures(1, mTextureHandle, 0); 
BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inScaled = false; 
InputStream in = mgr.open("testcube.bmp"); 
Bitmap bitmap = BitmapFactory.decodeStream(in); 
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureHandle[0]); 
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); 
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); 
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 
bitmap.recycle(); 

绘制函数:

GLES20.glEnable(GLES20.GL_DEPTH_TEST); 
GLES20.glDepthFunc(GLES20.GL_LEQUAL); 
GLES20.glDepthMask(true); 
GLES20.glUseProgram(mProgram); 
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); 
GLES20.glEnableVertexAttribArray(mPositionHandle); 
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer); 

mTextureUniformHandle = GLES20.glGetUniformLocation(mProgram, "uTexture"); 
mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgram, "vTexCoordinate"); 
GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
GLES20.glUniform1i(mTextureUniformHandle, 0); 
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, texBuffer); 
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle); 

mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); 
GLES20.glUniform4fv(mColorHandle, 1, color, 0); 
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); 
GLES20.glDrawElements(GLES20.GL_TRIANGLES, face_v.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer); 
GLES20.glDisableVertexAttribArray(mPositionHandle); 

最后着色器代码:

private final String vertexShaderCode = 
"uniform mat4 uMVPMatrix;" + 
"attribute vec4 vPosition;" + 
"attribute vec2 vTexCoordinate;" + 
"varying vec2 oTexCoordinate;" + 
"void main() {" + 
    "oTexCoordinate = vTexCoordinate;" + 
    " gl_Position = uMVPMatrix * vPosition;" + 
"}"; 
private final String fragmentShaderCode = 
"precision mediump float;" + 
"uniform vec4 vColor;" + 
"uniform sampler2D uTexture;" + 
"varying vec2 oTexCoordinate;" + 
"void main() {" + 
    " gl_FragColor = texture2D(uTexture, oTexCoordinate);" + 
"}"; 

任何帮助表示赞赏。

+0

当您阅读索引时,您是否考虑到.obj文件格式使用基于1的索引,但OpenGLES使用基于0的索引? – samgak

+0

是的,当我读他们时,我减去指数。 – user4780729

回答

1

.obj格式分别存储顶点数据,纹理坐标数据和法线,并为每个格式使用单独的索引。这意味着给定的顶点位置,纹理坐标或法线只会被写出一次,而网格中的不同面可以共享顶点索引,即使它们具有不同的纹理坐标。

然而,OpenGLES渲染网格时只使用一个索引缓冲区,所以你需要在你的顶点和纹理坐标独立的条目和普通数组为顶点的位置每组合,纹理坐标和正常的。

现在看起来您正在读取纹理坐标到数组中,然后将该数组作为float缓冲区原样传递给OpenGLES。问题在于,OpenGLES没有意识到与.obj文件中每个三角形关联的纹理数组中的索引。相反,OpenGLES将在查看纹理坐标时使用顶点索引。

所以你的脸数据,看起来像这样在你的obj文件:

f 2/1/1 1/2/1 5/3/1 
f 2/1/1 5/3/1 6/4/1 
f 6/5/2 7/6/2 3/7/2 

将有效地渲染,如果它是这样的:

f 2/2/2 1/1/1 5/5/5 
f 2/2/2 5/5/5 6/6/6 
f 6/6/6 7/7/7 3/3/3 

(忽略你AREN事实实际上还没有渲染法线)

您需要一个额外的预处理步骤,您可以在其中识别目标文件中每个顶点/纹理坐标/法线的组合。然后为顶点,纹理坐标数据和法线生成单独的数组,每个组合有一个条目(这意味着如果某些顶点位置具有不同的纹理坐标关联,则某些顶点位置将重复多次)。对于v/t/n的给定组合,3个数组中的索引应该匹配。然后根据这些新索引为三角形创建一个索引缓冲区。

另一种选择是根本不使用索引缓冲区。当你加载你的文件时,将你的顶点数据等读入数组中。然后根据三角形数量分配更大的数组,并根据obj文件处理索引,并根据各种索引将相应的顶点/ tex坐标/法线复制到数组中。然后,您将使用glDrawArrays而不是glDrawElements

+0

得到它的工作,谢谢。 – user4780729

+0

如果答案有助于解决您的问题,请将其标记为已接受(单击答案旁边的勾号) – samgak