1.初始化gl
setEGLContextClientVersion(2);??//申明使用版本號
setRenderer(renderer=new FGLRender(this));??//設置渲染器
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); //渲染模式
--說明:1.再考慮到適配較低版本手機時候,可能會需要驗證當前手機支持的版本
ActivityManager activityManager = (ActivityManager) getSystemServi(ACTIVITY_SERVICE);
if (activityManager == null){
throw new NullPointerException();
}
ConfigurationInfo deviceConfigurationInfo = activityManager.getDeviceConfigurationInfo();
if (deviceConfigurationInfo.reqGlEsVersion < 0x20000){
throw new UnSupportGlVersionException("unspport egl version");
}
2.關于渲染模式:一般情況下GLSurfaceview會在單獨一個線程中,調(diào)用渲染器的方法,默然會以顯示設備的刷新頻率不斷地渲染,可以設置renderMode為RENDERMODE_WHEN_DIRTY表示按請求渲染
2.編輯render
創(chuàng)建繪制圖形坐標,opengl繪制圖像都是映射在[-1,1]的范圍內(nèi),定義點的順序,最好也按照逆時針這種卷曲順序,這樣可優(yōu)化性能
以正方形為例:
final float cubePositions[] = {
-0.5f,-0.5f,??//一個三角形
0.5f,0.5f,
-0.5f,0.5f,
-0.5f,-0.5f,
0.5f,-0.5f,??//一個三角形
0.5f,0.5f,
-0.5f,0f,
0.5f,0f,????//一條線
0f,-0.25f,
0f,0.25f???//一條線
};
創(chuàng)建緩沖數(shù)組
mVertexData = ByteBuffer.allocateDirect(cubePositions.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
mVertexData.put(cubePositions);
mVertexData.position(0);
首先分配一塊本地內(nèi)存(不是垃圾管理機制控制),大小為頂點數(shù)組占字節(jié)數(shù)(一個float4個字節(jié)),
然后order按照本地字節(jié)序組織內(nèi)容,最后調(diào)用asFloatBuffer()可以避免操作字節(jié),而直接操作浮點數(shù)
引入shader
1.頂點著色器(vertex shader):用于生成每個頂點的最終位置,點位置確定,這樣opengl就可以將點組裝成點,直線,以及三角形
2.片段著色器(fragment shader):為組裝的點,直線,或者三角形的每個片段生成顏色
創(chuàng)建頂點著色器:
attribute vec4 a_Position;
void main()
{
gl_Position = a_Position;
}
片元著色器:
precision mediump float;
uniform vec4 u_Color;
void main()
{
gl_FragColor = u_Color;
}
加載著色器
現(xiàn)將之前寫好的著色器讀出來,按照各自的方式編譯頂點著色器(GLES20.GL_VERTEX_SHADER),片元著色器(GLES20.GL_FRAGMENT_SHADER)
int shaderObjectId = GLES20.glCreateShader(type);??//創(chuàng)建一個新的著色器對象,并返回id,返回值為0時及失敗
GLES20.glShaderSource(shaderObjectId,shaderCoder);??//上傳源代碼,將其關聯(lián)到上一步的id
GLES20.glCompileShader(shaderObjectId);???//編譯改著色器
我們可以檢查這個著色器是否編譯成功
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(shaderObjectId,GLES20.GL_COMPILE_STATUS,compileStatus,0);
if (compileStatus[0] == 0){??//編譯失敗
GLES20.glDeleteShader(shaderObjectId);
Log.e(TAG,"Compilation of shader failed");
return 0;
}
將著色器鏈接到opengl程序
int programeObjectId = GLES20.glCreateProgram();??//創(chuàng)建一個opengl程序
if (programeObjectId == 0){
Log.e(TAG,"create program failed");
return 0;
}
GLES20.glAttachShader(programeObjectId,vertexShaderId);???//附上著色器
GLES20.glAttachShader(programeObjectId,fragmentShaderId);
GLES20.glLinkProgram(programeObjectId);???//將所有著色器鏈接起來
也可以使用城西來檢查鏈接是否成功
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(programeObjectId,GLES20.GL_LINK_STATUS,linkStatus,0);
if (linkStatus[0] == 0){
GLES20.glDeleteProgram(programeObjectId);
Log.e(TAG,"link programe failed");
return 0;
}
告訴opengl 著色器繪制的位置
GLES20.glUseProgram(program);
mUniformLocation = GLES20.glGetUniformLocation(program, U_COLOR);??//獲取顏色位置
mAttribLocation = GLES20.glGetAttribLocation(program, A_POSITION); //獲取屬性位置
GLES20.glVertexAttribPointer(mAttribLocation,POSITION_COPOMENT_COUNT,GLES20.GL_FLOAT,false,0,mVertexData);??//告訴opengl 從緩沖區(qū)讀取數(shù)據(jù),就能找到a_position的位置數(shù)據(jù)
GLES20.glEnableVertexAttribArray(mAttribLocation);??//告訴opengl到哪里去找其他數(shù)據(jù)
開始繪制
GLES20.glUniform4f(mUniformLocation,1.0f,1.0f,1.0f,1.0f); //更新著色器代碼中u_Color的值 ,后面的值分別代表RGBA
GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,6); //繪制一個三角形,從數(shù)組第0個開始讀,6個長度,這就繪制了兩個三角形
//繪制下面的線和點
GLES20.glUniform4f(mUniformLocation,1.0f,0.0f,0.0f,1.0f);
GLES20.glDrawArrays(GLES20.GL_LINES,6,2);
GLES20.glUniform4f(mUniformLocation,0.0f,0.0f,1.0f,1.0f);
GLES20.glDrawArrays(GLES20.GL_POINTS,8,1);
GLES20.glUniform4f(mUniformLocation,1.0f,0.0f,0.0f,1.0f);
GLES20.glDrawArrays(GLES20.GL_POINTS,9,1);
待續(xù).................................................