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的值。你能解释一下在半个循环中三角形会下降的原因吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值