Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

여러분의 첫 2D 셰이더

소개

셰이더는 GPU에서 실행되며 그래픽을 렌더링하는 데 사용되는 특별한 프로그램입니다. 현대의 모든 렌더링은 셰이더로 동작합니다. 셰이더가 무엇인지에 대한 자세한 사항은 셰이더가 무엇입니까를 참조해 주세요.

이 튜토리얼에서는 정점 및 조각 함수를 모두 사용하여 셰이더를 작성하는 과정을 안내하여 셰이더 프로그램 작성의 실제적인 측면에 중점을 둘 것입니다. 이 튜토리얼은 셰이더의 완전 초보자를 대상으로 합니다.

참고

셰이더 작성 경험이 있고 Godot에서 셰이더가 어떻게 작동하는지에 대한 개요를 찾고 있다면 :ref:`Shading Reference <toc-shading-reference>`를 참조하세요.

설정

CanvasItem 셰이더 셰이더는 모든 3D 개체를 그리는 데 사용됩니다.

셰이더를 사용하려면 객체에 부착해야 하는 Material 내부에 부착해야 합니다. 자료는 Resource 유형입니다. 동일한 재료로 여러 개체를 그리려면 각 개체에 재료를 부착해야 합니다.

CanvasItem, Sprite2Ds, TileMapLayers, MeshInstance2Ds 등이 포함됩니다. 또한 상위 자료를 상속하는 옵션도 있습니다. 이는 동일한 재료를 사용하려는 노드 수가 많은 경우 유용할 수 있습니다.

시작하려면 Sprite2D 노드를 만듭니다. :ref:`캔버스에 그림을 그리는 한 모든 CanvasItem <doc_custom_raw_in_2d>`을 사용할 수 있으므로 이 튜토리얼에서는 그리기를 시작하기 가장 쉬운 CanvasItem인 Sprite2D를 사용하겠습니다.

인스펙터에서 "[empty]"라고 표시된 "Texture" 옆을 클릭하고 "Load"를 선택한 다음 "icon.svg"를 선택합니다. 새 프로젝트의 경우, Godot 아이콘입니다. 이제 뷰포트에 아이콘이 표시됩니다.

다음으로 인스펙터를 살펴보고 CanvasItem 섹션 아래에서 "Material" 옆을 클릭하고 "New ShaderMaterial"을 선택합니다. 그러면 새로운 재료 리소스가 생성됩니다. 나타나는 구를 클릭하세요. Godot는 현재 CanvasItem 셰이더 또는 Spatial 셰이더를 작성하고 있는지 알지 못하며 공간 셰이더의 출력을 미리 봅니다. 따라서 여러분이 보고 있는 것은 기본 Spatial 셰이더의 출력입니다.

참고

Material 리소스에서 상속된 재질(예: StandardMaterial3DParticleProcessMaterial)은 :ref:`class_ShaderMaterial`로 변환될 수 있으며 해당 기존 속성은 함께 제공되는 텍스트 셰이더로 변환됩니다. 이렇게 하려면 FileSystem 도크에서 재질을 마우스 오른쪽 버튼으로 클릭하고 **ShaderMaterial로 변환**을 선택합니다. 인스펙터에서 머티리얼에 대한 참조를 보유하는 속성을 마우스 오른쪽 버튼으로 클릭하여 이를 수행할 수도 있습니다.

"셰이더" 옆을 클릭하고 "새 셰이더"를 선택합니다. 마지막으로 방금 생성한 셰이더를 클릭하면 셰이더 편집기가 열립니다. 이제 첫 번째 셰이더 작성을 시작할 준비가 되었습니다.

당신의 첫 게임

Godot에서 모든 셰이더는 셰이더의 유형을 지정하는 줄로 시작합니다. 다음 형식을 사용합니다.

shader_type canvas_item;

CanvasItem 셰이더를 작성 중이므로 첫 번째 줄에 ``canvas_item``를 지정합니다. 모든 코드는 이 선언 아래에 위치합니다.

이 줄은 어떤 내장 변수와 기능을 제공할지 엔진에 알려줍니다.

Godot에서는 셰이더 작동 방법을 제어하기 위해 세 가지 기능을 재정의할 수 있습니다; vertex, fragmentlight. 이 튜토리얼에서는 정점 및 조각 함수를 모두 사용하여 셰이더를 작성하는 과정을 안내합니다. 조명 함수는 정점 및 조각 함수보다 훨씬 더 복잡하므로 여기서는 다루지 않습니다.

당신의 첫 프래그먼트 함수

조각 함수는 Sprite2D의 모든 픽셀에 대해 실행되며 해당 픽셀이 어떤 색상이어야 하는지 결정합니다.

이는 Sprite2D가 다루는 픽셀로 제한됩니다. 즉, Sprite2D 주위에 윤곽선을 만드는 데 사용할 수 없다는 의미입니다.

가장 기본적인 조각 함수는 모든 픽셀에 단일 색상을 할당하는 것 외에는 아무 작업도 수행하지 않습니다.

내장 변수 ``COLOR``에 ``vec4``를 작성하면 됩니다. ``vec4``는 4개의 숫자로 벡터를 구성하는 약어입니다. 벡터에 대한 자세한 내용은 :ref:`벡터 수학 튜토리얼 <doc_Vector_math>`을 참조하세요. ``COLOR``는 조각 함수에 대한 입력 변수이자 최종 출력입니다.

void fragment(){
  COLOR = vec4(0.4, 0.6, 0.9, 1.0);
}
../../../_images/blue-box.png

축하합니다! 이제 끝났습니다. Godot에서 첫 번째 셰이더를 성공적으로 작성했습니다.

이제 상황을 더 복잡하게 만들어 보겠습니다.

``COLOR``를 계산하는 데 사용할 수 있는 조각 함수에 대한 입력이 많이 있습니다. ``UV``도 그중 하나입니다. UV 좌표는 Sprite2D에 지정되며(당신도 모르게!) 메쉬의 각 부분에 대한 텍스처에서 읽을 위치를 셰이더에 알려줍니다.

조각 함수에서는 ``UV``에서만 읽을 수 있지만 다른 함수에서 사용하거나 ``COLOR``에 직접 값을 할당할 수 있습니다.

``UV``는 왼쪽에서 오른쪽, 위쪽에서 아래쪽까지 0~1 사이입니다.

../../../_images/iconuv.png
void fragment() {
  COLOR = vec4(UV, 0.5, 1.0);
}
../../../_images/UV.png

TEXTURE 내장 사용

기본 조각 함수는 설정된 Sprite2D 텍스처에서 읽어서 표시합니다.

Sprite2D에서 색상을 조정하려면 아래 코드와 같이 텍스처의 색상을 수동으로 조정할 수 있습니다.

void fragment(){
  // This shader will result in a blue-tinted icon
  COLOR.b = 1.0;
}

Sprite2D와 같은 특정 노드에는 TEXTURE``를 사용하여 셰이더에서 액세스할 있는 전용 텍스처 변수가 있습니다. Sprite2D 텍스처를 사용하여 다른 색상과 결합하려는 경우 ``UV``를 ``texture 함수와 함께 사용하여 이 변수에 액세스할 수 있습니다. 이를 사용하여 텍스처로 Sprite2D를 다시 그립니다.

void fragment(){
  COLOR = texture(TEXTURE, UV); // Read from texture again.
  COLOR.b = 1.0; //set blue channel to 1.0
}
../../../_images/blue-tex.png

Uniform 입력

균일한 입력은 전체 셰이더에서 동일한 데이터를 셰이더로 전달하는 데 사용됩니다.

다음과 같이 셰이더 상단에 유니폼을 정의하여 사용할 수 있습니다.

uniform float size;

사용에 대한 자세한 정보는 셰이딩 언어 문서를 참조하세요.

Sprite2D에서 파란색의 양을 변경하려면 유니폼을 추가하세요.

uniform float blue = 1.0; // you can assign a default value to uniforms

void fragment(){
  COLOR = texture(TEXTURE, UV); // Read from texture
  COLOR.b = blue;
}

이제 편집기에서 Sprite2D의 파란색 양을 변경할 수 있습니다. 셰이더를 생성한 위치 아래에서 인스펙터를 다시 살펴보세요. "셰이더 Param"이라는 섹션이 표시됩니다. 해당 섹션을 펼치면 방금 선언한 유니폼이 표시됩니다. 편집기에서 값을 변경하면 셰이더에 제공한 기본값을 덮어쓰게 됩니다.

쿼터니언(quaternions) 으로 보간하기

노드의 재료 자원에서 호출되는 set_shader_parameter() 함수를 사용하여 코드에서 유니폼을 변경할 수 있습니다. Sprite2D 노드를 사용하면 다음 코드를 사용하여 blue 유니폼을 설정할 수 있습니다.

var blue_value = 1.0
material.set_shader_parameter("blue", blue_value)

유니폼의 이름은 문자열입니다. 문자열은 철자와 대소문자를 포함하여 셰이더에 작성된 방식과 정확히 일치해야 합니다.

첫 번째 정점 함수

이제 우리에게 프래그먼트 함수가 있으니 버텍스 함수를 작성해 보겠습니다.

정점 함수를 사용하여 화면에서 각 정점이 끝나야 하는 위치를 계산합니다.

정점함수에서 가장 중요한 변수는 ``VERTEX``이다. 처음에는 모델의 꼭지점 좌표를 지정하지만 해당 꼭지점을 실제로 그릴 위치를 결정하기 위해 쓰기도 합니다. ``VERTEX``는 처음에 로컬 공간에 표시되는 ``vec2``입니다(즉, 카메라, 뷰포트 또는 상위 노드와 관련되지 않음).

``VERTEX``에 직접 추가하여 정점을 오프셋할 수 있습니다.

void vertex() {
  VERTEX += vec2(10.0, 0.0);
}

TIME 내장 변수와 결합하여 기본 애니메이션에 사용할 수 있습니다.

void vertex() {
  // Animate Sprite2D moving in big circle around its location
  VERTEX += vec2(cos(TIME)*100.0, sin(TIME)*100.0);
}

결론

핵심적으로 셰이더는 지금까지 본 작업을 수행하며 VERTEX``COLOR``를 계산합니다. 해당 변수에 값을 할당하기 위한 더 복잡한 수학적 전략을 생각해내는 것은 여러분에게 달려 있습니다.

영감을 얻으려면 고급 셰이더 튜토리얼을 살펴보고 Shadertoy`The Book of 셰이더 <https://thebookofshaders.com>`_와 같은 다른 사이트를 살펴보세요.