zoukankan      html  css  js  c++  java
  • opengl 教程(5) shader(2) uniform变量

          原帖地址: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

  • 相关阅读:
    字符串替换
    字符串查找
    字符串比较
    字节与字符串相互转换
    1365. How Many Numbers Are Smaller Than the Current Number
    1486. XOR Operation in an Array
    1431. Kids With the Greatest Number of Candies
    1470. Shuffle the Array
    1480. Running Sum of 1d Array
    【STM32H7教程】第56章 STM32H7的DMA2D应用之刷色块,位图和Alpha混合
  • 原文地址:https://www.cnblogs.com/mikewolf2002/p/2743118.html
Copyright © 2011-2022 走看看