Tutorial 5: Uniform Variables

本文源自:http://ogldev.atspace.co.uk/www/tutorial05/tutorial05.html

Uniform Variables

Background

我们将在这个教程中看到新的着色器变量类型-Uniform变量。Attribute和uniform变量的区别是,前者在整个绘制调用的时候一直保持不变,后者会在每次调用着色器的时候从顶点缓区中取出一个新的值并输入到着色器里面。这使得你在绘制调用前需要设置这个uniform变量的值,这样一来每次调用顶点着色器的时候才会访问到相同的值。Uniform变量对于存放光照参数(光照的位置和方向)、变换矩阵、纹理对象句柄等等相当的实用。

终于我们的教程能够在屏幕中移动某个物体了。为了实现这种功能,可以逐帧改变uniform变量和由GLUT提供的idle回调两种方式组合在一起。除非在特定的情况下GLUT并不会调用渲染回调。在最小化和最大化窗口或者是被其他窗口覆盖的时候,才会调用渲染回调。如果在打开程序后并没有修改窗口布局,渲染回调就只会调用一次。你可以尝试在渲染回调里面加入printf函数来验证一下。当你在最小化然后再最大化后仅仅会输出一次。在前面的教程中仅仅为GLUT注册一个渲染回调是合适的,但是现在我们需要反复的改变变量的取值。那么,通过注册idle渲染回调会完成这种功能。Idle回调在窗口系统没有接收到时间的时候会被调用。现在你用一个特定的回调函处理诸如时间更新或者注册idle回调函数。在这里,我们只在渲染函数中更新这个变量。

Source walkthru

glutIdleFunc(RenderSceneCB);

我们这里把渲染回调注册为了idle回调。当你决定用一个特定的idle回调的时候,需要在这个回调的最后调用glutPostRedisplay()。glutPostRedisplay()把窗口表机会需要重新渲染的状态。在下一帧时,GLUT主循环会调用渲染回调。

gScaleLocation = glGetUniformLocation(ShaderProgram, "gScale");
assert(gScaleLocation != 0xFFFFFFFF);

在链接过程序对象后,我们向程序对象查询uniform变量的位置。这也是一个C/C++程序环境需要映射到着色器运行环境的例子。当你编译着色器的时候,GLSL编译器会为每一个uniform变量分配一个索引。这个索引对于应用程序是可用的,可以通过索引来访问GPU中着色器相对应的变量。应用程序可以使用glGetUniformLocation来获取索引。可以向这个函数里面传入程序对象的句柄和变量的名字,函数的返回值在正确的情况下直接返回索引,错误的时候返回-1。这个时候检查错误也很重要(我们上面的代码可能会触发断言),否则后面更新的变量并不会传入着色器中。主要有两个原因可能会是函数调用失败。可能是你拼错了变量名字,也可能编译器直接把变量优化并抛弃了。如果GLSL编译器发现着色器中的变量并没有得到实际使用,编译器会直接丢弃它。这两种情况下glGetUniformLocation会调用失败。

static float Scale = 0.0f;
Scale += 0.001f;
glUniform1f(gScaleLocation, sinf(Scale));

我们分配了一个静态的浮点型变量,然后再每一个渲染函数中每次增加一点点(如果你的机器跑的太慢或过快的话,也许你可以每次增加0.001)。我们最终传入着色器的值是“Scale”变量的正弦值。这样就会创造了一个再-1.0与1.0之间循环的值。Sinf()函数传入的是弧度值而不是角度,但我们无需关心。我们可以用glUniform1f向着色器里面传递sinf()的结果。OpenGL提供了一系列像glUniform{1234}{if}这种形式的函数。可以通过这些函数把1D、2D、3D或者4D(glUniform的形式也会基于这些数量)的浮点或者整数型(i,f代表着类型前缀)向量传入着色器中。当然也有能够把向量地址还有矩阵的地址作为参数传入着色器的函数。我们传入函数的第一个参数就是位置索引,这个索引就是前面使用glGetUniformLocation()函数获取的。
现在我们需要看一下VS顶点着色器中的变化(FS片段着色器保持不变)

uniform float gScale;

在着色器中声明uniform变量

gl_Position = vec4(gScale * Position.x, gScale * Position.y, Position.z, 1.0);

我们在程序的每一帧用特定的值乘以位置向量的X和Y的值。你能解释一下在半个循环中三角形会下降的原因吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值