Shader 魔法的学习之路 – Hello World!(2)

内容纲要

这次我们来初步尝试下 shader 编程,由于 shader 编程在不同平台的编写形式不同,根据语法分为 glsl 和 hlsl,根据引擎分为:opengl、webgl、directx 和其他我不知道的引擎,一些游戏引擎又会针对 shader 做一些封装:Unity、UE、Godot。

这系列的教程不会详细讲不同平台的区别,虽然不同平台的函数、变量甚至语法可能都有差异,不过思路是共通的,本系列的代码均使用 webgl,而且为了方便快速体验 shader 编程,我们会在一个封装好的平台 https://www.shadertoy.com/ 上去写代码,如果你已经有熟悉的平台,例如 Unity,可以自己根据文中代码进行实践。

先来个 Hello World?不,我直接蓝屏!

对于 shader 编程来说,画个 hello world 还挺麻烦的,所以我们直接先画个蓝屏吧!

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    fragColor = vec4(0.0, 0.0, 1.0 ,1.0);
}

一句核心代码就实现了蓝屏,我们逐步看下上面的代码写的是什么意思。

首先我们定义了一个叫 mainImage 的函数,由于 shadertoy 做了一些封装,其实这个和传统的 shader 编程稍微有点不同。传统的 shader 编程这个函数应该叫 fragment,也被叫为 fragment shader ,也没有接受入参和出参。这个函数可以认为是系统给我们的钩子函数,绘制每个像素时都会调用这个函数,具体的执行时机由系统决定。

然后就是一句核心代码 fragColor = vec4(0.0, 0.0, 1.0 ,1.0)fragColor 是 webgl 的内置变量,表示当前像素的颜色。

后面的 vec4(0.0, 0.0, 1.0, 1.0)vec4 可以先看作是一个存了四个值的数据结构,变体还有 vec3vec2,里面的值类型都是 float(浮点数),vec3 存的就是三个值,以此类推。

我们给 vec4 设置的值是 (0.0, 0.0, 1.0, 1.0),因为这个值是赋给 fragColor 的,那这个值就表示的是颜色值,颜色值用 rgba 表示,所以这个值的意思是红色、绿色的值都为 0,蓝色和 alpha 值为 1.0,所以最终展现了蓝色。

再来个黄屏!

那如果我想要表现的是黄色,那要怎么做呢?根据颜色混合的原理,黄色=红色+绿色,所以我们这样设置:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    fragColor = vec4(1.0, 1.0, 0.0 ,1.0);
}

一个像《赛博朋克2077》跳票通知的东西就出来啦!

这篇文章的内容目前为止没讲太多东西,主要是先让大家熟悉一下,接下来就开始正式地绘制一些常规的图案了。

本次文章的作业是,让屏幕显示出呼伦贝尔大草原的颜色。

留下评论