GLSL shder的简单示例

来源:互联网 发布:淘宝图片大小多少和 编辑:程序博客网 时间:2024/05/29 13:43

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



原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 我的电话卡丢了怎么办 公司注销地税没有补齐怎么办 公司没有固定电话怎么办信用卡 申请信用卡公司没有固定电话怎么办 办理信用卡公司没有固定电话怎么办 江门市固话欠费停机后怎么办 物业交钥匙地面有裂缝怎么办 深圳交通卡丢了怎么办 没装etc走etc怎么办 找不到过敏源身体痒怎么办 微信客服电话打不通怎么办 华为手机网络信号不好怎么办 酷我好友动态加载不了怎么办? 米兔电话手表停机了怎么办 糖猫电话手表停机了怎么办 360电话手表停机了怎么办 小天才电话手表停机怎么办 移动手机卡不知道号码怎么办 天猫退款手机号换了怎么办 科目二考试脚抖怎么办 面试新工作没打电话怎么办 怀孕5个月胎位低怎么办 做业务很害怕打电话怎么办 固定电话总是接到骚扰电话怎么办 电话卡通话被限制了怎么办? 手机名单拉黑了怎么办 被苹果6s被拉黑怎么办 重庆福利企业解聘残疾职工怎么办 被银行拉入黑名单怎么办 借的钱还不起了怎么办 支付宝手机号空号了怎么办 到处贷不到钱了怎么办 还不起钱借不到怎么办 闯红灯收到短信不去扣分怎么办 被一家公司骗了怎么办 oppo手机无线网信号差怎么办 oppo手机无线网网速慢怎么办 电脑无法解析dns地址怎么办 vivox9手机卡顿反应慢怎么办 vivo手机设置成英文怎么办 wi-fi模块坏了怎么办