OpenGL ES (3):平面图形-表面纹理贴图

匿名 (未验证) 提交于 2019-12-02 22:56:40

1.简介


上一篇已经将一个平面图形绘制出来了,这一次我们将在上一次绘制出来的图形的表面上进行纹理贴图。

图片准备:(宽高须为2的N次方

最终图片是以Bitmap形式。现在考虑如何把这张图片映射到绘制的平面上?

纹理坐标数据以图片左上角为(0,0),右下角为(1,1)为基础

上一篇文章已经知道,面数组为{0,1,2,3,4,5}绘制,所以要给组成面的每个顶点,映射一个纹理坐标数据,如下:

float[]{

0f,0f , 1f,1f , 1f,0f

}

这样一张图片就全部映射到绘制的平面上了。

2.代码


 public class OtherShader implements GLSurfaceView.Renderer{     FloatBuffer vertextBuffer; //纹理坐标数据     FloatBuffer textureBuffer;     ByteBuffer faceBuffer;     private float roate; //使用的纹理     int texture;     Context context;      public OtherShader(Context context) {         this.context = context;         vertextBuffer = floatArray2Buffer(vertex);         faceBuffer = ByteBuffer.wrap(face);         textureBuffer = floatArray2Buffer(text);     }      float[] vertex = new float[]{             -0.5f , 0.5f , 0f ,             -0.5f , -0.5f , 0f ,             0.5f , -0.5f , 0f ,             -0.5f , 0.5f , 0f ,             0.5f , -0.5f , 0f ,             0.5f , 0.5f , 0f     };      byte[] face = new byte[]{             0,1,2,             3,4,5     };  //纹理坐标数据     float[] text = {             0f,0f , 0f,1f , 1f,1f,             0f,0f , 1f,1f , 1f,0f     };      //将顶点颜色数组转换为IntBuffer,是OpenGl ES所需要的,可以不设置顶点颜色     private IntBuffer intArray2Buffer(int[] rect1color) {         IntBuffer intBuffer;         //不用该方法得到IntBuffer,因为Android平台限制,Buffer必须为native Buffer,所以要通过allocateDirect()创建         //并且该Buffer必须是排序的,所以要order()方法进行排序         //intBuffer = IntBuffer.wrap(rect1color);         //因为一个int=4字节         ByteBuffer bb = ByteBuffer.allocateDirect(rect1color.length * 4);         bb.order(ByteOrder.nativeOrder());         intBuffer = bb.asIntBuffer();         intBuffer.put(rect1color);         intBuffer.position(0); //移到第一个点的数据         return intBuffer;     }      //将顶点位置数组转换为FloatBuffer,是OpenGl ES所需要的     private FloatBuffer floatArray2Buffer(float[] rect1) {         FloatBuffer floatBuffer;         //不用该方法得到FloatBuffer,因为Android平台限制,Buffer必须为native Buffer,所以要通过allocateDirect()创建         //并且该Buffer必须是排序的,所以要order()方法进行排序         //floatBuffer = FloatBuffer.wrap(rect1);         //因为一个int=4字节         ByteBuffer bb = ByteBuffer.allocateDirect(rect1.length * 4);         bb.order(ByteOrder.nativeOrder());         floatBuffer = bb.asFloatBuffer();         floatBuffer.put(rect1);         floatBuffer.position(0); //移到第一个点的数据         return floatBuffer;     }      @Override     public void onSurfaceCreated(GL10 gl, EGLConfig config) {         //关闭抗抖动         gl.glDisable(GL10.GL_DITHER);         //修正系统透视         gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT , GL10.GL_FASTEST);         //设置阴影平滑模式         gl.glShadeModel(GL10.GL_SMOOTH);         //启用深度测试 记录Z轴深度         gl.glEnable(GL10.GL_DEPTH_TEST);         //设置深度测试的类型         gl.glDepthFunc(GL10.GL_LEQUAL);          //*******启用2D纹理*************         gl.glEnable(GL10.GL_TEXTURE_2D);         //加载纹理         loadTexture(gl);     }      private void loadTexture(GL10 gl) {         Bitmap bitmap = null;         bitmap = BitmapFactory.decodeResource(context.getResources() , R.drawable.bj);         int[] textures = new int[1];         gl.glGenTextures(1 , textures , 0);         texture = textures[0];         gl.glBindTexture(GL10.GL_TEXTURE_2D , texture);         gl.glTexParameterf(GL10.GL_TEXTURE_2D , GL10.GL_TEXTURE_MIN_FILTER , GL10.GL_NEAREST);         gl.glTexParameterf(GL10.GL_TEXTURE_2D , GL10.GL_TEXTURE_MAG_FILTER , GL10.GL_LINEAR);         gl.glTexParameterf(GL10.GL_TEXTURE_2D , GL10.GL_TEXTURE_WRAP_S , GL10.GL_REPEAT);         gl.glTexParameterf(GL10.GL_TEXTURE_2D , GL10.GL_TEXTURE_WRAP_T , GL10.GL_REPEAT);         GLUtils.texImage2D(GL10.GL_TEXTURE_2D , 0 , bitmap , 0);         if (bitmap != null){             bitmap.recycle();         }     }      @Override     public void onSurfaceChanged(GL10 gl, int width, int height) {         //设置3D窗口的大小及位置         gl.glViewport(0 , 0 , width , height );         //将矩阵模式设置为投影矩阵         gl.glMatrixMode(GL10.GL_PROJECTION);         //初始化单位矩阵         gl.glLoadIdentity();         //计算透视窗宽高比         float ratio = (float)width/height;         //设置透视视窗的空间大小 默认为 -1,1,-1,1,-1,1         //gl.glFrustumf(-ratio , ratio , -1 , 1  ,1 , 10);     }      @Override     public void onDrawFrame(GL10 gl) {         //清除屏幕缓存和深度缓存         gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);         //启用顶点坐标数据         gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);         //设置当前矩形堆栈为模型堆栈         gl.glMatrixMode(GL10.GL_MODELVIEW);          //启用纹理贴图坐标数组         gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);         //重置当前的模型视图矩阵         gl.glLoadIdentity();        //如果需要用颜色填充平面,还需要禁用顶点颜色数据         gl.glColor4f(0.2f , 1.0f , 0.2f , 0.0f);         gl.glDisableClientState(GL10.GL_COLOR_ARRAY);         //绕y轴旋转         //gl.glRotatef(roate , 0f , 1f , 0f);         //设置顶点位置数据         gl.glVertexPointer(3 , GL10.GL_FLOAT , 0 , vertextBuffer);         //设置贴图数组         gl.glTexCoordPointer(2 , GL10.GL_FLOAT , 0 , textureBuffer);         //根据顶点绘制平面 //执行贴图          gl.glBindTexture(GL10.GL_TEXTURE_2D , texture);         gl.glDrawElements(GL10.GL_TRIANGLES, faceBuffer.remaining() , GL10.GL_UNSIGNED_BYTE , faceBuffer);           //停止绘制         gl.glFinish();         //停用坐标数据         gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);         //禁用纹理数组         gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);          roate+=1;         if (roate == 360){             roate = 0;         }     }   } 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!