graphics3ddirectxhlslpixel-shader

How to correct this HLSL pixel shader to round corners of a quad?


I'd like the make an HLSL pixel shader that can round the corners of a quad. I attempted to port this GLSL example the following way:

cbuffer CBuf : register(b0)
{
    float4 color;
    float2 dimensions;
    float radius;
    float na;
};

struct VSOut
{
    float4 pos    : SV_POSITION;
    float2 uv     : UV;
    uint   viewId : SV_RenderTargetArrayIndex;
};

float4 main(VSOut input) : SV_TARGET
{
    float2 coords = input.uv * dimensions;
    if 
    (
        length(coords)                           < radius ||
        length(coords - float2(0, dimensions.y)) < radius ||
        length(coords - float2(dimensions.x, 0)) < radius ||
        length(coords - dimensions)              < radius
    )
    {
        discard;
    }
    
    return color;
}

What I end up with is this: But I'm looking for more of a rounded rectangle shape. enter image description here


Solution

  • That shader is wrong and probably untested since it also has syntax errors. Something like this should do the trick:

    bool ShouldDiscard(float2 coords, float2 dimensions, float radius)
    {
            float2 circle_center = float2(radius, radius);
    
            if(length(coords - circle_center) > radius 
            && coords.x < circle_center.x && coords.y < circle_center.y) return true; //first circle
            
            circle_center.x += dimensions.x - 2*radius;
            
            if(length(coords - circle_center) > radius 
            && coords.x > circle_center.x && coords.y < circle_center.y) return true; //second circle
            
            circle_center.y += dimensions.y - 2*radius;
        
            if(length(coords - circle_center) > radius 
            && coords.x > circle_center.x && coords.y > circle_center.y) return true; //third circle
            
            circle_center.x -= dimensions.x - 2*radius;
            
            if(length(coords - circle_center) > radius 
            && coords.x < circle_center.x && coords.y > circle_center.y) return true; //fourth circle
            
            return false;
            
    }
    
    float4 main(VSOut input) : SV_TARGET
    {
        float2 coords = input.uv * dimensions;
        if (ShouldDiscard(coords, dimensions, radius))
            discard;
        return color;
    }
    

    The function ShouldDiscard offsets circle centers on appropriate positions and then it checks if the coords are out of the circle and if they are in the "corner side" of a circle.