2018년 1월 15일 월요일

GLSL Data Types

GLSL Data Types




Basic types : 기본형


GLSL 에서 Basic type 은 가장 기본이 되는 타입이다. 이에 반해 Non-basic type 이 있는데 이는 basic type의  집합이다.


Basic type에는 Scalars, Vectors, Matrices, Opaque types 들로 다시 세분화 된다.


Scalars


bool  
condition type 즉 조건에 사용되는 타입이다. 이는 true 또는 false 중 하나이다.


int
부호 있는 32 비트 정수이다. two’s complement 즉 2 의  n (32) 승 범위의 수이다.


uint
부호가 없는 32 비트 정수 이다.


float
single-precision 실수 이다.


double
double-precision 실수 이다.


Vectors : 벡터



bvecn
a vector of booleans, bools 벡터이다.


ivecn
vector of signed integers, 부호 있는 정수 백터


uvecn
부호 없는 정수 벡터


vecn
vector of single-precision floating point number, 실수 벡터


dvecn
vector of double precision floating point number , 배정도 실수 벡터


n 의 설명
벡터 형식에서 가장 뒤의 n 은 숫자로 치환될 것이다.
예를 들면 bvecn 이라는 것은 bvec2 , bvec3 와 같이 n 이 해당 벡터의 구성 요소 갯수를 뜻한다.


vec3 이라고 하면 3개의 float 를 갖는 것으로 각각의 이름은 x,y,z 가 된다.
예를 들어


vec3 pos;


라고 한다면
pos.x , pos.y , pos.z 순서로 구성된다.


그러므로 n 은 2,3,4 중 하나이어야 하며 4개의 경우  x,y,z,w 가 된다.

벡터의 연산
벡터 값에는 스칼라 값에 적용되는 동일한 수학 연산자가 적용될 수 있다. 이것들은 모두 각 구성 요소에 대해 구성 요소 별 작업을 수행한다. 그러나 이 연산자가 벡터에 대해 작업하려면 두 벡터가 같은 수의 구성 요소를 가져야한다.

Swizzling
벡터의 각 구성 요소들은 다음과 같이 참조 될 수 있다.


vec4 someVec;
someVec.x + someVec.y;


우리는 벡터의 구성 요소가 위와 같이 참조 되는 것을 swizzling 이라 부른다.
참조 이름들은 각각 x,y,z,w 가 되며 x 는 첫번째, y 는 두번째 … 이런식을 w 는 네번째가 된다.


이를 swizzling (뒤석다라는 뜻) 이라 부르게 된 동기는 다음과 같이 사용될 수 있기 때문이다.


vec2 someVec;
vec4 otherVec = someVec.xyxx;
vec3 thirdVec = otherVec.zyy;


즉 최대 4개의 문자의 조합에 의하여 새로운 벡터를 만들어 낼 수 있기 때문이다.
또한 otherVec.zyy 는 vec3 가 된다.


소스 벡터에 실제로 해당 구성 요소가 있는 한 최대 4 자의 모든 조합을 사용할 수 있다.
즉 vec3 에 대하여 w 를 참조한다면 컴파일 오류가 난다. 그 이유는 vec3 는 w 요소가 없기 때문이다.


Swizzling 은 l-value 즉 좌측 값으로 사용할 수 있다.


vec4 someVec;
someVec.wzyx = vec4(1.0, 2.0, 3.0, 4.0); // Reverses the order.
someVec.zx = vec2(3.0, 5.0); // Sets the 3rd component of someVec to 3.0 and the 1st component to 5.0


그러나 이렇게 좌측 값으로 사용할 때는 같은 요소를 두번 사용할 수 없다.
예를 들어 someVec.xx = vec2(4.0,4.0);
이러한 형식은 허용되지 않는다.


Swizzle mask 즉 구성요소 이름은 3가지를 제공하고 있다.


xyzw  : 좌표
rgba : 색상
stpq : 텍스쳐 좌표


이 3개의 세트는 실제로는 차이가 없다. 그러나 혼용해서 구성할 수는 없다.
“.xrs” 라고 할 수 없다는 것이다.


OpenGL 4.2 부터는 scalars 도 swizzling 할 수 있다. scalar 값은 오직 한개의 요소만 있게 된다.


float aFloat;
vec4 someVec = aFloat.xxxx;




Matrices : 행렬


벡터의 또다른 형태 또는 수학에서의 행렬을 말한다.
모든 행렬의 타입은 floating-point 를 갖고 이는 single-precision 또는 double-precision 이 될 수 있다.


행열을 n x m 의 크기를 갖으며 이는 2,3, 또는 4 의 크기를 갖을 수 있다.


  • matnxm: A matrix with n columns and m rows. OpenGL uses column-major matrices, which is standard for mathematics users.
    Example: mat3x4.
  • matn: A matrix with n columns and n rows. Shorthand for matnxn

OpenGL 4.0 이상에서는 dmat 를 사용하여 double-precision (배정도 실수) 를 사용할 수 있다.

matnxm 은 n행 m 열의 크기를 갖는 행열을 뜻한다.


matn 은 n 행 n 열의 행열을 뜻한다.


행열 자체에 대해서는 swizzling 을 사용할 수 없다. 단 각각의 행열 필드에 대하여 사용할 수 있다. 다음을 참고하라.


mat3 theMatrix;
theMatrix[1] = vec3(3.0, 3.0, 3.0); // Sets the second column to all 3.0s
theMatrix[2][0] = 16.0; // Sets the first entry of the third column to 16.0.


다음과 같이 각 열에 대하여 swizzle 을 사용할 수 있다.


mat3 theMatrix;
theMatrix[1].yzx = vec3(3.0, 1.0, 2.0);





Opaque types


Opaque 형식은 쉐이더가 어떤 방식으로 참조하는 일부 외부 객체를 나타낸다. 이러한 형식은 일반 변수와 다르게 그 “값”을 갖지 않는다. 실제 데이터를 참조하는 일종의 마커인 것이다.
따라서 함수 호출에 대한 인자, 즉 매개 변수로만 사용할 수 있다.
이러한 함수는 참조된 실제 데이터를 반환하거나 수정하는 함수일 것이다.
간단히 말해 c 언어의 포인터 비슷하다고 보면 된다.
이러한 형식에는 다음과 같은 것이 있다.


Samplers
텍스쳐 를 위해 사용할 수 있다.


Images
이미지 로딩가 저장에 사용한다.


Atomic counters
버퍼 오브젝트 내의 메모리 위치를 나타낸다.





Implicit conversion , 암묵적 변환

어떤 형식의 값은 암묵적으로 다른 형식의 값으로 변환이 가능하다. 이 말은 명시적 (explicit) 형식 변환이 필요 없다는 것이다.


signed integer (부호있는 정수) 는 unsigned integer (부호 없는 정수)로 암묵적으로 현형 될 수 있다. 그러나 그 반대는 항상 가능하지는 않다.


모든 정수 타입은 실수 타입으로 변경 가능하다. 또한 정수와 실수는 배정도 실수 (double)로 변환 될 수 있다.


벡터 역시 그 구성원의 기본형이 서로 변환 가능하면 암묵적 변환이 가능하다.



Arrays 배열


Basic type 기본형들은 다수의 요소들의 연속된 집합으로 만들 수 있다. 이는 C/C++ 의 배열과 매우 유사하지만 몇가지 제약을 둔다.
무엇보다 다차원 배열을 할수 없다는 것이 가장 큰 차이가 된다.


그러나 OpenGL 4.3 이후 부터는 Array of array 에 의하여 다차원을 구현할 수 있다.


배열의 크기는 상수 표현식으로 초기화 할 수 있다.


Geometry, Tessellation Control 과 Tessellation Evaluation Shader 입력되는 배열은 크기가 필요 없다.


전역 변수로 배열을 선언할 경우 그 크기가 없이 선언이 가능하나 나중에 그 크기를 선언해야 사용할 수 있다.


배열 크기는 컴파일시 정수 상수 표현식 이어야 한다.


몇 가지 예외를 제외하고는 모든 Storage Qualifier 유형의 변수에 대해 배열을 사용할 수 있다.


Fragment Shader의 출력은 배열이 될 수 없다.

배열의 길이는 다음과 같이 계산할 수 있다.


uniform float myValues[12];

...

myValues.length();    // Returns 12.

Opaque arrays

설명 생략…



Arrays of arrays

Core version 4.6 부터 사용 가능


uniform vec3 multidim[5][2];


uniform vec3[5][2] multidim;




Structs


Structs 는 C++ 의 구조체와 비슷하다.
GLSL 은 익명의 구조체를 지원하지 않는다. 익명의 구조체는 type name이 없는 구조체를 말한다. 또한 구조체는 적어도 하나의 멤버가 있어야 한다.


구조체는 또다른 구조체 안에 선언될 수 없다. 단 구조체 는 또다른 구조체 안에서 멤버로서 사용될 수는 있다.


struct Light
{
 vec3 eyePosOrDir;
 bool isDirectional;
 vec3 intensity;
 float attenuation;
} variableName;


위의 예에서 구조체 type은 Light 이고 변수 이름은 variableName 이다. C/C++ 과 같이 변수 이름은 생략될 수 있다.


구조체의 각 멤버에 대한 접근은 C/C++ 과 같은 형식으로 “.” 을 사용한다.




Constructors and initializers


생산자와 초기화


다음을 제외한 거의 모든 데이터 타입은 초기화 값으로 초기화 될 수 있다.



초기화 방법은 다음과 같다.


uniform int aValue = 5;


유니폼을 초기화하는 것은 프로그램 객체가 성공적으로 컴파일되고 링크 된 순간에만 변수를 설정 한다는 점에 유의해야 한다.


사용자는 해당 값을 수동으로 설정 하여 변경할 수 있다.

Literals , 리터럴


리터럴은 쉐이더에 기록된 값을 말한다. 이러한 리터럴 값은 모두 기본형의 값으로 기본형의 값을 초기화 하는데 사용될 수 있다. 또한 기본형의 상수로도 사용되어질 수 있다.


bool type의 리터럴은 true 와 false 이다.


정수 값은 기본적으로 int (부호 있는 정수) 형의 값이다. 만약 unsigned int 값을 사용하기 위해서는 숫자의 suffix 로 u 또는  U 를 사용하기 바란다.


C/C++ 에서와 같이 정소는 8진수 또는 16진수를 표시할 수 있다.  prefix 가 0 이면 8진수 , 0x 이면 16진수가 된다.


실수의 값 (소숫점이 있는 숫자)은 기본적으로 float 형 이다. 만약 소숫점이 없는 숫자를 실수로 만들기 위해서는 suffix 에 f 또는 F를 붙여 사용할 수 있으며 이러한 방법은 C/C++ 과 같다.


실수형은 지수형 표현이 가능하다. e 또는 E 문자로 실수와 지수를 구분하면 된다. 지수형은 항상  base-10 의 숫자이다. 즉 몇 의 10의 몇승 .. 이런 식이 된다.


GLSL 4.0 이후부터 double-precision float 를 사용할 수 있으며, 이러한 숫자를 만들기 위하여 suffix 에 lf 또는 LF 를 사용한다.


Constructors


기본형 이 아닌 복잡한 구조의 형식은 다음과 같은 constructor 에 의하여 초기화 되어질 수 있다.


typename​(value1​, value2​, ...)

여기서 typename은 construct 하기 위한 type의 이름 이고 value들은 리터럴 또는 미리 정의 한 변수들 또는 또다른 constructor 가 될 수 있다.


몇 개의 constructor들은 특별한 문법을 따라야 하는 경우도 있다.

Conversion constructors


기본 스칼라 타입 constructor들은 다른 type 으로 변환 될 수 있다.


from bool


만약 false 이면 정수는 0, 실수는 0.0 으로 변환 된다. 만약 true 이면 1로 변환될 것이다.


to bool


0 또는 0.0 은 모두 false 가 된다. 그외의 숫자는 true 가 된다.


between int and uint


해당 숫자의 bit 크기가 허용하는 범위에서 변환이 된다. 부호가 바뀔 수 있다.

Vector constructors


벡터의 생성자는 저장될 숫자들에 의하여 구성될 수 있다. vec3 는 3개의 숫자를 갖는다. 모든 벡터들은 단일 숫자에 의하여 생성될 수 있으며 이는 벡터의 모든 요수들의 값이 이 하나의 숫자로 설정된다는 것을 뜻한다.


그러므로 vec3(1.0) 은 vec3(1.0,1.0,1.0) 과 같다.


다음을 참고하기 바란다.
vec4(vec2(10.0, 11.0), 1.0, 3.5) == vec4(10.0, vec2(11.0, 1.0), 3.5);
vec3(vec4(1.0, 2.0, 3.0, 4.0)) == vec3(1.0, 2.0, 3.0);
vec4(vec3(1.0, 2.0, 3.0)); // error. Not enough components.
vec2(vec3(1.0, 2.0, 3.0)); // error. Too many components.


Matrix constructors


행렬에 대한 생성은 복잡하다. 만약 single scalar value를 가지고 생성된 행렬은 모든 행렬이 해당 값으로 초기화 되는 것이 아니라 행렬의 대각선 방향의 요소만 해당 값으로 초기화 된다.


만약 mat4(1.0) 일 경우 이러한 행렬은 identity matrix 즉 단위행렬이 된다.


복수의 값에 의한 생성은 행 우선 값으로 채워 진다. 즉 x 의 값은 첫번째 행에 할당되고 그다음 x 값은 다음 행에 할당 된다.


이러한 예를 다음에 보여준다.


mat2(
 float, float,   // first column
 float, float);  // second column

mat4(
 vec4,           // first column
 vec4,           // second column
 vec4,           // third column
 vec4);          // fourth column

mat3(
 vec2, float,    // first column
 vec2, float,    // second column
 vec2, float);   // third column


다른 행렬을 이용하여 새로운 행렬을 만들어 낼 수 있다. 이 경우 해당 행렬의 모든 행과 열은 새롭게 만들어지는 행렬에 복사 된다.


만약 복사될 행렬에 값이 없다면 해당 행렬의 값은 단위행렬 값으로 채워진다.


mat3 diagMatrix = mat3(5.0);  // Diagonal matrix with 5.0 on the diagonal.
mat4 otherMatrix = mat4(diagMatrix);


위의 예에서 otherMatrix 는 mat3 보다 큰 mat4 이다. 이경우 대각선 방향으로 3행 3열까지는 5.0 으로 채워 지지만 마지막 대각선 행열 값은 1.0 으로 될 것이다.


기존의 행렬에 의하여 새로운 행렬을 만들어 낼 경우 그 크기에 대한 제약은 없다. 예를 들면 4x2 행렬은 2x4 행렬로부터 초기화 될수도 있다는 것이다.


Array constructors


다음 형식과 같이 초기화되어 생성할 수 있다.
const float array[3] = float[3](2.5, 7.0, 1.5);


생성되는 array의 크기는 생략 가능하다. 생략된 경우 오른쪽 행렬의 크기를 따른다.


Struct Constructors


다음과 같이 생성할 수 있다.


struct Data
{
 float first;
 vec2 second;
};

Data dataValue = Data(1.4, vec2(16.0, 22.5));


Struct constructor에는 vector constructor 를 사용할 수 있다. 이러한 constructor들은 내포(nested)  될 수 있다. 그러므로 다음과 같은 구조를 만들 수 있다.


Data dataArray[3] = Data[3](
 Data(1.0, vec2(-19.0, 4.5)),
 Data(-3.0, vec2(2.718, 2.0)),
 Data(29.5, vec2(3.142, 3.333)));

Initializer lists


Data dataArray[3] = Data[3](
 Data(1.0, vec2(-19.0, 4.5)),
 Data(-3.0, vec2(2.718, 2.0)),
 Data(29.5, vec2(3.142, 3.333)));


C++11 과 같은 형식으로 초기화를 수행할 수 있따. 바로 { } 로 둘러 쌓여 수행할 수 있다.


Data dataArray[3] = {
 {1.0, {-19.0, 4.5} },
 {-3.0, {2.718, 2.0} },
 {29.5, {3.142, 3.333} } };

댓글 없음:

댓글 쓰기

Vertex , 정점 정보의 확장

Vertex , 정점 정보의 확장 그동안의 설명에 있어서 우리는 VERTEX 정보에 대하여 3 차원의 위치 정보만 사용하였다. struct VERTEX {float x,y,z;}; 이제 이를 확장하여 색상을...