Java OpenGL ES 2.0纹理映射问题

Java OpenGL ES 2.0纹理映射问题,java,textures,opengl-es-2.0,Java,Textures,Opengl Es 2.0,我正在使用OpenGL ES 2.0,并试图获得一个基本的纹理立方体.obj,作为Blender模型导入测试的一部分进行渲染 以下是.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.00000

我正在使用OpenGL ES 2.0,并试图获得一个基本的纹理立方体.obj,作为Blender模型导入测试的一部分进行渲染

以下是.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
以下是纹理:

下面是渲染结果:

下面是来自同一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);" +
"}";

非常感谢您的帮助。

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

但是,在渲染网格时,OpenGLES仅使用单个索引缓冲区,因此对于顶点位置、纹理坐标和法线的每个组合,需要在顶点和纹理坐标以及法线数组中有单独的条目

现在看起来您正在将纹理坐标读取到一个数组中,然后将该数组作为浮点缓冲区原样传递给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
(忽略您尚未实际渲染法线的事实)

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


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

进行绘制,您是否考虑到.obj文件格式使用基于1的索引,而OpenGLES使用基于0的索引?是,当我读入索引时,我会将其减去1。如果答案有助于解决您的问题,请将其标记为已接受(单击答案旁边的勾号)