01-第一段shaderToy代码.glsl

准备好了环境以后(未安装请移步https://www.jianshu.com/p/fdf87797e5ba),新建一个文件名为01-第一段shaderToy代码.glsl,并用vscode工具打开,输入如下代码

//他是一个内置的函数,函数名是固定的,不能修改
//iTime是一个内置的全局变量,表示时间,是一个float类型的变量,表示从程序开始运行到当前时间的秒数

vec2 ClipCoord(in vec2 fragCoord) {
    //偏移归一化坐标

    //fragCoord是片元坐标,iResolution.xy是屏幕分辨率,
    //这里fragCoord / iResolution.xy是将屏幕坐标转换为[0,1]的归一化坐标
    //然后减去0.5,是将坐标系原点从左上角移动到中心
    //为什么能够减去0.5呢?因为归一化坐标是[0,1],所以坐标系的中心是0.5
    //但是为什么iResolution.xy可以减去0.5,因为xy是vec2类型,是一个二维向量,所以可以直接减去0.5
    //向量减去一个数,是将向量的每个分量都减去这个数,
    //最终返回的是一个以中心为原点的归一化坐标
  return 2. * (fragCoord / iResolution.xy - 0.5);
}

// vec2 ClipCoord2(in vec2 fragCoord) {
//     //偏移归一化坐标
//   return 2. * (fragCoord - 0.5 * iResolution.xy) / iResolution.x;
// }

struct bg_color {
  vec3 color;
  float time;
};

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
  //片元着色器代码,入参为片元坐标,出参为片元颜色

  //bg_color是一个结构体,包含了一个vec3类型的color和一个float类型的time
  //这里bg是一个bg_color类型的变量,初始化了一个vec3类型的颜色和一个时间
  bg_color bg = bg_color(vec3(1., 1.0, 0.0), iTime);

  vec2 uv = ClipCoord(fragCoord);
  // vec2 uv = ClipCoord2(fragCoord);
  //length函数是一个内置函数,用来计算向量的长度,这里是计算uv向量的长度
  float coordlen = length(uv);
  float iTimeYS = bg.time - floor(bg.time);
  //先来一个纯色背景
  fragColor = vec4(bg.color, 1);

  // //如何在shader toy中取余数呢:iTime % 1.0这样是不对的,因为不支持这样的写法,正确的写法是iTime - floor(iTime)
  // //这里的iTimeYS会突然变成0,这样会导致颜色跳动,所以我们需要他是一个0-1然后再1-0的过程
  // //这样的话,颜色就会平滑的变化
  // //我们可以通过cos函数来实现这样的效果,iTimeYS是一个0-1的过程,cos(iTimeYS * 3.1415926)是一个1-0-1的过程
  // fragColor = vec4(cos(bg.time), bg.color.y, 1. - cos(bg.time), 1);
  // //如果长度小于0.5(相当于以屏幕中心为原点,半径在0.5以内),那么将颜色设置为红色
  if(coordlen <= 0.5) {
    fragColor = vec4(coordlen * 2., 1, 1, 1);
  }
  // fragColor = vec4(coordlen, 0, 0, 1);
}


保存代码,右键Shader Toy:Show GLSL Preview你将会看到如下界面:


image.png

接下来,我们将一行行的解释代码,以便于新手了解我们的程序如何运作:

首先shader toy提供一个入口函数mainImage,和一个内置变量iTime:
mainImage是片元着色器代码的函数名(这个名称不能改变,shader toy会调用这个函数,如果你改了就找不到了),入参为片元坐标,出参为片元颜色
iTime是浮点数时间,从程序运行开始计数,单位为秒

1.我们新建一个ClipCoord函数

为何先要新建函数呢?因为这里没有变量提升的概念,我们要用之前都需要先新建好。
ClipCoord函数的意义是偏移并归一化坐标,它把以左上角为原点的屏幕坐标系,转化为以屏幕中心为原点的归一化坐标系,”fragCoord / iResolution.xy“ 是归一化屏幕坐标,归一化以后再”-0.5“是为了再XY轴上偏移一半的距离,这样原点就由左上角移动到了中心,但是为了不让单条轴的范围是(-0.5,0.5),我们给他乘以2(这里可以理解为缩放),让它变成(-1,1)这样方便我们观察,也能缓解强迫症

2.新建一个构造体bg_color

入参为vec3初始背景色,外加一个时间参数(为了后续做动画使用),这个构造体仅仅只是为了把需要用到的参数集中管理,实际上不用构造体,仅用普通的变量也可以实现

3.新建一个mainImage函数(该函数名称不能修改,它是shader toy内置入口函数)

函数内依次:
创建背景构造体,


image.png

获取半径(后续用于判断图像范围)


image.png

给背景赋值背景色(给整个画布绘制颜色)


image.png

判断圆形范围(处于半径内的任何片元都是圆形区域)


image.png

在圆形区域内用圆的颜色覆盖背景色(由于之前已经绘制过背景色,此时的绘制实际上相当于在背景色之上覆盖圆形的颜色)


image.png

大工告成,代码重还有一些通过时间变量来改变颜色的代码段,可以让图像动起来,各位可以自行研究


image.png
总结:

背景和圆形都是通过计算的每一个片元的颜色来绘制的,片元着色器的意义就是根据你给定的逻辑给屏幕上色,而在编写逻辑的时候常常运用到一些数学知识比如绘制圆和三角函数计算,不过不用担心只要有高中数学水平就能够实现大部分的效果

要点:

1.浮点数必须和浮点数计算,所以代码中有“1.”、“.5”这样的写法
2.没有变量提升,要使用的变量与函数都需要提前声明
3.要认识shader toy的内置函数和内置变量

留下两个问题:

1.为什么绘制的圆有一些拉伸变形?
2.为什么下面这个计算公式的对象有xy两个值却能直接减去0.5?fragCoord / iResolution.xy - 0.5

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。