OpenGL ES 3.0之Shading Language(八)

各类OpenGL
ES
3.0程序供给一个巅峰着色器和贰个片段着色器去渲染一个图形。着色器概念是API
的基本,本篇将介绍着色器语言部分含有下边几项

本文是关于OpenGL ES的系统性学习进程,记录了温馨在就学OpenGL
ES时的获得。那篇文章的靶子是上学OpenGL
ES着色器语言。遭受是Xcode8.1+OpenGL ES
2.0脚下代码已经停放github下面,OpenGL ES入门02-OpenGL ES着色器

  1、变量和变量类型
  2、矢量和矩阵成立及挑选
  3、常量
  4、结议和阵列
  5、运算符、流动调查整和函数
  6、属性、只读变量和变量
  7、预管理和指令
  8、只读变量和变量压缩
  9、精度调整和不改变性

接待关心小编的 OpenGL ES入门专题

着色器是运维在GPU上的小程序。那么些小程序为图形渲染管线的某些特定部分而运维。从大圣旨义上来讲,着色器只是一种把输入转化为出口的程序。着色器也是一种非常独立的顺序,因为它们之间不可能互相通讯;它们中间独一的牵连独有经过输入和出口。

图片 1三角形绘制

着色器是利用一种叫GLSL的类C语言写成的。GLSL是为图形总结量身定制的,它满含部分对准向量和矩阵操作的有用特色。

终点着色器
是二个可编制程序的管理单元,推行顶点转换、纹理坐标转变、光照、材料等终端的有关操作,每顶点实践一遍。取代了价值观渲染管线中顶点转变、光照以及纹理坐标的管理。

attribute vec3 position;attribute vec3 color;varying vec3 outColor;void main(){ gl_Position = vec4(position, 1.0); outColor = color;}

片元着色器
是一个处理片元值及其相关联数据的可编制程序单元,片元着色器可施行纹理的访问、颜色的集中、雾化等操作,每片元推行一回。

precision mediump float;varying vec3 outColor;void main(){ gl_FragColor = vec4(outColor, 1.0);}
类型 说明
float 浮点型
bool 布尔型
int 整形
vec2 包含了2个浮点数的向量
vec3 包含了3个浮点数的向量
vec4 包含了4个浮点数的向量
ivec2 包含了2个整数的向量
ivec3 包含了3个整数的向量
ivec4 包含了4个整数的向量
bvec2 包含了2个布尔数的向量
bvec3 包含了3个布尔数的向量
bvec4 包含了4个布尔数的向量
mat2 2*2维矩阵
mat3 3*3维矩阵
mat4 4*4维矩阵
sampler1D 1D纹理采样器
sampler2D 2D纹理采样器
sampler3D 3D纹理采样器
samplerCube Cube纹理采样器

const
能够用来修饰任何基本数据类型。平时const变量在宣称的同一时间要举办最早化,结构体字段不可能使用const修饰吗,不过变量能够,并透过构造器实行开首化。富含数组的数组和结构体不可能宣称为常量,因为它们无法被开首化。

onst vec4 color = vec4 (1.0, 1.0, 1.0, 1.0);

attribute 变量只可以用于顶点着色器中,无法用于片元着色器。
一般用该变量来代表一些极端数据,如:顶点坐标、纹理坐标、颜色等。

uniforms
是一种从CPU中的应用向GPU中的着色器发送数据的主意,但uniform和终端属性有些分化。首先,uniform是全局的。全局意味着uniform变量必须在种种着色器程序对象中都以天下无敌的,而且它能够被着色器程序的即兴着色器在随便阶段访谈。第二,无论你把uniform值设置成什么,uniform会一贯保存它们的数量,直到它们被重新载入参数或更新。

samplers 一种独特的 uniform,用于呈现纹理。sampler
可用于顶点着色器和片元着色器。

varying
变量是从顶点着色器传递到片元着色器的多寡变量。顶点着色器能够利用易变变量来传递需求插值的水彩、法向量、纹理坐标等任性值。
在顶峰与片元shader程序间传递数据是很轻易的,一般在顶点shader中期维修改varying变量值,然后片元shader中动用该值,当然,该变量在极端及片元这两段shader程序中宣称必得是一样的
。比方:上边代码中应用程序中由顶点着色器传入片元着色器中的vColor变量。

图片 2精度修饰符

precision
能够用来分明私下认可精度修饰符。类型能够是int或float或采集样品器类型,precision-qualifier可以是lowp,
mediump,
恐怕highp。任何另外类型和修饰符都会引起错误。假使type是float类型,那么该精度(precision-qualifier)将适用于全部无精度修饰符的浮点数评释。假若type是int类型,那么该精度(precision-qualifier)将适用于具备无精度修饰符的整型数申明。包蕴全局变量申明,函数再次来到值表明,函数参数评释,和本地变量注脚等。未有注脚精度修饰符的变量将利用和它这两天的precision语句中的精度。

precision highp float;precision highp int;precision lowp sampler2D;precision lowp samplerCube;

gl_Position 顶点着色器内建变量,表示转换后点的半空中地点。
顶点着色器从应用程序中赢得原始的终极地方数据,那么些本来的终极数据在终端着色器中经过平移、旋转、缩放等数学转变后,生成新的终端地点。新的终端地点通过在顶峰着色器中写入gl_Position传递到渲染管线的后继阶段再三再四管理。

*** gl_PointSize***
顶点着色器内置变量,设置栅格化点的直径,也正是点的大大小小,日常用于点Smart,粒子等绘制。

gl_FragColor
片元着色器内置变量,用来保存片元着色器计算完结的片元颜色值,此颜色值将送入渲染管线的后继阶段展开管理。

static GLuint createGLShader(const char *shaderText, GLenum shaderType){ GLuint shader = glCreateShader(shaderType); glShaderSource(shader, 1, &shaderText, NULL); glCompileShader; int compiled = 0; glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); if (!compiled) { GLint infoLen = 0; glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &infoLen); if (infoLen > 1) { char *infoLog = malloc(sizeof * infoLen); if  { glGetShaderInfoLog (shader, infoLen, NULL, infoLog); GLlog("Error compiling shader: %s\n", infoLog); free; } } glDeleteShader; return 0; } return shader;}

1、创造着色器,通过glCreateShader成立着色器,type为着色器的门类GL_VERTEX_SHADER
和 GL_FRAGMENT_SHADER

glCreateShader (GLenum type) //type: GL_VERTEX_SHADER 或者 GL_FRAGMENT_SHADER

2、增多着色器源程序,将着色器源码关联到一个着色器对象shader上。string是三个有count行GLchar类型的字符串组成的数组,用来表示着色器的源代码数据。string能够以NULL结尾,也得以不是。假若length为NULL则string给出的每行都是以NULL结尾,不然length中必得有count个代表string长度的因素。(也正是说字符串以NULL结尾大家决不钦命长度,不然必需拟定每行的尺寸)

glShaderSource (GLuint shader, GLsizei count, const GLchar* const *string, const GLint* length)

3、编写翻译着色器源程序

glCompileShader (GLuint shader)

4、删除着色器

glDeleteShader (GLuint shader)

5、容错管理,通过glGetShaderiv获取编译状态,通过glGetShaderInfoLog获取错误音讯。

#define GL_COMPILE_STATUS 0x8B81#define GL_INFO_LOG_LENGTH 0x8B84glGetShaderiv (GLuint shader, GLenum pname, GLint* params) glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)

GLuint createGLProgram(const char *vertext, const char *frag){ GLuint program = glCreateProgram(); GLuint vertShader = createGLShader(vertext, GL_VERTEX_SHADER); GLuint fragShader = createGLShader(frag, GL_FRAGMENT_SHADER); if (vertShader == 0 || fragShader == 0) { return 0; } glAttachShader(program, vertShader); glAttachShader(program, fragShader); glLinkProgram; GLint success; glGetProgramiv(program, GL_LINK_STATUS, &success); if  { GLint infoLen; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen); if (infoLen > 1) { GLchar *infoText = malloc(sizeof*infoLen + 1); if  { memset(infoText, 0x00, sizeof*infoLen + 1); glGetProgramInfoLog(program, infoLen, NULL, infoText); GLlog("%s", infoText); free; } } glDeleteShader(vertShader); glDeleteShader(fragShader); glDeleteProgram; return 0; } glDetachShader(program, vertShader); glDetachShader(program, fragShader); glDeleteShader(vertShader); glDeleteShader(fragShader); return program;}

1、创设着色器程序

 glCreateProgram 

2、装配着色器

glAttachShader (GLuint program, GLuint shader)

3、链接着色器程序

glLinkProgram (GLuint program)

4、卸载着色器程序

glDetachShader (GLuint program, GLuint shader)

5、使用着色器程序

 glUseProgram (GLuint program)

6、容错管理

#define GL_LINK_STATUS 0x8B82#define GL_INFO_LOG_LENGTH 0x8B84glGetProgramiv (GLuint program, GLenum pname, GLint* params)glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)

- setupGLProgram{ NSString *vertFile = [[NSBundle mainBundle] pathForResource:@"vert.glsl" ofType:nil]; NSString *fragFile = [[NSBundle mainBundle] pathForResource:@"frag.glsl" ofType:nil]; _program = createGLProgramFromFile(vertFile.UTF8String, fragFile.UTF8String); glUseProgram;}- setupVertexData{ // 需要加static关键字,否则数据传输存在问题 static GLfloat vertices[] = { 0.0f, 0.5f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f }; GLint posSlot = glGetAttribLocation(_program, "position"); glVertexAttribPointer(posSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices); glEnableVertexAttribArray; //颜色数据 static GLfloat colors[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f }; GLint colorSlot = glGetAttribLocation(_program, "color"); glVertexAttribPointer(colorSlot, 3, GL_FLOAT, GL_FALSE, 0, colors); glEnableVertexAttribArray(colorSlot);}- render{ glClearColor(1.0, 1.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glViewport(0, 0, self.frame.size.width, self.frame.size.height);// 在这里初始化数据,可以加static关键字,也可以不加// GLfloat vertices[] = {// 0.0f, 0.5f, 0.0f,// -0.5f, -0.5f, 0.0f,// 0.5f, -0.5f, 0.0f// };// GLint posSlot = glGetAttribLocation(_program, "position");// glVertexAttribPointer(posSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices);// glEnableVertexAttribArray;// // GLfloat colors[] = {// 0.0f, 1.0f, 0.0f,// 0.0f, 1.0f, 0.0f,// 0.0f, 1.0f, 0.0f// };// GLint colorSlot = glGetAttribLocation(_program, "color");// glVertexAttribPointer(colorSlot, 3, GL_FLOAT, GL_FALSE, 0, colors);// glEnableVertexAttribArray(colorSlot); [self setupVertexData]; glDrawArrays(GL_TRIANGLES, 0, 3); //将指定 renderbuffer 呈现在屏幕上,在这里我们指定的是前面已经绑定为当前 renderbuffer 的那个,在 renderbuffer 可以被呈现之前,必须调用renderbufferStorage:fromDrawable: 为之分配存储空间。 [_context presentRenderbuffer:GL_RENDERBUFFER];}

glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)indx 指定要修改的顶点着色器中顶点变量id;size 指定每个顶点属性的组件数量。必须为1、2、3或者4。type 指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT;normalized 指定当被访问时,固定点数据值是否应该被归一化或者直接转换为固定点值;stride 指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0;ptr 顶点数据指针。

https://www.khronos.org/opengles/sdk/docs/reference\_cards/OpenGL-ES-2\_0-Reference-card.pdf

http://www.cnblogs.com/kesalin/archive/2012/11/25/opengl\_es\_tutorial\_02.html

一、变量和变量类型

  计算机图形学中,转变有二种基本的数据类型:矢量和矩阵。下图是OpenGL ES
着色器编程语言数据类型

                        
图片 3

 

 变量能够在宣称时最初化,或未来开始化,开端化是经过构造函数实行,也可做类型调换。

        

float myFloat = 1.0;
float myFloat2 = 1; // ERROR: invalid type conversion
bool myBool = true;
int myInt = 0;
int myInt2 = 0.0; // ERROR: invalid type conversion
myFloat = float(myBool); // Convert from bool -> float
myFloat = float(myInt); // Convert from int -> float
myBool = bool(myInt); // Convert from int -> bool

矢量一样能够转换

  

vec4 myVec4 = vec4(1.0); // myVec4 = {1.0, 1.0, 1.0,
// 1.0}
vec3 myVec3 = vec3(1.0,0.0,0.5); // myVec3 = {1.0, 0.0, 0.5}
vec3 temp = vec3(myVec3); // temp = myVec3
vec2 myVec2 = vec2(myVec3); // myVec2 = {myVec3.x,
// myVec3.y}
myVec4 = vec4(myVec2, temp); // myVec4 = {myVec2.x,
// myVec2.y,
// temp.x, temp.y}

矩阵转变

  

mat3 myMat3 = mat3(1.0, 0.0, 0.0, // First column
0.0, 1.0, 0.0, // Second column
0.0, 1.0, 1.0); // Third column

 

二、矢量和矩阵成分

矩阵成分能够由此三种格局取得,使用“.”操作符可能数组下标。依赖被给的因素的整合,每种被给的矩阵都能运用{x,
y, z, w}, {r, g, b, a},或{s, t, r,
q}表示。使用三种不一样的命名表是因为有二种坐标顶点、颜色和贴图。x, r, 或s
表示矩阵里的第一个因素,区别的命名格局独有是为了使用方便。可能说你能够选拔矩阵时混合使用矩阵命名格局,(但不能够使用.xgr,只可以一回利用一种命名准绳)。当使用“.”时,你也得以重新排列贰个矩阵。举例,

  

vec3 myVec3 = vec3(0.0, 1.0, 2.0); // myVec3 = {0.0, 1.0, 2.0}
vec3 temp;
temp = myVec3.xyz; // temp = {0.0, 1.0, 2.0}
temp = myVec3.xxx; // temp = {0.0, 0.0, 0.0}
temp = myVec3.zyx; // temp = {2.0, 1.0, 0.0}

矩阵也能够选取[]操作符,在这种下标方式[0]代表x,
[1]代表y。矩阵被以为是多少个矢量组成的,譬如mat2 被思考是多少个vec2s,mat3
是3 个vec3s。对矩阵,单独的列被接纳列下标[]入选。上边是例证:

mat4 myMat4 = mat4(1.0); // Initialize diagonal to 1.0
(identity)
vec4 colO = myMat4[0]; // Get colO vector out of the matrix
float ml_l = myMat4[1][1]; // Get element at [1][1] in matrix
float m2_2 = myMat4[2].z; // Get element at [2][2] in matrix

 

三、常量

  常量是在着色器中不得更动的数据类型。使用const修饰,必需在宣称时起首化。

const float zero = 0.0;
const float pi = 3.14159;
const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);
const mat4 identity = mat4(1.0);

 

四、结交涉数组

   结构

 像C
语言同样,能够凑合二种变量成为结构。在OpenGL ES 结构如下:

struct fogStruct
{
    vec4 color;
    float start;
    float end;
}  fogVar;

那将产生新的变量类型fogStruct,和新的变量名fogVar。使用可以初步化构造函数变量。定义二个构造类型,定义三个组织,三个同名的构造函数也被定义,必需是一定的。上面的布局能够被利用上边包车型客车语法初阶化:

 

fogVar = fogStruct(vec4(0.0, 1.0, 0.0, 0.0), // color
0.5, // start
2.0); // end

布局的结构基于结构的种类,它把各种成员做输入参数。访谈结构中的成分和C
语言同样。

vec4 color = fogVar.color;
float start = fogVar.start;
float end = fogVar.end;

  

  数组

OpenGL ES 数组语法和C
语言非常临近,索引以0 开端。上边是成立数组的事例:

 

float floatArray[4];
vec4 vecArray[2];

float a[4] = float[](1.0, 2.0, 3.0, 4.0);
float b[4] = float[4](1.0, 2.0, 3.0, 4.0);
vec2 c[2] = vec2[2](vec2(1.0), vec2(1.0));

 

五、操作符

图片 4

图片 5

 

那么些运算符使用和C
语言非常周边。但OpenGL ES
语法有严酷的语法限制,实施运算符的变量必需有同一的品类,二进制运算符(*,
/, +,
-)必得是浮点变量也许是整型变量。乘运算符能够在浮点、矢量、矩阵的重组中运转。比如:

 

float myFloat;
vec4 myVec4;
mat4 myMat4;
myVec4 = myVec4 * myFloat; // Multiplies each component of myVec4
// by a scalar myFloat
myVec4 = myVec4 * myVec4; // Multiplies each component of myVec4
// together (e.g., myVec4 ^ 2 )
myVec4 = myMat4 * myVec4; // Does a matrix * vector multiply of
// myMat4 * myVec4
myMat4 = myMat4 * myMat4; // Does a matrix * matrix multiply of
// myMat4 * myMat4
myMat4 = myMat4 * myFloat; // Multiplies each matrix component by
// the scalar myFloat

正如运算符(==, !=, <,
etc.)仅能够执行标量,矢量有极其的可比函数

 

六、函数

函数表明和C
语言同样,函数使用前,必得定义,它的原型必需交给。使用时丰裕临近C
语言。不相同是参数使用上,提供新鲜的变量限定词,指示变量是或不是能够被函数修改。这个限定词如下表:

图片 6

应用如下:

vec4 myFunc(inout float myFloat, // inout parameter
out vec4 myVec4, // out parameter
mat4 myMat4); // in parameter (default)

散射光总计函数。

vec4 diffuse(vec3 normal,
vec3 light,
vec4 baseColor)
{
    return baseColor * dot(normal, light);
}

OpenGL ES
函数不可能递归,原因是有的编写翻译工具施行这几个函数时,那会让那么些函数在线施行,最终使GPU
发生难点。

着色器语言也提供了放置函数。下边包车型大巴例证是,在有的着色器中总结基本反射光的着色器代码。

float nDotL = dot(normal , light);
float rDotV = dot(viewDir, (2.0 * normal) * nDotL C light);
float specular = specularColor * pow(rDotV, specularPower);

 

七、流动调查节表明

   调控语句语法和C 类似,if-then-else 逻辑也被利用,比方:

  

if(color.a < 0.25)
{
    color *= color.a;
}
else
{
    color = vec4(0.0);
}

原则表明式的结果必得是布尔值。也许说表明式基于布尔值总计,大概计算结果是布尔值(举个例子相比较运算)。

 

八、Uniforms

  Uniform

  是变量类型的一种修饰符。。uniform
是OpenGL ES 
中被输入着色器的只读值。。uniform被应用存款和储蓄各样着色器要求的数目,举个例子:转变矩阵、光照参数大概颜色。基本上各样输入着色器的常量参数像顶点和一部分(但在编写翻译时并不知道)应该是uniform。uniform
应该利用修饰词被声称为全局变量,如下:

uniform mat4 viewProjMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition;

uniform
的空间被顶点着色器和有个别着色器分享。也正是说顶点着色器和局部着色器被链接到一齐进去项目,它们分享一样的uniform。由此叁个在顶峰着色器中注明的uniform,也正是在局地着色器中也声称过了。当应用程序装载uniform
时,它的值在极端着色器和有些着色器都可用。

另叁个内需静心的是,uniform
被储存在硬件被称作常量存款和储蓄,那是一种分配在硬件上的囤积常量值的半空中。因为这种存款和储蓄须要的空中是定点的,在程序中这种uniform
的多寡是受限的。这几个限制能因此读gl_MaxVertexUniformVectors
和gl_马克斯FragmentUniformVectors编写翻译变量得出。(
大概用GL_MAX_VERTEX_UNIFORM_VECTORS 或GL_MAX_FRAGMENT_UNIFORM_
VECTO宝马X5S 为参数调用glGetIntegerv)OpenGL ES 3.0必须至少提供2伍二十一个终端着色器uniform 和2二十五个部分着色器uniform。但能够越多,

  Uniform Blocks

  

uniform TransformBlock
{
mat4 matViewProj;
mat3 matNormal;
mat3 matTexGen;
};
layout(location = 0) in vec4 a_position;
void main()
{
gl_Position = matViewProj * a_position;
}

 九、属性

  OpenGL ES
着色器语言的另一个变量是性质。属性别变化量仅仅在巅峰着色器中被应用,逐顶点的钦赐顶点着色器的输入。标准的被用来存款和储蓄地点、法线、贴图坐标和颜料数据。关键是明亮属性是每一种终端被绘制的详实数据。它实质上是着色器的使用者决定哪些数据是性质。

uniform mat4 u_matViewProjection;
attribute vec4 a_position;
attribute vec2 a_texCoord0;
varying vec2 v_texCoord;
void main(void)
{
    gl_Position = u_matViewProjection * a_position;
    v_texCoord = a_texCoord0;
}

  像uniform
同样,硬件对极端着色器的性质变量数量有限量。最大的属性数通过工具编写翻译支持gl_马克斯VertexAttribs
分明。(只怕采纳GL_MAX_VERTEX_ATTMuranoIBS 为参数调用glGetIntegerv
查询)最小数是8。假若为保障您的次序能在任何OpenGL ES 2.0
工具上编写翻译,确定保证您的性质不当先8。

变量被用来积攒顶点着色器的出口和有些着色器的输入。基本上各个终端着色器把出口数据转变成贰个或越多一些着色器的输入。那个变量也被部分着色器注脚(类型需合营),况且在光栅化阶段被线性插补产生图元。

varying vec2 texCoord;
varying vec4 color;

  变量也是有数据的界定(硬件上它们被用来做插补)。工具支持的最大数量是gl_MaxVaryingVectors
( 使用GL_MAX_VARYING_VECTOENVISIONS 为参数调用glGetIntegerv
查询)。最大数据是8.

  下边是极限着色器和有个别着色器的变量怎么着合营的扬言

 

// Vertex shader
uniform mat4 u_matViewProjection;
attribute vec4 a_position;
attribute vec2 a_texCoord0;
varying vec2 v_texCoord; // Varying in vertex shader
void main(void)
{
    gl_Position = u_matViewProjection * a_position;
    v_texCoord = a_texCoord0;
}

 

// Fragment shader
precision mediump float;
varying vec2 v_texCoord; // Varying in fragment shader
uniform sampler2D s_baseMap;
uniform sampler2D s_lightMap;
void main()
{
    vec4 baseColor;
    vec4 lightColor;
    baseColor = texture2D(s_baseMap, v_texCoord);
    lightColor = texture2D(s_lightMap, v_texCoord);
    gl_FragColor = baseColor * (lightColor + 0.25);
}

 

十、预管理指令

#define
#undef
#if
#ifdef
#ifndef
#else
#elif
#endif

  __LINE__ //
被着色器当前的行数代替
  __FILE__ // 在 OpenGL ES 中总是0
  __VERSION__ // OpenGL ES 着色器语言版本 (e.g., 100)
  GL_ES // 被 ES 着色器定义为值1

其他

  精度调节符,lowp,highp,mediump.对持有基于浮点的变量暗中同意的精度是浮点值,基于整型的变量暗中认可的精度是整型。在着色器中,
如果未有定义钦定精度,暗许对int 和float
的精度都是高。换句话说在终极着色器中并未有一些名进程决定的变量将是高素质。而一些着色器准绳却比不上。对浮点值未有默许的精度调控。每一个着色器必需评释暗许的着色器浮点精度或钦赐每个浮点变量的精度。即OpenGL
ES 2.0
不供给部分着色器帮衬高精度。决定是还是不是高精度被帮助是一些着色器是不是定义了GL_FRAGMENT_PRECISION_HIGH
宏(和工具输出OES_fragment_precision_high 扩张字符串)。

 

#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif

 

  最终要研究的标题是不改变性。在OpenGL ES 着色器编程语言里,invariant
是被用来另外极端着色器的变量输出的十分重要字。它代表如何和怎么必要他啊。着色器被编译时大概开展优化,一些指令被重新整理。指令重新整理意味着多少个着色器之间平等的揣摸不保证发生同样的结果。那是个难点在多通道着色器特殊情形下,依稀物体使用透明混合来绘制时。假若精度被使用来总计输出地方是不可信赖同样,精度的不如将促成artifacts。这在Z
fighting情形下平日发出。每一种像素十分小的Z
精度不一致引起了差异的反射。上面的例子呈现了进行多通道渲染时invariance
对获得不错的结果是相当重大的。上面包车型大巴圆环被绘制用二种格局。片段着色器先总计镜面反射光,再总括遇到光和散射光。顶点着色器不利用invariance,因而小的精度分化引起了Z
光在图

 

 

图片 7图片 8

invariant gl_Position;
invariant varying texCoord;

要是输出被发表为invariance,一样的企图输入同样,编写翻译器有限援助输出结果同样。比方你有五个终端着色器使用多通道图像投射矩阵依据输入总结输出。你能担保那二个地点是invariance。

 

 

uniform mat4 u_viewProjMatrix;
attribute vec4 a_vertex;
invariant gl_Position;
void main
{
//
    gl_Position = u_viewProjMatrix * a_vertex; // Will be the same
// value in all
// shaders with the
// same viewProjMatrix
// and vertex
}