본문 바로가기
Nuke/Blink Script

Blink Scripting 101 - UV 맵 생성 예제

by 르면가게 2024. 12. 11.

UV 맵 생성 예제 (Compositor용)


UV 맵 생성에서 고려할 점: Blink의 접근 방식

Blink에서 UV 맵을 생성할 때 고려해야 할 몇 가지 중요한 사항이 있습니다. 가장 중요한 점은 이미지의 접근 방식(eRead)에 따라 계산 방식이 달라진다는 것입니다. Blink에서는 두 가지 주요 접근 방식이 있습니다: eAccessPoint와 eAccessRandom입니다.

1. Image<eRead,eAccessPoint>

Image<eRead, eAccessPoint>는 Nuke의 설정에서 지정된 높이 타일 수에 따라 계산이 정의됩니다. 이 방식은 지정된 타일 크기 내에서만 계산이 이루어집니다. 즉, 이미지를 타일 단위로 나누어 처리할 때, 각 타일은 고정된 범위 내에서만 접근할 수 있습니다. 이 방식은 이미지가 큰 경우 성능을 최적화할 수 있지만, 특정한 위치나 크기의 데이터에 대해 제한적일 수 있습니다.

요약: 프로젝트 셋팅의 사이즈를 따라감

2. Image<eRead,eAccessRandom>

반면, Image<eRead, eAccessRandom>은 더 유연하게 동작합니다. 이 방식은 노드가 어떤 위치의 픽셀이든 자유롭게 접근할 수 있도록 합니다. 즉, 타일 단위로 구획을 나누지 않고, 이미지 전체를 대상으로 계산이 가능하므로 더 정밀한 데이터 처리가 가능합니다.

따라서, 해상도 설정에 따라 접근 방식의 선택은 성능과 처리 방식에 영향을 미칠 수 있습니다. 성능이 중요한 경우 eAccessPoint를 사용하고, 자유로운 픽셀 접근이 필요한 경우 eAccessRandom을 사용하는 것이 좋습니다.

요약: Input 데이터의 크기를 따라감


UV 맵 생성 수학: 정규화(Normalization)

UV 맵을 생성하는 과정에서 정규화는 매우 중요한 개념입니다. 이미지를 0에서 1 사이의 값으로 변환하려면, 각 픽셀의 상대적인 위치를 계산해야 합니다. 이는 정규화를 통해 이루어집니다.

정규화 개념

예를 들어, 너비가 10인 박스에서 각 픽셀의 상대적인 위치를 계산한다고 가정해 보겠습니다. 그러면 계산은 다음과 같이 이루어집니다:

  • 너비 = 10
  • 픽셀 위치 0의 상대 위치: 0 / 10 = 0
  • 픽셀 위치 5의 상대 위치: 5 / 10 = 0.5
  • 픽셀 위치 10의 상대 위치: 10 / 10 = 1

이와 같은 방식으로, 정규화는 각 픽셀의 좌표를 0에서 1 사이의 값으로 변환합니다. 이 값은 UV 맵에서 각 픽셀의 위치를 나타내며, 이후 텍스처 매핑이나 좌표 변환 등에 활용될 수 있습니다.

예시 코드: UV 맵 계산


UV 맵 1 (입력 이미지의 크기 샘플링)

목표

입력 이미지의 크기를 기반으로 UV 맵을 생성하여 픽셀의 상대적인 위치를 0에서 1 사이로 정규화(normalization)합니다.

코드

kernel UVmap : ImageComputationKernel<ePixelWise>
{
  Image<eRead, eAccessRandom, eEdgeClamped> src;   // 입력 이미지
  Image<eWrite> dst;                                // 출력 이미지

  local:
    float width;                                    // 너비 값을 저장할 변수
    float height;                                   // 높이 값을 저장할 변수

  void init() {
    width = src.bounds.x2;                          // 이미지의 오른쪽 가장자리 샘플링
    height = src.bounds.y2;                         // 이미지의 위쪽 가장자리 샘플링
  }

  void process(int2 pos) {
    dst(0) = pos.x / width;                         // X 위치를 너비로 나누어 정규화
    dst(1) = pos.y / height;                        // Y 위치를 높이로 나누어 정규화
    dst(2) = 0.0f;                                  // 파란색 채널은 0.0f
    dst(3) = 0.0f;                                  // 알파 채널은 0.0f
  }
};

설명

  • 입력 이미지 샘플링: src.bounds.x2와 src.bounds.y2를 사용하여 이미지의 너비와 높이를 계산합니다. x2는 오른쪽 가장자리, y2는 위쪽 가장자리를 나타냅니다.
  • 정규화: 각 픽셀의 X, Y 위치를 이미지의 크기로 나누어 0과 1 사이의 값을 생성합니다.
    • 예를 들어, 너비가 256이고 X 위치가 0이라면, 0 / 256 = 0이 됩니다.
    • X 위치가 256일 때는, 256 / 256 = 1이 됩니다.
  • 출력: 각 픽셀에 대해 UV 좌표를 계산하여 출력합니다. dst(0)은 빨간색 채널, dst(1)은 녹색 채널에 UV 값을 배치하고 나머지 채널은 0으로 설정합니다.

UV 맵 2 (사용자 정의 너비와 높이 사용)

목표

입력 이미지의 크기를 사용하지 않고, 사용자가 정의한 너비와 높이를 기반으로 UV 맵을 생성합니다. 이 방식으로 UV 맵을 사용자 맞춤형으로 조절할 수 있습니다.

코드

kernel UVmap2 : ImageComputationKernel<ePixelWise>
{
  Image<eWrite> dst;                               // 출력 이미지

  param:
    float width;                                   // 사용자 정의 너비
    float height;                                  // 사용자 정의 높이

  void define() {
    defineParam(width, "width", 256.0f);           // 기본값: 너비 256
    defineParam(height, "height", 256.0f);         // 기본값: 높이 256
  }

  void process(int2 pos) {
    dst(0) = pos.x / width;                        // X 위치를 정의한 너비로 나누어 정규화
    dst(1) = pos.y / height;                       // Y 위치를 정의한 높이로 나누어 정규화
    dst(2) = 0.0f;                                 // 파란색 채널은 0.0f
    dst(3) = 0.0f;                                 // 알파 채널은 0.0f
  }
};

설명

  • 사용자 정의 너비와 높이: param을 사용하여 width와 height를 정의하고 기본값을 설정합니다. 이 값들은 사용자가 노브를 통해 조정할 수 있습니다.
  • 정규화: 입력 이미지 크기 대신 width와 height를 사용하여 UV 좌표를 생성합니다. 이 방식은 더 유연하게 UV 맵을 정의할 수 있습니다.
  • 출력: 마찬가지로 dst(0)과 dst(1)에 UV 좌표를 배치하고, 나머지 채널은 0으로 설정합니다.

확장 아이디어: 사용자가 UV 맵에 제어 추가

사용자가 UV 맵을 더욱 세밀하게 조정할 수 있도록 곱셈 또는 나눗셈을 추가해보는 것이 재미있습니다. 예를 들어, pos.x나 pos.y를 width 또는 height와 곱하거나 나누어 범위의 확대/축소를 제어할 수 있습니다.


결과

  1. UV 맵 1: 이미지의 크기를 기반으로 UV 좌표를 정규화하여 출력합니다.
  2. UV 맵 2: 사용자가 정의한 너비와 높이를 사용하여 UV 맵을 생성합니다.

이러한 방식으로 Blink 스크립트를 활용하여 실용적인 UV 맵을 생성하고, 컴포지터 작업에서 유용하게 사용할 수 있습니다.

UV 맵 생성 예제 (Compositor용)


UV 맵 생성에서 고려할 점: Blink의 접근 방식

Blink에서 UV 맵을 생성할 때 고려해야 할 몇 가지 중요한 사항이 있습니다. 가장 중요한 점은 이미지의 접근 방식(eRead)에 따라 계산 방식이 달라진다는 것입니다. Blink에서는 두 가지 주요 접근 방식이 있습니다: eAccessPoint와 eAccessRandom입니다.

1. Image<eRead,eAccessPoint>

Image<eRead, eAccessPoint>는 Nuke의 설정에서 지정된 높이 타일 수에 따라 계산이 정의됩니다. 이 방식은 지정된 타일 크기 내에서만 계산이 이루어집니다. 즉, 이미지를 타일 단위로 나누어 처리할 때, 각 타일은 고정된 범위 내에서만 접근할 수 있습니다. 이 방식은 이미지가 큰 경우 성능을 최적화할 수 있지만, 특정한 위치나 크기의 데이터에 대해 제한적일 수 있습니다.

요약: 프로젝트 셋팅의 사이즈를 따라감

2. Image<eRead,eAccessRandom>

반면, Image<eRead, eAccessRandom>은 더 유연하게 동작합니다. 이 방식은 노드가 어떤 위치의 픽셀이든 자유롭게 접근할 수 있도록 합니다. 즉, 타일 단위로 구획을 나누지 않고, 이미지 전체를 대상으로 계산이 가능하므로 더 정밀한 데이터 처리가 가능합니다.

따라서, 해상도 설정에 따라 접근 방식의 선택은 성능과 처리 방식에 영향을 미칠 수 있습니다. 성능이 중요한 경우 eAccessPoint를 사용하고, 자유로운 픽셀 접근이 필요한 경우 eAccessRandom을 사용하는 것이 좋습니다.

요약: Input 데이터의 크기를 따라감


UV 맵 생성 수학: 정규화(Normalization)

UV 맵을 생성하는 과정에서 정규화는 매우 중요한 개념입니다. 이미지를 0에서 1 사이의 값으로 변환하려면, 각 픽셀의 상대적인 위치를 계산해야 합니다. 이는 정규화를 통해 이루어집니다.

정규화 개념

예를 들어, 너비가 10인 박스에서 각 픽셀의 상대적인 위치를 계산한다고 가정해 보겠습니다. 그러면 계산은 다음과 같이 이루어집니다:

  • 너비 = 10
  • 픽셀 위치 0의 상대 위치: 0 / 10 = 0
  • 픽셀 위치 5의 상대 위치: 5 / 10 = 0.5
  • 픽셀 위치 10의 상대 위치: 10 / 10 = 1

이와 같은 방식으로, 정규화는 각 픽셀의 좌표를 0에서 1 사이의 값으로 변환합니다. 이 값은 UV 맵에서 각 픽셀의 위치를 나타내며, 이후 텍스처 매핑이나 좌표 변환 등에 활용될 수 있습니다.

예시 코드: UV 맵 계산


UV 맵 1 (입력 이미지의 크기 샘플링)

목표

입력 이미지의 크기를 기반으로 UV 맵을 생성하여 픽셀의 상대적인 위치를 0에서 1 사이로 정규화(normalization)합니다.

코드

kernel UVmap : ImageComputationKernel<ePixelWise>
{
  Image<eRead, eAccessRandom, eEdgeClamped> src;   // 입력 이미지
  Image<eWrite> dst;                                // 출력 이미지

  local:
    float width;                                    // 너비 값을 저장할 변수
    float height;                                   // 높이 값을 저장할 변수

  void init() {
    width = src.bounds.x2;                          // 이미지의 오른쪽 가장자리 샘플링
    height = src.bounds.y2;                         // 이미지의 위쪽 가장자리 샘플링
  }

  void process(int2 pos) {
    dst(0) = pos.x / width;                         // X 위치를 너비로 나누어 정규화
    dst(1) = pos.y / height;                        // Y 위치를 높이로 나누어 정규화
    dst(2) = 0.0f;                                  // 파란색 채널은 0.0f
    dst(3) = 0.0f;                                  // 알파 채널은 0.0f
  }
};

설명

  • 입력 이미지 샘플링: src.bounds.x2와 src.bounds.y2를 사용하여 이미지의 너비와 높이를 계산합니다. x2는 오른쪽 가장자리, y2는 위쪽 가장자리를 나타냅니다.
  • 정규화: 각 픽셀의 X, Y 위치를 이미지의 크기로 나누어 0과 1 사이의 값을 생성합니다.
    • 예를 들어, 너비가 256이고 X 위치가 0이라면, 0 / 256 = 0이 됩니다.
    • X 위치가 256일 때는, 256 / 256 = 1이 됩니다.
  • 출력: 각 픽셀에 대해 UV 좌표를 계산하여 출력합니다. dst(0)은 빨간색 채널, dst(1)은 녹색 채널에 UV 값을 배치하고 나머지 채널은 0으로 설정합니다.


UV 맵 2 (사용자 정의 너비와 높이 사용)

목표

입력 이미지의 크기를 사용하지 않고, 사용자가 정의한 너비와 높이를 기반으로 UV 맵을 생성합니다. 이 방식으로 UV 맵을 사용자 맞춤형으로 조절할 수 있습니다.

코드

kernel UVmap2 : ImageComputationKernel<ePixelWise>
{
  Image<eWrite> dst;                               // 출력 이미지

  param:
    float width;                                   // 사용자 정의 너비
    float height;                                  // 사용자 정의 높이

  void define() {
    defineParam(width, "width", 256.0f);           // 기본값: 너비 256
    defineParam(height, "height", 256.0f);         // 기본값: 높이 256
  }

  void process(int2 pos) {
    dst(0) = pos.x / width;                        // X 위치를 정의한 너비로 나누어 정규화
    dst(1) = pos.y / height;                       // Y 위치를 정의한 높이로 나누어 정규화
    dst(2) = 0.0f;                                 // 파란색 채널은 0.0f
    dst(3) = 0.0f;                                 // 알파 채널은 0.0f
  }
};

설명

  • 사용자 정의 너비와 높이: param을 사용하여 width와 height를 정의하고 기본값을 설정합니다. 이 값들은 사용자가 노브를 통해 조정할 수 있습니다.
  • 정규화: 입력 이미지 크기 대신 width와 height를 사용하여 UV 좌표를 생성합니다. 이 방식은 더 유연하게 UV 맵을 정의할 수 있습니다.
  • 출력: 마찬가지로 dst(0)과 dst(1)에 UV 좌표를 배치하고, 나머지 채널은 0으로 설정합니다.


확장 아이디어: 사용자가 UV 맵에 제어 추가

사용자가 UV 맵을 더욱 세밀하게 조정할 수 있도록 곱셈 또는 나눗셈을 추가해보는 것이 재미있습니다. 예를 들어, pos.x나 pos.y를 width 또는 height와 곱하거나 나누어 범위의 확대/축소를 제어할 수 있습니다.


결과

  1. UV 맵 1: 이미지의 크기를 기반으로 UV 좌표를 정규화하여 출력합니다.
  2. UV 맵 2: 사용자가 정의한 너비와 높이를 사용하여 UV 맵을 생성합니다.

이러한 방식으로 Blink 스크립트를 활용하여 실용적인 UV 맵을 생성하고, 컴포지터 작업에서 유용하게 사용할 수 있습니다.