diff --git a/24-cubemaps/config.json b/24-cubemaps/config.json index ea49535..3fe7222 100644 --- a/24-cubemaps/config.json +++ b/24-cubemaps/config.json @@ -8,6 +8,18 @@ "vertex_path": "shaders/21-screen.vert.glsl", "frag_path": "shaders/21-screen.frag.glsl" }, + "skybox_shader": { + "vertex_path": "shaders/24-skybox.vert.glsl", + "frag_path": "shaders/24-skybox.frag.glsl" + }, + "skybox_faces": [ + "../assets/skybox/right.jpg", + "../assets/skybox/left.jpg", + "../assets/skybox/top.jpg", + "../assets/skybox/bottom.jpg", + "../assets/skybox/front.jpg", + "../assets/skybox/back.jpg" + ], "materials": { "default": { "ambient": [0.5, 0.5, 0.5], diff --git a/24-cubemaps/shaders/24-skybox.frag.glsl b/24-cubemaps/shaders/24-skybox.frag.glsl new file mode 100644 index 0000000..2205847 --- /dev/null +++ b/24-cubemaps/shaders/24-skybox.frag.glsl @@ -0,0 +1,11 @@ +#version 330 core +out vec4 FragColor; + +in vec3 TexCoords; + +uniform samplerCube skybox; + +void main() +{ + FragColor = texture(skybox, TexCoords); +} diff --git a/24-cubemaps/shaders/24-skybox.vert.glsl b/24-cubemaps/shaders/24-skybox.vert.glsl new file mode 100644 index 0000000..f3e48d6 --- /dev/null +++ b/24-cubemaps/shaders/24-skybox.vert.glsl @@ -0,0 +1,14 @@ +#version 330 core +layout (location = 0) in vec3 aPos; + +out vec3 TexCoords; + +uniform mat4 projection; +uniform mat4 view; + +void main() +{ + TexCoords = aPos; + vec4 pos = projection * view * vec4(aPos, 1.0); + gl_Position = pos.xyww; +} diff --git a/24-cubemaps/src/components.hpp b/24-cubemaps/src/components.hpp index ff9ff06..8753f4c 100644 --- a/24-cubemaps/src/components.hpp +++ b/24-cubemaps/src/components.hpp @@ -103,6 +103,8 @@ namespace components { struct Scene { components::Shader shader; components::Shader screen_shader; + components::Shader skybox_shader; + std::vector skybox_faces; std::unordered_map materials; std::unordered_map models; std::vector things; @@ -110,5 +112,5 @@ namespace components { Lighting light; }; - ENROLL_COMPONENT(Scene, shader, screen_shader, materials, models, things, camera, light); + ENROLL_COMPONENT(Scene, shader, screen_shader, skybox_shader, skybox_faces, materials, models, things, camera, light); } diff --git a/24-cubemaps/src/scene.cpp b/24-cubemaps/src/scene.cpp index b692bd4..645c12f 100644 --- a/24-cubemaps/src/scene.cpp +++ b/24-cubemaps/src/scene.cpp @@ -1,6 +1,7 @@ #include "scene.hpp" #include "dbc.hpp" #include +#include "skybox.hpp" void Scene::update() { float currentFrame = glfwGetTime(); @@ -51,6 +52,8 @@ void Scene::render(GLFWwindow* window) { draw_thing(shader, thing); } + render_skybox(projection); + framebuffer.commit(); framebuffer.draw(screen); @@ -73,3 +76,58 @@ void Scene::spawn(const std::string& name, components::Position& position, compo dbc::log($F("No model named: {}", name)); } } + +void Scene::init_skybox() { + glGenVertexArrays(1, &skyboxVAO); + glGenBuffers(1, &skyboxVBO); + glBindVertexArray(skyboxVAO); + glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); + + load_skybox_textures(); +} + + +void Scene::load_skybox_textures() { + int width = 0; + int height = 0; + int nrChannels = 0; + size_t face_i = 0; + + glGenTextures(1, &skybox_texture_id); + glBindTexture(GL_TEXTURE_CUBE_MAP, skybox_texture_id); + + for(const auto& face : skybox_faces) { + unsigned char *data = stbi_load(face.c_str(), &width, &height, &nrChannels, 0); + dbc::check(data != nullptr, $F("Failed to load skybox face {}", face)); + dbc::check(nrChannels == 3, $F("Skybox face {} must be RGB but you have {} channels", face, nrChannels)); + + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face_i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + face_i++; + + stbi_image_free(data); + } + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_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); +} + +void Scene::render_skybox(const glm::mat4& projection) { + glDepthFunc(GL_LEQUAL); + skybox_shader.use(); + glm::mat4 view = glm::mat4(glm::mat3(camera.look_at())); + skybox_shader.setMat4("view", view); + skybox_shader.setMat4("projection", projection); + + glBindVertexArray(skyboxVAO); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, skybox_texture_id); + glDrawArrays(GL_TRIANGLES, 0, 36); + glBindVertexArray(0); + glDepthFunc(GL_LESS); +} diff --git a/24-cubemaps/src/scene.hpp b/24-cubemaps/src/scene.hpp index edc4f39..152bf95 100644 --- a/24-cubemaps/src/scene.hpp +++ b/24-cubemaps/src/scene.hpp @@ -27,6 +27,8 @@ struct Thing { struct Scene { Shader shader; + Shader skybox_shader; + std::vector skybox_faces; Screen screen; FrameBuffer framebuffer; @@ -35,12 +37,16 @@ struct Scene { components::Lighting light; std::unordered_map models; std::vector things; - float deltaTime = 0.0f; float lastFrame = 0.0f; + unsigned int skyboxVAO = 0; + unsigned int skyboxVBO = 0; + unsigned int skybox_texture_id = 0; Scene(components::Scene& config): shader{config.shader.vertex_path, config.shader.frag_path}, + skybox_shader{config.skybox_shader.vertex_path, config.skybox_shader.frag_path}, + skybox_faces{config.skybox_faces}, screen{.shader={config.screen_shader.vertex_path, config.screen_shader.frag_path}}, materials{config.materials}, camera{ @@ -70,8 +76,12 @@ struct Scene { shader.setInt("texture1", 0); shader.apply_lighting(light); + skybox_shader.use(); + skybox_shader.setInt("skybox", 0); + framebuffer.init(); screen.init(); + init_skybox(); } void update(); @@ -79,4 +89,7 @@ struct Scene { void render(GLFWwindow* window); void cleanup(); void spawn(const std::string& name, components::Position& position, components::Rotation& rotation); + void init_skybox(); + void load_skybox_textures(); + void render_skybox(const glm::mat4& projection); }; diff --git a/24-cubemaps/src/skybox.hpp b/24-cubemaps/src/skybox.hpp new file mode 100644 index 0000000..9ac78e1 --- /dev/null +++ b/24-cubemaps/src/skybox.hpp @@ -0,0 +1,46 @@ +#pragma once + +float skyboxVertices[] = { + // positions + -1.0f, 1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + + -1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + + -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + + -1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, + + -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, 1.0f +}; diff --git a/assets/skybox/back.jpg b/assets/skybox/back.jpg new file mode 100644 index 0000000..470a679 Binary files /dev/null and b/assets/skybox/back.jpg differ diff --git a/assets/skybox/bottom.jpg b/assets/skybox/bottom.jpg new file mode 100644 index 0000000..893f394 Binary files /dev/null and b/assets/skybox/bottom.jpg differ diff --git a/assets/skybox/front.jpg b/assets/skybox/front.jpg new file mode 100644 index 0000000..4e17b77 Binary files /dev/null and b/assets/skybox/front.jpg differ diff --git a/assets/skybox/left.jpg b/assets/skybox/left.jpg new file mode 100644 index 0000000..5750b91 Binary files /dev/null and b/assets/skybox/left.jpg differ diff --git a/assets/skybox/right.jpg b/assets/skybox/right.jpg new file mode 100644 index 0000000..8963037 Binary files /dev/null and b/assets/skybox/right.jpg differ diff --git a/assets/skybox/top.jpg b/assets/skybox/top.jpg new file mode 100644 index 0000000..4db3c2a Binary files /dev/null and b/assets/skybox/top.jpg differ