본문 바로가기
Shader CG

1.2 도형 - Draw Rectangle - 1

by SimonLee 2023. 7. 9.
728x90

지난 시간 원에 이어서 사각형을 렌더링 해봅시다.

결국은 동일한 원리 이지만, 이해를 돕기 위해 2가지 방법을 설명 드립니다.

 

사각형을 렌더링 함수를 rect라고 정의 하겠습니다.

함수의 인자는 3가지 입니다.

1) float2 position 2) float2 size 3) float2 center

첫 번째는 모든 픽셀 정점의 위치 값

두 번째는 사각형의 가로 세로 길이

세 번째는 사각형의 중심

 

rect함수의 리턴값이 1이면 해당 픽셀이 사각형 내부로 정의 합니다.

 

사각형의 영역을 정의하기 위해서는 2개의 정보가 필요합니다.

사각형 기준으로 좌측하단 좌표와, 우측상단 좌표, 이 두가지 좌표만 있으면 사각형을 그릴수 있습니다.

1> 먼저 좌표를 구해봅시다.

 

좌측 하단좌표 A지점의 좌표는

center 좌표에서 x좌표는 (사각형의 가로길이 / 2)를 빼주면 되고,

y 좌표는 (사각형 세로길이 / 2) 를 빼주면 됩니다.

float dlx = center.x - (size.x * 0.5);

float dly = center.y - (size.y * 0.5);

 

x, y를 구분하지 않고 2차원으로 아래처럼도 가능합니다.

float2 A = center - (size * 0.5);

 

마찬가지로, 우측 상단좌표 B지점의 좌표는

center의 x좌표에 (사각형의 가로길이 / 2) 를 더해주면 되고,

center의 y 좌표에 (사각형 세로길이 / 2)를 더해주면 됩니다. 

float2 B = center + (size * 0.5);

 

2> 이제는 구해진 좌표를 사용해서 사각형을 영역을 생각해 봅시다.

파랑색 사각형 영역을 선택하기 위해서는 

1번 그림, 좌측 하단 기준으로 초록색 영역과 

2번 그림, 우측 상단 기준에서 빨강색 영역의 교차 지역이어야 합니다.

 

step 함수를 사용해서 1번, 2번 영역을 구해봅시다.

1 좌측 하단 A점 기준 사각형 영역

float2 dlArea = step(A, position)

--> A : 좌측 하단 좌표, position : 클립 스페이스에 해당하는 모든 정점 좌표.

 

빨강색 영역은 A좌표의 x, y값 보다 전부 큰 경우에 해당됩니다.

결국 dlArea.x, dlArea.y 값이 전부 1이면 해당 픽셀은 초록색 영역해당 되고, 아닌 경우는 빨간색 영역 입니다.

2 우측 상단 B점 기준 사각형 영역

 

float2 urArea = 1 - step(B, position)

--> B : 우측 상단 좌표, position : 클립 스페이스에 해당하는 모든 정점 좌표.

 

빨간색 영역은 B좌표의 x,y값 보다 전부 작은 경우에 해당됩니다.

결국 dlArea.x, dlArea.y 값이 전부 0이면 해당 픽셀은 빨강색 영역에 해당 되고, 아닌 경우는 초록색 영역 입니다.

사각형 내부에 해당하는 경우만 1로 만들어 주기 위하여, 값을 반전 시킵니다.

1에서 식을 빼주게 되면, 식이 0이면 1이 되고, 1이면 0이 되어 반전 효과를 줄 수 있습니다.

 

3> 이제 교차된 영역을 구하기 위해서 2개의 식의 결과를 곱해주면,  

교차 영역을 구하기 위해서는 두식이 전부 1인 경우에 해당이 되고,

이는 두식을 곱해서 1이 나오면 됩니다.

 

float2 result = step(A, pt) * (1 - step(B, pt));

result의 영역과 각 x,y 의미는 다음과 같습니다.

result.x가 1인 부분은 붉은색 영역이고

result.y가 1인 부분은 파랑색 영역 입니다.

교차 영역을 구하기 위하여 result.x와 result.y를 곱해 주면.

return result.x * result.y;

최종 리턴값이 1이면,

드디어 특정 정점의 x좌표, y좌표가 사각형 내부에 있는 경우 입니다. ^^

사각형 렌더링 결과

Shader "SimonLee/Shader8Unlit"
{
    Properties
    {
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float4 position: TEXCOORD1;
                float2 uv : TEXCOORD0;
            };
            
            v2f vert (appdata_base v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.position = v.vertex;
                o.uv = v.texcoord;
                return o;
            }

            float rect(fixed2 pt, fixed2 size, fixed2 center) 
            {
                float2 dl = center - (size * 0.5);
                float2 ur = center + (size * 0.5);
                float2 result = step(dl, pt) * (1 - step(ur, pt));
                return result.x * result.y;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                float2 size = (0.4, 0.4);
                float2 center = (0, 0.3);
                float3 color = fixed3(1,1,0) * rect(i.position.xy, size, center);
                return fixed4(color, 1.0);
            }
            ENDCG
        }
    }
}

 

728x90

'Shader CG' 카테고리의 다른 글

1.3 도형 - Rotation & Scailing Rect  (0) 2023.07.11
1.2 도형 - Draw Rectangle - 2  (0) 2023.07.09
1.1 도형 - draw Circle  (0) 2023.07.09
기초 3. 블렌딩 해보자 (step, smoothstep)  (0) 2023.07.06
기초 2. 블렌딩 해보자  (0) 2023.07.05