Allow GL3 to have hardware skinning

This commit is contained in:
Benau 2016-12-09 18:41:13 +08:00
parent b7e047b4c1
commit 76e070b709
7 changed files with 128 additions and 73 deletions

View File

@ -1,81 +1,86 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 the SuperTuxKart team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef GL_ES
uniform mat4 ModelMatrix;
uniform mat4 InverseModelMatrix;
uniform vec2 texture_trans;
#else
uniform mat4 ModelMatrix =
mat4(1., 0., 0., 0.,
0., 1., 0., 0.,
0., 0., 1., 0.,
0., 0., 0., 1.);
uniform mat4 InverseModelMatrix =
mat4(1., 0., 0., 0.,
0., 1., 0., 0.,
0., 0., 1., 0.,
0., 0., 0., 1.);
// skinning.vert
#version 330 compatibility
#define MAX_JOINT_NUM 36
#define MAX_LIGHT_NUM 8
uniform vec2 texture_trans = vec2(0., 0.);
#endif
uniform int skinning_offset;
uniform mat4 JointTransform[MAX_JOINT_NUM];
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;
void main()
out vec3 nor;
out vec3 tangent;
out vec3 bitangent;
out vec2 uv;
out vec4 color;
#stk_include "utils/getworldmatrix.vert"
void main(void)
{
int index;
vec4 ecPos;
vec3 normal;
vec3 light_dir;
float n_dot_l;
float dist;
mat4 TransposeInverseModelView = transpose(InverseModelMatrix * InverseViewMatrix);
vec4 idle_position = vec4(Position, 1.);
vec4 idle_normal = vec4(Normal, 0.);
vec4 skinned_position = vec4(0.);
vec4 skinned_normal = vec4(0.);
mat4 ModelTransform = gl_ModelViewProjectionMatrix;
// 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;
index = int(gl_Color.r * 255.99);
mat4 vertTran = JointTransform[index - 1];
// First bone:
single_bone_influenced_position = joint_matrices[clamp(Joint[0] + skinning_offset, 0, MAX_BONES)] * idle_position;
single_bone_influenced_position /= single_bone_influenced_position.w;
single_bone_influenced_normal = joint_matrices[clamp(Joint[0] + skinning_offset, 0, MAX_BONES)] * idle_normal;
skinned_position += Weight[0] * single_bone_influenced_position;
skinned_normal += Weight[0] * single_bone_influenced_normal;
index = int(gl_Color.g * 255.99);
if(index > 0)
vertTran += JointTransform[index - 1];
// Second bone:
single_bone_influenced_position = joint_matrices[clamp(Joint[1] + skinning_offset, 0, MAX_BONES)] * idle_position;
single_bone_influenced_position /= single_bone_influenced_position.w;
single_bone_influenced_normal = joint_matrices[clamp(Joint[1] + skinning_offset, 0, MAX_BONES)] * idle_normal;
skinned_position += Weight[1] * single_bone_influenced_position;
skinned_normal += Weight[1] * single_bone_influenced_normal;
index = int(gl_Color.b * 255.99);
if(index > 0)
vertTran += JointTransform[index - 1];
// Third bone:
single_bone_influenced_position = joint_matrices[clamp(Joint[2] + skinning_offset, 0, MAX_BONES)] * idle_position;
single_bone_influenced_position /= single_bone_influenced_position.w;
single_bone_influenced_normal = joint_matrices[clamp(Joint[2] + skinning_offset, 0, MAX_BONES)] * idle_normal;
skinned_position += Weight[2] * single_bone_influenced_position;
skinned_normal += Weight[2] * single_bone_influenced_normal;
index = int(gl_Color.a * 255.99);
if(index > 0)
vertTran += JointTransform[index - 1];
// Fourth bone:
single_bone_influenced_position = joint_matrices[clamp(Joint[3] + skinning_offset, 0, MAX_BONES)] * idle_position;
single_bone_influenced_position /= single_bone_influenced_position.w;
single_bone_influenced_normal = joint_matrices[clamp(Joint[3] + skinning_offset, 0, MAX_BONES)] * idle_normal;
skinned_position += Weight[3] * single_bone_influenced_position;
skinned_normal += Weight[3] * single_bone_influenced_normal;
ecPos = gl_ModelViewMatrix * vertTran * gl_Vertex;
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;
normal = (vertTran * vec4(gl_Normal, 0.0)).xyz;
normal = normalize(gl_NormalMatrix * normal);
gl_FrontColor = vec4(0,0,0,0);
for(int i = 0;i < MAX_LIGHT_NUM;i++)
{
light_dir = vec3(gl_LightSource[i].position-ecPos);
n_dot_l = max(dot(normal, normalize(light_dir)), 0.0);
dist = length(light_dir);
n_dot_l *= 1.0 / (gl_LightSource[0].constantAttenuation + gl_LightSource[0].linearAttenuation * dist);
gl_FrontColor += gl_LightSource[i].diffuse * n_dot_l;
}
gl_FrontColor = clamp(gl_FrontColor,0.3,1.0);
ModelTransform *= vertTran;
gl_Position = ModelTransform * gl_Vertex;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;
/*
// Reflections.
vec3 r = reflect( ecPos.xyz , normal );
float m = 2.0 * sqrt( r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0) );
gl_TexCoord[1].s = r.x/m + 0.5;
gl_TexCoord[1].t = r.y/m + 0.5;
*/
uv = vec2(Data1.x + texture_trans.x, Data1.y + texture_trans.y);
color = Color.zyxw;
}

View File

@ -46,6 +46,7 @@ void DrawCalls::clearLists()
ListDisplacement::getInstance()->clear();
ListMatDefault::getInstance()->clear();
ListSkinnedSolid::getInstance()->clear();
ListMatAlphaRef::getInstance()->clear();
ListMatSphereMap::getInstance()->clear();
ListMatDetails::getInstance()->clear();
@ -305,6 +306,12 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) :
core::vector2df(0.0f, 0.0f)));
break;
case Material::SHADERTYPE_SOLID_SKINNED_MESH:
ListSkinnedSolid::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, 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)), skinning_offset);
break;
case Material::SHADERTYPE_ALPHA_TEST:
ListMatAlphaRef::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans,
(mesh->m_render_info && mesh->m_material ?

View File

@ -176,6 +176,7 @@ void drawRSM(const core::matrix4 & rsm_matrix)
void GL3DrawPolicy::drawSolidFirstPass(const DrawCalls& draw_calls) const
{
renderMeshes1stPass<DefaultMaterial, 2, 1>();
renderMeshes1stPass<SkinnedSolid, 5, 2, 1>();
renderMeshes1stPass<SplattingMat, 2, 1>();
renderMeshes1stPass<UnlitMat, 3, 2, 1>();
renderMeshes1stPass<AlphaRef, 3, 2, 1>();
@ -191,6 +192,7 @@ void GL3DrawPolicy::drawSolidSecondPass (const DrawCalls& draw_calls,
const std::vector<GLuint>& prefilled_tex) const
{
renderMeshes2ndPass<DefaultMaterial, 4, 3, 1> (handles, prefilled_tex);
renderMeshes2ndPass<SkinnedSolid, 5, 4, 3, 1> (handles, prefilled_tex);
renderMeshes2ndPass<AlphaRef, 4, 3, 1> (handles, prefilled_tex);
renderMeshes2ndPass<UnlitMat, 3, 1 > (handles, prefilled_tex);
renderMeshes2ndPass<SplattingMat, 1 > (handles, prefilled_tex);

View File

@ -655,8 +655,8 @@ struct SkinnedSolid
typedef InstancedSkinnedMeshPass2Shader InstancedSecondPassShader;
//typedef InstancedShadowShader InstancedShadowPassShader;
//typedef CInstancedRSMShader InstancedRSMShader;
//typedef Shaders::ObjectPass1Shader FirstPassShader;
//typedef Shaders::ObjectPass2Shader SecondPassShader;
typedef Shaders::SkinnedMeshPass1Shader FirstPassShader;
typedef Shaders::SkinnedMeshPass2Shader SecondPassShader;
//typedef ShadowShader ShadowPassShader;
//typedef CRSMShader RSMShader;
typedef ListSkinnedSolid List;
@ -668,7 +668,7 @@ struct SkinnedSolid
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 SkinnedSolid
// ----------------------------------------------------------------------------
struct DefaultMaterial

View File

@ -359,6 +359,29 @@ Shaders::ObjectPass2Shader::ObjectPass2Shader()
5, "colorization_mask", ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // ObjectPass2Shader
// ============================================================================
Shaders::SkinnedMeshPass1Shader::SkinnedMeshPass1Shader()
{
loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert",
GL_FRAGMENT_SHADER, "object_pass1.frag");
assignUniforms("ModelMatrix", "InverseModelMatrix", "skinning_offset");
assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // SkinnedMeshPass1Shader
// ============================================================================
Shaders::SkinnedMeshPass2Shader::SkinnedMeshPass2Shader()
{
loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert",
GL_FRAGMENT_SHADER, "object_pass2.frag");
assignUniforms("ModelMatrix", "texture_trans", "color_change", "skinning_offset");
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);
} // SkinnedMeshPass2Shader
// ============================================================================
Shaders::TransparentShader::TransparentShader()
{

View File

@ -153,6 +153,24 @@ public:
}; // ObjectPass2Shader
// ========================================================================
class SkinnedMeshPass1Shader : public TextureShader<SkinnedMeshPass1Shader, 1,
core::matrix4, core::matrix4,
int>
{
public:
SkinnedMeshPass1Shader();
}; // SkinnedMeshPass1Shader
// ========================================================================
class SkinnedMeshPass2Shader : public TextureShader < SkinnedMeshPass2Shader, 6,
core::matrix4, core::vector2df,
core::vector2df, int >
{
public:
SkinnedMeshPass2Shader();
}; // SkinnedMeshPass2Shader
// ========================================================================
}; // class Shaders

View File

@ -119,7 +119,7 @@ class ListMatDefault : public MeshList<ListMatDefault, GLMesh *, core::matrix4,
// ----------------------------------------------------------------------------
class ListSkinnedSolid : public MeshList<ListSkinnedSolid, GLMesh *, core::matrix4,
core::matrix4, core::vector2df,
core::vector2df>
core::vector2df, int>
{};
// ----------------------------------------------------------------------------