From 2696ef256797bc7078d6cd302256e72402571a1e Mon Sep 17 00:00:00 2001 From: Benau Date: Sat, 30 Jul 2022 09:03:56 +0800 Subject: [PATCH] Add shader to render ghost kart --- data/shaders/ge_shaders/ghost.frag | 13 ++++++ .../src/ge_vulkan_draw_call.cpp | 11 ++++- lib/irrlicht/include/EMaterialTypes.h | 3 ++ src/karts/ghost_kart.cpp | 42 +++++++++++++++++++ src/karts/ghost_kart.hpp | 4 +- 5 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 data/shaders/ge_shaders/ghost.frag diff --git a/data/shaders/ge_shaders/ghost.frag b/data/shaders/ge_shaders/ghost.frag new file mode 100644 index 000000000..f3b6e559b --- /dev/null +++ b/data/shaders/ge_shaders/ghost.frag @@ -0,0 +1,13 @@ +layout(location = 0) in vec4 f_vertex_color; +layout(location = 1) in vec2 f_uv; +layout(location = 3) flat in int f_material_id; + +layout(location = 0) out vec4 o_color; + +#include "utils/sample_mesh_texture.h" + +void main() +{ + vec3 mixed_color = sampleMeshTexture0(f_material_id, f_uv).xyz * f_vertex_color.xyz; + o_color = vec4(mixed_color * 0.5, 0.5); +} diff --git a/lib/graphics_engine/src/ge_vulkan_draw_call.cpp b/lib/graphics_engine/src/ge_vulkan_draw_call.cpp index 070a6a916..21a0051db 100644 --- a/lib/graphics_engine/src/ge_vulkan_draw_call.cpp +++ b/lib/graphics_engine/src/ge_vulkan_draw_call.cpp @@ -257,6 +257,7 @@ std::string GEVulkanDrawCall::getShader(irr::scene::ISceneNode* node, case irr::video::EMT_ONETEXTURE_BLEND: return "alphablend"; case irr::video::EMT_SOLID_2_LAYER: return "decal"; case irr::video::EMT_STK_GRASS: return "grass"; + case irr::video::EMT_STK_GHOST: return "ghost"; default: return "solid"; } } // getShader @@ -308,9 +309,17 @@ void GEVulkanDrawCall::createAllPipelines(GEVulkanDriver* vk) settings.m_vertex_shader = "spm.vert"; settings.m_skinning_vertex_shader = "spm_skinning.vert"; settings.m_push_constants_func = nullptr; + + settings.m_depth_write = true; + settings.m_backface_culling = true; + settings.m_alphablend = true; + settings.m_drawing_priority = (char)9; + settings.m_fragment_shader = "ghost.frag"; + settings.m_shader_name = "ghost"; + createPipeline(vk, settings); + settings.m_depth_write = false; settings.m_backface_culling = false; - settings.m_alphablend = true; settings.m_drawing_priority = (char)10; settings.m_fragment_shader = "transparent.frag"; diff --git a/lib/irrlicht/include/EMaterialTypes.h b/lib/irrlicht/include/EMaterialTypes.h index e06a8879c..2e3216100 100644 --- a/lib/irrlicht/include/EMaterialTypes.h +++ b/lib/irrlicht/include/EMaterialTypes.h @@ -195,6 +195,9 @@ namespace video //! Alphatest material for grass without using vertex color in stk. */ EMT_STK_GRASS, + //! Render objects like ghost in stk (used by ghost karts for now). */ + EMT_STK_GHOST, + //! This value is not used. It only forces this enumeration to compile to 32 bit. EMT_FORCE_32BIT = 0x7fffffff }; diff --git a/src/karts/ghost_kart.cpp b/src/karts/ghost_kart.cpp index 03cdd7387..815fa8a88 100644 --- a/src/karts/ghost_kart.cpp +++ b/src/karts/ghost_kart.cpp @@ -22,6 +22,7 @@ #include "karts/controller/ghost_controller.hpp" #include "karts/kart_gfx.hpp" #include "karts/kart_model.hpp" +#include "graphics/irr_driver.hpp" #include "graphics/render_info.hpp" #include "modes/easter_egg_hunt.hpp" #include "modes/linear_world.hpp" @@ -45,6 +46,8 @@ GhostKart::GhostKart(const std::string& ident, unsigned int world_kart_id, // ---------------------------------------------------------------------------- void GhostKart::reset() { + m_current_attachment = -1; + m_graphical_y_offset = 0; m_node->setVisible(true); Kart::reset(); // This will set the correct start position @@ -80,6 +83,44 @@ void GhostKart::addReplayEvent(float time, } // addReplayEvent +// ---------------------------------------------------------------------------- +void GhostKart::setGhostKartMaterial() +{ + if (irr_driver->getVideoDriver()->getDriverType() != video::EDT_VULKAN || + m_current_attachment == (int)m_attachment->getType()) + return; + + m_current_attachment = (int)m_attachment->getType(); + std::function&)> set_ghost = + [&](core::array& child) + { + for (unsigned i = 0; i < child.size(); i++) + { + scene::ISceneNode* node = child[i]; + if (node->getType() != irr::scene::ESNT_ANIMATED_MESH && + node->getType() != irr::scene::ESNT_MESH) + continue; + if (node->getType() == scene::ESNT_ANIMATED_MESH) + { + scene::IAnimatedMeshSceneNode* anode = static_cast< + scene::IAnimatedMeshSceneNode*>(node); + anode->setReadOnlyMaterials(false); + for (unsigned j = 0; j < anode->getJointCount(); j++) + set_ghost(anode->getJointNode(j)->getChildren()); + } + else if (node->getType() == scene::ESNT_MESH) + { + static_cast(node) + ->setReadOnlyMaterials(false); + } + for (unsigned j = 0; j < node->getMaterialCount(); j++) + node->getMaterial(j).MaterialType = video::EMT_STK_GHOST; + set_ghost(node->getChildren()); + } + }; + set_ghost(m_node->getChildren()); +} // setGhostKartMaterial + // ---------------------------------------------------------------------------- /** Called once per rendered frame. It is used to only update any graphical * effects. @@ -96,6 +137,7 @@ void GhostKart::updateGraphics(float dt) Moveable::updateGraphics(center_shift, btQuaternion(0, 0, 0, 1)); // Also update attachment's graphics m_attachment->updateGraphics(dt); + setGhostKartMaterial(); } // updateGraphics // ---------------------------------------------------------------------------- diff --git a/src/karts/ghost_kart.hpp b/src/karts/ghost_kart.hpp index f3a60898a..b34daccb7 100644 --- a/src/karts/ghost_kart.hpp +++ b/src/karts/ghost_kart.hpp @@ -50,10 +50,12 @@ private: unsigned int m_last_egg_idx = 0; + int m_current_attachment; // ---------------------------------------------------------------------------- /** Compute the time at which the ghost finished the race */ void computeFinishTime(); - + // ---------------------------------------------------------------------------- + void setGhostKartMaterial(); public: GhostKart(const std::string& ident, unsigned int world_kart_id, int position, float color_hue,