着色器是在GPU上运行的程序.着色器使用OpenGL ES着色器语言(称为ES SL)编写. ES SL有自己的变量,数据类型,限定符,内置输入和输出.
数据类型
下表列出了基本知识OpenGL ES SL提供的数据类型.
Sr .No. | Type&说明 |
---|---|
1 | void 表示空值. |
2 | bool 接受真或假. |
3 | int 这是有符号整数数据类型. |
4 | float 这是浮动标量数据类型. |
5 | vec2,vec3,vec4 n分量浮点向量 |
6 | bvec2,bvec3,bvec4 布尔矢量 |
7 | ivec2,ivec3,ivec4 有符号整数向量 |
8 | mat2,mat3,mat4 2x2,3x3,4x4浮点矩阵 |
9 | sampler2D 访问2D纹理 |
10 | samplerCube 访问权限立方体映射纹理 |
限定符
主要有三个OpenGL ES中的限定符SL :
Sr.No. | 限定符&说明 |
---|---|
1 | 属性 此限定符充当顶点着色器和OpenGL ES之间的链接,用于每顶点数据.每次执行顶点着色器时,此属性的值都会更改. |
2 | 制服 此限定符链接着色器程序和WebGL应用程序.与属性限定符不同,制服的值不会改变.制服是只读的;您可以将它们与任何基本数据类型一起使用,以声明变量. 示例 : 制服 vec4 lightPosition; |
3 | 变化 此限定符在顶点着色器和片段着色器之间形成内插数据的链接.它可以与以下数据类型和减号一起使用; float,vec2,vec3,vec4,mat2,mat3,mat4或array. 示例 : 变化 vec3 正常; |
Vertex Shader
顶点着色器是一个程序代码,在每个顶点上调用.它将几何体(例如:三角形)从一个地方转换(移动)到另一个地方.它处理每个顶点(每个顶点数据)的数据,如顶点坐标,法线,颜色和纹理坐标.
在顶点着色器的ES GL代码中,程序员必须定义处理数据的属性.这些属性指向用JavaScript编写的顶点缓冲区对象.可以使用顶点着色器以及顶点变换和减号来执行以下任务;
顶点变换
正常转换和标准化
纹理坐标生成
纹理坐标转换
照明
色料应用
预定义变量
OpenGL ES SL提供以下预定义变量: vertex shader :
Sr.No. | 变量&说明 |
---|---|
1 | highp vec4 gl_Position; 保持顶点的位置. |
2 | mediump float gl_PointSize; 持有转换点大小.此变量的单位为像素. |
示例代码
查看以下顶点着色器的示例代码.它处理三角形的顶点.
attribute vec2 coordinates;void main(void) { gl_Position = vec4(coordinates, 0.0, 1.0);};
如果仔细观察上面的代码,我们已经声明了一个名为 coordinates 的属性变量. (此变量将使用方法 getAttribLocation()与顶点缓冲区对象关联.属性坐标作为参数传递给此方法以及着色器程序对象. )
在给定顶点着色器程序的第二步中,定义了 gl_position 变量.
gl_Position
gl_Position是预定义变量,仅在顶点着色器程序中可用.它包含顶点位置.在上面的代码中,坐标属性以向量的形式传递.由于顶点着色器是每顶点操作,因此会为每个顶点计算gl_position值.
稍后,gl_position值由原始装配,剪切,剔除和其他固定功能操作使用在顶点处理结束后对基元进行操作.
我们可以为顶点着色器的所有可能操作编写顶点着色器程序,我们将在本教程中单独讨论.
片段着色器
网格由多个三角形组成,每个三角形的表面称为片段的.片段着色器是在每个片段上的每个像素上运行的代码.这是为了计算和填充各个像素的颜色而编写的.可以使用片段着色器和减号执行以下任务;
内插值的操作
纹理访问
纹理应用
雾
颜色总和
预定义变量
OpenGL ES SL为片段着色器和减号提供以下预定义变量;
Sr.No. | 变量&描述 |
---|---|
1 | mediump vec4 gl_FragCoord ; 保持帧缓冲区内的片段位置. |
2 | bool gl_FrontFacing; 持有属于前置基元的片段. |
3 | mediump vec2 gl_PointCoord; 在一个点内保持片段位置(仅限光栅化点). |
4 | mediump vec4 gl_FragColor; 保持着色器的输出片段颜色值 |
5 | mediump vec4 gl_FragData [n] 保持颜色附件的片段颜色 n . |
示例代码
片段着色器的以下示例代码显示了如何操作将颜色应用于三角形中的每个像素.
void main(void) { gl_FragColor = vec4(0, 0.8, 0, 1);}
在上面的代码中,颜色值存储在变量 gl中.FragColor
.片段着色器程序使用固定的函数变量将输出传递给管道; FragColor就是其中之一.此变量保存模型像素的颜色值.
存储和编译着色器程序
由于着色器是独立程序,我们可以编写它们作为单独的脚本并在应用程序中使用.或者,您可以直接以字符串格式存储它们,如下所示.
var vertCode = 'attribute vec2 coordinates;' + 'void main(void) {' + ' gl_Position = vec4(coordinates, 0.0, 1.0);' + '}';
编译着色器
编译包括以下三个步骤 :
创建着色器对象
将源代码附加到创建的着色器对象
编译程序
创建顶点着色器
要创建空着色器,WebGL提供了一个名为 createShader的方法( ).它创建并返回着色器对象.其语法如下 :
Object createShader (enum type)
如语法中所述,此方法接受预定义的枚举值作为参数.我们有两个选项用于此 :
gl.VERTEX_SHADER 用于创建顶点着色器
gl.FRAGMENT_SHADER 用于创建片段着色器.
将源附加到着色器
您可以使用方法 shaderSource()将源代码附加到创建的着色器对象.其语法如下 :
void shaderSource(Object shader, string source)
此方法接受两个参数 :
着色器 : 您必须将创建的着色器对象作为一个参数传递.
来源 : 您必须以字符串格式传递着色器程序代码.
编译程序
到编译程序,你必须使用方法 compileShader().它的语法如下:
compileShader(Object shader)
此方法接受着色器程序对象作为参数.创建着色器程序对象后,将源代码附加到它并将该对象传递给此方法.
以下代码片段显示如何创建和编译顶点着色器以及片段着色器创建一个三角形.
// Vertex Shadervar vertCode = 'attribute vec3 coordinates;' + 'void main(void) {' + ' gl_Position = vec4(coordinates, 1.0);' + '}';var vertShader = gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vertShader, vertCode);gl.compileShader(vertShader); // Fragment Shadervar fragCode = 'void main(void) {' + ' gl_FragColor = vec4(0, 0.8, 0, 1);' + '}';var fragShader = gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fragShader, fragCode);gl.compileShader(fragShader);
合并程序
创建并编译着色器程序后,需要创建一个包含两者的组合程序着色器(顶点和片段).以下步骤需要遵循 :
创建程序对象
同时附加两者着色器
链接两个着色器
使用程序
创建程序对象
使用方法 createProgram()创建程序对象.它将返回一个空的程序对象.这是它的语法 :
createProgram();
附加着色器
使用方法 attachShader()
attachShader(Object program, Object shader);
此方法接受两个参数 :
计划 : 将创建的空程序对象作为一个参数传递.
着色器 : 传递一个已编译的着色器程序(顶点着色器,片段着色器)
注意 : 您需要使用此方法附加两个着色器.
链接着色器
使用 linkProgram()方法链接着色器,通过传递已连接着色器的程序对象.其语法如下 :
linkProgram(shaderProgram);
使用程序
WebGL提供了一种名为 useProgram()的方法.您需要将链接的程序传递给它.其语法如下 :
useProgram(shaderProgram);
以下代码段显示了如何创建,链接和使用组合着色器程序.
var shaderProgram = gl.createProgram(); gl.attachShader(shaderProgram,vertShader); gl.attachShader(shaderProgram,fragShader); gl.linkProgram(shaderProgram); gl.useProgram(shaderProgram);