Add dynamic draw call for skidmarks

This commit is contained in:
Benau 2017-12-28 16:14:09 +08:00
parent 52b19dd83a
commit 590850eacf
16 changed files with 771 additions and 314 deletions

View File

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

View File

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

View File

@ -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));
}
//-----------------------------------------------------------------------------

View File

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

View File

@ -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

View File

@ -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

View File

@ -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
*/
}

View File

@ -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*);
// ----------------------------------------------------------------------------

View 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
}

View 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>

View File

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

View File

@ -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"

View File

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

View File

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

View File

@ -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++)
{

View File

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