Add unlit and normal map skinned mesh shader

Also fix normal map with skinned mesh, now vertices and joints
will be recalculated for tangents mesh
This commit is contained in:
Benau 2016-12-14 16:28:37 +08:00
parent abe4ae2d6a
commit 85bd8c3146
15 changed files with 296 additions and 125 deletions

@ -39,25 +39,32 @@ void main(void)
mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin, Orientation, Scale) * InverseViewMatrix);
vec4 idle_position = vec4(Position, 1.);
vec4 idle_normal = vec4(Normal, 0.);
vec4 idle_tangent = vec4(Data1.z, Data1.w, Data2.x, 0.);
vec4 idle_bitangent = vec4(Data2.y, Data2.z, Data2.w, 0.);
vec4 skinned_position = vec4(0.);
vec4 skinned_normal = vec4(0.);
vec4 skinned_tangent = vec4(0.);
vec4 skinned_bitangent = vec4(0.);
// Note : For normal we assume no scale factor in bone (otherwise we'll have to compute inversematrix for each bones...)
for (int i = 0; i < 4; i++)
{
vec4 single_bone_influenced_position = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_position;
single_bone_influenced_position /= single_bone_influenced_position.w;
vec4 single_bone_influenced_normal = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_normal;
vec4 single_bone_influenced_tangent = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_tangent;
vec4 single_bone_influenced_bitangent = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_bitangent;
skinned_position += Weight[i] * single_bone_influenced_position;
skinned_normal += Weight[i] * single_bone_influenced_normal;
skinned_tangent += Weight[i] * single_bone_influenced_tangent;
skinned_bitangent += Weight[i] * single_bone_influenced_bitangent;
}
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;
tangent = (ViewMatrix * ModelMatrix * skinned_tangent).xyz;
bitangent = (ViewMatrix * ModelMatrix * skinned_bitangent).xyz;
uv = vec2(Data1.x + misc_data.x, Data1.y + misc_data.y);
color = Color.zyxw;
color_change = misc_data.zw;

@ -41,23 +41,28 @@ void main(void)
vec4 idle_normal = vec4(Normal, 0.);
vec4 skinned_position = vec4(0.);
vec4 skinned_normal = vec4(0.);
vec4 skinned_tangent = vec4(0.);
vec4 skinned_bitangent = vec4(0.);
// Note : For normal we assume no scale factor in bone (otherwise we'll have to compute inversematrix for each bones...)
for (int i = 0; i < 4; i++)
{
vec4 single_bone_influenced_position = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_position;
single_bone_influenced_position /= single_bone_influenced_position.w;
vec4 single_bone_influenced_normal = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_normal;
vec4 single_bone_influenced_tangent = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_tangent;
vec4 single_bone_influenced_bitangent = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_bitangent;
skinned_position += Weight[i] * single_bone_influenced_position;
skinned_normal += Weight[i] * single_bone_influenced_normal;
skinned_tangent += Weight[i] * single_bone_influenced_tangent;
skinned_bitangent += Weight[i] * single_bone_influenced_bitangent;
}
gl_Position = ProjectionMatrix * ViewMatrix * 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;
tangent = (ViewMatrix * ModelMatrix * skinned_tangent).xyz;
bitangent = (ViewMatrix * ModelMatrix * skinned_bitangent).xyz;
uv = vec2(Data1.x + texture_trans.x, Data1.y + texture_trans.y);
color = Color.zyxw;
}

@ -73,7 +73,7 @@ namespace scene
//! converts the vertex type of all meshbuffers to tangents.
/** E.g. used for bump mapping. */
virtual void convertMeshToTangents() = 0;
virtual void convertMeshToTangents(bool(*predicate)(IMeshBuffer*)) = 0;
//! Allows to enable hardware skinning.
/* This feature is not implementated in Irrlicht yet */

@ -646,6 +646,8 @@ SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const
buffer->drop();
}
break;
default:
break;
}// end switch
}// end for all mesh buffers
@ -751,6 +753,8 @@ IMesh* CMeshManipulator::createMeshUniquePrimitives(IMesh* mesh) const
buffer->drop();
}
break;
default:
break;
}// end switch
}// end for all mesh buffers
@ -987,6 +991,8 @@ IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool recalculateNor
vNew = v[idx[i]];
}
break;
default:
break;
}
core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew);
if (n)
@ -1075,6 +1081,8 @@ IMesh* CMeshManipulator::createMeshWith2TCoords(IMesh* mesh) const
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords, v[idx[i]].TCoords);
}
break;
default:
break;
}
core::map<video::S3DVertex2TCoords, int>::Node* n = vertMap.find(vNew);
if (n)
@ -1158,6 +1166,8 @@ IMesh* CMeshManipulator::createMeshWith1TCoords(IMesh* mesh) const
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
break;
default:
break;
}
core::map<video::S3DVertex, int>::Node* n = vertMap.find(vNew);
if (n)
@ -1805,6 +1815,8 @@ IMesh* CMeshManipulator::createForsythOptimizedMesh(const IMesh *mesh) const
buf->drop();
}
break;
default:
break;
}
delete [] vc;

@ -276,6 +276,8 @@ void COctreeSceneNode::render()
}
}
break;
default:
break;
}
}
@ -371,6 +373,8 @@ bool COctreeSceneNode::createTree(IMesh* mesh)
for (v=0; v<b->getVertexCount(); ++v)
nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]);
break;
default:
break;
}
polyCount += b->getIndexCount();
@ -424,6 +428,8 @@ bool COctreeSceneNode::createTree(IMesh* mesh)
for (v=0; v<b->getVertexCount(); ++v)
nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]);
break;
default:
break;
}
polyCount += b->getIndexCount();
@ -474,6 +480,8 @@ bool COctreeSceneNode::createTree(IMesh* mesh)
for (v=0; v<b->getVertexCount(); ++v)
nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]);
break;
default:
break;
}
polyCount += b->getIndexCount();
@ -487,6 +495,8 @@ bool COctreeSceneNode::createTree(IMesh* mesh)
nodeCount = TangentsOctree->getNodeCount();
}
break;
default:
break;
}
}

@ -1581,6 +1581,8 @@ void COpenGLDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCoun
case EVT_TANGENTS:
glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Color);
break;
default:
break;
}
}
else
@ -1676,6 +1678,8 @@ void COpenGLDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCoun
glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(48));
}
break;
default:
break;
}
renderArray(indexList, primitiveCount, pType, iType);
@ -1740,6 +1744,8 @@ void COpenGLDriver::getColorBuffer(const void* vertices, u32 vertexCount, E_VERT
}
}
break;
default:
break;
}
}
@ -1913,6 +1919,8 @@ void COpenGLDriver::draw2DVertexPrimitiveList(const void* vertices, u32 vertexCo
case EVT_TANGENTS:
glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Color);
break;
default:
break;
}
}
else
@ -1984,6 +1992,8 @@ void COpenGLDriver::draw2DVertexPrimitiveList(const void* vertices, u32 vertexCo
glVertexPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(0));
}
break;
default:
break;
}

@ -9,6 +9,7 @@
#include "CBoneSceneNode.h"
#include "IAnimatedMeshSceneNode.h"
#include "os.h"
#include "irrMap.h"
namespace irr
{
@ -751,28 +752,28 @@ bool CSkinnedMesh::setHardwareSkinning(bool on)
if (HardwareSkinning!=on)
{
if (on)
{
//set mesh to static pose...
for (u32 i=0; i<AllJoints.size(); ++i)
{
SJoint *joint=AllJoints[i];
for (u32 j=0; j<joint->Weights.size(); ++j)
{
const u16 buffer_id=joint->Weights[j].buffer_id;
const u32 vertex_id=joint->Weights[j].vertex_id;
LocalBuffers[buffer_id]->getVertex(vertex_id)->Pos = joint->Weights[j].StaticPos;
LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal = joint->Weights[j].StaticNormal;
LocalBuffers[buffer_id]->boundingBoxNeedsRecalculated();
}
}
}
toStaticPose();
HardwareSkinning=on;
}
return HardwareSkinning;
}
void CSkinnedMesh::toStaticPose()
{
for (u32 i=0; i<AllJoints.size(); ++i)
{
SJoint *joint=AllJoints[i];
for (u32 j=0; j<joint->Weights.size(); ++j)
{
const u16 buffer_id=joint->Weights[j].buffer_id;
const u32 vertex_id=joint->Weights[j].vertex_id;
LocalBuffers[buffer_id]->getVertex(vertex_id)->Pos = joint->Weights[j].StaticPos;
LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal = joint->Weights[j].StaticNormal;
LocalBuffers[buffer_id]->boundingBoxNeedsRecalculated();
}
}
}
void CSkinnedMesh::calculateGlobalMatrices(SJoint *joint,SJoint *parentJoint)
{
@ -1491,25 +1492,51 @@ void CSkinnedMesh::computeWeightInfluence(SJoint *joint, size_t &index, WeightIn
computeWeightInfluence(joint->Children[j], index, wi);
}
void CSkinnedMesh::convertMeshToTangents()
void CSkinnedMesh::convertMeshToTangents(bool(*predicate)(IMeshBuffer*))
{
// now calculate tangents
for (u32 b=0; b < LocalBuffers.size(); ++b)
bool recalculate_animation = false;
toStaticPose();
for (u32 b = 0; b < LocalBuffers.size(); b++)
{
if (LocalBuffers[b])
bool recalculate_joints = false;
core::map<u32, u32> vert_loc_map;
SSkinMeshBuffer* ssmb = LocalBuffers[b];
if (ssmb)
{
LocalBuffers[b]->convertToTangents();
if (!predicate(ssmb)) continue;
const s32 idxCnt = LocalBuffers[b]->getIndexCount();
u16* idx = LocalBuffers[b]->getIndices();
video::S3DVertexTangents* v =
(video::S3DVertexTangents*)LocalBuffers[b]->getVertices();
for (s32 i=0; i<idxCnt; i+=3)
recalculate_joints = true;
recalculate_animation = true;
core::map<video::S3DVertexTangents, u32> vert_map;
core::array<u16> tmp_indices;
for (u32 i = 0; i < ssmb->Indices.size(); i++)
{
u32 vert_location = 0;
const u32 cur_ver_loc = ssmb->Indices[i];
const video::S3DVertex& v_old = ssmb->Vertices_Standard[cur_ver_loc];
video::S3DVertexTangents v(v_old.Pos, v_old.Normal, v_old.Color, v_old.TCoords);
core::map<video::S3DVertexTangents, u32>::Node *n = vert_map.find(v);
if (n)
{
vert_location = n->getValue();
}
else
{
vert_location = ssmb->Vertices_Tangents.size();
ssmb->Vertices_Tangents.push_back(v);
vert_map.insert(v, vert_location);
}
vert_loc_map[cur_ver_loc] = vert_location;
tmp_indices.push_back(vert_location);
}
const s32 index_count = tmp_indices.size();
u16* idx = tmp_indices.pointer();
video::S3DVertexTangents* v = ssmb->Vertices_Tangents.pointer();
core::vector3df local_normal;
for (s32 i = 0; i < index_count; i += 3)
{
calculateTangents(
v[idx[i+0]].Normal,
local_normal,
v[idx[i+0]].Tangent,
v[idx[i+0]].Binormal,
v[idx[i+0]].Pos,
@ -1520,7 +1547,7 @@ void CSkinnedMesh::convertMeshToTangents()
v[idx[i+2]].TCoords);
calculateTangents(
v[idx[i+1]].Normal,
local_normal,
v[idx[i+1]].Tangent,
v[idx[i+1]].Binormal,
v[idx[i+1]].Pos,
@ -1531,7 +1558,7 @@ void CSkinnedMesh::convertMeshToTangents()
v[idx[i+0]].TCoords);
calculateTangents(
v[idx[i+2]].Normal,
local_normal,
v[idx[i+2]].Tangent,
v[idx[i+2]].Binormal,
v[idx[i+2]].Pos,
@ -1541,11 +1568,38 @@ void CSkinnedMesh::convertMeshToTangents()
v[idx[i+0]].TCoords,
v[idx[i+1]].TCoords);
}
ssmb->Indices = tmp_indices;
ssmb->Vertices_Standard.clear();
ssmb->VertexType = video::EVT_TANGENTS;
}
if (recalculate_joints)
{
Vertices_Moved[b].set_used(ssmb->getVertexCount());
for (u32 i = 0; i < AllJoints.size(); i++)
{
SJoint *joint = AllJoints[i];
for (u32 j = 0; j <joint->Weights.size(); j++)
{
if (joint->Weights[j].buffer_id == b)
{
core::map<u32, u32>::Node *n =
vert_loc_map.find(joint->Weights[j].vertex_id);
if (n)
{
joint->Weights[j].vertex_id = n->getValue();
}
}
}
}
}
}
if (recalculate_animation)
{
PreparedForSkinning = false;
checkForAnimation();
}
}
void CSkinnedMesh::calculateTangents(
core::vector3df& normal,
core::vector3df& tangent,

@ -114,7 +114,7 @@ namespace scene
virtual void setInterpolationMode(E_INTERPOLATION_MODE mode);
//! Convertes the mesh to contain tangent information
virtual void convertMeshToTangents();
virtual void convertMeshToTangents(bool(*predicate)(IMeshBuffer*));
//! Does the mesh have no animation
virtual bool isStatic();
@ -176,6 +176,8 @@ namespace scene
u32 getTotalJoints() const { return m_total_joints; }
private:
void toStaticPose();
void checkForAnimation();
void normalizeWeights();

@ -172,14 +172,16 @@ void SolidCommandBuffer::fill(SolidPassMeshMap *mesh_map)
Material::SHADERTYPE_SPHERE_MAP,
Material::SHADERTYPE_VEGETATION,
Material::SHADERTYPE_SOLID_SKINNED_MESH,
Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH);
Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH,
Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH);
fillInstanceData<InstanceDataThreeTex, SolidPassMeshMap>
(mesh_map, three_tex_material_list, InstanceTypeThreeTex);
std::vector<int> four_tex_material_list =
createVector<int>(Material::SHADERTYPE_DETAIL_MAP,
Material::SHADERTYPE_NORMAL_MAP);
Material::SHADERTYPE_NORMAL_MAP,
Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH);
fillInstanceData<InstanceDataFourTex, SolidPassMeshMap>
(mesh_map, four_tex_material_list, InstanceTypeFourTex);
@ -204,10 +206,6 @@ void ShadowCommandBuffer::fill(OtherMeshMap *mesh_map)
std::vector<int> shadow_tex_material_list;
for(int cascade=0; cascade<4; cascade++)
{
shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT
+ Material::SHADERTYPE_SOLID_SKINNED_MESH);
shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT
+ Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH);
shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT
+ Material::SHADERTYPE_SOLID);
shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT
@ -224,6 +222,14 @@ void ShadowCommandBuffer::fill(OtherMeshMap *mesh_map)
+ Material::SHADERTYPE_VEGETATION);
shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT
+ Material::SHADERTYPE_SPLATTING);
shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT
+ Material::SHADERTYPE_SOLID_SKINNED_MESH);
shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT
+ Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH);
shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT
+ Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH);
shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT
+ Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH);
}
fillInstanceData<InstanceDataSingleTex, OtherMeshMap>

@ -712,15 +712,20 @@ void DrawCalls::renderParticlesList() const
void DrawCalls::drawIndirectSolidFirstPass() const
{
m_solid_cmd_buffer->bind();
m_solid_cmd_buffer->drawIndirectFirstPass<SkinnedSolid>();
m_solid_cmd_buffer->drawIndirectFirstPass<SkinnedAlphaRef>();
m_solid_cmd_buffer->drawIndirectFirstPass<DefaultMaterial>();
m_solid_cmd_buffer->drawIndirectFirstPass<AlphaRef>();
m_solid_cmd_buffer->drawIndirectFirstPass<UnlitMat>();
m_solid_cmd_buffer->drawIndirectFirstPass<SphereMap>();
m_solid_cmd_buffer->drawIndirectFirstPass<GrassMat>(m_wind_dir);
m_solid_cmd_buffer->drawIndirectFirstPass<DetailMat>();
m_solid_cmd_buffer->drawIndirectFirstPass<NormalMat>();
m_solid_cmd_buffer->drawIndirectFirstPass<NormalMat>();
if (!CVS->supportsHardwareSkinning()) return;
m_solid_cmd_buffer->drawIndirectFirstPass<SkinnedSolid>();
m_solid_cmd_buffer->drawIndirectFirstPass<SkinnedAlphaRef>();
m_solid_cmd_buffer->drawIndirectFirstPass<SkinnedUnlitMat>();
m_solid_cmd_buffer->drawIndirectFirstPass<SkinnedNormalMat>();
}
// ----------------------------------------------------------------------------
@ -730,15 +735,19 @@ void DrawCalls::drawIndirectSolidFirstPass() const
void DrawCalls::multidrawSolidFirstPass() const
{
m_solid_cmd_buffer->bind();
m_solid_cmd_buffer->multidrawFirstPass<SkinnedSolid>();
m_solid_cmd_buffer->multidrawFirstPass<SkinnedAlphaRef>();
m_solid_cmd_buffer->multidrawFirstPass<DefaultMaterial>();
m_solid_cmd_buffer->multidrawFirstPass<AlphaRef>();
m_solid_cmd_buffer->multidrawFirstPass<SphereMap>();
m_solid_cmd_buffer->multidrawFirstPass<UnlitMat>();
m_solid_cmd_buffer->multidrawFirstPass<GrassMat>(m_wind_dir);
m_solid_cmd_buffer->multidrawFirstPass<NormalMat>();
m_solid_cmd_buffer->multidrawFirstPass<DetailMat>();
m_solid_cmd_buffer->multidrawFirstPass<DetailMat>();
if (!CVS->supportsHardwareSkinning()) return;
m_solid_cmd_buffer->multidrawFirstPass<SkinnedSolid>();
m_solid_cmd_buffer->multidrawFirstPass<SkinnedAlphaRef>();
m_solid_cmd_buffer->multidrawFirstPass<SkinnedUnlitMat>();
m_solid_cmd_buffer->multidrawFirstPass<SkinnedNormalMat>();
}
// ----------------------------------------------------------------------------
@ -751,8 +760,6 @@ void DrawCalls::multidrawSolidFirstPass() const
void DrawCalls::drawIndirectSolidSecondPass(const std::vector<GLuint> &prefilled_tex) const
{
m_solid_cmd_buffer->bind();
m_solid_cmd_buffer->drawIndirectSecondPass<SkinnedSolid>(prefilled_tex);
m_solid_cmd_buffer->drawIndirectSecondPass<SkinnedAlphaRef>(prefilled_tex);
m_solid_cmd_buffer->drawIndirectSecondPass<DefaultMaterial>(prefilled_tex);
m_solid_cmd_buffer->drawIndirectSecondPass<AlphaRef>(prefilled_tex);
m_solid_cmd_buffer->drawIndirectSecondPass<UnlitMat>(prefilled_tex);
@ -760,6 +767,12 @@ void DrawCalls::drawIndirectSolidSecondPass(const std::vector<GLuint> &prefilled
m_solid_cmd_buffer->drawIndirectSecondPass<GrassMat>(prefilled_tex, m_wind_dir);
m_solid_cmd_buffer->drawIndirectSecondPass<DetailMat>(prefilled_tex);
m_solid_cmd_buffer->drawIndirectSecondPass<NormalMat>(prefilled_tex);
if (!CVS->supportsHardwareSkinning()) return;
m_solid_cmd_buffer->drawIndirectSecondPass<SkinnedSolid>(prefilled_tex);
m_solid_cmd_buffer->drawIndirectSecondPass<SkinnedAlphaRef>(prefilled_tex);
m_solid_cmd_buffer->drawIndirectSecondPass<SkinnedUnlitMat>(prefilled_tex);
m_solid_cmd_buffer->drawIndirectSecondPass<SkinnedNormalMat>(prefilled_tex);
}
// ----------------------------------------------------------------------------
@ -771,8 +784,6 @@ void DrawCalls::drawIndirectSolidSecondPass(const std::vector<GLuint> &prefilled
void DrawCalls::multidrawSolidSecondPass(const std::vector<uint64_t> &handles) const
{
m_solid_cmd_buffer->bind();
m_solid_cmd_buffer->multidraw2ndPass<SkinnedSolid>(handles);
m_solid_cmd_buffer->multidraw2ndPass<SkinnedAlphaRef>(handles);
m_solid_cmd_buffer->multidraw2ndPass<DefaultMaterial>(handles);
m_solid_cmd_buffer->multidraw2ndPass<AlphaRef>(handles);
m_solid_cmd_buffer->multidraw2ndPass<SphereMap>(handles);
@ -780,6 +791,12 @@ void DrawCalls::multidrawSolidSecondPass(const std::vector<uint64_t> &handles) c
m_solid_cmd_buffer->multidraw2ndPass<NormalMat>(handles);
m_solid_cmd_buffer->multidraw2ndPass<DetailMat>(handles);
m_solid_cmd_buffer->multidraw2ndPass<GrassMat>(handles, m_wind_dir);
if (!CVS->supportsHardwareSkinning()) return;
m_solid_cmd_buffer->multidraw2ndPass<SkinnedSolid>(handles);
m_solid_cmd_buffer->multidraw2ndPass<SkinnedAlphaRef>(handles);
m_solid_cmd_buffer->multidraw2ndPass<SkinnedUnlitMat>(handles);
m_solid_cmd_buffer->multidraw2ndPass<SkinnedNormalMat>(handles);
}
// ----------------------------------------------------------------------------
@ -822,8 +839,6 @@ void DrawCalls::multidrawNormals() const
void DrawCalls::drawIndirectShadows(unsigned cascade) const
{
m_shadow_cmd_buffer->bind();
m_shadow_cmd_buffer->drawIndirect<SkinnedSolid>(cascade);
m_shadow_cmd_buffer->drawIndirect<SkinnedAlphaRef>(cascade);
m_shadow_cmd_buffer->drawIndirect<DefaultMaterial>(cascade);
m_shadow_cmd_buffer->drawIndirect<DetailMat>(cascade);
m_shadow_cmd_buffer->drawIndirect<AlphaRef>(cascade);
@ -832,6 +847,12 @@ void DrawCalls::drawIndirectShadows(unsigned cascade) const
m_shadow_cmd_buffer->drawIndirect<NormalMat>(cascade);
m_shadow_cmd_buffer->drawIndirect<SplattingMat>(cascade);
m_shadow_cmd_buffer->drawIndirect<SphereMap>(cascade);
if (!CVS->supportsHardwareSkinning()) return;
m_shadow_cmd_buffer->drawIndirect<SkinnedSolid>(cascade);
m_shadow_cmd_buffer->drawIndirect<SkinnedAlphaRef>(cascade);
m_shadow_cmd_buffer->drawIndirect<SkinnedUnlitMat>(cascade);
m_shadow_cmd_buffer->drawIndirect<SkinnedNormalMat>(cascade);
}
// ----------------------------------------------------------------------------
@ -842,8 +863,6 @@ void DrawCalls::drawIndirectShadows(unsigned cascade) const
void DrawCalls::multidrawShadows(unsigned cascade) const
{
m_shadow_cmd_buffer->bind();
m_shadow_cmd_buffer->multidrawShadow<SkinnedSolid>(cascade);
m_shadow_cmd_buffer->multidrawShadow<SkinnedAlphaRef>(cascade);
m_shadow_cmd_buffer->multidrawShadow<DefaultMaterial>(cascade);
m_shadow_cmd_buffer->multidrawShadow<DetailMat>(cascade);
m_shadow_cmd_buffer->multidrawShadow<NormalMat>(cascade);
@ -852,6 +871,12 @@ void DrawCalls::multidrawShadows(unsigned cascade) const
m_shadow_cmd_buffer->multidrawShadow<GrassMat,irr::core::vector3df>(cascade, m_wind_dir);
m_shadow_cmd_buffer->multidrawShadow<SplattingMat>(cascade);
m_shadow_cmd_buffer->multidrawShadow<SphereMap>(cascade);
if (!CVS->supportsHardwareSkinning()) return;
m_shadow_cmd_buffer->multidrawShadow<SkinnedSolid>(cascade);
m_shadow_cmd_buffer->multidrawShadow<SkinnedAlphaRef>(cascade);
m_shadow_cmd_buffer->multidrawShadow<SkinnedUnlitMat>(cascade);
m_shadow_cmd_buffer->multidrawShadow<SkinnedNormalMat>(cascade);
}
// ----------------------------------------------------------------------------

@ -151,7 +151,7 @@ public:
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);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)44);
glEnableVertexAttribArray(5);
glVertexAttribIPointer(5, 4, GL_INT, getVertexPitchFromType(tp), (GLvoid*)60);

@ -20,20 +20,35 @@
#ifndef SERVER_ONLY
const STK::Tuple<size_t> SkinnedSolid::FirstPassTextures
= STK::Tuple<size_t>(1);
= 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);
= 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> SkinnedAlphaRef::FirstPassTextures
= STK::Tuple<size_t, size_t>(0, 1);
= STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<size_t, size_t, size_t> SkinnedAlphaRef::SecondPassTextures
= STK::Tuple<size_t, size_t, size_t>(0, 1, 2);
= STK::Tuple<size_t, size_t, size_t>(0, 1, 2);
const STK::Tuple<size_t> SkinnedAlphaRef::ShadowTextures = STK::Tuple<size_t>(0);
const STK::Tuple<size_t> SkinnedAlphaRef::RSMTextures = STK::Tuple<size_t>(0);
// ----------------------------------------------------------------------------
const STK::Tuple<size_t, size_t> SkinnedUnlitMat::FirstPassTextures
= STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<size_t> SkinnedUnlitMat::SecondPassTextures = STK::Tuple<size_t>(0);
const STK::Tuple<size_t> SkinnedUnlitMat::ShadowTextures = STK::Tuple<size_t>(0);
const STK::Tuple<size_t> SkinnedUnlitMat::RSMTextures = STK::Tuple<size_t>(0);
// ----------------------------------------------------------------------------
const STK::Tuple<size_t, size_t> SkinnedNormalMat::FirstPassTextures
= STK::Tuple<size_t, size_t>(3, 1);
const STK::Tuple<size_t, size_t, size_t> SkinnedNormalMat::SecondPassTextures
= STK::Tuple<size_t, size_t, size_t>(0, 1, 2);
const STK::Tuple<> SkinnedNormalMat::ShadowTextures;
const STK::Tuple<size_t> SkinnedNormalMat::RSMTextures = STK::Tuple<size_t>(0);
// ----------------------------------------------------------------------------
const STK::Tuple<size_t> DefaultMaterial::FirstPassTextures
= STK::Tuple<size_t>(1);

@ -687,6 +687,38 @@ public:
} // InstancedSkinnedMeshRefPass2Shader
}; // InstancedSkinnedMeshRefPass2Shader
// ============================================================================
class InstancedSkinnedMeshUnlitShader : public TextureShader<InstancedSkinnedMeshUnlitShader, 4>
{
public:
InstancedSkinnedMeshUnlitShader()
{
if (!CVS->supportsHardwareSkinning()) return;
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert",
GL_FRAGMENT_SHADER, "instanced_object_unlit.frag");
assignUniforms();
assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED,
1, "SpecularMap", ST_NEAREST_FILTERED,
2, "SSAO", ST_BILINEAR_FILTERED,
3, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // InstancedSkinnedMeshUnlitShader
}; // InstancedSkinnedMeshUnlitShader
// ============================================================================
class InstancedSkinnedNormalMapShader : public TextureShader<InstancedSkinnedNormalMapShader, 2>
{
public:
InstancedSkinnedNormalMapShader()
{
if (!CVS->supportsHardwareSkinning()) return;
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert",
GL_FRAGMENT_SHADER, "instanced_normalmap.frag");
assignUniforms();
assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED,
1, "glossMap", ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // InstancedSkinnedNormalMapShader
}; // InstancedSkinnedNormalMapShader
// ============================================================================
class InstancedSkinnedShadowShader : public TextureShader<InstancedSkinnedShadowShader, 0, int>
{
@ -749,11 +781,10 @@ struct SkinnedSolid
typedef InstancedSkinnedMeshPass1Shader InstancedFirstPassShader;
typedef InstancedSkinnedMeshPass2Shader InstancedSecondPassShader;
typedef InstancedSkinnedShadowShader InstancedShadowPassShader;
//typedef CInstancedRSMShader InstancedRSMShader;
typedef Shaders::SkinnedMeshPass1Shader FirstPassShader;
typedef Shaders::SkinnedMeshPass2Shader SecondPassShader;
//typedef ShadowShader ShadowPassShader;
//typedef CRSMShader RSMShader;
// Todo: RSMs
typedef ListSkinnedSolid List;
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_SKINNED_MESH;
static const enum Material::ShaderType MaterialType
@ -771,11 +802,10 @@ struct SkinnedAlphaRef
typedef InstancedSkinnedMeshRefPass1Shader InstancedFirstPassShader;
typedef InstancedSkinnedMeshRefPass2Shader InstancedSecondPassShader;
typedef InstancedSkinnedRefShadowShader InstancedShadowPassShader;
//typedef CInstancedRSMShader InstancedRSMShader;
//typedef ObjectRefPass1Shader FirstPassShader;
//typedef ObjectRefPass2Shader SecondPassShader;
//typedef RefShadowShader ShadowPassShader;
//typedef CRSMShader RSMShader;
// Todo: RSMs
typedef ListSkinnedAlphaRef List;
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_SKINNED_MESH;
static const enum Material::ShaderType MaterialType =
@ -787,6 +817,48 @@ struct SkinnedAlphaRef
static const STK::Tuple<size_t> RSMTextures;
}; // struct SkinnedAlphaRef
// ----------------------------------------------------------------------------
struct SkinnedNormalMat
{
typedef InstancedSkinnedNormalMapShader InstancedFirstPassShader;
typedef InstancedSkinnedMeshPass2Shader InstancedSecondPassShader;
typedef InstancedSkinnedShadowShader InstancedShadowPassShader;
//typedef ObjectRefPass1Shader FirstPassShader;
//typedef ObjectRefPass2Shader SecondPassShader;
//typedef RefShadowShader ShadowPassShader;
// Todo: RSMs
typedef ListSkinnedNormalMap List;
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_SKINNED_MESH;
static const enum Material::ShaderType MaterialType =
Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH;
static const enum InstanceType Instance = InstanceTypeFourTex;
static const STK::Tuple<size_t, 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 SkinnedNormalMat
// ----------------------------------------------------------------------------
struct SkinnedUnlitMat
{
typedef InstancedSkinnedMeshRefPass1Shader InstancedFirstPassShader;
typedef InstancedSkinnedMeshUnlitShader InstancedSecondPassShader;
typedef InstancedSkinnedRefShadowShader InstancedShadowPassShader;
//typedef ObjectRefPass1Shader FirstPassShader;
//typedef ObjectRefPass2Shader SecondPassShader;
//typedef RefShadowShader ShadowPassShader;
// Todo: RSMs
typedef ListSkinnedUnlit List;
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_SKINNED_MESH;
static const enum Material::ShaderType MaterialType =
Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH;
static const enum InstanceType Instance = InstanceTypeThreeTex;
static const STK::Tuple<size_t, size_t> FirstPassTextures;
static const STK::Tuple<size_t> SecondPassTextures;
static const STK::Tuple<size_t> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
}; // struct SkinnedUnlitMat
// ----------------------------------------------------------------------------
struct DefaultMaterial
{

@ -421,6 +421,8 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh,
vNew = v[idx[i]];
}
break;
default:
break;
}
core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew);
if (n)
@ -479,54 +481,5 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh,
void MeshTools::createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh,
bool(*predicate)(scene::IMeshBuffer*))
{
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++)
{
scene::SSkinMeshBuffer* mb = all_mb[i];
if (mb && predicate(mb))
{
mb->convertToTangents();
const int index_count = mb->getIndexCount();
uint16_t* idx = mb->getIndices();
video::S3DVertexTangents* v =
(video::S3DVertexTangents*)mb->getVertices();
for (int i = 0; i < index_count; i += 3)
{
calculateTangents(
v[idx[i+0]].Normal,
v[idx[i+0]].Tangent,
v[idx[i+0]].Binormal,
v[idx[i+0]].Pos,
v[idx[i+1]].Pos,
v[idx[i+2]].Pos,
v[idx[i+0]].TCoords,
v[idx[i+1]].TCoords,
v[idx[i+2]].TCoords);
calculateTangents(
v[idx[i+1]].Normal,
v[idx[i+1]].Tangent,
v[idx[i+1]].Binormal,
v[idx[i+1]].Pos,
v[idx[i+2]].Pos,
v[idx[i+0]].Pos,
v[idx[i+1]].TCoords,
v[idx[i+2]].TCoords,
v[idx[i+0]].TCoords);
calculateTangents(
v[idx[i+2]].Normal,
v[idx[i+2]].Tangent,
v[idx[i+2]].Binormal,
v[idx[i+2]].Pos,
v[idx[i+0]].Pos,
v[idx[i+1]].Pos,
v[idx[i+2]].TCoords,
v[idx[i+0]].TCoords,
v[idx[i+1]].TCoords);
}
}
}
mesh->convertMeshToTangents(predicate);
}

@ -44,13 +44,13 @@ Material::ShaderType getMeshMaterialFromType(video::E_MATERIAL_TYPE material_typ
{
switch (material->getShaderType())
{
//case Material::SHADERTYPE_SOLID:
// if (material_type == Shaders::getShader(ES_NORMAL_MAP))
// return Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH;
case Material::SHADERTYPE_SOLID:
if (material_type == Shaders::getShader(ES_NORMAL_MAP))
return Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH;
case Material::SHADERTYPE_ALPHA_TEST:
return Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH;
//case Material::SHADERTYPE_SOLID_UNLIT:
// return Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH;
case Material::SHADERTYPE_SOLID_UNLIT:
return Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH;
default:
return Material::SHADERTYPE_SOLID_SKINNED_MESH;
}
@ -182,7 +182,7 @@ GLuint createVAO(GLuint vbo, GLuint idx, video::E_VERTEX_TYPE type)
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);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)44);
glEnableVertexAttribArray(5);
glVertexAttribIPointer(5, 4, GL_INT, getVertexPitchFromType(type), (GLvoid*)60);