OpenGL ES实现三棱锥纹理贴图

Kande ·
更新时间:2024-09-21
· 585 次阅读

这是老师布置的课后作业,闲来无事分享出来,也加深一遍自己的印象~

自己定义一个MyRenderer.java类:

package com.example.shiyan3_2; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLSurfaceView.Renderer; import android.opengl.GLUtils; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; public class MyRenderer implements Renderer { // 定义三棱椎的4个顶点 float[] taperVertices = new float[] { 0.0f, 0.5f, 0.0f, -0.5f, -0.5f, -0.2f, 0.5f, -0.5f, -0.2f, 0.0f, -0.2f, 0.2f }; // 定义三棱椎的4个三角面(没有使用) private byte[] taperFacets = new byte[]{ 0, 1, 2, // 0、1、2三个顶点组成一个面 0, 1, 3, // 0、1、3三个顶点组成一个面 1, 2, 3, // 1、2、3三个顶点组成一个面 0, 2, 3 // 0、2、3三个顶点组成一个面 }; //定义纹理贴图的坐标数据 private float[] taperTextures = { 1.0000f,1.0000f, 1.0000f,0.0000f, 0.0000f,0.0000f, 0.0000f,1.0000f }; // 分别定义三棱椎的4个三角面 ByteBuffer i1=ByteBuffer.wrap(new byte[]{ 0,1,2, }); ByteBuffer i2=ByteBuffer.wrap(new byte[]{ 0,1,3, }); ByteBuffer i3=ByteBuffer.wrap(new byte[]{ 1,2,3 }); ByteBuffer i4=ByteBuffer.wrap(new byte[]{ 0,2,3, }); Context context; // 定义Open GL ES绘制所需要的Buffer对象 FloatBuffer taperVerticesBuffer; //IntBuffer taperColorsBuffer; ByteBuffer taperFacetsBuffer; FloatBuffer taperTexturesBuffer; // 控制旋转的角度 private float rotate; //定义本程序所使用的纹理 private int texture; public MyRenderer(Context main) { this.context = main; // 将三棱椎的顶点位置数据数组包装成FloatBuffer taperVerticesBuffer = floatBufferUtil(taperVertices); // 将三棱椎的4个面的数组包装成ByteBuffer taperFacetsBuffer = ByteBuffer.wrap(taperFacets); //将立方体的纹理贴图的坐标数据包装成FLoatBuffer taperTexturesBuffer = floatBufferUtil(taperTextures); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // 关闭抗抖动 gl.glDisable(GL10.GL_DITHER); // 设置系统对透视进行修正 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); gl.glClearColor(0, 0, 0, 0); // 设置阴影平滑模式 gl.glShadeModel(GL10.GL_SMOOTH); // 启用深度测试 gl.glEnable(GL10.GL_DEPTH_TEST); // 设置深度测试的类型 gl.glDepthFunc(GL10.GL_LEQUAL); //启用2D纹理贴图 gl.glEnable(GL10.GL_TEXTURE_2D); //装载纹理 loadTexture(gl); } @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; // 调用此方法设置透视视窗的空间大小。 gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); } // 绘制图形的方法 int[] tex_id = new int[4]; @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.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // ① // 设置当前矩阵模式为模型视图。 gl.glMatrixMode(GL10.GL_MODELVIEW); // --------------------绘制图形--------------------- // 重置当前的模型视图矩阵 gl.glLoadIdentity(); gl.glTranslatef(0.0f, 0.0f, -1.5f); // 沿着Y轴旋转 gl.glRotatef(rotate, 0f, 0.2f, 0f); // 设置顶点的位置数据 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, taperVerticesBuffer); //设置贴图的坐标数据 gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, taperTexturesBuffer); // ② //执行纹理贴图 gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[0]); // ③ // 按taperFacetsBuffer指定的面绘制三角形 gl.glDrawElements(GL10.GL_TRIANGLE_STRIP , i1.remaining(), GL10.GL_UNSIGNED_BYTE, i1); gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[1]); // ③ // 按taperFacetsBuffer指定的面绘制三角形 gl.glDrawElements(GL10.GL_TRIANGLE_STRIP , i2.remaining(), GL10.GL_UNSIGNED_BYTE, i2); gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[2]); // ③ // 按taperFacetsBuffer指定的面绘制三角形 gl.glDrawElements(GL10.GL_TRIANGLE_STRIP , i3.remaining(), GL10.GL_UNSIGNED_BYTE, i3); gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[3]); // ③ // 按taperFacetsBuffer指定的面绘制三角形 gl.glDrawElements(GL10.GL_TRIANGLE_STRIP , i4.remaining(), GL10.GL_UNSIGNED_BYTE, i4); // 绘制结束 gl.glFinish(); //禁用顶点、纹理坐标数组 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // 旋转角度增加1 rotate+=1; } private void loadTexture(GL10 gl){ // 加载位图 Bitmap[] bm = new Bitmap[4]; bm[0]=BitmapFactory.decodeResource(context.getResources(), R.drawable.img1); bm[1]=BitmapFactory.decodeResource(context.getResources(), R.drawable.img2); bm[2]=BitmapFactory.decodeResource(context.getResources(), R.drawable.img3); bm[3]=BitmapFactory.decodeResource(context.getResources(), R.drawable.img4); try{ int[] textures = new int[1]; // 指定生成N个纹理(第一个参数指定生成一个纹理) // textures数组将负责存储所有纹理的代号 IntBuffer textureBuffer = IntBuffer.allocate(4); gl.glGenTextures(4,textureBuffer); tex_id = textureBuffer.array(); for(int i=0;i<4;i++){ // 获取textures纹理数组中的第一个纹理 //texture = textures[i]; // 通知OpenGL将texture纹理绑定到GL10.GL_TEXTURE_2D目标中 gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[i]); //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, bm[i], 0); if (bm[i] != null) bm[i].recycle(); } } finally { //生成纹理之后,回收位图 } } // 定义一个工具方法,将float[]数组转换为OpenGL ES所需的FloatBuffer private FloatBuffer floatBufferUtil(float[] arr) { FloatBuffer mBuffer; // 初始化ByteBuffer,长度为arr数组的长度*4,因为一个int占4个字节 ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4); // 数组排列用nativeOrder qbb.order(ByteOrder.nativeOrder()); mBuffer = qbb.asFloatBuffer(); mBuffer.put(arr); mBuffer.position(0); return mBuffer; } }

接下来是MainActivity.java:

package com.example.shiyan3_2; import android.app.Activity; import android.opengl.GLSurfaceView; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 创建一个GLSurfaceView,用于显示OpenGL绘制的图形 GLSurfaceView glView = new GLSurfaceView(this); // 创建GLSurfaceView的内容绘制器 MyRenderer myRender = new MyRenderer(this); // 为GLSurfaceView设置绘制器 glView.setRenderer(myRender); setContentView(glView); } }

记得加入纹理贴图,这里图片的格式是256x256的:

最后展示一下运行结果:

      

   


作者:FlorentinoAriza



棱锥 三棱锥 opengl

需要 登录 后方可回复, 如果你还没有账号请 注册新账号