【GLSL教程】(四)shder的简单示例 【转】
http://blog.csdn.net/racehorse/article/details/6638455
GLSL的Hello World
这一节中包含一个最基本的shader,它提供如下功能:顶点变换然后使用单一的颜色渲染图元。
顶点shader
前面已经说过,顶点shader负责完成顶点变换。这里将按照固定功能的方程完成顶点变换。
固定功能流水线中一个顶点通过模型视图矩阵以及投影矩阵进行变换,使用如下公式:
- vTrans = projection * modelview *incomingVertex
首先GLSL需要访问OpenGL状态,获得公式中的前两个矩阵。前面讲过,GLSL可以获取某些OpenGL状态信息的,这两个矩阵当然包括在内。可以通过预先定义的一致变量来获取它们:
- uniform mat4 gl_ModelViewMatrix;
- uniform mat4 gl_ProjectionMatrix;
接下来需要得到输入的顶点。通过预先定义的属性变量,所有的顶点将可以一个个传入顶点shader中。
- attribute vec4 gl_Vertex;
为了输出变换后的顶点,shader必须写入预先定义的vec4型变量gl_Position中,注意这个变量没有修饰符。
现在我们可以写一个仅仅进行顶点变换的顶点shader了。注意所有其他功能都将丧失,比如没有光照计算。顶点shader必须有一个main函数,如下面的代码所示:
- void main()
- {
- gl_Position =gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
- }
上面代码中变换每个顶点时,投影矩阵都将乘上模型视图矩阵,这显然非常浪费时间,因为这些矩阵不是随每个顶点变化的。注意这些矩阵是一致变量。
GLSL提供一些派生的矩阵,也就是说gl_ModelViewProjectionMatrix是上面两个矩阵的乘积,所以顶点shader也可以写成下面这样:
- void main()
- {
- gl_Position =gl_ModelViewProjectionMatrix * gl_Vertex;
- }
上面的操作能够获得和固定功能流水线相同的结果吗?理论上是如此,但实际上对顶点变换操作的顺序可能会不同。顶点变换通常在显卡中是高度优化的任务,所以有一个利用了这种优化的特定函数用来处理这个任务。这个神奇的函数如下:
- vec4 ftransform(void);
使用这个函数的另一个原因是float数据类型的精度限制。由于数据精度的限制,当使用不同的顺序计算时,可能得到不同的结果,因此GLSL提供这个函数保证获得最佳性能的同时,还能得到与固定功能流水线相同的结果。
这个函数按照与固定功能相同的步骤对输入顶点进行变换,然后返回变换后的顶点。所以shader可以重新写成如下形式:
- void main()
- {
- gl_Position =ftransform();
- }
片断shader
片断shader也有预先定义的变量gl_FragColor,可以向其中写入片断的颜色值。下面的代码就是一个片断shader,将所有片断绘制成淡蓝色:
- void main()
- {
- gl_FragColor =vec4(0.4,0.4,0.8,1.0);
- }
可以在此获得本节例子的源码:
http://lighthouse3d.com/wptest/wp-content/uploads/2011/03/glutglsl5_2.0.zip
颜色shader
GLSL可以读取一些OpenGL状态,在本节我们将学习如何访问在OpenGL中设置的glColor变量。
GLSL有一个属性变量记录当前颜色,也提供易变变量从顶点shader向片断shader传递颜色值。
- attribute vec4 gl_Color;
- varying vec4 gl_FrontColor; // writable onthe vertex shader
- varying vec4 gl_BackColor; // writable onthe vertex shader
- varying vec4 gl_Color; // readable on thefragment shader
变量使用思想如下:
1、OpenGL程序通过glColor传送颜色信息。
2、顶点shader通过属性gl_Color接收颜色值。
3、顶点shader计算正面和反面的颜色,然后分别保存在gl_FrontColor和gl_BackColor中。
4、片断shader接收易变变量gl_Color中存储的插值产生的颜色,由当前图元的方向决定颜色是gl_FrontColor还是gl_BackColor插值产生的。
5、片断shader根据易变变量gl_Color设置gl_FragColor。
前
面说过顶点shader和片断shader中传递的易变变量要有相同的名字,但这里是个例外,顶点shader中的gl_FrontColor和
gl_BackColor会根据图元的方向,自动转变为片断shader中的gl_Color。还要注意属性变量gl_Color和易变变量
gl_Color没有冲突,因为前者只存在于顶点shader,后者只存在于片断shader。
下面是顶点shader的例子,只计算了正面颜色:
- void main()
- {
- gl_FrontColor =gl_Color;
- gl_Position =ftransform();
- }
片断shader更加简单:
- void main()
- {
- gl_FragColor = gl_Color;
- }
基于GLEW的源代码:
http://lighthouse3d.com/wptest/wp-content/uploads/2011/03/colorglut_2.0.zip
扁平shader(Flatten Shader)
着色器编程让我们可以探索一些新效果,本节的例子展示了用奇怪的方法操作顶点得到的效果。
首先我们要得到一个扁平的3D模型,只需要在应用模型视图变换时将模型顶点的z坐标设为0就行了。下面是顶点shader的代码:
- void main(void)
- {
- vec4 v = vec4(gl_Vertex);
- v.z = 0.0;
- gl_Position =gl_ModelViewProjectionMatrix * v;
- }
我们先将gl_Vertex变量复制到一个局部变量v中。gl_Vertex是一个GLSL提供的属性变量,所以在顶点shader中它是只读的。
片断shader与“GLSL中的Hello World”一节相同,就只用设置一种颜色。
一个扁平的茶壶效果如下:
更进一步,我们需要在z坐标上使用一个正弦函数。将z坐标作为x坐标的函数,这样茶杯将呈现波浪的效果:
- void main(void)
- {
- vec4 v =vec4(gl_Vertex);
- v.z = sin(5.0*v.x)*0.25;
- gl_Position =gl_ModelViewProjectionMatrix * v;
- }
最
后我们需要加入一些顶点动画效果。为了达到这个目的我们需要增加一个变量记录变化的时间,或者帧数。一个顶点shader是无法记录不同顶点值的,更不用
说记录不同的帧了。所以我们需要在OpenGL程序中定义这个变量,然后作为一致变量传递给shader。假设在OpenGL程序中有一个名为time的
帧计数器,在shader中有个同名的一致变量。
顶点shader的代码如下:
- uniform float time;
- void main(void)
- {
- vec4 v =vec4(gl_Vertex);
- v.z = sin(5.0*v.x +time*0.01)*0.25;
- gl_Position =gl_ModelViewProjectionMatrix * v;
- }
在有关一致变量的小节讲过,在OpenGL程序中需要两个步骤:
·setup: 获取一致变量的存储位置
·render: 更新一致变量
设置(setup)步骤只有一条语句:
- loc =glGetUniformLocation(p,"time");
这里p是程序的句柄,time与顶点shader中定义的一致变量名称相同。变量loc是Glint类型的,必须定义在下面的渲染(render)函数也可以访问到的地方。渲染函数如下所示:
- void renderScene(void)
- {
- glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
- glLoadIdentity();
- gluLookAt(0.0,0.0,5.0,
- 0.0,0.0,0.0,
- 0.0f,1.0f,0.0f);
- glUniform1f(loc, time);
- glutSolidTeapot(1);
- time+=0.01;
- glutSwapBuffers();
- }
函数中的变量time在程序一开始初始化,然后每帧都会进行自增运算。
本节的GLEW源代码:
http://lighthouse3d.com/wptest/wp-content/uploads/2011/03/flatten_2.0.zip
【GLSL教程】(四)shder的简单示例 【转】的更多相关文章
- java基础之JDBC四:事务简单示例
/** * 事务 */ public class Test { public static void main(String[] args) { Connection conn = null; Pre ...
- ActiveMQ学习教程/2.简单示例
ActiveMQ学习教程(二)——简单示例 一.应用IDEA构建Maven项目 File->New->Module...->Maven->勾选->选择->Next ...
- pureMVC简单示例及其原理讲解四(Controller层)
本节将讲述pureMVC示例中的Controller层. Controller层有以下文件组成: AddUserCommand.as DeleteUserCommand.as ModelPrepCom ...
- Fastify 系列教程四 (求对象、响应对象和插件)
Fastify 系列教程: Fastify 系列教程一 (路由和日志) Fastify 系列教程二 (中间件.钩子函数和装饰器) Fastify 系列教程三 (验证.序列化和生命周期) Fastify ...
- 关于Ajax实现的简单示例
一.代码示例 关于Ajax的基本概念(包括XMLHttpRequest对象及其相关方法属性)移步这里(w3school中文版)学习了解. <!doctype html> <html ...
- 【Redis】三、Redis安装及简单示例
(四)Redis安装及使用 Redis的安装比较简单,仍然和大多数的Apache开源软件一样,只需要下载,解压,配置环境变量即可.具体安装过程参考:菜鸟教程Redis安装. 安装完成后,通过r ...
- 【Canvas】(1)---概述+简单示例
Canvas---概述+简单示例 如果通俗的去理解Canvas,我们可以去理解成它类似于我们电脑自带的画图工具一样,canvas首先是选择一块画布,然后在这个画布上描绘我们想画的东西,画好后展示给用户 ...
- DotNetty关键概念及简单示例(基于NET5)
DotNetty关键概念及简单示例(基于NET5) 目录 DotNetty关键概念及简单示例(基于NET5) 1.DotNetty 设计的关键 1.1 核心组件 1.1.1 Channel 1.1.2 ...
- WPF入门教程系列二十三——DataGrid示例(三)
DataGrid的选择模式 默认情况下,DataGrid 的选择模式为“全行选择”,并且可以同时选择多行(如下图所示),我们可以通过SelectionMode 和SelectionUnit 属性来修改 ...
随机推荐
- Python+Selenium练习篇之2-利用ID定位元素
在前面一篇文章,我们介绍了如何摘取页面字段,通过正则进行匹配符合要求的字段.如果感觉有点困难,不能立马理解,没有关系.把字符串摘取放到第一篇,是因为自动化测试脚本,经常要利用字符串操作,字符串切割,查 ...
- python-生成器迭代器及递归调用
生成器是一个可迭代的对象,它的执行会记住上一次返回时在函数体中的位置.对生成器第二次(或第 n 次)调用跳转至该函数上次执行位置继续往下执行,而上次调用的所有局部变量都保持不变. 生成器的特点:1.生 ...
- zookeeper Zookeeper
这是ZooKeeper客户端库的主要类.使用一个ZooKeeper服务,应用程序必须首先实例化ZooKeeper类的对象.所有的迭代都将通过调用ZooKeeper类的方法来完成.除非另有说明,该类的方 ...
- ValueStack、ActionContext
笔者不知道该用哪个词来形容ValueStack.ActionContext等可以在Struts2中用来存放数据的类.这些类使用的范围不同,得到的方法也不同,下面就来一一介绍. 1. ValueStac ...
- C#从大图中截取一部分图片
#region 从大图中截取一部分图片 /// <summary> /// 从大图中截取一部分图片 /// </summary> /// <param name=&quo ...
- Java给各个方法记录执行时间
Java给各个方法记录执行时间 long startTime = System.currentTimeMillis();...//要测试时间的方法LoggerFactory.getLogger(Bas ...
- 【bzoj4668】冷战 并查集按秩合并+朴素LCA
题目描述 1946 年 3 月 5 日,英国前首相温斯顿·丘吉尔在美国富尔顿发表“铁幕演说”,正式拉开了冷战序幕. 美国和苏联同为世界上的“超级大国”,为了争夺世界霸权,两国及其盟国展开了数十年的斗争 ...
- [bzoj3944] sum [杜教筛模板]
题面: 传送门 就是让你求$ \varphi\left(i\right) $以及$ \mu\left(i\right) $的前缀和 思路: 就是杜教筛的模板 我们把套路公式拿出来: $ g\left( ...
- 洛谷P3832 [NOI2017]蚯蚓排队 【链表 + 字符串hash】
题目链接 洛谷P3832 题解 字符串哈希然后丢到hash表里边查询即可 因为\(k \le 50\),1.2操作就暴力维护一下 经复杂度分析会发现直接这样暴力维护是对的 一开始自然溢出WA了,还以为 ...
- BZOJ2396 神奇的矩阵 【随机化 + 矩乘】
题目链接 BZOJ2396 题解 一种快速判断两个矩阵是否相等的方法: 对于两个\(n * n\)矩阵,两边同时乘一个\(n * 1\)的随机矩阵,如果结果相等,那么有很大概率两个矩阵相等 如果左边是 ...