前言

了解过如何绘制形状方法,在此之前也只介绍单个形状绘制,没有使用多个形状综合绘制。这里继续介绍绘制多种形状综合绘制的方法,一种能够方便结合多个形状绘制的方法形式。

再识MIX函数

mix函数之前有所了解作为混合功能对于后续形状渲染场景中有重要作用。mix函数是在两个值之间线性插值。在之前使用最广泛的应用场景就是两个纹理混合以及滤镜等效果,但其实mix函数也能作为渐变函数来使用。

如下代码中使用mix函数获取到x轴每个像素插值得到一个从[0,1]的渐变过程,成像上就是从黑色向着白色过渡的效果了。

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    float interpolatedValue = mix(0., 1., uv.x);
    vec3 col = vec3(interpolatedValue);
    gl_FragColor = vec4(col,1.0);
}

可以利用mix函数渐变形式来创建颜色渐变效果就能定制DIY专属背景色了。

vec3 getBackgroundColor(vec2 uv) {
    vec3 gradientStartColor = vec3(1.0, 0.0, 0.0);
    vec3 gradientEndColor = vec3(0., 0., 1.);
    return mix(gradientStartColor, gradientEndColor, uv.y); 
}

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    gl_FragColor = vec4(getBackgroundColor(uv),1.0);
}

mix函数入参是向量对象时将坐标作为分量基础对每个向量进行插值。

多种形状同时绘制

接下来介绍如何使用2D SDF绘制形状,例如圆形和方形。在此之前绘制形状函数都是以vec3向量返回。但是采用SDF形式返回是一个浮点数。SDF(signed distance fields)意思是有符号距离场,因此返回值是一个浮点数类型的距离。尤其是在2D SDF当中返回值通常是0或者1表示距离是在形状内部还是外部。

一般而言距离位置是相对某一个点来决定的,通常是形状的中心点位置。在之前绘制形状中介绍过当距离大于0表示该距离在圆外,若距离刚好等于距离则表示距离正好在圆的边缘上。

原先采用绘制圆函数方法如下:

vec3 sdfCircle(vec2 uv,float r){
    float d = length(uv) - r;
    return d > 0. ? vec3(1.) : vec3(0., 0., 1.); // 大于0超出画圆范围,小于0在画圆范围内
}

但是该方法存在一个问题就是绘制圆时必须定义个一个绘制圆的颜色和外部颜色。但对于开发者来说这样的方法似乎过于局限,若是能够将绘制外部颜色和形状颜色互相独立解耦化才是理想方法。这样也就能够在绘制场景中绘制不同颜色的形状和不同颜色的背景了。

vec3 getBackgroundColor(vec2 uv) {
    vec3 gradientStartColor = vec3(1.0, 0.0, 0.0);
    vec3 gradientEndColor = vec3(0., 0., 1.);
    return mix(gradientStartColor, gradientEndColor, uv.y); 
}

float sdfCircle(vec2 uv, float r, vec2 offset) {
  float x = uv.x - offset.x;
  float y = uv.y - offset.y;
  return length(vec2(x, y)) - r;
}

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    vec2 center = uv;
    center -= 0.5; 
    center.x *= iResolution.x/iResolution.y;
    // 背景
    vec3 background = getBackgroundColor(uv);
    // 圆
    float circle = sdfCircle(center, 0.1, vec2(0.));
    //混合结果   
    vec3 col = mix(vec3(0., 0., 1.),background, step(0., circle));
    gl_FragColor = vec4(col,1.0);
}

图片.png

从效果上可以看到实现了背景和形状绘制以及颜色绘制分离,在mix函数中vec3(0., 0., 1.)作为圆形的颜色,step函数判断是否在圆内。

// 方形
float square = sdfSquare(center, 0.1, vec2(0.2));
//混合结果   
vec3 col = mix(vec3(0., 0., 1.),background, step(0., circle));
col = mix(vec3(1, 0, 0), col, step(0., square));
gl_FragColor = vec4(col,1.0);

然后再新增方形绘制方法,在原先mix函数下再次mix一个方形就能够实现多个图像混合了。

总结

在此就学习到了如何使用mix函数实现渐变色效果,同时利用mix以及SDF方法实现了多种形状同时绘制的能力。当然形状图像还有其他许多例如星星爱心等都是可以去通过SDF形式实现完成的。