ICT290 / src / engine / skybox.cpp
skybox.cpp
Raw
#include "skybox.h"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

Skybox::Skybox(const std::shared_ptr<Model>& skyboxModel)
    : m_skyboxModel(skyboxModel) {}

void Skybox::draw(const glm::vec3& direction, const glm::vec3& up) const {
    if (m_skyboxModel != nullptr) {
        glPushAttrib(GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT);
        //  Drawn at outside the depth buffer so its always at the back
        glDisable(GL_DEPTH_TEST);
        // Disable blending so edges of the skybox aren't blended together
        glDisable(GL_BLEND);
        // Drawn without culling since we are inside the cube
        glDisable(GL_CULL_FACE);

        // Set the current projection matrix's z near and far
        float zNear = 0.1f, zFar = 10.f;
        float projectionMatrix[16];
        glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix);
        projectionMatrix[10] = -((zFar + zNear) / (zFar - zNear));
        projectionMatrix[14] = -(2 * zFar * zNear / (zFar - zNear));
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadMatrixf(projectionMatrix);

        // Draw skybox at origin around the camera, with relative direction to
        // the camera.
        glm::mat4 viewMatrix(1.0f);
        viewMatrix = glm::lookAt(glm::vec3{0, 0, 0}, direction, up);

        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();
        glLoadMatrixf(glm::value_ptr(viewMatrix));

        m_skyboxModel->draw();

        // Pop model-view matrix
        glPopMatrix();
        glMatrixMode(GL_PROJECTION);
        // Pop projection matrix
        glPopMatrix();
        // Reset to model-view matrix
        glMatrixMode(GL_MODELVIEW);
        // Pop attribute stack
        glPopAttrib();
    }
}

void Skybox::setModel(const std::shared_ptr<Model>& skyboxModel) {
    if (skyboxModel != nullptr) {
        m_skyboxModel = skyboxModel;
    }
}