2024.7.6(토) 6장 OpenGL ES와 쉐이더
OpenGL ES
- 제공되는 API와 쉐이딩 언어 알아야 함.
- 강의에서는 3.0 버전 이용
Shading Language
- GPU 전용 언어
- 행렬, 벡터 지원해주는 특별한 타입 O
→ vec4, ivec3, mat3, mat4 등
Vertex Shader
- Attributes: 위치와 같이 정점에 저장된 정점 별 데이터
- Uniforms: 월드 변환, 뷰 변환, 투영 변환과 같이 모든 정점마다 유니폼하게 적용되는 데이터
clip-space positionL 내장 변수에다 써 두기 = gl_Position
애트리뷰트가 m개인 경우, 각각의 위치는 0,1,2,…,m-1로 표기됨.
layout이라는 키워드를 사용해 position, normal, textCoord위치를 각각 0,1,2로 지정
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texCoord;
out 키워드로 쉐이더가 출력할 v_normal과 v_texCoord 정의
out vec3 v_normal; out vec2 v_texCoord;
void main(){
gl_Position = projMat * viewMat * worldMat * vec4(position, 1.0);
v_normal = normalize(transpose(inverse(mat3(worldMat))) * normal);
v_texCoord = texCoord;
}
메인 함수 - 오브젝트 공간에서 정의된 normal을 월드 공간으로 변환.
mat3(worldMat)은 월드 행렬의 왼쪽 위 3*3 부분 행렬을 말하는데, 이는 [L|t]로 표기된 월드 행렬 중 L을 의미한다. L의 역전치행렬이 normal에 곱해지고 정규화되어 출력 변수인 v_normal에 저장됨.
마지막 줄은 texCoord를 v_textCoord에 그대로 복사하는데, 총 세 개 출력 값(gl_Position, v_normal, v_texCoord)이 래스터라이저에게 전달됨.
GL 프로그램: 쉐이더 관리 & 쉐이더에 필요한 데이터 공급하는 역할.
함수는 gl로, 데이터는 GL로 시작함.
GLuint shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
- 쉐이더 오브젝트 - glCreateShader가 생성. GL_VERTEX_SHADER 또는 GL_FRAGMENT_SHADER 입력 받아 쉐이더 오브젝트의 ID를 리턴함.
- glShaderSource에 의해 쉐이더 오브젝트에 저장됨.
- 쉐이더 오브젝트는 glCompileShader에 의해 컴파일 됨.
GLuint program = glCreateProgram();
glAttachShader(program, shader);
glLinkProgram(program);
glUseProgram(program);
정점 및 프래그먼트 쉐이더 오브젝트는 모두 프로그램 오브젝트에 붙여져야 한다.
애트리뷰트와 유니폼
stuct Vertex {
glm::vec3 pos;
glm::vec3 nor;
glm::vec2 tex;
};
typedef GLushort Index;
struct ObjData {
std::vector<Vertex> vertices;
std::vector<Index> indices;
};
ObjData objData;
- 정점의 위치(pos), 노멀(nor), 텍스처 좌표(tex)를 가짐
- 여기서 사용된 glm은 OpenGL 수학 라이브러리
- GLSL와 동일 이름, 기능 가진 클래스와 함수 제공
GLuint abo;
glGenBuffer(1, &abo);
glBindBuffer(GL_ARRAY_BUFFER, abo);
glBufferData(GL_ARRAY_BUFFER,
(GLsizei) objData.vertices.size() * sizeof(Vertex),
objData.vertices.data(), GL_STATIC_DRAW);
- glGenBuffers(GLsizei n, GLunit* buffers) 호출해 버퍼 오브젝트 생성
- GL_ARRAY_BUFFER를 파라미터로 glBindBuffer 호출해 버퍼 오브젝트를 정점 배열에 바인드함.
CPU 메모리의 정점 및 인덱스 배열과 GPU 메모리의 버퍼 오브젝트
GPU 버퍼 오브젝트에 저장된 정점 애트리뷰트
pos, nor, tex 정점 애트리뷰트들이 배열 버퍼 오브젝트에 어떤 방식으로 저장되어 있는지 보여줌.
glEnableVertexAttribArray(0); // position = attribute 0
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (const GLvoid*) offsetof(Vertex, pos));
glEnableVertexAtrribArray(); // normal = attribute 1
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (const GLvoid*) offsetof(Vertex, nor));
glEnableBertexAttribArray(2); // texture coordinates = attribute 2
glVertexAttribPoint(2, 2, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (const GLvoid*) offsetof(Vertex, tex));
드로우콜
드로우콜: 폴리곤 메시를 그리는 명령을 내리는 것

- glDrawArrays(GL_RIANGLES, 0, 144) 호출
- glDrawElements 이용해 메시 그림.
이미지 출처
[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문]