macOS에서 OpenGL 프로그래밍 (2-2. 구조체와 벡터를 사용하여 정점 데이터 지정)

13014 단어 XcodemacosGLSLOpenGL
macOS에서 OpenGL 프로그래밍의 목차로 돌아가기

소개



지난번은 셰이더를 작성하고 읽고 VBO와 VAO를 사용하여 화면을 그리는 방법을 설명했습니다.

이번에는, 정점 데이터를 구조체와 vector를 사용해 준비해, 그것에 의해 VBO와 VAO 각각의 지정을 알기 쉽게 된다는 것을 해설하고 싶습니다.

1. VertexData 구조체 정의



Game.cpp를 편집하여 vector 헤더를 포함하여 정점 데이터를 나타내는 VertexData 구조체를 정의합니다.

Game.cpp(선두 부분)
#include "Game.hpp"

#include <cmath>
#include <vector>

struct VertexData
{
    GLfloat     pos[3];
    GLfloat     color[4];
};

GLfloat형의 수치를 3개 조합한 배열로 정점 좌표를 나타내, GLfloat형의 수치를 4개 조합한 배열로 색 정보를 나타냅니다.

2. Game 클래스의 생성자 재작성



다음으로, Game 클래스의 생성자를 편집해, 전회는 GLfloat형의 수치를 나란히 해 정점 데이터를 정의하고 있었던 것을, C++ 표준의 std::vector와 VertexData를 조합한 형태로 정점 데이터를 정의하도록(듯이) 로 변경합니다.

Game.cpp(생성자)
Game::Game()
{
    program = new ShaderProgram("myshader.vsh", "myshader.fsh");

    std::vector<VertexData> data;
    data.push_back({ { -0.5f, -0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } });
    data.push_back({ {  0.5f, -0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } });
    data.push_back({ {  0.0f,  0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } });

    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData) * data.size(), &data[0], GL_STATIC_DRAW);

    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), ((VertexData *)0)->pos);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexData), ((VertexData *)0)->color);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
}

어떻습니까? 정점 좌표와 색 정보를 따로 지정할 수 있게 되어 알기 쉬워졌고, 무엇보다 VBO와 VAO에서의 데이터 포맷의 지정도 알기 쉬워지고 있다고 생각합니다.

2.1. VBO 데이터 전송 방법 비교



실제로 봐 비교해 봅시다. 먼저 VBO 변경 전과 변경 후를 비교해 보겠습니다.

VBO 데이터 전송 비교
// 変更前
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 7 * 3, data, GL_STATIC_DRAW);

// 変更後
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData) * data.size(), &data[0], GL_STATIC_DRAW);

변경전은 GLfloat형의 수치가 정점 좌표 3개+색 정보 4개의 7개로, 한층 더 그것이 3 세트분 있는 것을 머리로 계산해 지정하지 않으면 안되었습니다.

그러나 변경 후의 것에서는, C++의 std::vector를 사용해, 데이터를 구조체로서 정리한 VertexData를 이용하는 것으로, 정점 데이터 1분의 사이즈를 「 sizeof(VertexData) 」라고 쓰는 것만으로 계산할 수 있다 size() 함수를 사용해 구한 데이터의 개수를 곱하는 것만으로 VBO의 지정을 할 수 있게 되어 있습니다.

2.2. VAO 포맷 지정 방법 비교



다음으로 VAO 변경 전과 변경 후를 비교해 보겠습니다.

VAO 형식 지정 비교
// 変更前
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 7, (GLfloat *)0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 7, ((GLfloat *)0)+3);

// 変更後
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), ((VertexData *)0)->pos);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexData), ((VertexData *)0)->color);
glVertexAtrribPointer() 함수의 다섯 번째 인수에서 데이터의 stride 값을 구하기 위해 변경 후에는 "sizeof(VertexData)"라고 쓰는 것만으로 좋아지는 것은 VBO와 같습니다.
glVertexAtrribPointer() 함수의 여섯 번째 인수에서 오프셋 값을 지정하는 방법에 대해 오프셋 값 0을 VertexData 포인터 형식으로 캐스팅 한 것을 사용하여 화살표 연산자로 pos와 color 각각의 배열에 액세스하여 pos 배열의 선두의 오프셋(offset)치와 color 배열의 선두의 오프셋(offset)치를 적절히 지정할 수 있게 되어 있습니다. 이것은 향후, 법선 벡터나 텍스처의 UV 좌표 등을 지정하는 등, 정점 속성의 수가 증가했을 경우에, 확실히 간단하게 오프셋치를 지정할 수 있게 되는 것을 나타내고 있습니다.

실행 결과는 이전과 동일합니다.



여기까지의 프로젝트 : MyGL은 _s로 p2-2. 지 p

3. 정리



이번에는 구조와 벡터를 사용하여 원본 데이터를 준비하여 VBO와 VAO를 더 쉽게 지정할 수 있다는 것을 알았습니다.

다음 번에는 인덱스 목록을 사용하여 정점 데이터의 순서를 제어하는 ​​방법을 설명합니다.

다음 기사 : macOS에서 OpenGL 프로그래밍 (2-3. 정점의 인덱스 목록을 사용하여 그리기)

좋은 웹페이지 즐겨찾기