// sb6.h 헤더 파일을 포함시킨다.
#include <sb7.h>
#include <vmath.h>
// sb6::application을 상속받는다.
class my_application : public sb7::application
{
public:
// 쉐이더 컴파일한다.
GLuint compile_shaders(void)
{
GLuint vertex_shader;
GLuint fragment_shader;
GLuint program;
// 버텍스 쉐이더 소스 코드
static const GLchar* vertex_shader_source[] =
{
"#version 430 core \n"
" \n"
"layout(location = 0) in vec3 pos; \n"
"layout(location = 1) in vec3 color; \n"
" \n"
"uniform mat4 rotMat; \n"
" \n"
"out vec3 vsColor; \n"
" \n"
"void main(void) \n"
"{ \n"
" gl_Position = rotMat*vec4(pos.x, pos.y, pos.z, 1.0); \n"
" \n"
" vsColor = color; \n"
"} \n"
};
// 프래그먼트 쉐이더 소스 코드
static const GLchar* fragment_shader_source[] =
{
"#version 430 core \n"
" \n"
"in vec3 vsColor; \n"
"out vec4 fragColor; \n"
" \n"
"void main(void) \n"
"{ \n"
" fragColor = vec4(vsColor, 1.0); \n"
"} \n"
};
// 버텍스 쉐이더를 생성하고 컴파일한다.
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, vertex_shader_source, NULL);
glCompileShader(vertex_shader);
// 프래그먼트 쉐이더를 생성하고 컴파일한다.
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, fragment_shader_source, NULL);
glCompileShader(fragment_shader);
// 프로그램을 생성하고 쉐이더를 Attach시키고 링크한다.
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
// 이제 프로그램이 쉐이더를 소유하므로 쉐이더를 삭제한다.
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return program;
}
// 애플리케이션 초기화 수행한다.
virtual void startup()
{
rendering_program = compile_shaders();
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
// 박스 점들의 위치와 컬러를 정의한다.
GLfloat vertices[] = {
-0.25f, 0.25f, -0.25f, 1.0f, 0.0f, 0.0f,
0.25f, -0.25f, -0.25f, 1.0f, 0.0f, 0.0f,
-0.25f, -0.25f, -0.25f, 1.0f, 0.0f, 0.0f,
0.25f, -0.25f, -0.25f, 1.0f, 0.0f, 0.0f,
-0.25f, 0.25f, -0.25f, 1.0f, 0.0f, 0.0f,
0.25f, 0.25f, -0.25f, 1.0f, 0.0f, 0.0f,
0.25f, -0.25f, -0.25f, 0.0f, 1.0f, 0.0f,
0.25f, 0.25f, -0.25f, 0.0f, 1.0f, 0.0f,
0.25f, -0.25f, 0.25f, 0.0f, 1.0f, 0.0f,
0.25f, -0.25f, 0.25f, 0.0f, 1.0f, 0.0f,
0.25f, 0.25f, -0.25f, 0.0f, 1.0f, 0.0f,
0.25f, 0.25f, 0.25f, 0.0f, 1.0f, 0.0f,
0.25f, -0.25f, 0.25f, 0.0f, 0.0f, 1.0f,
0.25f, 0.25f, 0.25f, 0.0f, 0.0f, 1.0f,
-0.25f, -0.25f, 0.25f, 0.0f, 0.0f, 1.0f,
-0.25f, -0.25f, 0.25f, 0.0f, 0.0f, 1.0f,
0.25f, 0.25f, 0.25f, 0.0f, 0.0f, 1.0f,
-0.25f, 0.25f, 0.25f, 0.0f, 0.0f, 1.0f,
-0.25f, -0.25f, 0.25f, 1.0f, 0.0f, 1.0f,
-0.25f, 0.25f, 0.25f, 1.0f, 0.0f, 1.0f,
-0.25f, -0.25f, -0.25f, 1.0f, 0.0f, 1.0f,
-0.25f, -0.25f, -0.25f, 1.0f, 0.0f, 1.0f,
-0.25f, 0.25f, 0.25f, 1.0f, 0.0f, 1.0f,
-0.25f, 0.25f, -0.25f, 1.0f, 0.0f, 1.0f,
-0.25f, -0.25f, 0.25f, 1.0f, 1.0f, 0.0f,
0.25f, -0.25f, -0.25f, 1.0f, 1.0f, 0.0f,
0.25f, -0.25f, 0.25f, 1.0f, 1.0f, 0.0f,
0.25f, -0.25f, -0.25f, 1.0f, 1.0f, 0.0f,
-0.25f, -0.25f, 0.25f, 1.0f, 1.0f, 0.0f,
-0.25f, -0.25f, -0.25f, 1.0f, 1.0f, 0.0f,
-0.25f, 0.25f, -0.25f, 0.0f, 1.0f, 1.0f,
0.25f, 0.25f, 0.25f, 0.0f, 1.0f, 1.0f,
0.25f, 0.25f, -0.25f, 0.0f, 1.0f, 1.0f,
0.25f, 0.25f, 0.25f, 0.0f, 1.0f, 1.0f,
-0.25f, 0.25f, -0.25f, 0.0f, 1.0f, 1.0f,
-0.25f, 0.25f, 0.25f, 0.0f, 1.0f, 1.0f
};
// VBO를 생성하여 vertices 값들을 복사
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// VBO를 나누어서 각 버텍스 속성으로 연결
// 위치 속성 (location = 0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 컬러 속성 (location = 1)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// VBO 및 버텍스 속성을 다 했으니 VBO와 VAO를 unbind한다.
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
// 애플리케이션 끝날 때 호출된다.
virtual void shutdown()
{
glDeleteVertexArrays(1, &VAO);
glDeleteProgram(rendering_program);
}
// 렌더링 virtual 함수를 작성해서 오버라이딩한다.
virtual void render(double currentTime)
{
const GLfloat color[] = { (float)sin(currentTime) * 0.5f + 0.5f, (float)cos(currentTime) * 0.5f + 0.5f, 0.0f, 1.0f };
const GLfloat black[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glClearBufferfv(GL_COLOR, 0, black);
//============================================================
glEnable(GL_CULL_FACE);
// 렌더링위해 생성한 프로그램 객체를 사용하도록 한다.
glUseProgram(rendering_program);
vmath::mat4 transM = vmath::translate(vmath::vec3((float)sin(currentTime), 0.0f, (float)cos(currentTime) * 0.3f));
float angle = currentTime * 150;
vmath::mat4 rotateM = vmath::rotate(angle, 0.0f, 1.0f, 0.0f);
vmath::vec3 eye(0.0, 1.0, -2.0);
vmath::vec3 center(0.0, 0.0, 0.0);
vmath::vec3 up(0.0, 1.0, 0.0);
vmath::mat4 lookAt = vmath::lookat(eye, center, up);
vmath::mat4 projM = vmath::perspective((float)cos(currentTime) * 20.f + 50.0f, info.windowWidth / info.windowHeight, 0.1f, 1000.0f);
// "rotMat" uniform에 대한 위치를 가져온다.
GLint rotMatLocation = glGetUniformLocation(rendering_program, "rotMat");
// "rotMat" uniform으로 전달한다.
glUniformMatrix4fv(rotMatLocation, 1, GL_FALSE, projM * lookAt * transM * rotateM);
// 원근투영 룩앳 도는거 회전
// 미리 설정한 VAO를 그리기 위해 bind한다.
glBindVertexArray(VAO);
// 삼각형을 12개 그린다. -> 정육면체
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 폴리곤 모드 쌉가능
glDrawArrays(GL_TRIANGLES, 0, 36);
}
private:
GLuint rendering_program;
GLuint VAO, VBO;
};
// DECLARE_MAIN의 하나뿐인 인스턴스
DECLARE_MAIN(my_application)
먼저 startup에서 삼각형 점의 위치들을 잡아준다
정육면체의 경우 총 12개의 삼각형이 들어가게 되므로 12개의 삼각형 점들을 정의해준다
transM은 오브젝트가 움직이는 매트릭스
rotateM은 오브젝트가 회전하는 매트릭스
eye는 카메라의 위치
center은 오브젝트의 위치
up은 카메라의 위쪽이 향하는 방향(카메라의 기울기)
projM은 카메라로부터 오브젝트의 거리가 멀 수록 오브젝트의 크기를 작아보기에 하는 매트릭스
lookAt은 eye, center, up을 포함하는 매트릭스이다
그리고 점의 위치에 원근투영, lookAt, 오브젝트의 움직임, 오브젝트의 회전을 순서대로 곱해주면
다음과 같은 결과물이 나온다
'opengl' 카테고리의 다른 글
opengl 텍스처 겹치기 / 컴파일 쉐이더, 텍스처로드 함수화 (0) | 2023.01.05 |
---|---|
opengl 텍스처 (0) | 2023.01.04 |
opengl 시점변환 원근투영 - 하드코딩 (0) | 2022.09.06 |
opengl 바람개비 회전 - 유니폼 VBO 사용 (0) | 2022.09.06 |
opengl 바람개비 보간 (0) | 2022.09.06 |