Add dynamic draw call for skidmarks
This commit is contained in:
parent
52b19dd83a
commit
590850eacf
@ -8,6 +8,7 @@
|
|||||||
#include "vector3d.h"
|
#include "vector3d.h"
|
||||||
#include "vector2d.h"
|
#include "vector2d.h"
|
||||||
#include "SColor.h"
|
#include "SColor.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
@ -253,6 +254,7 @@ struct S3DVertexTangents : public S3DVertex
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! SPM usage. */
|
||||||
struct S3DVertexSkinnedMesh
|
struct S3DVertexSkinnedMesh
|
||||||
{
|
{
|
||||||
core::vector3df m_position;
|
core::vector3df m_position;
|
||||||
@ -263,13 +265,22 @@ struct S3DVertexSkinnedMesh
|
|||||||
s16 m_joint_idx[4];
|
s16 m_joint_idx[4];
|
||||||
s16 m_weight[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
|
E_VERTEX_TYPE getType() const
|
||||||
{
|
{
|
||||||
return EVT_SKINNED_MESH;
|
return EVT_SKINNED_MESH;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline u32 getVertexPitchFromType(E_VERTEX_TYPE vertexType)
|
inline u32 getVertexPitchFromType(E_VERTEX_TYPE vertexType)
|
||||||
{
|
{
|
||||||
switch (vertexType)
|
switch (vertexType)
|
||||||
|
@ -204,6 +204,7 @@ void DrawCalls::prepareDrawCalls(scene::ICameraSceneNode *camnode)
|
|||||||
parseSceneManager(
|
parseSceneManager(
|
||||||
irr_driver->getSceneManager()->getRootSceneNode()->getChildren(),
|
irr_driver->getSceneManager()->getRootSceneNode()->getChildren(),
|
||||||
camnode);
|
camnode);
|
||||||
|
SP::handleDynamicDrawCall();
|
||||||
SP::updateModelMatrix();
|
SP::updateModelMatrix();
|
||||||
PROFILER_POP_CPU_MARKER();
|
PROFILER_POP_CPU_MARKER();
|
||||||
|
|
||||||
@ -221,7 +222,7 @@ void DrawCalls::prepareDrawCalls(scene::ICameraSceneNode *camnode)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000000);
|
reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000000);
|
||||||
}
|
}
|
||||||
while (reason == GL_TIMEOUT_EXPIRED);
|
while (reason == GL_TIMEOUT_EXPIRED);
|
||||||
}
|
}
|
||||||
glDeleteSync(m_sync);
|
glDeleteSync(m_sync);
|
||||||
|
@ -86,7 +86,8 @@ Material* MaterialManager::getMaterialFor(video::ITexture* t,
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
Material* MaterialManager::getMaterialSPM(std::string lay_one_tex_lc,
|
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;
|
std::string orignal_layer_one = lay_one_tex_lc;
|
||||||
core::stringc lc(lay_one_tex_lc.c_str());
|
core::stringc lc(lay_one_tex_lc.c_str());
|
||||||
@ -140,7 +141,8 @@ Material* MaterialManager::getMaterialSPM(std::string lay_one_tex_lc,
|
|||||||
}
|
}
|
||||||
} // for i
|
} // for i
|
||||||
}
|
}
|
||||||
return getSPMaterial("solid", StringUtils::getBasename(orignal_layer_one));
|
return getSPMaterial(def_shader_name,
|
||||||
|
StringUtils::getBasename(orignal_layer_one));
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -64,7 +64,8 @@ public:
|
|||||||
video::E_MATERIAL_TYPE material_type);
|
video::E_MATERIAL_TYPE material_type);
|
||||||
Material* getMaterialFor(video::ITexture* t);
|
Material* getMaterialFor(video::ITexture* t);
|
||||||
Material* getMaterialSPM(std::string lay_one_tex_lc,
|
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,
|
void setAllMaterialFlags(video::ITexture* t,
|
||||||
scene::IMeshBuffer *mb);
|
scene::IMeshBuffer *mb);
|
||||||
void adjustForFog(video::ITexture* t,
|
void adjustForFog(video::ITexture* t,
|
||||||
|
@ -20,42 +20,34 @@
|
|||||||
#include "graphics/skid_marks.hpp"
|
#include "graphics/skid_marks.hpp"
|
||||||
|
|
||||||
#include "config/stk_config.hpp"
|
#include "config/stk_config.hpp"
|
||||||
#include "graphics/irr_driver.hpp"
|
#include "graphics/central_settings.hpp"
|
||||||
#include "graphics/stk_mesh_scene_node.hpp"
|
#include "graphics/material_manager.hpp"
|
||||||
#include "karts/controller/controller.hpp"
|
|
||||||
#include "karts/abstract_kart.hpp"
|
#include "karts/abstract_kart.hpp"
|
||||||
#include "karts/skidding.hpp"
|
#include "karts/skidding.hpp"
|
||||||
#include "modes/world.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 "physics/btKart.hpp"
|
||||||
|
#include "utils/mini_glm.hpp"
|
||||||
|
|
||||||
#include <IMeshSceneNode.h>
|
#ifndef SERVER_ONLY
|
||||||
#include <SMesh.h>
|
|
||||||
|
|
||||||
float SkidMarks::m_avoid_z_fighting = 0.005f;
|
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;
|
const int SkidMarks::m_start_grey = 32;
|
||||||
|
|
||||||
/** Initialises empty skid marks. */
|
/** Initialises empty skid marks. */
|
||||||
SkidMarks::SkidMarks(const AbstractKart& kart, float width) : m_kart(kart)
|
SkidMarks::SkidMarks(const AbstractKart& kart, float width) : m_kart(kart)
|
||||||
{
|
{
|
||||||
m_width = width;
|
m_width = width;
|
||||||
m_material = new video::SMaterial();
|
m_material = material_manager->getMaterialSPM("skidmarks.png", "",
|
||||||
m_material->MaterialType = video::EMT_ONETEXTURE_BLEND;
|
"alphablend");
|
||||||
m_material->MaterialTypeParam =
|
m_shader = SP::getSPShader("alphablend");
|
||||||
pack_textureBlendFunc(video::EBF_SRC_ALPHA,
|
assert(m_shader != NULL);
|
||||||
video::EBF_ONE_MINUS_SRC_ALPHA,
|
m_skid_marking = false;
|
||||||
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;
|
|
||||||
} // SkidMark
|
} // SkidMark
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -63,7 +55,6 @@ SkidMarks::SkidMarks(const AbstractKart& kart, float width) : m_kart(kart)
|
|||||||
SkidMarks::~SkidMarks()
|
SkidMarks::~SkidMarks()
|
||||||
{
|
{
|
||||||
reset(); // remove all skid marks
|
reset(); // remove all skid marks
|
||||||
delete m_material;
|
|
||||||
} // ~SkidMarks
|
} // ~SkidMarks
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -71,17 +62,9 @@ SkidMarks::~SkidMarks()
|
|||||||
*/
|
*/
|
||||||
void SkidMarks::reset()
|
void SkidMarks::reset()
|
||||||
{
|
{
|
||||||
for(unsigned int i=0; i<m_nodes.size(); i++)
|
|
||||||
{
|
|
||||||
irr_driver->removeNode(m_nodes[i]);
|
|
||||||
m_left[i]->drop();
|
|
||||||
m_right[i]->drop();
|
|
||||||
}
|
|
||||||
m_left.clear();
|
m_left.clear();
|
||||||
m_right.clear();
|
m_right.clear();
|
||||||
m_nodes.clear();
|
|
||||||
m_skid_marking = false;
|
m_skid_marking = false;
|
||||||
m_current = -1;
|
|
||||||
} // reset
|
} // reset
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -96,11 +79,26 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
|||||||
if(m_kart.isWheeless())
|
if(m_kart.isWheeless())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float f = dt/stk_config->m_skid_fadeout_time*m_start_alpha;
|
float f = dt / stk_config->m_skid_fadeout_time;
|
||||||
for(unsigned int i=0; i<m_left.size(); i++)
|
auto it = m_left.begin();
|
||||||
|
while (it != m_left.end())
|
||||||
{
|
{
|
||||||
m_left[i]->fade(f);
|
if ((*it)->fade(f))
|
||||||
m_right[i]->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
|
// Get raycast information
|
||||||
@ -129,17 +127,11 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
|||||||
|
|
||||||
if(m_skid_marking)
|
if(m_skid_marking)
|
||||||
{
|
{
|
||||||
|
assert(!m_left.empty());
|
||||||
|
assert(!m_right.empty());
|
||||||
if (!is_skidding) // end skid marking
|
if (!is_skidding) // end skid marking
|
||||||
{
|
{
|
||||||
m_skid_marking = false;
|
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<STKMeshSceneNode*>(m_nodes[m_current]))
|
|
||||||
stkm->setReloadEachFrame(false);
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,23 +141,16 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
|||||||
delta.normalize();
|
delta.normalize();
|
||||||
delta *= m_width*0.5f;
|
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;
|
Vec3 newPoint = (raycast_left + raycast_right)/2;
|
||||||
// this linear distance does not account for the kart turning, it's true,
|
// this linear distance does not account for the kart turning, it's true,
|
||||||
// but it produces good enough results
|
// but it produces good enough results
|
||||||
float distance = (newPoint - start).length();
|
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_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);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,89 +167,75 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
|||||||
delta.normalize();
|
delta.normalize();
|
||||||
delta *= m_width*0.5f;
|
delta *= m_width*0.5f;
|
||||||
|
|
||||||
SkidMarkQuads *smq_left =
|
const int cleaning_threshold =
|
||||||
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<STKMeshSceneNode*>(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 =
|
|
||||||
core::clamp(int(World::getWorld()->getNumKarts()), 5, 15);
|
core::clamp(int(World::getWorld()->getNumKarts()), 5, 15);
|
||||||
if(m_current>=int(stk_config->m_max_skidmarks/cleaning_threshold))
|
while ((int)m_left.size() >=
|
||||||
m_current = 0;
|
stk_config->m_max_skidmarks / cleaning_threshold)
|
||||||
if(m_current>=(int)m_left.size())
|
|
||||||
{
|
{
|
||||||
m_left. push_back (smq_left );
|
m_left.erase(m_left.begin());
|
||||||
m_right.push_back (smq_right);
|
|
||||||
m_nodes.push_back (new_node);
|
|
||||||
}
|
}
|
||||||
else
|
while ((int)m_right.size() >=
|
||||||
|
stk_config->m_max_skidmarks / cleaning_threshold)
|
||||||
{
|
{
|
||||||
irr_driver->removeNode(m_nodes[m_current]);
|
m_right.erase(m_right.begin());
|
||||||
// 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_left [m_current] = smq_left;
|
m_left.emplace_back(
|
||||||
m_right [m_current] = smq_right;
|
new SkidMarkQuads(raycast_left-delta, raycast_left+delta,
|
||||||
m_nodes [m_current] = new_node;
|
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;
|
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
|
} // update
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left,
|
SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left,
|
||||||
const Vec3 &right,
|
const Vec3 &right,
|
||||||
const Vec3 &normal,
|
const Vec3 &normal,
|
||||||
video::SMaterial *material,
|
Material* material,
|
||||||
|
SP::SPShader* shader,
|
||||||
float z_offset,
|
float z_offset,
|
||||||
video::SColor* custom_color)
|
video::SColor* custom_color)
|
||||||
: scene::SMeshBuffer()
|
|
||||||
{
|
{
|
||||||
m_center_start = (left + right)/2;
|
m_center_start = (left + right)/2;
|
||||||
m_z_offset = z_offset;
|
m_z_offset = z_offset;
|
||||||
m_fade_out = 0.0f;
|
m_fade_out = 0.0f;
|
||||||
|
m_dy_dc = new SP::SPDynamicDrawCall(scene::EPT_TRIANGLE_STRIP,
|
||||||
|
shader, material);
|
||||||
|
static_cast<SP::SPPerObjectUniform*>(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 :
|
m_start_color = (custom_color != NULL ? *custom_color :
|
||||||
video::SColor(255,
|
video::SColor(255, SkidMarks::m_start_grey, SkidMarks::m_start_grey,
|
||||||
SkidMarks::m_start_grey,
|
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);
|
add(left, right, normal, 0.0f);
|
||||||
|
|
||||||
|
|
||||||
} // SkidMarkQuads
|
} // SkidMarkQuads
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
SkidMarks::SkidMarkQuads::~SkidMarkQuads()
|
||||||
|
{
|
||||||
|
SP::removeDynamicDrawCall(m_dy_dc);
|
||||||
|
delete m_dy_dc;
|
||||||
|
} // ~SkidMarkQuads
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Adds the two points to this SkidMarkQuads.
|
/** Adds the two points to this SkidMarkQuads.
|
||||||
* \param left,right Left and right coordinates.
|
* \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
|
// The skid marks must be raised slightly higher, otherwise it blends
|
||||||
// too much with the track.
|
// too much with the track.
|
||||||
int n = Vertices.size();
|
int n = m_dy_dc->getVertexCount();
|
||||||
|
|
||||||
video::S3DVertex v;
|
video::S3DVertexSkinnedMesh v;
|
||||||
v.Color = m_start_color;
|
v.m_color = m_start_color;
|
||||||
v.Color.setAlpha(0); // initially create all vertices at alpha=0...
|
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.
|
// 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,
|
// this ensures that the last two vertices are always at alpha=0,
|
||||||
// producing a fade-out effect
|
// producing a fade-out effect
|
||||||
if (n > 4)
|
if (n > 2)
|
||||||
{
|
{
|
||||||
Vertices[n - 1].Color.setAlpha(m_start_alpha);
|
m_dy_dc->getSPMVertex()[n - 1].m_color.setAlpha(m_start_alpha);
|
||||||
Vertices[n - 2].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.m_position = Vec3(right + normal * m_z_offset).toIrrVector();
|
||||||
v.Normal = normal.toIrrVector();
|
v.m_normal = MiniGLM::compressVector3(normal.toIrrVector());
|
||||||
v.TCoords = core::vector2df(0.0f, distance*0.5f);
|
short half_float_1 = 15360;
|
||||||
Vertices.push_back(v);
|
v.m_all_uvs[0] = half_float_1;
|
||||||
v.Pos = Vec3(right + normal * m_z_offset).toIrrVector();
|
v.m_all_uvs[1] = MiniGLM::toFloat16(distance * 0.5f);
|
||||||
v.TCoords = core::vector2df(1.0f, distance*0.5f);
|
m_dy_dc->addSPMVertex(v);
|
||||||
Vertices.push_back(v);
|
|
||||||
// Out of the box Irrlicht only supports triangle meshes and not
|
v.m_position = Vec3(left + normal * m_z_offset).toIrrVector();
|
||||||
// triangle strips. Since this is a strip it would be more efficient
|
v.m_all_uvs[0] = 0;
|
||||||
// to use a special triangle strip scene node.
|
v.m_all_uvs[1] = MiniGLM::toFloat16(distance * 0.5f);
|
||||||
if(n>=2)
|
m_dy_dc->addSPMVertex(v);
|
||||||
{
|
m_dy_dc->setUpdateOffset(n > 2 ? n - 2 : n);
|
||||||
Indices.push_back(n-2);
|
m_dy_dc->recalculateBoundingBox();
|
||||||
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);
|
|
||||||
|
|
||||||
setDirty();
|
|
||||||
} // add
|
} // add
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Fades the current skid marks.
|
/** Fades the current skid marks.
|
||||||
* \param f fade factor.
|
* \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;
|
m_fade_out += f;
|
||||||
// Changing the alpha value is quite expensive, so it's only done
|
if (m_fade_out >= 1.0f)
|
||||||
// about 10 times till 0 is reached.
|
|
||||||
if(m_fade_out*10>SkidMarks::m_start_alpha)
|
|
||||||
{
|
{
|
||||||
video::SColor &c = Material.DiffuseColor;
|
return true;
|
||||||
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; i<Vertices.size() - 2; i++)
|
|
||||||
{
|
|
||||||
Vertices[i].Color.setAlpha(a);
|
|
||||||
}
|
|
||||||
m_fade_out = 0.0f;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
} // fade
|
} // fade
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
#endif
|
||||||
/** Sets the fog handling for the skid marks.
|
|
||||||
* \param enabled True if fog should be enabled.
|
|
||||||
*/
|
|
||||||
void SkidMarks::adjustFog(bool enabled)
|
|
||||||
{
|
|
||||||
m_material->FogEnable = enabled;
|
|
||||||
}
|
|
||||||
|
@ -20,17 +20,21 @@
|
|||||||
#ifndef HEADER_SKID_MARK_HPP
|
#ifndef HEADER_SKID_MARK_HPP
|
||||||
#define HEADER_SKID_MARK_HPP
|
#define HEADER_SKID_MARK_HPP
|
||||||
|
|
||||||
|
#include <aabbox3d.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <SColor.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <aabbox3d.h>
|
|
||||||
#include <SMeshBuffer.h>
|
|
||||||
namespace irr
|
|
||||||
{
|
|
||||||
namespace video { class SMaterial; }
|
|
||||||
namespace scene { class ISceneNode; }
|
|
||||||
}
|
|
||||||
using namespace irr;
|
using namespace irr;
|
||||||
|
|
||||||
|
class Material;
|
||||||
|
|
||||||
|
namespace SP
|
||||||
|
{
|
||||||
|
class SPDynamicDrawCall;
|
||||||
|
class SPShader;
|
||||||
|
}
|
||||||
|
|
||||||
#include "utils/no_copy.hpp"
|
#include "utils/no_copy.hpp"
|
||||||
#include "utils/vec3.hpp"
|
#include "utils/vec3.hpp"
|
||||||
|
|
||||||
@ -51,9 +55,6 @@ private:
|
|||||||
/** Reduce effect of Z-fighting. */
|
/** Reduce effect of Z-fighting. */
|
||||||
float m_width;
|
float m_width;
|
||||||
|
|
||||||
/** Index of current (last added) skid mark quad. */
|
|
||||||
int m_current;
|
|
||||||
|
|
||||||
/** Initial alpha value. */
|
/** Initial alpha value. */
|
||||||
static const int m_start_alpha;
|
static const int m_start_alpha;
|
||||||
|
|
||||||
@ -61,10 +62,13 @@ private:
|
|||||||
static const int m_start_grey;
|
static const int m_start_grey;
|
||||||
|
|
||||||
/** Material to use for the skid marks. */
|
/** 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
|
/** Used to move skid marks at the same location slightly on
|
||||||
* top of each other to avoid a 'wobbling' effect when sometines
|
* top of each other to avoid a 'wobbling' effect when sometines
|
||||||
@ -74,35 +78,30 @@ private:
|
|||||||
/** Fade out = alpha value. */
|
/** Fade out = alpha value. */
|
||||||
float m_fade_out;
|
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;
|
video::SColor m_start_color;
|
||||||
|
|
||||||
/** Vector marking the start of the skidmarks (located between left and right wheel) */
|
/** Vector marking the start of the skidmarks (located between left and right wheel) */
|
||||||
Vec3 m_center_start;
|
Vec3 m_center_start;
|
||||||
|
|
||||||
|
SP::SPDynamicDrawCall* m_dy_dc;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SkidMarkQuads (const Vec3 &left, const Vec3 &right,
|
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);
|
float z_offset, video::SColor* custom_color = NULL);
|
||||||
|
~SkidMarkQuads();
|
||||||
void add (const Vec3 &left,
|
void add (const Vec3 &left,
|
||||||
const Vec3 &right,
|
const Vec3 &right,
|
||||||
const Vec3 &normal,
|
const Vec3 &normal,
|
||||||
float distance);
|
float distance);
|
||||||
void fade (float f);
|
bool fade (float f);
|
||||||
/** Returns the aabb of this skid mark quads. */
|
|
||||||
const core::aabbox3df &getAABB() { return m_aabb; }
|
|
||||||
const Vec3& getCenterStart() const { return m_center_start; }
|
const Vec3& getCenterStart() const { return m_center_start; }
|
||||||
}; // SkidMarkQuads
|
}; // SkidMarkQuads
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Two skidmark objects for the left and right wheel. */
|
/** Two skidmark objects for the left and right wheel. */
|
||||||
std::vector<SkidMarkQuads *> m_left, m_right;
|
std::vector<std::unique_ptr<SkidMarkQuads> > m_left, m_right;
|
||||||
|
|
||||||
/** The nodes where each left/right pair is attached to. */
|
|
||||||
std::vector<scene::ISceneNode *> m_nodes;
|
|
||||||
|
|
||||||
/** Shared static so that consecutive skidmarks are at a slightly
|
/** Shared static so that consecutive skidmarks are at a slightly
|
||||||
* different height. */
|
* different height. */
|
||||||
@ -115,8 +114,6 @@ public:
|
|||||||
video::SColor* custom_color = NULL);
|
video::SColor* custom_color = NULL);
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
void adjustFog(bool enabled);
|
|
||||||
|
|
||||||
}; // SkidMarks
|
}; // SkidMarks
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "graphics/rtts.hpp"
|
#include "graphics/rtts.hpp"
|
||||||
#include "graphics/shaders.hpp"
|
#include "graphics/shaders.hpp"
|
||||||
#include "graphics/stk_tex_manager.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_instanced_data.hpp"
|
||||||
#include "graphics/sp/sp_per_object_uniform.hpp"
|
#include "graphics/sp/sp_per_object_uniform.hpp"
|
||||||
#include "graphics/sp/sp_mesh.hpp"
|
#include "graphics/sp/sp_mesh.hpp"
|
||||||
@ -75,7 +76,7 @@ SPShader* g_glow_shader = NULL;
|
|||||||
typedef std::unordered_map<SPShader*, std::unordered_map<std::string,
|
typedef std::unordered_map<SPShader*, std::unordered_map<std::string,
|
||||||
std::unordered_set<SPMeshBuffer*> > > DrawCall;
|
std::unordered_set<SPMeshBuffer*> > > DrawCall;
|
||||||
|
|
||||||
DrawCall g_draw_calls[DCT_COUNT];
|
DrawCall g_draw_calls[DCT_FOR_VAO];
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
std::vector<std::pair<SPShader*, std::vector<std::pair<std::array<GLuint, 6>,
|
std::vector<std::pair<SPShader*, std::vector<std::pair<std::array<GLuint, 6>,
|
||||||
std::vector<std::pair<SPMeshBuffer*, int/*material_id*/> > > > > >
|
std::vector<std::pair<SPMeshBuffer*, int/*material_id*/> > > > > >
|
||||||
@ -94,7 +95,7 @@ std::vector<float> g_bounding_boxes;
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
core::vector3df g_wind_dir;
|
core::vector3df g_wind_dir;
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
//std::unordered_set<SPDynamicDrawCall*> g_dy_dc;
|
std::unordered_set<SPDynamicDrawCall*> g_dy_dc;
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
float g_frustums[5][24] = { { } };
|
float g_frustums[5][24] = { { } };
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -149,6 +150,12 @@ void fogUniformAssigner(SPUniformAssigner* ua)
|
|||||||
ua->setValue(fog_enable);
|
ua->setValue(fog_enable);
|
||||||
} // fogUniformAssigner
|
} // fogUniformAssigner
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
void zeroAlphaUniformAssigner(SPUniformAssigner* ua)
|
||||||
|
{
|
||||||
|
ua->setValue(0.0f);
|
||||||
|
} // zeroAlphaUniformAssigner
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void ghostAlphaAssigner(SPUniformAssigner* ua)
|
void ghostAlphaAssigner(SPUniformAssigner* ua)
|
||||||
{
|
{
|
||||||
@ -417,7 +424,7 @@ void loadShaders()
|
|||||||
addShader(shader);
|
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_pass.vert", GL_VERTEX_SHADER, RP_1ST);
|
||||||
shader->addShaderFile("sp_alpha_test.frag", GL_FRAGMENT_SHADER, RP_1ST);
|
shader->addShaderFile("sp_alpha_test.frag", GL_FRAGMENT_SHADER, RP_1ST);
|
||||||
@ -438,7 +445,7 @@ void loadShaders()
|
|||||||
|
|
||||||
addShader(shader);
|
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_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
|
||||||
shader->addShaderFile("sp_alpha_test.frag", GL_FRAGMENT_SHADER, RP_1ST);
|
shader->addShaderFile("sp_alpha_test.frag", GL_FRAGMENT_SHADER, RP_1ST);
|
||||||
@ -460,7 +467,7 @@ void loadShaders()
|
|||||||
addShader(shader);
|
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_pass.vert", GL_VERTEX_SHADER, RP_1ST);
|
||||||
shader->addShaderFile("sp_unlit.frag", GL_FRAGMENT_SHADER, RP_1ST);
|
shader->addShaderFile("sp_unlit.frag", GL_FRAGMENT_SHADER, RP_1ST);
|
||||||
@ -481,7 +488,7 @@ void loadShaders()
|
|||||||
|
|
||||||
addShader(shader);
|
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_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
|
||||||
shader->addShaderFile("sp_unlit.frag", GL_FRAGMENT_SHADER, RP_1ST);
|
shader->addShaderFile("sp_unlit.frag", GL_FRAGMENT_SHADER, RP_1ST);
|
||||||
@ -524,7 +531,7 @@ void loadShaders()
|
|||||||
|
|
||||||
addShader(shader);
|
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_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
|
||||||
shader->addShaderFile("sp_normal_map.frag", GL_FRAGMENT_SHADER, RP_1ST);
|
shader->addShaderFile("sp_normal_map.frag", GL_FRAGMENT_SHADER, RP_1ST);
|
||||||
@ -546,7 +553,7 @@ void loadShaders()
|
|||||||
addShader(shader);
|
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_pass.vert", GL_VERTEX_SHADER, RP_1ST);
|
||||||
shader->addShaderFile("sp_grass.frag", GL_FRAGMENT_SHADER,
|
shader->addShaderFile("sp_grass.frag", GL_FRAGMENT_SHADER,
|
||||||
RP_1ST);
|
RP_1ST);
|
||||||
@ -590,10 +597,7 @@ void loadShaders()
|
|||||||
static_cast<SPPerObjectUniform*>(shader)
|
static_cast<SPPerObjectUniform*>(shader)
|
||||||
->addAssignerFunction("fog_enabled", fogUniformAssigner);
|
->addAssignerFunction("fog_enabled", fogUniformAssigner);
|
||||||
static_cast<SPPerObjectUniform*>(shader)
|
static_cast<SPPerObjectUniform*>(shader)
|
||||||
->addAssignerFunction("custom_alpha", [](SPUniformAssigner* ua)
|
->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner);
|
||||||
{
|
|
||||||
ua->setValue(0.0f);
|
|
||||||
});
|
|
||||||
addShader(shader);
|
addShader(shader);
|
||||||
|
|
||||||
shader = new SPShader("alphablend", 1, true);
|
shader = new SPShader("alphablend", 1, true);
|
||||||
@ -609,10 +613,7 @@ void loadShaders()
|
|||||||
static_cast<SPPerObjectUniform*>(shader)
|
static_cast<SPPerObjectUniform*>(shader)
|
||||||
->addAssignerFunction("fog_enabled", fogUniformAssigner);
|
->addAssignerFunction("fog_enabled", fogUniformAssigner);
|
||||||
static_cast<SPPerObjectUniform*>(shader)
|
static_cast<SPPerObjectUniform*>(shader)
|
||||||
->addAssignerFunction("custom_alpha", [](SPUniformAssigner* ua)
|
->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner);
|
||||||
{
|
|
||||||
ua->setValue(0.0f);
|
|
||||||
});
|
|
||||||
addShader(shader);
|
addShader(shader);
|
||||||
|
|
||||||
shader = new SPShader("additive_skinned", 1, true);
|
shader = new SPShader("additive_skinned", 1, true);
|
||||||
@ -628,10 +629,7 @@ void loadShaders()
|
|||||||
static_cast<SPPerObjectUniform*>(shader)
|
static_cast<SPPerObjectUniform*>(shader)
|
||||||
->addAssignerFunction("fog_enabled", fogUniformAssigner);
|
->addAssignerFunction("fog_enabled", fogUniformAssigner);
|
||||||
static_cast<SPPerObjectUniform*>(shader)
|
static_cast<SPPerObjectUniform*>(shader)
|
||||||
->addAssignerFunction("custom_alpha", [](SPUniformAssigner* ua)
|
->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner);
|
||||||
{
|
|
||||||
ua->setValue(0.0f);
|
|
||||||
});
|
|
||||||
addShader(shader);
|
addShader(shader);
|
||||||
|
|
||||||
shader = new SPShader("additive", 1, true);
|
shader = new SPShader("additive", 1, true);
|
||||||
@ -647,10 +645,7 @@ void loadShaders()
|
|||||||
static_cast<SPPerObjectUniform*>(shader)
|
static_cast<SPPerObjectUniform*>(shader)
|
||||||
->addAssignerFunction("fog_enabled", fogUniformAssigner);
|
->addAssignerFunction("fog_enabled", fogUniformAssigner);
|
||||||
static_cast<SPPerObjectUniform*>(shader)
|
static_cast<SPPerObjectUniform*>(shader)
|
||||||
->addAssignerFunction("custom_alpha", [](SPUniformAssigner* ua)
|
->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner);
|
||||||
{
|
|
||||||
ua->setValue(0.0f);
|
|
||||||
});
|
|
||||||
addShader(shader);
|
addShader(shader);
|
||||||
|
|
||||||
shader = new SPShader("ghost_skinned", 1, true/*transparent_shader*/,
|
shader = new SPShader("ghost_skinned", 1, true/*transparent_shader*/,
|
||||||
@ -1344,6 +1339,120 @@ void addObject(SPMeshNode* node)
|
|||||||
#endif
|
#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<bool> 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()
|
void updateModelMatrix()
|
||||||
{
|
{
|
||||||
@ -1557,8 +1666,8 @@ void draw(RenderPass rp, DrawCallType dct)
|
|||||||
std::stringstream profiler_name;
|
std::stringstream profiler_name;
|
||||||
profiler_name << "SP::Draw " << dct << " with " << rp;
|
profiler_name << "SP::Draw " << dct << " with " << rp;
|
||||||
PROFILER_PUSH_CPU_MARKER(profiler_name.str().c_str(),
|
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 + rp + 2) / float(DCT_FOR_VAO + RP_COUNT) * 255.0f),
|
||||||
(uint8_t)(float(dct + 1) / (float)DCT_COUNT * 255.0f) ,
|
(uint8_t)(float(dct + 1) / (float)DCT_FOR_VAO * 255.0f) ,
|
||||||
(uint8_t)(float(rp + 1) / (float)RP_COUNT * 255.0f));
|
(uint8_t)(float(rp + 1) / (float)RP_COUNT * 255.0f));
|
||||||
|
|
||||||
assert(dct < DCT_FOR_VAO);
|
assert(dct < DCT_FOR_VAO);
|
||||||
@ -1570,7 +1679,7 @@ void draw(RenderPass rp, DrawCallType dct)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
p.first->use(rp);
|
p.first->use(rp);
|
||||||
std::vector<SPUniformAssigner*> shader_uniforms;
|
static std::vector<SPUniformAssigner*> shader_uniforms;
|
||||||
p.first->setUniformsPerObject(static_cast<SPPerObjectUniform*>
|
p.first->setUniformsPerObject(static_cast<SPPerObjectUniform*>
|
||||||
(p.first), &shader_uniforms, rp);
|
(p.first), &shader_uniforms, rp);
|
||||||
p.first->bindPrefilledTextures(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++)
|
for (unsigned k = 0; k < p.second[j].second.size(); k++)
|
||||||
{
|
{
|
||||||
/*std::vector<SPUniformAssigner*> draw_call_uniforms;
|
static std::vector<SPUniformAssigner*> draw_call_uniforms;
|
||||||
p.first->setUniformsPerObject(static_cast<SPPerObjectUniform*>
|
p.first->setUniformsPerObject(dynamic_cast<SPPerObjectUniform*>
|
||||||
(draw_call), &draw_call_uniforms, rp);
|
(p.second[j].second[k].first), &draw_call_uniforms, rp);
|
||||||
sp_draw_call_count++;*/
|
|
||||||
p.second[j].second[k].first->draw(dct,
|
p.second[j].second[k].first->draw(dct,
|
||||||
p.second[j].second[k].second/*material_id*/,
|
p.second[j].second[k].second/*material_id*/,
|
||||||
CVS->isARBBindlessTextureUsable() ||
|
CVS->isARBBindlessTextureUsable() ||
|
||||||
CVS->useArrayTextures());
|
CVS->useArrayTextures());
|
||||||
/*for (SPUniformAssigner* ua : draw_call_uniforms)
|
for (SPUniformAssigner* ua : draw_call_uniforms)
|
||||||
{
|
{
|
||||||
ua->reset();
|
ua->reset();
|
||||||
}*/
|
}
|
||||||
|
draw_call_uniforms.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (SPUniformAssigner* ua : shader_uniforms)
|
for (SPUniformAssigner* ua : shader_uniforms)
|
||||||
{
|
{
|
||||||
ua->reset();
|
ua->reset();
|
||||||
}
|
}
|
||||||
|
shader_uniforms.clear();
|
||||||
p.first->unuse(rp);
|
p.first->unuse(rp);
|
||||||
}
|
}
|
||||||
PROFILER_POP_CPU_MARKER();
|
PROFILER_POP_CPU_MARKER();
|
||||||
#endif
|
#endif
|
||||||
} // draw
|
} // draw
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
void d()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
void unsynchronisedUpdate()
|
|
||||||
{
|
|
||||||
for (SPDynamicDrawCall* dy_dc : g_dy_dc)
|
|
||||||
{
|
|
||||||
dy_dc->update(true);
|
|
||||||
}
|
|
||||||
} // unsynchronisedUpdate
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void addDynamicDrawCall(SPDynamicDrawCall* dy_dc)
|
void addDynamicDrawCall(SPDynamicDrawCall* dy_dc)
|
||||||
{
|
{
|
||||||
@ -1638,6 +1728,5 @@ void removeDynamicDrawCall(SPDynamicDrawCall* dy_dc)
|
|||||||
{
|
{
|
||||||
g_dy_dc.erase(dy_dc);
|
g_dy_dc.erase(dy_dc);
|
||||||
} // removeDynamicDrawCall
|
} // removeDynamicDrawCall
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -52,8 +52,7 @@ enum DrawCallType: unsigned int
|
|||||||
DCT_SHADOW3,
|
DCT_SHADOW3,
|
||||||
DCT_SHADOW4,
|
DCT_SHADOW4,
|
||||||
DCT_TRANSPARENT,
|
DCT_TRANSPARENT,
|
||||||
DCT_FOR_VAO,
|
DCT_FOR_VAO
|
||||||
DCT_COUNT = DCT_FOR_VAO
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& os, const DrawCallType& dct)
|
inline std::ostream& operator<<(std::ostream& os, const DrawCallType& dct)
|
||||||
@ -118,21 +117,13 @@ void drawGlow();
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void drawNormal();
|
void drawNormal();
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void drawBoundingBoxes();
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
void addObject(SPMeshNode*);
|
void addObject(SPMeshNode*);
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void removeObject(SPMeshNode*);
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
void cleanAllMeshBuffer();
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
void updateTransformation();
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
void initSTKRenderer(ShaderBasedRenderer*);
|
void initSTKRenderer(ShaderBasedRenderer*);
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void prepareScene();
|
void prepareScene();
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void unsynchronisedUpdate();
|
void handleDynamicDrawCall();
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void addDynamicDrawCall(SPDynamicDrawCall*);
|
void addDynamicDrawCall(SPDynamicDrawCall*);
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
228
src/graphics/sp/sp_dynamic_draw_call.cpp
Normal file
228
src/graphics/sp/sp_dynamic_draw_call.cpp
Normal file
@ -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
|
||||||
|
|
||||||
|
}
|
191
src/graphics/sp/sp_dynamic_draw_call.hpp
Normal file
191
src/graphics/sp/sp_dynamic_draw_call.hpp
Normal file
@ -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 <IMeshBuffer.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
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<bool> 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<video::S3DVertexSkinnedMesh>& 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 <S3DVertex.h>
|
@ -34,6 +34,11 @@ private:
|
|||||||
char m_data[32];
|
char m_data[32];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
SPInstancedData()
|
||||||
|
{
|
||||||
|
memset(m_data, 0, 32);
|
||||||
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
SPInstancedData(const core::matrix4& model_mat,
|
SPInstancedData(const core::matrix4& model_mat,
|
||||||
float texture_trans_x, float texture_trans_y, float hue,
|
float texture_trans_x, float texture_trans_y, float hue,
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include "graphics/central_settings.hpp"
|
#include "graphics/central_settings.hpp"
|
||||||
#include "graphics/graphics_restrictions.hpp"
|
#include "graphics/graphics_restrictions.hpp"
|
||||||
#include "graphics/material.hpp"
|
#include "graphics/material.hpp"
|
||||||
#include "graphics/material_manager.hpp"
|
|
||||||
#include "graphics/sp/sp_texture_manager.hpp"
|
#include "graphics/sp/sp_texture_manager.hpp"
|
||||||
#include "race/race_manager.hpp"
|
#include "race/race_manager.hpp"
|
||||||
#include "utils/mini_glm.hpp"
|
#include "utils/mini_glm.hpp"
|
||||||
@ -372,7 +371,7 @@ void SPMeshBuffer::recreateVAO(unsigned i)
|
|||||||
glEnableVertexAttribArray(7);
|
glEnableVertexAttribArray(7);
|
||||||
glVertexAttribPointer(7, 4, GL_HALF_FLOAT, GL_FALSE, pitch,
|
glVertexAttribPointer(7, 4, GL_HALF_FLOAT, GL_FALSE, pitch,
|
||||||
(void*)offset);
|
(void*)offset);
|
||||||
offset += 8;
|
offset += 8;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,7 @@ class SPTexture;
|
|||||||
|
|
||||||
class SPMeshBuffer : public IMeshBuffer
|
class SPMeshBuffer : public IMeshBuffer
|
||||||
{
|
{
|
||||||
private:
|
protected:
|
||||||
std::vector<std::tuple<size_t/*first_index_id*/,
|
std::vector<std::tuple<size_t/*first_index_id*/,
|
||||||
unsigned/*indices_count*/, Material*> > m_stk_material;
|
unsigned/*indices_count*/, Material*> > m_stk_material;
|
||||||
|
|
||||||
@ -54,6 +54,13 @@ private:
|
|||||||
|
|
||||||
std::vector<video::S3DVertexSkinnedMesh> m_vertices;
|
std::vector<video::S3DVertexSkinnedMesh> m_vertices;
|
||||||
|
|
||||||
|
GLuint m_ibo, m_vbo;
|
||||||
|
|
||||||
|
GLuint m_vao[DCT_FOR_VAO];
|
||||||
|
|
||||||
|
unsigned m_pitch;
|
||||||
|
|
||||||
|
private:
|
||||||
std::vector<uint16_t> m_indices;
|
std::vector<uint16_t> m_indices;
|
||||||
|
|
||||||
core::aabbox3d<f32> m_bounding_box;
|
core::aabbox3d<f32> m_bounding_box;
|
||||||
@ -62,16 +69,10 @@ private:
|
|||||||
|
|
||||||
void* m_ins_dat_mapped_ptr[DCT_FOR_VAO];
|
void* m_ins_dat_mapped_ptr[DCT_FOR_VAO];
|
||||||
|
|
||||||
GLuint m_ibo, m_vbo;
|
|
||||||
|
|
||||||
unsigned m_gl_instance_size[DCT_FOR_VAO];
|
unsigned m_gl_instance_size[DCT_FOR_VAO];
|
||||||
|
|
||||||
GLuint m_vao[DCT_FOR_VAO];
|
|
||||||
|
|
||||||
GLuint m_ins_array[DCT_FOR_VAO];
|
GLuint m_ins_array[DCT_FOR_VAO];
|
||||||
|
|
||||||
unsigned m_pitch;
|
|
||||||
|
|
||||||
bool m_uploaded_gl;
|
bool m_uploaded_gl;
|
||||||
|
|
||||||
bool m_uploaded_instance;
|
bool m_uploaded_instance;
|
||||||
@ -107,31 +108,8 @@ public:
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
~SPMeshBuffer();
|
~SPMeshBuffer();
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
bool combineMeshBuffer(SPMeshBuffer* spmb)
|
virtual void draw(DrawCallType dct, int material_id = -1,
|
||||||
{
|
bool bindless_texture = false) const
|
||||||
// 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
|
|
||||||
{
|
{
|
||||||
glBindVertexArray(m_vao[dct]);
|
glBindVertexArray(m_vao[dct]);
|
||||||
if (material_id == -1 || bindless_texture)
|
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 initDrawMaterial();
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void enableSkinningData() { m_skinned = true; }
|
void enableSkinningData() { m_skinned = true; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void uploadGLMesh();
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
Material* getSTKMaterial(unsigned first_index = 0) const
|
Material* getSTKMaterial(unsigned first_index = 0) const
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < m_stk_material.size(); i++)
|
for (unsigned i = 0; i < m_stk_material.size(); i++)
|
||||||
@ -248,8 +249,6 @@ public:
|
|||||||
m_ins_dat[dct].push_back(id);
|
m_ins_dat[dct].push_back(id);
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void uploadInstanceData();
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
void recreateVAO(unsigned i);
|
void recreateVAO(unsigned i);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
video::S3DVertexSkinnedMesh* getSPMVertex()
|
video::S3DVertexSkinnedMesh* getSPMVertex()
|
||||||
|
@ -218,6 +218,10 @@ void SPShader::setUniformsPerObject(SPPerObjectUniform* sppou,
|
|||||||
RenderPass rp)
|
RenderPass rp)
|
||||||
{
|
{
|
||||||
#ifndef SERVER_ONLY
|
#ifndef SERVER_ONLY
|
||||||
|
if (sppou == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (auto& p : m_uniforms[rp])
|
for (auto& p : m_uniforms[rp])
|
||||||
{
|
{
|
||||||
if (sppou->assignUniform(p.first, p.second))
|
if (sppou->assignUniform(p.first, p.second))
|
||||||
|
@ -55,7 +55,6 @@ enum RenderPass: unsigned int
|
|||||||
RP_1ST = 0,
|
RP_1ST = 0,
|
||||||
RP_2ND,
|
RP_2ND,
|
||||||
RP_SHADOW,
|
RP_SHADOW,
|
||||||
RP_RSM,
|
|
||||||
RP_COUNT
|
RP_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,6 +66,8 @@ inline std::ostream& operator<<(std::ostream& os, const RenderPass& rp)
|
|||||||
return os << "first pass";
|
return os << "first pass";
|
||||||
case RP_2ND:
|
case RP_2ND:
|
||||||
return os << "second pass";
|
return os << "second pass";
|
||||||
|
case RP_SHADOW:
|
||||||
|
return os << "shadow pass";
|
||||||
default:
|
default:
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
@ -102,14 +103,14 @@ private:
|
|||||||
|
|
||||||
public:
|
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 transparent_shader = false, int drawing_priority = 0,
|
||||||
bool use_alpha_channel = false)
|
bool use_alpha_channel = false)
|
||||||
: m_name(name), m_drawing_priority(drawing_priority),
|
: m_name(name), m_drawing_priority(drawing_priority),
|
||||||
m_transparent_shader(transparent_shader),
|
m_transparent_shader(transparent_shader),
|
||||||
m_use_alpha_channel(use_alpha_channel || 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
|
#ifndef SERVER_ONLY
|
||||||
for (unsigned rp = RP_1ST; rp < pass_count; rp++)
|
for (unsigned rp = RP_1ST; rp < pass_count; rp++)
|
||||||
{
|
{
|
||||||
|
@ -413,9 +413,6 @@ void Kart::reset()
|
|||||||
if (m_skidmarks)
|
if (m_skidmarks)
|
||||||
{
|
{
|
||||||
m_skidmarks->reset();
|
m_skidmarks->reset();
|
||||||
const Track *track =
|
|
||||||
track_manager->getTrack( race_manager->getTrackName() );
|
|
||||||
m_skidmarks->adjustFog(track->isFogEnabled() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 front(0, 0, getKartLength()*0.5f);
|
Vec3 front(0, 0, getKartLength()*0.5f);
|
||||||
@ -1529,7 +1526,7 @@ void Kart::update(float dt)
|
|||||||
static video::SColor green(255, 61, 87, 23);
|
static video::SColor green(255, 61, 87, 23);
|
||||||
|
|
||||||
// draw skidmarks if relevant (we force pink skidmarks on when hitting a bubblegum)
|
// 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_skidmarks->update(dt,
|
||||||
m_bubblegum_time > 0,
|
m_bubblegum_time > 0,
|
||||||
@ -2644,14 +2641,12 @@ void Kart::loadData(RaceManager::KartType type, bool is_animated_model)
|
|||||||
|
|
||||||
m_slipstream = new SlipStream(this);
|
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 = new SkidMarks(*this);
|
||||||
m_skidmarks->adjustFog(
|
|
||||||
track_manager->getTrack(race_manager->getTrackName())
|
|
||||||
->isFogEnabled() );
|
|
||||||
}
|
}
|
||||||
#ifndef SERVER_ONLY
|
|
||||||
bool create_shadow = m_kart_properties->getShadowTexture() != NULL &&
|
bool create_shadow = m_kart_properties->getShadowTexture() != NULL &&
|
||||||
!CVS->supportsShadows();
|
!CVS->supportsShadows();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user