没有合适的资源?快使用搜索试试~ 我知道了~
基于OPENGL的Shader入门编程
![star](https://csdnimg.cn/release/downloadcmsfe/public/img/star.98a08eaa.png)
温馨提示
![preview](https://dl-preview.csdnimg.cn/4452916/0001-d16b4262bd4003e556d0bcf283eeb050_thumbnail.jpeg)
![preview-icon](https://csdnimg.cn/release/downloadcmsfe/public/img/scale.ab9e0183.png)
试读
33页
本文是关于Shader的入门编程,基于OpenGL的,详细的描述了相关的API用法,以及编写了一些短例!
资源推荐
资源详情
资源评论
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![docx](https://img-home.csdnimg.cn/images/20210720083331.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![application/pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![thumb](https://img-home.csdnimg.cn/images/20210720083646.png)
![](https://csdnimg.cn/release/download_crawler_static/4452916/bg1.jpg)
Chapter 7. OpenGL Shading 语言的 API
ARB_shader_objects, ARB_vertex_shader,和 ARB_fragment_shader引入了新
的API和功能用来支持使用OpenGL Shading Language写shader。这个API集合在本书
中被称为OPENGL SHADING LANGUAGE API。为了检测一个OpenGL的实现是不是支持
OpenGL Shading语言,可以通过调用参数为GL_EXTENSIONS的函数glGetString来获
得一个字符串,检查在返回的字符串里是否含有"GL_ARB_shader_objects",
"GL_ARB_vertex_shader",和"GL_ARB_fragment_shader"这三个子字符串来判断。这
种机制也可以用来确定是系统是支持的OpenGL Shading 语言的版本号。如果返回的
扩展字符串里含有"GL_ARB_shading_language_100",那么OPENGL SHADING LANGUAGE
API支持 1.00 版本的OpenGL Shading语言。
Appendix B.
在这章里,我们将学习新加入的 OpenGL 函数(entry points),它们用来创建、
加载、编译、和连接 shader,这些函数还被用来给 shader 传递一般的顶点属性和
uniform 变量。支持 shader 的 OpenGL 入口函数详细列表见附录 B。
在本章的最后,我们将介绍用来创建和使用第 6 章里的 brick shader 的程序代
码。如果你已经等不及了,那么请先去看 7.11 节,然后再回来学习这些 API 的细节。
下面是创建和使用 OpenGL shader 的简介:
• 用glCreateShaderObjectARB创建一个或多个(空的)shader对象
• 调用glShaderSourceARB给shader提供源代码。
• 为每个 shader 调用 glCompileShaderARB 来编译它。
• 调用glCreateProgramObjectARB创建一个program对象.
• 通过调用 glAttachObjectARB 把所有的 shader 对象和 program 对象关联起
来。
• 调用 glLinkProgramARB 把 program 对象连接起来。
• 调用glUseProgramObjectARB把可执行的program设置成作为OpenGL当前状态
的一部分。
• 如果shader使用了uniform变量。如果想要对这些uniform变量进行处理,需
要通过调用glLinkProgramARB和glGetUniformLocationARB查询得到该变量,
然后再通过glUniformARB来赋值。
• 如果vertex shader自定义了attribute变量,有两种方式指定该属性对应的
索引值,首先可以通过在链接shader前调用glBindAttribLocationARB来设
定,也可以由OpenGL自动指定,在连接后可以通过调用函数
glGetAttribLocationARB来查询得到使用的索引值。顶点的一般属性
(Generic vertex attributes)也有两种方式送入vertex shader,第一种
是通过调用glVertexAttribARB,第二种是一起调用
glVertexAttribPointerARB 和 glEnableVertexArrayPointer,通过这些指
令就可以绘制顶点数组了。
![](https://csdnimg.cn/release/download_crawler_static/4452916/bg2.jpg)
7.1 建立 Shader 对象
OpenGL Shading 语言的 API 在设计的时候刻意的模仿了 C/C++应用程序的开发。
第一步是创建源代码,接下来代码必须通过编译,再将不同的编译模块连接到一起。
最后,连接后得到的代码就可以在目标处理器上运行。
为了让 OpenGL 支持高级 shading 语言这个概念,必须提供某些结构能用来分别
保存源代码、编译后的代码和可执行代码。我们定义了两个由 OpenGL 来管理的数据
结构或者说是对象来解决这个问题。这些对象满足了存储的需求,我们为这些对象
定义了一些操作,让它们有能力进行源代码的指定、编译、连接以及执行。当一个
对象被创建的后,OpenGL 返回这个对象的句柄(handle)。我们可以通过这个句柄来
操作和查询这个对象的参数等。
使用可编程硬件的第一步是创建一个 shader 对象。这将会创建一个由 OpenGL
管理的数据结构,用它来保存 shander 的源代码。用如下代码创建一个 shader:
GLhandleARB glCreateShaderObjectARB(GLenum shaderType)
创建一个空的 shader 对象,返回它的句柄。一个 shader 对象用来保存和维护
这个 shader 的源代码字符串。shaderType 用来指示这个被创建的 shader 的类型。
可以两种不同类型的 shader。类型为 GL_VERTEX_SHADER_ARB 的 shader 在可编程的
顶点处理器上运行的,它可以取代 OpenGL 固定功能的顶点处理过程。类型为
GL_FRAGMENT_SHADER_ARB 的 shader 是在可编程的片段处理器运行,可以取代 OpenGL
固定功能的片段处理过程。
创建后,shader 对象的 GL_OBJECT_TYPE_ARB 被设置为 GL_SHADER_OBJECT_ARB,
而 GL_OBJECT_SUBTYPE_ARB 则根据 shaderTypede 的类型被设置成
GL_VERTEX_SHADER_ARB 或者是 GL_FRAGMENT_SHADER_ARB。
当 shader 对象被创建后,表示源代码内容的字符串必须提供给 shader。Shader
的源代码以一个字符串数组的形式存储。定义一个 shader 的源代码的命令如下:
void glShaderSourceARB(GLhandleARB shader,
GLuint nstrings,
const GLcharARB **strings,
GLint *lengths)
把 shader 里的代码设置成由 strings 变量定义的一组保存代码的字符串变量,
则先前存储的代码将完全被覆盖。数组里字符串的个数由 nstrings 指定。如果
lengths 为 NULL,则默认所有的字符串都以 NULL 结尾。如果 lengths 不为 NULL,则
它指向一个包含每个字符串长度的数组。Lengths 数组里的每一个元素都包含了对
应字符串的长度(字符串的 null 字符不计算在内)或者一个小于0的数来表示字符
串以 null 结尾。源代码在这时候并不进行处理和分析,仅仅是简单的把代码拷贝到
![](https://csdnimg.cn/release/download_crawler_static/4452916/bg3.jpg)
shader 对象里。应用程序在这个函数返回后可以立即修改或者释放这个源代码的拷
贝。
一次可以提交多个字符串的优点包括:
• 可以用多个一样的片段来组织源代码。
• 可以在不同 shader 间共享前缀字符串(类似于头文件)。
• 可以共享一些#define 值来控制编译过程
• 可以用来包含自定义或者第三方的函数库。
7.2 Compiling Shader Objects 编译 shader 对象。
在源代码被加载到 shader 对象里后,源代码必须经过编译来检查其正确性。编
译的结果依然作为 shader 的一部分保存在 shader 对象里,直到下一次编译操作发
生,或者直到 shader 对象被删除。用来编译 shader 的命令如下:
void glCompileShaderARB(GLhandleARB shader)
这条指令编译已经保存在 shader 里的源代码。
编译的状态将作为 shader 对象状态的一部分保存在 shader 里。如果 shader 没有错
误,被正确编译,那么这个值被设置为 GL_TRUE,反之为 GL_FALSE。它可以通过给
glGetObjectParamenterARB 传递一个 GL_OBJECT_COMPILE_STATUS_ARB 来查询。
如果一个 shader 有词法、语法或者语义错误的话,将不能正确编译。无论编译
的结果是不是成功,编译的信息都包含在信息日志里面,这个日志可以通过调用函
数 glGetInfoLogARB 取得。
OpenGL Shading 语言的编译规则对于不同的 shader 类型是不同的。所以必须
考虑需要编译的是一个 vertex shader 还是一个 fragment shader。
编译操作的信息可以通过调用 glGetInfoLogARB(在 7.5 节中介绍)来获取。但是
不应该根据此信息判断编译是否成功。如果 shader 对象编译成功,输出信息可能为
空也可能包含编译操作的信息。如果编译不成功,那么信息日志中会包含发生的词
法、语法和语义错误,然后是警告信息以及其他编译器认为相关的信息。
glCompileShaderARB 不需要等到编译结束就可以将控制权返回给应用程序。其
它需要依赖于编译结束的函数(比如:glLinkProgramARB)将会阻塞直到编译结束。
如果你要保证在程序继续运行前,编译能正确结束的话,应该调用
glGetObjectParameterARB 来查询编译结果的正确性。查询操作将会阻塞直到编译
结束,状态变量有效为止。
7.3 Linking and Using Shaders 连接和使用 shader。
![](https://csdnimg.cn/release/download_crawler_static/4452916/bg4.jpg)
每个 shader 对象都是独立编译的。为了创建一个 program,应用程序需要一个
机制来指定一个列表,里面列出了将要连接到一起的所有 shader。我们需要先创建
一个 program 对象并且把所有需要连接到这个 program 的 shader 都连接到一起,创
建工作才能完成。
创建一个 program 对象使用下列命令:
GLhandleARB glCreateProgramObjectARB(void)
创建一个空的 program 对象返回它的句柄, shader 对象可以连接到 program
对象上,它能够把所有的 shader 对象连接起来从而构成一个应用程序。同时它也提
供了一种检查这些 shader 对象之间兼容性的手段(比如,检查 vertex shader 和
fragment shader 之间的兼容性)。如果一个 program 不再需要一个 shader 对象时,
shader 对象可以从 program 对象上 detach 掉。
在定义好一个 program 对象以后,shader 对象就可以连接(attach)到它上面。
Attach 只是给那些将要连接到一起的 shader 创建一个引用。这是应用程序用来创
建一个 program 的方法。Shader 对象用以下方法 attach 到 program 上:
void glAttachObjectARB(GLhandleARB program,
GLhandleARB shader)
该命令把 shader 对象的 shader 句柄 (注:函数声明中的那个形参
GLhandleARB shader)连接到 program 对象的 program 句柄(注:函数声明中的那个
形参 GLhandleARB program)上。这个动作指明了要连接到 program 上的 shader。
连接到 program 上的 shader 的个数没有明确的限制。不管一个 shader 是不是
已经连接到 program 对象上,所有对一个 shader 有效的操作都可以施加在其上。 在
一个 shader 对象的源代码被加载前,或者在编译前都可以将其 attach 到一个
program 上,也允许一个 shader 对象被连接到多个 program 上。换句话说。
glAttachObjectARB 只是简单的指定了将要连接到一起的 shader 对象的集合。
为了创建一个有效的 program,所有连接到 program 对象的 shader 对象都应该
被正确编译,Program 对象本身也必须被连接起来。连接操作将会给 uniform 变量
分配空间,完成各个独立编译的 shader 对象间的相互引用工作。检查确保 vertex
shader 和 fragment shader 之间的兼容性。用以下命令可以连接 program:
void glLinkProgramARB(GLhandleARB program)
把句柄为 program 的 program 对象连接起来。如果有 subtype 的类型为
GL_VERTEX_SHADER_ARB 的 shader 对象连接到 program 上,它们将会被连接到一起
创建一个可以运行在可编程 vertex processor 上的可执行代码。如果有 subtype
的类型为 GL_FRAGMENT_SHADER_ARB 的 shader 对象连接到 program 上,它们将会被
连接到一起,创建一个可以运行在可编程 fragment processor 上的可执行代码。
![](https://csdnimg.cn/release/download_crawler_static/4452916/bg5.jpg)
连接操作的状态将被保存成program对象状态的一部分。如果shader没有错误,被正确
编译,那么这个值被设置为GL_TRUE,反之为GL_FALSE。它可以通过给
glGetObjectParamenterARB传递一个GL_OBJECT_LINK_STATUS_ARB参数来查询。
如果连接成功,并且指定的program对象已经被前面最近的一个指令
glUseProgramObjectARB设置成当前激活的应许,则将生成shader的可执行代码并将
其设置成当前OpenGL渲染状态的一部分。
连接成功后,所有program自定义uniform变量(见 7.7 节)将被初始化为 0,
program对象的每一个激活的uniform变量都将被分配一个位置(location),这可
以通过glGetUniformLocationARB来查询。但是,这时候每一个自定义的attribute
变量(见 7.6 节)还没有被绑定到一个普通的attribute索引上。
如果一个program包含了GL_VERTEX_SHADER_ARB类型的shader对象,但是没有包
含GL_FRAGMENT_SHADER_ARB类型的shader对象。vertex shader将自动和固定管线功
能的fragmetn处理例程连接到一起。同样的。如果一个program只包含了
GL_FRAGMENT_SHADER_ARB类型的shader对象而没有包含
GL_VERTEX_SHADER_ARB类型
的shader对象。Fragment shader隐含的将和固定管线功能的vertex处理管道连接。
连接一个 program 对象将可能因为下列原因而失败:
• attribute 变量数目超过了 OpenGL 实现所能支持的最大数目。
• uniform 变量数目超过了 OpenGL 实现所能支持的最大数目。
• Vertex shader 或者 fragment shader 没有 main 函数。
• 在 fragment shader 里声明的 varying 变量在 vertex shader 里没有声明成
相同的类型(或者根本就没有声明)。
• 函数或者变量名字无法解析。
• 共享的全局变量被定义成不同的类型或者被初始化成不同的值。
• 有一个或者多个连接到 program 的 shader 对象没有被成功的编译。
如果连接操作成功,将产生一个 program 对象。它可能包含一个可被 vertex 处
理器运行的可执行程序,一个可被 fragment 处理器运行的可执行程序,或者两个都
有。不管编译是不是成功,以前的信息和可执行代码都将丢失。当连接操作结束后,
应用程序可以修改那些被连接到 program 上的 shader 对象,可以进行编译,也可以
detach shader 对象或者 attach 新的 shader 对象到 program 对象上。这些操作都
不会影响到 program 对象的属性,直到下一个连接操作为止。
连接操作的信息可以通过调用 glGetInfoLogARB(在第 7.5 章描述)来获得。如
果连接操作成功,信息日志可能为空,也可能包含连接操作的信息。如果连接不成
功,信息日志里包含发生的连接错误的信息,以及其它编译器有选择提供的警告信
息。
glLinkProgramARB 不需要等到连接操作完成才返回控制权给应用程序。任何依
赖于连接结果的命令将会阻塞直到连接操作结束。如果你想保证在继续执行前连接
操作完成的话,可以通过调用 glGetObjectParameterARB 来查询连接是不是成功。
这个查询动作将被阻塞直到连接操作完成,状态变量有效为止。
剩余32页未读,继续阅读
![avatar](https://profile-avatar.csdnimg.cn/f91cc1f3da9d4ee09702c7754ba1e05a_yaolin170.jpg!1)
yaolin170
- 粉丝: 0
- 资源: 2
上传资源 快速赚钱
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助
![voice](https://csdnimg.cn/release/downloadcmsfe/public/img/voice.245cc511.png)
![center-task](https://csdnimg.cn/release/downloadcmsfe/public/img/center-task.c2eda91a.png)
安全验证
文档复制为VIP权益,开通VIP直接复制
![dialog-icon](https://csdnimg.cn/release/downloadcmsfe/public/img/green-success.6a4acb44.png)
- 1
- 2
前往页