Merge branch 'hardware_skinning'
This commit is contained in:
commit
ffa4ad84cb
@ -63,5 +63,11 @@ layout (std140) uniform LightingData
|
||||
float rL21;
|
||||
float rL22;
|
||||
};
|
||||
|
||||
layout (std140) uniform SkinningData
|
||||
{
|
||||
mat4 joint_matrices[MAX_BONES];
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // HEADER_TXT
|
||||
|
77
data/shaders/instanced_skinning.vert
Normal file
77
data/shaders/instanced_skinning.vert
Normal file
@ -0,0 +1,77 @@
|
||||
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 int 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 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 * 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;
|
||||
#ifdef Use_Bindless_Texture
|
||||
handle = Handle;
|
||||
secondhandle = SecondHandle;
|
||||
thirdhandle = ThirdHandle;
|
||||
fourthhandle = FourthHandle;
|
||||
#endif
|
||||
}
|
57
data/shaders/instanced_skinning_shadow.vert
Normal file
57
data/shaders/instanced_skinning_shadow.vert
Normal file
@ -0,0 +1,57 @@
|
||||
uniform int layer;
|
||||
|
||||
layout(location = 0) in vec3 Position;
|
||||
layout(location = 3) in vec4 Data1;
|
||||
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;
|
||||
#ifdef Use_Bindless_Texture
|
||||
layout(location = 11) in uvec2 Handle;
|
||||
#endif
|
||||
layout(location = 15) in int skinning_offset;
|
||||
|
||||
#ifdef VSLayer
|
||||
out vec2 uv;
|
||||
#ifdef Use_Bindless_Texture
|
||||
flat out uvec2 handle;
|
||||
#endif
|
||||
#else
|
||||
out vec2 tc;
|
||||
out int layerId;
|
||||
#ifdef Use_Bindless_Texture
|
||||
flat out uvec2 hdle;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#stk_include "utils/getworldmatrix.vert"
|
||||
|
||||
void main(void)
|
||||
{
|
||||
mat4 ModelMatrix = getWorldMatrix(Origin, Orientation, Scale);
|
||||
vec4 idle_position = vec4(Position, 1.);
|
||||
vec4 skinned_position = vec4(0.);
|
||||
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;
|
||||
skinned_position += Weight[i] * single_bone_influenced_position;
|
||||
}
|
||||
|
||||
#ifdef VSLayer
|
||||
gl_Layer = layer;
|
||||
gl_Position = ShadowViewProjMatrixes[gl_Layer] * ModelMatrix * skinned_position;
|
||||
uv = Data1.xy;
|
||||
#ifdef Use_Bindless_Texture
|
||||
handle = Handle;
|
||||
#endif
|
||||
#else
|
||||
layerId = layer;
|
||||
gl_Position = ShadowViewProjMatrixes[layerId] * ModelMatrix * skinned_position;
|
||||
tc = Data1.xy;
|
||||
#ifdef Use_Bindless_Texture
|
||||
hdle = Handle;
|
||||
#endif
|
||||
#endif
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
#ifdef Use_Bindless_Texture
|
||||
layout(bindless_sampler) uniform sampler2D normalMap;
|
||||
layout(bindless_sampler) uniform sampler2D DiffuseForAlpha;
|
||||
layout(bindless_sampler) uniform sampler2D glossMap;
|
||||
#else
|
||||
uniform sampler2D normalMap;
|
||||
uniform sampler2D DiffuseForAlpha;
|
||||
uniform sampler2D glossMap;
|
||||
#endif
|
||||
|
||||
in vec3 tangent;
|
||||
@ -17,7 +17,7 @@ void main()
|
||||
{
|
||||
// normal in Tangent Space
|
||||
vec3 TS_normal = 2.0 * texture(normalMap, uv).rgb - 1.0;
|
||||
float alpha = texture(DiffuseForAlpha, uv).a;
|
||||
float gloss = texture(glossMap, uv).x;
|
||||
// Because of interpolation, we need to renormalize
|
||||
vec3 Frag_tangent = normalize(tangent);
|
||||
vec3 Frag_normal = normalize(cross(Frag_tangent, bitangent));
|
||||
@ -25,5 +25,5 @@ void main()
|
||||
|
||||
vec3 FragmentNormal = TS_normal.x * Frag_tangent + TS_normal.y * Frag_bitangent - TS_normal.z * Frag_normal;
|
||||
EncodedNormal.xy = 0.5 * EncodeNormal(normalize(FragmentNormal)) + 0.5;
|
||||
EncodedNormal.z = 1. - alpha;
|
||||
EncodedNormal.z = gloss;
|
||||
}
|
||||
|
@ -1,81 +1,70 @@
|
||||
// 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 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;
|
||||
}
|
||||
|
||||
mat4 ModelTransform = gl_ModelViewProjectionMatrix;
|
||||
|
||||
index = int(gl_Color.r * 255.99);
|
||||
mat4 vertTran = JointTransform[index - 1];
|
||||
|
||||
index = int(gl_Color.g * 255.99);
|
||||
if(index > 0)
|
||||
vertTran += JointTransform[index - 1];
|
||||
|
||||
index = int(gl_Color.b * 255.99);
|
||||
if(index > 0)
|
||||
vertTran += JointTransform[index - 1];
|
||||
|
||||
index = int(gl_Color.a * 255.99);
|
||||
if(index > 0)
|
||||
vertTran += JointTransform[index - 1];
|
||||
|
||||
ecPos = gl_ModelViewMatrix * vertTran * gl_Vertex;
|
||||
|
||||
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;
|
||||
*/
|
||||
gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * skinned_position;
|
||||
// Keep orthogonality
|
||||
nor = (TransposeInverseModelView * skinned_normal).xyz;
|
||||
// Keep direction
|
||||
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;
|
||||
}
|
||||
|
37
data/shaders/skinning_shadow.vert
Normal file
37
data/shaders/skinning_shadow.vert
Normal file
@ -0,0 +1,37 @@
|
||||
uniform mat4 ModelMatrix;
|
||||
uniform int skinning_offset;
|
||||
uniform int layer;
|
||||
|
||||
layout(location = 0) in vec3 Position;
|
||||
layout(location = 3) in vec4 Data1;
|
||||
layout(location = 5) in ivec4 Joint;
|
||||
layout(location = 6) in vec4 Weight;
|
||||
|
||||
#ifdef VSLayer
|
||||
out vec2 uv;
|
||||
#else
|
||||
out vec2 tc;
|
||||
out int layerId;
|
||||
#endif
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec4 idle_position = vec4(Position, 1.);
|
||||
vec4 skinned_position = vec4(0.);
|
||||
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;
|
||||
skinned_position += Weight[i] * single_bone_influenced_position;
|
||||
}
|
||||
|
||||
#ifdef VSLayer
|
||||
gl_Layer = layer;
|
||||
uv = Data1.xy;
|
||||
gl_Position = ShadowViewProjMatrixes[gl_Layer] * ModelMatrix * skinned_position;
|
||||
#else
|
||||
layerId = layer;
|
||||
tc = Data1.xy;
|
||||
gl_Position = ShadowViewProjMatrixes[layerId] * ModelMatrix * skinned_position;
|
||||
#endif
|
||||
}
|
@ -30,6 +30,11 @@ if(APPLE)
|
||||
endif()
|
||||
|
||||
add_definitions(-DNDEBUG=1 -DIRRLICHT_EXPORTS=1 -DPNG_THREAD_UNSAFE_OK -DPNG_NO_MMX_CODE -DPNG_NO_MNG_FEATURES)
|
||||
|
||||
if(UNIX OR MINGW)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(/D_IRR_STATIC_LIB_)
|
||||
add_definitions(/D_CRT_SECURE_NO_WARNINGS) # Shut up about unsafe stuff
|
||||
|
@ -116,6 +116,8 @@ namespace scene
|
||||
NewVertices=new CSpecificVertexList<video::S3DVertexTangents>;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (Vertices)
|
||||
{
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include "aabbox3d.h"
|
||||
#include "IMesh.h"
|
||||
|
||||
typedef void (*SkinningCallback)(const irr::core::matrix4& m, int joint, int offset);
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
|
@ -371,6 +371,8 @@ protected:
|
||||
func(verts[i]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (boundingBoxUpdate)
|
||||
{
|
||||
|
@ -69,11 +69,11 @@ namespace scene
|
||||
virtual void animateMesh(f32 frame, f32 blend)=0;
|
||||
|
||||
//! Preforms a software skin on this mesh based of joint positions
|
||||
virtual void skinMesh(f32 strength=1.f) = 0;
|
||||
virtual void skinMesh(f32 strength=1.f, SkinningCallback sc = NULL, int offset = -1) = 0;
|
||||
|
||||
//! 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 */
|
||||
|
@ -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,54 @@ 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;
|
||||
Vertex.Tangent=core::vector3df(0.0f, 0.0f, 0.0f);
|
||||
Vertex.Binormal=core::vector3df(0.0f, 0.0f, 0.0f);
|
||||
Vertex.m_joint_idx1 = 0;
|
||||
Vertex.m_joint_idx2 = 0;
|
||||
Vertex.m_joint_idx3 = 0;
|
||||
Vertex.m_joint_idx4 = 0;
|
||||
Vertex.m_weight1 = 0;
|
||||
Vertex.m_weight2 = 0;
|
||||
Vertex.m_weight3 = 0;
|
||||
Vertex.m_weight4 = 0;
|
||||
Vertices_SkinnedMesh.push_back(Vertex);
|
||||
}
|
||||
}
|
||||
if (VertexType==video::EVT_TANGENTS)
|
||||
{
|
||||
for(u32 n=0;n<Vertices_Tangents.size();++n)
|
||||
{
|
||||
video::S3DVertexSkinnedMesh Vertex;
|
||||
Vertex.Color=Vertices_Tangents[n].Color;
|
||||
Vertex.Pos=Vertices_Tangents[n].Pos;
|
||||
Vertex.Normal=Vertices_Tangents[n].Normal;
|
||||
Vertex.TCoords=Vertices_Tangents[n].TCoords;
|
||||
Vertex.Tangent=Vertices_Tangents[n].Tangent;
|
||||
Vertex.Binormal=Vertices_Tangents[n].Binormal;
|
||||
Vertex.m_joint_idx1 = 0;
|
||||
Vertex.m_joint_idx2 = 0;
|
||||
Vertex.m_joint_idx3 = 0;
|
||||
Vertex.m_joint_idx4 = 0;
|
||||
Vertex.m_weight1 = 0;
|
||||
Vertex.m_weight2 = 0;
|
||||
Vertex.m_weight3 = 0;
|
||||
Vertex.m_weight4 = 0;
|
||||
Vertices_SkinnedMesh.push_back(Vertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Convert to tangents vertex type
|
||||
virtual void convertToTangents()
|
||||
{
|
||||
@ -250,6 +320,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 +336,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 +352,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 +368,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 +384,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 +400,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 +463,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;
|
||||
|
||||
|
@ -12,18 +12,25 @@ namespace irr
|
||||
namespace core
|
||||
{
|
||||
|
||||
//! Sinks an element into the heap.
|
||||
//! Function object which can be used for sorting (default)
|
||||
template<class T>
|
||||
inline void heapsink(T*array, s32 element, s32 max)
|
||||
inline bool sortless(const T& a, const T& b)
|
||||
{
|
||||
return a < b;
|
||||
}
|
||||
|
||||
//! Sinks an element into the heap with a custom compare function
|
||||
template<class T, class Compare>
|
||||
inline void heapsink(T*array, s32 element, s32 max, Compare cmp)
|
||||
{
|
||||
while ((element<<1) < max) // there is a left child
|
||||
{
|
||||
s32 j = (element<<1);
|
||||
|
||||
if (j+1 < max && array[j] < array[j+1])
|
||||
if (j+1 < max && cmp(array[j], array[j+1]))
|
||||
j = j+1; // take right child
|
||||
|
||||
if (array[element] < array[j])
|
||||
if (cmp(array[element], array[j]))
|
||||
{
|
||||
T t = array[j]; // swap elements
|
||||
array[j] = array[element];
|
||||
@ -35,10 +42,9 @@ inline void heapsink(T*array, s32 element, s32 max)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Sorts an array with size 'size' using heapsort.
|
||||
template<class T>
|
||||
inline void heapsort(T* array_, s32 size)
|
||||
//! Sorts an array with size 'size' using heapsort with a custom compare function
|
||||
template<class T, class Compare>
|
||||
inline void heapsort(T* array_, s32 size, Compare cmp)
|
||||
{
|
||||
// for heapsink we pretent this is not c++, where
|
||||
// arrays start with index 0. So we decrease the array pointer,
|
||||
@ -51,7 +57,7 @@ inline void heapsort(T* array_, s32 size)
|
||||
// build heap
|
||||
|
||||
for (i=((size-1)/2); i>=0; --i)
|
||||
heapsink(virtualArray, i+1, virtualSize-1);
|
||||
heapsink(virtualArray, i+1, virtualSize-1, cmp);
|
||||
|
||||
// sort array, leave out the last element (0)
|
||||
for (i=size-1; i>0; --i)
|
||||
@ -59,7 +65,7 @@ inline void heapsort(T* array_, s32 size)
|
||||
T t = array_[0];
|
||||
array_[0] = array_[i];
|
||||
array_[i] = t;
|
||||
heapsink(virtualArray, 1, i + 1);
|
||||
heapsink(virtualArray, 1, i + 1, cmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -394,10 +394,17 @@ public:
|
||||
void sort()
|
||||
{
|
||||
if (!is_sorted && used>1)
|
||||
heapsort(data, used);
|
||||
heapsort(data, used, sortless<T>);
|
||||
is_sorted = true;
|
||||
}
|
||||
|
||||
template<class Compare>
|
||||
void sort(Compare cmp)
|
||||
{
|
||||
if (!is_sorted && used>1)
|
||||
heapsort(data, used, cmp);
|
||||
is_sorted = true;
|
||||
}
|
||||
|
||||
//! Performs a binary search for an element, returns -1 if not found.
|
||||
/** The array will be sorted before the binary search if it is not
|
||||
|
@ -178,7 +178,7 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode()
|
||||
}
|
||||
}
|
||||
|
||||
IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
||||
IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(SkinningCallback sc, int offset)
|
||||
{
|
||||
if(Mesh->getMeshType() != EAMT_SKINNED)
|
||||
{
|
||||
@ -203,7 +203,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
||||
skinnedMesh->animateMesh(getFrameNr(), 1.0f);
|
||||
|
||||
// Update the skinned mesh for the current joint transforms.
|
||||
skinnedMesh->skinMesh(AnimationStrength);
|
||||
skinnedMesh->skinMesh(AnimationStrength, sc, offset);
|
||||
|
||||
if (JointMode == EJUOR_READ)//read from mesh
|
||||
{
|
||||
|
@ -161,7 +161,7 @@ namespace scene
|
||||
protected:
|
||||
|
||||
//! Get a static mesh for the current frame of this animated mesh
|
||||
IMesh* getMeshForCurrentFrame();
|
||||
virtual IMesh* getMeshForCurrentFrame(SkinningCallback sc = NULL, int offset = -1);
|
||||
|
||||
void buildFrameNr(u32 timeMs);
|
||||
void checkJoints();
|
||||
|
@ -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
|
||||
{
|
||||
@ -22,12 +23,12 @@ CSkinnedMesh::CSkinnedMesh()
|
||||
LastAnimatedFrame(-1), SkinnedLastFrame(false),
|
||||
InterpolationMode(EIM_LINEAR),
|
||||
HasAnimation(false), PreparedForSkinning(false),
|
||||
AnimateNormals(true), HardwareSkinning(false)
|
||||
AnimateNormals(true), HardwareSkinning(false), m_total_joints(0),
|
||||
m_current_joint(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CSkinnedMesh");
|
||||
#endif
|
||||
|
||||
SkinningBuffers=&LocalBuffers;
|
||||
}
|
||||
|
||||
@ -74,12 +75,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;
|
||||
}
|
||||
|
||||
@ -93,6 +101,12 @@ IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32
|
||||
//! blend: {0-old position, 1-New position}
|
||||
void CSkinnedMesh::animateMesh(f32 frame, f32 blend)
|
||||
{
|
||||
if (HardwareSkinning && LastAnimatedFrame==frame)
|
||||
{
|
||||
SkinnedLastFrame=false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HasAnimation || LastAnimatedFrame==frame)
|
||||
return;
|
||||
|
||||
@ -445,7 +459,7 @@ void CSkinnedMesh::getFrameData(f32 frame, SJoint *joint,
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
//! Preforms a software skin on this mesh based of joint positions
|
||||
void CSkinnedMesh::skinMesh(f32 strength)
|
||||
void CSkinnedMesh::skinMesh(f32 strength, SkinningCallback sc, int offset)
|
||||
{
|
||||
if (!HasAnimation || SkinnedLastFrame)
|
||||
return;
|
||||
@ -456,7 +470,13 @@ void CSkinnedMesh::skinMesh(f32 strength)
|
||||
//-----------------
|
||||
|
||||
SkinnedLastFrame=true;
|
||||
if (!HardwareSkinning)
|
||||
m_current_joint = 0;
|
||||
if (HardwareSkinning)
|
||||
{
|
||||
for (u32 i = 0; i < RootJoints.size(); i++)
|
||||
skinJoint(RootJoints[i], 0, strength, sc, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Software skin....
|
||||
u32 i;
|
||||
@ -486,65 +506,73 @@ void CSkinnedMesh::skinMesh(f32 strength)
|
||||
updateBoundingBox();
|
||||
}
|
||||
|
||||
void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength)
|
||||
void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength,
|
||||
SkinningCallback sc, int offset)
|
||||
{
|
||||
if (joint->Weights.size())
|
||||
{
|
||||
//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];
|
||||
if (sc != NULL) sc(jointVertexPull, m_current_joint, offset);
|
||||
m_current_joint++;
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
//Skin all children
|
||||
for (u32 j=0; j<joint->Children.size(); ++j)
|
||||
skinJoint(joint->Children[j], joint, strength);
|
||||
skinJoint(joint->Children[j], joint, strength, sc, offset);
|
||||
}
|
||||
|
||||
|
||||
@ -724,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)
|
||||
{
|
||||
@ -1139,7 +1167,7 @@ void CSkinnedMesh::finalize()
|
||||
|
||||
void CSkinnedMesh::updateBoundingBox(void)
|
||||
{
|
||||
if(!SkinningBuffers)
|
||||
if(HardwareSkinning || !SkinningBuffers)
|
||||
return;
|
||||
|
||||
core::array<SSkinMeshBuffer*> & buffer = *SkinningBuffers;
|
||||
@ -1382,26 +1410,133 @@ void CSkinnedMesh::addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes,
|
||||
SkinnedLastFrame=false;
|
||||
}
|
||||
|
||||
|
||||
void CSkinnedMesh::convertMeshToTangents()
|
||||
void CSkinnedMesh::convertForSkinning()
|
||||
{
|
||||
// now calculate tangents
|
||||
for (u32 b=0; b < LocalBuffers.size(); ++b)
|
||||
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])
|
||||
{
|
||||
LocalBuffers[b]->convertToTangents();
|
||||
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([]
|
||||
(const JointInfluence& a, const JointInfluence& b)
|
||||
{ return a.weight > b.weight; });
|
||||
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 = -100000;
|
||||
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_total_joints = m_current_joint;
|
||||
}
|
||||
|
||||
const s32 idxCnt = LocalBuffers[b]->getIndexCount();
|
||||
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++;
|
||||
}
|
||||
|
||||
u16* idx = LocalBuffers[b]->getIndices();
|
||||
video::S3DVertexTangents* v =
|
||||
(video::S3DVertexTangents*)LocalBuffers[b]->getVertices();
|
||||
for (u32 j = 0; j < joint->Children.size(); j++)
|
||||
computeWeightInfluence(joint->Children[j], index, wi);
|
||||
}
|
||||
|
||||
for (s32 i=0; i<idxCnt; i+=3)
|
||||
void CSkinnedMesh::convertMeshToTangents(bool(*predicate)(IMeshBuffer*))
|
||||
{
|
||||
bool recalculate_animation = false;
|
||||
toStaticPose();
|
||||
for (u32 b = 0; b < LocalBuffers.size(); b++)
|
||||
{
|
||||
bool recalculate_joints = false;
|
||||
core::map<u32, u32> vert_loc_map;
|
||||
SSkinMeshBuffer* ssmb = LocalBuffers[b];
|
||||
if (ssmb)
|
||||
{
|
||||
if (!predicate(ssmb)) continue;
|
||||
|
||||
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,
|
||||
@ -1412,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,
|
||||
@ -1423,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,
|
||||
@ -1433,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,
|
||||
|
@ -14,6 +14,16 @@
|
||||
#include "matrix4.h"
|
||||
#include "quaternion.h"
|
||||
|
||||
class JointInfluence
|
||||
{
|
||||
public:
|
||||
int joint_idx;
|
||||
float weight;
|
||||
};
|
||||
|
||||
typedef irr::core::array<irr::core::array
|
||||
<irr::core::array<JointInfluence> > > WeightInfluence;
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
@ -25,7 +35,6 @@ namespace scene
|
||||
class CSkinnedMesh: public ISkinnedMesh
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CSkinnedMesh();
|
||||
|
||||
@ -52,7 +61,7 @@ namespace scene
|
||||
virtual void animateMesh(f32 frame, f32 blend);
|
||||
|
||||
//! Preforms a software skin on this mesh based of joint positions
|
||||
virtual void skinMesh(f32 strength=1.f);
|
||||
virtual void skinMesh(f32 strength=1.f, SkinningCallback sc = NULL, int offset = -1);
|
||||
|
||||
//! returns amount of mesh buffers.
|
||||
virtual u32 getMeshBufferCount() const;
|
||||
@ -105,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();
|
||||
@ -159,7 +168,16 @@ namespace scene
|
||||
void addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes,
|
||||
IAnimatedMeshSceneNode* node,
|
||||
ISceneManager* smgr);
|
||||
|
||||
void convertForSkinning();
|
||||
|
||||
void computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi);
|
||||
|
||||
u32 getTotalJoints() const { return m_total_joints; }
|
||||
|
||||
private:
|
||||
void toStaticPose();
|
||||
|
||||
void checkForAnimation();
|
||||
|
||||
void normalizeWeights();
|
||||
@ -175,7 +193,8 @@ private:
|
||||
|
||||
void calculateGlobalMatrices(SJoint *Joint,SJoint *ParentJoint);
|
||||
|
||||
void skinJoint(SJoint *Joint, SJoint *ParentJoint, f32 strength=1.f);
|
||||
void skinJoint(SJoint *Joint, SJoint *ParentJoint, f32 strength=1.f,
|
||||
SkinningCallback sc = NULL, int offset = -1);
|
||||
|
||||
void calculateTangents(core::vector3df& normal,
|
||||
core::vector3df& tangent, core::vector3df& binormal,
|
||||
@ -205,6 +224,8 @@ private:
|
||||
bool PreparedForSkinning;
|
||||
bool AnimateNormals;
|
||||
bool HardwareSkinning;
|
||||
u32 m_total_joints;
|
||||
u32 m_current_joint;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Modify this file to change the last-modified date when you add/remove a file.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
|
||||
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
|
||||
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")
|
||||
|
@ -400,6 +400,8 @@ void CBatchingMesh::recalculateDestBufferBoundingBox(u32 i)
|
||||
case video::EVT_TANGENTS:
|
||||
((SMeshBufferTangents*)DestBuffers[i].Buffer)->recalculateBoundingBox();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,4 +444,8 @@ bool CentralVideoSettings::isDefferedEnabled() const
|
||||
return UserConfigParams::m_dynamic_lights && !GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_ADVANCED_PIPELINE);
|
||||
}
|
||||
|
||||
bool CentralVideoSettings::supportsHardwareSkinning() const
|
||||
{
|
||||
return isARBUniformBufferObjectUsable() && isARBExplicitAttribLocationUsable() && getGLSLVersion() >= 330;
|
||||
}
|
||||
#endif // !SERVER_ONLY
|
||||
|
@ -95,6 +95,7 @@ public:
|
||||
bool supportsIndirectInstancingRendering() const;
|
||||
bool supportsComputeShadersFiltering() const;
|
||||
bool supportsAsyncInstanceUpload() const;
|
||||
bool supportsHardwareSkinning() const;
|
||||
|
||||
// "Macro" around feature support and user config
|
||||
bool isShadowEnabled() const;
|
||||
|
@ -29,6 +29,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);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -45,6 +46,7 @@ void InstanceFiller<InstanceDataThreeTex>::add(GLMesh* mesh,
|
||||
instance.Texture = mesh->TextureHandles[0];
|
||||
instance.SecondTexture = mesh->TextureHandles[1];
|
||||
instance.ThirdTexture = mesh->TextureHandles[2];
|
||||
instance.skinning_offset = STK::tuple_get<3>(is);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -62,6 +64,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);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -155,7 +158,7 @@ SolidCommandBuffer::SolidCommandBuffer(): CommandBuffer()
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void SolidCommandBuffer::fill(SolidPassMeshMap *mesh_map)
|
||||
void SolidCommandBuffer::fill(MeshMap *mesh_map)
|
||||
{
|
||||
clearMeshes();
|
||||
|
||||
@ -167,16 +170,20 @@ void SolidCommandBuffer::fill(SolidPassMeshMap *mesh_map)
|
||||
Material::SHADERTYPE_ALPHA_TEST,
|
||||
Material::SHADERTYPE_SOLID_UNLIT,
|
||||
Material::SHADERTYPE_SPHERE_MAP,
|
||||
Material::SHADERTYPE_VEGETATION);
|
||||
Material::SHADERTYPE_VEGETATION,
|
||||
Material::SHADERTYPE_SOLID_SKINNED_MESH,
|
||||
Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH,
|
||||
Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH);
|
||||
|
||||
fillInstanceData<InstanceDataThreeTex, SolidPassMeshMap>
|
||||
fillInstanceData<InstanceDataThreeTex, MeshMap>
|
||||
(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>
|
||||
fillInstanceData<InstanceDataFourTex, MeshMap>
|
||||
(mesh_map, four_tex_material_list, InstanceTypeFourTex);
|
||||
|
||||
if (!CVS->supportsAsyncInstanceUpload())
|
||||
@ -189,7 +196,7 @@ ShadowCommandBuffer::ShadowCommandBuffer(): CommandBuffer()
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void ShadowCommandBuffer::fill(OtherMeshMap *mesh_map)
|
||||
void ShadowCommandBuffer::fill(MeshMap *mesh_map)
|
||||
{
|
||||
clearMeshes();
|
||||
|
||||
@ -215,9 +222,17 @@ 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>
|
||||
fillInstanceData<InstanceDataSingleTex, MeshMap>
|
||||
(mesh_map, shadow_tex_material_list, InstanceTypeShadow);
|
||||
|
||||
if (!CVS->supportsAsyncInstanceUpload())
|
||||
@ -231,7 +246,7 @@ ReflectiveShadowMapCommandBuffer::ReflectiveShadowMapCommandBuffer()
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void ReflectiveShadowMapCommandBuffer::fill(OtherMeshMap *mesh_map)
|
||||
void ReflectiveShadowMapCommandBuffer::fill(MeshMap *mesh_map)
|
||||
{
|
||||
clearMeshes();
|
||||
|
||||
@ -245,7 +260,7 @@ void ReflectiveShadowMapCommandBuffer::fill(OtherMeshMap *mesh_map)
|
||||
Material::SHADERTYPE_DETAIL_MAP,
|
||||
Material::SHADERTYPE_NORMAL_MAP);
|
||||
|
||||
fillInstanceData<InstanceDataSingleTex, OtherMeshMap>
|
||||
fillInstanceData<InstanceDataSingleTex, MeshMap>
|
||||
(mesh_map, rsm_material_list, InstanceTypeRSM);
|
||||
|
||||
if (!CVS->supportsAsyncInstanceUpload())
|
||||
@ -259,14 +274,14 @@ GlowCommandBuffer::GlowCommandBuffer()
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GlowCommandBuffer::fill(OtherMeshMap *mesh_map)
|
||||
void GlowCommandBuffer::fill(MeshMap *mesh_map)
|
||||
{
|
||||
clearMeshes();
|
||||
|
||||
if(!CVS->supportsAsyncInstanceUpload())
|
||||
mapIndirectBuffer();
|
||||
|
||||
fillInstanceData<GlowInstanceData, OtherMeshMap>
|
||||
fillInstanceData<GlowInstanceData, MeshMap>
|
||||
(mesh_map, createVector<int>(0), InstanceTypeGlow);
|
||||
if (!CVS->supportsAsyncInstanceUpload())
|
||||
glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER);
|
||||
|
@ -31,7 +31,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, int32_t> InstanceSettings;
|
||||
|
||||
struct InstanceList
|
||||
{
|
||||
@ -39,10 +39,7 @@ struct InstanceList
|
||||
std::vector<InstanceSettings> m_instance_settings;
|
||||
};
|
||||
|
||||
typedef std::unordered_map <std::pair<scene::IMeshBuffer*, RenderInfo*>, InstanceList,
|
||||
MeshRenderInfoHash, MeshRenderInfoEquals> SolidPassMeshMap;
|
||||
|
||||
typedef std::unordered_map <irr::scene::IMeshBuffer *, InstanceList > OtherMeshMap;
|
||||
typedef std::unordered_map <irr::scene::IMeshBuffer *, InstanceList > MeshMap;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Fill origin, orientation and scale attributes
|
||||
@ -271,7 +268,7 @@ class SolidCommandBuffer: public CommandBuffer<static_cast<int>(Material::SHADER
|
||||
{
|
||||
public:
|
||||
SolidCommandBuffer();
|
||||
void fill(SolidPassMeshMap *mesh_map);
|
||||
void fill(MeshMap *mesh_map);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** First rendering pass; draw all meshes associated with the same material
|
||||
@ -458,7 +455,7 @@ class ShadowCommandBuffer: public CommandBuffer<4*static_cast<int>(Material::SHA
|
||||
{
|
||||
public:
|
||||
ShadowCommandBuffer();
|
||||
void fill(OtherMeshMap *mesh_map);
|
||||
void fill(MeshMap *mesh_map);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Draw shadowmaps for meshes with the same material
|
||||
@ -532,7 +529,7 @@ class ReflectiveShadowMapCommandBuffer: public CommandBuffer<static_cast<int>(Ma
|
||||
{
|
||||
public:
|
||||
ReflectiveShadowMapCommandBuffer();
|
||||
void fill(OtherMeshMap *mesh_map);
|
||||
void fill(MeshMap *mesh_map);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Draw reflective shadow map for meshes with the same material
|
||||
@ -615,7 +612,7 @@ class GlowCommandBuffer: public CommandBuffer<1>
|
||||
{
|
||||
public:
|
||||
GlowCommandBuffer();
|
||||
void fill(OtherMeshMap *mesh_map);
|
||||
void fill(MeshMap *mesh_map);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Draw glowing meshes.
|
||||
|
@ -24,6 +24,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"
|
||||
@ -31,11 +32,14 @@
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/profiler.hpp"
|
||||
|
||||
#include <numeric>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void DrawCalls::clearLists()
|
||||
{
|
||||
ListBlendTransparent::getInstance()->clear();
|
||||
ListAdditiveTransparent::getInstance()->clear();
|
||||
ListTranslucentSkinned::getInstance()->clear();
|
||||
ListTranslucentStandard::getInstance()->clear();
|
||||
ListTranslucentTangents::getInstance()->clear();
|
||||
ListTranslucent2TCoords::getInstance()->clear();
|
||||
@ -43,6 +47,10 @@ void DrawCalls::clearLists()
|
||||
ListAdditiveTransparentFog::getInstance()->clear();
|
||||
ListDisplacement::getInstance()->clear();
|
||||
|
||||
ListSkinnedSolid::getInstance()->clear();
|
||||
ListSkinnedAlphaRef::getInstance()->clear();
|
||||
ListSkinnedNormalMap::getInstance()->clear();
|
||||
ListSkinnedUnlit::getInstance()->clear();
|
||||
ListMatDefault::getInstance()->clear();
|
||||
ListMatAlphaRef::getInstance()->clear();
|
||||
ListMatSphereMap::getInstance()->clear();
|
||||
@ -243,8 +251,34 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
|
||||
for (GLMesh *mesh : node->TransparentMesh[TM_DISPLACEMENT])
|
||||
pushVector(ListDisplacement::getInstance(), mesh, Node->getAbsoluteTransformation());
|
||||
|
||||
int32_t skinning_offset = 0;
|
||||
STKAnimatedMesh* am = dynamic_cast<STKAnimatedMesh*>(Node);
|
||||
if (am && am->useHardwareSkinning() &&
|
||||
(!culled_for_cams[0] || !culled_for_cams[1] || !culled_for_cams[2] ||
|
||||
!culled_for_cams[3] || !culled_for_cams[4] || !culled_for_cams[5]))
|
||||
{
|
||||
skinning_offset = getSkinningOffset() + 1/*reserved identity matrix*/;
|
||||
if (skinning_offset + am->getTotalJoints() >
|
||||
SharedGPUObjects::getMaxMat4Size())
|
||||
{
|
||||
Log::error("DrawCalls", "Don't have enough space to render skinned"
|
||||
" mesh %s! Max joints can hold: %d",
|
||||
am->getMeshDebugName().c_str(),
|
||||
SharedGPUObjects::getMaxMat4Size());
|
||||
return;
|
||||
}
|
||||
m_mesh_for_skinning.insert(am);
|
||||
am->setSkinningOffset(skinning_offset * 16 * sizeof(float));
|
||||
}
|
||||
|
||||
if (!culled_for_cams[0])
|
||||
{
|
||||
for (GLMesh *mesh : node->TransparentMesh[TM_TRANSLUCENT_SKN])
|
||||
{
|
||||
pushVector(ListTranslucentSkinned::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans,
|
||||
skinning_offset, (mesh->m_render_info && mesh->m_render_info->isTransparent() ? custom_alpha : 1.0f));
|
||||
}
|
||||
|
||||
for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
|
||||
{
|
||||
if (CVS->supportsIndirectInstancingRendering())
|
||||
@ -255,7 +289,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 +301,11 @@ 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);
|
||||
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,
|
||||
m_solid_pass_mesh[Mat][mesh->mb].m_mesh = mesh;
|
||||
m_solid_pass_mesh[Mat][mesh->mb].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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -288,6 +318,28 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
|
||||
{
|
||||
switch (Mat)
|
||||
{
|
||||
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_SKINNED_MESH:
|
||||
ListSkinnedAlphaRef::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_SOLID_UNLIT_SKINNED_MESH:
|
||||
ListSkinnedUnlit::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans,
|
||||
core::vector2df(0.0f, 0.0f), skinning_offset);
|
||||
break;
|
||||
case Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH:
|
||||
ListSkinnedNormalMap::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_SOLID:
|
||||
ListMatDefault::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans,
|
||||
(mesh->m_render_info && mesh->m_material ?
|
||||
@ -351,7 +403,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
|
||||
@ -363,6 +415,22 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
|
||||
{
|
||||
switch (Mat)
|
||||
{
|
||||
case Material::SHADERTYPE_SOLID_SKINNED_MESH:
|
||||
ListSkinnedSolid::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans,
|
||||
core::vector2df(0.0f, 0.0f), skinning_offset);
|
||||
break;
|
||||
case Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH:
|
||||
ListSkinnedAlphaRef::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans,
|
||||
core::vector2df(0.0f, 0.0f), skinning_offset);
|
||||
break;
|
||||
case Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH:
|
||||
ListSkinnedUnlit::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans,
|
||||
core::vector2df(0.0f, 0.0f), skinning_offset);
|
||||
break;
|
||||
case Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH:
|
||||
ListSkinnedNormalMap::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans,
|
||||
core::vector2df(0.0f, 0.0f), skinning_offset);
|
||||
break;
|
||||
case Material::SHADERTYPE_SOLID:
|
||||
ListMatDefault::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f));
|
||||
break;
|
||||
@ -419,7 +487,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -432,6 +500,12 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
|
||||
{
|
||||
switch (Mat)
|
||||
{
|
||||
// Todo: RSMs
|
||||
case Material::SHADERTYPE_SOLID_SKINNED_MESH:
|
||||
case Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH:
|
||||
case Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH:
|
||||
case Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH:
|
||||
break;
|
||||
case Material::SHADERTYPE_SOLID:
|
||||
ListMatDefault::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f));
|
||||
break;
|
||||
@ -551,7 +625,7 @@ void DrawCalls::prepareDrawCalls( ShadowMatrices& shadow_matrices,
|
||||
{
|
||||
m_wind_dir = getWindDir();
|
||||
clearLists();
|
||||
|
||||
m_mesh_for_skinning.clear();
|
||||
for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
|
||||
{
|
||||
m_solid_pass_mesh[Mat].clear();
|
||||
@ -569,6 +643,7 @@ void DrawCalls::prepareDrawCalls( ShadowMatrices& shadow_matrices,
|
||||
&m_immediate_draw_list, camnode, shadow_matrices);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
irr_driver->setSkinningJoint(getSkinningOffset());
|
||||
// Add a 1 s timeout
|
||||
if (!m_sync)
|
||||
m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
@ -688,7 +763,13 @@ void DrawCalls::drawIndirectSolidFirstPass() const
|
||||
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>();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -704,7 +785,13 @@ void DrawCalls::multidrawSolidFirstPass() const
|
||||
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>();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -724,6 +811,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);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -742,6 +835,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);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -792,6 +891,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);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -810,6 +915,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);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -866,4 +977,12 @@ void DrawCalls::multidrawGlow() const
|
||||
}
|
||||
#endif // !defined(USE_GLES2)
|
||||
|
||||
#endif // !SERVER_ONLY
|
||||
// ----------------------------------------------------------------------------
|
||||
int32_t DrawCalls::getSkinningOffset() const
|
||||
{
|
||||
return std::accumulate(m_mesh_for_skinning.begin(),
|
||||
m_mesh_for_skinning.end(), 0, []
|
||||
(const size_t previous, const STKAnimatedMesh* m)
|
||||
{ return previous + m->getTotalJoints(); });
|
||||
} // getSkinningOffset
|
||||
#endif // !SERVER_ONLY
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
class ParticleSystemProxy;
|
||||
class ShadowMatrices;
|
||||
class STKAnimatedMesh;
|
||||
class STKBillboard;
|
||||
|
||||
class DrawCalls
|
||||
@ -37,14 +38,15 @@ private:
|
||||
std::vector<irr::scene::ISceneNode *> m_immediate_draw_list;
|
||||
std::vector<STKBillboard *> m_billboard_list;
|
||||
std::vector<ParticleSystemProxy *> m_particles_list;
|
||||
std::set<STKAnimatedMesh*> m_mesh_for_skinning;
|
||||
|
||||
std::vector<float> m_bounding_boxes;
|
||||
|
||||
/** meshes to draw */
|
||||
SolidPassMeshMap m_solid_pass_mesh [ Material::SHADERTYPE_COUNT];
|
||||
OtherMeshMap m_shadow_pass_mesh [4 * Material::SHADERTYPE_COUNT];
|
||||
OtherMeshMap m_reflective_shadow_map_mesh [ Material::SHADERTYPE_COUNT];
|
||||
OtherMeshMap m_glow_pass_mesh;
|
||||
MeshMap m_solid_pass_mesh [ Material::SHADERTYPE_COUNT];
|
||||
MeshMap m_shadow_pass_mesh [4 * Material::SHADERTYPE_COUNT];
|
||||
MeshMap m_reflective_shadow_map_mesh [ Material::SHADERTYPE_COUNT];
|
||||
MeshMap m_glow_pass_mesh;
|
||||
|
||||
#if !defined(USE_GLES2)
|
||||
/** meshes data in VRAM */
|
||||
@ -106,6 +108,7 @@ public:
|
||||
void drawIndirectGlow() const;
|
||||
void multidrawGlow() const;
|
||||
void renderBoundingBoxes();
|
||||
int32_t getSkinningOffset() const;
|
||||
};
|
||||
|
||||
#endif // !SERVER_ONLY
|
||||
|
@ -185,6 +185,12 @@ void GL3DrawPolicy::drawSolidFirstPass(const DrawCalls& draw_calls) const
|
||||
renderMeshes1stPass<NormalMat, 2, 1>();
|
||||
renderMeshes1stPass<SphereMap, 2, 1>();
|
||||
renderMeshes1stPass<DetailMat, 2, 1>();
|
||||
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
renderMeshes1stPass<SkinnedSolid, 5, 2, 1>();
|
||||
renderMeshes1stPass<SkinnedAlphaRef, 5, 3, 2, 1>();
|
||||
renderMeshes1stPass<SkinnedUnlitMat, 5, 3, 2, 1>();
|
||||
renderMeshes1stPass<SkinnedNormalMat, 5, 2, 1>();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -200,6 +206,12 @@ void GL3DrawPolicy::drawSolidSecondPass (const DrawCalls& draw_calls,
|
||||
renderMeshes2ndPass<DetailMat, 1 > (handles, prefilled_tex);
|
||||
renderMeshes2ndPass<GrassMat, 4, 3, 1> (handles, prefilled_tex);
|
||||
renderMeshes2ndPass<NormalMat, 4, 3, 1> (handles, prefilled_tex);
|
||||
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
renderMeshes2ndPass<SkinnedSolid, 5, 4, 3, 1> (handles, prefilled_tex);
|
||||
renderMeshes2ndPass<SkinnedAlphaRef, 5, 4, 3, 1> (handles, prefilled_tex);
|
||||
renderMeshes2ndPass<SkinnedUnlitMat, 5, 3, 1 > (handles, prefilled_tex);
|
||||
renderMeshes2ndPass<SkinnedNormalMat, 5, 4, 3, 1> (handles, prefilled_tex);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -222,6 +234,12 @@ void GL3DrawPolicy::drawShadows(const DrawCalls& draw_calls, unsigned cascade) c
|
||||
renderShadow<AlphaRef, 1>(cascade);
|
||||
renderShadow<UnlitMat, 1>(cascade);
|
||||
renderShadow<GrassMat, 3, 1>(cascade);
|
||||
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
renderShadow<SkinnedSolid, 5, 1>(cascade);
|
||||
renderShadow<SkinnedAlphaRef, 5, 1>(cascade);
|
||||
renderShadow<SkinnedUnlitMat, 5, 1>(cascade);
|
||||
renderShadow<SkinnedNormalMat, 5, 1>(cascade);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -242,6 +242,14 @@ void AbstractGeometryPasses::renderTransparent(const DrawCalls& draw_calls,
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
if (CVS->supportsHardwareSkinning())
|
||||
{
|
||||
renderTransparenPass<Shaders::SkinnedTransparentShader, video::EVT_SKINNED_MESH, 4, 3, 2, 1>(
|
||||
TexUnits(RenderGeometry::TexUnit(0, true)),
|
||||
ListTranslucentSkinned::getInstance());
|
||||
}
|
||||
|
||||
renderTransparenPass<Shaders::TransparentShader, video::EVT_STANDARD, 3, 2, 1>(
|
||||
TexUnits(RenderGeometry::TexUnit(0, true)),
|
||||
ListTranslucentStandard::getInstance());
|
||||
|
@ -142,6 +142,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(4);
|
||||
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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -143,6 +143,8 @@ IrrDriver::IrrDriver()
|
||||
m_boundingboxesviz = false;
|
||||
m_last_light_bucket_distance = 0;
|
||||
m_clear_color = video::SColor(255, 100, 101, 140);
|
||||
m_skinning_joint = 0;
|
||||
|
||||
} // IrrDriver
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -917,7 +919,6 @@ void IrrDriver::applyResolutionSettings()
|
||||
// FIXME: this load sequence is (mostly) duplicated from main.cpp!!
|
||||
// That's just error prone
|
||||
// (we're sure to update main.cpp at some point and forget this one...)
|
||||
ShaderBase::updateShaders();
|
||||
VAOManager::getInstance()->kill();
|
||||
resetTextureTable();
|
||||
cleanUnicolorTextures();
|
||||
@ -928,6 +929,7 @@ void IrrDriver::applyResolutionSettings()
|
||||
}
|
||||
delete m_renderer;
|
||||
initDevice();
|
||||
ShaderBase::updateShaders();
|
||||
|
||||
font_manager = new FontManager();
|
||||
font_manager->loadFonts();
|
||||
@ -1959,10 +1961,12 @@ void IrrDriver::displayFPS()
|
||||
|
||||
if ((UserConfigParams::m_artist_debug_mode)&&(CVS->isGLSL()))
|
||||
{
|
||||
fps_string = _("FPS: %d/%d/%d - PolyCount: %d Solid, "
|
||||
"%d Shadows - LightDist : %d",
|
||||
fps_string = StringUtils::insertValues
|
||||
(L"FPS: %d/%d/%d - PolyCount: %d Solid, "
|
||||
"%d Shadows - LightDist : %d, Total skinning joints: %d",
|
||||
min, fps, max, m_renderer->getPolyCount(SOLID_NORMAL_AND_DEPTH_PASS),
|
||||
m_renderer->getPolyCount(SHADOW_PASS), m_last_light_bucket_distance);
|
||||
m_renderer->getPolyCount(SHADOW_PASS), m_last_light_bucket_distance,
|
||||
m_skinning_joint);
|
||||
}
|
||||
else
|
||||
fps_string = _("FPS: %d/%d/%d - %d KTris", min, fps, max, (int)roundf(kilotris));
|
||||
|
@ -177,6 +177,7 @@ private:
|
||||
|
||||
|
||||
unsigned m_last_light_bucket_distance;
|
||||
unsigned m_skinning_joint;
|
||||
u32 m_renderpass;
|
||||
class STKMeshSceneNode *m_sun_interposer;
|
||||
core::vector3df m_sun_direction;
|
||||
@ -296,6 +297,7 @@ public:
|
||||
void showPointer();
|
||||
void hidePointer();
|
||||
void setLastLightBucketDistance(unsigned d) { m_last_light_bucket_distance = d; }
|
||||
void setSkinningJoint(unsigned d) { m_skinning_joint = d; }
|
||||
bool isPointerShown() const { return m_pointer_shown; }
|
||||
core::position2di getMouseLocation();
|
||||
|
||||
|
@ -48,15 +48,19 @@ public:
|
||||
enum ShaderType
|
||||
{
|
||||
SHADERTYPE_SOLID = 0,
|
||||
SHADERTYPE_SOLID_SKINNED_MESH,
|
||||
SHADERTYPE_ALPHA_TEST,
|
||||
SHADERTYPE_ALPHA_TEST_SKINNED_MESH,
|
||||
SHADERTYPE_ALPHA_BLEND,
|
||||
SHADERTYPE_ADDITIVE,
|
||||
SHADERTYPE_SOLID_UNLIT,
|
||||
SHADERTYPE_SOLID_UNLIT_SKINNED_MESH,
|
||||
/** Effect that makes grass wave as in the wind */
|
||||
SHADERTYPE_VEGETATION,
|
||||
SHADERTYPE_WATER,
|
||||
SHADERTYPE_SPHERE_MAP,
|
||||
SHADERTYPE_NORMAL_MAP,
|
||||
SHADERTYPE_NORMAL_MAP_SKINNED_MESH,
|
||||
SHADERTYPE_DETAIL_MAP,
|
||||
SHADERTYPE_SPLATTING,
|
||||
SHADERTYPE_COUNT,
|
||||
|
@ -19,6 +19,37 @@
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
|
||||
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> SkinnedAlphaRef::FirstPassTextures
|
||||
= 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);
|
||||
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);
|
||||
const STK::Tuple<size_t, size_t, size_t> DefaultMaterial::SecondPassTextures
|
||||
|
@ -145,18 +145,17 @@ public:
|
||||
InstancedShadowShader()
|
||||
{
|
||||
#if !defined(USE_GLES2)
|
||||
// Geometry shader needed
|
||||
// Geometry shader needed
|
||||
if (CVS->getGLSLVersion() < 150)
|
||||
return;
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanciedshadow.vert",
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_shadow.vert",
|
||||
GL_FRAGMENT_SHADER, "shadow.frag");
|
||||
}
|
||||
else
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanciedshadow.vert",
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_shadow.vert",
|
||||
GL_GEOMETRY_SHADER, "instanced_shadow.geom",
|
||||
GL_FRAGMENT_SHADER, "shadow.frag");
|
||||
}
|
||||
@ -297,8 +296,8 @@ public:
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert",
|
||||
GL_FRAGMENT_SHADER, "normalmap.frag");
|
||||
assignUniforms("ModelMatrix", "InverseModelMatrix");
|
||||
assignSamplerNames(1, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED,
|
||||
0, "DiffuseForAlpha", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||
assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED,
|
||||
1, "glossMap", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||
} // NormalMapShader
|
||||
|
||||
}; // NormalMapShader
|
||||
@ -391,12 +390,12 @@ public:
|
||||
return;
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
{
|
||||
loadProgram(OBJECT,GL_VERTEX_SHADER, "instanciedshadow.vert",
|
||||
loadProgram(OBJECT,GL_VERTEX_SHADER, "instanced_shadow.vert",
|
||||
GL_FRAGMENT_SHADER, "instanced_shadowref.frag");
|
||||
}
|
||||
else
|
||||
{
|
||||
loadProgram(OBJECT,GL_VERTEX_SHADER, "instanciedshadow.vert",
|
||||
loadProgram(OBJECT,GL_VERTEX_SHADER, "instanced_shadow.vert",
|
||||
GL_GEOMETRY_SHADER, "instanced_shadow.geom",
|
||||
GL_FRAGMENT_SHADER, "instanced_shadowref.frag");
|
||||
}
|
||||
@ -523,12 +522,12 @@ public:
|
||||
return;
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanciedgrassshadow.vert",
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_grassshadow.vert",
|
||||
GL_FRAGMENT_SHADER, "instanced_shadowref.frag");
|
||||
}
|
||||
else
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanciedgrassshadow.vert",
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_grassshadow.vert",
|
||||
GL_GEOMETRY_SHADER, "instanced_shadow.geom",
|
||||
GL_FRAGMENT_SHADER, "instanced_shadowref.frag");
|
||||
}
|
||||
@ -618,8 +617,415 @@ public:
|
||||
} // InstancedDetailedObjectPass2Shader
|
||||
}; // InstancedDetailedObjectPass2Shader
|
||||
|
||||
// ============================================================================
|
||||
class SkinnedPass1Shader : public TextureShader<SkinnedPass1Shader, 1,
|
||||
core::matrix4, core::matrix4,
|
||||
int>
|
||||
{
|
||||
public:
|
||||
SkinnedPass1Shader()
|
||||
{
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
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);
|
||||
} // SkinnedPass1Shader
|
||||
}; // SkinnedPass1Shader
|
||||
|
||||
// ============================================================================
|
||||
class InstancedSkinnedPass1Shader : public TextureShader<InstancedSkinnedPass1Shader, 1>
|
||||
{
|
||||
public:
|
||||
InstancedSkinnedPass1Shader()
|
||||
{
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert",
|
||||
GL_FRAGMENT_SHADER, "instanced_object_pass1.frag");
|
||||
assignUniforms();
|
||||
assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||
} // InstancedSkinnedPass1Shader
|
||||
}; // InstancedSkinnedPass1Shader
|
||||
|
||||
// ============================================================================
|
||||
class SkinnedPass2Shader : public TextureShader<SkinnedPass2Shader, 6,
|
||||
core::matrix4, core::vector2df,
|
||||
core::vector2df, int >
|
||||
{
|
||||
public:
|
||||
SkinnedPass2Shader()
|
||||
{
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
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);
|
||||
} // SkinnedPass2Shader
|
||||
}; // SkinnedPass2Shader
|
||||
|
||||
// ============================================================================
|
||||
class InstancedSkinnedPass2Shader : public TextureShader<InstancedSkinnedPass2Shader, 6>
|
||||
{
|
||||
public:
|
||||
InstancedSkinnedPass2Shader()
|
||||
{
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
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);
|
||||
} // InstancedSkinnedPass2Shader
|
||||
}; // InstancedSkinnedPass2Shader
|
||||
|
||||
// ============================================================================
|
||||
class SkinnedRefPass1Shader : public TextureShader<SkinnedRefPass1Shader, 2,
|
||||
core::matrix4,
|
||||
core::matrix4,
|
||||
core::vector2df, int>
|
||||
{
|
||||
public:
|
||||
SkinnedRefPass1Shader()
|
||||
{
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert",
|
||||
GL_FRAGMENT_SHADER, "objectref_pass1.frag");
|
||||
assignUniforms("ModelMatrix", "InverseModelMatrix", "texture_trans",
|
||||
"skinning_offset");
|
||||
assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED,
|
||||
1, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||
} // SkinnedRefPass1Shader
|
||||
}; // SkinnedRefPass1Shader
|
||||
|
||||
// ============================================================================
|
||||
class InstancedSkinnedRefPass1Shader : public TextureShader<InstancedSkinnedRefPass1Shader, 2>
|
||||
{
|
||||
public:
|
||||
InstancedSkinnedRefPass1Shader()
|
||||
{
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert",
|
||||
GL_FRAGMENT_SHADER, "instanced_objectref_pass1.frag");
|
||||
assignUniforms();
|
||||
assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED,
|
||||
1, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||
} // InstancedSkinnedRefPass1Shader
|
||||
}; // InstancedSkinnedRefPass1Shader
|
||||
|
||||
// ============================================================================
|
||||
class SkinnedRefPass2Shader : public TextureShader<SkinnedRefPass2Shader, 6,
|
||||
core::matrix4,
|
||||
core::vector2df,
|
||||
core::vector2df, int>
|
||||
{
|
||||
public:
|
||||
SkinnedRefPass2Shader()
|
||||
{
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert",
|
||||
GL_FRAGMENT_SHADER, "objectref_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);
|
||||
} // SkinnedRefPass2Shader
|
||||
}; // SkinnedRefPass2Shader
|
||||
|
||||
// ============================================================================
|
||||
class InstancedSkinnedRefPass2Shader : public TextureShader<InstancedSkinnedRefPass2Shader, 6>
|
||||
{
|
||||
public:
|
||||
InstancedSkinnedRefPass2Shader()
|
||||
{
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert",
|
||||
GL_FRAGMENT_SHADER, "instanced_objectref_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);
|
||||
} // InstancedSkinnedRefPass2Shader
|
||||
}; // InstancedSkinnedRefPass2Shader
|
||||
|
||||
// ============================================================================
|
||||
class SkinnedUnlitShader : public TextureShader<SkinnedUnlitShader, 4,
|
||||
core::matrix4, core::vector2df,
|
||||
int>
|
||||
{
|
||||
public:
|
||||
SkinnedUnlitShader()
|
||||
{
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert",
|
||||
GL_FRAGMENT_SHADER, "object_unlit.frag");
|
||||
assignUniforms("ModelMatrix", "texture_trans", "skinning_offset");
|
||||
assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED,
|
||||
1, "SpecularMap", ST_NEAREST_FILTERED,
|
||||
2, "SSAO", ST_BILINEAR_FILTERED,
|
||||
3, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||
} // SkinnedUnlitShader
|
||||
}; // SkinnedUnlitShader
|
||||
|
||||
// ============================================================================
|
||||
class InstancedSkinnedUnlitShader : public TextureShader<InstancedSkinnedUnlitShader, 4>
|
||||
{
|
||||
public:
|
||||
InstancedSkinnedUnlitShader()
|
||||
{
|
||||
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);
|
||||
} // InstancedSkinnedUnlitShader
|
||||
}; // InstancedSkinnedUnlitShader
|
||||
|
||||
// ============================================================================
|
||||
class SkinnedNormalMapShader : public TextureShader<SkinnedNormalMapShader, 2,
|
||||
core::matrix4,
|
||||
core::matrix4, int>
|
||||
{
|
||||
public:
|
||||
SkinnedNormalMapShader()
|
||||
{
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert",
|
||||
GL_FRAGMENT_SHADER, "normalmap.frag");
|
||||
assignUniforms("ModelMatrix", "InverseModelMatrix", "skinning_offset");
|
||||
assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED,
|
||||
1, "glossMap", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||
} // SkinnedNormalMapShader
|
||||
}; // SkinnedNormalMapShader
|
||||
|
||||
// ============================================================================
|
||||
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 SkinnedShadowShader : public TextureShader<SkinnedShadowShader, 0,
|
||||
core::matrix4, int, int>
|
||||
{
|
||||
public:
|
||||
SkinnedShadowShader()
|
||||
{
|
||||
#if !defined(USE_GLES2)
|
||||
// Geometry shader needed
|
||||
if (CVS->getGLSLVersion() < 150 || !CVS->supportsHardwareSkinning())
|
||||
return;
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning_shadow.vert",
|
||||
GL_FRAGMENT_SHADER, "shadow.frag");
|
||||
}
|
||||
else
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning_shadow.vert",
|
||||
GL_GEOMETRY_SHADER, "shadow.geom",
|
||||
GL_FRAGMENT_SHADER, "shadow.frag");
|
||||
}
|
||||
assignUniforms("ModelMatrix", "skinning_offset", "layer");
|
||||
#endif
|
||||
} // SkinnedShadowShader
|
||||
}; // SkinnedShadowShader
|
||||
|
||||
// ============================================================================
|
||||
class InstancedSkinnedShadowShader : public TextureShader<InstancedSkinnedShadowShader, 0, int>
|
||||
{
|
||||
public:
|
||||
InstancedSkinnedShadowShader()
|
||||
{
|
||||
#if !defined(USE_GLES2)
|
||||
// Geometry shader needed
|
||||
if (CVS->getGLSLVersion() < 150 || !CVS->supportsHardwareSkinning())
|
||||
return;
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert",
|
||||
GL_FRAGMENT_SHADER, "shadow.frag");
|
||||
}
|
||||
else
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert",
|
||||
GL_GEOMETRY_SHADER, "instanced_shadow.geom",
|
||||
GL_FRAGMENT_SHADER, "shadow.frag");
|
||||
}
|
||||
assignUniforms("layer");
|
||||
#endif
|
||||
} // InstancedSkinnedShadowShader
|
||||
}; // InstancedSkinnedShadowShader
|
||||
|
||||
// ============================================================================
|
||||
class SkinnedRefShadowShader : public TextureShader<SkinnedRefShadowShader, 1,
|
||||
core::matrix4, int, int>
|
||||
{
|
||||
public:
|
||||
SkinnedRefShadowShader()
|
||||
{
|
||||
#if !defined(USE_GLES2)
|
||||
// Geometry shader needed
|
||||
if (CVS->getGLSLVersion() < 150 || !CVS->supportsHardwareSkinning())
|
||||
return;
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning_shadow.vert",
|
||||
GL_FRAGMENT_SHADER, "shadowref.frag");
|
||||
}
|
||||
else
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning_shadow.vert",
|
||||
GL_GEOMETRY_SHADER, "shadow.geom",
|
||||
GL_FRAGMENT_SHADER, "shadowref.frag");
|
||||
}
|
||||
assignUniforms("ModelMatrix", "skinning_offset", "layer");
|
||||
assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||
#endif
|
||||
} // SkinnedRefShadowShader
|
||||
}; // SkinnedRefShadowShader
|
||||
|
||||
// ============================================================================
|
||||
class InstancedSkinnedRefShadowShader : public TextureShader<InstancedSkinnedRefShadowShader,
|
||||
1, int>
|
||||
{
|
||||
public:
|
||||
InstancedSkinnedRefShadowShader()
|
||||
{
|
||||
#if !defined(USE_GLES2)
|
||||
// Geometry shader needed
|
||||
if (CVS->getGLSLVersion() < 150 || !CVS->supportsHardwareSkinning())
|
||||
return;
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert",
|
||||
GL_FRAGMENT_SHADER, "instanced_shadowref.frag");
|
||||
}
|
||||
else
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert",
|
||||
GL_GEOMETRY_SHADER, "instanced_shadow.geom",
|
||||
GL_FRAGMENT_SHADER, "instanced_shadowref.frag");
|
||||
}
|
||||
assignUniforms("layer");
|
||||
assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||
#endif
|
||||
} // InstancedSkinnedRefShadowShader
|
||||
}; // InstancedSkinnedRefShadowShader
|
||||
|
||||
// ============================================================================
|
||||
struct SkinnedSolid
|
||||
{
|
||||
typedef InstancedSkinnedPass1Shader InstancedFirstPassShader;
|
||||
typedef InstancedSkinnedPass2Shader InstancedSecondPassShader;
|
||||
typedef InstancedSkinnedShadowShader InstancedShadowPassShader;
|
||||
typedef SkinnedPass1Shader FirstPassShader;
|
||||
typedef SkinnedPass2Shader SecondPassShader;
|
||||
typedef SkinnedShadowShader ShadowPassShader;
|
||||
// Todo: RSMs
|
||||
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 = InstanceTypeThreeTex;
|
||||
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 SkinnedSolid
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
struct SkinnedAlphaRef
|
||||
{
|
||||
typedef InstancedSkinnedRefPass1Shader InstancedFirstPassShader;
|
||||
typedef InstancedSkinnedRefPass2Shader InstancedSecondPassShader;
|
||||
typedef InstancedSkinnedRefShadowShader InstancedShadowPassShader;
|
||||
typedef SkinnedRefPass1Shader FirstPassShader;
|
||||
typedef SkinnedRefPass2Shader SecondPassShader;
|
||||
typedef SkinnedRefShadowShader ShadowPassShader;
|
||||
// Todo: RSMs
|
||||
typedef ListSkinnedAlphaRef List;
|
||||
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_SKINNED_MESH;
|
||||
static const enum Material::ShaderType MaterialType =
|
||||
Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH;
|
||||
static const enum InstanceType Instance = InstanceTypeThreeTex;
|
||||
static const STK::Tuple<size_t, size_t> FirstPassTextures;
|
||||
static const STK::Tuple<size_t, size_t, size_t> SecondPassTextures;
|
||||
static const STK::Tuple<size_t> ShadowTextures;
|
||||
static const STK::Tuple<size_t> RSMTextures;
|
||||
}; // struct SkinnedAlphaRef
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
struct SkinnedNormalMat
|
||||
{
|
||||
typedef InstancedSkinnedNormalMapShader InstancedFirstPassShader;
|
||||
typedef InstancedSkinnedPass2Shader InstancedSecondPassShader;
|
||||
typedef InstancedSkinnedShadowShader InstancedShadowPassShader;
|
||||
typedef SkinnedNormalMapShader FirstPassShader;
|
||||
typedef SkinnedPass2Shader SecondPassShader;
|
||||
typedef SkinnedShadowShader 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 InstancedSkinnedRefPass1Shader InstancedFirstPassShader;
|
||||
typedef InstancedSkinnedUnlitShader InstancedSecondPassShader;
|
||||
typedef InstancedSkinnedRefShadowShader InstancedShadowPassShader;
|
||||
typedef SkinnedRefPass1Shader FirstPassShader;
|
||||
typedef SkinnedUnlitShader SecondPassShader;
|
||||
typedef SkinnedRefShadowShader 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
|
||||
{
|
||||
typedef InstancedObjectPass1Shader InstancedFirstPassShader;
|
||||
|
@ -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)
|
||||
@ -480,54 +482,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);
|
||||
}
|
||||
|
@ -19,197 +19,16 @@
|
||||
#ifndef SERVER_ONLY
|
||||
|
||||
#include "graphics/shader.hpp"
|
||||
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "graphics/gl_headers.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/shared_gpu_objects.hpp"
|
||||
#include "graphics/spherical_harmonics.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
|
||||
std::string ShaderBase::m_shader_header = "";
|
||||
std::vector<void(*)()> ShaderBase::m_all_kill_functions;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns a string with the content of header.txt (which contains basic
|
||||
* shader defines).
|
||||
*/
|
||||
const std::string& ShaderBase::getHeader()
|
||||
{
|
||||
// Only read file first time
|
||||
if (m_shader_header.empty())
|
||||
{
|
||||
std::ifstream stream(file_manager->getShader("header.txt"), std::ios::in);
|
||||
if (stream.is_open())
|
||||
{
|
||||
std::string line = "";
|
||||
while (getline(stream, line))
|
||||
m_shader_header += "\n" + line;
|
||||
stream.close();
|
||||
}
|
||||
} // if m_shader_header.empty()
|
||||
|
||||
return m_shader_header;
|
||||
} // getHeader
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Loads a single shader.
|
||||
* \param file Filename of the shader to load.
|
||||
* \param type Type of the shader.
|
||||
*/
|
||||
GLuint ShaderBase::loadShader(const std::string &file, unsigned type)
|
||||
{
|
||||
GLuint id = glCreateShader(type);
|
||||
|
||||
std::ostringstream code;
|
||||
#if !defined(USE_GLES2)
|
||||
code << "#version " << CVS->getGLSLVersion()<<"\n";
|
||||
#else
|
||||
if (CVS->isGLSL())
|
||||
code << "#version 300 es\n";
|
||||
#endif
|
||||
|
||||
#if !defined(USE_GLES2)
|
||||
// Some drivers report that the compute shaders extension is available,
|
||||
// but they report only OpenGL 3.x version, and thus these extensions
|
||||
// must be enabled manually. Otherwise the shaders compilation will fail
|
||||
// because STK tries to use extensions which are available, but disabled
|
||||
// by default.
|
||||
if (type == GL_COMPUTE_SHADER)
|
||||
{
|
||||
if (CVS->isARBComputeShaderUsable())
|
||||
code << "#extension GL_ARB_compute_shader : enable\n";
|
||||
if (CVS->isARBImageLoadStoreUsable())
|
||||
code << "#extension GL_ARB_shader_image_load_store : enable\n";
|
||||
if (CVS->isARBArraysOfArraysUsable())
|
||||
code << "#extension GL_ARB_arrays_of_arrays : enable\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
code << "#extension GL_AMD_vertex_shader_layer : enable\n";
|
||||
|
||||
if (CVS->isARBExplicitAttribLocationUsable())
|
||||
code << "#extension GL_ARB_explicit_attrib_location : enable\n";
|
||||
|
||||
if (CVS->isAZDOEnabled())
|
||||
{
|
||||
code << "#extension GL_ARB_bindless_texture : enable\n";
|
||||
code << "#define Use_Bindless_Texture\n";
|
||||
}
|
||||
code << "//" << file << "\n";
|
||||
if (!CVS->isARBUniformBufferObjectUsable())
|
||||
code << "#define UBO_DISABLED\n";
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
code << "#define VSLayer\n";
|
||||
if (CVS->needsRGBBindlessWorkaround())
|
||||
code << "#define SRGBBindlessFix\n";
|
||||
|
||||
#if !defined(USE_GLES2)
|
||||
//shader compilation fails with some drivers if there is no precision qualifier
|
||||
if (type == GL_FRAGMENT_SHADER)
|
||||
code << "precision mediump float;\n";
|
||||
#else
|
||||
int range[2], precision;
|
||||
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision);
|
||||
|
||||
if (precision > 0)
|
||||
code << "precision highp float;\n";
|
||||
else
|
||||
code << "precision mediump float;\n";
|
||||
#endif
|
||||
|
||||
code << getHeader();
|
||||
|
||||
std::ifstream stream(file_manager->getShader(file), std::ios::in);
|
||||
if (stream.is_open())
|
||||
{
|
||||
std::string Line = "";
|
||||
while (getline(stream, Line))
|
||||
{
|
||||
const std::string stk_include = "#stk_include";
|
||||
std::size_t pos = Line.find(stk_include);
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
std::size_t pos = Line.find("\"");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
Log::error("shader", "Invalid #stk_include line: '%s'.", Line.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string filename = Line.substr(pos+1);
|
||||
|
||||
pos = filename.find("\"");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
Log::error("shader", "Invalid #stk_include line: '%s'.", Line.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
filename = filename.substr(0, pos);
|
||||
|
||||
std::ifstream include_stream(file_manager->getShader(filename), std::ios::in);
|
||||
if (!include_stream.is_open())
|
||||
{
|
||||
Log::error("shader", "Couldn't open included shader: '%s'.", filename.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string include_line = "";
|
||||
while (getline(include_stream, include_line))
|
||||
{
|
||||
code << "\n" << include_line;
|
||||
}
|
||||
|
||||
include_stream.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
code << "\n" << Line;
|
||||
}
|
||||
}
|
||||
|
||||
stream.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("shader", "Can not open '%s'.", file.c_str());
|
||||
}
|
||||
|
||||
Log::info("shader", "Compiling shader : %s", file.c_str());
|
||||
const std::string &source = code.str();
|
||||
char const *source_pointer = source.c_str();
|
||||
int len = source.size();
|
||||
glShaderSource(id, 1, &source_pointer, &len);
|
||||
glCompileShader(id);
|
||||
|
||||
GLint result = GL_FALSE;
|
||||
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
int info_length;
|
||||
Log::error("GLWrap", "Error in shader %s", file.c_str());
|
||||
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &info_length);
|
||||
if (info_length<0)
|
||||
info_length = 1024;
|
||||
char *error_message = new char[info_length];
|
||||
error_message[0] = 0;
|
||||
glGetShaderInfoLog(id, info_length, NULL, error_message);
|
||||
Log::error("GLWrap", error_message);
|
||||
delete[] error_message;
|
||||
}
|
||||
|
||||
glGetError();
|
||||
|
||||
return id;
|
||||
} // loadShader
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Loads a transform feedback buffer shader with a given number of varying
|
||||
* parameters.
|
||||
@ -238,7 +57,7 @@ int ShaderBase::loadTFBProgram(const std::string &shader_name,
|
||||
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &info_log_length);
|
||||
char *error_message = new char[info_log_length];
|
||||
glGetProgramInfoLog(m_program, info_log_length, NULL, error_message);
|
||||
Log::error("GLWrap", error_message);
|
||||
Log::error("ShaderBase", error_message);
|
||||
delete[] error_message;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "graphics/gl_headers.hpp"
|
||||
#include "graphics/shader_files_manager.hpp"
|
||||
#include "graphics/shared_gpu_objects.hpp"
|
||||
#include "utils/singleton.hpp"
|
||||
|
||||
@ -40,13 +41,6 @@
|
||||
*/
|
||||
class ShaderBase
|
||||
{
|
||||
private:
|
||||
// Static members
|
||||
/** Stores the context of header.txt, to avoid reading
|
||||
* this file repeatedly. */
|
||||
static std::string m_shader_header;
|
||||
|
||||
|
||||
protected:
|
||||
/** Maintains a list of all shaders. */
|
||||
static std::vector<void (*)()> m_all_kill_functions;
|
||||
@ -75,9 +69,13 @@ protected:
|
||||
void loadAndAttachShader(GLint shader_type, const std::string &name,
|
||||
Types ... args)
|
||||
{
|
||||
GLint shader_id = loadShader(name, shader_type);
|
||||
GLint shader_id = ShaderFilesManager::getInstance()
|
||||
->getShaderFile(name, shader_type);
|
||||
glAttachShader(m_program, shader_id);
|
||||
glDeleteShader(shader_id);
|
||||
GLint is_deleted = GL_TRUE;
|
||||
glGetShaderiv(shader_id, GL_DELETE_STATUS, &is_deleted);
|
||||
if (is_deleted == GL_FALSE)
|
||||
glDeleteShader(shader_id);
|
||||
loadAndAttachShader(args...);
|
||||
} // loadAndAttachShader
|
||||
// ------------------------------------------------------------------------
|
||||
@ -89,9 +87,6 @@ protected:
|
||||
loadAndAttachShader(shader_type, std::string(name), args...);
|
||||
} // loadAndAttachShader
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
const std::string& getHeader();
|
||||
GLuint loadShader(const std::string &file, unsigned type);
|
||||
void setAttribute(AttributeType type);
|
||||
|
||||
public:
|
||||
@ -152,6 +147,7 @@ private:
|
||||
{
|
||||
bindPoint("MatrixData", 0);
|
||||
bindPoint("LightingData", 1);
|
||||
bindPoint("SkinningData", 2);
|
||||
} // assignUniformsImpl
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@ -360,12 +356,12 @@ public:
|
||||
glGetProgramiv(m_program, GL_LINK_STATUS, &Result);
|
||||
if (Result == GL_FALSE) {
|
||||
int info_length;
|
||||
Log::error("GLWrapp", "Error when linking these shaders :");
|
||||
Log::error("Shader", "Error when linking these shaders :");
|
||||
printFileList(args...);
|
||||
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &info_length);
|
||||
char *error_message = new char[info_length];
|
||||
glGetProgramInfoLog(m_program, info_length, NULL, error_message);
|
||||
Log::error("GLWrapp", error_message);
|
||||
Log::error("Shader", error_message);
|
||||
delete[] error_message;
|
||||
}
|
||||
} // loadProgram
|
||||
|
@ -268,10 +268,12 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode,
|
||||
bool hasShadow,
|
||||
bool forceRTT)
|
||||
{
|
||||
if(CVS->isARBUniformBufferObjectUsable())
|
||||
if (CVS->isARBUniformBufferObjectUsable())
|
||||
{
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedGPUObjects::getViewProjectionMatricesUBO());
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 1, SharedGPUObjects::getLightingDataUBO());
|
||||
if (CVS->supportsHardwareSkinning())
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 2, SharedGPUObjects::getSkinningUBO());
|
||||
}
|
||||
irr_driver->getSceneManager()->setActiveCamera(camnode);
|
||||
|
||||
@ -639,7 +641,9 @@ ShaderBasedRenderer::ShaderBasedRenderer()
|
||||
m_skybox = NULL;
|
||||
m_spherical_harmonics = new SphericalHarmonics(irr_driver->getAmbientLight().toSColor());
|
||||
m_nb_static_glowing = 0;
|
||||
|
||||
Log::info("ShaderBasedRenderer", "Preloading shaders...");
|
||||
preloadShaderFiles();
|
||||
|
||||
if (CVS->isAZDOEnabled())
|
||||
{
|
||||
m_geometry_passes = new GeometryPasses<MultidrawPolicy>();
|
||||
@ -655,7 +659,7 @@ ShaderBasedRenderer::ShaderBasedRenderer()
|
||||
m_geometry_passes = new GeometryPasses<GL3DrawPolicy>();
|
||||
Log::info("ShaderBasedRenderer", "Geometry will be rendered with GL3 policy.");
|
||||
}
|
||||
|
||||
|
||||
m_post_processing = new PostProcessing(irr_driver->getVideoDriver());
|
||||
}
|
||||
|
||||
@ -679,6 +683,7 @@ ShaderBasedRenderer::~ShaderBasedRenderer()
|
||||
delete m_spherical_harmonics;
|
||||
delete m_skybox;
|
||||
delete m_rtts;
|
||||
ShaderFilesManager::kill();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -698,7 +703,7 @@ void ShaderBasedRenderer::onUnloadWorld()
|
||||
{
|
||||
delete m_rtts;
|
||||
m_rtts = NULL;
|
||||
removeSkyBox();
|
||||
removeSkyBox();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -959,4 +964,60 @@ void ShaderBasedRenderer::renderToTexture(GL3RenderTarget *render_target,
|
||||
|
||||
} //renderToTexture
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void ShaderBasedRenderer::preloadShaderFiles()
|
||||
{
|
||||
ShaderFilesManager* sfm = ShaderFilesManager::getInstance();
|
||||
|
||||
sfm->addShaderFile("object_pass.vert", GL_VERTEX_SHADER);
|
||||
sfm->addShaderFile("object_pass1.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("splatting.frag", GL_FRAGMENT_SHADER);
|
||||
if (CVS->supportsHardwareSkinning())
|
||||
sfm->addShaderFile("skinning.vert", GL_VERTEX_SHADER);
|
||||
sfm->addShaderFile("transparent.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("coloredquad.vert", GL_VERTEX_SHADER);
|
||||
sfm->addShaderFile("coloredquad.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("screenquad.vert", GL_VERTEX_SHADER);
|
||||
sfm->addShaderFile("tonemap.frag", GL_FRAGMENT_SHADER);
|
||||
if (!GraphicsRestrictions::isDisabled
|
||||
(GraphicsRestrictions::GR_FRAMEBUFFER_SRGB_WORKING))
|
||||
sfm->addShaderFile("passthrough.frag", GL_FRAGMENT_SHADER);
|
||||
|
||||
sfm->addShaderFile("billboard.vert", GL_VERTEX_SHADER);
|
||||
sfm->addShaderFile("billboard.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("pointemitter.vert", GL_VERTEX_SHADER);
|
||||
sfm->addShaderFile("particle.vert", GL_VERTEX_SHADER);
|
||||
sfm->addShaderFile("particle.frag", GL_FRAGMENT_SHADER);
|
||||
|
||||
if (CVS->supportsIndirectInstancingRendering())
|
||||
{
|
||||
sfm->addShaderFile("instanced_object_pass.vert", GL_VERTEX_SHADER);
|
||||
if (CVS->supportsHardwareSkinning())
|
||||
sfm->addShaderFile("instanced_skinning.vert", GL_VERTEX_SHADER);
|
||||
sfm->addShaderFile("instanced_object_pass1.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("instanced_object_pass2.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("instanced_objectref_pass1.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("instanced_objectref_pass2.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("instanced_object_unlit.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("instanced_normalmap.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("instanced_grass.vert", GL_VERTEX_SHADER);
|
||||
sfm->addShaderFile("instanced_grass_pass2.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("instanced_objectpass_spheremap.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("instanced_detailed_object_pass2.frag", GL_FRAGMENT_SHADER);
|
||||
}
|
||||
else
|
||||
{
|
||||
sfm->addShaderFile("object_pass2.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("objectref_pass1.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("objectref_pass2.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("object_unlit.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("normalmap.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("grass_pass.vert", GL_VERTEX_SHADER);
|
||||
sfm->addShaderFile("grass_pass2.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("objectpass_spheremap.frag", GL_FRAGMENT_SHADER);
|
||||
sfm->addShaderFile("detailed_object_pass2.frag", GL_FRAGMENT_SHADER);
|
||||
}
|
||||
|
||||
} //preloadShaderFiles
|
||||
|
||||
#endif // !SERVER_ONLY
|
||||
|
@ -85,7 +85,7 @@ private:
|
||||
|
||||
void debugPhysics();
|
||||
void renderPostProcessing(Camera * const camera);
|
||||
|
||||
void preloadShaderFiles();
|
||||
|
||||
public:
|
||||
ShaderBasedRenderer();
|
||||
|
253
src/graphics/shader_files_manager.cpp
Normal file
253
src/graphics/shader_files_manager.cpp
Normal file
@ -0,0 +1,253 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2016 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
|
||||
#include "graphics/shader_files_manager.hpp"
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "graphics/shared_gpu_objects.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns a string with the content of header.txt (which contains basic
|
||||
* shader defines).
|
||||
*/
|
||||
const std::string& ShaderFilesManager::getHeader()
|
||||
{
|
||||
// Stores the content of header.txt, to avoid reading this file repeatedly.
|
||||
static std::string shader_header;
|
||||
|
||||
// Only read file first time
|
||||
if (shader_header.empty())
|
||||
{
|
||||
std::ifstream stream(file_manager->getShader("header.txt"), std::ios::in);
|
||||
if (stream.is_open())
|
||||
{
|
||||
std::string line = "";
|
||||
while (std::getline(stream, line))
|
||||
shader_header += "\n" + line;
|
||||
stream.close();
|
||||
}
|
||||
} // if shader_header.empty()
|
||||
|
||||
return shader_header;
|
||||
} // getHeader
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Loads a single shader. This is NOT cached, use addShaderFile for that.
|
||||
* \param file Filename of the shader to load.
|
||||
* \param type Type of the shader.
|
||||
*/
|
||||
GLuint ShaderFilesManager::loadShader(const std::string &file, unsigned type)
|
||||
{
|
||||
const GLuint id = glCreateShader(type);
|
||||
|
||||
std::ostringstream code;
|
||||
#if !defined(USE_GLES2)
|
||||
code << "#version " << CVS->getGLSLVersion()<<"\n";
|
||||
#else
|
||||
if (CVS->isGLSL())
|
||||
code << "#version 300 es\n";
|
||||
#endif
|
||||
|
||||
#if !defined(USE_GLES2)
|
||||
// Some drivers report that the compute shaders extension is available,
|
||||
// but they report only OpenGL 3.x version, and thus these extensions
|
||||
// must be enabled manually. Otherwise the shaders compilation will fail
|
||||
// because STK tries to use extensions which are available, but disabled
|
||||
// by default.
|
||||
if (type == GL_COMPUTE_SHADER)
|
||||
{
|
||||
if (CVS->isARBComputeShaderUsable())
|
||||
code << "#extension GL_ARB_compute_shader : enable\n";
|
||||
if (CVS->isARBImageLoadStoreUsable())
|
||||
code << "#extension GL_ARB_shader_image_load_store : enable\n";
|
||||
if (CVS->isARBArraysOfArraysUsable())
|
||||
code << "#extension GL_ARB_arrays_of_arrays : enable\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
code << "#extension GL_AMD_vertex_shader_layer : enable\n";
|
||||
|
||||
if (CVS->isARBExplicitAttribLocationUsable())
|
||||
code << "#extension GL_ARB_explicit_attrib_location : enable\n";
|
||||
|
||||
if (CVS->isAZDOEnabled())
|
||||
{
|
||||
code << "#extension GL_ARB_bindless_texture : enable\n";
|
||||
code << "#define Use_Bindless_Texture\n";
|
||||
}
|
||||
code << "//" << file << "\n";
|
||||
if (!CVS->isARBUniformBufferObjectUsable())
|
||||
code << "#define UBO_DISABLED\n";
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
code << "#define VSLayer\n";
|
||||
if (CVS->needsRGBBindlessWorkaround())
|
||||
code << "#define SRGBBindlessFix\n";
|
||||
|
||||
#if !defined(USE_GLES2)
|
||||
// shader compilation fails with some drivers if there is no precision
|
||||
// qualifier
|
||||
if (type == GL_FRAGMENT_SHADER)
|
||||
code << "precision mediump float;\n";
|
||||
#else
|
||||
int range[2], precision;
|
||||
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range,
|
||||
&precision);
|
||||
|
||||
if (precision > 0)
|
||||
code << "precision highp float;\n";
|
||||
else
|
||||
code << "precision mediump float;\n";
|
||||
#endif
|
||||
code << "#define MAX_BONES " << SharedGPUObjects::getMaxMat4Size() << "\n";
|
||||
|
||||
code << getHeader();
|
||||
|
||||
std::ifstream stream(file_manager->getShader(file), std::ios::in);
|
||||
if (stream.is_open())
|
||||
{
|
||||
const std::string stk_include = "#stk_include";
|
||||
std::string line;
|
||||
|
||||
while (std::getline(stream, line))
|
||||
{
|
||||
const std::size_t pos = line.find(stk_include);
|
||||
|
||||
// load the custom file pointed by the #stk_include directive
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
// find the start "
|
||||
std::size_t pos = line.find("\"");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
Log::error("ShaderFilesManager", "Invalid #stk_include"
|
||||
" line: '%s'.", line.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string filename = line.substr(pos + 1);
|
||||
|
||||
// find the end "
|
||||
pos = filename.find("\"");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
Log::error("ShaderFilesManager", "Invalid #stk_include"
|
||||
" line: '%s'.", line.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
filename = filename.substr(0, pos);
|
||||
|
||||
// read the whole include file
|
||||
std::ifstream include_stream(file_manager->getShader(filename), std::ios::in);
|
||||
if (!include_stream.is_open())
|
||||
{
|
||||
Log::error("ShaderFilesManager", "Couldn't open included"
|
||||
" shader: '%s'.", filename.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string include_line = "";
|
||||
while (std::getline(include_stream, include_line))
|
||||
{
|
||||
code << "\n" << include_line;
|
||||
}
|
||||
include_stream.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
code << "\n" << line;
|
||||
}
|
||||
}
|
||||
|
||||
stream.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ShaderFilesManager", "Can not open '%s'.", file.c_str());
|
||||
}
|
||||
|
||||
Log::info("ShaderFilesManager", "Compiling shader : %s", file.c_str());
|
||||
const std::string &source = code.str();
|
||||
char const *source_pointer = source.c_str();
|
||||
int len = source.size();
|
||||
glShaderSource(id, 1, &source_pointer, &len);
|
||||
glCompileShader(id);
|
||||
|
||||
GLint result = GL_FALSE;
|
||||
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
// failed to compile
|
||||
int info_length;
|
||||
Log::error("ShaderFilesManager", "Error in shader %s", file.c_str());
|
||||
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &info_length);
|
||||
if (info_length < 0)
|
||||
info_length = 1024;
|
||||
char *error_message = new char[info_length];
|
||||
error_message[0] = 0;
|
||||
glGetShaderInfoLog(id, info_length, NULL, error_message);
|
||||
Log::error("ShaderFilesManager", error_message);
|
||||
delete[] error_message;
|
||||
}
|
||||
glGetError();
|
||||
|
||||
return id;
|
||||
} // loadShader
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Loads a single shader file, and add it to the loaded (cached) list
|
||||
* \param file Filename of the shader to load.
|
||||
* \param type Type of the shader.
|
||||
*/
|
||||
GLuint ShaderFilesManager::addShaderFile(const std::string &file, unsigned type)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// Make sure no duplicated shader is added somewhere else
|
||||
std::unordered_map<std::string, GLuint>::const_iterator i =
|
||||
m_shader_files_loaded.find(file);
|
||||
assert(i == m_shader_files_loaded.end());
|
||||
#endif
|
||||
|
||||
const GLuint id = loadShader(file, type);
|
||||
m_shader_files_loaded[file] = id;
|
||||
return id;
|
||||
} // addShaderFile
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Get a shader file. If the shader is not already in the cache it will be loaded and cached.
|
||||
* \param file Filename of the shader to load.
|
||||
* \param type Type of the shader.
|
||||
*/
|
||||
GLuint ShaderFilesManager::getShaderFile(const std::string &file, unsigned type)
|
||||
{
|
||||
// found in cache
|
||||
auto it = m_shader_files_loaded.find(file);
|
||||
if (it != m_shader_files_loaded.end())
|
||||
return it->second;
|
||||
|
||||
// add to the cache now
|
||||
return addShaderFile(file, type);
|
||||
} // getShaderFile
|
||||
|
||||
#endif // !SERVER_ONLY
|
60
src/graphics/shader_files_manager.hpp
Normal file
60
src/graphics/shader_files_manager.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2016 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
|
||||
#ifndef HEADER_SHADER_FILES_MANAGER_HPP
|
||||
#define HEADER_SHADER_FILES_MANAGER_HPP
|
||||
|
||||
#include "graphics/gl_headers.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/singleton.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class ShaderFilesManager : public Singleton<ShaderFilesManager>, NoCopy
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Map from a filename to a shader indentifier. Used for caching shaders.
|
||||
*/
|
||||
std::unordered_map<std::string, GLuint> m_shader_files_loaded;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
const std::string& getHeader();
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
ShaderFilesManager() {}
|
||||
// ------------------------------------------------------------------------
|
||||
~ShaderFilesManager() { clean(); }
|
||||
// ------------------------------------------------------------------------
|
||||
void clean() { m_shader_files_loaded.clear(); }
|
||||
// ------------------------------------------------------------------------
|
||||
GLuint loadShader(const std::string &file, unsigned type);
|
||||
// ------------------------------------------------------------------------
|
||||
GLuint addShaderFile(const std::string &file, unsigned type);
|
||||
// ------------------------------------------------------------------------
|
||||
GLuint getShaderFile(const std::string &file, unsigned type);
|
||||
|
||||
}; // ShaderFilesManager
|
||||
|
||||
#endif
|
||||
|
||||
#endif // !SERVER_ONLY
|
@ -174,69 +174,6 @@ static std::string loadHeader()
|
||||
return result;
|
||||
} // loadHeader
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Mostly from shader tutorial
|
||||
GLuint loadShader(const char * file, unsigned type)
|
||||
{
|
||||
GLuint Id = glCreateShader(type);
|
||||
char versionString[20];
|
||||
#if !defined(USE_GLES2)
|
||||
sprintf(versionString, "#version %d\n", CVS->getGLSLVersion());
|
||||
#else
|
||||
if (CVS->isGLSL())
|
||||
sprintf(versionString, "#version 300 es\n");
|
||||
#endif
|
||||
std::string Code = versionString;
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
Code += "#extension GL_AMD_vertex_shader_layer : enable\n";
|
||||
if (CVS->isAZDOEnabled())
|
||||
{
|
||||
Code += "#extension GL_ARB_bindless_texture : enable\n";
|
||||
Code += "#define Use_Bindless_Texture\n";
|
||||
}
|
||||
std::ifstream Stream(file, std::ios::in);
|
||||
Code += "//" + std::string(file) + "\n";
|
||||
if (!CVS->isARBUniformBufferObjectUsable())
|
||||
Code += "#define UBO_DISABLED\n";
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
Code += "#define VSLayer\n";
|
||||
if (CVS->needsRGBBindlessWorkaround())
|
||||
Code += "#define SRGBBindlessFix\n";
|
||||
Code += loadHeader();
|
||||
if (Stream.is_open())
|
||||
{
|
||||
std::string Line = "";
|
||||
while (getline(Stream, Line))
|
||||
Code += "\n" + Line;
|
||||
Stream.close();
|
||||
}
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength;
|
||||
Log::info("GLWrap", "Compiling shader : %s", file);
|
||||
char const * SourcePointer = Code.c_str();
|
||||
int length = (int)strlen(SourcePointer);
|
||||
glShaderSource(Id, 1, &SourcePointer, &length);
|
||||
glCompileShader(Id);
|
||||
|
||||
glGetShaderiv(Id, GL_COMPILE_STATUS, &Result);
|
||||
if (Result == GL_FALSE)
|
||||
{
|
||||
Log::error("GLWrap", "Error in shader %s", file);
|
||||
glGetShaderiv(Id, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
if (InfoLogLength<0)
|
||||
InfoLogLength = 1024;
|
||||
char *ErrorMessage = new char[InfoLogLength];
|
||||
ErrorMessage[0] = 0;
|
||||
glGetShaderInfoLog(Id, InfoLogLength, NULL, ErrorMessage);
|
||||
Log::error("GLWrap", ErrorMessage);
|
||||
delete[] ErrorMessage;
|
||||
}
|
||||
|
||||
glGetError();
|
||||
|
||||
return Id;
|
||||
} // loadShader
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Shaders::loadShaders()
|
||||
{
|
||||
@ -361,6 +298,16 @@ Shaders::ObjectPass2Shader::ObjectPass2Shader()
|
||||
5, "colorization_mask", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||
} // ObjectPass2Shader
|
||||
|
||||
// ============================================================================
|
||||
Shaders::SkinnedTransparentShader::SkinnedTransparentShader()
|
||||
{
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert",
|
||||
GL_FRAGMENT_SHADER, "transparent.frag");
|
||||
assignUniforms("ModelMatrix", "texture_trans", "skinning_offset", "custom_alpha");
|
||||
assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||
} // SkinnedTransparentShader
|
||||
|
||||
// ============================================================================
|
||||
Shaders::TransparentShader::TransparentShader()
|
||||
{
|
||||
|
@ -155,6 +155,15 @@ public:
|
||||
}; // ObjectPass2Shader
|
||||
|
||||
// ========================================================================
|
||||
class SkinnedTransparentShader : public TextureShader<SkinnedTransparentShader, 1,
|
||||
core::matrix4, core::vector2df,
|
||||
int, float >
|
||||
{
|
||||
public:
|
||||
SkinnedTransparentShader();
|
||||
}; // SkinnedTransparentShader
|
||||
|
||||
// ========================================================================
|
||||
|
||||
|
||||
}; // class Shaders
|
||||
|
@ -19,6 +19,10 @@
|
||||
|
||||
#include "graphics/shared_gpu_objects.hpp"
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include "matrix4.h"
|
||||
#include <algorithm>
|
||||
|
||||
GLuint SharedGPUObjects::m_billboard_vbo;
|
||||
GLuint SharedGPUObjects::m_sky_tri_vbo;
|
||||
@ -31,6 +35,8 @@ 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;
|
||||
int SharedGPUObjects::m_max_mat4_size = 1024;
|
||||
bool SharedGPUObjects::m_has_been_initialised = false;
|
||||
|
||||
/** Initialises m_full_screen_quad_vbo.
|
||||
@ -168,6 +174,26 @@ void SharedGPUObjects::initLightingDataUBO()
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
} // initLightingDataUBO
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void SharedGPUObjects::initSkinningUBO()
|
||||
{
|
||||
assert(CVS->isARBUniformBufferObjectUsable());
|
||||
irr::core::matrix4 m;
|
||||
glGenBuffers(1, &m_skinning_ubo);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, m_skinning_ubo);
|
||||
int max_size = 0;
|
||||
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_size);
|
||||
max_size = std::min(max_size, 65536);
|
||||
m_max_mat4_size = max_size / 16 / sizeof(float);
|
||||
Log::info("SharedGPUObjects", "Hardware skinning supported, max joints"
|
||||
" support: %d", m_max_mat4_size);
|
||||
glBufferData(GL_UNIFORM_BUFFER, max_size, 0, GL_STREAM_DRAW);
|
||||
// Reserve a identity matrix for non moving mesh in animated model used by
|
||||
// vertex shader calculation
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, 16 * sizeof(float), m.pointer());
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
} // initSkinningUBO
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void SharedGPUObjects::initParticleQuadVBO()
|
||||
{
|
||||
@ -197,10 +223,12 @@ void SharedGPUObjects::init()
|
||||
initFrustrumVBO();
|
||||
initParticleQuadVBO();
|
||||
|
||||
if(CVS->isARBUniformBufferObjectUsable())
|
||||
if (CVS->isARBUniformBufferObjectUsable())
|
||||
{
|
||||
initShadowVPMUBO();
|
||||
initLightingDataUBO();
|
||||
initLightingDataUBO();
|
||||
if (CVS->supportsHardwareSkinning())
|
||||
initSkinningUBO();
|
||||
}
|
||||
|
||||
m_has_been_initialised = true;
|
||||
|
@ -37,6 +37,8 @@ private:
|
||||
static GLuint m_ui_vao;
|
||||
static GLuint m_quad_buffer;
|
||||
static GLuint m_quad_vbo;
|
||||
static GLuint m_skinning_ubo;
|
||||
static int m_max_mat4_size;
|
||||
|
||||
static void initQuadVBO();
|
||||
static void initQuadBuffer();
|
||||
@ -46,6 +48,7 @@ private:
|
||||
static void initShadowVPMUBO();
|
||||
static void initLightingDataUBO();
|
||||
static void initParticleQuadVBO();
|
||||
static void initSkinningUBO();
|
||||
|
||||
public:
|
||||
static void init();
|
||||
@ -116,7 +119,18 @@ public:
|
||||
assert(m_has_been_initialised);
|
||||
return m_quad_vbo;
|
||||
} // getQuadVBO
|
||||
}; // class SharedGPUObjecctS
|
||||
// ------------------------------------------------------------------------
|
||||
static GLuint getSkinningUBO()
|
||||
{
|
||||
assert(m_has_been_initialised);
|
||||
return m_skinning_ubo;
|
||||
} // getSkinningUBO
|
||||
// ------------------------------------------------------------------------
|
||||
static int getMaxMat4Size()
|
||||
{
|
||||
return m_max_mat4_size;
|
||||
} // getMaxMat4Size
|
||||
}; // class SharedGPUObjects
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -22,12 +22,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;
|
||||
|
||||
@ -36,7 +37,8 @@ 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), m_skinning_offset(-1)
|
||||
{
|
||||
isGLInitialized = false;
|
||||
isMaterialInitialized = false;
|
||||
@ -46,6 +48,7 @@ const core::vector3df& scale, RenderInfo* render_info, bool all_parts_colorized)
|
||||
#ifdef DEBUG
|
||||
m_debug_name = debug_name;
|
||||
#endif
|
||||
resetSkinningState(mesh);
|
||||
}
|
||||
|
||||
STKAnimatedMesh::~STKAnimatedMesh()
|
||||
@ -80,6 +83,7 @@ void STKAnimatedMesh::setMesh(scene::IAnimatedMesh* mesh)
|
||||
isMaterialInitialized = false;
|
||||
cleanGLMeshes();
|
||||
CAnimatedMeshSceneNode::setMesh(mesh);
|
||||
resetSkinningState(mesh);
|
||||
}
|
||||
|
||||
void STKAnimatedMesh::updateNoGL()
|
||||
@ -96,21 +100,22 @@ void STKAnimatedMesh::updateNoGL()
|
||||
|
||||
if (!isMaterialInitialized)
|
||||
{
|
||||
// Use a default render info to distinguish same mesh buffer created by
|
||||
// different animated mesh node in vao manager when using instanced
|
||||
// rendering
|
||||
RenderInfo* default_ri = NULL;
|
||||
if (CVS->isARBBaseInstanceUsable())
|
||||
{
|
||||
default_ri = new RenderInfo();
|
||||
m_static_render_info.push_back(default_ri);
|
||||
}
|
||||
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
const u32 mb_count = m->getMeshBufferCount();
|
||||
for (u32 i = 0; i < mb_count; ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
if (!mb)
|
||||
continue;
|
||||
|
||||
scene::SSkinMeshBuffer* ssmb = NULL;
|
||||
video::E_VERTEX_TYPE prev_type = mb->getVertexType();
|
||||
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)
|
||||
@ -128,7 +133,7 @@ void STKAnimatedMesh::updateNoGL()
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_ri = default_ri;
|
||||
cur_ri = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -144,7 +149,9 @@ void STKAnimatedMesh::updateNoGL()
|
||||
assert(cur_ri ? cur_ri->isStatic() : true);
|
||||
GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name,
|
||||
affected || m_all_parts_colorized || (cur_ri
|
||||
&& cur_ri->isTransparent()) ? cur_ri : default_ri));
|
||||
&& cur_ri->isTransparent()) ? cur_ri : NULL));
|
||||
|
||||
if (m_skinned_mesh) ssmb->VertexType = prev_type;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
|
||||
@ -152,6 +159,15 @@ void STKAnimatedMesh::updateNoGL()
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
if (!mb)
|
||||
continue;
|
||||
|
||||
scene::SSkinMeshBuffer* ssmb = NULL;
|
||||
video::E_VERTEX_TYPE prev_type = mb->getVertexType();
|
||||
if (m_skinned_mesh)
|
||||
{
|
||||
ssmb = dynamic_cast<scene::SSkinMeshBuffer*>(mb);
|
||||
ssmb->VertexType = video::EVT_SKINNED_MESH;
|
||||
}
|
||||
|
||||
video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType;
|
||||
f32 MaterialTypeParam = mb->getMaterial().MaterialTypeParam;
|
||||
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type);
|
||||
@ -163,25 +179,29 @@ void STKAnimatedMesh::updateNoGL()
|
||||
continue;
|
||||
}
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
video::E_VERTEX_TYPE vt = mb->getVertexType();
|
||||
Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb);
|
||||
|
||||
if (rnd->isTransparent())
|
||||
{
|
||||
TransparentMaterial TranspMat = getTransparentMaterialFromType(type, MaterialTypeParam, material);
|
||||
TransparentMaterial TranspMat = getTransparentMaterialFromType(type, vt, MaterialTypeParam, material);
|
||||
TransparentMesh[TranspMat].push_back(&mesh);
|
||||
}
|
||||
else if (mesh.m_render_info != NULL && mesh.m_render_info->isTransparent())
|
||||
{
|
||||
if (mesh.VAOType == video::EVT_TANGENTS)
|
||||
if (mesh.VAOType == video::EVT_SKINNED_MESH)
|
||||
TransparentMesh[TM_TRANSLUCENT_SKN].push_back(&mesh);
|
||||
else if (mesh.VAOType == video::EVT_TANGENTS)
|
||||
TransparentMesh[TM_TRANSLUCENT_TAN].push_back(&mesh);
|
||||
else
|
||||
TransparentMesh[TM_TRANSLUCENT_STD].push_back(&mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
Material::ShaderType MatType = getMeshMaterialFromType(type, mb->getVertexType(), material, NULL);
|
||||
Material::ShaderType MatType = getMeshMaterialFromType(type, vt, material, NULL);
|
||||
MeshSolidMaterial[MatType].push_back(&mesh);
|
||||
}
|
||||
if (m_skinned_mesh) ssmb->VertexType = prev_type;
|
||||
}
|
||||
isMaterialInitialized = true;
|
||||
}
|
||||
@ -207,16 +227,21 @@ void STKAnimatedMesh::updateNoGL()
|
||||
|
||||
void STKAnimatedMesh::updateGL()
|
||||
{
|
||||
|
||||
scene::IMesh* m = getMeshForCurrentFrame();
|
||||
|
||||
if (!isGLInitialized)
|
||||
{
|
||||
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
|
||||
for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
if (!mb)
|
||||
continue;
|
||||
scene::SSkinMeshBuffer* ssmb = NULL;
|
||||
video::E_VERTEX_TYPE prev_type = mb->getVertexType();
|
||||
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);
|
||||
@ -237,7 +262,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);
|
||||
mesh.vaoBaseVertex = p.first;
|
||||
mesh.vaoOffset = p.second;
|
||||
}
|
||||
@ -247,10 +272,20 @@ void STKAnimatedMesh::updateGL()
|
||||
mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType());
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
if (m_skinned_mesh) ssmb->VertexType = prev_type;
|
||||
}
|
||||
isGLInitialized = true;
|
||||
}
|
||||
|
||||
if (useHardwareSkinning() && m_skinned_mesh->getTotalJoints() == 0) return;
|
||||
|
||||
scene::IMesh* m = getMeshForCurrentFrame();
|
||||
if (useHardwareSkinning())
|
||||
{
|
||||
m_skinning_offset = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i<m->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = m->getMeshBuffer(i);
|
||||
@ -294,5 +329,48 @@ void STKAnimatedMesh::render()
|
||||
updateGL();
|
||||
}
|
||||
|
||||
#endif // !SERVER_ONLY
|
||||
int STKAnimatedMesh::getTotalJoints() const
|
||||
{
|
||||
return m_skinned_mesh->getTotalJoints();
|
||||
}
|
||||
|
||||
void STKAnimatedMesh::resetSkinningState(scene::IAnimatedMesh* mesh)
|
||||
{
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
m_skinning_offset = -1;
|
||||
setHardwareSkinning(true);
|
||||
if (m_skinned_mesh)
|
||||
m_skinned_mesh->convertForSkinning();
|
||||
}
|
||||
|
||||
scene::IMesh* STKAnimatedMesh::getMeshForCurrentFrame(SkinningCallback sc,
|
||||
int offset)
|
||||
{
|
||||
if (!useHardwareSkinning())
|
||||
return scene::CAnimatedMeshSceneNode::getMeshForCurrentFrame();
|
||||
if (m_skinning_offset == -1)
|
||||
return Mesh;
|
||||
|
||||
return scene::CAnimatedMeshSceneNode::getMeshForCurrentFrame
|
||||
(uploadJoints, m_skinning_offset);
|
||||
}
|
||||
|
||||
void STKAnimatedMesh::setHardwareSkinning(bool val)
|
||||
{
|
||||
if (!CVS->supportsHardwareSkinning()) return;
|
||||
if (val)
|
||||
m_skinned_mesh = dynamic_cast<scene::CSkinnedMesh*>(Mesh);
|
||||
else
|
||||
m_skinned_mesh = NULL;
|
||||
}
|
||||
|
||||
void STKAnimatedMesh::uploadJoints(const irr::core::matrix4& m,
|
||||
int joint, int offset)
|
||||
{
|
||||
assert(offset != -1);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, SharedGPUObjects::getSkinningUBO());
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, offset + joint * 16 * sizeof(float),
|
||||
16 * sizeof(float), m.pointer());
|
||||
}
|
||||
|
||||
#endif // !SERVER_ONLY
|
||||
|
@ -26,6 +26,10 @@
|
||||
#include <irrTypes.h>
|
||||
|
||||
class RenderInfo;
|
||||
namespace irr
|
||||
{
|
||||
namespace scene { class CSkinnedMesh; }
|
||||
}
|
||||
|
||||
class STKAnimatedMesh : public irr::scene::CAnimatedMeshSceneNode, public STKMeshCommon
|
||||
{
|
||||
@ -50,10 +54,23 @@ public:
|
||||
virtual void render();
|
||||
virtual void setMesh(irr::scene::IAnimatedMesh* mesh);
|
||||
virtual bool glow() const { return false; }
|
||||
virtual irr::scene::IMesh* getMeshForCurrentFrame(SkinningCallback sc = NULL,
|
||||
int offset = -1);
|
||||
int getTotalJoints() const;
|
||||
void setSkinningOffset(int offset) { m_skinning_offset = offset; }
|
||||
bool useHardwareSkinning() const { return m_skinned_mesh != NULL; }
|
||||
void setHardwareSkinning(bool val);
|
||||
void resetSkinningState(scene::IAnimatedMesh*);
|
||||
|
||||
// Callback for skinning mesh
|
||||
static void uploadJoints(const irr::core::matrix4& m,
|
||||
int joint, int offset);
|
||||
private:
|
||||
RenderInfo* m_mesh_render_info;
|
||||
bool m_all_parts_colorized;
|
||||
bool m_got_animated_matrix;
|
||||
irr::scene::CSkinnedMesh* m_skinned_mesh;
|
||||
int m_skinning_offset;
|
||||
};
|
||||
|
||||
#endif // STKANIMATEDMESH_HPP
|
||||
|
@ -40,6 +40,24 @@ Material::ShaderType getMeshMaterialFromType(video::E_MATERIAL_TYPE material_typ
|
||||
layer2_material->getShaderType() == Material::SHADERTYPE_SPLATTING)
|
||||
return Material::SHADERTYPE_SPLATTING;
|
||||
|
||||
if (tp == video::EVT_SKINNED_MESH)
|
||||
{
|
||||
switch (material->getShaderType())
|
||||
{
|
||||
case Material::SHADERTYPE_SOLID:
|
||||
if (material_type == Shaders::getShader(ES_NORMAL_MAP))
|
||||
return Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH;
|
||||
else
|
||||
return Material::SHADERTYPE_SOLID_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;
|
||||
default:
|
||||
return Material::SHADERTYPE_SOLID_SKINNED_MESH;
|
||||
}
|
||||
}
|
||||
|
||||
switch (material->getShaderType())
|
||||
{
|
||||
default:
|
||||
@ -55,9 +73,13 @@ Material::ShaderType getMeshMaterialFromType(video::E_MATERIAL_TYPE material_typ
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
TransparentMaterial getTransparentMaterialFromType(video::E_MATERIAL_TYPE type,
|
||||
video::E_VERTEX_TYPE tp,
|
||||
f32 MaterialTypeParam,
|
||||
Material* material)
|
||||
{
|
||||
if (tp == video::EVT_SKINNED_MESH)
|
||||
return TM_TRANSLUCENT_SKN;
|
||||
|
||||
if (type == Shaders::getShader(ES_DISPLACE))
|
||||
{
|
||||
if (CVS->isDefferedEnabled())
|
||||
@ -157,6 +179,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(4);
|
||||
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");
|
||||
}
|
||||
@ -205,8 +243,6 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb, const std::string& debug_name,
|
||||
}
|
||||
result.VAOType = mb->getVertexType();
|
||||
result.Stride = getVertexPitchFromType(result.VAOType);
|
||||
|
||||
|
||||
result.IndexCount = mb->getIndexCount();
|
||||
switch (mb->getPrimitiveType())
|
||||
{
|
||||
@ -236,7 +272,7 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb, const std::string& debug_name,
|
||||
for (unsigned i = 0; i < 8; i++)
|
||||
result.textures[i] = mb->getMaterial().getTexture(i);
|
||||
result.texture_trans = core::vector2df(0.0f, 0.0f);
|
||||
result.VAOType = mb->getVertexType();
|
||||
|
||||
return result;
|
||||
} // allocateMeshBuffer
|
||||
|
||||
@ -409,12 +445,16 @@ void initTextures(GLMesh &mesh, Material::ShaderType mat)
|
||||
case Material::SHADERTYPE_SPHERE_MAP:
|
||||
case Material::SHADERTYPE_SOLID_UNLIT:
|
||||
case Material::SHADERTYPE_VEGETATION:
|
||||
case Material::SHADERTYPE_SOLID_SKINNED_MESH:
|
||||
case Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH:
|
||||
case Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH:
|
||||
setTexture(mesh, 0, true, getShaderTypeName(mat));
|
||||
setTexture(mesh, 1, false, getShaderTypeName(mat));
|
||||
setTexture(mesh, 2, false, getShaderTypeName(mat));
|
||||
break;
|
||||
case Material::SHADERTYPE_DETAIL_MAP:
|
||||
case Material::SHADERTYPE_NORMAL_MAP:
|
||||
case Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH:
|
||||
setTexture(mesh, 0, true, getShaderTypeName(mat));
|
||||
setTexture(mesh, 1, false, getShaderTypeName(mat));
|
||||
setTexture(mesh, 2, false, getShaderTypeName(mat));
|
||||
|
@ -37,6 +37,7 @@ enum TransparentMaterial
|
||||
TM_DEFAULT,
|
||||
TM_ADDITIVE,
|
||||
TM_DISPLACEMENT,
|
||||
TM_TRANSLUCENT_SKN,
|
||||
TM_TRANSLUCENT_STD,
|
||||
TM_TRANSLUCENT_TAN,
|
||||
TM_TRANSLUCENT_2TC,
|
||||
@ -91,6 +92,7 @@ public:
|
||||
virtual void updateGL() = 0;
|
||||
virtual bool glow() const = 0;
|
||||
virtual bool isImmediateDraw() const { return false; }
|
||||
const std::string& getMeshDebugName() const { return m_debug_name; }
|
||||
}; // STKMeshCommon
|
||||
|
||||
|
||||
@ -110,10 +112,34 @@ public:
|
||||
}; // MeshList
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
class ListSkinnedSolid : public MeshList<ListSkinnedSolid, GLMesh *, core::matrix4,
|
||||
core::matrix4, core::vector2df,
|
||||
core::vector2df, int>
|
||||
{};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
class ListSkinnedAlphaRef : public MeshList<ListSkinnedAlphaRef, GLMesh *,
|
||||
core::matrix4, core::matrix4,
|
||||
core::vector2df, core::vector2df, int>
|
||||
{};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
class ListSkinnedNormalMap : public MeshList<ListSkinnedNormalMap, GLMesh *,
|
||||
core::matrix4, core::matrix4,
|
||||
core::vector2df, core::vector2df, int>
|
||||
{};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
class ListSkinnedUnlit : public MeshList<ListSkinnedUnlit, GLMesh *,
|
||||
core::matrix4, core::matrix4,
|
||||
core::vector2df, core::vector2df, int>
|
||||
{};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
class ListMatDefault : public MeshList<ListMatDefault, GLMesh *, core::matrix4,
|
||||
core::matrix4, core::vector2df,
|
||||
core::vector2df>
|
||||
core::matrix4, core::vector2df,
|
||||
core::vector2df>
|
||||
{};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -172,6 +198,12 @@ class ListAdditiveTransparent : public MiscList<ListAdditiveTransparent,
|
||||
core::vector2df, float>
|
||||
{};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
class ListTranslucentSkinned : public MiscList<ListTranslucentSkinned,
|
||||
GLMesh *, core::matrix4,
|
||||
core::vector2df, int, float>
|
||||
{};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
class ListTranslucentStandard : public MiscList<ListTranslucentStandard,
|
||||
GLMesh *, core::matrix4,
|
||||
@ -218,6 +250,7 @@ Material::ShaderType getMeshMaterialFromType(video::E_MATERIAL_TYPE MaterialType
|
||||
Material* layer2Material);
|
||||
// ----------------------------------------------------------------------------
|
||||
TransparentMaterial getTransparentMaterialFromType(video::E_MATERIAL_TYPE,
|
||||
video::E_VERTEX_TYPE tp,
|
||||
f32 MaterialTypeParam,
|
||||
Material* material);
|
||||
|
||||
|
@ -207,6 +207,7 @@ void STKMeshSceneNode::updateNoGL()
|
||||
}
|
||||
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
video::E_VERTEX_TYPE vt = mb->getVertexType();
|
||||
Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb);
|
||||
if (mesh.m_render_info != NULL && mesh.m_render_info->isTransparent() && !rnd->isTransparent())
|
||||
{
|
||||
@ -218,7 +219,7 @@ void STKMeshSceneNode::updateNoGL()
|
||||
}
|
||||
else if (rnd->isTransparent())
|
||||
{
|
||||
TransparentMaterial TranspMat = getTransparentMaterialFromType(type, MaterialTypeParam, material);
|
||||
TransparentMaterial TranspMat = getTransparentMaterialFromType(type, vt, MaterialTypeParam, material);
|
||||
if (!immediate_draw)
|
||||
TransparentMesh[TranspMat].push_back(&mesh);
|
||||
else
|
||||
@ -230,7 +231,7 @@ void STKMeshSceneNode::updateNoGL()
|
||||
Material* material2 = NULL;
|
||||
if (mb->getMaterial().getTexture(1) != NULL)
|
||||
material2 = material_manager->getMaterialFor(mb->getMaterial().getTexture(1), mb);
|
||||
Material::ShaderType MatType = getMeshMaterialFromType(type, mb->getVertexType(), material, material2);
|
||||
Material::ShaderType MatType = getMeshMaterialFromType(type, vt, material, material2);
|
||||
if (!immediate_draw)
|
||||
MeshSolidMaterial[MatType].push_back(&mesh);
|
||||
}
|
||||
|
@ -163,6 +163,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_INT, sizeof(InstanceDataSingleTex), (GLvoid*)(11 * sizeof(float)));
|
||||
glVertexAttribDivisorARB(15, 1);
|
||||
}
|
||||
|
||||
template<>
|
||||
@ -181,6 +184,9 @@ void VAOInstanceUtil<InstanceDataThreeTex>::SetVertexAttrib()
|
||||
glEnableVertexAttribArray(13);
|
||||
glVertexAttribIPointer(13, 2, GL_UNSIGNED_INT, sizeof(InstanceDataThreeTex), (GLvoid*)(13 * sizeof(float) + 4 * sizeof(unsigned)));
|
||||
glVertexAttribDivisorARB(13, 1);
|
||||
glEnableVertexAttribArray(15);
|
||||
glVertexAttribIPointer(15, 1, GL_INT, sizeof(InstanceDataThreeTex), (GLvoid*)(13 * sizeof(float) + 6 * sizeof(unsigned)));;
|
||||
glVertexAttribDivisorARB(15, 1);
|
||||
}
|
||||
|
||||
template<>
|
||||
@ -202,6 +208,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_INT, sizeof(InstanceDataFourTex), (GLvoid*)(13 * sizeof(float) + 8 * sizeof(unsigned)));
|
||||
glVertexAttribDivisorARB(15, 1);
|
||||
}
|
||||
|
||||
template<>
|
||||
@ -218,7 +227,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];
|
||||
@ -266,6 +275,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;
|
||||
@ -284,6 +295,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;
|
||||
}
|
||||
};
|
||||
|
||||
@ -298,10 +311,12 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp, RenderInfo* ri)
|
||||
void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp)
|
||||
{
|
||||
size_t old_vtx_cnt = last_vertex[tp];
|
||||
size_t old_idx_cnt = last_index[tp];
|
||||
@ -332,28 +347,26 @@ void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp, RenderInfo* ri)
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, old_idx_cnt * sizeof(u16), mb->getIndexCount() * sizeof(u16), mb->getIndices());
|
||||
}
|
||||
|
||||
std::pair<scene::IMeshBuffer*, RenderInfo*> key(mb, ri);
|
||||
mappedBaseVertex[tp][key] = old_vtx_cnt;
|
||||
mappedBaseIndex[tp][key] = old_idx_cnt * sizeof(u16);
|
||||
mappedBaseVertex[tp][mb] = old_vtx_cnt;
|
||||
mappedBaseIndex[tp][mb] = old_idx_cnt * sizeof(u16);
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb, RenderInfo* ri)
|
||||
std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb)
|
||||
{
|
||||
VTXTYPE tp = getVTXTYPE(mb->getVertexType());
|
||||
std::pair<scene::IMeshBuffer*, RenderInfo*> key(mb, ri);
|
||||
if (mappedBaseVertex[tp].find(key) == mappedBaseVertex[tp].end())
|
||||
if (mappedBaseVertex[tp].find(mb) == mappedBaseVertex[tp].end())
|
||||
{
|
||||
assert(mappedBaseIndex[tp].find(key) == mappedBaseIndex[tp].end());
|
||||
append(mb, tp, ri);
|
||||
assert(mappedBaseIndex[tp].find(mb) == mappedBaseIndex[tp].end());
|
||||
append(mb, tp);
|
||||
regenerateVAO(tp);
|
||||
regenerateInstancedVAO();
|
||||
}
|
||||
|
||||
std::unordered_map<std::pair<scene::IMeshBuffer*, RenderInfo*>, unsigned, MeshRenderInfoHash, MeshRenderInfoEquals>::iterator It;
|
||||
It = mappedBaseVertex[tp].find(key);
|
||||
std::unordered_map<scene::IMeshBuffer*, unsigned>::iterator It;
|
||||
It = mappedBaseVertex[tp].find(mb);
|
||||
assert(It != mappedBaseVertex[tp].end());
|
||||
unsigned vtx = It->second;
|
||||
It = mappedBaseIndex[tp].find(key);
|
||||
It = mappedBaseIndex[tp].find(mb);
|
||||
assert(It != mappedBaseIndex[tp].end());
|
||||
return std::pair<unsigned, unsigned>(vtx, It->second);
|
||||
}
|
||||
|
@ -26,8 +26,6 @@
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
class RenderInfo;
|
||||
|
||||
enum InstanceType
|
||||
{
|
||||
InstanceTypeThreeTex,
|
||||
@ -62,6 +60,7 @@ struct InstanceDataSingleTex
|
||||
float Z;
|
||||
} Scale;
|
||||
uint64_t Texture;
|
||||
int32_t skinning_offset;
|
||||
#ifdef WIN32
|
||||
};
|
||||
#else
|
||||
@ -98,6 +97,7 @@ struct InstanceDataThreeTex
|
||||
uint64_t Texture;
|
||||
uint64_t SecondTexture;
|
||||
uint64_t ThirdTexture;
|
||||
int32_t skinning_offset;
|
||||
#ifdef WIN32
|
||||
};
|
||||
#else
|
||||
@ -135,6 +135,7 @@ struct InstanceDataFourTex
|
||||
uint64_t SecondTexture;
|
||||
uint64_t ThirdTexture;
|
||||
uint64_t FourthTexture;
|
||||
int32_t skinning_offset;
|
||||
#ifdef WIN32
|
||||
};
|
||||
#else
|
||||
@ -171,40 +172,16 @@ struct GlowInstanceData
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#include <functional>
|
||||
|
||||
class MeshRenderInfoHash
|
||||
{
|
||||
public:
|
||||
size_t operator() (const std::pair<irr::scene::IMeshBuffer*, RenderInfo*> &p) const
|
||||
{
|
||||
return (std::hash<irr::scene::IMeshBuffer*>()(p.first) ^
|
||||
(std::hash<RenderInfo*>()(p.second) << 1));
|
||||
}
|
||||
};
|
||||
|
||||
struct MeshRenderInfoEquals : std::binary_function
|
||||
<const std::pair<irr::scene::IMeshBuffer*, RenderInfo*>&,
|
||||
const std::pair<irr::scene::IMeshBuffer*, RenderInfo*>&, bool>
|
||||
{
|
||||
result_type operator() (first_argument_type lhs,
|
||||
second_argument_type rhs) const
|
||||
{
|
||||
return (lhs.first == rhs.first) &&
|
||||
(lhs.second == rhs.second);
|
||||
}
|
||||
};
|
||||
|
||||
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];
|
||||
void *VBOPtr[VTXTYPE_COUNT], *IBOPtr[VTXTYPE_COUNT];
|
||||
size_t RealVBOSize[VTXTYPE_COUNT], RealIBOSize[VTXTYPE_COUNT];
|
||||
size_t last_vertex[VTXTYPE_COUNT], last_index[VTXTYPE_COUNT];
|
||||
std::unordered_map <std::pair<irr::scene::IMeshBuffer*, RenderInfo*>, unsigned, MeshRenderInfoHash, MeshRenderInfoEquals> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
|
||||
std::unordered_map<irr::scene::IMeshBuffer*, unsigned> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
|
||||
std::map<std::pair<irr::video::E_VERTEX_TYPE, InstanceType>, GLuint> InstanceVAO;
|
||||
|
||||
void cleanInstanceVAOs();
|
||||
@ -214,10 +191,10 @@ class VAOManager : public Singleton<VAOManager>
|
||||
size_t getVertexPitch(enum VTXTYPE) const;
|
||||
VTXTYPE getVTXTYPE(irr::video::E_VERTEX_TYPE type);
|
||||
irr::video::E_VERTEX_TYPE getVertexType(enum VTXTYPE tp);
|
||||
void append(irr::scene::IMeshBuffer *, VTXTYPE tp, RenderInfo* ri = NULL);
|
||||
void append(irr::scene::IMeshBuffer *, VTXTYPE tp);
|
||||
public:
|
||||
VAOManager();
|
||||
std::pair<unsigned, unsigned> getBase(irr::scene::IMeshBuffer *, RenderInfo* ri = NULL);
|
||||
std::pair<unsigned, unsigned> getBase(irr::scene::IMeshBuffer *);
|
||||
GLuint getInstanceBuffer(InstanceType it) { return instance_vbo[it]; }
|
||||
void *getInstanceBufferPtr(InstanceType it) { return Ptr[it]; }
|
||||
unsigned getVBO(irr::video::E_VERTEX_TYPE type) { return vbo[getVTXTYPE(type)]; }
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "graphics/material_manager.hpp"
|
||||
#include "graphics/mesh_tools.hpp"
|
||||
#include "graphics/render_info.hpp"
|
||||
#include "graphics/stk_animated_mesh.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "io/xml_node.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
@ -361,11 +362,7 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models, bool always_anim
|
||||
|
||||
node = irr_driver->addAnimatedMesh(m_mesh, "kartmesh",
|
||||
NULL/*parent*/, getRenderInfo());
|
||||
// as animated mesh are not cheap to render use frustum box culling
|
||||
if (CVS->isGLSL())
|
||||
node->setAutomaticCulling(scene::EAC_OFF);
|
||||
else
|
||||
node->setAutomaticCulling(scene::EAC_FRUSTUM_BOX);
|
||||
node->setAutomaticCulling(scene::EAC_FRUSTUM_BOX);
|
||||
#endif
|
||||
if (always_animated)
|
||||
{
|
||||
@ -1031,7 +1028,17 @@ void KartModel::attachHat()
|
||||
m_hat_node = irr_driver->addMesh(hat_mesh, "hat");
|
||||
bone->addChild(m_hat_node);
|
||||
m_animated_node->setCurrentFrame((float)m_animation_frame[AF_STRAIGHT]);
|
||||
m_animated_node->OnAnimate(0);
|
||||
#ifndef SERVER_ONLY
|
||||
STKAnimatedMesh* am = dynamic_cast<STKAnimatedMesh*>(m_animated_node);
|
||||
if (am)
|
||||
{
|
||||
am->setHardwareSkinning(false);
|
||||
am->OnAnimate(0);
|
||||
am->setHardwareSkinning(true);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
m_animated_node->OnAnimate(0);
|
||||
bone->updateAbsolutePosition();
|
||||
// With the hat node attached to the head bone, we have to
|
||||
// reverse the transformation of the bone, so that the hat
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "utils/translation.hpp"
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/shared_gpu_objects.hpp"
|
||||
|
||||
#include <IGUIEnvironment.h>
|
||||
|
||||
@ -36,8 +37,12 @@ using namespace irr::gui;
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
CustomVideoSettingsDialog::CustomVideoSettingsDialog(const float w, const float h) :
|
||||
ModalDialog(w, h)
|
||||
ModalDialog(w, h), m_all_kart_animated(true)
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
m_all_kart_animated = SharedGPUObjects::getMaxMat4Size() > 512 ||
|
||||
!CVS->supportsHardwareSkinning();
|
||||
#endif
|
||||
loadFromFile("custom_video_settings.stkgui");
|
||||
updateActivation();
|
||||
}
|
||||
@ -64,8 +69,11 @@ void CustomVideoSettingsDialog::beforeAddingWidgets()
|
||||
//I18N: animations setting (only karts with human players are animated)
|
||||
kart_anim->addLabel(_("Human players only")); // 1
|
||||
//I18N: animations setting (all karts are animated)
|
||||
kart_anim->addLabel(_("Enabled for all")); // 2
|
||||
kart_anim->setValue(UserConfigParams::m_show_steering_animations);
|
||||
if (m_all_kart_animated)
|
||||
kart_anim->addLabel(_("Enabled for all")); // 2
|
||||
kart_anim->setValue(!m_all_kart_animated &&
|
||||
UserConfigParams::m_show_steering_animations == 2 ?
|
||||
1 : UserConfigParams::m_show_steering_animations);
|
||||
|
||||
SpinnerWidget* filtering = getWidget<SpinnerWidget>("filtering");
|
||||
int value = 0;
|
||||
@ -242,6 +250,8 @@ void CustomVideoSettingsDialog::updateActivation()
|
||||
getWidget<CheckBoxWidget>("global_illumination")->setActive(light);
|
||||
getWidget<CheckBoxWidget>("glow")->setActive(light);
|
||||
getWidget<CheckBoxWidget>("bloom")->setActive(light);
|
||||
getWidget<SpinnerWidget>("steering_animations")
|
||||
->setMax(m_all_kart_animated ? 2 : 1);
|
||||
|
||||
if (!CVS->supportsShadows() && !CVS->supportsGlobalIllumination())
|
||||
{
|
||||
|
@ -27,7 +27,8 @@
|
||||
*/
|
||||
class CustomVideoSettingsDialog : public GUIEngine::ModalDialog
|
||||
{
|
||||
|
||||
private:
|
||||
bool m_all_kart_animated;
|
||||
public:
|
||||
/**
|
||||
* Creates a modal dialog with given percentage of screen width and height
|
||||
|
@ -20,7 +20,9 @@
|
||||
#include "audio/sfx_manager.hpp"
|
||||
#include "audio/sfx_base.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/shared_gpu_objects.hpp"
|
||||
#include "guiengine/screen.hpp"
|
||||
#include "guiengine/widgets/button_widget.hpp"
|
||||
#include "guiengine/widgets/check_box_widget.hpp"
|
||||
@ -44,73 +46,71 @@ using namespace GUIEngine;
|
||||
|
||||
DEFINE_SCREEN_SINGLETON( OptionsScreenVideo );
|
||||
|
||||
struct GFXPreset
|
||||
// ----------------------------------------------------------------------------
|
||||
void OptionsScreenVideo::initPresets()
|
||||
{
|
||||
bool lights;
|
||||
int shadows;
|
||||
bool bloom;
|
||||
bool motionblur;
|
||||
bool lightshaft;
|
||||
bool glow;
|
||||
bool mlaa;
|
||||
bool ssao;
|
||||
bool weather;
|
||||
bool animatedScenery;
|
||||
int animatedCharacters;
|
||||
int anisotropy;
|
||||
/** Depth of field */
|
||||
bool dof;
|
||||
bool global_illumination;
|
||||
bool degraded_ibl;
|
||||
int hd_textures;
|
||||
};
|
||||
|
||||
static GFXPreset GFX_PRESETS[] =
|
||||
{
|
||||
{
|
||||
m_presets.push_back
|
||||
({
|
||||
false /* light */, 0 /* shadow */, false /* bloom */, false /* motionblur */,
|
||||
false /* lightshaft */, false /* glow */, false /* mlaa */, false /* ssao */, false /* weather */,
|
||||
false /* animatedScenery */, 0 /* animatedCharacters */, 0 /* anisotropy */,
|
||||
false /* depth of field */, false /* global illumination */, true /* degraded IBL */, 0 /* hd_textures */
|
||||
},
|
||||
});
|
||||
|
||||
{
|
||||
m_presets.push_back
|
||||
({
|
||||
false /* light */, 0 /* shadow */, false /* bloom */, false /* motionblur */,
|
||||
false /* lightshaft */, false /* glow */, false /* mlaa */, false /* ssao */, false /* weather */,
|
||||
true /* animatedScenery */, 1 /* animatedCharacters */, 4 /* anisotropy */,
|
||||
false /* depth of field */, false /* global illumination */, true /* degraded IBL */, 0 /* hd_textures */
|
||||
},
|
||||
});
|
||||
|
||||
{
|
||||
m_presets.push_back
|
||||
({
|
||||
true /* light */, 0 /* shadow */, false /* bloom */, false /* motionblur */,
|
||||
false /* lightshaft */, false /* glow */, false /* mlaa */, false /* ssao */, true /* weather */,
|
||||
true /* animatedScenery */, 1 /* animatedCharacters */, 4 /* anisotropy */,
|
||||
false /* depth of field */, false /* global illumination */, true /* degraded IBL */, 1 /* hd_textures */
|
||||
},
|
||||
});
|
||||
|
||||
{
|
||||
m_presets.push_back
|
||||
({
|
||||
true /* light */, 0 /* shadow */, false /* bloom */, true /* motionblur */,
|
||||
true /* lightshaft */, true /* glow */, true /* mlaa */, false /* ssao */, true /* weather */,
|
||||
true /* animatedScenery */, 1 /* animatedCharacters */, 8 /* anisotropy */,
|
||||
false /* depth of field */, false /* global illumination */, false /* degraded IBL */, 1 /* hd_textures */
|
||||
},
|
||||
});
|
||||
|
||||
{
|
||||
m_presets.push_back
|
||||
({
|
||||
true /* light */, 512 /* shadow */, true /* bloom */, true /* motionblur */,
|
||||
true /* lightshaft */, true /* glow */, true /* mlaa */, true /* ssao */, true /* weather */,
|
||||
true /* animatedScenery */, 2 /* animatedCharacters */, 16 /* anisotropy */,
|
||||
true /* animatedScenery */,
|
||||
#ifndef SERVER_ONLY
|
||||
(SharedGPUObjects::getMaxMat4Size() > 512 || !CVS->supportsHardwareSkinning() ? 2 : 1),
|
||||
#else
|
||||
2 /* animatedCharacters */,
|
||||
#endif
|
||||
16 /* anisotropy */,
|
||||
true /* depth of field */, false /* global illumination */, false /* degraded IBL */, 1 /* hd_textures */
|
||||
},
|
||||
});
|
||||
|
||||
{
|
||||
m_presets.push_back
|
||||
({
|
||||
true /* light */, 1024 /* shadow */, true /* bloom */, true /* motionblur */,
|
||||
true /* lightshaft */, true /* glow */, true /* mlaa */, true /* ssao */, true /* weather */,
|
||||
true /* animatedScenery */, 2 /* animatedCharacters */, 16 /* anisotropy */,
|
||||
true /* animatedScenery */,
|
||||
#ifndef SERVER_ONLY
|
||||
(SharedGPUObjects::getMaxMat4Size() > 512 || !CVS->supportsHardwareSkinning() ? 2 : 1),
|
||||
#else
|
||||
2 /* animatedCharacters */,
|
||||
#endif
|
||||
16 /* anisotropy */,
|
||||
true /* depth of field */, true /* global illumination */, false /* degraded IBL */, 1 /* hd_textures */
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
static const int GFX_LEVEL_AMOUNT = 6;
|
||||
} // initPresets
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
struct Resolution
|
||||
{
|
||||
@ -144,6 +144,7 @@ struct Resolution
|
||||
OptionsScreenVideo::OptionsScreenVideo() : Screen("options_video.stkgui")
|
||||
{
|
||||
m_inited = false;
|
||||
initPresets();
|
||||
} // OptionsScreenVideo
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -151,12 +152,12 @@ OptionsScreenVideo::OptionsScreenVideo() : Screen("options_video.stkgui")
|
||||
void OptionsScreenVideo::loadedFromFile()
|
||||
{
|
||||
m_inited = false;
|
||||
|
||||
assert(m_presets.size() == 6);
|
||||
|
||||
GUIEngine::SpinnerWidget* gfx =
|
||||
getWidget<GUIEngine::SpinnerWidget>("gfx_level");
|
||||
gfx->m_properties[GUIEngine::PROP_MAX_VALUE] =
|
||||
StringUtils::toString(GFX_LEVEL_AMOUNT);
|
||||
StringUtils::toString(m_presets.size());
|
||||
|
||||
} // loadedFromFile
|
||||
|
||||
@ -334,25 +335,25 @@ void OptionsScreenVideo::updateGfxSlider()
|
||||
assert( gfx != NULL );
|
||||
|
||||
bool found = false;
|
||||
for (int l=0; l<GFX_LEVEL_AMOUNT; l++)
|
||||
for (unsigned int l = 0; l < m_presets.size(); l++)
|
||||
{
|
||||
if (GFX_PRESETS[l].animatedCharacters == UserConfigParams::m_show_steering_animations &&
|
||||
GFX_PRESETS[l].animatedScenery == UserConfigParams::m_graphical_effects &&
|
||||
GFX_PRESETS[l].anisotropy == UserConfigParams::m_anisotropic &&
|
||||
GFX_PRESETS[l].bloom == UserConfigParams::m_bloom &&
|
||||
GFX_PRESETS[l].glow == UserConfigParams::m_glow &&
|
||||
GFX_PRESETS[l].lights == UserConfigParams::m_dynamic_lights &&
|
||||
GFX_PRESETS[l].lightshaft == UserConfigParams::m_light_shaft &&
|
||||
GFX_PRESETS[l].mlaa == UserConfigParams::m_mlaa &&
|
||||
GFX_PRESETS[l].motionblur == UserConfigParams::m_motionblur &&
|
||||
//GFX_PRESETS[l].shaders == UserConfigParams::m_pixel_shaders
|
||||
GFX_PRESETS[l].shadows == UserConfigParams::m_shadows_resolution &&
|
||||
GFX_PRESETS[l].ssao == UserConfigParams::m_ssao &&
|
||||
GFX_PRESETS[l].weather == UserConfigParams::m_weather_effects &&
|
||||
GFX_PRESETS[l].dof == UserConfigParams::m_dof &&
|
||||
GFX_PRESETS[l].global_illumination == UserConfigParams::m_gi &&
|
||||
GFX_PRESETS[l].degraded_ibl == UserConfigParams::m_degraded_IBL &&
|
||||
GFX_PRESETS[l].hd_textures == (UserConfigParams::m_high_definition_textures & 0x01))
|
||||
if (m_presets[l].animatedCharacters == UserConfigParams::m_show_steering_animations &&
|
||||
m_presets[l].animatedScenery == UserConfigParams::m_graphical_effects &&
|
||||
m_presets[l].anisotropy == UserConfigParams::m_anisotropic &&
|
||||
m_presets[l].bloom == UserConfigParams::m_bloom &&
|
||||
m_presets[l].glow == UserConfigParams::m_glow &&
|
||||
m_presets[l].lights == UserConfigParams::m_dynamic_lights &&
|
||||
m_presets[l].lightshaft == UserConfigParams::m_light_shaft &&
|
||||
m_presets[l].mlaa == UserConfigParams::m_mlaa &&
|
||||
m_presets[l].motionblur == UserConfigParams::m_motionblur &&
|
||||
//m_presets[l].shaders == UserConfigParams::m_pixel_shaders
|
||||
m_presets[l].shadows == UserConfigParams::m_shadows_resolution &&
|
||||
m_presets[l].ssao == UserConfigParams::m_ssao &&
|
||||
m_presets[l].weather == UserConfigParams::m_weather_effects &&
|
||||
m_presets[l].dof == UserConfigParams::m_dof &&
|
||||
m_presets[l].global_illumination == UserConfigParams::m_gi &&
|
||||
m_presets[l].degraded_ibl == UserConfigParams::m_degraded_IBL &&
|
||||
m_presets[l].hd_textures == (UserConfigParams::m_high_definition_textures & 0x01))
|
||||
{
|
||||
gfx->setValue(l + 1);
|
||||
found = true;
|
||||
@ -513,23 +514,23 @@ void OptionsScreenVideo::eventCallback(Widget* widget, const std::string& name,
|
||||
|
||||
const int level = gfx_level->getValue() - 1;
|
||||
|
||||
UserConfigParams::m_show_steering_animations = GFX_PRESETS[level].animatedCharacters;
|
||||
UserConfigParams::m_graphical_effects = GFX_PRESETS[level].animatedScenery;
|
||||
UserConfigParams::m_anisotropic = GFX_PRESETS[level].anisotropy;
|
||||
UserConfigParams::m_bloom = GFX_PRESETS[level].bloom;
|
||||
UserConfigParams::m_glow = GFX_PRESETS[level].glow;
|
||||
UserConfigParams::m_dynamic_lights = GFX_PRESETS[level].lights;
|
||||
UserConfigParams::m_light_shaft = GFX_PRESETS[level].lightshaft;
|
||||
UserConfigParams::m_mlaa = GFX_PRESETS[level].mlaa;
|
||||
UserConfigParams::m_motionblur = GFX_PRESETS[level].motionblur;
|
||||
//UserConfigParams::m_pixel_shaders = GFX_PRESETS[level].shaders;
|
||||
UserConfigParams::m_shadows_resolution = GFX_PRESETS[level].shadows;
|
||||
UserConfigParams::m_ssao = GFX_PRESETS[level].ssao;
|
||||
UserConfigParams::m_weather_effects = GFX_PRESETS[level].weather;
|
||||
UserConfigParams::m_dof = GFX_PRESETS[level].dof;
|
||||
UserConfigParams::m_gi = GFX_PRESETS[level].global_illumination;
|
||||
UserConfigParams::m_degraded_IBL = GFX_PRESETS[level].degraded_ibl;
|
||||
UserConfigParams::m_high_definition_textures = 0x02 | GFX_PRESETS[level].hd_textures;
|
||||
UserConfigParams::m_show_steering_animations = m_presets[level].animatedCharacters;
|
||||
UserConfigParams::m_graphical_effects = m_presets[level].animatedScenery;
|
||||
UserConfigParams::m_anisotropic = m_presets[level].anisotropy;
|
||||
UserConfigParams::m_bloom = m_presets[level].bloom;
|
||||
UserConfigParams::m_glow = m_presets[level].glow;
|
||||
UserConfigParams::m_dynamic_lights = m_presets[level].lights;
|
||||
UserConfigParams::m_light_shaft = m_presets[level].lightshaft;
|
||||
UserConfigParams::m_mlaa = m_presets[level].mlaa;
|
||||
UserConfigParams::m_motionblur = m_presets[level].motionblur;
|
||||
//UserConfigParams::m_pixel_shaders = m_presets[level].shaders;
|
||||
UserConfigParams::m_shadows_resolution = m_presets[level].shadows;
|
||||
UserConfigParams::m_ssao = m_presets[level].ssao;
|
||||
UserConfigParams::m_weather_effects = m_presets[level].weather;
|
||||
UserConfigParams::m_dof = m_presets[level].dof;
|
||||
UserConfigParams::m_gi = m_presets[level].global_illumination;
|
||||
UserConfigParams::m_degraded_IBL = m_presets[level].degraded_ibl;
|
||||
UserConfigParams::m_high_definition_textures = 0x02 | m_presets[level].hd_textures;
|
||||
|
||||
updateGfxSlider();
|
||||
}
|
||||
|
@ -25,7 +25,26 @@
|
||||
|
||||
namespace GUIEngine { class Widget; }
|
||||
|
||||
struct Input;
|
||||
struct GFXPreset
|
||||
{
|
||||
bool lights;
|
||||
int shadows;
|
||||
bool bloom;
|
||||
bool motionblur;
|
||||
bool lightshaft;
|
||||
bool glow;
|
||||
bool mlaa;
|
||||
bool ssao;
|
||||
bool weather;
|
||||
bool animatedScenery;
|
||||
int animatedCharacters;
|
||||
int anisotropy;
|
||||
/** Depth of field */
|
||||
bool dof;
|
||||
bool global_illumination;
|
||||
bool degraded_ibl;
|
||||
int hd_textures;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Graphics options screen
|
||||
@ -33,11 +52,14 @@ struct Input;
|
||||
*/
|
||||
class OptionsScreenVideo : public GUIEngine::Screen, public GUIEngine::ScreenSingleton<OptionsScreenVideo>
|
||||
{
|
||||
private:
|
||||
OptionsScreenVideo();
|
||||
bool m_inited;
|
||||
std::vector<GFXPreset> m_presets;
|
||||
|
||||
void updateTooltip();
|
||||
|
||||
void initPresets();
|
||||
public:
|
||||
friend class GUIEngine::ScreenSingleton<OptionsScreenVideo>;
|
||||
|
||||
|
@ -203,7 +203,6 @@ TrackObjectPresentationLibraryNode::TrackObjectPresentationLibraryNode(
|
||||
}
|
||||
std::string lib_node_path = lib_path + "node.xml";
|
||||
std::string lib_script_file_path = lib_path + "scripting.as";
|
||||
World* world = World::getWorld();
|
||||
|
||||
if (local_lib_node_path.size() > 0 && file_manager->fileExists(local_lib_node_path))
|
||||
{
|
||||
|
@ -236,9 +236,10 @@ bool handleContextMenuAction(s32 cmd_id)
|
||||
case DEBUG_GRAPHICS_RELOAD_SHADERS:
|
||||
#ifndef SERVER_ONLY
|
||||
Log::info("Debug", "Reloading shaders...");
|
||||
ShaderBase::updateShaders();
|
||||
ShaderFilesManager::getInstance()->clean();
|
||||
ShaderBase::updateShaders();
|
||||
#endif
|
||||
break;
|
||||
break;
|
||||
case DEBUG_GRAPHICS_RESET:
|
||||
if (physics)
|
||||
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
|
||||
|
@ -434,9 +434,7 @@ void Profiler::draw()
|
||||
s32 y_up_sync = (s32)(MARGIN_Y*screen_size.Height);
|
||||
s32 y_down_sync = (s32)( (MARGIN_Y + (2+nb_thread_infos)*LINE_HEIGHT)*screen_size.Height );
|
||||
|
||||
driver->draw2DLine(core::vector2di(x_sync, y_up_sync),
|
||||
core::vector2di(x_sync, y_down_sync),
|
||||
video::SColor(0xFF, 0x00, 0x00, 0x00));
|
||||
GL32_draw2DRectangle(video::SColor(0xFF, 0x00, 0x00, 0x00), core::rect<s32>(x_sync, y_up_sync, x_sync + 1, y_down_sync));
|
||||
}
|
||||
|
||||
// Draw the hovered markers' names
|
||||
|
Loading…
x
Reference in New Issue
Block a user