From 48235a5d7752d560e91ce9dfd2b2aa700f33e7ff Mon Sep 17 00:00:00 2001 From: hiker Date: Sat, 30 May 2015 11:29:08 +1000 Subject: [PATCH] Turned ShadowMatrices into a stand-alone proper class. --- src/graphics/irr_driver.cpp | 31 +++--- src/graphics/irr_driver.hpp | 20 ++-- src/graphics/render.cpp | 72 ++----------- src/graphics/render_geometry.cpp | 19 ++-- src/graphics/render_lighting.cpp | 17 ++-- src/graphics/shadow_matrixes.cpp | 169 ++++++++++++++++++++++++------- src/graphics/shadow_matrixes.hpp | 81 ++++++++++++++- src/graphics/stkscenemanager.cpp | 32 +++--- 8 files changed, 285 insertions(+), 156 deletions(-) diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 24df1148f..7f21a42cd 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -31,6 +31,7 @@ #include "graphics/post_processing.hpp" #include "graphics/referee.hpp" #include "graphics/shaders.hpp" +#include "graphics/shadow_matrixes.hpp" #include "graphics/stkanimatedmesh.hpp" #include "graphics/stkbillboard.hpp" #include "graphics/stkmeshscenenode.hpp" @@ -105,6 +106,7 @@ const int MIN_SUPPORTED_WIDTH = 800; */ IrrDriver::IrrDriver() { + m_shadow_matrices = NULL; m_resolution_changing = RES_CHANGE_NONE; m_phase = SOLID_NORMAL_AND_DEPTH_PASS; m_device = createDevice(video::EDT_NULL, @@ -121,10 +123,6 @@ IrrDriver::IrrDriver() m_mipviz = m_wireframe = m_normals = m_ssaoviz = \ m_lightviz = m_shadowviz = m_distortviz = m_rsm = m_rh = m_gi = m_boundingboxesviz = false; SkyboxCubeMap = m_last_light_bucket_distance = 0; - m_shadow_camnodes[0] = NULL; - m_shadow_camnodes[1] = NULL; - m_shadow_camnodes[2] = NULL; - m_shadow_camnodes[3] = NULL; memset(object_count, 0, sizeof(object_count)); } // IrrDriver @@ -152,6 +150,8 @@ IrrDriver::~IrrDriver() m_device = NULL; m_modes.clear(); + delete m_shadow_matrices; + m_shadow_matrices = NULL; Shaders::destroy(); delete m_wind; } // ~IrrDriver @@ -194,6 +194,14 @@ GPUTimer &IrrDriver::getGPUTimer(unsigned i) return m_perf_query[i]; } +// ---------------------------------------------------------------------------- +void IrrDriver::computeMatrixesAndCameras(scene::ICameraSceneNode *const camnode, + size_t width, size_t height) +{ + m_current_screen_size = core::vector2df(float(width), float(height)); + m_shadow_matrices->computeMatrixesAndCameras(camnode, width, height); +} // computeMatrixesAndCameras + // ---------------------------------------------------------------------------- #if defined(__linux__) && !defined(ANDROID) @@ -519,9 +527,6 @@ void IrrDriver::initDevice() m_mrt.clear(); m_mrt.reallocate(2); - m_suncam = m_scene_manager->addCameraSceneNode(0, vector3df(0), vector3df(0), -1, false); - m_suncam->grab(); - m_suncam->setParent(NULL); } else { @@ -588,6 +593,7 @@ void IrrDriver::initDevice() // so let's decide ourselves...) m_device->getCursorControl()->setVisible(true); m_pointer_shown = true; + m_shadow_matrices = new ShadowMatrices(); } // initDevice // ---------------------------------------------------------------------------- @@ -1701,7 +1707,7 @@ video::ITexture* IrrDriver::applyMask(video::ITexture* texture, // ---------------------------------------------------------------------------- void IrrDriver::setRTT(RTT* rtt) { - memset(m_shadow_camnodes, 0, 4 * sizeof(void*)); + m_shadow_matrices->resetShadowCamNodes(); m_rtts = rtt; } // ---------------------------------------------------------------------------- @@ -1710,7 +1716,8 @@ void IrrDriver::onLoadWorld() if (CVS->isGLSL()) { const core::recti &viewport = Camera::getCamera(0)->getViewport(); - size_t width = viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X, height = viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y; + size_t width = viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X; + size_t height = viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y; m_rtts = new RTT(width, height); } } @@ -2514,11 +2521,7 @@ scene::ISceneNode *IrrDriver::addLight(const core::vector3df &pos, float energy, { //m_sun_interposer->setPosition(pos); //m_sun_interposer->updateAbsolutePosition(); - - m_suncam->setPosition(pos); - m_suncam->updateAbsolutePosition(); - - m_rsm_matrix_initialized = false; + m_shadow_matrices->addLight(pos); ((WaterShaderProvider *) Shaders::getCallback(ES_WATER) )->setSunPosition(pos); } diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index 26d84babd..a5657790d 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -62,6 +62,7 @@ class PerCameraNode; class PostProcessing; class LightNode; class ShadowImportance; +class ShadowMatrices; enum STKRenderingPass { @@ -200,12 +201,6 @@ private: Wind *m_wind; /** RTTs. */ RTT *m_rtts; - std::vector sun_ortho_matrix; - core::vector3df rh_extend; - core::matrix4 rh_matrix; - core::matrix4 rsm_matrix; - bool m_rsm_matrix_initialized; - bool m_rsm_map_available; core::vector2df m_current_screen_size; core::dimension2du m_actual_screen_size; @@ -240,6 +235,8 @@ private: enum {RES_CHANGE_NONE, RES_CHANGE_YES, RES_CHANGE_CANCEL} m_resolution_changing; + ShadowMatrices *m_shadow_matrices; + public: GLuint SkyboxCubeMap; GLuint SkyboxSpecularProbe; @@ -298,12 +295,8 @@ private: unsigned poly_count[PASS_COUNT]; u32 m_renderpass; class STKMeshSceneNode *m_sun_interposer; - scene::ICameraSceneNode *m_suncam; core::vector3df m_sun_direction; video::SColorf m_suncolor; - std::pair m_shadow_scales[4]; - scene::ICameraSceneNode *m_shadow_camnodes[4]; - float m_shadows_cam[4][24]; std::vector m_glowing; @@ -361,10 +354,6 @@ public: void renderSkybox(const scene::ICameraSceneNode *camera); void setPhase(STKRenderingPass); STKRenderingPass getPhase() const; - const std::vector &getShadowViewProj() const - { - return sun_ortho_matrix; - } void IncreaseObjectCount(); void IncreasePolyCount(unsigned); core::array &getMainSetup(); @@ -670,6 +659,9 @@ public: // ------------------------------------------------------------------------ class STKMeshSceneNode *getSunInterposer() { return m_sun_interposer; } // ------------------------------------------------------------------------ + ShadowMatrices *getShadowMatrices() { return m_shadow_matrices; } + // ------------------------------------------------------------------------ + void cleanSunInterposer(); void createSunInterposer(); // ------------------------------------------------------------------------ diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 8ad400230..c91e611ec 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -30,6 +30,7 @@ #include "graphics/rtts.hpp" #include "graphics/screenquad.hpp" #include "graphics/shaders.hpp" +#include "graphics/shadow_matrixes.hpp" #include "graphics/stkmeshscenenode.hpp" #include "items/item_manager.hpp" #include "modes/world.hpp" @@ -57,36 +58,6 @@ public: } // InstancedColorizeShader }; // InstancedColorizeShader -// ============================================================================ -class ViewFrustrumShader : public Shader -{ -private: - GLuint m_frustrum_vao; - -public: ViewFrustrumShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "frustrum.vert", - GL_FRAGMENT_SHADER, "coloredquad.frag"); - - assignUniforms("color", "idx"); - - glGenVertexArrays(1, &m_frustrum_vao); - glBindVertexArray(m_frustrum_vao); - glBindBuffer(GL_ARRAY_BUFFER, SharedGPUObjects::getFrustrumVBO()); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, - SharedGPUObjects::getFrustrumIndices()); - glBindVertexArray(0); - } // ViewFrustrumShader - // ------------------------------------------------------------------------ - void bindVertexArray() - { - glBindVertexArray(m_frustrum_vao); - } // bindVertexArray - -}; // ViewFrustrumShader - // ============================================================================ extern std::vector BoundingBoxes; @@ -313,7 +284,7 @@ void IrrDriver::renderGLSL(float dt) } else if (irr_driver->getShadowViz()) { - renderShadowsDebug(); + getShadowMatrices()->renderShadowsDebug(); } else { @@ -401,7 +372,7 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po // Shadows { // To avoid wrong culling, use the largest view possible - m_scene_manager->setActiveCamera(m_suncam); + m_scene_manager->setActiveCamera(getShadowMatrices()->getSunCam()); if (CVS->isDefferedEnabled() && CVS->isShadowEnabled() && hasShadow) { @@ -528,14 +499,17 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po m_post_processing->renderRHDebug(m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2], - rh_matrix, rh_extend); + getShadowMatrices()->getRHMatrix(), + getShadowMatrices()->getRHExtend()); } if (getGI()) { glDisable(GL_BLEND); m_rtts->getFBO(FBO_COLORS).bind(); - m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH()); + m_post_processing->renderGI(getShadowMatrices()->getRHMatrix(), + getShadowMatrices()->getRHExtend(), + m_rtts->getRH()); } PROFILER_PUSH_CPU_MARKER("- Glow", 0xFF, 0xFF, 0x00); @@ -677,36 +651,6 @@ void IrrDriver::renderParticles() // m_scene_manager->drawAll(scene::ESNRP_TRANSPARENT_EFFECT); } -static void renderWireFrameFrustrum(float *tmp, unsigned i) -{ - ViewFrustrumShader::getInstance()->use(); - ViewFrustrumShader::getInstance()->bindVertexArray(); - glBindBuffer(GL_ARRAY_BUFFER, SharedGPUObjects::getFrustrumVBO()); - - glBufferSubData(GL_ARRAY_BUFFER, 0, 8 * 3 * sizeof(float), (void *)tmp); - ViewFrustrumShader::getInstance()->setUniforms(video::SColor(255, 0, 255, 0), i); - glDrawElements(GL_LINES, 24, GL_UNSIGNED_INT, 0); -} - - -void IrrDriver::renderShadowsDebug() -{ - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glViewport(0, UserConfigParams::m_height / 2, UserConfigParams::m_width / 2, UserConfigParams::m_height / 2); - m_post_processing->renderTextureLayer(m_rtts->getShadowFBO().getRTT()[0], 0); - renderWireFrameFrustrum(m_shadows_cam[0], 0); - glViewport(UserConfigParams::m_width / 2, UserConfigParams::m_height / 2, UserConfigParams::m_width / 2, UserConfigParams::m_height / 2); - m_post_processing->renderTextureLayer(m_rtts->getShadowFBO().getRTT()[0], 1); - renderWireFrameFrustrum(m_shadows_cam[1], 1); - glViewport(0, 0, UserConfigParams::m_width / 2, UserConfigParams::m_height / 2); - m_post_processing->renderTextureLayer(m_rtts->getShadowFBO().getRTT()[0], 2); - renderWireFrameFrustrum(m_shadows_cam[2], 2); - glViewport(UserConfigParams::m_width / 2, 0, UserConfigParams::m_width / 2, UserConfigParams::m_height / 2); - m_post_processing->renderTextureLayer(m_rtts->getShadowFBO().getRTT()[0], 3); - renderWireFrameFrustrum(m_shadows_cam[3], 3); - glViewport(0, 0, UserConfigParams::m_width, UserConfigParams::m_height); -} - // ---------------------------------------------------------------------------- void IrrDriver::renderGlow(std::vector& glows) diff --git a/src/graphics/render_geometry.cpp b/src/graphics/render_geometry.cpp index c33a93188..8d93874e1 100644 --- a/src/graphics/render_geometry.cpp +++ b/src/graphics/render_geometry.cpp @@ -16,19 +16,20 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "graphics/irr_driver.hpp" -#include "central_settings.hpp" + #include "config/user_config.hpp" #include "graphics/callbacks.hpp" +#include "graphics/central_settings.hpp" #include "graphics/glwrap.hpp" #include "graphics/post_processing.hpp" #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" +#include "graphics/shadow_matrixes.hpp" +#include "graphics/stkscenemanager.hpp" #include "modes/world.hpp" #include "utils/log.hpp" #include "utils/profiler.hpp" #include "utils/tuple.hpp" -#include "stkscenemanager.hpp" -#include "utils/profiler.hpp" #include @@ -1815,11 +1816,14 @@ void IrrDriver::renderShadows() if (CVS->isARBTextureViewUsable()) { + const std::pair* shadow_scales + = getShadowMatrices()->getShadowScales(); + for (unsigned i = 0; i < 2; i++) { m_post_processing->renderGaussian6BlurLayer(m_rtts->getShadowFBO(), i, - 2.f * m_shadow_scales[0].first / m_shadow_scales[i].first, - 2.f * m_shadow_scales[0].second / m_shadow_scales[i].second); + 2.f * shadow_scales[0].first / shadow_scales[i].first, + 2.f * shadow_scales[0].second / shadow_scales[i].second); } } glBindTexture(GL_TEXTURE_2D_ARRAY, m_rtts->getShadowFBO().getRTT()[0]); @@ -1920,12 +1924,13 @@ void multidrawRSM(Args...args) // ---------------------------------------------------------------------------- void IrrDriver::renderRSM() { - if (m_rsm_map_available) + if (getShadowMatrices()->isRSMMapAvail()) return; ScopedGPUTimer Timer(getGPUTimer(Q_RSM)); m_rtts->getRSM().bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + const core::matrix4 &rsm_matrix = getShadowMatrices()->getRSMMatrix(); drawRSM(rsm_matrix); drawRSM(rsm_matrix); drawRSM(rsm_matrix); @@ -1953,5 +1958,5 @@ void IrrDriver::renderRSM() renderRSMShadow(rsm_matrix); renderRSMShadow(rsm_matrix); } - m_rsm_map_available = true; + getShadowMatrices()->setRSMMapAvail(true); } // renderRSM diff --git a/src/graphics/render_lighting.cpp b/src/graphics/render_lighting.cpp index abcd8f7f2..3287c7707 100644 --- a/src/graphics/render_lighting.cpp +++ b/src/graphics/render_lighting.cpp @@ -447,8 +447,9 @@ void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow) for (unsigned i = 0; i < 32; i++) { NVWorkaroundRadianceHintsConstructionShader::getInstance() - ->setUniforms(rsm_matrix, rh_matrix, - rh_extend, i, + ->setUniforms(getShadowMatrices()->getRSMMatrix(), + getShadowMatrices()->getRHMatrix(), + getShadowMatrices()->getRHExtend(), i, irr_driver->getSunColor()); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -463,14 +464,14 @@ void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow) m_rtts->getRSM().getDepthTexture() ); RadianceHintsConstructionShader::getInstance() - ->setUniforms(rsm_matrix, rh_matrix, rh_extend, + ->setUniforms(getShadowMatrices()->getRSMMatrix(), + getShadowMatrices()->getRHMatrix(), + getShadowMatrices()->getRHExtend(), irr_driver->getSunColor()); glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 32); } } - - for (unsigned i = 0; i < sun_ortho_matrix.size(); i++) - sun_ortho_matrix[i] *= getInvViewMatrix(); + getShadowMatrices()->updateSunOrthoMatrices(); m_rtts->getFBO(FBO_COMBINED_DIFFUSE_SPECULAR).bind(); glClear(GL_COLOR_BUFFER_BIT); @@ -478,7 +479,9 @@ void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow) if (CVS->isGlobalIlluminationEnabled() && hasShadow) { ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_GI)); - m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH()); + m_post_processing->renderGI(getShadowMatrices()->getRHMatrix(), + getShadowMatrices()->getRHExtend(), + m_rtts->getRH()); } m_rtts->getFBO(FBO_COMBINED_DIFFUSE_SPECULAR).bind(); diff --git a/src/graphics/shadow_matrixes.cpp b/src/graphics/shadow_matrixes.cpp index 7a371a29a..f4333909f 100644 --- a/src/graphics/shadow_matrixes.cpp +++ b/src/graphics/shadow_matrixes.cpp @@ -18,7 +18,10 @@ #include "graphics/shadow_matrixes.hpp" #include "graphics/central_settings.hpp" +#include "graphics/glwrap.hpp" #include "graphics/irr_driver.hpp" +#include "graphics/post_processing.hpp" +#include "graphics/rtts.hpp" #include "graphics/shaders.hpp" #include "graphics/shared_gpu_objects.hpp" #include "modes/world.hpp" @@ -35,8 +38,6 @@ #define MIN2(a, b) ((a) > (b) ? (b) : (a)) -float ShadowMatrices::m_shadow_split[5] = { 1., 5., 20., 50., 150 }; - // ============================================================================ class LightspaceBoundingBoxShader : public TextureShader +{ +private: + GLuint m_frustrum_vao; + +public: ViewFrustrumShader() + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "frustrum.vert", + GL_FRAGMENT_SHADER, "coloredquad.frag"); + + assignUniforms("color", "idx"); + + glGenVertexArrays(1, &m_frustrum_vao); + glBindVertexArray(m_frustrum_vao); + glBindBuffer(GL_ARRAY_BUFFER, SharedGPUObjects::getFrustrumVBO()); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, + SharedGPUObjects::getFrustrumIndices()); + glBindVertexArray(0); + } // ViewFrustrumShader + // ------------------------------------------------------------------------ + void bindVertexArray() + { + glBindVertexArray(m_frustrum_vao); + } // bindVertexArray + +}; // ViewFrustrumShader + +// ============================================================================ +ShadowMatrices::ShadowMatrices() +{ + m_sun_cam = irr_driver->getSceneManager() + ->addCameraSceneNode(0, vector3df(0), vector3df(0), -1, false); + m_sun_cam->grab(); + m_sun_cam->setParent(NULL); + + m_shadow_cam_nodes[0] = NULL; + m_shadow_cam_nodes[1] = NULL; + m_shadow_cam_nodes[2] = NULL; + m_shadow_cam_nodes[3] = NULL; +} // ShadowMatrices +// ---------------------------------------------------------------------------- +void ShadowMatrices::addLight(const core::vector3df &pos) +{ + m_sun_cam->setPosition(pos); + m_sun_cam->updateAbsolutePosition(); + + m_rsm_matrix_initialized = false; + +} // addLight + +// ---------------------------------------------------------------------------- +void ShadowMatrices::updateSunOrthoMatrices() +{ + for (unsigned i = 0; i < m_sun_ortho_matrices.size(); i++) + m_sun_ortho_matrices[i] *= irr_driver->getInvViewMatrix(); +} // updateSunOrthoMatrices + // ============================================================================ static std::vector getFrustrumVertex(const scene::SViewFrustum &frustrum) { @@ -101,7 +164,7 @@ static std::vector getFrustrumVertex(const scene::SViewFrustum &frust * \param pointsInside a vector of point in 3d space. * \param size returns the size (width, height) of shadowmap coverage */ -static core::matrix4 getTighestFitOrthoProj(const core::matrix4 &transform, +core::matrix4 ShadowMatrices::getTighestFitOrthoProj(const core::matrix4 &transform, const std::vector &pointsInside, std::pair &size) { @@ -154,8 +217,8 @@ static core::matrix4 getTighestFitOrthoProj(const core::matrix4 &transform, * TODO : The depth histogram part is commented out, needs to tweak it when * I have some motivation */ -void IrrDriver::updateSplitAndLightcoordRangeFromComputeShaders(size_t width, - size_t height) +void ShadowMatrices::updateSplitAndLightcoordRangeFromComputeShaders(unsigned int width, + unsigned int height) { struct CascadeBoundingBox { @@ -192,9 +255,9 @@ void IrrDriver::updateSplitAndLightcoordRangeFromComputeShaders(size_t width, LightspaceBoundingBoxShader::getInstance()->use(); LightspaceBoundingBoxShader::getInstance() - ->setTextureUnits(getDepthStencilTexture()); + ->setTextureUnits(irr_driver->getDepthStencilTexture()); LightspaceBoundingBoxShader::getInstance() - ->setUniforms(m_suncam->getViewMatrix(), + ->setUniforms(m_sun_cam->getViewMatrix(), ShadowMatrices::m_shadow_split[1], ShadowMatrices::m_shadow_split[2], ShadowMatrices::m_shadow_split[3], @@ -210,7 +273,7 @@ void IrrDriver::updateSplitAndLightcoordRangeFromComputeShaders(size_t width, ShadowMatricesGenerationShader::getInstance()->use(); ShadowMatricesGenerationShader::getInstance() - ->setUniforms(m_suncam->getViewMatrix()); + ->setUniforms(m_sun_cam->getViewMatrix()); glDispatchCompute(4, 1, 1); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); @@ -229,12 +292,12 @@ void IrrDriver::updateSplitAndLightcoordRangeFromComputeShaders(size_t width, * \param width of the rendering viewport * \param height of the rendering viewport */ -void IrrDriver::computeMatrixesAndCameras(scene::ICameraSceneNode * const camnode, - size_t width, size_t height) +void ShadowMatrices::computeMatrixesAndCameras(scene::ICameraSceneNode *const camnode, + unsigned int width, unsigned int height) { if (CVS->isSDSMEnabled()) updateSplitAndLightcoordRangeFromComputeShaders(width, height); - static_cast(m_scene_manager) + static_cast(irr_driver->getSceneManager()) ->OnAnimate(os::Timer::getTime()); camnode->render(); irr_driver->setProjMatrix(irr_driver->getVideoDriver() @@ -243,7 +306,6 @@ void IrrDriver::computeMatrixesAndCameras(scene::ICameraSceneNode * const camnod ->getTransform(video::ETS_VIEW)); irr_driver->genProjViewMatrix(); - m_current_screen_size = core::vector2df(float(width), float(height)); const float oldfar = camnode->getFarValue(); const float oldnear = camnode->getNearValue(); @@ -269,15 +331,15 @@ void IrrDriver::computeMatrixesAndCameras(scene::ICameraSceneNode * const camnod memcpy(&tmp[48], irr_driver->getInvProjMatrix().pointer(), 16 * sizeof(float)); memcpy(&tmp[64], irr_driver->getProjViewMatrix().pointer(), 16 * sizeof(float)); - m_suncam->render(); + m_sun_cam->render(); for (unsigned i = 0; i < 4; i++) { - if (m_shadow_camnodes[i]) - delete m_shadow_camnodes[i]; - m_shadow_camnodes[i] = (scene::ICameraSceneNode *) m_suncam->clone(); + if (m_shadow_cam_nodes[i]) + delete m_shadow_cam_nodes[i]; + m_shadow_cam_nodes[i] = (scene::ICameraSceneNode *) m_sun_cam->clone(); } - sun_ortho_matrix.clear(); - const core::matrix4 &SunCamViewMatrix = m_suncam->getViewMatrix(); + m_sun_ortho_matrices.clear(); + const core::matrix4 &sun_cam_view_matrix = m_sun_cam->getViewMatrix(); if (World::getWorld() && World::getWorld()->getTrack()) { @@ -330,16 +392,16 @@ void IrrDriver::computeMatrixesAndCameras(scene::ICameraSceneNode * const camnod memcpy(m_shadows_cam[i], tmp, 24 * sizeof(float)); std::vector vectors = getFrustrumVertex(*frustrum); - tmp_matrix = getTighestFitOrthoProj(SunCamViewMatrix, vectors, + tmp_matrix = getTighestFitOrthoProj(sun_cam_view_matrix, vectors, m_shadow_scales[i]); - m_shadow_camnodes[i]->setProjectionMatrix(tmp_matrix, true); - m_shadow_camnodes[i]->render(); + m_shadow_cam_nodes[i]->setProjectionMatrix(tmp_matrix, true); + m_shadow_cam_nodes[i]->render(); - sun_ortho_matrix.push_back( - getVideoDriver()->getTransform(video::ETS_PROJECTION) - * getVideoDriver()->getTransform(video::ETS_VIEW) ); + m_sun_ortho_matrices.push_back( + irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION) + * irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW) ); } // Rsm Matrix and camera @@ -347,42 +409,42 @@ void IrrDriver::computeMatrixesAndCameras(scene::ICameraSceneNode * const camnod { if (trackbox.MinEdge.X != trackbox.MaxEdge.X && trackbox.MinEdge.Y != trackbox.MaxEdge.Y && - // Cover the case where SunCamViewMatrix is null - SunCamViewMatrix.getScale() != core::vector3df(0., 0., 0.)) + // Cover the case where sun_cam_view_matrix is null + sun_cam_view_matrix.getScale() != core::vector3df(0., 0., 0.)) { - SunCamViewMatrix.transformBoxEx(trackbox); + sun_cam_view_matrix.transformBoxEx(trackbox); core::matrix4 tmp_matrix; tmp_matrix.buildProjectionMatrixOrthoLH(trackbox.MinEdge.X, trackbox.MaxEdge.X, trackbox.MaxEdge.Y, trackbox.MinEdge.Y, 30, trackbox.MaxEdge.Z); - m_suncam->setProjectionMatrix(tmp_matrix, true); - m_suncam->render(); + m_sun_cam->setProjectionMatrix(tmp_matrix, true); + m_sun_cam->render(); } - rsm_matrix = getVideoDriver()->getTransform(video::ETS_PROJECTION) - * getVideoDriver()->getTransform(video::ETS_VIEW); + m_rsm_matrix = irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION) + * irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW); m_rsm_matrix_initialized = true; m_rsm_map_available = false; } - rh_extend = core::vector3df(128, 64, 128); + m_rh_extend = core::vector3df(128, 64, 128); core::vector3df campos = camnode->getAbsolutePosition(); core::vector3df translation(8 * floor(campos.X / 8), 8 * floor(campos.Y / 8), 8 * floor(campos.Z / 8)); - rh_matrix.setTranslation(translation); + m_rh_matrix.setTranslation(translation); - assert(sun_ortho_matrix.size() == 4); + assert(m_sun_ortho_matrices.size() == 4); // reset normal camera camnode->setNearValue(oldnear); camnode->setFarValue(oldfar); camnode->render(); - size_t size = irr_driver->getShadowViewProj().size(); + size_t size = m_sun_ortho_matrices.size(); for (unsigned i = 0; i < size; i++) memcpy(&tmp[16 * i + 80], - irr_driver->getShadowViewProj()[i].pointer(), + m_sun_ortho_matrices[i].pointer(), 16 * sizeof(float)); } @@ -400,3 +462,38 @@ void IrrDriver::computeMatrixesAndCameras(scene::ICameraSceneNode * const camnod glBufferSubData(GL_UNIFORM_BUFFER, 0, (16 * 9 + 2) * sizeof(float), tmp); } // computeMatrixesAndCameras + +// ---------------------------------------------------------------------------- +void ShadowMatrices::renderWireFrameFrustrum(float *tmp, unsigned i) +{ + ViewFrustrumShader::getInstance()->use(); + ViewFrustrumShader::getInstance()->bindVertexArray(); + glBindBuffer(GL_ARRAY_BUFFER, SharedGPUObjects::getFrustrumVBO()); + + glBufferSubData(GL_ARRAY_BUFFER, 0, 8 * 3 * sizeof(float), (void *)tmp); + ViewFrustrumShader::getInstance()->setUniforms(video::SColor(255, 0, 255, 0), i); + glDrawElements(GL_LINES, 24, GL_UNSIGNED_INT, 0); +} +// ---------------------------------------------------------------------------- +void ShadowMatrices::renderShadowsDebug() +{ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, UserConfigParams::m_height / 2, + UserConfigParams::m_width / 2, UserConfigParams::m_height / 2); + PostProcessing *post_processing = irr_driver->getPostProcessing(); + RTT *rtt = irr_driver->getRTT(); + post_processing->renderTextureLayer(rtt->getShadowFBO().getRTT()[0], 0); + renderWireFrameFrustrum(m_shadows_cam[0], 0); + glViewport(UserConfigParams::m_width / 2, UserConfigParams::m_height / 2, + UserConfigParams::m_width / 2, UserConfigParams::m_height / 2); + post_processing->renderTextureLayer(rtt->getShadowFBO().getRTT()[0], 1); + renderWireFrameFrustrum(m_shadows_cam[1], 1); + glViewport(0, 0, UserConfigParams::m_width / 2, UserConfigParams::m_height / 2); + post_processing->renderTextureLayer(rtt->getShadowFBO().getRTT()[0], 2); + renderWireFrameFrustrum(m_shadows_cam[2], 2); + glViewport(UserConfigParams::m_width / 2, 0, UserConfigParams::m_width / 2, + UserConfigParams::m_height / 2); + post_processing->renderTextureLayer(rtt->getShadowFBO().getRTT()[0], 3); + renderWireFrameFrustrum(m_shadows_cam[3], 3); + glViewport(0, 0, UserConfigParams::m_width, UserConfigParams::m_height); +} diff --git a/src/graphics/shadow_matrixes.hpp b/src/graphics/shadow_matrixes.hpp index 25f31b01c..ad64374a7 100644 --- a/src/graphics/shadow_matrixes.hpp +++ b/src/graphics/shadow_matrixes.hpp @@ -19,10 +19,89 @@ #ifndef HEADER_SHADOW_MATRICES_HPP #define HEADER_SHADOW_MATRICES_HPP +#include "matrix4.h" +#include "vector3d.h" + +#include +#include + +namespace irr +{ + namespace scene { class ICameraSceneNode; } +} + +using namespace irr; + + + class ShadowMatrices { public: - static float m_shadow_split[5]; + static float m_shadow_split[5]; + +private: + std::vector m_sun_ortho_matrices; + scene::ICameraSceneNode *m_sun_cam; + scene::ICameraSceneNode *m_shadow_cam_nodes[4]; + std::pair m_shadow_scales[4]; + core::matrix4 m_rsm_matrix; + bool m_rsm_matrix_initialized; + float m_shadows_cam[4][24]; + bool m_rsm_map_available; + core::vector3df m_rh_extend; + core::matrix4 m_rh_matrix; + + + void updateSplitAndLightcoordRangeFromComputeShaders(unsigned int width, + unsigned int height); + core::matrix4 getTighestFitOrthoProj(const core::matrix4 &transform, + const std::vector &pointsInside, + std::pair &size); + void renderWireFrameFrustrum(float *tmp, unsigned i); +public: + + ShadowMatrices(); + + void computeMatrixesAndCameras(scene::ICameraSceneNode *const camnode, + unsigned int width, unsigned int height); + void addLight(const core::vector3df &pos); + void updateSunOrthoMatrices(); + void renderShadowsDebug(); + + // ------------------------------------------------------------------------ + void resetShadowCamNodes() + { + memset(m_shadow_cam_nodes, 0, 4 * sizeof(void*)); + } // resetShadowCamNodes + // ------------------------------------------------------------------------ + scene::ICameraSceneNode** getShadowCamNodes() + { + return m_shadow_cam_nodes; + } // getShadowCamNodes + // ------------------------------------------------------------------------ + scene::ICameraSceneNode* getSunCam() { return m_sun_cam; } + // ------------------------------------------------------------------------ + core::matrix4& getRHMatrix() { return m_rh_matrix; } + // ------------------------------------------------------------------------ + core::vector3df& getRHExtend() { return m_rh_extend; } + // ------------------------------------------------------------------------ + core::matrix4& getRSMMatrix() { return m_rsm_matrix; } + // ------------------------------------------------------------------------ + std::vector& getSunOrthoMatrices() + { + return m_sun_ortho_matrices; + } + // ------------------------------------------------------------------------ + void setRSMMapAvail(bool b) { m_rsm_map_available = b; } + // ------------------------------------------------------------------------ + bool isRSMMapAvail() const { return m_rsm_map_available; } + // ------------------------------------------------------------------------ + const std::pair* getShadowScales() const + { + return m_shadow_scales; + } + // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ }; // class ShadowMatrices diff --git a/src/graphics/stkscenemanager.cpp b/src/graphics/stkscenemanager.cpp index 0b76b8d6e..32a500cde 100644 --- a/src/graphics/stkscenemanager.cpp +++ b/src/graphics/stkscenemanager.cpp @@ -15,26 +15,28 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#include "graphics/glwrap.hpp" #include "graphics/stkscenemanager.hpp" -#include "graphics/stkmesh.hpp" -#include "graphics/irr_driver.hpp" + +#include "graphics/callbacks.hpp" #include "graphics/central_settings.hpp" -#include "stkanimatedmesh.hpp" -#include "stkmeshscenenode.hpp" -#include "utils/ptr_vector.hpp" -#include -#include -#include "callbacks.hpp" -#include "utils/cpp2011.hpp" +#include "graphics/glwrap.hpp" +#include "graphics/irr_driver.hpp" +#include "graphics/lod_node.hpp" +#include "graphics/shadow_matrixes.hpp" +#include "graphics/stkanimatedmesh.hpp" +#include "graphics/stkmesh.hpp" +#include "graphics/stkmeshscenenode.hpp" #include "modes/world.hpp" #include "tracks/track.hpp" -#include "lod_node.hpp" +#include "utils/cpp2011.hpp" #include "utils/profiler.hpp" +#include "utils/ptr_vector.hpp" #include "utils/time.hpp" +#include #include #include +#include #include #include @@ -601,7 +603,11 @@ PROFILER_PUSH_CPU_MARKER("- culling", 0xFF, 0xFF, 0x0); bool cam = false, rsmcam = false; bool shadowcam[4] = { false, false, false, false }; - parseSceneManager(List, ImmediateDrawList::getInstance(), camnode, m_shadow_camnodes, m_suncam, cam, shadowcam, rsmcam, !m_rsm_map_available); + parseSceneManager(List, ImmediateDrawList::getInstance(), camnode, + getShadowMatrices()->getShadowCamNodes(), + getShadowMatrices()->getSunCam(), cam, + shadowcam, rsmcam, + !getShadowMatrices()->isRSMMapAvail()); PROFILER_POP_CPU_MARKER(); // Add a 1 s timeout @@ -809,7 +815,7 @@ PROFILER_POP_CPU_MARKER(); } } #pragma omp section - if (!m_rsm_map_available) + if (!getShadowMatrices()->isRSMMapAvail()) { size_t offset = 0, current_cmd = 0; if (!CVS->supportsAsyncInstanceUpload())