// sb6.h 헤더 파일을 포함시킨다.
#include <sb7.h>
#include <vmath.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.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"
"layout(location = 2) in vec2 texCoord; \n"
" \n"
"uniform mat4 rotMat; \n"
" \n"
"out vec3 vsColor; \n"
"out vec2 vsTexCoord; \n"
" \n"
"void main(void) \n"
"{ \n"
" gl_Position = rotMat*vec4(pos.x, pos.y, pos.z, 1.0); \n"
" \n"
" vsColor = color; \n"
" vsTexCoord = texCoord; \n"
"} \n"
};
// 프래그먼트 쉐이더 소스 코드
static const GLchar* fragment_shader_source[] =
{
"#version 430 core \n"
" \n"
"in vec3 vsColor; \n"
"in vec2 vsTexCoord; \n"
"uniform sampler2D texture1; \n"
"out vec4 fragColor; \n"
" \n"
"void main(void) \n"
"{ \n"
" fragColor = texture(texture1, vsTexCoord); \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);
// 박스 점들의 위치와 컬러를 정의한다.
//삼각형이 12개 필요함
GLfloat vertices[] = {
//맨 앞 사각형
-0.25f, 0.25f, -0.25f, 1.0f, 0.0f, 0.0f,0.0f,1.0f,
0.25f, -0.25f, -0.25f, 1.0f, 0.0f, 0.0f,1.0f,0.0f,
-0.25f, -0.25f, -0.25f, 1.0f, 0.0f, 0.0f,0.0f,0.0f,
0.25f, -0.25f, -0.25f, 1.0f, 0.0f, 0.0f,1.0f,0.0f,
-0.25f, 0.25f, -0.25f, 1.0f, 0.0f, 0.0f,0.0f,1.0f,
0.25f, 0.25f, -0.25f, 1.0f, 0.0f, 0.0f,1.0f,1.0f,
//왼쪽 측면 사각형
0.25f, -0.25f, -0.25f, 0.0f, 1.0f, 0.0f,0.0f,0.0f,
0.25f, 0.25f, -0.25f, 0.0f, 1.0f, 0.0f,0.0f,1.0f,
0.25f, -0.25f, 0.25f, 0.0f, 1.0f, 0.0f,1.0f,0.0f,
0.25f, -0.25f, 0.25f, 0.0f, 1.0f, 0.0f,1.0f,0.0f,
0.25f, 0.25f, -0.25f, 0.0f, 1.0f, 0.0f,0.0f,1.0f,
0.25f, 0.25f, 0.25f, 0.0f, 1.0f, 0.0f,1.0f,1.0f,
//뒤에 사각형
0.25f, -0.25f, 0.25f, 0.0f, 0.0f, 1.0f,0.0f,0.0f,
0.25f, 0.25f, 0.25f, 0.0f, 0.0f, 1.0f,0.0f,1.0f,
-0.25f, -0.25f, 0.25f, 0.0f, 0.0f, 1.0f,1.0f,0.0f,
-0.25f, -0.25f, 0.25f, 0.0f, 0.0f, 1.0f,1.0f,0.0f,
0.25f, 0.25f, 0.25f, 0.0f, 0.0f, 1.0f,0.0f,1.0f,
-0.25f, 0.25f, 0.25f, 0.0f, 0.0f, 1.0f,1.0f,1.0f,
//오른쪽 측면 사각형
-0.25f, -0.25f, 0.25f, 1.0f, 0.0f, 1.0f,0.0f,0.0f,
-0.25f, 0.25f, 0.25f, 1.0f, 0.0f, 1.0f,0.0f,1.0f,
-0.25f, -0.25f, -0.25f, 1.0f, 0.0f, 1.0f,1.0f,0.0f,
-0.25f, -0.25f, -0.25f, 1.0f, 0.0f, 1.0f,1.0f,0.0f,
-0.25f, 0.25f, 0.25f, 1.0f, 0.0f, 1.0f,0.0f,1.0f,
-0.25f, 0.25f, -0.25f, 1.0f, 0.0f, 1.0f,1.0f,1.0f,
//아래 사각형
-0.25f, -0.25f, 0.25f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,
0.25f, -0.25f, -0.25f, 1.0f, 1.0f, 0.0f,1.0f,0.0f,
0.25f, -0.25f, 0.25f, 1.0f, 1.0f, 0.0f,0.0f,0.0f,
0.25f, -0.25f, -0.25f, 1.0f, 1.0f, 0.0f,1.0f,0.0f,
-0.25f, -0.25f, 0.25f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,
-0.25f, -0.25f, -0.25f, 1.0f, 1.0f, 0.0f,1.0f,1.0f,
//위에 사각형
-0.25f, 0.25f, -0.25f, 0.0f, 1.0f, 1.0f,0.0f,1.0f,
0.25f, 0.25f, 0.25f, 0.0f, 1.0f, 1.0f,1.0f,0.0f,
0.25f, 0.25f, -0.25f, 0.0f, 1.0f, 1.0f,0.0f,0.0f,
0.25f, 0.25f, 0.25f, 0.0f, 1.0f, 1.0f,1.0f,0.0f,
-0.25f, 0.25f, -0.25f, 0.0f, 1.0f, 1.0f,0.0f,1.0f,
-0.25f, 0.25f, 0.25f, 0.0f, 1.0f, 1.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, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 컬러 속성 (location = 1)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 텍스처 좌표 속성 (location = 2)
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
// VBO 및 버텍스 속성을 다 했으니 VBO와 VAO를 unbind한다.
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
//---텍스트 처리
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
// 텍스처 이미지 로드하기
int width1, height1, nrChannels1;
unsigned char* data1 = stbi_load("side1.png", &width1, &height1, &nrChannels1, 0);
if (data1) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width1, height1, 0, GL_RGB, GL_UNSIGNED_BYTE, data1);
glGenerateMipmap(GL_TEXTURE_2D);
}
stbi_image_free(data1);
// 텍스처 샘플링/필터링 설정
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//----------
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
// 텍스처 이미지 로드하기
int width2, height2, nrChannels2;
unsigned char* data2 = stbi_load("side2.png", &width2, &height2, &nrChannels2, 0);
if (data2) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width2, height2, 0, GL_RGB, GL_UNSIGNED_BYTE, data2);
glGenerateMipmap(GL_TEXTURE_2D);
}
stbi_image_free(data2);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//----------------------------
glGenTextures(1, &texture3);
glBindTexture(GL_TEXTURE_2D, texture3);
// 텍스처 이미지 로드하기
int width3, height3, nrChannels3;
unsigned char* data3 = stbi_load("side3.png", &width3, &height3, &nrChannels3, 0);
if (data3) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width3, height3, 0, GL_RGB, GL_UNSIGNED_BYTE, data3);
glGenerateMipmap(GL_TEXTURE_2D);
}
stbi_image_free(data3);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//------------------
glGenTextures(1, &texture4);
glBindTexture(GL_TEXTURE_2D, texture4);
// 텍스처 이미지 로드하기
int width4, height4, nrChannels4;
unsigned char* data4 = stbi_load("side4.png", &width4, &height4, &nrChannels4, 0);
if (data4) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width4, height4, 0, GL_RGB, GL_UNSIGNED_BYTE, data4);
glGenerateMipmap(GL_TEXTURE_2D);
}
stbi_image_free(data4);
// 텍스처 샘플링/필터링 설정
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//------------------------
glGenTextures(1, &texture5);
glBindTexture(GL_TEXTURE_2D, texture5);
// 텍스처 이미지 로드하기
int width5, height5, nrChannels5;
unsigned char* data5 = stbi_load("side5.png", &width5, &height5, &nrChannels5, 0);
if (data5) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width5, height5, 0, GL_RGB, GL_UNSIGNED_BYTE, data5);
glGenerateMipmap(GL_TEXTURE_2D);
}
stbi_image_free(data5);
// 텍스처 샘플링/필터링 설정
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//--------------------------
glGenTextures(1, &texture6);
glBindTexture(GL_TEXTURE_2D, texture6);
// 텍스처 이미지 로드하기
int width6, height6, nrChannels6;
unsigned char* data6 = stbi_load("side6.png", &width6, &height6, &nrChannels6, 0);
if (data6) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width6, height6, 0, GL_RGB, GL_UNSIGNED_BYTE, data6);
glGenerateMipmap(GL_TEXTURE_2D);
}
stbi_image_free(data6);
// 텍스처 샘플링/필터링 설정
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
// 애플리케이션 끝날 때 호출된다.
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);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);// 정육면체처럼 보이게 해주는 함수
//=========================박스========================
// 렌더링위해 생성한 프로그램 객체를 사용하도록 한다.
glUseProgram(rendering_program);
vmath::mat4 transM = vmath::translate(vmath::vec3(0.0f, 0.8f, 0.0f));
float angle = currentTime * 100;
vmath::mat4 rotateM = vmath::rotate(angle, 0.0f, 1.0f, 0.0f);
vmath::mat4 rotateM10 = vmath::rotate(angle, 1.0f, 0.0f, 0.0f);
vmath::mat4 rotateM11 = vmath::rotate(angle, 0.0f, 0.0f, 1.0f);
vmath::vec3 eye(0.0, 1.5, -4.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(35.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 * rotateM10 * rotateM11);
glUniform1i(glGetUniformLocation(rendering_program, "texture1"), 5);
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_2D, texture1);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glUniform1i(glGetUniformLocation(rendering_program, "texture1"), 6);
glActiveTexture(GL_TEXTURE6);
glBindTexture(GL_TEXTURE_2D, texture2);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 6, 6);
glUniform1i(glGetUniformLocation(rendering_program, "texture1"), 7);
glActiveTexture(GL_TEXTURE7);
glBindTexture(GL_TEXTURE_2D, texture3);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 12, 6);
glUniform1i(glGetUniformLocation(rendering_program, "texture1"), 8);
glActiveTexture(GL_TEXTURE8);
glBindTexture(GL_TEXTURE_2D, texture4);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 18, 6);
glUniform1i(glGetUniformLocation(rendering_program, "texture1"), 9);
glActiveTexture(GL_TEXTURE9);
glBindTexture(GL_TEXTURE_2D, texture5);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 24, 6);
glUniform1i(glGetUniformLocation(rendering_program, "texture1"), 10);
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D, texture6);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 30, 6);
}
private:
GLuint rendering_program;
GLuint VAO, VBO;
GLuint EBO;
GLuint texture1, texture2, texture3, texture4, texture5, texture6;
};
// DECLARE_MAIN의 하나뿐인 인스턴스
DECLARE_MAIN(my_application)
먼저 정육면체의 점 위치를 저장할 VBO와 VAO를 선언하고 각 면에 붙일 텍스쳐를 6개 선언한다
startup에서 vertices[]배열 안에 삼각형 꼭지점의 좌표,색,가져올 텍스쳐의 좌표를 지정한다
한줄 앞의 3 값은 x,y,z값
4~6의 값은 r,g,b 값
7~8의 값은 가져올 텍스쳐의 좌표이다.
0번째부터 3칸까지 location = 0으로 보냄
4번째부터 6칸까지 location = 1로 보냄
7~8칸은 location =2로 보냄
startup의 텍스처 처리 부분이다
png 이미지 파일을 불러와서 data1에 저장하고 GL_TEXTURE_2D에 텍스처를 생성한다.
보낸 값은 쉐이더에서 in 으로 불러온다.
render함수에서 텍스처연결은 다음과 같다
uniform을 통해 쉐이더에서 선언한 texture1로 텍스처를 보내서 bind하고
glDrawArrays를 사용해 한쪽 면(0~6)은 같은 텍스처,
두번째 면(7~12)
세번째 면(13~18)... 이런식으로 다른 텍스처를 보내고 그려주는 것을 반복한다.
'opengl' 카테고리의 다른 글
opengl 라이팅 Phong모델 (0) | 2023.01.05 |
---|---|
opengl 텍스처 겹치기 / 컴파일 쉐이더, 텍스처로드 함수화 (0) | 2023.01.05 |
opengl 시점변환 원근투영 - opengl라이브러리 (0) | 2022.09.06 |
opengl 시점변환 원근투영 - 하드코딩 (0) | 2022.09.06 |
opengl 바람개비 회전 - 유니폼 VBO 사용 (0) | 2022.09.06 |