opengl 教程(5) shader(2) uniform变量

简介: 原帖地址:http://ogldev.atspace.co.uk/www/tutorial05/tutorial05.html         在这篇教程中,我们将接触到一种新的shader变量uniform variables,这种变量和属性变量的区别:属性变量是指每个顶点shader调用时,都会根据属性的位置从顶点缓冲中装入该顶点的相应属性值,而uniform变量,则对每个draw调用保持不变,这意味着你在draw调用前装入该变量,然后draw中每个顶点shader执行时,都能访问该变量,而且该变量值会保持不变。

      原帖地址:http://ogldev.atspace.co.uk/www/tutorial05/tutorial05.html

 

      在这篇教程中,我们将接触到一种新的shader变量uniform variables,这种变量和属性变量的区别:属性变量是指每个顶点shader调用时,都会根据属性的位置从顶点缓冲中装入该顶点的相应属性值,而uniform变量,则对每个draw调用保持不变,这意味着你在draw调用前装入该变量,然后draw中每个顶点shader执行时,都能访问该变量,而且该变量值会保持不变。uniform变量常用来存储一些draw执行时候的常量数据,比如光照参数、变化矩阵、纹理对象句柄等等。注:uniform变量类似于D3D11中的const buffer中的变量

      在这篇教程中,我们会使渲染的物体在屏幕上运动,实现动画的效果。主要通过绑定一个uniform变量以及一个idle回调函数来实现,uniform变量的值在每帧中都会变化。

      GLUT不会重复调用我们的渲染函数,只有发生一些特殊事件的时候,才会执行渲染操作,比如窗口最大化、最小化,当前窗口被别的窗口遮挡等等,如果程序执行后,我们不做任何变化,则渲染函数只会执行一次,我们可以通过在渲染函数中增加一个print函数来验证它,在最大化、最小化窗口时候,该函数会在控制台窗口会打印相关信息。如果实现静态物体的渲染,这种方法当然可以,但是在本教程中,我们要实现动画,需要重复调用渲染函数,该怎么实现呢?我们可以注册一个idle回调函数,把渲染函数放在该函数中,或者直接把渲染函数注册成idle函数,在GLUT不接受windows系统事件时,idle函数会重复执行,这样结合idle函数和变化的uniform变量,我们就可以实现动画的效果。

主要代码:

glutIdleFunc(RenderSceneCB);

       通过上面的代码,我们把渲染函数注册成idle函数,需要注意的是在渲染函数的末尾要加上glutPostRedisplay()函数调用,否则的话idle函数会反复执行,但渲染函数却没有,glutPostRedisplay()会重绘当前显示窗口,并保证下一次glut消息循环中,渲染函数会被调用。

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

      通过查询shader程序对象,我们能够得到uniform变量的位置,该位置和该uniform变量在shader代码中的位置一致。通常情况下,我们不能直接访问和更新uniform变量。在glsl compiler编译shader代码时候,它会给每个uniform变量分配一个索引,在shader内部访问uniform变量都是通过这个索引来实现的,应用程序则是通过glGetUniformLocation函数来访问相应的uniform变量,函数的参数为shader程序句柄以及uniform变量名字。函数调用成功,则会返回索引值,失败的话返回-1,对返回值进行错误检测也非常重要,这样可以保证shader值被正确更新。在两种情况下,该函数会调用失败,第一种就是变量名字拼写错误,或者就是compiler进行的优化操作,这时也不能得到正确的索引值

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

      我们定义一个缩放因子变量,每次渲染函数调用时候,该变量都增加0.001。该变量的sin值通过函数glUniform1f传输到shader中去。使用sin函数值可以保证Scale范围在[-1,1]之间,注意sinf的参数是以弧度为单位。opengl提供了glUniform{1234}{if}函数的多个版本,分别用来装入1维、2维、3维、4维向量,i表示变量是整数,f表示变量是浮点,该函数也有向量和矩阵的版本,可以用来设置向量或矩阵类型的uniform变量。该函数的第一个参数是我们用glGetUniformLocation函数得到的uniform变量索引值。

下面我们看下VS中的代码变化(注意:FS和上篇教程中一致,没有变化)。

uniform float gScale;

首先在shader中声明该uniform类型变量。

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

我们用uniform变量gScale,改变顶点的x、y值,这样每帧中x、y坐标值都不同,从而实现动画的效果。

程序运行后效果如下:

image

相关文章
高级OPENGL, 利用uniform块接口
高级OPENGL, 利用uniform块接口
高级OPENGL, 利用uniform块接口
|
小程序 知识图谱 异构计算
|
Kotlin
嵌入式实践教程--OpenGL3.0 Shader使用
嵌入式实践教程--OpenGL3.0 Shader使用
|
存储 索引
OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形 下
OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形
OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形 下
|
存储 C语言 C++
OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形 上
OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形
OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形 上
|
存储 缓存 并行计算
使用计算着色器(Compute Shader)模拟粒子效果【OpenGL】【GLSL】
使用计算着色器(Compute Shader)模拟粒子效果【OpenGL】【GLSL】
924 0
使用计算着色器(Compute Shader)模拟粒子效果【OpenGL】【GLSL】
|
存储 编译器 API
OpenGL ES Shader相关API 总结【4】—— GLSL 语法小结【持续更新】
OpenGL ES Shader相关API 总结【4】—— GLSL 语法小结【持续更新】
312 0
OpenGL ES Shader相关API 总结【4】—— GLSL 语法小结【持续更新】
|
API 索引
OpenGL ES Shader相关API 总结【2】——执行绘制命令
OpenGL ES Shader相关API 总结【2】——执行绘制命令
131 0
OpenGL ES Shader相关API 总结【2】——执行绘制命令
|
C语言 异构计算
OpenGL shader 程序基础
Shader, 即着色器,是一种类C语法的程序,用于封装硬件相关部分的代码。与普通程序的区别在于 shader 是通过GPU来执行的。 需要给GPU而不是CPU写程序的原因是GPU在处理图形相关运算时远远快于CPU。 不同的 shader 程序在使用时编译成本机硬件支持的机器指令。
256 0