#version 330 core
in vec3 frag_normal;
in vec3 frag_worldPos;
in vec2 TexCoord; // 버텍스 세이더에서 uv 가져옴
out vec4 out_color; // 물체에 적용할 텍스처
uniform vec3 g_lightAmbient;
uniform vec3 g_lightPos;
uniform vec3 g_lightColor;
uniform vec3 g_objectColor;
uniform vec3 g_cameraPos;
uniform sampler2D texture1;
void main(void)
{
vec3 ambient = g_lightAmbient * g_lightColor;
vec3 normalVector = normalize(frag_normal);
vec3 lightDir = normalize(g_lightPos - frag_worldPos);
float diffuseLight = max(dot(normalVector, lightDir), 0.0);
vec3 diffuse = diffuseLight * g_lightColor;
int shininess = 128;
vec3 viewDir = normalize(g_cameraPos - frag_worldPos);
vec3 reflectDir = reflect(-lightDir, normalVector);
float specularLight = max(dot(viewDir, reflectDir), 0.0);
specularLight = pow(specularLight, shininess);
vec3 specular = specularLight * g_lightColor;
vec3 result = (ambient + diffuse + specular) * g_objectColor;
out_color = vec4(result, 1.0);
out_color = texture(texture1, TexCoord) * out_color; // 조명과 텍스처 모두 적용
}
stb_image.h 라이브러리가 미리 컴파일된 헤더에 적용이 안되서 main.cpp에 Texture
클래스를 생성함
#include "stdafx.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include "Shape.h"
#include "ShaderManager.h"
#include "Camera.h"
#include "Cube.h"
#include "Sphere.h"
#include "Light.h"
GLvoid drawScene(GLvoid);
GLvoid Reshape(int w, int h);
GLvoid Keyboard(unsigned char key, int x, int y);
GLvoid TimerFunction1(int value);
GLvoid Mouse(int button, int state, int x, int y);
GLfloat mx = 0.0f;
GLfloat my = 0.0f;
GLuint shader_program_ID;
ShaderManager shader_manager;
Camera cam;
Sphere sphere;
Light light;
Cube cube;
bool isTimer1On = false;
bool isTimer2On = false;
bool isTimer3On = false;
bool isAllStop = false;
class Texture {
public:
Texture() : skydata(stbi_load("Resources/sky.jpg", &tex_w, &tex_h, &numberOfChannel, 3)){
data[0] = stbi_load("Resources/tex0.png", &tex_w, &tex_h, &numberOfChannel, 3);
data[1] = stbi_load("Resources/tex1.png", &tex_w, &tex_h, &numberOfChannel, 3);
data[2] = stbi_load("Resources/tex2.png", &tex_w, &tex_h, &numberOfChannel, 3);
data[3] = stbi_load("Resources/tex3.png", &tex_w, &tex_h, &numberOfChannel, 3);
data[4] = stbi_load("Resources/tex4.png", &tex_w, &tex_h, &numberOfChannel, 3);
data[5] = stbi_load("Resources/tex5.png", &tex_w, &tex_h, &numberOfChannel, 3);
}
~Texture() {
stbi_image_free(skydata);
for (size_t i = 0; i < 6; i++)
{
stbi_image_free(data[i]);
}
}
void Init() {
glGenTextures(1, &texture_id); //--- 텍스처 생성
glBindTexture(GL_TEXTURE_2D, texture_id); //--- 텍스처 바인딩
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);
}
int tex_w = 200;
int tex_h = 200;
int numberOfChannel = 1;
unsigned char* skydata;
unsigned char* data[6];
unsigned int texture_id;
};
GLvoid drawScene() //--- 콜백 함수: 그리기 콜백 함수
{
//--- 변경된 배경색 설정
glClearColor(background_color.r, background_color.g, background_color.b, 1.0f); // 바탕색을 변경
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 설정된 색으로 전체를 칠하기
glFrontFace(GL_CCW);
glEnable(GL_DEPTH_TEST);
//glEnable(GL_CULL_FACE);
Texture tex;
tex.Init();
glUseProgram(shader_program_ID);
shader_manager.Mapping();
light.lightAmbient_loc = shader_manager.lightAmbi_loc;
light.lightPos_loc = shader_manager.lightPos_loc;
light.lightColor_loc = shader_manager.lightColor_loc;
light.objColor_loc = shader_manager.objColor_loc;
light.Init();
cam.view_loc = shader_manager.view_loc;
cam.cameraPos_loc = shader_manager.cameraPos_loc;
cam.proj_loc = shader_manager.proj_loc;
cam.Init();
glTexImage2D(GL_TEXTURE_2D, 0, 3, tex.tex_w, tex.tex_h, 0, GL_RGB, GL_UNSIGNED_BYTE, tex.skydata); //---텍스처 이미지 정의
cube.Init_And_Render(shader_manager.model_loc);
glTexImage2D(GL_TEXTURE_2D, 0, 3, tex.tex_w, tex.tex_h, 0, GL_RGB, GL_UNSIGNED_BYTE, tex.data[0]); //---텍스처 이미지 정의
sphere.Init_And_Render(shader_manager.model_loc);
glutSwapBuffers();
isAllStop = false;
glDisable(GL_DEPTH_TEST);
//glDisable(GL_CULL_FACE);
}
GLvoid Reshape(int w, int h) //--- 콜백 함수: 다시 그리기 콜백 함수
{
WIN_W = (float)w;
WIN_H = (float)h;
glViewport(0, 0, w, h);
}
GLvoid Keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 'r': case 'R':
light.isPlus_light = true;
if (!isTimer1On)
glutTimerFunc(100, TimerFunction1, 1);
isTimer1On = true;
break;
}
glutPostRedisplay(); //--- 배경색이 바뀔때마다 출력 콜백함수를 호출하여 화면을 refresh 한다
}
//앞면이 올라가고 로봇이 팔다리를 흔듦
GLvoid TimerFunction1(int value)
{
if (light.isPlus_light) {
light.yRotate_light -= 1.0 / 58.0;
light.yRotate_lightbox += 1.0f;
}
else if (!light.isPlus_light) {
light.yRotate_light += 1.0 / 58.0;
light.yRotate_lightbox -= 1.0f;
}
glutPostRedisplay(); // 화면 재 출력
if (isTimer1On)
glutTimerFunc(100, TimerFunction1, 1);
}
GLvoid Mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
}
glutPostRedisplay();
}
int main(int argc, char** argv) //--- 윈도우 출력하고 콜백함수 설정
{ //--- 윈도우 생성하기
glutInit(&argc, argv); // glut 초기화
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); // 디스플레이 모드 설정
glutInitWindowPosition(WIN_X, WIN_Y); // 윈도우의 위치 지정
glutInitWindowSize((int)WIN_W, (int)WIN_H); // 윈도우의 크기 지정
glutCreateWindow("Example1"); // 윈도우 생성 (윈도우 이름)
//--- GLEW 초기화하기
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) // glew 초기화
{
std::cerr << "Unable to initialize GLEW" << std::endl;
exit(EXIT_FAILURE);
}
else
std::cout << "GLEW Initialized\n";
if (!shader_manager.Init_Program()) {
cerr << "Error: Shader Program 생성 실패" << endl;
std::exit(EXIT_FAILURE);
}
shader_program_ID = shader_manager.shader_program_ID;
stbi_set_flip_vertically_on_load(true); //--- 이미지가 거꾸로 읽힌다면 추가
if (!sphere.Init_VAO(shader_program_ID)) {
cerr << "Error: 구 생성 실패" << endl;
std::exit(EXIT_FAILURE);
}
cube.texturing_face = 2;
if (!cube.Init_VAO(shader_program_ID)) {
cerr << "Error: 구 생성 실패" << endl;
std::exit(EXIT_FAILURE);
}
glutDisplayFunc(drawScene); // 출력 함수의 지정
glutReshapeFunc(Reshape); // 다시 그리기 함수 지정
glutKeyboardFunc(Keyboard);
glutMouseFunc(Mouse);
glutMainLoop(); // 이벤트 처리 시작
}