]> git.localhorst.tv Git - blobs.git/commitdiff
basic sky box
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 17 Dec 2017 16:17:31 +0000 (17:17 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 17 Dec 2017 16:17:31 +0000 (17:17 +0100)
README.md
assets
src/app/Assets.hpp
src/app/app.cpp
src/app/states.cpp
src/graphics/Camera.hpp
src/graphics/SkyBox.hpp [new file with mode: 0644]
src/graphics/shader.cpp
src/graphics/viewport.cpp

index 70d4af62c46e649c383a276ea8367eed4bbe70d7..4f12594d4ddfc7fd59595c214e3aa46e9b53c137 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,2 +1,4 @@
 # blobs [![Build Status](https://travis-ci.org/HolySmoke86/blobs.svg?branch=master)](https://travis-ci.org/HolySmoke86/blobs) [![codecov.io](https://codecov.io/github/HolySmoke86/blobs/coverage.svg?branch=master)](https://codecov.io/github/HolySmoke86/blobs?branch=master)
 blobs
+
+Many thanks for the sky box to [StumpyStrust from opengameart.org](https://opengameart.org/content/space-skyboxes-0)
diff --git a/assets b/assets
index f2587b6b95d73b9b2d2d871e9a8f5b5dae702965..7c4c2fb847cfdf25d90d6b2c46442b8cf899a96a 160000 (submodule)
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit f2587b6b95d73b9b2d2d871e9a8f5b5dae702965
+Subproject commit 7c4c2fb847cfdf25d90d6b2c46442b8cf899a96a
index 0512f7e5642c3f67c85a6a92b56d11ea233648df..0d725ccef34a527e1c5c540a1df91f96256db9c8 100644 (file)
@@ -6,8 +6,10 @@
 #include "../graphics/ArrayTexture.hpp"
 #include "../graphics/Canvas.hpp"
 #include "../graphics/CreatureSkin.hpp"
+#include "../graphics/CubeMap.hpp"
 #include "../graphics/Font.hpp"
 #include "../graphics/PlanetSurface.hpp"
+#include "../graphics/SkyBox.hpp"
 #include "../graphics/SunSurface.hpp"
 #include "../math/GaloisLFSR.hpp"
 #include "../world/Resource.hpp"
@@ -29,6 +31,7 @@ struct Assets {
        std::string data_path;
        std::string font_path;
        std::string skin_path;
+       std::string sky_path;
        std::string tile_path;
 
        math::GaloisLFSR random;
@@ -49,6 +52,7 @@ struct Assets {
        struct {
                graphics::ArrayTexture tiles;
                graphics::ArrayTexture skins;
+               graphics::CubeMap sky;
        } textures;
 
        struct {
@@ -57,6 +61,7 @@ struct Assets {
                graphics::PlanetSurface planet_surface;
                graphics::SunSurface sun_surface;
                graphics::CreatureSkin creature_skin;
+               graphics::SkyBox sky_box;
        } shaders;
 
        Assets();
@@ -73,6 +78,7 @@ struct Assets {
 
        void LoadTileTexture(const std::string &name, graphics::ArrayTexture &, int layer) const;
        void LoadSkinTexture(const std::string &name, graphics::ArrayTexture &, int layer) const;
+       void LoadSkyTexture(const std::string &name, graphics::CubeMap &) const;
 
 };
 
index f847a79176701f174a60bdaf323b5efda252320f..0f50aa75d00104a21fe5a32a988bef297a98580f 100644 (file)
@@ -175,6 +175,7 @@ Assets::Assets()
 , data_path(path + "data/")
 , font_path(path + "fonts/")
 , skin_path(path + "skins/")
+, sky_path(path + "skies/")
 , tile_path(path + "tiles/")
 , random(0x6283B64CEFE57925)
 , fonts{
@@ -223,6 +224,11 @@ Assets::Assets()
        LoadSkinTexture("spots", textures.skins, 4);
        LoadSkinTexture("circles", textures.skins, 5);
        textures.skins.FilterTrilinear();
+
+       textures.sky.Bind();
+       LoadSkyTexture("blue", textures.sky);
+       textures.sky.FilterTrilinear();
+       textures.sky.WrapEdge();
 }
 
 Assets::~Assets() {
@@ -385,5 +391,71 @@ void Assets::LoadSkinTexture(const string &name, graphics::ArrayTexture &tex, in
        SDL_FreeSurface(srf);
 }
 
+void Assets::LoadSkyTexture(const string &name, graphics::CubeMap &cm) const {
+       string full = sky_path + name;
+       string right = full + "-right.png";
+       string left = full + "-left.png";
+       string top = full + "-top.png";
+       string bottom = full + "-bottom.png";
+       string back = full + "-back.png";
+       string front = full + "-front.png";
+
+       SDL_Surface *srf = nullptr;
+
+       if (!(srf = IMG_Load(right.c_str()))) throw SDLError("IMG_Load");
+       try {
+               cm.Data(graphics::CubeMap::RIGHT, *srf);
+       } catch (...) {
+               SDL_FreeSurface(srf);
+               throw;
+       }
+       SDL_FreeSurface(srf);
+
+       if (!(srf = IMG_Load(left.c_str()))) throw SDLError("IMG_Load");
+       try {
+               cm.Data(graphics::CubeMap::LEFT, *srf);
+       } catch (...) {
+               SDL_FreeSurface(srf);
+               throw;
+       }
+       SDL_FreeSurface(srf);
+
+       if (!(srf = IMG_Load(top.c_str()))) throw SDLError("IMG_Load");
+       try {
+               cm.Data(graphics::CubeMap::TOP, *srf);
+       } catch (...) {
+               SDL_FreeSurface(srf);
+               throw;
+       }
+       SDL_FreeSurface(srf);
+
+       if (!(srf = IMG_Load(bottom.c_str()))) throw SDLError("IMG_Load");
+       try {
+               cm.Data(graphics::CubeMap::BOTTOM, *srf);
+       } catch (...) {
+               SDL_FreeSurface(srf);
+               throw;
+       }
+       SDL_FreeSurface(srf);
+
+       if (!(srf = IMG_Load(back.c_str()))) throw SDLError("IMG_Load");
+       try {
+               cm.Data(graphics::CubeMap::BACK, *srf);
+       } catch (...) {
+               SDL_FreeSurface(srf);
+               throw;
+       }
+       SDL_FreeSurface(srf);
+
+       if (!(srf = IMG_Load(front.c_str()))) throw SDLError("IMG_Load");
+       try {
+               cm.Data(graphics::CubeMap::FRONT, *srf);
+       } catch (...) {
+               SDL_FreeSurface(srf);
+               throw;
+       }
+       SDL_FreeSurface(srf);
+}
+
 }
 }
index 8647ff63d49ce4375645395b9df14fa353ba63ec..3736331cb54532935d4b16ec9ac0098eae19f09a 100644 (file)
@@ -89,6 +89,8 @@ void MasterState::OnResize(int w, int h) {
        assets.shaders.sun_surface.SetVP(cam.View(), cam.Projection());
        assets.shaders.creature_skin.Activate();
        assets.shaders.creature_skin.SetVP(cam.View(), cam.Projection());
+       assets.shaders.sky_box.Activate();
+       assets.shaders.sky_box.SetVP(cam.View() * cam.Universe(), cam.Projection());
 }
 
 void MasterState::OnUpdate(int dt) {
@@ -244,6 +246,8 @@ void MasterState::OnRender(graphics::Viewport &viewport) {
        cam.LookAt(glm::vec3(cam_pos), glm::vec3(cam_focus), glm::vec3(cam_up));
        assets.shaders.planet_surface.Activate();
        assets.shaders.planet_surface.SetV(cam.View());
+       assets.shaders.sky_box.Activate();
+       assets.shaders.sky_box.SetV(cam.View() * cam.Universe());
        assets.shaders.sun_surface.Activate();
        assets.shaders.sun_surface.SetV(cam.View());
        assets.shaders.creature_skin.Activate();
@@ -306,6 +310,10 @@ void MasterState::OnRender(graphics::Viewport &viewport) {
                c->Draw(viewport);
        }
 
+       assets.shaders.sky_box.Activate();
+       assets.shaders.sky_box.SetTexture(assets.textures.sky);
+       assets.shaders.sky_box.Draw();
+
        viewport.ClearDepth();
        bp.Draw(viewport);
        cp.Draw(viewport);
index b00d580615558457ef488076a013b8fedf027920..a3a9e577a8a5dd5cbfadbf0a405a76abb45c38b5 100644 (file)
@@ -39,6 +39,7 @@ public:
        const glm::mat4 &Projection() const noexcept { return projection; }
        const glm::mat4 &View() const noexcept { return view; }
        glm::mat4 Model(const world::Body &) const noexcept;
+       glm::mat4 Universe() const noexcept;
 
 private:
        void UpdateProjection() noexcept;
diff --git a/src/graphics/SkyBox.hpp b/src/graphics/SkyBox.hpp
new file mode 100644 (file)
index 0000000..8326c64
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef BLOBS_GRAPHICS_SKYBOX_HPP_
+#define BLOBS_GRAPHICS_SKYBOX_HPP_
+
+#include "Program.hpp"
+#include "SimpleVAO.hpp"
+
+#include  <cstdint>
+
+
+namespace blobs {
+namespace graphics {
+
+class CubeMap;
+
+class SkyBox {
+
+public:
+       SkyBox();
+       ~SkyBox();
+
+       SkyBox(const SkyBox &) = delete;
+       SkyBox &operator =(const SkyBox &) = delete;
+
+       SkyBox(SkyBox &&) = delete;
+       SkyBox &operator =(SkyBox &&) = delete;
+
+public:
+       void Activate() noexcept;
+
+       void SetV(const glm::mat4 &v) noexcept;
+       void SetP(const glm::mat4 &p) noexcept;
+       void SetVP(const glm::mat4 &v, const glm::mat4 &p) noexcept;
+       void SetTexture(CubeMap &) noexcept;
+
+       const glm::mat4 &V() const noexcept { return v; }
+       const glm::mat4 &P() const noexcept { return p; }
+       const glm::mat4 &VP() const noexcept { return vp; }
+
+       void Draw() const noexcept;
+
+private:
+       Program prog;
+
+       glm::mat4 v;
+       glm::mat4 p;
+       glm::mat4 vp;
+
+       GLuint vp_handle;
+       GLuint sampler_handle;
+
+       SimpleVAO<glm::vec3, std::uint8_t> vao;
+
+};
+
+}
+}
+
+#endif
index b74d225f8d49b34a8d749fa5c127f8f9dbc381eb..f68b5b523c450f1f373ad27ef4b7343d215d3b99 100644 (file)
@@ -4,9 +4,11 @@
 #include "PlanetSurface.hpp"
 #include "Program.hpp"
 #include "Shader.hpp"
+#include "SkyBox.hpp"
 #include "SunSurface.hpp"
 
 #include "ArrayTexture.hpp"
+#include "CubeMap.hpp"
 #include "Texture.hpp"
 #include "../app/init.hpp"
 
@@ -330,6 +332,131 @@ void PlanetSurface::SetNumLights(int n) noexcept {
 }
 
 
+SkyBox::SkyBox()
+: prog()
+, v(1.0f)
+, p(1.0f)
+, vp(1.0f) {
+       prog.LoadShader(
+               GL_VERTEX_SHADER,
+               "#version 330 core\n"
+
+               "layout(location = 0) in vec3 vtx_position;\n"
+
+               "uniform mat4 VP;\n"
+
+               "out vec3 vtx_viewspace;\n"
+
+               "void main() {\n"
+                       "gl_Position = VP * vec4(vtx_position, 1.0);\n"
+                       "gl_Position.z = gl_Position.w;\n"
+                       "vtx_viewspace = vtx_position;\n"
+               "}\n"
+       );
+       prog.LoadShader(
+               GL_FRAGMENT_SHADER,
+               "#version 330 core\n"
+
+               "in vec3 vtx_viewspace;\n"
+
+               "uniform samplerCube tex_sampler;\n"
+
+               "out vec3 color;\n"
+
+               "void main() {\n"
+                       "color = texture(tex_sampler, vtx_viewspace).rgb;\n"
+               "}\n"
+       );
+       prog.Link();
+       if (!prog.Linked()) {
+               prog.Log(std::cerr);
+               throw std::runtime_error("link program");
+       }
+       vp_handle = prog.UniformLocation("VP");
+       sampler_handle = prog.UniformLocation("tex_sampler");
+
+       vao.Bind();
+       vao.BindAttributes();
+       vao.EnableAttribute(0);
+       vao.AttributePointer<glm::vec3>(0, false, 0);
+       vao.ReserveAttributes(8, GL_STATIC_DRAW);
+       {
+               auto attrib = vao.MapAttributes(GL_WRITE_ONLY);
+               attrib[0] = glm::vec3(-1.0f, -1.0f, -1.0f);
+               attrib[1] = glm::vec3(-1.0f, -1.0f,  1.0f);
+               attrib[2] = glm::vec3(-1.0f,  1.0f, -1.0f);
+               attrib[3] = glm::vec3(-1.0f,  1.0f,  1.0f);
+               attrib[4] = glm::vec3( 1.0f, -1.0f, -1.0f);
+               attrib[5] = glm::vec3( 1.0f, -1.0f,  1.0f);
+               attrib[6] = glm::vec3( 1.0f,  1.0f, -1.0f);
+               attrib[7] = glm::vec3( 1.0f,  1.0f,  1.0f);
+       }
+       vao.BindElements();
+       vao.ReserveElements(14, GL_STATIC_DRAW);
+       {
+               auto element = vao.MapElements(GL_WRITE_ONLY);
+               element[ 0] = 1;
+               element[ 1] = 0;
+               element[ 2] = 3;
+               element[ 3] = 2;
+               element[ 4] = 6;
+               element[ 5] = 0;
+               element[ 6] = 4;
+               element[ 7] = 1;
+               element[ 8] = 5;
+               element[ 9] = 3;
+               element[10] = 7;
+               element[11] = 6;
+               element[12] = 5;
+               element[13] = 4;
+       }
+       vao.Unbind();
+}
+
+SkyBox::~SkyBox() {
+}
+
+void SkyBox::Activate() noexcept {
+       prog.Use();
+       glEnable(GL_DEPTH_TEST);
+       glDepthFunc(GL_LEQUAL);
+       glDisable(GL_CULL_FACE);
+       glDisable(GL_BLEND);
+}
+
+void SkyBox::SetV(const glm::mat4 &vv) noexcept {
+       v = vv;
+       v[0].w = 0.0f;
+       v[1].w = 0.0f;
+       v[2].w = 0.0f;
+       v[3] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
+       vp = p * v;
+       prog.Uniform(vp_handle, vp);
+}
+
+void SkyBox::SetP(const glm::mat4 &pp) noexcept {
+       p = pp;
+       vp = p * v;
+       prog.Uniform(vp_handle, vp);
+}
+
+void SkyBox::SetVP(const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
+       p = pp;
+       SetV(vv);
+}
+
+void SkyBox::SetTexture(CubeMap &cm) noexcept {
+       glActiveTexture(GL_TEXTURE0);
+       cm.Bind();
+       prog.Uniform(sampler_handle, GLint(0));
+}
+
+void SkyBox::Draw() const noexcept {
+       vao.Bind();
+       vao.DrawTriangleStrip(14);
+}
+
+
 SunSurface::SunSurface()
 : prog() {
        prog.LoadShader(
index e4a29278babc60e703fdfe7d5911d2751cb1399c..a3189314f2e58f7bf4ceec2585c61d4b0882e629 100644 (file)
@@ -81,6 +81,12 @@ glm::mat4 Camera::Model(const world::Body &b) const noexcept {
        }
 }
 
+glm::mat4 Camera::Universe() const noexcept {
+       return glm::mat4(track_orient
+               ? ref->InverseTransform() * ref->ToUniverse()
+               : ref->ToUniverse());
+}
+
 void Camera::UpdateProjection() noexcept {
        projection = glm::infinitePerspective(fov, aspect, near);
 }