2015-04-12 156 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