OpenGL Shader-SDF对形状组合效果

1,103 阅读2分钟

「这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战

前言

之前学习了如何使用SDF绘制形状图像,像是圆形方形等。接下来继续通过SDF操作将形状图像组合在一起创建更复杂更有趣的形状。

像是原来使用SDF实现了同时绘制圆形和方形,但其实除此之外还能使用SDF来完成更多“组合”。

image.png

下面来介绍使用SDF实现其他操作,还是使用圆形和方形作为参考例子。开始前依旧使用之前绘制形状的SDF代码。

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;
}

float sdfSquare(vec2 uv, float size, vec2 offset) {
  float x = uv.x - offset.x;
  float y = uv.y - offset.y;
  return max(abs(x), abs(y)) - size;
}

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.));
    // 方形
    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);
}

SDF组合操作

合并

合并就是将两个形状组合在一起。

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.));
    // 方形
    float square = sdfSquare(center, 0.1, vec2(0.1,0.));

    float res; 
    res = min(circle, square);
    res = step(0., res); 
    //混合结果   
    vec3 col = mix(vec3(0., 0., 1.),background,res);
    gl_FragColor = vec4(col,1.0);
}

相交

相交只取圆形和方形相交的部分

res = max(circle, square);
res = step(0., res); 
//混合结果   
vec3 col = mix(vec3(0., 0., 1.),background,res);
gl_FragColor = vec4(col,1.0);

image.png

非相交

以方形为目标的非相交是和圆形非相交的部分

res = max(-circle, square);
res = step(0., res); 
//混合结果   
vec3 col = mix(vec3(0., 0., 1.),background,res);
gl_FragColor = vec4(col,1.0);

image.png

以圆形形为目标的非相交是和方形非相交的部分

res = max(circle, -square);
res = step(0., res); 
//混合结果   
vec3 col = mix(vec3(0., 0., 1.),background,res);
gl_FragColor = vec4(col,1.0);

image.png

异或

异或组合是取圆形和方形两者互不相交的部分

res = max(min(circle, square), -max(circle, square));
res = step(0., res); 
//混合结果   
vec3 col = mix(vec3(0., 0., 1.),background,res);
gl_FragColor = vec4(col,1.0);

image.png