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
- openGL ES 实现绘画圆 与条带,点索引 (IV)
- openGL ES 2.0 点与点之间的绘制方式(III)
- openGL ES Android 绘制点
- Qt 与 OpenGL ES
- Android OpenGL ES(八):绘制点Point
- opengl三角形剖分与三角形条带化
- opengl三角形剖分与三角形条带化
- OpenGL ES教程IV之着色(原文对照)
- Opengl ES初识 (Opengl ES笔记)
- android 用OPENGL ES 实现投影效果(正交投影与透视投影)
- OpenGL ES 使用顶点索引绘制立方体
- OPENGL-ES之顶点索引绘图
- GlusterFS:条带(Stripe)实现源码研究
- OpenGL Es(一)
- openGL es实现小实例
- Opengl ES 映射表实现
- OpenGL ES 2.0简单实现
- OpenGL ES Shader 实现代码
- JDBC:Java中枚举类型和PostgreSQL数据库中枚举类型的映射
- java生成输出验证码图片,并进行验证的代码
- what's new in ios6 ios7 ios8
- c#winform使用WebBrowser 大全
- 异常和日志的作用
- openGL ES 实现绘画圆 与条带,点索引 (IV)
- android Fragments详解六:处理fragement的生命周期
- Oracle RAC 几个常见的错误观点
- PHP开发环境终于找全了!
- Python笔记——Ubuntu下Pydev+Eclipse
- Fragment的简单显示
- Unity3D的Legacy动画系统中应用Root Motion
- PhotoShop算法实现进阶-模糊滤镜-高斯滤波(二十三)
- java根据ip获取ip所在地址的类