1.步骤
1.1创建GLSurfaceView实例
1.2检查系统是否支持opengl es2.0
1.3为opengl es2.0配置渲染表面(即创建自定义渲染器,主要的相关操作都在此处进行)
1.4.显示GLSurfaceView
1.5.Acticity生命周期与GLSurfaceView同步
2.eclipse设置静态导入(static import)
因为调用2.0版本相关函数都是采用静态方式,使用静态导入可以减少了冗长的代码。设置如图所示
3.引入Opengl管道
我们操作的数据(顶点数据或颜色数据)复制到了OpenGL可以存取的本地内存;在显示到屏幕上之前,它需要在OpenGL的管道中传递,这就需要使用着色器(shader)的子例程。这些着色器会告诉图形处理单元(GPU)如何绘制数据。
3.1顶点着色器(vertex shader)生成每个顶点的最终位置,针对每个顶点,它都会执行一次;一旦最终位置确定了,OpenGL就可以把这些可见顶点的集合组装成点、直线、以及三角形。
3.2片段着色器(fragment shader)为组成点、直线或者三角形的每个片段生成最终的颜色,针对每个片段,它都会执行一次;一个片段是一个小的、单一颜色的长方形区域,类似于计算机屏幕上的一个像素。
一旦最后的颜色生成了,OpenGL就会把他们写到一块称为帧缓冲区(frame buffer)的内存中,然后,android会把这个帧缓冲区显示在屏幕上。
3.3OpenGL管道概述:读取顶点数据->执行顶点着色器->组装图元->光栅化图元->执行片段着色器->写入帧缓冲区->显示在屏幕上
4.着色器源码
//顶点着色器/res/raw/simple_vertex_shader.glsl
attribute vec4 a_Position;
void main()
{
gl_Position = a_Position;
gl_PointSize = 10.0;
}
//片段着色器/res/raw/simple_fragment_shader.glsl
//precision为精度限定符:可以选择lowp、mediump、highp;顶点着色器默认为hitghp
precision mediump float;
uniform vec4 u_Color;
void main()
{
gl_FragColor = u_Color;
}
5.自定义渲染器源码
package com.example.firstopengl;
import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
import static android.opengl.GLES20.GL_FLOAT;
import static android.opengl.GLES20.GL_LINES;
import static android.opengl.GLES20.GL_POINTS;
import static android.opengl.GLES20.GL_TRIANGLES;
import static android.opengl.GLES20.glClear;
import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glDrawArrays;
import static android.opengl.GLES20.glEnableVertexAttribArray;
import static android.opengl.GLES20.glGetAttribLocation;
import static android.opengl.GLES20.glGetUniformLocation;
import static android.opengl.GLES20.glUniform4f;
import static android.opengl.GLES20.glUseProgram;
import static android.opengl.GLES20.glVertexAttribPointer;
import static android.opengl.GLES20.glViewport;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;
public class MyRenderer implements Renderer {
private final Context context;
private static final int POSITION_COMPINENT_COUNT = 2;// 坐标xy2个值
private static final int BYTES_PER_FLOAT = 4;// float类型由4个byte构成
private final FloatBuffer vertexData;// 本地系统存储点的数据
private int program;// 着色器的链接程序
private static final String U_COLOR = "u_Color";
private int uColorLocation;
private static final String A_POSITION = "a_Position";
private int aPositionLocation;
public MyRenderer(Context context) {
// TODO Auto-generated constructor stub
this.context = context;
// 三角形的卷曲顺序:逆时针描点,指出物体前后区分(即前面物体会挡住后面物体)
//屏幕坐标:左下角(-1,-1),右下角(1,-1),右上角(1,1),左上角(-1,1),中心点(0,0)
float[] datas = {
// table
-0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f,
// line
-0.5f, 0.0f, 0.5f, 0.0f,
// mallets
0.0f, -0.25f, 0.0f, 0.25f };
//吧内存从java堆复制到本地堆,因为opengl是在本地系统操作的
//申请本地系统内存
vertexData = ByteBuffer.allocateDirect(datas.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
//赋值
vertexData.put(datas);
}
// 绘制每一帧时,GLSurfaceView调用(suface创建后)
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
// 清除屏幕颜色
glClear(GL_COLOR_BUFFER_BIT);
// 绘制table
glUniform4f(uColorLocation, 1.0f, 1.0f, 1.0f, 1.0f);
glDrawArrays(GL_TRIANGLES, 0, 6);
// 绘制分割线
glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
glDrawArrays(GL_LINES, 6, 2);
// 绘制蓝色的mallet
glUniform4f(uColorLocation, 0.0f, 0.0f, 1.0f, 1.0f);
glDrawArrays(GL_POINTS, 8, 1);
// 绘制红色的mallet
glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
glDrawArrays(GL_POINTS, 9, 1);
}
// suface视图大小改变时,GLSurfaceView调用(suface创建后)
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
// 设置视图大小
glViewport(0, 0, width, height);
}
// suface创建时,GLSurfaceView调用
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
// 清空屏幕的颜色
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// 顶点着色器与片段着色器代码
String vertexShaderSoure = TRReader.readTFfromRes(context, R.raw.simple_vertex_shader);
String fragmentShaderSoure = TRReader.readTFfromRes(context, R.raw.simple_fragment_shader);
// 获取对对应着色器
int vertexShader = ShaderHelper.conpileVertexShader(vertexShaderSoure);
int fragmentShader = ShaderHelper.conpileFragmentShader(fragmentShaderSoure);
program = ShaderHelper.linkProgram(vertexShader, fragmentShader);
if (LoggerConfig.ON) {
ShaderHelper.validateProgram(program);
}
//使用自定义的程序
glUseProgram(program);
// 获得uniform与attribute位置
uColorLocation = glGetUniformLocation(program, U_COLOR);
aPositionLocation = glGetAttribLocation(program, A_POSITION);
// 关联顶点属性
vertexData.position(0);
glVertexAttribPointer(aPositionLocation, // 属性位置
POSITION_COMPINENT_COUNT, // 顶点参数个数
GL_FLOAT, // 顶点数据类型
false, // 整型数据才有意义
0, // 多余一个属性才有意义
vertexData);// 数据内存
// 使能顶点数组
glEnableVertexAttribArray(aPositionLocation);
}
}
6.工程源码:https://github.com/HQlin/ShaderOpenGL