2D SDF推导1: 基础和Circle

534 阅读4分钟

image.png

计算机绘图

19世纪末欧洲绘画出现一个流派,名为点彩派(Pointillism),这种风格强调了画面色彩的分离,以小点的形式将纯粹的颜色应用于画布上,它们在视觉混合下产生了详尽的色调。 image.png 这种流派的作画方式就是计算机绘画的方式。屏幕由像素点组成,点可以用一个坐标(x,y)(x,y)表示,例如这个点距离屏幕的上边缘有几个像素,距离屏幕的左边缘有几个像素。 在计算机绘图中,这个坐标出于习惯的原因一般用(u,v)(u,v)来表示。 每个点可以显示不同的颜色。 红,绿,蓝的不同比例可以组合出任意颜色,所以任何一个颜色可以用(r,g,b)(r,g,b)来表示。所以如果我们要让计算机画一个图形,就要告诉计算机在哪一个位置画一个什么颜色。 所谓的图形程序就是一个函数color=f(position)color=f(position), 位置(u,v)(u,v)是自标量,颜色(r,g,b)(r,g,b)是因变量

语言与工具

工程师通过不同的编程语言和计算机沟通,让计算机处理工作。不同编程语言的文本就是程序, Shader就是一种告诉计算机如何画图的程序,它的所有功能就是给计算机讲清楚color=f(position)color=f(position)这个函数是什么。 shader是运行在图形处理单元(GPU)上的,负责渲染图形和特效。shader主要用于计算机图形的光照、阴影、颜色等效果,它们是现代图形渲染管线中不可或缺的一部分。随着图形处理硬件的发展,着色器已经变得越来越强大,允许开发者实现复杂和现实的视觉效果。 ShaderToy 是一个Shader在线平台,专为图形编程爱好者、艺术家和开发者设计。它允许用户创建、共享和学习着色器(Shader),ShaderToy 提供了一个独特的环境,可以在线写Shader,并实时查看其图形效果。这对于学习图形编程、实验新的视觉效果以及探索数学和算法在视觉艺术中的应用非常有用。 GeoGebra 是一个多功能的数学软件,专门针对学习和教学数学而设计,从初中数学到大学级别的内容均有涵盖。它结合了几何学、代数、表格、图形绘制、统计和微积分等多种数学功能。 以上就是我整个探索过程中用到的所有工具GLSL一种Shader语言,我将在在ShaderToy写GLSL, 用Geobebra来理解Shader. 下图为GeoGebra表示显示屏image.png

画一个长方形

假如要画一个长方形,如何表示color=f(position)color=f(position)呢?这个长方形以坐标系原点为中心点,Length=1.2Length=1.2image.png 一个很朴素的想法就是,当x在[-0.4, 0.4]且y在[-0.6, 0.6]就把颜色画成黑色,其他都化成白色。 尝试讲这个想法变成一个函数。

# current poisition
position = [x, y]

# draw function
if -0.6 < position.x < 0.6 and -0.4 < position.y < 0.4:
    draw(black)
else
    draw(white)

而变成Shader也非常类似

#define WHITE vec3(1.0)
#define BLACK vec3(0.0)



void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	
    // convert screen to [-1, 1] coordinate
    vec2 point = (2.0*fragCoord-iResolution.xy)/iResolution.y;
    
    
    if ( point.x < 0.6 && 
         point.x > -0.6 && 
         point.y < 0.4 && 
         point.y > -0.4) {
         
        fragColor = vec4(BLACK,1.0);
        
    } else {
    
        fragColor = vec4(WHITE, 1.0);
    }
     
    
}

image.png

画一个圆

假如要画一个圆形,如何表示color=f(position)color=f(position)呢?这个圆以坐标系原点为中心点,radius=0.5radius=0.5 一个很朴素的想法就是, 当 position 距离中心点< 0.5就画黑色,否则画白色 image.pngimage.png

# current poisition
position = [x, y]
center = [0, 0]
distance = distance(position, center)

# draw function
if distance < 0.5:
    draw(BLACK)
else:
    draw(WHITE)

而变成Shader也非常类似

距离边缘 SDF

上一部分求的距离是距离中心的距离, 假如距离变成了求圆的边缘呢

image.pngimage.png 如果我们用距边缘的距离作为颜色,越靠近边缘越黑。可以得到上面一张图


    float radius = 0.8;
    float dist = abs(length(point) - radius);
    
    float grayColor = floor(dist * 20.0) / 20.0;
    fragColor = vec4(vec3(grayColor), 0.);

这就引出本文标题的概念。2D SDF(Signed Distance Field)指的是二维有符号距离场。SDF 是计算几何的一个技术,用来表示一个形状或场景中点与表面之间的最短距离,其中 "有符号" 指距离可以是正数或负数。正数表明点在形状的外部,负数表明点在形状的内部,而零通常指在形状的边界上。 SDF 是定义在二维空间中每一点上的函数,常被用来快速和容易地表示复杂的形状和场景,特别是在图形学和物理模拟中。在二维空间中,SDF 可以描述线条、曲线、多边形等的边缘和内外部。 SDF 有以下优点

  • 简化运算:使用 SDF 可以使碰撞检测、光线投射和形状合并变得简单。
  • 渲染效率:在图形渲染中,SDF 可用于快速渲染高质量的平滑边缘,特别是在文本渲染和矢量图形上。
  • 容易变形和联合:SDF 很容易实现形状变形以及不同形状之间的布尔运算(如交集、并集和差集)