这是GLSL shader系列第一篇文章,本文学习目标:
- 安装编辑工具
- 编写hello world程序
安装插件
我使用VSCode编写shader代码,在VSCode上有两个好用的插件需要先装一下:
- Shader languages support for VS Code
- glsl-canvas:主要用于在VSCode中对着色器的效果进行预览
2 Hello World!
新建一个helloworld.frag
文件,在其中编写如下代码:
#ifdef GL_ES
precision mediump float;
#endif
void main() {
gl_FragColor=vec4(1.,0.,0.,1.0);
}
然后在VSCode中按下Ctrl+Shift+P
,输入Show glslCanvas
后即可在屏幕中看到预览效果,一张全红的图片。至此,恭喜你已经完成了Hello world程序的编写,是不是非常简单?下面对代码做个介绍。
#ifdef GL_ES
precision mediump float;
#endif
在前3行检查了是否定义了GL_ES,这通常在移动端或浏览器下会定义,第2行指定了浮点数float的精度为中等,也可以指定为低精度lowp
或高精度highp
,精度越低执行速度越快,但质量会降低。你甚至可以直接将这段代码删除,程序仍能正常运行。
void main() {
gl_FragColor=vec4(1.,0.,0.,1.0);
}
这是着色器的主要代码,看到main()
函数你就应该知道,这也是程序的入口。在函数内部给gl_FragColor
变量进行赋值,gl_FragColor
是GLSL内置的变量,用输出最终的颜色。vec4
是一种数据类型,其中分别存储RGB和透明度数据,取值范围均为0~1之间。注意,vec4里面的数值都是浮点类型的。
3 再进一步
前面的示例程序太简单了,这次我们加点难度,看如下代码:
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
void main() {
vec2 st = gl_FragCoord.xy/u_resolution;
gl_FragColor=vec4(st.x,st.y,0.,1.0);
}
这段代码的执行结果有趣了起来,屏幕中出现了这样的图像:
这是怎么回事呢?
首先来看uniform vec2 u_resolution;
指定了着色器接受的入参:类型为vec2
的u_resolution
,其中存储了画布的宽高。
再介绍一下gl_FragCoord
,这是片元着色器中定义好的值,存储片段(像素)点的坐标x
和y
的值,因此使用这两个值就能够知道当前着色器计算的是画布上哪个位置的颜色。
因此st
中存储的值,相当于将像素点的横坐标和纵坐标做了归一化处理,左下角是直角坐标系的原点(0, 0)
, 右下角坐标是(1,0)
,左上角的坐标是0,1
,因此这三个点相对应的rgba值就分别为rbga(0,0,0,0)
,(1,0,0,0)
和(0,1,0,0)
,即对应黑色、红色和绿色,其余像素点的取值是中间值。到这里,你是否明白其中的原理了呢?
4 更上一层楼
接下来玩点更有意思的:
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform float u_time;
void main() {
vec2 st = gl_FragCoord.xy/u_resolution;
gl_FragColor=vec4(st.x,st.y,sin(u_time),1.0);
}
uniform float u_time
是传入的时间,能够不断递增,这一次我们将gl_FragColor
中的蓝色通道的值改为sin(u_time)
,这样随着时间的变化,每个像素点的蓝色通道的取值就会在0-1之间变换,让图片动起来。