[OpenGL3] 삼각형 그리기
VBO(Vertex Buffer Object) 그리기
- VBO를 그리기 위해선 다음과 같은 과정을 거친다.
- 버텍스 버퍼 지정
- 새로운 버퍼 생성
- 생성한 버퍼에 타겟을 할당
- 버퍼에 실제 데이터를 넣는다.
- 버퍼 활성화
- 저장한 데이터의 속성 정보 지정
- 버텍스의 시작과 끝, 방식을 설정한다.
- 버퍼 비활성화
OpenGL
상세 코드 설명
-
버텍스 버퍼 지정 및 새로운 버퍼 생성
GLuint vertexbuffer_name
: 버텍스 버퍼 지정glGenBuffers(GLsizei n, GLuint * buffers)
: 새로운 버퍼 생성n
: 새로 생성하는 버퍼 개수buffers
: 버퍼 객체의 이름이 저장된 공간- 예시
GLuint vertexbuffer; glGenBuffers(1, &vertexbuffer);
- 생성한 버퍼에 타겟을 할당
void glBindBuffer(GLenum target, GLuint buffer)
target
: 버퍼 객체가 바인딩 되는 대상- 만약에
target
이GL_ARRAY_BUFFER
이면 정점에 대한 데이터를 생성할 버퍼로 지정
Buffer Binding Target Purpose GL_ARRAY_BUFFER Vertex attributes GL_ATOMIC_COUNTER_BUFFER Atomic counter storage GL_COPY_READ_BUFFER Buffer copy source GL_COPY_WRITE_BUFFER Buffer copy destination GL_DISPATCH_INDIRECT_BUFFER Indirect compute dispatch commands GL_DRAW_INDIRECT_BUFFER Indirect command arguments GL_ELEMENT_ARRAY_BUFFER Vertex array indices GL_PIXEL_PACK_BUFFER Pixel read target GL_PIXEL_UNPACK_BUFFER Texture data source GL_QUERY_BUFFER Query result buffer GL_SHADER_STORAGE_BUFFER Read-write storage for shaders GL_TEXTURE_BUFFER Texture data buffer GL_TRANSFORM_FEEDBACK_BUFFER Transform feedback buffer GL_UNIFORM_BUFFER Uniform block storage - 만약에
- 예제
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
-
버퍼에 실제 데이터를 넣는다.
void glBufferData(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
size
: 데이터 크기data
: 데이터 주소값usage
: 데이터의 사용 패턴, 아래와 같은 키워드를 조합하여 만든다. 만약GL_STATIC_DRAW
라면 한번 데이터가 저장되면 변경되지 않는다.- STREAM : 데이터 저장소 내용을 한 번 수정하여 최대 몇 번까지 사용할 것이다.
- STATIC : 데이터 저장소 내용을 한 번 수정하여 여러 번 사용할 것이다.
- DYNAMIC : 데이터 저장소 내용을 반복적으로 수정하여 여러 번 사용한다.
- DRAW : 어플리케이션에 의해 데이터 저장소 내용이 수정되어 GL 도면 및 영상 사양 명령의 소스로 사용된다.
- READ : GL의 데이터를 읽음으로써 데이터 저장소 내용을 수정하고, 어플리케이션에 의해 질의 시 해당 데이터를 반환하는 데 사용한다.
- COPY : GL의 데이터를 읽어 데이터 저장소 내용을 수정하여 GL 도면 및 영상 사양 명령의 소스로 사용한다.
-
예제
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
-
저장한 데이터의 속성 정보 지정
void glVertexAttribPointer( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,const GLvoid * pointer)
index
: 정점 속성의 인덱스 지정(샘플에선 위치-0, 색상 정보-1로 지정)size
: 속성의 구성 요소 수, triangle일 때는 3!type
: 데이터 타입 유형normalized
: 고정 소수점 데이터 값을 정규화할지stride
:byte offset
지정pointer
: 첫번째 데이터의 오프셋 지정-
예제
glVertexAttribPointer( 0, // 위치 : 0 색상 : 1 3, // size 3개씩 묶을 것이다. GL_FLOAT, // type GL_FALSE, // normalized? 0, // stride (void*)0 // array buffer offset );
-
버텍스의 시작과 끝, 방식을 설정
glDrawArrays(GLenum polygon, GLuint start, GLuint end)
polygon
: 어떤 폴리곤으로 그려낼지 표시,GL_TRIANGLES
로 하면 삼각형들을 그려낸다.start
: 시작end
: 끝 ( 시작 + 정점 개수)- 예제
/* 삼각형 하나를 그려낸다.*/ glDrawArrays(GL_TRIANGLES, 0, 3);
-
버퍼 활성화 & 비활성화
void glEnableVertexAttribArray(GLuint index)
void glDisableVertexAttribArray(GLuint index)
삼각형 그리기 main
코드
```cpp
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#define GLEW_STATIC
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <GLFW/glfw3.h>
GLFWwindow* window;
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
#include "common/shader.hpp"
int main( void )
{
// Initialise GLFW
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
getchar();
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Open a window and create its OpenGL context
window = glfwCreateWindow( 1024, 768, "Tutorial 02 - Red triangle", NULL, NULL);
if( window == NULL ){
fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
do{
// Clear the screen
glClear( GL_COLOR_BUFFER_BIT );
// Use our shader
glUseProgram(programID);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 3); // 3 indices starting at 0 -> 1 triangle
glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
// Cleanup VBO
glDeleteBuffers(1, &vertexbuffer);
glDeleteVertexArrays(1, &VertexArrayID);
glDeleteProgram(programID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}