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

如何在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 alpha
		float 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;
    @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(); 
    } 
}


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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值