简体   繁体   中英

How to create a proper rounded rectangle in WebGL?

I have tried to implement the answer from this question but there seems to be a bit of a problem. If you open their ShaderToys and try changing the border radius, the size (width and height) of the rounded rectangle change as well.

I'm looking for a solution like this shadertoy where changing the border radius doesn't change the size of the shape. Unfortunately in this shader toy, it's a filled in rounded rectangle.

Is it possible to have a non-filled in rounded rectangle (so, only the border), but also have it such that if you change the border radius that the shape doesn't grow or shrink size?

I'm looking to implement a similar effect to CSS where you can specify the border-radius of a div and it only changes the border's radius without also changing the size of the shape.

Here's an image demonstrating the problem. The left result was with boxRounding set to 0.5 and the right result was with boxRounding set to 0.20 . Notice how they're a much different size. Is there any way to make both shapes the same size, but just with a different border radius?

在此处输入图像描述

For a rectangular outline you have to compute the absolut value of the fragment to the outline:

float smoothedAlpha = 
    1.0 - smoothstep(-edgeSoftness, edgeSoftness, abs(distance) - thickness);

Complete shadertoy shader ( 2D rounded rectangular outline ):

// from http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
float roundedBoxSDF(vec2 CenterPosition, vec2 Size, float Radius)
{
    return length(max(abs(CenterPosition)-Size+Radius,0.0))-Radius;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    vec2  size           = vec2(300.0, 200.0);
    vec2  location       = iMouse.xy;
    float thickness      = 5.0;
    float shadowSoftness = 30.0f;
    vec2  shadowOffset   = vec2(10.0, -10.0);
    float edgeSoftness   = 1.0;
    float radius         = (sin(iTime*2.0) + 1.0) * 30.0 + thickness * 2.0;
    
    float distance       = roundedBoxSDF(location - fragCoord.xy, size/2.0, radius);
    float smoothedAlpha  = 1.0 - smoothstep(-edgeSoftness, edgeSoftness, abs(distance) - thickness);
    vec4  quadColor      = mix(vec4(1.0), vec4(0.0, 0.2, 1.0, smoothedAlpha), smoothedAlpha);
    
    float shadowDistance = roundedBoxSDF(location + shadowOffset - fragCoord.xy, size/2.0, radius);
    float shadowAlpha    = 1.0 - smoothstep(-shadowSoftness/2.0, shadowSoftness/2.0, abs(shadowDistance));
    vec4 shadowColor     = vec4(0.4, 0.4, 0.4, 1.0);
    fragColor            = mix(quadColor, shadowColor, shadowAlpha - smoothedAlpha);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM