我学习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 |
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); //返回未使用的纹理对象名称
点、线、三角形光栅化后输出的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]两者都赋值。
|
|
|
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各个处理环节的运算只与直接控制的参数相关;