Как исправить этот пиксельный шейдер HLSL, чтобы скруглить углы четырехугольника?

Я хотел бы сделать пиксельный шейдер HLSL, который может скруглять углы четырехугольника. Я попытался портировать это пример GLSL следующим образом:

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

В итоге я получаю следующее: Но я ищу более прямоугольную форму со скругленными углами. введите здесь описание изображения


person cecil    schedule 19.01.2021    source источник


Ответы (1)


Этот шейдер неправильный и, вероятно, непроверенный, поскольку он также содержит синтаксические ошибки. Что-то вроде этого должно помочь:

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

Функция ShouldDiscard смещает центры кругов в соответствующих позициях, а затем проверяет, находятся ли координаты за пределами круга и находятся ли они на угловой стороне круга.

person zezanjee    schedule 19.01.2021
comment
Спасибо. Это прекрасно работает! - person cecil; 19.01.2021