diff --git a/data/shaders/frustrum.vert b/data/shaders/frustrum.vert new file mode 100644 index 000000000..489241b4d --- /dev/null +++ b/data/shaders/frustrum.vert @@ -0,0 +1,18 @@ +layout (std140) uniform MatrixesData +{ + mat4 ViewMatrix; + mat4 ProjectionMatrix; + mat4 InverseViewMatrix; + mat4 InverseProjectionMatrix; + mat4 ShadowViewProjMatrixes[4]; + vec2 screen; +}; + +uniform int idx; + +in vec3 Position; + +void main(void) +{ + gl_Position = ShadowViewProjMatrixes[idx] * vec4(Position, 1.); +} diff --git a/data/shaders/layertexturequad.frag b/data/shaders/layertexturequad.frag new file mode 100644 index 000000000..d9be4690b --- /dev/null +++ b/data/shaders/layertexturequad.frag @@ -0,0 +1,10 @@ +uniform sampler2DArray tex; +uniform int layer; + +in vec2 uv; +out vec4 FragColor; + +void main() +{ + FragColor = texture(tex, vec3(uv, float(layer))); +} \ No newline at end of file diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index bfffa6c3c..48ceb741d 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -345,6 +345,7 @@ private: class STKMeshSceneNode *m_sun_interposer; scene::CLensFlareSceneNode *m_lensflare; scene::ICameraSceneNode *m_suncam; + float m_shadows_cam[4][24]; std::vector m_glowing; @@ -380,6 +381,7 @@ private: void renderSSAO(); void renderLights(unsigned pointlightCount); void renderDisplacement(); + void renderShadowsDebug(); void doScreenShot(); public: IrrDriver(); diff --git a/src/graphics/post_processing.cpp b/src/graphics/post_processing.cpp index 648e76301..928efeac4 100644 --- a/src/graphics/post_processing.cpp +++ b/src/graphics/post_processing.cpp @@ -479,6 +479,21 @@ void PostProcessing::renderPassThrough(GLuint tex) glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } +void PostProcessing::renderTextureLayer(unsigned tex, unsigned layer) +{ + glUseProgram(FullScreenShader::LayerPassThroughShader::Program); + glBindVertexArray(FullScreenShader::LayerPassThroughShader::vao); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D_ARRAY, tex); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glUniform1i(FullScreenShader::LayerPassThroughShader::uniform_texture, 0); + glUniform1i(FullScreenShader::LayerPassThroughShader::uniform_layer, layer); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} + void PostProcessing::renderGlow(unsigned tex) { diff --git a/src/graphics/post_processing.hpp b/src/graphics/post_processing.hpp index edf314700..a0e6c4484 100644 --- a/src/graphics/post_processing.hpp +++ b/src/graphics/post_processing.hpp @@ -90,6 +90,7 @@ public: /** Render tex. Used for blit/texture resize */ void renderPassThrough(unsigned tex); + void renderTextureLayer(unsigned tex, unsigned layer); void applyMLAA(); void renderMotionBlur(unsigned cam, FrameBuffer &in_fbo, FrameBuffer &out_fbo); diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 89a1b46aa..6c890d65f 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -197,6 +197,10 @@ void IrrDriver::renderGLSL(float dt) glViewport(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y); m_post_processing->renderPassThrough(m_rtts->getRSM().getRTT()[0]); } + else if (irr_driver->getShadowViz()) + { + renderShadowsDebug(); + } else fbo->BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y); } @@ -730,6 +734,34 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz camnode->setFarValue(FarValues[i]); camnode->setNearValue(NearValues[i]); camnode->render(); + const scene::SViewFrustum *frustrum = camnode->getViewFrustum(); + float tmp[24] = { + frustrum->getFarLeftDown().X, + frustrum->getFarLeftDown().Y, + frustrum->getFarLeftDown().Z, + frustrum->getFarLeftUp().X, + frustrum->getFarLeftUp().Y, + frustrum->getFarLeftUp().Z, + frustrum->getFarRightDown().X, + frustrum->getFarRightDown().Y, + frustrum->getFarRightDown().Z, + frustrum->getFarRightUp().X, + frustrum->getFarRightUp().Y, + frustrum->getFarRightUp().Z, + frustrum->getNearLeftDown().X, + frustrum->getNearLeftDown().Y, + frustrum->getNearLeftDown().Z, + frustrum->getNearLeftUp().X, + frustrum->getNearLeftUp().Y, + frustrum->getNearLeftUp().Z, + frustrum->getNearRightDown().X, + frustrum->getNearRightDown().Y, + frustrum->getNearRightDown().Z, + frustrum->getNearRightUp().X, + frustrum->getNearRightUp().Y, + frustrum->getNearRightUp().Z, + }; + memcpy(m_shadows_cam[i], tmp, 24 * sizeof(float)); const core::aabbox3df smallcambox = camnode-> getViewFrustum()->getBoundingBox(); core::aabbox3df trackbox(vmin->toIrrVector(), vmax->toIrrVector() - @@ -739,8 +771,32 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz core::aabbox3df box = smallcambox; box = box.intersect(trackbox); - - SunCamViewMatrix.transformBoxEx(trackbox); + float xmin = INFINITY, xmax = -INFINITY; + float ymin = INFINITY, ymax = -INFINITY; + float zmin = INFINITY, zmax = -INFINITY; + const vector3df vectors[] = + { + frustrum->getFarLeftDown(), + frustrum->getFarLeftUp(), + frustrum->getFarRightDown(), + frustrum->getFarRightUp(), + frustrum->getNearLeftDown(), + frustrum->getNearLeftUp(), + frustrum->getNearRightDown(), + frustrum->getNearRightUp() + }; + for (unsigned j = 0; j < 8; j++) + { + vector3df vector; + SunCamViewMatrix.transformVect(vector, vectors[j]); + xmin = MIN2(xmin, vector.X); + xmax = MAX2(xmax, vector.X); + ymin = MIN2(ymin, vector.Y); + ymax = MAX2(ymax, vector.Y); + zmin = MIN2(zmin, vector.Z); + zmax = MAX2(zmax, vector.Z); + } +/* SunCamViewMatrix.transformBoxEx(trackbox); SunCamViewMatrix.transformBoxEx(box); core::vector3df extent = box.getExtent(); @@ -750,12 +806,12 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz // Snap to texels const float units_per_w = w / 1024; - const float units_per_h = h / 1024; + const float units_per_h = h / 1024;*/ - float left = box.MinEdge.X; - float right = box.MaxEdge.X; - float up = box.MaxEdge.Y; - float down = box.MinEdge.Y; + float left = xmin; + float right = xmax; + float up = ymin; + float down = ymax; core::matrix4 tmp_matrix; @@ -768,15 +824,26 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz } tmp_matrix.buildProjectionMatrixOrthoLH(left, right, - up, down, - 30, z); + down, up, + 30, zmax); m_suncam->setProjectionMatrix(tmp_matrix, true); m_suncam->render(); sun_ortho_matrix.push_back(getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW)); } if ((tick % 100) == 2) - rsm_matrix = sun_ortho_matrix[3]; + { + core::aabbox3df trackbox(vmin->toIrrVector(), vmax->toIrrVector() - + core::vector3df(0, 30, 0)); + SunCamViewMatrix.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(); + rsm_matrix = getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW); + } 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)); @@ -847,6 +914,36 @@ void IrrDriver::renderShadows() } } +static void renderWireFrameFrustrum(float *tmp, unsigned i) +{ + glUseProgram(MeshShader::ViewFrustrumShader::Program); + glBindVertexArray(MeshShader::ViewFrustrumShader::frustrumvao); + glBindBuffer(GL_ARRAY_BUFFER, SharedObject::frustrumvbo); + + glBufferSubData(GL_ARRAY_BUFFER, 0, 8 * 3 * sizeof(float), (void *)tmp); + MeshShader::ViewFrustrumShader::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->getShadowDepthTex(), 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->getShadowDepthTex(), 1); + renderWireFrameFrustrum(m_shadows_cam[1], 1); + glViewport(0, 0, UserConfigParams::m_width / 2, UserConfigParams::m_height / 2); + m_post_processing->renderTextureLayer(m_rtts->getShadowDepthTex(), 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->getShadowDepthTex(), 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/shaders.cpp b/src/graphics/shaders.cpp index 1744ce8ad..efaa65ad2 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -169,6 +169,26 @@ static void initCubeVBO() glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * 6 * sizeof(int), indices, GL_STATIC_DRAW); } +GLuint SharedObject::frustrumvbo = 0; +GLuint SharedObject::frustrumindexes = 0; + +static void initFrustrumVBO() +{ + glGenBuffers(1, &SharedObject::frustrumvbo); + glBindBuffer(GL_ARRAY_BUFFER, SharedObject::frustrumvbo); + glBufferData(GL_ARRAY_BUFFER, 8 * 3 * sizeof(float), 0, GL_DYNAMIC_DRAW); + + int indices[24] = { + 0, 1, 1, 3, 3, 2, 2, 0, + 4, 5, 5, 7, 7, 6, 6, 4, + 0, 4, 1, 5, 2, 6, 3, 7, + }; + + glGenBuffers(1, &SharedObject::frustrumindexes); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedObject::frustrumindexes); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 12 * 2 * sizeof(int), indices, GL_STATIC_DRAW); +} + GLuint SharedObject::ViewProjectionMatrixesUBO; static void initShadowVPMUBO() @@ -271,6 +291,7 @@ void Shaders::loadShaders() initQuadBuffer(); initBillboardVBO(); initCubeVBO(); + initFrustrumVBO(); initShadowVPMUBO(); FullScreenShader::BloomBlendShader::init(); FullScreenShader::BloomShader::init(); @@ -286,6 +307,7 @@ void Shaders::loadShaders() FullScreenShader::Gaussian6VBlurShader::init(); FullScreenShader::GlowShader::init(); FullScreenShader::PassThroughShader::init(); + FullScreenShader::LayerPassThroughShader::init(); FullScreenShader::LinearizeDepthShader::init(); FullScreenShader::SSAOShader::init(); FullScreenShader::SunLightShader::init(); @@ -336,6 +358,7 @@ void Shaders::loadShaders() MeshShader::InstancedRefShadowShader::init(); MeshShader::GrassShadowShader::init(); MeshShader::SkyboxShader::init(); + MeshShader::ViewFrustrumShader::init(); ParticleShader::FlipParticleRender::init(); ParticleShader::HeightmapSimulationShader::init(); ParticleShader::SimpleParticleRender::init(); @@ -1791,6 +1814,41 @@ namespace MeshShader glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); glUniform1i(uniform_tex, TU_tex); } + + GLuint ViewFrustrumShader::Program; + GLuint ViewFrustrumShader::attrib_position; + GLuint ViewFrustrumShader::uniform_color; + GLuint ViewFrustrumShader::uniform_idx; + GLuint ViewFrustrumShader::frustrumvao; + + void ViewFrustrumShader::init() + { + Program = LoadProgram( + GL_VERTEX_SHADER, file_manager->getAsset("shaders/frustrum.vert").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/coloredquad.frag").c_str()); + attrib_position = glGetAttribLocation(Program, "Position"); + if (!UserConfigParams::m_ubo_disabled) + { + GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); + glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); + } + uniform_color = glGetUniformLocation(Program, "color"); + uniform_idx = glGetUniformLocation(Program, "idx"); + + glGenVertexArrays(1, &frustrumvao); + glBindVertexArray(frustrumvao); + glBindBuffer(GL_ARRAY_BUFFER, SharedObject::frustrumvbo); + glEnableVertexAttribArray(attrib_position); + glVertexAttribPointer(attrib_position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedObject::frustrumindexes); + glBindVertexArray(0); + } + + void ViewFrustrumShader::setUniforms(const video::SColor &color, unsigned idx) + { + glUniform4i(uniform_color, color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); + glUniform1i(uniform_idx, idx); + } } namespace LightShader @@ -2557,6 +2615,20 @@ namespace FullScreenShader vao = createVAO(Program); } + GLuint LayerPassThroughShader::Program; + GLuint LayerPassThroughShader::uniform_texture; + GLuint LayerPassThroughShader::uniform_layer; + GLuint LayerPassThroughShader::vao; + void LayerPassThroughShader::init() + { + Program = LoadProgram( + GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/layertexturequad.frag").c_str()); + uniform_texture = glGetUniformLocation(Program, "tex"); + uniform_layer = glGetUniformLocation(Program, "layer"); + vao = createVAO(Program); + } + GLuint LinearizeDepthShader::Program; GLuint LinearizeDepthShader::uniform_zn; GLuint LinearizeDepthShader::uniform_zf; diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index 53089372f..26e955545 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -29,7 +29,7 @@ class SharedObject { public: static GLuint billboardvbo; - static GLuint cubevbo, cubeindexes; + static GLuint cubevbo, cubeindexes, frustrumvbo, frustrumindexes; static GLuint ViewProjectionMatrixesUBO; }; @@ -424,6 +424,18 @@ public: static void setUniforms(const core::matrix4 &ModelMatrix, const core::vector2df &screen, unsigned TU_tex); }; +class ViewFrustrumShader +{ +public: + static GLuint Program; + static GLuint attrib_position; + static GLuint uniform_color, uniform_idx; + static GLuint frustrumvao; + + static void init(); + static void setUniforms(const video::SColor &color, unsigned idx); +}; + } #define MAXLIGHT 32 @@ -720,6 +732,16 @@ public: static void init(); }; +class LayerPassThroughShader +{ +public: + static GLuint Program; + static GLuint uniform_layer, uniform_texture; + static GLuint vao; + + static void init(); +}; + class LinearizeDepthShader { public: diff --git a/src/karts/kart_model.cpp b/src/karts/kart_model.cpp index 9870fb957..b95b8dbee 100644 --- a/src/karts/kart_model.cpp +++ b/src/karts/kart_model.cpp @@ -340,7 +340,10 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models, bool always_anim node = irr_driver->addAnimatedMesh(m_mesh); // as animated mesh are not cheap to render use frustum box culling - node->setAutomaticCulling(scene::EAC_FRUSTUM_BOX); + if (irr_driver->isGLSL()) + node->setAutomaticCulling(scene::EAC_OFF); + else + node->setAutomaticCulling(scene::EAC_FRUSTUM_BOX); if (always_animated) {