openGL ES 实现绘画圆 与条带,点索引 (IV)

来源:互联网 发布:windows批处理教程 编辑:程序博客网 时间:2024/06/05 14:17

如何在OpenGl ES 中实现绘画圆 与条带,以及实现点索引:

ok、二话不说上代码,


首先是ShaderUtil.java文件:

package com.example.sample_5_9_mine;import java.io.ByteArrayOutputStream;import java.io.InputStream;import android.content.res.Resources;import android.opengl.GLES20;import android.util.Log;public class ShaderUtil {public static int loadShader(int shaderType,String source){int shader = GLES20.glCreateShader(shaderType);if(shader != 0){GLES20.glShaderSource(shader,source);GLES20.glCompileShader(shader);int[] compiled = new int[1];GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled,0);if(compiled[0] == 0){Log.e("ES20_ERROR:","Could not compiled shader");Log.e("ES20_ERRROR",GLES20.glGetShaderInfoLog(shader));GLES20.glDeleteShader(shader);shader = 0;}}return 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("glAttachError");GLES20.glLinkProgram(program);int[] linkStatus = new int[1];GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus,0);if(linkStatus[0] != GLES20.GL_TRUE){Log.e("ES_ERROR","Could not lined");Log.e("ES_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");throw new RuntimeException(op + ":glError");}}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;}}


Constant.java文件:

package com.example.sample_5_9_mine;public class Constant {public static final float UNIT_SIZE = 1f;public static float ratio;}


MatrixState.java文件:

package com.example.sample_5_9_mine;import java.nio.ByteBuffer;import android.opengl.Matrix;public class MatrixState {private static float[] mProjMatrix = new float[16];private static float[] mVMatrix = new float[16];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){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, float cy, float cz,float tx, float ty, float tz,float upx, float upy, float upz){Matrix.setLookAtM(mVMatrix, 0, cx, cy, cz, tx, ty, tz, upx, upy, upz);}public static void setProjectFrustum(float left, float right,float bottom,float top, float near, float far){Matrix.frustumM(mProjMatrix, 0, left, right, bottom, top, near, far);}public static void setProjectOrtho(float left, float right,float bottom,float top, float near, float 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;}}


Belt.java文件:

package com.example.sample_5_9_mine;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import android.opengl.GLES20;public class Belt {int mProgram;int muMVPMatrixHandle;int maPositionHandle;int maColorHandle;String mVertexShader;String mFragmentShader;FloatBuffer mVertexBuffer;FloatBuffer mColorBuffer;private ByteBuffer mIndexBuffer;int vCount = 0;int iCount = 0;public Belt(MySurfaceView mv){initVertexData();initShader(mv);}public void initVertexData(){ int n = 6; vCount = 2 * (n + 1); float angdegBegin = -90; float angdegEnd = 90; float angdegSpan = (angdegEnd - angdegBegin) / n;  float[] vertices = new float[vCount * 3];  int count = 0; for(float angdeg = angdegBegin;angdeg <= angdegEnd;angdeg += angdegSpan){ double angrad = Math.toRadians(angdeg);  vertices[count++] = (float) (-0.6f * Constant.UNIT_SIZE * Math.sin(angrad));// 顶点坐标vertices[count++] = (float) (0.6f * Constant.UNIT_SIZE * Math.cos(angrad));vertices[count++] = 0;// 当前点vertices[count++] = (float) (-Constant.UNIT_SIZE * Math.sin(angrad));// 顶点坐标vertices[count++] = (float) (Constant.UNIT_SIZE * Math.cos(angrad));vertices[count++] = 0; }  ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); vbb.order(ByteOrder.nativeOrder()); mVertexBuffer = vbb.asFloatBuffer(); mVertexBuffer.put(vertices); mVertexBuffer.position(0);  iCount = vCount; byte indices[] = new byte[iCount]; for(int i = 0; i< iCount;i++){ indices[i] = (byte) i; }  mIndexBuffer = ByteBuffer.allocateDirect(indices.length); mIndexBuffer.put(indices); mIndexBuffer.position(0);  count = 0; float colors[] = new float[vCount * 4]; for(int i= 0; i<colors.length;i+=8){ colors[count++] = 1;         colors[count++] = 1;         colors[count++] = 1;         colors[count++] = 0;                colors[count++] = 0;         colors[count++] = 1;         colors[count++] = 1;         colors[count++] = 0; }  ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4); cbb.order(ByteOrder.nativeOrder()); mColorBuffer = cbb.asFloatBuffer(); mColorBuffer.put(colors); mColorBuffer.position(0);}public void initShader(MySurfaceView mv) {mVertexShader = ShaderUtil.loadFromAssetsFile("vertex.sh",mv.getResources());mFragmentShader = ShaderUtil.loadFromAssetsFile("frag.sh",mv.getResources());mProgram = ShaderUtil.createProgram(mVertexShader, mFragmentShader);maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");maColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");} public void drawSelf() {GLES20.glUseProgram(mProgram);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.glDrawElements(GLES20.GL_TRIANGLE_STRIP, iCount,GLES20.GL_UNSIGNED_BYTE, mIndexBuffer);}}


Circle.java文件:

package com.example.sample_5_9_mine;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import android.opengl.GLES20;public class Circle {int mProgram;int muMVPMatrixHandle;int maPositionHandle;int maColorHandle;String mVertexShader;String mFragmentShader;FloatBuffer mVertexBuffer;FloatBuffer mColorBuffer;private ByteBuffer mIndexBuffer;int vCount = 0;int iCount = 0;public Circle(MySurfaceView mv){initVertexData();initShader(mv);}public void initVertexData(){int n = 10;//参考Belt.java文件终于知道为什么这里是加2不是加1了!//原因如下:作为条带,分成6份,需要在第七份上加一组边,//Circle也是这样啊,表面上第一条边和最后一条边重合了,//实际上在for循环时,重合的第一条边和最后一天都会画了一次~vCount = n + 2;float angdegSpan = 360.0f / n;float[] vertices = new float[vCount * 3];int count = 0;vertices[count++] = 0;vertices[count++] = 0;vertices[count++] = 0;for(float angdeg = 0;Math.ceil(angdeg) <= 360;angdeg+=angdegSpan){double angrad = Math.toRadians(angdeg);vertices[count++] = (float) (-Constant.UNIT_SIZE * Math.sin(angrad));vertices[count++] = (float) ( Constant.UNIT_SIZE * Math.cos(angrad));vertices[count++] = 0;}ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);vbb.order(ByteOrder.nativeOrder());mVertexBuffer = vbb.asFloatBuffer();mVertexBuffer.put(vertices);mVertexBuffer.position(0);iCount = vCount;byte indices[] = new byte[iCount];for(int i = 0;i<iCount;i++){indices[i] = (byte)i;}mIndexBuffer = ByteBuffer.allocateDirect(indices.length);mIndexBuffer.put(indices);mIndexBuffer.position(0);count = 0;//r g b alphafloat colors[] = new float[vCount*4];colors[count++] = 1;colors[count++] = 1;colors[count++] = 1;colors[count++] = 0;//因为这里是一次上色四个值!for(int i = 4;i<colors.length; i+=4){colors[count++] = 0;colors[count++] = 1;colors[count++] = 0;colors[count++] = 0;}ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);cbb.order(ByteOrder.nativeOrder());mColorBuffer = cbb.asFloatBuffer();mColorBuffer.put(colors);mColorBuffer.position(0);}public void initShader(MySurfaceView mv){mVertexShader = ShaderUtil.loadFromAssetsFile("vertex.sh", mv.getResources());mFragmentShader = ShaderUtil.loadFromAssetsFile("frag.sh", mv.getResources());mProgram = ShaderUtil.createProgram(mVertexShader, mFragmentShader);maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");maColorHandle = GLES20.glGetAttribLocation(mProgram,"aColor");muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram,"uMVPMatrix");}public void drawSelf(){GLES20.glUseProgram(mProgram);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.glDrawElements(GLES20.GL_TRIANGLE_FAN, iCount,GLES20.GL_UNSIGNED_BYTE,mIndexBuffer);}}


MySurfaceView.java文件:

package com.example.sample_5_9_mine;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.content.Context;import android.opengl.GLES20;import android.opengl.GLSurfaceView;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);//设置渲染模式为主动渲染       }private class SceneRenderer implements GLSurfaceView.Renderer     {   Belt belt;//条状物    Circle circle;//圆            public void onDrawFrame(GL10 gl)         {         //清除深度缓冲与颜色缓冲            GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);            //保护现场            MatrixState.pushMatrix();             //绘制条状物            MatrixState.pushMatrix();            MatrixState.translate(-1.3f, 0, 0);//沿x方向平移            belt.drawSelf();                MatrixState.popMatrix();            //绘制圆            MatrixState.pushMatrix();            MatrixState.translate(1.3f, 0, 0);//沿x方向平移            circle.drawSelf();                MatrixState.popMatrix();                       //恢复现场            MatrixState.popMatrix();        }          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, Constant.ratio, -1, 1, 20, 100);// 调用此方法产生摄像机9参数位置矩阵MatrixState.setCamera(0, 8f, 30, 0f, 0f, 0f, 0f, 1.0f, 0.0f);                        //初始化变换矩阵            MatrixState.setInitStack();        }        public void onSurfaceCreated(GL10 gl, EGLConfig config) {            //设置屏幕背景色RGBA            GLES20.glClearColor(0.5f,0.5f,0.5f, 1.0f);              //创建圆对象            circle=new Circle(MySurfaceView.this);            //创建条状物对象            belt=new Belt(MySurfaceView.this);            //打开深度检测            GLES20.glEnable(GLES20.GL_DEPTH_TEST);            //打开背面剪裁               GLES20.glEnable(GLES20.GL_CULL_FACE);        }    }}


MainActivity.java文件:

package com.example.sample_5_9_mine;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;    @Overrideprotected 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);// 初始化GLSurfaceViewmGLSurfaceView = 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();     } }


frag.sh文件:

precision mediump float;varying  vec4 vColor; //接收从顶点着色器过来的参数varying vec3 vPosition;//接收从顶点着色器过来的顶点位置void main() {     gl_FragColor = vColor;//给此片元颜色值}


vertex.sh文件:

uniform mat4 uMVPMatrix; //总变换矩阵attribute vec3 aPosition;  //顶点位置attribute vec4 aColor;    //顶点颜色varying  vec4 vColor;  //用于传递给片元着色器的变量void main()  {   gl_Position = uMVPMatrix * vec4(aPosition,1); //根据总变换矩阵计算此次绘制此顶点位置   vColor = aColor;//将接收的颜色传递给片元着色器}


0 0
原创粉丝点击