教程地址
【中文版】高级GLSL
【英文版】Advanced GLSL
学习记录
GLSL ,OpenGL Shading Language 。我们之前的代码中用了不少,但都是很短的代码,不管是顶点着色器或者是片段着色器都是简单的几行,我们对其了解也很少,这篇文章中就专门介绍 GLSL 。我们将会讨论一些有趣的内建变量(Built-in Variable),管理着色器输入和输出的新方式以及一个叫做Uniform缓冲对象(Uniform Buffer Object)的有用工具。
所谓内建变量,其实就是着色器已经给我们定义好的变量,比如 gl_Position ,这个我们所有顶点着色器都使用过的变量,他定义输出了顶点的位置。
除了 gl_Position 外,GLSL 内建了很多其他变量,比如 gl_PointSize ,他允许我们修改每一个点的大小,当我们使用 GL_POINTS 为图元进行绘制时可以使用。
gl_PointSize 的使用比较简单,当在 OpenGL 中启用 gl_PontSize 之后,我们直接在顶点着色器里调用就是了。(此时我们需要将 glDrawArrays() 的绘制参数改为 GL_POINTS)
1 |
|
在这里我们将其设置为顶点 z 轴(深度)的十倍,这样有一种越靠近我们顶点越大的感觉。
顶点着色器中还有一个内建变量 gl_VertexID ,用来访问我们当前所绘制的顶点的索引,当使用索引绘制时,即 glDrawElements 时他会存储当前索引,当使用 glDrawArrays 绘制时会存储当前已渲染的图元个数。这个变量可以被我们使用已做出一些有趣的效果,用刚才绘制的点的代码来示例,我们可以使每一个的颜色不同。
在顶点着色器中,我们使用 gl_VertexID 去设置一个到片段着色器的 vec4 变量,并在片段着色器中进行渲染。
1 |
|
1 |
|
由于顶点 ID 不同,所以亮度不同,效果如下:
前两个是顶点着色器的内建变量,现在我们来看下片段着色器中的变量 gl_FragCoord ,gl_FragCoord 的 x 和 y 分量分别是屏幕的 x , y 坐标,z 则是深度变量,相当于 z 轴。以此,我们可以通过这个变量去对模型在屏幕的各个部位进行不同的着色,或者去实现其他有趣的效果。
我们将顶点分别放在屏幕中心两侧(x 轴0点两侧),并且略微调大了 gl_PointSize 使得等下效果更加显著。现在,我们在片段着色器里进行修改。
1 |
|
由于我们的屏幕 width 值为1920,所以960正好是一半,这样我们将凡是在屏幕 x 轴左边的全部渲染为白色,右边则是刚才的颜色。效果如下:
可以看到,即便是一个点,只要依旧可以进行不同的着色。
接下来一个是 gl_FrontFacing 变量,这是一个布尔值变量,他告诉了我们当前的片段属于正面还是背面,以此我们也可以进行着色,例如对箱子外部和内部渲染不同的纹理等。(由于我这里代码只有点的,这个就不演示了)用法也极为简单:
1 |
|
另外一个变量 gl_FragDepth 允许我们在片段着色器里修改深度值,然而,由我们自己设置深度值有一个很大的缺点,只要我们在片段着色器中对gl_FragDepth进行写入,OpenGL就会(像深度测试小节中讨论的那样)禁用所有的提前深度测试(Early Depth Testing)。它被禁用的原因是,OpenGL无法在片段着色器运行之前得知片段将拥有的深度值,因为片段着色器可能会完全修改这个深度值。在写入gl_FragDepth时,你就需要考虑到它所带来的性能影响。