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