opengles绘制立方体

来源:互联网 发布:师洋淘宝店铺 编辑:程序博客网 时间:2024/04/29 22:37

本人比较懒,不说废话,直接贴代码,代码后附有完整项目

package test.com.opengles5_3;import android.opengl.GLES20;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;/** * Created by hbin on 2016/8/2. * 颜色立方体 */public class Cube {    int mProgram;//自定义渲染管线着色器程序id    int muMVPMatrixHandle;//总变换矩阵引用    int maPositionHandle;//顶点位置属性引用    int maColorHandle;//顶点颜色属性引用    String mVertexShader;//顶点设色器代码脚本    String mFragmentShader;//片元着色器代码脚本    FloatBuffer mVertexBuffer;//顶点坐标数据缓冲    FloatBuffer mColorBuffer;//顶点着色数据缓冲    int vCount=0;    public Cube(MySurfaceView mv){            initVertexData();            initShader(mv);    }    //初始化顶点坐标与着色数据的方法    public void initVertexData()    {        //总顶点数        vCount=12*6;//一共6个面,每个面12个顶点,每个面4个三角形        float vertices[]=new float[]                {                    //opengles以三角形方式绘制多边形,此处把一个平面分成4个三角形进行绘制                    //以立方体的中心点作为三维坐标系的原点,z轴穿过前面,后面的中心点                    //x轴穿过左右面的中心点                    //y轴穿过上下面的中心点                        //前面                        0,0,Constant.UNIT_SIZE,//前面的中心点                        Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,// 右上                        -Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,//左上                        0,0,Constant.UNIT_SIZE,//前面中心点                        -Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,//左上                        -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,//左下                        0,0,Constant.UNIT_SIZE,//前面中心点                        -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,//左下                        Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,//右下                        0,0,Constant.UNIT_SIZE,//前面中心点                        Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,//右下                        Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,//右上                        //后面                        0,0,-Constant.UNIT_SIZE,//后面中心点                        Constant.UNIT_SIZE,Constant.UNIT_SIZE,-Constant.UNIT_SIZE,//右上                        Constant.UNIT_SIZE,-Constant.UNIT_SIZE,-Constant.UNIT_SIZE,//右下                        0,0,-Constant.UNIT_SIZE,//后面中心点                        Constant.UNIT_SIZE,-Constant.UNIT_SIZE,-Constant.UNIT_SIZE,//右下                        -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,-Constant.UNIT_SIZE,//左下                        0,0,-Constant.UNIT_SIZE,//后面中心点                        -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,-Constant.UNIT_SIZE,//左下                        -Constant.UNIT_SIZE,Constant.UNIT_SIZE,-Constant.UNIT_SIZE,//左上                        0,0,-Constant.UNIT_SIZE,//后面中心点                        -Constant.UNIT_SIZE,Constant.UNIT_SIZE,-Constant.UNIT_SIZE,//左上                        Constant.UNIT_SIZE,Constant.UNIT_SIZE,-Constant.UNIT_SIZE,//右上                        //左面                        -Constant.UNIT_SIZE,0,0,//左面中心点                        -Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,//左前                        -Constant.UNIT_SIZE,Constant.UNIT_SIZE,-Constant.UNIT_SIZE,//左后                        -Constant.UNIT_SIZE,0,0,//左面中心点                        -Constant.UNIT_SIZE,Constant.UNIT_SIZE,-Constant.UNIT_SIZE,//左后                        -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,-Constant.UNIT_SIZE,//左下                        -Constant.UNIT_SIZE,0,0,//左面中心点                        -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,-Constant.UNIT_SIZE,//左下                        -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,//右下                        -Constant.UNIT_SIZE,0,0,//左面中心点                        -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,//右下                        -Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,// 左后                        //右面                        Constant.UNIT_SIZE,0,0,                        Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,                        Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,                        Constant.UNIT_SIZE,0,0,                        Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,                        Constant.UNIT_SIZE,-Constant.UNIT_SIZE,-Constant.UNIT_SIZE,                        Constant.UNIT_SIZE,0,0,                        Constant.UNIT_SIZE,-Constant.UNIT_SIZE,-Constant.UNIT_SIZE,                        Constant.UNIT_SIZE,Constant.UNIT_SIZE,-Constant.UNIT_SIZE,                        Constant.UNIT_SIZE,0,0,                        Constant.UNIT_SIZE,Constant.UNIT_SIZE,-Constant.UNIT_SIZE,                        Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,                        //上面                        0,Constant.UNIT_SIZE,0,                        Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,                        Constant.UNIT_SIZE,Constant.UNIT_SIZE,-Constant.UNIT_SIZE,                        0,Constant.UNIT_SIZE,0,                        Constant.UNIT_SIZE,Constant.UNIT_SIZE,-Constant.UNIT_SIZE,                        -Constant.UNIT_SIZE,Constant.UNIT_SIZE,-Constant.UNIT_SIZE,                        0,Constant.UNIT_SIZE,0,                        -Constant.UNIT_SIZE,Constant.UNIT_SIZE,-Constant.UNIT_SIZE,                        -Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,                        0,Constant.UNIT_SIZE,0,                        -Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,                        Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,                        //下面                        0,-Constant.UNIT_SIZE,0,                        Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,                        -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,                        0,-Constant.UNIT_SIZE,0,                        -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,                        -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,-Constant.UNIT_SIZE,                        0,-Constant.UNIT_SIZE,0,                        -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,-Constant.UNIT_SIZE,                        Constant.UNIT_SIZE,-Constant.UNIT_SIZE,-Constant.UNIT_SIZE,                        0,-Constant.UNIT_SIZE,0,                        Constant.UNIT_SIZE,-Constant.UNIT_SIZE,-Constant.UNIT_SIZE,                        Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,                };            //创建顶点坐标数据缓冲            ////vertices.length*4是因为一个float四个字节        ByteBuffer vbb=ByteBuffer.allocateDirect(vertices.length*4);        vbb.order(ByteOrder.nativeOrder());//设置字节顺序        mVertexBuffer=vbb.asFloatBuffer();//转为Float型缓冲        mVertexBuffer.put(vertices);//向缓冲区放入顶点坐标数据        mVertexBuffer.position(0);//设置缓冲区起始位置        //顶点颜色值数组,每个顶点4个色彩值  RGBA        float colors[]=new float[]{                //前面                1,1,1,0,//中间为白色                1,0,0,0,                1,0,0,0,                1,1,1,0,//中间为白色                1,0,0,0,                1,0,0,0,                1,1,1,0,//中间为白色                1,0,0,0,                1,0,0,0,                1,1,1,0,//中间为白色                1,0,0,0,                1,0,0,0,                //后面                1,1,1,0,//中间为白色                0,0,1,0,                0,0,1,0,                1,1,1,0,//中间为白色                0,0,1,0,                0,0,1,0,                1,1,1,0,//中间为白色                0,0,1,0,                0,0,1,0,                1,1,1,0,//中间为白色                0,0,1,0,                0,0,1,0,                //左面                1,1,1,0,//中间为白色                1,0,1,0,                1,0,1,0,                1,1,1,0,//中间为白色                1,0,1,0,                1,0,1,0,                1,1,1,0,//中间为白色                1,0,1,0,                1,0,1,0,                1,1,1,0,//中间为白色                1,0,1,0,                1,0,1,0,                //右面                1,1,1,0,//中间为白色                1,1,0,0,                1,1,0,0,                1,1,1,0,//中间为白色                1,1,0,0,                1,1,0,0,                1,1,1,0,//中间为白色                1,1,0,0,                1,1,0,0,                1,1,1,0,//中间为白色                1,1,0,0,                1,1,0,0,                //上面                1,1,1,0,//中间为白色                0,1,0,0,                0,1,0,0,                1,1,1,0,//中间为白色                0,1,0,0,                0,1,0,0,                1,1,1,0,//中间为白色                0,1,0,0,                0,1,0,0,                1,1,1,0,//中间为白色                0,1,0,0,                0,1,0,0,                //下面                1,1,1,0,//中间为白色                0,1,1,0,                0,1,1,0,                1,1,1,0,//中间为白色                0,1,1,0,                0,1,1,0,                1,1,1,0,//中间为白色                0,1,1,0,                0,1,1,0,                1,1,1,0,//中间为白色                0,1,1,0,                0,1,1,0,        };        //创建顶点着色数据缓冲        ByteBuffer cbb=ByteBuffer.allocateDirect(colors.length*4);        cbb.order(ByteOrder.nativeOrder());//设置字节序        mColorBuffer=cbb.asFloatBuffer();//转换为Float型缓冲        mColorBuffer.put(colors);//向缓冲区放入顶点着色数据        mColorBuffer.position(0);//设置缓冲区起始位置    }    //初始化shader    public void initShader(MySurfaceView mv)    {        //加载顶点着色器的脚本内容        mVertexShader=ShaderUtil.loadFromAssetsFile("vertex.sh",mv.getResources());        //加载片元着色器的脚本内容        mFragmentShader=ShaderUtil.loadFromAssetsFile("frag.sh",mv.getResources());        //基于顶点着色器与片元着色器创建程序        mProgram=ShaderUtil.createProgram(mVertexShader,mFragmentShader);        // 获取程序中顶点位置属性引用id        maPositionHandle= GLES20.glGetAttribLocation(mProgram, "aPosition");        //获取程序中顶点颜色属性引用id        maColorHandle=GLES20.glGetAttribLocation(mProgram,"aColor");        //获取程序中总变换矩阵引用id        muMVPMatrixHandle=GLES20.glGetUniformLocation(mProgram,"uMVPMatrix");    }    public void drawSelf()    {        //制定使用某套shader程序        GLES20.glUseProgram(mProgram);        //将最终变换矩阵传入shader程序        GLES20.glUniformMatrix4fv(muMVPMatrixHandle,1,false,MatrixState.getFinalMatrix(),0);        //为画笔指定顶点位置数据        GLES20.glVertexAttribPointer                (                    maPositionHandle,                        3,                        GLES20.GL_FLOAT,                        false,                        3*4,                        mVertexBuffer                );        //为画笔指定顶点着色数据        GLES20.glVertexAttribPointer                (                    maColorHandle,                        4,                        GLES20.GL_FLOAT,                        false,                        4*4,                        mColorBuffer                );        //允许顶点位置数据数组        GLES20.glEnableVertexAttribArray(maPositionHandle);        GLES20.glEnableVertexAttribArray(maColorHandle);        //绘制立方立方体        GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,vCount);    }}

package test.com.opengles5_3;import android.app.Activity;import android.content.pm.ActivityInfo;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;public class MainActivity extends Activity {    private MySurfaceView mGLSurfaceView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        // 设置为全屏        requestWindowFeature(Window.FEATURE_NO_TITLE);        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                WindowManager.LayoutParams.FLAG_FULLSCREEN);        // 设置为横屏模式        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);        // 初始化GLSurfaceView        mGLSurfaceView = new MySurfaceView(this);        // 切换到主界面        setContentView(mGLSurfaceView);        mGLSurfaceView.requestFocus();// 获取焦点        mGLSurfaceView.setFocusableInTouchMode(true);// 设置为可触控    }    @Override    protected void onResume() {        super.onResume();        mGLSurfaceView.onResume();    }    @Override    protected void onPause() {        super.onPause();        mGLSurfaceView.onPause();    }}

package test.com.opengles5_3;import android.opengl.Matrix;import java.nio.ByteBuffer;/** * Created by hbin on 2016/8/2. * 存储系统矩阵状态的类 */public class MatrixState {    private static float[] mProjMatrix=new float[16];//4x4矩阵,投影用    private static float[] mVMatrix=new float[16];//摄像机位置朝向9参数矩阵    private static float[] currMatrix;//当前变换矩阵    //保护变换矩阵的栈    static float[][] mStack=new float[10][16];    static int stackTop=-1;    public static void setInitStack()    {        currMatrix=new float[16];        Matrix.setRotateM(currMatrix,0,0,1,0,0);    }    public static void pushMatrix(){//保护变换矩阵        stackTop++;        for (int i=0;i<16;i++){            mStack[stackTop][i]=currMatrix[i];        }    }    public static void popMatrix(){//恢复变换矩阵        for (int i=0;i<16;i++){            currMatrix[i]=mStack[stackTop][i];        }        stackTop--;    }    public static void translate(float x,float y,float z){//设置沿xyz轴移动        Matrix.translateM(currMatrix,0,x,y,z);    }    //设置摄像机    static ByteBuffer llbb=ByteBuffer.allocateDirect(3*4);    static float[] cameraLocation=new float[3];//摄像机位置    public static void setCamera            (                    float cx,//摄像机位置x                    float cy,//摄像机位置y                    float cz,//摄像机位置z                    float tx,//摄像机目标点x                    float ty,//摄像机目标点y                    float tz,//摄像机目标点z                    float upx,//摄像机UP向量x分量                    float upy,//摄像机UP向量y分量                    float upz//摄像机up向量z分量            )    {        Matrix.setLookAtM                (                        mVMatrix,                        0,                        cx,                        cy,                        cz,                        tx,                        ty,                        tz,                        upx,                        upy,                        upz                );    }    //设置透视投影参数    public static void setProjectFrustum    (            float left,//near面的left            float right,//near面的right            float bottom,//near面的bottom            float top,//near面的top            float near,//near面的距离            float far //far面的距离    )    {        Matrix.frustumM(mProjMatrix, 0, left, right, bottom, top, near, far);    }    //设置正交投影参数    public static void setProjectOrtho    (        float left,//near面的left        float right,//near面的right        float bottom,//near面的bottom        float top,//near面的top        float near,//near面距离        float far //far面距离    )    {        Matrix.orthoM(mProjMatrix,0,left,right,bottom,top,near,far);    }    //获取具体物体的总变换矩阵    static float[] mMVPMatrix=new float[16];    public static float[] getFinalMatrix()    {        Matrix.multiplyMM(mMVPMatrix,0,mVMatrix,0,currMatrix,0);        Matrix.multiplyMM(mMVPMatrix,0,mProjMatrix,0,mMVPMatrix,0);        return mMVPMatrix;    }    //获取具体物体的变换矩阵    public static float[] getMMatrix()    {        return currMatrix;    }}

package test.com.opengles5_3;import android.content.Context;import android.opengl.GLES20;import android.opengl.GLSurfaceView;import android.util.Log;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;/** * Created by hbin on 2016/8/2. */public class MySurfaceView extends GLSurfaceView{    private SceneRenderer mRenderer;//场景渲染器    public MySurfaceView(Context context) {        super(context);        this.setEGLContextClientVersion(2);//设置使用opengl es2.0        mRenderer=new SceneRenderer();//创建场景渲染器        setRenderer(mRenderer); //设置渲染器        setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染        //setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);    }    private class SceneRenderer implements GLSurfaceView.Renderer    {        Cube cube;//立方体        @Override        public void onSurfaceCreated(GL10 gl, EGLConfig config) {            //设置屏幕背景色RGBA            GLES20.glClearColor(0.5f,0.5f,0.5f,1.0f);            //创建立方体对象            cube=new Cube(MySurfaceView.this);            //打开深度检测            GLES20.glEnable(GLES20.GL_DEPTH_TEST);            //打开背面剪裁            GLES20.glEnable(GLES20.GL_CULL_FACE);        }        @Override        public void onSurfaceChanged(GL10 gl, int width, int height) {           //设置视窗大小及位置            GLES20.glViewport(0,0,width,height);            //计算GLSurfaceView的宽高比            Constant.ratio=(float)width/height;            //调用此方法计算产生透视投影矩阵            MatrixState.setProjectFrustum(-Constant.ratio*0.8f, Constant.ratio*1.2f, -1, 1, 20, 100);            //设置摄像机观察矩阵            MatrixState.setCamera(-16f,8f,45,0f,0f,0f,0f,1.0f,0.0f);            //MatrixState.setCamera(-16f,8f,45,1f,0f,1f,0f,1.0f,0.0f);            //初始化变换矩阵            MatrixState.setInitStack();        }        @Override        public void onDrawFrame(GL10 gl) {           // Log.i("hb-2","onDrawFrame");            //清除深度缓冲与颜色缓冲            GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);            //绘制原立方体            MatrixState.pushMatrix();            cube.drawSelf();            MatrixState.popMatrix();            //绘制变换后的立方体            MatrixState.pushMatrix();            MatrixState.translate(3, 1, -1);            cube.drawSelf();            MatrixState.popMatrix();        }    }}

package test.com.opengles5_3;import java.io.ByteArrayOutputStream;import java.io.InputStream;import android.content.res.Resources;import android.opengl.GLES20;import android.util.Log;//加载顶点Shader与片元Shader的工具类public class ShaderUtil{    //加载制定shader的方法    public static int loadShader    (            int shaderType, //shader的类型  GLES20.GL_VERTEX_SHADER   GLES20.GL_FRAGMENT_SHADER            String source   //shader的脚本字符串    )    {        //创建一个新shader        int shader = GLES20.glCreateShader(shaderType);        //若创建成功则加载shader        if (shader != 0)        {            //加载shader的源代码            GLES20.glShaderSource(shader, source);            //编译shader            GLES20.glCompileShader(shader);            //存放编译成功shader数量的数组            int[] compiled = new int[1];            //获取Shader的编译情况            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);            if (compiled[0] == 0)            {//若编译失败则显示错误日志并删除此shader                Log.e("ES20_ERROR", "Could not compile shader " + shaderType + ":");                Log.e("ES20_ERROR", GLES20.glGetShaderInfoLog(shader));                GLES20.glDeleteShader(shader);                shader = 0;            }        }        return shader;    }    //创建shader程序的方法    public static int createProgram(String vertexSource, String fragmentSource)    {        //加载顶点着色器        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);        if (vertexShader == 0)        {            return 0;        }        //加载片元着色器        int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);        if (pixelShader == 0)        {            return 0;        }        //创建程序        int program = GLES20.glCreateProgram();        //若程序创建成功则向程序中加入顶点着色器与片元着色器        if (program != 0)        {            //向程序中加入顶点着色器            GLES20.glAttachShader(program, vertexShader);            checkGlError("glAttachShader");            //向程序中加入片元着色器            GLES20.glAttachShader(program, pixelShader);            checkGlError("glAttachShader");            //链接程序            GLES20.glLinkProgram(program);            //存放链接成功program数量的数组            int[] linkStatus = new int[1];            //获取program的链接情况            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);            //若链接失败则报错并删除程序            if (linkStatus[0] != GLES20.GL_TRUE)            {                Log.e("ES20_ERROR", "Could not link program: ");                Log.e("ES20_ERROR", GLES20.glGetProgramInfoLog(program));                GLES20.glDeleteProgram(program);                program = 0;            }        }        return program;    }    //检查每一步操作是否有错误的方法    public static void checkGlError(String op)    {        int error;        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR)        {            Log.e("ES20_ERROR", op + ": glError " + error);            throw new RuntimeException(op + ": glError " + error);        }    }    //从sh脚本中加载shader内容的方法    public static String loadFromAssetsFile(String fname,Resources r)    {        String result=null;        try        {            InputStream in=r.getAssets().open(fname);            int ch=0;            ByteArrayOutputStream baos = new ByteArrayOutputStream();            while((ch=in.read())!=-1)            {                baos.write(ch);            }            byte[] buff=baos.toByteArray();            baos.close();            in.close();            result=new String(buff,"UTF-8");            result=result.replaceAll("\\r\\n","\n");        }        catch(Exception e)        {            e.printStackTrace();        }        return result;    }}

效果图


完整项目下载地址

http://download.csdn.net/detail/hb707934728/9593961

0 0
原创粉丝点击