이번 시간에는 오픈지엘에서 EBO를 이용하여 삼각형을 그려보겠다.
● Element Buffer Object (EBO)
EBO란 그리려는 도형의 정점 인덱스를 배치하여 인덱스 리스트 순서대로 그리는 방법이다.
VBO에 비해 중복되는 정점을 막을 수 있고 도형이 복잡해졌을 때 인덱스 리스트 만으로 수월하게 그릴 수 있다.
하지만 obj나 fbx 형식의 오브젝트는 EBO를 이용하여 사용하지 못하는 점을 주의해야한다.
01. EBO 추가 버퍼 생성
GLuint VAO, VBO[2], EBO;
GLvoid InitBuffer()
{
glGenVertexArrays(1, &VAO);
glGenBuffers(2, VBO);
glGenBuffers(1, &EBO);
}
02. EBO에 사용할 도형 인덱스 배열 추가
void DrawRect()
{
// 사각형 위치
const float vertexPosition[] =
{
-0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f
};
// 사각형 인덱스
const int vertexIndeces[] =
{
0, 1, 2,
0, 2, 3
};
// 사각형 색상
const float vertexColor[] =
{
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0
};
...
}
03. EBO를 바인드 하고 glDrawElements 함수 이용하여 도형 그리기
void DrawTriangle()
{
...
// VAO 바인드
glBindVertexArray(VAO);
// 사각형 위치 버퍼 바인드
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPosition), vertexPosition, GL_STATIC_DRAW);
// 사각형 인덱스 버퍼 바인드
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertexIndeces), vertexIndeces, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glEnableVertexAttribArray(0);
// 사각형 색상 버퍼 바인드
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexColor), vertexColor, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glEnableVertexAttribArray(1);
// 사각형 그리기
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
전체코드
#include <iostream>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <gl/freeglut_ext.h>
#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "freeglut.lib")
#define _CRT_SECURE_NO_WARNINGS
#define WIDTH 800
#define HEIGHT 600
#define BYTE_SIZE_RECT 48
using namespace std;
// 콜벡 함수
GLvoid Render(GLvoid);
GLvoid Reshape(int w, int h);
// VAO, VBO, EBO
GLuint VAO, VBO[2], EBO;
void DrawRect();
GLchar* vertexSource, * fragmentSource; // 소스코드 저장 변수
GLuint vertexShader, fragmentShader; //세이더 객체
GLuint shaderProgramID; // 세이더 프로그램
GLint CreateShader(const char* file, int type);
GLvoid CreateShaderProgram();
GLvoid InitBuffer();
void main(int argc, char** argv)
{
// 윈도우 생성
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(0, 0);
glutInitWindowSize(WIDTH, HEIGHT);
glutCreateWindow("Draw Rect by using EBO");
// GLEW 초기화하기
glewExperimental = GL_TRUE;
glewInit();
InitBuffer();
CreateShaderProgram();
glutDisplayFunc(Render);
glutMainLoop();
}
GLvoid Render()
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
DrawRect();
glutSwapBuffers();
}
GLvoid Reshape(int w, int h)
{
// 뷰포트 기본 WIDTH HEIGHT로 설정
glViewport(0, 0, w, h);
}
GLvoid InitBuffer()
{
glGenVertexArrays(1, &VAO);
glGenBuffers(2, VBO);
glGenBuffers(1, &EBO);
}
char* GetBuf(const char* file)
{
FILE* fptr;
long length;
char* buf;
// 파일 읽기 형식으로 열기
fopen_s(&fptr, file, "rb");
// 예외처리
if (!fptr) return NULL;
// 파일 buf로 변환
fseek(fptr, 0, SEEK_END);
length = ftell(fptr);
buf = (char*)malloc(length + 1);
fseek(fptr, 0, SEEK_SET);
fread(buf, length, 1, fptr);
// 파일 종료
fclose(fptr);
buf[length] = 0;
return buf;
}
GLint CreateShader(const char* file, int type)
{
// glsl 파일 읽기
GLchar* source = GetBuf(file);
// 객체 생성
GLint shader = glCreateShader(type);
glShaderSource(shader, 1, (const GLchar**)&source, 0);
glCompileShader(shader);
// 컴파일 에러 체크
GLint result;
GLchar errorLog[512];
glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
if (!result)
{
glGetShaderInfoLog(shader, 512, NULL, errorLog);
std::cerr << "ERROR: 컴파일 실패\n" << errorLog << std::endl;
return 0;
}
return shader;
}
void CreateShaderProgram()
{
vertexShader = CreateShader("vertex.glsl", GL_VERTEX_SHADER);
fragmentShader = CreateShader("fragment.glsl", GL_FRAGMENT_SHADER);
// 세이더 프로그램 생성
shaderProgramID = glCreateProgram();
glAttachShader(shaderProgramID, vertexShader);
glAttachShader(shaderProgramID, fragmentShader);
glLinkProgram(shaderProgramID);
// 세이더 삭제
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// 세이더 프로그램 사용
glUseProgram(shaderProgramID);
}
void DrawRect()
{
// 사각형 위치
const float vertexPosition[] =
{
-0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f
};
// 사각형 인덱스
const int vertexIndeces[] =
{
0, 1, 2,
0, 2, 3
};
// 사각형 색상
const float vertexColor[] =
{
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0
};
// VAO 바인드
glBindVertexArray(VAO);
// 사각형 위치 버퍼 바인드
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPosition), vertexPosition, GL_STATIC_DRAW);
// 사각형 인덱스 버퍼 바인드
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertexIndeces), vertexIndeces, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glEnableVertexAttribArray(0);
// 사각형 색상 버퍼 바인드
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexColor), vertexColor, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glEnableVertexAttribArray(1);
// 사각형 그리기
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
'프로그래밍 > OpenGL' 카테고리의 다른 글
[OpenGL] 오픈지엘 3차원 큐브 그리기 (1) | 2024.02.09 |
---|---|
[OpenGL] 오픈지엘 EBO를 이용한 2차원 도형 그리기 및 응용 (0) | 2024.02.09 |
[OpenGL] 오픈지엘 VAO와 VBO를 이용한 삼각형 그리기 (0) | 2024.02.06 |
[OpenGL] 오픈지엘 GLSL 쉐이더 적용 (0) | 2024.02.05 |
[OpenGL] 오픈지엘 그래픽스 파이프라인 (0) | 2024.02.04 |