일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- Directx12
- shaders
- bufferobjects
- 수학 #기하학 #벡터 #벡터연산 #선형대수학
- react
- 회전행렬
- 수학
- callbacks
- Drawcall
- initialization
- ibo
- kubernetes
- LiV
- vertexattributeobject
- bufferswap
- liltoon
- 쿼터니온
- vao
- VRChat
- unity
- indexbufferobject
- OpenGL
- VRC
- vertexbufferobject
- MongoDB
- ReactJS
- BeatSaber
- 3d 기하학
- NVM
- vbo
- Today
- Total
To Paint a World
OpenGL - 3. Buffer Objects 본문
BufferObject
#pragma once
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <vector>
template<typename T>
class BufferObject {
private:
unsigned int _id;
int _type;
std::vector<T> * _data;
public:
BufferObject( int type, std::vector<T> * data);
~BufferObject();
void Bind() const;
void Unbind() const;
void BufferData() const;
void SetAttribPointer(unsigned int vao, int dtype) const;
inline std::vector<T> * GetVector() const {return _data; }
inline std::vector<T> * GetSize() const {return _data->size(); }
};
BufferObject 생성과 삭제
template<typename T>
BufferObject<T>::BufferObject(int type, std::vector<T> * data) {
if (!!data)
_data = data;
else
_data = new std::vector<T>();
_type = type;
glGenBuffers(1, &_id);
}
template<typename T>
BufferObject<T>::~BufferObject() {
glDeleteBuffers(1, &_id);
}
glGenBuffers 를 호출하여 버퍼 오브젝트를 생성한다.
glGenBuffers(1, &_id) 는 buffer object 를 1개 생성하여 buffer object name 을 _id 의 값에 배정한다.
_type 에는 glBindBuffer 의 target 을 배정한다. (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER 등)
_data 에는 glBindBuffer 를 통해 GPU 로 보낼 데이터의 벡터를 지정한다.
BufferObject 바인딩 & 언바인딩
template<typename T>
void BufferObject<T>::Bind() const {
glBindBuffer(_type, _id);
}
template<typename T>
void BufferObject<T>::Unbind() const {
glBindBuffer(_type, 0);
}
Bind() 는 glBindBuffer 를 호출하여, buffer object name 이 _id 의 값인 buffer object 를 _target 에 바인딩한다.
Unbind() 는 _target 을 언바인딩한다. buffer object name = 0 으로 설정하면 unbind 된다.
BufferObject 데이터 버퍼링
template<typename T>
void BufferObject<T>::BufferData() const {
Bind();
glBufferData(_type, _data->size() * sizeof(T), _data->data(), GL_STATIC_DRAW);
Unbind();
}
glBufferData 를 호출하여, _type 에 _data 값을 업데이트 해준다.
다음 argument 대로 호출한다.
glBufferData(vbo 의 타겟, 복사할 데이터의 크기 (byte 단위), 데이터의 시작 포인터, GL_STATIC_DRAW)
BufferObject - Vertex Attribute Pointer 세팅
template<typename T>
void BufferObject<T>::SetAttribPointer(unsigned int vao, int dtype) const {
Bind();
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
switch(dtype) {
case GL_FLOAT:
glVertexAttribPointer(0, sizeof(T) / sizeof(float), dtype, GL_FALSE, sizeof(T), nullptr);
break;
case GL_DOUBLE:
glVertexAttribPointer(0, sizeof(T) / sizeof(double), dtype, GL_FALSE, sizeof(T), nullptr);
break;
}
glBindVertexArray(0);
Unbind();
}
만약 Buffer Object 가 Vertex Buffer Object 라면 (_type == GL_ARRAY_BUFFER), 배열은 {x1, y1, z1, x2, y2, z2, ..., xn, yn, zn} 와 같은 구조를 띄고 있게 된다. 여기서 한 vertex 는 {x1, y1, z1} 등과 같이 여러 개의 attribute 의 묶음으로 정의될 수 있다. 이처럼 vertex attribute 의 정보를 저장하는 구조체가 Vertex Array Object 이다.
먼저 glBindVertexArray 를 통해 VAO 를 바인딩하고, glVertexAttribPointer 를 호출하여 현재 바인딩된 VBO 를 어떤 attribute 로 분할할지 지정하여 VAO 에 attribute 정보를 저장한다.
다음과 같은 argument 를 패스하여 호출한다.
glVertexAttribPointer(0, attribute 의 수, GL 자료형, GL_FALSE, vertex 의 크기 (바이트), nullptr);
MainApp - Vertex Buffer Object 를 통해 정점 그리기
typedef pair<float, float> Point;
class MainApp : GLApp {
// ...
protected:
vector<Point> points;
Point* selected_point = NULL;
protected:
unsigned int vao;
BufferObject<Point>* vbo;
};
Point 자료형을 선언한다.
MainApp 에 VAO 와 VBO 를 추가한다. VBO 는 Point 구조체를 참조하는 BufferObject 로 생성한다.
bool MainApp::Initialize() {
// init GLApp functionalities
GLApp::InitOpenGL();
GLApp::InitCallbacks();
// init render objects
glGenVertexArrays(1, &vao);
vbo = new BufferObject<Point>(GL_ARRAY_BUFFER, &points);
vbo->SetAttribPointer(vao, GL_FLOAT);
// init points
points.push_back({0.0f, 0.5f});
points.push_back({-0.5f, -0.5f});
points.push_back({0.5f, -0.5f});
}
Vertex Array Object 를 생성하여 이름을 vao 에 저장하고, points 데이터와 연결된 Vertex Buffer Object 를 생성한다.
glBindBuffer 의 타겟이 GL_ARRAY_BUFFER 인 것이 Vertex Buffer Object 이다.
위에서 정의한 SetAttribPointer 함수를 호출하면 자동으로 vertex attribute 가 VAO 에 저장된다.
void MainApp::Draw() {
vbo->BufferData();
glBindVertexArray(vao);
vbo->Bind();
glPointSize(10.0f);
glDrawArrays(GL_POINTS, 0, points.size());
vbo->Unbind();
glBindVertexArray(0);
}
각 드로우 콜마다,
1. VBO 의 BufferData 를 호출하여 데이터를 GPU 에 업로드한다.
2. VAO 와 VBO 를 바인딩한다.
3. glDrawArrays 를 호출하여, 각 vertex 를 그린다.
빌드 시 다음과 같이 삼각형의 정점이 그려진 것을 확인할 수 있다.
MainApp - Index Buffer Object 를 통해 간선 그리기
typedef pair<float, float> Point;
typedef pair<unsigned int, unsigned int> Edge;
class MainApp : GLApp {
// ...
protected:
vector<Point> points;
vector<Edge> edges;
Point* selected_point = NULL;
protected:
unsigned int vao;
BufferObject<Point>* vbo;
BufferObject<Edge>* ibo;
};
Edge 자료형을 선언하고, Edge 의 vector 와 Index Buffer Object 를 생성한다.
bool MainApp::Initialize() {
// init GLApp functionalities
GLApp::InitOpenGL();
GLApp::InitCallbacks();
// init render objects
glGenVertexArrays(1, &vao);
vbo = new BufferObject<Point>(GL_ARRAY_BUFFER, &points);
vbo->SetAttribPointer(vao, GL_FLOAT);
ibo = new BufferObject<Edge>(GL_ELEMENT_ARRAY_BUFFER, &edges);
// init points & edges
points.push_back({0.0f, 0.5f});
points.push_back({-0.5f, -0.5f});
points.push_back({0.5f, -0.5f});
edges.push_back({0,1});
edges.push_back({1,2});
edges.push_back({2,0});
return true;
}
Index Buffer Object 의 타겟은 GL_ELEMENT_ARRAY_BUFFER 이다.
Vertex Buffer Object 와 달리, 별도의 attribute 설정을 하지 않는다.
void MainApp::Draw() {
vbo->BufferData();
ibo->BufferData();
glBindVertexArray(vao);
vbo->Bind();
glPointSize(10.0f);
glDrawArrays(GL_POINTS, 0, points.size());
vbo->Unbind();
ibo->Bind();
glLineWidth(2.0f);
glDrawElements(GL_LINES, 2 * edges.size(), GL_UNSIGNED_INT, nullptr);
ibo->Unbind();
glBindVertexArray(0);
}
Index Buffer Object 를 바인딩하고, glDrawElements 를 호출하여 간선을 그린다.
'3D Engine > OpenGL' 카테고리의 다른 글
OpenGL - 5. Uniforms (0) | 2025.02.18 |
---|---|
OpenGL - 4. Shaders (1) | 2025.01.06 |
OpenGL - 2. Input Callbacks (0) | 2024.12.26 |
OpenGL - 1. Initialization (3) | 2024.12.26 |