glBufferSubDataglBufferData라는 메서드가 있음
unsigned int cubeVBO;
glGenBuffers(1, &cubeVBO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
이런식으로 vbo의 사이즈를 지정하고, data를 넘겨서 gpu메모리에 박을때 사용하는거임
만약 gpu메모리에 박힌 vbo를 사용하던중에 임의의 vbo데이터 변경이 생겨야한다면??
뭐 다시 glBufferData를 호출할 수도 있겠음ㅇㅇ
하지만 기본적으로 glBufferData는 메모리 초기화, 재할당을 하게됨
따라서 최적화를 위해 glBufferSubData라는걸 사용해주면 좋음
glBufferSubData(GL_ARRAY_BUFFER, 24, sizeof(data), &data); // Range: [24, 24 + sizeof(data)]
파라미터는 순서대로
target, offset, size, data임
target버퍼에 offset만큼 건너뛴 메모리 공간에 변경할 값들의 size와 값 변경할 data를 넣어주면 됨
간단스~
대신 glBufferSubData는 이미 할당된 메모리 공간을 사용해야하므로,
glBufferData로 먼저 메모리를 할당해두고 사용해야함
꼼수로
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), nullptr, GL_STATIC_DRAW);
이렇게 data를 비워뒀다가
glBufferSubData로 나중에 값이 완전해진후에 채워도 됨
glMapBuffergpu 버퍼를 cpu의 포인터로 연결해서 사용할 수 있도록 하는거임
위의 glBufferSubData는 gpu내에서 직접 버퍼에 수정을 하는거였다면
glMapBuffer는 버퍼를 cpu로 불러와서 cpu에서 수정을 하거나 읽기만 하도록 할 수 있는거임
float data[] = {
0.5f, 1.0f, -0.35f
[...]
};
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// mapBuffer로 포인터 얻기
void *ptr = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
// 복사
memcpy(ptr, data, sizeof(data));
// 포인터 해제
glUnmapBuffer(GL_ARRAY_BUFFER);
위의 glBufferSubData를 이용해 여러개로 나뉘어진 정점 속성을 하나로 묶어서 더 간편하고 알아보기 쉽게 사용할 수 있음
지금까지 우리는
float cubeVertices[] = {
// positions // texture Coords
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
//...
};
이런식으로 하나의 data를 이용해
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
직접 offset을 계산해서 넣어주는 방식으로 사용했음
하지만 glBufferSubData를 사용하면 이제 다르게 사용가능함
float positions[] = { ... };
float normals[] = { ... };
float tex[] = { ... };
uint32_t VAO, VBO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(positions) + sizeof(normals) + sizeof(tex), nullptr, GL_STATIC_DRAW)
// fill buffer
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(positions), &positions);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(positions), sizeof(normals), &normals);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(positions) + sizeof(normals), sizeof(tex), &tex);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(sizeof(positions)));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)(sizeof(positions) + sizeof(normals)));
확실히 코드가 더 직관적이게 바뀜
3개의 정점마다 vertex attributes매핑
이지~~
glCopyBufferSubData자 위의 방식들은
버퍼의 값 변경,
gpu버퍼를 cpu에서 사용하도록 포인터 오픈
이었음
그럼 버퍼를 버퍼로 복사하려면 어떻게 해야할까?
걍 개쉬움
void glCopyBufferSubData(GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size);
를 사용하면 됨
readtarget의 버퍼를 writetarget으로 복사를 하는데
readtarget버퍼의 readoffset을 시작으로
writetarget버퍼의 writeoffset부터 size만큼 버퍼를 채움
예를들어
GL_ARRAY_BUFFER -> GL_ELEMENT_ARRAY_BUFFER
이렇게 복사하는거임
근데 문제가 있음
GL_ARRAY_BUFFER에서 GL_ARRAY_BUFFER로 복사를 하려고 하면??
readtarget과 writetarget에 같은 버퍼를 넣을순 없음
이걸 해결하기위해 존재하는 버퍼가
GL_COPY_READ_BUFFER & GL_COPY_WRITE_BUFFER임
그래서 대충 사용법을 보면
glBindBuffer(GL_COPY_READ_BUFFER, vbo1);
glBindBuffer(GL_COPY_WRITE_BUFFER, vbo2);
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, 8 * sizeof(float));
//_______________________________________________
float vertexData[] = { ... };
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
glBindBuffer(GL_COPY_WRITE_BUFFER, vbo2);
glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, 8 * sizeof(float));
이렇게 되는거임