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的摘抄,小部分是看不明白了,从其他地方找的参考资料。


OpenGLOpenGL 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)

cOpenGL 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处理前,vertexstate包括:多个基本属性值集;vertex shader处理后,vertexstate包括: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后,才能弄得比较明白。
   DrawArraysDrawElements定义顶点属性数据,而后顶点属性数据由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>0OpenGL 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 );//断开programshader的连接

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 );//返回名为nameuniform变量位置

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_UNITSvertex shader

MAX_TEXTURE_IMAGE_UNITS: fragmentshader

MAX_COMBINED_TEXTURE_IMAGE_UNITSboth shader


Vertex shadertexture 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

顶点P1P2varying值为c1,c2,则交点Pvaryingc如下:

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)

考虑在窗口坐标中通过移位(xy)转换一个基本图元p而得到一个基本图元p‘,其中xy是整型的。如果p‘p都是未裁剪的,那么由p’生成的片元f‘是和由p生成的f是一致的,除了f‘的中心坐标是由f的中心坐标偏移了(xy)。


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由整型的xy栅格坐标、SAMPLESvarying值集合和一个由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各个处理环节的运算只与直接控制的参数相关;

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenGL ES 2.0是一种图形编程接口,用于开发移动设备上的2D和3D图形应用程序。由于其高效性、跨平台性和灵活性,它成为许多手机游戏和应用程序的首选。 要下载OpenGL ES 2.0,首先需要考虑的是您使用的平台。通常,OpenGL ES 2.0可以在Android、iOS和Windows等操作系统上使用。 对于Android设备,您可以在Google Play商店上搜索“OpenGL ES 2.0”并下载适用于您的设备的OpenGL ES 2.0开发工具包(SDK)。您还可以通过在计算机上安装Android开发套件(SDK)并使用Android Studio或Eclipse等IDE来开发OpenGL ES 2.0应用程序。 对于iOS设备,OpenGL ES 2.0通常已经预装在iOS系统中,无需单独下载。您可以使用Xcode IDE来开发在iOS设备上运行的OpenGL ES 2.0应用程序。 对于Windows操作系统,您可以通过访问Khronos Group的官方网站来下载OpenGL ES 2.0的开发工具包(SDK)。您可以选择从官方提供的软件包中选择适用于您的Windows版本。 除了操作系统特定的下载之外,您还可以在各种开发者论坛、网站和教程上找到OpenGL ES 2.0的相关示例代码和资源。这些资源可以帮助您更好地了解和使用OpenGL ES 2.0来开发高质量的图形应用程序。 总之,要下载OpenGL ES 2.0,您需要根据您使用的平台选择适当的开发工具包或SDK。随后,您可以使用IDE和其他资源开始在您的设备上开发出色的OpenGL ES 2.0应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值