openGL ES 2.0 点与点之间的绘制方式(III)

本文详细介绍了ShaderUtil类用于加载顶点Shader与片元Shader的方法,以及Constant类中定义的一些常量,展示了它们在OpenGL编程中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ShaderUtil.java文件:

package com.example.sample_5_5_mine;


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;
   }
}

Constant.java文件:

package com.example.sample_5_5_mine;

public class Constant {

	public static float UNIT_SIZE = 1f;
	
	public static float ratio;
	
	public static final int GL_POINTS = 0;
	public static final int GL_LINES = 1;
	public static final int GL_STRIP = 2;
	public static final int GL_LINE_LOOP = 3;
	
	public static int CURR_DRAW_MODE = 0;
}

MatrixState.java文件:

package com.example.sample_5_5_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 setProjectionFrustum(
			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 setProjectionOrtho(
			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;
    }
}

PontsOrLines.java文件:

package com.example.sample_5_5_mine;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import android.opengl.GLES20;

public class PointsOrLines {
	int mProgram;
	String mVertexShader;
	String mFragmentShader;
	
	int muMVPMatrixHandle;
	
	int maPositionHandle;
	int maColorHandle;
	
	FloatBuffer mVertexBuffer;
	FloatBuffer mColorBuffer;
	
	int vCount = 0;
	
	public PointsOrLines(MySurfaceView mv){
		initVertexData();
		initShader(mv);
	}
	
	public void initVertexData(){
		vCount = 5;
		
		float vertices[] = new float[]{
				0, 0, 0, Constant.UNIT_SIZE, Constant.UNIT_SIZE, 0,
				-Constant.UNIT_SIZE, Constant.UNIT_SIZE, 0,
				-Constant.UNIT_SIZE, -Constant.UNIT_SIZE, 0,
				Constant.UNIT_SIZE, -Constant.UNIT_SIZE, 0, 
		};
		
		ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
		vbb.order(ByteOrder.nativeOrder());
		mVertexBuffer = vbb.asFloatBuffer();
		mVertexBuffer.put(vertices);
		mVertexBuffer.position(0);
		
		float colors[] = new float[]{
				1, 1, 0, 0,// 黄
				1, 1, 1, 0,// 白
				0, 1, 0, 0,// 绿
				1, 1, 1, 0,// 白
				1, 1, 0, 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, 4*4, mColorBuffer);
		
		GLES20.glEnableVertexAttribArray(maPositionHandle);
		GLES20.glEnableVertexAttribArray(maColorHandle);
		
		GLES20.glLineWidth(10);
		switch(Constant.CURR_DRAW_MODE){
		case Constant.GL_POINTS:
			GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vCount);
			break;
		case Constant.GL_LINES:
			GLES20.glDrawArrays(GLES20.GL_LINES, 0, vCount);
			break;
		case Constant.GL_STRIP:
			GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, vCount);
			break;
		case Constant.GL_LINE_LOOP:
			GLES20.glDrawArrays(GLES20.GL_LINE_LOOP, 0, vCount);
			break;
		}
	}
}





MySurfaceView.java文件:

package com.example.sample_5_5_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;

public class MySurfaceView extends GLSurfaceView{

	private SceneRenderer mRenderer;
	public MySurfaceView(Context context) {
		super(context);
		// TODO 自动生成的构造函数存根
		this.setEGLContextClientVersion(2);
		mRenderer = new SceneRenderer();
		setRenderer(mRenderer);
		Constant.CURR_DRAW_MODE = Constant.GL_POINTS;
	}
	
	private class SceneRenderer implements GLSurfaceView.Renderer{

		PointsOrLines PointsOrLines;
		@Override
		public void onDrawFrame(GL10 arg0) {
			// TODO 自动生成的方法存根
			GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
			MatrixState.pushMatrix();
			MatrixState.pushMatrix();
			PointsOrLines.drawSelf();
			MatrixState.popMatrix();
			MatrixState.popMatrix();
		}

		@Override
		public void onSurfaceChanged(GL10 gl, int width, int height) {
			// TODO 自动生成的方法存根
			GLES20.glViewport(0, 0, width, height);
			Constant.ratio = (float) width / height;
			MatrixState.setProjectionFrustum(-Constant.ratio, Constant.ratio, -1, 1, 20, 100);
			MatrixState.setCamera(0, 8f, 30, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
			MatrixState.setInitStack();
		}

		@Override
		public void onSurfaceCreated(GL10 arg0, EGLConfig arg1) {
			// TODO 自动生成的方法存根
			GLES20.glClearColor(0, 0, 0, 1.0f);
			PointsOrLines = new PointsOrLines(MySurfaceView.this);
			GLES20.glEnable(GLES20.GL_DEPTH_TEST);
			GLES20.glEnable(GLES20.GL_CULL_FACE);
		}}

	
}

MainActivity.java文件:

package com.example.sample_5_5_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;

public class MySurfaceView extends GLSurfaceView{

	private SceneRenderer mRenderer;
	public MySurfaceView(Context context) {
		super(context);
		// TODO 自动生成的构造函数存根
		this.setEGLContextClientVersion(2);
		mRenderer = new SceneRenderer();
		setRenderer(mRenderer);
		Constant.CURR_DRAW_MODE = Constant.GL_POINTS;
	}
	
	private class SceneRenderer implements GLSurfaceView.Renderer{

		PointsOrLines PointsOrLines;
		@Override
		public void onDrawFrame(GL10 arg0) {
			// TODO 自动生成的方法存根
			GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
			MatrixState.pushMatrix();
			MatrixState.pushMatrix();
			PointsOrLines.drawSelf();
			MatrixState.popMatrix();
			MatrixState.popMatrix();
		}

		@Override
		public void onSurfaceChanged(GL10 gl, int width, int height) {
			// TODO 自动生成的方法存根
			GLES20.glViewport(0, 0, width, height);
			Constant.ratio = (float) width / height;
			MatrixState.setProjectionFrustum(-Constant.ratio, Constant.ratio, -1, 1, 20, 100);
			MatrixState.setCamera(0, 8f, 30, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
			MatrixState.setInitStack();
		}

		@Override
		public void onSurfaceCreated(GL10 arg0, EGLConfig arg1) {
			// TODO 自动生成的方法存根
			GLES20.glClearColor(0, 0, 0, 1.0f);
			PointsOrLines = new PointsOrLines(MySurfaceView.this);
			GLES20.glEnable(GLES20.GL_DEPTH_TEST);
			GLES20.glEnable(GLES20.GL_CULL_FACE);
		}}

	
}

activity_main.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/main_liner"
    >

	<RadioGroup 
		android:id="@+id/RadioGroup01" 
		android:layout_width="wrap_content" 
		android:layout_height="wrap_content"
		android:orientation="horizontal"
	>	
		<LinearLayout 
			android:id="@+id/LinearLayout01" 
			android:layout_width="wrap_content" 
			android:layout_height="wrap_content"
			android:orientation="vertical"
		>
				<RadioButton 
					android:text="GL_POINTS" 
					android:id="@+id/RadioButton00" 
					android:layout_width="wrap_content" 
					android:layout_height="wrap_content"
					android:checked="true"
				>
				</RadioButton>
				<RadioButton 
					android:text="GL_LINES" 
					android:id="@+id/RadioButton01" 
					android:layout_width="wrap_content" 
					android:layout_height="wrap_content"
				>
				</RadioButton>
		</LinearLayout>
		
		<LinearLayout 
			android:id="@+id/LinearLayout02" 
			android:layout_width="wrap_content" 
			android:layout_height="wrap_content"
			android:orientation="vertical"
		>
			<RadioButton 
				android:text="GL_LINE_STRIP" 
				android:id="@+id/RadioButton02" 
				android:layout_width="wrap_content" 
				android:layout_height="wrap_content"
			>
			</RadioButton>
			<RadioButton 
				android:text="GL_LINE_LOOP" 
				android:id="@+id/RadioButton03" 
				android:layout_width="wrap_content" 
				android:layout_height="wrap_content"
			>
			</RadioButton>
		</LinearLayout>
	</RadioGroup>
</LinearLayout>

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); //根据总变换矩阵计算此次绘制此顶点位置
   gl_PointSize=10.0;
   vColor = aColor;//将接收的颜色传递给片元着色器
}                      




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值