IT/공부 정리

[UNITY/C#] Catmull-Rom 스플라인을 사용하여 곡선 및 텍스처에 적용하기

rinix_x 2023. 3. 19. 03:17
반응형

Unity C#에서 주어진 좌표 사이에 선을 그릴 때 자연스러운 곡선을 만들기 위해 Catmull-Rom 스플라인을 사용한다.

이 스플라인은 부드러운 곡선을 사용하여 점을 보간하여 자연스럽게 보이는 선을 만들어준다.

 

Unity C#에서 Catmull-Rom 스플라인을 사용하려면 새 빈 게임 개체를 만들고 여기에 Line Renderer 구성 요소를 추가하면 된다. 그런 다음 다음 코드를 사용하여 Catmull-Rom 스플라인을 사용하여 라인 렌더러의 위치를 ​​설정할 수 있다.

 

해당 방안을 유니티에서 사용하기 위해서는 다음 단계를 진행하면 된다.

1. Unity 장면에서 빈 GameObject를 생성하고 여기에 LineRenderer 구성 요소를 추가
2. 스플라인의 제어점을 나타내는 'Vector3' 점의 배열을 만든다.
3. Unity에서 제공하는 CatmullRomSpline 클래스를 사용하여 스플라인의 포인트를 계산한다. 제어점 배열을 인수로 전달하여 CatmullRomSpline.Calculate() 메서드를 호출하여 이 작업을 수행
4. LineRenderer의 positionCount 속성을 CatmullRomSpline.Calculate() 메서드로 계산된 포인트 수로 설정한다.
5. LineRenderer의 SetPosition() 메서드를 스플라인에서 계산된 각 점으로 설정한다.

 

다음은 Unity C#에서 Catmull-Rom 스플라인을 사용하는 방법을 보여주는 예제 코드이다.

using UnityEngine;

public class CatmullRomSplineExample : MonoBehaviour
{
    public int numPoints = 10;
    public float spacing = 0.1f;

    private LineRenderer lineRenderer;

    void Start()
    {
        lineRenderer = GetComponent<LineRenderer>();

        Vector3[] controlPoints = new Vector3[]
        {
            new Vector3(0, 0, 0),
            new Vector3(1, 1, 0),
            new Vector3(2, -1, 0),
            new Vector3(3, 0, 0)
        };

        Vector3[] points = CatmullRomSpline.Calculate(controlPoints, numPoints, spacing);

        lineRenderer.positionCount = points.Length;
        lineRenderer.SetPositions(points);
    }
}

해당 예제에서는 먼저 스플라인에 대한 4개의 제어점을 배열에 설정한 다음 CatmullRomSpline.Calculate() 메서드를 사용하여 스플라인을 따라 점 집합을 계산했다. 그리고 마지막으로 LineRenderer의 위치 수를 계산된 포인트 수로 설정하고 라인 렌더러의 위치를 ​​계산된 포인트로 설정했다.

 

이제 이것을 텍스쳐에 적용하고자 한다.

Catmull-Rom 스플라인을 사용하여 곡선을 생성한 다음 Unity C#의 텍스처에 적용하고자 한다. 먼저  LineRenderer 구성 요소를 사용하여 곡선을 그리고 텍스처를 LineRenderer의 재질로 설정한다.

 

하나의 예시 코드를 보여주자면.

using System.Collections.Generic;
using UnityEngine;

public class SplineTexture : MonoBehaviour
{
    public Texture2D texture;
    public int resolution = 256;
    public float spacing = 0.1f;

    private LineRenderer lineRenderer;
    private List<Vector3> points = new List<Vector3>();

    void Start()
    {
        lineRenderer = GetComponent<LineRenderer>();

        // Generate points on the spline
        for (float t = 0; t <= 1; t += spacing)
        {
            Vector3 point = CatmullRomSpline.GetPointOnSpline(transform, t);
            points.Add(point);
        }

        // Set the number of vertices on the line renderer to match the number of points
        lineRenderer.positionCount = points.Count;

        // Set the positions of the line renderer to match the points
        lineRenderer.SetPositions(points.ToArray());

        // Create a new material and set the texture to it
        Material material = new Material(Shader.Find("Sprites/Default"));
        material.mainTexture = texture;

        // Set the material of the line renderer to the new material
        lineRenderer.material = material;
    }
}

이 스크립트는 CatmullRomSpline.GetPointOnSpline 메서드를 사용하여 Catmull-Rom 스플라인에 점을 생성하고 점과 일치하도록 LineRenderer의 위치를 ​​설정하고 LineRenderer의 재질을 지정된 텍스처가 있는 새 재질로 설정했다. 이 스크립트를 장면의 GameObject에 첨부하고 텍스처, 해상도 및 간격을 지정하여 텍스처가 적용된 곡선을 생성할 수 있다.

 

 

위의 것들을 이용하여 영역 안과 밖을 구분하며, 텍스처를 변경하고자 한다.

 Unity C#에서 위의 곡선으로 그린 ​​영역의 안쪽과 바깥쪽을 구분하여 텍스처의 색상을 변경할 수 있습니다. 이를 달성하는 한 가지 방법은 텍스처 매핑이라는 기술을 사용하는 것이다.

먼저 내부에 검은색 픽셀이 있고 외부에 투명한 픽셀이 있는 채울 영역을 나타내는 텍스처를 만들어야 한다. 이미지 편집기에서 영역의 모양을 그리고 투명한 PNG 파일로 내보내면 된다.

그런 다음 채우려는 영역을 덮는 메시에 이 텍스처를 적용할 수 있습니다. Catmull-Rom 스플라인을 사용하여 메시의 모양을 정의하고 영역의 모양을 따르도록 할 수 있다.

텍스처의 색상을 변경하려면 텍스처를 샘플링하고 검정색 픽셀에 색상을 적용하는 셰이더를 사용할 수 있다. 이를 수행하는 한 가지 방법은 "lerp" 기능을 사용하여 텍스처의 알파 값을 기준으로 원래 색상과 새 색상 사이를 보간하는 것이다.


다음은 이를 수행하는 셰이더의 예입니다.

 

 

Shader "Custom/ColorMap" {
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
    }

    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _Color;

            v2f vert (appdata v) {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target {
                fixed4 col = tex2D(_MainTex, i.uv);
                col.rgb = lerp(col.rgb, _Color.rgb, col.a);
                col.a = _Color.a * col.a;
                return col;
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

이 셰이더를 사용하여 텍스처가 있는 메시를 렌더링하고 원하는 색상을 "_Color" 매개변수에 전달할 수 있다. 셰이더는 텍스처의 알파 값을 기준으로 텍스처의 원래 색상과 새 색상 사이를 보간한다.

 

 

 

 

 

 

 

 

반응형

'IT > 공부 정리' 카테고리의 다른 글

TypeScript  (0) 2023.09.25
MQTT, MQTT Protocol란  (0) 2023.06.16
캣멀-롬 스플라인(Catmull-Rom Splines)  (0) 2023.03.19
[UNITY/C#] C#고급 프로그래밍  (0) 2023.03.09
[UNITY] C# list 사용법  (0) 2023.02.24