当前位置:网站首页>Shadertoy基础教学01、画圆(smoothstep()函数讲解)

Shadertoy基础教学01、画圆(smoothstep()函数讲解)

2022-06-23 03:52:00 宗浩多捞

1、原教学视频链接
2、Shadertoy网址链接


在这个网站上进行像素着色器代码的编辑,有两点需要了解:

  • 像素着色器的输入如下图所示,这些属性我们可以直接使用
    在这里插入图片描述
  • 函数void mainImage(out vec4 fragColor, in vec2 fragCoord)
    • out vec4 fragColor :当前像素输出的颜色值
    • in vec2 fragCoord:当前像素的屏幕空间中的x,y坐标

1 画圆

1.1 基础讲解

首先,我们把屏幕空间的坐标映射到纹理坐标空间[0,1]。可以通过除以视口分辨率来实现

    vec2 uv = fragCoord/iResolution.xy;	

为了方便,可以选择把坐标系原点(0,0)移动到屏幕正中心

	uv -= vec2(0.5, 0.5);

我们的视口一般不会是正方形,比如800x600这种分辨率,因此x轴的像素数量是比y轴要多200个的,而我们的x,y坐标取值范围都在[0,1],这就会导致对每个像素而言,x轴上的长度要比y轴上的更小所以:在竖轴上,(0,0)到(0,3)有3个像素,而横轴上的(0,0)到(3,0)有4个像素。 在这种情况下直接画圆,得到的会是椭圆,因为最终显示器上的像素都是 正方形的 。竖轴上3个像素,横轴上4个像素,必然得到一个椭圆

在这里插入图片描述在这里插入图片描述
因此,需要把纹理空间的像素们也变成正方形的,很明显我们每个像素的水平长度即宽度是不够的,因此要把纹理坐标的x分量乘以视口宽高比

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

1.2 smoothstep()内置函数的使用(可选)

让圆的边界更平滑,原理就不讲咯,很简单,可以参考这篇文章。我没搜它的源码,但是它的伪代码长下面这样。

它与超级常见的clamp()的唯二区别就是

  • 边界外的不直接返回边界值,而是0 、1
  • 边界内的值不直接范围t自身,而是稍微操作一下,让曲线更平滑
float smoothstep(float t1, float t2, float t)
{
    
	// 分支中相等的情况没写,无所谓的,放哪个区间都可以
	if (t1 < t2)
	{
    
		if (t < t1)
			return 0;
		else if (t > t1 && t < t2)
			return f(t);	
		else if (t > t2)
			return 1;
	}
	if (t1 > t2)
	{
    
		if (t < t1)
			return 1;
		else if (t > t1 && t < t2)
			return f(t);	
		else if (t > t2)
			return 0;
	}
	if (t1 == t2)
	{
    
		if (t < t1)
			return 0;
		else
			return 1;
	}
	
}

1.3 完整代码

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    
    vec2 uv = fragCoord/iResolution.xy;		
    
    uv -= 0.5;     // 左下角(-0.5,-0.5),右上角(0.5,0.5)
    uv.x *= iResolution.x / iResolution.y; // 让像素变成正方形, 区间也变了,懒得算了哈,明显的x轴的上区间上限更大了
    
    float d = length(uv);
    float r = 0.3;
    if (d > r) 
    	c = 1.0; 
    else 
    	c = 0.0;
    fragColor = vec4(vec3(c), 1.0);
}

结果图,有锯齿
在这里插入图片描述


如果采用smoothstep()平滑过度一下

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    
    vec2 uv = fragCoord/iResolution.xy;// [0,1]
    
    uv -= 0.5;// [-0.5,0.5]
    uv.x *= iResolution.x / iResolution.y; // 让像素变成正方形
    
    float d = length(uv);
    float r = 0.3;
    float c = smoothstep(r, r + .2, d);

    fragColor = vec4(vec3(c), 1.);
}

是不是很滑
在这里插入图片描述

如果更改一下参数,还可以实现更模糊的效果
在这里插入图片描述

原网站

版权声明
本文为[宗浩多捞]所创,转载请带上原文链接,感谢
https://blog.csdn.net/Motarookie/article/details/125409098