OpenGL 쉐이더 프로그래밍 - GLSL 자료형

타입·2025년 7월 22일

컴퓨터 그래픽스

목록 보기
5/24

GLSL 자료형

자료형

  • C types
    int, uint, float, double, bool
  • vectors
    float형: vec2, vec3, vec4 (n차원 벡터)
    (int형 벡터: ivec{n}, boolean형 벡터: bvec{n})
    벡터 하나가 레지스터 하나에 저장
  • matrices
    float형: mat2, mat3, mat4 (nxn 행렬)
    열 우선방식 사용 주의! - C++은 행 우선방식
  • C++ 스타일의 생성자
    vec3 a = vec3(1.0, 2.0, 3.0);
    vec2 b = vec2(a);

vector

레지스터(cluster) 하나에 최대 4개의 float 저장 가능
vec4: 1개의 레지스터 전부 사용
vec3/vec2/float: 각자 1개의 레지스터의 일부만 사용 (나머지는 비어있게)

member 접근은 C 스타일 selection 연산자 "."
float.x, float.y, float.z, float.w

  • float 타입의 값을 자유롭게 저장 가능
    array, 좌표(xyzw), 텍스처 좌표(stpq), RGBA(rgba) 색상 등
    논리적으로는 각 멤버에 접근 가능하지만, 물리적으로는 한 개의 레지스터를 사용

Swizzling 연산

멤버 변수를 뒤섞는 연산
레지스터 레벨에서 병렬 프로세싱 가능

  • 레지스터 멤버들의 효과적 선택/분리
vec4 v = vec4(0.1, 0.2, 0.3, 1.0);
vec4 a = v;

a = v.xyzw // default (0.1, 0.2, 0.3, 1.0)
a = v.wzyx // shuffle (1.0, 0.3, 0.2, 0.1)
a = v.xxyy; // repeat (0.1, 0.1, 0.2, 0.2)
vec3 b = v.xyz; // selection (0.1, 0.2, 0.3)
a.yz = vec2(0.5, 0.6) // (a.x, 0.5, 0.6, a.w)
v.xyzw = v.wzyx // self-swizzling

GLSL Matrix

Matrix

행렬 원소는 float형만 저장 가능

열 우선방식으로 원소 저장 (n x m: n열 m행)

// float
a0

// mat2
a0 a2
a1 a3

// mat3
a0 a3 a6
a1 a4 a7
a2 a5 a8

// mat4
a0	a4	a8	a12
a1	a5	a9	a13
a2	a6	a10	a14
a3	a7	a11	a15
  • 행렬: vector의 집합
    a[1][0] = a행렬의 1열 0행의 원소 반환
    a[1] = a행렬의 1열 vector 반환
    a[1].yzx = vec3(3.0, 1.0, 2.0); // swizzling 연산 가능

실제로는 matrix 값을 shader 프로그램에서 직접 제어할 일은 거의 없음
C의 행 우선 행렬을 GLSL에게 전달 시 열 우선으로 변환하는 기능도 있음

Registers in GPU

전체 행렬은 여러 레지스터에 저장 (레지스터 하나에 벡터 하나가 들어가므로)
mat4라면 4개의 레지스터, mat3라면 3개의 레지스터에 저장

GLSL 언어적 특징

GLSL 특징

  • pointer 자료형이 없음
    vector와 matrix를 기본 자료형으로 사용
    함수의 parameter로 in/out 가능

  • C++ 스타일의 구조체 사용 가능
    구조체도 함수의 parameter로 in/out 가능

  • C/C++ 연산자들 중 일부를 지원

  • 함수 호출 (변수 전달)
    • call by value-return
      변수가 복사되어 들어옴
      변수 반환 시 복사하여 대입
    • in (default) / out / inout
      void func(in float x, out float y)
      {
      	...
      } // 함수 종료 시의 y 값을 복사하여 반환
  • Math Functions
    • Standard C functions
    • 거의 모든 함수에서 병렬 처리 가능

GLSL Qualifiers

Qualifiers

자격 표시자

  • C/C++ qualifier
    const, volatile, readonly, writeonly

  • float의 정밀도 조정 (precision qualifier)
    정밀도에 따른 속도 제어 가능
    highp / mediump / lowp

  • register에 대한 qualifier
    shader 별로 input/output에 따라 사용

  • Uniform Registers
    C/C++ 프로그램에서 미리 세팅, shader 내부에서는 constant 유지
    uniform qualifier로 명시
    uniform mat4 xform;

varying colors 프로그램

각 꼭짓점마다 다른 색상을 가진 삼각형을 하나 그리는 프로그램

vertex shader 쪽에선 색상을 받아 그대로 바이패스
Primitive Assembly와 Rasterization 단계에서 Bi-linear Interpolation 처리되어 삼각형 내부의 색상이 부드럽게 채워짐
결과를 fragment shader에서 받아 화면에 출력

프로그램 디자인

접두사 a는 attribute 레지스터
접두사 v는 varying 레지스터
(uniform 레지스터는 u)

  • vertex shader
    • in vec4 aPos: vertex의 위치
    • in vec4 aColor: vertex의 색상
    • out vec4 vColor: 넘겨줄 색상
void main(void) {
	gl_Position = aPos; // vertex 위치를 그대로 전달
	vColor = aColor; // vertex 색상도 그대로 전달
}
  • fragment shader
    • in vec4 vColor: vertex의 색상
    • out vec4 FragColor: 출력할 색상
void main(void) {
	FragColor = vColor; // vertex 색상을 그대로 전달
}

Vertex Shader 실행

각 프로세서에서 vertex 위치와 vertex 색상을 받아 넘겨줌

// parallel processing (병렬 처리)
GLfloat vertPos[] = {
	-0.5F, -0.5F, 0.0F, 1.0F, // processor #0
	+0.5F, -0.5F, 0.0F, 1.0F, // processor #1
	-0.5F, +0.5F, 0.0F, 1.0F, // processor #2
};

GLfloat vertColor[] = {
	1.0F, 0.0F, 0.0F, 1.0F, // red		- processor #0
	0.0F, 1.0F, 0.0F, 1.0F, // green	- processor #1
	0.0F, 0.0F, 1.0F, 1.0F, // blue		- processor #2
};

Rasterization

varying 레지스터를 이중 선형 보간 처리

  • 가중치에 따른 색상 결정
    vColor = α vColor0 + β vColor1 + γ vColor2
    (α+β+γ = 1)

Fragment Shader 실행

Rasterization 이후의 색상 값을 받음

예제 코드의 컴파일 오류가 계속 발생하였는데 소스 파일에 common.c 파일을 솔루션에 포함시킨 것이 문제였음

#include "./common.c"
이렇게 common.c 파일을 include시키려면 솔루션에 파일을 추가시키면 안됨

만약 솔루션에 추가시키고 싶다면
common.c에 정의한 함수들을 main 코드에서 extern으로 미리 선언해주어야 컴파일 오류가 발생하지 않음

profile
주니어 언리얼 프로그래머

0개의 댓글