First version of hardware skinning
Todo: shadow, non-instanced shaders, culling, changeable offset...
This commit is contained in:
parent
23883b83c1
commit
57d9e83ed4
@ -63,5 +63,11 @@ layout (std140) uniform LightingData
|
||||
float rL21;
|
||||
float rL22;
|
||||
};
|
||||
|
||||
layout (std140) uniform SkinningData
|
||||
{
|
||||
mat4 joint_matrices[1000];
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // HEADER_TXT
|
||||
|
120
data/shaders/instanced_skinning.vert
Normal file
120
data/shaders/instanced_skinning.vert
Normal 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
|
||||
}
|
@ -116,6 +116,8 @@ namespace scene
|
||||
NewVertices=new CSpecificVertexList<video::S3DVertexTangents>;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (Vertices)
|
||||
{
|
||||
|
@ -371,6 +371,8 @@ protected:
|
||||
func(verts[i]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (boundingBoxUpdate)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -48,6 +48,7 @@ public:
|
||||
enum ShaderType
|
||||
{
|
||||
SHADERTYPE_SOLID = 0,
|
||||
SHADERTYPE_SOLID_SKINNED_MESH,
|
||||
SHADERTYPE_ALPHA_TEST,
|
||||
SHADERTYPE_ALPHA_BLEND,
|
||||
SHADERTYPE_ADDITIVE,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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++)
|
||||
|
@ -150,6 +150,7 @@ private:
|
||||
{
|
||||
bindPoint("MatrixData", 0);
|
||||
bindPoint("LightingData", 1);
|
||||
bindPoint("SkinningData", 2);
|
||||
} // assignUniformsImpl
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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];
|
||||
|
Loading…
x
Reference in New Issue
Block a user