텍스쳐를 입히기 전 먼저 도형들에 텍스쳐 좌표를 넣어줄 것이다.
현재 만들어둔 도형은 삼각형으로만 이루어진 피라미드 모양이므로, 각 면에 다음과 같은 모양으로 텍스쳐를 입힐 것이다.
이 점을 감안하면서 각 버텍스마다 텍스쳐 좌표를 지정해주었다.
GLfloat vertices[] =
{
//x y z u v
-1.0f, -1.0f, 0.0f, 0.f, 0.f,
0.0f, 1.0f, 0.0f, 0.5f, 1.f,
0.0f, -1.0f, 1.0f, 1.f, 0.f,
0.0f, -1.0f, 1.0f, 0.f, 0.f,
0.0f, 1.0f, 0.0f, 0.5f, 1.f,
1.0f, -1.0f, 0.0f, 1.f, 0.f,
1.0f, -1.0f, 0.0f, 0.f, 0.f,
0.0f, 1.0f, 0.0f, 0.5f, 1.f,
-1.0f, -1.0f, 0.0f, 1.f, 0.f,
-1.0f, -1.0f, 0.0f, 0.f, 0.f,
0.0f, -1.0f, 1.0f, 0.5f, 1.f,
1.0f, -1.0f, 0.0f, 1.f, 0.f
};
u, v가 텍스쳐의 S축, T축 좌표이다.
버텍스 배열 구조가 조금 바뀌었으므로 VAO가 VBO를 해석하는 방식도 수정이 필요하다.
따라서 Mesh 클래스의 CreateMesh 함수를 수정해주었다.
void Mesh::CreateMesh(GLfloat* vertices, unsigned int vertices_size)
{
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices_size, vertices, GL_STATIC_DRAW); // static draw : 넣은 값을 바꾸지 않겠다
// 0번 attribute : 3개를 연달아 읽고, 5칸 점프한다.
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, 0);
glEnableVertexAttribArray(0);
// 1번 attribute : 2개를 연달아 읽고, 5칸 점프한다. 시작점은 3번 index이다.
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (void*)(sizeof(GLfloat) * 3));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
vertexArrSize = vertices_size;
}
VAO의 0번 attribute는 position을, 1번 attribute는 texcoord(텍스쳐좌표)를 담게 할 것이다.
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, 0) 를 살펴보자면,
우선 첫번째 파라미터는 VAO의 몇 번 attribute에 연결할 지를 의미한다. 여기서는 0번 attribute에 연결했다.
두번째 파라미터는 몇개씩 읽을 것인가인데, x, y, z값 3개를 읽는 것이므로 3이 들어간다.
4번째 파라미터가 중요한데, stride를 의미한다. 한번 읽고 다음 것은 몇칸 뛰어서 읽을 것인가를 의미한다.
원래는 버텍스의 position 데이터만 연속으로 저장되어있기 때문에 이것을 0으로 했어도 됐었다.
그러나 이제는 [0번 버텍스 포지션, 0번 버텍스 텍스쳐좌표, 1번 버텍스 포지션, 1번 버텍스 텍스쳐좌표, 2번 버텍스 포지션, ...] 이런식으로 버텍스마다 attribute가 번갈아 나오기 때문에 올바른 stride를 정해줘야 한다.
stride를 5로 넣어주었는데, 한 자리에서 3개를 쭉 읽은 후 5칸 건너뛰어야 다음 position이 나오기 때문이다.
건너뛰고 그 자리에서 3개를 읽고, 또 건너뛰고... 의 반복이다.
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (void*)(sizeof(GLfloat) * 3)) 의 경우
텍스쳐좌표를 1번 attribute에 연결하며,
2개씩 읽으며,
stride는 마찬가지로 5이다.
마지막 파라미터로 (void*)(sizeof(GLfloat) * 3)을 넣어주었는데, 이는 읽는 시작점의 offset을 의미한다.
텍스쳐좌표는 위 이미지에서 보시다시피 3번부터 시작하므로 저렇게 넣어준 것이다.
이렇게 VAO의 0번 attribute는 position을, 1번 attribute는 texcoord를 담도록 수정완료했다.
다음 포스팅에서는 쉐이더를 통해 텍스쳐를 실제로 모델링에 발라볼 것이다.
'OpenGL > 공부' 카테고리의 다른 글
[OpenGL] Phong Reflection Model - 개요 (1) | 2024.06.15 |
---|---|
[OpenGL] Textures (6) - 적용 (sampler2D) (+Instancing) (1) | 2024.06.13 |
[OpenGL] Textures (4) - 로드(stb_image), 생성, 바인딩(Texture Unit) (1) | 2024.06.13 |
[OpenGL] Textures (3) - Wrapping (0) | 2024.06.12 |
[OpenGL] Textures (2) - Mipmap (0) | 2024.06.06 |