百度文庫(kù)地址:https://wenku.baidu.com/view/bd64ef8c33d4b14e8424684f?fr=prin
與OpenGL ES1.x渲染管線相比,OpenGL ES 2.0渲染管線中“頂點(diǎn)著色器”取代了OpenGL ES 1.x渲染管線中的“變換和光照”;“片元著色器”取代了OpenGL ES 1.x渲染管線中的“紋理環(huán)境和顏色求和”、“霧”以及“Alpha測(cè)試”。
這使得開(kāi)發(fā)人員在使用OpenGL ES 2.0API進(jìn)行開(kāi)發(fā)時(shí),不得不編寫(xiě)著色器代碼,來(lái)完成一些頂點(diǎn)變換和紋理顏色計(jì)算的工作。
這里介紹的與shader相關(guān)的部分主要分為三個(gè)階段:
1.加載shader,其中包括加載shader、編譯shader 、連接shader并且產(chǎn)生著色器程序id(文中的1、2、3部分);
2.獲取指向頂點(diǎn)著色器相應(yīng)數(shù)據(jù)的Index(文中的第4部分);
3.根據(jù)Index向頂點(diǎn)著色器中傳遞數(shù)據(jù)(文中的第5 部分);
1. 著色器與著色語(yǔ)言
著色語(yǔ)言是一種類C語(yǔ)言,但不像C語(yǔ)言一樣支持雙精度浮點(diǎn)型(double)、字節(jié)型(byte)、短整型(short)、長(zhǎng)整型(long),并且取消了C中的聯(lián)合體(union)、枚舉類型(enum)、無(wú)符號(hào)數(shù)(unsigned)以及位運(yùn)算等特性。
著色語(yǔ)言中有許多內(nèi)建的原生數(shù)據(jù)類型以及構(gòu)建數(shù)據(jù)類型,如:浮點(diǎn)型(float)、布爾型(bool)、整型(int)、矩陣型(matrix)以及向量型(vec2、vec3等)等??傮w來(lái)說(shuō),這些數(shù)據(jù)類型可以分為標(biāo)量、向量、矩陣、采樣器、結(jié)構(gòu)體以及數(shù)組等。
shader支持下面數(shù)據(jù)類型:
Float bool int
vec2 包含了2個(gè)浮點(diǎn)數(shù)的向量
vec3 包含了3個(gè)浮點(diǎn)數(shù)的向量
vec4 包含了4個(gè)浮點(diǎn)數(shù)的向量
ivec2 包含了2個(gè)整數(shù)的向量
ivec3 包含了3個(gè)整數(shù)的向量
ivec4 包含了4個(gè)整數(shù)的向量
bvec2 包含了2個(gè)布爾數(shù)的向量
bvec3 包含了3個(gè)布爾數(shù)的向量
bvec4 包含了4個(gè)布爾數(shù)的向量
mat2 22維矩陣
mat3 33維矩陣
mat4 4*4維矩陣
sampler1D 1D紋理著色器
sampler2D 2D紋理著色器
sampler3D 3D紋理著色器
1.1、 頂點(diǎn)著色器
(1) 頂點(diǎn)著色器代碼
uniform mat4 uMVPMatrix; //應(yīng)用程序傳入頂點(diǎn)著色器的總變換矩陣
attribute vec4 aPosition; //應(yīng)用程序傳入頂點(diǎn)著色器的頂點(diǎn)位置
attribute vec2 aTextureCoord; //應(yīng)用程序傳入頂點(diǎn)著色器的頂點(diǎn)紋理坐標(biāo)
attribute vec4 aColor //應(yīng)用程序傳入頂點(diǎn)著色器的頂點(diǎn)顏色變量
varying vec4 vColor //用于傳遞給片元著色器的頂點(diǎn)顏色數(shù)據(jù)
varying vec2 vTextureCoord; //用于傳遞給片元著色器的頂點(diǎn)紋理數(shù)據(jù)
void main()
{
gl_Position = uMVPMatrix * aPosition; //根據(jù)總變換矩陣計(jì)算此次繪制此頂點(diǎn)位置
vColor = aColor; //將頂點(diǎn)顏色數(shù)據(jù)傳入片元著色器
vTextureCoord = aTextureCoord; //將接收的紋理坐標(biāo)傳遞給片元著色器
}
(2) 頂點(diǎn)著色器介紹
頂點(diǎn)著色器是一個(gè)可編程的處理單元,并且執(zhí)行頂點(diǎn)的變換、紋理坐標(biāo)的變換、光照、材質(zhì)的應(yīng)用等頂點(diǎn)的相關(guān)操作,每頂點(diǎn)執(zhí)行一次。
頂點(diǎn)著色器替代了頂點(diǎn)變換、光照以及紋理坐標(biāo)的處理,開(kāi)發(fā)人員可以根據(jù)自己的需求自行開(kāi)發(fā)頂點(diǎn)變換、光照以及紋理坐標(biāo)的處理,大大增加了程序的靈活性。
頂點(diǎn)著色器主要是傳入相應(yīng)的Attribute變量、Uniforms變量、采樣器以及臨時(shí)變量,經(jīng)過(guò)頂點(diǎn)著色器后生成Varying變量。如圖1-1所示。

圖1-1頂點(diǎn)著色器工作原理
- Attribute變量(屬性變量)只能用于頂點(diǎn)著色器中,而不能在片元著色器中使用。一般用于每個(gè)頂點(diǎn)都各自不同的量,如頂點(diǎn)位置、顏色等。
Uniforms變量(一致變量)用來(lái)將數(shù)據(jù)值從應(yīng)用程其序傳遞到頂點(diǎn)著色器或者片元著色器。一般用于對(duì)同一組頂點(diǎn)組成的單個(gè)3D物體中所有頂點(diǎn)都相同的量,如當(dāng)前的光源位置、總變換矩陣等。 - Varying變量(易變變量)是從頂點(diǎn)著色器傳遞到片元著色器的數(shù)據(jù)變量。頂點(diǎn)著色器可以使用易變變量來(lái)傳遞需要插值的顏色、法向量、紋理坐標(biāo)等任意值。例如:上面代碼中應(yīng)用程序中由頂點(diǎn)著色器傳入片元著色器中的vColor變量。
- gl_Position頂點(diǎn)著色器從應(yīng)用程序中獲得原始的頂點(diǎn)位置數(shù)據(jù),這些原始的頂點(diǎn)數(shù)據(jù)在頂點(diǎn)著色器中經(jīng)過(guò)平移、旋轉(zhuǎn)、縮放等數(shù)學(xué)變換后,生成新的頂點(diǎn)位置。新的頂點(diǎn)位置通過(guò)在頂點(diǎn)著色器中寫(xiě)入gl_Position傳遞到渲染管線的后繼階段繼續(xù)處理。
- gl_PointSize頂點(diǎn)著色器中可以計(jì)算一個(gè)點(diǎn)的大小(單位為像素),并將其賦值給gl_PointSize(標(biāo)量float類型)以傳遞給渲染管 線。如果沒(méi)有明確賦值的話,就是采用默認(rèn)值1了。gl_PointSize的值一般只有在采用了點(diǎn)繪制方式之后才有意義。
1.2、 片元著色器
(1) 片元著色器代碼
precision mediump float; //設(shè)置工作精度
varying vec4 vColor; //接收從頂點(diǎn)著色器過(guò)來(lái)的頂點(diǎn)顏色數(shù)據(jù)
varying vec2 vTextureCoord; //接收從頂點(diǎn)著色器過(guò)來(lái)的紋理坐標(biāo)
uniform sampler2D sTexture; //紋理采樣器,代表一幅紋理
void main() {
gl_FragColor = texture2D(sTexture, vTextureCoord) * vColor; //進(jìn)行紋理采樣
}
此片元著色器的主要功能為根據(jù)接收的記錄片元紋理坐標(biāo)的易變變量中的紋理坐標(biāo),調(diào)用texture2D內(nèi)建函數(shù)從采樣器中進(jìn)行紋理采樣,得到此片元的顏色值。最后,將采樣到的顏色值傳給gl_FragColor內(nèi)建變量,完成片元的著色。
(2) 片元著色器介紹
片元著色器是一個(gè)處理片元值及其相關(guān)聯(lián)數(shù)據(jù)的可編程單元,片元著色器可執(zhí)行紋理的訪問(wèn)、顏色的匯總、霧化等操作,每片元執(zhí)行一次。
片元著色器替代了紋理、顏色求和、霧以及Alpha測(cè)試,這一部分是需要開(kāi)發(fā)者自己開(kāi)發(fā)的。

- Varying指的是從頂點(diǎn)著色器傳遞到片元著色器的數(shù)據(jù)變量。
- gl_FragColor(vec4類型)內(nèi)置變量用來(lái)由片元著色器計(jì)算完成的片元顏色值,此顏色值將送入渲染管線的后繼階段進(jìn)行處理,例如片元著色器中g(shù)l_FragColor = vColor。
- 加載著色器腳本代碼loadShader方法的介紹
/*
*shader的類型 GLES20.GL_VERTEX_SHADER GLES20.GL_FRAGMENT_SHADER
*shader的腳本字符串
*/
private int loadShader( int shaderType,String source ) {
//創(chuàng)建一個(gè)新shader
int shader = GLES20.glCreateShader(shaderType);
//若創(chuàng)建成功則加載shader
if (shader != 0) {
//加載shader的源代碼
GLES20.glShaderSource(shader, source);
//編譯shader
GLES20.glCompileShader(shader);
//存放編譯成功shader數(shù)量的數(shù)組
int[] compiled = new int[1];
//獲取Shader的編譯情況
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
//若編譯失敗則顯示錯(cuò)誤日志并刪除此shader
Log.e(TAG, "Could not compile shader " + shaderType + ":");
Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
該方法中主要為三個(gè)方法
GLES20.glCreateShader(shaderType);
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
3.1. GLES20.glCreateShader(shaderType);
用glCreateShader創(chuàng)建一個(gè)容納shader的容器,稱為shader容器。
方法參數(shù):
GLES20.GL_VERTEX_SHADER (頂點(diǎn)shader)
GLES20.GL_FRAGMENT_SHADER (片元shader)
函數(shù)原型為:
int glCreateShader (int type)
如果調(diào)用成功的話,函數(shù)將返回一個(gè)整形的正整數(shù)作為shader容器的id。
3.2. GLES20.glShaderSource(shader, source);
接下來(lái),要在創(chuàng)建好的shader容器中添加shader的源代碼。源代碼應(yīng)該以字符串?dāng)?shù)組的形式表示。當(dāng)然,也可以只用一個(gè)字符串來(lái)包含所有的源代碼。
glShaderSource函數(shù)的原型如下:
void glShaderSource (int shader, String string)
參數(shù)含義:
shader是代表shader容器的id(由glCreateShader返回的整形數(shù));
strings是包含源程序的字符串?dāng)?shù)組;
3.3. GLES20.glCompileShader(shader);
最后,使用glCompileShader函數(shù)來(lái)對(duì)shader容器中的源代碼進(jìn)行編譯。
函數(shù)的原型如下:
void glCompileShader (int shader)
參數(shù)含義:
shader是代表shader容器的id
3.4. 調(diào)試
調(diào)試一個(gè)shader是非常困難的。shader的世界里沒(méi)有printf,無(wú)法在控制臺(tái)中打印調(diào)試信息。但是可以通過(guò)一些OpenGL提供的函數(shù)來(lái)獲取編譯和連接過(guò)程中的信息。
在編譯階段使用glGetShaderiv獲取編譯情況,在連接階段使用glGetProgramiv獲取連接情況。
當(dāng)錯(cuò)誤產(chǎn)生的時(shí)候,還可以從InfoLog中獲得更多的信息。InfoLog中存儲(chǔ)了關(guān)于上一個(gè)操作執(zhí)行時(shí)的相關(guān)信息,比如編譯階段的警告和錯(cuò)誤,以及連接階段產(chǎn)生的問(wèn)題。不幸的是對(duì)于錯(cuò)誤信息沒(méi)有統(tǒng)一的標(biāo)準(zhǔn),所以不同的硬件或驅(qū)動(dòng)程序?qū)⑻峁┎煌腻e(cuò)誤信息。
編譯階段使用glGetShaderInfoLog獲取編譯錯(cuò)誤,
(1) 編譯階段使用glGetShaderiv獲取編譯情況
void glGetShaderiv (int shader, int pname, int[] params, int offset)
參數(shù)含義:
shader是一個(gè)shader的id;
pname使用GL_COMPILE_STATUS;
params是返回值,如果一切正常返回GL_TRUE代,否則返回GL_FALSE。
(2) 編譯階段使用glGetShaderInfoLog獲取編譯錯(cuò)誤
函數(shù)原型:
String glGetShaderInfoLog (int shader)
參數(shù)含義:
shader是一個(gè)頂點(diǎn)shader或者片元shader的id
這里值得一說(shuō)的是,筆者隨便打印了一個(gè)shader的編譯錯(cuò)誤,得出的string字符串卻為空,不知原因?????。
(3) 在連接階段使用glGetProgramiv獲取連接情況
函數(shù)原型:
void glGetProgramiv (int program, int pname, int[] params, int offset)
參數(shù)含義:
program是一個(gè)著色器程序的id;
pname是GL_LINK_STATUS;
param是返回值,如果一切正常返回GL_TRUE代,否則返回GL_FALSE。
(4) 在連接階段使用glGetProgramInfoLog獲取連接錯(cuò)誤
函數(shù)原型:
String glGetProgramInfoLog (int program)
參數(shù)含義:
program是一個(gè)著色器程序的id;
對(duì)于連接錯(cuò)誤的打印,因?yàn)樯袥](méi)有遇到過(guò),所以不知道打印字符串的信息。
(5) 清理shader的glDeleteShader方法
當(dāng)不再需要某個(gè)shader或某個(gè)程序的時(shí)候,需要對(duì)其進(jìn)行清理,以釋放資源。前面,提到過(guò)如何向一個(gè)程序中添加一個(gè)shader。這里可調(diào)用下面的函數(shù)來(lái)將一個(gè)shader從一個(gè)程序中清除掉:
函數(shù)原型:
void glDeleteShader (int shader);
參數(shù)含義:
shader是要被排除的頂點(diǎn)shader或者片元shader的id
如果,一個(gè)shader被刪除之前沒(méi)有從相應(yīng)的程序中排除,那么這個(gè)shader不會(huì)被實(shí)際刪除,而只是被標(biāo)記為被刪除;當(dāng)shader被從程序中排除的時(shí)候,才會(huì)被真正地刪除。
- 生成著色器程序id的createProgram方法介紹
//創(chuàng)建shader程序的方法
private int createProgram(String vertexSource, String fragmentSource) {
//加載頂點(diǎn)著色器
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;
}
//創(chuàng)建著色器程序
int program = GLES20.glCreateProgram();
//若程序創(chuàng)建成功則向程序中加入頂點(diǎn)著色器與片元著色器
if (program != 0) {
//向程序中加入頂點(diǎn)著色器
GLES20.glAttachShader(program, vertexShader);
//向程序中加入片元著色器
GLES20.glAttachShader(program, pixelShader);
//鏈接程序
GLES20.glLinkProgram(program);
//存放鏈接成功program數(shù)量的數(shù)組
int[] linkStatus = new int[1];
//獲取program的鏈接情況
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
//若鏈接失敗則報(bào)錯(cuò)并刪除程序
if (linkStatus[0] != GLES20.GL_TRUE) {
Log.e(TAG, "Could not link program: ");
Log.e(TAG, GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
program = 0;
}
}
return program;
}
3.1. glCreateProgram
在連接shader之前,首先要?jiǎng)?chuàng)建一個(gè)容納程序的容器,稱為著色器程序容器??梢酝ㄟ^(guò)glCreateProgram函數(shù)來(lái)創(chuàng)建一個(gè)程序容器。
函數(shù)的原型如下:
int glCreateProgram ()
如果函數(shù)調(diào)用成功將返回一個(gè)整形正整數(shù)作為該著色器程序的id
3.2. glAttachShader
接下來(lái),我們要將shader容器添加到程序中。這時(shí)的shader容器不一定需要被編譯,他們甚至不需要包含任何的代碼。我們要做的只是將shader容器添加到程序中。使用glAttachShader函數(shù)來(lái)為程序添加shader容器。
函數(shù)的原型如下:
void glAttachShader (int program, int shader)
參數(shù)含義:
program是著色器程序容器的id;
shader是要添加的頂點(diǎn)或者片元shader容器的id。
如果你同時(shí)擁有了,頂點(diǎn)shader和片元shader,需要分別將他們各自的兩個(gè)shader容器添加的程序容器中。
3.3. glLinkProgram
最后,使用glLinkProgram來(lái)連接程序。
函數(shù)的原型如下:
void glLinkProgram (int program)
參數(shù)含義:
program是著色器程序容器的id
在連接操作執(zhí)行以后,可以任意修改shader的源代碼,對(duì)shader重新編譯不會(huì)影響整個(gè)程序,除非重新連接程序。
3.4. glUseProgram
在連接了程序以后,我們可以使用glUseProgram函數(shù)來(lái)加載并使用連接好的程序。glUseProgram函數(shù)原型如下:
void glUseProgram (int program)
參數(shù)含義:
program是要使用的著色器程序的id,
如果將program設(shè)置為0,表示使用固定功能管線。如果程序已經(jīng)在使用的時(shí)候,對(duì)程序進(jìn)行重新編譯,編譯后的應(yīng)用程序會(huì)自動(dòng)替代以前的那個(gè)被調(diào)用,這時(shí)你不需要再次調(diào)用這個(gè)函數(shù)。
- 獲取指向頂點(diǎn)著色器相應(yīng)數(shù)據(jù)的Index(glGetAttribLocation方法, glGetUniformLocation方法)
public int mProgram; //自定義渲染管線程序id
public int muMVPMatrixHandle; //總變換矩陣引用id
public int maPositionHandle; //頂點(diǎn)位置屬性引用id
public int maTextureHandle; //頂點(diǎn)紋理坐標(biāo)屬性引用id
public int maColorHandle; //頂點(diǎn)顏色坐標(biāo)屬性引用id
//基于頂點(diǎn)著色器與片元著色器創(chuàng)建著色器程序, 生成著色器程序id
mProgram = createProgram(mVertexShader, mFragmentShader);
//獲取指向著色器中aPosition的index
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//獲取指向著色器中aTextureCoord的index
maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
//獲取指向著色器中aColor的index
maColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
//獲取指向著色器中uMVPMatrix的index
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
glGetAttribLocation
調(diào)用 glGetAttribLocation 來(lái)獲取頂點(diǎn)著色器中,指定attribute名的index。以后就可以通過(guò)這個(gè)index向頂點(diǎn)著色器中傳遞數(shù)據(jù)。獲取失敗則返回-1。
- 向頂點(diǎn)著色器中傳遞數(shù)據(jù)
在創(chuàng)建了定點(diǎn)著色器和片源著色器后,我們?cè)贠penGL中如何使用這兩個(gè)著色器呢,我們從下面的示例代碼來(lái)學(xué)習(xí)。
使用第4節(jié)獲取的指向頂點(diǎn)著色器相應(yīng)數(shù)據(jù)的各個(gè)Index,就能將我們自己定義的頂點(diǎn)數(shù)據(jù)、 頂點(diǎn)顏色數(shù)據(jù)以及紋理頂點(diǎn)映射數(shù)據(jù)傳遞到頂點(diǎn)著色器當(dāng)中了。在傳遞數(shù)據(jù)前先要調(diào)用GLES20.glUseProgram(mProgram);方法使用 我們?cè)诘?節(jié)創(chuàng)建的著色器程序mProgram。
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//將最終變換矩陣傳入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//設(shè)置緩沖區(qū)起始位置
mRectBuffer.position(0);
//頂點(diǎn)位置數(shù)據(jù)傳入著色器
GLES20.glVertexAttribPointer(maPositionHandle,
3,
GLES20.GL_FLOAT,
false,
20,
mRectBuffer);
//頂點(diǎn)顏色數(shù)據(jù)傳入著色器中
GLES20.glVertexAttribPointer(maColorHandle, 4, GLES20.GL_FLOAT, false, 4*4, mColorBuffer);
//頂點(diǎn)坐標(biāo)傳遞到頂點(diǎn)著色器
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 20, mRectBuffer);
//允許使用頂點(diǎn)坐標(biāo)數(shù)組
GLES20.glEnableVertexAttribArray(maPositionHandle);
//允許使用頂點(diǎn)顏色數(shù)組
GLES20.glDisableVertexAttribArray(maColorHandle);
//允許使用定點(diǎn)紋理數(shù)組
GLES20.glEnableVertexAttribArray(maTextureHandle);
//綁定紋理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
//三角形繪制方式
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4);
}
5.1. glUseProgram
在連接了程序以后,我們可以使用glUseProgram函數(shù)來(lái)加載并使用連接好的程序。glUseProgram函數(shù)原型如下:
void glUseProgram (int program)
參數(shù)含義:
program是要使用的著色器程序的id,
如果將program設(shè)置為0,表示使用固定功能管線。如果程序已經(jīng)在使用的時(shí)候,對(duì)程序進(jìn)行重新編譯,編譯后的應(yīng)用程序會(huì)自動(dòng)替代以前的那個(gè)被調(diào)用,這時(shí)你不需要再次調(diào)用這個(gè)函數(shù)。
5.2. glVertexAttribPointer
glVertexAttribPointer — 定義頂點(diǎn)屬性數(shù)組
函數(shù)原型:
void glVertexAttribPointer ( int indx,
int size,
int type,
boolean normalized,
int stride,
Buffer ptr )
參數(shù)含義:
index 指定要修改的頂點(diǎn)著色器中頂點(diǎn)屬性的索引值
size 指定每個(gè)頂點(diǎn)屬性的組件數(shù)量。必須為1、2、3或者4。如position是由3個(gè)(x,y,z)組成,而顏色是4個(gè)(r,g,b,a))
type 指定數(shù)組中每個(gè)組件的數(shù)據(jù)類型??捎玫姆?hào)常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值為GL_FLOAT。
normalized指定當(dāng)被訪問(wèn)時(shí),固定點(diǎn)數(shù)據(jù)值是否應(yīng)該被歸一化(GL_TRUE)或者直接轉(zhuǎn)換為固定點(diǎn)值(GL_FALSE)。
stride 指定連續(xù)頂點(diǎn)屬性之間的偏移量。如果為0,那么頂點(diǎn)屬性會(huì)被理解為:它們是緊密排列在一起的。初始值為0。如果normalized被設(shè)置為 GL_TRUE,意味著整數(shù)型的值會(huì)被映射至區(qū)間-1,1,或者區(qū)間[0,1](無(wú)符號(hào)整數(shù)),反之,這些值會(huì)被直接轉(zhuǎn)換為浮點(diǎn)值而不 進(jìn)行歸一化處理。
Ptr頂點(diǎn)的緩沖數(shù)據(jù)
5.3. 啟用或者禁用頂點(diǎn)屬性數(shù)組
要啟用或者禁用頂點(diǎn)屬性數(shù)組,調(diào)用glEnableVertexAttribArray和 glDisableVertexAttribArray傳入?yún)?shù)index。如果啟用,那么當(dāng)glDrawArrays或者glDrawElements 被調(diào)用時(shí),頂點(diǎn)屬性數(shù)組會(huì)被使用。
5.4. glActiveTexture
glActiveTexture — 選擇活動(dòng)紋理單元
函數(shù)原型:
void glActiveTexture (int texture)
參數(shù)含義:
texture指定哪一個(gè)紋理單元被置為活動(dòng)狀態(tài)。texture必須是GL_TEXTUREi之一,其中0 <= i < GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,初始值為GL_TEXTURE0。
glActiveTexture 確定了后續(xù)的紋理狀態(tài)改變影響哪個(gè)紋理,紋理單元的數(shù)量是依據(jù)該紋理單元所被支持的具體實(shí)現(xiàn)。