OpenGL ES着色器语言之语句和结构体(官方文档第六章)

OpenGL ES着色器语言的程序块基本构成如下:

语句和声明

函数定义

选择(if-else)

迭代(for, while, do-while)

跳跃(discard, return, break, continue)

6.1函数定义

  着色器是由一系列全局声明和函数定义组成的。函数声明规范如下:

                  // prototypereturnType functionName (type0 arg0, type1 arg1, ..., typen argn);函数定义规范如下:// definitionreturnType functionName (type0 arg0, type1 arg1, ..., typen argn){// do some computationreturn returnValue;}

数组可以作为参数,但是不能作为返回值。当把数组作为形参时,数组的元素个数也必须同时传进去。数组作为实参传进函数时,只使用函数的名称即可,不要带下标。

结构体也可以作为参数,返回值也可以是不包含数组的结构体。

main函数是着色器的入口函数。顶点和片元着色器必须包含一个main函数。它没有参数,也没有返回值,而且必须声明为void。

6.1.1  函数调用约定

函数通过值返回的方式被调用。这意味着,在调用时输入参数被拷贝进函数,在函数退出前输出参数被拷贝出给调用者。

函数声明或定义中控制参数拷进还是拷出的方法如下:

  • 关键字in用来说明参数是拷进参数,不能拷出
  • 关键字out用来说明参数是拷出参数,不能拷进
  • 关键字inout用来说明参数既可以是拷进参数,也可以使拷出参数
  • 没有使用修饰符的函数参数默认为指定in

6.2  选择

着色语言的条件控制流使用if 或 if-else:

if (bool-expression)true-statement或者if (bool-expression)true-statement
elsefalse-statement

6.3  迭代

while和do循环规范如下:

for (for-init-statement; condition(opt); expression)
statement-no-new-scope
while (condition)
statement-no-new-scope
do
statement
while (expression)

for循环的condition语句是可选的,没有该语句的话默认为true。

6.4  跳跃语句

continue;
break;
return;
return expression;
discard; // in the fragment shader language only

没有goto语句。

continue只能用在循环中,程序执行到continue得时候会自动舍弃后面的操作而进入下一次循环。

break;也只能用在循环中,作用是直接跳出其所在的那层循环。

discard关键字只能使用在片元着色器中。它用在片元着色器中来放弃对当前片元的操作。这个关键字导致片元直接被忽略并且不会更新任何缓冲区。最典型的用法是在一个条件语句中,如:

if(indensity < 0.0)

discard;

   片元着色器可能会测试一个片元的alpha值,并根据测试忽视片元

需要注意的是着色器执行后会出现覆盖测试(coverage test),覆盖测试可以改变alpha的值。

return语句直接导致退出当前函数。

OpenGL ES着色器语言之内建变量(官方文档第七章)

有些OpenGL ES操作在顶点处理器和片元处理器之间有特定的功能,有些在片元处理器之后又特定的功能,着色器通过内建变量同这些固定功能进行通信。

在OpenGL ES中,内建特殊变量部分来自顶点着色器的输出变量,部分来自于片元着色器的输入变量和输出变量。不同于用户定义的varying变量,内建特殊变量不用在顶点语言和片元语言之间保持严格的一对一对应。相反,两个语言各有自己的一套变量集合。

7.1  顶点着色器特定变量

变量gl_Position仅可用在顶点语言中,并且用来写入奇次顶点位置。所有符合语法规则的顶点着色器都应该给该变量写入一个值。可以在着色器运行期间的任何时候给它写入新值,也可以随时读取它的值。这个值可以用在顶点处理开始之后的图元装配,剪裁,剔除和其他操作图元的固定功能上。如果检测到gl_Position没有被写入,或者在写入前被读取,编译器会产生一个诊断信息,但是并不是所有的情况都能检测的到。如果顶点着色器已经执行,但是并没有写入gl_Position,那么gl_Position的值是未定义的。

  gl_PointSize也是只能用在顶点语言中,顶点着色器用它来写入将要光栅化的点的尺寸,单位是像素

用来与特定功能通信的内建顶点着色器变量本质上是按照如下方式声明的:

highp vec4 gl_Position; // should be written to
mediump float gl_PointSize; // may be written to

如果这些值没有被写入过,那么它们的值是未定义的。着色器在给它们写入值之后也可以将它们的值读取出来以重新获取写入的值。如果被多次写入过值,最近写入的值有效。

这些内建变量具有全局作用域。

7.2  片元着色器特定变量

片元着色器的输出值由OpenGL ES管线的后端固定函数进行处理。片元着色器使用gl_FragColor和gl_FragData内建变量向OpenGL ES管线输出值,除非关键字discard被执行。

对于片元着色器来说,向gl_FragColor和gl_FragData写入值不是必要的。许多算法,如阴影体,包含未被写入颜色值的渲染通道。

在片元着色器中这些变量可能会被写入多次。如果这样的话,在后续的固定功能管线中使用的就是最后一次被赋的值。这些变量可以在写入值之后随时将值读取出来。如果在读取之前没有被写入值的话,那么将得到一个未定义的值。

   写入gl_FragColor是为了指明随后固定功能管线要用到的片元颜色值。如果后续固定功能管线要使用这个片元颜色值,但是着色器又没有给它写入值,那么片元颜色值将是一个未定义的值。
         gl_FragData变量值是一个数组。向gl_FragData[n]写入数据时为了指明后续固定功能管线要使用的片元数据n。如果后续固定功能管线要使用这个片元数据,但是着色器又没有给它写入值,那么片元数据将是一个未定义的值。

如果着色器静态地给gl_FragColor赋值,那么它就不会给gl_FragData的任何元素赋值。如果着色器静态地给gl_FragData的任何元素赋值,那么它就不会给gl_FragColor赋值。也就是说,着色器不会同时给gl_FragColor和gl_FragData变量都赋值。

(如果着色器包含对变量x的静态赋值,在预处理之后,着色器包含一个向x写入值的语句,不论如何,运行时控制流都会执行该语句。)

如果着色器执行了discard关键字,片元将被直接扔掉,gl_FragColor和gl_FragData的值也会变得毫不相干。

gl_FragCoord是片元着色器中的只读变量,它保存了片元相对窗口的坐标位置:x, y, z, 1/w。这个值是顶点处理产生片元后固定功能内插图元的结果。组件z是用于表示片元深度的深度值。

gl_FrontFacing是片元着色器的内建只读变量,如果片元属于一个当前图元,那么这个值就为true。这个变量的一个用法就是来模拟两面光,通过选择由顶点着色器计算的两个颜色中的一个。

gl_PointCoord是片元着色器的内建只读变量,它的值是当前片元所在点图元的二维坐标。点的范围是0.0到1.0。如果当前的图元不是一个点,那么从gl_PointCoord读出的值是未定义的。

片元着色器的内建变量本质上的声明形式如下:

mediump vec4 gl_FragCoord;
bool gl_FrontFacing;
mediump vec4 gl_FragColor;
mediump vec4 gl_FragData[gl_MaxDrawBuffers];
mediump vec2 gl_PointCoord;

它们的行为并不像没有存储修饰符的变量;这些内建变量拥有全局作用域。

7.3  顶点着色器内建属性

OpenGL ES中没有内建属性值。

7.4  内建常量

顶点和片元着色器提供了如下内建常量:

//
// 相关常量实现。下面的示例值是这些最大值所允许的最小值。
//
const mediump int gl_MaxVertexAttribs = 8;
const mediump int gl_MaxVertexUniformVectors = 128;
const mediump int gl_MaxVaryingVectors = 8;
const mediump int gl_MaxVertexTextureImageUnits = 0;
const mediump int gl_MaxCombinedTextureImageUnits = 8;
const mediump int gl_MaxTextureImageUnits = 8;
const mediump int gl_MaxFragmentUniformVectors = 16;
const mediump int gl_MaxDrawBuffers = 1;

7.5  内建uniform状态

为了方便访问OpenGL ES处理状态,OpenGL ES定义了以下uniform变量。如果片言语言的某个实现不支持highp,并且罗列的状态又是highp,那么片元语言将其作为mediump处理。

//
// 窗口坐标的深度范围
//
struct gl_DepthRangeParameters {
highp float near; // n
highp float far; // f
highp float diff; // f - n
};
uniform gl_DepthRangeParameters gl_DepthRange;

OpenGL ES着色器语言之内建函数(官方文档第八章)

OpenGL ES着色语言为标量和向量操作定义了一套内建便利函数。有些内建函数可以用在多个类型的着色器中,有些是针对固定硬件的,所以这部分只能用在某个特定的着色器上。

内建函数基本上可以分为一下三类:

(1)它们使用一些简便的方式提供必要的硬件功能,如材质贴图。这些函数单独通过着色器是无法模拟出来的。

(2)它们展示了一些可以常简单的写入的繁琐操作(clamp, mix等),但是这些操作非常普遍,并且提供直接对硬件的支持。对于编译器来说,将表达式映射到复杂的装配线指令上是非常困难的。

(3)它们提供了对图形硬件的操作,并且在适当时候进行加速。三角函数就是一个很好的例子。

有些函数名称和常见的C库函数类似,但是它们支持向量的输入和更多的传统标量输入。

建议应用程序尽量使用内建函数而不是在着色器中实现相同的计算,因为内建函数是经过最大优化的(如,有些内建函数是直接操作硬件的)。

用户定义的代码可以重载内建函数,但最好不要重新定义它们。

内建函数的输入参数(和相应的输出的参数)可以是float, vec2, vec3, vec4。对于函数的任何特定应用,实际的类型必须和所有的参数和返回值相同。就像mat,必须为mat2, mat3, mat4.

参数和返回值的精度修饰符是隐藏的,对于材质函数,返回类型的精度必须和采样器类型匹配。

uniform lowp sampler2D sampler;
highp vec2 coord;
...
lowp vec4 col = texture2D (sampler, coord); // texture2D 返回类型的精度为lowp

其他内建函数形参的精度修饰是没有任何关联的。内建函数的调用将返回输入参数的最高精度。

8.1  角度和三角函数

标识为angle的函数参数假定以弧度为单位。这些函数不可能出现被0除的情况,如果被除数为0,结果是未定义的。

radian函数是将角度转换为弧度,degrees函数是将弧度转换为角度。sin, cos, tan都是标准的三角函数。asin, acos, atan是反三角函数。genType有点像面向对象中泛型,即如果genType是float型的,那么

genType pow (genType x, genType y)

就变成了:

float pow (float x, float y)

同理,如果genType是int型的,那么就变成了:

int pow (int x, int y);

8.2  指数函数

(1)genType pow (genType x, genType y)

x的y次方。如果x小于0,结果是未定义的。同样,如果x=0并且y<=0,结果也是未定义的。使用时应特别注意。

(2)genType exp (genType x)

e的x次方

(3)genType log (genType x)

计算满足x等于e的y次方的y的值。如果x的值小于0,结果是未定义的。

(4)genType exp2 (genType x)

计算2的x次方

(5)genType log2 (genType x)

计算满足x等于2的y次方的y的值。如果x的值小于0,结果是未定义的。

(6)genType sqrt (genType x)

计算x的开方。如果x小于0,结果是未定义的。

(7)genType inversesqrt (genType x)

计算x的开方之一的值,如果x小于等于0,结果是未定义的。

8.3  常用函数

(1)genType abs (genType x)

返回x的绝对值

(2)genType sign (genType x)

如果x>0,返回1.0;如果x=0,返回0,如果x<0,返回-1.0

(3)genType floor (genType x)

返回小于等于x的最大整数值

(4)genType ceil (genType x)

返回大于等于x的最小整数值

(5)genType fract (genType x)

返回x-floor(x),即返回x的小数部分

(6)genType mod (genType x, float y)、genType mod (genType x, genType y)

返回x – y * floor (x/y),即求模计算%

(7)genType min (genType x, genType y),genType min (genType x, float y)

返回x和y的值较小的那个值。

(8)genType max (genType x, genType y),genType max (genType x, float y)

返回x和y的值较大的那个值。

(9)genType clamp (genType x, genType minVal, genType maxVal)、genType clamp (genType x, float minVal, float maxVal)

clamp翻译为夹具,就叫夹具函数吧,这个函数是什么意思呢?看看解释的意思是:获取x和minVal之间较大的那个值,然后再拿较大的那个值和最后那个最大的值进行比较然后获取较小的那个,意思就明白了,clamp实际上是获得三个参数中大小处在中间的那个值。函数有个说明:如果minVal > minMax的话,函数返回的结果是未定的。也就是说x的值大小没有限制,但是minval的值必须比maxVal小。

(10)genType mix (genType x, genType y, genType a)、genType mix (genType x, genType y, float a)

返回线性混合的x和y,如:x⋅(1−a)+y⋅a

(11)genType step (genType edge, genType x),genType step (float edge, genType x)

如果x < edge,返回0.0,否则返回1.0

(12)genType smoothstep (genType edge0,genType edge1,genType x),genType smoothstep (float edge0,float edge1,genType x)

如果x <= edge0,返回0.0 ;如果x >= edge1 返回1.0;如果edge0 < x < edge1,则执行0~1之间的平滑埃尔米特差值。如果edge0 >= edge1,结果是未定义的。

8.4  几何函数

(1)float length (genType x)

返回向量x的长度

(2)float distance (genType p0, genType p1)

计算向量p0,p1之间的距离

(3)float dot (genType x, genType y)

向量x,y之间的点积

(4)vec3 cross (vec3 x, vec3 y)

向量x,y之间的叉积

(5)genType normalize (genType x)

标准化向量,返回一个方向和x相同但长度为1的向量

(6)genType faceforward(genType N, genType I, genType Nref)

如果Nref和I的点积小于0,返回N;否则,返回-N;

(7)genType reflect (genType I, genType N)

返回反射向量

(8)genType refract(genType I, genType N,float eta)

返回折射向量

8.5  矩阵函数

(1)mat matrixCompMult (mat x, mat y)

矩阵x乘以y,result[i][j]是 x[i][j] 和 y[i][j] 的标量积。注意,要获取线性代数矩阵的乘法,使用乘法操作符*。

8.6  向量相关函数

相关或相等的操作符(<, <=, >, >=, ==, !=)被定义(或保留),返回一个标量布尔值。下面, “bvec” 是表示bvec2, bvec3, or bvec4的占位符, “ivec”是ivec2, ivec3, or ivec4的占位符,  “vec” 是vec2, vec3, or vec4的占位符. 在任何情况下,输入和返回值向量的长度必须匹配。

(1)lessThan

比较x < y.

(2)lessThanEqual

比较x<=y

(3)greaterThan

比较x>y

(4)greaterThanEqual

比较x>=y

(5)equal

比较x==y

(6)notEqual

比较x!=y

(7)bool any(bvec x)

如果向量x的任何组件为true,则结果返回true。

(8)bool all(bvec x)

如果向量x的所有组件均为true,则结果返回true。

(9)bvec not(bvec x)

返回向量x的互补矩阵

8.7  材质查找函数

   纹理(材质)查找函数对于定点着色器和片元着色器都适用。然而,定点着色器的细节级别并不是通过固定功能计算的,所以顶点着色器和片元着色器纹理查找之间还是有一些差别的。一下函数是通过采样器访问纹理,和使用OpenGL ES API是一样的。纹理属性如尺寸,像素格式,维数,过滤方法,纹理映射匹配数,深度比较等等在OpenGL ES API中都有定义。

在下面的函数中,bias参数对于片元着色器来说是可选的。但在定点着色器中不可使用。对于片元着色器,如果使用了bias这个参数,它被加到优先细节的计算级别中来执行纹理访问操作。如果bias没有使用,那么实现将自动选择一个默认级别。对于非纹理映射的纹理,纹理是直接被使用的。如果是纹理映射的,并且在片元着色器中执行,那么使用LOD来进行纹理查找。如果是纹理映射的,并且在顶点着色器中执行,那么使用的是基本纹理。

以Lod结尾的内建函数只能用在顶点着色器中,在带有Lod的函数中,lod参数直接用来表示细节级别。

8.8  片元处理函数

片元处理函数只有在片元语言中才有,但在GLSL ES中没有片元处理函数。

转载于:https://www.cnblogs.com/Anita9002/p/4931091.html

OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)...相关推荐

  1. OpenGL ES着色器语言之变量和数据类型

    所有变量和函数在使用前必须声明.变量和函数名是标识符. 没有默认类型,所有变量和函数声明必须包含一个声明类型以及可选的修饰符.变量在声明的时候首先要标明类型,后边可以跟多个变量,之间用逗号隔开.很多情 ...

  2. OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)

    OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章) 4.5精度和精度修饰符 4.5.1范围和精度 用于存储和展示浮点数.整数变量的范围和精度依赖于数值的源(varying,unifo ...

  3. OpenGL ES着色器语言(GLSL ES)规范 ——下篇

    文章目录 前言 分支和循环 if.if-else for continue.break.discard 着色器内置变量 函数 函数定义 规范声明 webgl内置函数 存储限定字 const attri ...

  4. iOS OpenGl ES着色器

    首先创建两个文件分别为simple.frag和simple.vert simple.frag内容 const char* SimpleFragmentShader = STRINGIFY(varyin ...

  5. OpenGLES2.0着色器语言glsl

    OpenGLES2.0中是强制使用可编程的渲染管线的,使用的是glsl着色器语言,因为着色器语言是使用的GPU,即图形处理单元,而不是CPU,这样可以使CPU从繁重的几何计算和像素的处理中解脱出来了. ...

  6. OpenGL着色器语言GLSL语法总结

    GLSL语法与C语言类似. 1.变量类型 基础类型:bool,int,uint,float,double与C语言的类型类似. 向量类型:vecN,bvecN,ivecN,uvecN,dvecN,N表示 ...

  7. OpenGL学习——着色器

    基于上一个 你好,三角形 的代码绘制修改点击蓝色字体查看 着色器 给三角形换色 三角形变换颜色 五彩三角形 给三角形换色 如果我们打算从一个着色器向另一个着色器发送数据,我们必须在发送方着色器中声明一 ...

  8. OpenGL编译着色器

    1.读入着色器的代码 一般着色器的代码可以写在raw下创建glsl文件. gls是openGL的着色语言. 1.1.顶点着色器 定义的每个单一的顶点,顶点着色器都会调用一次,当他被调用的时候,会在a_ ...

  9. 可编程渲染管线与着色器语言

    Programming pipeline & shading language 大家好,今天想给大家介绍一下可编程渲染管线和着色器语言的相关基础知识,使想上手SHADER编程的童鞋们可以快速揭 ...

最新文章

  1. php怎样弄成中文,php怎样替换中文字符
  2. PHP问题 —— Warning: PHP Startup: Unable to load dyna
  3. rmReport 自适应行高(自动行高)
  4. nginx安装(正式)
  5. java 链表 最小堆优先级队列_关于Java集合的小抄
  6. 【无线串口模块快速选型指南】通信频点、芯片、通信距离、功率灵敏度、电流 空中速率
  7. android WebView总 结
  8. python相机拍照显示_从solvePnP获取摄影机姿势
  9. flutter从0到1构建大前端应用 pdf_推荐前端热门GitHub代码库「值得收藏」
  10. 途牛windows转linux,在 Windows 中通过 VirtualBox 启动物理硬盘上的 Linux 操作系统...
  11. 世界首富洛克菲勒的6句忠告,每个字都值钱
  12. 修复jqgrid setgridparam postdata 的多次查询条件累加
  13. 通用的linux下安装配置svn独立服务
  14. Android View框架总结(四)View布局流程之Measure
  15. 2.1~3 32位及64位x86处理器介绍
  16. IC卡、ID卡、CPU卡、RFID、NFC大致区分一览表
  17. 峰值信噪比PSNR~均方差MSE matlab实现
  18. 千呼万唤始出来:JUC灵魂AQS终于来了
  19. linuxmint/ubuntu修改主机名hostnam
  20. 什么是视频比特率:完整指南

热门文章

  1. python天天学怎么样-Python天天学_01_基础1
  2. python教学网站-python教学网站
  3. 运行python需要网吗-vs能运行python吗
  4. python画柱形图-Python绘制柱状图
  5. python编程零基础-如何零基础入门Python编程?
  6. python中的time库安装步骤-python中time模块需要安装么
  7. python代码壁纸-一个爬取壁纸的python代码
  8. 上海python培训班-上海哪家python培训班比较靠谱?
  9. python工程师-Python工程师必看的面试问题与解答(中)
  10. python编程经典案例-精心整理!9个 Python 实用案例分享