First version of hardware skinning

Todo: shadow, non-instanced shaders, culling, changeable offset...
This commit is contained in:
Benau 2016-12-07 02:15:11 +08:00
parent 23883b83c1
commit 57d9e83ed4
27 changed files with 612 additions and 65 deletions

View File

@ -63,5 +63,11 @@ layout (std140) uniform LightingData
float rL21;
float rL22;
};
layout (std140) uniform SkinningData
{
mat4 joint_matrices[1000];
};
#endif
#endif // HEADER_TXT

View File

@ -0,0 +1,120 @@
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec4 Color;
layout(location = 3) in vec4 Data1;
layout(location = 4) in vec4 Data2;
layout(location = 5) in ivec4 Joint;
layout(location = 6) in vec4 Weight;
layout(location = 7) in vec3 Origin;
layout(location = 8) in vec3 Orientation;
layout(location = 9) in vec3 Scale;
layout(location = 10) in vec4 misc_data;
#ifdef Use_Bindless_Texture
layout(location = 11) in sampler2D Handle;
layout(location = 12) in sampler2D SecondHandle;
layout(location = 13) in sampler2D ThirdHandle;
layout(location = 14) in sampler2D FourthHandle;
#endif
layout(location = 15) in uint skinning_offset;
out vec3 nor;
out vec3 tangent;
out vec3 bitangent;
out vec2 uv;
out vec4 color;
out vec2 color_change;
#ifdef Use_Bindless_Texture
flat out sampler2D handle;
flat out sampler2D secondhandle;
flat out sampler2D thirdhandle;
flat out sampler2D fourthhandle;
#endif
#stk_include "utils/getworldmatrix.vert"
void main(void)
{
mat4 ModelMatrix = getWorldMatrix(Origin, Orientation, Scale);
mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin, Orientation, Scale) * InverseViewMatrix);
vec4 idle_position = vec4(Position, 1.);
vec4 idle_normal = vec4(Normal, 0.);
vec4 skinned_position = vec4(0.);
vec4 skinned_normal = vec4(0.);
// Note : For normal we assume no scale factor in bone (otherwise we'll have to compute inversematrix for each bones...)
vec4 single_bone_influenced_position;
vec4 single_bone_influenced_normal;
if (Joint[0] >= 0)
{
single_bone_influenced_position = joint_matrices[Joint[0] + skinning_offset] * idle_position;
single_bone_influenced_position /= single_bone_influenced_position.w;
single_bone_influenced_normal = joint_matrices[Joint[0] + skinning_offset] * idle_normal;
}
else
{
single_bone_influenced_position = idle_position;
single_bone_influenced_normal = idle_normal;
}
skinned_position += Weight[0] * single_bone_influenced_position;
skinned_normal += Weight[0] * single_bone_influenced_normal;
if (Joint[1] >= 0)
{
single_bone_influenced_position= joint_matrices[Joint[1] + skinning_offset] * idle_position;
single_bone_influenced_position /= single_bone_influenced_position.w;
single_bone_influenced_normal = joint_matrices[Joint[1] + skinning_offset] * idle_normal;
}
else
{
single_bone_influenced_position = idle_position;
single_bone_influenced_normal = idle_normal;
}
skinned_position += Weight[1] * single_bone_influenced_position;
skinned_normal += Weight[1] * single_bone_influenced_normal;
if (Joint[2] >= 0)
{
single_bone_influenced_position = joint_matrices[Joint[2] + skinning_offset] * idle_position;
single_bone_influenced_position /= single_bone_influenced_position.w;
single_bone_influenced_normal = joint_matrices[Joint[2] + skinning_offset] * idle_normal;
}
else
{
single_bone_influenced_position = idle_position;
single_bone_influenced_normal = idle_normal;
}
skinned_position += Weight[2] * single_bone_influenced_position;
skinned_normal += Weight[2] * single_bone_influenced_normal;
if (Joint[3] >= 0)
{
single_bone_influenced_position = joint_matrices[Joint[3] + skinning_offset] * idle_position;
single_bone_influenced_position /= single_bone_influenced_position.w;
single_bone_influenced_normal = joint_matrices[Joint[3] + skinning_offset] * idle_normal;
}
else
{
single_bone_influenced_position = idle_position;
single_bone_influenced_normal = idle_normal;
}
skinned_position += Weight[3] * single_bone_influenced_position;
skinned_normal += Weight[3] * single_bone_influenced_normal;
gl_Position = ProjectionViewMatrix * ModelMatrix * skinned_position;
// Keep orthogonality
nor = (TransposeInverseModelView * skinned_normal).xyz;
// Keep direction
tangent = (ViewMatrix * ModelMatrix * vec4(Data1.z, Data1.w, Data2.x, 0.)).xyz;
bitangent = (ViewMatrix * ModelMatrix * vec4(Data2.y, Data2.z, Data2.w, 0.)).xyz;
uv = vec2(Data1.x + misc_data.x, Data1.y + misc_data.y);
color = Color.zyxw;
color_change = misc_data.zw;
#ifdef Use_Bindless_Texture
handle = Handle;
secondhandle = SecondHandle;
thirdhandle = ThirdHandle;
fourthhandle = FourthHandle;
#endif
}

View File

@ -116,6 +116,8 @@ namespace scene
NewVertices=new CSpecificVertexList<video::S3DVertexTangents>;
break;
}
default:
break;
}
if (Vertices)
{

View File

@ -371,6 +371,8 @@ protected:
func(verts[i]);
}
break;
default:
break;
}
if (boundingBoxUpdate)
{

View File

@ -26,7 +26,9 @@ enum E_VERTEX_TYPE
//! Vertex with a tangent and binormal vector, video::S3DVertexTangents.
/** Usually used for tangent space normal mapping. */
EVT_TANGENTS
EVT_TANGENTS,
EVT_SKINNED_MESH
};
//! Array holding the built in vertex type names
@ -251,6 +253,22 @@ struct S3DVertexTangents : public S3DVertex
}
};
struct S3DVertexSkinnedMesh : public S3DVertexTangents
{
s32 m_joint_idx1;
s32 m_joint_idx2;
s32 m_joint_idx3;
s32 m_joint_idx4;
f32 m_weight1;
f32 m_weight2;
f32 m_weight3;
f32 m_weight4;
E_VERTEX_TYPE getType() const
{
return EVT_SKINNED_MESH;
}
};
inline u32 getVertexPitchFromType(E_VERTEX_TYPE vertexType)
@ -261,6 +279,8 @@ inline u32 getVertexPitchFromType(E_VERTEX_TYPE vertexType)
return sizeof(video::S3DVertex2TCoords);
case video::EVT_TANGENTS:
return sizeof(video::S3DVertexTangents);
case video::EVT_SKINNED_MESH:
return sizeof(video::S3DVertexSkinnedMesh);
default:
return sizeof(video::S3DVertex);
}

View File

@ -50,6 +50,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
return (video::S3DVertex*)&Vertices_2TCoords[index];
case video::EVT_TANGENTS:
return (video::S3DVertex*)&Vertices_Tangents[index];
case video::EVT_SKINNED_MESH:
return (video::S3DVertex*)&Vertices_SkinnedMesh[index];
default:
return &Vertices_Standard[index];
}
@ -64,6 +66,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
return Vertices_2TCoords.const_pointer();
case video::EVT_TANGENTS:
return Vertices_Tangents.const_pointer();
case video::EVT_SKINNED_MESH:
return Vertices_SkinnedMesh.const_pointer();
default:
return Vertices_Standard.const_pointer();
}
@ -78,6 +82,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
return Vertices_2TCoords.pointer();
case video::EVT_TANGENTS:
return Vertices_Tangents.pointer();
case video::EVT_SKINNED_MESH:
return Vertices_SkinnedMesh.pointer();
default:
return Vertices_Standard.pointer();
}
@ -92,6 +98,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
return Vertices_2TCoords.size();
case video::EVT_TANGENTS:
return Vertices_Tangents.size();
case video::EVT_SKINNED_MESH:
return Vertices_SkinnedMesh.size();
default:
return Vertices_Standard.size();
}
@ -180,6 +188,20 @@ struct SSkinMeshBuffer : public IMeshBuffer
}
break;
}
case video::EVT_SKINNED_MESH:
{
if (Vertices_SkinnedMesh.empty())
BoundingBox.reset(0,0,0);
else
{
BoundingBox.reset(Vertices_SkinnedMesh[0].Pos);
for (u32 i=1; i<Vertices_SkinnedMesh.size(); ++i)
BoundingBox.addInternalPoint(Vertices_SkinnedMesh[i].Pos);
}
break;
}
default:
break;
}
}
@ -208,6 +230,23 @@ struct SSkinMeshBuffer : public IMeshBuffer
}
}
void convertForSkinning()
{
if (VertexType==video::EVT_STANDARD)
{
for(u32 n=0;n<Vertices_Standard.size();++n)
{
video::S3DVertexSkinnedMesh Vertex = {};
Vertex.Color=Vertices_Standard[n].Color;
Vertex.Pos=Vertices_Standard[n].Pos;
Vertex.Normal=Vertices_Standard[n].Normal;
Vertex.TCoords=Vertices_Standard[n].TCoords;
Vertices_SkinnedMesh.push_back(Vertex);
}
}
}
//! Convert to tangents vertex type
virtual void convertToTangents()
{
@ -250,6 +289,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
return Vertices_2TCoords[i].Pos;
case video::EVT_TANGENTS:
return Vertices_Tangents[i].Pos;
case video::EVT_SKINNED_MESH:
return Vertices_SkinnedMesh[i].Pos;
default:
return Vertices_Standard[i].Pos;
}
@ -264,6 +305,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
return Vertices_2TCoords[i].Pos;
case video::EVT_TANGENTS:
return Vertices_Tangents[i].Pos;
case video::EVT_SKINNED_MESH:
return Vertices_SkinnedMesh[i].Pos;
default:
return Vertices_Standard[i].Pos;
}
@ -278,6 +321,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
return Vertices_2TCoords[i].Normal;
case video::EVT_TANGENTS:
return Vertices_Tangents[i].Normal;
case video::EVT_SKINNED_MESH:
return Vertices_SkinnedMesh[i].Normal;
default:
return Vertices_Standard[i].Normal;
}
@ -292,6 +337,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
return Vertices_2TCoords[i].Normal;
case video::EVT_TANGENTS:
return Vertices_Tangents[i].Normal;
case video::EVT_SKINNED_MESH:
return Vertices_SkinnedMesh[i].Normal;
default:
return Vertices_Standard[i].Normal;
}
@ -306,6 +353,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
return Vertices_2TCoords[i].TCoords;
case video::EVT_TANGENTS:
return Vertices_Tangents[i].TCoords;
case video::EVT_SKINNED_MESH:
return Vertices_SkinnedMesh[i].TCoords;
default:
return Vertices_Standard[i].TCoords;
}
@ -320,6 +369,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
return Vertices_2TCoords[i].TCoords;
case video::EVT_TANGENTS:
return Vertices_Tangents[i].TCoords;
case video::EVT_SKINNED_MESH:
return Vertices_SkinnedMesh[i].TCoords;
default:
return Vertices_Standard[i].TCoords;
}
@ -381,6 +432,7 @@ struct SSkinMeshBuffer : public IMeshBuffer
core::array<video::S3DVertexTangents> Vertices_Tangents;
core::array<video::S3DVertex2TCoords> Vertices_2TCoords;
core::array<video::S3DVertexSkinnedMesh> Vertices_SkinnedMesh;
core::array<video::S3DVertex> Vertices_Standard;
core::array<u16> Indices;

View File

@ -18,7 +18,7 @@ namespace scene
//! constructor
CSkinnedMesh::CSkinnedMesh()
: SkinningBuffers(0), AnimationFrames(0.f), FramesPerSecond(25.f),
: m_joint_total_size(0), SkinningBuffers(0), AnimationFrames(0.f), FramesPerSecond(25.f),
LastAnimatedFrame(-1), SkinnedLastFrame(false),
InterpolationMode(EIM_LINEAR),
HasAnimation(false), PreparedForSkinning(false),
@ -27,7 +27,6 @@ CSkinnedMesh::CSkinnedMesh()
#ifdef _DEBUG
setDebugName("CSkinnedMesh");
#endif
SkinningBuffers=&LocalBuffers;
}
@ -74,12 +73,19 @@ void CSkinnedMesh::setAnimationSpeed(f32 fps)
//! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level.
IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
{
const bool is_hw_skinning_before = HardwareSkinning;
if (is_hw_skinning_before)
HardwareSkinning = false;
//animate(frame,startFrameLoop, endFrameLoop);
if (frame==-1)
return this;
animateMesh((f32)frame, 1.0f);
skinMesh();
if (is_hw_skinning_before)
HardwareSkinning = true;
return this;
}
@ -456,7 +462,13 @@ void CSkinnedMesh::skinMesh(f32 strength)
//-----------------
SkinnedLastFrame=true;
if (!HardwareSkinning)
m_joint_matrixes.clear();
if (HardwareSkinning)
{
for (u32 i = 0; i < RootJoints.size(); i++)
skinJoint(RootJoints[i], 0, strength);
}
else
{
//Software skin....
u32 i;
@ -493,52 +505,58 @@ void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength)
//Find this joints pull on vertices...
core::matrix4 jointVertexPull(core::matrix4::EM4CONST_NOTHING);
jointVertexPull.setbyproduct(joint->GlobalAnimatedMatrix, joint->GlobalInversedMatrix);
core::vector3df thisVertexMove, thisNormalMove;
core::array<scene::SSkinMeshBuffer*> &buffersUsed=*SkinningBuffers;
//Skin Vertices Positions and Normals...
for (u32 i=0; i<joint->Weights.size(); ++i)
if (HardwareSkinning)
{
SWeight& weight = joint->Weights[i];
m_joint_matrixes.push_back(jointVertexPull);
}
else
{
core::vector3df thisVertexMove, thisNormalMove;
// Pull this vertex...
jointVertexPull.transformVect(thisVertexMove, weight.StaticPos);
core::array<scene::SSkinMeshBuffer*> &buffersUsed=*SkinningBuffers;
if (AnimateNormals)
jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal);
// Apply animation strength
if(strength != 1.f)
//Skin Vertices Positions and Normals...
for (u32 i=0; i<joint->Weights.size(); ++i)
{
thisVertexMove = core::lerp(weight.StaticPos, thisVertexMove, strength);
if(AnimateNormals)
thisNormalMove = core::lerp(weight.StaticNormal, thisNormalMove, strength);
}
SWeight& weight = joint->Weights[i];
if (! (*(weight.Moved)) )
{
*(weight.Moved) = true;
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos = thisVertexMove * weight.strength;
// Pull this vertex...
jointVertexPull.transformVect(thisVertexMove, weight.StaticPos);
if (AnimateNormals)
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal = thisNormalMove * weight.strength;
jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal);
//*(weight._Pos) = thisVertexMove * weight.strength;
// Apply animation strength
if(strength != 1.f)
{
thisVertexMove = core::lerp(weight.StaticPos, thisVertexMove, strength);
if(AnimateNormals)
thisNormalMove = core::lerp(weight.StaticNormal, thisNormalMove, strength);
}
if (! (*(weight.Moved)) )
{
*(weight.Moved) = true;
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos = thisVertexMove * weight.strength;
if (AnimateNormals)
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal = thisNormalMove * weight.strength;
//*(weight._Pos) = thisVertexMove * weight.strength;
}
else
{
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos += thisVertexMove * weight.strength;
if (AnimateNormals)
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal += thisNormalMove * weight.strength;
//*(weight._Pos) += thisVertexMove * weight.strength;
}
buffersUsed[weight.buffer_id]->boundingBoxNeedsRecalculated();
}
else
{
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos += thisVertexMove * weight.strength;
if (AnimateNormals)
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal += thisNormalMove * weight.strength;
//*(weight._Pos) += thisVertexMove * weight.strength;
}
buffersUsed[weight.buffer_id]->boundingBoxNeedsRecalculated();
}
}
@ -1382,6 +1400,85 @@ void CSkinnedMesh::addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes,
SkinnedLastFrame=false;
}
void CSkinnedMesh::convertForSkinning()
{
if (HardwareSkinning) return;
setHardwareSkinning(true);
WeightInfluence wi;
for (u32 b = 0; b < LocalBuffers.size(); b++)
{
if (LocalBuffers[b])
LocalBuffers[b]->convertForSkinning();
wi.push_back(core::array<core::array<JointInfluence>> ());
for (u32 i = 0; i < LocalBuffers[b]->getVertexCount(); i++)
wi[b].push_back(core::array<JointInfluence>());
}
size_t idx = 0;
for (u32 i = 0; i < RootJoints.size(); i++)
computeWeightInfluence(RootJoints[i], idx, wi);
for (u32 b = 0; b < LocalBuffers.size(); b++)
{
if (LocalBuffers[b])
{
const u32 total = wi[b].size();
_IRR_DEBUG_BREAK_IF(LocalBuffers[b]->getVertexCount() != total);
for (u32 i = 0; i < total; i++)
{
core::array<JointInfluence> this_influence;
core::array<JointInfluence> reported_weight = wi[b][i];
reported_weight.sort();
float remaining_weight = 1.0f;
for (u32 j = 0; j < 4; j++)
{
JointInfluence influence;
if (reported_weight.size() > j)
influence = reported_weight[j];
else
{
influence.joint_idx = -1;
influence.weight = remaining_weight;
}
remaining_weight -= influence.weight;
this_influence.push_back(influence);
}
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx1 = this_influence[0].joint_idx;
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx2 = this_influence[1].joint_idx;
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx3 = this_influence[2].joint_idx;
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx4 = this_influence[3].joint_idx;
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight1 = this_influence[0].weight;
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight2 = this_influence[1].weight;
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight3 = this_influence[2].weight;
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight4 = this_influence[3].weight;
}
}
}
SkinnedLastFrame = false;
skinMesh();
m_joint_total_size = m_joint_matrixes.size() * sizeof(core::matrix4);
}
void CSkinnedMesh::computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi)
{
if (!joint->Weights.empty())
{
for (u32 i = 0; i < joint->Weights.size(); i++)
{
SWeight& weight = joint->Weights[i];
JointInfluence tmp;
tmp.joint_idx = index;
tmp.weight = weight.strength;
wi[weight.buffer_id][weight.vertex_id].push_back(tmp);
}
index++;
}
for (u32 j = 0; j < joint->Children.size(); j++)
computeWeightInfluence(joint->Children[j], index, wi);
}
void CSkinnedMesh::convertMeshToTangents()
{

View File

@ -14,6 +14,20 @@
#include "matrix4.h"
#include "quaternion.h"
class JointInfluence
{
public:
int joint_idx;
float weight;
bool operator < (const JointInfluence& other) const
{
return weight < other.weight;
}
};
typedef irr::core::array<irr::core::array
<irr::core::array<JointInfluence> > > WeightInfluence;
namespace irr
{
namespace scene
@ -25,7 +39,6 @@ namespace scene
class CSkinnedMesh: public ISkinnedMesh
{
public:
//! constructor
CSkinnedMesh();
@ -159,6 +172,19 @@ namespace scene
void addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes,
IAnimatedMeshSceneNode* node,
ISceneManager* smgr);
void convertForSkinning();
void computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi);
const void* getJointPointer() const { return m_joint_matrixes.const_pointer(); }
u32 getTotalJointSize() const
{
_IRR_DEBUG_BREAK_IF(m_joint_total_size == 0);
return m_joint_total_size;
}
private:
void checkForAnimation();
@ -204,7 +230,9 @@ private:
bool HasAnimation;
bool PreparedForSkinning;
bool AnimateNormals;
bool HardwareSkinning;
bool HardwareSkinning;
core::array<core::matrix4> m_joint_matrixes;
u32 m_joint_total_size;
};
} // end namespace scene

View File

@ -27,6 +27,7 @@ void InstanceFiller<InstanceDataSingleTex>::add(GLMesh* mesh,
{
fillOriginOrientationScale<InstanceDataSingleTex>(STK::tuple_get<0>(is), instance);
instance.Texture = mesh->TextureHandles[0];
instance.skinning_offset = STK::tuple_get<3>(is);
}
// ----------------------------------------------------------------------------
@ -60,6 +61,7 @@ void InstanceFiller<InstanceDataFourTex>::add(GLMesh* mesh,
instance.SecondTexture = mesh->TextureHandles[1];
instance.ThirdTexture = mesh->TextureHandles[2];
instance.FourthTexture = mesh->TextureHandles[3];
instance.skinning_offset = STK::tuple_get<3>(is);
}
// ----------------------------------------------------------------------------
@ -172,7 +174,8 @@ void SolidCommandBuffer::fill(SolidPassMeshMap *mesh_map)
std::vector<int> four_tex_material_list =
createVector<int>(Material::SHADERTYPE_DETAIL_MAP,
Material::SHADERTYPE_NORMAL_MAP);
Material::SHADERTYPE_NORMAL_MAP,
Material::SHADERTYPE_SOLID_SKINNED_MESH);
fillInstanceData<InstanceDataFourTex, SolidPassMeshMap>
(mesh_map, four_tex_material_list, InstanceTypeFourTex);

View File

@ -29,7 +29,7 @@
#include <array>
#include <unordered_map>
typedef STK::Tuple<scene::ISceneNode*, core::vector2df, core::vector2df> InstanceSettings;
typedef STK::Tuple<scene::ISceneNode*, core::vector2df, core::vector2df, uint32_t> InstanceSettings;
struct InstanceList
{

View File

@ -22,6 +22,7 @@
#include "graphics/lod_node.hpp"
#include "graphics/materials.hpp"
#include "graphics/shadow_matrices.hpp"
#include "graphics/stk_animated_mesh.hpp"
#include "graphics/stk_billboard.hpp"
#include "graphics/stk_mesh.hpp"
#include "graphics/stk_mesh_scene_node.hpp"
@ -30,6 +31,8 @@
#include "tracks/track.hpp"
#include "utils/profiler.hpp"
#include <numeric>
// ----------------------------------------------------------------------------
void DrawCalls::clearLists()
{
@ -175,6 +178,28 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
return;
}
uint32_t skinning_offset = 0;
STKAnimatedMesh* am = dynamic_cast<STKAnimatedMesh*>(Node);
if (am && am->useHardwareSkinning())
{
SkinningOffset::const_iterator it = m_skinning_offsets.find(am);
if (it != m_skinning_offsets.end())
{
skinning_offset = am->getSkinningOffset() / sizeof(core::matrix4);
}
else
{
const uint32_t cur_offset =
std::accumulate(m_skinning_offsets.begin(),
m_skinning_offsets.end(), 0, [] (const size_t previous,
const std::pair<STKAnimatedMesh*, uint32_t>& p)
{ return previous + p.second; });
am->setSkinningOffset(cur_offset);
m_skinning_offsets[am] = am->getTotalJointSize();
skinning_offset = cur_offset / sizeof(core::matrix4);
}
}
bool culled_for_cams[6] = { true, true, true, true, true, true };
culled_for_cams[0] = isCulledPrecise(cam, Node,
irr_driver->getBoundingBoxesViz());
@ -255,7 +280,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
{
m_glow_pass_mesh[mesh->mb].m_mesh = mesh;
m_glow_pass_mesh[mesh->mb].m_instance_settings
.emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f));
.emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f), skinning_offset);
}
if (Mat == Material::SHADERTYPE_SPLATTING)
{
@ -267,15 +292,12 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
}
else
{
// Only take render info into account if the node is not static (animated)
// So they can have different animation
std::pair<scene::IMeshBuffer*, RenderInfo*> mesh_render_info(mesh->mb,
dynamic_cast<STKMeshSceneNode*>(Node) == NULL ? mesh->m_render_info : NULL);
std::pair<scene::IMeshBuffer*, RenderInfo*> mesh_render_info(mesh->mb, NULL);
m_solid_pass_mesh[Mat][mesh_render_info].m_mesh = mesh;
m_solid_pass_mesh[Mat][mesh_render_info].m_instance_settings.emplace_back(Node, mesh->texture_trans,
(mesh->m_render_info && mesh->m_material ?
core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) :
core::vector2df(0.0f, 0.0f)));
core::vector2df(0.0f, 0.0f)), skinning_offset);
}
}
}
@ -351,7 +373,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
{
m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_mesh = mesh;
m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_instance_settings
.emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f));
.emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f), skinning_offset);
}
}
else
@ -419,7 +441,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
{
m_reflective_shadow_map_mesh[Mat][mesh->mb].m_mesh = mesh;
m_reflective_shadow_map_mesh[Mat][mesh->mb].m_instance_settings
.emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f));
.emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f), skinning_offset);
}
}
}
@ -683,6 +705,7 @@ void DrawCalls::drawIndirectSolidFirstPass() const
{
m_solid_cmd_buffer->bind();
m_solid_cmd_buffer->drawIndirectFirstPass<DefaultMaterial>();
m_solid_cmd_buffer->drawIndirectFirstPass<SkinnedSolid>();
m_solid_cmd_buffer->drawIndirectFirstPass<AlphaRef>();
m_solid_cmd_buffer->drawIndirectFirstPass<UnlitMat>();
m_solid_cmd_buffer->drawIndirectFirstPass<SphereMap>();
@ -718,6 +741,7 @@ void DrawCalls::drawIndirectSolidSecondPass(const std::vector<GLuint> &prefilled
{
m_solid_cmd_buffer->bind();
m_solid_cmd_buffer->drawIndirectSecondPass<DefaultMaterial>(prefilled_tex);
m_solid_cmd_buffer->drawIndirectSecondPass<SkinnedSolid>(prefilled_tex);
m_solid_cmd_buffer->drawIndirectSecondPass<AlphaRef>(prefilled_tex);
m_solid_cmd_buffer->drawIndirectSecondPass<UnlitMat>(prefilled_tex);
m_solid_cmd_buffer->drawIndirectSecondPass<SphereMap>(prefilled_tex);

View File

@ -24,8 +24,11 @@
class ParticleSystemProxy;
class ShadowMatrices;
class STKAnimatedMesh;
class STKBillboard;
typedef std::unordered_map<STKAnimatedMesh*, uint32_t> SkinningOffset;
class DrawCalls
{
private:
@ -36,6 +39,7 @@ private:
std::vector<irr::scene::ISceneNode *> m_immediate_draw_list;
std::vector<STKBillboard *> m_billboard_list;
std::vector<ParticleSystemProxy *> m_particles_list;
SkinningOffset m_skinning_offsets;
std::vector<float> m_bounding_boxes;
@ -105,6 +109,7 @@ public:
void drawIndirectGlow() const;
void multidrawGlow() const;
void renderBoundingBoxes();
void resetSkinningOffsets() { m_skinning_offsets.clear(); }
};
#endif //HEADER_DRAW_CALLS_HPP

View File

@ -140,6 +140,22 @@ public:
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)48);
break;
case video::EVT_SKINNED_MESH:
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
glEnableVertexAttribArray(3);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)44);
glEnableVertexAttribArray(5);
glVertexAttribIPointer(5, 4, GL_INT, getVertexPitchFromType(tp), (GLvoid*)60);
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)76);
break;
}
}
};

View File

@ -48,6 +48,7 @@ public:
enum ShaderType
{
SHADERTYPE_SOLID = 0,
SHADERTYPE_SOLID_SKINNED_MESH,
SHADERTYPE_ALPHA_TEST,
SHADERTYPE_ALPHA_BLEND,
SHADERTYPE_ADDITIVE,

View File

@ -24,6 +24,14 @@ const STK::Tuple<size_t, size_t, size_t> DefaultMaterial::SecondPassTextures
const STK::Tuple<> DefaultMaterial::ShadowTextures;
const STK::Tuple<size_t> DefaultMaterial::RSMTextures = STK::Tuple<size_t>(0);
// ----------------------------------------------------------------------------
const STK::Tuple<size_t> SkinnedSolid::FirstPassTextures
= STK::Tuple<size_t>(1);
const STK::Tuple<size_t, size_t, size_t> SkinnedSolid::SecondPassTextures
= STK::Tuple<size_t, size_t, size_t>(0, 1, 2);
const STK::Tuple<> SkinnedSolid::ShadowTextures;
const STK::Tuple<size_t> SkinnedSolid::RSMTextures = STK::Tuple<size_t>(0);
// ----------------------------------------------------------------------------
const STK::Tuple<size_t, size_t> AlphaRef::FirstPassTextures
= STK::Tuple<size_t, size_t>(0, 1);

View File

@ -616,8 +616,61 @@ public:
} // InstancedDetailedObjectPass2Shader
}; // InstancedDetailedObjectPass2Shader
// ============================================================================
class InstancedSkinnedMeshPass1Shader : public TextureShader<InstancedSkinnedMeshPass1Shader, 1>
{
public:
InstancedSkinnedMeshPass1Shader()
{
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert",
GL_FRAGMENT_SHADER, "instanced_object_pass1.frag");
assignUniforms();
assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // InstancedSkinnedMeshPass1Shader
}; // InstancedSkinnedMeshPass1Shader
// ============================================================================
class InstancedSkinnedMeshPass2Shader : public TextureShader<InstancedSkinnedMeshPass2Shader, 6>
{
public:
InstancedSkinnedMeshPass2Shader()
{
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert",
GL_FRAGMENT_SHADER, "instanced_object_pass2.frag");
assignUniforms();
assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED,
1, "SpecularMap", ST_NEAREST_FILTERED,
2, "SSAO", ST_BILINEAR_FILTERED,
3, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED,
4, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED,
5, "colorization_mask", ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // InstancedSkinnedMeshPass2Shader
}; // InstancedSkinnedMeshPass2Shader
// ============================================================================
struct SkinnedSolid
{
typedef InstancedSkinnedMeshPass1Shader InstancedFirstPassShader;
typedef InstancedSkinnedMeshPass2Shader InstancedSecondPassShader;
//typedef InstancedShadowShader InstancedShadowPassShader;
//typedef CInstancedRSMShader InstancedRSMShader;
//typedef Shaders::ObjectPass1Shader FirstPassShader;
//typedef Shaders::ObjectPass2Shader SecondPassShader;
//typedef ShadowShader ShadowPassShader;
//typedef CRSMShader RSMShader;
typedef ListSkinnedSolid List;
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_SKINNED_MESH;
static const enum Material::ShaderType MaterialType
= Material::SHADERTYPE_SOLID_SKINNED_MESH;
static const enum InstanceType Instance = InstanceTypeFourTex;
static const STK::Tuple<size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t, size_t> SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
}; // struct DefaultMaterial
// ----------------------------------------------------------------------------
struct DefaultMaterial
{
typedef InstancedObjectPass1Shader InstancedFirstPassShader;

View File

@ -476,7 +476,7 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh,
void MeshTools::createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh,
bool(*predicate)(scene::IMeshBuffer*))
{
{return;
core::array<scene::SSkinMeshBuffer*>& all_mb = mesh->getMeshBuffers();
const int all_mb_size = all_mb.size();
for (int i = 0; i < all_mb_size; i++)

View File

@ -150,6 +150,7 @@ private:
{
bindPoint("MatrixData", 0);
bindPoint("LightingData", 1);
bindPoint("SkinningData", 2);
} // assignUniformsImpl
// ------------------------------------------------------------------------

View File

@ -270,6 +270,7 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode,
{
glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedGPUObjects::getViewProjectionMatricesUBO());
glBindBufferBase(GL_UNIFORM_BUFFER, 1, SharedGPUObjects::getLightingDataUBO());
glBindBufferBase(GL_UNIFORM_BUFFER, 2, SharedGPUObjects::getSkinningUBO());
}
irr_driver->getSceneManager()->setActiveCamera(camnode);
@ -697,6 +698,7 @@ void ShaderBasedRenderer::onUnloadWorld()
delete m_rtts;
m_rtts = NULL;
removeSkyBox();
m_draw_calls.resetSkinningOffsets();
}
// ----------------------------------------------------------------------------

View File

@ -29,6 +29,7 @@ GLuint SharedGPUObjects::m_full_screen_quad_vao;
GLuint SharedGPUObjects::m_ui_vao;
GLuint SharedGPUObjects::m_quad_buffer;
GLuint SharedGPUObjects::m_quad_vbo;
GLuint SharedGPUObjects::m_skinning_ubo;
bool SharedGPUObjects::m_has_been_initialised = false;
/** Initialises m_full_screen_quad_vbo.
@ -166,6 +167,17 @@ void SharedGPUObjects::initLightingDataUBO()
glBindBuffer(GL_UNIFORM_BUFFER, 0);
} // initLightingDataUBO
// ----------------------------------------------------------------------------
void SharedGPUObjects::initSkinningUBO()
{
assert(CVS->isARBUniformBufferObjectUsable());
glGenBuffers(1, &m_skinning_ubo);
glBindBuffer(GL_UNIFORM_BUFFER, m_skinning_ubo);
glBufferData(GL_UNIFORM_BUFFER, 1000 * 16 * sizeof(float), 0,
GL_STREAM_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
} // initSkinningUBO
// ----------------------------------------------------------------------------
void SharedGPUObjects::initParticleQuadVBO()
{
@ -198,7 +210,8 @@ void SharedGPUObjects::init()
if(CVS->isARBUniformBufferObjectUsable())
{
initShadowVPMUBO();
initLightingDataUBO();
initLightingDataUBO();
initSkinningUBO();
}
m_has_been_initialised = true;

View File

@ -37,6 +37,7 @@ private:
static GLuint m_ui_vao;
static GLuint m_quad_buffer;
static GLuint m_quad_vbo;
static GLuint m_skinning_ubo;
static void initQuadVBO();
static void initQuadBuffer();
@ -46,6 +47,7 @@ private:
static void initShadowVPMUBO();
static void initLightingDataUBO();
static void initParticleQuadVBO();
static void initSkinningUBO();
public:
static void init();
@ -116,6 +118,12 @@ public:
assert(m_has_been_initialised);
return m_quad_vbo;
} // getQuadVBO
// ------------------------------------------------------------------------
static GLuint getSkinningUBO()
{
assert(m_has_been_initialised);
return m_skinning_ubo;
} // getSkinningUBO
}; // class SharedGPUObjecctS

View File

@ -20,12 +20,13 @@
#include "graphics/central_settings.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/render_info.hpp"
#include "graphics/shared_gpu_objects.hpp"
#include "graphics/stk_mesh.hpp"
#include "graphics/vao_manager.hpp"
#include <IMaterialRenderer.h>
#include <ISceneManager.h>
#include <ISkinnedMesh.h>
#include "../../lib/irrlicht/source/Irrlicht/CSkinnedMesh.h"
using namespace irr;
@ -34,7 +35,7 @@ irr::scene::ISceneManager* mgr, s32 id, const std::string& debug_name,
const core::vector3df& position,
const core::vector3df& rotation,
const core::vector3df& scale, RenderInfo* render_info, bool all_parts_colorized) :
CAnimatedMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
CAnimatedMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale), m_skinned_mesh(NULL)
{
isGLInitialized = false;
isMaterialInitialized = false;
@ -43,6 +44,10 @@ const core::vector3df& scale, RenderInfo* render_info, bool all_parts_colorized)
#ifdef DEBUG
m_debug_name = debug_name;
#endif
m_skinning_offset = -1;
m_skinned_mesh = dynamic_cast<scene::CSkinnedMesh*>(Mesh);
if (m_skinned_mesh)
m_skinned_mesh->convertForSkinning();
}
STKAnimatedMesh::~STKAnimatedMesh()
@ -108,6 +113,16 @@ void STKAnimatedMesh::updateNoGL()
for (u32 i = 0; i < mb_count; ++i)
{
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
if (!mb)
continue;
scene::SSkinMeshBuffer* ssmb = NULL;
if (m_skinned_mesh)
{
ssmb = dynamic_cast<scene::SSkinMeshBuffer*>(mb);
ssmb->VertexType = video::EVT_SKINNED_MESH;
}
bool affected = false;
RenderInfo* cur_ri = m_mesh_render_info;
if (!m_all_parts_colorized && mb && cur_ri)
@ -142,6 +157,8 @@ void STKAnimatedMesh::updateNoGL()
GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name,
affected || m_all_parts_colorized || (cur_ri
&& cur_ri->isTransparent()) ? cur_ri : default_ri));
if (m_skinned_mesh) ssmb->VertexType = video::EVT_STANDARD;
}
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
@ -162,7 +179,7 @@ void STKAnimatedMesh::updateNoGL()
GLMesh &mesh = GLmeshes[i];
Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb);
if (rnd->isTransparent())
/*if (rnd->isTransparent())
{
TransparentMaterial TranspMat = getTransparentMaterialFromType(type, MaterialTypeParam, material);
TransparentMesh[TranspMat].push_back(&mesh);
@ -174,10 +191,10 @@ void STKAnimatedMesh::updateNoGL()
else
TransparentMesh[TM_TRANSLUCENT_STD].push_back(&mesh);
}
else
else*/
{
Material::ShaderType MatType = getMeshMaterialFromType(type, mb->getVertexType(), material, NULL);
MeshSolidMaterial[MatType].push_back(&mesh);
MeshSolidMaterial[m_skinned_mesh ? Material::SHADERTYPE_SOLID_SKINNED_MESH : MatType].push_back(&mesh);
}
}
isMaterialInitialized = true;
@ -213,6 +230,13 @@ void STKAnimatedMesh::updateGL()
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
if (!mb)
continue;
scene::SSkinMeshBuffer* ssmb = NULL;
if (m_skinned_mesh)
{
ssmb = dynamic_cast<scene::SSkinMeshBuffer*>(mb);
ssmb->VertexType = video::EVT_SKINNED_MESH;
}
video::IVideoDriver* driver = SceneManager->getVideoDriver();
video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType;
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type);
@ -233,7 +257,7 @@ void STKAnimatedMesh::updateGL()
if (CVS->isARBBaseInstanceUsable())
{
std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb, GLmeshes[i].m_render_info);
std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb,NULL /*GLmeshes[i].m_render_info*/);
mesh.vaoBaseVertex = p.first;
mesh.vaoOffset = p.second;
}
@ -243,10 +267,20 @@ void STKAnimatedMesh::updateGL()
mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType());
glBindVertexArray(0);
}
if (m_skinned_mesh) ssmb->VertexType = video::EVT_STANDARD;
}
isGLInitialized = true;
}
if (m_skinned_mesh)
{
assert(m_skinning_offset != -1);
glBindBuffer(GL_UNIFORM_BUFFER, SharedGPUObjects::getSkinningUBO());
glBufferSubData(GL_UNIFORM_BUFFER, m_skinning_offset,
m_skinned_mesh->getTotalJointSize(), m_skinned_mesh->getJointPointer());
return;
}
for (u32 i = 0; i<m->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* mb = m->getMeshBuffer(i);
@ -289,3 +323,8 @@ void STKAnimatedMesh::render()
updateNoGL();
updateGL();
}
int STKAnimatedMesh::getTotalJointSize() const
{
return m_skinned_mesh->getTotalJointSize();
}

View File

@ -26,6 +26,10 @@
#include <irrTypes.h>
class RenderInfo;
namespace irr
{
namespace scene { class CSkinnedMesh; }
}
class STKAnimatedMesh : public irr::scene::CAnimatedMeshSceneNode, public STKMeshCommon
{
@ -50,9 +54,15 @@ public:
virtual void render();
virtual void setMesh(irr::scene::IAnimatedMesh* mesh);
virtual bool glow() const { return false; }
int getTotalJointSize() const;
int getSkinningOffset() const { return m_skinning_offset; }
void setSkinningOffset(int offset) { m_skinning_offset = offset; }
bool useHardwareSkinning() const { return m_skinned_mesh!= NULL; }
private:
RenderInfo* m_mesh_render_info;
bool m_all_parts_colorized;
irr::scene::CSkinnedMesh* m_skinned_mesh;
int m_skinning_offset;
};
#endif // STKANIMATEDMESH_HPP

View File

@ -155,6 +155,22 @@ GLuint createVAO(GLuint vbo, GLuint idx, video::E_VERTEX_TYPE type)
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE,
getVertexPitchFromType(type), (GLvoid*)48);
break;
case video::EVT_SKINNED_MESH:
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)12);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(type), (GLvoid*)24);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)28);
glEnableVertexAttribArray(3);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)44);
glEnableVertexAttribArray(5);
glVertexAttribIPointer(5, 4, GL_INT, getVertexPitchFromType(type), (GLvoid*)60);
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)76);
break;
default:
assert(0 && "Wrong vertex type");
}
@ -346,8 +362,8 @@ static void setTexture(GLMesh &mesh, unsigned i, bool is_srgb,
{
if (!mesh.textures[i])
{
Log::error("STKMesh", "Missing texture %d for material %s", i,
mat_name.c_str());
//Log::error("STKMesh", "Missing texture %d for material %s", i,
// mat_name.c_str());
// use unicolor texture to replace missing texture
mesh.textures[i] =
getUnicolorTexture(video::SColor(255, 127, 127, 127));
@ -413,6 +429,7 @@ void initTextures(GLMesh &mesh, Material::ShaderType mat)
break;
case Material::SHADERTYPE_DETAIL_MAP:
case Material::SHADERTYPE_NORMAL_MAP:
case Material::SHADERTYPE_SOLID_SKINNED_MESH:
setTexture(mesh, 0, true, getShaderTypeName(mat));
setTexture(mesh, 1, false, getShaderTypeName(mat));
setTexture(mesh, 2, false, getShaderTypeName(mat));

View File

@ -116,6 +116,12 @@ class ListMatDefault : public MeshList<ListMatDefault, GLMesh *, core::matrix4,
core::vector2df>
{};
// ----------------------------------------------------------------------------
class ListSkinnedSolid : public MeshList<ListSkinnedSolid, GLMesh *, core::matrix4,
core::matrix4, core::vector2df,
core::vector2df>
{};
// ----------------------------------------------------------------------------
class ListMatAlphaRef : public MeshList<ListMatAlphaRef, GLMesh *, core::matrix4,
core::matrix4, core::vector2df,

View File

@ -161,6 +161,9 @@ void VAOInstanceUtil<InstanceDataSingleTex>::SetVertexAttrib()
glEnableVertexAttribArray(11);
glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceDataSingleTex), (GLvoid*)(9 * sizeof(float)));
glVertexAttribDivisorARB(11, 1);
glEnableVertexAttribArray(15);
glVertexAttribIPointer(15, 1, GL_UNSIGNED_INT, sizeof(InstanceDataSingleTex), (GLvoid*)(11 * sizeof(float)));
glVertexAttribDivisorARB(15, 1);
}
template<>
@ -200,6 +203,9 @@ void VAOInstanceUtil<InstanceDataFourTex>::SetVertexAttrib()
glEnableVertexAttribArray(14);
glVertexAttribIPointer(14, 2, GL_UNSIGNED_INT, sizeof(InstanceDataFourTex), (GLvoid*)(13 * sizeof(float) + 6 * sizeof(unsigned)));
glVertexAttribDivisorARB(14, 1);
glEnableVertexAttribArray(15);
glVertexAttribIPointer(15, 1, GL_UNSIGNED_INT, sizeof(InstanceDataFourTex), (GLvoid*)(13 * sizeof(float) + 8 * sizeof(unsigned)));
glVertexAttribDivisorARB(15, 1);
}
template<>
@ -216,7 +222,7 @@ void VAOManager::regenerateInstancedVAO()
{
cleanInstanceVAOs();
enum video::E_VERTEX_TYPE IrrVT[] = { video::EVT_STANDARD, video::EVT_2TCOORDS, video::EVT_TANGENTS };
enum video::E_VERTEX_TYPE IrrVT[] = { video::EVT_STANDARD, video::EVT_2TCOORDS, video::EVT_TANGENTS, video::EVT_SKINNED_MESH };
for (unsigned i = 0; i < VTXTYPE_COUNT; i++)
{
video::E_VERTEX_TYPE tp = IrrVT[i];
@ -264,6 +270,8 @@ size_t VAOManager::getVertexPitch(enum VTXTYPE tp) const
return getVertexPitchFromType(video::EVT_2TCOORDS);
case VTXTYPE_TANGENT:
return getVertexPitchFromType(video::EVT_TANGENTS);
case VTXTYPE_SKINNED_MESH:
return getVertexPitchFromType(video::EVT_SKINNED_MESH);
default:
assert(0 && "Wrong vtxtype");
return -1;
@ -282,6 +290,8 @@ VAOManager::VTXTYPE VAOManager::getVTXTYPE(video::E_VERTEX_TYPE type)
return VTXTYPE_TCOORD;
case video::EVT_TANGENTS:
return VTXTYPE_TANGENT;
case video::EVT_SKINNED_MESH:
return VTXTYPE_SKINNED_MESH;
}
};
@ -296,6 +306,8 @@ irr::video::E_VERTEX_TYPE VAOManager::getVertexType(enum VTXTYPE tp)
return video::EVT_2TCOORDS;
case VTXTYPE_TANGENT:
return video::EVT_TANGENTS;
case VTXTYPE_SKINNED_MESH:
return video::EVT_SKINNED_MESH;
}
}

View File

@ -62,6 +62,7 @@ struct InstanceDataSingleTex
float Z;
} Scale;
uint64_t Texture;
uint32_t skinning_offset;
#ifdef WIN32
};
#else
@ -135,6 +136,7 @@ struct InstanceDataFourTex
uint64_t SecondTexture;
uint64_t ThirdTexture;
uint64_t FourthTexture;
uint32_t skinning_offset;
#ifdef WIN32
};
#else
@ -197,7 +199,7 @@ struct MeshRenderInfoEquals : std::binary_function
class VAOManager : public Singleton<VAOManager>
{
enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT };
enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_SKINNED_MESH, VTXTYPE_COUNT };
GLuint vbo[VTXTYPE_COUNT], ibo[VTXTYPE_COUNT], vao[VTXTYPE_COUNT];
GLuint instance_vbo[InstanceTypeCount];
void *Ptr[InstanceTypeCount];