OpenGL ES实现三棱锥纹理贴图

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

自己定义一个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的:

最后展示一下运行结果:

      

   

发布了2 篇原创文章 · 获赞 2 · 访问量 39

猜你喜欢

转载自blog.csdn.net/FlorentinoAriza/article/details/105411895