diff --git a/lib/irrlicht/include/S3DVertex.h b/lib/irrlicht/include/S3DVertex.h index 4da158a61..0527f8d82 100644 --- a/lib/irrlicht/include/S3DVertex.h +++ b/lib/irrlicht/include/S3DVertex.h @@ -8,6 +8,7 @@ #include "vector3d.h" #include "vector2d.h" #include "SColor.h" +#include namespace irr { @@ -253,6 +254,7 @@ struct S3DVertexTangents : public S3DVertex } }; +//! SPM usage. */ struct S3DVertexSkinnedMesh { core::vector3df m_position; @@ -263,13 +265,22 @@ struct S3DVertexSkinnedMesh s16 m_joint_idx[4]; s16 m_weight[4]; + S3DVertexSkinnedMesh() + { + m_normal = 0; + m_color.color = -1; + memset(m_all_uvs, 0, 8); + m_tangent = 0; + memset(m_joint_idx, 0, 8); + memset(m_weight, 0, 8); + } + E_VERTEX_TYPE getType() const { return EVT_SKINNED_MESH; } }; - inline u32 getVertexPitchFromType(E_VERTEX_TYPE vertexType) { switch (vertexType) diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index e73a26f3b..e7635992b 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -204,6 +204,7 @@ void DrawCalls::prepareDrawCalls(scene::ICameraSceneNode *camnode) parseSceneManager( irr_driver->getSceneManager()->getRootSceneNode()->getChildren(), camnode); + SP::handleDynamicDrawCall(); SP::updateModelMatrix(); PROFILER_POP_CPU_MARKER(); @@ -221,7 +222,7 @@ void DrawCalls::prepareDrawCalls(scene::ICameraSceneNode *camnode) do { reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000000); - } + } while (reason == GL_TIMEOUT_EXPIRED); } glDeleteSync(m_sync); diff --git a/src/graphics/material_manager.cpp b/src/graphics/material_manager.cpp index 70ac9f54e..e8063f9b1 100644 --- a/src/graphics/material_manager.cpp +++ b/src/graphics/material_manager.cpp @@ -86,7 +86,8 @@ Material* MaterialManager::getMaterialFor(video::ITexture* t, //----------------------------------------------------------------------------- Material* MaterialManager::getMaterialSPM(std::string lay_one_tex_lc, - std::string lay_two_tex_lc) + std::string lay_two_tex_lc, + const std::string& def_shader_name) { std::string orignal_layer_one = lay_one_tex_lc; core::stringc lc(lay_one_tex_lc.c_str()); @@ -140,7 +141,8 @@ Material* MaterialManager::getMaterialSPM(std::string lay_one_tex_lc, } } // for i } - return getSPMaterial("solid", StringUtils::getBasename(orignal_layer_one)); + return getSPMaterial(def_shader_name, + StringUtils::getBasename(orignal_layer_one)); } //----------------------------------------------------------------------------- diff --git a/src/graphics/material_manager.hpp b/src/graphics/material_manager.hpp index b3c91256f..58598ead5 100644 --- a/src/graphics/material_manager.hpp +++ b/src/graphics/material_manager.hpp @@ -64,7 +64,8 @@ public: video::E_MATERIAL_TYPE material_type); Material* getMaterialFor(video::ITexture* t); Material* getMaterialSPM(std::string lay_one_tex_lc, - std::string lay_two_tex_lc); + std::string lay_two_tex_lc, + const std::string& def_shader_name = "solid"); void setAllMaterialFlags(video::ITexture* t, scene::IMeshBuffer *mb); void adjustForFog(video::ITexture* t, diff --git a/src/graphics/skid_marks.cpp b/src/graphics/skid_marks.cpp index 346d76d0d..92b073b59 100644 --- a/src/graphics/skid_marks.cpp +++ b/src/graphics/skid_marks.cpp @@ -20,42 +20,34 @@ #include "graphics/skid_marks.hpp" #include "config/stk_config.hpp" -#include "graphics/irr_driver.hpp" -#include "graphics/stk_mesh_scene_node.hpp" -#include "karts/controller/controller.hpp" +#include "graphics/central_settings.hpp" +#include "graphics/material_manager.hpp" #include "karts/abstract_kart.hpp" #include "karts/skidding.hpp" #include "modes/world.hpp" +#include "graphics/sp/sp_base.hpp" +#include "graphics/sp/sp_dynamic_draw_call.hpp" +#include "graphics/sp/sp_per_object_uniform.hpp" +#include "graphics/sp/sp_shader.hpp" +#include "graphics/sp/sp_uniform_assigner.hpp" #include "physics/btKart.hpp" +#include "utils/mini_glm.hpp" -#include -#include +#ifndef SERVER_ONLY float SkidMarks::m_avoid_z_fighting = 0.005f; -const int SkidMarks::m_start_alpha = 128; +const int SkidMarks::m_start_alpha = 200; const int SkidMarks::m_start_grey = 32; /** Initialises empty skid marks. */ SkidMarks::SkidMarks(const AbstractKart& kart, float width) : m_kart(kart) { - m_width = width; - m_material = new video::SMaterial(); - m_material->MaterialType = video::EMT_ONETEXTURE_BLEND; - m_material->MaterialTypeParam = - pack_textureBlendFunc(video::EBF_SRC_ALPHA, - video::EBF_ONE_MINUS_SRC_ALPHA, - video::EMFN_MODULATE_1X, - video::EAS_TEXTURE | video::EAS_VERTEX_COLOR); - m_material->AmbientColor = video::SColor(128, 0, 0, 0); - m_material->DiffuseColor = video::SColor(128, 16, 16, 16); - //m_material->AmbientColor = video::SColor(255, 255, 255, 255); - //m_material->DiffuseColor = video::SColor(255, 255, 255, 255); - m_material->setFlag(video::EMF_ANISOTROPIC_FILTER, true); - m_material->setFlag(video::EMF_ZWRITE_ENABLE, false); - m_material->Shininess = 0; - m_material->TextureLayer[0].Texture = irr_driver->getTexture("skidmarks.png"); - m_skid_marking = false; - m_current = -1; + m_width = width; + m_material = material_manager->getMaterialSPM("skidmarks.png", "", + "alphablend"); + m_shader = SP::getSPShader("alphablend"); + assert(m_shader != NULL); + m_skid_marking = false; } // SkidMark //----------------------------------------------------------------------------- @@ -63,7 +55,6 @@ SkidMarks::SkidMarks(const AbstractKart& kart, float width) : m_kart(kart) SkidMarks::~SkidMarks() { reset(); // remove all skid marks - delete m_material; } // ~SkidMarks //----------------------------------------------------------------------------- @@ -71,17 +62,9 @@ SkidMarks::~SkidMarks() */ void SkidMarks::reset() { - for(unsigned int i=0; iremoveNode(m_nodes[i]); - m_left[i]->drop(); - m_right[i]->drop(); - } m_left.clear(); m_right.clear(); - m_nodes.clear(); m_skid_marking = false; - m_current = -1; } // reset //----------------------------------------------------------------------------- @@ -96,11 +79,26 @@ void SkidMarks::update(float dt, bool force_skid_marks, if(m_kart.isWheeless()) return; - float f = dt/stk_config->m_skid_fadeout_time*m_start_alpha; - for(unsigned int i=0; im_skid_fadeout_time; + auto it = m_left.begin(); + while (it != m_left.end()) { - m_left[i]->fade(f); - m_right[i]->fade(f); + if ((*it)->fade(f)) + { + it = m_left.erase(it); + continue; + } + it++; + } + it = m_right.begin(); + while (it != m_right.end()) + { + if ((*it)->fade(f)) + { + it = m_right.erase(it); + continue; + } + it++; } // Get raycast information @@ -129,17 +127,11 @@ void SkidMarks::update(float dt, bool force_skid_marks, if(m_skid_marking) { + assert(!m_left.empty()); + assert(!m_right.empty()); if (!is_skidding) // end skid marking { m_skid_marking = false; -#ifndef SERVER_ONLY - // The vertices and indices will not change anymore - // (till these skid mark quads are deleted) - m_left[m_current]->setHardwareMappingHint(scene::EHM_STATIC); - m_right[m_current]->setHardwareMappingHint(scene::EHM_STATIC); - if (STKMeshSceneNode* stkm = dynamic_cast(m_nodes[m_current])) - stkm->setReloadEachFrame(false); -#endif return; } @@ -149,23 +141,16 @@ void SkidMarks::update(float dt, bool force_skid_marks, delta.normalize(); delta *= m_width*0.5f; - Vec3 start = m_left[m_current]->getCenterStart(); + Vec3 start = m_left.back()->getCenterStart(); Vec3 newPoint = (raycast_left + raycast_right)/2; // this linear distance does not account for the kart turning, it's true, // but it produces good enough results float distance = (newPoint - start).length(); - m_left [m_current]->add(raycast_left-delta, raycast_left+delta, + m_left.back()->add(raycast_left-delta, raycast_left+delta, m_kart.getNormal(), distance); - m_right[m_current]->add(raycast_right-delta, raycast_right+delta, + m_right.back()->add(raycast_right-delta, raycast_right+delta, m_kart.getNormal(), distance); - // Adjust the boundary box of the mesh to include the - // adjusted aabb of its buffers. - //core::aabbox3df aabb=m_nodes[m_current]->getMesh() - // ->getBoundingBox(); - //aabb.addInternalBox(m_left[m_current]->getAABB()); - //aabb.addInternalBox(m_right[m_current]->getAABB()); - //m_nodes[m_current]->getMesh()->setBoundingBox(aabb); return; } @@ -182,89 +167,75 @@ void SkidMarks::update(float dt, bool force_skid_marks, delta.normalize(); delta *= m_width*0.5f; - SkidMarkQuads *smq_left = - new SkidMarkQuads(raycast_left-delta, raycast_left+delta, - m_kart.getNormal(), m_material, m_avoid_z_fighting, - custom_color); - scene::SMesh *new_mesh = new scene::SMesh(); - new_mesh->addMeshBuffer(smq_left); - - SkidMarkQuads *smq_right = - new SkidMarkQuads(raycast_right-delta, raycast_right+delta, - m_kart.getNormal(), m_material, m_avoid_z_fighting, - custom_color); - new_mesh->addMeshBuffer(smq_right); - scene::ISceneNode *new_node = irr_driver->addMesh(new_mesh, "skidmark"); -#ifndef SERVER_ONLY - if (STKMeshSceneNode* stkm = dynamic_cast(new_node)) - stkm->setReloadEachFrame(true); -#ifdef DEBUG - std::string debug_name = m_kart.getIdent()+" (skid-mark)"; - new_node->setName(debug_name.c_str()); -#endif -#endif - - // We don't keep a reference to the mesh here, so we have to decrement - // the reference count (which is set to 1 when doing "new SMesh())". - // The scene node will keep the mesh alive. - new_mesh->drop(); - m_current++; - int cleaning_threshold = + const int cleaning_threshold = core::clamp(int(World::getWorld()->getNumKarts()), 5, 15); - if(m_current>=int(stk_config->m_max_skidmarks/cleaning_threshold)) - m_current = 0; - if(m_current>=(int)m_left.size()) + while ((int)m_left.size() >= + stk_config->m_max_skidmarks / cleaning_threshold) { - m_left. push_back (smq_left ); - m_right.push_back (smq_right); - m_nodes.push_back (new_node); + m_left.erase(m_left.begin()); } - else + while ((int)m_right.size() >= + stk_config->m_max_skidmarks / cleaning_threshold) { - irr_driver->removeNode(m_nodes[m_current]); - // Not necessary to delete m_nodes: removeNode - // deletes the node since its refcount reaches zero. - m_left[m_current]->drop(); - m_right[m_current]->drop(); + m_right.erase(m_right.begin()); + } - m_left [m_current] = smq_left; - m_right [m_current] = smq_right; - m_nodes [m_current] = new_node; - } + m_left.emplace_back( + new SkidMarkQuads(raycast_left-delta, raycast_left+delta, + m_kart.getNormal(), m_material, m_shader, + m_avoid_z_fighting, custom_color)); + + m_right.emplace_back( + new SkidMarkQuads(raycast_right-delta, raycast_right+delta, + m_kart.getNormal(), m_material, m_shader, + m_avoid_z_fighting, custom_color)); m_skid_marking = true; - // More triangles are added each frame, so for now leave it - // to stream. - m_left[m_current]->setHardwareMappingHint(scene::EHM_STREAM); - m_right[m_current]->setHardwareMappingHint(scene::EHM_STREAM); } // update //============================================================================= SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left, const Vec3 &right, const Vec3 &normal, - video::SMaterial *material, + Material* material, + SP::SPShader* shader, float z_offset, video::SColor* custom_color) - : scene::SMeshBuffer() { m_center_start = (left + right)/2; m_z_offset = z_offset; m_fade_out = 0.0f; - + m_dy_dc = new SP::SPDynamicDrawCall(scene::EPT_TRIANGLE_STRIP, + shader, material); + static_cast(m_dy_dc)->addAssignerFunction + ("custom_alpha", [this](SP::SPUniformAssigner* ua)->void + { + // SP custom_alpha is assigned 1 - x, so this is correct + ua->setValue(m_fade_out); + }); + SP::addDynamicDrawCall(m_dy_dc); m_start_color = (custom_color != NULL ? *custom_color : - video::SColor(255, - SkidMarks::m_start_grey, - SkidMarks::m_start_grey, - SkidMarks::m_start_grey)); + video::SColor(255, SkidMarks::m_start_grey, SkidMarks::m_start_grey, + SkidMarks::m_start_grey)); + + if (CVS->isDefferedEnabled()) + { + video::SColorf tmp(m_start_color); + m_start_color.setRed(SP::srgbToLinear(tmp.r)); + m_start_color.setGreen(SP::srgbToLinear(tmp.g)); + m_start_color.setBlue(SP::srgbToLinear(tmp.b)); + } - Material = *material; - m_aabb = core::aabbox3df(left.toIrrVector()); add(left, right, normal, 0.0f); - - } // SkidMarkQuads +//----------------------------------------------------------------------------- +SkidMarks::SkidMarkQuads::~SkidMarkQuads() +{ + SP::removeDynamicDrawCall(m_dy_dc); + delete m_dy_dc; +} // ~SkidMarkQuads + //----------------------------------------------------------------------------- /** Adds the two points to this SkidMarkQuads. * \param left,right Left and right coordinates. @@ -276,78 +247,50 @@ void SkidMarks::SkidMarkQuads::add(const Vec3 &left, { // The skid marks must be raised slightly higher, otherwise it blends // too much with the track. - int n = Vertices.size(); + int n = m_dy_dc->getVertexCount(); - video::S3DVertex v; - v.Color = m_start_color; - v.Color.setAlpha(0); // initially create all vertices at alpha=0... + video::S3DVertexSkinnedMesh v; + v.m_color = m_start_color; + v.m_color.setAlpha(0); // initially create all vertices at alpha=0... // then when adding a new set of vertices, make the previous 2 opaque. // this ensures that the last two vertices are always at alpha=0, // producing a fade-out effect - if (n > 4) + if (n > 2) { - Vertices[n - 1].Color.setAlpha(m_start_alpha); - Vertices[n - 2].Color.setAlpha(m_start_alpha); + m_dy_dc->getSPMVertex()[n - 1].m_color.setAlpha(m_start_alpha); + m_dy_dc->getSPMVertex()[n - 2].m_color.setAlpha(m_start_alpha); } - v.Pos = Vec3(left + normal * m_z_offset).toIrrVector(); - v.Normal = normal.toIrrVector(); - v.TCoords = core::vector2df(0.0f, distance*0.5f); - Vertices.push_back(v); - v.Pos = Vec3(right + normal * m_z_offset).toIrrVector(); - v.TCoords = core::vector2df(1.0f, distance*0.5f); - Vertices.push_back(v); - // Out of the box Irrlicht only supports triangle meshes and not - // triangle strips. Since this is a strip it would be more efficient - // to use a special triangle strip scene node. - if(n>=2) - { - Indices.push_back(n-2); - Indices.push_back(n ); - Indices.push_back(n-1); - Indices.push_back(n-1); - Indices.push_back(n ); - Indices.push_back(n+1); - } - // Adjust the axis-aligned boundary boxes. - m_aabb.addInternalPoint(left.toIrrVector() ); - m_aabb.addInternalPoint(right.toIrrVector()); - setBoundingBox(m_aabb); + v.m_position = Vec3(right + normal * m_z_offset).toIrrVector(); + v.m_normal = MiniGLM::compressVector3(normal.toIrrVector()); + short half_float_1 = 15360; + v.m_all_uvs[0] = half_float_1; + v.m_all_uvs[1] = MiniGLM::toFloat16(distance * 0.5f); + m_dy_dc->addSPMVertex(v); + + v.m_position = Vec3(left + normal * m_z_offset).toIrrVector(); + v.m_all_uvs[0] = 0; + v.m_all_uvs[1] = MiniGLM::toFloat16(distance * 0.5f); + m_dy_dc->addSPMVertex(v); + m_dy_dc->setUpdateOffset(n > 2 ? n - 2 : n); + m_dy_dc->recalculateBoundingBox(); - setDirty(); } // add // ---------------------------------------------------------------------------- /** Fades the current skid marks. * \param f fade factor. + * \return true if this skid mark can be deleted (alpha == zero) */ -void SkidMarks::SkidMarkQuads::fade(float f) +bool SkidMarks::SkidMarkQuads::fade(float f) { m_fade_out += f; - // Changing the alpha value is quite expensive, so it's only done - // about 10 times till 0 is reached. - if(m_fade_out*10>SkidMarks::m_start_alpha) + if (m_fade_out >= 1.0f) { - video::SColor &c = Material.DiffuseColor; - int a = c.getAlpha(); - a -= (a < m_fade_out ? a : (int)m_fade_out); - - c.setAlpha(a); - // the first 2 and last 2 already have alpha=0 for fade-in and fade-out - for(unsigned int i=2; iFogEnable = enabled; -} +#endif diff --git a/src/graphics/skid_marks.hpp b/src/graphics/skid_marks.hpp index bac8f3ab5..f6da37a5d 100644 --- a/src/graphics/skid_marks.hpp +++ b/src/graphics/skid_marks.hpp @@ -20,17 +20,21 @@ #ifndef HEADER_SKID_MARK_HPP #define HEADER_SKID_MARK_HPP +#include +#include +#include #include -#include -#include -namespace irr -{ - namespace video { class SMaterial; } - namespace scene { class ISceneNode; } -} using namespace irr; +class Material; + +namespace SP +{ + class SPDynamicDrawCall; + class SPShader; +} + #include "utils/no_copy.hpp" #include "utils/vec3.hpp" @@ -51,9 +55,6 @@ private: /** Reduce effect of Z-fighting. */ float m_width; - /** Index of current (last added) skid mark quad. */ - int m_current; - /** Initial alpha value. */ static const int m_start_alpha; @@ -61,10 +62,13 @@ private: static const int m_start_grey; /** Material to use for the skid marks. */ - video::SMaterial *m_material; + Material* m_material; + + /** Shader(alphablend) to use for the skid marks. */ + SP::SPShader* m_shader; // ------------------------------------------------------------------------ - class SkidMarkQuads : public scene::SMeshBuffer, public NoCopy + class SkidMarkQuads : public NoCopy { /** Used to move skid marks at the same location slightly on * top of each other to avoid a 'wobbling' effect when sometines @@ -74,35 +78,30 @@ private: /** Fade out = alpha value. */ float m_fade_out; - /** For culling, we need the overall radius of the skid marks. We - * approximate this by maintaining an axis-aligned boundary box. */ - core::aabbox3df m_aabb; - video::SColor m_start_color; /** Vector marking the start of the skidmarks (located between left and right wheel) */ Vec3 m_center_start; + SP::SPDynamicDrawCall* m_dy_dc; + public: SkidMarkQuads (const Vec3 &left, const Vec3 &right, - const Vec3 &normal, video::SMaterial *material, + const Vec3 &normal, Material* material, + SP::SPShader* shader, float z_offset, video::SColor* custom_color = NULL); + ~SkidMarkQuads(); void add (const Vec3 &left, const Vec3 &right, const Vec3 &normal, float distance); - void fade (float f); - /** Returns the aabb of this skid mark quads. */ - const core::aabbox3df &getAABB() { return m_aabb; } + bool fade (float f); const Vec3& getCenterStart() const { return m_center_start; } }; // SkidMarkQuads // ------------------------------------------------------------------------ /** Two skidmark objects for the left and right wheel. */ - std::vector m_left, m_right; - - /** The nodes where each left/right pair is attached to. */ - std::vector m_nodes; + std::vector > m_left, m_right; /** Shared static so that consecutive skidmarks are at a slightly * different height. */ @@ -115,8 +114,6 @@ public: video::SColor* custom_color = NULL); void reset(); - void adjustFog(bool enabled); - }; // SkidMarks #endif diff --git a/src/graphics/sp/sp_base.cpp b/src/graphics/sp/sp_base.cpp index c5c456501..10a9b04a1 100644 --- a/src/graphics/sp/sp_base.cpp +++ b/src/graphics/sp/sp_base.cpp @@ -30,6 +30,7 @@ #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" #include "graphics/stk_tex_manager.hpp" +#include "graphics/sp/sp_dynamic_draw_call.hpp" #include "graphics/sp/sp_instanced_data.hpp" #include "graphics/sp/sp_per_object_uniform.hpp" #include "graphics/sp/sp_mesh.hpp" @@ -75,7 +76,7 @@ SPShader* g_glow_shader = NULL; typedef std::unordered_map > > DrawCall; -DrawCall g_draw_calls[DCT_COUNT]; +DrawCall g_draw_calls[DCT_FOR_VAO]; // ---------------------------------------------------------------------------- std::vector, std::vector > > > > > @@ -94,7 +95,7 @@ std::vector g_bounding_boxes; // ---------------------------------------------------------------------------- core::vector3df g_wind_dir; // ---------------------------------------------------------------------------- -//std::unordered_set g_dy_dc; +std::unordered_set g_dy_dc; // ---------------------------------------------------------------------------- float g_frustums[5][24] = { { } }; // ---------------------------------------------------------------------------- @@ -149,6 +150,12 @@ void fogUniformAssigner(SPUniformAssigner* ua) ua->setValue(fog_enable); } // fogUniformAssigner +// ---------------------------------------------------------------------------- +void zeroAlphaUniformAssigner(SPUniformAssigner* ua) +{ + ua->setValue(0.0f); +} // zeroAlphaUniformAssigner + // ---------------------------------------------------------------------------- void ghostAlphaAssigner(SPUniformAssigner* ua) { @@ -417,7 +424,7 @@ void loadShaders() addShader(shader); // ======================================================================== - shader = new SPShader("alphatest", 4, false, 0, true); + shader = new SPShader("alphatest", 3, false, 0, true); shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_alpha_test.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -438,7 +445,7 @@ void loadShaders() addShader(shader); - shader = new SPShader("alphatest_skinned", 4, false, 0, true); + shader = new SPShader("alphatest_skinned", 3, false, 0, true); shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_alpha_test.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -460,7 +467,7 @@ void loadShaders() addShader(shader); // ======================================================================== - shader = new SPShader("unlit", 4, false, 0, true); + shader = new SPShader("unlit", 3, false, 0, true); shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_unlit.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -481,7 +488,7 @@ void loadShaders() addShader(shader); - shader = new SPShader("unlit_skinned", 4, false, 0, true); + shader = new SPShader("unlit_skinned", 3, false, 0, true); shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_unlit.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -524,7 +531,7 @@ void loadShaders() addShader(shader); - shader = new SPShader("normalmap_skinned", 4, false); + shader = new SPShader("normalmap_skinned", 3, false); shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_normal_map.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -546,7 +553,7 @@ void loadShaders() addShader(shader); // ======================================================================== - shader = new SPShader("grass", 4, false, 0, true); + shader = new SPShader("grass", 3, false, 0, true); shader->addShaderFile("sp_grass_pass.vert", GL_VERTEX_SHADER, RP_1ST); shader->addShaderFile("sp_grass.frag", GL_FRAGMENT_SHADER, RP_1ST); @@ -590,10 +597,7 @@ void loadShaders() static_cast(shader) ->addAssignerFunction("fog_enabled", fogUniformAssigner); static_cast(shader) - ->addAssignerFunction("custom_alpha", [](SPUniformAssigner* ua) - { - ua->setValue(0.0f); - }); + ->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner); addShader(shader); shader = new SPShader("alphablend", 1, true); @@ -609,10 +613,7 @@ void loadShaders() static_cast(shader) ->addAssignerFunction("fog_enabled", fogUniformAssigner); static_cast(shader) - ->addAssignerFunction("custom_alpha", [](SPUniformAssigner* ua) - { - ua->setValue(0.0f); - }); + ->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner); addShader(shader); shader = new SPShader("additive_skinned", 1, true); @@ -628,10 +629,7 @@ void loadShaders() static_cast(shader) ->addAssignerFunction("fog_enabled", fogUniformAssigner); static_cast(shader) - ->addAssignerFunction("custom_alpha", [](SPUniformAssigner* ua) - { - ua->setValue(0.0f); - }); + ->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner); addShader(shader); shader = new SPShader("additive", 1, true); @@ -647,10 +645,7 @@ void loadShaders() static_cast(shader) ->addAssignerFunction("fog_enabled", fogUniformAssigner); static_cast(shader) - ->addAssignerFunction("custom_alpha", [](SPUniformAssigner* ua) - { - ua->setValue(0.0f); - }); + ->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner); addShader(shader); shader = new SPShader("ghost_skinned", 1, true/*transparent_shader*/, @@ -1344,6 +1339,120 @@ void addObject(SPMeshNode* node) #endif } +// ---------------------------------------------------------------------------- +void handleDynamicDrawCall() +{ + for (SPDynamicDrawCall* dydc : g_dy_dc) + { + if (!dydc->isVisible()) + { + continue; + } + dydc->resetCullingResult(); + SPShader* shader = dydc->getShader(); + core::aabbox3df bb = dydc->getBoundingBox(); + dydc->getAbsoluteTransformation().transformBoxEx(bb); + std::vector discard; + discard.resize((g_handle_shadow ? 5 : 1), false); + for (int dc_type = 0; dc_type < (g_handle_shadow ? 5 : 1); dc_type++) + { + for (int i = 0; i < 24; i += 4) + { + bool outside = true; + for (int j = 0; j < 8; j++) + { + const float dist = + getCorner(bb, j).X * g_frustums[dc_type][i] + + getCorner(bb, j).Y * g_frustums[dc_type][i + 1] + + getCorner(bb, j).Z * g_frustums[dc_type][i + 2] + + g_frustums[dc_type][i + 3]; + outside = outside && dist < 0.0f; + if (!outside) + { + break; + } + } + if (outside) + { + discard[dc_type] = true; + break; + } + } + } + if (g_handle_shadow ? + (discard[0] && discard[1] && discard[2] && discard[3] && + discard[4]) : discard[0]) + { + continue; + } + + for (int dc_type = 0; dc_type < (g_handle_shadow ? 5 : 1); dc_type++) + { + if (discard[dc_type]) + { + continue; + } + if (dc_type == 0) + { + sp_solid_poly_count += dydc->getVertexCount(); + } + else + { + sp_shadow_poly_count += dydc->getVertexCount(); + } + if (shader->isTransparent()) + { + // Transparent shader should always uses mesh samplers + // All transparent draw calls go DCT_TRANSPARENT + if (dc_type == 0) + { + auto& ret = g_draw_calls[DCT_TRANSPARENT][shader]; + if (CVS->isARBBindlessTextureUsable() || + CVS->useArrayTextures()) + { + ret[""].insert(dydc); + } + else + { + for (auto& p : dydc->getTextureCompare()) + { + ret[p.first].insert(dydc); + } + } + dydc->setCullingResult(DCT_TRANSPARENT, false); + } + else + { + continue; + } + } + else + { + dydc->setCullingResult((DrawCallType)dc_type, false); + // Check if shader for render pass uses mesh samplers + const RenderPass check_pass = + dc_type == DCT_NORMAL ? RP_1ST : RP_SHADOW; + const bool sampler_less = shader->samplerLess(check_pass) || + CVS->isARBBindlessTextureUsable() || + CVS->useArrayTextures(); + auto& ret = g_draw_calls[dc_type][shader]; + if (sampler_less) + { + ret[""].insert(dydc); + } + else + { + for (auto& p : dydc->getTextureCompare()) + { + ret[p.first].insert(dydc); + } + } + } + g_instances.insert(dydc); + } + } +} + // ---------------------------------------------------------------------------- void updateModelMatrix() { @@ -1557,8 +1666,8 @@ void draw(RenderPass rp, DrawCallType dct) std::stringstream profiler_name; profiler_name << "SP::Draw " << dct << " with " << rp; PROFILER_PUSH_CPU_MARKER(profiler_name.str().c_str(), - (uint8_t)(float(dct + rp + 2) / float(DCT_COUNT + RP_COUNT) * 255.0f), - (uint8_t)(float(dct + 1) / (float)DCT_COUNT * 255.0f) , + (uint8_t)(float(dct + rp + 2) / float(DCT_FOR_VAO + RP_COUNT) * 255.0f), + (uint8_t)(float(dct + 1) / (float)DCT_FOR_VAO * 255.0f) , (uint8_t)(float(rp + 1) / (float)RP_COUNT * 255.0f)); assert(dct < DCT_FOR_VAO); @@ -1570,7 +1679,7 @@ void draw(RenderPass rp, DrawCallType dct) continue; } p.first->use(rp); - std::vector shader_uniforms; + static std::vector shader_uniforms; p.first->setUniformsPerObject(static_cast (p.first), &shader_uniforms, rp); p.first->bindPrefilledTextures(rp); @@ -1583,50 +1692,31 @@ void draw(RenderPass rp, DrawCallType dct) } for (unsigned k = 0; k < p.second[j].second.size(); k++) { - /*std::vector draw_call_uniforms; - p.first->setUniformsPerObject(static_cast - (draw_call), &draw_call_uniforms, rp); - sp_draw_call_count++;*/ + static std::vector draw_call_uniforms; + p.first->setUniformsPerObject(dynamic_cast + (p.second[j].second[k].first), &draw_call_uniforms, rp); p.second[j].second[k].first->draw(dct, p.second[j].second[k].second/*material_id*/, CVS->isARBBindlessTextureUsable() || CVS->useArrayTextures()); - /*for (SPUniformAssigner* ua : draw_call_uniforms) + for (SPUniformAssigner* ua : draw_call_uniforms) { ua->reset(); - }*/ + } + draw_call_uniforms.clear(); } } for (SPUniformAssigner* ua : shader_uniforms) { ua->reset(); } + shader_uniforms.clear(); p.first->unuse(rp); } PROFILER_POP_CPU_MARKER(); #endif } // draw -//----------------------------------------------------------------------------- - -// ---------------------------------------------------------------------------- -void d() -{ -/* - -*/ -} - -/* -// ---------------------------------------------------------------------------- -void unsynchronisedUpdate() -{ - for (SPDynamicDrawCall* dy_dc : g_dy_dc) - { - dy_dc->update(true); - } -} // unsynchronisedUpdate - // ---------------------------------------------------------------------------- void addDynamicDrawCall(SPDynamicDrawCall* dy_dc) { @@ -1638,6 +1728,5 @@ void removeDynamicDrawCall(SPDynamicDrawCall* dy_dc) { g_dy_dc.erase(dy_dc); } // removeDynamicDrawCall -*/ } diff --git a/src/graphics/sp/sp_base.hpp b/src/graphics/sp/sp_base.hpp index 50cef9938..b04778248 100644 --- a/src/graphics/sp/sp_base.hpp +++ b/src/graphics/sp/sp_base.hpp @@ -52,8 +52,7 @@ enum DrawCallType: unsigned int DCT_SHADOW3, DCT_SHADOW4, DCT_TRANSPARENT, - DCT_FOR_VAO, - DCT_COUNT = DCT_FOR_VAO + DCT_FOR_VAO }; inline std::ostream& operator<<(std::ostream& os, const DrawCallType& dct) @@ -118,21 +117,13 @@ void drawGlow(); // ---------------------------------------------------------------------------- void drawNormal(); // ---------------------------------------------------------------------------- -void drawBoundingBoxes(); -// ---------------------------------------------------------------------------- void addObject(SPMeshNode*); // ---------------------------------------------------------------------------- -void removeObject(SPMeshNode*); -// ---------------------------------------------------------------------------- -void cleanAllMeshBuffer(); -// ---------------------------------------------------------------------------- -void updateTransformation(); -// ---------------------------------------------------------------------------- void initSTKRenderer(ShaderBasedRenderer*); // ---------------------------------------------------------------------------- void prepareScene(); // ---------------------------------------------------------------------------- -void unsynchronisedUpdate(); +void handleDynamicDrawCall(); // ---------------------------------------------------------------------------- void addDynamicDrawCall(SPDynamicDrawCall*); // ---------------------------------------------------------------------------- diff --git a/src/graphics/sp/sp_dynamic_draw_call.cpp b/src/graphics/sp/sp_dynamic_draw_call.cpp new file mode 100644 index 000000000..7ed15ab28 --- /dev/null +++ b/src/graphics/sp/sp_dynamic_draw_call.cpp @@ -0,0 +1,228 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2017 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// 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/sp/sp_dynamic_draw_call.hpp" +#include "graphics/sp/sp_texture.hpp" +#include "graphics/central_settings.hpp" +#include "graphics/graphics_restrictions.hpp" +#include "graphics/material.hpp" +#include "graphics/sp/sp_texture_manager.hpp" +#include "race/race_manager.hpp" +#include "utils/mini_glm.hpp" +#include "utils/string_utils.hpp" + +namespace SP +{ +// ---------------------------------------------------------------------------- +SPDynamicDrawCall::SPDynamicDrawCall(scene::E_PRIMITIVE_TYPE pt, + SPShader* shader, Material* m) + : SPMeshBuffer() +{ +#ifndef SERVER_ONLY + m_primitive_type = pt; + m_shader = shader; + m_stk_material[0] = std::make_tuple(0u, 0u, m); + m_textures.resize(m_stk_material.size()); + for (unsigned j = 0; j < 6; j++) + { + m_textures[0][j] = SPTextureManager::get()->getTexture + (std::get<2>(m_stk_material[0])->getSamplerPath(j), + j == 0 ? std::get<2>(m_stk_material[0]) : NULL, + j < 2 && CVS->isDefferedEnabled()); + } + m_tex_cmp[m_textures[0][0]->getPath() + m_textures[0][1]->getPath()] = 0; + m_pitch = 48; + resetCullingResult(); + + // Rerserve 4 vertices, and use m_ibo buffer for instance array + glGenBuffers(1, &m_vbo); + m_vertices.reserve(4); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + glBufferData(GL_ARRAY_BUFFER, 4 * 48, NULL, GL_DYNAMIC_DRAW); + glGenBuffers(1, &m_ibo); + glBindBuffer(GL_ARRAY_BUFFER, m_ibo); + glBufferData(GL_ARRAY_BUFFER, 32 + 48/*Max textures handles*/, NULL, + GL_DYNAMIC_DRAW); + SPInstancedData id = SPInstancedData(m_trans, 0.0f, 0.0f, 0.0f, 0); + glBufferSubData(GL_ARRAY_BUFFER, 0, 32, &id); + SPTextureManager::get()->increaseGLCommandFunctionCount(1); + SPTextureManager::get()->addGLCommandFunction + (std::bind(&SPDynamicDrawCall::initTextureDyDc, this)); + glBindBuffer(GL_ARRAY_BUFFER, 0); + recreateDynamicVAO(); +#endif +} // SPDynamicDrawCall + +// ---------------------------------------------------------------------------- +bool SPDynamicDrawCall::initTextureDyDc() +{ +#ifndef SERVER_ONLY + for (unsigned i = 0; i < m_stk_material.size(); i++) + { + for (unsigned j = 0; j < 6; j++) + { + if (!m_textures[i][j]->initialized()) + { + return false; + } + } + } + if (!(CVS->useArrayTextures() || CVS->isARBBindlessTextureUsable())) + { + return true; + } + glBindBuffer(GL_ARRAY_BUFFER, m_ibo); + if (CVS->useArrayTextures()) + { + for (unsigned i = 0; i < 6; i++) + { + uint16_t array_index = (uint16_t) + m_textures[0][i]->getTextureArrayIndex(); + glBufferSubData(GL_ARRAY_BUFFER, 32 + (i * 2), 2, &array_index); + } + } + else + { + for (unsigned i = 0; i < 6; i++) + { + glBufferSubData(GL_ARRAY_BUFFER, 32 + (i * 8), 8, + m_textures[0][i]->getTextureHandlePointer()); + } + } + glBindBuffer(GL_ARRAY_BUFFER, 0); +#endif + return true; +} // initTextureDyDc + +// ---------------------------------------------------------------------------- +void SPDynamicDrawCall::recreateDynamicVAO() +{ +#ifndef SERVER_ONLY + if (m_vao[0] != 0) + { + glDeleteVertexArrays(1, &m_vao[0]); + } + glGenVertexArrays(1, &m_vao[0]); + glBindVertexArray(m_vao[0]); + + size_t offset = 0; + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + // Position + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 48, (void*)offset); + offset += 12; + + // Normal, if 10bit vector normalization is wrongly done by drivers, use + // original value and normalize ourselves in shader + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 4, GL_INT_2_10_10_10_REV, + GraphicsRestrictions::isDisabled + (GraphicsRestrictions::GR_10BIT_VECTOR) ? GL_FALSE : GL_TRUE, 48, + (void*)offset); + offset += 4; + + // Vertex color + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, 48, + (void*)offset); + offset += 4; + + // 1st texture coordinates + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 2, GL_HALF_FLOAT, GL_FALSE, 48, (void*)offset); + offset += 4; + // 2nd texture coordinates + glEnableVertexAttribArray(4); + glVertexAttribPointer(4, 2, GL_HALF_FLOAT, GL_FALSE, 48, + (void*)offset); + offset += 4; + + // Tangent and bi-tanget sign + glEnableVertexAttribArray(5); + glVertexAttribPointer(5, 4, GL_INT_2_10_10_10_REV, + GraphicsRestrictions::isDisabled + (GraphicsRestrictions::GR_10BIT_VECTOR) ? GL_FALSE : GL_TRUE, + 48, (void*)offset); + offset += 4; + + // 4 Joint indices + glEnableVertexAttribArray(6); + glVertexAttribIPointer(6, 4, GL_SHORT, 48, (void*)offset); + offset += 8; + // 4 Joint weights + glEnableVertexAttribArray(7); + glVertexAttribPointer(7, 4, GL_HALF_FLOAT, GL_FALSE, 48, + (void*)offset); + offset += 8; + + glBindBuffer(GL_ARRAY_BUFFER, m_ibo); + // Origin + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, 32 + 48, (void*)0); + glVertexAttribDivisorARB(8, 1); + // Rotation (quaternion .xyz) + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 4, GL_INT_2_10_10_10_REV, + GraphicsRestrictions::isDisabled + (GraphicsRestrictions::GR_10BIT_VECTOR) ? GL_FALSE : GL_TRUE, 32 + 48, + (void*)12); + glVertexAttribDivisorARB(9, 1); + // Scale (3 half floats and .w for quaternion .w) + glEnableVertexAttribArray(10); + glVertexAttribPointer(10, 4, GL_HALF_FLOAT, GL_FALSE, 32 + 48, (void*)16); + glVertexAttribDivisorARB(10, 1); + // Texture translation + glEnableVertexAttribArray(11); + glVertexAttribPointer(11, 2, GL_HALF_FLOAT, GL_FALSE, 32 + 48, (void*)24); + glVertexAttribDivisorARB(11, 1); + // Misc data (skinning offset and hue change) + glEnableVertexAttribArray(12); + glVertexAttribIPointer(12, 2, GL_SHORT, 32 + 48, (void*)28); + glVertexAttribDivisorARB(12, 1); + + if (CVS->useArrayTextures()) + { + // uvec4 + uvec2 for 6 texture array indices + glEnableVertexAttribArray(13); + glVertexAttribIPointer(13, 4, GL_UNSIGNED_SHORT, 32 + 48, (void*)32); + glVertexAttribDivisorARB(13, 1); + glEnableVertexAttribArray(14); + glVertexAttribIPointer(14, 2, GL_UNSIGNED_SHORT, 32 + 48, (void*)40); + glVertexAttribDivisorARB(14, 1); + glDisableVertexAttribArray(15); + } + else if (CVS->isARBBindlessTextureUsable()) + { + // 3 * 2 uvec2 for bindless samplers + glEnableVertexAttribArray(13); + glVertexAttribIPointer(13, 4, GL_UNSIGNED_INT, 32 + 48, (void*)32); + glVertexAttribDivisorARB(13, 1); + glEnableVertexAttribArray(14); + glVertexAttribIPointer(14, 4, GL_UNSIGNED_INT, 32 + 48, (void*)48); + glVertexAttribDivisorARB(14, 1); + glEnableVertexAttribArray(15); + glVertexAttribIPointer(15, 4, GL_UNSIGNED_INT, 32 + 48, (void*)64); + glVertexAttribDivisorARB(15, 1); + } + + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + +#endif +} // recreateVAO + +} \ No newline at end of file diff --git a/src/graphics/sp/sp_dynamic_draw_call.hpp b/src/graphics/sp/sp_dynamic_draw_call.hpp new file mode 100644 index 000000000..4f2802095 --- /dev/null +++ b/src/graphics/sp/sp_dynamic_draw_call.hpp @@ -0,0 +1,191 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2017 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HEADER_SP_DYNAMIC_DRAW_CALL_HPP +#define HEADER_SP_DYNAMIC_DRAW_CALL_HPP + +#include "graphics/sp/sp_mesh_buffer.hpp" +#include "graphics/sp/sp_per_object_uniform.hpp" + +#include + +#include +#include +#include +#include +#include +#include + +using namespace irr; +using namespace scene; + +class Material; + +namespace SP +{ +class SPShader; + + +class SPDynamicDrawCall : public SPMeshBuffer, public SPPerObjectUniform +{ +private: + core::matrix4 m_trans; + + SPShader* m_shader; + + core::vector2df m_texture_trans; + + scene::E_PRIMITIVE_TYPE m_primitive_type; + + unsigned m_gl_vbo_size = 4; + + int m_update_offset = -1; + + std::vector m_culling_result; + + bool m_visible = true; + + bool m_update_trans = false; + + // ------------------------------------------------------------------------ + bool initTextureDyDc(); + // ------------------------------------------------------------------------ + void recreateDynamicVAO(); + +public: + SPDynamicDrawCall(scene::E_PRIMITIVE_TYPE pt, SPShader* shader, + Material* m); + // ------------------------------------------------------------------------ + ~SPDynamicDrawCall() {} + // ------------------------------------------------------------------------ + virtual void draw(DrawCallType dct, int material_id = -1, + bool bindless_texture = false) const + { +#ifndef SERVER_ONLY + if (m_culling_result[dct]) + { + return; + } + glBindVertexArray(m_vao[0]); + glDrawArraysInstanced( + m_primitive_type == EPT_TRIANGLES ? GL_TRIANGLES : + m_primitive_type == EPT_TRIANGLE_STRIP ? GL_TRIANGLE_STRIP : + GL_TRIANGLE_FAN, 0, getVertexCount(), 1); +#endif + } + // ------------------------------------------------------------------------ + virtual void uploadInstanceData() + { +#ifndef SERVER_ONLY + if (m_texture_trans.X != 0.0f || m_texture_trans.Y != 0.0f || + m_update_trans) + { + m_update_trans = false; + SPInstancedData id = SPInstancedData(m_trans, + m_texture_trans.X, m_texture_trans.Y, 0.0f, 0); + glBindBuffer(GL_ARRAY_BUFFER, m_ibo); + glBufferSubData(GL_ARRAY_BUFFER, 0, 32, &id); + } + if (m_update_offset >= 0 && !m_vertices.empty()) + { + if ((unsigned)m_vertices.capacity() > m_gl_vbo_size) + { + m_update_offset = 0; + glDeleteBuffers(1, &m_vbo); + glGenBuffers(1, &m_vbo); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + m_gl_vbo_size = (unsigned)m_vertices.capacity(); + glBufferData(GL_ARRAY_BUFFER, m_gl_vbo_size * 48, NULL, + GL_DYNAMIC_DRAW); + recreateDynamicVAO(); + } + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + const int length = ((int)m_vertices.size() - m_update_offset) * 48; + assert(length > 0); + glBufferSubData(GL_ARRAY_BUFFER, m_update_offset * 48, length, + m_vertices.data() + m_update_offset); + m_update_offset = -1; + } + glBindBuffer(GL_ARRAY_BUFFER, 0); +#endif + } + // ------------------------------------------------------------------------ + virtual void uploadGLMesh() {} + // ------------------------------------------------------------------------ + virtual void enableTextureMatrix(unsigned mat_id) {} + // ------------------------------------------------------------------------ + SPShader* getShader() const { return m_shader; } + // ------------------------------------------------------------------------ + std::vector& getVerticesVector() + { return m_vertices; } + // ------------------------------------------------------------------------ + core::vector2df& getTextureTrans() { return m_texture_trans; } + // ------------------------------------------------------------------------ + void setUpdateOffset(int offset) { m_update_offset = offset; } + // ------------------------------------------------------------------------ + void resetCullingResult() + { + m_culling_result.clear(); + m_culling_result.resize(DCT_FOR_VAO, true); + } + // ------------------------------------------------------------------------ + void setCullingResult(DrawCallType dct, bool ret) + { m_culling_result[dct] = ret; } + // ------------------------------------------------------------------------ + bool isVisible() const { return m_visible; } + // ------------------------------------------------------------------------ + void setVisible(bool val) { m_visible = val; } + // ------------------------------------------------------------------------ + const core::matrix4& getAbsoluteTransformation() const { return m_trans; } + // ------------------------------------------------------------------------ + void setAbsoluteTransformation(core::matrix4& mat) + { + m_trans = mat; + m_update_trans = true; + } + // ------------------------------------------------------------------------ + void setPosition(const core::vector3df pos) + { + m_trans.setTranslation(pos); + m_update_trans = true; + } + // ------------------------------------------------------------------------ + void setRotationRadians(const core::vector3df rot) + { + m_trans.setRotationRadians(rot); + m_update_trans = true; + } + // ------------------------------------------------------------------------ + void setRotationDegrees(const core::vector3df rot) + { + m_trans.setRotationDegrees(rot); + m_update_trans = true; + } + // ------------------------------------------------------------------------ + void setScale(const core::vector3df scale) + { + m_trans.setScale(scale); + m_update_trans = true; + } + +}; + +} + +#endif + +#include \ No newline at end of file diff --git a/src/graphics/sp/sp_instanced_data.hpp b/src/graphics/sp/sp_instanced_data.hpp index 679c1ddac..706f4d8c6 100644 --- a/src/graphics/sp/sp_instanced_data.hpp +++ b/src/graphics/sp/sp_instanced_data.hpp @@ -34,6 +34,11 @@ private: char m_data[32]; public: + // ------------------------------------------------------------------------ + SPInstancedData() + { + memset(m_data, 0, 32); + } // ------------------------------------------------------------------------ SPInstancedData(const core::matrix4& model_mat, float texture_trans_x, float texture_trans_y, float hue, diff --git a/src/graphics/sp/sp_mesh_buffer.cpp b/src/graphics/sp/sp_mesh_buffer.cpp index 056f5bff3..fbafbd9c0 100644 --- a/src/graphics/sp/sp_mesh_buffer.cpp +++ b/src/graphics/sp/sp_mesh_buffer.cpp @@ -20,7 +20,6 @@ #include "graphics/central_settings.hpp" #include "graphics/graphics_restrictions.hpp" #include "graphics/material.hpp" -#include "graphics/material_manager.hpp" #include "graphics/sp/sp_texture_manager.hpp" #include "race/race_manager.hpp" #include "utils/mini_glm.hpp" @@ -372,7 +371,7 @@ void SPMeshBuffer::recreateVAO(unsigned i) glEnableVertexAttribArray(7); glVertexAttribPointer(7, 4, GL_HALF_FLOAT, GL_FALSE, pitch, (void*)offset); - offset += 8; + offset += 8; } else { diff --git a/src/graphics/sp/sp_mesh_buffer.hpp b/src/graphics/sp/sp_mesh_buffer.hpp index eabb51656..13d2b5e33 100644 --- a/src/graphics/sp/sp_mesh_buffer.hpp +++ b/src/graphics/sp/sp_mesh_buffer.hpp @@ -44,7 +44,7 @@ class SPTexture; class SPMeshBuffer : public IMeshBuffer { -private: +protected: std::vector > m_stk_material; @@ -54,6 +54,13 @@ private: std::vector m_vertices; + GLuint m_ibo, m_vbo; + + GLuint m_vao[DCT_FOR_VAO]; + + unsigned m_pitch; + +private: std::vector m_indices; core::aabbox3d m_bounding_box; @@ -62,16 +69,10 @@ private: void* m_ins_dat_mapped_ptr[DCT_FOR_VAO]; - GLuint m_ibo, m_vbo; - unsigned m_gl_instance_size[DCT_FOR_VAO]; - GLuint m_vao[DCT_FOR_VAO]; - GLuint m_ins_array[DCT_FOR_VAO]; - unsigned m_pitch; - bool m_uploaded_gl; bool m_uploaded_instance; @@ -107,31 +108,8 @@ public: // ------------------------------------------------------------------------ ~SPMeshBuffer(); // ------------------------------------------------------------------------ - bool combineMeshBuffer(SPMeshBuffer* spmb) - { - // We only use 16bit vertices - if (spmb->m_vertices.size() + m_vertices.size() > 65536) - { - return false; - } - const uint16_t old_vtx_count = (uint16_t)m_vertices.size(); - m_vertices.insert(m_vertices.end(), spmb->m_vertices.begin(), - spmb->m_vertices.end()); - for (uint16_t& idx : spmb->m_indices) - { - idx += old_vtx_count; - } - m_stk_material.emplace_back(getIndexCount(), spmb->getIndexCount(), - std::get<2>(spmb->m_stk_material[0])); - m_indices.insert(m_indices.end(), spmb->m_indices.begin(), - spmb->m_indices.end()); - return true; - } - // ------------------------------------------------------------------------ - void bindVAO(DrawCallType dct) const { glBindVertexArray(m_vao[dct]); } - // ------------------------------------------------------------------------ - void draw(DrawCallType dct, int material_id = -1, - bool bindless_texture = false) const + virtual void draw(DrawCallType dct, int material_id = -1, + bool bindless_texture = false) const { glBindVertexArray(m_vao[dct]); if (material_id == -1 || bindless_texture) @@ -165,12 +143,35 @@ public: } } // ------------------------------------------------------------------------ + virtual void uploadGLMesh(); + // ------------------------------------------------------------------------ + virtual void uploadInstanceData(); + // ------------------------------------------------------------------------ + bool combineMeshBuffer(SPMeshBuffer* spmb) + { + // We only use 16bit vertices + if (spmb->m_vertices.size() + m_vertices.size() > 65536) + { + return false; + } + const uint16_t old_vtx_count = (uint16_t)m_vertices.size(); + m_vertices.insert(m_vertices.end(), spmb->m_vertices.begin(), + spmb->m_vertices.end()); + for (uint16_t& idx : spmb->m_indices) + { + idx += old_vtx_count; + } + m_stk_material.emplace_back(getIndexCount(), spmb->getIndexCount(), + std::get<2>(spmb->m_stk_material[0])); + m_indices.insert(m_indices.end(), spmb->m_indices.begin(), + spmb->m_indices.end()); + return true; + } + // ------------------------------------------------------------------------ void initDrawMaterial(); // ------------------------------------------------------------------------ void enableSkinningData() { m_skinned = true; } // ------------------------------------------------------------------------ - void uploadGLMesh(); - // ------------------------------------------------------------------------ Material* getSTKMaterial(unsigned first_index = 0) const { for (unsigned i = 0; i < m_stk_material.size(); i++) @@ -248,8 +249,6 @@ public: m_ins_dat[dct].push_back(id); } // ------------------------------------------------------------------------ - void uploadInstanceData(); - // ------------------------------------------------------------------------ void recreateVAO(unsigned i); // ------------------------------------------------------------------------ video::S3DVertexSkinnedMesh* getSPMVertex() diff --git a/src/graphics/sp/sp_shader.cpp b/src/graphics/sp/sp_shader.cpp index b386d1b48..97df4ce4c 100644 --- a/src/graphics/sp/sp_shader.cpp +++ b/src/graphics/sp/sp_shader.cpp @@ -218,6 +218,10 @@ void SPShader::setUniformsPerObject(SPPerObjectUniform* sppou, RenderPass rp) { #ifndef SERVER_ONLY + if (sppou == NULL) + { + return; + } for (auto& p : m_uniforms[rp]) { if (sppou->assignUniform(p.first, p.second)) diff --git a/src/graphics/sp/sp_shader.hpp b/src/graphics/sp/sp_shader.hpp index 808f1d2ab..b2aa31507 100644 --- a/src/graphics/sp/sp_shader.hpp +++ b/src/graphics/sp/sp_shader.hpp @@ -55,7 +55,6 @@ enum RenderPass: unsigned int RP_1ST = 0, RP_2ND, RP_SHADOW, - RP_RSM, RP_COUNT }; @@ -67,6 +66,8 @@ inline std::ostream& operator<<(std::ostream& os, const RenderPass& rp) return os << "first pass"; case RP_2ND: return os << "second pass"; + case RP_SHADOW: + return os << "shadow pass"; default: return os; } @@ -102,14 +103,14 @@ private: public: // ------------------------------------------------------------------------ - SPShader(const std::string& name, unsigned pass_count = 4, + SPShader(const std::string& name, unsigned pass_count = 3, bool transparent_shader = false, int drawing_priority = 0, bool use_alpha_channel = false) : m_name(name), m_drawing_priority(drawing_priority), m_transparent_shader(transparent_shader), m_use_alpha_channel(use_alpha_channel || transparent_shader) { - memset(m_program, 0, sizeof(GLuint) * 4); + memset(m_program, 0, 12); #ifndef SERVER_ONLY for (unsigned rp = RP_1ST; rp < pass_count; rp++) { diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index ba740c6a7..7e4fa3404 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -413,9 +413,6 @@ void Kart::reset() if (m_skidmarks) { m_skidmarks->reset(); - const Track *track = - track_manager->getTrack( race_manager->getTrackName() ); - m_skidmarks->adjustFog(track->isFogEnabled() ); } Vec3 front(0, 0, getKartLength()*0.5f); @@ -1529,7 +1526,7 @@ void Kart::update(float dt) static video::SColor green(255, 61, 87, 23); // draw skidmarks if relevant (we force pink skidmarks on when hitting a bubblegum) - if(m_kart_properties->getSkidEnabled()) + if(m_kart_properties->getSkidEnabled() && m_skidmarks) { m_skidmarks->update(dt, m_bubblegum_time > 0, @@ -2644,14 +2641,12 @@ void Kart::loadData(RaceManager::KartType type, bool is_animated_model) m_slipstream = new SlipStream(this); - if (m_kart_properties->getSkidEnabled()) +#ifndef SERVER_ONLY + if (m_kart_properties->getSkidEnabled() && CVS->isGLSL()) { m_skidmarks = new SkidMarks(*this); - m_skidmarks->adjustFog( - track_manager->getTrack(race_manager->getTrackName()) - ->isFogEnabled() ); } -#ifndef SERVER_ONLY + bool create_shadow = m_kart_properties->getShadowTexture() != NULL && !CVS->supportsShadows();