shadertoy入门教程

shadertoy入门

暑假想自学渲染,图形学基础并不扎实,打算开始边实践边学习!
在shadertoy看到了很多厉害的渲染画面,但自己都不知道从哪看起,在youtube上看了入门教程,做笔记如下:

本文参考如下:

参考视频https://www.youtube.com/watch?v=u5HAYVHsasc

参考文章

https://blog.csdn.net/candycat1992/article/details/44039077

https://blog.csdn.net/weixin_28710515/article/details/89784772

https://zhuanlan.zhihu.com/p/157758600

介绍

在这里插入图片描述

点击右下角的❓可以查看相关信息,包括一些可使用的函数、以及等等;

这个网上的所有shader都是GLSL的pixel shaders。那么什么是pixel shader呢?如果我们需要渲染一个刚好铺盖整个屏幕的全屏的方形平板,那么这个方形的fragment shader就是一个pixel shader。这是因为此时,每一个fragment对应了屏幕上的一个pixel。也因此,pixel shader的很多输入都是相同的。(摘自 https://blog.csdn.net/candycat1992/article/details/44039077

输入输出

fragCoord:屏幕输入位置坐标(x, y);

fragColor:对应坐标的像素颜色(r, g, b, a);

一些公共变量

uniform vec3      iResolution;           // 屏幕分辨率
uniform float     iGlobalTime;           // 当前渲染运行的时间
uniform float     iChannelTime[4];       // channel playback time (in seconds)
uniform vec3      iChannelResolution[4]; // channel resolution (in pixels)
uniform vec4      iMouse;                // 鼠标位置
uniform samplerXX iChannel0..3;          // input channel. XX = 2D/Cube
uniform vec4      iDate;                 // (year, month, day, time in seconds)
uniform float     iSampleRate;           // sound sample rate (i.e., 44100)

主函数样例说明:TODO

画一个圆

首先看一下uv坐标关于屏幕位置的变化规律

  • 令 fragColor = vec4(uv.x, 0, 0, 1.0); 可以得到如此的渐变图片,这是因为最左边uv.x = 0,而最右边uv.x = 1;所以屏幕颜色沿着x轴由(0, 0, 0)渐变到(1, 0, 0)。
    在这里插入图片描述

  • 将fragColor 改成 vec4(0, uv.y, 0, 1.0) 和 vec4(uv.x, uv.y, 0, 1.0)可以分别看到竖下来渐变的绿到黑,以及红绿渐变。

画一个椭圆

由此,我们得知uv坐标的变化规律(当然本来大概也知道),可以根据此画一个圆:距离圆心某个距离内的点为白色,外部的为黑色;而距离即为uv坐标到圆心坐标的向量长度

float drawCircle(vec2 uv, vec2 center, float radius)
{
    float c = length(uv - center);
    if(c > radius)
        return 0.;
    else
        return 1.;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord/iResolution.xy;

    float col = drawCircle(uv, vec2(0.5, 0.5), 0.4);

    // Output to screen
    fragColor = vec4(vec3(col), 1.0);
}

在这里插入图片描述

画一个圆

x、y的比例变化得到正圆

由于屏幕长宽不同,而归一化后的长宽范围又都在[0,1]之间,因此需要进行一个转化使得x,y的单位长度相同,以获得正圆。在主函数调用drawCircle前加入转化:

uv.x *= iResolution.x / iResolution.y;

此时画出的圆不在正中间,可以在本语句前加入uv-=.5;让原点在正中间。

边缘模糊

加上内置smoothstep函数可以使得边缘模糊

float drawCircle(vec2 uv, vec2 center, float radius, float blur)
{
    float c = length(uv - center);
    float res = smoothstep(radius, radius-blur, c);
    return res;
}

其中,smoothstep函数内部实现如下:

float smoothstep(float t1, float t2, float x) {
  x = clamp((x - t1) / (t2 - t1), 0.0, 1.0); 
  return x * x * (3 - 2 * x);
}

smoothstep可以用来生成0到1的平滑过渡值,它也叫平滑阶梯函数。其函数图像如下:

在这里插入图片描述

画多个圆

简单的图像叠加就能画出多个圆:因为(0,0,0)是黑色,而(1,1,1)是白色,因此颜色相加时能让黑色区域加白圆,相减时在白色区域加黑圆。

float drawCircle(vec2 uv, vec2 center, float radius, float blur)
{
    float c = length(uv - center);
    float res = smoothstep(radius, radius-blur, c);
    return res;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;
    
    uv -= .5;
    uv.x *= iResolution.x / iResolution.y;

    float col = drawCircle(uv, vec2(0, 0), 0.4, 0.01);
    
    col += drawCircle(uv, vec2(0.5, 0), 0.1, 0.02);
    
    col -= drawCircle(uv, vec2(0, -0.2), 0.2, 0.03);

    // Output to screen
    fragColor = vec4(vec3(col), 1.0);
}

在这里插入图片描述

*乘的操作也可以得到别的结果,也可以试试。

画一个笑脸:)

通过圆环的叠加、上色等等操作就能画上一个笑脸啦。

在这里插入图片描述

float drawCircle(vec2 uv, vec2 center, float radius, float blur)
{
    float c = length(uv - center);
    float res = smoothstep(radius, radius-blur, c);
    return res;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;
    
    uv -= .5;
    uv.x *= iResolution.x / iResolution.y;

    float mask = drawCircle(uv, vec2(0.), .4, .05);
    
    //draw eyes
    mask -= drawCircle(uv, vec2(-.12, .155), .07, .02);
    mask -= drawCircle(uv, vec2(.12, .155), .07, .02);
    
    //draw mouth
    float mouth = drawCircle(uv, vec2(0., 0.), .3, .02);
    mouth -= drawCircle(uv, vec2(0., .1), .3, .02);
    
    mask -= mouth;
    
    //color the face
    vec3 col = vec3(1., 1., 0) * mask;
    
    fragColor = vec4(col, 1.0);
}
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值