From 86391e8b8ed38eae30f9e7c7cd0e5ca247aee433 Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 14 Nov 2022 14:04:23 +0800 Subject: [PATCH] Add shadow rendering for legacy video drivers --- src/graphics/shadow.cpp | 112 +++++++++++++++++++++++++++++++++------- src/graphics/shadow.hpp | 10 ++++ src/karts/kart.cpp | 2 +- 3 files changed, 103 insertions(+), 21 deletions(-) diff --git a/src/graphics/shadow.cpp b/src/graphics/shadow.cpp index f598274ab..5ca793cb2 100644 --- a/src/graphics/shadow.cpp +++ b/src/graphics/shadow.cpp @@ -19,6 +19,9 @@ #include "graphics/shadow.hpp" #include "karts/abstract_kart.hpp" #include "karts/skidding.hpp" +#include "graphics/central_settings.hpp" +#include "graphics/irr_driver.hpp" +#include "graphics/material.hpp" #include "graphics/sp/sp_shader_manager.hpp" #include "graphics/sp/sp_dynamic_draw_call.hpp" #include "physics/btKart.hpp" @@ -27,32 +30,67 @@ #ifndef SERVER_ONLY +#include +#include +#include + Shadow::Shadow(Material* shadow_mat, const AbstractKart& kart) - : m_dy_dc(NULL), m_shadow_enabled(false), m_kart(kart) + : m_node(NULL), m_shadow_enabled(false), m_kart(kart) { - m_dy_dc = std::make_shared - (scene::EPT_TRIANGLE_STRIP, - SP::SPShaderManager::get()->getSPShader("alphablend"), shadow_mat); + if (CVS->isGLSL()) + { + m_dy_dc = std::make_shared + (scene::EPT_TRIANGLE_STRIP, + SP::SPShaderManager::get()->getSPShader("alphablend"), shadow_mat); - m_dy_dc->getVerticesVector().resize(4); - video::S3DVertexSkinnedMesh* v = m_dy_dc->getVerticesVector().data(); - v[0].m_all_uvs[0] = 0; - v[0].m_all_uvs[1] = 0; - v[1].m_all_uvs[0] = 15360; - v[1].m_all_uvs[1] = 0; - v[3].m_all_uvs[0] = 15360; - v[3].m_all_uvs[1] = 15360; - v[2].m_all_uvs[0] = 0; - v[2].m_all_uvs[1] = 15360; + m_dy_dc->getVerticesVector().resize(4); + video::S3DVertexSkinnedMesh* v = m_dy_dc->getVerticesVector().data(); + v[0].m_all_uvs[0] = 0; + v[0].m_all_uvs[1] = 0; + v[1].m_all_uvs[0] = 15360; + v[1].m_all_uvs[1] = 0; + v[3].m_all_uvs[0] = 15360; + v[3].m_all_uvs[1] = 15360; + v[2].m_all_uvs[0] = 0; + v[2].m_all_uvs[1] = 15360; - m_dy_dc->setVisible(false); - SP::addDynamicDrawCall(m_dy_dc); + m_dy_dc->setVisible(false); + SP::addDynamicDrawCall(m_dy_dc); + } + else + { + video::S3DVertex v; + v.Color = (video::SColor)-1; + std::array vertices = {{ v, v, v, v }}; + std::array indices = {{ 0, 1, 2, 0, 2, 3 }}; + scene::SMeshBuffer* buffer = new scene::SMeshBuffer(); + buffer->append(vertices.data(), vertices.size(), indices.data(), + indices.size()); + buffer->getTCoords(0) = core::vector2df(0.0f, 0.0f); + buffer->getTCoords(1) = core::vector2df(1.0f, 0.0f); + buffer->getTCoords(2) = core::vector2df(1.0f, 1.0f); + buffer->getTCoords(3) = core::vector2df(0.0f, 1.0f); + shadow_mat->setMaterialProperties(&buffer->getMaterial(), buffer); + buffer->getMaterial().setTexture(0, shadow_mat->getTexture()); + buffer->setHardwareMappingHint(scene::EHM_STREAM); + scene::SMesh* mesh = new scene::SMesh(); + mesh->addMeshBuffer(buffer); + mesh->setBoundingBox(buffer->getBoundingBox()); + buffer->drop(); + std::string debug_name = m_kart.getIdent() + " (shadow)"; + m_node = static_cast( + irr_driver->addMesh(mesh, debug_name)); + mesh->drop(); + } } // Shadow // ---------------------------------------------------------------------------- Shadow::~Shadow() { - m_dy_dc->removeFromSP(); + if (m_dy_dc) + m_dy_dc->removeFromSP(); + else if (m_node) + irr_driver->removeNode(m_node); } // ~Shadow // ---------------------------------------------------------------------------- @@ -68,14 +106,20 @@ void Shadow::update(bool enabled) m_shadow_enabled = enabled; if (m_shadow_enabled) { - m_dy_dc->setVisible(true); + if (m_dy_dc) + m_dy_dc->setVisible(true); + else if (m_node) + m_node->setVisible(true); } else { - m_dy_dc->setVisible(false); + if (m_dy_dc) + m_dy_dc->setVisible(false); + else if (m_node) + m_node->setVisible(false); } } - if (m_shadow_enabled) + if (m_shadow_enabled && m_dy_dc) { video::S3DVertexSkinnedMesh* v = m_dy_dc->getVerticesVector().data(); v[0].m_position.X = -1; v[0].m_position.Z = 1; v[0].m_position.Y = 0; @@ -101,6 +145,34 @@ void Shadow::update(bool enabled) m_dy_dc->recalculateBoundingBox(); m_dy_dc->setUpdateOffset(0); } + else if (m_shadow_enabled && m_node) + { + Vec3 position[4]; + position[0] = Vec3(-1.0f, 0.0f, 1.0f); + position[1] = Vec3( 1.0f, 0.0f, 1.0f); + position[2] = Vec3( 1.0f, 0.0f, -1.0f); + position[3] = Vec3(-1.0f, 0.0f, -1.0f); + btTransform kart_trans = m_kart.getSmoothedTrans(); + btTransform skidding_rotation; + skidding_rotation.setOrigin(Vec3(0, 0, 0)); + skidding_rotation.setRotation + (btQuaternion(m_kart.getSkidding()->getVisualSkidRotation(), 0, 0)); + kart_trans *= skidding_rotation; + scene::IMesh* mesh = m_node->getMesh(); + scene::IMeshBuffer* buffer = mesh->getMeshBuffer(0); + for (unsigned i = 0; i < 4; i++) + { + const btWheelInfo& wi = m_kart.getVehicle()->getWheelInfo(i); + Vec3 up_vector = kart_trans.getBasis().getColumn(1); + up_vector = up_vector * (wi.m_raycastInfo.m_suspensionLength - 0.02f); + Vec3 pos = kart_trans(position[i]) - up_vector; + buffer->getPosition(i) = pos.toIrrVector(); + buffer->getNormal(i) = Vec3(wi.m_raycastInfo.m_contactNormalWS) + .toIrrVector(); + } + buffer->recalculateBoundingBox(); + mesh->setBoundingBox(buffer->getBoundingBox()); + } } // update #endif diff --git a/src/graphics/shadow.hpp b/src/graphics/shadow.hpp index dc7c439ac..669905c72 100644 --- a/src/graphics/shadow.hpp +++ b/src/graphics/shadow.hpp @@ -30,6 +30,14 @@ namespace SP class SPDynamicDrawCall; } +namespace irr +{ + namespace scene + { + class IMeshSceneNode; + } +} + /** * \brief This class is used to enable a shadow for a kart. * For now it uses a simple texture to simulate the shadow, real time shadows might @@ -42,6 +50,8 @@ private: /** The dynamic draw call of the shadow. */ std::shared_ptr m_dy_dc; + irr::scene::IMeshSceneNode* m_node; + /** If a kart is flying, the shadow is disabled (since it is * stuck to the kart, i.e. the shadow would be flying, too). */ bool m_shadow_enabled; diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 321d48cb5..b0abe2f7c 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -3012,7 +3012,7 @@ void Kart::loadData(RaceManager::KartType type, bool is_animated_model) } if (!GUIEngine::isNoGraphics() && - CVS->isGLSL() && !CVS->isShadowEnabled() && m_kart_properties + (!CVS->isGLSL() || !CVS->isShadowEnabled()) && m_kart_properties ->getShadowMaterial()->getSamplerPath(0) != "unicolor_white") { m_shadow.reset(new Shadow(m_kart_properties->getShadowMaterial(),