天天看點

OpenGL ES 2.0 Specification (OES 2.0規範)學習筆記

我學習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]兩者都指派。

4 Per-Fragment 操作和framebuffer

framebuffer可分兩類

a windows系統提供的預設framebuffer對象

b 應用建立的非顯示framebuffer對象

bitplane:framebufer中每一像素的每一bit組成一個bitplane,每一bitplane包含一個像素的一個bit。這些bitplane可以組成color, depth, stencil buffers。

對于windows系統framebuffer,color buffer包含一個front buffer,一個back buffer,典型來說,front buffer對應正在顯示器顯示的畫面,而back buffer目前不可見。

對于應用建立的非顯示framebuffer,color buffer名為COLOR_ATTACHMENT0,depth buffer名為DEPTH_ATTACHMENT,stencil buffer名為STENCIL_ATTACHMENT。

所有的bitplane預設狀态是不确定的。

4.1 Per-fragment操作

figure 4.1 Per-fragment操作

4.1.1 Pixel Ownership Test

    這個測試判斷framebuffer中位置(xw,yw)是否是GL控制的,若不是windows系統決定這一fragment的命運。這個測試允許windows系統控制GL的行為,例如GL視窗遮擋等。

    應用建立的framebuffer中的像素總是歸OpenGL ES所控制,而非windows系統。

4.1.2 Scissor Test

    這個測試判斷framebuffer中位置(xw,yw)是否位于scissor矩形内部,矩形由四個參數設定如下:

void Scissor( int left, int bottom, sizeiwidth, sizei height );

//若left <= xw < left + width且bottom<= yw < bottom + height,scissor測試通過,否則fragment舍。

這個測試通過Enable/Disable常量SCISSOR_TEST來使能/禁用。若禁用,認為SCISSOR測試總是通過的。

4.1.3 多重采樣Fragment操作

這一步,根據SAMPLE_ALPHA_TO_COVERAGE,SAMPLE_COVERAGE, SAMPLE_ COVERAGE_VALUE和SAMPLE_COVERAGE_INVERT的值修改fragment的alpha和coverage的值。當然這是在SAMPLE_BUFFERS不等于1的時候有作用。

若SAMPLE_ALPHA_TO_COVERAGE使能,根據采樣點的alpha值生成一個臨時的coverage值,這個值與原coverage值進行AND運算後,生成fragment新的coverage值。

若SAMPLE_ALPHA_TO_COVERAGE禁用,fragment的新coverage值等于原值。

alpha值對應coverage值算法。。。

若SAMPLE_COVERAGE使能,fragment的coverage值還與另一個臨時coverage值進行AND運算。該臨時coverage值是SAMPLE_COVERAGE_VALUE的函數,而非alpha值。若SAMPLE_COVERAGE_INVERT= TRUE,臨時coverage值求非後與原值AND運算。

void SampleCoverage( clampf value,boolean invert ); //設定SAMPLE_COVERAGE_VALUE, SAMPLE_COVERAGE_INVERT的值

4.1.4 Stencil Test

這個測試,stencilbuffer位置(xw,yw)的值與一個參考值進行比較,根據比較結果判定是否舍棄fragment。這個測試通過Enable/Disable常量STENCIL_TEST來使能/禁用。若禁用,fragment總是未經修改直接通過的。

兩類stencil相關狀态,名為正面stencil state集和背面stencil state集。Stencil測試處理非多邊形的光栅化輸出(點,線,位圖,圖像矩陣)以及正面多邊形光栅化輸出時,使用正面stencil state集;處理背面多邊形光栅化輸出時,使用背面stencil state集。

Stencil Test控制函數如下:

void StencilFunc( enum func, int ref, uintmask ); //設定兩類stencilstate集相同值;

void StencilFuncSeparate( enum face,enum func, int ref, uint mask ); //face = FRONT, BACK或FRONT_AND_BACK

void StencilOp( enum sfail, enum dpfail,enum dppass ); //設定兩類stencilstate集相同值;

void StencilOpSeparate( enum face, enumsfail, enum dpfail, enum dppass ); //face = FRONT, BACK或FRONT_AND_BACK

StencilFunc和StencilFuncSeparate函數有三個參數用以控制stencil測試是否通過;ref是比較的參考值,stencilbuffer中相應的值和參考值在比較前先同mask進行位AND運算,比較結果根據func來判定stencil測試是否通過。Func值有NEVER, ALWAYS, LESS, LEQUAL,EQUAL, GEQUAL, GREATER或NOTEQUAL。

StencilOp和StencilOpSeparate函數有三個參數來影響測試結果的影響。Sfail規定了stencil測試失敗後對stencil buffer中相應值有什麼動作要做。相應動作有KEEP, ZERO,REPLACE, INCR, DECR, INVERT, INCR_WRAP 和DECR_WRAP。Dpfail, dppass分别規定了深度測試(depth test)失敗或通過對stencil buffer的動作。

若stencil測試失敗,fragment舍去。

初始時,stencil測試禁用,正面背面的參考值為0,比較函數為ALWAYS,MASK為全1,stencil動作為KEEP。

若不存在stencilbuffer,測試預設通過。

4.1.5 深度緩存測試(depth buffer test)

若深度緩存測試失敗,fragment舍去。通過Enable/DisableDEPTH_TEST可以來使能/禁用這一測試。若禁用,不進行深度比較和深度緩存的更新,fragment直接送入後續處理,stencil值按照深度測試通過的方式進行修改。

void DepthFunc( enum func ); //比較函數可以設定為NEVER, ALWAYS, LESS, LEQUAL, EQUAL, GREATER, GEQUAL, NOTEQUAL,比較雙方是輸入fragment的zw值與深度緩存目前位置的深度值。

若深度緩存測試失敗,舍去目前fragment,目前stencil的值根據4.1.4方式更新。否則以zw更新fragment對應位置深度緩存中的值,同時更新stencil buffer相應值。

若不存在深度緩存,測試預設通過。

4.1.6 Blending

此環節通過Blend公式混合輸入fragment的RGBA值與framebuffer中相應位置的RGBA值。Blending基于輸入fragment的alpha值和framebuffer中相應存儲的alpha值。

通過Enable/DisableBLEND可以來使能/禁用這一環節,若禁用fragment直接送入下一環節。

void BlendEquation( enum mode ); //同時指定RGB, ALPHA的模式

void BlendEquationSeparate( enum modeRGB, enummodeAlpha ); //分别指定兩模式模式有FUNC_ADD,FUNC_SUBTRACT或FUNC_REVERSESUBTRACT.

Framebuffer中的目标RGBA分量是定點數,blending操作是浮點的,blending前預設有定點轉換浮點的操作,轉換有0,1不變性。

Blend公式如下所示,

Mode = FUNC_ADD,

R = Rs*Sr + Rd*Dr,G = Gs*Sg + Gd*Dg,B = Bs*Sb + Bd*Db,A = As*Sa + Ad*Da

Mode = FUNC_SUBSTRACT,

R = Rs*Sr - Rd*Dr,G = Gs*Sg - Gd*Dg,B = Bs*Sb - Bd*Db,A = As*Sa - Ad*Da

Mode = FUNC_REVERSE_SUBSTRACT,

R = Rd*Dr - Rs*Sr,G = Gd*Dg - Gs*Sg,B = Bd*Db - Bs*Sb,A = Ad*Da - As*Sa

其中Sr, Sg, Sb, Sa是源混合因子,由源混合函數決定,Dr, Dg, Db, Da是目标混合因子,由目标混合函數決定。

混合函數如下:

void BlendFuncSeparate( enum srcRGB,enum dstRGB, enum srcAlpha, enum dstAlpha ); //分别指定兩模式

void BlendFunc( enum src, enum dst); //同時指定RGB, ALPHA的模式混合函數和相應的混合因子如下所示,F代表S(源因子)或者D(目标因子)。FUNC=ZERO,

Fr=0,Fg=0,Fb=0, Fa=0

FUNC=ONE,

Fr=1,Fg=1,Fb=1, Fa=1

FUNC=SRC_COLOR,

Fr=Rs,Fg=Gs,Fb=Bs, Fa=As

FUNC=ONE_MINUS_SRC_COLOR,

Fr=1-Rs,Fg=1-Gs,Fb=1-Bs, Fa=1-As

FUNC=DST_COLOR,

Fr=Rd,Fg=Gd,Fb=Bd, Fa=Ad

FUNC=ONE_MINUS_DST_COLOR,

Fr=1-Rd,Fg=1-Gd,Fb=1-Bd, Fa=1-Ad

FUNC=SRC_ALPHA,

Fr=As,Fg=As,Fb=As, Fa=As

FUNC=ONE_MINUS_SRC_ALPHA,

Fr=1-As,Fg=1-As,Fb=1-As, Fa=1-As

FUNC=DST_ALPHA,

Fr=Ad,Fg=Ad,Fb=Ad, Fa=Ad

FUNC=ONE_MINUS_DST_ALPHA,

Fr=1-Ad,Fg=1-Ad,Fb=1-Ad, Fa=1-Ad

FUNC=CONSTANT_COLOR,

Fr=Rc,Fg=Gc,Fb=Bc, Fa=Ac

FUNC=ONE_MINUS_CONSTANT_COLOR,

Fr=1-Rc,Fg=1-Gc,Fb=1-Bc, Fa=1-Ac

FUNC=CONSTANT_ALPHA,

Fr=Ac,Fg=Ac,Fb=Ac, Fa=Ac

FUNC=ONE_MINUS_CONSTANT_ALPHA,

Fr=1-Ac,Fg=1-Ac,Fb=1-Ac, Fa=1-Ac

FUNC=SRC_ALPHA_SATURATE(隻對源因子有意義)

Sr=f, Sg=f, Sb=f, Sa=1,(其中f = min(As,1-Ad))  

void BlendColor( clampf red, clampfgreen, clampf blue, clampf alpha ); //設定constant color, Cc

blending狀态

初始blend公式對RGB和Alpha模式都是FUNC_ADD,初始混合函數對于源因子是ONE,對于目标因子是ZERO,初始constant color是(0,0,0,0),初始時blending禁用。

若color buffer不存在alpha,Ad預設1。

4.1.7 抖動(Dithering)

通過Enable/Disable DITHER可以來使能/禁用這一環節。預設使能。

抖動處理可以随機化量化噪聲,可以使得低位數顯示裝置顯示高位數效果。

對于顔色分量c,是一個浮點數,存入framebuffer前需轉換成定點數,若framebuffer資料認為是m位定點數(都在小數點左邊,此處浮點數不再認為[0,1]内)。我們讓抖動輸出c1,滿足max(0,ceil(c)-1) <= c1 <=ceil(c),也就是說c1可以取兩個值。

具體抖動算法與實作相關,不過必須隻與輸入顔色分量值和fragment的x,y視窗坐标有關。這一點是為了避免一些no-good effect。抖動算法實作可以參考下文,以及OpenGL® ES 2.0 Programming Guide中dithering章節。

http://www.virtualdub.org/blog/pivot/entry.php?id=151

4.1.8 多重采樣fragment處理的說明

若SAMPLE_BUFFERS=1,stencil test,depth test,blending和dithering操作作用在每個pixel sample上,而非fragment。若該sample coverage為1,進行stencil, depth, blending, dithering等處理,否則無處理。

優化處理:可以隻在fragment最中間的sample上做stencil, depth等測試,若需要更新,所有Multisample buffer的stencil, depth都更新為這一fragment的值。

Multsample buffer處理完後,color sample buffer需要合并生成一個color值,寫入選擇的color buffer。具體實作可能會延後寫入color buffer。合并的算法實作相關,推薦是對每一顔色分量進行簡單的平均。

4.2 整個framebuffer操作

4.2.1選擇寫入的buffer

color值寫入front/back buffer是single/back buffered context由決定的。

4.2.2 buffer更新的微觀控制

void ColorMask( boolean r, booleang, boolean b,boolean a ); //若boolean為真,允許寫入相應分量

void DepthMask( boolean mask ); //若mask非零,允許寫入深度值zw

void StencilMask( uint mask );//mask是s比特位的整數mask,對應s比特位的stencil buffer。

void StencilMaskSeparate( enum face,uint mask ); //face可以是FRONT, BACK或FRONT_AND_BACK

ES是否不支援colorindex mode? 這裡沒有提供OpenGL的IndexMask函數,參考OpenGL中相應函數如下,

http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node104.html

若SAMPLE_BUFFERS=1,上面四個函數控制multisample buffer更新。Color mask對color buffer的更新沒有影響。即使color mask全部關閉,color sample仍然按照前面章節的說明更新color buffer。

4.2.3 清除緩存

void Clear( bitfield buf ); //COLOR_BUFFER_BIT,DEPTH_BUFFER_BIT, STENCIL_BUFFER_BIT,分别指清除color, depth, stencil緩存;

void ClearColor( clampf r, clampf g,clampf b, clampf a ); //設定color buffer的清除顔色值,浮點數[0,1]輸入轉成framebuffer的定點數(2.1.2);

void ClearDepthf( clampf d ); //設定depth buffer的清除深度值,浮點數[0,1]輸入轉成framebuffer的定點數(2.12.1);

voidClearStencil( int s ); //設定stencil buffer的清除值,整數; 若clear函數被調用,在per-fragment上隻允許進行pixel ownership test, scissortest, dithering處理。4.2.2 中mask處理也生效。若clear對應buffer不存在,沒有效果而已。初始的RGBA清楚值為(0,0,0,0),stencil清除值為0,深度清除值為1.0。

清除multisample buffer

設定COLOR_BUFFER_BIT,DEPTH_BUFFER_BIT, STENCIL_BUFFER_BIT為1,相應清除color,depth, stencil buffer。

4.3 讀取像素們(Reading Pixels)

4.3.1 Reading Pixels

Figure 4.2 讀取像素操作

上圖說明了如何将像素從framebuffer讀出然後存入client memory。

void ReadPixels( int x, int y, sizeiwidth, sizei height, enum format, enum type, void *data );  

ReadPixels函數的這些參數定義了3.6.2中的像素矩形。(Format, type)隻允許(RGBA, UNSIGNED_BYTE)或者從表3.4中選擇實作的特定組合,不能是LUMINANCE或LUMINANCE_ALPHA。GetIntegerv讀取IMPLEMENTATION_COLOR_READ_FORMAT 和IMPLEMENTATION_COLOR_READ_TYPE可以獲知該特定組合。

像素的存儲模式可以是PACK ALIGNMENT=1,2,4,8(預設4)。

讀取的像素值來源于正在作為寫入對象的color buffer。若FRAMEBUFFER_BINDING=0,像素值來源于目前連接配接的framebuffer對象的COLOR_ATTACHMENT0。

ReadPixels傳回在color buffer中所有(i,j)值,其中x<=i<x+width,y<=j<y+height。若不存在alpha buffer,相應分量傳回1.0。

RGBA值轉換

Framebuffer讀出的定點值先[0,1]飽和處理f,而後根據下表轉化成相應的GL類型值c。

若type = INT,GL type int, c = [(2^32 - 1)f - 1]/2;

若type = UNSIGNED_BYTE,GL type ubyte, c = (2^8 - 1)f;

若type = UNSIGNED_SHORT_5_6_5,GL type ushort, c = (2^N - 1)f;

若type = UNSIGNED_SHORT_4_4_4_4,GL type ushort, c = (2^N - 1)f;

若type = UNSIGNED_SHORT_5_5_5_1,GL type ushort, c = (2^N - 1)f;

像素讀取出來後放置在clientmemory中,記憶體組織方式如同TexImage2D。見章節3.6.2。

4.3.2 像素繪制/讀取狀态

PixelStore設定的狀态,影響着像素讀取。

4.4 FrameBuffer對象

預設的,GL使用windows系統提供的framebuffer,存儲,尺寸,位置和圖像格式等由windos完全控制。本章節着重說明應用建立的framebuffer。

應用建立的framebuffer對象包裝framebuffer方式正如同紋理對象包裝紋理的方式。特别的,framebuffer對象包含了顔色、深度和圖案邏輯緩存等需要的狀态。對于每一個邏輯緩存,一個framebuffer關聯的圖像可以和framebuffer聯接,以用來存儲邏輯緩存的渲染輸出。Framebuffer可關聯的圖像包含紋理圖像以及渲染緩存圖像。

允許渲染緩存圖像與framebuffer聯接,OpenGL ES支援離屏渲染。同時允許紋理圖像與framebuffer聯接,ES支援渲染生成紋理圖像。

4.4.1連接配接和管理framebuffer對象

預設的,目标FRAMEBUFFER連接配接的framebuffer值0,指向了windows系統的預設framebuffer,第4章的操作對象是預設framebuffer。若FRAMEBUFFER連接配接的framebuffer不為0,指向了應用建立的framebuffer,也就是第4章的操作對象。

void BindFramebuffer( enum target,uint framebuffer ); //target=FRAMEBUFFER,framebuffer為未使用無符号整數名稱。

BindFramebuffer建立的framebuffer分别有一個color連接配接點,depth連接配接點,stencil連接配接點。

BindFramebuffer可用來連接配接一個已有的framebuffer對象。

目前連接配接的framebuffer對象:ES操作影響的圖像來源地,查詢擷取的狀态來源地;fragment操作的目的地,也是ReadPixels的來源地;

對于應用建立的framebuffer:

pixel ownership test通過,也就是說framebuffer對所有的像素點有領地所有權;

color buffer沒有所謂的前台緩存(front buffer),背景緩存(back buffer);

唯一的colorbuffer對應連接配接點COLOR_ATTACHMENT0;

唯一的depthbuffer對應連接配接點DEPTH_ATTACHMENT;

唯一的stencilbuffer對應連接配接點STENCIL_ATTACHMENT;

無多重采樣buffer,SAMPLES = 0,SAMPLE_BUFFERS=0;(怎麼了解?難道生成離屏圖像或者紋理圖像不需要多重采樣?還是意味着生成過程中可以有,但是結束後多重采樣緩存廢棄了?)

void DeleteFramebuffers( sizei n, uint*framebuffers ); //删除framebuffer對象

void GenFramebuffers( sizei n, uint*framebuffers ); //傳回n個未使用的framebuffer對象名  

4.4.2 圖像關聯的framebuffer對象

對于應用framebuffer,framebuffer可關聯的圖像,可以從framebuffer進行關聯,斷開關聯;而系統預設framebuffer的圖像關聯不允許修改。

一幅圖像可以同時和多個framebuffer關聯,進而節省單一framebuffer的記憶體消耗(這可能在多重采樣中很有用)。一個邏輯buffer不能和多幅圖像關聯?

4.4.3 渲染緩存對象(renderbuffer)

渲染緩存是一個包含單幅可渲染内部格式的資料存儲對象。

void BindRenderbuffer( enum target,uint renderbuffer ); //target=RENDERBUFFER,建立渲染緩存圖像

OpenGL ES影響目前連接配接的渲染緩存對象。

GetIntegerV可以擷取目前的RENDERBUFFER_BINDING。

void DeleteRenderbuffers( sizei n, const uint*renderbuffers ); //删除渲染緩存對象

void GenRenderbuffers( sizei n, uint*renderbuffers ); //擷取未使用渲染緩存對象名稱

void RenderbufferStorage( enum target,enum internalformat, sizei width, sizei height ); //設定渲染緩存的資料存儲,

target = RENDERBUFFERinternalformat:包括如下5種格式,

DEPTH_COMPONENT16——depth-renderable,D(16)

RGBA4——color-renderable,R(4),G(4),B(4),A(4)

RGB5_A1——color-renderable,R(5),G(5),B(5),A(1)

RGB565——color-renderable ,R(5),G(6),B(5)

STENCIL_INDEX8——stencil-renderable,S(8)

Width,height:渲染緩存的像素尺寸,不能大于MAX_RENDERBUFFER_SIZE。

void FramebufferRenderbuffer( enumtarget, enum attachment, enum renderbuffertarget, uint renderbuffer ); //聯接渲染緩存對象和framebuffer中的邏輯緩存,target=FRAMEBUFFER;

attachment:COLOR_ATTACHMENT0, DEPTH_ATTACHMENT或STENCIL_ATTACHMENT;

renderbuffertarget:RENDERBUFFER

renderbuffer:需要聯接的渲染緩存對象名

若執行成功,

FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE =RENDERBUFFER,

FRAMEBUFFER_ATTACHMENT_OBJECT_NAME =renderbuffer;

聯接紋理圖像和framebuffer

ES支援通過CopyTexImage2D和CopyTexSubImage2D拷貝渲染内容到紋理圖像。ES也支援直接渲染到紋理圖像。

void FramebufferTexture2D( enumtarget, enum attachment, enum textarget, uint texture, int level );

target:FRAMEBUFFER;

texture:已存在的紋理對象或cube map紋理對象;

textarget:TEXTURE_2D,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

level:紋理圖像的mipmap level,必須為0;

FramebufferTexture2D函數執行成功後,

FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE =TEXTURE,

FRAMEBUFFER_ATTACHMENT_OBJECT_NAME =texture;

FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL= level;

若texture是cubemap紋理,FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = textarget;已有的紋理對象狀态不變;

4.4.4 已聯接framebuffer的紋理對象的渲染

必須避免在紋理對象進行渲染時,将此紋理對象與framebuffer聯接。小心死循環哦!

4.4.5 Framebuffer完整性

Framebuffer關聯完整性

若聯接點attachment的FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE不為NONE,需要滿足如下條件才能認為是framebuffer關聯完整:

image是FRAMEBUFFER_ATTACHMENT_OBJECT_NAME對象的分量,并且類型為FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE;

image的width和height非零;

若attachment是COLOR_ATTACHMENT0,image必須要有一個color-renderable的内部格式;

若attachment是DEPTH_ATTACHMENT,image必須要有一個depth-renderable的内部格式;

若attachment是STENCIL_ATTACHMENT0,image必須要有一個stencil-renderable的内部格式;

framebuffer完整性

framebuffer是完整的,意味着是windows系統提供的framebuffer,或者滿足如下所有條件:

所有framebuffer連接配接點是framebuffer關聯完整的;

至少有一幅圖像連接配接到framebuffer;

所有關聯的圖像有相同width和height;

所有關聯的圖像内部格式的組合不違反實作相關的限制;

enum CheckFramebufferStatus( enumtarget ); //檢查framebuffer是否完整, target=FRAMEBUFFER

4.4.6 framebuffer狀态有關的值

FRAMEBUFFER_BINDING

4.4.7 像素和關聯圖像元素的映射

R,G,B,A分量轉化為關聯圖像的内部格式。ColorMask, DepthMask, StencilMask, StencilMaskSeperate依然有效。

4.4.8 Errors  

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各個處理環節的運算隻與直接控制的參數相關;

上一篇: Lock()

繼續閱讀