我學習OpenGL ES2.0的路線是,在已有圖形學了解的基礎上,先讀OpenGL ES2.0 full spec,讀完spec後再學習書本
Addison.Wesley.OpenGL.ES.2.0.Programming.Guide.Aug,編幾個ES程式加深了解。接着再研究ES的硬體實作。。。
是以一開始将是OpenGL ES2.0 full spec的摘抄,小部分是看不明白了,從其他地方找的參考資料。
OpenGL與OpenGL ES的異同在文檔
OpenGL ES Common Profile Specification 2.0(Difference Specification).
以下若沒有着重說明,GL簡稱指的是OpenGL ES,函數名省略gl字首。
1 .介紹
程式員角度
OpenGL ES程式包含
a. 在framebuffer中開辟一個繪制視窗,
b. 在繪制視窗中配置設定context
companion API Khronos Native PlatformGraphicsInterface(EGL)
c.OpenGL ES command
c.1. 繪制點、線、面等幾何的基本繪制單元
c.2. 控制如何光栅化這些基本繪制單元的設定,例如光照,顔色,三維模組化空間到二維可視空間的轉換
c.3. framebuffer直接操作指令,例如讀像素點。
實作者角度
OpenGL ES是一系列控制圖形硬體操作的指令。硬體實作者,需要提供給一個CPU軟體接口。對于部分OpenGLES指令,是在CPU中用軟體實作或者在圖形硬體中實作,需要很好的劃分。
CPU軟體可以擷取大量的狀态資訊。
協定制定者角度
OpenGL ES 是一個控制特定繪制指令的狀态機模型。所有實作需要産生協定中指定方法相同的輸出。
OpenGL ES 2.0支援OpenGL ES 1.0 shading language。
2.OpenGL ES Operation
2.1 OpenGL ES基礎
基本繪制單元由一個或多個頂點定義,一個頂點指一個點,一條邊的一個端點,一個三角形的一個頂點。每個頂點包含屬性有:位置坐标,顔色,法向量,紋理坐标等。在圖形流水線中,一般每個頂點經過獨立、順序和相同的處理。例外就是當映射到特定區域時一些頂點進行了裁剪,這時候會改變一些頂點的屬性或者新插入一些頂點。
指令一般按照接收到的順序依次執行,從接收到完成可能會有一些延遲。一個基本繪制單元在前一個已經完全繪制完畢才能影響framebuffer。是以,queries和像素讀等指令傳回的結果應該與所有前面GL指令執行完畢的結果一緻。大體上,一個GL指令對于工作模式和framebuffer的影響,應當在下一個指令起作用前完成。
GL的資料綁定發生在指令執行時,也就是指令的參數在指令接收到時interpreted。指令接收後資料的變化不影響GL目前指令。
GL允許直接控制3D,2D圖形的基本操作,這些操作包含:應用特定的shader程式(執行變換,光照,紋理,shading操作) ,以及内部的反走樣和紋理濾波。GL不提供描述和模組化複雜幾何物體的機制。也就是說GL隻提供複雜幾何物體是怎麼render的機制。
GL設計可以運作在不同功能和性能的圖形硬體下。為便于相容差異性,GL spec按照GL操作的理想行為描述。在一些允許實際行為偏離理想行為的情形下,GL spec規定近似實作需要符合的規則。
2.1.1 數值計算
通常由floating-point實作運算, 範圍和精度需要滿足 ”Floating-Point Computation” below.
浮點運算規則
浮點數最大值232
x*0 =0*x = 0, 1*x = x*1 = x, x+0 = 0+x = x, 00 = 1
GL指令需要正常處理所有正常的浮點數,異常的浮點數不能使得GL中斷或終止。非浮點數輸入不需要滿足此規則。
定點運算規則
頂點屬性資料可以用32位的2進制補碼表示,16位小數。
基本規則
除法操作時,除數是0,結果不确定,但不能引起GL中斷或終止。
2.1.2 資料格式轉換
歸一化整數,無符号數在[0,1],注意0,1值都可取到,
有符号數在[-1,1],-1,1值都可取到。
歸一化整數轉浮點數
對于無符号b位整數c,f = c/(2^b-1)
對于有符号b位整數c,f = (2c+1)/(2^b-1)
浮點數轉歸一化整數
對于無符号b位整數c,c = f * (2^b - 1)
對于有符号b位整數c,c = (f * (2^b - 1) – 1)/2
浮點數轉framebuffer定點數
2.2 GL state
GL state 分兩類,GL server類和GL client類
大多數state都是GL server類
2.3 GL指令文法
指令聲明格式如下
rtype Name{1234}{Φ i f}{Φ v} ([args,] T arg1, …, T arg N [, args])
固定類型參數的資料格式(13種)
GL Type Minimum Bit Width Description
boolean1 Boolean
byte8 Signed binaryinteger
ubyte8 Unsigned binaryinteger
char8 charactersmaking up strings
short16 Signed 2’scomplement binary integer
ushort16 Unsignedbinary integer
int 32 Signed 2’s complement binaryinteger
uint32 Unsignedbinary integer
fixed32 Signed 2’scomplement 16.16 scaled integer
sizei32 Non-negativebinary integer size
enum32 Enumeratedbinary integer value
intptrptrbits Signed 2’s complement binary integer
sizeiptrptrbits Non-negative binary integer size
bitfield32 Bit field
float32 Floating-pointvalue
clampf32 Floating-pointvalue clamped to [0; 1]
C語言内建int<->float轉換,無int<->fix, float<->fix
enum <-> 無scale fixed, int * 2^16<->fixed
2.4 基本GL操作
figure2.1 GL框圖
此框圖可以很好的描述GL操作,具體實作不限于此框圖中的結構和順序。
2.5 GL Errors
指令enum GetError( void );
傳回上次調用該指令後GL發生的錯誤代碼,調用間隔中發生的同類型錯誤隻記錄一次。
錯誤類型如下:
Error Description Offending command ignored?
INVALIDENUM enum argument out of range Yes
INVALIDFRAMEBUFFER OPERATION Framebuffer is incomplete Yes
INVALIDVALUE Numeric argumentout of range Yes
INVALIDOPERATION Operation illegalin current state Yes
OUTOF MEMORY Not enough memoryleft to execute command Unknown
除了發生記憶體溢出的緻命錯誤,其他GL錯誤的指令不改變指令修改的值,若有傳回值傳回0。
2.6 Primitives和頂點
GL中,使用頂點數組對應一系列基本屬性,組成幾何物體。7種幾何物體如下:
point, line strips, line segment loops, separatedline segments, triangle strips, triangle fans, and separated triangles.
每個頂點對應一個基本頂點屬性,每個屬性用1,2,3或4個标量值表示。基本頂點屬性可由vertex shaders讀寫,用以計算出後續階段處理所需的值。
Vertex shader處理前,vertex的state包括:多個基本屬性值集;vertex shader處理後,vertex的state包括:screen空間坐标和vertex shader其他輸出。
Figure: Vertexprocessing and primitive assembly
2.6.1 Primitive類型
指令DrawArray和DrawElements傳入 GL一個頂點序列。這倆指令的參數mode指定繪制primitive的類型。
Points:mode POINTS,每一頂點對應一個單獨的point圖形。
Line Strips:mode LINE_STRIP,第一個頂點是第一個線段的起始點,第i個頂點是第i個線段的起始點,也是第i-1個線段的結束點(i>2)。
需要的state包括:前一個頂點的處理結果,目前頂點是否第一個頂點的布爾标志。
Line Loops:modeLINE_LOOP,和Line Strips大緻相同,除了最後的頂點和第一個頂點組成一個線段。
需要的state包括:Line Strips的state相同需求,以及第一個頂點的處理結果。
Separate Lines:modeLINE,每一雙頂點組成一個線段。如果頂點個數為奇數個,最後一個頂點忽略。
需要的state包括:Line Strips的state相同需求(意義有所不同)。
Triangles Strips:modeTRIANGLE_STRIP,最先的三個頂點(順序很關鍵)組成第一個三角形,後續的每個頂點和前面的兩個頂點組成新的一個三角形。若頂點個數少于三個,忽略。
需要的state包括:第一個三角形是否已處理完成的布爾标志,已存儲A,B的兩個頂點,下一個頂點存儲的指針。
Triangle Fans:modeTRIANGLE_FAN,基本同TriangleStrips,除了下一個頂點總是覆寫位置B。
Separate Triangles:modeTRIANGLES,第3i+1, 3i+2,3i+3個頂點組成第i個三角形。其他基本同Triangle Strips。
三角形的頂點順序很關鍵!
Figure 2.3 a. Triangle Strips b. TriangleFans c. Independent Triangles
2.7 目前頂點state
Vertex shaders讀寫一個4個分量組成的頂點屬性數組。數組從0開始索引,最大容量由實作中定義的常數MAX_VERTEX_ATTRIBS定義。
當一個頂點數組中目前頂點未使能,頂點的屬性由目前基本屬性值定義(此句話意思不太明白)。可以任意時間調用下面函數來修改目前基本屬性值:
voidVertexAttrib{1234}{f}( uint index, T values );
voidVertexAttrib{1234}{f}v( uint index, T values );
函數将屬性值values寫入屬性數組第index項,每項包含屬性分量x,y,z,w。
VertexAttrib1*寫入x分量,同時置y,z = 0, w = 1;
VertexAttrib2*寫入x,y分量,同時置z = 0, w = 1;
VertexAttrib3*寫入x,y,z分量,同時置w = 1;
VertexAttrib4*寫入x,y,z,w分量。
若index大于等于MAX_VERTEXATTRIBS,GL報錯誤 INVALID_VALUE。
VertexAttrib*指令在vertex shader中可以用來載入聲明成2x2,3x3,4x4矩陣形式的屬性。矩陣的每一列占用4分量屬性數組中的一項,矩陣按列為主順序載入4分量屬性數組。同一矩陣的所有列載入數組的索引值依次增大。
OpenGL頂點處理需要的state也就是MAX_VERTEX ATTRIBS組存儲基本頂點屬性的4分量單精度浮點數組。所有屬性初始值[0 0 0 1]。
2.8 頂點數組
頂點數組存于clientaddress space。Client可以指定最多MAX_VERTEXATTRIBS個數組對應一個或多個基本頂點屬性。(注意這裡一個數組的概念和2.7似乎不一樣,數組的長度是下面的size)。
數組元素:數組裡的一個/兩個/三個或四個值對應一個基本頂點屬性。數組元素裡的資料在記憶體中連續存儲。
指令
void VertexAttribPointer( uint index, intsize, enum type,boolean normalized, sizei stride, const void *pointer );
指定了這些數組的組織和位置。
Command Sizes Normalized Types
VertexAttribPointer 1,2,3,4 flag byte, ubyte, short, ushort, fixed, float
type: 數組中資料類型
size: 每個頂點的屬性個數。若size不在下面範圍内,GL報error。
normalized: 整數是否歸一化為[0,1]或者[-1,1]
index: 索引了哪一個基本頂點屬性數組,若大于等于MAX_VERTEX ATTRIBS,GL報error。
stride: 若stride=0,數組元素也連續存儲。若stride為負,GL報error。Stride等于第i個元素和第i+1個元素的存儲間隔(以記憶體基本單元計數)。
pointer: 指向記憶體中第一個元素的第一個資料的位置。
每一個基本屬性數組可以調用以下函數使能和禁用。
voidEnableVertexAttribArray( uint index );
voidDisableVertexAttribArray( uint index );
指令
voidDrawArrays( enum mode, int first, sizei count );
voidDrawElements( enum mode, sizei count, enum type, void *indices );
If an array corresponding to a generic attribute requiredby a vertex shader is not enabled, then the corresponding element is taken fromthe current generic attribute state (see section 2.7).
http://www.gamedev.net/community/forums/topic.asp?topic_id=208558
glDrawElementsvs glDrawArrays
(注意是OpenGL,非ES,以下類似)
CoderTCD Membersince: 9/10/2001
Which one isfaster?
Ostsol Membersince: 12/20/2002 From: Edmonton, Canada
If you're usingindex arrays (with VBO) they're probably around the same speed. If not, thenDrawElements requires an array of indices to be tossed across the AGP bus eachframe can contribute greatly to the saturation of AGP bandwidth, which resultsin a performance hit. DrawArrays requires only a few integers to be passedacross the bus and therefore has less of an impact on bandwidth. Of course,there are cases where DrawArrays simply cannot be used.
GameCat Membersince: 10/17/2001 From: Stockholm, Sweden
DrawArraysobviously can't be used with index arrays as it doesn't take any indices. Ingeneral, DrawElements is faster unless you don't have any shared vertices atall, then DrawArrays is faster. This has to do with the vertex cache amongother things.
DrawRangeElementsis generally better than DrawElements although the difference is smaller whenyou use VBO's. If you use standard vertex arrays, DrawRangeElements should bemuch faster.
OpenGLVertex Array
舉例子比較了 glDrawElements和glDrawArrays,
http://www.songho.ca/opengl/gl_vertexarray.html
大緻來說,繪制一個不同多邊形有公用頂點的物體,glDrawElements相比較glDrawArrays,避免了重複頂點的GL資料發送,多了索引資料的發送,注意索引資料也是需要一定的帶寬。
注意:同一頂點在不同多邊形會有不同的屬性(例如normal),這時候需要将此頂點重複定義。
2.9 Buffer Object
參考OpenGL vertexbuffer object,
http://www.songho.ca/opengl/gl_vbo.html
頂點數組可以存儲在serveraddress space,VBO提供了vertex array(頂點資料在不同多邊形共享)和display list(資料可以給多個client共享)的好處,而避免了vertex array(資料需要頻繁的從client->server搬運)和display list(資料不能友善的修改)的壞處。
VBO: vertex buffer object
一個bufferobject使用BindBuffer函數建立,
void BindBuffer( enum target, uintbuffer );
//執行後,無符号數名稱buffer,被建立為target的buffer object
//target代表buffer oject是vertex array data還是index array data
BindBuffer還可用以連接配接一個已有的buffer object,原有連接配接會被斷開。
Buffer object删除如下,
void DeleteBuffers( sizei n, constuint *buffers );
//執行GenBuffers後,在buffers指向記憶體單元連續存儲n個沒有使用的bufferoject名稱。
void GenBuffers( sizei n, uint*buffers );
若調用DeleteBuffers删除Buffer object,同一線程中所有連接配接到此object的都複位為0,另外線程中連接配接到此object的不受影響,但是傳回不确定的值,例如報GL error或者render異常,但是程式不能中止。
可以将clientmemory的資料拷貝入servermemory中Buffer object的存儲空間,如下:
void BufferData( enum target,sizeiptr size, const void *data, enum usage );
data:指向client memory中源資料位置,
若GL不能建立size大小的存儲空間,報error OUT_OF_MEMORY
client調用如下函數,修改部分或全部buffer object中的資料:
void BufferSubData( enum target,intptr offset, sizeiptr size, const void *data );
若size或offset <0,或者offset+data> BUFFER_SIZE,GL報INVALID_VALUE error。
2.9.1 Buffer objects中的頂點數組
當buffer object的連接配接非0時,基本頂點屬性數組來源于server中的buffer,rendering函數DrawArrays和DrawElements其他操作基本同vertex array中一樣。
允許基本頂點屬性數組部分來源于client memory,部分來源于buffer object的組合。
2.9.2 Buffer objects中的數組索引
buffer object target = ELEMENT_ARRAY_BUFFER
注意GL實作中,ARRAY_BUFFER和ELEMENT_ARRAY_BUFFER的在server memory中的不同存儲方式,會帶來性能的明顯變化。
2.10 Vertex Shader
此部分需要閱讀OpenGL ES 2.0 Programming Guide後,才能弄得比較明白。
DrawArrays和DrawElements定義頂點屬性資料,而後頂點屬性資料由vertex shader處理。Vertex shader處理的頂點屬性資料來源于頂點數組元素相應的頂點屬性,若對應該屬性沒有頂點數組連接配接,則來源于相應的目前基本屬性值。
Vertex shader處理完成後,頂點輸入primitive assembly子產品。
vertex shader:每一個頂點的處理操作代碼,vertex shader使用的語言在OpenGL ES Shading Language Specification中定義。
Shader調用有兩種可選,
a.shader代碼載入shader對象,編譯,
b.預編譯的shader二進制代碼直接載入shader對象
若布爾标志SHADER_COMPILE為TRUE,OpenGL ES支援shader編譯器。若NUM_SHADER_ BINARY_FORMATS>0,OpenGL ES支援二進制載入。
一個Program對象,可以包含一個Vertex Shader對象和Fragment Shader
2.10.1 載入和編譯shader源代碼
uint CreateShader( enum type );//建立shader對象,type = VERTEX_SHADER
void ShaderSource( uint shader,sizei count, const char **string, const int *length ); //載入源代碼
void CompileShader( uint shader );
void ReleaseShaderCompiler( void );
2.10.2 載入shader二進制
void ShaderBinary( sizei count, const uint *shaders, enum binaryformat, const void *binary, sizei length );
相關常量:SHADER_BINARY_FORMATSNUM_SHADER_BINARY_FORMATS
if shader binary interfaces aresupported, then an OpenGL ES implementation may require that an optimized pairof vertex and fragment shader binaries that were compiled together be specifiedto LinkProgram. Not specifying an optimized pair may cause LinkProgram to fail.
2.10.3 Program Objects
program object: GL可程式設計階段的所有shader object的集合
executables: 可程式設計執行階段執行的program。
uint CreateProgram( void ); //建立一個Program對象
void AttachShader( uint program,uint shader ); //連接配接shader對象和program對象
一個program對象不能連接配接同一類型的多個shader對象,一個shader對象可以連接配接一個或多個program對象。
void DetachShader( uint program,uint shader );//斷開program和shader的連接配接
void LinkProgram( uint program ); //連結program對象,狀态LINK_STATUS可由GetProgramiv讀取
void UseProgram( uint program ); //目前rendering state使用program對象執行,若program=0,…
void DeleteProgram( uint program );//删除program對象
2.10.4 Shader Variables
vertex attributes
float,vec2,vec3,vec4,mat2,mat3,mat4編譯器和連結器若判定shader會使用某個基本屬性,則認為該屬性是active。
void GetActiveAttrib( uint program,uint index, sizei bufSize, sizei *length, int *size, enum *type, char *name );
//傳回索引index對應的active屬性
int GetAttribLocation( uint program,const char *name ); //傳回name對應的index
void BindAttribLocation( uintprogram, uint index, const char *name );
//名為name的屬性變量連接配接為索引為index的基本頂點屬性,不影響目前連結的program,影響下一個連結的program。
Uniforms
MAX_VERTEX_UNIFORM_VECTORS
int GetUniformLocation( uintprogram, const char *name );//傳回名為name的uniform變量位置
void GetActiveUniform( uint program, uint index, sizei bufSize, sizei *length, int *size, enum *type, char *name );
// void Uniform{1234}{if}( intlocation, T value );
void Uniform{1234}{if}v( intlocation, sizei count, T value );
void UniformMatrix{234}fv( intlocation, sizei count, boolean transpose, const float *value );
應用程式通過OpenGL ES2.0 API傳入shader的變量,該變量存儲了隻讀的常數值,稱為uniforms
samplers
标志texture對象, sampler的值标志着正通路的texture image單元。
Uniform1i{v};
varying variables
MAX_VARYING_VECTORS. interpolators
2.10.5 Shader Execution
Texture Access
MAX_VERTEX_TEXTURE_IMAGE_UNITS:vertex shader
MAX_TEXTURE_IMAGE_UNITS: fragmentshader
MAX_COMBINED_TEXTURE_IMAGE_UNITS:both shader
Vertex shader的texture lookup函數,需要一個顯式的level-of-detail 參數l
Validation
void ValidateProgram( uint program); //在目前GL state下,判定program對象是否可以運作,根據判定結果修改program對象的VALIDATE_STATUS, Undefined Behavior
實作相關,數組越界等的保護..
2.10.6 Required State
目前program對象名稱
shader object
shader object名稱,無符号整數SHADER TYPE值,
整數删除标志,初始FALSE上次編譯标志,初始FALSE
information log,字元數組,初始空
information log長度,整數
concatenatedshader string,字元數組,初始空
concatenated shader string長度,整數
program object
program object名稱,無符号整數
删除标志,初始FALSE上次連結結果标志,初始FALSE
上次有效性檢查結果标志,初始FALSE
連接配接的shader對象個數,整數
所有連接配接的shader對象的名稱清單,無符号整數
information log,字元數組,初始空
information log長度,整數
active uniforms的個數,整數
每個active uniform的,位置,大小,類型——整數,名稱——字元串數組
每個active uniform的值,字(word)
active attributes的個數,整數
每個active attributes的,位置,大小,類型——整數,名稱——字元串數組
2.11 Primitive Assembly和shader後頂點處理
頂點經過shader處理後,頂點根據mode組合成基本圖元
Primitive Assembly操作包含:
裁剪坐标的透視除法
視圖映射,包含深度範圍縮放
基本圖元裁剪
裁剪varying輸出
2.12 坐标變換
shader輸出頂點坐标gl_Position是在裁剪坐标系中,頂點的裁剪坐标經透視除法産生歸一化裝置坐标,然後經視圖變換轉化為視窗坐标。
裁剪坐标(xc, yc, zc, wc)
歸一化裝置坐标(Xd, yd, zd) =(xc/wc, yc/wc, zc/wc)
視窗坐标(xw,yw,zw) =(xd*px/2 + ox, yd*py/2 + oy, zd*(f-n)/2 + (f+n)/2)
void DepthRangef( clampf n, clampf f );
void Viewport( int x, int y, sizei w, sizei h ); //ox = x + w/2, oy = y + h/2; px =w, py = h.
2.13 基本圖元裁剪
裁剪體如下:
wc <=xc<=wc
wc<=yc<=wc
wc<=zc<=wc
若基本圖元是點,若在裁剪體外頭,直接裁沒了,若在裡頭,繼續保留;
若基本圖元是線段,若線段全在裡頭,繼續保留,若線段全在外頭,裁沒了,若部分在裡頭,求出和裁剪體的交點坐标和其他屬性,建構新線段;
對于線段P1P2與裁剪面的交點P有公式:
P = tP1 + (1 -t)P2。(0<=t<=1)
若基本圖元是三角形,将三角形和六個裁剪面依次作處理,裁減可能會引起頂點個數的增加,進而建構新的多邊形(可能是3,4,5邊形)。
在這裡對于非三角形,是否轉換成多個三角形,然後後續處理?
wc為負的情況,GL不需處理。
2.13.1 Clipping Varying Outputs
頂點P1P2的varying值為c1,c2,則交點P的varying值c如下:
c = tc1+ (1-t)c2
3 光栅化
http://www.moandroid.com/?p=961ES1.1相關
光栅化就是基本圖元轉換為螢幕上二維圖像的過程。
光栅化操作可以分兩部分:
a.标明視窗坐标系上哪一些正方形整數栅格被基本圖元占據;
b.給這些栅格指定顔色和深度資訊
光栅化的結果傳遞給GL(per-fragment操作)的下一階段,更新framebuffer中的相應資料。
Figure 3.1 光栅化
每個fragment的顔色值由fragment shader運算得出(使用varying value),最後深度值由光栅化操作得出。
Fragment: 一個正方形栅格,有相應的z(深度)值和varying data等參數。
這些參數稱為fragment的關聯資料。
Fragment左下角位置位于整數栅格坐标。光栅化操作于fragment的中心,坐标偏移整數(1/2,1/2)。
此處和direct3D不一緻,
OpenGL3.2版本可配置fragment中心坐标。
http://www.devklog.net/2009/08/03/opengl-3-2-officially-released/
OpenGL3.2 release highlights:
Configurable fragment center coordinates (ARB_fragment_coord_conventions).This basically lets you configure the fragment center and origin for fragmentprocessing (e.g. fragment shaders). With this extension, you can adopt the Direct3D9 conventions (pixel center at <0.0, 0.0> and origin atupper-left corner of window) or the Direct3D 10 conventions (pixel center at <0.5,0.5> and origin at upper-left corner of window). This does not affectrasterization or transformation (which you can modify using existing OpenGLstate).
Direct3D vs. OpenGL其他差别,參考
http://hi.baidu.com/telnet2008/blog/item/561b0703733eb081d53f7c08.html
Directly Mapping Texels to Pixels
http://www.cnblogs.com/ttthink/articles/1577987.html
3.1 不變性(invariance)
考慮在視窗坐标中通過移位(x,y)轉換一個基本圖元p而得到一個基本圖元p‘,其中x和y是整型的。如果p‘和p都是未裁剪的,那麼由p’生成的片元f‘是和由p生成的f是一緻的,除了f‘的中心坐标是由f的中心坐标偏移了(x,y)。
3.2 多重采樣(multisampling)
多重采樣是一種對所有GL圖元(點、線段、三角形)進行抗鋸齒處理的技術。這種技術在每個像素中對圖元多次采樣。這多個采樣點的顔色是一樣的,一個像素更新一次,抗鋸齒在應用級别看起來是自動進行的。每個采樣包含顔色、深度和stencil資訊,顔色(包括紋理操作),深度和stencil資訊更新同單采樣模式。
幀緩存裡多了一個多重采樣緩存。像素的采樣值,包括顔色、深度和stencil值,都儲存在這種緩存裡。當幀緩存包括一個多重采樣緩存,那麼它就不再擁有深度和stencil緩存,即使多重采樣緩存并沒有儲存深度和stencil值。盡管如此,顔色緩存和多重采樣緩存是共存的。
多重采樣抗鋸齒技術對于給三角形着色是非常有價值的,因為它不需要對隐面消除做排序,它可以正确的處理臨近的三角形、目标輪廓和相交的三角形。
如果SAMPLE_BUFFERS的值為1,圖元光栅化模式為多重采樣光栅化。否則是單采樣光栅化。SAMPLE_BUFFERS的值可調用GetIntegerv函數查詢。
采樣數:SAMPLES可用GetIntegerv函數查詢,
每個fragment包含SAMPLES比特位的coverage值,SAMPLES個深度值,varying值集。可以賦給不同采樣的varying值相同的值。Varying值插值計算的位置可以在像素内按照實作相關選擇。是以每個像素fragment由整型的x、y栅格坐标、SAMPLES個varying值集合和一個由SAMPLES比特的覆寫值組成。
像素内的sample采樣位置模式不必固定,可以逐像素不同。
3.3 點
點的覆寫區域是,其中(xw,yw)是點中心的視窗坐标
xw – size < x < xw + size
yw – size < y < yw + size
需要對sample中心被覆寫的fragment做處理,
這部分相對于OpenGL ES Common/Common-Lite 規範(版本 1.1.12)将淡化因子,點的邊界圓等等合并為fragment shader對輸入(s,t)做處理。
s =1/2 + (xf + 1/2 – xw)/size
t =1/2 + (yf + 1/2 – yw)/size
其中(xf,yf)是整數的fragment視窗坐标,
點大小通過變量gl_PointSize設定。
3.3.1 點的多重采樣光栅化
與單采樣基本類似,除了将sample中心換為多重sample的中心。
3.4 線段光栅化
void LineWidth( floatwidth ); //設定線段寬度
3.4.1 基本線段光栅化
線段可分兩種:
x-major,斜率[-1,1]
y-major,other
“diamond exit”規則
類似direct3D中實作,注意端點在菱形邊界上的實作異同,參考
http://msdn.microsoft.com/en-us/library/ee415722%28VS.85%29.aspx
Figure 3.2. Bresenham算法示意圖. 顯示了部分線段,每個像素包含一個白色的菱形區域; 線段離開這些區域的相應像素産生fragment
每個中心為(xf,yf)的fragment,定義的菱形區域為
Rf = { (x,y) | |x – xf| + |y – yf| < 1/2}
當線段端點位于Rf邊界上,簡化處理,将端點擾動一小分量(e,e^2),
也就是線段PaPb,(xa,ya), (xb,yb),變為Pa’Pb’ (xa-e, ya-e^2), (xb-e,yb-e^2),光栅化PaPb等效成光栅化Pa’Pb’,注意選取e要滿足,Pb’也不在Rf上,同時對于任意的e’< e擾動,光栅化産生相同的fragment。
若Pa,Pb位于fragment中心,half-open處理
因為diamondexit的精确實作比較複雜,可以允許一些有誤差的線段光栅化實作,誤差容許為(conformancetesting?)
a.實作産生的fragment與相應diamond exit算法産生的fragment坐标x,y分量不偏離>1;
b.實作産生的fragment個數與diamond exit算法産生的fragment個數不偏離>1;
c.對于x-major線段,不應産生在一列的fragment,對于y-major線段,不應産生在一行的fragment,
d.兩個線段相連的fragment連續性和重複性問題
fragment資料求解
光栅化線段PaPb,(xa,ya), (xb,yb)産生fragment的中心Pr(xd,yd),
對于varingdata,需要透視校正插值,
對于z,直接線性插值
f = (1- t) fa + t fb
3.4.2 其他線段特性
線段的寬度在3.4.1中為預設1。本節說明寬度大于1的線段光栅化
Non-antialiased模式
Figure 3.3.Non-antialiased模式寬線段光栅化. x-major線段情形,粗線标明理想的線段位置,細線标明偏移後的線段. X标明光栅化産生該fragment
3.4.3 線段光栅化state
需要線段寬度值…
3.4.4 線段多重采樣光栅化
多重采樣光栅化時,線段被轉化為一個矩形區域,如下圖所示,
Figure 3.4 多重采樣光栅化線段的區域, (x-major case)
理想線段在矩形區域的中間,矩形的高為線段寬度。Fragment中的sample point若被矩形區域包含,該sample point的coverage值為1。Vertex shader的varying輸出和深度值根據3.4.1中等式求解。
多重采樣光栅化必須支援寬度為1的線段。
3.5 多邊形
triangle strip, triangle fan, or series of separate triangles
3.5.1 基本多邊形光栅化
第一步,背面、正面判定
對于n個頂點的多變性,視窗坐标,計算面積a,公式略,
void FrontFace( enum dir ); //設定CCW,CW模式
若是counter-clockwise(CCW)模式,a=-a
若是clockwise(CCW)模式,a=a
若a為正,正面,否則為背面
void CullFace( enum mode ); //根據mode=FRONT, BACK or FRONT_AND_BACK做剔除處理,
變量CULL_FACE使能多邊形剔除。
點采樣(point sampling.):判定多邊形光栅化産生哪些fragment。如何進行點采樣參考direct3D相關部分,
http://msdn.microsoft.com/en-us/library/ee415722%28VS.85%29.aspx
質心坐标:對于三角形内部或者邊界上任意點的屬性P,有三個數a,b,c,屬于[0,1],a+b+c = 1,
P = a*Pa + b*Pb + c*Pc,
其中a=A(PPbPc)/A(PaPbPc),b= A(PPaPc)/A(PaPbPc),c= A(PPaPb)/A(PaPbPc)
A(lmn)為三個點lmn組成三角形的面積。
Varying value輸出,透視校正插值,
對于深度z,線性插值
f = a*fa + b*fb + c*fc
3.5.2 深度偏移
光栅化三角形輸出的所有fragment的深度值可以疊加一個偏移量,通過函數設定一個三角形疊加一個偏移量。
void PolygonOffset( float factor, floatunits );
三角形的最大深度斜率m,
r是實作相關的深度值最小的區分精度,該區分可以在光栅化過程保持有效。
三角形的深度偏移量o,
o = m*factor + r*units
fragment的深度值結果clamp在[0,1]内。
3.5.3 多重采樣三角形光栅化
對于fragment中有采樣點滿足3.5.1點采樣的,三角形光栅化将輸出這個fragment。
若三角形已剔除,沒有輸出。
使用3.5.1中質心插值計算每個輸出fragment的每個sample的varing輸出和深度資訊。實作中也可以用pixel中一點的插值輸出近似該點所有sample值。
3.5.4 多邊形光栅化state
深度偏移的參數
3.6 像素矩形
本節說明像素矩形如何在client記憶體中組織,以及如何在client記憶體和GL間互相傳輸。
3.6.1 像素存儲模式
像素存儲模式影響TexImage2D和ReadPixels指令,
void PixelStorei( enum pname, T param );
參數UNPACK_ALIGNMENT:類型integer,初始值4,可設為1,2,4,8
3.6.2像素矩形傳輸
Figure 3.5. Transfer of pixel rectangles tothe GL. 輸出RGBA pixels.
Format:
Format Name | Element Meaning and Order | Target Buffer |
ALPHA | A | Color |
RGB | R, G, B | Color |
RGBA | R, G, B, A | Color |
LUMINANCE | Luminance | Color |
LUMINANCE_ALPHA | Luminance, A | Color |
Type:
type Parameter Token Name | Corresponding GL Data Type | Special Interpretation |
UNSIGNED_BYTE | ubyte | No |
UNSIGNED_SHORT_5_6_5 | ushort | Yes |
UNSIGNED_SHORT_4_4_4_4 | ushort | Yes |
UNSIGNED_SHORT_5_5_5_1 | ushort | Yes |
Format, type的有效組合
Format | Type | Bytes per Pixel |
RGBA | UNSIGNED_BYTE | 4 |
RGB | UNSIGNED_BYTE | 3 |
RGBA | UNSIGNED_SHORT_4_4_4_4 | 2 |
RGBA | UNSIGNED_SHORT_5_5_5_1 | 2 |
RGB | UNSIGNED_SHORT_5_6_5 | 2 |
LUMINANCE ALPHA | UNSIGNED_BYTE | 2 |
LUMINANCE | UNSIGNED_BYTE | 1 |
ALPHA | UNSIGNED BYTE | 1 |
Width, height:像素矩形的寬度和高度
Unpacking
UNSIGNED_SHORT_5_6_5:
Bit15-Bit11:1st component
Bit10-Bit5:2nd component
Bit4-Bit0:3rd component
UNSIGNED_SHORT_4_4_4_4:
Bit15-Bit12:1st component
Bit11-Bit8:2nd component
Bit7-Bi4:3rd component
Bit3-Bit0:4th component
UNSIGNED_SHORT_5_5_5_1:
Bit15-Bit11:1st component
Bit10-Bit6:2nd component
Bit5-Bit1:3rd component
Bit0:4th component
Table 3.7: Packed pixel field assignments.
Format | First Component | Second Component | Third Component | Fourth Component |
RGB | red | green | blue | |
RGBA | red | green | blue | alpha |
浮點轉換
将整形等轉換為浮點數,轉換須遵循2.1.2章節說明
RGB轉換
若format為luminance, luminance_alpha,将luminance拷貝到RGB三個分量
RGBA轉換
對于隻含RGB值的,添加A=1.0
3.7 紋理
void ActiveTexture( enum texture );//指定active的紋理圖像單元選擇ACTIVE_TEXTURE;
active的紋理單元可以用紋理圖像指令處理,包括TexImage,BindTexture,
TEXTUREi = TEXTURE0 + i,
active的紋理圖像單元選擇初始值為TEXTURE0
3.7.1Texture Image Specification
void TexImage2D( enum target, int level, intinternalformat, sizei width, sizei height, int border, enum format, enum type,void *data );//設定紋理圖像
target:二維紋理TEXTURE_2D,cube map紋理(6個二維紋理圖像的集合),每個面對應一個target,
TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_NEGATIVE_X,
TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP_NEGATIVE_Y,
TEXTURE_CUBE_MAP_POSITIVE_Z, TEXTURE_CUBE_MAP_NEGATIVE_Z
Format:圖像資料格式
Type:圖像資料類型
Data:client記憶體資料指針
Width:寬度
Height:高度,對于cub map紋理,width = height
Level:整數level-of-detail
Border:0
選擇的紋理采用3.6.2中方式,輸出R,G,B,A分量,clamp在[0,1]内。R,G,B,A分量轉換為内部紋理格式(根據internalformat),需要和format比對。紋理圖像處理時不支援格式的轉換。
Base Internal Format | RGBA | Internal Components |
ALPHA | A | A |
LUMINANCE | R | L |
LUMINANCE ALPHA | R,A | L,A |
RGB | R,G,B | R,G,B |
RGBA | R,G,B,A | R,G,B,A |
紋理圖像是記憶體中一序列的值組,第一組對應紋理圖的左下角,後續的組按照自左向右自底向上的順序填充記憶體。
第N個紋素(texel)坐标(i,j)
i = (N mod width)
j = (floor(N/width) mod height)
每個顔色分量轉換為n比特位的定點數k,代表k/(2^n-1)。
主紋理圖像的level-of-detail值為0,
最大的紋理width,height至少為2^(k-lod),k為log2(MAX_TEXTURE_SIZE),lod是level-of-detail。
GL指定的紋理圖像解碼後,拷貝到GL的内部存儲空間。解碼後的紋理圖像稱為紋理數組(texture array)。一個紋理數組的元素(i,j)稱為一個紋素(texel)。一個fragment的紋素值取決于該fragment的(s,t)坐标,不完全必要對應一個實際的紋素。如下圖
Figure 3.6. 一個紋理圖像和坐标通路,(n=3,m=2),混合鄰近的兩個紋素産生紋理值
3.7.2 Alternate Texture Image Specification Commands
void CopyTexImage2D( enum target, intlevel, enum internalformat, int x, int y, sizei width, sizei height, int border); //基本同TexImage2D,除了圖像資料來源于framebuffer
target:二維紋理TEXTURE_2D,cube map紋理(6個二維紋理圖像的集合),每個面對應一個target,
TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_NEGATIVE_X,
TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP_NEGATIVE_Y,
TEXTURE_CUBE_MAP_POSITIVE_Z, TEXTURE_CUBE_MAP_NEGATIVE_Z
x, y, width, and height:ReadPixels函數相應的參數,指定了圖像的寬和高,圖像左下角坐标。
CopyTexImage2D擷取的圖像資料與ReadPixels參數format=RGBA擷取的圖像資料有相同格式,後續處理與TexImage2D函數相同。
level, internalformat border:同TexImage2D。
internalformat:受限制取值滿足條件:不能添加framebuffer中沒有的分量,如下表所示
Texture Format | |||||
Color Buffer | A | L | LA | RGB | RGBA |
A | YES | ||||
RGB | YES | YES | |||
RGBA | YES | YES | YES | YES | YES |
下列兩函數指定已有紋理數組中的一塊區域,
void TexSubImage2D( enum target, int level,int xoffset, int yoffset, sizei width, sizei height, enum format, enum type,void *data ); //和TexImage2D函數關聯,有相同的參數含義;
void CopyTexSubImage2D( enum target, intlevel, int xoffset, int yoffset, int x, int y, sizei width,
sizei height ); //和CopyTexImage2D函數關聯,有相同的參數含義;這個函數的xoffset/x,yoffset/y有啥差別和聯系麼?回頭再研究
xoffset, yoffset:指定區域在紋理數組左下角的坐标偏移量。
3.7.3壓縮的紋理圖像
GL不指定壓縮格式,GL擴充可以定義壓縮格式,
NUM_COMPRESSED_TEXTURE_FORMATS:壓縮格式個數
COMPRESSED_TEXTURE_FORMATS:支援的壓縮格式清單
void CompressedTexImage2D( enum target, intlevel, enum internalformat, sizei width, sizei height, int border, sizeiimageSize, void *data ); //定義了一個有特定壓縮格式的紋理圖像
data:internalformat壓縮格式的壓縮圖像資料指針。Target等參數同TexImage2D函數;
imageSize:壓縮圖像資料大小(位元組);
void CompressedTexSubImage2D( enum target,int level, int xoffset, int yoffset, sizei width, sizei height, enum format,sizei imageSize, void *data ); //指定壓縮紋理數組中的一個區域,參數同TexSubImage2D,不過不同格式對xoffset,yoffset,width,height取值有要求,注意不能随意取。
3.7.4Texture Parameters
設定紋理參數的函數:
void TexParameter{if}( enum target, enumpname, T param );
void TexParameter{if}v( enum target, enumpname, T params );
target:必須是TEXTURE_2D或者TEXTURE_CUBE_MAP.
Pname和取值對應如下:
Name | Type | 合理的值 |
TEXTURE_WRAP_S | integer | CLAMP_TO_EDGE, REPEAT, MIRRORED_REPEAT |
TEXTURE_WRAP_T | integer | CLAMP TO_EDGE, REPEAT, MIRRORED REPEAT |
TEXTURE_MIN_FILTER | integer | NEAREST LINEAR NEAREST_MIPMAP_NEAREST NEAREST_MIPMAP_LINEAR LINEAR_MIPMAP_NEAREST LINEAR_MIPMAP_LINEAR |
TEXTURE_MAG_FILTER | integer | NEAREST, LINEAR |
3.7.5 Cube Map Texture Selection
紋理坐标:(s, t, r)
方向矢量:從cube中心到cube上某點的方向矢量(rx,ry,rz)。
major axis方向:從三個方向矢量中選出的最大絕對值的分量。
Major Axis Direction | Target | sc | tc | ma |
+rx | TEXTURE_CUBE_MAP_POSITIVE_X | -rz | -ry | rx |
-rx | TEXTURE_CUBE_MAP_NEGATIVE_X | rz | -ry | rx |
+ry | TEXTURE_CUBE_MAP_POSITIVE_Y | rx | rz | ry |
-ry | TEXTURE_CUBE_MAP NEGATIVE_Y | rx | -rz | ry |
+rz | TEXTURE_CUBE_MAP_POSITIVE_Z | rx | -ry | rz |
-rz | TEXTURE_CUBE_MAP_NEGATIVE_Z | -rx | -ry | rz |
Cube 紋理必須映射到cube上去嗎?
s = (sc/|ma| + 1)/2;
t = (tc/|ma| + 1)/2;
(s, t)用來從target的面上查找計算出紋理值。
3.7.6 Texture Wrap Modes
REPEAT:f – floor(f);
CLAMP_TO_EDGE:[1/2N,1-1/2N];
MIRRORED_REPEAT:
If floor(f) is even,mirror(f) = f – floor(f),
Else if floor(f) is odd, mirror(f) =1 – f + floor(f);
3.7.7 紋理縮小
圖元應用紋理,意味着紋理圖像空間到framebuffer圖像空間的映射。基本上類似于建立一幅重采樣的紋理圖像。怎麼進行采樣濾波會取決于紋理圖像是放大還是縮小。
Level-of-detail參數λ(x,y) = log2 ρ(x,y);//ρ(x,y)是縮放因子
若是λ(x,y) <=某常數c,認為紋理圖像放大,否則是縮小
給定s(x,y),t(x,y), wt, ht
u(x,y) = s(x,y) * wt,v(x,y) = t(x,y) * ht;
對于多邊形所有fragment内部對應的u,v,
對于一線段,
對于一點,ρ = 1。
等式3.12, 3.13給出紋理縮放的最佳效果,可是實作其運算太複雜。近似用函數f(x,y)實作滿足如下:
max{mu,mv}<=f(x, y)<= mu + mv
若λ推得紋理需進行縮小,TEXTURE_MIN_FILTER值用來選擇如何計算紋理值。
TEXTURE_MIN_FILTER = NEAREST,位置(i,j)的紋素就是該點紋理值,其中
if s<1, i = floor(u), else if s==1, i =wt – 1;
if t<1, j = floor(v), else if t==1, j =ht – 1;
TEXTURE_MIN_FILTER = LINEAR,先求出2x2紋素塊的值i0, j0, i1, j1(level = 0),其中
i0 = floor(u-1/2), j0 = floor(v-1/2),
i1 = i0 + 1, j1 = j0 + 1, (注意CLAMP或REPEAT的處理)
α = frac(u – 1/2)
β = frac(v – 1/2)
紋理值τ = (1-α)(1-β)τi0j0+α(1-β)τi1j0 + (1-α) βτi0j1 +αβτi1j1
Mipmapping
Mipmap由level-of-detail指定
對于NEAREST_MIPMAP_NEAREST和LINEAR_MIPMAP_NEAREST,
根據λ值确定選擇level= d的mipmap數組選擇如下僞代碼,
if λ <= 1/2, d = 0,
else if λ >1/2 and λ <= q+1/2, d =ceil(λ+1/2) – 1,
else d = q
然後對選中的d數組,進行NEAREST或LINEAR的濾波得出紋理值;
對于NEAREST_MIPMAP_LINEAR和LINEAR_MIPMAP_LINEAR,
選擇level=d1,d2的兩個mipmap數組
if λ >= q, d1 = q,
else d = floor(λ),
if λ >= q, d2 = q,
else d = d1+1,
然後對選中的d1,d2數組,進行NEAREST或LINEAR的濾波得出兩個紋理值τ1, τ2;
最終的紋理值τ = [1-frac(λ)]τ1 + frac(λ)τ2
3.7.8 紋理放大
若λ推得紋理放大,放大方式由TEXTURE_MAG_FILTER的值選擇,總是選擇level=0的紋理數組,
TEXTURE_MAG_FILTER = NEAREST
同紋理縮小時的NEAREST求解,
TEXTURE_MAG_FILTER = LINEAR
同紋理縮小時的LINEAR求解,
注意c的選擇,使得同一場合應用縮小的紋理不會比放大的紋理更sharper。(0.5 0)
3.7.9 紋理緩沖附加條件
紋理值無定義當如下條件同時滿足: 看不明白!!
FRAMEBUFFER_BINDING的framebuffer對象F;
紋理對象對應framebufferF的連接配接點A;
TEXTURE MIN FILTER = NEAREST/LINEAR,且A的FRAMEBUFFER_ATTACHMENT_ TEXTURE_LEVEL = 0,
或者TEXTURE_MIN_FILTER= NEAREST_MIPMAP_NEAREST, NEAREST_MIPMAP_LINEAR,
LINEAR_MIPMAP_NEAREST,
或者LINEAR_MIPMAP_LINEAR,A的FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0~mip-level。
3.7.10 紋理完整性和非2的指數次方紋理
紋理是完整的,意味着紋理操作涉及的所有的紋理數組和參數是定義正确的。
一個二維的紋理是完整的條件如下:
紋理mipmap數組(從0到q)都指定為相同的internalformat;
數組的大小遵循3.7.7中的規則;
每個level=0的數組大小是正的;
對于cube map紋理,cube完整的條件如下:
組成cube紋理的六個level=0的紋理圖像有着相同的正的正方的大小;
都有着相同的internalformat;
Cube map紋理是mipmap cube完整的條件:
除了需要是cube完整的,每個紋理圖像是完整的。
紋理圖像規定中完整的影響:
具體實作中,若要支援level=1或更大的紋理圖像數組的建立,首先需要能支援相應的圖像數組集合。
3.7.11 mipmap的生成
void GenerateMipmap( enum target ); //生成mipmap
target:TEXTURE_2D或TEXTURE_CUBE_MAP
GenerateMipmap函數根據level0數組,計算出完整的mipmap數組集合,level=1~level=q的原有數組被新計算的數組替代,level0數組不變;
所有新計算出mipmap數組的internalformat同level0的數組,大小需要滿足3.7.10所述。
Level0的數組不能是壓縮的internalformat,否則GL報INVALID_OPERATION。
3.7.12 紋理state
兩類,紋理資料和屬性,紋理縮放模式
3.7.13 紋理對象
除了預設的TEXTURE_2D和TEXTURE_CUBE_MAP,可以建立有名稱的紋理對象;
void BindTexture(enum target, uinttexture); //建立紋理對象,連接配接一個未使用的名稱到TEXTURE_2D或TEXTURE_CUBE_MAP,也可以修改已有紋理對象的連接配接;
新建立的紋理對象有3.7.12中所有的state。
void DeleteTextures( sizei n, uint*textures ); //删除已有的n個紋理對象
void GenTextures( sizei n, uint *textures); //傳回未使用的紋理對象名稱
3.8 Fragment Shaders
點、線、三角形光栅化後輸出的Fragment的處理,歸fragment shader管。
Fragment shader和vertex shader類似,是由一些操作代碼定義,支援二進制代碼和源碼兩種模式。
建立Fragmentshader使用2.10.1中類似的方法,除了type = FRAGMENT_SHADER。
3.8.1 shader變量
MAX_FRAGMENT_UNIFORM_VECTORS
可讀取光栅化輸出varying資料,包括vertex shader自定義的varying資料;
Fragment内部varying資料:fragment位置,視圖z坐标,正面标志;
3.8.2 Shader 執行
Fragment shader處理輸入的fragment。
3.8.3 紋理通路
Fragment shader執行紋理查尋,GL根據3.7.7, 3.7.8中所述計算濾波輸出的紋理值,根據下表轉化為紋理源色Cs。
Texture Base Internal Format | Texture source color (Rs;Gs;Bs) | Texture source alpha As |
ALPHA | (0; 0; 0) | At |
LUMINANCE | (Lt;Lt;Lt) | 1 |
LUMINANCE ALPHA | (Lt;Lt;Lt) | At |
RGB | (Rt;Gt;Bt) | 1 |
RGBA | (Rt;Gt;Bt) | At |
在level-of-detail計算時, du/dx, du/dy, dv/dx,dv/dy,dw/dx,dw/dy的計算可以用OpenGLES shading language specification中8.8章節近似方法。
若fragmentshader使用的sampler關聯的紋理對象不完整,傳回(R,G,B,A) = (0,0,0,1);sampler在其他這些場合也會傳回(0,0,0,1)
a.調用的二維sampler對應的紋理圖像不是二的指數次方圖像,并且紋理wrap模式不是CLAMP_TO_EDGE或者縮小濾波器不是NEAREST或者LINEAR;
b.調用的cube map sampler對應的任意一個紋理圖像不是二的指數次方圖像,并且紋理wrap模式不是CLAMP_TO_EDGE或者縮小濾波器不是NEAREST或者LINEAR;
c.調用的cube map sampler,對應的cube map紋理圖像不是cube完整的,或者TEXTURE_MIN_FILTER決定需要mipmap并且紋理不是mipmap cube完整的;
常數MAX_TEXTURE_IMAGE_UNITS:一個shader能通路的最大的獨立紋理單元數目
shader輸入
OpenGL ES Shading Languagespecification定義了可以作為fragmentshader的輸入變量。
内建變量gl_FragCoord包含fragment的 x,y,z,1/w,其中z分量預設轉化成浮點數,已經添加了多邊形的偏移量,另外z=0,1是不變量(大概是圖形流水線處理流程保持z等于這兩個值)。1/w值根據裁剪坐标系wc計算得出。
内建變量gl_FrontFacing=TRUE,當且僅當fragment來源于front face的基本圖元。
shader輸出
OpenGL ES Shading Languagespecification定義了可以作為fragmentshader的輸出變量,包含gl_FragColor和gl_FragData[0] (相容桌面OpenGL,但是隻有其中單獨一個fragment顔色輸出在OpenGL ES有意義。)
Fragmentshader輸出最終的fragment顔色值或者fragment資料的值,截止在[0,1]内,轉化成章節2.1.2中說明的framebuffer定點顔色分量。
指派gl_FragColor(gl_FragData[0])指定了流水線後續階段的fragment顔色值(顔色值No.0)。未在shader中指派的顔色值是不确定的。Shader中也不能随機的給gl_FragColor和gl_FragData[0]兩者都指派。
| |
5 其他函數5.1 Flush和Finish
Flush在一定時間内完成所有GL指令;Finish等待所有GL指令的完成;
void Flush( void );
void Finish( void );
5.2 Hints
void Hint( enumtarget, enum hint );
target=GENERATE_MIPMAP_HINT
hint=FASTEST/NICEST/DONT_CARE
6 狀态和狀态需求
6.1 查詢GL狀态
6.1.1 簡單查詢
void GetBooleanv(enum value, boolean *data );
void GetIntegerv(enum value, int *data );
void GetFloatv(enum value, float *data );
boolean IsEnabled(enum value );
6.1.2 數值轉換
GetBooleanv:非零浮點數整數對應TRUE;
GetIntegerv:布爾數對應1/0,浮點數舍入到最近的整數,例外是RGBA分量和DepthRangef值,清屏深度值,歸一化坐标值根據表4.4轉換;
GetFloatv:布爾數對應1.0/0.0,整數值強制轉化為浮點數;
6.1.3 枚舉查詢
voidGetTexParameter{if}v( enum target, enum value, T data );
target=TEXTURE_2D/TEXTURE_CUBE_MAP
voidGetBufferParameteriv( enum target, enum value,T data );
target=ARRAY_BUFFER/ELEMENT_ARRAY_BUFFER
voidGetFramebufferAttachmentParameteriv( enum target, enum attachment, enum pname,int *params );
void GetRenderbufferParameteriv( enumtarget, enum pname, int* params );
6.1.4 紋理查詢
booleanIsTexture( uint texture );
6.1.5 字元串 Queries
ubyte*GetString( enum name );
name=VENDOR/RENDERER/VERSION/SHADING_LANGUAGE_VERSION/EXTENSIONS
6.1.6 Buffer對象查詢
boolean IsBuffer(uint buffer);
6.1.7 Framebuffer Object andRenderbuffer Queries
boolean IsFramebuffer( uintframebuffer );
boolean IsRenderbuffer( uintrenderbuffer );
6.1.8 Shader and Program Queries
boolean IsShader( uint shader );
void GetShaderiv( uint shader, enumpname, int *params );
boolean IsProgram( uint program );
void GetProgramiv( uint program,enum pname, int *params );
void GetAttachedShaders( uintprogram, sizei maxCount, sizei *count, uint *shaders );
void GetShaderInfoLog( uint shader,sizei bufSize, sizei *length, char *infoLog );
void GetProgramInfoLog( uintprogram, sizei bufSize, sizei *length, char *infoLog );
void GetShaderSource( uint shader,sizei bufSize, sizei *length, char *source );
void GetShaderPrecisionFormat( enumshadertype, enum precisiontype, int *range, int *precision );
void GetVertexAttribfv( uint index,enum pname, float *params );
void GetVertexAttribiv( uint index,enum pname, int *params );
void GetVertexAttribPointerv( uintindex, enum pname, void **pointer );
void GetUniformfv( uint program, intlocation, float *params );
void GetUniformiv( uint program, intlocation, int *params );
6.2 狀态表
附錄A 不變性
GL不是像素相等的,是以不要求所有GL實作保證有着精确的符合。但是,在一個實作中相同條件下,生成的圖像要求有精确的符合。
A.1 可重複性
對于任意同樣的GL和framebuffer狀态,同樣的GL指令執行後的GL和framebuffer狀态要完全相同。
可重複性可以避免視覺噪聲,而且提供可測試性。
A.2 Multi-Pass算法
不變性的要求有時候非常難以實作,例如相同功能的軟體硬體的切換實作。
A.3 不變性規則
規則1:對于任意給定的GL和framebuffer起始狀态,任意的GL指令每次調用執行後的GL和framebuffer狀态要完全相同。
規則2:下列狀态的改變沒有附加作用(其他狀态不受此變化影響):
必須的——
framebuffer内容(所有位平面)
scissor參數(除enable外)
writemasks(顔色,深度,圖案)
清除螢幕值(顔色,深度,圖案)
強烈推薦的——
stencil參數(除enable外)
depth test參數(除enable外)
blend參數(除enable外)
像素存儲
多邊形偏移參數(除enable以及影響的fragment depth外)
規則3:per-fragment各個處理環節的運算隻與直接控制的參數相關;