[OpenGL ES] 9. SL, Shader Language (쉐이더 언어)

[OpenGL ES] 9. SL, Shader Language (쉐이더 언어)


Shader Language(이하 SL)

OpenGL ES, shader 언어는 표준 c와 비슷하다. 변수 선언과 함수 문법도 같고, if-then-else, 반복문도 같다. 심지어 #if, #ifdef, #define과 같은 매크로도 있다.


OpenGL ES, shader language는 가능한 한 빠르게 실행되도록 만들어야 하니, 반복문이나 조건문 사용에 신중히 처리해야 한다. Shader는 GPU가 처리하고, 부동 소수점(float) 계산에 최적화되어 있다는 것을 기억해라.


OpenGL ES, SL은 고유한 데이터 타입을 가지고 있다.


 SL's Data Type

 Same as C

 Description

 void

 void

 Can represent any data type 

 float

 float

 The range depends on the precision

 bool

 unsigned char

 0 to 1

 int

 char/short/int

 The range depends on the precision

 vec2

 -

 Array of 2 float. {x,y}, {r,g}, {s,t}

 vec3

 -

 Array of 3 float. {x,y,z}, {r,g,b}, {s,t,r}

 vec4

 -

 Array of 4 float. {x,y,z,w}, {r,g,b,a}, {s,t,r,q}

 bvec2

 -

 Array of 2 float. {x,y}, {r,g}, {s,t}

 bvec3

 -

 Array of 3 float. {x,y,z}, {r,g,b}, {s,t,r}

 bvec4

 -

 Array of 4 float. {x,y,z,w}, {r,g,b,a}, {s,t,r,q}

 mat2

 -

 Array of 2 float. {x,y}, {r,g}, {s,t}

 mat3

 -

 Array of 3 float. {x,y,z}, {r,g,b}, {s,t,r}

 mat4

 -

 Array of 4 float. {x,y,z,w}, {r,g,b,a}, {s,t,r,q}

 sampler2D

 -

 Special type to access a 2D texture

 samplerCube

 -

 Special type to access a Cube (3D texture)


모든 vector 데이터 타입은 (vec*, bvec*, ivec*) “.” 기호나 [x]처럼 배열을 통해서 요소에 접근할 수 있다.


OpenGL ES, xyzw, rgba, strg들은 벡터에 접근할 수 있는 요소들이다. 예를 들어 .xyz는 vec4에서 앞의 3개 요소를 나타낸다(x,y,z,w 중 x,y,z). Vec2에서는 .xyz요소가 없기 때문에 쓸 수 없다. vec2는 .xy뿐이다.


요소의 순서도 바꿀 수 있다. vec4에서 .yzx는 2번째, 3번째, 1번째 요소를 가져온다. vec 데이터 타입은 벡터의 xyzw, 색의 rgba, 텍스쳐 좌표 strg로 쓰일 수 있다.


하지만 .xrt 처럼 섞어서 사용할 수는 없다.


1
2
3
4
5
6
7
8
9
vec4 myVec4 = vec4(0.01.02.03.0);  
vec3 myVec3;  
vec2 myVec2;
 
myVec3 = myVec4.xyz; // myVec3 = {0.0, 1.0, 2.0};  
myVec3 = myVec4.zzx; // myVec3 = {2.0, 2.0, 0.0};  
myVec2 = myVec4.bg;  // myVec2 = {2.0, 1.0};  
myVec4.xw = myVec2;  // myVec4 = {2.0, 1.0, 2.0, 1.0};  
myVec4[1= 5.0;     // myVec4 = {2.0, 5.0, 2.0, 1.0};  
cs


매우 간단한 OpenGL ES 예제다.


이젠 변환에 대해서 알아보는데 변환할 때엔 주의가 필요하다. SL은 소수점(이하 정밀도)을 사용해 데이터 타입의 최소값, 최대값을 정한다. 변수 선언 시 그 앞에 붙여서 쓴다.


OpenGL ES SL[[OpenGL ES] 9. SL, Shader Language (쉐이더 언어)]


데이터 타입의 범위는 하드웨어에 따라 달라질 수 있으며, 아래 표는 OpenGL ES, SL에서 규정한 최소한의 범위다.


 Precision

 Floation Point Range

 Integer Range

 lowp

 -2.0 to 2.0

 -256 to 256

 mediump

 -16,384.0 to 16,384.0

 -1,024 to 1,024

 highp

 -4,611,686,018,427,387,904.0 to 4,611,686,018,427,387,904.0

 0 to 1


변수마다 앞에 정밀도를 붙이는 대신, precision 키워드로 전역에 적용할 수도 있다. 정밀도 한정자는 데이터 타입을 바꿀 때 필요하다.


가능하면 피하는 게 좋지만, 정말 필요할 때에는 도움을 될 것이다. 예를 들어 float를 int로 바꿀 때 mediump float와 lowp int를 쓸 수 있다. 만약 lowp float를 lowp int로 바꾸면 -2~2의 정수 값만 받을 수 있다.


변환 시에는 OpenGL ES 내장된 함수를 써야 한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
precision mediump float;  
precision lowp int;
 
vec4 myVec4 = vec4(0.01.02.03.0);  
ivec3 myIvec3;  
mediump ivec2 myIvec2;
 
// This will fail. Because the data types are not compatible.
//myIvec3 = myVec4.zyx;
 
myIvec3 = ivec3(myVec4.zyx);    // This is OK.  
myIvec2.x = myIvec3.y;            // This is OK.
 
myIvec2.y = 1024;
 
// This is OK too, but the myIvec3.x will assume its maximum value.
// Instead 1024, it will be 256, because the precisions are not
// equivalent here.
myIvec3.x = myIvec2.y;  
cs


floating-point(부동 소수점)로 연산하는 게 성능상 좋다(GPU 때문에). 곱셈이나 다른 연산에도 부동 소수점을 쉽게 쓸 수 있다.


행렬 타입(Matrices), 벡터 타입(vectors), 부동 소수점 타입(float) 모두 호환이 된다. 행렬의 곱셈(matrices multiplications)처럼 복잡한 연산도 한 줄로 해결된다.


OpenGL ES Shader language[[OpenGL ES] 9. SL, Shader Language (쉐이더 언어)]


아래처럼 말이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mat4 myMat4;  
mat3 myMat3;  
vec4 myVec4 = vec4(0.01.02.03.0);  
vec3 myVec3 = vec3(-1.0-2.0-3.0);  
float myFloat = 2.0;
 
// A mat4 has 16 elements, could be constructed by 4 vec4.
myMat4 = mat4(myVec4,myVec4,myVec4,myVec4);
 
// A float will multiply each vector value.
myVec4 = myFloat * myVec4;
 
// A mat4 multiplying a vec4 will result in a vec4.
myVec4 = myMat4 * myVec4;
 
// Using the accessor, we can multiply two vector of different orders.
myVec4.xyz = myVec3 * myVec4.xyz;
 
// A mat3 produced by a mat4 will take the first 9 elements.
myMat3 = mat3(myMat4);
 
// A mat3 multiplying a vec3 will result in a vec3.
myVec3 = myMat3 * myVec3;  
cs


C언어처럼 여러 종류의 데이터 타입의 배열에도 사용할 수 있고, 구조체도 정의가 가능하다.


C언어처럼 OpenGL ES, SL은 프로그램의 시작 함수인 void main()을 갖고 있어야 한다(main이 없으면 컴파일 불가). SL의 함수는 C언어와 동일하게 동작하지만, SL은 inline 언어라는 걸 기억해라. 함수는 호출되기 전에 만들어져야 한다. 따라서, void main() 앞에 함수를 놓아야 한다.


자, 이제 깊게 들어가서 정확히 vertex, fragment shader가 뭘 만드는지 알아보자.


출처 : All About OpenGL ES 2.X 번역

[OpenGL ES] 9. SL, Shader Language (쉐이더 언어)

댓글(0)

Designed by JB FACTORY