Implement skybox

This commit is contained in:
Abdelrahman Said 2024-12-28 00:14:25 +00:00
parent 68cc990650
commit 13bedc164c
9 changed files with 106 additions and 3 deletions

BIN
images/skybox/back.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

BIN
images/skybox/bottom.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

BIN
images/skybox/front.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 KiB

BIN
images/skybox/left.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 KiB

BIN
images/skybox/right.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 KiB

BIN
images/skybox/top.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

11
shaders/sb_frag.glsl Normal file
View File

@ -0,0 +1,11 @@
#version 330 core
in vec3 uv_coords;
uniform samplerCube cubemap;
out vec4 color;
void main() {
color = texture(cubemap, uv_coords);
}

16
shaders/sb_vert.glsl Normal file
View File

@ -0,0 +1,16 @@
#version 330 core
layout(location=0) in vec3 position;
layout(location=1) in vec3 normal;
layout(location=2) in vec2 uv;
uniform mat4 view;
uniform mat4 projection;
out vec3 uv_coords;
void main() {
vec4 pos = projection * view * vec4(position, 1.0);
gl_Position = pos.xyww;
uv_coords = position;
}

View File

@ -144,6 +144,7 @@ struct FrameBuffer {
FrameBuffer create_frame_buffer(unsigned int width, unsigned int height); FrameBuffer create_frame_buffer(unsigned int width, unsigned int height);
void delete_frame_buffer(FrameBuffer &buffer); void delete_frame_buffer(FrameBuffer &buffer);
GLuint load_cubemap(std::vector<std::string> textures);
int main() { int main() {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
@ -221,8 +222,36 @@ int main() {
13, 15, 16 13, 15, 16
}; };
Model backpack = {"models/suzanne/suzanne.obj"}; Model suzanne = {"models/suzanne/suzanne.obj"};
Mesh light = {vertices, indices, {}}; Mesh light = {vertices, indices, {}};
std::vector<Vertex> skybox_vertices = {
Vertex{glm::vec3(-1.0f, 1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3( 1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3( 1.0f, 1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3( 1.0f, -1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
Vertex{glm::vec3( 1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
};
std::vector<GLuint> skybox_indices = {
0, 1, 2,
2, 3, 0,
4, 1, 0,
0, 5, 4,
2, 6, 7,
7, 3, 2,
4, 5, 7,
7, 6, 4,
0, 3, 7,
7, 5, 0,
1, 4, 2,
2, 4, 6,
};
Mesh skybox = {skybox_vertices, skybox_indices, {}};
std::vector<Vertex> screen_vertices = { std::vector<Vertex> screen_vertices = {
Vertex{glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(0.0f, 0.0f)}, Vertex{glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(0.0f, 0.0f)},
@ -240,6 +269,7 @@ int main() {
Shader main_shader {"shaders/vert.glsl", "shaders/frag.glsl"}; Shader main_shader {"shaders/vert.glsl", "shaders/frag.glsl"};
Shader light_shader {"shaders/vert.glsl", "shaders/light_frag.glsl"}; Shader light_shader {"shaders/vert.glsl", "shaders/light_frag.glsl"};
Shader skybox_shader {"shaders/sb_vert.glsl", "shaders/sb_frag.glsl"};
Shader post_processing {"shaders/pp_vert.glsl", "shaders/pp_frag.glsl"}; Shader post_processing {"shaders/pp_vert.glsl", "shaders/pp_frag.glsl"};
const float camera_speed = 25.0f; const float camera_speed = 25.0f;
@ -262,6 +292,7 @@ int main() {
main_shader.set_float("material.shininess", 32.0f); main_shader.set_float("material.shininess", 32.0f);
light_shader.set_mat4("projection", projection); light_shader.set_mat4("projection", projection);
skybox_shader.set_mat4("projection", projection);
std::vector<glm::vec3> point_light_positions = { std::vector<glm::vec3> point_light_positions = {
glm::vec3( 0.7f, 0.2f, 2.0f), glm::vec3( 0.7f, 0.2f, 2.0f),
@ -317,6 +348,18 @@ int main() {
memset(quadratic, 0, sizeof(quadratic)); memset(quadratic, 0, sizeof(quadratic));
} }
// Load cube map
std::vector<std::string> cube_map_textures = {
"images/skybox/right.jpg",
"images/skybox/left.jpg",
"images/skybox/top.jpg",
"images/skybox/bottom.jpg",
"images/skybox/front.jpg",
"images/skybox/back.jpg",
};
GLuint cubemap = load_cubemap(cube_map_textures);
const float sensitivity = 0.1f; const float sensitivity = 0.1f;
int last_mouse_x = WINDOW_HALF_WIDTH; int last_mouse_x = WINDOW_HALF_WIDTH;
int last_mouse_y = WINDOW_HALF_HEIGHT; int last_mouse_y = WINDOW_HALF_HEIGHT;
@ -402,13 +445,16 @@ int main() {
main_shader.set_float("spot_light.outer_cutoff", glm::cos(glm::radians(17.5))); main_shader.set_float("spot_light.outer_cutoff", glm::cos(glm::radians(17.5)));
main_shader.set_mat4("view", view); main_shader.set_mat4("view", view);
light_shader.set_mat4("view", view); light_shader.set_mat4("view", view);
skybox_shader.set_mat4("view", glm::mat4(glm::mat3(view)));
// Main render pass // Main render pass
glBindFramebuffer(GL_FRAMEBUFFER, offscreen_buffer.fbo); glBindFramebuffer(GL_FRAMEBUFFER, offscreen_buffer.fbo);
glClearColor(0.04f, 0.08f, 0.08f, 1.0f); glClearColor(0.04f, 0.08f, 0.08f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f)); model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
@ -416,7 +462,7 @@ int main() {
main_shader.activate(); main_shader.activate();
main_shader.set_mat4("model", model); main_shader.set_mat4("model", model);
main_shader.set_mat3("normal_mat", normal_mat); main_shader.set_mat3("normal_mat", normal_mat);
backpack.draw(main_shader); suzanne.draw(main_shader);
// Draw light source // Draw light source
for (int i = 0; i < point_light_positions.size(); ++i) { for (int i = 0; i < point_light_positions.size(); ++i) {
@ -428,6 +474,14 @@ int main() {
light.draw(light_shader); light.draw(light_shader);
} }
// Draw skybox
glDisable(GL_CULL_FACE);
skybox_shader.activate();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
skybox_shader.set_int("cubemap", 0);
skybox.draw(skybox_shader);
// wireframe mode // wireframe mode
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
@ -816,3 +870,25 @@ void delete_frame_buffer(FrameBuffer &buffer) {
glDeleteTextures(1, &buffer.color); glDeleteTextures(1, &buffer.color);
glDeleteRenderbuffers(1, &buffer.depth_stencil); glDeleteRenderbuffers(1, &buffer.depth_stencil);
} }
GLuint load_cubemap(std::vector<std::string> textures) {
GLuint cubemap;
glGenTextures(1, &cubemap);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
int width, height, channels;
uint8_t *tex;
for (unsigned int i = 0; i < textures.size(); ++i) {
tex = stbi_load(textures[i].c_str(), &width, &height, &channels, 0);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, tex);
stbi_image_free(tex);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
return cubemap;
}