C와 비슷한 High Level 언어 - main() 함수로 Shader Program 시작
OpenGL 프로그램 컴파일 하여 exe 파일 생성
exe 파일 실행 후 Vertex Shader, Fragment Shader 소스코드 각자 컴파일
GPU는 각 Shader Program을 2개 동시 실행
메모리에서 user data를 vertex input으로 들어오면, 결국 framebuffer로 화면 출력
Vertex Shader의 소스파일을 컴파일하여 obj 파일 생성
Fragment Shader의 소스파일을 컴파일하여 obj 파일 생성
Shader Program에서 각 obj 파일을 attach 후 Link하여 exe 파일 생성
Use하여 GPU에서 exe 파일 실행
vertex data를 제공하면 실행된 Vertex Shader Program과 Fragment Shader Program을 거쳐 결과 출력
vertex data를 정의하기 위해선 좌표계 필요
OpenGL에서 디폴트로 사용하는 좌표계는 x와 y 값이 (-1 ~ +1)로 제한
// OpenGL 3.3 버전의 코어 피쳐만 사용하는 Shader Program
#version 330 core
// input 레지스터 중 하나를 vertexPos라는 이름으로 사용
// vec4 타입으로 4개의 구성요소를 모두 사용
in vec4 vertexPos;
// input 레지스터의 vertexPos로 들어오는 내용을
// output 레지스터의 gl_Position으로 그대로 보냄
void main(void) {
gl_Position = vertexPos; // gl_Position: vertex의 위치
}
- layout 키워드
레지스터 위치 강제 할당
똑같은 레지스터를 두 변수가 사용하려고 하면 컴파일 에러 발생// attribute 레지스터의 5번 위치에 할당 layout (location = 5) in vec4 vertexPos;
(x,y,z,w) 4개씩 묶어 병렬 처리로 실행
동시에 실행하여 Vertex Shader 처리 후 Primitive Assembly 단계에서 삼각형으로 결합
이후 Rasterization 단계에서 삼각형 내부의 픽셀에 대해 Fragment Shader로 전달
GLfloat vertPos[] = {
-0.5F, -0.5F, 0.0F, 1.0F, // processor #1 실행
+0.5F, -0.5F, 0.0F, 1.0F, // processor #2 실행
-0.5F, +0.5F, 0.0F, 1.0F, // processor #3 실행
};
#version 330 core
// output 레지스터를 FragColor라는 이름으로 사용
// vec4(4차원) 타입으로 설정
out vec4 FragColor;
void main(void) {
FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Red Color (RGBA)
}
여러 픽셀에 대해서 동시에 병렬 처리
각 픽셀마다 Fragment Shader를 가져다 붙여 똑같은 프로그램이 실행
결국 모든 픽셀이 빨간색으로 보이게 됨
const char* vertSource =
"#version 330 core \n\
in vec4 vertexPos; \n\
void main(void) { \n\
gl_Position = vertexPos; \n\
}";
const char* fragSource =
"#version 330 core \n\
out vec4 FragColor; \n\
void main(void) { \n\
FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n\
}";
GLuint vert = 0; // vertex shader ID number
GLuint frag = 0; // fragment shader ID number
GLuint prog = 0; // shader program ID number
void initFunc(void) {
// vert: vertex shader
vert = glCreateShader(GL_VERTEX_SHADER); // 어느 타입의 Shader 오브젝트를 만들지 결정, shaderID를 반환
glShaderSource(vert, 1, &vertSource, NULL); // 문자열 형태의 소스코드를 다운로드
glCompileShader(vert); // 컴파일하여 obj 파일 생성
// frag: fragment shader
frag = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(frag, 1, &fragSource, NULL);
glCompileShader(frag);
// prog: program
prog = glCreateProgram(); // Shader Program 생성, programID를 반환
glAttachShader(prog, vert); // 프로그램에 Shader를 연결
glAttachShader(prog, frag); // 한 프로그램엔 Vertex/Fragment Shader 필요
glLinkProgram(prog); // obj 파일을 exe파일로 제작
// execute it!
glUseProgram(prog); // 프로그램을 GPU에서 실행
}
void drawFunc(void) {
// clear in gray color
glClear(GL_COLOR_BUFFER_BIT);
// provide the vertex attributes
GLuint loc = glGetAttribLocation(prog, "vertexPos"); // vertexPos 이름을 쓰는 레지스터의 위치 반환
glEnableVertexAttribArray(loc); // 해당 위치의 레지스터 활성화
glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, 0, vertPos); // Vertex Shader의 input으로 전달
// draw a triangle
glDrawArrays(GL_TRIANGLES, 0, 3); // 0번째부터 3개의 데이터를 삼각형으로 해석
// done
glFinish(); // 커맨드 큐의 모든 명령 실행
}

OpenGL Manuals
https://www.opengl.org
https://registry.khronos.org/OpenGL-Refpages/gl4/