본문 바로가기
공부/DirectX3D

[DirectX3D] PostEffect 블러(Blur)효과 적용하기 ( + Filter )

by MY블로그 2023. 8. 22.

쉐이더 파일을 사용하여 PostEffect를 구현하고 PixelShader 에서 추가적으로 Blur 효과를 적용하여 봅니다.

포스트 이펙트를 사용한 블러(Blur) 효과

아래의 효과들은 적용전(좌측), 적용후(우측)으로 비교하여 보도록 합니다.

블러의 효과들은 상수버퍼를 사용한 클래스를 통하여 값을 변경하여 강도 조절이 가능합니다.

1. 크로스 블러 (Cross Blur)

크로스 블러는 픽셀들이 상,하,좌,우의 교차(Cross)방향으로 퍼진듯한 느낌이 표현됩니다.

크로스 블러
float4 CrossBlur(float2 uv)
{
    float4 color = 0;
    for (int i = 0; i < count; i++)
    {
        float divX = (1 + i) / width;
        float divY = (1 + i) / height;
        color += TextureD.Sample(SamplerD, float2(uv.x + divX, uv.y));
        color += TextureD.Sample(SamplerD, float2(uv.x - divX, uv.y));
        color += TextureD.Sample(SamplerD, float2(uv.x, uv.y + divY));
        color += TextureD.Sample(SamplerD, float2(uv.x, uv.y - divY));
    }

    color /= count * 4;
    return color;
}

2. 옥타 블러 (Octa Blur)

옥타 블러는 1.크로스 블러 보다 조금더 세세하게 8개의 방향으로 픽셀들이 퍼진듯한 느낌이 표현됩니다.

옥타 블러
static const float2 arr[8] =
{
    float2(-1, -1), float2(0, -1), float2(1, -1),
    float2(-1, 0), float2(1, 0),
    float2(-1, 1), float2(0, 1), float2(1, 1)
};
float4 OctaBlur(float2 uv)
{
    float4 color = 0;
    for (int i = 0; i < count; i++)
    {
        float divX = (1 + i) / width;
        float divY = (1 + i) / height;
        for (int j = 0; j < 8; j++)
        {
            float x = arr[j].x * divX + uv.x;
            float y = arr[j].y * divY + uv.y;
            color += TextureD.Sample(SamplerD, float2(x, y));
        }
    }
    color /= count * 8;
    return color;
}

3. 가우시안 블러 (Gaussian Blur)

가우시안 블러는 2.옥타 블러 보다 더욱 세세한느낌으로 퍼진 느낌이 표현됩니다.

가우시안 블러
static const float weights[13] =
{
    0.0561f, 0.1353f, 0.2780f, 0.4868f, 0.7261f, 0.9231f,
    1.0f,
    0.9231f, 0.7261f, 0.4868f, 0.2780f, 0.1353f, 0.0561f
};
float4 GaussianBlur(float2 uv)
{
    float divX = 1.0f / width;
    float divY = 1.0f / height;
    float sum = 0;
    float4 color = 0;
    for (int i = -6; i <= 6; i++)
    {
        float2 temp = uv + float2(divX * i * count, 0);
        color += weights[6 + i] * TextureD.Sample(SamplerD, temp);
        temp = uv + float2(0, divY * i * count);
        color += weights[6 + i] * TextureD.Sample(SamplerD, temp);
        sum += weights[6 + i] * 2;
    }
    color /= sum;
    return color;
}

4. 모자이크 블러 (Mosaic Blur)

모자이크 블러는 말그대로 모자이크 처리된듯 픽셀의 단위가 강조된 느낌이 표현됩니다.

모자이크 블러
float4 Mosaic(float2 uv)
{
    int x = (int) (uv.x * count);
    int y = (int) (uv.y * count);
    float2 temp;
    temp.x = (float) x / count;
    temp.y = (float) y / count;
    return TextureD.Sample(SamplerD, temp);
}

5. 라디얼 블러 (Radial Blur)

라디얼 블러는 중심점을기준으로 일정거리의 외부의 픽셀들이 퍼진듯한 느낌이 표현됩니다.

예를들어 레이싱게임에서 부스터로 가속이되어있는상태의 효과와 유사합니다.

라디얼 블러
float4 RadialBlur(float2 uv)
{
    float2 radiusUV = uv - float2(0.5f, 0.5f);
    float r = length(radiusUV);
    radiusUV /= r;
    r = saturate(2 * r / width);
    float2 delta = -radiusUV * r * r * height / count;
    float4 color = 0;
    for (int i = 0; i < count; i++)
    {
        color += TextureD.Sample(SamplerD, uv);
        uv += delta;
    }
    color /= count;
    return color;
}

6. 워터 블러 (Water Blur)

워터 블러는 물의 표면처럼 잔잔한 일그러짐의 느낌이 표현 됩니다.

위의 예시 이미지는 y축을 기준으로 효과를 표현하여 가로선의 느낌이 강하게 들고 있습니다.

반대로 x축을 기준으로 효과를 표현한다면 세로선의 느낌표현이 되고, xy의 모든 축을 기준으로 효과를 표현할 경우

사각형의 구간이 나뉘는 듯한 느낌표현이 가능 합니다.(아래의 이미지 참고)

워터블러 x, y축의 값을 모두 변경 하였을 경우

워터 블러
float4 Water(float2 uv)
{
	uv.x = uv.x + (sin(uv.x * count) * 0.03);
    uv.y = uv.y + (sin(uv.y * count) * 0.03);
    float4 Color = TextureD.Sample(SamplerD, uv);
    return Color;
}

포스트 이펙트를 사용한 필터(Filter) 효과

0. 필터X

1. 모노

모노
BaseColor.rgb = (BaseColor.r + BaseColor.g + BaseColor.b) / 3.0f;

2. 세피아

세피아
float3 temp = (BaseColor.r + BaseColor.g + BaseColor.b) / 3.0f;
BaseColor.r = dot(temp.rgb, float3(0.393f, 0.769f, 0.189f));
BaseColor.g = dot(temp.rgb, float3(0.349f, 0.686f, 0.168f));
BaseColor.b = dot(temp.rgb, float3(0.272f, 0.534f, 0.131f));

3. 색계단

색계단
BaseColor.r *= count;
BaseColor.g *= count;
BaseColor.b *= count;

BaseColor.r = floor(BaseColor.r);
BaseColor.g = floor(BaseColor.g);
BaseColor.b = floor(BaseColor.b);

BaseColor.r /= count;
BaseColor.g /= count;
BaseColor.b /= count;

4. 색반전

색반전
BaseColor.rgb = (1.0f - BaseColor.rgb);

댓글