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.
Checking the stable version of the documentation...
음영 언어
소개
Godot는 GLSL ES 3.0과 유사한 셰이딩 언어를 사용합니다. 대부분의 데이터 유형과 함수가 지원되며, 남은 몇 가지 데이터 유형과 함수는 시간이 지남에 따라 추가될 가능성이 높습니다.
GLSL에 이미 익숙하다면, :ref:`Godot Shader Migration Guide<doc_converting_glsl_to_godot_shaders>`는 일반 GLSL에서 Godot의 셰이딩 언어로 전환하는 데 도움이 되는 리소스입니다.
데이터 유형
대부분의 GLSL ES 3.0 데이터 유형이 지원됩니다.
유형 |
설명 |
|---|---|
무효 |
Void 데이터 유형으로, 아무것도 반환하지 않는 함수에만 유용합니다. |
부끄러운 |
불리언 데이터 타입으로 |
bvec2 |
부울의 2성분 벡터입니다. |
bvec3 |
부울의 3성분 벡터입니다. |
bvec4 |
부울의 4성분 벡터입니다. |
정수 |
32비트 부호 있는 스칼라 정수입니다. |
ivec2 |
부호 있는 정수로 구성된 2성분 벡터입니다. |
ivec3 |
부호 있는 정수로 구성된 3성분 벡터입니다. |
ivec4 |
부호 있는 정수로 구성된 4성분 벡터입니다. |
단위 |
부호 없는 스칼라 정수; 음수를 포함할 수 없습니다. |
uvec2 |
부호 없는 정수로 구성된 2성분 벡터입니다. |
uvec3 |
부호 없는 정수로 구성된 3성분 벡터입니다. |
uvec4 |
부호 없는 정수로 구성된 4성분 벡터입니다. |
플로트 |
부동 소수점 숫자 (실수) |
vec2 |
부동 소수점 값으로 구성된 2성분 벡터입니다. |
vec3 |
부동 소수점 값으로 구성된 3성분 벡터입니다. |
vec4 |
부동 소수점 값으로 구성된 4성분 벡터입니다. |
매트2 |
2x2 행렬(열 주요 순서). |
매트3 |
3x3 행렬(열 주요 순서). |
매트4 |
4x4 행렬(열 주요 순서). |
샘플러2D |
float로 읽혀지는 2D 텍스처 바인딩을 위한 샘플러 유형입니다. |
isampler2D |
부호 있는 정수로 읽혀지는 2D 텍스처 바인딩을 위한 샘플러 유형입니다. |
usampler2D |
부호 없는 정수로 읽혀지는 2D 텍스처 바인딩을 위한 샘플러 유형입니다. |
예제 |
float로 읽혀지는 2D 텍스처 배열 바인딩을 위한 샘플러 유형입니다. |
예제 |
부호 있는 정수로 읽혀지는 2D 텍스처 배열 바인딩을 위한 샘플러 유형입니다. |
예제 |
부호 없는 정수로 읽혀지는 2D 텍스처 배열 바인딩을 위한 샘플러 유형입니다. |
예제 |
float로 읽혀지는 3D 텍스처 바인딩을 위한 샘플러 유형입니다. |
예제 |
부호 있는 정수로 읽히는 3D 텍스처 바인딩을 위한 샘플러 유형입니다. |
예제 |
부호 없는 정수로 읽히는 3D 텍스처 바인딩을 위한 샘플러 유형입니다. |
샘플러큐브 |
float로 읽혀지는 큐브맵 바인딩을 위한 샘플러 유형입니다. |
예제 |
부동 소수점으로 읽혀지는 큐브맵 배열을 바인딩하기 위한 샘플러 유형입니다. Forward+ 및 Mobile에서만 지원되며 호환성은 지원되지 않습니다. |
예제 |
외부 샘플러 유형. 호환성/Android 플랫폼에서만 지원됩니다. |
이러한 유형은 함수 매개변수나 반환 값으로도 사용할 수 있는 arrays 또는 structs 안에 넣을 수도 있습니다. 배열은 유니폼으로 사용할 수 있지만 구조체는 사용할 수 없습니다.
경고
지역 변수는 ``0.0``와 같은 기본값으로 초기화되지 않습니다. 변수를 먼저 할당하지 않고 사용하면 해당 메모리 위치에 이미 존재하는 모든 값이 포함되어 예측할 수 없는 시각적 결함이 나타납니다. 그러나 유니폼과 가변은 기본값으로 초기화됩니다.
캐스트하기
GLSL ES 3.0과 마찬가지로 크기는 동일하지만 유형이 다른 스칼라와 벡터 간의 암시적 캐스팅은 허용되지 않습니다. 크기가 다른 유형의 캐스팅도 허용되지 않습니다. 변환은 생성자를 통해 명시적으로 수행되어야 합니다.
예시:
float a = 2; // invalid
float a = 2.0; // valid
float a = float(2); // valid
기본 정수 상수는 부호가 있으므로 부호 없는 상수로 변환하려면 항상 캐스팅이 필요합니다.
int a = 2; // valid
uint a = 2; // invalid
uint a = uint(2); // valid
멤버
벡터 유형의 개별 스칼라 멤버는 "x", "y", "z" 및 "w" 멤버를 통해 액세스됩니다. 또는 "r", "g", "b" 및 "a"를 사용하는 것도 작동하며 동일합니다. 귀하의 필요에 가장 적합한 것을 사용하십시오.
행렬의 경우 m[column][row] 인덱싱 구문을 사용하여 각 스칼라에 액세스하거나 m[column]``를 사용하여 열 인덱스별로 벡터에 액세스합니다. 예를 들어 mat4 변환 행렬(4번째 열, 2번째 줄)에서 변환의 y 구성 요소에 액세스하려면 ``m[3][1] 또는 ``m[3].y``를 사용합니다.
건설 중
벡터 유형의 구성은 항상 다음을 통과해야 합니다.
// The required amount of scalars
vec4 a = vec4(0.0, 1.0, 2.0, 3.0);
// Complementary vectors and/or scalars
vec4 a = vec4(vec2(0.0, 1.0), vec2(2.0, 3.0));
vec4 a = vec4(vec3(0.0, 1.0, 2.0), 3.0);
// A single scalar for the whole vector
vec4 a = vec4(0.0);
행렬 유형을 구성하려면 열로 해석되는 행렬과 동일한 차원의 벡터가 필요합니다. matx(float) 구문을 사용하여 대각 행렬을 작성할 수도 있습니다. 따라서 ``mat4(1.0)``는 단위 행렬입니다.
mat2 m2 = mat2(vec2(1.0, 0.0), vec2(0.0, 1.0));
mat3 m3 = mat3(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0));
mat4 identity = mat4(1.0);
행렬은 다른 차원의 행렬로부터 구축될 수도 있습니다. 두 가지 규칙이 있습니다:
1. If a larger matrix is constructed from a smaller matrix, the additional rows and columns are set to the values they would have in an identity matrix. 1. If a smaller matrix is constructed from a larger matrix, the top, left submatrix of the larger matrix is used.
mat3 basis = mat3(MODEL_MATRIX);
mat4 m4 = mat4(basis);
mat2 m2 = mat2(m4);
스위즐링
결과가 다른 벡터 유형(또는 스칼라)인 한 순서에 관계없이 구성 요소의 조합을 얻을 수 있습니다. 이것은 설명된 것보다 보여지는 것이 더 쉽습니다.
vec4 a = vec4(0.0, 1.0, 2.0, 3.0);
vec3 b = a.rgb; // Creates a vec3 with vec4 components.
vec3 b = a.ggg; // Also valid; creates a vec3 and fills it with a single vec4 component.
vec3 b = a.bgr; // "b" will be vec3(2.0, 1.0, 0.0).
vec3 b = a.xyz; // Also rgba, xyzw are equivalent.
vec3 b = a.stp; // And stpq (for texture coordinates).
float c = b.w; // Invalid, because "w" is not present in vec3 b.
vec3 c = b.xrt; // Invalid, mixing different styles is forbidden.
b.rrr = a.rgb; // Invalid, assignment with duplication.
b.bgr = a.rgb; // Valid assignment. "b"'s "blue" component will be "a"'s "red" and vice versa.
정밀도
데이터 유형에 정밀도 수정자를 추가할 수 있습니다. 유니폼, 변수, 인수 및 가변에 사용하십시오.
lowp vec4 a = vec4(0.0, 1.0, 2.0, 3.0); // low precision, usually 8 bits per component mapped to 0-1
mediump vec4 a = vec4(0.0, 1.0, 2.0, 3.0); // medium precision, usually 16 bits or half float
highp vec4 a = vec4(0.0, 1.0, 2.0, 3.0); // high precision, uses full float or integer range (32 bit default)
일부 작업에 낮은 정밀도를 사용하면 관련된 수학 속도가 빨라질 수 있습니다(정밀도는 낮아지지만). 이는 정점 프로세서 기능(대부분의 경우 전체 정밀도가 필요함)에서는 거의 필요하지 않지만 조각 프로세서에서는 종종 유용합니다.
일부 아키텍처(주로 모바일)는 이로 인해 상당한 이점을 얻을 수 있지만 정밀도 간 변환으로 인한 추가 오버헤드와 같은 단점이 있습니다. 자세한 내용은 대상 아키텍처 설명서를 참조하세요. 많은 경우 모바일 드라이버는 일관되지 않거나 예상치 못한 동작을 일으키므로 필요한 경우가 아니면 정밀도를 지정하지 않는 것이 가장 좋습니다.
배열
배열은 유사한 유형의 여러 변수에 대한 컨테이너입니다.
지역 변수(Local Variables)
지역 배열은 함수에서 선언됩니다. 샘플러를 제외하고 허용되는 모든 데이터 유형을 사용할 수 있습니다. 배열 선언은 C 스타일 구문([const] + [precision] + typename + identifier + [array size])을 따릅니다.
void fragment() {
float arr[3];
}
다음과 같이 처음에 초기화될 수 있습니다.
float float_arr[3] = float[3] (1.0, 0.5, 0.0); // first constructor
int int_arr[3] = int[] (2, 1, 0); // second constructor
vec2 vec2_arr[3] = { vec2(1.0, 1.0), vec2(0.5, 0.5), vec2(0.0, 0.0) }; // third constructor
bool bool_arr[] = { true, true, false }; // fourth constructor - size is defined automatically from the element count
하나의 표현식으로 여러 배열(크기가 다른 경우에도)을 선언할 수 있습니다.
float a[3] = float[3] (1.0, 0.5, 0.0),
b[2] = { 1.0, 0.5 },
c[] = { 0.7 },
d = 0.0,
e[5];
배열 요소에 액세스하려면 인덱싱 구문을 사용하세요.
float arr[3];
arr[0] = 1.0; // setter
COLOR.r = arr[0]; // getter
어레이에는 .length() 기능도 내장되어 있습니다(내장된 length() 기능과 혼동하지 마십시오). 어떤 매개변수도 허용하지 않으며 배열의 크기를 반환합니다.
float arr[] = { 0.0, 1.0, 0.5, -1.0 };
for (int i = 0; i < arr.length(); i++) {
// ...
}
참고
0보다 작거나 배열 크기보다 큰 인덱스를 사용하면 셰이더가 충돌하고 렌더링이 중단됩니다. 이를 방지하려면 length(), if 또는 clamp() 함수를 사용하여 인덱스가 0과 배열 길이 사이에 있는지 확인하세요. 항상 신중하게 코드를 테스트하고 확인하세요. 상수 표현식이나 숫자를 전달하면 편집기는 이러한 충돌을 방지하기 위해 경계를 확인합니다.
지역 변수(Local Variables)
전역 공간에서 배열을 const 또는 ``uniform``로 선언할 수 있습니다.
shader_type spatial;
const lowp vec3 v[1] = lowp vec3[1] ( vec3(0, 0, 1) );
uniform lowp vec3 w[1];
void fragment() {
ALBEDO = v[0] + w[0];
}
참고
전역 배열은 선언에 추가된 const 또는 ``uniform``를 제외하고 로컬 배열과 동일한 구문을 사용합니다. 균일한 배열은 기본값을 가질 수 없습니다.
상수
해당 변수를 불변으로 만들려면 변수 선언 앞에 const 키워드를 사용하세요. 즉, 수정할 수 없습니다. 샘플러를 제외한 모든 기본 유형은 상수로 선언될 수 있습니다. 상수 값에 액세스하고 사용하는 것이 유니폼을 사용하는 것보다 약간 빠릅니다. 상수는 선언 시 초기화되어야 합니다.
const vec2 a = vec2(0.0, 1.0);
vec2 b;
a = b; // invalid
b = a; // valid
상수는 수정할 수 없고 추가로 힌트를 가질 수 없지만, 여러 개의 상수(동일한 유형이 있는 경우)를 단일 표현식으로 선언할 수 있습니다.
const vec2 V1 = vec2(1, 1), V2 = vec2(2, 2);
변수와 마찬가지로 배열도 ``const``로 선언할 수 있습니다.
const float arr[] = { 1.0, 0.5, 0.0 };
arr[0] = 1.0; // invalid
COLOR.r = arr[0]; // valid
상수는 전역(함수 외부)으로 선언하거나 로컬(함수 내부)로 선언할 수 있습니다. 전역 상수는 수정이 필요하지 않은 셰이더 전체의 값에 액세스하려는 경우에 유용합니다. 유니폼과 마찬가지로 전역 상수는 모든 셰이더 단계 간에 공유되지만 셰이더 외부에서는 액세스할 수 없습니다.
shader_type spatial;
const float GOLDEN_RATIO = 1.618033988749894;
float 유형의 상수는 소수점 이하 부분에 . 표기법을 사용하거나 과학적 표기법을 사용하여 초기화해야 합니다. 선택적 f 접미사도 지원됩니다.
float a = 1.0;
float b = 1.0f; // same, using suffix for clarity
float c = 1e-1; // gives 0.1 by using the scientific notation
uint``(부호 없는 정수) 유형의 상수에는 부호 있는 정수와 구별하기 위해 ``u 접미사가 있어야 합니다. 또는 uint(x) 내장 변환 기능을 사용하여 이를 수행할 수 있습니다.
uint a = 1u;
uint b = uint(1);
생성자
구조체는 셰이더 코드를 더 효과적으로 추상화하는 데 사용할 수 있는 복합 유형입니다. 다음과 같이 전역 범위에서 선언할 수 있습니다.
struct PointLight {
vec3 position;
vec3 color;
float intensity;
};
선언 후 다음과 같이 인스턴스화하고 초기화할 수 있습니다.
void fragment()
{
PointLight light;
light.position = vec3(0.0);
light.color = vec3(1.0, 0.0, 0.0);
light.intensity = 0.5;
}
또는 동일한 목적으로 구조체 생성자를 사용합니다.
PointLight light = PointLight(vec3(0.0), vec3(1.0, 0.0, 0.0), 0.5);
구조체에는 다른 구조체나 배열이 포함될 수 있으며 전역 상수로 인스턴스화할 수도 있습니다.
shader_type spatial;
...
struct Scene {
PointLight lights[2];
};
const Scene scene = Scene(PointLight[2](PointLight(vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), 1.0), PointLight(vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), 1.0)));
void fragment()
{
ALBEDO = scene.lights[0].color;
}
함수에 전달할 수도 있습니다.
shader_type canvas_item;
...
Scene construct_scene(PointLight light1, PointLight light2) {
return Scene({light1, light2});
}
void fragment()
{
COLOR.rgb = construct_scene(PointLight(vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), 1.0), PointLight(vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 1.0), 1.0)).lights[0].color;
}
연산자
Godot 셰이딩 언어는 GLSL ES 3.0과 동일한 연산자 세트를 지원합니다. 다음은 우선순위에 따른 목록입니다.
우선순위 |
클래스 |
연산자 |
1 (최고) |
괄호 묶기 |
() |
2 |
단항 |
+, -, !, ~ |
3 |
곱나눗셈 |
/, *, % |
4 |
덧뺄셈 |
+, - |
5 |
비트 단위 이동 |
<<, >> |
6 |
부등호 |
<, >, <=, >= |
7 |
등호 |
==, != |
8 |
비트 단위 AND |
& |
9 |
비트 단위 제외 OR |
^ |
10 |
비트 단위 포함 OR |
| |
11 |
논리 AND |
&& |
12 (최저) |
논리 포함 OR |
|| |
참고
벡터 또는 행렬(곱셈, 나눗셈 등)을 허용하는 대부분의 연산자는 구성 요소별로 작동합니다. 즉, 함수는 각 벡터의 첫 번째 값에 적용된 다음 각 벡터의 두 번째 값에 적용됩니다. 몇 가지 예:
연산자 |
동등한 스칼라 연산 |
|---|---|
|
|
|
|
|
|
`GLSL 언어 사양 <http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf>`_은 섹션 5.10 벡터 및 행렬 연산에서 다음과 같이 말합니다.
몇 가지 예외를 제외하고 작업은 구성 요소별로 이루어집니다. 일반적으로 연산자가 벡터나 행렬에 대해 연산을 수행할 때는 벡터나 행렬의 각 구성요소에 대해 구성요소별 방식으로 독립적으로 연산을 수행합니다. [...] 예외는 행렬 곱하기 벡터, 벡터 곱하기 행렬 및 행렬 곱하기입니다. 이는 구성 요소별로 작동하지 않고 올바른 선형 대수 곱셈을 수행합니다.
흐름 제어
Godot Shading 언어는 가장 일반적인 유형의 흐름 제어를 지원합니다:
// `if`, `else if` and `else`.
if (cond) {
} else if (other_cond) {
} else {
}
// Ternary operator.
// This is an expression that behaves like `if`/`else` and returns the value.
// If `cond` evaluates to `true`, `result` will be `9`.
// Otherwise, `result` will be `5`.
int result = cond ? 9 : 5;
// `switch`.
switch (i) { // `i` should be a signed integer expression.
case -1:
break;
case 0:
return; // `break` or `return` to avoid running the next `case`.
case 1: // Fallthrough (no `break` or `return`): will run the next `case`.
case 2:
break;
//...
default: // Only run if no `case` above matches. Optional.
break;
}
// `for` loop. Best used when the number of elements to iterate on
// is known in advance.
for (int i = 0; i < 10; i++) {
}
// `while` loop. Best used when the number of elements to iterate on
// is not known in advance.
while (cond) {
}
// `do while`. Like `while`, but always runs at least once even if `cond`
// never evaluates to `true`.
do {
} while (cond);
최신 GPU에는 무한 루프가 존재할 수 있으며 애플리케이션(편집기 포함)이 정지될 수 있다는 점을 명심하세요. Godot는 이것으로부터 당신을 보호할 수 없으므로, 이런 실수를 하지 않도록 조심하세요!
또한 부동 소수점 값을 숫자와 비교할 때는 정확한 숫자 대신 *범위*와 비교해야 합니다.
``if (value == 0.3)``와 같은 비교는 ``true``로 평가되지 않을 수 있습니다. 부동 소수점 수학은 대략적인 경우가 많으며 예상을 뛰어넘을 수 있습니다. 하드웨어에 따라 다르게 동작할 수도 있습니다.
하지 마세요 이렇게 하지 마세요.
float value = 0.1 + 0.2;
// May not evaluate to `true`!
if (value == 0.3) {
// ...
}
대신 항상 엡실론 값을 사용하여 범위 비교를 수행하십시오. 부동 소수점 숫자가 클수록(그리고 부동 소수점 숫자의 정확도가 낮을수록) 엡실론 값은 더 커야 합니다.
const float EPSILON = 0.0001;
if (value >= 0.3 - EPSILON && value <= 0.3 + EPSILON) {
// ...
}
자세한 내용은 `floating-point-gui.de <https://floating-point-gui.de/>`__을 참조하세요.
폐기
조각, 조명 및 사용자 정의 함수(조각 또는 조명에서 호출됨)는 discard 키워드를 사용할 수 있습니다. 사용하는 경우 조각이 삭제되고 아무 것도 기록되지 않습니다.
``discard``를 사용하면 셰이더를 사용하는 모든 표면에서 깊이 프리패스가 효과적이지 않게 되므로 성능 비용이 발생한다는 점에 유의하세요. 또한 버려진 픽셀은 여전히 정점 셰이더에서 렌더링되어야 합니다. 즉, 모든 픽셀에 ``discard``를 사용하는 셰이더는 처음에 객체를 렌더링하지 않는 것에 비해 렌더링 비용이 여전히 더 많이 듭니다.
함수
Godot 셰이더에서 기능을 정의하는 것이 가능합니다. 다음 구문을 사용합니다.
ret_type func_name(args) {
return ret_type; // if returning a value
}
// a more specific example:
int sum2(int a, int b) {
return a + b;
}
호출하는 함수보다 위에(편집기의 상위) 정의된 함수만 사용할 수 있습니다. 위에서 이미 정의한(또는 내장된 함수 이름) 함수를 다시 정의하면 오류가 발생합니다.
함수 인수에는 특별한 한정자가 있을 수 있습니다:
in: 인수가 읽기 전용임을 의미합니다(기본값).
out: 인수가 쓰기 전용임을 의미합니다.
inout: 인수가 참조를 통해 완전히 전달되었음을 의미합니다.
const: 인수가 상수이고 변경될 수 없으며 in 한정자와 결합될 수 있음을 의미합니다.
아래 예:
void sum2(int a, int b, inout int result) {
result = a + b;
}
함수 오버로딩이 지원됩니다. 이름은 같지만 인수는 다른 여러 함수를 정의할 수 있습니다. ``int``에서 ``float``로(``1``에서 ``1.0``로)와 같이 오버로드된 함수 호출에서 `암시적 캐스팅 <Casting>`_은 허용되지 않습니다.
vec3 get_color(int t) {
return vec3(1, 0, 0); // Red color.
}
vec3 get_color(float t) {
return vec3(0, 1, 0); // Green color.
}
void fragment() {
vec3 red = get_color(1);
vec3 green = get_color(1.0);
}
변화
정점에서 프래그먼트(또는 라이트) 프로세서 함수로 데이터를 전송하기 위해 *가변*이 사용됩니다. *정점 프로세서*의 모든 기본 정점에 대해 설정되고 값은 *조각 프로세서*의 모든 픽셀에 대해 보간됩니다.
shader_type spatial;
varying vec3 some_color;
void vertex() {
some_color = NORMAL; // Make the normal the color.
}
void fragment() {
ALBEDO = some_color;
}
void light() {
DIFFUSE_LIGHT = some_color * 100; // optionally
}
Varying은 배열일 수도 있습니다.
shader_type spatial;
varying float var_arr[3];
void vertex() {
var_arr[0] = 1.0;
var_arr[1] = 0.0;
}
void fragment() {
ALBEDO = vec3(var_arr[0], var_arr[1], var_arr[2]); // red color
}
varying 키워드를 사용하여 조각*에서 *라이트 프로세서로 데이터를 보내는 것도 가능합니다. 그렇게 하려면 조각*에 할당하고 나중에 *빛 기능에서 사용할 수 있습니다.
shader_type spatial;
varying vec3 some_light;
void fragment() {
some_light = ALBEDO * 100.0; // Make a shining light.
}
void light() {
DIFFUSE_LIGHT = some_light;
}
다음과 같은 사용자 정의 기능이나 라이트 프로세서 기능에는 가변 기능이 할당되지 않을 수 있습니다.
shader_type spatial;
varying float test;
void foo() {
test = 0.0; // Error.
}
void vertex() {
test = 0.0;
}
void light() {
test = 0.0; // Error too.
}
이 제한은 초기화 전에 잘못된 사용을 방지하기 위해 도입되었습니다.
보간 한정자
셰이딩 파이프라인 중에 특정 값이 보간됩니다. *보간 한정자*를 사용하여 이러한 보간이 수행되는 방식을 수정할 수 있습니다.
shader_type spatial;
varying flat vec3 our_color;
void vertex() {
our_color = COLOR.rgb;
}
void fragment() {
ALBEDO = our_color;
}
가능한 보간 한정자는 두 가지가 있습니다.
예선 |
설명 |
|---|---|
평평한 |
값은 보간되지 않습니다. |
부드러운 |
값은 올바른 관점으로 보간됩니다. 이것이 기본값입니다. |
유니폼
함수 외부에서 셰이더의 전역 범위에 정의된 *uniforms*를 사용하여 셰이더에 값을 전달하는 것이 가능합니다. 나중에 셰이더가 재질에 할당되면 유니폼이 재질 검사기에서 편집 가능한 매개변수로 나타납니다. 셰이더 내에서는 유니폼을 작성할 수 없습니다. ``void``를 제외한 모든 :ref:`데이터 유형 <doc_shading_언어_data_types>`은 유니폼이 될 수 있습니다.
shader_type spatial;
uniform float some_value;
uniform vec3 colors[3];
머티리얼 인스펙터의 에디터에서 유니폼을 설정할 수 있습니다. 또는 :ref:`코드 <doc_shading_언어_setting_uniforms_from_code>`에서 설정할 수도 있습니다.
Uniform 입력
Godot는 선택적인 유니폼 힌트를 제공하여 컴파일러가 유니폼의 용도와 편집자가 사용자가 유니폼을 수정할 수 있도록 허용하는 방법을 이해할 수 있도록 합니다.
shader_type spatial;
uniform vec4 color : source_color;
uniform float amount : hint_range(0, 1);
uniform vec4 other_color : source_color = vec4(1.0); // Default values go after the hint.
uniform sampler2D image : source_color;
유니폼에는 기본값을 할당할 수도 있습니다.
shader_type spatial;
uniform vec4 some_vector = vec4(0.0);
uniform vec4 some_color : source_color = vec4(1.0);
기본값과 힌트를 추가할 때 기본값은 힌트 뒤에 옵니다.
유니폼 힌트의 전체 목록은 아래와 같습니다:
유형 |
힌트 |
설명 |
|---|---|---|
vec3, vec4 |
source_color |
색상으로 사용됩니다. |
정수 |
힌트_enum("문자열1", "문자열2") |
int 입력을 편집기에 드롭다운 위젯으로 표시합니다. |
정수, 부동 소수점 |
힌트_범위(최소, 최대[, step]) |
범위(최소/최대/단계 포함)의 값으로 제한됩니다. |
샘플러2D |
source_color |
알베도로 사용 |
샘플러2D |
hint_normal |
노멀맵으로 사용됩니다. |
샘플러2D |
hint_default_white |
값 또는 알베도 색상으로 기본값은 불투명한 흰색입니다. |
샘플러2D |
hint_default_black |
값 또는 알베도 색상으로 기본값은 불투명한 검정색입니다. |
샘플러2D |
hint_default_transparent |
값 또는 알베도 색상으로 기본값은 투명한 검정색입니다. |
샘플러2D |
비등방성 |
플로우맵으로 기본값은 오른쪽입니다. |
샘플러2D |
힌트_거칠기[_r, _g, _b, _a, _normal, _gray] |
가져올 때 거칠기 제한에 사용됩니다(반사 앨리어싱을 줄이려는 시도). ``_normal``는 고주파 세부 사항이 있는 영역에서 거칠기가 증가하면서 거칠기 제한기를 안내하는 노멀 맵입니다. |
샘플러2D |
필터[_nearest, _linear][_mipmap][_anisotropic] |
지정된 텍스처 필터링을 활성화했습니다. |
샘플러2D |
반복[_enable, _disable] |
텍스처 반복을 활성화했습니다. |
샘플러2D |
hint_screen_texture |
질감은 화면 질감입니다. |
샘플러2D |
행성 텍스처 만들기 |
텍스처는 깊이 텍스처입니다. |
샘플러2D |
hint_normal_roughness_texture |
텍스처는 일반 거칠기 텍스처입니다(Forward+에서만 지원됨). |
hint_enum 사용
hint_enum 유니폼을 사용하여 읽을 수 있는 드롭다운 위젯으로 int 값에 액세스할 수 있습니다.
uniform int noise_type : hint_enum("OpenSimplex2", "Cellular", "Perlin", "Value") = 0;
GDScript와 유사한 콜론 구문을 사용하여 hint_enum 유니폼에 명시적 값을 할당할 수 있습니다.
uniform int character_speed: hint_enum("Slow:30", "Average:60", "Very Fast:200") = 60;
값은 선택한 옵션의 인덱스(예: 0, 1 또는 2) 또는 콜론 구문으로 할당된 값(예: 30, 60 또는 200)에 해당하는 정수로 저장됩니다. set_shader_parameter()``로 값을 설정할 때는 ``String 이름이 아닌 정수 값을 사용해야 합니다.
RigidBody2D 사용하기
*sRGB 색상 데이터*가 포함된 모든 텍스처를 올바르게 샘플링하려면 source_color 힌트가 필요합니다. 이는 Godot가 선형 색상 공간에서 렌더링하지만 일부 텍스처에는 sRGB 색상 데이터가 포함되어 있기 때문입니다. 이 힌트를 사용하지 않으면 텍스처가 바랜 것처럼 보입니다.
알베도 및 색상 텍스처에는 일반적으로 source_color 힌트가 있어야 합니다. 일반, 거칠기, 금속성 및 높이 텍스처에는 일반적으로 source_color 힌트가 필요하지 않습니다.
Forward+ 및 모바일 렌더러에서는 source_color 힌트를 사용해야 하며, HDR 2D<class_ProjectSettings_property_rendering/viewport/hdr_2d>`가 활성화된 경우 ``canvas_item` 셰이더에서는 필요합니다. source_color 힌트는 호환성 렌더러에 대한 선택 사항이며 HDR 2D``가 비활성화된 경우 ``canvas_item 셰이더에 대한 힌트입니다. 하지만 source_color 힌트는 렌더러를 변경하거나 ``HDR 2D``를 비활성화한 경우에도 작동하므로 항상 사용하는 것이 좋습니다.
Uniform 입력
검사기의 한 섹션에 여러 유니폼을 그룹화하려면 다음과 같이 group_uniform 키워드를 사용할 수 있습니다.
group_uniforms MyGroup;
uniform sampler2D test;
다음을 사용하여 그룹을 닫을 수 있습니다.
group_uniforms;
구문은 하위 그룹도 지원합니다(이 전에 기본 그룹을 선언하는 것이 필수는 아닙니다).
group_uniforms MyGroup.MySubgroup;
벡터 내장 타입
때로는 다양한 셰이더의 매개변수를 한 번에 수정하고 싶을 때가 있습니다. 일반 유니폼의 경우 모든 셰이더를 추적하고 각각에 대해 유니폼을 설정해야 하므로 많은 작업이 필요합니다. 글로벌 유니폼을 사용하면 모든 셰이더, 모든 셰이더 유형(canvas_item, spatial, particles, sky 및 fog)에서 사용할 수 있는 유니폼을 생성하고 업데이트할 수 있습니다.
전역 유니폼은 씬의 많은 객체에 영향을 미치는 환경 효과(예: 플레이어가 근처에 있을 때 나뭇잎이 휘어지거나 객체가 바람에 따라 움직이는 경우)에 특히 유용합니다.
참고
*글로벌 유니폼*은 개인 셰이더의 *글로벌 범위*와 동일하지 않습니다. 일반 유니폼은 셰이더 기능 외부에서 정의되므로 셰이더의 전역 범위인 반면, 전역 유니폼은 전체 프로젝트의 모든 셰이더에 전역적입니다(그러나 각 셰이더 내에서도 전역 범위에 속함).
글로벌 유니폼을 생성하려면 프로젝트 설정**를 연 다음 **셰이더 Globals 탭으로 이동하세요. 유니폼 이름(대소문자 구분)과 유형을 지정한 다음 대화상자 오른쪽 상단에 있는 **추가**를 클릭하세요. 그런 다음 유니폼 목록에서 값을 클릭하여 유니폼에 할당된 값을 편집할 수 있습니다.
프로젝트 설정의 셰이더 Globals 탭에 글로벌 유니폼 추가
글로벌 유니폼을 생성한 후 다음과 같이 셰이더에서 사용할 수 있습니다.
shader_type canvas_item;
global uniform vec4 my_color;
void fragment() {
COLOR = my_color.rgb;
}
전역 유니폼은 셰이더가 저장될 때 프로젝트 설정에 반드시 존재해야 합니다. 그렇지 않으면 컴파일이 실패합니다. 셰이더 코드에서 ``global uniform vec4 my_color = ...``를 사용하여 기본값을 할당할 수 있지만 어쨌든 전역 유니폼은 항상 프로젝트 설정에서 정의되어야 하므로 무시됩니다.
런타임 시 전역 유니폼 값을 변경하려면 스크립트에서 RenderingServer.global_shader_parameter_set 메서드를 사용하세요.
RenderingServer.global_shader_parameter_set("my_color", Color(0.3, 0.6, 1.0))
설정 데이터에는 CPU와 GPU 간의 동기화가 필요하지 않으므로 성능에 영향을 주지 않고 원하는 만큼 전역 균일 값을 할당할 수 있습니다.
또한 여러분의 노드를 반환 타입으로 사용할 수 있습니다:
RenderingServer.global_shader_parameter_add("my_color", RenderingServer.GLOBAL_VAR_TYPE_COLOR, Color(0.3, 0.6, 1.0))
RenderingServer.global_shader_parameter_remove("my_color")
런타임에 전역 유니폼을 추가하거나 제거하면 성능 비용이 발생하지만 스크립트에서 전역 유니폼 값을 가져오는 것과 비교할 때 그다지 뚜렷하지는 않습니다(아래 경고 참조).
인스턴스별 유니폼
때로는 재료를 사용하여 각 노드의 매개변수를 수정하고 싶을 수도 있습니다. 예를 들어, 나무가 가득한 숲에서 각 나무의 색상을 약간씩 다르게 하여 손으로 편집할 수 있게 하려는 경우입니다. 인스턴스별 유니폼이 없으면 각 나무에 대해 고유한 재질을 만들어야 합니다(각각 약간 다른 색조를 가짐). 이는 재료 관리를 더욱 복잡하게 만들고 더 고유한 재료 인스턴스가 필요한 씬로 인해 성능 오버헤드도 발생합니다. 정점 색상도 여기에서 사용할 수 있지만 각 색상에 대해 고유한 메시 복사본을 만들어야 하며 이로 인해 성능 오버헤드도 발생합니다.
인스턴스별 유니폼은 각 머티리얼 인스턴스가 아닌 각 GeometryInstance3D에 설정됩니다. 여러 재질이 할당된 메쉬로 작업하거나 MultiMesh 설정을 사용할 때 이 점을 고려하십시오.
shader_type spatial;
// Provide a hint to edit as a color. Optionally, a default value can be provided.
// If no default value is provided, the type's default is used (e.g. opaque black for colors).
instance uniform vec4 my_color : source_color = vec4(1.0, 0.5, 0.0, 1.0);
void fragment() {
ALBEDO = my_color.rgb;
}
셰이더를 저장한 후 인스펙터를 사용하여 인스턴스별 유니폼 값을 변경할 수 있습니다.
인스펙터의 GeometryInstance3D 섹션에서 인스턴스별 유니폼 값 설정
class_GeometryInstance3D`에서 상속된 노드의 :ref:`set_instance_shader_parameter 메서드를 사용하여 인스턴스별 균일 값을 런타임에 설정할 수도 있습니다.
$MeshInstance3D.set_instance_shader_parameter("my_color", Color(0.3, 0.6, 1.0))
인스턴스별 유니폼을 사용할 때 주의해야 할 몇 가지 제한 사항이 있습니다.
인스턴스별 유니폼은 텍스처나 배열을 지원하지 않으며 일반 스칼라 및 벡터 유형만 지원합니다. 해결 방법으로 텍스처 배열을 일반 유니폼으로 전달한 다음 인스턴스별 유니폼을 사용하여 그릴 텍스처의 인덱스를 전달할 수 있습니다.
참고
GLSL 4.0 이전 버전(예: GLSL 3.3 이하)에서는 샘플러 배열이 컴파일 타임 상수 표현식으로만 인덱싱될 수 있으므로 인스턴스별 유니폼을 사용하여 텍스처 배열을 직접 인덱싱할 수 없습니다. 이는 호환성 렌더러로 컴파일된 셰이더에 영향을 미칩니다.
영향을 받은 경우
switch문을 사용하여 텍스처를 선택하세요.
uniform sampler2D texture_array[2];
instance uniform int texture_index;
void fragment() {
vec4 color;
switch (texture_index) {
case 0:
color = texture(texture_array[0], UV);
break;
case 1:
color = texture(texture_array[1], UV);
break;
}
COLOR = color;
}
셰이더당 인스턴스 유니폼의 실제 최대 제한은 16개입니다.
메시가 여러 재료를 사용하는 경우, 발견된 첫 번째 메시 재료에 대한 매개변수는 동일한 이름, 인덱스 및 유형을 갖지 않는 한 후속 메시 재료보다 "우승"합니다. 이 경우 모든 매개변수가 올바르게 영향을 받습니다.
위와 같은 상황이 발생하면
instance_index힌트를 사용하여 인스턴스 유니폼의 인덱스(0-15)를 수동으로 지정하여 충돌을 피할 수 있습니다.
instance uniform vec4 my_color : source_color, instance_index(5);
코드에서 리소스 불러오기
set_shader_parameter() 메서드를 사용하여 GDScript에서 유니폼을 설정할 수 있습니다.
material.set_shader_parameter("some_value", some_value)
material.set_shader_parameter("colors", [Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)])
참고
``set_shader_parameter()``에 대한 첫 번째 인수는 셰이더의 유니폼 이름입니다. 셰이더의 유니폼 이름과 정확히 일치해야 합니다. 그렇지 않으면 인식되지 않습니다.
GDScript는 GLSL과 다른 변수 유형을 사용하므로 GDScript에서 셰이더로 변수를 전달할 때 Godot는 자동으로 유형을 변환합니다. 다음은 해당 유형의 표입니다.
GLSL 유형 |
GDScript |
메모 |
|---|---|---|
부끄러운 |
부끄러운 |
|
bvec2 |
정수 |
비트 0(LSB)이 x에 해당하는 비트별 압축형 정수입니다. 예를 들어 (bx, by)의 bvec2는 다음과 같은 방법으로 생성될 수 있습니다. bvec2_input: int = (int(bx)) | (int(by) << 1)
|
bvec3 |
정수 |
비트 0(LSB)이 x에 해당하는 비트별 압축형 정수입니다. |
bvec4 |
정수 |
비트 0(LSB)이 x에 해당하는 비트별 압축형 정수입니다. |
정수 |
정수 |
|
ivec2 |
버전 |
|
ivec3 |
버전 |
|
ivec4 |
버전 |
|
단위 |
정수 |
|
uvec2 |
버전 |
|
uvec3 |
버전 |
|
uvec4 |
버전 |
|
플로트 |
플로트 |
|
vec2 |
벡터2 |
|
vec3 |
벡터3, 색상 |
Color를 사용하면 (r, g, b)로 해석됩니다. |
vec4 |
벡터4, 색상, Rect2, 평면, 쿼터니언 |
Color를 사용하면 (r, g, b, a)로 해석됩니다. Rect2를 사용하면 (position.x, position.y, size.x, size.y)로 해석됩니다. Plane을 사용하면 (normal.x,normal.y,normal.z,d)로 해석됩니다. |
매트2 |
변형 |
|
매트3 |
기저 |
|
매트4 |
변형 |
Transform3D를 사용하면 w Vector가 항등으로 설정됩니다. |
샘플러2D |
텍스처 |
|
isampler2D |
텍스처 |
|
usampler2D |
텍스처 |
|
예제 |
예제 |
|
예제 |
예제 |
|
예제 |
예제 |
|
예제 |
텍스처 |
|
예제 |
텍스처 |
|
예제 |
텍스처 |
|
샘플러큐브 |
큐브맵 |
프로젝트를 Godot 3.x에서 4.x로 마이그레이션하는 방법에 대한 지침은 :ref:`doc_upgrading_to_godot_4`를 참조하세요. |
예제 |
예제 |
Forward+ 및 Mobile에서만 지원되며 호환성은 지원되지 않습니다. |
예제 |
텍스처 |
S3TC (모바일/웹 플랫폼은 지원하지 않음). |
참고
유형이 일치하지 않아도 오류가 발생하지 않으므로 GDScript에서 셰이더 유니폼을 설정할 때는 주의하세요. 셰이더는 정의되지 않은 동작을 나타냅니다. 특히 여기에는 GDScript int/float(64비트)를 Godot 셰이더 언어 int/float(32비트)로 설정하는 것이 포함됩니다. 이는 높은 정밀도가 요구되는 경우 의도하지 않은 결과를 초래할 수 있습니다.
Uniform 입력
하나의 셰이더에 사용할 수 있는 셰이더 유니폼의 총 크기에는 제한이 있습니다. 대부분의 데스크톱 플랫폼에서 이 제한은 65536``바이트 또는 4096 ``vec4 유니폼입니다. 모바일 플랫폼에서 제한은 일반적으로 16384``바이트 또는 1024 ``vec4 유니폼입니다. vec2 또는 vec3``와 같이 ``vec4``보다 작은 벡터 유니폼은 ``vec4 크기로 채워집니다. int 또는 float``와 같은 스칼라 유니폼은 패딩되지 않으며, ``bool``는 ``int 크기로 패딩됩니다.
배열은 해당 내용의 전체 크기로 계산됩니다. 이 제한보다 큰 균일한 배열이 필요한 경우 텍스처의 *내용*은 이 제한에 포함되지 않고 샘플러 유니폼의 크기만 계산되므로 대신 데이터를 텍스처로 패킹하는 것이 좋습니다.
인스턴스 편집하기
UV, COLOR 및 VERTEX``와 같은 다양한 내장 변수를 사용할 수 있습니다. 사용할 수 있는 변수는 셰이더의 유형(``spatial, canvas_item, particle 등)과 사용되는 기능(vertex, fragment, light, start, process, sky 또는 fog). 사용 가능한 내장 변수 목록은 해당 페이지를 참조하세요.
내장 함수
GLSL ES 3.0을 준수하는 다양한 내장 기능이 지원됩니다. 자세한 내용은 내장 함수 페이지를 참조하세요.
주석
음영 언어는 C# 및 C++에서 사용되는 것과 동일한 주석 구문을 지원하며, 한 줄 주석에는 ``//``를 사용하고 여러 줄 주석에는 ``/* */``를 사용합니다.
또한 셰이더 매개변수를 가리키면 검사기에 표시되는 문서 설명을 사용할 수 있습니다. 문서 주석은 현재
uniform선언 바로 위에 배치되는 경우에만 지원됩니다. 이러한 문서 주석은 여러 줄 주석 구문(한 줄에 사용되는 경우에도)만 지원하며 앞에 별표 하나만(/*) 대신 두 개 앞에 별표(/**)를 사용해야 합니다.후속 행의 별표는 필수는 아니지만 :ref:`doc_shaders_style_guide`에 따라 권장됩니다. 이러한 별표는 검사기에 의해 자동으로 제거되므로 도구 설명에 표시되지 않습니다.