Add dynamic draw call for skidmarks
This commit is contained in:
parent
52b19dd83a
commit
590850eacf
@ -8,6 +8,7 @@
|
||||
#include "vector3d.h"
|
||||
#include "vector2d.h"
|
||||
#include "SColor.h"
|
||||
#include <cstring>
|
||||
|
||||
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)
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -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,
|
||||
|
@ -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 <IMeshSceneNode.h>
|
||||
#include <SMesh.h>
|
||||
#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; i<m_nodes.size(); i++)
|
||||
{
|
||||
irr_driver->removeNode(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; i<m_left.size(); i++)
|
||||
float f = dt / stk_config->m_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<STKMeshSceneNode*>(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<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 =
|
||||
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<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 :
|
||||
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; i<Vertices.size() - 2; i++)
|
||||
{
|
||||
Vertices[i].Color.setAlpha(a);
|
||||
}
|
||||
m_fade_out = 0.0f;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // fade
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** 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;
|
||||
}
|
||||
#endif
|
||||
|
@ -20,17 +20,21 @@
|
||||
#ifndef HEADER_SKID_MARK_HPP
|
||||
#define HEADER_SKID_MARK_HPP
|
||||
|
||||
#include <aabbox3d.h>
|
||||
#include <memory>
|
||||
#include <SColor.h>
|
||||
#include <vector>
|
||||
|
||||
#include <aabbox3d.h>
|
||||
#include <SMeshBuffer.h>
|
||||
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<SkidMarkQuads *> m_left, m_right;
|
||||
|
||||
/** The nodes where each left/right pair is attached to. */
|
||||
std::vector<scene::ISceneNode *> m_nodes;
|
||||
std::vector<std::unique_ptr<SkidMarkQuads> > 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
|
||||
|
@ -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<SPShader*, std::unordered_map<std::string,
|
||||
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<SPMeshBuffer*, int/*material_id*/> > > > > >
|
||||
@ -94,7 +95,7 @@ std::vector<float> g_bounding_boxes;
|
||||
// ----------------------------------------------------------------------------
|
||||
core::vector3df g_wind_dir;
|
||||
// ----------------------------------------------------------------------------
|
||||
//std::unordered_set<SPDynamicDrawCall*> g_dy_dc;
|
||||
std::unordered_set<SPDynamicDrawCall*> 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<SPPerObjectUniform*>(shader)
|
||||
->addAssignerFunction("fog_enabled", fogUniformAssigner);
|
||||
static_cast<SPPerObjectUniform*>(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<SPPerObjectUniform*>(shader)
|
||||
->addAssignerFunction("fog_enabled", fogUniformAssigner);
|
||||
static_cast<SPPerObjectUniform*>(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<SPPerObjectUniform*>(shader)
|
||||
->addAssignerFunction("fog_enabled", fogUniformAssigner);
|
||||
static_cast<SPPerObjectUniform*>(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<SPPerObjectUniform*>(shader)
|
||||
->addAssignerFunction("fog_enabled", fogUniformAssigner);
|
||||
static_cast<SPPerObjectUniform*>(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<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()
|
||||
{
|
||||
@ -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<SPUniformAssigner*> shader_uniforms;
|
||||
static std::vector<SPUniformAssigner*> shader_uniforms;
|
||||
p.first->setUniformsPerObject(static_cast<SPPerObjectUniform*>
|
||||
(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<SPUniformAssigner*> draw_call_uniforms;
|
||||
p.first->setUniformsPerObject(static_cast<SPPerObjectUniform*>
|
||||
(draw_call), &draw_call_uniforms, rp);
|
||||
sp_draw_call_count++;*/
|
||||
static std::vector<SPUniformAssigner*> draw_call_uniforms;
|
||||
p.first->setUniformsPerObject(dynamic_cast<SPPerObjectUniform*>
|
||||
(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
|
||||
*/
|
||||
|
||||
}
|
||||
|
@ -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*);
|
||||
// ----------------------------------------------------------------------------
|
||||
|
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];
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
SPInstancedData()
|
||||
{
|
||||
memset(m_data, 0, 32);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
SPInstancedData(const core::matrix4& model_mat,
|
||||
float texture_trans_x, float texture_trans_y, float hue,
|
||||
|
@ -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"
|
||||
|
@ -44,7 +44,7 @@ class SPTexture;
|
||||
|
||||
class SPMeshBuffer : public IMeshBuffer
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
std::vector<std::tuple<size_t/*first_index_id*/,
|
||||
unsigned/*indices_count*/, Material*> > m_stk_material;
|
||||
|
||||
@ -54,6 +54,13 @@ private:
|
||||
|
||||
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;
|
||||
|
||||
core::aabbox3d<f32> 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()
|
||||
|
@ -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))
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user