4 minute read

VBO(Vertex Buffer Object) 그리기

  • VBO를 그리기 위해선 다음과 같은 과정을 거친다.
    1. 버텍스 버퍼 지정
    2. 새로운 버퍼 생성
    3. 생성한 버퍼에 타겟을 할당
    4. 버퍼에 실제 데이터를 넣는다.
    5. 버퍼 활성화
    6. 저장한 데이터의 속성 정보 지정
    7. 버텍스의 시작과 끝, 방식을 설정한다.
    8. 버퍼 비활성화

OpenGL 상세 코드 설명

  1. 버텍스 버퍼 지정 및 새로운 버퍼 생성

    • GLuint vertexbuffer_name : 버텍스 버퍼 지정
    • glGenBuffers(GLsizei n, GLuint * buffers) : 새로운 버퍼 생성 n : 새로 생성하는 버퍼 개수 buffers : 버퍼 객체의 이름이 저장된 공간
    • 예시
        GLuint vertexbuffer;
        glGenBuffers(1, &vertexbuffer);
      
  2. 생성한 버퍼에 타겟을 할당
    • void glBindBuffer(GLenum target, GLuint buffer)
      • target : 버퍼 객체가 바인딩 되는 대상
        • 만약에 targetGL_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);
      
  3. 버퍼에 실제 데이터를 넣는다.

    • void glBufferData(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
    • size : 데이터 크기
    • data : 데이터 주소값
    • usage : 데이터의 사용 패턴, 아래와 같은 키워드를 조합하여 만든다. 만약 GL_STATIC_DRAW라면 한번 데이터가 저장되면 변경되지 않는다.
      1. STREAM : 데이터 저장소 내용을 한 번 수정하여 최대 몇 번까지 사용할 것이다.
      2. STATIC : 데이터 저장소 내용을 한 번 수정하여 여러 번 사용할 것이다.
      3. DYNAMIC : 데이터 저장소 내용을 반복적으로 수정하여 여러 번 사용한다.
      4. DRAW : 어플리케이션에 의해 데이터 저장소 내용이 수정되어 GL 도면 및 영상 사양 명령의 소스로 사용된다.
      5. READ : GL의 데이터를 읽음으로써 데이터 저장소 내용을 수정하고, 어플리케이션에 의해 질의 시 해당 데이터를 반환하는 데 사용한다.
      6. COPY : GL의 데이터를 읽어 데이터 저장소 내용을 수정하여 GL 도면 및 영상 사양 명령의 소스로 사용한다.
    • 예제

            glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
      
  4. 저장한 데이터의 속성 정보 지정

    • 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
        );
      
  5. 버텍스의 시작과 끝, 방식을 설정

    • glDrawArrays(GLenum polygon, GLuint start, GLuint end)
    • polygon : 어떤 폴리곤으로 그려낼지 표시, GL_TRIANGLES로 하면 삼각형들을 그려낸다.
    • start : 시작
    • end : 끝 ( 시작 + 정점 개수)
    • 예제
            /* 삼각형 하나를 그려낸다.*/
            glDrawArrays(GL_TRIANGLES, 0, 3);
      
  6. 버퍼 활성화 & 비활성화

    • 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;
}

Categories:

Updated: