在这一小节,主要学习GLSL的基本数据类型以及控制结构。GLSL具备了C++和Java的很多特性,我们会先了解所有着色阶段共有的特性,再了解各个着色器的专属特性。


1、着色器的基本结构

一个着色器程序和一个C程序类似,都是从main()函数开始执行的。同样支持单行注释//以及多行注释/**/

#version 330 core
void main(){
// add test code
}

 2、着色器的数据类型

GLSL是一种强类型的语言,所有变量使用前的必须声明。可用字母、数字、以及下划线字符来组成变量名字。但是数字或者下划线字符不能作为变量名的第一个字符,也不能使用连续下划线。

所有变量都必须在声明的同时进行初始化。

类型透明:基本数据类型(float、double、int、uint、bool)以及聚合类型(所谓聚合类型就是基本类型的合并)

类型不透明:采样器(sampler)、图像(Image)、原子计数器(atomic counter)。

前面提到的聚合类型,每个基本类型都有对应的聚合类型,以int为例,有2D向量(vec2)、3D向量(vec3)、4D向量(vec4)以及矩阵(mat2、mat4)等类型。

需要注意的是对于矩阵类型比如mat4×3,其中第一个值表示列数,第二个值表示行数。此外,矩阵的指定需要遵循主序的原则。也就是说,传入的数据将先填充列,然后填充行。

向量与矩阵中的元素是可以单独访问和设置的。下面主要说三种比较特殊的分量

(x,y,z,w) 与位置相关的分量

(r,g,b,a)  与颜色相关的分量

(s,t,p,q)  与纹理坐标相关的分量

此外,还有数组类型,一个大小为n的数组的元素范围是0到n-1。

float coeff[3];
float[3] coeff;
int indices[];

类似其他语言比如C++/Java。  

数组拥有构造函数 float coeff[3] = float[3](2.38, 3.14, 42.0)

GLSL的数组可以获取数组的长度 length() 该函数返回元素的个数。因为长度值在编译时就是已知的,所以length()方法会返回一个编译时常量。

 3、着色器的存储限制符(Storage Qualifiers)

数据类型可以通过一些修饰符来改变自己的行为。GLSL中一共定义了4种全局范围内的修饰符。

1、const 将一个变量定义为只读形式,可以理解为常量的意思

2、in 设置为着色器阶段的输入变量

3、out 设置为着色器阶段的输出变量

4、uniform 表示唯一,对所有几何图元的值都是一致的,除非应用程序对它执行了更新,否则着色器是并不会影响它的值的变化的。

5、buffer 设置应用程序共享的愉快可读写的内存

6、shared  只能用于用于计算着色器当中,它可以建立本地工作组内共享的内存。

4、逻辑语句

与其他语言类似GLSL提供了大量的操作符以及控制语句执行流程的逻辑操作

包括算术运算符、操作符、ifels、while、for、break、continue、return等,

这里有个特殊的关键字 discard 它只能用于片元着色器中,用于丢弃当前的片元、终止着色器的运行,不过这也得取决于具体的硬件实现。

另外函数的声明以及定义和C/C++类似,并且使用函数之前必须先声明,否则会产生错误。但是,需要特别注意的是,GLSL中没有指针或者引用的概念,

因此,GLSL提供了参数限制符,来表明其参数时候可以修改或者拷贝到函数等等,类型如下:

1、in 将数据拷贝到函数中(默认)

2、const in 将只读数据拷贝到函数中

3、out 从函数中获取数值

4、inout 将数据拷贝到函数中,并且返回函数中修改的数据


以上大概了解了GLSL的数据类型以及语句,下面是一些零散的知识点,先看看,以后用到时再重新回顾。


1、计算的不变性

GLSL无法保证在不同的着色器中,两个完全相同的计算公式会得到完全一样的结果。因此GLSL提供了invariant和precise关键字来保持着色器之间的计算不变性。

关于这个知识点,暂时无法理解,以后再回顾。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2、着色器的预处理器(跳过)

3、数据块接口(Interface Blocks)

着色器与应用程序之间,或者着色器阶段之间共享的变量可以组织为变量块的形式,并且有的时候必须采用这种形式

例如 uniform块、in块、out块、buffer块等等。

写法有点类型结构体的写法:

下面以uniform为例
uniform b{
  vec4 v1;
  bool v2;
};
一个uniform块中只可以包含透明类型的变量,而且uniform块必须在全局作用域内声明。

注意:着色器中的数据类型有两种:不透明以及透明的。上文有提及。

4、从应用程序中访问uniform块

uniform变量是着色器与应用程序之间共享数据的桥梁,因此如果着色器中的uniform变量是定义在命名的uniform块中,那么就有必要找到不同变量的偏移值。

5、Buffer块

GLSL中的buffer块,或者对于应用程序而言,就是着色器的存储缓存对象(shader storage buffe object)

与uniform块类似,但是buffer块更为强大。如果不需要写入缓存,那么可以直接使用uniform块,并且硬件设备本身可能也没有足够的资源空间来支持buffer块,

但是uniform块通常是足够的。

6、in/out块


关于着色器的编译

OpenGL着色器程序的编写与C语言等基于编译器的语言非常类似。

我们使用编译器来解析程序,检查是否存在错误,然后将它翻译为目标代码obj。然后,在连接过程中将一系列目标文件合并,并产生最终的可执行程序。

在程序中使用GLSL着色器的过程与之类似,只不过编译器和连接器都是OpenGL API的一部分而已。

常规步骤:

对于每一个着色器对象:

  1、创建一个着色器对象

  2、将着色器源代码编译为对象

  3、验证着色器的编译是否成功

将后需要将多个着色器对象链接为一个着色器程序,包括:

  1、创建一个着色器程序

  2、将着色器对象关联到着色器程序

  3、连接着色器程序。

  4、判断着色器的连接过程是否成功完成

  5、使用着色器来处理顶点和片元

相关OpenGL函数

  1、创建着色器对象  glCreateShader(GLenum type)

     type必须是  GL_VERTEX_SHADER、GL_FFRAGMENT_SHADER、

              GL_TESS_CONTROL_SHADER、GL_TESS_EVALUATION_SHADER、GL_GEOMETRY_SHADER

     中的一个。

  2、将着色器的源代码关联到这个对象上。  glShaderSource(...)

  3、编译着色器对象的源代码       glCompileShader()

  4、将着色器对象shader关联到着色器程序program中    glAttachShader()

and so on...


不知不觉明天就是11月份了。一份小记拖了将近2个月,我也是醉了。

最近发现了DOOM3源码,如获至宝。以后有时间会研究下约翰卡马克大神的这个引擎。

10月31日

广州

【OPENGL】第三篇 着色器基础(二)的更多相关文章

  1. 【OPENGL】第三篇 着色器基础(一)

    在这一章,我们会学习什么是着色器(Shader),什么是着色器语言(OpenGL Shading Language-GLSL),以及着色器怎么和OpenGL程序交互. 首先我们先来看看什么叫着色器. ...

  2. [OpenGL ES 02]OpenGL ES渲染管线与着色器

    [OpenGL ES 02]OpenGL ES渲染管线与着色器 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循"署名-非商业用途-保持一致"创 ...

  3. Unity 着色器基础知识

    一.着色器基础知识 着色器通过代码模拟物体表面发生的事情,其实就是GPU中运行的一段代码. 着色器的类型: 顶点着色器.片元着色器.无光照着色器.表面着色器.图像特效着色器.计算着色器. 坐标空间: ...

  4. Unity 渲染教程(二):着色器基础

    转载:https://www.jianshu.com/p/7db167704056 这是关于渲染基础的系列教程的第二部分.这个渲染基础的系列教程的第一部分是有关矩阵的内容.在这篇文章中我们将编写我们的 ...

  5. OpenGL学习笔记(三)着色器

    目录 Shader是什么 GLSL 数据类型 输入与输出 顶点着色器向片段着色器发送数据 Uniform 制作三色渐变三角形 对着色器程序进行封装 参考资料:OpenGL中文翻译 Shader是什么 ...

  6. OpenGL ES 3.0顶点着色器(二)

    #version es uniform mat4 u_mvpMatrix; in vec4 a_position; in vec4 a_color;out vec4 v_color;void main ...

  7. MongoDB基础教程系列--第三篇 MongoDB基本操作(二)

    1.集合操作 1.1.创建集合 MongoDB 用 db.createCollection(name, options) 方法创建集合. 格式 db.createCollection(name, op ...

  8. 第三篇、Swift基础学习

    1.常量与变量 什么是常量和变量 在Swift中规定:在定义一个标识符时必须明确说明该标识符是一个常量还是变量 使用let来定义常量,定义之后不可以修改 使用var来定义变量,定义之后可以修改 变量的 ...

  9. 第三篇:python基础_3

    本篇内容 文件处理补充 函数基本语法及特性 参数 返回值 嵌套函数 一.文件处理补充 1.文件操作的内置方法 #!/usr/bin/env pyhon #encoding: utf-8 #auth: ...

随机推荐

  1. MySQL正则表达式

    正则表达式作用是匹配方本,将一个模式(正则表达式)与一个文本串进行比较. MySQL用WHERE子句对正则表达式提供了初步的支持,允许你指定用正则表达式过滤SELECT检索出的数据. MySQL仅支持 ...

  2. 关于.NET 的邮件发送类

    .NET 类库中已经有现成的封好的类库了,只要引用System.Net.Mail命名空间即可实现发邮件的功能 以下是代码 public class SendMail { private string ...

  3. SQL变量、Substring、charindex、case函数、去除重复

      isnull(aa,0)删除表数据: truncate table aaa 添加字段: ALTER TABLE table1 ADD col1 varchar(200) DEFAULT '2008 ...

  4. 麦咖啡阻挡正常打开Excel文件

    双击打开Excel文件,提示如下图: Excel文件被麦咖啡做阻挡,无法正常打开 处理方案: 过一会儿还是出现此问题,干脆就把缓冲区保护给禁用掉

  5. Android Design Support Library使用详解

    Android Design Support Library使用详解 Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的And ...

  6. LED BIN code

    在LED选型时,一开始我们都知道要选个某种颜色,在选个尺寸,但在到具体选的时候,就会被那些个各种各样的参数搞得迷糊,这个主要对一个最让人困惑的参数-BIN CODE做整理. BIN就是bining的缩 ...

  7. C++中const关键字的使用总结

    C++中使用const关键字来修饰常量,下面从两个方面总结:变量和成员函数. 变量:const可以修饰普通变量.指针(数组)和结构体. 1.const修饰普通变量是最简单的情形.这样的用法多为在程序中 ...

  8. josn

     <?php$arr=array('name'=>'张三','age'=>19,'sex'=>'男','status'=>'未婚','className'=>'FG ...

  9. UE4 代码编写细节:静态变量

    Note:因为在切换关切时,会GC掉所有GameThread线程下的Object类,如果Static是UOBject 请调用AddToRoot函数  当然如果你的UObject子类Object是在自己 ...

  10. js 正则表达式 转至(七郎's Blog)

    //匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线 var re =new RegExp("^[a-zA-Z][a-zA-Z0-9_]{5,19}$"); if( ...