Android OpenGL es 3D Rubik Cube 多纹理贴图

时间:2022-09-10 21:57:53

以第3个面为例,贴出的参数为:

1
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP,4,GL10.GL_UNSIGNED_BYTE, indices3);

下面详细的说明下第二个参数代表的含义,在网上对于第二个参数的理解有两种说法,一种是要贴的图像(不只局限为平面图行)的顶点的个数,一种是平面的个数乘以每个平面顶点的个数。这里需要注意的是第二种说法才是正确的!由于本例中由于是多纹理映射,每个面对应的材质不同所以按面为单位贴,每个正方形面4个顶点,所以对应的参数为4。

原apidemo中的mIndexBuffer是按照三角形做顶点映射的,具体的可以打LOG查看:
在draw()中添加如下代码即可查看:

1
2
3
4
5
if(count == 0)
       for(int i=0 ; i< 12* 26; ++i)
              Log.i("mindexBuffer","x:"+ Integer.toString(mIndexBuffer.get(i* 3))+ " y: "    
                                               + Integer.toString(mIndexBuffer.get(i*3 + 1))+ " z: "
                                               + Integer.toString(mIndexBuffer.get(i*3 + 2)));

2.关于纹理坐标的问题。
由于opengl es没有自动生成纹理坐标的函数(opengl有),需要自己定义纹理坐标。
常见的纹理坐标有两种单位:

1
2
gl.glTexCoordPointer(2, GL10.GL_FLOAT,0, mTextureBuffer);  //floatbuffer类型。以1.0为单位
gl.glTexCoordPointer(2, GL10.GL_GL_FIXED,0, mTextureBufferFront); //像素intbuffer类型的。以0x1000即65536为单位。

关于纹理坐标的写法详见我上面发的url。
这里有个非常重要的问题就是顶点坐标的坐标映射对纹理坐标同样有效,也就是说上面提到的indices1,indices2,indices3,indices4,indices5,indices6对纹理坐标同样有效。这样我们得到的第一个小立方体对应的六个面的textureBuffer分别为:

1
2
3
4
5
6
mTextureBufferFront = FloatBuffer.wrap(newfloat[]{ 0, 0,0, 0, 0,0, 0, 0,0, 1, 1,1, 0, 0,1, 0,});
mTextureBufferBack = FloatBuffer.wrap(newfloat[]{ 1, 1,0, 1, 1,0, 0, 0,0, 0, 0,0, 0, 0,0, 0,});
mTextureBufferLeft = FloatBuffer.wrap(newfloat[]{ 0, 1,0, 0, 0,0, 0, 0,1, 1, 0,0, 1, 0,0, 0,});
mTextureBufferRight = FloatBuffer.wrap(newfloat[]{ 0, 0,1, 1, 0,0, 1, 0,0, 0, 0,1, 0, 0,0, 0,});
mTextureBufferTop = FloatBuffer.wrap(newfloat[]{ 0, 0,0, 0, 1,1, 0, 1,0, 0, 0,0, 1, 0,0, 0,});
mTextureBufferBottom = FloatBuffer.wrap(newfloat[]{0, 1,1, 1, 0,0, 0, 0,0, 0, 1,0, 0, 0,0, 0,});

3.虚拟机可以正常加载图片,但是真机无法加载图片
不知道是不是内部设计的缺陷,opengl es只能加载名为drawable文件下图片,高中低像素文件夹drawable-hdpi,drawable-mdpi,drawable-ldpi问价下的图片都无法加载;
而且图片最好是png或者bmp,jpg格式的图片由于位深原因可能无法正常贴图;
图片必须得是n^2大小的;
常量的话最好使用GL10而不是GL11;
顶点坐标缓存,纹理坐标缓存,索引缓存如果不是native型直接的缓存,会在较高版本的真机运行时出现:
“called a GL11 Pointer method with an indirect Buffer. ” 的错误。以纹理坐标为例,正确的写法必须是:

1
2
3
bb = ByteBuffer.allocateDirect(num* 4);
bb.order(ByteOrder.nativeOrder());
mTextureBufferFront = bb.asFloatBuffer();

以上,欢迎相互交流学习!
附上运行效果图:
Android OpenGL es 3D Rubik Cube 多纹理贴图Android OpenGL es 3D Rubik Cube 多纹理贴图