本文主要介紹入門基于Android OpenGL ES的Hello world工程基本環(huán)境搭建。

概要
- 編譯OpenGL 程序
- 配置相關(guān)頂點(diǎn)數(shù)據(jù)
- 繪制操作
介紹
使用OpenGL繪制圖形時(shí),類似向服務(wù)器發(fā)起各種繪制的請求,本地端代碼其實(shí)就是圍繞著如何發(fā)起請求、組織數(shù)據(jù),因此OpenGL其實(shí)是一個(gè)大的狀態(tài)機(jī),接收各種指令而進(jìn)行繪制操作。
編譯OpenGL 程序
既然OpenGL是在服務(wù)器端運(yùn)行的,它肯定也需要運(yùn)行代碼的。OpenGL的代碼是由本地提交源文件,進(jìn)行編譯、連接、運(yùn)行的,這和C語言的運(yùn)行的流程是一致的。
OpenGL上運(yùn)行代碼分為頂點(diǎn)著色器和片段著色器,頂點(diǎn)著色器是告訴GPU三角形的三個(gè)頂點(diǎn)是在哪里畫,片段著色器是告訴GPU這個(gè)三角形中每個(gè)像素是要畫成什么樣的顏色。如何來表示這個(gè)邏輯,OpenGL用的是自己的GLSL語言,這其實(shí)也跟C語言是差不多的。
version 300 es
in vec4 vPosition;
void main()
{
gl_Position = vPosition;
}
以上是頂點(diǎn)著色器的代碼,“gl_Position = vPosition ”中,gl_Position 是內(nèi)置變量,其實(shí)就是告訴CPU當(dāng)前要在哪個(gè)位置頂點(diǎn)。編譯一個(gè)OpenGL 代碼實(shí)現(xiàn)如下:
String vShaderStr =
"#version 300 es \n"
+ "in vec4 vPosition; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = vPosition; \n"
+ "} \n";
String fShaderStr =
"#version 300 es \n"
+ "precision mediump float; \n"
+ "out vec4 fragColor; \n"
+ "void main() \n"
+ "{ \n"
+ " fragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 ); \n"
+ "} \n";
int vertexShader;
int fragmentShader;
int programObject;
int[] linked = new int[1];
// Load the vertex/fragment shaders
vertexShader = LoadShader ( GLES30.GL_VERTEX_SHADER, vShaderStr );
fragmentShader = LoadShader ( GLES30.GL_FRAGMENT_SHADER, fShaderStr );
// Create the program object
programObject = GLES30.glCreateProgram();
if ( programObject == 0 )
{
return;
}
GLES30.glAttachShader ( programObject, vertexShader );
GLES30.glAttachShader ( programObject, fragmentShader );
// Bind vPosition to attribute 0
GLES30.glBindAttribLocation ( programObject, 0, "vPosition" );
// Link the program
GLES30.glLinkProgram ( programObject );
// Check the link status
GLES30.glGetProgramiv ( programObject, GLES30.GL_LINK_STATUS, linked, 0 );
if ( linked[0] == 0 )
{
Log.e ( TAG, "Error linking program:" );
Log.e ( TAG, GLES30.glGetProgramInfoLog ( programObject ) );
GLES30.glDeleteProgram ( programObject );
return;
}
其中加載編譯任一著色器代碼如下:
private int LoadShader ( int type, String shaderSrc )
{
int shader;
int[] compiled = new int[1];
// Create the shader object
shader = GLES30.glCreateShader ( type );
if ( shader == 0 )
{
return 0;
}
// Load the shader source
GLES30.glShaderSource ( shader, shaderSrc );
// Compile the shader
GLES30.glCompileShader ( shader );
// Check the compile status
GLES30.glGetShaderiv ( shader, GLES30.GL_COMPILE_STATUS, compiled, 0 );
if ( compiled[0] == 0 )
{
Log.e ( TAG, GLES30.glGetShaderInfoLog ( shader ) );
GLES30.glDeleteShader ( shader );
return 0;
}
return shader;
}
以上的所有操作就是給GPU準(zhǔn)備一個(gè)可供著色器運(yùn)行的程序,但是目前仍沒有上傳數(shù)據(jù)。
上傳渲染數(shù)據(jù)
說明
上傳給著色器的數(shù)據(jù)分為兩種:
屬性數(shù)據(jù)(Attribute):如頂點(diǎn)位置、紋理坐標(biāo)、用于光線計(jì)算的表面法線用于計(jì)算屏幕上每個(gè)頂點(diǎn)的最終位置,針對(duì)每個(gè)頂點(diǎn)著色器都會(huì)執(zhí)行一次
Uniform數(shù)據(jù): 我在理解中,屬性數(shù)據(jù)如果相當(dāng)于常量數(shù)據(jù),那么Uniform相當(dāng)于程序中的變量,每次渲染時(shí)CPU都可以給其上傳一個(gè)新的值供著色器使用
上傳數(shù)據(jù)
要上傳數(shù)據(jù)給CPU,需要先綁定頂點(diǎn)著色器的位置:
GLES30.glBindAttribLocation ( programObject, 0, "vPosition" );
以上綁定程序programObject頂點(diǎn)著色器的vPosition屬性變量的標(biāo)識(shí)下標(biāo)為0,該下標(biāo)是對(duì)vPosition操作的標(biāo)識(shí),接下來上傳頂點(diǎn)數(shù)據(jù) :
GLES30.glVertexAttribPointer ( 0, 3, GLES30.GL_FLOAT, false, 0, mVertices );
GLES30.glEnableVertexAttribArray ( 0 );
glVertexAttribPointer用來上傳頂點(diǎn)數(shù)據(jù)
public static void glVertexAttribPointer(
int indx,
int size,
int type,
boolean normalized,
int stride,
java.nio.Buffer ptr
)
上傳數(shù)據(jù)的參數(shù)比較多,涵義如下:
int index,//屬性數(shù)據(jù)下標(biāo)位置,也就是之前綁定的下標(biāo)
int size,//每個(gè)頂點(diǎn)有多少個(gè)分量與其關(guān)聯(lián),如果只使用(x,y),那就是2
int type,//頂點(diǎn)的數(shù)據(jù)類型
boolean normalized,//type為整形有意義
int stride,//一個(gè)數(shù)據(jù)存儲(chǔ)于多個(gè)屬性時(shí),表示每個(gè)頂點(diǎn)的跨距
java.nio.Buffer ptr//數(shù)據(jù)區(qū)
繪制圖形
直接使用頂點(diǎn)數(shù)據(jù)不使用VBO來繪制使用的是:
void glDrawArrays( GLenum mode,
GLint first,
GLsizei count);
對(duì)應(yīng)在本程序中使用:
GLES30.glDrawArrays ( GLES30.GL_TRIANGLES, 0, 3 );
mode 指繪制模式,包括點(diǎn)、線、三角形等方式
first 指原來頂點(diǎn)數(shù)據(jù)的以指定的size(3)切分之后的起始坐標(biāo)
count 指繪制3個(gè)三個(gè)形