openGL ES 2.0 初始化(I)

本文详细介绍了使用OpenGL ES 2.0进行三维图形绘制的过程,包括ShaderUtil文件的创建、MyTDView文件的实现以及Triangle类的配置。重点在于通过Shader文件、渲染器和顶点数据的交互,实现三维图形的动态旋转效果。通过资产文件加载Shader源代码,并创建和链接着色器程序,最终在视图中展示三角形的旋转动画。

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

ok、好了今天学习了“openGL ES 2.0

现在把今天学习到的东东做一个总结,本demo是运行在安装有android sdk的Eclipse上实现的:

好了总结开始:

起先是ShaderUtil.java文件:

package com.example.initopengles_mine;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
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 compile shader" + shaderType + ":");
				Log.e("ES20_ERROR",GLES20.glGetShaderInfoLog(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("glAttachShader");
			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("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);
		}
	}
	
	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) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return result;
	}
}


好了,现在是MyTDView.java文件:

package com.example.initopengles_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;
import android.opengl.Matrix;


public class MyTDView extends GLSurfaceView{

	final float ANGLE_SPAN = 0.375f;
	RotateThread rthread;
	SceneRenderer mRenderer;
	
	public MyTDView(Context context) {
		super(context);
		// TODO 自动生成的构造函数存根
		this.setEGLContextClientVersion(2);
		mRenderer = new SceneRenderer();
		this.setRenderer(mRenderer);
		this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
	}
	private class SceneRenderer implements GLSurfaceView.Renderer{

		Triangle tle;
		@Override
		public void onDrawFrame(GL10 gl) {
			// TODO 自动生成的方法存根
			GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
			tle.drawSelf();
		}

		@Override
		public void onSurfaceChanged(GL10 gl, int width, int height) {
			// TODO 自动生成的方法存根
			GLES20.glViewport(0, 0, width, height);
			float ratio = (float) width / height;
			//错在这里了~
			Matrix.frustumM(Triangle.mProjMatrix, 0, -ratio, ratio, -1, 1, 1 , 10);
			Matrix.setLookAtM(Triangle.mVMatrix, 0 , 0 , 0, 3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
		}

		@Override
		public void onSurfaceCreated(GL10 gl, EGLConfig config) {
			// TODO 自动生成的方法存根
			GLES20.glClearColor(0, 0, 0, 1.0f);
			tle = new Triangle(MyTDView.this);
			GLES20.glEnable(GLES20.GL_DEPTH_TEST);
			rthread = new RotateThread();
			rthread.start();
		}
		
	}

	public class RotateThread extends Thread{
		public boolean flag = true;

		@Override
		public void run() {
			// TODO 自动生成的方法存根
			//super.run();
			while(flag){
				mRenderer.tle.xAngle = mRenderer.tle.xAngle + ANGLE_SPAN;
				try{
					Thread.sleep(20);
				}
				catch(Exception e){
					e.printStackTrace();
				}
			}
		}
		
	}

}


ok、现在就是Triangle.java文件的配置:

package com.example.initopengles_mine;

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

import android.opengl.GLES20;
import android.opengl.Matrix;

public class Triangle {
	public static float[] mProjMatrix = new float[16];
	public static float[] mVMatrix = new float[16];
	public static float[] mMVPMatrix;
	int mProgram;
	
	int muMVPMatrixHandle;
	int maPositionHandle;
	int maColorHandle;
	String mVertexShader;
	String mFragmentShader;	
	static float[] mMMatrix = new float[16];
	
	FloatBuffer mVertexBuffer;
	FloatBuffer mColorBuffer;
	int vCount = 0;
	float xAngle = 0;
	public Triangle(MyTDView mv){
		initVertexData();
		intShader(mv);
	}
	public void initVertexData(){
		vCount = 3;
		final float UNIT_SIZE = 0.2f;
		float vertices[] = new float[]{
				-4 * UNIT_SIZE, 0,0,0,-4*UNIT_SIZE,0,4*UNIT_SIZE,0,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,1,0,0,0,1,0,0,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 intShader(MyTDView 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);
		Matrix.setRotateM(mMMatrix,0,0,0,1,0);
		Matrix.translateM(mMMatrix, 0, 0, 0, 1);
		Matrix.rotateM(mMMatrix, 0, xAngle, 1, 0, 0);
		GLES20.glUniformMatrix4fv(
				muMVPMatrixHandle, 1, false, Triangle.getFinalMatrix(mMMatrix),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);
		
	}
	public static float[] getFinalMatrix(float[] spec){
		mMVPMatrix = new float[16];
		Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, spec, 0);
		//少了一句:
		 Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0); 
		return mMVPMatrix;
		
	}
}

,万事俱备,之前东风:

最后最后配置MainActivity.javj文件:

package com.example.initopengles_mine;

import android.os.Bundle;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.view.Menu;

public class MainActivity extends Activity {

	MyTDView mview;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		
		mview = new MyTDView(this);
		mview.requestFocus();
		mview.setFocusableInTouchMode(true);		
		setContentView(mview);
		
	}
	
	

	@Override
	protected void onPause() {
		// TODO 自动生成的方法存根
		super.onPause();
		mview.onPause();
	}



	@Override
	protected void onResume() {
		// TODO 自动生成的方法存根
		super.onResume();
		mview.onResume();
	}

	/*

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	*/

}


好了,

今天就总结到这里~~

祝大家周末愉快~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值