연산자
식은 연산자에 의해 문장 부호가 붙은 변수 및 리터럴의 시퀀스입니다. 연산자는 변수와 리터럴이 결합되고 비교되고 선택되는 등의 방법을 결정합니다. 연산자는 다음과 같습니다.
운영자 이름 | 연산자 |
---|---|
가산 연산자 및 곱하기 연산자 | +, -, *, /, % |
배열 연산자 | [i] |
할당 연산자 | =, +=, -=, *=, /=, %= |
이진 캐스트 | 부동 소수 및 int에 대한 C 규칙, 부울에 대한 C 규칙 또는 HLSL 내장 함수 |
비트 연산자 | ~, <<, >>, &, |, ^, <<=, >>=, &=, |=, ^= |
부울 수학 연산자 | & &, ||, ?: |
캐스트 연산자 | (형식) |
쉼표 연산자 | , |
비교 연산자 | <, >, ==, !=, <=, >= |
접두사 또는 후위 연산자 | ++, -- |
구조 연산자 | . |
단항 연산자 | !, -, + |
대부분의 연산자는 구성 요소별로 수행되므로 각 변수의 각 구성 요소에 대해 연산이 독립적으로 수행됩니다. 예를 들어 1-구성 요소 변수에는 하나의 연산이 수행됩니다. 반면에 4-구성 요소 변수에는 각 구성 요소에 대해 하나씩 4번의 연산이 수행됩니다.
+ 및 *와 같이 값에 대해 작업을 수행하는 모든 연산자는 각 구성 요소별로 작동합니다.
비교 연산자는 다중 구성 요소 변수와 함께 전체 또는 모든 내장 함수를 사용하지 않는 한 단일 구성 요소가 작동해야 합니다. if 문에는 단일 bool이 필요하지만 bool4를 받기 때문에 다음 연산이 실패합니다.
if (A4 < B4)
다음 연산은 성공합니다.
if ( any(A4 < B4) )
if ( all(A4 < B4) )
이진 캐스트 연산자 asfloat, asint 등은 각 구성 요소별로 작동합니다. 특수 규칙이 문서화된 asdouble은 예외입니다.
마침표, 쉼표 및 배열 대괄호와 같은 선택 연산자는 구성 요소별로 작동하지 않습니다.
캐스트 연산자는 구성 요소 수를 변경합니다. 다음 캐스트 연산은 해당 동등성을 보여 줍니다.
(float) i4 -> float(i4.x)
(float4)i -> float4(i, i, i, i)
가산 연산자 및 곱하기 연산자
가산 연산자 및 곱하기 연산자는 +, -, *, /, %입니다.
int i1 = 1;
int i2 = 2;
int i3 = i1 + i2; // i3 = 3
i3 = i1 * i2; // i3 = 1 * 2 = 2
i3 = i1/i2; // i3 = 1/3 = 0.333. Truncated to 0 because i3 is an integer.
i3 = i2/i1; // i3 = 2/1 = 2
float f1 = 1.0;
float f2 = 2.0f;
float f3 = f1 - f2; // f3 = 1.0 - 2.0 = -1.0
f3 = f1 * f2; // f3 = 1.0 * 2.0 = 2.0
f3 = f1/f2; // f3 = 1.0/2.0 = 0.5
f3 = f2/f1; // f3 = 2.0/1.0 = 2.0
모듈러스 연산자는 나누기의 나머지 부분을 반환합니다. 정수 및 부동 소수점 숫자를 사용할 때 다른 결과가 발생합니다. 소수인 정수 나머지 부분은 잘립니다.
int i1 = 1;
int i2 = 2;
i3 = i1 % i2; // i3 = remainder of 1/2, which is 1
i3 = i2 % i1; // i3 = remainder of 2/1, which is 0
i3 = 5 % 2; // i3 = remainder of 5/2, which is 1
i3 = 9 % 2; // i3 = remainder of 9/2, which is 1
정수 사용 시 모듈러스 연산자는 소수 나머지를 자릅니다.
f3 = f1 % f2; // f3 = remainder of 1.0/2.0, which is 0.5
f3 = f2 % f1; // f3 = remainder of 2.0/1.0, which is 0.0
% 연산자는 양쪽이 모두 양수이거나 음수인 경우에만 정의됩니다. C와 달리 부동 소수점 데이터 형식과 정수에서도 작동합니다.
배열 연산자
배열 구성원 선택 연산자 "[i]"는 배열에서 하나 이상의 구성 요소를 선택합니다. 0부터 시작하는 인덱스를 포함하는 대괄호 집합입니다.
int arrayOfInts[4] = { 0,1,2,3 };
arrayOfInts[0] = 2;
arrayOfInts[1] = arrayOfInts[0];
배열 연산자를 사용하여 벡터에 액세스할 수도 있습니다.
float4 4D_Vector = { 0.0f, 1.0f, 2.0f, 3.0f };
float 1DFloat = 4D_Vector[1]; // 1.0f
배열 연산자는 추가적인 인덱스를 추가하여 행렬에 액세스할 수도 있습니다.
float4x4 mat4x4 = {{0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} };
mat4x4[0][1] = 1.1f;
float 1DFloat = mat4x4[0][1]; // 0.0f
첫 번째 인덱스는 0부터 시작하는 행 인덱스입니다. 두 번째 인덱스는 0부터 시작하는 열 인덱스입니다.
대입 연산자
할당 연산자는 =, +=, -=, *=, /=입니다.
변수에는 리터럴 값이 할당될 수 있습니다.
int i = 1;
float f2 = 3.1f;
bool b = false;
string str = "string";
변수에는 수학 연산의 결과가 할당될 수도 있습니다.
int i1 = 1;
i1 += 2; // i1 = 1 + 2 = 3
변수는 등호의 양쪽에서 사용할 수 있습니다.
float f3 = 0.5f;
f3 *= f3; // f3 = 0.5 * 0.5 = 0.25
소수점 변수의 분할은 소수점 나머지가 문제가 되지 않기 때문에 예상대로입니다.
float f1 = 1.0;
f1 /= 3.0f; // f1 = 1.0/3.0 = 0.333
분할될 수 있는 정수(특히 잘림이 결과에 영향을 주는 경우)를 사용하는 경우 주의해야 합니다. 이 예제는 데이터 형식을 제외하고 이전 예제와 동일합니다. 잘림으로 인해 매우 다른 결과가 발생합니다.
int i1 = 1;
i1 /= 3; // i1 = 1/3 = 0.333, which gets truncated to 0
이진 캐스트
int와 float 간의 캐스팅 작업은 int 형식을 자르기 위한 C 규칙에 따라 숫자 값을 적절한 표현으로 변환합니다. 부동 소수 자릿수에서 int로 값을 캐스팅하고 부동 소수 자릿수로 다시 캐스팅하면 대상의 정밀도에 따라 손실 변환이 발생합니다.
이진 캐스트는 숫자의 비트 표현을 대상 데이터 형식으로 재해석하는 내장 함수(DirectX HLSL)를 사용하여 수행할 수도 있습니다.
asfloat() // Cast to float
asint() // Cast to int
asuint() // Cast to uint
비트 연산자
HLSL은 다른 연산자와 관련하여 C와 동일한 우선 순위를 따르는 다음 비트 연산자를 지원합니다. 다음 표는 연산자들에 대해 설명합니다.
참고
비트 연산자는 Direct3D 10 이상의 하드웨어가 있는 셰이더 모델 4_0이 필요합니다.
연산자 | 기능 |
---|---|
~ | 논리적 NOT |
<< | 왼쪽 Shift |
>> | 오른쪽 Shift |
& | 논리적 And |
| | 논리 Or 연산입니다. |
^ | 논리적 Xor |
<<= | 왼쪽 Shift Equal |
>>= | 오른쪽 Shift Equal |
&= | And Equal |
|= | Or Equal |
^= | Xor Equal |
비트 연산자는 int 및 uint 데이터 형식에서만 작동하도록 정의됩니다. float 또는 구조체 데이터 형식에서 비트 연산자를 사용하려고 하면 오류가 발생합니다.
부울 수학 연산자
부울 수학 연산자는 &&& ||, ?:
bool b1 = true;
bool b2 = false;
bool b3 = b1 && b2 // b3 = true AND false = false
b3 = b1 || b2 // b3 = true OR false = true
&&, || 및 ?: C의 단락 평가와 달리 HLSL 식은 벡터 작업이므로 평가를 단락하지 않습니다. 식의 모든 면은 항상 평가됩니다.
부울 연산자는 구성 요소별로 작동합니다. 즉, 두 벡터를 비교하는 경우 결과는 각 구성 요소에 대한 비교의 부울 결과를 포함하는 벡터입니다.
부울 연산자를 사용하는 식의 경우 각 변수의 크기 및 구성 요소 형식은 작업이 발생하기 전에 동일하게 승격됩니다. 승격된 형식은 식의 결과 형식뿐만 아니라 작업이 수행되는 해상도를 결정합니다. 예를 들어 int3 + float 식은 평가를 위해 float3 + float3으로 승격되고 결과는 float3 형식입니다.
캐스트 연산자
괄호 안에 형식 이름이 앞에 오는 식은 명시적 형식 캐스트입니다. 형식 캐스트는 원래 식을 캐스트의 데이터 형식으로 변환합니다. 일반적으로 단순한 데이터 형식을 더 복잡한 데이터 형식(승격 캐스트 포함)으로 캐스팅할 수 있지만, 일부의 복잡한 데이터 형식만 단순한 데이터 형식(강등 캐스트 포함)으로 캐스팅할 수 있습니다.
오른쪽의 형식 캐스팅만 합법적입니다. 예를 들어 (int)myFloat = myInt;
와 같은 식은 불법입니다. 대신 myFloat = (float)myInt;
를 사용하세요.
컴파일러는 암시적 형식 캐스트도 수행합니다. 예를 들어 다음 두 식은 동일합니다.
int2 b = int2(1,2) + 2;
int2 b = int2(1,2) + int2(2,2);
쉼표 연산자
쉼표 연산자(,)는 순서대로 평가할 하나 이상의 식을 구분합니다. 시퀀스의 마지막 식의 값은 시퀀스의 값으로 사용됩니다.
다음은 주목할 필요가 있는 한 가지 사례입니다. 생성자 형식이 실수로 등호의 오른쪽에서 누락된 경우 오른쪽에는 이제 3개의 쉼표로 구분된 4개의 식이 포함됩니다.
// Instead of using a constructor
float4 x = float4(0,0,0,1);
// The type on the right side is accidentally left off
float4 x = (0,0,0,1);
쉼표 연산자는 식을 왼쪽에서 오른쪽 순서로 평가합니다. 그러면 오른쪽이 다음과 같이 단축됩니다.
float4 x = 1;
이 사례에서 HLSL은 스칼라 승격을 사용하므로 결과는 다음과 같이 작성된 것처럼 표시됩니다.
float4 x = float4(1,1,1,1);
이 경우 오른쪽에서 float4 형식을 벗어나는 것은 유효한 문이므로 컴파일러에서 검색할 수 없는 실수일 수 있습니다.
비교 연산자
비교 연산자는 <, >, ==, !=, <=, >=입니다.
스칼라 값보다 큰(또는 작은) 값을 비교합니다.
if( dot(lightDirection, normalVector) > 0 )
// Do something; the face is lit
if( dot(lightDirection, normalVector) < 0 )
// Do nothing; the face is backwards
또는 스칼라 값과 같은(또는 같지 않은) 값을 비교합니다.
if(color.a == 0)
// Skip processing because the face is invisible
if(color.a != 0)
// Blend two colors together using the alpha value
또는 두 값을 결합하고 스칼라 값보다 크거나 같은(또는 작거나 같은) 값을 비교합니다.
if( position.z >= oldPosition.z )
// Skip the new face because it is behind the existing face
if( currentValue <= someInitialCondition )
// Reset the current value to its initial condition
이러한 각 비교는 스칼라 데이터 형식으로 수행할 수 있습니다.
비교 연산자를 벡터 및 행렬 형식과 함께 사용하려면 전체 또는 모든 내장 함수를 사용합니다.
if 문에는 단일 bool이 필요하지만 bool4를 받기 때문에 이 연산이 실패합니다.
if (A4 < B4)
다음 연산들은 성공합니다.
if ( any(A4 < B4) )
if ( all(A4 < B4) )
접두사 또는 후위 연산자
접두사 및 후위 연산자는 ++, --입니다. 접두사 연산자는 식이 평가되기 전에 변수의 내용을 변경합니다. 후위 연산자는 식이 평가된 후 변수의 내용을 변경합니다.
이 경우 루프는 i의 내용을 사용하여 루프 수를 추적합니다.
float4 arrayOfFloats[4] = { 1.0f, 2.0f, 3.0f, 4.4f };
for (int i = 0; i<4; )
{
arrayOfFloats[i++] *= 2;
}
후위 증가 연산자(++)가 사용되므로 arrayOfFloats[i]는 2를 곱한 후 증분합니다. 접두사 증가 연산자를 사용하도록 약간 다시 정렬할 수 있습니다. 두 예제 모두 동일하지만 이쪽이 읽기 더 어렵습니다.
float4 arrayOfFloats[4] = { 1.0f, 2.0f, 3.0f, 4.4f };
for (int i = 0; i<4; )
{
arrayOfFloats[++i - 1] *= 2;
}
접두사 연산자(++)가 사용되므로 arrayOfFloats[i+1 - 1]에서 i가 증분된 후 2를 곱합니다.
접두사 감소 및 후위 감소 연산자(--)는 증가 연산자와 동일한 시퀀스에 적용됩니다. 차이점은 감소가 1을 더하는 대신 1을 뺍니다.
구조 연산자
구조체 멤버 선택 연산자(.)는 마침표입니다. 이 구조가 지정된 경우:
struct position
{
float4 x;
float4 y;
float4 z;
};
다음과 같이 읽을 수 있습니다.
struct position pos = { 1,2,3 };
float 1D_Float = pos.x
1D_Float = pos.y
각 멤버는 구조 연산자를 사용하여 읽거나 쓸 수 있습니다.
struct position pos = { 1,2,3 };
pos.x = 2.0f;
pos.z = 1.0f; // z = 1.0f
pos.z = pos.x // z = 2.0f
단항 연산자
단항 연산자는 !, -, +입니다.
단항 연산자는 단일 피연산자에서 작동합니다.
bool b = false;
bool b2 = !b; // b2 = true
int i = 2;
int i2 = -i; // i2 = -2
int j = +i2; // j = +2
연산자 우선 순위
식에 둘 이상의 연산자가 포함된 경우 연산자 우선 순위에 따라 계산 순서가 결정됩니다. HLSL의 연산자 우선 순위는 C와 동일한 우선 순위를 따릅니다.
설명
중괄호({,})는 문 블록을 시작하고 종료합니다. 문 블록이 단일 문을 사용하는 경우 중괄호는 선택 사항입니다.
관련 항목