본문 바로가기
Shader CG

1.3 도형 - Rotation & Scailing Rect

by SimonLee 2023. 7. 11.

opengles를 공부했을때 rotation, scale matrix를 사용해본적이 있으실 겁니다.

position에 matrix 행렬을 곱해서 회전을 시켜봅시다.

 

회전행렬 공식은 다음과 같습니다.

float2x2 getRotationMatrix(float theta) 
{
    float s = sin(theta);
    float c = cos(theta);
    return float2x2(c, -s, s, c);
}

float2x2 타입은 라는 것은 2 by 2 행렬 입니다.

계산 유도 과정 입니다.

 

 

회전 매트릭스를 position에 곱하면 됩니다.

곱하기만 하면 원점 중심으로 회전합니다.

float2 pt = mul(mat, pos);

 

회전축을 설정하려면 어떻게 하냐면

회전 축 값을 빼주었다가 다시 더해 줍니다.

 

원점으로 사각형을 가지고 와서 회전한 뒤 다시 원래 위치에 가져다 놓는것으로

이해 하시면 됩니다.

float2 pt = mul(mat, pos - _Center) + _Center;

 

이번엔 스케일링을 해봅시다.

스케일링은 크기를 변화하는 것을 의미합니다.

float2x2 getScaleMatrix(float scale)
{
	return float2x2(scale,0,0,scale);
}

행렬 곱셈하는 법을 아시면 이해하실 겁니다.

 

Scale Transform Matrix

 

여기서 이해하면 좋은 내용을 소개 합니다.

물체의 이동, 회전, 크기변환 적용할 행렬을 전부 곱한 최종 행렬을 Transform Matrix라고 합니다.

이 최종 행렬을 position에 곱해주면 최종 목적지의 position 값이 나오게 됩니다.

 

Rotation, Scale 경우 어떤 순서든 행렬식을 곱해도 행렬식 결과에는 영향이 없습니다.

 

반면에 이동 행렬인 Transition Transform은 

Rotation, Scale Transform과 다르게 비선형 Transform 이라고 합니다.

 

계산 과정에 Transition Transform 들어가면 순서에 영향을 줍니다.

Transition 후 Rotation 순서와 Rotation 후 Transition의 순서는 다릅니다.

 

그래서 행렬을 적용하는 순서가 중요한데

행렬식은 뒤에서 부터 적용이 된다고 생각하시면 됩니다.

최종 행렬 = A 행렬 * B 행렬 * position  인 경우,

position에 B행렬이 적용이 되고, 그 다음 A행렬이 적용 됩니다.

 

위 그림중 1번에 위 공식을 적용을 해보면

먼저 적용해야 할 행렬은 B행렬 (90도 회전), 그 다음 적용할 행렬 A 행렬 (2, 0 이동)

으로 보면 되겠습니다.

 

아래 코드에서는 Scailing 적용하고 rotation을 적용 했네요.

이런 경우는 순서와 상관이 없습니다.

 

아래 코드에서 행렬식을 계산하는 부분 입니다.

float2x2 matr = getRotationMatrix(_Time.y);
float2x2 mats = getScaleMatrix((sin(_Time.y) + 1)/3 + 0.5);
float2x2 mat = mul(matr, mats);

 

Scale 파라메터에 sin(Time.y)  + 1 을 계산하면 범위가 0 ~ 2 이고,

3을 나누고 0.5를 더하면 대강 0 ~ 1정도가 나오겠네요.

Scale + Rotation 하는 행렬

Shader "SimonLee/Shader11Unlit"
{
    Properties
    {
        _Color("Square Color", Color) = (1.0,1.0,0,1.0)
        _Center("Center", Vector) = (0, 0, 0, 0)
        _Size("Size", Float) = 0.3
        _Anchor("Anchor", Vector) = (0.15, 0.15, 0, 0)

    }
    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;
            };
            
            v2f vert (appdata_base v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.position = v.vertex;
                return o;
            }

            fixed4 _Color;
            float _Size;
            float4 _Center;
            float4 _Anchor;

            float2x2 getRotationMatrix(float theta) {
                float s = sin(theta);
                float c = cos(theta);
                return float2x2(c, -s, s, c);
            }

            float rect(float2 pt, float2 anchor, float2 size, float2 center) {
                float2 p = pt - center;
                float2 halfsize = size / 2.0;
                float horz = step(-halfsize.x - anchor.x, p.x) - step(halfsize.x - anchor.x, p.x);
                float vert = step(-halfsize.y - anchor.y, p.y) - step(halfsize.y - anchor.y, p.y);
                return horz * vert;
            }

            float2x2 getScaleMatrix(float scale) {
                return float2x2(scale, 0, 0, scale);
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float2 pos = i.position * 2.0;
                float2 size = _Size;                
                
                float2x2 matr = getRotationMatrix(_Time.y);
                float2x2 mats = getScaleMatrix((sin(_Time.y) + 1) / 3 + 0.5);
                float2x2 mat = mul(matr, mats);
                
                float2 pt = mul(mat, pos - _Center) + _Center;
                
                
                float3 color = _Color * rect(pt, _Anchor.xy, size, _Center);
                
                return fixed4(color, 1.0);
            }
            ENDCG
        }
    }
}

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

1.5 도형 - Draw Circle 심화  (2) 2023.07.18
1.4 도형 - 타일링  (0) 2023.07.13
1.2 도형 - Draw Rectangle - 2  (0) 2023.07.09
1.2 도형 - Draw Rectangle - 1  (0) 2023.07.09
1.1 도형 - draw Circle  (0) 2023.07.09