Add shadow rendering for legacy video drivers

This commit is contained in:
Benau 2022-11-14 14:04:23 +08:00
parent 58223928d8
commit 86391e8b8e
3 changed files with 103 additions and 21 deletions

View File

@ -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,8 +30,14 @@
#ifndef SERVER_ONLY
#include <array>
#include <SMesh.h>
#include <SMeshBuffer.h>
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)
{
if (CVS->isGLSL())
{
m_dy_dc = std::make_shared<SP::SPDynamicDrawCall>
(scene::EPT_TRIANGLE_STRIP,
@ -47,12 +56,41 @@ Shadow::Shadow(Material* shadow_mat, const AbstractKart& kart)
m_dy_dc->setVisible(false);
SP::addDynamicDrawCall(m_dy_dc);
}
else
{
video::S3DVertex v;
v.Color = (video::SColor)-1;
std::array<video::S3DVertex, 4> vertices = {{ v, v, v, v }};
std::array<uint16_t, 6> 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<scene::IMeshSceneNode*>(
irr_driver->addMesh(mesh, debug_name));
mesh->drop();
}
} // Shadow
// ----------------------------------------------------------------------------
Shadow::~Shadow()
{
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)
{
if (m_dy_dc)
m_dy_dc->setVisible(true);
else if (m_node)
m_node->setVisible(true);
}
else
{
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

View File

@ -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<SP::SPDynamicDrawCall> 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;

View File

@ -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(),