OpenGL과 GLFW, GLEW 설명과 마름모 생성 튜토리얼
2020. 8. 11. 10:17ㆍ프로그래밍
반응형
OpenGL과 GLFW, GLEW 설명과 마름모 생성 튜토리얼
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h> //OpenGL 확장팩
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
using namespace glm;
GLFWwindow* window;
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_E && action == GLFW_PRESS) {
printf("E Pressed\n");
}
if (key == GLFW_KEY_Q && action == GLFW_RELEASE) {
printf("Q Released\n");
}
}
int main()
{
// Initialise GLFW
if( !glfwInit() )
{
fprintf( stderr, "GLFW 초기화 실패\n" );
getchar();
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4); //안티엘리어싱 4배(멀티 픽셀 샘플링)
glfwWindowHint(GLFW_RESIZABLE,GL_FALSE); //창 크기 조절
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //최대 버전 요구
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); //최소 버전 요구
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //향후 지원되지 않는 것은 제외함을 의미
//창 열기
window = glfwCreateWindow( 1024, 768, "Window", NULL, NULL);
if( window == NULL ){
fprintf( stderr, "GLFW 창 열기 실패\n" );
getchar();
glfwTerminate();
return -1;
}
//현재 무슨 window를 사용할지 설정
glfwMakeContextCurrent(window);
//window 창에 대해서 입력받기 설정
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
//키 입력 콜백 설정
glfwSetKeyCallback(window, key_callback);
glewExperimental = true; // GLEW에 코어프로필 사용 설정
if (glewInit() != GLEW_OK) {
fprintf(stderr, "GLEW을 초기화 하는데에 실패했습니다.\n");
getchar();
glfwTerminate();
return -1;
}
glClearColor(0.0f, 0.0f, 0.7f, 0.0f);
//VAO, VBO 설정 ....
//코드
do{
glClear(GL_COLOR_BUFFER_BIT);
//활성화, 그리기 코드..
glfwSwapBuffers(window); //더블 버퍼링, 버퍼 교체
glfwPollEvents(); //설정한 콜백들(key callback.. 등) 호출
}
while( glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS
&& glfwWindowShouldClose(window) == 0);
//VAO, VBO 정리 코드
glfwTerminate();
return 0;
}
기본코드를 작성 했습니다. 이 글에서는 VAO, VBO를 이용하여서 마름모를 그리는 것을 할 것입니다.
1. VAO 생성
VAO는 Vertex Array Object의 줄임말입니다. 이름에서도 알 수 있듯이 배열입니다. 길이는 1이 될 수도 있습니다. 생성하기 나름이죠. 또 VAO의 한개의 element는 공식문서에서 '이름'으로 불리기도 합니다.
GLuint VertexArrayID; //GLuint는 '이름' 역할을 하며, OpenGL의 객체입니다.
glGenVertexArrays(1, &VertexArrayID); //VAOs 생성 (한개) = 길이 1짜리 배열
glBindVertexArray(VertexArrayID); //이 VAO를 사용하겠다고 설정
VAO를 생성했습니다. 잊지마세요 이건 배열입니다. 하지만 그저 한개의 GLuint 를 넣어도 됩니다. 그렇담 결국에 길이 1짜리 배열인거와 같은겁니다.
어쨌거나 VAO는 배열이나, VAO는 한 덩어리 처럼 사용합니다.
//마름모 꼭지점 벡터들. 3개의 꼭지점이 한개의 면입니다.
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, 0.0f, 0.0f, //
1.0f, 0.0f, 0.0f, // 마름모 부분의 아랫면
0.0f, -1.0f, 0.0f, //
-1.0f, 0.0f, 0.0f, //
1.0f, 0.0f, 0.0f, // 마름모 부분의 윗면
0.0f, 1.0f, 0.0f, //
};
마름모는 2개의 삼각형으로 구성되어있습니다.(뭐 다르게 자른다면 4개, 8개도 되겠네요) 따라서 2개의면, 즉 6개의 점을 만들었습니다. 아래와 같은 좌표계입니다.
2. VBO 생성과 VBO를 VAO에 적용
GLuint vertexbuffer; //한개의 객체가 될수 있으며, '이름'입니다.
glGenBuffers(1, &vertexbuffer); //VBO 생성 (Vertex buffer object)
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); //버퍼 사용 설정합니다.
//사용하기로한 vertexbuffer에 좌표점 설정
//STATIC_DRAW는 추후 변화 없음을 나타낸다. DYNAMIC_DRAW는 추후 변경 가능
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
3. 마름모 그리기
do{
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(0); //첫번째 VAO (아까 생성한것) 활성화
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); //VBO 사용 설정
glVertexAttribPointer( //속성 지정(렌더링 할때 혹은, 초기화 할때 등..)
0, // 0번째의 Attribute라는것을 지정. 다른 수도 가능
3, // xyz임으로 3. xyzw이면 4
GL_FLOAT, // glBufferData로 넘긴 데이터의 타입 -> Float
GL_FALSE, // 정규화(normalized)
0, // 간격
(void*)0 // 배열 오프셋
);
glDrawArrays(GL_TRIANGLES, 0, 6); //점 0부터 6까지 그립니다.
glDisableVertexAttribArray(0);
glfwSwapBuffers(window); //더블 버퍼링, 버퍼 교체
glfwPollEvents(); //설정한 콜백들(key callback.. 등) 호출
}
while( glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS
&& glfwWindowShouldClose(window) == 0);
주석으로 다 적어놨습니다.
4. 정리
glDeleteBuffers(1, &vertexbuffer);
glDeleteVertexArrays(1, &VertexArrayID);
5. 전체코드
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h> //OpenGL 확장팩
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
using namespace glm;
GLFWwindow* window;
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_E && action == GLFW_PRESS) {
printf("E Pressed\n");
}
if (key == GLFW_KEY_Q && action == GLFW_RELEASE) {
printf("Q Released\n");
}
}
int main()
{
// Initialise GLFW
if( !glfwInit() )
{
fprintf( stderr, "GLFW 초기화 실패\n" );
getchar();
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4); //안티엘리어싱 4배(멀티 픽셀 샘플링)
glfwWindowHint(GLFW_RESIZABLE,GL_FALSE); //창 크기 조절
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //최대 버전 요구
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); //최소 버전 요구
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //향후 지원되지 않는 것은 제외함을 의미
//창 열기
window = glfwCreateWindow( 1024, 768, "Window", NULL, NULL);
if( window == NULL ){
fprintf( stderr, "GLFW 창 열기 실패\n" );
getchar();
glfwTerminate();
return -1;
}
//현재 무슨 window를 사용할지 설정
glfwMakeContextCurrent(window);
//window 창에 대해서 입력받기 설정
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
//키 입력 콜백 설정
glfwSetKeyCallback(window, key_callback);
glewExperimental = true; // GLEW에 코어프로필 사용 설정
if (glewInit() != GLEW_OK) {
fprintf(stderr, "GLEW을 초기화 하는데에 실패했습니다.\n");
getchar();
glfwTerminate();
return -1;
}
glClearColor(0.0f, 0.3f, 0.1f, 0.0f);
GLuint VertexArrayID; //GLuint는 '이름' 역할을 하며, OpenGL의 객체입니다.
glGenVertexArrays(1, &VertexArrayID); //VAOs 생성 (한개) = 길이 1짜리 배열
glBindVertexArray(VertexArrayID); //이 VAO를 사용하겠다고 설정
//마름모 꼭지점 벡터들. 3개의 꼭지점이 한개의 면입니다.
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, 0.0f, 0.0f, //
1.0f, 0.0f, 0.0f, // 마름모 부분의 아랫면
0.0f, -1.0f, 0.0f, //
-1.0f, 0.0f, 0.0f, //
1.0f, 0.0f, 0.0f, // 마름모 부분의 윗면
0.0f, 1.0f, 0.0f, //
};
GLuint vertexbuffer; //한개의 객체가 될수 있으며, '이름'입니다.
glGenBuffers(1, &vertexbuffer); //VBO 생성 (Vertex buffer object)
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); //버퍼 사용 설정합니다.
//사용하기로한 vertexbuffer에 좌표점 설정
//STATIC_DRAW는 추후 변화 없음을 나타낸다. DYNAMIC_DRAW는 추후 변경 가능
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
do{
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(0); //첫번째 VAO (아까 생성한것) 활성화
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); //VBO 사용 설정
glVertexAttribPointer( //속성 지정(렌더링 할때 혹은, 초기화 할때 등..)
0, // 0번째의 Attribute라는것을 지정. 다른 수도 가능
3, // xyz임으로 3. xyzw이면 4
GL_FLOAT, // glBufferData로 넘긴 데이터의 타입 -> Float
GL_FALSE, // 정규화(normalized)
0, // 간격
(void*)0 // 배열 버퍼의 오프셋(offset; 옮기는 값)
);
glDrawArrays(GL_TRIANGLES, 0, 6); //점 0부터 6까지 그립니다.
glDisableVertexAttribArray(0);
glfwSwapBuffers(window); //더블 버퍼링, 버퍼 교체
glfwPollEvents(); //설정한 콜백들(key callback.. 등) 호출
}
while( glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS
&& glfwWindowShouldClose(window) == 0);
glDeleteBuffers(1, &vertexbuffer);
glDeleteVertexArrays(1, &VertexArrayID);
glfwTerminate();
return 0;
}
반응형
'프로그래밍' 카테고리의 다른 글
러스트 Rust, 라이프 타임이란? (0) | 2021.03.08 |
---|---|
Fedora 33 설치 후기 및 장단점 (2) | 2020.12.02 |
OpenGL과 GLFW 새 창 열기 튜토리얼 (0) | 2020.08.10 |
[Node.Js] HTTPS 인증하고, 서버 운영하기 (0) | 2020.01.10 |
[SCIKIT LEARN] CSV 파일을 데이터 배열로 나만의 데이터 만들기 (0) | 2019.11.03 |