From 3f167f672848c83d96dfc34bbd4812fd6be7dff4 Mon Sep 17 00:00:00 2001 From: Marianne Gagnon Date: Thu, 26 Mar 2015 18:31:16 -0400 Subject: [PATCH 001/206] Do not load glossmaps when they are disabled --- src/graphics/material.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphics/material.cpp b/src/graphics/material.cpp index f6fbc3d00..5a7d08316 100644 --- a/src/graphics/material.cpp +++ b/src/graphics/material.cpp @@ -712,7 +712,7 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m { ITexture *tex; ITexture *glossytex; - if (m_gloss_map.size() > 0) + if (m_gloss_map.size() > 0 && UserConfigParams::m_dynamic_lights) { glossytex = irr_driver->getTexture(m_gloss_map); } From 57d9e83ed49703244486dd93b2deebe869c705d2 Mon Sep 17 00:00:00 2001 From: Benau Date: Wed, 7 Dec 2016 02:15:11 +0800 Subject: [PATCH 002/206] First version of hardware skinning Todo: shadow, non-instanced shaders, culling, changeable offset... --- data/shaders/header.txt | 6 + data/shaders/instanced_skinning.vert | 120 ++++++++++++ lib/irrlicht/include/CVertexBuffer.h | 2 + lib/irrlicht/include/IMeshManipulator.h | 2 + lib/irrlicht/include/S3DVertex.h | 22 ++- lib/irrlicht/include/SSkinMeshBuffer.h | 52 +++++ lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp | 177 ++++++++++++++---- lib/irrlicht/source/Irrlicht/CSkinnedMesh.h | 32 +++- src/graphics/command_buffer.cpp | 5 +- src/graphics/command_buffer.hpp | 2 +- src/graphics/draw_calls.cpp | 40 +++- src/graphics/draw_calls.hpp | 5 + src/graphics/glwrap.hpp | 16 ++ src/graphics/material.hpp | 1 + src/graphics/materials.cpp | 8 + src/graphics/materials.hpp | 53 ++++++ src/graphics/mesh_tools.cpp | 2 +- src/graphics/shader.hpp | 1 + src/graphics/shader_based_renderer.cpp | 2 + src/graphics/shared_gpu_objects.cpp | 15 +- src/graphics/shared_gpu_objects.hpp | 8 + src/graphics/stk_animated_mesh.cpp | 51 ++++- src/graphics/stk_animated_mesh.hpp | 10 + src/graphics/stk_mesh.cpp | 21 ++- src/graphics/stk_mesh.hpp | 6 + src/graphics/vao_manager.cpp | 14 +- src/graphics/vao_manager.hpp | 4 +- 27 files changed, 612 insertions(+), 65 deletions(-) create mode 100644 data/shaders/instanced_skinning.vert diff --git a/data/shaders/header.txt b/data/shaders/header.txt index a14e9539a..253e82a29 100644 --- a/data/shaders/header.txt +++ b/data/shaders/header.txt @@ -63,5 +63,11 @@ layout (std140) uniform LightingData float rL21; float rL22; }; + +layout (std140) uniform SkinningData +{ + mat4 joint_matrices[1000]; +}; + #endif #endif // HEADER_TXT diff --git a/data/shaders/instanced_skinning.vert b/data/shaders/instanced_skinning.vert new file mode 100644 index 000000000..fb22ca2e0 --- /dev/null +++ b/data/shaders/instanced_skinning.vert @@ -0,0 +1,120 @@ +layout(location = 0) in vec3 Position; +layout(location = 1) in vec3 Normal; +layout(location = 2) in vec4 Color; +layout(location = 3) in vec4 Data1; +layout(location = 4) in vec4 Data2; +layout(location = 5) in ivec4 Joint; +layout(location = 6) in vec4 Weight; + +layout(location = 7) in vec3 Origin; +layout(location = 8) in vec3 Orientation; +layout(location = 9) in vec3 Scale; +layout(location = 10) in vec4 misc_data; +#ifdef Use_Bindless_Texture +layout(location = 11) in sampler2D Handle; +layout(location = 12) in sampler2D SecondHandle; +layout(location = 13) in sampler2D ThirdHandle; +layout(location = 14) in sampler2D FourthHandle; +#endif +layout(location = 15) in uint skinning_offset; + +out vec3 nor; +out vec3 tangent; +out vec3 bitangent; +out vec2 uv; +out vec4 color; +out vec2 color_change; +#ifdef Use_Bindless_Texture +flat out sampler2D handle; +flat out sampler2D secondhandle; +flat out sampler2D thirdhandle; +flat out sampler2D fourthhandle; +#endif + +#stk_include "utils/getworldmatrix.vert" + +void main(void) +{ + mat4 ModelMatrix = getWorldMatrix(Origin, Orientation, Scale); + mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin, Orientation, Scale) * InverseViewMatrix); + + vec4 idle_position = vec4(Position, 1.); + vec4 idle_normal = vec4(Normal, 0.); + vec4 skinned_position = vec4(0.); + vec4 skinned_normal = vec4(0.); + // Note : For normal we assume no scale factor in bone (otherwise we'll have to compute inversematrix for each bones...) + vec4 single_bone_influenced_position; + vec4 single_bone_influenced_normal; + if (Joint[0] >= 0) + { + single_bone_influenced_position = joint_matrices[Joint[0] + skinning_offset] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + single_bone_influenced_normal = joint_matrices[Joint[0] + skinning_offset] * idle_normal; + } + else + { + single_bone_influenced_position = idle_position; + single_bone_influenced_normal = idle_normal; + } + skinned_position += Weight[0] * single_bone_influenced_position; + skinned_normal += Weight[0] * single_bone_influenced_normal; + + if (Joint[1] >= 0) + { + single_bone_influenced_position= joint_matrices[Joint[1] + skinning_offset] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + single_bone_influenced_normal = joint_matrices[Joint[1] + skinning_offset] * idle_normal; + } + else + { + single_bone_influenced_position = idle_position; + single_bone_influenced_normal = idle_normal; + } + skinned_position += Weight[1] * single_bone_influenced_position; + skinned_normal += Weight[1] * single_bone_influenced_normal; + + if (Joint[2] >= 0) + { + single_bone_influenced_position = joint_matrices[Joint[2] + skinning_offset] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + single_bone_influenced_normal = joint_matrices[Joint[2] + skinning_offset] * idle_normal; + } + else + { + single_bone_influenced_position = idle_position; + single_bone_influenced_normal = idle_normal; + } + skinned_position += Weight[2] * single_bone_influenced_position; + skinned_normal += Weight[2] * single_bone_influenced_normal; + + if (Joint[3] >= 0) + { + single_bone_influenced_position = joint_matrices[Joint[3] + skinning_offset] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + single_bone_influenced_normal = joint_matrices[Joint[3] + skinning_offset] * idle_normal; + } + else + { + single_bone_influenced_position = idle_position; + single_bone_influenced_normal = idle_normal; + } + skinned_position += Weight[3] * single_bone_influenced_position; + skinned_normal += Weight[3] * single_bone_influenced_normal; + + gl_Position = ProjectionViewMatrix * ModelMatrix * skinned_position; + // Keep orthogonality + nor = (TransposeInverseModelView * skinned_normal).xyz; + // Keep direction + tangent = (ViewMatrix * ModelMatrix * vec4(Data1.z, Data1.w, Data2.x, 0.)).xyz; + bitangent = (ViewMatrix * ModelMatrix * vec4(Data2.y, Data2.z, Data2.w, 0.)).xyz; + + uv = vec2(Data1.x + misc_data.x, Data1.y + misc_data.y); + color = Color.zyxw; + color_change = misc_data.zw; +#ifdef Use_Bindless_Texture + handle = Handle; + secondhandle = SecondHandle; + thirdhandle = ThirdHandle; + fourthhandle = FourthHandle; +#endif +} diff --git a/lib/irrlicht/include/CVertexBuffer.h b/lib/irrlicht/include/CVertexBuffer.h index c721419dd..826873023 100644 --- a/lib/irrlicht/include/CVertexBuffer.h +++ b/lib/irrlicht/include/CVertexBuffer.h @@ -116,6 +116,8 @@ namespace scene NewVertices=new CSpecificVertexList; break; } + default: + break; } if (Vertices) { diff --git a/lib/irrlicht/include/IMeshManipulator.h b/lib/irrlicht/include/IMeshManipulator.h index 3476c5789..b4c7d8710 100644 --- a/lib/irrlicht/include/IMeshManipulator.h +++ b/lib/irrlicht/include/IMeshManipulator.h @@ -371,6 +371,8 @@ protected: func(verts[i]); } break; + default: + break; } if (boundingBoxUpdate) { diff --git a/lib/irrlicht/include/S3DVertex.h b/lib/irrlicht/include/S3DVertex.h index bf0fd5b89..3d12edde6 100644 --- a/lib/irrlicht/include/S3DVertex.h +++ b/lib/irrlicht/include/S3DVertex.h @@ -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); } diff --git a/lib/irrlicht/include/SSkinMeshBuffer.h b/lib/irrlicht/include/SSkinMeshBuffer.h index 046378d3b..d510741eb 100644 --- a/lib/irrlicht/include/SSkinMeshBuffer.h +++ b/lib/irrlicht/include/SSkinMeshBuffer.h @@ -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_Tangents; core::array Vertices_2TCoords; + core::array Vertices_SkinnedMesh; core::array Vertices_Standard; core::array Indices; diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp index 92ec49820..01cf773a6 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp @@ -18,7 +18,7 @@ namespace scene //! constructor CSkinnedMesh::CSkinnedMesh() -: SkinningBuffers(0), AnimationFrames(0.f), FramesPerSecond(25.f), +: m_joint_total_size(0), SkinningBuffers(0), AnimationFrames(0.f), FramesPerSecond(25.f), LastAnimatedFrame(-1), SkinnedLastFrame(false), InterpolationMode(EIM_LINEAR), HasAnimation(false), PreparedForSkinning(false), @@ -27,7 +27,6 @@ CSkinnedMesh::CSkinnedMesh() #ifdef _DEBUG setDebugName("CSkinnedMesh"); #endif - SkinningBuffers=&LocalBuffers; } @@ -74,12 +73,19 @@ void CSkinnedMesh::setAnimationSpeed(f32 fps) //! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level. IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) { + const bool is_hw_skinning_before = HardwareSkinning; + if (is_hw_skinning_before) + HardwareSkinning = false; //animate(frame,startFrameLoop, endFrameLoop); if (frame==-1) return this; animateMesh((f32)frame, 1.0f); skinMesh(); + + if (is_hw_skinning_before) + HardwareSkinning = true; + return this; } @@ -456,7 +462,13 @@ void CSkinnedMesh::skinMesh(f32 strength) //----------------- SkinnedLastFrame=true; - if (!HardwareSkinning) + m_joint_matrixes.clear(); + if (HardwareSkinning) + { + for (u32 i = 0; i < RootJoints.size(); i++) + skinJoint(RootJoints[i], 0, strength); + } + else { //Software skin.... u32 i; @@ -493,52 +505,58 @@ void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength) //Find this joints pull on vertices... core::matrix4 jointVertexPull(core::matrix4::EM4CONST_NOTHING); jointVertexPull.setbyproduct(joint->GlobalAnimatedMatrix, joint->GlobalInversedMatrix); - - core::vector3df thisVertexMove, thisNormalMove; - - core::array &buffersUsed=*SkinningBuffers; - - //Skin Vertices Positions and Normals... - for (u32 i=0; iWeights.size(); ++i) + if (HardwareSkinning) { - SWeight& weight = joint->Weights[i]; + m_joint_matrixes.push_back(jointVertexPull); + } + else + { + core::vector3df thisVertexMove, thisNormalMove; - // Pull this vertex... - jointVertexPull.transformVect(thisVertexMove, weight.StaticPos); + core::array &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; iWeights.size(); ++i) { - thisVertexMove = core::lerp(weight.StaticPos, thisVertexMove, strength); - if(AnimateNormals) - thisNormalMove = core::lerp(weight.StaticNormal, thisNormalMove, strength); - } + SWeight& weight = joint->Weights[i]; - if (! (*(weight.Moved)) ) - { - *(weight.Moved) = true; - - buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos = thisVertexMove * weight.strength; + // Pull this vertex... + jointVertexPull.transformVect(thisVertexMove, weight.StaticPos); if (AnimateNormals) - buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal = thisNormalMove * weight.strength; + jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal); - //*(weight._Pos) = thisVertexMove * weight.strength; + // Apply animation strength + if(strength != 1.f) + { + thisVertexMove = core::lerp(weight.StaticPos, thisVertexMove, strength); + if(AnimateNormals) + thisNormalMove = core::lerp(weight.StaticNormal, thisNormalMove, strength); + } + + if (! (*(weight.Moved)) ) + { + *(weight.Moved) = true; + + buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos = thisVertexMove * weight.strength; + + if (AnimateNormals) + buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal = thisNormalMove * weight.strength; + + //*(weight._Pos) = thisVertexMove * weight.strength; + } + else + { + buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos += thisVertexMove * weight.strength; + + if (AnimateNormals) + buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal += thisNormalMove * weight.strength; + + //*(weight._Pos) += thisVertexMove * weight.strength; + } + + buffersUsed[weight.buffer_id]->boundingBoxNeedsRecalculated(); } - else - { - buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos += thisVertexMove * weight.strength; - - if (AnimateNormals) - buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal += thisNormalMove * weight.strength; - - //*(weight._Pos) += thisVertexMove * weight.strength; - } - - buffersUsed[weight.buffer_id]->boundingBoxNeedsRecalculated(); } } @@ -1382,6 +1400,85 @@ void CSkinnedMesh::addJoints(core::array &jointChildSceneNodes, SkinnedLastFrame=false; } +void CSkinnedMesh::convertForSkinning() +{ + if (HardwareSkinning) return; + + setHardwareSkinning(true); + WeightInfluence wi; + for (u32 b = 0; b < LocalBuffers.size(); b++) + { + if (LocalBuffers[b]) + LocalBuffers[b]->convertForSkinning(); + + wi.push_back(core::array> ()); + for (u32 i = 0; i < LocalBuffers[b]->getVertexCount(); i++) + wi[b].push_back(core::array()); + } + + size_t idx = 0; + for (u32 i = 0; i < RootJoints.size(); i++) + computeWeightInfluence(RootJoints[i], idx, wi); + + for (u32 b = 0; b < LocalBuffers.size(); b++) + { + if (LocalBuffers[b]) + { + const u32 total = wi[b].size(); + _IRR_DEBUG_BREAK_IF(LocalBuffers[b]->getVertexCount() != total); + for (u32 i = 0; i < total; i++) + { + core::array this_influence; + core::array reported_weight = wi[b][i]; + reported_weight.sort(); + float remaining_weight = 1.0f; + for (u32 j = 0; j < 4; j++) + { + JointInfluence influence; + if (reported_weight.size() > j) + influence = reported_weight[j]; + else + { + influence.joint_idx = -1; + influence.weight = remaining_weight; + } + remaining_weight -= influence.weight; + this_influence.push_back(influence); + } + LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx1 = this_influence[0].joint_idx; + LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx2 = this_influence[1].joint_idx; + LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx3 = this_influence[2].joint_idx; + LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx4 = this_influence[3].joint_idx; + LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight1 = this_influence[0].weight; + LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight2 = this_influence[1].weight; + LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight3 = this_influence[2].weight; + LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight4 = this_influence[3].weight; + } + } + } + SkinnedLastFrame = false; + skinMesh(); + m_joint_total_size = m_joint_matrixes.size() * sizeof(core::matrix4); +} + +void CSkinnedMesh::computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi) +{ + if (!joint->Weights.empty()) + { + for (u32 i = 0; i < joint->Weights.size(); i++) + { + SWeight& weight = joint->Weights[i]; + JointInfluence tmp; + tmp.joint_idx = index; + tmp.weight = weight.strength; + wi[weight.buffer_id][weight.vertex_id].push_back(tmp); + } + index++; + } + + for (u32 j = 0; j < joint->Children.size(); j++) + computeWeightInfluence(joint->Children[j], index, wi); +} void CSkinnedMesh::convertMeshToTangents() { diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h index 2c66bbf9b..086590c64 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h @@ -14,6 +14,20 @@ #include "matrix4.h" #include "quaternion.h" +class JointInfluence +{ +public: + int joint_idx; + float weight; + bool operator < (const JointInfluence& other) const + { + return weight < other.weight; + } +}; + +typedef irr::core::array > > WeightInfluence; + namespace irr { namespace scene @@ -25,7 +39,6 @@ namespace scene class CSkinnedMesh: public ISkinnedMesh { public: - //! constructor CSkinnedMesh(); @@ -159,6 +172,19 @@ namespace scene void addJoints(core::array &jointChildSceneNodes, IAnimatedMeshSceneNode* node, ISceneManager* smgr); + + void convertForSkinning(); + + void computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi); + + const void* getJointPointer() const { return m_joint_matrixes.const_pointer(); } + + u32 getTotalJointSize() const + { + _IRR_DEBUG_BREAK_IF(m_joint_total_size == 0); + return m_joint_total_size; + } + private: void checkForAnimation(); @@ -204,7 +230,9 @@ private: bool HasAnimation; bool PreparedForSkinning; bool AnimateNormals; - bool HardwareSkinning; + bool HardwareSkinning; + core::array m_joint_matrixes; + u32 m_joint_total_size; }; } // end namespace scene diff --git a/src/graphics/command_buffer.cpp b/src/graphics/command_buffer.cpp index c0bc3fa11..b12445016 100644 --- a/src/graphics/command_buffer.cpp +++ b/src/graphics/command_buffer.cpp @@ -27,6 +27,7 @@ void InstanceFiller::add(GLMesh* mesh, { fillOriginOrientationScale(STK::tuple_get<0>(is), instance); instance.Texture = mesh->TextureHandles[0]; + instance.skinning_offset = STK::tuple_get<3>(is); } // ---------------------------------------------------------------------------- @@ -60,6 +61,7 @@ void InstanceFiller::add(GLMesh* mesh, instance.SecondTexture = mesh->TextureHandles[1]; instance.ThirdTexture = mesh->TextureHandles[2]; instance.FourthTexture = mesh->TextureHandles[3]; + instance.skinning_offset = STK::tuple_get<3>(is); } // ---------------------------------------------------------------------------- @@ -172,7 +174,8 @@ void SolidCommandBuffer::fill(SolidPassMeshMap *mesh_map) std::vector four_tex_material_list = createVector(Material::SHADERTYPE_DETAIL_MAP, - Material::SHADERTYPE_NORMAL_MAP); + Material::SHADERTYPE_NORMAL_MAP, + Material::SHADERTYPE_SOLID_SKINNED_MESH); fillInstanceData (mesh_map, four_tex_material_list, InstanceTypeFourTex); diff --git a/src/graphics/command_buffer.hpp b/src/graphics/command_buffer.hpp index 506e882e4..9befd35aa 100644 --- a/src/graphics/command_buffer.hpp +++ b/src/graphics/command_buffer.hpp @@ -29,7 +29,7 @@ #include #include -typedef STK::Tuple InstanceSettings; +typedef STK::Tuple InstanceSettings; struct InstanceList { diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 166175030..269a35a02 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -22,6 +22,7 @@ #include "graphics/lod_node.hpp" #include "graphics/materials.hpp" #include "graphics/shadow_matrices.hpp" +#include "graphics/stk_animated_mesh.hpp" #include "graphics/stk_billboard.hpp" #include "graphics/stk_mesh.hpp" #include "graphics/stk_mesh_scene_node.hpp" @@ -30,6 +31,8 @@ #include "tracks/track.hpp" #include "utils/profiler.hpp" +#include + // ---------------------------------------------------------------------------- void DrawCalls::clearLists() { @@ -175,6 +178,28 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, return; } + uint32_t skinning_offset = 0; + STKAnimatedMesh* am = dynamic_cast(Node); + if (am && am->useHardwareSkinning()) + { + SkinningOffset::const_iterator it = m_skinning_offsets.find(am); + if (it != m_skinning_offsets.end()) + { + skinning_offset = am->getSkinningOffset() / sizeof(core::matrix4); + } + else + { + const uint32_t cur_offset = + std::accumulate(m_skinning_offsets.begin(), + m_skinning_offsets.end(), 0, [] (const size_t previous, + const std::pair& p) + { return previous + p.second; }); + am->setSkinningOffset(cur_offset); + m_skinning_offsets[am] = am->getTotalJointSize(); + skinning_offset = cur_offset / sizeof(core::matrix4); + } + } + bool culled_for_cams[6] = { true, true, true, true, true, true }; culled_for_cams[0] = isCulledPrecise(cam, Node, irr_driver->getBoundingBoxesViz()); @@ -255,7 +280,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, { m_glow_pass_mesh[mesh->mb].m_mesh = mesh; m_glow_pass_mesh[mesh->mb].m_instance_settings - .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f)); + .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f), skinning_offset); } if (Mat == Material::SHADERTYPE_SPLATTING) { @@ -267,15 +292,12 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, } else { - // Only take render info into account if the node is not static (animated) - // So they can have different animation - std::pair mesh_render_info(mesh->mb, - dynamic_cast(Node) == NULL ? mesh->m_render_info : NULL); + std::pair mesh_render_info(mesh->mb, NULL); m_solid_pass_mesh[Mat][mesh_render_info].m_mesh = mesh; m_solid_pass_mesh[Mat][mesh_render_info].m_instance_settings.emplace_back(Node, mesh->texture_trans, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : - core::vector2df(0.0f, 0.0f))); + core::vector2df(0.0f, 0.0f)), skinning_offset); } } } @@ -351,7 +373,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, { m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_mesh = mesh; m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_instance_settings - .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f)); + .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f), skinning_offset); } } else @@ -419,7 +441,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, { m_reflective_shadow_map_mesh[Mat][mesh->mb].m_mesh = mesh; m_reflective_shadow_map_mesh[Mat][mesh->mb].m_instance_settings - .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f)); + .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f), skinning_offset); } } } @@ -683,6 +705,7 @@ void DrawCalls::drawIndirectSolidFirstPass() const { m_solid_cmd_buffer->bind(); m_solid_cmd_buffer->drawIndirectFirstPass(); + m_solid_cmd_buffer->drawIndirectFirstPass(); m_solid_cmd_buffer->drawIndirectFirstPass(); m_solid_cmd_buffer->drawIndirectFirstPass(); m_solid_cmd_buffer->drawIndirectFirstPass(); @@ -718,6 +741,7 @@ void DrawCalls::drawIndirectSolidSecondPass(const std::vector &prefilled { m_solid_cmd_buffer->bind(); m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); + m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); diff --git a/src/graphics/draw_calls.hpp b/src/graphics/draw_calls.hpp index 4222c39f5..febf51644 100644 --- a/src/graphics/draw_calls.hpp +++ b/src/graphics/draw_calls.hpp @@ -24,8 +24,11 @@ class ParticleSystemProxy; class ShadowMatrices; +class STKAnimatedMesh; class STKBillboard; +typedef std::unordered_map SkinningOffset; + class DrawCalls { private: @@ -36,6 +39,7 @@ private: std::vector m_immediate_draw_list; std::vector m_billboard_list; std::vector m_particles_list; + SkinningOffset m_skinning_offsets; std::vector m_bounding_boxes; @@ -105,6 +109,7 @@ public: void drawIndirectGlow() const; void multidrawGlow() const; void renderBoundingBoxes(); + void resetSkinningOffsets() { m_skinning_offsets.clear(); } }; #endif //HEADER_DRAW_CALLS_HPP diff --git a/src/graphics/glwrap.hpp b/src/graphics/glwrap.hpp index dbb7522e9..791a5ed8d 100644 --- a/src/graphics/glwrap.hpp +++ b/src/graphics/glwrap.hpp @@ -140,6 +140,22 @@ public: glEnableVertexAttribArray(6); glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)48); break; + case video::EVT_SKINNED_MESH: + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24); + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28); + glEnableVertexAttribArray(3); + glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)44); + glEnableVertexAttribArray(5); + glVertexAttribIPointer(5, 4, GL_INT, getVertexPitchFromType(tp), (GLvoid*)60); + glEnableVertexAttribArray(6); + glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)76); + break; } } }; diff --git a/src/graphics/material.hpp b/src/graphics/material.hpp index 69df9ad21..69d2bfac3 100644 --- a/src/graphics/material.hpp +++ b/src/graphics/material.hpp @@ -48,6 +48,7 @@ public: enum ShaderType { SHADERTYPE_SOLID = 0, + SHADERTYPE_SOLID_SKINNED_MESH, SHADERTYPE_ALPHA_TEST, SHADERTYPE_ALPHA_BLEND, SHADERTYPE_ADDITIVE, diff --git a/src/graphics/materials.cpp b/src/graphics/materials.cpp index c700832dc..5acbda0fd 100644 --- a/src/graphics/materials.cpp +++ b/src/graphics/materials.cpp @@ -24,6 +24,14 @@ const STK::Tuple DefaultMaterial::SecondPassTextures const STK::Tuple<> DefaultMaterial::ShadowTextures; const STK::Tuple DefaultMaterial::RSMTextures = STK::Tuple(0); +// ---------------------------------------------------------------------------- +const STK::Tuple SkinnedSolid::FirstPassTextures + = STK::Tuple(1); +const STK::Tuple SkinnedSolid::SecondPassTextures + = STK::Tuple(0, 1, 2); +const STK::Tuple<> SkinnedSolid::ShadowTextures; +const STK::Tuple SkinnedSolid::RSMTextures = STK::Tuple(0); + // ---------------------------------------------------------------------------- const STK::Tuple AlphaRef::FirstPassTextures = STK::Tuple(0, 1); diff --git a/src/graphics/materials.hpp b/src/graphics/materials.hpp index acc063d36..f40a04466 100644 --- a/src/graphics/materials.hpp +++ b/src/graphics/materials.hpp @@ -616,8 +616,61 @@ public: } // InstancedDetailedObjectPass2Shader }; // InstancedDetailedObjectPass2Shader +// ============================================================================ +class InstancedSkinnedMeshPass1Shader : public TextureShader +{ +public: + InstancedSkinnedMeshPass1Shader() + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", + GL_FRAGMENT_SHADER, "instanced_object_pass1.frag"); + + assignUniforms(); + assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); + } // InstancedSkinnedMeshPass1Shader +}; // InstancedSkinnedMeshPass1Shader // ============================================================================ +class InstancedSkinnedMeshPass2Shader : public TextureShader +{ +public: + InstancedSkinnedMeshPass2Shader() + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", + GL_FRAGMENT_SHADER, "instanced_object_pass2.frag"); + assignUniforms(); + assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, + 1, "SpecularMap", ST_NEAREST_FILTERED, + 2, "SSAO", ST_BILINEAR_FILTERED, + 3, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 4, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 5, "colorization_mask", ST_TRILINEAR_ANISOTROPIC_FILTERED); + } // InstancedSkinnedMeshPass2Shader +}; // InstancedSkinnedMeshPass2Shader + +// ============================================================================ +struct SkinnedSolid +{ + typedef InstancedSkinnedMeshPass1Shader InstancedFirstPassShader; + typedef InstancedSkinnedMeshPass2Shader InstancedSecondPassShader; + //typedef InstancedShadowShader InstancedShadowPassShader; + //typedef CInstancedRSMShader InstancedRSMShader; + //typedef Shaders::ObjectPass1Shader FirstPassShader; + //typedef Shaders::ObjectPass2Shader SecondPassShader; + //typedef ShadowShader ShadowPassShader; + //typedef CRSMShader RSMShader; + typedef ListSkinnedSolid List; + static const enum video::E_VERTEX_TYPE VertexType = video::EVT_SKINNED_MESH; + static const enum Material::ShaderType MaterialType + = Material::SHADERTYPE_SOLID_SKINNED_MESH; + static const enum InstanceType Instance = InstanceTypeFourTex; + static const STK::Tuple FirstPassTextures; + static const STK::Tuple SecondPassTextures; + static const STK::Tuple<> ShadowTextures; + static const STK::Tuple RSMTextures; +}; // struct DefaultMaterial + +// ---------------------------------------------------------------------------- struct DefaultMaterial { typedef InstancedObjectPass1Shader InstancedFirstPassShader; diff --git a/src/graphics/mesh_tools.cpp b/src/graphics/mesh_tools.cpp index 95bf286ee..6104cb35e 100644 --- a/src/graphics/mesh_tools.cpp +++ b/src/graphics/mesh_tools.cpp @@ -476,7 +476,7 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, void MeshTools::createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh, bool(*predicate)(scene::IMeshBuffer*)) -{ +{return; core::array& all_mb = mesh->getMeshBuffers(); const int all_mb_size = all_mb.size(); for (int i = 0; i < all_mb_size; i++) diff --git a/src/graphics/shader.hpp b/src/graphics/shader.hpp index adfc64cde..785075f2d 100644 --- a/src/graphics/shader.hpp +++ b/src/graphics/shader.hpp @@ -150,6 +150,7 @@ private: { bindPoint("MatrixData", 0); bindPoint("LightingData", 1); + bindPoint("SkinningData", 2); } // assignUniformsImpl // ------------------------------------------------------------------------ diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index ff56248ff..34ba6b05a 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -270,6 +270,7 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode, { glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedGPUObjects::getViewProjectionMatricesUBO()); glBindBufferBase(GL_UNIFORM_BUFFER, 1, SharedGPUObjects::getLightingDataUBO()); + glBindBufferBase(GL_UNIFORM_BUFFER, 2, SharedGPUObjects::getSkinningUBO()); } irr_driver->getSceneManager()->setActiveCamera(camnode); @@ -697,6 +698,7 @@ void ShaderBasedRenderer::onUnloadWorld() delete m_rtts; m_rtts = NULL; removeSkyBox(); + m_draw_calls.resetSkinningOffsets(); } // ---------------------------------------------------------------------------- diff --git a/src/graphics/shared_gpu_objects.cpp b/src/graphics/shared_gpu_objects.cpp index 7104c1761..68305ddff 100644 --- a/src/graphics/shared_gpu_objects.cpp +++ b/src/graphics/shared_gpu_objects.cpp @@ -29,6 +29,7 @@ GLuint SharedGPUObjects::m_full_screen_quad_vao; GLuint SharedGPUObjects::m_ui_vao; GLuint SharedGPUObjects::m_quad_buffer; GLuint SharedGPUObjects::m_quad_vbo; +GLuint SharedGPUObjects::m_skinning_ubo; bool SharedGPUObjects::m_has_been_initialised = false; /** Initialises m_full_screen_quad_vbo. @@ -166,6 +167,17 @@ void SharedGPUObjects::initLightingDataUBO() glBindBuffer(GL_UNIFORM_BUFFER, 0); } // initLightingDataUBO +// ---------------------------------------------------------------------------- +void SharedGPUObjects::initSkinningUBO() +{ + assert(CVS->isARBUniformBufferObjectUsable()); + glGenBuffers(1, &m_skinning_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, m_skinning_ubo); + glBufferData(GL_UNIFORM_BUFFER, 1000 * 16 * sizeof(float), 0, + GL_STREAM_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); +} // initSkinningUBO + // ---------------------------------------------------------------------------- void SharedGPUObjects::initParticleQuadVBO() { @@ -198,7 +210,8 @@ void SharedGPUObjects::init() if(CVS->isARBUniformBufferObjectUsable()) { initShadowVPMUBO(); - initLightingDataUBO(); + initLightingDataUBO(); + initSkinningUBO(); } m_has_been_initialised = true; diff --git a/src/graphics/shared_gpu_objects.hpp b/src/graphics/shared_gpu_objects.hpp index edcf5093e..df2436884 100644 --- a/src/graphics/shared_gpu_objects.hpp +++ b/src/graphics/shared_gpu_objects.hpp @@ -37,6 +37,7 @@ private: static GLuint m_ui_vao; static GLuint m_quad_buffer; static GLuint m_quad_vbo; + static GLuint m_skinning_ubo; static void initQuadVBO(); static void initQuadBuffer(); @@ -46,6 +47,7 @@ private: static void initShadowVPMUBO(); static void initLightingDataUBO(); static void initParticleQuadVBO(); + static void initSkinningUBO(); public: static void init(); @@ -116,6 +118,12 @@ public: assert(m_has_been_initialised); return m_quad_vbo; } // getQuadVBO + // ------------------------------------------------------------------------ + static GLuint getSkinningUBO() + { + assert(m_has_been_initialised); + return m_skinning_ubo; + } // getSkinningUBO }; // class SharedGPUObjecctS diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp index d51bd8698..148f6353a 100644 --- a/src/graphics/stk_animated_mesh.cpp +++ b/src/graphics/stk_animated_mesh.cpp @@ -20,12 +20,13 @@ #include "graphics/central_settings.hpp" #include "graphics/material_manager.hpp" #include "graphics/render_info.hpp" +#include "graphics/shared_gpu_objects.hpp" #include "graphics/stk_mesh.hpp" #include "graphics/vao_manager.hpp" #include #include -#include +#include "../../lib/irrlicht/source/Irrlicht/CSkinnedMesh.h" using namespace irr; @@ -34,7 +35,7 @@ irr::scene::ISceneManager* mgr, s32 id, const std::string& debug_name, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale, RenderInfo* render_info, bool all_parts_colorized) : - CAnimatedMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale) + CAnimatedMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale), m_skinned_mesh(NULL) { isGLInitialized = false; isMaterialInitialized = false; @@ -43,6 +44,10 @@ const core::vector3df& scale, RenderInfo* render_info, bool all_parts_colorized) #ifdef DEBUG m_debug_name = debug_name; #endif + m_skinning_offset = -1; + m_skinned_mesh = dynamic_cast(Mesh); + if (m_skinned_mesh) + m_skinned_mesh->convertForSkinning(); } STKAnimatedMesh::~STKAnimatedMesh() @@ -108,6 +113,16 @@ void STKAnimatedMesh::updateNoGL() for (u32 i = 0; i < mb_count; ++i) { scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); + if (!mb) + continue; + + scene::SSkinMeshBuffer* ssmb = NULL; + if (m_skinned_mesh) + { + ssmb = dynamic_cast(mb); + ssmb->VertexType = video::EVT_SKINNED_MESH; + } + bool affected = false; RenderInfo* cur_ri = m_mesh_render_info; if (!m_all_parts_colorized && mb && cur_ri) @@ -142,6 +157,8 @@ void STKAnimatedMesh::updateNoGL() GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name, affected || m_all_parts_colorized || (cur_ri && cur_ri->isTransparent()) ? cur_ri : default_ri)); + + if (m_skinned_mesh) ssmb->VertexType = video::EVT_STANDARD; } for (u32 i = 0; i < m->getMeshBufferCount(); ++i) @@ -162,7 +179,7 @@ void STKAnimatedMesh::updateNoGL() GLMesh &mesh = GLmeshes[i]; Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb); - if (rnd->isTransparent()) + /*if (rnd->isTransparent()) { TransparentMaterial TranspMat = getTransparentMaterialFromType(type, MaterialTypeParam, material); TransparentMesh[TranspMat].push_back(&mesh); @@ -174,10 +191,10 @@ void STKAnimatedMesh::updateNoGL() else TransparentMesh[TM_TRANSLUCENT_STD].push_back(&mesh); } - else + else*/ { Material::ShaderType MatType = getMeshMaterialFromType(type, mb->getVertexType(), material, NULL); - MeshSolidMaterial[MatType].push_back(&mesh); + MeshSolidMaterial[m_skinned_mesh ? Material::SHADERTYPE_SOLID_SKINNED_MESH : MatType].push_back(&mesh); } } isMaterialInitialized = true; @@ -213,6 +230,13 @@ void STKAnimatedMesh::updateGL() scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); if (!mb) continue; + scene::SSkinMeshBuffer* ssmb = NULL; + if (m_skinned_mesh) + { + ssmb = dynamic_cast(mb); + ssmb->VertexType = video::EVT_SKINNED_MESH; + } + video::IVideoDriver* driver = SceneManager->getVideoDriver(); video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType; video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type); @@ -233,7 +257,7 @@ void STKAnimatedMesh::updateGL() if (CVS->isARBBaseInstanceUsable()) { - std::pair p = VAOManager::getInstance()->getBase(mb, GLmeshes[i].m_render_info); + std::pair p = VAOManager::getInstance()->getBase(mb,NULL /*GLmeshes[i].m_render_info*/); mesh.vaoBaseVertex = p.first; mesh.vaoOffset = p.second; } @@ -243,10 +267,20 @@ void STKAnimatedMesh::updateGL() mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType()); glBindVertexArray(0); } + if (m_skinned_mesh) ssmb->VertexType = video::EVT_STANDARD; } isGLInitialized = true; } + if (m_skinned_mesh) + { + assert(m_skinning_offset != -1); + glBindBuffer(GL_UNIFORM_BUFFER, SharedGPUObjects::getSkinningUBO()); + glBufferSubData(GL_UNIFORM_BUFFER, m_skinning_offset, + m_skinned_mesh->getTotalJointSize(), m_skinned_mesh->getJointPointer()); + return; + } + for (u32 i = 0; igetMeshBufferCount(); ++i) { scene::IMeshBuffer* mb = m->getMeshBuffer(i); @@ -289,3 +323,8 @@ void STKAnimatedMesh::render() updateNoGL(); updateGL(); } + +int STKAnimatedMesh::getTotalJointSize() const +{ + return m_skinned_mesh->getTotalJointSize(); +} diff --git a/src/graphics/stk_animated_mesh.hpp b/src/graphics/stk_animated_mesh.hpp index f7c10019e..0afb27ee7 100644 --- a/src/graphics/stk_animated_mesh.hpp +++ b/src/graphics/stk_animated_mesh.hpp @@ -26,6 +26,10 @@ #include class RenderInfo; +namespace irr +{ + namespace scene { class CSkinnedMesh; } +} class STKAnimatedMesh : public irr::scene::CAnimatedMeshSceneNode, public STKMeshCommon { @@ -50,9 +54,15 @@ public: virtual void render(); virtual void setMesh(irr::scene::IAnimatedMesh* mesh); virtual bool glow() const { return false; } + int getTotalJointSize() const; + int getSkinningOffset() const { return m_skinning_offset; } + void setSkinningOffset(int offset) { m_skinning_offset = offset; } + bool useHardwareSkinning() const { return m_skinned_mesh!= NULL; } private: RenderInfo* m_mesh_render_info; bool m_all_parts_colorized; + irr::scene::CSkinnedMesh* m_skinned_mesh; + int m_skinning_offset; }; #endif // STKANIMATEDMESH_HPP diff --git a/src/graphics/stk_mesh.cpp b/src/graphics/stk_mesh.cpp index e58faece5..9cd2df055 100644 --- a/src/graphics/stk_mesh.cpp +++ b/src/graphics/stk_mesh.cpp @@ -155,6 +155,22 @@ GLuint createVAO(GLuint vbo, GLuint idx, video::E_VERTEX_TYPE type) glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)48); break; + case video::EVT_SKINNED_MESH: + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), 0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)12); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(type), (GLvoid*)24); + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)28); + glEnableVertexAttribArray(3); + glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)44); + glEnableVertexAttribArray(5); + glVertexAttribIPointer(5, 4, GL_INT, getVertexPitchFromType(type), (GLvoid*)60); + glEnableVertexAttribArray(6); + glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)76); + break; default: assert(0 && "Wrong vertex type"); } @@ -346,8 +362,8 @@ static void setTexture(GLMesh &mesh, unsigned i, bool is_srgb, { if (!mesh.textures[i]) { - Log::error("STKMesh", "Missing texture %d for material %s", i, - mat_name.c_str()); + //Log::error("STKMesh", "Missing texture %d for material %s", i, + // mat_name.c_str()); // use unicolor texture to replace missing texture mesh.textures[i] = getUnicolorTexture(video::SColor(255, 127, 127, 127)); @@ -413,6 +429,7 @@ void initTextures(GLMesh &mesh, Material::ShaderType mat) break; case Material::SHADERTYPE_DETAIL_MAP: case Material::SHADERTYPE_NORMAL_MAP: + case Material::SHADERTYPE_SOLID_SKINNED_MESH: setTexture(mesh, 0, true, getShaderTypeName(mat)); setTexture(mesh, 1, false, getShaderTypeName(mat)); setTexture(mesh, 2, false, getShaderTypeName(mat)); diff --git a/src/graphics/stk_mesh.hpp b/src/graphics/stk_mesh.hpp index 3e089bcac..39a113422 100644 --- a/src/graphics/stk_mesh.hpp +++ b/src/graphics/stk_mesh.hpp @@ -116,6 +116,12 @@ class ListMatDefault : public MeshList {}; +// ---------------------------------------------------------------------------- +class ListSkinnedSolid : public MeshList +{}; + // ---------------------------------------------------------------------------- class ListMatAlphaRef : public MeshList::SetVertexAttrib() glEnableVertexAttribArray(11); glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceDataSingleTex), (GLvoid*)(9 * sizeof(float))); glVertexAttribDivisorARB(11, 1); + glEnableVertexAttribArray(15); + glVertexAttribIPointer(15, 1, GL_UNSIGNED_INT, sizeof(InstanceDataSingleTex), (GLvoid*)(11 * sizeof(float))); + glVertexAttribDivisorARB(15, 1); } template<> @@ -200,6 +203,9 @@ void VAOInstanceUtil::SetVertexAttrib() glEnableVertexAttribArray(14); glVertexAttribIPointer(14, 2, GL_UNSIGNED_INT, sizeof(InstanceDataFourTex), (GLvoid*)(13 * sizeof(float) + 6 * sizeof(unsigned))); glVertexAttribDivisorARB(14, 1); + glEnableVertexAttribArray(15); + glVertexAttribIPointer(15, 1, GL_UNSIGNED_INT, sizeof(InstanceDataFourTex), (GLvoid*)(13 * sizeof(float) + 8 * sizeof(unsigned))); + glVertexAttribDivisorARB(15, 1); } template<> @@ -216,7 +222,7 @@ void VAOManager::regenerateInstancedVAO() { cleanInstanceVAOs(); - enum video::E_VERTEX_TYPE IrrVT[] = { video::EVT_STANDARD, video::EVT_2TCOORDS, video::EVT_TANGENTS }; + enum video::E_VERTEX_TYPE IrrVT[] = { video::EVT_STANDARD, video::EVT_2TCOORDS, video::EVT_TANGENTS, video::EVT_SKINNED_MESH }; for (unsigned i = 0; i < VTXTYPE_COUNT; i++) { video::E_VERTEX_TYPE tp = IrrVT[i]; @@ -264,6 +270,8 @@ size_t VAOManager::getVertexPitch(enum VTXTYPE tp) const return getVertexPitchFromType(video::EVT_2TCOORDS); case VTXTYPE_TANGENT: return getVertexPitchFromType(video::EVT_TANGENTS); + case VTXTYPE_SKINNED_MESH: + return getVertexPitchFromType(video::EVT_SKINNED_MESH); default: assert(0 && "Wrong vtxtype"); return -1; @@ -282,6 +290,8 @@ VAOManager::VTXTYPE VAOManager::getVTXTYPE(video::E_VERTEX_TYPE type) return VTXTYPE_TCOORD; case video::EVT_TANGENTS: return VTXTYPE_TANGENT; + case video::EVT_SKINNED_MESH: + return VTXTYPE_SKINNED_MESH; } }; @@ -296,6 +306,8 @@ irr::video::E_VERTEX_TYPE VAOManager::getVertexType(enum VTXTYPE tp) return video::EVT_2TCOORDS; case VTXTYPE_TANGENT: return video::EVT_TANGENTS; + case VTXTYPE_SKINNED_MESH: + return video::EVT_SKINNED_MESH; } } diff --git a/src/graphics/vao_manager.hpp b/src/graphics/vao_manager.hpp index 62bd9d23d..d15bd2072 100644 --- a/src/graphics/vao_manager.hpp +++ b/src/graphics/vao_manager.hpp @@ -62,6 +62,7 @@ struct InstanceDataSingleTex float Z; } Scale; uint64_t Texture; + uint32_t skinning_offset; #ifdef WIN32 }; #else @@ -135,6 +136,7 @@ struct InstanceDataFourTex uint64_t SecondTexture; uint64_t ThirdTexture; uint64_t FourthTexture; + uint32_t skinning_offset; #ifdef WIN32 }; #else @@ -197,7 +199,7 @@ struct MeshRenderInfoEquals : std::binary_function class VAOManager : public Singleton { - 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]; From a3905a1e19d348bd5b5c658c2b4763e8ac300437 Mon Sep 17 00:00:00 2001 From: Benau Date: Wed, 7 Dec 2016 08:07:01 +0800 Subject: [PATCH 003/206] Allow tangent mesh to be converted --- lib/irrlicht/include/SSkinMeshBuffer.h | 35 +++++++++++++++++-- lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp | 4 +-- lib/irrlicht/source/Irrlicht/CSkinnedMesh.h | 34 +++++++++--------- src/graphics/mesh_tools.cpp | 2 +- 4 files changed, 53 insertions(+), 22 deletions(-) diff --git a/lib/irrlicht/include/SSkinMeshBuffer.h b/lib/irrlicht/include/SSkinMeshBuffer.h index d510741eb..902b635ef 100644 --- a/lib/irrlicht/include/SSkinMeshBuffer.h +++ b/lib/irrlicht/include/SSkinMeshBuffer.h @@ -236,17 +236,48 @@ struct SSkinMeshBuffer : public IMeshBuffer { for(u32 n=0;n > > WeightInfluence; namespace irr @@ -173,17 +173,17 @@ namespace scene IAnimatedMeshSceneNode* node, ISceneManager* smgr); - void convertForSkinning(); + void convertForSkinning(); - void computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi); + void computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi); - const void* getJointPointer() const { return m_joint_matrixes.const_pointer(); } + const void* getJointPointer() const { return m_joint_matrixes.const_pointer(); } u32 getTotalJointSize() const { _IRR_DEBUG_BREAK_IF(m_joint_total_size == 0); return m_joint_total_size; - } + } private: void checkForAnimation(); @@ -230,7 +230,7 @@ private: bool HasAnimation; bool PreparedForSkinning; bool AnimateNormals; - bool HardwareSkinning; + bool HardwareSkinning; core::array m_joint_matrixes; u32 m_joint_total_size; }; diff --git a/src/graphics/mesh_tools.cpp b/src/graphics/mesh_tools.cpp index 6104cb35e..95bf286ee 100644 --- a/src/graphics/mesh_tools.cpp +++ b/src/graphics/mesh_tools.cpp @@ -476,7 +476,7 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, void MeshTools::createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh, bool(*predicate)(scene::IMeshBuffer*)) -{return; +{ core::array& all_mb = mesh->getMeshBuffers(); const int all_mb_size = all_mb.size(); for (int i = 0; i < all_mb_size; i++) From ac8d7aa8c73c67bfc937f20af541274048869306 Mon Sep 17 00:00:00 2001 From: Benau Date: Wed, 7 Dec 2016 08:18:19 +0800 Subject: [PATCH 004/206] Try to fix the build --- lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp index bacaa6922..a49e58db1 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp @@ -1411,7 +1411,7 @@ void CSkinnedMesh::convertForSkinning() if (LocalBuffers[b]) LocalBuffers[b]->convertForSkinning(); - wi.push_back(core::array> ()); + wi.push_back(core::array > ()); for (u32 i = 0; i < LocalBuffers[b]->getVertexCount(); i++) wi[b].push_back(core::array()); } From fcebb5c2e6daf08c3f10a5563be2a1b361f1ae3f Mon Sep 17 00:00:00 2001 From: Benau Date: Wed, 7 Dec 2016 09:29:40 +0800 Subject: [PATCH 005/206] Fix crash with normal map skinned mesh --- src/graphics/stk_animated_mesh.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp index 148f6353a..698ad76fa 100644 --- a/src/graphics/stk_animated_mesh.cpp +++ b/src/graphics/stk_animated_mesh.cpp @@ -117,6 +117,7 @@ void STKAnimatedMesh::updateNoGL() continue; scene::SSkinMeshBuffer* ssmb = NULL; + video::E_VERTEX_TYPE prev_type = mb->getVertexType(); if (m_skinned_mesh) { ssmb = dynamic_cast(mb); @@ -158,7 +159,7 @@ void STKAnimatedMesh::updateNoGL() affected || m_all_parts_colorized || (cur_ri && cur_ri->isTransparent()) ? cur_ri : default_ri)); - if (m_skinned_mesh) ssmb->VertexType = video::EVT_STANDARD; + if (m_skinned_mesh) ssmb->VertexType = prev_type; } for (u32 i = 0; i < m->getMeshBufferCount(); ++i) @@ -231,6 +232,7 @@ void STKAnimatedMesh::updateGL() if (!mb) continue; scene::SSkinMeshBuffer* ssmb = NULL; + video::E_VERTEX_TYPE prev_type = mb->getVertexType(); if (m_skinned_mesh) { ssmb = dynamic_cast(mb); @@ -267,7 +269,7 @@ void STKAnimatedMesh::updateGL() mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType()); glBindVertexArray(0); } - if (m_skinned_mesh) ssmb->VertexType = video::EVT_STANDARD; + if (m_skinned_mesh) ssmb->VertexType = prev_type; } isGLInitialized = true; } From d21e5e0f76a16d6787ece20c26a51314ae9c1ea5 Mon Sep 17 00:00:00 2001 From: Benau Date: Wed, 7 Dec 2016 16:08:57 +0800 Subject: [PATCH 006/206] Make skinning offset changeable by culling --- lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp | 2 +- src/graphics/draw_calls.cpp | 39 ++++++++----------- src/graphics/draw_calls.hpp | 5 +-- src/graphics/shader_based_renderer.cpp | 3 +- src/graphics/stk_animated_mesh.cpp | 25 ++++++++---- src/graphics/stk_animated_mesh.hpp | 6 +-- src/graphics/stk_mesh.cpp | 4 +- 7 files changed, 40 insertions(+), 44 deletions(-) diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp index a49e58db1..ed09ae5a9 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp @@ -1458,7 +1458,7 @@ void CSkinnedMesh::convertForSkinning() } SkinnedLastFrame = false; skinMesh(); - m_joint_total_size = m_joint_matrixes.size() * sizeof(core::matrix4); + m_joint_total_size = m_joint_matrixes.size(); } void CSkinnedMesh::computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi) diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 269a35a02..ec7e18ce9 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -178,28 +178,6 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, return; } - uint32_t skinning_offset = 0; - STKAnimatedMesh* am = dynamic_cast(Node); - if (am && am->useHardwareSkinning()) - { - SkinningOffset::const_iterator it = m_skinning_offsets.find(am); - if (it != m_skinning_offsets.end()) - { - skinning_offset = am->getSkinningOffset() / sizeof(core::matrix4); - } - else - { - const uint32_t cur_offset = - std::accumulate(m_skinning_offsets.begin(), - m_skinning_offsets.end(), 0, [] (const size_t previous, - const std::pair& p) - { return previous + p.second; }); - am->setSkinningOffset(cur_offset); - m_skinning_offsets[am] = am->getTotalJointSize(); - skinning_offset = cur_offset / sizeof(core::matrix4); - } - } - bool culled_for_cams[6] = { true, true, true, true, true, true }; culled_for_cams[0] = isCulledPrecise(cam, Node, irr_driver->getBoundingBoxesViz()); @@ -268,6 +246,21 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, for (GLMesh *mesh : node->TransparentMesh[TM_DISPLACEMENT]) pushVector(ListDisplacement::getInstance(), mesh, Node->getAbsoluteTransformation()); + uint32_t skinning_offset = 0; + STKAnimatedMesh* am = dynamic_cast(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 = + std::accumulate(m_mesh_for_skinning.begin(), + m_mesh_for_skinning.end(), 0, [] (const size_t previous, + const STKAnimatedMesh* m) + { return previous + m->getTotalJointSize(); }); + m_mesh_for_skinning.insert(am); + am->setSkinningOffset(skinning_offset * sizeof(core::matrix4)); + } + if (!culled_for_cams[0]) { for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat) @@ -573,7 +566,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(); diff --git a/src/graphics/draw_calls.hpp b/src/graphics/draw_calls.hpp index febf51644..e45333e56 100644 --- a/src/graphics/draw_calls.hpp +++ b/src/graphics/draw_calls.hpp @@ -27,8 +27,6 @@ class ShadowMatrices; class STKAnimatedMesh; class STKBillboard; -typedef std::unordered_map SkinningOffset; - class DrawCalls { private: @@ -39,7 +37,7 @@ private: std::vector m_immediate_draw_list; std::vector m_billboard_list; std::vector m_particles_list; - SkinningOffset m_skinning_offsets; + std::set m_mesh_for_skinning; std::vector m_bounding_boxes; @@ -109,7 +107,6 @@ public: void drawIndirectGlow() const; void multidrawGlow() const; void renderBoundingBoxes(); - void resetSkinningOffsets() { m_skinning_offsets.clear(); } }; #endif //HEADER_DRAW_CALLS_HPP diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index 34ba6b05a..140635edb 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -697,8 +697,7 @@ void ShaderBasedRenderer::onUnloadWorld() { delete m_rtts; m_rtts = NULL; - removeSkyBox(); - m_draw_calls.resetSkinningOffsets(); + removeSkyBox(); } // ---------------------------------------------------------------------------- diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp index 698ad76fa..13f37149c 100644 --- a/src/graphics/stk_animated_mesh.cpp +++ b/src/graphics/stk_animated_mesh.cpp @@ -35,7 +35,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), m_skinned_mesh(NULL) + CAnimatedMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale), + m_skinned_mesh(NULL), m_skinning_offset(-1) { isGLInitialized = false; isMaterialInitialized = false; @@ -44,10 +45,7 @@ const core::vector3df& scale, RenderInfo* render_info, bool all_parts_colorized) #ifdef DEBUG m_debug_name = debug_name; #endif - m_skinning_offset = -1; - m_skinned_mesh = dynamic_cast(Mesh); - if (m_skinned_mesh) - m_skinned_mesh->convertForSkinning(); + resetSkinningState(mesh); } STKAnimatedMesh::~STKAnimatedMesh() @@ -82,6 +80,7 @@ void STKAnimatedMesh::setMesh(scene::IAnimatedMesh* mesh) isMaterialInitialized = false; cleanGLMeshes(); CAnimatedMeshSceneNode::setMesh(mesh); + resetSkinningState(mesh); } void STKAnimatedMesh::updateNoGL() @@ -274,12 +273,14 @@ void STKAnimatedMesh::updateGL() isGLInitialized = true; } - if (m_skinned_mesh) + if (useHardwareSkinning()) { - assert(m_skinning_offset != -1); + if (m_skinning_offset == -1) return; glBindBuffer(GL_UNIFORM_BUFFER, SharedGPUObjects::getSkinningUBO()); glBufferSubData(GL_UNIFORM_BUFFER, m_skinning_offset, - m_skinned_mesh->getTotalJointSize(), m_skinned_mesh->getJointPointer()); + m_skinned_mesh->getTotalJointSize() * sizeof(core::matrix4), + m_skinned_mesh->getJointPointer()); + m_skinning_offset = -1; return; } @@ -330,3 +331,11 @@ int STKAnimatedMesh::getTotalJointSize() const { return m_skinned_mesh->getTotalJointSize(); } + +void STKAnimatedMesh::resetSkinningState(scene::IAnimatedMesh* mesh) +{ + m_skinning_offset = -1; + m_skinned_mesh = dynamic_cast(mesh); + if (m_skinned_mesh) + m_skinned_mesh->convertForSkinning(); +} diff --git a/src/graphics/stk_animated_mesh.hpp b/src/graphics/stk_animated_mesh.hpp index 0afb27ee7..3115f0edc 100644 --- a/src/graphics/stk_animated_mesh.hpp +++ b/src/graphics/stk_animated_mesh.hpp @@ -55,9 +55,9 @@ public: virtual void setMesh(irr::scene::IAnimatedMesh* mesh); virtual bool glow() const { return false; } int getTotalJointSize() const; - int getSkinningOffset() const { return m_skinning_offset; } - void setSkinningOffset(int offset) { m_skinning_offset = offset; } - bool useHardwareSkinning() const { return m_skinned_mesh!= NULL; } + void setSkinningOffset(int offset) { m_skinning_offset = offset; } + bool useHardwareSkinning() const { return m_skinned_mesh != NULL; } + void resetSkinningState(scene::IAnimatedMesh*); private: RenderInfo* m_mesh_render_info; bool m_all_parts_colorized; diff --git a/src/graphics/stk_mesh.cpp b/src/graphics/stk_mesh.cpp index 9cd2df055..c8bf040b1 100644 --- a/src/graphics/stk_mesh.cpp +++ b/src/graphics/stk_mesh.cpp @@ -219,8 +219,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()) { @@ -250,7 +248,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 From 407ed319de9b5f0ffbc0acf2ecdccdabc0a49a81 Mon Sep 17 00:00:00 2001 From: Benau Date: Wed, 7 Dec 2016 16:26:22 +0800 Subject: [PATCH 007/206] Show debug info about total skinning joints being calculated --- src/graphics/draw_calls.cpp | 16 +++++++++++----- src/graphics/draw_calls.hpp | 1 + src/graphics/irr_driver.cpp | 6 ++++-- src/graphics/irr_driver.hpp | 2 ++ 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index ec7e18ce9..3c1ac7d44 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -252,11 +252,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, (!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 = - std::accumulate(m_mesh_for_skinning.begin(), - m_mesh_for_skinning.end(), 0, [] (const size_t previous, - const STKAnimatedMesh* m) - { return previous + m->getTotalJointSize(); }); + skinning_offset = getSkinningOffset(); m_mesh_for_skinning.insert(am); am->setSkinningOffset(skinning_offset * sizeof(core::matrix4)); } @@ -584,6 +580,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); @@ -882,3 +879,12 @@ void DrawCalls::multidrawGlow() const m_glow_cmd_buffer->multidraw(); } #endif // !defined(USE_GLES2) + +// ---------------------------------------------------------------------------- +uint32_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->getTotalJointSize(); }); +} // getSkinningOffset diff --git a/src/graphics/draw_calls.hpp b/src/graphics/draw_calls.hpp index e45333e56..f052f3cf1 100644 --- a/src/graphics/draw_calls.hpp +++ b/src/graphics/draw_calls.hpp @@ -107,6 +107,7 @@ public: void drawIndirectGlow() const; void multidrawGlow() const; void renderBoundingBoxes(); + uint32_t getSkinningOffset() const; }; #endif //HEADER_DRAW_CALLS_HPP diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 22afc323a..de8f93099 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -139,6 +139,7 @@ IrrDriver::IrrDriver() m_lightviz = m_shadowviz = m_distortviz = m_rsm = m_rh = m_gi = false; m_boundingboxesviz = false; m_last_light_bucket_distance = 0; + m_skinning_joint = 0; } // IrrDriver // ---------------------------------------------------------------------------- @@ -1899,9 +1900,10 @@ void IrrDriver::displayFPS() if ((UserConfigParams::m_artist_debug_mode)&&(CVS->isGLSL())) { fps_string = _("FPS: %d/%d/%d - PolyCount: %d Solid, " - "%d Shadows - LightDist : %d", + "%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)); diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index 2dc8b03f7..c7803d8c8 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -173,6 +173,7 @@ private: bool m_boundingboxesviz; unsigned m_last_light_bucket_distance; + unsigned m_skinning_joint; u32 m_renderpass; class STKMeshSceneNode *m_sun_interposer; core::vector3df m_sun_direction; @@ -292,6 +293,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(); From 21d9117b2d2bc4af144291e922d503e60e08f841 Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 8 Dec 2016 16:12:54 +0800 Subject: [PATCH 008/206] Fix matrix4 pointer in windows Also allow minimum azdo rendering and avoid skinning empty joints --- lib/irrlicht/source/Irrlicht/CSkinnedMesh.h | 14 ++++++++++++-- src/graphics/draw_calls.cpp | 4 +++- src/graphics/stk_animated_mesh.cpp | 10 +++++++--- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h index 64a93e24d..0ffdc6984 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h @@ -14,6 +14,17 @@ #include "matrix4.h" #include "quaternion.h" +class Matrix4x4 +{ +private: + float data[16]; +public: + inline Matrix4x4(const irr::core::matrix4& m) + { + memcpy(data, m.pointer(), 16 * sizeof(float)); + } +}; + class JointInfluence { public: @@ -181,7 +192,6 @@ namespace scene u32 getTotalJointSize() const { - _IRR_DEBUG_BREAK_IF(m_joint_total_size == 0); return m_joint_total_size; } @@ -231,7 +241,7 @@ private: bool PreparedForSkinning; bool AnimateNormals; bool HardwareSkinning; - core::array m_joint_matrixes; + core::array m_joint_matrixes; u32 m_joint_total_size; }; diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 3c1ac7d44..431561c50 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -254,7 +254,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, { skinning_offset = getSkinningOffset(); m_mesh_for_skinning.insert(am); - am->setSkinningOffset(skinning_offset * sizeof(core::matrix4)); + am->setSkinningOffset(skinning_offset * 16 * sizeof(float)); } if (!culled_for_cams[0]) @@ -712,6 +712,7 @@ void DrawCalls::multidrawSolidFirstPass() const { m_solid_cmd_buffer->bind(); m_solid_cmd_buffer->multidrawFirstPass(); + m_solid_cmd_buffer->multidrawFirstPass(); m_solid_cmd_buffer->multidrawFirstPass(); m_solid_cmd_buffer->multidrawFirstPass(); m_solid_cmd_buffer->multidrawFirstPass(); @@ -750,6 +751,7 @@ void DrawCalls::multidrawSolidSecondPass(const std::vector &handles) c { m_solid_cmd_buffer->bind(); m_solid_cmd_buffer->multidraw2ndPass(handles); + m_solid_cmd_buffer->multidraw2ndPass(handles); m_solid_cmd_buffer->multidraw2ndPass(handles); m_solid_cmd_buffer->multidraw2ndPass(handles); m_solid_cmd_buffer->multidraw2ndPass(handles); diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp index 13f37149c..df131f8c5 100644 --- a/src/graphics/stk_animated_mesh.cpp +++ b/src/graphics/stk_animated_mesh.cpp @@ -243,7 +243,7 @@ void STKAnimatedMesh::updateGL() video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type); GLMesh &mesh = GLmeshes[i]; - if (!rnd->isTransparent()) + if (1)//!rnd->isTransparent()) { Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb); Material* material2 = NULL; @@ -251,7 +251,7 @@ void STKAnimatedMesh::updateGL() material2 = material_manager->getMaterialFor(mb->getMaterial().getTexture(1), mb); Material::ShaderType MatType = getMeshMaterialFromType(type, mb->getVertexType(), material, material2); - initTextures(mesh, MatType); + initTextures(mesh, m_skinned_mesh ? Material::SHADERTYPE_SOLID_SKINNED_MESH : MatType); } else initTexturesTransparent(mesh); @@ -278,7 +278,7 @@ void STKAnimatedMesh::updateGL() if (m_skinning_offset == -1) return; glBindBuffer(GL_UNIFORM_BUFFER, SharedGPUObjects::getSkinningUBO()); glBufferSubData(GL_UNIFORM_BUFFER, m_skinning_offset, - m_skinned_mesh->getTotalJointSize() * sizeof(core::matrix4), + m_skinned_mesh->getTotalJointSize() * 16 * sizeof(float), m_skinned_mesh->getJointPointer()); m_skinning_offset = -1; return; @@ -337,5 +337,9 @@ void STKAnimatedMesh::resetSkinningState(scene::IAnimatedMesh* mesh) m_skinning_offset = -1; m_skinned_mesh = dynamic_cast(mesh); if (m_skinned_mesh) + { m_skinned_mesh->convertForSkinning(); + if (m_skinned_mesh->getTotalJointSize() == 0) + m_skinned_mesh = NULL; + } } From b7e047b4c1883e5f511c165ba365fc6230b92725 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 9 Dec 2016 14:16:30 +0800 Subject: [PATCH 009/206] Avoid using else if in skinning vertex shader --- data/shaders/header.txt | 3 +- data/shaders/instanced_skinning.vert | 64 ++++++------------- lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp | 2 +- src/graphics/command_buffer.hpp | 2 +- src/graphics/draw_calls.cpp | 6 +- src/graphics/draw_calls.hpp | 2 +- src/graphics/shared_gpu_objects.cpp | 6 ++ src/graphics/vao_manager.cpp | 4 +- src/graphics/vao_manager.hpp | 4 +- 9 files changed, 37 insertions(+), 56 deletions(-) diff --git a/data/shaders/header.txt b/data/shaders/header.txt index 253e82a29..88ee3a2be 100644 --- a/data/shaders/header.txt +++ b/data/shaders/header.txt @@ -1,5 +1,6 @@ #ifndef HEADER_TXT #define HEADER_TXT +#define MAX_BONES 1000 #ifdef UBO_DISABLED uniform mat4 ViewMatrix; uniform mat4 ProjectionMatrix; @@ -66,7 +67,7 @@ layout (std140) uniform LightingData layout (std140) uniform SkinningData { - mat4 joint_matrices[1000]; + mat4 joint_matrices[MAX_BONES]; }; #endif diff --git a/data/shaders/instanced_skinning.vert b/data/shaders/instanced_skinning.vert index fb22ca2e0..69aa38ecd 100644 --- a/data/shaders/instanced_skinning.vert +++ b/data/shaders/instanced_skinning.vert @@ -16,7 +16,7 @@ layout(location = 12) in sampler2D SecondHandle; layout(location = 13) in sampler2D ThirdHandle; layout(location = 14) in sampler2D FourthHandle; #endif -layout(location = 15) in uint skinning_offset; +layout(location = 15) in int skinning_offset; out vec3 nor; out vec3 tangent; @@ -42,62 +42,36 @@ void main(void) vec4 idle_normal = vec4(Normal, 0.); vec4 skinned_position = vec4(0.); vec4 skinned_normal = vec4(0.); + // Note : For normal we assume no scale factor in bone (otherwise we'll have to compute inversematrix for each bones...) vec4 single_bone_influenced_position; vec4 single_bone_influenced_normal; - if (Joint[0] >= 0) - { - single_bone_influenced_position = joint_matrices[Joint[0] + skinning_offset] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - single_bone_influenced_normal = joint_matrices[Joint[0] + skinning_offset] * idle_normal; - } - else - { - single_bone_influenced_position = idle_position; - single_bone_influenced_normal = idle_normal; - } + + // First bone: + single_bone_influenced_position = joint_matrices[clamp(Joint[0] + skinning_offset, 0, MAX_BONES)] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + single_bone_influenced_normal = joint_matrices[clamp(Joint[0] + skinning_offset, 0, MAX_BONES)] * idle_normal; skinned_position += Weight[0] * single_bone_influenced_position; skinned_normal += Weight[0] * single_bone_influenced_normal; - if (Joint[1] >= 0) - { - single_bone_influenced_position= joint_matrices[Joint[1] + skinning_offset] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - single_bone_influenced_normal = joint_matrices[Joint[1] + skinning_offset] * idle_normal; - } - else - { - single_bone_influenced_position = idle_position; - single_bone_influenced_normal = idle_normal; - } + // Second bone: + single_bone_influenced_position = joint_matrices[clamp(Joint[1] + skinning_offset, 0, MAX_BONES)] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + single_bone_influenced_normal = joint_matrices[clamp(Joint[1] + skinning_offset, 0, MAX_BONES)] * idle_normal; skinned_position += Weight[1] * single_bone_influenced_position; skinned_normal += Weight[1] * single_bone_influenced_normal; - if (Joint[2] >= 0) - { - single_bone_influenced_position = joint_matrices[Joint[2] + skinning_offset] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - single_bone_influenced_normal = joint_matrices[Joint[2] + skinning_offset] * idle_normal; - } - else - { - single_bone_influenced_position = idle_position; - single_bone_influenced_normal = idle_normal; - } + // Third bone: + single_bone_influenced_position = joint_matrices[clamp(Joint[2] + skinning_offset, 0, MAX_BONES)] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + single_bone_influenced_normal = joint_matrices[clamp(Joint[2] + skinning_offset, 0, MAX_BONES)] * idle_normal; skinned_position += Weight[2] * single_bone_influenced_position; skinned_normal += Weight[2] * single_bone_influenced_normal; - if (Joint[3] >= 0) - { - single_bone_influenced_position = joint_matrices[Joint[3] + skinning_offset] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - single_bone_influenced_normal = joint_matrices[Joint[3] + skinning_offset] * idle_normal; - } - else - { - single_bone_influenced_position = idle_position; - single_bone_influenced_normal = idle_normal; - } + // Fourth bone: + single_bone_influenced_position = joint_matrices[clamp(Joint[3] + skinning_offset, 0, MAX_BONES)] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + single_bone_influenced_normal = joint_matrices[clamp(Joint[3] + skinning_offset, 0, MAX_BONES)] * idle_normal; skinned_position += Weight[3] * single_bone_influenced_position; skinned_normal += Weight[3] * single_bone_influenced_normal; diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp index ed09ae5a9..3fb8e715b 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp @@ -1439,7 +1439,7 @@ void CSkinnedMesh::convertForSkinning() influence = reported_weight[j]; else { - influence.joint_idx = -1; + influence.joint_idx = -1000; influence.weight = remaining_weight; } remaining_weight -= influence.weight; diff --git a/src/graphics/command_buffer.hpp b/src/graphics/command_buffer.hpp index 9befd35aa..c3d038ecb 100644 --- a/src/graphics/command_buffer.hpp +++ b/src/graphics/command_buffer.hpp @@ -29,7 +29,7 @@ #include #include -typedef STK::Tuple InstanceSettings; +typedef STK::Tuple InstanceSettings; struct InstanceList { diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 431561c50..8b4e774d4 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -246,13 +246,13 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, for (GLMesh *mesh : node->TransparentMesh[TM_DISPLACEMENT]) pushVector(ListDisplacement::getInstance(), mesh, Node->getAbsoluteTransformation()); - uint32_t skinning_offset = 0; + int32_t skinning_offset = 0; STKAnimatedMesh* am = dynamic_cast(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(); + skinning_offset = getSkinningOffset() + 1/*reserved identity matrix*/; m_mesh_for_skinning.insert(am); am->setSkinningOffset(skinning_offset * 16 * sizeof(float)); } @@ -883,7 +883,7 @@ void DrawCalls::multidrawGlow() const #endif // !defined(USE_GLES2) // ---------------------------------------------------------------------------- -uint32_t DrawCalls::getSkinningOffset() const +int32_t DrawCalls::getSkinningOffset() const { return std::accumulate(m_mesh_for_skinning.begin(), m_mesh_for_skinning.end(), 0, [] diff --git a/src/graphics/draw_calls.hpp b/src/graphics/draw_calls.hpp index f052f3cf1..55d7b12c5 100644 --- a/src/graphics/draw_calls.hpp +++ b/src/graphics/draw_calls.hpp @@ -107,7 +107,7 @@ public: void drawIndirectGlow() const; void multidrawGlow() const; void renderBoundingBoxes(); - uint32_t getSkinningOffset() const; + int32_t getSkinningOffset() const; }; #endif //HEADER_DRAW_CALLS_HPP diff --git a/src/graphics/shared_gpu_objects.cpp b/src/graphics/shared_gpu_objects.cpp index 68305ddff..85b56a60f 100644 --- a/src/graphics/shared_gpu_objects.cpp +++ b/src/graphics/shared_gpu_objects.cpp @@ -18,6 +18,8 @@ #include "graphics/shared_gpu_objects.hpp" #include "graphics/central_settings.hpp" +#include "matrix4.h" + GLuint SharedGPUObjects::m_billboard_vbo; GLuint SharedGPUObjects::m_sky_tri_vbo; GLuint SharedGPUObjects::m_frustrum_vbo; @@ -171,10 +173,14 @@ void SharedGPUObjects::initLightingDataUBO() void SharedGPUObjects::initSkinningUBO() { assert(CVS->isARBUniformBufferObjectUsable()); + irr::core::matrix4 m; glGenBuffers(1, &m_skinning_ubo); glBindBuffer(GL_UNIFORM_BUFFER, m_skinning_ubo); glBufferData(GL_UNIFORM_BUFFER, 1000 * 16 * sizeof(float), 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 diff --git a/src/graphics/vao_manager.cpp b/src/graphics/vao_manager.cpp index 04e752b1a..7e880da3f 100644 --- a/src/graphics/vao_manager.cpp +++ b/src/graphics/vao_manager.cpp @@ -162,7 +162,7 @@ void VAOInstanceUtil::SetVertexAttrib() glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceDataSingleTex), (GLvoid*)(9 * sizeof(float))); glVertexAttribDivisorARB(11, 1); glEnableVertexAttribArray(15); - glVertexAttribIPointer(15, 1, GL_UNSIGNED_INT, sizeof(InstanceDataSingleTex), (GLvoid*)(11 * sizeof(float))); + glVertexAttribIPointer(15, 1, GL_INT, sizeof(InstanceDataSingleTex), (GLvoid*)(11 * sizeof(float))); glVertexAttribDivisorARB(15, 1); } @@ -204,7 +204,7 @@ void VAOInstanceUtil::SetVertexAttrib() glVertexAttribIPointer(14, 2, GL_UNSIGNED_INT, sizeof(InstanceDataFourTex), (GLvoid*)(13 * sizeof(float) + 6 * sizeof(unsigned))); glVertexAttribDivisorARB(14, 1); glEnableVertexAttribArray(15); - glVertexAttribIPointer(15, 1, GL_UNSIGNED_INT, sizeof(InstanceDataFourTex), (GLvoid*)(13 * sizeof(float) + 8 * sizeof(unsigned))); + glVertexAttribIPointer(15, 1, GL_INT, sizeof(InstanceDataFourTex), (GLvoid*)(13 * sizeof(float) + 8 * sizeof(unsigned))); glVertexAttribDivisorARB(15, 1); } diff --git a/src/graphics/vao_manager.hpp b/src/graphics/vao_manager.hpp index d15bd2072..76a752dfd 100644 --- a/src/graphics/vao_manager.hpp +++ b/src/graphics/vao_manager.hpp @@ -62,7 +62,7 @@ struct InstanceDataSingleTex float Z; } Scale; uint64_t Texture; - uint32_t skinning_offset; + int32_t skinning_offset; #ifdef WIN32 }; #else @@ -136,7 +136,7 @@ struct InstanceDataFourTex uint64_t SecondTexture; uint64_t ThirdTexture; uint64_t FourthTexture; - uint32_t skinning_offset; + int32_t skinning_offset; #ifdef WIN32 }; #else From 76e070b70973a1fa8cb47e2d19b50d025e1a7269 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 9 Dec 2016 18:41:13 +0800 Subject: [PATCH 010/206] Allow GL3 to have hardware skinning --- data/shaders/skinning.vert | 143 +++++++++++++++++---------------- src/graphics/draw_calls.cpp | 7 ++ src/graphics/draw_policies.cpp | 2 + src/graphics/materials.hpp | 6 +- src/graphics/shaders.cpp | 23 ++++++ src/graphics/shaders.hpp | 18 +++++ src/graphics/stk_mesh.hpp | 2 +- 7 files changed, 128 insertions(+), 73 deletions(-) diff --git a/data/shaders/skinning.vert b/data/shaders/skinning.vert index e9d4dd144..25718a9cc 100644 --- a/data/shaders/skinning.vert +++ b/data/shaders/skinning.vert @@ -1,81 +1,86 @@ -// SuperTuxKart - a fun racing game with go-kart -// Copyright (C) 2013 the SuperTuxKart team -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 3 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +#ifdef GL_ES +uniform mat4 ModelMatrix; +uniform mat4 InverseModelMatrix; +uniform vec2 texture_trans; +#else +uniform mat4 ModelMatrix = + mat4(1., 0., 0., 0., + 0., 1., 0., 0., + 0., 0., 1., 0., + 0., 0., 0., 1.); +uniform mat4 InverseModelMatrix = + mat4(1., 0., 0., 0., + 0., 1., 0., 0., + 0., 0., 1., 0., + 0., 0., 0., 1.); -// skinning.vert -#version 330 compatibility -#define MAX_JOINT_NUM 36 -#define MAX_LIGHT_NUM 8 +uniform vec2 texture_trans = vec2(0., 0.); +#endif +uniform int skinning_offset; -uniform mat4 JointTransform[MAX_JOINT_NUM]; +layout(location = 0) in vec3 Position; +layout(location = 1) in vec3 Normal; +layout(location = 2) in vec4 Color; +layout(location = 3) in vec4 Data1; +layout(location = 4) in vec4 Data2; +layout(location = 5) in ivec4 Joint; +layout(location = 6) in vec4 Weight; -void main() +out vec3 nor; +out vec3 tangent; +out vec3 bitangent; +out vec2 uv; +out vec4 color; + +#stk_include "utils/getworldmatrix.vert" + +void main(void) { - int index; - vec4 ecPos; - vec3 normal; - vec3 light_dir; - float n_dot_l; - float dist; + mat4 TransposeInverseModelView = transpose(InverseModelMatrix * InverseViewMatrix); + vec4 idle_position = vec4(Position, 1.); + vec4 idle_normal = vec4(Normal, 0.); + vec4 skinned_position = vec4(0.); + vec4 skinned_normal = vec4(0.); - mat4 ModelTransform = gl_ModelViewProjectionMatrix; + // Note : For normal we assume no scale factor in bone (otherwise we'll have to compute inversematrix for each bones...) + vec4 single_bone_influenced_position; + vec4 single_bone_influenced_normal; - index = int(gl_Color.r * 255.99); - mat4 vertTran = JointTransform[index - 1]; + // First bone: + single_bone_influenced_position = joint_matrices[clamp(Joint[0] + skinning_offset, 0, MAX_BONES)] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + single_bone_influenced_normal = joint_matrices[clamp(Joint[0] + skinning_offset, 0, MAX_BONES)] * idle_normal; + skinned_position += Weight[0] * single_bone_influenced_position; + skinned_normal += Weight[0] * single_bone_influenced_normal; - index = int(gl_Color.g * 255.99); - if(index > 0) - vertTran += JointTransform[index - 1]; + // Second bone: + single_bone_influenced_position = joint_matrices[clamp(Joint[1] + skinning_offset, 0, MAX_BONES)] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + single_bone_influenced_normal = joint_matrices[clamp(Joint[1] + skinning_offset, 0, MAX_BONES)] * idle_normal; + skinned_position += Weight[1] * single_bone_influenced_position; + skinned_normal += Weight[1] * single_bone_influenced_normal; - index = int(gl_Color.b * 255.99); - if(index > 0) - vertTran += JointTransform[index - 1]; + // Third bone: + single_bone_influenced_position = joint_matrices[clamp(Joint[2] + skinning_offset, 0, MAX_BONES)] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + single_bone_influenced_normal = joint_matrices[clamp(Joint[2] + skinning_offset, 0, MAX_BONES)] * idle_normal; + skinned_position += Weight[2] * single_bone_influenced_position; + skinned_normal += Weight[2] * single_bone_influenced_normal; - index = int(gl_Color.a * 255.99); - if(index > 0) - vertTran += JointTransform[index - 1]; + // Fourth bone: + single_bone_influenced_position = joint_matrices[clamp(Joint[3] + skinning_offset, 0, MAX_BONES)] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + single_bone_influenced_normal = joint_matrices[clamp(Joint[3] + skinning_offset, 0, MAX_BONES)] * idle_normal; + skinned_position += Weight[3] * single_bone_influenced_position; + skinned_normal += Weight[3] * single_bone_influenced_normal; - ecPos = gl_ModelViewMatrix * vertTran * gl_Vertex; + gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * skinned_position; + // Keep orthogonality + nor = (TransposeInverseModelView * skinned_normal).xyz; + // Keep direction + tangent = (ViewMatrix * ModelMatrix * vec4(Data1.z, Data1.w, Data2.x, 0.)).xyz; + bitangent = (ViewMatrix * ModelMatrix * vec4(Data2.y, Data2.z, Data2.w, 0.)).xyz; - normal = (vertTran * vec4(gl_Normal, 0.0)).xyz; - normal = normalize(gl_NormalMatrix * normal); - - gl_FrontColor = vec4(0,0,0,0); - for(int i = 0;i < MAX_LIGHT_NUM;i++) - { - light_dir = vec3(gl_LightSource[i].position-ecPos); - n_dot_l = max(dot(normal, normalize(light_dir)), 0.0); - dist = length(light_dir); - n_dot_l *= 1.0 / (gl_LightSource[0].constantAttenuation + gl_LightSource[0].linearAttenuation * dist); - gl_FrontColor += gl_LightSource[i].diffuse * n_dot_l; - } - gl_FrontColor = clamp(gl_FrontColor,0.3,1.0); - - - ModelTransform *= vertTran; - - gl_Position = ModelTransform * gl_Vertex; - gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1; - - /* - // Reflections. - vec3 r = reflect( ecPos.xyz , normal ); - float m = 2.0 * sqrt( r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0) ); - gl_TexCoord[1].s = r.x/m + 0.5; - gl_TexCoord[1].t = r.y/m + 0.5; - */ + uv = vec2(Data1.x + texture_trans.x, Data1.y + texture_trans.y); + color = Color.zyxw; } diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 8b4e774d4..5d9a2a17b 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -46,6 +46,7 @@ void DrawCalls::clearLists() ListDisplacement::getInstance()->clear(); ListMatDefault::getInstance()->clear(); + ListSkinnedSolid::getInstance()->clear(); ListMatAlphaRef::getInstance()->clear(); ListMatSphereMap::getInstance()->clear(); ListMatDetails::getInstance()->clear(); @@ -305,6 +306,12 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); break; + case Material::SHADERTYPE_SOLID_SKINNED_MESH: + ListSkinnedSolid::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, + (mesh->m_render_info && mesh->m_material ? + core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : + core::vector2df(0.0f, 0.0f)), skinning_offset); + break; case Material::SHADERTYPE_ALPHA_TEST: ListMatAlphaRef::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, (mesh->m_render_info && mesh->m_material ? diff --git a/src/graphics/draw_policies.cpp b/src/graphics/draw_policies.cpp index 69e10b4ee..c8ce67ef5 100644 --- a/src/graphics/draw_policies.cpp +++ b/src/graphics/draw_policies.cpp @@ -176,6 +176,7 @@ void drawRSM(const core::matrix4 & rsm_matrix) void GL3DrawPolicy::drawSolidFirstPass(const DrawCalls& draw_calls) const { renderMeshes1stPass(); + renderMeshes1stPass(); renderMeshes1stPass(); renderMeshes1stPass(); renderMeshes1stPass(); @@ -191,6 +192,7 @@ void GL3DrawPolicy::drawSolidSecondPass (const DrawCalls& draw_calls, const std::vector& prefilled_tex) const { renderMeshes2ndPass (handles, prefilled_tex); + renderMeshes2ndPass (handles, prefilled_tex); renderMeshes2ndPass (handles, prefilled_tex); renderMeshes2ndPass (handles, prefilled_tex); renderMeshes2ndPass (handles, prefilled_tex); diff --git a/src/graphics/materials.hpp b/src/graphics/materials.hpp index f40a04466..852256148 100644 --- a/src/graphics/materials.hpp +++ b/src/graphics/materials.hpp @@ -655,8 +655,8 @@ struct SkinnedSolid typedef InstancedSkinnedMeshPass2Shader InstancedSecondPassShader; //typedef InstancedShadowShader InstancedShadowPassShader; //typedef CInstancedRSMShader InstancedRSMShader; - //typedef Shaders::ObjectPass1Shader FirstPassShader; - //typedef Shaders::ObjectPass2Shader SecondPassShader; + typedef Shaders::SkinnedMeshPass1Shader FirstPassShader; + typedef Shaders::SkinnedMeshPass2Shader SecondPassShader; //typedef ShadowShader ShadowPassShader; //typedef CRSMShader RSMShader; typedef ListSkinnedSolid List; @@ -668,7 +668,7 @@ struct SkinnedSolid static const STK::Tuple SecondPassTextures; static const STK::Tuple<> ShadowTextures; static const STK::Tuple RSMTextures; -}; // struct DefaultMaterial +}; // struct SkinnedSolid // ---------------------------------------------------------------------------- struct DefaultMaterial diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index a531c5cd9..cde15b7ab 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -359,6 +359,29 @@ Shaders::ObjectPass2Shader::ObjectPass2Shader() 5, "colorization_mask", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // ObjectPass2Shader +// ============================================================================ +Shaders::SkinnedMeshPass1Shader::SkinnedMeshPass1Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + GL_FRAGMENT_SHADER, "object_pass1.frag"); + assignUniforms("ModelMatrix", "InverseModelMatrix", "skinning_offset"); + assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // SkinnedMeshPass1Shader + +// ============================================================================ +Shaders::SkinnedMeshPass2Shader::SkinnedMeshPass2Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + GL_FRAGMENT_SHADER, "object_pass2.frag"); + assignUniforms("ModelMatrix", "texture_trans", "color_change", "skinning_offset"); + assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, + 1, "SpecularMap", ST_NEAREST_FILTERED, + 2, "SSAO", ST_BILINEAR_FILTERED, + 3, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 4, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 5, "colorization_mask", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // SkinnedMeshPass2Shader + // ============================================================================ Shaders::TransparentShader::TransparentShader() { diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index 33a0094c2..820c4a78f 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -153,6 +153,24 @@ public: }; // ObjectPass2Shader // ======================================================================== + class SkinnedMeshPass1Shader : public TextureShader + { + public: + SkinnedMeshPass1Shader(); + }; // SkinnedMeshPass1Shader + + // ======================================================================== + class SkinnedMeshPass2Shader : public TextureShader < SkinnedMeshPass2Shader, 6, + core::matrix4, core::vector2df, + core::vector2df, int > + { + public: + SkinnedMeshPass2Shader(); + }; // SkinnedMeshPass2Shader + + // ======================================================================== }; // class Shaders diff --git a/src/graphics/stk_mesh.hpp b/src/graphics/stk_mesh.hpp index 39a113422..7552eb380 100644 --- a/src/graphics/stk_mesh.hpp +++ b/src/graphics/stk_mesh.hpp @@ -119,7 +119,7 @@ class ListMatDefault : public MeshList + core::vector2df, int> {}; // ---------------------------------------------------------------------------- From f2422317ba0588ab0ac097639a1324abf8cca44a Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 9 Dec 2016 20:26:26 +0800 Subject: [PATCH 011/206] Auto fallback to software skinning if not supported Currently explicit attribute location, uniform buffer object and opengl greater or equal 3.3 are required for hardware skinning So even intel hd3000 in linux can do hardware skinning --- src/graphics/central_settings.cpp | 5 +++++ src/graphics/central_settings.hpp | 1 + src/graphics/materials.hpp | 2 ++ src/graphics/shaders.cpp | 2 ++ src/graphics/stk_animated_mesh.cpp | 1 + 5 files changed, 11 insertions(+) diff --git a/src/graphics/central_settings.cpp b/src/graphics/central_settings.cpp index c2c839263..a96ddf5ea 100644 --- a/src/graphics/central_settings.cpp +++ b/src/graphics/central_settings.cpp @@ -442,3 +442,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; +} diff --git a/src/graphics/central_settings.hpp b/src/graphics/central_settings.hpp index fd0042479..71a50fdf1 100644 --- a/src/graphics/central_settings.hpp +++ b/src/graphics/central_settings.hpp @@ -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; diff --git a/src/graphics/materials.hpp b/src/graphics/materials.hpp index 852256148..5880f698f 100644 --- a/src/graphics/materials.hpp +++ b/src/graphics/materials.hpp @@ -603,6 +603,7 @@ class InstancedDetailedObjectPass2Shader : public TextureShadersupportsHardwareSkinning()) return; loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", GL_FRAGMENT_SHADER, "instanced_detailed_object_pass2.frag"); @@ -622,6 +623,7 @@ class InstancedSkinnedMeshPass1Shader : public TextureShadersupportsHardwareSkinning()) return; loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", GL_FRAGMENT_SHADER, "instanced_object_pass1.frag"); diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index cde15b7ab..b42b8d4f8 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -362,6 +362,7 @@ Shaders::ObjectPass2Shader::ObjectPass2Shader() // ============================================================================ Shaders::SkinnedMeshPass1Shader::SkinnedMeshPass1Shader() { + if (!CVS->supportsHardwareSkinning()) return; loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", GL_FRAGMENT_SHADER, "object_pass1.frag"); assignUniforms("ModelMatrix", "InverseModelMatrix", "skinning_offset"); @@ -371,6 +372,7 @@ Shaders::SkinnedMeshPass1Shader::SkinnedMeshPass1Shader() // ============================================================================ Shaders::SkinnedMeshPass2Shader::SkinnedMeshPass2Shader() { + 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"); diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp index df131f8c5..c262372d9 100644 --- a/src/graphics/stk_animated_mesh.cpp +++ b/src/graphics/stk_animated_mesh.cpp @@ -334,6 +334,7 @@ int STKAnimatedMesh::getTotalJointSize() const void STKAnimatedMesh::resetSkinningState(scene::IAnimatedMesh* mesh) { + if (!CVS->supportsHardwareSkinning()) return; m_skinning_offset = -1; m_skinned_mesh = dynamic_cast(mesh); if (m_skinned_mesh) From 94f6d09bf52590bfba7b31f3e4f0bace7e2d0f4d Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 9 Dec 2016 22:37:17 +0800 Subject: [PATCH 012/206] Allow indirect and azdo shadow rendering for skinned mesh --- data/shaders/instanced_skinning_shadow.vert | 72 +++++++++++++++++++++ src/graphics/command_buffer.cpp | 2 + src/graphics/draw_calls.cpp | 2 + src/graphics/materials.hpp | 32 ++++++++- 4 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 data/shaders/instanced_skinning_shadow.vert diff --git a/data/shaders/instanced_skinning_shadow.vert b/data/shaders/instanced_skinning_shadow.vert new file mode 100644 index 000000000..359980dc1 --- /dev/null +++ b/data/shaders/instanced_skinning_shadow.vert @@ -0,0 +1,72 @@ +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.); + vec4 single_bone_influenced_position; + + // First bone: + single_bone_influenced_position = joint_matrices[clamp(Joint[0] + skinning_offset, 0, MAX_BONES)] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + skinned_position += Weight[0] * single_bone_influenced_position; + + // Second bone: + single_bone_influenced_position = joint_matrices[clamp(Joint[1] + skinning_offset, 0, MAX_BONES)] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + skinned_position += Weight[1] * single_bone_influenced_position; + + // Third bone: + single_bone_influenced_position = joint_matrices[clamp(Joint[2] + skinning_offset, 0, MAX_BONES)] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + skinned_position += Weight[2] * single_bone_influenced_position; + + // Fourth bone: + single_bone_influenced_position = joint_matrices[clamp(Joint[3] + skinning_offset, 0, MAX_BONES)] * idle_position; + single_bone_influenced_position /= single_bone_influenced_position.w; + skinned_position += Weight[3] * 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 +} diff --git a/src/graphics/command_buffer.cpp b/src/graphics/command_buffer.cpp index b12445016..30745ac33 100644 --- a/src/graphics/command_buffer.cpp +++ b/src/graphics/command_buffer.cpp @@ -202,6 +202,8 @@ void ShadowCommandBuffer::fill(OtherMeshMap *mesh_map) { shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT + Material::SHADERTYPE_SOLID); + 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); shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 5d9a2a17b..af86018cf 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -808,6 +808,7 @@ void DrawCalls::drawIndirectShadows(unsigned cascade) const { m_shadow_cmd_buffer->bind(); m_shadow_cmd_buffer->drawIndirect(cascade); + m_shadow_cmd_buffer->drawIndirect(cascade); m_shadow_cmd_buffer->drawIndirect(cascade); m_shadow_cmd_buffer->drawIndirect(cascade); m_shadow_cmd_buffer->drawIndirect(cascade); @@ -826,6 +827,7 @@ void DrawCalls::multidrawShadows(unsigned cascade) const { m_shadow_cmd_buffer->bind(); m_shadow_cmd_buffer->multidrawShadow(cascade); + m_shadow_cmd_buffer->multidrawShadow(cascade); m_shadow_cmd_buffer->multidrawShadow(cascade); m_shadow_cmd_buffer->multidrawShadow(cascade); m_shadow_cmd_buffer->multidrawShadow(cascade); diff --git a/src/graphics/materials.hpp b/src/graphics/materials.hpp index 5880f698f..99f7ff739 100644 --- a/src/graphics/materials.hpp +++ b/src/graphics/materials.hpp @@ -143,7 +143,6 @@ public: InstancedShadowShader() { #if !defined(USE_GLES2) - // Geometry shader needed // Geometry shader needed if (CVS->getGLSLVersion() < 150) return; @@ -603,7 +602,6 @@ class InstancedDetailedObjectPass2Shader : public TextureShadersupportsHardwareSkinning()) return; loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", GL_FRAGMENT_SHADER, "instanced_detailed_object_pass2.frag"); @@ -638,6 +636,7 @@ class InstancedSkinnedMeshPass2Shader : public TextureShadersupportsHardwareSkinning()) return; loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", GL_FRAGMENT_SHADER, "instanced_object_pass2.frag"); assignUniforms(); @@ -650,12 +649,39 @@ public: } // InstancedSkinnedMeshPass2Shader }; // InstancedSkinnedMeshPass2Shader +// ============================================================================ +class InstancedSkinningShadowShader : public TextureShader +{ +public: + InstancedSkinningShadowShader() + { +#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 + } // InstancedSkinningShadowShader + +}; // InstancedSkinningShadowShader + // ============================================================================ struct SkinnedSolid { typedef InstancedSkinnedMeshPass1Shader InstancedFirstPassShader; typedef InstancedSkinnedMeshPass2Shader InstancedSecondPassShader; - //typedef InstancedShadowShader InstancedShadowPassShader; + typedef InstancedSkinningShadowShader InstancedShadowPassShader; //typedef CInstancedRSMShader InstancedRSMShader; typedef Shaders::SkinnedMeshPass1Shader FirstPassShader; typedef Shaders::SkinnedMeshPass2Shader SecondPassShader; From c68492f42becac24350f96a998f366383fe5a1e2 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 9 Dec 2016 23:21:41 +0800 Subject: [PATCH 013/206] Use a for loop for four bones (thanks leyyin suggestion!) --- data/shaders/instanced_skinning.vert | 40 +++++---------------- data/shaders/instanced_skinning_shadow.vert | 27 ++++---------- data/shaders/skinning.vert | 39 +++++--------------- 3 files changed, 22 insertions(+), 84 deletions(-) diff --git a/data/shaders/instanced_skinning.vert b/data/shaders/instanced_skinning.vert index 69aa38ecd..391bfcda9 100644 --- a/data/shaders/instanced_skinning.vert +++ b/data/shaders/instanced_skinning.vert @@ -37,43 +37,19 @@ void main(void) { mat4 ModelMatrix = getWorldMatrix(Origin, Orientation, Scale); mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin, Orientation, Scale) * InverseViewMatrix); - vec4 idle_position = vec4(Position, 1.); vec4 idle_normal = vec4(Normal, 0.); vec4 skinned_position = vec4(0.); vec4 skinned_normal = vec4(0.); - // Note : For normal we assume no scale factor in bone (otherwise we'll have to compute inversematrix for each bones...) - vec4 single_bone_influenced_position; - vec4 single_bone_influenced_normal; - - // First bone: - single_bone_influenced_position = joint_matrices[clamp(Joint[0] + skinning_offset, 0, MAX_BONES)] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - single_bone_influenced_normal = joint_matrices[clamp(Joint[0] + skinning_offset, 0, MAX_BONES)] * idle_normal; - skinned_position += Weight[0] * single_bone_influenced_position; - skinned_normal += Weight[0] * single_bone_influenced_normal; - - // Second bone: - single_bone_influenced_position = joint_matrices[clamp(Joint[1] + skinning_offset, 0, MAX_BONES)] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - single_bone_influenced_normal = joint_matrices[clamp(Joint[1] + skinning_offset, 0, MAX_BONES)] * idle_normal; - skinned_position += Weight[1] * single_bone_influenced_position; - skinned_normal += Weight[1] * single_bone_influenced_normal; - - // Third bone: - single_bone_influenced_position = joint_matrices[clamp(Joint[2] + skinning_offset, 0, MAX_BONES)] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - single_bone_influenced_normal = joint_matrices[clamp(Joint[2] + skinning_offset, 0, MAX_BONES)] * idle_normal; - skinned_position += Weight[2] * single_bone_influenced_position; - skinned_normal += Weight[2] * single_bone_influenced_normal; - - // Fourth bone: - single_bone_influenced_position = joint_matrices[clamp(Joint[3] + skinning_offset, 0, MAX_BONES)] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - single_bone_influenced_normal = joint_matrices[clamp(Joint[3] + skinning_offset, 0, MAX_BONES)] * idle_normal; - skinned_position += Weight[3] * single_bone_influenced_position; - skinned_normal += Weight[3] * single_bone_influenced_normal; + 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; + skinned_position += Weight[i] * single_bone_influenced_position; + skinned_normal += Weight[i] * single_bone_influenced_normal; + } gl_Position = ProjectionViewMatrix * ModelMatrix * skinned_position; // Keep orthogonality diff --git a/data/shaders/instanced_skinning_shadow.vert b/data/shaders/instanced_skinning_shadow.vert index 359980dc1..2d2542e1e 100644 --- a/data/shaders/instanced_skinning_shadow.vert +++ b/data/shaders/instanced_skinning_shadow.vert @@ -32,27 +32,12 @@ void main(void) mat4 ModelMatrix = getWorldMatrix(Origin, Orientation, Scale); vec4 idle_position = vec4(Position, 1.); vec4 skinned_position = vec4(0.); - vec4 single_bone_influenced_position; - - // First bone: - single_bone_influenced_position = joint_matrices[clamp(Joint[0] + skinning_offset, 0, MAX_BONES)] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - skinned_position += Weight[0] * single_bone_influenced_position; - - // Second bone: - single_bone_influenced_position = joint_matrices[clamp(Joint[1] + skinning_offset, 0, MAX_BONES)] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - skinned_position += Weight[1] * single_bone_influenced_position; - - // Third bone: - single_bone_influenced_position = joint_matrices[clamp(Joint[2] + skinning_offset, 0, MAX_BONES)] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - skinned_position += Weight[2] * single_bone_influenced_position; - - // Fourth bone: - single_bone_influenced_position = joint_matrices[clamp(Joint[3] + skinning_offset, 0, MAX_BONES)] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - skinned_position += Weight[3] * single_bone_influenced_position; + 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; diff --git a/data/shaders/skinning.vert b/data/shaders/skinning.vert index 25718a9cc..d4a0d65e8 100644 --- a/data/shaders/skinning.vert +++ b/data/shaders/skinning.vert @@ -41,38 +41,15 @@ void main(void) vec4 idle_normal = vec4(Normal, 0.); vec4 skinned_position = vec4(0.); vec4 skinned_normal = vec4(0.); - // Note : For normal we assume no scale factor in bone (otherwise we'll have to compute inversematrix for each bones...) - vec4 single_bone_influenced_position; - vec4 single_bone_influenced_normal; - - // First bone: - single_bone_influenced_position = joint_matrices[clamp(Joint[0] + skinning_offset, 0, MAX_BONES)] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - single_bone_influenced_normal = joint_matrices[clamp(Joint[0] + skinning_offset, 0, MAX_BONES)] * idle_normal; - skinned_position += Weight[0] * single_bone_influenced_position; - skinned_normal += Weight[0] * single_bone_influenced_normal; - - // Second bone: - single_bone_influenced_position = joint_matrices[clamp(Joint[1] + skinning_offset, 0, MAX_BONES)] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - single_bone_influenced_normal = joint_matrices[clamp(Joint[1] + skinning_offset, 0, MAX_BONES)] * idle_normal; - skinned_position += Weight[1] * single_bone_influenced_position; - skinned_normal += Weight[1] * single_bone_influenced_normal; - - // Third bone: - single_bone_influenced_position = joint_matrices[clamp(Joint[2] + skinning_offset, 0, MAX_BONES)] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - single_bone_influenced_normal = joint_matrices[clamp(Joint[2] + skinning_offset, 0, MAX_BONES)] * idle_normal; - skinned_position += Weight[2] * single_bone_influenced_position; - skinned_normal += Weight[2] * single_bone_influenced_normal; - - // Fourth bone: - single_bone_influenced_position = joint_matrices[clamp(Joint[3] + skinning_offset, 0, MAX_BONES)] * idle_position; - single_bone_influenced_position /= single_bone_influenced_position.w; - single_bone_influenced_normal = joint_matrices[clamp(Joint[3] + skinning_offset, 0, MAX_BONES)] * idle_normal; - skinned_position += Weight[3] * single_bone_influenced_position; - skinned_normal += Weight[3] * single_bone_influenced_normal; + 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; + skinned_position += Weight[i] * single_bone_influenced_position; + skinned_normal += Weight[i] * single_bone_influenced_normal; + } gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * skinned_position; // Keep orthogonality From fcd1e2830e60f381324a76b39208a25f311c30b2 Mon Sep 17 00:00:00 2001 From: Benau Date: Sat, 10 Dec 2016 16:16:40 +0800 Subject: [PATCH 014/206] Use callback function to directly upload joints without copying --- lib/irrlicht/include/IAnimatedMesh.h | 2 + lib/irrlicht/include/ISkinnedMesh.h | 2 +- .../Irrlicht/CAnimatedMeshSceneNode.cpp | 4 +- .../source/Irrlicht/CAnimatedMeshSceneNode.h | 2 +- lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp | 25 ++++++++---- lib/irrlicht/source/Irrlicht/CSkinnedMesh.h | 27 +++---------- src/graphics/draw_calls.cpp | 2 +- src/graphics/stk_animated_mesh.cpp | 38 +++++++++++++------ src/graphics/stk_animated_mesh.hpp | 8 +++- 9 files changed, 63 insertions(+), 47 deletions(-) diff --git a/lib/irrlicht/include/IAnimatedMesh.h b/lib/irrlicht/include/IAnimatedMesh.h index 3e08528df..7091f3e22 100644 --- a/lib/irrlicht/include/IAnimatedMesh.h +++ b/lib/irrlicht/include/IAnimatedMesh.h @@ -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 diff --git a/lib/irrlicht/include/ISkinnedMesh.h b/lib/irrlicht/include/ISkinnedMesh.h index 93dbec801..3fd16ed6e 100644 --- a/lib/irrlicht/include/ISkinnedMesh.h +++ b/lib/irrlicht/include/ISkinnedMesh.h @@ -69,7 +69,7 @@ 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. */ diff --git a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.cpp b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.cpp index e7a2714a4..a0bfc5b93 100644 --- a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.cpp +++ b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.cpp @@ -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 { diff --git a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h index 9e747d25b..d75fbf8d5 100644 --- a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h +++ b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h @@ -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(); diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp index 3fb8e715b..fd5beddb0 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp @@ -22,7 +22,8 @@ CSkinnedMesh::CSkinnedMesh() LastAnimatedFrame(-1), SkinnedLastFrame(false), InterpolationMode(EIM_LINEAR), HasAnimation(false), PreparedForSkinning(false), - AnimateNormals(true), HardwareSkinning(false), m_joint_total_size(0) + AnimateNormals(true), HardwareSkinning(false), m_total_joints(0), + m_current_joint(0) { #ifdef _DEBUG setDebugName("CSkinnedMesh"); @@ -99,6 +100,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; @@ -451,7 +458,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; @@ -462,11 +469,11 @@ void CSkinnedMesh::skinMesh(f32 strength) //----------------- SkinnedLastFrame=true; - m_joint_matrixes.clear(); + m_current_joint = 0; if (HardwareSkinning) { for (u32 i = 0; i < RootJoints.size(); i++) - skinJoint(RootJoints[i], 0, strength); + skinJoint(RootJoints[i], 0, strength, sc, offset); } else { @@ -498,7 +505,8 @@ 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()) { @@ -507,7 +515,8 @@ void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength) jointVertexPull.setbyproduct(joint->GlobalAnimatedMatrix, joint->GlobalInversedMatrix); if (HardwareSkinning) { - m_joint_matrixes.push_back(jointVertexPull); + if (sc != NULL) sc(jointVertexPull, m_current_joint, offset); + m_current_joint++; } else { @@ -562,7 +571,7 @@ void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength) //Skin all children for (u32 j=0; jChildren.size(); ++j) - skinJoint(joint->Children[j], joint, strength); + skinJoint(joint->Children[j], joint, strength, sc, offset); } @@ -1458,7 +1467,7 @@ void CSkinnedMesh::convertForSkinning() } SkinnedLastFrame = false; skinMesh(); - m_joint_total_size = m_joint_matrixes.size(); + m_total_joints = m_current_joint; } void CSkinnedMesh::computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi) diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h index 0ffdc6984..7e6311faf 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h @@ -14,17 +14,6 @@ #include "matrix4.h" #include "quaternion.h" -class Matrix4x4 -{ -private: - float data[16]; -public: - inline Matrix4x4(const irr::core::matrix4& m) - { - memcpy(data, m.pointer(), 16 * sizeof(float)); - } -}; - class JointInfluence { public: @@ -76,7 +65,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; @@ -188,12 +177,7 @@ namespace scene void computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi); - const void* getJointPointer() const { return m_joint_matrixes.const_pointer(); } - - u32 getTotalJointSize() const - { - return m_joint_total_size; - } + u32 getTotalJoints() const { return m_total_joints; } private: void checkForAnimation(); @@ -211,7 +195,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, @@ -241,8 +226,8 @@ private: bool PreparedForSkinning; bool AnimateNormals; bool HardwareSkinning; - core::array m_joint_matrixes; - u32 m_joint_total_size; + u32 m_total_joints; + u32 m_current_joint; }; } // end namespace scene diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index b1ed2b2d1..3e79c936c 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -899,6 +899,6 @@ 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->getTotalJointSize(); }); + { return previous + m->getTotalJoints(); }); } // getSkinningOffset #endif // !SERVER_ONLY diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp index d06a375c6..c87805b2d 100644 --- a/src/graphics/stk_animated_mesh.cpp +++ b/src/graphics/stk_animated_mesh.cpp @@ -222,12 +222,9 @@ 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) @@ -275,13 +272,9 @@ void STKAnimatedMesh::updateGL() isGLInitialized = true; } + scene::IMesh* m = getMeshForCurrentFrame(); if (useHardwareSkinning()) { - if (m_skinning_offset == -1) return; - glBindBuffer(GL_UNIFORM_BUFFER, SharedGPUObjects::getSkinningUBO()); - glBufferSubData(GL_UNIFORM_BUFFER, m_skinning_offset, - m_skinned_mesh->getTotalJointSize() * 16 * sizeof(float), - m_skinned_mesh->getJointPointer()); m_skinning_offset = -1; return; } @@ -329,9 +322,9 @@ void STKAnimatedMesh::render() updateGL(); } -int STKAnimatedMesh::getTotalJointSize() const +int STKAnimatedMesh::getTotalJoints() const { - return m_skinned_mesh->getTotalJointSize(); + return m_skinned_mesh->getTotalJoints(); } void STKAnimatedMesh::resetSkinningState(scene::IAnimatedMesh* mesh) @@ -342,9 +335,30 @@ void STKAnimatedMesh::resetSkinningState(scene::IAnimatedMesh* mesh) if (m_skinned_mesh) { m_skinned_mesh->convertForSkinning(); - if (m_skinned_mesh->getTotalJointSize() == 0) + if (m_skinned_mesh->getTotalJoints() == 0) m_skinned_mesh = NULL; } } +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::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 diff --git a/src/graphics/stk_animated_mesh.hpp b/src/graphics/stk_animated_mesh.hpp index 3115f0edc..f86ec69fc 100644 --- a/src/graphics/stk_animated_mesh.hpp +++ b/src/graphics/stk_animated_mesh.hpp @@ -54,10 +54,16 @@ public: virtual void render(); virtual void setMesh(irr::scene::IAnimatedMesh* mesh); virtual bool glow() const { return false; } - int getTotalJointSize() const; + 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 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; From ceef7495d2cd0c02cec3af8279a58d8af8ca3843 Mon Sep 17 00:00:00 2001 From: Benau Date: Sun, 11 Dec 2016 11:01:02 +0800 Subject: [PATCH 015/206] Enable culling for animated mesh Use the first frame bounding box for it, don't update each frame --- lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp | 2 +- src/karts/kart_model.cpp | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp index fd5beddb0..a90000f98 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp @@ -1166,7 +1166,7 @@ void CSkinnedMesh::finalize() void CSkinnedMesh::updateBoundingBox(void) { - if(!SkinningBuffers) + if(HardwareSkinning || !SkinningBuffers) return; core::array & buffer = *SkinningBuffers; diff --git a/src/karts/kart_model.cpp b/src/karts/kart_model.cpp index 32f54e479..ca143e3f4 100644 --- a/src/karts/kart_model.cpp +++ b/src/karts/kart_model.cpp @@ -361,11 +361,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) { From f6490b6fa607196b277505f07ab1ce67acbc3690 Mon Sep 17 00:00:00 2001 From: Benau Date: Sun, 11 Dec 2016 13:21:17 +0800 Subject: [PATCH 016/206] Allow array to capture lambada Also use a correct sorting function, will be useful later if we only need the more influetial bones. --- lib/irrlicht/CMakeLists.txt | 5 ++++ lib/irrlicht/include/heapsort.h | 26 ++++++++++++------- lib/irrlicht/include/irrArray.h | 9 ++++++- lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp | 4 ++- lib/irrlicht/source/Irrlicht/CSkinnedMesh.h | 4 --- 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/lib/irrlicht/CMakeLists.txt b/lib/irrlicht/CMakeLists.txt index debd4b8e6..d85a415b6 100644 --- a/lib/irrlicht/CMakeLists.txt +++ b/lib/irrlicht/CMakeLists.txt @@ -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 diff --git a/lib/irrlicht/include/heapsort.h b/lib/irrlicht/include/heapsort.h index 6f87665cd..26d8cd95d 100644 --- a/lib/irrlicht/include/heapsort.h +++ b/lib/irrlicht/include/heapsort.h @@ -12,18 +12,25 @@ namespace irr namespace core { -//! Sinks an element into the heap. +//! Function object which can be used for sorting (default) template -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 +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 -inline void heapsort(T* array_, s32 size) +//! Sorts an array with size 'size' using heapsort with a custom compare function +template +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); } } diff --git a/lib/irrlicht/include/irrArray.h b/lib/irrlicht/include/irrArray.h index 7dab5937a..afd4bb82c 100644 --- a/lib/irrlicht/include/irrArray.h +++ b/lib/irrlicht/include/irrArray.h @@ -394,10 +394,17 @@ public: void sort() { if (!is_sorted && used>1) - heapsort(data, used); + heapsort(data, used, sortless); is_sorted = true; } + template + 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 diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp index a90000f98..8f54b0a15 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp @@ -1439,7 +1439,9 @@ void CSkinnedMesh::convertForSkinning() { core::array this_influence; core::array reported_weight = wi[b][i]; - reported_weight.sort(); + 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++) { diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h index 7e6311faf..00d924d09 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h @@ -19,10 +19,6 @@ class JointInfluence public: int joint_idx; float weight; - bool operator < (const JointInfluence& other) const - { - return weight < other.weight; - } }; typedef irr::core::array Date: Sun, 11 Dec 2016 15:50:53 +0800 Subject: [PATCH 017/206] Use a non-hardcoded values for mat4 array (max 1024) Also cull mesh that doesn't have enough space to be rendered --- data/shaders/header.txt | 1 - lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp | 2 +- src/graphics/draw_calls.cpp | 9 +++++++++ src/graphics/shader.cpp | 3 ++- src/graphics/shared_gpu_objects.cpp | 9 +++++++-- src/graphics/shared_gpu_objects.hpp | 8 +++++++- src/graphics/stk_mesh.hpp | 1 + 7 files changed, 27 insertions(+), 6 deletions(-) diff --git a/data/shaders/header.txt b/data/shaders/header.txt index 88ee3a2be..c5d5326b7 100644 --- a/data/shaders/header.txt +++ b/data/shaders/header.txt @@ -1,6 +1,5 @@ #ifndef HEADER_TXT #define HEADER_TXT -#define MAX_BONES 1000 #ifdef UBO_DISABLED uniform mat4 ViewMatrix; uniform mat4 ProjectionMatrix; diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp index 8f54b0a15..981584e83 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp @@ -1450,7 +1450,7 @@ void CSkinnedMesh::convertForSkinning() influence = reported_weight[j]; else { - influence.joint_idx = -1000; + influence.joint_idx = -100000; influence.weight = remaining_weight; } remaining_weight -= influence.weight; diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 3e79c936c..8fe44fbbd 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -256,6 +256,15 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, !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)); } diff --git a/src/graphics/shader.cpp b/src/graphics/shader.cpp index 951c4ed13..f2f704978 100644 --- a/src/graphics/shader.cpp +++ b/src/graphics/shader.cpp @@ -117,12 +117,13 @@ GLuint ShaderBase::loadShader(const std::string &file, unsigned type) #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(); diff --git a/src/graphics/shared_gpu_objects.cpp b/src/graphics/shared_gpu_objects.cpp index 06836f29d..b06b82de6 100644 --- a/src/graphics/shared_gpu_objects.cpp +++ b/src/graphics/shared_gpu_objects.cpp @@ -21,6 +21,7 @@ #include "graphics/central_settings.hpp" #include "matrix4.h" +#include GLuint SharedGPUObjects::m_billboard_vbo; GLuint SharedGPUObjects::m_sky_tri_vbo; @@ -34,6 +35,7 @@ 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. @@ -178,8 +180,11 @@ void SharedGPUObjects::initSkinningUBO() irr::core::matrix4 m; glGenBuffers(1, &m_skinning_ubo); glBindBuffer(GL_UNIFORM_BUFFER, m_skinning_ubo); - glBufferData(GL_UNIFORM_BUFFER, 1000 * 16 * sizeof(float), 0, - GL_STREAM_DRAW); + 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); + 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()); diff --git a/src/graphics/shared_gpu_objects.hpp b/src/graphics/shared_gpu_objects.hpp index df2436884..a8dd3d59a 100644 --- a/src/graphics/shared_gpu_objects.hpp +++ b/src/graphics/shared_gpu_objects.hpp @@ -38,6 +38,7 @@ private: 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(); @@ -124,7 +125,12 @@ public: assert(m_has_been_initialised); return m_skinning_ubo; } // getSkinningUBO -}; // class SharedGPUObjecctS + // ------------------------------------------------------------------------ + static int getMaxMat4Size() + { + return m_max_mat4_size; + } // getMaxMat4Size +}; // class SharedGPUObjects #endif diff --git a/src/graphics/stk_mesh.hpp b/src/graphics/stk_mesh.hpp index 7552eb380..a78a44ef8 100644 --- a/src/graphics/stk_mesh.hpp +++ b/src/graphics/stk_mesh.hpp @@ -91,6 +91,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 From 4327885f070b209946cc0cd987a0ca40c35d9e56 Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 12 Dec 2016 01:00:57 +0800 Subject: [PATCH 018/206] Add alpha test skinned mesh instanced shaders --- src/graphics/command_buffer.cpp | 14 +++-- src/graphics/draw_calls.cpp | 18 ++++-- src/graphics/material.hpp | 4 ++ src/graphics/materials.cpp | 24 +++++--- src/graphics/materials.hpp | 99 ++++++++++++++++++++++++++++-- src/graphics/stk_animated_mesh.cpp | 14 ++++- src/graphics/stk_mesh.cpp | 21 ++++++- src/graphics/stk_mesh.hpp | 30 +++++++-- src/graphics/vao_manager.cpp | 3 + src/graphics/vao_manager.hpp | 1 + 10 files changed, 194 insertions(+), 34 deletions(-) diff --git a/src/graphics/command_buffer.cpp b/src/graphics/command_buffer.cpp index 2e940deb8..86766ee06 100644 --- a/src/graphics/command_buffer.cpp +++ b/src/graphics/command_buffer.cpp @@ -46,6 +46,7 @@ void InstanceFiller::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); } // ---------------------------------------------------------------------------- @@ -169,15 +170,16 @@ 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); fillInstanceData (mesh_map, three_tex_material_list, InstanceTypeThreeTex); std::vector four_tex_material_list = createVector(Material::SHADERTYPE_DETAIL_MAP, - Material::SHADERTYPE_NORMAL_MAP, - Material::SHADERTYPE_SOLID_SKINNED_MESH); + Material::SHADERTYPE_NORMAL_MAP); fillInstanceData (mesh_map, four_tex_material_list, InstanceTypeFourTex); @@ -202,10 +204,12 @@ void ShadowCommandBuffer::fill(OtherMeshMap *mesh_map) std::vector shadow_tex_material_list; for(int cascade=0; cascade<4; cascade++) { - shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT - + Material::SHADERTYPE_SOLID); shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT + Material::SHADERTYPE_SOLID_SKINNED_MESH); + shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT + + Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH); + shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT + + Material::SHADERTYPE_SOLID); shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT + Material::SHADERTYPE_ALPHA_TEST); shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 8fe44fbbd..0f6f10dc5 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -712,8 +712,9 @@ void DrawCalls::renderParticlesList() const void DrawCalls::drawIndirectSolidFirstPass() const { m_solid_cmd_buffer->bind(); - m_solid_cmd_buffer->drawIndirectFirstPass(); m_solid_cmd_buffer->drawIndirectFirstPass(); + m_solid_cmd_buffer->drawIndirectFirstPass(); + m_solid_cmd_buffer->drawIndirectFirstPass(); m_solid_cmd_buffer->drawIndirectFirstPass(); m_solid_cmd_buffer->drawIndirectFirstPass(); m_solid_cmd_buffer->drawIndirectFirstPass(); @@ -729,8 +730,9 @@ void DrawCalls::drawIndirectSolidFirstPass() const void DrawCalls::multidrawSolidFirstPass() const { m_solid_cmd_buffer->bind(); - m_solid_cmd_buffer->multidrawFirstPass(); m_solid_cmd_buffer->multidrawFirstPass(); + m_solid_cmd_buffer->multidrawFirstPass(); + m_solid_cmd_buffer->multidrawFirstPass(); m_solid_cmd_buffer->multidrawFirstPass(); m_solid_cmd_buffer->multidrawFirstPass(); m_solid_cmd_buffer->multidrawFirstPass(); @@ -749,8 +751,9 @@ void DrawCalls::multidrawSolidFirstPass() const void DrawCalls::drawIndirectSolidSecondPass(const std::vector &prefilled_tex) const { m_solid_cmd_buffer->bind(); - m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); + m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); + m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); @@ -768,8 +771,9 @@ void DrawCalls::drawIndirectSolidSecondPass(const std::vector &prefilled void DrawCalls::multidrawSolidSecondPass(const std::vector &handles) const { m_solid_cmd_buffer->bind(); - m_solid_cmd_buffer->multidraw2ndPass(handles); m_solid_cmd_buffer->multidraw2ndPass(handles); + m_solid_cmd_buffer->multidraw2ndPass(handles); + m_solid_cmd_buffer->multidraw2ndPass(handles); m_solid_cmd_buffer->multidraw2ndPass(handles); m_solid_cmd_buffer->multidraw2ndPass(handles); m_solid_cmd_buffer->multidraw2ndPass(handles); @@ -818,8 +822,9 @@ void DrawCalls::multidrawNormals() const void DrawCalls::drawIndirectShadows(unsigned cascade) const { m_shadow_cmd_buffer->bind(); - m_shadow_cmd_buffer->drawIndirect(cascade); m_shadow_cmd_buffer->drawIndirect(cascade); + m_shadow_cmd_buffer->drawIndirect(cascade); + m_shadow_cmd_buffer->drawIndirect(cascade); m_shadow_cmd_buffer->drawIndirect(cascade); m_shadow_cmd_buffer->drawIndirect(cascade); m_shadow_cmd_buffer->drawIndirect(cascade); @@ -837,8 +842,9 @@ void DrawCalls::drawIndirectShadows(unsigned cascade) const void DrawCalls::multidrawShadows(unsigned cascade) const { m_shadow_cmd_buffer->bind(); - m_shadow_cmd_buffer->multidrawShadow(cascade); m_shadow_cmd_buffer->multidrawShadow(cascade); + m_shadow_cmd_buffer->multidrawShadow(cascade); + m_shadow_cmd_buffer->multidrawShadow(cascade); m_shadow_cmd_buffer->multidrawShadow(cascade); m_shadow_cmd_buffer->multidrawShadow(cascade); m_shadow_cmd_buffer->multidrawShadow(cascade); diff --git a/src/graphics/material.hpp b/src/graphics/material.hpp index 69d2bfac3..49a3e3993 100644 --- a/src/graphics/material.hpp +++ b/src/graphics/material.hpp @@ -50,14 +50,18 @@ public: SHADERTYPE_SOLID = 0, SHADERTYPE_SOLID_SKINNED_MESH, SHADERTYPE_ALPHA_TEST, + SHADERTYPE_ALPHA_TEST_SKINNED_MESH, SHADERTYPE_ALPHA_BLEND, + SHADERTYPE_ALPHA_BLEND_SKINNED_MESH, 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, diff --git a/src/graphics/materials.cpp b/src/graphics/materials.cpp index 385f1568d..326b53d7f 100644 --- a/src/graphics/materials.cpp +++ b/src/graphics/materials.cpp @@ -19,6 +19,22 @@ #ifndef SERVER_ONLY +const STK::Tuple SkinnedSolid::FirstPassTextures += STK::Tuple(1); +const STK::Tuple SkinnedSolid::SecondPassTextures += STK::Tuple(0, 1, 2); +const STK::Tuple<> SkinnedSolid::ShadowTextures; +const STK::Tuple SkinnedSolid::RSMTextures = STK::Tuple(0); + +// ---------------------------------------------------------------------------- +const STK::Tuple SkinnedAlphaRef::FirstPassTextures += STK::Tuple(0, 1); +const STK::Tuple SkinnedAlphaRef::SecondPassTextures += STK::Tuple(0, 1, 2); +const STK::Tuple SkinnedAlphaRef::ShadowTextures = STK::Tuple(0); +const STK::Tuple SkinnedAlphaRef::RSMTextures = STK::Tuple(0); + +// ---------------------------------------------------------------------------- const STK::Tuple DefaultMaterial::FirstPassTextures = STK::Tuple(1); const STK::Tuple DefaultMaterial::SecondPassTextures @@ -26,14 +42,6 @@ const STK::Tuple DefaultMaterial::SecondPassTextures const STK::Tuple<> DefaultMaterial::ShadowTextures; const STK::Tuple DefaultMaterial::RSMTextures = STK::Tuple(0); -// ---------------------------------------------------------------------------- -const STK::Tuple SkinnedSolid::FirstPassTextures - = STK::Tuple(1); -const STK::Tuple SkinnedSolid::SecondPassTextures - = STK::Tuple(0, 1, 2); -const STK::Tuple<> SkinnedSolid::ShadowTextures; -const STK::Tuple SkinnedSolid::RSMTextures = STK::Tuple(0); - // ---------------------------------------------------------------------------- const STK::Tuple AlphaRef::FirstPassTextures = STK::Tuple(0, 1); diff --git a/src/graphics/materials.hpp b/src/graphics/materials.hpp index fd8abfe91..79fd0a6cb 100644 --- a/src/graphics/materials.hpp +++ b/src/graphics/materials.hpp @@ -652,10 +652,46 @@ public: }; // InstancedSkinnedMeshPass2Shader // ============================================================================ -class InstancedSkinningShadowShader : public TextureShader +class InstancedSkinnedMeshRefPass1Shader : public TextureShader { public: - InstancedSkinningShadowShader() + InstancedSkinnedMeshRefPass1Shader() + { + 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); + } // InstancedSkinnedMeshRefPass1Shader + +}; // InstancedSkinnedMeshRefPass1Shader + +// ============================================================================ +class InstancedSkinnedMeshRefPass2Shader : public TextureShader +{ +public: + InstancedSkinnedMeshRefPass2Shader() + { + 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); + } // InstancedSkinnedMeshRefPass2Shader +}; // InstancedSkinnedMeshRefPass2Shader + +// ============================================================================ +class InstancedSkinnedShadowShader : public TextureShader +{ +public: + InstancedSkinnedShadowShader() { #if !defined(USE_GLES2) // Geometry shader needed @@ -674,16 +710,45 @@ public: } assignUniforms("layer"); #endif - } // InstancedSkinningShadowShader + } // InstancedSkinnedShadowShader -}; // InstancedSkinningShadowShader +}; // InstancedSkinnedShadowShader + +// ============================================================================ +class InstancedSkinnedRefShadowShader : public TextureShader +{ +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 InstancedSkinnedMeshPass1Shader InstancedFirstPassShader; typedef InstancedSkinnedMeshPass2Shader InstancedSecondPassShader; - typedef InstancedSkinningShadowShader InstancedShadowPassShader; + typedef InstancedSkinnedShadowShader InstancedShadowPassShader; //typedef CInstancedRSMShader InstancedRSMShader; typedef Shaders::SkinnedMeshPass1Shader FirstPassShader; typedef Shaders::SkinnedMeshPass2Shader SecondPassShader; @@ -693,13 +758,35 @@ struct SkinnedSolid static const enum video::E_VERTEX_TYPE VertexType = video::EVT_SKINNED_MESH; static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_SOLID_SKINNED_MESH; - static const enum InstanceType Instance = InstanceTypeFourTex; + static const enum InstanceType Instance = InstanceTypeThreeTex; static const STK::Tuple FirstPassTextures; static const STK::Tuple SecondPassTextures; static const STK::Tuple<> ShadowTextures; static const STK::Tuple RSMTextures; }; // struct SkinnedSolid +// ---------------------------------------------------------------------------- +struct SkinnedAlphaRef +{ + typedef InstancedSkinnedMeshRefPass1Shader InstancedFirstPassShader; + typedef InstancedSkinnedMeshRefPass2Shader InstancedSecondPassShader; + typedef InstancedSkinnedRefShadowShader InstancedShadowPassShader; + //typedef CInstancedRSMShader InstancedRSMShader; + //typedef ObjectRefPass1Shader FirstPassShader; + //typedef ObjectRefPass2Shader SecondPassShader; + //typedef RefShadowShader ShadowPassShader; + //typedef CRSMShader RSMShader; + 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 FirstPassTextures; + static const STK::Tuple SecondPassTextures; + static const STK::Tuple ShadowTextures; + static const STK::Tuple RSMTextures; +}; // struct SkinnedAlphaRef + // ---------------------------------------------------------------------------- struct DefaultMaterial { diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp index c87805b2d..f010d1e9f 100644 --- a/src/graphics/stk_animated_mesh.cpp +++ b/src/graphics/stk_animated_mesh.cpp @@ -168,6 +168,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(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); @@ -196,8 +205,9 @@ void STKAnimatedMesh::updateNoGL() else*/ { Material::ShaderType MatType = getMeshMaterialFromType(type, mb->getVertexType(), material, NULL); - MeshSolidMaterial[m_skinned_mesh ? Material::SHADERTYPE_SOLID_SKINNED_MESH : MatType].push_back(&mesh); + MeshSolidMaterial[MatType].push_back(&mesh); } + if (m_skinned_mesh) ssmb->VertexType = prev_type; } isMaterialInitialized = true; } @@ -250,7 +260,7 @@ void STKAnimatedMesh::updateGL() material2 = material_manager->getMaterialFor(mb->getMaterial().getTexture(1), mb); Material::ShaderType MatType = getMeshMaterialFromType(type, mb->getVertexType(), material, material2); - initTextures(mesh, m_skinned_mesh ? Material::SHADERTYPE_SOLID_SKINNED_MESH : MatType); + initTextures(mesh, MatType); } else initTexturesTransparent(mesh); diff --git a/src/graphics/stk_mesh.cpp b/src/graphics/stk_mesh.cpp index 2ce4e23a0..02dd61f8b 100644 --- a/src/graphics/stk_mesh.cpp +++ b/src/graphics/stk_mesh.cpp @@ -40,6 +40,22 @@ 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; + 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: @@ -423,13 +439,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_SOLID_SKINNED_MESH: + 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)); diff --git a/src/graphics/stk_mesh.hpp b/src/graphics/stk_mesh.hpp index a78a44ef8..f79dc20f8 100644 --- a/src/graphics/stk_mesh.hpp +++ b/src/graphics/stk_mesh.hpp @@ -112,15 +112,33 @@ public: // ---------------------------------------------------------------------------- -class ListMatDefault : public MeshList +class ListSkinnedSolid : public MeshList {}; // ---------------------------------------------------------------------------- -class ListSkinnedSolid : public MeshList +class ListSkinnedAlphaRef : public MeshList +{}; + +// ---------------------------------------------------------------------------- +class ListSkinnedNormalMap : public MeshList +{}; + +// ---------------------------------------------------------------------------- +class ListSkinnedUnlit : public MeshList +{}; + +// ---------------------------------------------------------------------------- +class ListMatDefault : public MeshList {}; // ---------------------------------------------------------------------------- diff --git a/src/graphics/vao_manager.cpp b/src/graphics/vao_manager.cpp index 9cc278e2a..1fac8bbf9 100644 --- a/src/graphics/vao_manager.cpp +++ b/src/graphics/vao_manager.cpp @@ -184,6 +184,9 @@ void VAOInstanceUtil::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<> diff --git a/src/graphics/vao_manager.hpp b/src/graphics/vao_manager.hpp index 76a752dfd..b30e712c3 100644 --- a/src/graphics/vao_manager.hpp +++ b/src/graphics/vao_manager.hpp @@ -99,6 +99,7 @@ struct InstanceDataThreeTex uint64_t Texture; uint64_t SecondTexture; uint64_t ThirdTexture; + int32_t skinning_offset; #ifdef WIN32 }; #else From a420b0936365d760433858766c5afe29579bdbb1 Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 12 Dec 2016 13:24:34 +0800 Subject: [PATCH 019/206] Disable all karts animation if UBO size not big enough --- src/graphics/shared_gpu_objects.cpp | 3 + .../dialogs/custom_video_settings.cpp | 16 +- .../dialogs/custom_video_settings.hpp | 3 +- src/states_screens/options_screen_video.cpp | 143 +++++++++--------- src/states_screens/options_screen_video.hpp | 24 ++- 5 files changed, 109 insertions(+), 80 deletions(-) diff --git a/src/graphics/shared_gpu_objects.cpp b/src/graphics/shared_gpu_objects.cpp index b06b82de6..700406cdb 100644 --- a/src/graphics/shared_gpu_objects.cpp +++ b/src/graphics/shared_gpu_objects.cpp @@ -19,6 +19,7 @@ #include "graphics/shared_gpu_objects.hpp" #include "graphics/central_settings.hpp" +#include "utils/log.hpp" #include "matrix4.h" #include @@ -184,6 +185,8 @@ void SharedGPUObjects::initSkinningUBO() 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 diff --git a/src/states_screens/dialogs/custom_video_settings.cpp b/src/states_screens/dialogs/custom_video_settings.cpp index ccfccf71c..11d585bca 100644 --- a/src/states_screens/dialogs/custom_video_settings.cpp +++ b/src/states_screens/dialogs/custom_video_settings.cpp @@ -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 @@ -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("filtering"); int value = 0; @@ -242,6 +250,8 @@ void CustomVideoSettingsDialog::updateActivation() getWidget("global_illumination")->setActive(light); getWidget("glow")->setActive(light); getWidget("bloom")->setActive(light); + getWidget("steering_animations") + ->setMax(m_all_kart_animated ? 2 : 1); if (!CVS->supportsShadows() && !CVS->supportsGlobalIllumination()) { diff --git a/src/states_screens/dialogs/custom_video_settings.hpp b/src/states_screens/dialogs/custom_video_settings.hpp index a80c6eca2..58eb80e09 100644 --- a/src/states_screens/dialogs/custom_video_settings.hpp +++ b/src/states_screens/dialogs/custom_video_settings.hpp @@ -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 diff --git a/src/states_screens/options_screen_video.cpp b/src/states_screens/options_screen_video.cpp index 1925851b4..5d4751d57 100644 --- a/src/states_screens/options_screen_video.cpp +++ b/src/states_screens/options_screen_video.cpp @@ -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,63 @@ 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 */, + (SharedGPUObjects::getMaxMat4Size() > 512 || !CVS->supportsHardwareSkinning() ? 2 : 1)/* animatedCharacters */, + 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 */, + (SharedGPUObjects::getMaxMat4Size() > 512 || !CVS->supportsHardwareSkinning() ? 2 : 1)/* animatedCharacters */, + 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 +136,7 @@ struct Resolution OptionsScreenVideo::OptionsScreenVideo() : Screen("options_video.stkgui") { m_inited = false; + initPresets(); } // OptionsScreenVideo // ---------------------------------------------------------------------------- @@ -151,12 +144,12 @@ OptionsScreenVideo::OptionsScreenVideo() : Screen("options_video.stkgui") void OptionsScreenVideo::loadedFromFile() { m_inited = false; - + assert(m_presets.size() == 6); GUIEngine::SpinnerWidget* gfx = getWidget("gfx_level"); gfx->m_properties[GUIEngine::PROP_MAX_VALUE] = - StringUtils::toString(GFX_LEVEL_AMOUNT); + StringUtils::toString(m_presets.size()); } // loadedFromFile @@ -334,25 +327,25 @@ void OptionsScreenVideo::updateGfxSlider() assert( gfx != NULL ); bool found = false; - for (int l=0; lsetValue(l + 1); found = true; @@ -513,23 +506,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(); } diff --git a/src/states_screens/options_screen_video.hpp b/src/states_screens/options_screen_video.hpp index 745863b2c..5d800c19c 100644 --- a/src/states_screens/options_screen_video.hpp +++ b/src/states_screens/options_screen_video.hpp @@ -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 { +private: OptionsScreenVideo(); bool m_inited; + std::vector m_presets; void updateTooltip(); + void initPresets(); public: friend class GUIEngine::ScreenSingleton; From 269e440d0cc3a2fc57baaf0dd2cd61ad76d87459 Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 12 Dec 2016 13:43:01 +0800 Subject: [PATCH 020/206] Avoid translating artist debug mode only fps string --- src/graphics/irr_driver.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 99e152b2b..13f5d4a29 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -1959,7 +1959,8 @@ void IrrDriver::displayFPS() if ((UserConfigParams::m_artist_debug_mode)&&(CVS->isGLSL())) { - fps_string = _("FPS: %d/%d/%d - PolyCount: %d Solid, " + 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, From abe4ae2d6a5418b1495f0f3c3d2359f7efcc11c7 Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 12 Dec 2016 13:54:43 +0800 Subject: [PATCH 021/206] Fix server only stk --- src/states_screens/options_screen_video.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/states_screens/options_screen_video.cpp b/src/states_screens/options_screen_video.cpp index 5d4751d57..4d912de92 100644 --- a/src/states_screens/options_screen_video.cpp +++ b/src/states_screens/options_screen_video.cpp @@ -86,7 +86,11 @@ void OptionsScreenVideo::initPresets() true /* light */, 512 /* shadow */, true /* bloom */, true /* motionblur */, true /* lightshaft */, true /* glow */, true /* mlaa */, true /* ssao */, true /* weather */, true /* animatedScenery */, - (SharedGPUObjects::getMaxMat4Size() > 512 || !CVS->supportsHardwareSkinning() ? 2 : 1)/* animatedCharacters */, +#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 */ }); @@ -96,7 +100,11 @@ void OptionsScreenVideo::initPresets() true /* light */, 1024 /* shadow */, true /* bloom */, true /* motionblur */, true /* lightshaft */, true /* glow */, true /* mlaa */, true /* ssao */, true /* weather */, true /* animatedScenery */, - (SharedGPUObjects::getMaxMat4Size() > 512 || !CVS->supportsHardwareSkinning() ? 2 : 1)/* animatedCharacters */, +#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 */ }); From 85bd8c31465428e6b50d9b4b591891d7728e55ee Mon Sep 17 00:00:00 2001 From: Benau Date: Wed, 14 Dec 2016 16:28:37 +0800 Subject: [PATCH 022/206] Add unlit and normal map skinned mesh shader Also fix normal map with skinned mesh, now vertices and joints will be recalculated for tangents mesh --- data/shaders/instanced_skinning.vert | 13 +- data/shaders/skinning.vert | 11 +- lib/irrlicht/include/ISkinnedMesh.h | 2 +- .../source/Irrlicht/CMeshManipulator.cpp | 12 ++ .../source/Irrlicht/COctreeSceneNode.cpp | 10 ++ .../source/Irrlicht/COpenGLDriver.cpp | 10 ++ lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp | 118 +++++++++++++----- lib/irrlicht/source/Irrlicht/CSkinnedMesh.h | 4 +- src/graphics/command_buffer.cpp | 18 ++- src/graphics/draw_calls.cpp | 53 +++++--- src/graphics/glwrap.hpp | 2 +- src/graphics/materials.cpp | 23 +++- src/graphics/materials.hpp | 80 +++++++++++- src/graphics/mesh_tools.cpp | 53 +------- src/graphics/stk_mesh.cpp | 12 +- 15 files changed, 296 insertions(+), 125 deletions(-) diff --git a/data/shaders/instanced_skinning.vert b/data/shaders/instanced_skinning.vert index 391bfcda9..49a029361 100644 --- a/data/shaders/instanced_skinning.vert +++ b/data/shaders/instanced_skinning.vert @@ -39,25 +39,32 @@ void main(void) mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin, Orientation, Scale) * InverseViewMatrix); vec4 idle_position = vec4(Position, 1.); vec4 idle_normal = vec4(Normal, 0.); + vec4 idle_tangent = vec4(Data1.z, Data1.w, Data2.x, 0.); + vec4 idle_bitangent = vec4(Data2.y, Data2.z, Data2.w, 0.); vec4 skinned_position = vec4(0.); vec4 skinned_normal = vec4(0.); + vec4 skinned_tangent = vec4(0.); + vec4 skinned_bitangent = vec4(0.); // Note : For normal we assume no scale factor in bone (otherwise we'll have to compute inversematrix for each bones...) for (int i = 0; i < 4; i++) { vec4 single_bone_influenced_position = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_position; single_bone_influenced_position /= single_bone_influenced_position.w; vec4 single_bone_influenced_normal = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_normal; + vec4 single_bone_influenced_tangent = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_tangent; + vec4 single_bone_influenced_bitangent = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_bitangent; skinned_position += Weight[i] * single_bone_influenced_position; skinned_normal += Weight[i] * single_bone_influenced_normal; + skinned_tangent += Weight[i] * single_bone_influenced_tangent; + skinned_bitangent += Weight[i] * single_bone_influenced_bitangent; } gl_Position = ProjectionViewMatrix * ModelMatrix * skinned_position; // Keep orthogonality nor = (TransposeInverseModelView * skinned_normal).xyz; // Keep direction - tangent = (ViewMatrix * ModelMatrix * vec4(Data1.z, Data1.w, Data2.x, 0.)).xyz; - bitangent = (ViewMatrix * ModelMatrix * vec4(Data2.y, Data2.z, Data2.w, 0.)).xyz; - + tangent = (ViewMatrix * ModelMatrix * skinned_tangent).xyz; + bitangent = (ViewMatrix * ModelMatrix * skinned_bitangent).xyz; uv = vec2(Data1.x + misc_data.x, Data1.y + misc_data.y); color = Color.zyxw; color_change = misc_data.zw; diff --git a/data/shaders/skinning.vert b/data/shaders/skinning.vert index d4a0d65e8..44bc95705 100644 --- a/data/shaders/skinning.vert +++ b/data/shaders/skinning.vert @@ -41,23 +41,28 @@ void main(void) vec4 idle_normal = vec4(Normal, 0.); vec4 skinned_position = vec4(0.); vec4 skinned_normal = vec4(0.); + vec4 skinned_tangent = vec4(0.); + vec4 skinned_bitangent = vec4(0.); // Note : For normal we assume no scale factor in bone (otherwise we'll have to compute inversematrix for each bones...) for (int i = 0; i < 4; i++) { vec4 single_bone_influenced_position = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_position; single_bone_influenced_position /= single_bone_influenced_position.w; vec4 single_bone_influenced_normal = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_normal; + vec4 single_bone_influenced_tangent = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_tangent; + vec4 single_bone_influenced_bitangent = joint_matrices[clamp(Joint[i] + skinning_offset, 0, MAX_BONES)] * idle_bitangent; skinned_position += Weight[i] * single_bone_influenced_position; skinned_normal += Weight[i] * single_bone_influenced_normal; + skinned_tangent += Weight[i] * single_bone_influenced_tangent; + skinned_bitangent += Weight[i] * single_bone_influenced_bitangent; } gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * skinned_position; // Keep orthogonality nor = (TransposeInverseModelView * skinned_normal).xyz; // Keep direction - tangent = (ViewMatrix * ModelMatrix * vec4(Data1.z, Data1.w, Data2.x, 0.)).xyz; - bitangent = (ViewMatrix * ModelMatrix * vec4(Data2.y, Data2.z, Data2.w, 0.)).xyz; - + tangent = (ViewMatrix * ModelMatrix * skinned_tangent).xyz; + bitangent = (ViewMatrix * ModelMatrix * skinned_bitangent).xyz; uv = vec2(Data1.x + texture_trans.x, Data1.y + texture_trans.y); color = Color.zyxw; } diff --git a/lib/irrlicht/include/ISkinnedMesh.h b/lib/irrlicht/include/ISkinnedMesh.h index 3fd16ed6e..7a36aa307 100644 --- a/lib/irrlicht/include/ISkinnedMesh.h +++ b/lib/irrlicht/include/ISkinnedMesh.h @@ -73,7 +73,7 @@ namespace scene //! converts the vertex type of all meshbuffers to tangents. /** E.g. used for bump mapping. */ - virtual void convertMeshToTangents() = 0; + virtual void convertMeshToTangents(bool(*predicate)(IMeshBuffer*)) = 0; //! Allows to enable hardware skinning. /* This feature is not implementated in Irrlicht yet */ diff --git a/lib/irrlicht/source/Irrlicht/CMeshManipulator.cpp b/lib/irrlicht/source/Irrlicht/CMeshManipulator.cpp index db9ecf30d..5ad585f45 100644 --- a/lib/irrlicht/source/Irrlicht/CMeshManipulator.cpp +++ b/lib/irrlicht/source/Irrlicht/CMeshManipulator.cpp @@ -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::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::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::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; diff --git a/lib/irrlicht/source/Irrlicht/COctreeSceneNode.cpp b/lib/irrlicht/source/Irrlicht/COctreeSceneNode.cpp index eb105dd1f..04e221312 100644 --- a/lib/irrlicht/source/Irrlicht/COctreeSceneNode.cpp +++ b/lib/irrlicht/source/Irrlicht/COctreeSceneNode.cpp @@ -276,6 +276,8 @@ void COctreeSceneNode::render() } } break; + default: + break; } } @@ -371,6 +373,8 @@ bool COctreeSceneNode::createTree(IMesh* mesh) for (v=0; vgetVertexCount(); ++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; vgetVertexCount(); ++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; vgetVertexCount(); ++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; } } diff --git a/lib/irrlicht/source/Irrlicht/COpenGLDriver.cpp b/lib/irrlicht/source/Irrlicht/COpenGLDriver.cpp index e866c7215..3bf8a5894 100644 --- a/lib/irrlicht/source/Irrlicht/COpenGLDriver.cpp +++ b/lib/irrlicht/source/Irrlicht/COpenGLDriver.cpp @@ -1581,6 +1581,8 @@ void COpenGLDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCoun case EVT_TANGENTS: glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), &(static_cast(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(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; } diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp index 981584e83..429ef82b2 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp @@ -9,6 +9,7 @@ #include "CBoneSceneNode.h" #include "IAnimatedMeshSceneNode.h" #include "os.h" +#include "irrMap.h" namespace irr { @@ -751,28 +752,28 @@ bool CSkinnedMesh::setHardwareSkinning(bool on) if (HardwareSkinning!=on) { if (on) - { - - //set mesh to static pose... - for (u32 i=0; iWeights.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; iWeights.size(); ++j) + { + const u16 buffer_id=joint->Weights[j].buffer_id; + const u32 vertex_id=joint->Weights[j].vertex_id; + LocalBuffers[buffer_id]->getVertex(vertex_id)->Pos = joint->Weights[j].StaticPos; + LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal = joint->Weights[j].StaticNormal; + LocalBuffers[buffer_id]->boundingBoxNeedsRecalculated(); + } + } +} void CSkinnedMesh::calculateGlobalMatrices(SJoint *joint,SJoint *parentJoint) { @@ -1491,25 +1492,51 @@ void CSkinnedMesh::computeWeightInfluence(SJoint *joint, size_t &index, WeightIn computeWeightInfluence(joint->Children[j], index, wi); } -void CSkinnedMesh::convertMeshToTangents() +void CSkinnedMesh::convertMeshToTangents(bool(*predicate)(IMeshBuffer*)) { - // now calculate tangents - for (u32 b=0; b < LocalBuffers.size(); ++b) + bool recalculate_animation = false; + toStaticPose(); + for (u32 b = 0; b < LocalBuffers.size(); b++) { - if (LocalBuffers[b]) + bool recalculate_joints = false; + core::map vert_loc_map; + SSkinMeshBuffer* ssmb = LocalBuffers[b]; + if (ssmb) { - LocalBuffers[b]->convertToTangents(); + if (!predicate(ssmb)) continue; - const s32 idxCnt = LocalBuffers[b]->getIndexCount(); - - u16* idx = LocalBuffers[b]->getIndices(); - video::S3DVertexTangents* v = - (video::S3DVertexTangents*)LocalBuffers[b]->getVertices(); - - for (s32 i=0; i vert_map; + core::array 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::Node *n = vert_map.find(v); + if (n) + { + vert_location = n->getValue(); + } + else + { + vert_location = ssmb->Vertices_Tangents.size(); + ssmb->Vertices_Tangents.push_back(v); + vert_map.insert(v, vert_location); + } + vert_loc_map[cur_ver_loc] = vert_location; + tmp_indices.push_back(vert_location); + } + const s32 index_count = tmp_indices.size(); + u16* idx = tmp_indices.pointer(); + video::S3DVertexTangents* v = ssmb->Vertices_Tangents.pointer(); + core::vector3df local_normal; + for (s32 i = 0; i < index_count; i += 3) { calculateTangents( - v[idx[i+0]].Normal, + local_normal, v[idx[i+0]].Tangent, v[idx[i+0]].Binormal, v[idx[i+0]].Pos, @@ -1520,7 +1547,7 @@ void CSkinnedMesh::convertMeshToTangents() v[idx[i+2]].TCoords); calculateTangents( - v[idx[i+1]].Normal, + local_normal, v[idx[i+1]].Tangent, v[idx[i+1]].Binormal, v[idx[i+1]].Pos, @@ -1531,7 +1558,7 @@ void CSkinnedMesh::convertMeshToTangents() v[idx[i+0]].TCoords); calculateTangents( - v[idx[i+2]].Normal, + local_normal, v[idx[i+2]].Tangent, v[idx[i+2]].Binormal, v[idx[i+2]].Pos, @@ -1541,11 +1568,38 @@ void CSkinnedMesh::convertMeshToTangents() v[idx[i+0]].TCoords, v[idx[i+1]].TCoords); } + ssmb->Indices = tmp_indices; + ssmb->Vertices_Standard.clear(); + ssmb->VertexType = video::EVT_TANGENTS; + } + if (recalculate_joints) + { + Vertices_Moved[b].set_used(ssmb->getVertexCount()); + for (u32 i = 0; i < AllJoints.size(); i++) + { + SJoint *joint = AllJoints[i]; + for (u32 j = 0; j Weights.size(); j++) + { + if (joint->Weights[j].buffer_id == b) + { + core::map::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, diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h index 00d924d09..0dd3a43bf 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h @@ -114,7 +114,7 @@ namespace scene virtual void setInterpolationMode(E_INTERPOLATION_MODE mode); //! Convertes the mesh to contain tangent information - virtual void convertMeshToTangents(); + virtual void convertMeshToTangents(bool(*predicate)(IMeshBuffer*)); //! Does the mesh have no animation virtual bool isStatic(); @@ -176,6 +176,8 @@ namespace scene u32 getTotalJoints() const { return m_total_joints; } private: + void toStaticPose(); + void checkForAnimation(); void normalizeWeights(); diff --git a/src/graphics/command_buffer.cpp b/src/graphics/command_buffer.cpp index 86766ee06..a7e4a624b 100644 --- a/src/graphics/command_buffer.cpp +++ b/src/graphics/command_buffer.cpp @@ -172,14 +172,16 @@ void SolidCommandBuffer::fill(SolidPassMeshMap *mesh_map) Material::SHADERTYPE_SPHERE_MAP, Material::SHADERTYPE_VEGETATION, Material::SHADERTYPE_SOLID_SKINNED_MESH, - Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH); + Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH, + Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH); fillInstanceData (mesh_map, three_tex_material_list, InstanceTypeThreeTex); std::vector four_tex_material_list = createVector(Material::SHADERTYPE_DETAIL_MAP, - Material::SHADERTYPE_NORMAL_MAP); + Material::SHADERTYPE_NORMAL_MAP, + Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH); fillInstanceData (mesh_map, four_tex_material_list, InstanceTypeFourTex); @@ -204,10 +206,6 @@ void ShadowCommandBuffer::fill(OtherMeshMap *mesh_map) std::vector shadow_tex_material_list; for(int cascade=0; cascade<4; cascade++) { - shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT - + Material::SHADERTYPE_SOLID_SKINNED_MESH); - shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT - + Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH); shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT + Material::SHADERTYPE_SOLID); shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT @@ -224,6 +222,14 @@ void ShadowCommandBuffer::fill(OtherMeshMap *mesh_map) + Material::SHADERTYPE_VEGETATION); shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT + Material::SHADERTYPE_SPLATTING); + shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT + + Material::SHADERTYPE_SOLID_SKINNED_MESH); + shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT + + Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH); + shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT + + Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH); + shadow_tex_material_list.push_back(cascade * Material::SHADERTYPE_COUNT + + Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH); } fillInstanceData diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 0f6f10dc5..18ddd6b9f 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -712,15 +712,20 @@ void DrawCalls::renderParticlesList() const void DrawCalls::drawIndirectSolidFirstPass() const { m_solid_cmd_buffer->bind(); - m_solid_cmd_buffer->drawIndirectFirstPass(); - m_solid_cmd_buffer->drawIndirectFirstPass(); + m_solid_cmd_buffer->drawIndirectFirstPass(); m_solid_cmd_buffer->drawIndirectFirstPass(); m_solid_cmd_buffer->drawIndirectFirstPass(); m_solid_cmd_buffer->drawIndirectFirstPass(); m_solid_cmd_buffer->drawIndirectFirstPass(m_wind_dir); m_solid_cmd_buffer->drawIndirectFirstPass(); - m_solid_cmd_buffer->drawIndirectFirstPass(); + m_solid_cmd_buffer->drawIndirectFirstPass(); + + if (!CVS->supportsHardwareSkinning()) return; + m_solid_cmd_buffer->drawIndirectFirstPass(); + m_solid_cmd_buffer->drawIndirectFirstPass(); + m_solid_cmd_buffer->drawIndirectFirstPass(); + m_solid_cmd_buffer->drawIndirectFirstPass(); } // ---------------------------------------------------------------------------- @@ -730,15 +735,19 @@ void DrawCalls::drawIndirectSolidFirstPass() const void DrawCalls::multidrawSolidFirstPass() const { m_solid_cmd_buffer->bind(); - m_solid_cmd_buffer->multidrawFirstPass(); - m_solid_cmd_buffer->multidrawFirstPass(); m_solid_cmd_buffer->multidrawFirstPass(); m_solid_cmd_buffer->multidrawFirstPass(); m_solid_cmd_buffer->multidrawFirstPass(); m_solid_cmd_buffer->multidrawFirstPass(); m_solid_cmd_buffer->multidrawFirstPass(m_wind_dir); m_solid_cmd_buffer->multidrawFirstPass(); - m_solid_cmd_buffer->multidrawFirstPass(); + m_solid_cmd_buffer->multidrawFirstPass(); + + if (!CVS->supportsHardwareSkinning()) return; + m_solid_cmd_buffer->multidrawFirstPass(); + m_solid_cmd_buffer->multidrawFirstPass(); + m_solid_cmd_buffer->multidrawFirstPass(); + m_solid_cmd_buffer->multidrawFirstPass(); } // ---------------------------------------------------------------------------- @@ -751,8 +760,6 @@ void DrawCalls::multidrawSolidFirstPass() const void DrawCalls::drawIndirectSolidSecondPass(const std::vector &prefilled_tex) const { m_solid_cmd_buffer->bind(); - m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); - m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); @@ -760,6 +767,12 @@ void DrawCalls::drawIndirectSolidSecondPass(const std::vector &prefilled m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex, m_wind_dir); m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); + + if (!CVS->supportsHardwareSkinning()) return; + m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); + m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); + m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); + m_solid_cmd_buffer->drawIndirectSecondPass(prefilled_tex); } // ---------------------------------------------------------------------------- @@ -771,8 +784,6 @@ void DrawCalls::drawIndirectSolidSecondPass(const std::vector &prefilled void DrawCalls::multidrawSolidSecondPass(const std::vector &handles) const { m_solid_cmd_buffer->bind(); - m_solid_cmd_buffer->multidraw2ndPass(handles); - m_solid_cmd_buffer->multidraw2ndPass(handles); m_solid_cmd_buffer->multidraw2ndPass(handles); m_solid_cmd_buffer->multidraw2ndPass(handles); m_solid_cmd_buffer->multidraw2ndPass(handles); @@ -780,6 +791,12 @@ void DrawCalls::multidrawSolidSecondPass(const std::vector &handles) c m_solid_cmd_buffer->multidraw2ndPass(handles); m_solid_cmd_buffer->multidraw2ndPass(handles); m_solid_cmd_buffer->multidraw2ndPass(handles, m_wind_dir); + + if (!CVS->supportsHardwareSkinning()) return; + m_solid_cmd_buffer->multidraw2ndPass(handles); + m_solid_cmd_buffer->multidraw2ndPass(handles); + m_solid_cmd_buffer->multidraw2ndPass(handles); + m_solid_cmd_buffer->multidraw2ndPass(handles); } // ---------------------------------------------------------------------------- @@ -822,8 +839,6 @@ void DrawCalls::multidrawNormals() const void DrawCalls::drawIndirectShadows(unsigned cascade) const { m_shadow_cmd_buffer->bind(); - m_shadow_cmd_buffer->drawIndirect(cascade); - m_shadow_cmd_buffer->drawIndirect(cascade); m_shadow_cmd_buffer->drawIndirect(cascade); m_shadow_cmd_buffer->drawIndirect(cascade); m_shadow_cmd_buffer->drawIndirect(cascade); @@ -832,6 +847,12 @@ void DrawCalls::drawIndirectShadows(unsigned cascade) const m_shadow_cmd_buffer->drawIndirect(cascade); m_shadow_cmd_buffer->drawIndirect(cascade); m_shadow_cmd_buffer->drawIndirect(cascade); + + if (!CVS->supportsHardwareSkinning()) return; + m_shadow_cmd_buffer->drawIndirect(cascade); + m_shadow_cmd_buffer->drawIndirect(cascade); + m_shadow_cmd_buffer->drawIndirect(cascade); + m_shadow_cmd_buffer->drawIndirect(cascade); } // ---------------------------------------------------------------------------- @@ -842,8 +863,6 @@ void DrawCalls::drawIndirectShadows(unsigned cascade) const void DrawCalls::multidrawShadows(unsigned cascade) const { m_shadow_cmd_buffer->bind(); - m_shadow_cmd_buffer->multidrawShadow(cascade); - m_shadow_cmd_buffer->multidrawShadow(cascade); m_shadow_cmd_buffer->multidrawShadow(cascade); m_shadow_cmd_buffer->multidrawShadow(cascade); m_shadow_cmd_buffer->multidrawShadow(cascade); @@ -852,6 +871,12 @@ void DrawCalls::multidrawShadows(unsigned cascade) const m_shadow_cmd_buffer->multidrawShadow(cascade, m_wind_dir); m_shadow_cmd_buffer->multidrawShadow(cascade); m_shadow_cmd_buffer->multidrawShadow(cascade); + + if (!CVS->supportsHardwareSkinning()) return; + m_shadow_cmd_buffer->multidrawShadow(cascade); + m_shadow_cmd_buffer->multidrawShadow(cascade); + m_shadow_cmd_buffer->multidrawShadow(cascade); + m_shadow_cmd_buffer->multidrawShadow(cascade); } // ---------------------------------------------------------------------------- diff --git a/src/graphics/glwrap.hpp b/src/graphics/glwrap.hpp index d59393448..e150bb06f 100644 --- a/src/graphics/glwrap.hpp +++ b/src/graphics/glwrap.hpp @@ -151,7 +151,7 @@ public: glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24); glEnableVertexAttribArray(3); glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28); - glEnableVertexAttribArray(3); + glEnableVertexAttribArray(4); glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)44); glEnableVertexAttribArray(5); glVertexAttribIPointer(5, 4, GL_INT, getVertexPitchFromType(tp), (GLvoid*)60); diff --git a/src/graphics/materials.cpp b/src/graphics/materials.cpp index 326b53d7f..38ef4aea7 100644 --- a/src/graphics/materials.cpp +++ b/src/graphics/materials.cpp @@ -20,20 +20,35 @@ #ifndef SERVER_ONLY const STK::Tuple SkinnedSolid::FirstPassTextures -= STK::Tuple(1); + = STK::Tuple(1); const STK::Tuple SkinnedSolid::SecondPassTextures -= STK::Tuple(0, 1, 2); + = STK::Tuple(0, 1, 2); const STK::Tuple<> SkinnedSolid::ShadowTextures; const STK::Tuple SkinnedSolid::RSMTextures = STK::Tuple(0); // ---------------------------------------------------------------------------- const STK::Tuple SkinnedAlphaRef::FirstPassTextures -= STK::Tuple(0, 1); + = STK::Tuple(0, 1); const STK::Tuple SkinnedAlphaRef::SecondPassTextures -= STK::Tuple(0, 1, 2); + = STK::Tuple(0, 1, 2); const STK::Tuple SkinnedAlphaRef::ShadowTextures = STK::Tuple(0); const STK::Tuple SkinnedAlphaRef::RSMTextures = STK::Tuple(0); +// ---------------------------------------------------------------------------- +const STK::Tuple SkinnedUnlitMat::FirstPassTextures + = STK::Tuple(0, 1); +const STK::Tuple SkinnedUnlitMat::SecondPassTextures = STK::Tuple(0); +const STK::Tuple SkinnedUnlitMat::ShadowTextures = STK::Tuple(0); +const STK::Tuple SkinnedUnlitMat::RSMTextures = STK::Tuple(0); + +// ---------------------------------------------------------------------------- +const STK::Tuple SkinnedNormalMat::FirstPassTextures + = STK::Tuple(3, 1); +const STK::Tuple SkinnedNormalMat::SecondPassTextures + = STK::Tuple(0, 1, 2); +const STK::Tuple<> SkinnedNormalMat::ShadowTextures; +const STK::Tuple SkinnedNormalMat::RSMTextures = STK::Tuple(0); + // ---------------------------------------------------------------------------- const STK::Tuple DefaultMaterial::FirstPassTextures = STK::Tuple(1); diff --git a/src/graphics/materials.hpp b/src/graphics/materials.hpp index 79fd0a6cb..6355fcc96 100644 --- a/src/graphics/materials.hpp +++ b/src/graphics/materials.hpp @@ -687,6 +687,38 @@ public: } // InstancedSkinnedMeshRefPass2Shader }; // InstancedSkinnedMeshRefPass2Shader +// ============================================================================ +class InstancedSkinnedMeshUnlitShader : public TextureShader +{ +public: + InstancedSkinnedMeshUnlitShader() + { + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", + GL_FRAGMENT_SHADER, "instanced_object_unlit.frag"); + assignUniforms(); + assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, + 1, "SpecularMap", ST_NEAREST_FILTERED, + 2, "SSAO", ST_BILINEAR_FILTERED, + 3, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); + } // InstancedSkinnedMeshUnlitShader +}; // InstancedSkinnedMeshUnlitShader + +// ============================================================================ +class InstancedSkinnedNormalMapShader : public TextureShader +{ +public: + InstancedSkinnedNormalMapShader() + { + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", + GL_FRAGMENT_SHADER, "instanced_normalmap.frag"); + assignUniforms(); + assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 1, "glossMap", ST_TRILINEAR_ANISOTROPIC_FILTERED); + } // InstancedSkinnedNormalMapShader +}; // InstancedSkinnedNormalMapShader + // ============================================================================ class InstancedSkinnedShadowShader : public TextureShader { @@ -749,11 +781,10 @@ struct SkinnedSolid typedef InstancedSkinnedMeshPass1Shader InstancedFirstPassShader; typedef InstancedSkinnedMeshPass2Shader InstancedSecondPassShader; typedef InstancedSkinnedShadowShader InstancedShadowPassShader; - //typedef CInstancedRSMShader InstancedRSMShader; typedef Shaders::SkinnedMeshPass1Shader FirstPassShader; typedef Shaders::SkinnedMeshPass2Shader SecondPassShader; //typedef ShadowShader ShadowPassShader; - //typedef CRSMShader RSMShader; + // Todo: RSMs typedef ListSkinnedSolid List; static const enum video::E_VERTEX_TYPE VertexType = video::EVT_SKINNED_MESH; static const enum Material::ShaderType MaterialType @@ -771,11 +802,10 @@ struct SkinnedAlphaRef typedef InstancedSkinnedMeshRefPass1Shader InstancedFirstPassShader; typedef InstancedSkinnedMeshRefPass2Shader InstancedSecondPassShader; typedef InstancedSkinnedRefShadowShader InstancedShadowPassShader; - //typedef CInstancedRSMShader InstancedRSMShader; //typedef ObjectRefPass1Shader FirstPassShader; //typedef ObjectRefPass2Shader SecondPassShader; //typedef RefShadowShader ShadowPassShader; - //typedef CRSMShader RSMShader; + // Todo: RSMs typedef ListSkinnedAlphaRef List; static const enum video::E_VERTEX_TYPE VertexType = video::EVT_SKINNED_MESH; static const enum Material::ShaderType MaterialType = @@ -787,6 +817,48 @@ struct SkinnedAlphaRef static const STK::Tuple RSMTextures; }; // struct SkinnedAlphaRef +// ---------------------------------------------------------------------------- +struct SkinnedNormalMat +{ + typedef InstancedSkinnedNormalMapShader InstancedFirstPassShader; + typedef InstancedSkinnedMeshPass2Shader InstancedSecondPassShader; + typedef InstancedSkinnedShadowShader InstancedShadowPassShader; + //typedef ObjectRefPass1Shader FirstPassShader; + //typedef ObjectRefPass2Shader SecondPassShader; + //typedef RefShadowShader ShadowPassShader; + // Todo: RSMs + typedef ListSkinnedNormalMap List; + static const enum video::E_VERTEX_TYPE VertexType = video::EVT_SKINNED_MESH; + static const enum Material::ShaderType MaterialType = + Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH; + static const enum InstanceType Instance = InstanceTypeFourTex; + static const STK::Tuple FirstPassTextures; + static const STK::Tuple SecondPassTextures; + static const STK::Tuple<> ShadowTextures; + static const STK::Tuple RSMTextures; +}; // struct SkinnedNormalMat + +// ---------------------------------------------------------------------------- +struct SkinnedUnlitMat +{ + typedef InstancedSkinnedMeshRefPass1Shader InstancedFirstPassShader; + typedef InstancedSkinnedMeshUnlitShader InstancedSecondPassShader; + typedef InstancedSkinnedRefShadowShader InstancedShadowPassShader; + //typedef ObjectRefPass1Shader FirstPassShader; + //typedef ObjectRefPass2Shader SecondPassShader; + //typedef RefShadowShader ShadowPassShader; + // Todo: RSMs + typedef ListSkinnedUnlit List; + static const enum video::E_VERTEX_TYPE VertexType = video::EVT_SKINNED_MESH; + static const enum Material::ShaderType MaterialType = + Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH; + static const enum InstanceType Instance = InstanceTypeThreeTex; + static const STK::Tuple FirstPassTextures; + static const STK::Tuple SecondPassTextures; + static const STK::Tuple ShadowTextures; + static const STK::Tuple RSMTextures; +}; // struct SkinnedUnlitMat + // ---------------------------------------------------------------------------- struct DefaultMaterial { diff --git a/src/graphics/mesh_tools.cpp b/src/graphics/mesh_tools.cpp index cbc1f83a7..d7f0e78c1 100644 --- a/src/graphics/mesh_tools.cpp +++ b/src/graphics/mesh_tools.cpp @@ -421,6 +421,8 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, vNew = v[idx[i]]; } break; + default: + break; } core::map::Node* n = vertMap.find(vNew); if (n) @@ -479,54 +481,5 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, void MeshTools::createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh, bool(*predicate)(scene::IMeshBuffer*)) { - core::array& 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); } diff --git a/src/graphics/stk_mesh.cpp b/src/graphics/stk_mesh.cpp index 02dd61f8b..a42337694 100644 --- a/src/graphics/stk_mesh.cpp +++ b/src/graphics/stk_mesh.cpp @@ -44,13 +44,13 @@ Material::ShaderType getMeshMaterialFromType(video::E_MATERIAL_TYPE material_typ { switch (material->getShaderType()) { - //case Material::SHADERTYPE_SOLID: - // if (material_type == Shaders::getShader(ES_NORMAL_MAP)) - // return Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH; + case Material::SHADERTYPE_SOLID: + if (material_type == Shaders::getShader(ES_NORMAL_MAP)) + return Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH; case Material::SHADERTYPE_ALPHA_TEST: return Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH; - //case Material::SHADERTYPE_SOLID_UNLIT: - // return Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH; + case Material::SHADERTYPE_SOLID_UNLIT: + return Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH; default: return Material::SHADERTYPE_SOLID_SKINNED_MESH; } @@ -182,7 +182,7 @@ GLuint createVAO(GLuint vbo, GLuint idx, video::E_VERTEX_TYPE type) glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(type), (GLvoid*)24); glEnableVertexAttribArray(3); glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)28); - glEnableVertexAttribArray(3); + glEnableVertexAttribArray(4); glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)44); glEnableVertexAttribArray(5); glVertexAttribIPointer(5, 4, GL_INT, getVertexPitchFromType(type), (GLvoid*)60); From a696fd6dffcae43f518e835128bfd3a4c5d65c33 Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 15 Dec 2016 09:52:02 +0800 Subject: [PATCH 023/206] Add transparent skinned mesh shader --- data/shaders/skinning.vert | 2 ++ src/graphics/CBatchingMesh.cpp | 2 ++ src/graphics/draw_calls.cpp | 12 +++++++++++- src/graphics/geometry_passes.cpp | 8 ++++++++ src/graphics/material.hpp | 1 - src/graphics/shaders.cpp | 10 ++++++++++ src/graphics/shaders.hpp | 9 +++++++++ src/graphics/stk_animated_mesh.cpp | 15 +++++++++------ src/graphics/stk_mesh.cpp | 8 ++++++-- src/graphics/stk_mesh.hpp | 8 ++++++++ src/graphics/stk_mesh_scene_node.cpp | 5 +++-- 11 files changed, 68 insertions(+), 12 deletions(-) diff --git a/data/shaders/skinning.vert b/data/shaders/skinning.vert index 44bc95705..e64ec294d 100644 --- a/data/shaders/skinning.vert +++ b/data/shaders/skinning.vert @@ -39,6 +39,8 @@ void main(void) 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.); diff --git a/src/graphics/CBatchingMesh.cpp b/src/graphics/CBatchingMesh.cpp index a039f17bf..ba0c2e6a5 100644 --- a/src/graphics/CBatchingMesh.cpp +++ b/src/graphics/CBatchingMesh.cpp @@ -400,6 +400,8 @@ void CBatchingMesh::recalculateDestBufferBoundingBox(u32 i) case video::EVT_TANGENTS: ((SMeshBufferTangents*)DestBuffers[i].Buffer)->recalculateBoundingBox(); break; + default: + break; } } diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 18ddd6b9f..3fa5c8f74 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -40,6 +40,7 @@ void DrawCalls::clearLists() { ListBlendTransparent::getInstance()->clear(); ListAdditiveTransparent::getInstance()->clear(); + ListTranslucentSkinned::getInstance()->clear(); ListTranslucentStandard::getInstance()->clear(); ListTranslucentTangents::getInstance()->clear(); ListTranslucent2TCoords::getInstance()->clear(); @@ -47,8 +48,11 @@ void DrawCalls::clearLists() ListAdditiveTransparentFog::getInstance()->clear(); ListDisplacement::getInstance()->clear(); - ListMatDefault::getInstance()->clear(); ListSkinnedSolid::getInstance()->clear(); + ListSkinnedAlphaRef::getInstance()->clear(); + ListSkinnedNormalMap::getInstance()->clear(); + ListSkinnedUnlit::getInstance()->clear(); + ListMatDefault::getInstance()->clear(); ListMatAlphaRef::getInstance()->clear(); ListMatSphereMap::getInstance()->clear(); ListMatDetails::getInstance()->clear(); @@ -271,6 +275,12 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, 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()) diff --git a/src/graphics/geometry_passes.cpp b/src/graphics/geometry_passes.cpp index f9fb65400..3ed23a14e 100644 --- a/src/graphics/geometry_passes.cpp +++ b/src/graphics/geometry_passes.cpp @@ -241,6 +241,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( + TexUnits(RenderGeometry::TexUnit(0, true)), + ListTranslucentSkinned::getInstance()); + } + renderTransparenPass( TexUnits(RenderGeometry::TexUnit(0, true)), ListTranslucentStandard::getInstance()); diff --git a/src/graphics/material.hpp b/src/graphics/material.hpp index 49a3e3993..f45196fc3 100644 --- a/src/graphics/material.hpp +++ b/src/graphics/material.hpp @@ -52,7 +52,6 @@ public: SHADERTYPE_ALPHA_TEST, SHADERTYPE_ALPHA_TEST_SKINNED_MESH, SHADERTYPE_ALPHA_BLEND, - SHADERTYPE_ALPHA_BLEND_SKINNED_MESH, SHADERTYPE_ADDITIVE, SHADERTYPE_SOLID_UNLIT, SHADERTYPE_SOLID_UNLIT_SKINNED_MESH, diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index 577798b38..fcbcb3d65 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -386,6 +386,16 @@ Shaders::SkinnedMeshPass2Shader::SkinnedMeshPass2Shader() 5, "colorization_mask", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // SkinnedMeshPass2Shader +// ============================================================================ +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() { diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index 263b8d99d..1b97829f9 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -173,6 +173,15 @@ public: }; // SkinnedMeshPass2Shader // ======================================================================== + class SkinnedTransparentShader : public TextureShader + { + public: + SkinnedTransparentShader(); + }; // SkinnedTransparentShader + + // ======================================================================== }; // class Shaders diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp index f010d1e9f..06f78a08e 100644 --- a/src/graphics/stk_animated_mesh.cpp +++ b/src/graphics/stk_animated_mesh.cpp @@ -188,23 +188,26 @@ 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()) + 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*/ + 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; @@ -252,7 +255,7 @@ void STKAnimatedMesh::updateGL() video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type); GLMesh &mesh = GLmeshes[i]; - if (1)//!rnd->isTransparent()) + if (!rnd->isTransparent()) { Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb); Material* material2 = NULL; diff --git a/src/graphics/stk_mesh.cpp b/src/graphics/stk_mesh.cpp index a42337694..0ac2241e3 100644 --- a/src/graphics/stk_mesh.cpp +++ b/src/graphics/stk_mesh.cpp @@ -71,9 +71,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()) @@ -378,8 +382,8 @@ static void setTexture(GLMesh &mesh, unsigned i, bool is_srgb, { if (!mesh.textures[i]) { - //Log::error("STKMesh", "Missing texture %d for material %s", i, - // mat_name.c_str()); + Log::error("STKMesh", "Missing texture %d for material %s", i, + mat_name.c_str()); // use unicolor texture to replace missing texture mesh.textures[i] = getUnicolorTexture(video::SColor(255, 127, 127, 127)); diff --git a/src/graphics/stk_mesh.hpp b/src/graphics/stk_mesh.hpp index f79dc20f8..7a5b2a7e5 100644 --- a/src/graphics/stk_mesh.hpp +++ b/src/graphics/stk_mesh.hpp @@ -37,6 +37,7 @@ enum TransparentMaterial TM_DEFAULT, TM_ADDITIVE, TM_DISPLACEMENT, + TM_TRANSLUCENT_SKN, TM_TRANSLUCENT_STD, TM_TRANSLUCENT_TAN, TM_TRANSLUCENT_2TC, @@ -197,6 +198,12 @@ class ListAdditiveTransparent : public MiscList {}; +// ---------------------------------------------------------------------------- +class ListTranslucentSkinned : public MiscList +{}; + // ---------------------------------------------------------------------------- class ListTranslucentStandard : public MiscListgetVertexType(); Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb); if (mesh.m_render_info != NULL && mesh.m_render_info->isTransparent() && !rnd->isTransparent()) { @@ -217,7 +218,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 @@ -229,7 +230,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); } From 1f23e6e783af4fdd248536e3fbe1a196dc9e5ba0 Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 15 Dec 2016 11:44:09 +0800 Subject: [PATCH 024/206] Remove code used to duplicate VAOs for animated meshes --- src/graphics/command_buffer.cpp | 18 +++++++++--------- src/graphics/command_buffer.hpp | 13 +++++-------- src/graphics/draw_calls.cpp | 5 ++--- src/graphics/draw_calls.hpp | 8 ++++---- src/graphics/stk_animated_mesh.cpp | 16 +++------------- src/graphics/vao_manager.cpp | 22 ++++++++++------------ src/graphics/vao_manager.hpp | 30 +++--------------------------- 7 files changed, 36 insertions(+), 76 deletions(-) diff --git a/src/graphics/command_buffer.cpp b/src/graphics/command_buffer.cpp index a7e4a624b..fa41e86ed 100644 --- a/src/graphics/command_buffer.cpp +++ b/src/graphics/command_buffer.cpp @@ -158,7 +158,7 @@ SolidCommandBuffer::SolidCommandBuffer(): CommandBuffer() } // ---------------------------------------------------------------------------- -void SolidCommandBuffer::fill(SolidPassMeshMap *mesh_map) +void SolidCommandBuffer::fill(MeshMap *mesh_map) { clearMeshes(); @@ -175,7 +175,7 @@ void SolidCommandBuffer::fill(SolidPassMeshMap *mesh_map) Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH, Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH); - fillInstanceData + fillInstanceData (mesh_map, three_tex_material_list, InstanceTypeThreeTex); std::vector four_tex_material_list = @@ -183,7 +183,7 @@ void SolidCommandBuffer::fill(SolidPassMeshMap *mesh_map) Material::SHADERTYPE_NORMAL_MAP, Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH); - fillInstanceData + fillInstanceData (mesh_map, four_tex_material_list, InstanceTypeFourTex); if (!CVS->supportsAsyncInstanceUpload()) @@ -196,7 +196,7 @@ ShadowCommandBuffer::ShadowCommandBuffer(): CommandBuffer() } // ---------------------------------------------------------------------------- -void ShadowCommandBuffer::fill(OtherMeshMap *mesh_map) +void ShadowCommandBuffer::fill(MeshMap *mesh_map) { clearMeshes(); @@ -232,7 +232,7 @@ void ShadowCommandBuffer::fill(OtherMeshMap *mesh_map) + Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH); } - fillInstanceData + fillInstanceData (mesh_map, shadow_tex_material_list, InstanceTypeShadow); if (!CVS->supportsAsyncInstanceUpload()) @@ -246,7 +246,7 @@ ReflectiveShadowMapCommandBuffer::ReflectiveShadowMapCommandBuffer() } // ---------------------------------------------------------------------------- -void ReflectiveShadowMapCommandBuffer::fill(OtherMeshMap *mesh_map) +void ReflectiveShadowMapCommandBuffer::fill(MeshMap *mesh_map) { clearMeshes(); @@ -260,7 +260,7 @@ void ReflectiveShadowMapCommandBuffer::fill(OtherMeshMap *mesh_map) Material::SHADERTYPE_DETAIL_MAP, Material::SHADERTYPE_NORMAL_MAP); - fillInstanceData + fillInstanceData (mesh_map, rsm_material_list, InstanceTypeRSM); if (!CVS->supportsAsyncInstanceUpload()) @@ -274,14 +274,14 @@ GlowCommandBuffer::GlowCommandBuffer() } // ---------------------------------------------------------------------------- -void GlowCommandBuffer::fill(OtherMeshMap *mesh_map) +void GlowCommandBuffer::fill(MeshMap *mesh_map) { clearMeshes(); if(!CVS->supportsAsyncInstanceUpload()) mapIndirectBuffer(); - fillInstanceData + fillInstanceData (mesh_map, createVector(0), InstanceTypeGlow); if (!CVS->supportsAsyncInstanceUpload()) glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); diff --git a/src/graphics/command_buffer.hpp b/src/graphics/command_buffer.hpp index 6ae425c73..0fade2f85 100644 --- a/src/graphics/command_buffer.hpp +++ b/src/graphics/command_buffer.hpp @@ -39,10 +39,7 @@ struct InstanceList std::vector m_instance_settings; }; -typedef std::unordered_map , InstanceList, - MeshRenderInfoHash, MeshRenderInfoEquals> SolidPassMeshMap; - -typedef std::unordered_map OtherMeshMap; +typedef std::unordered_map MeshMap; // ---------------------------------------------------------------------------- /** Fill origin, orientation and scale attributes @@ -271,7 +268,7 @@ class SolidCommandBuffer: public CommandBuffer(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(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(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. diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 5e77434b7..fc6bb0a6a 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -301,9 +301,8 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, } else { - std::pair mesh_render_info(mesh->mb, NULL); - m_solid_pass_mesh[Mat][mesh_render_info].m_mesh = mesh; - m_solid_pass_mesh[Mat][mesh_render_info].m_instance_settings.emplace_back(Node, mesh->texture_trans, + 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)), skinning_offset); diff --git a/src/graphics/draw_calls.hpp b/src/graphics/draw_calls.hpp index fc72c4cb9..707f42493 100644 --- a/src/graphics/draw_calls.hpp +++ b/src/graphics/draw_calls.hpp @@ -43,10 +43,10 @@ private: std::vector 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 */ diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp index 06f78a08e..588eae88d 100644 --- a/src/graphics/stk_animated_mesh.cpp +++ b/src/graphics/stk_animated_mesh.cpp @@ -99,16 +99,6 @@ 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) @@ -142,7 +132,7 @@ void STKAnimatedMesh::updateNoGL() } else { - cur_ri = default_ri; + cur_ri = NULL; } } else @@ -158,7 +148,7 @@ 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; } @@ -270,7 +260,7 @@ void STKAnimatedMesh::updateGL() if (CVS->isARBBaseInstanceUsable()) { - std::pair p = VAOManager::getInstance()->getBase(mb,NULL /*GLmeshes[i].m_render_info*/); + std::pair p = VAOManager::getInstance()->getBase(mb); mesh.vaoBaseVertex = p.first; mesh.vaoOffset = p.second; } diff --git a/src/graphics/vao_manager.cpp b/src/graphics/vao_manager.cpp index 1fac8bbf9..0a9914284 100644 --- a/src/graphics/vao_manager.cpp +++ b/src/graphics/vao_manager.cpp @@ -316,7 +316,7 @@ irr::video::E_VERTEX_TYPE VAOManager::getVertexType(enum VTXTYPE tp) } } -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]; @@ -347,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 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 VAOManager::getBase(scene::IMeshBuffer *mb, RenderInfo* ri) +std::pair VAOManager::getBase(scene::IMeshBuffer *mb) { VTXTYPE tp = getVTXTYPE(mb->getVertexType()); - std::pair 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, unsigned, MeshRenderInfoHash, MeshRenderInfoEquals>::iterator It; - It = mappedBaseVertex[tp].find(key); + std::unordered_map::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(vtx, It->second); } diff --git a/src/graphics/vao_manager.hpp b/src/graphics/vao_manager.hpp index b30e712c3..a9aff69cd 100644 --- a/src/graphics/vao_manager.hpp +++ b/src/graphics/vao_manager.hpp @@ -174,30 +174,6 @@ struct GlowInstanceData #pragma pack(pop) #endif -#include - -class MeshRenderInfoHash -{ -public: - size_t operator() (const std::pair &p) const - { - return (std::hash()(p.first) ^ - (std::hash()(p.second) << 1)); - } -}; - -struct MeshRenderInfoEquals : std::binary_function - &, - const std::pair&, 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 { enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_SKINNED_MESH, VTXTYPE_COUNT }; @@ -207,7 +183,7 @@ class VAOManager : public Singleton 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 , unsigned, MeshRenderInfoHash, MeshRenderInfoEquals> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT]; + std::unordered_map mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT]; std::map, GLuint> InstanceVAO; void cleanInstanceVAOs(); @@ -217,10 +193,10 @@ class VAOManager : public Singleton 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 getBase(irr::scene::IMeshBuffer *, RenderInfo* ri = NULL); + std::pair 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)]; } From 2e2345289cbc01814cd130e612c35e43315aca35 Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 15 Dec 2016 12:17:39 +0800 Subject: [PATCH 025/206] Don't upload / bind skinning ubo if not supported --- src/graphics/shader_based_renderer.cpp | 5 +++-- src/graphics/shared_gpu_objects.cpp | 5 +++-- src/graphics/vao_manager.hpp | 2 -- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index 655f0141b..4c8e3e278 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -268,11 +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()); - glBindBufferBase(GL_UNIFORM_BUFFER, 2, SharedGPUObjects::getSkinningUBO()); + if (CVS->supportsHardwareSkinning()) + glBindBufferBase(GL_UNIFORM_BUFFER, 2, SharedGPUObjects::getSkinningUBO()); } irr_driver->getSceneManager()->setActiveCamera(camnode); diff --git a/src/graphics/shared_gpu_objects.cpp b/src/graphics/shared_gpu_objects.cpp index 700406cdb..0ae121a1d 100644 --- a/src/graphics/shared_gpu_objects.cpp +++ b/src/graphics/shared_gpu_objects.cpp @@ -223,11 +223,12 @@ void SharedGPUObjects::init() initFrustrumVBO(); initParticleQuadVBO(); - if(CVS->isARBUniformBufferObjectUsable()) + if (CVS->isARBUniformBufferObjectUsable()) { initShadowVPMUBO(); initLightingDataUBO(); - initSkinningUBO(); + if (CVS->supportsHardwareSkinning()) + initSkinningUBO(); } m_has_been_initialised = true; diff --git a/src/graphics/vao_manager.hpp b/src/graphics/vao_manager.hpp index a9aff69cd..c02d19d43 100644 --- a/src/graphics/vao_manager.hpp +++ b/src/graphics/vao_manager.hpp @@ -26,8 +26,6 @@ #include #include -class RenderInfo; - enum InstanceType { InstanceTypeThreeTex, From 035271d6ec97513868bcb2d53c9cd65948c0363d Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 15 Dec 2016 12:56:08 +0800 Subject: [PATCH 026/206] Remove GL error about draw2DLine Use GL32_draw2DRectangle, only works if it's a straight line. --- src/utils/profiler.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/utils/profiler.cpp b/src/utils/profiler.cpp index bbcfb54ad..b359cdcf6 100644 --- a/src/utils/profiler.cpp +++ b/src/utils/profiler.cpp @@ -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(x_sync, y_up_sync, x_sync + 1, y_down_sync)); } // Draw the hovered markers' names From 3d814d1036e829e65a0832b4b3f0d22ca97b55cd Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 15 Dec 2016 13:30:26 +0800 Subject: [PATCH 027/206] Fix wrong case handling --- src/graphics/stk_mesh.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/graphics/stk_mesh.cpp b/src/graphics/stk_mesh.cpp index 0ac2241e3..68519c590 100644 --- a/src/graphics/stk_mesh.cpp +++ b/src/graphics/stk_mesh.cpp @@ -47,6 +47,8 @@ Material::ShaderType getMeshMaterialFromType(video::E_MATERIAL_TYPE material_typ 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: From 752d847b09b1802c30aec77f34139d7af8010f4c Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 15 Dec 2016 15:55:14 +0800 Subject: [PATCH 028/206] Add the remaining shaders for GL3 hardware skinning Also use the same shader code for normal map shader --- data/shaders/normalmap.frag | 8 +- data/shaders/skinning_shadow.vert | 37 ++++ src/graphics/draw_calls.cpp | 51 ++++- src/graphics/draw_policies.cpp | 20 +- src/graphics/materials.hpp | 258 +++++++++++++++++++---- src/graphics/shaders.cpp | 25 --- src/graphics/shaders.hpp | 18 -- src/tracks/track_object_presentation.cpp | 1 - 8 files changed, 315 insertions(+), 103 deletions(-) create mode 100644 data/shaders/skinning_shadow.vert diff --git a/data/shaders/normalmap.frag b/data/shaders/normalmap.frag index 5b5e02688..916c36ce4 100644 --- a/data/shaders/normalmap.frag +++ b/data/shaders/normalmap.frag @@ -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; } diff --git a/data/shaders/skinning_shadow.vert b/data/shaders/skinning_shadow.vert new file mode 100644 index 000000000..6fc5d35c8 --- /dev/null +++ b/data/shaders/skinning_shadow.vert @@ -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 +} diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index fc6bb0a6a..dab61bce0 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -318,18 +318,34 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, { switch (Mat) { - case Material::SHADERTYPE_SOLID: - ListMatDefault::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))); - break; case Material::SHADERTYPE_SOLID_SKINNED_MESH: ListSkinnedSolid::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f)), skinning_offset); break; + case Material::SHADERTYPE_ALPHA_TEST_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 ? + core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : + core::vector2df(0.0f, 0.0f))); + break; case Material::SHADERTYPE_ALPHA_TEST: ListMatAlphaRef::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, (mesh->m_render_info && mesh->m_material ? @@ -399,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; @@ -468,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; @@ -719,7 +757,6 @@ void DrawCalls::renderParticlesList() const void DrawCalls::drawIndirectSolidFirstPass() const { m_solid_cmd_buffer->bind(); - m_solid_cmd_buffer->drawIndirectFirstPass(); m_solid_cmd_buffer->drawIndirectFirstPass(); m_solid_cmd_buffer->drawIndirectFirstPass(); diff --git a/src/graphics/draw_policies.cpp b/src/graphics/draw_policies.cpp index a37fe0295..3595d212d 100644 --- a/src/graphics/draw_policies.cpp +++ b/src/graphics/draw_policies.cpp @@ -178,7 +178,6 @@ void drawRSM(const core::matrix4 & rsm_matrix) void GL3DrawPolicy::drawSolidFirstPass(const DrawCalls& draw_calls) const { renderMeshes1stPass(); - renderMeshes1stPass(); renderMeshes1stPass(); renderMeshes1stPass(); renderMeshes1stPass(); @@ -186,6 +185,12 @@ void GL3DrawPolicy::drawSolidFirstPass(const DrawCalls& draw_calls) const renderMeshes1stPass(); renderMeshes1stPass(); renderMeshes1stPass(); + + if (!CVS->supportsHardwareSkinning()) return; + renderMeshes1stPass(); + renderMeshes1stPass(); + renderMeshes1stPass(); + renderMeshes1stPass(); } // ---------------------------------------------------------------------------- @@ -194,7 +199,6 @@ void GL3DrawPolicy::drawSolidSecondPass (const DrawCalls& draw_calls, const std::vector& prefilled_tex) const { renderMeshes2ndPass (handles, prefilled_tex); - renderMeshes2ndPass (handles, prefilled_tex); renderMeshes2ndPass (handles, prefilled_tex); renderMeshes2ndPass (handles, prefilled_tex); renderMeshes2ndPass (handles, prefilled_tex); @@ -202,6 +206,12 @@ void GL3DrawPolicy::drawSolidSecondPass (const DrawCalls& draw_calls, renderMeshes2ndPass (handles, prefilled_tex); renderMeshes2ndPass (handles, prefilled_tex); renderMeshes2ndPass (handles, prefilled_tex); + + if (!CVS->supportsHardwareSkinning()) return; + renderMeshes2ndPass (handles, prefilled_tex); + renderMeshes2ndPass (handles, prefilled_tex); + renderMeshes2ndPass (handles, prefilled_tex); + renderMeshes2ndPass (handles, prefilled_tex); } // ---------------------------------------------------------------------------- @@ -224,6 +234,12 @@ void GL3DrawPolicy::drawShadows(const DrawCalls& draw_calls, unsigned cascade) c renderShadow(cascade); renderShadow(cascade); renderShadow(cascade); + + if (!CVS->supportsHardwareSkinning()) return; + renderShadow(cascade); + renderShadow(cascade); + renderShadow(cascade); + renderShadow(cascade); } // ---------------------------------------------------------------------------- diff --git a/src/graphics/materials.hpp b/src/graphics/materials.hpp index 6355fcc96..239a97ad1 100644 --- a/src/graphics/materials.hpp +++ b/src/graphics/materials.hpp @@ -296,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 @@ -618,25 +618,62 @@ public: }; // InstancedDetailedObjectPass2Shader // ============================================================================ -class InstancedSkinnedMeshPass1Shader : public TextureShader +class SkinnedPass1Shader : public TextureShader { public: - InstancedSkinnedMeshPass1Shader() + 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 +{ +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); - } // InstancedSkinnedMeshPass1Shader -}; // InstancedSkinnedMeshPass1Shader + } // InstancedSkinnedPass1Shader +}; // InstancedSkinnedPass1Shader // ============================================================================ -class InstancedSkinnedMeshPass2Shader : public TextureShader +class SkinnedPass2Shader : public TextureShader { public: - InstancedSkinnedMeshPass2Shader() + 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 +{ +public: + InstancedSkinnedPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", @@ -648,31 +685,71 @@ public: 3, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED, 4, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, 5, "colorization_mask", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // InstancedSkinnedMeshPass2Shader -}; // InstancedSkinnedMeshPass2Shader + } // InstancedSkinnedPass2Shader +}; // InstancedSkinnedPass2Shader // ============================================================================ -class InstancedSkinnedMeshRefPass1Shader : public TextureShader +class SkinnedRefPass1Shader : public TextureShader { public: - InstancedSkinnedMeshRefPass1Shader() + 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 +{ +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); - } // InstancedSkinnedMeshRefPass1Shader - -}; // InstancedSkinnedMeshRefPass1Shader + } // InstancedSkinnedRefPass1Shader +}; // InstancedSkinnedRefPass1Shader // ============================================================================ -class InstancedSkinnedMeshRefPass2Shader : public TextureShader +class SkinnedRefPass2Shader : public TextureShader { public: - InstancedSkinnedMeshRefPass2Shader() + 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 +{ +public: + InstancedSkinnedRefPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", @@ -684,14 +761,33 @@ public: 3, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED, 4, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, 5, "colorization_mask", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // InstancedSkinnedMeshRefPass2Shader -}; // InstancedSkinnedMeshRefPass2Shader + } // InstancedSkinnedRefPass2Shader +}; // InstancedSkinnedRefPass2Shader // ============================================================================ -class InstancedSkinnedMeshUnlitShader : public TextureShader +class SkinnedUnlitShader : public TextureShader { public: - InstancedSkinnedMeshUnlitShader() + 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 +{ +public: + InstancedSkinnedUnlitShader() { if (!CVS->supportsHardwareSkinning()) return; loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", @@ -701,8 +797,25 @@ public: 1, "SpecularMap", ST_NEAREST_FILTERED, 2, "SSAO", ST_BILINEAR_FILTERED, 3, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // InstancedSkinnedMeshUnlitShader -}; // InstancedSkinnedMeshUnlitShader + } // InstancedSkinnedUnlitShader +}; // InstancedSkinnedUnlitShader + +// ============================================================================ +class SkinnedNormalMapShader : public TextureShader +{ +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 @@ -719,6 +832,33 @@ public: } // InstancedSkinnedNormalMapShader }; // InstancedSkinnedNormalMapShader +// ============================================================================ +class SkinnedShadowShader : public TextureShader +{ +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 { @@ -743,9 +883,36 @@ public: assignUniforms("layer"); #endif } // InstancedSkinnedShadowShader - }; // InstancedSkinnedShadowShader +// ============================================================================ +class SkinnedRefShadowShader : public TextureShader +{ +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 @@ -772,18 +939,17 @@ public: assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); #endif } // InstancedSkinnedRefShadowShader - }; // InstancedSkinnedRefShadowShader // ============================================================================ struct SkinnedSolid { - typedef InstancedSkinnedMeshPass1Shader InstancedFirstPassShader; - typedef InstancedSkinnedMeshPass2Shader InstancedSecondPassShader; + typedef InstancedSkinnedPass1Shader InstancedFirstPassShader; + typedef InstancedSkinnedPass2Shader InstancedSecondPassShader; typedef InstancedSkinnedShadowShader InstancedShadowPassShader; - typedef Shaders::SkinnedMeshPass1Shader FirstPassShader; - typedef Shaders::SkinnedMeshPass2Shader SecondPassShader; - //typedef ShadowShader ShadowPassShader; + 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; @@ -799,12 +965,12 @@ struct SkinnedSolid // ---------------------------------------------------------------------------- struct SkinnedAlphaRef { - typedef InstancedSkinnedMeshRefPass1Shader InstancedFirstPassShader; - typedef InstancedSkinnedMeshRefPass2Shader InstancedSecondPassShader; + typedef InstancedSkinnedRefPass1Shader InstancedFirstPassShader; + typedef InstancedSkinnedRefPass2Shader InstancedSecondPassShader; typedef InstancedSkinnedRefShadowShader InstancedShadowPassShader; - //typedef ObjectRefPass1Shader FirstPassShader; - //typedef ObjectRefPass2Shader SecondPassShader; - //typedef RefShadowShader ShadowPassShader; + 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; @@ -821,11 +987,11 @@ struct SkinnedAlphaRef struct SkinnedNormalMat { typedef InstancedSkinnedNormalMapShader InstancedFirstPassShader; - typedef InstancedSkinnedMeshPass2Shader InstancedSecondPassShader; + typedef InstancedSkinnedPass2Shader InstancedSecondPassShader; typedef InstancedSkinnedShadowShader InstancedShadowPassShader; - //typedef ObjectRefPass1Shader FirstPassShader; - //typedef ObjectRefPass2Shader SecondPassShader; - //typedef RefShadowShader ShadowPassShader; + 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; @@ -841,12 +1007,12 @@ struct SkinnedNormalMat // ---------------------------------------------------------------------------- struct SkinnedUnlitMat { - typedef InstancedSkinnedMeshRefPass1Shader InstancedFirstPassShader; - typedef InstancedSkinnedMeshUnlitShader InstancedSecondPassShader; + typedef InstancedSkinnedRefPass1Shader InstancedFirstPassShader; + typedef InstancedSkinnedUnlitShader InstancedSecondPassShader; typedef InstancedSkinnedRefShadowShader InstancedShadowPassShader; - //typedef ObjectRefPass1Shader FirstPassShader; - //typedef ObjectRefPass2Shader SecondPassShader; - //typedef RefShadowShader ShadowPassShader; + 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; diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index fcbcb3d65..ed8e6c238 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -361,31 +361,6 @@ Shaders::ObjectPass2Shader::ObjectPass2Shader() 5, "colorization_mask", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // ObjectPass2Shader -// ============================================================================ -Shaders::SkinnedMeshPass1Shader::SkinnedMeshPass1Shader() -{ - 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); -} // SkinnedMeshPass1Shader - -// ============================================================================ -Shaders::SkinnedMeshPass2Shader::SkinnedMeshPass2Shader() -{ - 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); -} // SkinnedMeshPass2Shader - // ============================================================================ Shaders::SkinnedTransparentShader::SkinnedTransparentShader() { diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index 1b97829f9..57231d84b 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -154,24 +154,6 @@ public: ObjectPass2Shader(); }; // ObjectPass2Shader - // ======================================================================== - class SkinnedMeshPass1Shader : public TextureShader - { - public: - SkinnedMeshPass1Shader(); - }; // SkinnedMeshPass1Shader - - // ======================================================================== - class SkinnedMeshPass2Shader : public TextureShader < SkinnedMeshPass2Shader, 6, - core::matrix4, core::vector2df, - core::vector2df, int > - { - public: - SkinnedMeshPass2Shader(); - }; // SkinnedMeshPass2Shader - // ======================================================================== class SkinnedTransparentShader : public TextureShader 0 && file_manager->fileExists(local_lib_node_path)) { From 79e5aadd4d212cbc549584f5a4e29d8894cde219 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 16 Dec 2016 10:04:35 +0800 Subject: [PATCH 029/206] Avoid using software skinning on empty joint objects --- src/graphics/stk_animated_mesh.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp index 588eae88d..75af0fc74 100644 --- a/src/graphics/stk_animated_mesh.cpp +++ b/src/graphics/stk_animated_mesh.cpp @@ -275,6 +275,8 @@ void STKAnimatedMesh::updateGL() isGLInitialized = true; } + if (useHardwareSkinning() && m_skinned_mesh->getTotalJoints() == 0) return; + scene::IMesh* m = getMeshForCurrentFrame(); if (useHardwareSkinning()) { @@ -336,11 +338,7 @@ void STKAnimatedMesh::resetSkinningState(scene::IAnimatedMesh* mesh) m_skinning_offset = -1; m_skinned_mesh = dynamic_cast(mesh); if (m_skinned_mesh) - { m_skinned_mesh->convertForSkinning(); - if (m_skinned_mesh->getTotalJoints() == 0) - m_skinned_mesh = NULL; - } } scene::IMesh* STKAnimatedMesh::getMeshForCurrentFrame(SkinningCallback sc, From 90a556fe9cb3de22404df12210b8eb5d38e5a04e Mon Sep 17 00:00:00 2001 From: Benau Date: Sat, 17 Dec 2016 15:59:40 +0800 Subject: [PATCH 030/206] Try to share shaders across different programs Todo: non-instanced version --- sources.cmake | 2 +- src/graphics/2dutils.cpp | 9 +- src/graphics/irr_driver.cpp | 2 +- src/graphics/lighting_passes.cpp | 21 ++- src/graphics/materials.hpp | 110 +++++------ src/graphics/post_processing.cpp | 47 ++--- src/graphics/shader.hpp | 25 ++- src/graphics/shader_based_renderer.cpp | 42 ++++- src/graphics/shader_based_renderer.hpp | 2 +- src/graphics/shaders.cpp | 22 +-- src/graphics/shadow_matrices.cpp | 3 +- src/graphics/shared_shader.cpp | 28 +++ src/graphics/shared_shader.hpp | 49 +++++ src/graphics/shared_shader_manager.hpp | 81 ++++++++ src/graphics/shared_shaders.hpp | 244 +++++++++++++++++++++++++ src/graphics/skybox.cpp | 4 +- src/graphics/stk_mesh_scene_node.cpp | 3 +- src/utils/debug.cpp | 6 +- 18 files changed, 584 insertions(+), 116 deletions(-) create mode 100644 src/graphics/shared_shader.cpp create mode 100644 src/graphics/shared_shader.hpp create mode 100644 src/graphics/shared_shader_manager.hpp create mode 100644 src/graphics/shared_shaders.hpp diff --git a/sources.cmake b/sources.cmake index d4f28ae4d..ba4868d71 100644 --- a/sources.cmake +++ b/sources.cmake @@ -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/*") diff --git a/src/graphics/2dutils.cpp b/src/graphics/2dutils.cpp index 87bf3a16e..42fab11e0 100644 --- a/src/graphics/2dutils.cpp +++ b/src/graphics/2dutils.cpp @@ -24,6 +24,7 @@ #include "graphics/shader.hpp" #include "graphics/shaders.hpp" #include "graphics/shared_gpu_objects.hpp" +#include "graphics/shared_shaders.hpp" #include "graphics/texture_manager.hpp" #include "graphics/texture_shader.hpp" #include "utils/cpp2011.hpp" @@ -43,7 +44,7 @@ public: Primitive2DList() { loadProgram(OBJECT, GL_VERTEX_SHADER, "primitive2dlist.vert", - GL_FRAGMENT_SHADER, "transparent.frag"); + GET_SS(SharedTransparent)); assignUniforms("custom_alpha"); assignSamplerNames(0, "tex", ST_BILINEAR_FILTERED); } // Primitive2DList @@ -58,7 +59,7 @@ class UniformColoredTextureRectShader : public TextureShaderkill(); resetTextureTable(); cleanUnicolorTextures(); @@ -930,6 +929,7 @@ void IrrDriver::applyResolutionSettings() } delete m_renderer; initDevice(); + ShaderBase::updateShaders(); font_manager = new FontManager(); font_manager->loadFonts(); diff --git a/src/graphics/lighting_passes.cpp b/src/graphics/lighting_passes.cpp index 55675ed8d..cf321c176 100644 --- a/src/graphics/lighting_passes.cpp +++ b/src/graphics/lighting_passes.cpp @@ -26,7 +26,8 @@ #include "graphics/post_processing.hpp" #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" -#include "graphics/shadow_matrices.hpp" +#include "graphics/shadow_matrices.hpp" +#include "graphics/shared_shaders.hpp" #include "modes/world.hpp" #include "tracks/track.hpp" #include "utils/profiler.hpp" @@ -63,7 +64,7 @@ class FogShader : public TextureShader public: FogShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "fog.frag"); assignUniforms("density", "col"); assignSamplerNames(0, "tex", ST_NEAREST_FILTERED); @@ -190,12 +191,12 @@ public: { if (CVS->isAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert", + loadProgram(OBJECT, GET_SS(SharedSlicedScreenQuad), GL_FRAGMENT_SHADER, "rh.frag"); } else { - loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert", + loadProgram(OBJECT, GET_SS(SharedSlicedScreenQuad), GL_GEOMETRY_SHADER, "rhpassthrough.geom", GL_FRAGMENT_SHADER, "rh.frag"); } @@ -238,7 +239,7 @@ class GlobalIlluminationReconstructionShader public: GlobalIlluminationReconstructionShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "gi.frag"); assignUniforms("rh_matrix", "inv_rh_matrix", "extents"); @@ -271,7 +272,7 @@ class IBLShader : public TextureShader public: IBLShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "IBL.frag"); assignUniforms(); assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, @@ -286,7 +287,7 @@ class DegradedIBLShader : public TextureShader public: DegradedIBLShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "degraded_ibl.frag"); assignUniforms(); assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED); @@ -301,7 +302,7 @@ class ShadowedSunLightShaderPCF : public TextureShader { public: InstancedObjectPass1Shader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", - GL_FRAGMENT_SHADER, "instanced_object_pass1.frag"); + loadProgram(OBJECT, GET_SS(SharedInstanced), + GET_SS(SharedInstancedPass1)); assignUniforms(); assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); @@ -46,8 +46,8 @@ class InstancedObjectRefPass1Shader : public TextureShaderisAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanciedshadow.vert", + loadProgram(OBJECT, GET_SS(SharedInstancedShadow), GL_FRAGMENT_SHADER, "shadow.frag"); } else { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanciedshadow.vert", + loadProgram(OBJECT, GET_SS(SharedInstancedShadow), GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "shadow.frag"); } @@ -222,7 +222,7 @@ class SphereMapShader : public TextureShader public: SplattingShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + loadProgram(OBJECT, GET_SS(SharedObject), GL_FRAGMENT_SHADER, "splatting.frag"); assignUniforms("ModelMatrix"); @@ -277,7 +277,7 @@ class ObjectRefPass1Shader : public TextureShaderisAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT,GL_VERTEX_SHADER, "instanciedshadow.vert", + loadProgram(OBJECT,GET_SS(SharedInstancedShadow), GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } else { - loadProgram(OBJECT,GL_VERTEX_SHADER, "instanciedshadow.vert", + loadProgram(OBJECT,GET_SS(SharedInstancedShadow), GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } @@ -442,9 +442,9 @@ public: NormalVisualizer() { #if !defined(USE_GLES2) - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", + loadProgram(OBJECT, GET_SS(SharedInstanced), GL_GEOMETRY_SHADER, "normal_visualizer.geom", - GL_FRAGMENT_SHADER, "coloredquad.frag"); + GET_SS(SharedColoredQuad)); assignUniforms("color"); #endif } // NormalVisualizer @@ -473,8 +473,8 @@ class InstancedGrassPass1Shader : public TextureShadersupportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", - GL_FRAGMENT_SHADER, "object_pass1.frag"); + loadProgram(OBJECT, GET_SS(SharedSkinning), + GET_SS(SharedPass1)); assignUniforms("ModelMatrix", "InverseModelMatrix", "skinning_offset"); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // SkinnedPass1Shader @@ -640,8 +640,8 @@ public: InstancedSkinnedPass1Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", - GL_FRAGMENT_SHADER, "instanced_object_pass1.frag"); + loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), + GET_SS(SharedInstancedPass1)); assignUniforms(); assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // InstancedSkinnedPass1Shader @@ -656,7 +656,7 @@ public: SkinnedPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(OBJECT, GET_SS(SharedSkinning), GL_FRAGMENT_SHADER, "object_pass2.frag"); assignUniforms("ModelMatrix", "texture_trans", "color_change", "skinning_offset"); @@ -676,8 +676,8 @@ public: InstancedSkinnedPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", - GL_FRAGMENT_SHADER, "instanced_object_pass2.frag"); + loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), + GET_SS(SharedInstancedPass2)); assignUniforms(); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, 1, "SpecularMap", ST_NEAREST_FILTERED, @@ -698,7 +698,7 @@ public: SkinnedRefPass1Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(OBJECT, GET_SS(SharedSkinning), GL_FRAGMENT_SHADER, "objectref_pass1.frag"); assignUniforms("ModelMatrix", "InverseModelMatrix", "texture_trans", "skinning_offset"); @@ -714,8 +714,8 @@ public: InstancedSkinnedRefPass1Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", - GL_FRAGMENT_SHADER, "instanced_objectref_pass1.frag"); + loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), + GET_SS(SharedInstancedRefPass1)); assignUniforms(); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED, 1, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); @@ -732,7 +732,7 @@ public: SkinnedRefPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(OBJECT, GET_SS(SharedSkinning), GL_FRAGMENT_SHADER, "objectref_pass2.frag"); assignUniforms("ModelMatrix", "texture_trans", "color_change", "skinning_offset"); @@ -752,8 +752,8 @@ public: InstancedSkinnedRefPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", - GL_FRAGMENT_SHADER, "instanced_objectref_pass2.frag"); + loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), + GET_SS(SharedInstancedRefPass2)); assignUniforms(); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, 1, "SpecularMap", ST_NEAREST_FILTERED, @@ -773,7 +773,7 @@ public: SkinnedUnlitShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(OBJECT, GET_SS(SharedSkinning), GL_FRAGMENT_SHADER, "object_unlit.frag"); assignUniforms("ModelMatrix", "texture_trans", "skinning_offset"); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, @@ -790,8 +790,8 @@ public: InstancedSkinnedUnlitShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", - GL_FRAGMENT_SHADER, "instanced_object_unlit.frag"); + loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), + GET_SS(SharedInstancedUnlit)); assignUniforms(); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, 1, "SpecularMap", ST_NEAREST_FILTERED, @@ -809,7 +809,7 @@ public: SkinnedNormalMapShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(OBJECT, GET_SS(SharedSkinning), GL_FRAGMENT_SHADER, "normalmap.frag"); assignUniforms("ModelMatrix", "InverseModelMatrix", "skinning_offset"); assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, @@ -824,8 +824,8 @@ public: InstancedSkinnedNormalMapShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", - GL_FRAGMENT_SHADER, "instanced_normalmap.frag"); + loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), + GET_SS(SharedInstancedNormal)); assignUniforms(); assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, 1, "glossMap", ST_TRILINEAR_ANISOTROPIC_FILTERED); @@ -871,12 +871,12 @@ public: return; if (CVS->isAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + loadProgram(OBJECT, GET_SS(SharedInstancedSkinningShadow), GL_FRAGMENT_SHADER, "shadow.frag"); } else { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + loadProgram(OBJECT, GET_SS(SharedInstancedSkinningShadow), GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "shadow.frag"); } @@ -926,12 +926,12 @@ public: return; if (CVS->isAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + loadProgram(OBJECT, GET_SS(SharedInstancedSkinningShadow), GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } else { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + loadProgram(OBJECT, GET_SS(SharedInstancedSkinningShadow), GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } diff --git a/src/graphics/post_processing.cpp b/src/graphics/post_processing.cpp index 3ba0be240..da6e1f8bb 100644 --- a/src/graphics/post_processing.cpp +++ b/src/graphics/post_processing.cpp @@ -30,6 +30,7 @@ #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" #include "graphics/shared_gpu_objects.hpp" +#include "graphics/shared_shaders.hpp" #include "graphics/stk_mesh_scene_node.hpp" #include "graphics/texture_manager.hpp" #include "graphics/weather.hpp" @@ -56,7 +57,7 @@ class Gaussian3HBlurShader : public TextureShader public: BloomShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "bloom.frag"); assignUniforms("scale"); assignSamplerNames(0, "tex", ST_NEAREST_FILTERED); @@ -364,7 +365,7 @@ public: if (!lensDustTex) lensDustTex = irr_driver->getTexture(FileManager::TEXTURE, "gfx_lensDust_a.png"); - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "bloomblend.frag"); assignUniforms(); assignSamplerNames(0, "tex_128", ST_BILINEAR_FILTERED, @@ -391,7 +392,7 @@ class LensBlendShader : public TextureShader public: LensBlendShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "lensblend.frag"); assignUniforms(); @@ -419,7 +420,7 @@ public: ToneMapShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "tonemap.frag"); assignUniforms("vignette_weight"); assignSamplerNames(0, "text", ST_NEAREST_FILTERED); @@ -439,7 +440,7 @@ class DepthOfFieldShader : public TextureShader public: DepthOfFieldShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "dof.frag"); assignUniforms(); @@ -481,7 +482,7 @@ class PassThroughShader : public TextureShader public: PassThroughShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "passthrough.frag"); assignUniforms("width", "height"); assignSamplerNames(0, "tex", ST_BILINEAR_FILTERED); @@ -505,7 +506,7 @@ private: public: LayerPassThroughShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "layertexturequad.frag"); m_tu_texture = 0; assignUniforms("layer"); @@ -531,7 +532,7 @@ class LinearizeDepthShader : public TextureShader public: SSAOShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "ssao.frag"); assignUniforms("radius", "k", "sigma"); @@ -605,7 +606,7 @@ class MotionBlurShader : public TextureShader public: GodFadeShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "godfade.frag"); assignUniforms("col"); assignSamplerNames(0, "tex", ST_BILINEAR_FILTERED); @@ -650,7 +651,7 @@ class GodRayShader : public TextureShader public: GodRayShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "godray.frag"); assignUniforms("sunpos"); @@ -671,7 +672,7 @@ class MLAAColorEdgeDetectionSHader public: MLAAColorEdgeDetectionSHader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "mlaa_color1.frag"); assignUniforms("PIXEL_SIZE"); assignSamplerNames(0, "colorMapG", ST_NEAREST_FILTERED); @@ -692,7 +693,7 @@ class MLAABlendWeightSHader : public TextureShader + void loadAndAttachShader(SharedShader* ss, Types ... args) + { + GLint shader_id = ss->getShaderID(); + glAttachShader(m_program, 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 + // ------------------------------------------------------------------------ /** Convenience interface using const char. */ template void loadAndAttachShader(GLint shader_type, const char *name, @@ -90,12 +103,12 @@ protected: } // loadAndAttachShader // ------------------------------------------------------------------------ - const std::string& getHeader(); - GLuint loadShader(const std::string &file, unsigned type); + static const std::string& getHeader(); void setAttribute(AttributeType type); public: ShaderBase(); + static GLuint loadShader(const std::string &file, unsigned type); int loadTFBProgram(const std::string &vertex_file_path, const char **varyings, unsigned varyingscount); @@ -285,7 +298,13 @@ protected: Log::error("shader", filepath); printFileList(args...); } // printFileList - + // ------------------------------------------------------------------------ + template + void printFileList(SharedShader* ss, Types ... args) + { + Log::error("shader", ss->getName()); + printFileList(args...); + } // printFileList // ------------------------------------------------------------------------ /** End recursion for variadic template. */ private: diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index 4c8e3e278..6253bfb56 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -31,6 +31,7 @@ #include "graphics/render_target.hpp" #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" +#include "graphics/shared_shaders.hpp" #include "graphics/skybox.hpp" #include "graphics/spherical_harmonics.hpp" #include "graphics/texture_manager.hpp" @@ -641,7 +642,8 @@ ShaderBasedRenderer::ShaderBasedRenderer() m_skybox = NULL; m_spherical_harmonics = new SphericalHarmonics(irr_driver->getAmbientLight().toSColor()); m_nb_static_glowing = 0; - + preloadSharedShaders(); + if (CVS->isAZDOEnabled()) { m_geometry_passes = new GeometryPasses(); @@ -681,6 +683,7 @@ ShaderBasedRenderer::~ShaderBasedRenderer() delete m_spherical_harmonics; delete m_skybox; delete m_rtts; + SharedShaderManager::kill(); } // ---------------------------------------------------------------------------- @@ -961,4 +964,41 @@ void ShaderBasedRenderer::renderToTexture(GL3RenderTarget *render_target, } //renderToTexture +void ShaderBasedRenderer::preloadSharedShaders() +{ + SharedShaderManager* ssm = SharedShaderManager::getInstance(); + // Common shaders: + ssm->addSharedShader(new SharedObject()); + ssm->addSharedShader(new SharedPass1()); + if (CVS->supportsHardwareSkinning()) + ssm->addSharedShader(new SharedSkinning()); + ssm->addSharedShader(new SharedTransparent()); + ssm->addSharedShader(new SharedTexturedQuad()); + ssm->addSharedShader(new SharedColoredQuad()); + ssm->addSharedShader(new SharedSlicedScreenQuad()); + ssm->addSharedShader(new SharedScreenQuad()); + + if (CVS->supportsIndirectInstancingRendering()) + { + ssm->addSharedShader(new SharedInstanced()); + if (CVS->supportsHardwareSkinning()) + ssm->addSharedShader(new SharedInstancedSkinning()); + ssm->addSharedShader(new SharedInstancedPass1()); + ssm->addSharedShader(new SharedInstancedPass2()); + ssm->addSharedShader(new SharedInstancedRefPass1()); + ssm->addSharedShader(new SharedInstancedRefPass2()); + ssm->addSharedShader(new SharedInstancedUnlit()); + ssm->addSharedShader(new SharedInstancedNormal()); + ssm->addSharedShader(new SharedInstancedGrass()); + ssm->addSharedShader(new SharedInstancedGrassPass2()); + if (CVS->isShadowEnabled()) + { + ssm->addSharedShader(new SharedInstancedShadow()); + if (CVS->supportsHardwareSkinning()) + ssm->addSharedShader(new SharedInstancedSkinningShadow()); + } + } + +} //preLoadSharedShaders + #endif // !SERVER_ONLY diff --git a/src/graphics/shader_based_renderer.hpp b/src/graphics/shader_based_renderer.hpp index e5e33752d..e3a97ed88 100644 --- a/src/graphics/shader_based_renderer.hpp +++ b/src/graphics/shader_based_renderer.hpp @@ -85,7 +85,7 @@ private: void debugPhysics(); void renderPostProcessing(Camera * const camera); - + void preloadSharedShaders(); public: ShaderBasedRenderer(); diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index ed8e6c238..f448bd488 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -100,6 +100,7 @@ #include "graphics/gpu_particles.hpp" #include "graphics/irr_driver.hpp" #include "graphics/shared_gpu_objects.hpp" +#include "graphics/shared_shaders.hpp" #include "io/file_manager.hpp" #include "utils/log.hpp" @@ -340,8 +341,8 @@ void Shaders::check(const int num) // Solid Normal and depth pass shaders Shaders::ObjectPass1Shader::ObjectPass1Shader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "object_pass1.frag"); + loadProgram(OBJECT, GET_SS(SharedObject), + GET_SS(SharedPass1)); assignUniforms("ModelMatrix", "InverseModelMatrix"); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // ObjectPass1Shader @@ -350,7 +351,7 @@ Shaders::ObjectPass1Shader::ObjectPass1Shader() // Solid Lit pass shaders Shaders::ObjectPass2Shader::ObjectPass2Shader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + loadProgram(OBJECT, GET_SS(SharedObject), GL_FRAGMENT_SHADER, "object_pass2.frag"); assignUniforms("ModelMatrix", "texture_trans", "color_change"); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, @@ -365,8 +366,8 @@ Shaders::ObjectPass2Shader::ObjectPass2Shader() Shaders::SkinnedTransparentShader::SkinnedTransparentShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", - GL_FRAGMENT_SHADER, "transparent.frag"); + loadProgram(OBJECT, GET_SS(SharedSkinning), + GET_SS(SharedTransparent)); assignUniforms("ModelMatrix", "texture_trans", "skinning_offset", "custom_alpha"); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // SkinnedTransparentShader @@ -374,8 +375,8 @@ Shaders::SkinnedTransparentShader::SkinnedTransparentShader() // ============================================================================ Shaders::TransparentShader::TransparentShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "transparent.frag"); + loadProgram(OBJECT, GET_SS(SharedObject), + GET_SS(SharedTransparent)); assignUniforms("ModelMatrix", "texture_trans", "custom_alpha"); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // TransparentShader @@ -383,7 +384,7 @@ Shaders::TransparentShader::TransparentShader() // ============================================================================ Shaders::TransparentFogShader::TransparentFogShader() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + loadProgram(OBJECT, GET_SS(SharedObject), GL_FRAGMENT_SHADER, "transparentfog.frag"); assignUniforms("ModelMatrix", "texture_trans", "fogmax", "startH", "endH", "start", "end", "col"); @@ -393,9 +394,8 @@ Shaders::TransparentFogShader::TransparentFogShader() // ============================================================================ Shaders::ColoredLine::ColoredLine() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "coloredquad.frag"); - + loadProgram(OBJECT, GET_SS(SharedObject), + GET_SS(SharedColoredQuad)); assignUniforms("color"); glGenVertexArrays(1, &m_vao); diff --git a/src/graphics/shadow_matrices.cpp b/src/graphics/shadow_matrices.cpp index 9ba9f0b6a..c3dc5e51b 100644 --- a/src/graphics/shadow_matrices.cpp +++ b/src/graphics/shadow_matrices.cpp @@ -27,6 +27,7 @@ #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" #include "graphics/shared_gpu_objects.hpp" +#include "graphics/shared_shaders.hpp" #include "modes/world.hpp" #include "physics/triangle_mesh.hpp" #include "tracks/track.hpp" @@ -95,7 +96,7 @@ private: public: ViewFrustrumShader() { loadProgram(OBJECT, GL_VERTEX_SHADER, "frustrum.vert", - GL_FRAGMENT_SHADER, "coloredquad.frag"); + GET_SS(SharedColoredQuad)); assignUniforms("color", "idx"); diff --git a/src/graphics/shared_shader.cpp b/src/graphics/shared_shader.cpp new file mode 100644 index 000000000..238c86b7a --- /dev/null +++ b/src/graphics/shared_shader.cpp @@ -0,0 +1,28 @@ +// 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/shared_shader.hpp" +#include "graphics/shader.hpp" + +void SharedShader::loadSharedShader() +{ + m_shader_id = ShaderBase::loadShader(getName(), getShaderType()); +}; // loadSharedShader + +#endif // !SERVER_ONLY diff --git a/src/graphics/shared_shader.hpp b/src/graphics/shared_shader.hpp new file mode 100644 index 000000000..68a941e4e --- /dev/null +++ b/src/graphics/shared_shader.hpp @@ -0,0 +1,49 @@ +// 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_SHARED_SHADER_HPP +#define HEADER_SHARED_SHADER_HPP + +#include "graphics/gl_headers.hpp" +#include "utils/no_copy.hpp" + +class SharedShader : public NoCopy +{ +private: + GLuint m_shader_id; +public: + // ------------------------------------------------------------------------ + SharedShader() { m_shader_id = 0; } + // ------------------------------------------------------------------------ + virtual ~SharedShader() {} + // ------------------------------------------------------------------------ + GLuint getShaderID() const { return m_shader_id; } + // ------------------------------------------------------------------------ + virtual const char* getName() = 0; + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() = 0; + // ------------------------------------------------------------------------ + void loadSharedShader(); + +}; // SharedShader + +#endif + +#endif // !SERVER_ONLY + diff --git a/src/graphics/shared_shader_manager.hpp b/src/graphics/shared_shader_manager.hpp new file mode 100644 index 000000000..17a8fd45d --- /dev/null +++ b/src/graphics/shared_shader_manager.hpp @@ -0,0 +1,81 @@ +// 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_SHARED_SHADER_MANAGER_HPP +#define HEADER_SHARED_SHADER_MANAGER_HPP + +#include "graphics/shared_shader.hpp" +#include "utils/no_copy.hpp" +#include "utils/singleton.hpp" + +#include +#include +#include +#include + +class SharedShaderManager : public Singleton, NoCopy +{ +private: + std::unordered_map m_shaders_map; + + std::vector m_shared_shaders; + + unsigned int m_shared_shader_loaded; + +public: + // ------------------------------------------------------------------------ + SharedShaderManager() { m_shared_shader_loaded = 0; } + // ------------------------------------------------------------------------ + ~SharedShaderManager() + { + for (SharedShader* ss : m_shared_shaders) + delete ss; + } // ~SharedShaderManager + // ------------------------------------------------------------------------ + template + void addSharedShader(T* ss) + { + ss->loadSharedShader(); + m_shaders_map[std::type_index(typeid(T))] = m_shared_shader_loaded++; + m_shared_shaders.push_back(ss); + } // addSharedShader + // ------------------------------------------------------------------------ + template T* getSharedShader() + { + std::unordered_map::const_iterator i = + m_shaders_map.find(std::type_index(typeid(T))); + if (i != m_shaders_map.end()) + { + T* ss = dynamic_cast(m_shared_shaders[i->second]); + assert(ss != NULL); + return ss; + } + else + { + T* new_ss = new T(); + addSharedShader(new_ss); + return new_ss; + } + } // getSharedShader +}; // SharedShaderManager + +#endif + +#endif // !SERVER_ONLY + diff --git a/src/graphics/shared_shaders.hpp b/src/graphics/shared_shaders.hpp new file mode 100644 index 000000000..98ed601c2 --- /dev/null +++ b/src/graphics/shared_shaders.hpp @@ -0,0 +1,244 @@ +// 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_SHARED_SHADERS_HPP +#define HEADER_SHARED_SHADERS_HPP + +#include "graphics/shared_shader_manager.hpp" +#include "utils/cpp2011.hpp" + +#define GET_SS(SS) SharedShaderManager::getInstance()->getSharedShader() + +// ============================================================================ +// Common shaders: +class SharedObject : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "object_pass.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedObject + +// ============================================================================ +class SharedPass1 : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "object_pass1.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedPass1 + +// ============================================================================ +class SharedSkinning : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "skinning.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedSkinning + +// ============================================================================ +class SharedTransparent : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "transparent.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedTransparent + +// ============================================================================ +class SharedTexturedQuad : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "texturedquad.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedTexturedQuad + +// ============================================================================ +class SharedColoredQuad : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "coloredquad.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedColoredQuad + +// ============================================================================ +class SharedSlicedScreenQuad : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "slicedscreenquad.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedSlicedScreenQuad + +// ============================================================================ +class SharedScreenQuad : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "screenquad.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedScreenQuad + +// ============================================================================ +// Instanced shaders: +class SharedInstanced : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_object_pass.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedInstanced + +// ============================================================================ +class SharedInstancedSkinning : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_skinning.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedInstancedSkinning + +// ============================================================================ +class SharedInstancedPass1 : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_object_pass1.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedPass1 + +// ============================================================================ +class SharedInstancedPass2 : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_object_pass2.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedPass2 + +// ============================================================================ +class SharedInstancedRefPass1 : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_objectref_pass1.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedRefPass1 + +// ============================================================================ +class SharedInstancedRefPass2 : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_objectref_pass2.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedRefPass2 + +// ============================================================================ +class SharedInstancedUnlit : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_object_unlit.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedUnlit + +// ============================================================================ +class SharedInstancedNormal : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_normalmap.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedNormal + +// ============================================================================ +class SharedInstancedGrass : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_grass.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedInstancedGrass + +// ============================================================================ +class SharedInstancedGrassPass2 : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_grass_pass2.frag"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } +}; // SharedInstancedGrassPass2 + +// ============================================================================ +class SharedInstancedShadow : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE { return "instanciedshadow.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedInstancedShadow + +// ============================================================================ +class SharedInstancedSkinningShadow : public SharedShader +{ +public: + // ------------------------------------------------------------------------ + virtual const char* getName() OVERRIDE + { return "instanced_skinning_shadow.vert"; } + // ------------------------------------------------------------------------ + virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } +}; // SharedInstancedSkinningShadow + +#endif + +#endif // !SERVER_ONLY + diff --git a/src/graphics/skybox.cpp b/src/graphics/skybox.cpp index fd1c597b8..0bb22c5ce 100644 --- a/src/graphics/skybox.cpp +++ b/src/graphics/skybox.cpp @@ -21,7 +21,7 @@ #include "graphics/central_settings.hpp" #include "graphics/irr_driver.hpp" #include "graphics/shaders.hpp" - +#include "graphics/shared_shaders.hpp" #include #include @@ -64,7 +64,7 @@ public: GLuint m_tu_samples; SpecularIBLGenerator() { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + loadProgram(OBJECT, GET_SS(SharedScreenQuad), GL_FRAGMENT_SHADER, "importance_sampling_specular.frag"); assignUniforms("PermutationMatrix", "ViewportSize"); m_tu_samples = 1; diff --git a/src/graphics/stk_mesh_scene_node.cpp b/src/graphics/stk_mesh_scene_node.cpp index 7b2c6c0ab..e915e53e4 100644 --- a/src/graphics/stk_mesh_scene_node.cpp +++ b/src/graphics/stk_mesh_scene_node.cpp @@ -24,6 +24,7 @@ #include "graphics/material_manager.hpp" #include "graphics/render_info.hpp" #include "graphics/rtts.hpp" +#include "graphics/shared_shaders.hpp" #include "graphics/stk_mesh.hpp" #include "graphics/texture_manager.hpp" #include "graphics/vao_manager.hpp" @@ -40,7 +41,7 @@ class ColorizeShader : public ShadersetDebugMode(IrrDebugDrawer::DM_NONE); From 7894e5c8642b325c8c8f530ac7f9d74a1cc1f448 Mon Sep 17 00:00:00 2001 From: Benau Date: Sun, 18 Dec 2016 09:27:50 +0800 Subject: [PATCH 031/206] Try to use a smarter approach --- sources.cmake | 2 +- src/graphics/2dutils.cpp | 9 +- src/graphics/irr_driver.cpp | 2 +- src/graphics/lighting_passes.cpp | 21 +-- src/graphics/materials.hpp | 110 +++++------ src/graphics/post_processing.cpp | 47 +++-- src/graphics/shader.hpp | 25 +-- src/graphics/shader_based_renderer.cpp | 42 +---- src/graphics/shader_based_renderer.hpp | 2 +- src/graphics/shaders.cpp | 22 +-- src/graphics/shadow_matrices.cpp | 3 +- src/graphics/shared_shader.cpp | 28 --- src/graphics/shared_shader.hpp | 49 ----- src/graphics/shared_shader_manager.hpp | 81 -------- src/graphics/shared_shaders.hpp | 244 ------------------------- src/graphics/skybox.cpp | 4 +- src/graphics/stk_mesh_scene_node.cpp | 3 +- src/utils/debug.cpp | 6 +- 18 files changed, 116 insertions(+), 584 deletions(-) delete mode 100644 src/graphics/shared_shader.cpp delete mode 100644 src/graphics/shared_shader.hpp delete mode 100644 src/graphics/shared_shader_manager.hpp delete mode 100644 src/graphics/shared_shaders.hpp diff --git a/sources.cmake b/sources.cmake index ba4868d71..d4f28ae4d 100644 --- a/sources.cmake +++ b/sources.cmake @@ -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/*") diff --git a/src/graphics/2dutils.cpp b/src/graphics/2dutils.cpp index 42fab11e0..87bf3a16e 100644 --- a/src/graphics/2dutils.cpp +++ b/src/graphics/2dutils.cpp @@ -24,7 +24,6 @@ #include "graphics/shader.hpp" #include "graphics/shaders.hpp" #include "graphics/shared_gpu_objects.hpp" -#include "graphics/shared_shaders.hpp" #include "graphics/texture_manager.hpp" #include "graphics/texture_shader.hpp" #include "utils/cpp2011.hpp" @@ -44,7 +43,7 @@ public: Primitive2DList() { loadProgram(OBJECT, GL_VERTEX_SHADER, "primitive2dlist.vert", - GET_SS(SharedTransparent)); + GL_FRAGMENT_SHADER, "transparent.frag"); assignUniforms("custom_alpha"); assignSamplerNames(0, "tex", ST_BILINEAR_FILTERED); } // Primitive2DList @@ -59,7 +58,7 @@ class UniformColoredTextureRectShader : public TextureShaderkill(); resetTextureTable(); cleanUnicolorTextures(); @@ -929,7 +930,6 @@ void IrrDriver::applyResolutionSettings() } delete m_renderer; initDevice(); - ShaderBase::updateShaders(); font_manager = new FontManager(); font_manager->loadFonts(); diff --git a/src/graphics/lighting_passes.cpp b/src/graphics/lighting_passes.cpp index cf321c176..55675ed8d 100644 --- a/src/graphics/lighting_passes.cpp +++ b/src/graphics/lighting_passes.cpp @@ -26,8 +26,7 @@ #include "graphics/post_processing.hpp" #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" -#include "graphics/shadow_matrices.hpp" -#include "graphics/shared_shaders.hpp" +#include "graphics/shadow_matrices.hpp" #include "modes/world.hpp" #include "tracks/track.hpp" #include "utils/profiler.hpp" @@ -64,7 +63,7 @@ class FogShader : public TextureShader public: FogShader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "fog.frag"); assignUniforms("density", "col"); assignSamplerNames(0, "tex", ST_NEAREST_FILTERED); @@ -191,12 +190,12 @@ public: { if (CVS->isAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GET_SS(SharedSlicedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert", GL_FRAGMENT_SHADER, "rh.frag"); } else { - loadProgram(OBJECT, GET_SS(SharedSlicedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert", GL_GEOMETRY_SHADER, "rhpassthrough.geom", GL_FRAGMENT_SHADER, "rh.frag"); } @@ -239,7 +238,7 @@ class GlobalIlluminationReconstructionShader public: GlobalIlluminationReconstructionShader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "gi.frag"); assignUniforms("rh_matrix", "inv_rh_matrix", "extents"); @@ -272,7 +271,7 @@ class IBLShader : public TextureShader public: IBLShader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "IBL.frag"); assignUniforms(); assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, @@ -287,7 +286,7 @@ class DegradedIBLShader : public TextureShader public: DegradedIBLShader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "degraded_ibl.frag"); assignUniforms(); assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED); @@ -302,7 +301,7 @@ class ShadowedSunLightShaderPCF : public TextureShader { public: InstancedObjectPass1Shader() { - loadProgram(OBJECT, GET_SS(SharedInstanced), - GET_SS(SharedInstancedPass1)); + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", + GL_FRAGMENT_SHADER, "instanced_object_pass1.frag"); assignUniforms(); assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); @@ -46,8 +46,8 @@ class InstancedObjectRefPass1Shader : public TextureShaderisAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GET_SS(SharedInstancedShadow), + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanciedshadow.vert", GL_FRAGMENT_SHADER, "shadow.frag"); } else { - loadProgram(OBJECT, GET_SS(SharedInstancedShadow), + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanciedshadow.vert", GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "shadow.frag"); } @@ -222,7 +222,7 @@ class SphereMapShader : public TextureShader public: SplattingShader() { - loadProgram(OBJECT, GET_SS(SharedObject), + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", GL_FRAGMENT_SHADER, "splatting.frag"); assignUniforms("ModelMatrix"); @@ -277,7 +277,7 @@ class ObjectRefPass1Shader : public TextureShaderisAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT,GET_SS(SharedInstancedShadow), + loadProgram(OBJECT,GL_VERTEX_SHADER, "instanciedshadow.vert", GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } else { - loadProgram(OBJECT,GET_SS(SharedInstancedShadow), + loadProgram(OBJECT,GL_VERTEX_SHADER, "instanciedshadow.vert", GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } @@ -442,9 +442,9 @@ public: NormalVisualizer() { #if !defined(USE_GLES2) - loadProgram(OBJECT, GET_SS(SharedInstanced), + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", GL_GEOMETRY_SHADER, "normal_visualizer.geom", - GET_SS(SharedColoredQuad)); + GL_FRAGMENT_SHADER, "coloredquad.frag"); assignUniforms("color"); #endif } // NormalVisualizer @@ -473,8 +473,8 @@ class InstancedGrassPass1Shader : public TextureShadersupportsHardwareSkinning()) return; - loadProgram(OBJECT, GET_SS(SharedSkinning), - GET_SS(SharedPass1)); + 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 @@ -640,8 +640,8 @@ public: InstancedSkinnedPass1Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), - GET_SS(SharedInstancedPass1)); + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", + GL_FRAGMENT_SHADER, "instanced_object_pass1.frag"); assignUniforms(); assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // InstancedSkinnedPass1Shader @@ -656,7 +656,7 @@ public: SkinnedPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GET_SS(SharedSkinning), + loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", GL_FRAGMENT_SHADER, "object_pass2.frag"); assignUniforms("ModelMatrix", "texture_trans", "color_change", "skinning_offset"); @@ -676,8 +676,8 @@ public: InstancedSkinnedPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), - GET_SS(SharedInstancedPass2)); + 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, @@ -698,7 +698,7 @@ public: SkinnedRefPass1Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GET_SS(SharedSkinning), + loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", GL_FRAGMENT_SHADER, "objectref_pass1.frag"); assignUniforms("ModelMatrix", "InverseModelMatrix", "texture_trans", "skinning_offset"); @@ -714,8 +714,8 @@ public: InstancedSkinnedRefPass1Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), - GET_SS(SharedInstancedRefPass1)); + 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); @@ -732,7 +732,7 @@ public: SkinnedRefPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GET_SS(SharedSkinning), + loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", GL_FRAGMENT_SHADER, "objectref_pass2.frag"); assignUniforms("ModelMatrix", "texture_trans", "color_change", "skinning_offset"); @@ -752,8 +752,8 @@ public: InstancedSkinnedRefPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), - GET_SS(SharedInstancedRefPass2)); + 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, @@ -773,7 +773,7 @@ public: SkinnedUnlitShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GET_SS(SharedSkinning), + 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, @@ -790,8 +790,8 @@ public: InstancedSkinnedUnlitShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), - GET_SS(SharedInstancedUnlit)); + 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, @@ -809,7 +809,7 @@ public: SkinnedNormalMapShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GET_SS(SharedSkinning), + loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", GL_FRAGMENT_SHADER, "normalmap.frag"); assignUniforms("ModelMatrix", "InverseModelMatrix", "skinning_offset"); assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, @@ -824,8 +824,8 @@ public: InstancedSkinnedNormalMapShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GET_SS(SharedInstancedSkinning), - GET_SS(SharedInstancedNormal)); + 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); @@ -871,12 +871,12 @@ public: return; if (CVS->isAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GET_SS(SharedInstancedSkinningShadow), + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", GL_FRAGMENT_SHADER, "shadow.frag"); } else { - loadProgram(OBJECT, GET_SS(SharedInstancedSkinningShadow), + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "shadow.frag"); } @@ -926,12 +926,12 @@ public: return; if (CVS->isAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GET_SS(SharedInstancedSkinningShadow), + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } else { - loadProgram(OBJECT, GET_SS(SharedInstancedSkinningShadow), + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } diff --git a/src/graphics/post_processing.cpp b/src/graphics/post_processing.cpp index da6e1f8bb..3ba0be240 100644 --- a/src/graphics/post_processing.cpp +++ b/src/graphics/post_processing.cpp @@ -30,7 +30,6 @@ #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" #include "graphics/shared_gpu_objects.hpp" -#include "graphics/shared_shaders.hpp" #include "graphics/stk_mesh_scene_node.hpp" #include "graphics/texture_manager.hpp" #include "graphics/weather.hpp" @@ -57,7 +56,7 @@ class Gaussian3HBlurShader : public TextureShader public: BloomShader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "bloom.frag"); assignUniforms("scale"); assignSamplerNames(0, "tex", ST_NEAREST_FILTERED); @@ -365,7 +364,7 @@ public: if (!lensDustTex) lensDustTex = irr_driver->getTexture(FileManager::TEXTURE, "gfx_lensDust_a.png"); - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "bloomblend.frag"); assignUniforms(); assignSamplerNames(0, "tex_128", ST_BILINEAR_FILTERED, @@ -392,7 +391,7 @@ class LensBlendShader : public TextureShader public: LensBlendShader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "lensblend.frag"); assignUniforms(); @@ -420,7 +419,7 @@ public: ToneMapShader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "tonemap.frag"); assignUniforms("vignette_weight"); assignSamplerNames(0, "text", ST_NEAREST_FILTERED); @@ -440,7 +439,7 @@ class DepthOfFieldShader : public TextureShader public: DepthOfFieldShader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "dof.frag"); assignUniforms(); @@ -482,7 +481,7 @@ class PassThroughShader : public TextureShader public: PassThroughShader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "passthrough.frag"); assignUniforms("width", "height"); assignSamplerNames(0, "tex", ST_BILINEAR_FILTERED); @@ -506,7 +505,7 @@ private: public: LayerPassThroughShader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "layertexturequad.frag"); m_tu_texture = 0; assignUniforms("layer"); @@ -532,7 +531,7 @@ class LinearizeDepthShader : public TextureShader public: SSAOShader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "ssao.frag"); assignUniforms("radius", "k", "sigma"); @@ -606,7 +605,7 @@ class MotionBlurShader : public TextureShader public: GodFadeShader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "godfade.frag"); assignUniforms("col"); assignSamplerNames(0, "tex", ST_BILINEAR_FILTERED); @@ -651,7 +650,7 @@ class GodRayShader : public TextureShader public: GodRayShader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "godray.frag"); assignUniforms("sunpos"); @@ -672,7 +671,7 @@ class MLAAColorEdgeDetectionSHader public: MLAAColorEdgeDetectionSHader() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "mlaa_color1.frag"); assignUniforms("PIXEL_SIZE"); assignSamplerNames(0, "colorMapG", ST_NEAREST_FILTERED); @@ -693,7 +692,7 @@ class MLAABlendWeightSHader : public TextureShader - void loadAndAttachShader(SharedShader* ss, Types ... args) - { - GLint shader_id = ss->getShaderID(); - glAttachShader(m_program, 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 - // ------------------------------------------------------------------------ /** Convenience interface using const char. */ template void loadAndAttachShader(GLint shader_type, const char *name, @@ -103,12 +90,12 @@ protected: } // loadAndAttachShader // ------------------------------------------------------------------------ - static const std::string& getHeader(); + const std::string& getHeader(); + GLuint loadShader(const std::string &file, unsigned type); void setAttribute(AttributeType type); public: ShaderBase(); - static GLuint loadShader(const std::string &file, unsigned type); int loadTFBProgram(const std::string &vertex_file_path, const char **varyings, unsigned varyingscount); @@ -298,13 +285,7 @@ protected: Log::error("shader", filepath); printFileList(args...); } // printFileList - // ------------------------------------------------------------------------ - template - void printFileList(SharedShader* ss, Types ... args) - { - Log::error("shader", ss->getName()); - printFileList(args...); - } // printFileList + // ------------------------------------------------------------------------ /** End recursion for variadic template. */ private: diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index 6253bfb56..4c8e3e278 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -31,7 +31,6 @@ #include "graphics/render_target.hpp" #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" -#include "graphics/shared_shaders.hpp" #include "graphics/skybox.hpp" #include "graphics/spherical_harmonics.hpp" #include "graphics/texture_manager.hpp" @@ -642,8 +641,7 @@ ShaderBasedRenderer::ShaderBasedRenderer() m_skybox = NULL; m_spherical_harmonics = new SphericalHarmonics(irr_driver->getAmbientLight().toSColor()); m_nb_static_glowing = 0; - preloadSharedShaders(); - + if (CVS->isAZDOEnabled()) { m_geometry_passes = new GeometryPasses(); @@ -683,7 +681,6 @@ ShaderBasedRenderer::~ShaderBasedRenderer() delete m_spherical_harmonics; delete m_skybox; delete m_rtts; - SharedShaderManager::kill(); } // ---------------------------------------------------------------------------- @@ -964,41 +961,4 @@ void ShaderBasedRenderer::renderToTexture(GL3RenderTarget *render_target, } //renderToTexture -void ShaderBasedRenderer::preloadSharedShaders() -{ - SharedShaderManager* ssm = SharedShaderManager::getInstance(); - // Common shaders: - ssm->addSharedShader(new SharedObject()); - ssm->addSharedShader(new SharedPass1()); - if (CVS->supportsHardwareSkinning()) - ssm->addSharedShader(new SharedSkinning()); - ssm->addSharedShader(new SharedTransparent()); - ssm->addSharedShader(new SharedTexturedQuad()); - ssm->addSharedShader(new SharedColoredQuad()); - ssm->addSharedShader(new SharedSlicedScreenQuad()); - ssm->addSharedShader(new SharedScreenQuad()); - - if (CVS->supportsIndirectInstancingRendering()) - { - ssm->addSharedShader(new SharedInstanced()); - if (CVS->supportsHardwareSkinning()) - ssm->addSharedShader(new SharedInstancedSkinning()); - ssm->addSharedShader(new SharedInstancedPass1()); - ssm->addSharedShader(new SharedInstancedPass2()); - ssm->addSharedShader(new SharedInstancedRefPass1()); - ssm->addSharedShader(new SharedInstancedRefPass2()); - ssm->addSharedShader(new SharedInstancedUnlit()); - ssm->addSharedShader(new SharedInstancedNormal()); - ssm->addSharedShader(new SharedInstancedGrass()); - ssm->addSharedShader(new SharedInstancedGrassPass2()); - if (CVS->isShadowEnabled()) - { - ssm->addSharedShader(new SharedInstancedShadow()); - if (CVS->supportsHardwareSkinning()) - ssm->addSharedShader(new SharedInstancedSkinningShadow()); - } - } - -} //preLoadSharedShaders - #endif // !SERVER_ONLY diff --git a/src/graphics/shader_based_renderer.hpp b/src/graphics/shader_based_renderer.hpp index e3a97ed88..e5e33752d 100644 --- a/src/graphics/shader_based_renderer.hpp +++ b/src/graphics/shader_based_renderer.hpp @@ -85,7 +85,7 @@ private: void debugPhysics(); void renderPostProcessing(Camera * const camera); - void preloadSharedShaders(); + public: ShaderBasedRenderer(); diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index f448bd488..ed8e6c238 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -100,7 +100,6 @@ #include "graphics/gpu_particles.hpp" #include "graphics/irr_driver.hpp" #include "graphics/shared_gpu_objects.hpp" -#include "graphics/shared_shaders.hpp" #include "io/file_manager.hpp" #include "utils/log.hpp" @@ -341,8 +340,8 @@ void Shaders::check(const int num) // Solid Normal and depth pass shaders Shaders::ObjectPass1Shader::ObjectPass1Shader() { - loadProgram(OBJECT, GET_SS(SharedObject), - GET_SS(SharedPass1)); + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + GL_FRAGMENT_SHADER, "object_pass1.frag"); assignUniforms("ModelMatrix", "InverseModelMatrix"); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // ObjectPass1Shader @@ -351,7 +350,7 @@ Shaders::ObjectPass1Shader::ObjectPass1Shader() // Solid Lit pass shaders Shaders::ObjectPass2Shader::ObjectPass2Shader() { - loadProgram(OBJECT, GET_SS(SharedObject), + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", GL_FRAGMENT_SHADER, "object_pass2.frag"); assignUniforms("ModelMatrix", "texture_trans", "color_change"); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, @@ -366,8 +365,8 @@ Shaders::ObjectPass2Shader::ObjectPass2Shader() Shaders::SkinnedTransparentShader::SkinnedTransparentShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GET_SS(SharedSkinning), - GET_SS(SharedTransparent)); + 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 @@ -375,8 +374,8 @@ Shaders::SkinnedTransparentShader::SkinnedTransparentShader() // ============================================================================ Shaders::TransparentShader::TransparentShader() { - loadProgram(OBJECT, GET_SS(SharedObject), - GET_SS(SharedTransparent)); + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + GL_FRAGMENT_SHADER, "transparent.frag"); assignUniforms("ModelMatrix", "texture_trans", "custom_alpha"); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // TransparentShader @@ -384,7 +383,7 @@ Shaders::TransparentShader::TransparentShader() // ============================================================================ Shaders::TransparentFogShader::TransparentFogShader() { - loadProgram(OBJECT, GET_SS(SharedObject), + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", GL_FRAGMENT_SHADER, "transparentfog.frag"); assignUniforms("ModelMatrix", "texture_trans", "fogmax", "startH", "endH", "start", "end", "col"); @@ -394,8 +393,9 @@ Shaders::TransparentFogShader::TransparentFogShader() // ============================================================================ Shaders::ColoredLine::ColoredLine() { - loadProgram(OBJECT, GET_SS(SharedObject), - GET_SS(SharedColoredQuad)); + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + GL_FRAGMENT_SHADER, "coloredquad.frag"); + assignUniforms("color"); glGenVertexArrays(1, &m_vao); diff --git a/src/graphics/shadow_matrices.cpp b/src/graphics/shadow_matrices.cpp index c3dc5e51b..9ba9f0b6a 100644 --- a/src/graphics/shadow_matrices.cpp +++ b/src/graphics/shadow_matrices.cpp @@ -27,7 +27,6 @@ #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" #include "graphics/shared_gpu_objects.hpp" -#include "graphics/shared_shaders.hpp" #include "modes/world.hpp" #include "physics/triangle_mesh.hpp" #include "tracks/track.hpp" @@ -96,7 +95,7 @@ private: public: ViewFrustrumShader() { loadProgram(OBJECT, GL_VERTEX_SHADER, "frustrum.vert", - GET_SS(SharedColoredQuad)); + GL_FRAGMENT_SHADER, "coloredquad.frag"); assignUniforms("color", "idx"); diff --git a/src/graphics/shared_shader.cpp b/src/graphics/shared_shader.cpp deleted file mode 100644 index 238c86b7a..000000000 --- a/src/graphics/shared_shader.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// 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/shared_shader.hpp" -#include "graphics/shader.hpp" - -void SharedShader::loadSharedShader() -{ - m_shader_id = ShaderBase::loadShader(getName(), getShaderType()); -}; // loadSharedShader - -#endif // !SERVER_ONLY diff --git a/src/graphics/shared_shader.hpp b/src/graphics/shared_shader.hpp deleted file mode 100644 index 68a941e4e..000000000 --- a/src/graphics/shared_shader.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// 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_SHARED_SHADER_HPP -#define HEADER_SHARED_SHADER_HPP - -#include "graphics/gl_headers.hpp" -#include "utils/no_copy.hpp" - -class SharedShader : public NoCopy -{ -private: - GLuint m_shader_id; -public: - // ------------------------------------------------------------------------ - SharedShader() { m_shader_id = 0; } - // ------------------------------------------------------------------------ - virtual ~SharedShader() {} - // ------------------------------------------------------------------------ - GLuint getShaderID() const { return m_shader_id; } - // ------------------------------------------------------------------------ - virtual const char* getName() = 0; - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() = 0; - // ------------------------------------------------------------------------ - void loadSharedShader(); - -}; // SharedShader - -#endif - -#endif // !SERVER_ONLY - diff --git a/src/graphics/shared_shader_manager.hpp b/src/graphics/shared_shader_manager.hpp deleted file mode 100644 index 17a8fd45d..000000000 --- a/src/graphics/shared_shader_manager.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// 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_SHARED_SHADER_MANAGER_HPP -#define HEADER_SHARED_SHADER_MANAGER_HPP - -#include "graphics/shared_shader.hpp" -#include "utils/no_copy.hpp" -#include "utils/singleton.hpp" - -#include -#include -#include -#include - -class SharedShaderManager : public Singleton, NoCopy -{ -private: - std::unordered_map m_shaders_map; - - std::vector m_shared_shaders; - - unsigned int m_shared_shader_loaded; - -public: - // ------------------------------------------------------------------------ - SharedShaderManager() { m_shared_shader_loaded = 0; } - // ------------------------------------------------------------------------ - ~SharedShaderManager() - { - for (SharedShader* ss : m_shared_shaders) - delete ss; - } // ~SharedShaderManager - // ------------------------------------------------------------------------ - template - void addSharedShader(T* ss) - { - ss->loadSharedShader(); - m_shaders_map[std::type_index(typeid(T))] = m_shared_shader_loaded++; - m_shared_shaders.push_back(ss); - } // addSharedShader - // ------------------------------------------------------------------------ - template T* getSharedShader() - { - std::unordered_map::const_iterator i = - m_shaders_map.find(std::type_index(typeid(T))); - if (i != m_shaders_map.end()) - { - T* ss = dynamic_cast(m_shared_shaders[i->second]); - assert(ss != NULL); - return ss; - } - else - { - T* new_ss = new T(); - addSharedShader(new_ss); - return new_ss; - } - } // getSharedShader -}; // SharedShaderManager - -#endif - -#endif // !SERVER_ONLY - diff --git a/src/graphics/shared_shaders.hpp b/src/graphics/shared_shaders.hpp deleted file mode 100644 index 98ed601c2..000000000 --- a/src/graphics/shared_shaders.hpp +++ /dev/null @@ -1,244 +0,0 @@ -// 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_SHARED_SHADERS_HPP -#define HEADER_SHARED_SHADERS_HPP - -#include "graphics/shared_shader_manager.hpp" -#include "utils/cpp2011.hpp" - -#define GET_SS(SS) SharedShaderManager::getInstance()->getSharedShader() - -// ============================================================================ -// Common shaders: -class SharedObject : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE { return "object_pass.vert"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } -}; // SharedObject - -// ============================================================================ -class SharedPass1 : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE { return "object_pass1.frag"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } -}; // SharedPass1 - -// ============================================================================ -class SharedSkinning : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE { return "skinning.vert"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } -}; // SharedSkinning - -// ============================================================================ -class SharedTransparent : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE { return "transparent.frag"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } -}; // SharedTransparent - -// ============================================================================ -class SharedTexturedQuad : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE { return "texturedquad.vert"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } -}; // SharedTexturedQuad - -// ============================================================================ -class SharedColoredQuad : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE { return "coloredquad.frag"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } -}; // SharedColoredQuad - -// ============================================================================ -class SharedSlicedScreenQuad : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE { return "slicedscreenquad.vert"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } -}; // SharedSlicedScreenQuad - -// ============================================================================ -class SharedScreenQuad : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE { return "screenquad.vert"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } -}; // SharedScreenQuad - -// ============================================================================ -// Instanced shaders: -class SharedInstanced : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE - { return "instanced_object_pass.vert"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } -}; // SharedInstanced - -// ============================================================================ -class SharedInstancedSkinning : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE - { return "instanced_skinning.vert"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } -}; // SharedInstancedSkinning - -// ============================================================================ -class SharedInstancedPass1 : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE - { return "instanced_object_pass1.frag"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } -}; // SharedInstancedPass1 - -// ============================================================================ -class SharedInstancedPass2 : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE - { return "instanced_object_pass2.frag"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } -}; // SharedInstancedPass2 - -// ============================================================================ -class SharedInstancedRefPass1 : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE - { return "instanced_objectref_pass1.frag"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } -}; // SharedInstancedRefPass1 - -// ============================================================================ -class SharedInstancedRefPass2 : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE - { return "instanced_objectref_pass2.frag"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } -}; // SharedInstancedRefPass2 - -// ============================================================================ -class SharedInstancedUnlit : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE - { return "instanced_object_unlit.frag"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } -}; // SharedInstancedUnlit - -// ============================================================================ -class SharedInstancedNormal : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE - { return "instanced_normalmap.frag"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } -}; // SharedInstancedNormal - -// ============================================================================ -class SharedInstancedGrass : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE - { return "instanced_grass.vert"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } -}; // SharedInstancedGrass - -// ============================================================================ -class SharedInstancedGrassPass2 : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE - { return "instanced_grass_pass2.frag"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_FRAGMENT_SHADER; } -}; // SharedInstancedGrassPass2 - -// ============================================================================ -class SharedInstancedShadow : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE { return "instanciedshadow.vert"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } -}; // SharedInstancedShadow - -// ============================================================================ -class SharedInstancedSkinningShadow : public SharedShader -{ -public: - // ------------------------------------------------------------------------ - virtual const char* getName() OVERRIDE - { return "instanced_skinning_shadow.vert"; } - // ------------------------------------------------------------------------ - virtual unsigned getShaderType() OVERRIDE { return GL_VERTEX_SHADER; } -}; // SharedInstancedSkinningShadow - -#endif - -#endif // !SERVER_ONLY - diff --git a/src/graphics/skybox.cpp b/src/graphics/skybox.cpp index 0bb22c5ce..fd1c597b8 100644 --- a/src/graphics/skybox.cpp +++ b/src/graphics/skybox.cpp @@ -21,7 +21,7 @@ #include "graphics/central_settings.hpp" #include "graphics/irr_driver.hpp" #include "graphics/shaders.hpp" -#include "graphics/shared_shaders.hpp" + #include #include @@ -64,7 +64,7 @@ public: GLuint m_tu_samples; SpecularIBLGenerator() { - loadProgram(OBJECT, GET_SS(SharedScreenQuad), + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "importance_sampling_specular.frag"); assignUniforms("PermutationMatrix", "ViewportSize"); m_tu_samples = 1; diff --git a/src/graphics/stk_mesh_scene_node.cpp b/src/graphics/stk_mesh_scene_node.cpp index e915e53e4..7b2c6c0ab 100644 --- a/src/graphics/stk_mesh_scene_node.cpp +++ b/src/graphics/stk_mesh_scene_node.cpp @@ -24,7 +24,6 @@ #include "graphics/material_manager.hpp" #include "graphics/render_info.hpp" #include "graphics/rtts.hpp" -#include "graphics/shared_shaders.hpp" #include "graphics/stk_mesh.hpp" #include "graphics/texture_manager.hpp" #include "graphics/vao_manager.hpp" @@ -41,7 +40,7 @@ class ColorizeShader : public ShadersetDebugMode(IrrDebugDrawer::DM_NONE); From 2a9656bfdc995ad177067ba0e2a754f914dbddaa Mon Sep 17 00:00:00 2001 From: Benau Date: Sun, 18 Dec 2016 10:51:05 +0800 Subject: [PATCH 032/206] Allow all shader files to be loaded only once Todo: preload --- sources.cmake | 2 +- src/graphics/irr_driver.cpp | 2 +- src/graphics/shader.cpp | 184 +------------------- src/graphics/shader.hpp | 19 +-- src/graphics/shader_based_renderer.cpp | 1 + src/graphics/shader_files_manager.cpp | 228 +++++++++++++++++++++++++ src/graphics/shader_files_manager.hpp | 59 +++++++ src/graphics/shaders.cpp | 63 ------- src/utils/debug.cpp | 5 +- 9 files changed, 301 insertions(+), 262 deletions(-) create mode 100644 src/graphics/shader_files_manager.cpp create mode 100644 src/graphics/shader_files_manager.hpp diff --git a/sources.cmake b/sources.cmake index d4f28ae4d..ba4868d71 100644 --- a/sources.cmake +++ b/sources.cmake @@ -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/*") diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 6b92b20c5..909420162 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -919,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(); @@ -930,6 +929,7 @@ void IrrDriver::applyResolutionSettings() } delete m_renderer; initDevice(); + ShaderBase::updateShaders(); font_manager = new FontManager(); font_manager->loadFonts(); diff --git a/src/graphics/shader.cpp b/src/graphics/shader.cpp index f2f704978..2383cab50 100644 --- a/src/graphics/shader.cpp +++ b/src/graphics/shader.cpp @@ -19,198 +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 #include #include -std::string ShaderBase::m_shader_header = ""; std::vector 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 << "#define MAX_BONES " << SharedGPUObjects::getMaxMat4Size() << "\n"; - - 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. @@ -239,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; } diff --git a/src/graphics/shader.hpp b/src/graphics/shader.hpp index 8e6ab5e93..ac4bd5e2a 100644 --- a/src/graphics/shader.hpp +++ b/src/graphics/shader.hpp @@ -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 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: diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index 4c8e3e278..512f74b6f 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -681,6 +681,7 @@ ShaderBasedRenderer::~ShaderBasedRenderer() delete m_spherical_harmonics; delete m_skybox; delete m_rtts; + ShaderFilesManager::kill(); } // ---------------------------------------------------------------------------- diff --git a/src/graphics/shader_files_manager.cpp b/src/graphics/shader_files_manager.cpp new file mode 100644 index 000000000..9b4adb40a --- /dev/null +++ b/src/graphics/shader_files_manager.cpp @@ -0,0 +1,228 @@ +// 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 +#include + +std::string ShaderFilesManager::m_shader_header = ""; + +// ---------------------------------------------------------------------------- +/** Returns a string with the content of header.txt (which contains basic + * shader defines). + */ +const std::string& ShaderFilesManager::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 file, and add it to the loaded list + * \param file Filename of the shader to load. + * \param type Type of the shader. + */ +GLuint ShaderFilesManager::addShaderFile(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 << "#define MAX_BONES " << SharedGPUObjects::getMaxMat4Size() << "\n"; + + 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("ShaderFilesManager", "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("ShaderFilesManager", "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("ShaderFilesManager", "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("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) + { + 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(); + m_shader_files_loaded[file] = id; + return id; + +} // addShaderFile + +// ---------------------------------------------------------------------------- +GLuint ShaderFilesManager::getShaderFile(const std::string &file, + unsigned type) +{ + std::unordered_map::const_iterator i = + m_shader_files_loaded.find(file); + if (i != m_shader_files_loaded.end()) + return i->second; + else + return addShaderFile(file, type); + +} // getShaderFile + +#endif // !SERVER_ONLY diff --git a/src/graphics/shader_files_manager.hpp b/src/graphics/shader_files_manager.hpp new file mode 100644 index 000000000..9fbba938b --- /dev/null +++ b/src/graphics/shader_files_manager.hpp @@ -0,0 +1,59 @@ +// 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 +#include +#include + +class ShaderFilesManager : public Singleton, NoCopy +{ +private: + /** Stores the context of header.txt, to avoid reading + * this file repeatedly. */ + static std::string m_shader_header; + + std::unordered_map m_shader_files_loaded; + + // ------------------------------------------------------------------------ + const std::string& getHeader(); + +public: + // ------------------------------------------------------------------------ + ShaderFilesManager() {} + // ------------------------------------------------------------------------ + ~ShaderFilesManager() { clean(); } + // ------------------------------------------------------------------------ + void clean() { m_shader_files_loaded.clear(); } + // ------------------------------------------------------------------------ + GLuint addShaderFile(const std::string &file, unsigned type); + // ------------------------------------------------------------------------ + GLuint getShaderFile(const std::string &file, unsigned type); + +}; // ShaderFilesManager + +#endif + +#endif // !SERVER_ONLY diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index ed8e6c238..d00b06dbc 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -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() { diff --git a/src/utils/debug.cpp b/src/utils/debug.cpp index 0d7e351d1..6b4468ef1 100644 --- a/src/utils/debug.cpp +++ b/src/utils/debug.cpp @@ -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); From 7ea4f3082462fa302e6a83fa3dc31b69146f80f2 Mon Sep 17 00:00:00 2001 From: Benau Date: Sun, 18 Dec 2016 13:49:58 +0800 Subject: [PATCH 033/206] Make sure no duplicated shader is added somewhere else --- src/graphics/shader.hpp | 4 ++-- src/graphics/shader_files_manager.cpp | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/graphics/shader.hpp b/src/graphics/shader.hpp index ac4bd5e2a..46ab6fcf6 100644 --- a/src/graphics/shader.hpp +++ b/src/graphics/shader.hpp @@ -356,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 diff --git a/src/graphics/shader_files_manager.cpp b/src/graphics/shader_files_manager.cpp index 9b4adb40a..37de97c5d 100644 --- a/src/graphics/shader_files_manager.cpp +++ b/src/graphics/shader_files_manager.cpp @@ -59,6 +59,13 @@ const std::string& ShaderFilesManager::getHeader() GLuint ShaderFilesManager::addShaderFile(const std::string &file, unsigned type) { +#ifdef DEBUG + // Make sure no duplicated shader is added somewhere else + std::unordered_map::const_iterator i = + m_shader_files_loaded.find(file); + assert(i == m_shader_files_loaded.end()); +#endif + GLuint id = glCreateShader(type); std::ostringstream code; @@ -214,7 +221,7 @@ GLuint ShaderFilesManager::addShaderFile(const std::string &file, // ---------------------------------------------------------------------------- GLuint ShaderFilesManager::getShaderFile(const std::string &file, - unsigned type) + unsigned type) { std::unordered_map::const_iterator i = m_shader_files_loaded.find(file); From 4477dbb0fbc56ea5b7c94ce24062e1d087a7e665 Mon Sep 17 00:00:00 2001 From: Benau Date: Sun, 18 Dec 2016 14:51:27 +0800 Subject: [PATCH 034/206] Preload shaders that delay kart selection screen the most Plus some suggestion from #1787 --- src/graphics/shader_based_renderer.cpp | 62 +++++++++++++++++++++++++- src/graphics/shader_based_renderer.hpp | 2 +- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index 512f74b6f..b2275ad04 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -641,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(); @@ -657,7 +659,7 @@ ShaderBasedRenderer::ShaderBasedRenderer() m_geometry_passes = new GeometryPasses(); Log::info("ShaderBasedRenderer", "Geometry will be rendered with GL3 policy."); } - + m_post_processing = new PostProcessing(irr_driver->getVideoDriver()); } @@ -962,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 diff --git a/src/graphics/shader_based_renderer.hpp b/src/graphics/shader_based_renderer.hpp index e5e33752d..125e14be1 100644 --- a/src/graphics/shader_based_renderer.hpp +++ b/src/graphics/shader_based_renderer.hpp @@ -85,7 +85,7 @@ private: void debugPhysics(); void renderPostProcessing(Camera * const camera); - + void preloadShaderFiles(); public: ShaderBasedRenderer(); From 4f2e2331ee9981c097533387715a2961e3345226 Mon Sep 17 00:00:00 2001 From: Benau Date: Sun, 18 Dec 2016 14:59:37 +0800 Subject: [PATCH 035/206] Correct the spelling of shader files --- ...edgrassshadow.vert => instanced_grassshadow.vert} | 0 .../{instanciedshadow.vert => instanced_shadow.vert} | 0 src/graphics/materials.hpp | 12 ++++++------ 3 files changed, 6 insertions(+), 6 deletions(-) rename data/shaders/{instanciedgrassshadow.vert => instanced_grassshadow.vert} (100%) rename data/shaders/{instanciedshadow.vert => instanced_shadow.vert} (100%) diff --git a/data/shaders/instanciedgrassshadow.vert b/data/shaders/instanced_grassshadow.vert similarity index 100% rename from data/shaders/instanciedgrassshadow.vert rename to data/shaders/instanced_grassshadow.vert diff --git a/data/shaders/instanciedshadow.vert b/data/shaders/instanced_shadow.vert similarity index 100% rename from data/shaders/instanciedshadow.vert rename to data/shaders/instanced_shadow.vert diff --git a/src/graphics/materials.hpp b/src/graphics/materials.hpp index 239a97ad1..aa5805af4 100644 --- a/src/graphics/materials.hpp +++ b/src/graphics/materials.hpp @@ -150,12 +150,12 @@ public: 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"); } @@ -390,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"); } @@ -522,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"); } From d0229cd85ec42f0c39061e0c1b23f3a910b6dbcc Mon Sep 17 00:00:00 2001 From: Daniel Butum Date: Sun, 18 Dec 2016 13:30:49 +0200 Subject: [PATCH 036/206] Separate the non-cached shader loading in ShaderFilesManager --- src/graphics/shader_files_manager.cpp | 92 ++++++++++++++++----------- src/graphics/shader_files_manager.hpp | 9 +-- 2 files changed, 60 insertions(+), 41 deletions(-) diff --git a/src/graphics/shader_files_manager.cpp b/src/graphics/shader_files_manager.cpp index 37de97c5d..01c32b28e 100644 --- a/src/graphics/shader_files_manager.cpp +++ b/src/graphics/shader_files_manager.cpp @@ -26,47 +26,39 @@ #include #include -std::string ShaderFilesManager::m_shader_header = ""; - // ---------------------------------------------------------------------------- /** 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 (m_shader_header.empty()) + if (shader_header.empty()) { - std::ifstream stream(file_manager->getShader("header.txt"), - std::ios::in); + 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; + while (std::getline(stream, line)) + shader_header += "\n" + line; stream.close(); } - } // if m_shader_header.empty() + } // if shader_header.empty() - return m_shader_header; + return shader_header; } // getHeader // ---------------------------------------------------------------------------- -/** Loads a single shader file, and add it to the loaded list +/** 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::addShaderFile(const std::string &file, - unsigned type) +GLuint ShaderFilesManager::loadShader(const std::string &file, unsigned type) { -#ifdef DEBUG - // Make sure no duplicated shader is added somewhere else - std::unordered_map::const_iterator i = - m_shader_files_loaded.find(file); - assert(i == m_shader_files_loaded.end()); -#endif - - GLuint id = glCreateShader(type); + const GLuint id = glCreateShader(type); std::ostringstream code; #if !defined(USE_GLES2) @@ -134,13 +126,17 @@ GLuint ShaderFilesManager::addShaderFile(const std::string &file, 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::string line; + + while (std::getline(stream, line)) { - const std::string stk_include = "#stk_include"; - std::size_t pos = line.find(stk_include); + 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) { @@ -151,6 +147,7 @@ GLuint ShaderFilesManager::addShaderFile(const std::string &file, std::string filename = line.substr(pos + 1); + // find the end " pos = filename.find("\""); if (pos == std::string::npos) { @@ -161,8 +158,8 @@ GLuint ShaderFilesManager::addShaderFile(const std::string &file, filename = filename.substr(0, pos); - std::ifstream include_stream(file_manager->getShader(filename), - std::ios::in); + // 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" @@ -171,7 +168,7 @@ GLuint ShaderFilesManager::addShaderFile(const std::string &file, } std::string include_line = ""; - while (getline(include_stream, include_line)) + while (std::getline(include_stream, include_line)) { code << "\n" << include_line; } @@ -201,6 +198,7 @@ GLuint ShaderFilesManager::addShaderFile(const std::string &file, 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); @@ -212,24 +210,44 @@ GLuint ShaderFilesManager::addShaderFile(const std::string &file, 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::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 // ---------------------------------------------------------------------------- -GLuint ShaderFilesManager::getShaderFile(const std::string &file, - unsigned type) +/** 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) { - std::unordered_map::const_iterator i = - m_shader_files_loaded.find(file); - if (i != m_shader_files_loaded.end()) - return i->second; - else - return addShaderFile(file, 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 diff --git a/src/graphics/shader_files_manager.hpp b/src/graphics/shader_files_manager.hpp index 9fbba938b..aa11d90a0 100644 --- a/src/graphics/shader_files_manager.hpp +++ b/src/graphics/shader_files_manager.hpp @@ -31,10 +31,9 @@ class ShaderFilesManager : public Singleton, NoCopy { private: - /** Stores the context of header.txt, to avoid reading - * this file repeatedly. */ - static std::string m_shader_header; - + /** + * Map from a filename to a shader indentifier. Used for caching shaders. + */ std::unordered_map m_shader_files_loaded; // ------------------------------------------------------------------------ @@ -48,6 +47,8 @@ public: // ------------------------------------------------------------------------ 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); From 581ca964fdf583d7a3f8c167c72b82c19940ea52 Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 19 Dec 2016 11:06:05 +0800 Subject: [PATCH 037/206] Fix hats with hardware skinning --- src/graphics/stk_animated_mesh.cpp | 11 ++++++++++- src/graphics/stk_animated_mesh.hpp | 1 + src/karts/kart_model.cpp | 11 ++++++++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp index 75af0fc74..16e14d78e 100644 --- a/src/graphics/stk_animated_mesh.cpp +++ b/src/graphics/stk_animated_mesh.cpp @@ -336,7 +336,7 @@ void STKAnimatedMesh::resetSkinningState(scene::IAnimatedMesh* mesh) { if (!CVS->supportsHardwareSkinning()) return; m_skinning_offset = -1; - m_skinned_mesh = dynamic_cast(mesh); + setHardwareSkinning(true); if (m_skinned_mesh) m_skinned_mesh->convertForSkinning(); } @@ -353,6 +353,15 @@ scene::IMesh* STKAnimatedMesh::getMeshForCurrentFrame(SkinningCallback sc, (uploadJoints, m_skinning_offset); } +void STKAnimatedMesh::setHardwareSkinning(bool val) +{ + if (!CVS->supportsHardwareSkinning()) return; + if (val) + m_skinned_mesh = dynamic_cast(Mesh); + else + m_skinned_mesh = NULL; +} + void STKAnimatedMesh::uploadJoints(const irr::core::matrix4& m, int joint, int offset) { diff --git a/src/graphics/stk_animated_mesh.hpp b/src/graphics/stk_animated_mesh.hpp index f86ec69fc..42884bc9d 100644 --- a/src/graphics/stk_animated_mesh.hpp +++ b/src/graphics/stk_animated_mesh.hpp @@ -59,6 +59,7 @@ public: 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 diff --git a/src/karts/kart_model.cpp b/src/karts/kart_model.cpp index ca143e3f4..413dc1fb3 100644 --- a/src/karts/kart_model.cpp +++ b/src/karts/kart_model.cpp @@ -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" @@ -1027,7 +1028,15 @@ 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); + STKAnimatedMesh* am = dynamic_cast(m_animated_node); + if (am) + { + am->setHardwareSkinning(false); + am->OnAnimate(0); + am->setHardwareSkinning(true); + } + else + 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 From c26f8150f49936c6037090d321e251fd94abb63b Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 19 Dec 2016 11:17:45 +0800 Subject: [PATCH 038/206] Fix server only build --- src/karts/kart_model.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/karts/kart_model.cpp b/src/karts/kart_model.cpp index 413dc1fb3..cfdfcc531 100644 --- a/src/karts/kart_model.cpp +++ b/src/karts/kart_model.cpp @@ -1028,6 +1028,7 @@ 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]); +#ifndef SERVER_ONLY STKAnimatedMesh* am = dynamic_cast(m_animated_node); if (am) { @@ -1036,6 +1037,7 @@ void KartModel::attachHat() am->setHardwareSkinning(true); } else +#endif m_animated_node->OnAnimate(0); bone->updateAbsolutePosition(); // With the hat node attached to the head bone, we have to From 082661db651e55164d87e769adf397e7fc655e6d Mon Sep 17 00:00:00 2001 From: Deve Date: Tue, 20 Dec 2016 22:44:36 +0100 Subject: [PATCH 039/206] Add a possibility to change touch device settings in GUI --- data/gui/multitouch_settings.stkgui | 52 ++++++++ .../dialogs/multitouch_settings_dialog.cpp | 112 ++++++++++++++++++ .../dialogs/multitouch_settings_dialog.hpp | 46 +++++++ src/states_screens/options_screen_input.cpp | 25 +++- 4 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 data/gui/multitouch_settings.stkgui create mode 100644 src/states_screens/dialogs/multitouch_settings_dialog.cpp create mode 100644 src/states_screens/dialogs/multitouch_settings_dialog.hpp diff --git a/data/gui/multitouch_settings.stkgui b/data/gui/multitouch_settings.stkgui new file mode 100644 index 000000000..77e05cd40 --- /dev/null +++ b/data/gui/multitouch_settings.stkgui @@ -0,0 +1,52 @@ + + +
+
+ + + +
+
diff --git a/src/states_screens/dialogs/multitouch_settings_dialog.cpp b/src/states_screens/dialogs/multitouch_settings_dialog.cpp new file mode 100644 index 000000000..f163b5614 --- /dev/null +++ b/src/states_screens/dialogs/multitouch_settings_dialog.cpp @@ -0,0 +1,112 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2014-2015 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. + +#include "states_screens/dialogs/multitouch_settings_dialog.hpp" + +#include "config/user_config.hpp" +#include "guiengine/widgets/spinner_widget.hpp" +#include "utils/translation.hpp" + +#include + + +using namespace GUIEngine; +using namespace irr; +using namespace irr::core; +using namespace irr::gui; + +// ----------------------------------------------------------------------------- + +MultitouchSettingsDialog::MultitouchSettingsDialog(const float w, const float h) + : ModalDialog(w, h) +{ + loadFromFile("multitouch_settings.stkgui"); +} + +// ----------------------------------------------------------------------------- + +MultitouchSettingsDialog::~MultitouchSettingsDialog() +{ +} + +// ----------------------------------------------------------------------------- + +void MultitouchSettingsDialog::beforeAddingWidgets() +{ + updateValues(); +} + +// ----------------------------------------------------------------------------- + +GUIEngine::EventPropagation MultitouchSettingsDialog::processEvent( + const std::string& eventSource) +{ + if (eventSource == "close") + { + SpinnerWidget* scale = getWidget("scale"); + assert(scale != NULL); + UserConfigParams::m_multitouch_scale = scale->getValue() / 100.0f; + + SpinnerWidget* deadzone_edge = getWidget("deadzone_edge"); + assert(deadzone_edge != NULL); + UserConfigParams::m_multitouch_deadzone_edge = + deadzone_edge->getValue() / 100.0f; + + SpinnerWidget* deadzone_center = getWidget("deadzone_center"); + assert(deadzone_center != NULL); + UserConfigParams::m_multitouch_deadzone_center = + deadzone_center->getValue() / 100.0f; + + user_config->saveConfig(); + + ModalDialog::dismiss(); + return GUIEngine::EVENT_BLOCK; + } + else if (eventSource == "restore") + { + UserConfigParams::m_multitouch_scale.revertToDefaults(); + UserConfigParams::m_multitouch_deadzone_edge.revertToDefaults(); + UserConfigParams::m_multitouch_deadzone_center.revertToDefaults(); + + updateValues(); + + return GUIEngine::EVENT_BLOCK; + } + + return GUIEngine::EVENT_LET; +} // processEvent + +// ----------------------------------------------------------------------------- + +void MultitouchSettingsDialog::updateValues() +{ + SpinnerWidget* scale = getWidget("scale"); + assert(scale != NULL); + scale->setValue((int)(UserConfigParams::m_multitouch_scale * 100.0f)); + + SpinnerWidget* deadzone_edge = getWidget("deadzone_edge"); + assert(deadzone_edge != NULL); + deadzone_edge->setValue( + (int)(UserConfigParams::m_multitouch_deadzone_edge * 100.0f)); + + SpinnerWidget* deadzone_center = getWidget("deadzone_center"); + assert(deadzone_center != NULL); + deadzone_center->setValue( + (int)(UserConfigParams::m_multitouch_deadzone_center * 100.0f)); +} + +// ----------------------------------------------------------------------------- diff --git a/src/states_screens/dialogs/multitouch_settings_dialog.hpp b/src/states_screens/dialogs/multitouch_settings_dialog.hpp new file mode 100644 index 000000000..0bc4c485a --- /dev/null +++ b/src/states_screens/dialogs/multitouch_settings_dialog.hpp @@ -0,0 +1,46 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2014-2015 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 HEADER_MULTITOUCH_SETTINGS_DIALOG_HPP +#define HEADER_MULTITOUCH_SETTINGS_DIALOG_HPP + +#include "guiengine/modaldialog.hpp" + +/** + * \brief Dialog that allows the player to adjust multitouch steering settings + * \ingroup states_screens + */ +class MultitouchSettingsDialog : public GUIEngine::ModalDialog +{ +private: + void updateValues(); + +public: + /** + * Creates a modal dialog with given percentage of screen width and height + */ + MultitouchSettingsDialog(const float percentWidth, const float percentHeight); + ~MultitouchSettingsDialog(); + + virtual void beforeAddingWidgets(); + + GUIEngine::EventPropagation processEvent(const std::string& eventSource); + +}; + +#endif diff --git a/src/states_screens/options_screen_input.cpp b/src/states_screens/options_screen_input.cpp index 17bbde76e..e8728fdd7 100644 --- a/src/states_screens/options_screen_input.cpp +++ b/src/states_screens/options_screen_input.cpp @@ -33,6 +33,7 @@ #include "states_screens/options_screen_video.hpp" #include "states_screens/options_screen_ui.hpp" #include "states_screens/dialogs/add_device_dialog.hpp" +#include "states_screens/dialogs/multitouch_settings_dialog.hpp" #include "states_screens/state_manager.hpp" #include "states_screens/user_screen.hpp" #include "utils/string_utils.hpp" @@ -81,8 +82,10 @@ void OptionsScreenInput::buildDeviceList() assert( m_icon_bank != NULL ); devices->setIcons(m_icon_bank); + + DeviceManager* device_manager = input_manager->getDeviceManager(); - const int keyboard_config_count = input_manager->getDeviceManager()->getKeyboardConfigAmount(); + const int keyboard_config_count = device_manager->getKeyboardConfigAmount(); for (int i=0; iaddItem(internal_name, (core::stringw(" ") + _("Keyboard %i", i)).c_str(), 0 /* icon */); } - const int gpad_config_count = input_manager->getDeviceManager()->getGamePadConfigAmount(); + const int gpad_config_count = device_manager->getGamePadConfigAmount(); for (int i = 0; i < gpad_config_count; i++) { - GamepadConfig *config = input_manager->getDeviceManager()->getGamepadConfig(i); + GamepadConfig *config = device_manager->getGamepadConfig(i); // Don't display the configuration if a matching device is not available if (config->isPlugged()) @@ -126,6 +129,13 @@ void OptionsScreenInput::buildDeviceList() devices->addItem(internal_name, name, icon); } // if config->isPlugged } // for igetMultitouchDevice(); + + if (touch_device != NULL) + { + devices->addItem("touch_device", " Touch device", 1); + } } // buildDeviceList // ----------------------------------------------------------------------------- @@ -252,6 +262,15 @@ void OptionsScreenInput::eventCallback(Widget* widget, const std::string& name, selection.c_str()); } } + else if (selection.find("touch_device") != std::string::npos) + { + // Don't edit multitouch settings during a race, because it needs + // to re-create all buttons to take an effect + if (StateManager::get()->getGameState() != GUIEngine::INGAME_MENU) + { + new MultitouchSettingsDialog(0.8f, 0.9f); + } + } else { Log::error("OptionsScreenInput", "Cannot read internal input device ID: %s", selection.c_str()); From 53ee40af70976ea028d58af9b8d1f091e7f6e03c Mon Sep 17 00:00:00 2001 From: Deve Date: Tue, 20 Dec 2016 23:05:26 +0100 Subject: [PATCH 040/206] Update multitouch device when settings are changed --- src/input/multitouch_device.cpp | 18 +++++++++++++----- src/input/multitouch_device.hpp | 2 ++ .../dialogs/multitouch_settings_dialog.cpp | 17 ++++++++++++++--- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/input/multitouch_device.cpp b/src/input/multitouch_device.cpp index 3e06d10fd..a27072170 100644 --- a/src/input/multitouch_device.cpp +++ b/src/input/multitouch_device.cpp @@ -44,11 +44,7 @@ MultitouchDevice::MultitouchDevice() event.y = 0; } - m_deadzone_center = UserConfigParams::m_multitouch_deadzone_center; - m_deadzone_center = std::min(std::max(m_deadzone_center, 0.0f), 0.5f); - - m_deadzone_edge = UserConfigParams::m_multitouch_deadzone_edge; - m_deadzone_edge = std::min(std::max(m_deadzone_edge, 0.0f), 0.5f); + updateConfigParams(); } // MultitouchDevice // ---------------------------------------------------------------------------- @@ -225,6 +221,18 @@ void MultitouchDevice::updateDeviceState(unsigned int event_id) } } // updateDeviceState +// ---------------------------------------------------------------------------- +/** Updates config parameters i.e. when they are modified in options + */ +void MultitouchDevice::updateConfigParams() +{ + m_deadzone_center = UserConfigParams::m_multitouch_deadzone_center; + m_deadzone_center = std::min(std::max(m_deadzone_center, 0.0f), 0.5f); + + m_deadzone_edge = UserConfigParams::m_multitouch_deadzone_edge; + m_deadzone_edge = std::min(std::max(m_deadzone_edge, 0.0f), 0.5f); +} // updateConfigParams + // ---------------------------------------------------------------------------- /** Helper function that returns a steering factor for steering button. * \param value The axis value from 0 to 1. diff --git a/src/input/multitouch_device.hpp b/src/input/multitouch_device.hpp index eb32b5720..580554dbf 100644 --- a/src/input/multitouch_device.hpp +++ b/src/input/multitouch_device.hpp @@ -107,6 +107,8 @@ public: void updateDeviceState(unsigned int event_id); void handleControls(MultitouchButton* button); + + void updateConfigParams(); }; // MultitouchDevice diff --git a/src/states_screens/dialogs/multitouch_settings_dialog.cpp b/src/states_screens/dialogs/multitouch_settings_dialog.cpp index f163b5614..3df12258c 100644 --- a/src/states_screens/dialogs/multitouch_settings_dialog.cpp +++ b/src/states_screens/dialogs/multitouch_settings_dialog.cpp @@ -19,6 +19,9 @@ #include "config/user_config.hpp" #include "guiengine/widgets/spinner_widget.hpp" +#include "input/device_manager.hpp" +#include "input/input_manager.hpp" +#include "input/multitouch_device.hpp" #include "utils/translation.hpp" #include @@ -59,18 +62,26 @@ GUIEngine::EventPropagation MultitouchSettingsDialog::processEvent( { SpinnerWidget* scale = getWidget("scale"); assert(scale != NULL); - UserConfigParams::m_multitouch_scale = scale->getValue() / 100.0f; + UserConfigParams::m_multitouch_scale = (float)scale->getValue() / 100.0f; SpinnerWidget* deadzone_edge = getWidget("deadzone_edge"); assert(deadzone_edge != NULL); UserConfigParams::m_multitouch_deadzone_edge = - deadzone_edge->getValue() / 100.0f; + (float)deadzone_edge->getValue() / 100.0f; SpinnerWidget* deadzone_center = getWidget("deadzone_center"); assert(deadzone_center != NULL); UserConfigParams::m_multitouch_deadzone_center = - deadzone_center->getValue() / 100.0f; + (float)deadzone_center->getValue() / 100.0f; + MultitouchDevice* touch_device = input_manager->getDeviceManager()-> + getMultitouchDevice(); + + if (touch_device != NULL) + { + touch_device->updateConfigParams(); + } + user_config->saveConfig(); ModalDialog::dismiss(); From bfd57659eb40ec2dcccb49af9f02922b211a60a6 Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 22 Dec 2016 11:17:52 +0800 Subject: [PATCH 041/206] Remove unused file --- sources.cmake | 4 +- src/graphics/stk_scene_manager.cpp | 67 ------------------------------ src/graphics/stk_scene_manager.hpp | 37 ----------------- 3 files changed, 2 insertions(+), 106 deletions(-) delete mode 100644 src/graphics/stk_scene_manager.cpp delete mode 100644 src/graphics/stk_scene_manager.hpp diff --git a/sources.cmake b/sources.cmake index 0ed51e3ff..d4f28ae4d 100644 --- a/sources.cmake +++ b/sources.cmake @@ -1,6 +1,6 @@ # 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/*") -file(GLOB_RECURSE STK_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${PROJECT_BINARY_DIR}/tmp/*.rc") +file(GLOB_RECURSE STK_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${PROJECT_BINARY_DIR}/tmp/*.rc") diff --git a/src/graphics/stk_scene_manager.cpp b/src/graphics/stk_scene_manager.cpp deleted file mode 100644 index b26181ab8..000000000 --- a/src/graphics/stk_scene_manager.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// SuperTuxKart - a fun racing game with go-kart -// Copyright (C) 2014-2015 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/stk_scene_manager.hpp" -#include -#include - -using namespace irr; - -// From irrlicht code -static -bool isBoxInFrontOfPlane(const core::plane3df &plane, const core::vector3df edges[8]) -{ - for (u32 j = 0; j<8; ++j) - if (plane.classifyPointRelation(edges[j]) != core::ISREL3D_FRONT) - return false; - return true; -} - -std::vector BoundingBoxes; - -void addEdge(const core::vector3df &P0, const core::vector3df &P1) -{ - BoundingBoxes.push_back(P0.X); - BoundingBoxes.push_back(P0.Y); - BoundingBoxes.push_back(P0.Z); - BoundingBoxes.push_back(P1.X); - BoundingBoxes.push_back(P1.Y); - BoundingBoxes.push_back(P1.Z); -} - -bool isCulledPrecise(const scene::ICameraSceneNode *cam, const scene::ISceneNode *node) -{ - if (!node->getAutomaticCulling()) - return false; - - const core::matrix4 &trans = node->getAbsoluteTransformation(); - const scene::SViewFrustum &frust = *cam->getViewFrustum(); - - core::vector3df edges[8]; - node->getBoundingBox().getEdges(edges); - for (unsigned i = 0; i < 8; i++) - trans.transformVect(edges[i]); - - for (s32 i = 0; i < scene::SViewFrustum::VF_PLANE_COUNT; ++i) - if (isBoxInFrontOfPlane(frust.planes[i], edges)) - return true; - return false; -} - -#endif // !SERVER_ONLY diff --git a/src/graphics/stk_scene_manager.hpp b/src/graphics/stk_scene_manager.hpp deleted file mode 100644 index 8fc984b6a..000000000 --- a/src/graphics/stk_scene_manager.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// SuperTuxKart - a fun racing game with go-kart -// Copyright (C) 2014-2015 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. - - -// Not really a scene manager yet but hold algorithm that -// rework scene manager output - -#ifndef SERVER_ONLY - -#ifndef HEADER_STKSCENEMANAGER_HPP -#define HEADER_STKSCENEMANAGER_HPP - -#include -#include -#include - -void addEdge(const irr::core::vector3df &P0, const irr::core::vector3df &P1); - -bool isCulledPrecise(const irr::scene::ICameraSceneNode *cam, const irr::scene::ISceneNode *node); - -#endif - -#endif // supertuxkart From 28841d601d51f31be5317517828ef2c0be042fd4 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 23 Dec 2016 00:44:26 +0800 Subject: [PATCH 042/206] Remove old code for getting straight frame With hardware skinning it is not necessary --- src/graphics/irr_driver.cpp | 6 ++---- src/graphics/irr_driver.hpp | 3 +-- src/graphics/stk_mesh_scene_node.cpp | 17 +++-------------- src/graphics/stk_mesh_scene_node.hpp | 4 +--- src/karts/kart_model.cpp | 13 ++++--------- 5 files changed, 11 insertions(+), 32 deletions(-) diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 909420162..7b2013a7f 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -1228,8 +1228,7 @@ scene::IMeshSceneNode *IrrDriver::addMesh(scene::IMesh *mesh, const std::string& debug_name, scene::ISceneNode *parent, RenderInfo* render_info, - bool all_parts_colorized, - int frame_for_mesh) + bool all_parts_colorized) { #ifdef SERVER_ONLY return m_scene_manager->addMeshSceneNode(mesh, parent); @@ -1247,8 +1246,7 @@ scene::IMeshSceneNode *IrrDriver::addMesh(scene::IMesh *mesh, core::vector3df(0, 0, 0), core::vector3df(1.0f, 1.0f, 1.0f), true, render_info, - all_parts_colorized, - frame_for_mesh); + all_parts_colorized); node->drop(); return node; diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index a7d7bf17e..250db4fc3 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -255,8 +255,7 @@ public: const std::string& debug_name, scene::ISceneNode *parent = NULL, RenderInfo* render_info = NULL, - bool all_parts_colorized = false, - int frame_for_mesh = -1); + bool all_parts_colorized = false); PerCameraNode *addPerCameraNode(scene::ISceneNode* node, scene::ICameraSceneNode* cam, scene::ISceneNode *parent = NULL); diff --git a/src/graphics/stk_mesh_scene_node.cpp b/src/graphics/stk_mesh_scene_node.cpp index e734b5c2b..77ffe2233 100644 --- a/src/graphics/stk_mesh_scene_node.cpp +++ b/src/graphics/stk_mesh_scene_node.cpp @@ -52,14 +52,12 @@ STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::s32 id, const std::string& debug_name, const irr::core::vector3df& position, const irr::core::vector3df& rotation, - const irr::core::vector3df& scale, bool createGLMeshes, RenderInfo* render_info, bool all_parts_colorized, - int frame_for_mesh) : + const irr::core::vector3df& scale, bool createGLMeshes, RenderInfo* render_info, bool all_parts_colorized) : CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale) { isDisplacement = false; immediate_draw = false; update_each_frame = false; - m_frame_for_mesh = frame_for_mesh; isGlow = false; m_got_animated_matrix = false; @@ -262,18 +260,9 @@ void STKMeshSceneNode::updateGL() { if (isGLInitialized) return; - - scene::IAnimatedMesh* am = dynamic_cast(Mesh); - scene::IMesh* m = Mesh; - if (am && m_frame_for_mesh > -1) + for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) { - // Get the correct frame of animation for animated mesh - m = am->getMesh(m_frame_for_mesh); - } - - for (u32 i = 0; i < m->getMeshBufferCount(); ++i) - { - scene::IMeshBuffer* mb = m->getMeshBuffer(i); + scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); if (!mb) continue; GLMesh &mesh = GLmeshes[i]; diff --git a/src/graphics/stk_mesh_scene_node.hpp b/src/graphics/stk_mesh_scene_node.hpp index 5275217f3..ef4da1556 100644 --- a/src/graphics/stk_mesh_scene_node.hpp +++ b/src/graphics/stk_mesh_scene_node.hpp @@ -29,7 +29,6 @@ class STKMeshSceneNode : public irr::scene::CMeshSceneNode, public STKMeshCommon { protected: PtrVector m_static_render_info; - int m_frame_for_mesh; bool m_got_animated_matrix; std::vector GLmeshes; core::matrix4 ModelViewProjectionMatrix; @@ -60,8 +59,7 @@ public: const irr::core::vector3df& rotation = irr::core::vector3df(0, 0, 0), const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f), bool createGLMeshes = true, - RenderInfo* render_info = NULL, bool all_parts_colorized = false, - int frame_for_mesh = -1); + RenderInfo* render_info = NULL, bool all_parts_colorized = false); virtual void render(); virtual void setMesh(irr::scene::IMesh* mesh); virtual void OnRegisterSceneNode(); diff --git a/src/karts/kart_model.cpp b/src/karts/kart_model.cpp index cfdfcc531..c0544df05 100644 --- a/src/karts/kart_model.cpp +++ b/src/karts/kart_model.cpp @@ -427,21 +427,16 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models, bool always_anim : 0; scene::IMesh* main_frame = m_mesh; -#ifndef SERVER_ONLY - if (!CVS->isGLSL()) - { - main_frame = m_mesh->getMesh(straight_frame); - main_frame->setHardwareMappingHint(scene::EHM_STATIC); - } -#endif + main_frame = m_mesh->getMesh(straight_frame); + main_frame->setHardwareMappingHint(scene::EHM_STATIC); std::string debug_name; #ifdef DEBUG - debug_name = m_model_filename + " (kart-model)"; + debug_name = m_model_filename + " (kart-model)"; #endif node = irr_driver->addMesh(main_frame, debug_name, - NULL /*parent*/, getRenderInfo(), false, straight_frame); + NULL /*parent*/, getRenderInfo()); #ifdef DEBUG node->setName(debug_name.c_str()); From 8008ec851eb448274b03d06e00bee2c537448b42 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 23 Dec 2016 01:31:13 +0800 Subject: [PATCH 043/206] Allow to use hardware skinning with opengl 3.1 Now we only need UBO to store the joint matrices to support it --- data/shaders/instanced_skinning.vert | 16 +++++++++ data/shaders/instanced_skinning_shadow.vert | 11 ++++++ data/shaders/skinning.vert | 10 ++++++ data/shaders/skinning_shadow.vert | 7 ++++ src/graphics/central_settings.cpp | 2 +- src/graphics/materials.hpp | 40 ++++++++++----------- src/graphics/shader.cpp | 15 ++++++++ src/graphics/shader.hpp | 1 + src/graphics/shaders.cpp | 2 +- 9 files changed, 82 insertions(+), 22 deletions(-) diff --git a/data/shaders/instanced_skinning.vert b/data/shaders/instanced_skinning.vert index 49a029361..c8e192143 100644 --- a/data/shaders/instanced_skinning.vert +++ b/data/shaders/instanced_skinning.vert @@ -1,3 +1,4 @@ +#if __VERSION__ >= 330 layout(location = 0) in vec3 Position; layout(location = 1) in vec3 Normal; layout(location = 2) in vec4 Color; @@ -17,6 +18,21 @@ layout(location = 13) in sampler2D ThirdHandle; layout(location = 14) in sampler2D FourthHandle; #endif layout(location = 15) in int skinning_offset; +#else +in vec3 Position; +in vec3 Normal; +in vec4 Color; +in vec4 Data1; +in vec4 Data2; +in ivec4 Joint; +in vec4 Weight; + +in vec3 Origin; +in vec3 Orientation; +in vec3 Scale; +in vec4 misc_data; +in int skinning_offset; +#endif out vec3 nor; out vec3 tangent; diff --git a/data/shaders/instanced_skinning_shadow.vert b/data/shaders/instanced_skinning_shadow.vert index 2d2542e1e..21e4a5294 100644 --- a/data/shaders/instanced_skinning_shadow.vert +++ b/data/shaders/instanced_skinning_shadow.vert @@ -1,5 +1,6 @@ uniform int layer; +#if __VERSION__ >= 330 layout(location = 0) in vec3 Position; layout(location = 3) in vec4 Data1; layout(location = 5) in ivec4 Joint; @@ -11,6 +12,16 @@ layout(location = 9) in vec3 Scale; layout(location = 11) in uvec2 Handle; #endif layout(location = 15) in int skinning_offset; +#else +in vec3 Position; +in vec4 Data1; +in ivec4 Joint; +in vec4 Weight; +in vec3 Origin; +in vec3 Orientation; +in vec3 Scale; +in int skinning_offset; +#endif #ifdef VSLayer out vec2 uv; diff --git a/data/shaders/skinning.vert b/data/shaders/skinning.vert index e64ec294d..2652fc10e 100644 --- a/data/shaders/skinning.vert +++ b/data/shaders/skinning.vert @@ -18,6 +18,7 @@ uniform vec2 texture_trans = vec2(0., 0.); #endif uniform int skinning_offset; +#if __VERSION__ >= 330 layout(location = 0) in vec3 Position; layout(location = 1) in vec3 Normal; layout(location = 2) in vec4 Color; @@ -25,6 +26,15 @@ layout(location = 3) in vec4 Data1; layout(location = 4) in vec4 Data2; layout(location = 5) in ivec4 Joint; layout(location = 6) in vec4 Weight; +#else +in vec3 Position; +in vec3 Normal; +in vec4 Color; +in vec4 Data1; +in vec4 Data2; +in ivec4 Joint; +in vec4 Weight; +#endif out vec3 nor; out vec3 tangent; diff --git a/data/shaders/skinning_shadow.vert b/data/shaders/skinning_shadow.vert index 6fc5d35c8..6e8d8fb3b 100644 --- a/data/shaders/skinning_shadow.vert +++ b/data/shaders/skinning_shadow.vert @@ -2,10 +2,17 @@ uniform mat4 ModelMatrix; uniform int skinning_offset; uniform int layer; +#if __VERSION__ >= 330 layout(location = 0) in vec3 Position; layout(location = 3) in vec4 Data1; layout(location = 5) in ivec4 Joint; layout(location = 6) in vec4 Weight; +#else +in vec3 Position; +in vec4 Data1; +in ivec4 Joint; +in vec4 Weight; +#endif #ifdef VSLayer out vec2 uv; diff --git a/src/graphics/central_settings.cpp b/src/graphics/central_settings.cpp index cea030f3f..56a267260 100644 --- a/src/graphics/central_settings.cpp +++ b/src/graphics/central_settings.cpp @@ -446,6 +446,6 @@ bool CentralVideoSettings::isDefferedEnabled() const bool CentralVideoSettings::supportsHardwareSkinning() const { - return isARBUniformBufferObjectUsable() && isARBExplicitAttribLocationUsable() && getGLSLVersion() >= 330; + return isARBUniformBufferObjectUsable(); } #endif // !SERVER_ONLY diff --git a/src/graphics/materials.hpp b/src/graphics/materials.hpp index aa5805af4..7845a1654 100644 --- a/src/graphics/materials.hpp +++ b/src/graphics/materials.hpp @@ -626,7 +626,7 @@ public: SkinnedPass1Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning.vert", GL_FRAGMENT_SHADER, "object_pass1.frag"); assignUniforms("ModelMatrix", "InverseModelMatrix", "skinning_offset"); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); @@ -640,7 +640,7 @@ public: InstancedSkinnedPass1Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning.vert", GL_FRAGMENT_SHADER, "instanced_object_pass1.frag"); assignUniforms(); assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); @@ -656,7 +656,7 @@ public: SkinnedPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning.vert", GL_FRAGMENT_SHADER, "object_pass2.frag"); assignUniforms("ModelMatrix", "texture_trans", "color_change", "skinning_offset"); @@ -676,7 +676,7 @@ public: InstancedSkinnedPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning.vert", GL_FRAGMENT_SHADER, "instanced_object_pass2.frag"); assignUniforms(); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, @@ -698,7 +698,7 @@ public: SkinnedRefPass1Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning.vert", GL_FRAGMENT_SHADER, "objectref_pass1.frag"); assignUniforms("ModelMatrix", "InverseModelMatrix", "texture_trans", "skinning_offset"); @@ -714,7 +714,7 @@ public: InstancedSkinnedRefPass1Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning.vert", GL_FRAGMENT_SHADER, "instanced_objectref_pass1.frag"); assignUniforms(); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED, @@ -732,7 +732,7 @@ public: SkinnedRefPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning.vert", GL_FRAGMENT_SHADER, "objectref_pass2.frag"); assignUniforms("ModelMatrix", "texture_trans", "color_change", "skinning_offset"); @@ -752,7 +752,7 @@ public: InstancedSkinnedRefPass2Shader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning.vert", GL_FRAGMENT_SHADER, "instanced_objectref_pass2.frag"); assignUniforms(); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, @@ -773,7 +773,7 @@ public: SkinnedUnlitShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning.vert", GL_FRAGMENT_SHADER, "object_unlit.frag"); assignUniforms("ModelMatrix", "texture_trans", "skinning_offset"); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, @@ -790,7 +790,7 @@ public: InstancedSkinnedUnlitShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning.vert", GL_FRAGMENT_SHADER, "instanced_object_unlit.frag"); assignUniforms(); assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, @@ -809,7 +809,7 @@ public: SkinnedNormalMapShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning.vert", GL_FRAGMENT_SHADER, "normalmap.frag"); assignUniforms("ModelMatrix", "InverseModelMatrix", "skinning_offset"); assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, @@ -824,7 +824,7 @@ public: InstancedSkinnedNormalMapShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning.vert", GL_FRAGMENT_SHADER, "instanced_normalmap.frag"); assignUniforms(); assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, @@ -845,12 +845,12 @@ public: return; if (CVS->isAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning_shadow.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning_shadow.vert", GL_FRAGMENT_SHADER, "shadow.frag"); } else { - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning_shadow.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning_shadow.vert", GL_GEOMETRY_SHADER, "shadow.geom", GL_FRAGMENT_SHADER, "shadow.frag"); } @@ -871,12 +871,12 @@ public: return; if (CVS->isAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", GL_FRAGMENT_SHADER, "shadow.frag"); } else { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "shadow.frag"); } @@ -898,12 +898,12 @@ public: return; if (CVS->isAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning_shadow.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning_shadow.vert", GL_FRAGMENT_SHADER, "shadowref.frag"); } else { - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning_shadow.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning_shadow.vert", GL_GEOMETRY_SHADER, "shadow.geom", GL_FRAGMENT_SHADER, "shadowref.frag"); } @@ -926,12 +926,12 @@ public: return; if (CVS->isAMDVertexShaderLayerUsable()) { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } else { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", GL_GEOMETRY_SHADER, "instanced_shadow.geom", GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); } diff --git a/src/graphics/shader.cpp b/src/graphics/shader.cpp index 2383cab50..ec3ac239e 100644 --- a/src/graphics/shader.cpp +++ b/src/graphics/shader.cpp @@ -142,6 +142,7 @@ void ShaderBase::setAttribute(AttributeType type) glBindAttribLocation(m_program, 7, "Origin"); glBindAttribLocation(m_program, 8, "Orientation"); glBindAttribLocation(m_program, 9, "Scale"); + glBindAttribLocation(m_program, 10, "misc_data"); break; case PARTICLES_SIM: glBindAttribLocation(m_program, 0, "particle_position"); @@ -160,6 +161,20 @@ void ShaderBase::setAttribute(AttributeType type) glBindAttribLocation(m_program, 5, "rotationvec"); glBindAttribLocation(m_program, 6, "anglespeed"); break; + case SKINNED_MESH: + glBindAttribLocation(m_program, 0, "Position"); + glBindAttribLocation(m_program, 1, "Normal"); + glBindAttribLocation(m_program, 2, "Color"); + glBindAttribLocation(m_program, 3, "Data1"); + glBindAttribLocation(m_program, 4, "Data2"); + glBindAttribLocation(m_program, 5, "Joint"); + glBindAttribLocation(m_program, 6, "Weight"); + glBindAttribLocation(m_program, 7, "Origin"); + glBindAttribLocation(m_program, 8, "Orientation"); + glBindAttribLocation(m_program, 9, "Scale"); + glBindAttribLocation(m_program, 10, "misc_data"); + glBindAttribLocation(m_program, 15, "skinning_offset"); + break; } } // setAttribute diff --git a/src/graphics/shader.hpp b/src/graphics/shader.hpp index 46ab6fcf6..7df252576 100644 --- a/src/graphics/shader.hpp +++ b/src/graphics/shader.hpp @@ -50,6 +50,7 @@ protected: OBJECT, PARTICLES_SIM, PARTICLES_RENDERING, + SKINNED_MESH, }; // AttributeType /** OpenGL's program id. */ diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index d00b06dbc..5c623d329 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -302,7 +302,7 @@ Shaders::ObjectPass2Shader::ObjectPass2Shader() Shaders::SkinnedTransparentShader::SkinnedTransparentShader() { if (!CVS->supportsHardwareSkinning()) return; - loadProgram(OBJECT, GL_VERTEX_SHADER, "skinning.vert", + loadProgram(SKINNED_MESH, 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); From 6fb93fa20833e3fa1cc03f93eb523b3d5d8ec562 Mon Sep 17 00:00:00 2001 From: Tobias Markus Date: Fri, 23 Dec 2016 01:17:31 +0100 Subject: [PATCH 044/206] Fix compilation on macOS 10.12 (#2701) --- lib/irrlicht/source/Irrlicht/MacOSX/CIrrDeviceMacOSX.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/irrlicht/source/Irrlicht/MacOSX/CIrrDeviceMacOSX.mm b/lib/irrlicht/source/Irrlicht/MacOSX/CIrrDeviceMacOSX.mm index 3550ab9ec..73845c9c7 100644 --- a/lib/irrlicht/source/Irrlicht/MacOSX/CIrrDeviceMacOSX.mm +++ b/lib/irrlicht/source/Irrlicht/MacOSX/CIrrDeviceMacOSX.mm @@ -719,7 +719,7 @@ bool CIrrDeviceMacOSX::createWindow() if (!CreationParams.WindowId) { [Window center]; - [(NSFileManager *)Window setDelegate:[NSApp delegate]]; + [(NSFileManager *)Window setDelegate:[(NSFileManager *)NSApp delegate]]; if(CreationParams.DriverType == video::EDT_OPENGL) [OGLContext setView:[Window contentView]]; From 969592e3fc93686933645c56e85fa7beca819669 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 23 Dec 2016 09:19:46 +0800 Subject: [PATCH 045/206] Try to fix framerate drop after few laps Because skidmark left are never culled --- src/graphics/draw_calls.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index dab61bce0..9f305f313 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -180,7 +180,8 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, if (node->isImmediateDraw()) { - ImmediateDraw->push_back(Node); + if (!isCulledPrecise(cam, Node, irr_driver->getBoundingBoxesViz())) + ImmediateDraw->push_back(Node); return; } From a339975df66f69d20fbec3caa5d1a4ad6d44c2cd Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 23 Dec 2016 10:08:12 +0800 Subject: [PATCH 046/206] Clean skidmark earlier if there are many karts --- data/stk_config.xml | 6 ++++-- src/graphics/skid_marks.cpp | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/data/stk_config.xml b/data/stk_config.xml index 8b2259340..b1f30d3e6 100644 --- a/data/stk_config.xml +++ b/data/stk_config.xml @@ -72,8 +72,10 @@ delta-angle="0.5" /> - + time for skidmarks to fade out. Maximum number will over + current number of karts, so the more karts, the less + skidmark is on track. --> + diff --git a/src/graphics/skid_marks.cpp b/src/graphics/skid_marks.cpp index 22b6b493a..9843bb0e7 100644 --- a/src/graphics/skid_marks.cpp +++ b/src/graphics/skid_marks.cpp @@ -25,6 +25,7 @@ #include "karts/controller/controller.hpp" #include "karts/abstract_kart.hpp" #include "karts/skidding.hpp" +#include "modes/world.hpp" #include "physics/btKart.hpp" #include @@ -208,7 +209,9 @@ void SkidMarks::update(float dt, bool force_skid_marks, // The scene node will keep the mesh alive. new_mesh->drop(); m_current++; - if(m_current>=stk_config->m_max_skidmarks) + int cleaning_threshold = + core::clamp(int(World::getWorld()->getNumKarts()), 5, 15); + if(m_current>=int(stk_config->m_max_skidmarks/cleaning_threshold)) m_current = 0; if(m_current>=(int)m_left.size()) { From f7e2122b790b4ca7d262eca4f2ed436e977d72d9 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 23 Dec 2016 10:36:35 +0800 Subject: [PATCH 047/206] Allow drawing instanced glow color without explicit location --- data/shaders/glow_object.vert | 19 ++++++++++--------- src/graphics/draw_policies.cpp | 7 +------ src/graphics/vao_manager.cpp | 6 +++--- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/data/shaders/glow_object.vert b/data/shaders/glow_object.vert index e7b7cddab..78cd0279a 100644 --- a/data/shaders/glow_object.vert +++ b/data/shaders/glow_object.vert @@ -1,15 +1,16 @@ +#if __VERSION__ >= 330 layout(location = 0) in vec3 Position; -layout(location = 1) in vec3 Normal; -layout(location = 2) in vec4 Color; -layout(location = 3) in vec2 Texcoord; -layout(location = 5) in vec3 Tangent; -layout(location = 6) in vec3 Bitangent; - layout(location = 7) in vec3 Origin; layout(location = 8) in vec3 Orientation; layout(location = 9) in vec3 Scale; -layout(location = 15) in vec4 GlowColor; - +layout(location = 10) in vec4 misc_data; +#else +in vec3 Position; +in vec3 Origin; +in vec3 Orientation; +in vec3 Scale; +in vec4 misc_data; +#endif flat out vec4 glowColor; #stk_include "utils/getworldmatrix.vert" @@ -19,5 +20,5 @@ void main(void) mat4 ModelMatrix = getWorldMatrix(Origin, Orientation, Scale); mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin, Orientation, Scale) * InverseViewMatrix); gl_Position = ProjectionViewMatrix * ModelMatrix * vec4(Position, 1.); - glowColor = GlowColor; + glowColor = misc_data; } diff --git a/src/graphics/draw_policies.cpp b/src/graphics/draw_policies.cpp index 3595d212d..210f82a51 100644 --- a/src/graphics/draw_policies.cpp +++ b/src/graphics/draw_policies.cpp @@ -288,12 +288,7 @@ void IndirectDrawPolicy::drawGlow(const DrawCalls& draw_calls, const std::vector& glows) const { #if !defined(USE_GLES2) - //to draw Glow with indirect commands, we also need GL_ARB_explicit_attrib_location extension - //TODO: add a way to render glow without explicit attrib - if(CVS->isARBExplicitAttribLocationUsable()) - { - draw_calls.drawIndirectGlow(); - } + draw_calls.drawIndirectGlow(); #endif // !defined(USE_GLES2) } diff --git a/src/graphics/vao_manager.cpp b/src/graphics/vao_manager.cpp index 0a9914284..969f55e9d 100644 --- a/src/graphics/vao_manager.cpp +++ b/src/graphics/vao_manager.cpp @@ -217,9 +217,9 @@ template<> void VAOInstanceUtil::SetVertexAttrib() { SetVertexAttrib_impl(); - glEnableVertexAttribArray(15); - glVertexAttribPointer(15, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GlowInstanceData), (GLvoid*)(9 * sizeof(float))); - glVertexAttribDivisorARB(15, 1); + glEnableVertexAttribArray(10); + glVertexAttribPointer(10, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GlowInstanceData), (GLvoid*)(9 * sizeof(float))); + glVertexAttribDivisorARB(10, 1); } From d932451295dc88ea7096946a8a025a1e72259387 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 23 Dec 2016 11:33:48 +0800 Subject: [PATCH 048/206] Don't out a interpolated color change It will should be determined by colorization mask in fragment shader --- data/shaders/instanced_grass.vert | 2 +- data/shaders/instanced_grass_pass2.frag | 2 +- data/shaders/instanced_object_pass.vert | 2 +- data/shaders/instanced_object_pass2.frag | 2 +- data/shaders/instanced_objectref_pass2.frag | 2 +- data/shaders/instanced_skinning.vert | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/data/shaders/instanced_grass.vert b/data/shaders/instanced_grass.vert index 76088f23e..dcfba88a5 100644 --- a/data/shaders/instanced_grass.vert +++ b/data/shaders/instanced_grass.vert @@ -30,7 +30,7 @@ in vec4 misc_data; out vec3 nor; out vec2 uv; -out vec2 color_change; +flat out vec2 color_change; #ifdef Use_Bindless_Texture flat out sampler2D handle; flat out sampler2D secondhandle; diff --git a/data/shaders/instanced_grass_pass2.frag b/data/shaders/instanced_grass_pass2.frag index 4d69593f0..6ba698f7b 100644 --- a/data/shaders/instanced_grass_pass2.frag +++ b/data/shaders/instanced_grass_pass2.frag @@ -14,7 +14,7 @@ flat in sampler2D thirdhandle; #endif in vec3 nor; in vec2 uv; -in vec2 color_change; +flat in vec2 color_change; out vec4 FragColor; #stk_include "utils/getLightFactor.frag" diff --git a/data/shaders/instanced_object_pass.vert b/data/shaders/instanced_object_pass.vert index e92bb1490..de0befb04 100644 --- a/data/shaders/instanced_object_pass.vert +++ b/data/shaders/instanced_object_pass.vert @@ -39,7 +39,7 @@ out vec3 bitangent; out vec2 uv; out vec2 uv_bis; out vec4 color; -out vec2 color_change; +flat out vec2 color_change; #ifdef Use_Bindless_Texture flat out sampler2D handle; flat out sampler2D secondhandle; diff --git a/data/shaders/instanced_object_pass2.frag b/data/shaders/instanced_object_pass2.frag index 120f3e21a..38198e916 100644 --- a/data/shaders/instanced_object_pass2.frag +++ b/data/shaders/instanced_object_pass2.frag @@ -12,7 +12,7 @@ flat in sampler2D thirdhandle; in vec2 uv; in vec4 color; -in vec2 color_change; +flat in vec2 color_change; out vec4 FragColor; #stk_include "utils/getLightFactor.frag" diff --git a/data/shaders/instanced_objectref_pass2.frag b/data/shaders/instanced_objectref_pass2.frag index a3e75b026..4d3aae883 100644 --- a/data/shaders/instanced_objectref_pass2.frag +++ b/data/shaders/instanced_objectref_pass2.frag @@ -11,7 +11,7 @@ flat in sampler2D thirdhandle; #endif in vec2 uv; in vec4 color; -in vec2 color_change; +flat in vec2 color_change; out vec4 FragColor; #stk_include "utils/getLightFactor.frag" diff --git a/data/shaders/instanced_skinning.vert b/data/shaders/instanced_skinning.vert index c8e192143..6802642a4 100644 --- a/data/shaders/instanced_skinning.vert +++ b/data/shaders/instanced_skinning.vert @@ -39,7 +39,7 @@ out vec3 tangent; out vec3 bitangent; out vec2 uv; out vec4 color; -out vec2 color_change; +flat out vec2 color_change; #ifdef Use_Bindless_Texture flat out sampler2D handle; flat out sampler2D secondhandle; From 31f2a720caa7ff41b67934d81719a6e12467a851 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 23 Dec 2016 14:44:18 +0800 Subject: [PATCH 049/206] Try to reduce the header size of materials.hpp Plus header clean up --- src/graphics/draw_calls.cpp | 1 + src/graphics/gpu_particles.cpp | 1 - src/graphics/irr_driver.hpp | 18 +- src/graphics/lighting_passes.cpp | 1438 +++++++++++++------------- src/graphics/materials.cpp | 753 +++++++++++++- src/graphics/materials.hpp | 842 +++------------ src/graphics/particle_emitter.cpp | 1 - src/graphics/rtts.cpp | 10 +- src/graphics/shaders.cpp | 25 - src/graphics/shaders.hpp | 17 - src/graphics/shadow_matrices.cpp | 2 +- src/graphics/skybox.cpp | 3 +- src/graphics/stk_billboard.cpp | 2 +- src/graphics/stk_mesh.cpp | 5 +- src/graphics/stk_mesh_scene_node.cpp | 51 +- src/graphics/stk_mesh_scene_node.hpp | 15 +- src/graphics/texture_manager.cpp | 4 +- src/graphics/vao_manager.hpp | 2 +- src/tracks/graph.cpp | 1 - 19 files changed, 1688 insertions(+), 1503 deletions(-) diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 9f305f313..fc9a1ea35 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -24,6 +24,7 @@ #include "graphics/lod_node.hpp" #include "graphics/materials.hpp" #include "graphics/shadow_matrices.hpp" +#include "graphics/shaders.hpp" #include "graphics/stk_animated_mesh.hpp" #include "graphics/stk_billboard.hpp" #include "graphics/stk_mesh.hpp" diff --git a/src/graphics/gpu_particles.cpp b/src/graphics/gpu_particles.cpp index 261ee565b..7640f4277 100644 --- a/src/graphics/gpu_particles.cpp +++ b/src/graphics/gpu_particles.cpp @@ -22,7 +22,6 @@ #include "config/user_config.hpp" #include "graphics/irr_driver.hpp" #include "graphics/particle_emitter.hpp" -#include "graphics/shaders.hpp" #include "graphics/shared_gpu_objects.hpp" #include "graphics/texture_manager.hpp" #include "graphics/texture_shader.hpp" diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index 250db4fc3..4d40d8b46 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -312,15 +312,15 @@ public: std::unique_ptr createRenderTarget(const irr::core::dimension2du &dimension, const std::string &name); #endif - // ------------------------------------------------------------------------ - /** Returns the color to clear the back buffer. */ - const irr::video::SColor& getClearColor() const { return m_clear_color; } - // ------------------------------------------------------------------------ - /** Sets the color to use when clearing the back buffer. */ - void setClearbackBufferColor(irr::video::SColor color) - { - m_clear_color = color; - } // setClearbackBufferColor + // ------------------------------------------------------------------------ + /** Returns the color to clear the back buffer. */ + const irr::video::SColor& getClearColor() const { return m_clear_color; } + // ------------------------------------------------------------------------ + /** Sets the color to use when clearing the back buffer. */ + void setClearbackBufferColor(irr::video::SColor color) + { + m_clear_color = color; + } // setClearbackBufferColor // ------------------------------------------------------------------------ /** Convenience function that loads a texture with default parameters diff --git a/src/graphics/lighting_passes.cpp b/src/graphics/lighting_passes.cpp index 55675ed8d..abe094af3 100644 --- a/src/graphics/lighting_passes.cpp +++ b/src/graphics/lighting_passes.cpp @@ -20,722 +20,722 @@ #include "graphics/lighting_passes.hpp" #include "config/user_config.hpp" #include "graphics/central_settings.hpp" -#include "graphics/glwrap.hpp" -#include "graphics/irr_driver.hpp" -#include "graphics/light.hpp" -#include "graphics/post_processing.hpp" -#include "graphics/rtts.hpp" -#include "graphics/shaders.hpp" -#include "graphics/shadow_matrices.hpp" -#include "modes/world.hpp" -#include "tracks/track.hpp" -#include "utils/profiler.hpp" - -class LightBaseClass -{ -public: - struct PointLightInfo - { - float posX; - float posY; - float posZ; - float energy; - float red; - float green; - float blue; - float radius; - }; -public: - static const unsigned int MAXLIGHT = 32; -public: - static struct PointLightInfo m_point_lights_info[MAXLIGHT]; -}; // LightBaseClass - -const unsigned int LightBaseClass::MAXLIGHT; - -// ============================================================================ -LightBaseClass::PointLightInfo m_point_lights_info[LightBaseClass::MAXLIGHT]; - - -// ============================================================================ -class FogShader : public TextureShader -{ -public: - FogShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", - GL_FRAGMENT_SHADER, "fog.frag"); - assignUniforms("density", "col"); - assignSamplerNames(0, "tex", ST_NEAREST_FILTERED); - } // FogShader - // ------------------------------------------------------------------------ - void render(float start, const core::vector3df &color, GLuint depth_stencil_texture) - { - setTextureUnits(depth_stencil_texture); - drawFullScreenEffect(1.f / (40.f * start), color); - - } // render -}; // FogShader - -// ============================================================================ -class PointLightShader : public TextureShader < PointLightShader, 2 > -{ -public: - GLuint vbo; - GLuint vao; - PointLightShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "pointlight.vert", - GL_FRAGMENT_SHADER, "pointlight.frag"); - - assignUniforms(); - assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, - 1, "dtex", ST_NEAREST_FILTERED); - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, - LightBaseClass::MAXLIGHT * sizeof(LightBaseClass::PointLightInfo), - 0, GL_DYNAMIC_DRAW); - - GLuint attrib_Position = glGetAttribLocation(m_program, "Position"); - GLuint attrib_Color = glGetAttribLocation(m_program, "Color"); - GLuint attrib_Energy = glGetAttribLocation(m_program, "Energy"); - GLuint attrib_Radius = glGetAttribLocation(m_program, "Radius"); - - glEnableVertexAttribArray(attrib_Position); - glVertexAttribPointer(attrib_Position, 3, GL_FLOAT, GL_FALSE, - sizeof(LightBaseClass::PointLightInfo), 0); - glEnableVertexAttribArray(attrib_Energy); - glVertexAttribPointer(attrib_Energy, 1, GL_FLOAT, GL_FALSE, - sizeof(LightBaseClass::PointLightInfo), - (GLvoid*)(3 * sizeof(float))); - glEnableVertexAttribArray(attrib_Color); - glVertexAttribPointer(attrib_Color, 3, GL_FLOAT, GL_FALSE, - sizeof(LightBaseClass::PointLightInfo), - (GLvoid*)(4 * sizeof(float))); - glEnableVertexAttribArray(attrib_Radius); - glVertexAttribPointer(attrib_Radius, 1, GL_FLOAT, GL_FALSE, - sizeof(LightBaseClass::PointLightInfo), - (GLvoid*)(7 * sizeof(float))); - - glVertexAttribDivisorARB(attrib_Position, 1); - glVertexAttribDivisorARB(attrib_Energy, 1); - glVertexAttribDivisorARB(attrib_Color, 1); - glVertexAttribDivisorARB(attrib_Radius, 1); - } // PointLightShader -}; // PointLightShader - - - - -// ============================================================================ -class PointLightScatterShader : public TextureShader -{ -public: - GLuint vbo; - GLuint vao; - PointLightScatterShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "pointlight.vert", - GL_FRAGMENT_SHADER, "pointlightscatter.frag"); - - assignUniforms("density", "fogcol"); - assignSamplerNames(0, "dtex", ST_NEAREST_FILTERED); - - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - - glBindBuffer(GL_ARRAY_BUFFER, PointLightShader::getInstance()->vbo); - - GLuint attrib_Position = glGetAttribLocation(m_program, "Position"); - GLuint attrib_Color = glGetAttribLocation(m_program, "Color"); - GLuint attrib_Energy = glGetAttribLocation(m_program, "Energy"); - GLuint attrib_Radius = glGetAttribLocation(m_program, "Radius"); - - glEnableVertexAttribArray(attrib_Position); - glVertexAttribPointer(attrib_Position, 3, GL_FLOAT, GL_FALSE, - sizeof(LightBaseClass::PointLightInfo), 0); - glEnableVertexAttribArray(attrib_Energy); - glVertexAttribPointer(attrib_Energy, 1, GL_FLOAT, GL_FALSE, - sizeof(LightBaseClass::PointLightInfo), - (GLvoid*)(3 * sizeof(float))); - glEnableVertexAttribArray(attrib_Color); - glVertexAttribPointer(attrib_Color, 3, GL_FLOAT, GL_FALSE, - sizeof(LightBaseClass::PointLightInfo), - (GLvoid*)(4 * sizeof(float))); - glEnableVertexAttribArray(attrib_Radius); - glVertexAttribPointer(attrib_Radius, 1, GL_FLOAT, GL_FALSE, - sizeof(LightBaseClass::PointLightInfo), - (GLvoid*)(7 * sizeof(float))); - - glVertexAttribDivisorARB(attrib_Position, 1); - glVertexAttribDivisorARB(attrib_Energy, 1); - glVertexAttribDivisorARB(attrib_Color, 1); - glVertexAttribDivisorARB(attrib_Radius, 1); - } // PointLightScatterShader -}; - -#if !defined(USE_GLES2) -// ============================================================================ -class RadianceHintsConstructionShader - : public TextureShader -{ -public: - RadianceHintsConstructionShader() - { - if (CVS->isAMDVertexShaderLayerUsable()) - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert", - GL_FRAGMENT_SHADER, "rh.frag"); - } - else - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert", - GL_GEOMETRY_SHADER, "rhpassthrough.geom", - GL_FRAGMENT_SHADER, "rh.frag"); - } - - assignUniforms("RSMMatrix", "RHMatrix", "extents", "suncol"); - assignSamplerNames(0, "ctex", ST_BILINEAR_FILTERED, - 1, "ntex", ST_BILINEAR_FILTERED, - 2, "dtex", ST_BILINEAR_FILTERED); - } // RadianceHintsConstructionShader -}; // RadianceHintsConstructionShader - -// ============================================================================ -// Workaround for a bug found in kepler nvidia linux and fermi nvidia windows -class NVWorkaroundRadianceHintsConstructionShader - : public TextureShader -{ -public: - NVWorkaroundRadianceHintsConstructionShader() - { - loadProgram(OBJECT,GL_VERTEX_SHADER,"slicedscreenquad_nvworkaround.vert", - GL_GEOMETRY_SHADER, "rhpassthrough.geom", - GL_FRAGMENT_SHADER, "rh.frag"); - - assignUniforms("RSMMatrix", "RHMatrix", "extents", "slice", "suncol"); - - assignSamplerNames(0, "ctex", ST_BILINEAR_FILTERED, - 1, "ntex", ST_BILINEAR_FILTERED, - 2, "dtex", ST_BILINEAR_FILTERED); - } // NVWorkaroundRadianceHintsConstructionShader -}; // NVWorkaroundRadianceHintsConstructionShader -#endif // !defined(USE_GLES2) - -// ============================================================================ -class GlobalIlluminationReconstructionShader - : public TextureShader -{ -public: - GlobalIlluminationReconstructionShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", - GL_FRAGMENT_SHADER, "gi.frag"); - - assignUniforms("rh_matrix", "inv_rh_matrix", "extents"); - assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, - 1, "dtex", ST_NEAREST_FILTERED, - 2, "SHR", ST_VOLUME_LINEAR_FILTERED, - 3, "SHG", ST_VOLUME_LINEAR_FILTERED, - 4, "SHB", ST_VOLUME_LINEAR_FILTERED); - } // GlobalIlluminationReconstructionShader - - // ------------------------------------------------------------------------ - void render(const core::matrix4 &rh_matrix, - const core::vector3df &rh_extend, const FrameBuffer &fb, - GLuint normal_depth_texture, - GLuint depth_stencil_texture) - { - core::matrix4 inv_rh_matrix; - rh_matrix.getInverse(inv_rh_matrix); - glDisable(GL_DEPTH_TEST); - setTextureUnits(normal_depth_texture, - depth_stencil_texture, - fb.getRTT()[0], fb.getRTT()[1], fb.getRTT()[2]); - drawFullScreenEffect(rh_matrix, inv_rh_matrix, rh_extend); - } // render -}; // GlobalIlluminationReconstructionShader - -// ============================================================================ -class IBLShader : public TextureShader -{ -public: - IBLShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", - GL_FRAGMENT_SHADER, "IBL.frag"); - assignUniforms(); - assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, - 1, "dtex", ST_NEAREST_FILTERED, - 2, "probe", ST_TRILINEAR_CUBEMAP); - } // IBLShader -}; // IBLShader - -// ============================================================================ -class DegradedIBLShader : public TextureShader -{ -public: - DegradedIBLShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", - GL_FRAGMENT_SHADER, "degraded_ibl.frag"); - assignUniforms(); - assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED); - } // DegradedIBLShader -}; // DegradedIBLShader - -// ============================================================================ -class ShadowedSunLightShaderPCF : public TextureShader -{ -public: - ShadowedSunLightShaderPCF() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", - GL_FRAGMENT_SHADER, "sunlightshadow.frag"); - - // Use 8 to circumvent a catalyst bug when binding sampler - assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, - 1, "dtex", ST_NEAREST_FILTERED, - 8, "shadowtex", ST_SHADOW_SAMPLER); - assignUniforms("split0", "split1", "split2", "splitmax", "shadow_res"); - } // ShadowedSunLightShaderPCF - // ------------------------------------------------------------------------ - void render(GLuint normal_depth_texture, - GLuint depth_stencil_texture, - const FrameBuffer& shadow_framebuffer) - { - setTextureUnits(normal_depth_texture, - depth_stencil_texture, - shadow_framebuffer.getDepthTexture() ); - drawFullScreenEffect(ShadowMatrices::m_shadow_split[1], - ShadowMatrices::m_shadow_split[2], - ShadowMatrices::m_shadow_split[3], - ShadowMatrices::m_shadow_split[4], - float(UserConfigParams::m_shadows_resolution) ); - - } // render -}; // ShadowedSunLightShaderPCF - -// ============================================================================ -class ShadowedSunLightShaderESM : public TextureShader -{ -public: - ShadowedSunLightShaderESM() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", - GL_FRAGMENT_SHADER, "sunlightshadowesm.frag"); - - // Use 8 to circumvent a catalyst bug when binding sampler - assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, - 1, "dtex", ST_NEAREST_FILTERED, - 8, "shadowtex", ST_TRILINEAR_CLAMPED_ARRAY2D); - - assignUniforms("split0", "split1", "split2", "splitmax"); - } // ShadowedSunLightShaderESM - // ------------------------------------------------------------------------ - void render(GLuint normal_depth_texture, - GLuint depth_stencil_texture, - const FrameBuffer& shadow_framebuffer) - { - setTextureUnits(normal_depth_texture, - depth_stencil_texture, - shadow_framebuffer.getRTT()[0]); - drawFullScreenEffect(ShadowMatrices::m_shadow_split[1], - ShadowMatrices::m_shadow_split[2], - ShadowMatrices::m_shadow_split[3], - ShadowMatrices::m_shadow_split[4]); - } // render -}; // ShadowedSunLightShaderESM - - -// ============================================================================ -class SunLightShader : public TextureShader -{ -public: - SunLightShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", - GL_FRAGMENT_SHADER, "sunlight.frag"); - - assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, - 1, "dtex", ST_NEAREST_FILTERED); - assignUniforms("direction", "col"); - } // SunLightShader - // ------------------------------------------------------------------------ - void render(const core::vector3df &direction, const video::SColorf &col, - GLuint normal_depth_texture, - GLuint depth_stencil_texture) - { - glEnable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glBlendFunc(GL_ONE, GL_ONE); - glBlendEquation(GL_FUNC_ADD); - - setTextureUnits(normal_depth_texture, depth_stencil_texture); - drawFullScreenEffect(direction, col); - } // render -}; // SunLightShader - -// ============================================================================ -static void renderPointLights(unsigned count, - GLuint normal_depth_rander_target, - GLuint depth_stencil_texture) -{ - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE); - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - - PointLightShader::getInstance()->use(); - glBindVertexArray(PointLightShader::getInstance()->vao); - glBindBuffer(GL_ARRAY_BUFFER, PointLightShader::getInstance()->vbo); - glBufferSubData(GL_ARRAY_BUFFER, 0, - count * sizeof(LightBaseClass::PointLightInfo), - m_point_lights_info); - - PointLightShader::getInstance()->setTextureUnits( - normal_depth_rander_target, - depth_stencil_texture); - PointLightShader::getInstance()->setUniforms(); - - glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count); -} // renderPointLights - -// ---------------------------------------------------------------------------- -void LightingPasses::renderEnvMap(GLuint normal_depth_texture, - GLuint depth_stencil_texture, - GLuint specular_probe) -{ - glDisable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE); - - if (UserConfigParams::m_degraded_IBL) - { - DegradedIBLShader::getInstance()->use(); - glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO()); - - DegradedIBLShader::getInstance() - ->setTextureUnits(normal_depth_texture); - DegradedIBLShader::getInstance()->setUniforms(); - } - else - { - IBLShader::getInstance()->use(); - glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO()); - - IBLShader::getInstance()->setTextureUnits( - normal_depth_texture, - depth_stencil_texture, - specular_probe); - IBLShader::getInstance()->setUniforms(); - } - - glDrawArrays(GL_TRIANGLES, 0, 3); - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glEnable(GL_DEPTH_TEST); - glDisable(GL_BLEND); -} // renderEnvMap - -// ---------------------------------------------------------------------------- -void LightingPasses::renderSunlight(const core::vector3df &direction, - const video::SColorf &col, - GLuint normal_depth_texture, - GLuint depth_stencil_texture) -{ - SunLightShader::getInstance()->render(direction, col, - normal_depth_texture, - depth_stencil_texture); -} // renderSunlight - - -// ---------------------------------------------------------------------------- -void LightingPasses::updateLightsInfo(scene::ICameraSceneNode * const camnode, - float dt) -{ - std::vector lights = irr_driver->getLights(); - const u32 lightcount = (u32)lights.size(); - const core::vector3df &campos = camnode->getAbsolutePosition(); - - std::vector BucketedLN[15]; - for (unsigned int i = 0; i < lightcount; i++) - { - if (!lights[i]->isVisible()) - continue; - - if (!lights[i]->isPointLight()) - { - lights[i]->render(); - continue; - } - const core::vector3df &lightpos = - (lights[i]->getAbsolutePosition() - campos); - unsigned idx = (unsigned)(lightpos.getLength() / 10); - if (idx > 14) - idx = 14; - BucketedLN[idx].push_back(lights[i]); - } - - m_point_light_count = 0; - bool multiplayer = (race_manager->getNumLocalPlayers() > 1); - - for (unsigned i = 0; i < 15; i++) - { - for (unsigned j = 0; j < BucketedLN[i].size(); j++) - { - if (++m_point_light_count >= LightBaseClass::MAXLIGHT) - { - LightNode* light_node = BucketedLN[i].at(j); - light_node->setEnergyMultiplier(0.0f); - } - else - { - LightNode* light_node = BucketedLN[i].at(j); - - float em = light_node->getEnergyMultiplier(); - if (em < 1.0f) - { - // In single-player, fade-in lights. - // In multi-player, can't do that, the light objects are shared by all players - if (multiplayer) - light_node->setEnergyMultiplier(1.0f); - else - light_node->setEnergyMultiplier(std::min(1.0f, em + dt)); - } - - const core::vector3df &pos = light_node->getAbsolutePosition(); - m_point_lights_info[m_point_light_count].posX = pos.X; - m_point_lights_info[m_point_light_count].posY = pos.Y; - m_point_lights_info[m_point_light_count].posZ = pos.Z; - - m_point_lights_info[m_point_light_count].energy = - light_node->getEffectiveEnergy(); - - const core::vector3df &col = light_node->getColor(); - m_point_lights_info[m_point_light_count].red = col.X; - m_point_lights_info[m_point_light_count].green = col.Y; - m_point_lights_info[m_point_light_count].blue = col.Z; - - // Light radius - m_point_lights_info[m_point_light_count].radius = light_node->getRadius(); - } - } - if (m_point_light_count > LightBaseClass::MAXLIGHT) - { - irr_driver->setLastLightBucketDistance(i * 10); - break; - } - } - - m_point_light_count++; -} // updateLightsInfo - -// ---------------------------------------------------------------------------- -void LightingPasses::renderRadianceHints( const ShadowMatrices& shadow_matrices, - const FrameBuffer& radiance_hint_framebuffer, - const FrameBuffer& reflective_shadow_map_framebuffer) -{ -#if !defined(USE_GLES2) - glDisable(GL_BLEND); - radiance_hint_framebuffer.bind(); - glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO()); - if (CVS->needRHWorkaround()) - { - NVWorkaroundRadianceHintsConstructionShader::getInstance()->use(); - NVWorkaroundRadianceHintsConstructionShader::getInstance() - ->setTextureUnits( - reflective_shadow_map_framebuffer.getRTT()[0], - reflective_shadow_map_framebuffer.getRTT()[1], - reflective_shadow_map_framebuffer.getDepthTexture()); - for (unsigned i = 0; i < 32; i++) - { - NVWorkaroundRadianceHintsConstructionShader::getInstance() - ->setUniforms(shadow_matrices.getRSMMatrix(), - shadow_matrices.getRHMatrix(), - shadow_matrices.getRHExtend(), i, - irr_driver->getSunColor()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - } - } - else - { - RadianceHintsConstructionShader::getInstance()->use(); - RadianceHintsConstructionShader::getInstance() - ->setTextureUnits( - reflective_shadow_map_framebuffer.getRTT()[0], - reflective_shadow_map_framebuffer.getRTT()[1], - reflective_shadow_map_framebuffer.getDepthTexture() - ); - RadianceHintsConstructionShader::getInstance() - ->setUniforms(shadow_matrices.getRSMMatrix(), - shadow_matrices.getRHMatrix(), - shadow_matrices.getRHExtend(), - irr_driver->getSunColor()); - glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 32); - } -#endif //!defined(USE_GLES2) -} // renderRadianceHints - -// ---------------------------------------------------------------------------- -void LightingPasses::renderGlobalIllumination( const ShadowMatrices& shadow_matrices, - const FrameBuffer& radiance_hint_framebuffer, - GLuint normal_depth_texture, - GLuint depth_stencil_texture) -{ - GlobalIlluminationReconstructionShader::getInstance() - ->render(shadow_matrices.getRHMatrix(), shadow_matrices.getRHExtend(), - radiance_hint_framebuffer, normal_depth_texture, - depth_stencil_texture); -} - -// ---------------------------------------------------------------------------- -void LightingPasses::renderLights( bool has_shadow, - GLuint normal_depth_texture, - GLuint depth_stencil_texture, - const FrameBuffer& shadow_framebuffer, - GLuint specular_probe) -{ - { - ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_ENVMAP)); - renderEnvMap(normal_depth_texture, - depth_stencil_texture, - specular_probe); - } - - // Render sunlight if and only if track supports shadow - const Track* const track = Track::getCurrentTrack(); - if (!track|| track->hasShadows()) - { - ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_SUN)); - if (World::getWorld() && CVS->isShadowEnabled() && has_shadow) - { - glEnable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glBlendFunc(GL_ONE, GL_ONE); - glBlendEquation(GL_FUNC_ADD); - - - if (CVS->isESMEnabled()) - { - ShadowedSunLightShaderESM::getInstance()->render(normal_depth_texture, - depth_stencil_texture, - shadow_framebuffer); - } - else - { - ShadowedSunLightShaderPCF::getInstance()->render(normal_depth_texture, - depth_stencil_texture, - shadow_framebuffer); - } - } - else - renderSunlight(irr_driver->getSunDirection(), - irr_driver->getSunColor(), - normal_depth_texture, - depth_stencil_texture); - } - - //points lights - { - ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_POINTLIGHTS)); - renderPointLights(std::min(m_point_light_count, LightBaseClass::MAXLIGHT), - normal_depth_texture, - depth_stencil_texture); - } -} // renderLights - -// ---------------------------------------------------------------------------- -void LightingPasses::renderAmbientScatter(GLuint depth_stencil_texture) -{ - const Track * const track = Track::getCurrentTrack(); - - // This function is only called once per frame - thus no need for setters. - float start = track->getFogStart() + .001f; - const video::SColor tmpcol = track->getFogColor(); - - core::vector3df col(tmpcol.getRed() / 255.0f, - tmpcol.getGreen() / 255.0f, - tmpcol.getBlue() / 255.0f); - - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE); - - FogShader::getInstance()->render(start, col, depth_stencil_texture); -} // renderAmbientScatter - -// ---------------------------------------------------------------------------- -void LightingPasses::renderLightsScatter(GLuint depth_stencil_texture, - const FrameBuffer& half1_framebuffer, - const FrameBuffer& half2_framebuffer, - const FrameBuffer& colors_framebuffer, - const PostProcessing* post_processing) -{ - half1_framebuffer.bind(); - glClearColor(0., 0., 0., 0.); - glClear(GL_COLOR_BUFFER_BIT); - - const Track * const track = Track::getCurrentTrack(); - - // This function is only called once per frame - thus no need for setters. - float start = track->getFogStart() + .001f; - const video::SColor tmpcol = track->getFogColor(); - - core::vector3df col(tmpcol.getRed() / 255.0f, - tmpcol.getGreen() / 255.0f, - tmpcol.getBlue() / 255.0f); - - glDepthMask(GL_FALSE); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE); - - glEnable(GL_DEPTH_TEST); - core::vector3df col2(1., 1., 1.); - - PointLightScatterShader::getInstance()->use(); - glBindVertexArray(PointLightScatterShader::getInstance()->vao); - - PointLightScatterShader::getInstance() - ->setTextureUnits(depth_stencil_texture); - PointLightScatterShader::getInstance() - ->setUniforms(1.f / (40.f * start), col2); - - glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, - std::min(m_point_light_count, - LightBaseClass::MAXLIGHT)); - - glDisable(GL_BLEND); - post_processing->renderGaussian6Blur(half1_framebuffer, - half2_framebuffer, 5., 5.); - glEnable(GL_BLEND); - - glDisable(GL_DEPTH_TEST); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - colors_framebuffer.bind(); - post_processing->renderPassThrough(half1_framebuffer.getRTT()[0], - colors_framebuffer.getWidth(), - colors_framebuffer.getHeight()); -} // renderLightsScatter - -#endif +#include "graphics/glwrap.hpp" +#include "graphics/irr_driver.hpp" +#include "graphics/light.hpp" +#include "graphics/post_processing.hpp" +#include "graphics/rtts.hpp" +#include "graphics/shadow_matrices.hpp" +#include "graphics/texture_shader.hpp" +#include "modes/world.hpp" +#include "tracks/track.hpp" +#include "utils/profiler.hpp" + +class LightBaseClass +{ +public: + struct PointLightInfo + { + float posX; + float posY; + float posZ; + float energy; + float red; + float green; + float blue; + float radius; + }; +public: + static const unsigned int MAXLIGHT = 32; +public: + static struct PointLightInfo m_point_lights_info[MAXLIGHT]; +}; // LightBaseClass + +const unsigned int LightBaseClass::MAXLIGHT; + +// ============================================================================ +LightBaseClass::PointLightInfo m_point_lights_info[LightBaseClass::MAXLIGHT]; + + +// ============================================================================ +class FogShader : public TextureShader +{ +public: + FogShader() + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + GL_FRAGMENT_SHADER, "fog.frag"); + assignUniforms("density", "col"); + assignSamplerNames(0, "tex", ST_NEAREST_FILTERED); + } // FogShader + // ------------------------------------------------------------------------ + void render(float start, const core::vector3df &color, GLuint depth_stencil_texture) + { + setTextureUnits(depth_stencil_texture); + drawFullScreenEffect(1.f / (40.f * start), color); + + } // render +}; // FogShader + +// ============================================================================ +class PointLightShader : public TextureShader < PointLightShader, 2 > +{ +public: + GLuint vbo; + GLuint vao; + PointLightShader() + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "pointlight.vert", + GL_FRAGMENT_SHADER, "pointlight.frag"); + + assignUniforms(); + assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, + 1, "dtex", ST_NEAREST_FILTERED); + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, + LightBaseClass::MAXLIGHT * sizeof(LightBaseClass::PointLightInfo), + 0, GL_DYNAMIC_DRAW); + + GLuint attrib_Position = glGetAttribLocation(m_program, "Position"); + GLuint attrib_Color = glGetAttribLocation(m_program, "Color"); + GLuint attrib_Energy = glGetAttribLocation(m_program, "Energy"); + GLuint attrib_Radius = glGetAttribLocation(m_program, "Radius"); + + glEnableVertexAttribArray(attrib_Position); + glVertexAttribPointer(attrib_Position, 3, GL_FLOAT, GL_FALSE, + sizeof(LightBaseClass::PointLightInfo), 0); + glEnableVertexAttribArray(attrib_Energy); + glVertexAttribPointer(attrib_Energy, 1, GL_FLOAT, GL_FALSE, + sizeof(LightBaseClass::PointLightInfo), + (GLvoid*)(3 * sizeof(float))); + glEnableVertexAttribArray(attrib_Color); + glVertexAttribPointer(attrib_Color, 3, GL_FLOAT, GL_FALSE, + sizeof(LightBaseClass::PointLightInfo), + (GLvoid*)(4 * sizeof(float))); + glEnableVertexAttribArray(attrib_Radius); + glVertexAttribPointer(attrib_Radius, 1, GL_FLOAT, GL_FALSE, + sizeof(LightBaseClass::PointLightInfo), + (GLvoid*)(7 * sizeof(float))); + + glVertexAttribDivisorARB(attrib_Position, 1); + glVertexAttribDivisorARB(attrib_Energy, 1); + glVertexAttribDivisorARB(attrib_Color, 1); + glVertexAttribDivisorARB(attrib_Radius, 1); + } // PointLightShader +}; // PointLightShader + + + + +// ============================================================================ +class PointLightScatterShader : public TextureShader +{ +public: + GLuint vbo; + GLuint vao; + PointLightScatterShader() + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "pointlight.vert", + GL_FRAGMENT_SHADER, "pointlightscatter.frag"); + + assignUniforms("density", "fogcol"); + assignSamplerNames(0, "dtex", ST_NEAREST_FILTERED); + + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + glBindBuffer(GL_ARRAY_BUFFER, PointLightShader::getInstance()->vbo); + + GLuint attrib_Position = glGetAttribLocation(m_program, "Position"); + GLuint attrib_Color = glGetAttribLocation(m_program, "Color"); + GLuint attrib_Energy = glGetAttribLocation(m_program, "Energy"); + GLuint attrib_Radius = glGetAttribLocation(m_program, "Radius"); + + glEnableVertexAttribArray(attrib_Position); + glVertexAttribPointer(attrib_Position, 3, GL_FLOAT, GL_FALSE, + sizeof(LightBaseClass::PointLightInfo), 0); + glEnableVertexAttribArray(attrib_Energy); + glVertexAttribPointer(attrib_Energy, 1, GL_FLOAT, GL_FALSE, + sizeof(LightBaseClass::PointLightInfo), + (GLvoid*)(3 * sizeof(float))); + glEnableVertexAttribArray(attrib_Color); + glVertexAttribPointer(attrib_Color, 3, GL_FLOAT, GL_FALSE, + sizeof(LightBaseClass::PointLightInfo), + (GLvoid*)(4 * sizeof(float))); + glEnableVertexAttribArray(attrib_Radius); + glVertexAttribPointer(attrib_Radius, 1, GL_FLOAT, GL_FALSE, + sizeof(LightBaseClass::PointLightInfo), + (GLvoid*)(7 * sizeof(float))); + + glVertexAttribDivisorARB(attrib_Position, 1); + glVertexAttribDivisorARB(attrib_Energy, 1); + glVertexAttribDivisorARB(attrib_Color, 1); + glVertexAttribDivisorARB(attrib_Radius, 1); + } // PointLightScatterShader +}; + +#if !defined(USE_GLES2) +// ============================================================================ +class RadianceHintsConstructionShader + : public TextureShader +{ +public: + RadianceHintsConstructionShader() + { + if (CVS->isAMDVertexShaderLayerUsable()) + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert", + GL_FRAGMENT_SHADER, "rh.frag"); + } + else + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert", + GL_GEOMETRY_SHADER, "rhpassthrough.geom", + GL_FRAGMENT_SHADER, "rh.frag"); + } + + assignUniforms("RSMMatrix", "RHMatrix", "extents", "suncol"); + assignSamplerNames(0, "ctex", ST_BILINEAR_FILTERED, + 1, "ntex", ST_BILINEAR_FILTERED, + 2, "dtex", ST_BILINEAR_FILTERED); + } // RadianceHintsConstructionShader +}; // RadianceHintsConstructionShader + +// ============================================================================ +// Workaround for a bug found in kepler nvidia linux and fermi nvidia windows +class NVWorkaroundRadianceHintsConstructionShader + : public TextureShader +{ +public: + NVWorkaroundRadianceHintsConstructionShader() + { + loadProgram(OBJECT,GL_VERTEX_SHADER,"slicedscreenquad_nvworkaround.vert", + GL_GEOMETRY_SHADER, "rhpassthrough.geom", + GL_FRAGMENT_SHADER, "rh.frag"); + + assignUniforms("RSMMatrix", "RHMatrix", "extents", "slice", "suncol"); + + assignSamplerNames(0, "ctex", ST_BILINEAR_FILTERED, + 1, "ntex", ST_BILINEAR_FILTERED, + 2, "dtex", ST_BILINEAR_FILTERED); + } // NVWorkaroundRadianceHintsConstructionShader +}; // NVWorkaroundRadianceHintsConstructionShader +#endif // !defined(USE_GLES2) + +// ============================================================================ +class GlobalIlluminationReconstructionShader + : public TextureShader +{ +public: + GlobalIlluminationReconstructionShader() + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + GL_FRAGMENT_SHADER, "gi.frag"); + + assignUniforms("rh_matrix", "inv_rh_matrix", "extents"); + assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, + 1, "dtex", ST_NEAREST_FILTERED, + 2, "SHR", ST_VOLUME_LINEAR_FILTERED, + 3, "SHG", ST_VOLUME_LINEAR_FILTERED, + 4, "SHB", ST_VOLUME_LINEAR_FILTERED); + } // GlobalIlluminationReconstructionShader + + // ------------------------------------------------------------------------ + void render(const core::matrix4 &rh_matrix, + const core::vector3df &rh_extend, const FrameBuffer &fb, + GLuint normal_depth_texture, + GLuint depth_stencil_texture) + { + core::matrix4 inv_rh_matrix; + rh_matrix.getInverse(inv_rh_matrix); + glDisable(GL_DEPTH_TEST); + setTextureUnits(normal_depth_texture, + depth_stencil_texture, + fb.getRTT()[0], fb.getRTT()[1], fb.getRTT()[2]); + drawFullScreenEffect(rh_matrix, inv_rh_matrix, rh_extend); + } // render +}; // GlobalIlluminationReconstructionShader + +// ============================================================================ +class IBLShader : public TextureShader +{ +public: + IBLShader() + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + GL_FRAGMENT_SHADER, "IBL.frag"); + assignUniforms(); + assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, + 1, "dtex", ST_NEAREST_FILTERED, + 2, "probe", ST_TRILINEAR_CUBEMAP); + } // IBLShader +}; // IBLShader + +// ============================================================================ +class DegradedIBLShader : public TextureShader +{ +public: + DegradedIBLShader() + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + GL_FRAGMENT_SHADER, "degraded_ibl.frag"); + assignUniforms(); + assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED); + } // DegradedIBLShader +}; // DegradedIBLShader + +// ============================================================================ +class ShadowedSunLightShaderPCF : public TextureShader +{ +public: + ShadowedSunLightShaderPCF() + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + GL_FRAGMENT_SHADER, "sunlightshadow.frag"); + + // Use 8 to circumvent a catalyst bug when binding sampler + assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, + 1, "dtex", ST_NEAREST_FILTERED, + 8, "shadowtex", ST_SHADOW_SAMPLER); + assignUniforms("split0", "split1", "split2", "splitmax", "shadow_res"); + } // ShadowedSunLightShaderPCF + // ------------------------------------------------------------------------ + void render(GLuint normal_depth_texture, + GLuint depth_stencil_texture, + const FrameBuffer& shadow_framebuffer) + { + setTextureUnits(normal_depth_texture, + depth_stencil_texture, + shadow_framebuffer.getDepthTexture() ); + drawFullScreenEffect(ShadowMatrices::m_shadow_split[1], + ShadowMatrices::m_shadow_split[2], + ShadowMatrices::m_shadow_split[3], + ShadowMatrices::m_shadow_split[4], + float(UserConfigParams::m_shadows_resolution) ); + + } // render +}; // ShadowedSunLightShaderPCF + +// ============================================================================ +class ShadowedSunLightShaderESM : public TextureShader +{ +public: + ShadowedSunLightShaderESM() + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + GL_FRAGMENT_SHADER, "sunlightshadowesm.frag"); + + // Use 8 to circumvent a catalyst bug when binding sampler + assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, + 1, "dtex", ST_NEAREST_FILTERED, + 8, "shadowtex", ST_TRILINEAR_CLAMPED_ARRAY2D); + + assignUniforms("split0", "split1", "split2", "splitmax"); + } // ShadowedSunLightShaderESM + // ------------------------------------------------------------------------ + void render(GLuint normal_depth_texture, + GLuint depth_stencil_texture, + const FrameBuffer& shadow_framebuffer) + { + setTextureUnits(normal_depth_texture, + depth_stencil_texture, + shadow_framebuffer.getRTT()[0]); + drawFullScreenEffect(ShadowMatrices::m_shadow_split[1], + ShadowMatrices::m_shadow_split[2], + ShadowMatrices::m_shadow_split[3], + ShadowMatrices::m_shadow_split[4]); + } // render +}; // ShadowedSunLightShaderESM + + +// ============================================================================ +class SunLightShader : public TextureShader +{ +public: + SunLightShader() + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", + GL_FRAGMENT_SHADER, "sunlight.frag"); + + assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED, + 1, "dtex", ST_NEAREST_FILTERED); + assignUniforms("direction", "col"); + } // SunLightShader + // ------------------------------------------------------------------------ + void render(const core::vector3df &direction, const video::SColorf &col, + GLuint normal_depth_texture, + GLuint depth_stencil_texture) + { + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glBlendFunc(GL_ONE, GL_ONE); + glBlendEquation(GL_FUNC_ADD); + + setTextureUnits(normal_depth_texture, depth_stencil_texture); + drawFullScreenEffect(direction, col); + } // render +}; // SunLightShader + +// ============================================================================ +static void renderPointLights(unsigned count, + GLuint normal_depth_rander_target, + GLuint depth_stencil_texture) +{ + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE, GL_ONE); + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + + PointLightShader::getInstance()->use(); + glBindVertexArray(PointLightShader::getInstance()->vao); + glBindBuffer(GL_ARRAY_BUFFER, PointLightShader::getInstance()->vbo); + glBufferSubData(GL_ARRAY_BUFFER, 0, + count * sizeof(LightBaseClass::PointLightInfo), + m_point_lights_info); + + PointLightShader::getInstance()->setTextureUnits( + normal_depth_rander_target, + depth_stencil_texture); + PointLightShader::getInstance()->setUniforms(); + + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count); +} // renderPointLights + +// ---------------------------------------------------------------------------- +void LightingPasses::renderEnvMap(GLuint normal_depth_texture, + GLuint depth_stencil_texture, + GLuint specular_probe) +{ + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE, GL_ONE); + + if (UserConfigParams::m_degraded_IBL) + { + DegradedIBLShader::getInstance()->use(); + glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO()); + + DegradedIBLShader::getInstance() + ->setTextureUnits(normal_depth_texture); + DegradedIBLShader::getInstance()->setUniforms(); + } + else + { + IBLShader::getInstance()->use(); + glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO()); + + IBLShader::getInstance()->setTextureUnits( + normal_depth_texture, + depth_stencil_texture, + specular_probe); + IBLShader::getInstance()->setUniforms(); + } + + glDrawArrays(GL_TRIANGLES, 0, 3); + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); +} // renderEnvMap + +// ---------------------------------------------------------------------------- +void LightingPasses::renderSunlight(const core::vector3df &direction, + const video::SColorf &col, + GLuint normal_depth_texture, + GLuint depth_stencil_texture) +{ + SunLightShader::getInstance()->render(direction, col, + normal_depth_texture, + depth_stencil_texture); +} // renderSunlight + + +// ---------------------------------------------------------------------------- +void LightingPasses::updateLightsInfo(scene::ICameraSceneNode * const camnode, + float dt) +{ + std::vector lights = irr_driver->getLights(); + const u32 lightcount = (u32)lights.size(); + const core::vector3df &campos = camnode->getAbsolutePosition(); + + std::vector BucketedLN[15]; + for (unsigned int i = 0; i < lightcount; i++) + { + if (!lights[i]->isVisible()) + continue; + + if (!lights[i]->isPointLight()) + { + lights[i]->render(); + continue; + } + const core::vector3df &lightpos = + (lights[i]->getAbsolutePosition() - campos); + unsigned idx = (unsigned)(lightpos.getLength() / 10); + if (idx > 14) + idx = 14; + BucketedLN[idx].push_back(lights[i]); + } + + m_point_light_count = 0; + bool multiplayer = (race_manager->getNumLocalPlayers() > 1); + + for (unsigned i = 0; i < 15; i++) + { + for (unsigned j = 0; j < BucketedLN[i].size(); j++) + { + if (++m_point_light_count >= LightBaseClass::MAXLIGHT) + { + LightNode* light_node = BucketedLN[i].at(j); + light_node->setEnergyMultiplier(0.0f); + } + else + { + LightNode* light_node = BucketedLN[i].at(j); + + float em = light_node->getEnergyMultiplier(); + if (em < 1.0f) + { + // In single-player, fade-in lights. + // In multi-player, can't do that, the light objects are shared by all players + if (multiplayer) + light_node->setEnergyMultiplier(1.0f); + else + light_node->setEnergyMultiplier(std::min(1.0f, em + dt)); + } + + const core::vector3df &pos = light_node->getAbsolutePosition(); + m_point_lights_info[m_point_light_count].posX = pos.X; + m_point_lights_info[m_point_light_count].posY = pos.Y; + m_point_lights_info[m_point_light_count].posZ = pos.Z; + + m_point_lights_info[m_point_light_count].energy = + light_node->getEffectiveEnergy(); + + const core::vector3df &col = light_node->getColor(); + m_point_lights_info[m_point_light_count].red = col.X; + m_point_lights_info[m_point_light_count].green = col.Y; + m_point_lights_info[m_point_light_count].blue = col.Z; + + // Light radius + m_point_lights_info[m_point_light_count].radius = light_node->getRadius(); + } + } + if (m_point_light_count > LightBaseClass::MAXLIGHT) + { + irr_driver->setLastLightBucketDistance(i * 10); + break; + } + } + + m_point_light_count++; +} // updateLightsInfo + +// ---------------------------------------------------------------------------- +void LightingPasses::renderRadianceHints( const ShadowMatrices& shadow_matrices, + const FrameBuffer& radiance_hint_framebuffer, + const FrameBuffer& reflective_shadow_map_framebuffer) +{ +#if !defined(USE_GLES2) + glDisable(GL_BLEND); + radiance_hint_framebuffer.bind(); + glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO()); + if (CVS->needRHWorkaround()) + { + NVWorkaroundRadianceHintsConstructionShader::getInstance()->use(); + NVWorkaroundRadianceHintsConstructionShader::getInstance() + ->setTextureUnits( + reflective_shadow_map_framebuffer.getRTT()[0], + reflective_shadow_map_framebuffer.getRTT()[1], + reflective_shadow_map_framebuffer.getDepthTexture()); + for (unsigned i = 0; i < 32; i++) + { + NVWorkaroundRadianceHintsConstructionShader::getInstance() + ->setUniforms(shadow_matrices.getRSMMatrix(), + shadow_matrices.getRHMatrix(), + shadow_matrices.getRHExtend(), i, + irr_driver->getSunColor()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + } + else + { + RadianceHintsConstructionShader::getInstance()->use(); + RadianceHintsConstructionShader::getInstance() + ->setTextureUnits( + reflective_shadow_map_framebuffer.getRTT()[0], + reflective_shadow_map_framebuffer.getRTT()[1], + reflective_shadow_map_framebuffer.getDepthTexture() + ); + RadianceHintsConstructionShader::getInstance() + ->setUniforms(shadow_matrices.getRSMMatrix(), + shadow_matrices.getRHMatrix(), + shadow_matrices.getRHExtend(), + irr_driver->getSunColor()); + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 32); + } +#endif //!defined(USE_GLES2) +} // renderRadianceHints + +// ---------------------------------------------------------------------------- +void LightingPasses::renderGlobalIllumination( const ShadowMatrices& shadow_matrices, + const FrameBuffer& radiance_hint_framebuffer, + GLuint normal_depth_texture, + GLuint depth_stencil_texture) +{ + GlobalIlluminationReconstructionShader::getInstance() + ->render(shadow_matrices.getRHMatrix(), shadow_matrices.getRHExtend(), + radiance_hint_framebuffer, normal_depth_texture, + depth_stencil_texture); +} + +// ---------------------------------------------------------------------------- +void LightingPasses::renderLights( bool has_shadow, + GLuint normal_depth_texture, + GLuint depth_stencil_texture, + const FrameBuffer& shadow_framebuffer, + GLuint specular_probe) +{ + { + ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_ENVMAP)); + renderEnvMap(normal_depth_texture, + depth_stencil_texture, + specular_probe); + } + + // Render sunlight if and only if track supports shadow + const Track* const track = Track::getCurrentTrack(); + if (!track|| track->hasShadows()) + { + ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_SUN)); + if (World::getWorld() && CVS->isShadowEnabled() && has_shadow) + { + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glBlendFunc(GL_ONE, GL_ONE); + glBlendEquation(GL_FUNC_ADD); + + + if (CVS->isESMEnabled()) + { + ShadowedSunLightShaderESM::getInstance()->render(normal_depth_texture, + depth_stencil_texture, + shadow_framebuffer); + } + else + { + ShadowedSunLightShaderPCF::getInstance()->render(normal_depth_texture, + depth_stencil_texture, + shadow_framebuffer); + } + } + else + renderSunlight(irr_driver->getSunDirection(), + irr_driver->getSunColor(), + normal_depth_texture, + depth_stencil_texture); + } + + //points lights + { + ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_POINTLIGHTS)); + renderPointLights(std::min(m_point_light_count, LightBaseClass::MAXLIGHT), + normal_depth_texture, + depth_stencil_texture); + } +} // renderLights + +// ---------------------------------------------------------------------------- +void LightingPasses::renderAmbientScatter(GLuint depth_stencil_texture) +{ + const Track * const track = Track::getCurrentTrack(); + + // This function is only called once per frame - thus no need for setters. + float start = track->getFogStart() + .001f; + const video::SColor tmpcol = track->getFogColor(); + + core::vector3df col(tmpcol.getRed() / 255.0f, + tmpcol.getGreen() / 255.0f, + tmpcol.getBlue() / 255.0f); + + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE, GL_ONE); + + FogShader::getInstance()->render(start, col, depth_stencil_texture); +} // renderAmbientScatter + +// ---------------------------------------------------------------------------- +void LightingPasses::renderLightsScatter(GLuint depth_stencil_texture, + const FrameBuffer& half1_framebuffer, + const FrameBuffer& half2_framebuffer, + const FrameBuffer& colors_framebuffer, + const PostProcessing* post_processing) +{ + half1_framebuffer.bind(); + glClearColor(0., 0., 0., 0.); + glClear(GL_COLOR_BUFFER_BIT); + + const Track * const track = Track::getCurrentTrack(); + + // This function is only called once per frame - thus no need for setters. + float start = track->getFogStart() + .001f; + const video::SColor tmpcol = track->getFogColor(); + + core::vector3df col(tmpcol.getRed() / 255.0f, + tmpcol.getGreen() / 255.0f, + tmpcol.getBlue() / 255.0f); + + glDepthMask(GL_FALSE); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE, GL_ONE); + + glEnable(GL_DEPTH_TEST); + core::vector3df col2(1., 1., 1.); + + PointLightScatterShader::getInstance()->use(); + glBindVertexArray(PointLightScatterShader::getInstance()->vao); + + PointLightScatterShader::getInstance() + ->setTextureUnits(depth_stencil_texture); + PointLightScatterShader::getInstance() + ->setUniforms(1.f / (40.f * start), col2); + + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, + std::min(m_point_light_count, + LightBaseClass::MAXLIGHT)); + + glDisable(GL_BLEND); + post_processing->renderGaussian6Blur(half1_framebuffer, + half2_framebuffer, 5., 5.); + glEnable(GL_BLEND); + + glDisable(GL_DEPTH_TEST); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + colors_framebuffer.bind(); + post_processing->renderPassThrough(half1_framebuffer.getRTT()[0], + colors_framebuffer.getWidth(), + colors_framebuffer.getHeight()); +} // renderLightsScatter + +#endif diff --git a/src/graphics/materials.cpp b/src/graphics/materials.cpp index 38ef4aea7..866fa2a9d 100644 --- a/src/graphics/materials.cpp +++ b/src/graphics/materials.cpp @@ -16,9 +16,732 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "graphics/materials.hpp" +#include "graphics/vao_manager.hpp" #ifndef SERVER_ONLY +// ============================================================================ +// Solid Normal and depth pass shaders +ObjectPass1Shader::ObjectPass1Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + GL_FRAGMENT_SHADER, "object_pass1.frag"); + assignUniforms("ModelMatrix", "InverseModelMatrix"); + assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // ObjectPass1Shader + +// ============================================================================ +// Solid Lit pass shaders +ObjectPass2Shader::ObjectPass2Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + GL_FRAGMENT_SHADER, "object_pass2.frag"); + assignUniforms("ModelMatrix", "texture_trans", "color_change"); + 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); +} // ObjectPass2Shader + +// ============================================================================ +InstancedObjectPass1Shader::InstancedObjectPass1Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", + GL_FRAGMENT_SHADER, "instanced_object_pass1.frag"); + assignUniforms(); + assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // InstancedObjectPass1Shader + +// ============================================================================ +InstancedObjectRefPass1Shader::InstancedObjectRefPass1Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", + GL_FRAGMENT_SHADER, "instanced_objectref_pass1.frag"); + assignUniforms(); + assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 1, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // InstancedObjectRefPass1Shader + +// ============================================================================ +ObjectRefPass2Shader::ObjectRefPass2Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + GL_FRAGMENT_SHADER, "objectref_pass2.frag"); + assignUniforms("ModelMatrix", "texture_trans", "color_change"); + 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); +} // ObjectRefPass2Shader + +// ============================================================================ +InstancedObjectPass2Shader::InstancedObjectPass2Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.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); +} // InstancedObjectPass2Shader + +// ============================================================================ +InstancedObjectRefPass2Shader::InstancedObjectRefPass2Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.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); +} // InstancedObjectRefPass2Shader + +// ============================================================================ +ShadowShader::ShadowShader() +{ +#if !defined(USE_GLES2) + // Geometry shader needed + if (CVS->getGLSLVersion() < 150) + return; + if (CVS->isAMDVertexShaderLayerUsable()) + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "shadow.vert", + GL_FRAGMENT_SHADER, "shadow.frag"); + } + else + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "shadow.vert", + GL_GEOMETRY_SHADER, "shadow.geom", + GL_FRAGMENT_SHADER, "shadow.frag"); + } + assignUniforms("ModelMatrix", "layer"); +#endif +} // ShadowShader + +// ============================================================================ +InstancedShadowShader::InstancedShadowShader() +{ +#if !defined(USE_GLES2) + // Geometry shader needed + if (CVS->getGLSLVersion() < 150) + return; + if (CVS->isAMDVertexShaderLayerUsable()) + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_shadow.vert", + GL_FRAGMENT_SHADER, "shadow.frag"); + } + else + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_shadow.vert", + GL_GEOMETRY_SHADER, "instanced_shadow.geom", + GL_FRAGMENT_SHADER, "shadow.frag"); + } + assignUniforms("layer"); +#endif +} // InstancedShadowShader + +// ============================================================================ +CRSMShader::CRSMShader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "rsm.vert", + GL_FRAGMENT_SHADER, "rsm.frag"); + assignUniforms("ModelMatrix", "texture_trans", "RSMMatrix"); + assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // CRSMShader + +// ============================================================================ +SplattingRSMShader::SplattingRSMShader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "rsm.vert", + GL_FRAGMENT_SHADER, "splatting_rsm.frag"); + assignUniforms("ModelMatrix", "RSMMatrix"); + assignSamplerNames(0, "tex_layout", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 1, "tex_detail0", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 2, "tex_detail1", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 3, "tex_detail2", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 4, "tex_detail3", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // SplattingRSMShader + +// ============================================================================ +CInstancedRSMShader::CInstancedRSMShader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_rsm.vert", + GL_FRAGMENT_SHADER, "instanced_rsm.frag"); + assignUniforms("RSMMatrix"); + assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // CInstancedRSMShader + +// ============================================================================ +SphereMapShader::SphereMapShader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + GL_FRAGMENT_SHADER, "objectpass_spheremap.frag"); + assignUniforms("ModelMatrix", "InverseModelMatrix"); + assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, + 1, "SpecularMap", ST_NEAREST_FILTERED, + 2, "SSAO", ST_BILINEAR_FILTERED, + 3, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // SphereMapShader + +// ============================================================================ +InstancedSphereMapShader::InstancedSphereMapShader() +{ + loadProgram(OBJECT, + GL_VERTEX_SHADER, "instanced_object_pass.vert", + GL_FRAGMENT_SHADER, "instanced_objectpass_spheremap.frag"); + assignUniforms(); + assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, + 1, "SpecularMap", ST_NEAREST_FILTERED, + 2, "SSAO", ST_BILINEAR_FILTERED, + 3, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // InstancedSphereMapShader + +// ============================================================================ +SplattingShader::SplattingShader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + GL_FRAGMENT_SHADER, "splatting.frag"); + assignUniforms("ModelMatrix"); + assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, + 1, "SpecularMap", ST_NEAREST_FILTERED, + 2, "SSAO", ST_BILINEAR_FILTERED, + 3, "tex_layout", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 4, "tex_detail0", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 5, "tex_detail1", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 6, "tex_detail2", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 7, "tex_detail3", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // SplattingShader + +// ============================================================================ +ObjectRefPass1Shader::ObjectRefPass1Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + GL_FRAGMENT_SHADER, "objectref_pass1.frag"); + assignUniforms("ModelMatrix", "InverseModelMatrix", "texture_trans"); + assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 1, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // ObjectRefPass1Shader + +// ============================================================================ +NormalMapShader::NormalMapShader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + GL_FRAGMENT_SHADER, "normalmap.frag"); + assignUniforms("ModelMatrix", "InverseModelMatrix"); + assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 1, "glossMap", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // NormalMapShader + +// ============================================================================ +InstancedNormalMapShader::InstancedNormalMapShader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", + GL_FRAGMENT_SHADER, "instanced_normalmap.frag"); + assignUniforms(); + assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 1, "glossMap", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // InstancedNormalMapShader + +// ============================================================================ +ObjectUnlitShader::ObjectUnlitShader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + GL_FRAGMENT_SHADER, "object_unlit.frag"); + assignUniforms("ModelMatrix", "texture_trans"); + assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, + 1, "SpecularMap", ST_NEAREST_FILTERED, + 2, "SSAO", ST_BILINEAR_FILTERED, + 3, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // ObjectUnlitShader + +// ============================================================================ +InstancedObjectUnlitShader::InstancedObjectUnlitShader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.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); +} // InstancedObjectUnlitShader + +// ============================================================================ +RefShadowShader::RefShadowShader() +{ +#if !defined(USE_GLES2) + // Geometry shader needed + if (CVS->getGLSLVersion() < 150) + return; + if (CVS->isAMDVertexShaderLayerUsable()) + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "shadow.vert", + GL_FRAGMENT_SHADER, "shadowref.frag"); + } + else + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "shadow.vert", + GL_GEOMETRY_SHADER, "shadow.geom", + GL_FRAGMENT_SHADER, "shadowref.frag"); + } + assignUniforms("ModelMatrix", "layer"); + assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +#endif +} // RefShadowShader + +// ============================================================================ +InstancedRefShadowShader::InstancedRefShadowShader() +{ +#if !defined(USE_GLES2) + // Geometry shader needed + if (CVS->getGLSLVersion() < 150) + return; + if (CVS->isAMDVertexShaderLayerUsable()) + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_shadow.vert", + GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); + } + else + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_shadow.vert", + GL_GEOMETRY_SHADER, "instanced_shadow.geom", + GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); + } + assignUniforms("layer"); + assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +#endif +} // InstancedRefShadowShader + +// ============================================================================ +DisplaceMaskShader::DisplaceMaskShader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "displace.vert", + GL_FRAGMENT_SHADER, "white.frag"); + assignUniforms("ModelMatrix"); +} // DisplaceMaskShader + +// ============================================================================ +DisplaceShader::DisplaceShader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "displace.vert", + GL_FRAGMENT_SHADER, "displace.frag"); + assignUniforms("ModelMatrix", "dir", "dir2"); + assignSamplerNames(0, "displacement_tex", ST_BILINEAR_FILTERED, + 1, "color_tex", ST_BILINEAR_FILTERED, + 2, "mask_tex", ST_BILINEAR_FILTERED, + 3, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // DisplaceShader + +// ============================================================================ +NormalVisualizer::NormalVisualizer() +{ +#if !defined(USE_GLES2) + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", + GL_GEOMETRY_SHADER, "normal_visualizer.geom", + GL_FRAGMENT_SHADER, "coloredquad.frag"); + assignUniforms("color"); +#endif +} // NormalVisualizer + +// ============================================================================ +GrassPass1Shader::GrassPass1Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "grass_pass.vert", + GL_FRAGMENT_SHADER, "objectref_pass1.frag"); + assignUniforms("ModelMatrix", "InverseModelMatrix", "windDir"); + assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 1, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // GrassPass1Shader + +// ============================================================================ +InstancedGrassPass1Shader::InstancedGrassPass1Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_grass.vert", + GL_FRAGMENT_SHADER, "instanced_objectref_pass1.frag"); + assignUniforms("windDir"); + assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 1, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // InstancedGrassPass1Shader + +// ============================================================================ +GrassShadowShader::GrassShadowShader() +{ +#if !defined(USE_GLES2) + // Geometry shader needed + if (CVS->getGLSLVersion() < 150) + return; + if (CVS->isAMDVertexShaderLayerUsable()) + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "shadow_grass.vert", + GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); + } + else + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "shadow_grass.vert", + GL_GEOMETRY_SHADER, "shadow.geom", + GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); + } + assignUniforms("ModelMatrix", "windDir", "layer"); + assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +#endif +} // GrassShadowShader + +// ============================================================================ +InstancedGrassShadowShader::InstancedGrassShadowShader() +{ +#if !defined(USE_GLES2) + // Geometry shader needed + if (CVS->getGLSLVersion() < 150) + return; + if (CVS->isAMDVertexShaderLayerUsable()) + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_grassshadow.vert", + GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); + } + else + { + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_grassshadow.vert", + GL_GEOMETRY_SHADER, "instanced_shadow.geom", + GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); + } + assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); + assignUniforms("layer", "windDir"); +#endif +} // InstancedGrassShadowShader + +// ============================================================================ +GrassPass2Shader::GrassPass2Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "grass_pass.vert", + GL_FRAGMENT_SHADER, "grass_pass2.frag"); + assignUniforms("ModelMatrix", "windDir", "color_change"); + assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, + 1, "SpecularMap", ST_NEAREST_FILTERED, + 2, "SSAO", ST_BILINEAR_FILTERED, + 3, "dtex", ST_NEAREST_FILTERED, + 4, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 5, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 6, "colorization_mask", + ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // GrassPass2Shader + +// ============================================================================ +InstancedGrassPass2Shader::InstancedGrassPass2Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_grass.vert", + GL_FRAGMENT_SHADER, "instanced_grass_pass2.frag"); + assignUniforms("windDir"); + assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, + 1, "SpecularMap", ST_NEAREST_FILTERED, + 2, "SSAO", ST_BILINEAR_FILTERED, + 3, "dtex", ST_NEAREST_FILTERED, + 4, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 5, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 6, "colorization_mask", + ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // InstancedGrassPass2Shader + +// ============================================================================ +DetailedObjectPass2Shader::DetailedObjectPass2Shader() +{ + loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", + GL_FRAGMENT_SHADER, "detailed_object_pass2.frag"); + assignUniforms("ModelMatrix"); + assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, + 1, "SpecularMap", ST_NEAREST_FILTERED, + 2, "SSAO", ST_BILINEAR_FILTERED, + 3, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 4, "Detail", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 5, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // DetailedObjectPass2Shader + +// ============================================================================ +InstancedDetailedObjectPass2Shader::InstancedDetailedObjectPass2Shader() +{ + loadProgram(OBJECT, + GL_VERTEX_SHADER, "instanced_object_pass.vert", + GL_FRAGMENT_SHADER, "instanced_detailed_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, "Detail", ST_TRILINEAR_ANISOTROPIC_FILTERED, + 5, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // InstancedDetailedObjectPass2Shader + +// ============================================================================ +SkinnedPass1Shader::SkinnedPass1Shader() +{ + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning.vert", + GL_FRAGMENT_SHADER, "object_pass1.frag"); + assignUniforms("ModelMatrix", "InverseModelMatrix", "skinning_offset"); + assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // SkinnedPass1Shader + +// ============================================================================ +InstancedSkinnedPass1Shader::InstancedSkinnedPass1Shader() +{ + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(SKINNED_MESH, + GL_VERTEX_SHADER, "instanced_skinning.vert", + GL_FRAGMENT_SHADER, "instanced_object_pass1.frag"); + assignUniforms(); + assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); +} // InstancedSkinnedPass1Shader + +// ============================================================================ +SkinnedPass2Shader::SkinnedPass2Shader() +{ + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(SKINNED_MESH, 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 + +// ============================================================================ +InstancedSkinnedPass2Shader::InstancedSkinnedPass2Shader() +{ + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(SKINNED_MESH, + 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 + +// ============================================================================ +SkinnedRefPass1Shader::SkinnedRefPass1Shader() +{ + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(SKINNED_MESH, 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 + +// ============================================================================ +InstancedSkinnedRefPass1Shader::InstancedSkinnedRefPass1Shader() +{ + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(SKINNED_MESH, + 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 + +// ============================================================================ +SkinnedRefPass2Shader::SkinnedRefPass2Shader() +{ + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(SKINNED_MESH, 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 + +// ============================================================================ +InstancedSkinnedRefPass2Shader::InstancedSkinnedRefPass2Shader() +{ + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(SKINNED_MESH, + 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 + +// ============================================================================ +SkinnedUnlitShader::SkinnedUnlitShader() +{ + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(SKINNED_MESH, 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 + +// ============================================================================ +InstancedSkinnedUnlitShader::InstancedSkinnedUnlitShader() +{ + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(SKINNED_MESH, + 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 + +// ============================================================================ +SkinnedNormalMapShader::SkinnedNormalMapShader() +{ + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(SKINNED_MESH, 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 + +// ============================================================================ +InstancedSkinnedNormalMapShader::InstancedSkinnedNormalMapShader() +{ + if (!CVS->supportsHardwareSkinning()) return; + loadProgram(SKINNED_MESH, 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 + +// ============================================================================ +SkinnedShadowShader::SkinnedShadowShader() +{ +#if !defined(USE_GLES2) + // Geometry shader needed + if (CVS->getGLSLVersion() < 150 || !CVS->supportsHardwareSkinning()) + return; + if (CVS->isAMDVertexShaderLayerUsable()) + { + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning_shadow.vert", + GL_FRAGMENT_SHADER, "shadow.frag"); + } + else + { + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning_shadow.vert", + GL_GEOMETRY_SHADER, "shadow.geom", + GL_FRAGMENT_SHADER, "shadow.frag"); + } + assignUniforms("ModelMatrix", "skinning_offset", "layer"); +#endif +} // SkinnedShadowShader + +// ============================================================================ +InstancedSkinnedShadowShader::InstancedSkinnedShadowShader() +{ +#if !defined(USE_GLES2) + // Geometry shader needed + if (CVS->getGLSLVersion() < 150 || !CVS->supportsHardwareSkinning()) + return; + if (CVS->isAMDVertexShaderLayerUsable()) + { + loadProgram(SKINNED_MESH, + GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + GL_FRAGMENT_SHADER, "shadow.frag"); + } + else + { + loadProgram(SKINNED_MESH, + GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + GL_GEOMETRY_SHADER, "instanced_shadow.geom", + GL_FRAGMENT_SHADER, "shadow.frag"); + } + assignUniforms("layer"); +#endif +} // InstancedSkinnedShadowShader + +// ============================================================================ +SkinnedRefShadowShader::SkinnedRefShadowShader() +{ +#if !defined(USE_GLES2) + // Geometry shader needed + if (CVS->getGLSLVersion() < 150 || !CVS->supportsHardwareSkinning()) + return; + if (CVS->isAMDVertexShaderLayerUsable()) + { + loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning_shadow.vert", + GL_FRAGMENT_SHADER, "shadowref.frag"); + } + else + { + loadProgram(SKINNED_MESH, 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 + +// ============================================================================ +InstancedSkinnedRefShadowShader::InstancedSkinnedRefShadowShader() +{ +#if !defined(USE_GLES2) + // Geometry shader needed + if (CVS->getGLSLVersion() < 150 || !CVS->supportsHardwareSkinning()) + return; + if (CVS->isAMDVertexShaderLayerUsable()) + { + loadProgram(SKINNED_MESH, + GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", + GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); + } + else + { + loadProgram(SKINNED_MESH, + 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 + +// ============================================================================ +const InstanceType SkinnedSolid::Instance = InstanceTypeThreeTex; const STK::Tuple SkinnedSolid::FirstPassTextures = STK::Tuple(1); const STK::Tuple SkinnedSolid::SecondPassTextures @@ -27,21 +750,27 @@ const STK::Tuple<> SkinnedSolid::ShadowTextures; const STK::Tuple SkinnedSolid::RSMTextures = STK::Tuple(0); // ---------------------------------------------------------------------------- +const InstanceType SkinnedAlphaRef::Instance = InstanceTypeThreeTex; const STK::Tuple SkinnedAlphaRef::FirstPassTextures = STK::Tuple(0, 1); const STK::Tuple SkinnedAlphaRef::SecondPassTextures = STK::Tuple(0, 1, 2); -const STK::Tuple SkinnedAlphaRef::ShadowTextures = STK::Tuple(0); +const STK::Tuple SkinnedAlphaRef::ShadowTextures + = STK::Tuple(0); const STK::Tuple SkinnedAlphaRef::RSMTextures = STK::Tuple(0); // ---------------------------------------------------------------------------- +const InstanceType SkinnedUnlitMat::Instance = InstanceTypeThreeTex; const STK::Tuple SkinnedUnlitMat::FirstPassTextures = STK::Tuple(0, 1); -const STK::Tuple SkinnedUnlitMat::SecondPassTextures = STK::Tuple(0); -const STK::Tuple SkinnedUnlitMat::ShadowTextures = STK::Tuple(0); +const STK::Tuple SkinnedUnlitMat::SecondPassTextures + = STK::Tuple(0); +const STK::Tuple SkinnedUnlitMat::ShadowTextures + = STK::Tuple(0); const STK::Tuple SkinnedUnlitMat::RSMTextures = STK::Tuple(0); // ---------------------------------------------------------------------------- +const InstanceType SkinnedNormalMat::Instance = InstanceTypeFourTex; const STK::Tuple SkinnedNormalMat::FirstPassTextures = STK::Tuple(3, 1); const STK::Tuple SkinnedNormalMat::SecondPassTextures @@ -50,6 +779,7 @@ const STK::Tuple<> SkinnedNormalMat::ShadowTextures; const STK::Tuple SkinnedNormalMat::RSMTextures = STK::Tuple(0); // ---------------------------------------------------------------------------- +const InstanceType DefaultMaterial::Instance = InstanceTypeThreeTex; const STK::Tuple DefaultMaterial::FirstPassTextures = STK::Tuple(1); const STK::Tuple DefaultMaterial::SecondPassTextures @@ -58,6 +788,7 @@ const STK::Tuple<> DefaultMaterial::ShadowTextures; const STK::Tuple DefaultMaterial::RSMTextures = STK::Tuple(0); // ---------------------------------------------------------------------------- +const InstanceType AlphaRef::Instance = InstanceTypeThreeTex; const STK::Tuple AlphaRef::FirstPassTextures = STK::Tuple(0, 1); const STK::Tuple AlphaRef::SecondPassTextures @@ -66,12 +797,14 @@ const STK::Tuple AlphaRef::ShadowTextures = STK::Tuple(0); const STK::Tuple AlphaRef::RSMTextures = STK::Tuple(0); // ---------------------------------------------------------------------------- +const InstanceType SphereMap::Instance = InstanceTypeThreeTex; const STK::Tuple SphereMap::FirstPassTextures = STK::Tuple(1); const STK::Tuple SphereMap::SecondPassTextures = STK::Tuple(0); const STK::Tuple<> SphereMap::ShadowTextures; const STK::Tuple SphereMap::RSMTextures = STK::Tuple(0); // ---------------------------------------------------------------------------- +const InstanceType UnlitMat::Instance = InstanceTypeThreeTex; const STK::Tuple UnlitMat::FirstPassTextures = STK::Tuple(0, 1); const STK::Tuple UnlitMat::SecondPassTextures = STK::Tuple(0); @@ -79,6 +812,7 @@ const STK::Tuple UnlitMat::ShadowTextures = STK::Tuple(0); const STK::Tuple UnlitMat::RSMTextures = STK::Tuple(0); // ---------------------------------------------------------------------------- +const InstanceType GrassMat::Instance = InstanceTypeThreeTex; const STK::Tuple GrassMat::FirstPassTextures = STK::Tuple(0, 1); const STK::Tuple GrassMat::SecondPassTextures @@ -87,6 +821,7 @@ const STK::Tuple GrassMat::ShadowTextures = STK::Tuple(0); const STK::Tuple GrassMat::RSMTextures = STK::Tuple(0); // ---------------------------------------------------------------------------- +const InstanceType NormalMat::Instance = InstanceTypeFourTex; const STK::Tuple NormalMat::FirstPassTextures = STK::Tuple(3, 1); const STK::Tuple NormalMat::SecondPassTextures @@ -95,6 +830,7 @@ const STK::Tuple<> NormalMat::ShadowTextures; const STK::Tuple NormalMat::RSMTextures = STK::Tuple(0); // ---------------------------------------------------------------------------- +const InstanceType DetailMat::Instance = InstanceTypeFourTex; const STK::Tuple DetailMat::FirstPassTextures = STK::Tuple(1); const STK::Tuple DetailMat::SecondPassTextures = STK::Tuple(0, 3, 1); @@ -102,12 +838,15 @@ const STK::Tuple<> DetailMat::ShadowTextures; const STK::Tuple DetailMat::RSMTextures = STK::Tuple(0); // ---------------------------------------------------------------------------- -const STK::Tuple SplattingMat::FirstPassTextures = STK::Tuple(7); +const STK::Tuple SplattingMat::FirstPassTextures + = STK::Tuple(7); const STK::Tuple - SplattingMat::SecondPassTextures - = STK::Tuple(1, 3, 4, 5, 6); + SplattingMat::SecondPassTextures + = STK::Tuple(1, 3, 4, 5, 6); const STK::Tuple<> SplattingMat::ShadowTextures; -const STK::Tuple SplattingMat::RSMTextures +const STK::Tuple + SplattingMat::RSMTextures = STK::Tuple(1, 3, 4, 5, 6); +// ---------------------------------------------------------------------------- #endif diff --git a/src/graphics/materials.hpp b/src/graphics/materials.hpp index 7845a1654..955752975 100644 --- a/src/graphics/materials.hpp +++ b/src/graphics/materials.hpp @@ -20,333 +20,171 @@ #ifndef SERVER_ONLY -#include "graphics/shader.hpp" -#include "graphics/shaders.hpp" #include "graphics/stk_mesh.hpp" -#include "graphics/vao_manager.hpp" +#include "graphics/texture_shader.hpp" +enum InstanceType : unsigned int; // ============================================================================ -class InstancedObjectPass1Shader : public TextureShader +class ObjectPass1Shader : public TextureShader { public: - InstancedObjectPass1Shader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", - GL_FRAGMENT_SHADER, "instanced_object_pass1.frag"); - - assignUniforms(); - assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // InstancedObjectPass1Shader -}; // class InstancedObjectPass1Shader + ObjectPass1Shader(); +}; // ObjectPass1Shader // ============================================================================ -class InstancedObjectRefPass1Shader : public TextureShader +class ObjectPass2Shader : public TextureShader { public: - InstancedObjectRefPass1Shader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", - GL_FRAGMENT_SHADER, "instanced_objectref_pass1.frag"); + ObjectPass2Shader(); +}; // ObjectPass2Shader - assignUniforms(); - assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 1, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } +// ============================================================================ +class InstancedObjectPass1Shader + : public TextureShader +{ +public: + InstancedObjectPass1Shader(); +}; // InstancedObjectPass1Shader +// ============================================================================ +class InstancedObjectRefPass1Shader + : public TextureShader +{ +public: + InstancedObjectRefPass1Shader(); }; // InstancedObjectRefPass1Shader // ============================================================================ -class ObjectRefPass2Shader : public TextureShader +class ObjectRefPass2Shader: public TextureShader { public: - ObjectRefPass2Shader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "objectref_pass2.frag"); - assignUniforms("ModelMatrix", "texture_trans", "color_change"); - 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); - } // ObjectRefPass2Shader + ObjectRefPass2Shader(); }; // ObjectRefPass2Shader // ============================================================================ -class InstancedObjectPass2Shader : public TextureShader +class InstancedObjectPass2Shader + : public TextureShader { public: - InstancedObjectPass2Shader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.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); - } // InstancedObjectPass2Shader + InstancedObjectPass2Shader(); }; // InstancedObjectPass2Shader // ============================================================================ -class InstancedObjectRefPass2Shader : public TextureShader +class InstancedObjectRefPass2Shader + : public TextureShader { public: - InstancedObjectRefPass2Shader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.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); - } // InstancedObjectRefPass2Shader + InstancedObjectRefPass2Shader(); }; // InstancedObjectRefPass2Shader // ============================================================================ class ShadowShader : public TextureShader { public: - ShadowShader() - { -#if !defined(USE_GLES2) - // Geometry shader needed - if (CVS->getGLSLVersion() < 150) - return; - if (CVS->isAMDVertexShaderLayerUsable()) - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "shadow.vert", - GL_FRAGMENT_SHADER, "shadow.frag"); - } - else - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "shadow.vert", - GL_GEOMETRY_SHADER, "shadow.geom", - GL_FRAGMENT_SHADER, "shadow.frag"); - } - assignUniforms("ModelMatrix", "layer"); -#endif - } // ShadowShader + ShadowShader(); }; // ShadowShader // ============================================================================ -class InstancedShadowShader : public TextureShader +class InstancedShadowShader : public TextureShader { public: - InstancedShadowShader() - { -#if !defined(USE_GLES2) - // Geometry shader needed - if (CVS->getGLSLVersion() < 150) - return; - if (CVS->isAMDVertexShaderLayerUsable()) - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_shadow.vert", - GL_FRAGMENT_SHADER, "shadow.frag"); - } - else - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_shadow.vert", - GL_GEOMETRY_SHADER, "instanced_shadow.geom", - GL_FRAGMENT_SHADER, "shadow.frag"); - } - assignUniforms("layer"); -#endif - } // InstancedShadowShader - + InstancedShadowShader(); }; // InstancedShadowShader // ============================================================================ -class CRSMShader : public TextureShader +class CRSMShader : public TextureShader { public: - CRSMShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "rsm.vert", - GL_FRAGMENT_SHADER, "rsm.frag"); - - assignUniforms("ModelMatrix", "texture_trans", "RSMMatrix"); - assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // CRSMShader + CRSMShader(); }; // CRSMShader - // ============================================================================ -class SplattingRSMShader : public TextureShader +class SplattingRSMShader : public TextureShader { public: - SplattingRSMShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "rsm.vert", - GL_FRAGMENT_SHADER, "splatting_rsm.frag"); - - assignUniforms("ModelMatrix", "RSMMatrix"); - assignSamplerNames(0, "tex_layout", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 1, "tex_detail0", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 2, "tex_detail1", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 3, "tex_detail2", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 4, "tex_detail3", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // SplattingRSMShader - + SplattingRSMShader(); }; // SplattingRSMShader // ============================================================================ -class CInstancedRSMShader : public TextureShader +class CInstancedRSMShader : public TextureShader { public: - CInstancedRSMShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_rsm.vert", - GL_FRAGMENT_SHADER, "instanced_rsm.frag"); - - assignUniforms("RSMMatrix"); - assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // CInstancedRSMShader + CInstancedRSMShader(); }; // CInstancedRSMShader // ============================================================================ class SphereMapShader : public TextureShader + core::matrix4> { public: - SphereMapShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "objectpass_spheremap.frag"); - assignUniforms("ModelMatrix", "InverseModelMatrix"); - assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, - 1, "SpecularMap", ST_NEAREST_FILTERED, - 2, "SSAO", ST_BILINEAR_FILTERED, - 3, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // SphereMapShader + SphereMapShader(); }; // SphereMapShader // ============================================================================ -class InstancedSphereMapShader : public TextureShader +class InstancedSphereMapShader : public TextureShader { public: - InstancedSphereMapShader() - { - loadProgram(OBJECT, - GL_VERTEX_SHADER, "instanced_object_pass.vert", - GL_FRAGMENT_SHADER, "instanced_objectpass_spheremap.frag"); - assignUniforms(); - assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, - 1, "SpecularMap", ST_NEAREST_FILTERED, - 2, "SSAO", ST_BILINEAR_FILTERED, - 3, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // InstancedSphereMapShader + InstancedSphereMapShader(); }; // InstancedSphereMapShader // ============================================================================ class SplattingShader : public TextureShader { public: - SplattingShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "splatting.frag"); - assignUniforms("ModelMatrix"); - - assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, - 1, "SpecularMap", ST_NEAREST_FILTERED, - 2, "SSAO", ST_BILINEAR_FILTERED, - 3, "tex_layout", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 4, "tex_detail0", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 5, "tex_detail1", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 6, "tex_detail2", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 7, "tex_detail3", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // SplattingShader + SplattingShader(); }; // SplattingShader // ============================================================================ -class ObjectRefPass1Shader : public TextureShader +class ObjectRefPass1Shader : public TextureShader { public: - ObjectRefPass1Shader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "objectref_pass1.frag"); - assignUniforms("ModelMatrix", "InverseModelMatrix", "texture_trans"); - assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 1, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // ObjectRefPass1Shader + ObjectRefPass1Shader(); }; // ObjectRefPass1Shader - // ============================================================================ class NormalMapShader : public TextureShader + core::matrix4> { public: - NormalMapShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "normalmap.frag"); - assignUniforms("ModelMatrix", "InverseModelMatrix"); - assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 1, "glossMap", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // NormalMapShader - + NormalMapShader(); }; // NormalMapShader // ============================================================================ -class InstancedNormalMapShader : public TextureShader +class InstancedNormalMapShader : public TextureShader { public: - InstancedNormalMapShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", - GL_FRAGMENT_SHADER, "instanced_normalmap.frag"); - assignUniforms(); - assignSamplerNames(0, "normalMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 1, "glossMap", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // InstancedNormalMapShader + InstancedNormalMapShader(); }; // InstancedNormalMapShader // ============================================================================ -class ObjectUnlitShader : public TextureShader +class ObjectUnlitShader : public TextureShader { public: - ObjectUnlitShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "object_unlit.frag"); - assignUniforms("ModelMatrix", "texture_trans"); - assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, - 1, "SpecularMap", ST_NEAREST_FILTERED, - 2, "SSAO", ST_BILINEAR_FILTERED, - 3, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // ObjectUnlitShader + ObjectUnlitShader(); }; // ObjectUnlitShader // ============================================================================ -class InstancedObjectUnlitShader : public TextureShader +class InstancedObjectUnlitShader + : public TextureShader { public: - InstancedObjectUnlitShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.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); - } // InstancedObjectUnlitShader + InstancedObjectUnlitShader(); }; // InstancedObjectUnlitShader // ============================================================================ @@ -354,27 +192,7 @@ class RefShadowShader : public TextureShader { public: - RefShadowShader() - { -#if !defined(USE_GLES2) - // Geometry shader needed - if (CVS->getGLSLVersion() < 150) - return; - if (CVS->isAMDVertexShaderLayerUsable()) - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "shadow.vert", - GL_FRAGMENT_SHADER, "shadowref.frag"); - } - else - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "shadow.vert", - GL_GEOMETRY_SHADER, "shadow.geom", - GL_FRAGMENT_SHADER, "shadowref.frag"); - } - assignUniforms("ModelMatrix", "layer"); - assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); -#endif - } // RefShadowShader + RefShadowShader(); }; // RefShadowShader // ============================================================================ @@ -382,239 +200,96 @@ class InstancedRefShadowShader : public TextureShader { public: - InstancedRefShadowShader() - { -#if !defined(USE_GLES2) - // Geometry shader needed - if (CVS->getGLSLVersion() < 150) - return; - if (CVS->isAMDVertexShaderLayerUsable()) - { - loadProgram(OBJECT,GL_VERTEX_SHADER, "instanced_shadow.vert", - GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); - } - else - { - loadProgram(OBJECT,GL_VERTEX_SHADER, "instanced_shadow.vert", - GL_GEOMETRY_SHADER, "instanced_shadow.geom", - GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); - } - assignUniforms("layer"); - assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); -#endif - } // InstancedRefShadowShader + InstancedRefShadowShader(); }; // InstancedRefShadowShader // ============================================================================ class DisplaceMaskShader : public Shader { public: - DisplaceMaskShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "displace.vert", - GL_FRAGMENT_SHADER, "white.frag"); - assignUniforms("ModelMatrix"); - } // DisplaceMaskShader + DisplaceMaskShader(); }; // DisplaceMaskShader // ============================================================================ class DisplaceShader : public TextureShader + core::vector2df, core::vector2df> { public: - DisplaceShader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "displace.vert", - GL_FRAGMENT_SHADER, "displace.frag"); - assignUniforms("ModelMatrix", "dir", "dir2"); - - assignSamplerNames(0, "displacement_tex", ST_BILINEAR_FILTERED, - 1, "color_tex", ST_BILINEAR_FILTERED, - 2, "mask_tex", ST_BILINEAR_FILTERED, - 3, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // DisplaceShader + DisplaceShader(); }; // DisplaceShader // ============================================================================ class NormalVisualizer : public Shader { public: - NormalVisualizer() - { -#if !defined(USE_GLES2) - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert", - GL_GEOMETRY_SHADER, "normal_visualizer.geom", - GL_FRAGMENT_SHADER, "coloredquad.frag"); - assignUniforms("color"); -#endif - } // NormalVisualizer + NormalVisualizer(); }; // NormalVisualizer // ============================================================================ -class GrassPass1Shader : public TextureShader +class GrassPass1Shader : public TextureShader { public: - GrassPass1Shader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "grass_pass.vert", - GL_FRAGMENT_SHADER, "objectref_pass1.frag"); - assignUniforms("ModelMatrix", "InverseModelMatrix", "windDir"); - assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 1, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // GrassPass1Shader - -}; // class GrassPass1Shader + GrassPass1Shader(); +}; // GrassPass1Shader // ============================================================================ -class InstancedGrassPass1Shader : public TextureShader +class InstancedGrassPass1Shader + : public TextureShader { public: - InstancedGrassPass1Shader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_grass.vert", - GL_FRAGMENT_SHADER, "instanced_objectref_pass1.frag"); - assignUniforms("windDir"); - assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 1, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // InstancedGrassPass1Shader + InstancedGrassPass1Shader(); }; // InstancedGrassPass1Shader // ============================================================================ -class GrassShadowShader : public TextureShader +class GrassShadowShader : public TextureShader { public: - GrassShadowShader() - { -#if !defined(USE_GLES2) - // Geometry shader needed - if (CVS->getGLSLVersion() < 150) - return; - if (CVS->isAMDVertexShaderLayerUsable()) - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "shadow_grass.vert", - GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); - } - else - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "shadow_grass.vert", - GL_GEOMETRY_SHADER, "shadow.geom", - GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); - } - assignUniforms("ModelMatrix", "windDir", "layer"); - assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); -#endif - } // GrassShadowShader + GrassShadowShader(); }; // GrassShadowShader // ============================================================================ -class InstancedGrassShadowShader : public TextureShader +class InstancedGrassShadowShader + : public TextureShader { public: - InstancedGrassShadowShader() - { -#if !defined(USE_GLES2) - // Geometry shader needed - if (CVS->getGLSLVersion() < 150) - return; - if (CVS->isAMDVertexShaderLayerUsable()) - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_grassshadow.vert", - GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); - } - else - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_grassshadow.vert", - GL_GEOMETRY_SHADER, "instanced_shadow.geom", - GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); - } - - assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - assignUniforms("layer", "windDir"); -#endif - } // InstancedGrassShadowShader + InstancedGrassShadowShader(); }; // InstancedGrassShadowShader - // ============================================================================ -class GrassPass2Shader : public TextureShader +class GrassPass2Shader : public TextureShader { public: - GrassPass2Shader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "grass_pass.vert", - GL_FRAGMENT_SHADER, "grass_pass2.frag"); - assignUniforms("ModelMatrix", "windDir", "color_change"); - assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, - 1, "SpecularMap", ST_NEAREST_FILTERED, - 2, "SSAO", ST_BILINEAR_FILTERED, - 3, "dtex", ST_NEAREST_FILTERED, - 4, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 5, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 6, "colorization_mask", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // GrassPass2Shader + GrassPass2Shader(); }; // GrassPass2Shader // ============================================================================ -class InstancedGrassPass2Shader : public TextureShader +class InstancedGrassPass2Shader + : public TextureShader { public: - InstancedGrassPass2Shader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_grass.vert", - GL_FRAGMENT_SHADER, "instanced_grass_pass2.frag"); - assignUniforms("windDir"); - assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, - 1, "SpecularMap", ST_NEAREST_FILTERED, - 2, "SSAO", ST_BILINEAR_FILTERED, - 3, "dtex", ST_NEAREST_FILTERED, - 4, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 5, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 6, "colorization_mask", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // InstancedGrassPass2Shader + InstancedGrassPass2Shader(); }; // InstancedGrassPass2Shader // ============================================================================ -class DetailedObjectPass2Shader : public TextureShader +class DetailedObjectPass2Shader + : public TextureShader { public: - DetailedObjectPass2Shader() - { - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "detailed_object_pass2.frag"); - assignUniforms("ModelMatrix"); - assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED, - 1, "SpecularMap", ST_NEAREST_FILTERED, - 2, "SSAO", ST_BILINEAR_FILTERED, - 3, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 4, "Detail", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 5, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // DetailedObjectPass2Shader + DetailedObjectPass2Shader(); }; // DetailedObjectPass2Shader // ============================================================================ -class InstancedDetailedObjectPass2Shader : public TextureShader +class InstancedDetailedObjectPass2Shader + : public TextureShader { public: - InstancedDetailedObjectPass2Shader() - { - loadProgram(OBJECT, - GL_VERTEX_SHADER, "instanced_object_pass.vert", - GL_FRAGMENT_SHADER, "instanced_detailed_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, "Detail", ST_TRILINEAR_ANISOTROPIC_FILTERED, - 5, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // InstancedDetailedObjectPass2Shader + InstancedDetailedObjectPass2Shader(); }; // InstancedDetailedObjectPass2Shader // ============================================================================ @@ -623,28 +298,15 @@ class SkinnedPass1Shader : public TextureShader { public: - SkinnedPass1Shader() - { - if (!CVS->supportsHardwareSkinning()) return; - loadProgram(SKINNED_MESH, 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(); }; // SkinnedPass1Shader // ============================================================================ -class InstancedSkinnedPass1Shader : public TextureShader +class InstancedSkinnedPass1Shader + : public TextureShader { public: - InstancedSkinnedPass1Shader() - { - if (!CVS->supportsHardwareSkinning()) return; - loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning.vert", - GL_FRAGMENT_SHADER, "instanced_object_pass1.frag"); - assignUniforms(); - assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED); - } // InstancedSkinnedPass1Shader + InstancedSkinnedPass1Shader(); }; // InstancedSkinnedPass1Shader // ============================================================================ @@ -653,39 +315,15 @@ class SkinnedPass2Shader : public TextureShader { public: - SkinnedPass2Shader() - { - if (!CVS->supportsHardwareSkinning()) return; - loadProgram(SKINNED_MESH, 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(); }; // SkinnedPass2Shader // ============================================================================ -class InstancedSkinnedPass2Shader : public TextureShader +class InstancedSkinnedPass2Shader + : public TextureShader { public: - InstancedSkinnedPass2Shader() - { - if (!CVS->supportsHardwareSkinning()) return; - loadProgram(SKINNED_MESH, 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(); }; // InstancedSkinnedPass2Shader // ============================================================================ @@ -695,31 +333,15 @@ class SkinnedRefPass1Shader : public TextureShader { public: - SkinnedRefPass1Shader() - { - if (!CVS->supportsHardwareSkinning()) return; - loadProgram(SKINNED_MESH, 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(); }; // SkinnedRefPass1Shader // ============================================================================ -class InstancedSkinnedRefPass1Shader : public TextureShader +class InstancedSkinnedRefPass1Shader + : public TextureShader { public: - InstancedSkinnedRefPass1Shader() - { - if (!CVS->supportsHardwareSkinning()) return; - loadProgram(SKINNED_MESH, 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(); }; // InstancedSkinnedRefPass1Shader // ============================================================================ @@ -729,39 +351,15 @@ class SkinnedRefPass2Shader : public TextureShader { public: - SkinnedRefPass2Shader() - { - if (!CVS->supportsHardwareSkinning()) return; - loadProgram(SKINNED_MESH, 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(); }; // SkinnedRefPass2Shader // ============================================================================ -class InstancedSkinnedRefPass2Shader : public TextureShader +class InstancedSkinnedRefPass2Shader + : public TextureShader { public: - InstancedSkinnedRefPass2Shader() - { - if (!CVS->supportsHardwareSkinning()) return; - loadProgram(SKINNED_MESH, 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(); }; // InstancedSkinnedRefPass2Shader // ============================================================================ @@ -770,34 +368,15 @@ class SkinnedUnlitShader : public TextureShader { public: - SkinnedUnlitShader() - { - if (!CVS->supportsHardwareSkinning()) return; - loadProgram(SKINNED_MESH, 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(); }; // SkinnedUnlitShader // ============================================================================ -class InstancedSkinnedUnlitShader : public TextureShader +class InstancedSkinnedUnlitShader + : public TextureShader { public: - InstancedSkinnedUnlitShader() - { - if (!CVS->supportsHardwareSkinning()) return; - loadProgram(SKINNED_MESH, 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(); }; // InstancedSkinnedUnlitShader // ============================================================================ @@ -806,30 +385,15 @@ class SkinnedNormalMapShader : public TextureShader { public: - SkinnedNormalMapShader() - { - if (!CVS->supportsHardwareSkinning()) return; - loadProgram(SKINNED_MESH, 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(); }; // SkinnedNormalMapShader // ============================================================================ -class InstancedSkinnedNormalMapShader : public TextureShader +class InstancedSkinnedNormalMapShader + : public TextureShader { public: - InstancedSkinnedNormalMapShader() - { - if (!CVS->supportsHardwareSkinning()) return; - loadProgram(SKINNED_MESH, 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(); }; // InstancedSkinnedNormalMapShader // ============================================================================ @@ -837,52 +401,15 @@ class SkinnedShadowShader : public TextureShader { public: - SkinnedShadowShader() - { -#if !defined(USE_GLES2) - // Geometry shader needed - if (CVS->getGLSLVersion() < 150 || !CVS->supportsHardwareSkinning()) - return; - if (CVS->isAMDVertexShaderLayerUsable()) - { - loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning_shadow.vert", - GL_FRAGMENT_SHADER, "shadow.frag"); - } - else - { - loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning_shadow.vert", - GL_GEOMETRY_SHADER, "shadow.geom", - GL_FRAGMENT_SHADER, "shadow.frag"); - } - assignUniforms("ModelMatrix", "skinning_offset", "layer"); -#endif - } // SkinnedShadowShader + SkinnedShadowShader(); }; // SkinnedShadowShader // ============================================================================ -class InstancedSkinnedShadowShader : public TextureShader +class InstancedSkinnedShadowShader + : public TextureShader { public: - InstancedSkinnedShadowShader() - { -#if !defined(USE_GLES2) - // Geometry shader needed - if (CVS->getGLSLVersion() < 150 || !CVS->supportsHardwareSkinning()) - return; - if (CVS->isAMDVertexShaderLayerUsable()) - { - loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", - GL_FRAGMENT_SHADER, "shadow.frag"); - } - else - { - loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", - GL_GEOMETRY_SHADER, "instanced_shadow.geom", - GL_FRAGMENT_SHADER, "shadow.frag"); - } - assignUniforms("layer"); -#endif - } // InstancedSkinnedShadowShader + InstancedSkinnedShadowShader(); }; // InstancedSkinnedShadowShader // ============================================================================ @@ -890,55 +417,15 @@ class SkinnedRefShadowShader : public TextureShader { public: - SkinnedRefShadowShader() - { -#if !defined(USE_GLES2) - // Geometry shader needed - if (CVS->getGLSLVersion() < 150 || !CVS->supportsHardwareSkinning()) - return; - if (CVS->isAMDVertexShaderLayerUsable()) - { - loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "skinning_shadow.vert", - GL_FRAGMENT_SHADER, "shadowref.frag"); - } - else - { - loadProgram(SKINNED_MESH, 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(); }; // SkinnedRefShadowShader // ============================================================================ -class InstancedSkinnedRefShadowShader : public TextureShader +class InstancedSkinnedRefShadowShader + : public TextureShader { public: - InstancedSkinnedRefShadowShader() - { -#if !defined(USE_GLES2) - // Geometry shader needed - if (CVS->getGLSLVersion() < 150 || !CVS->supportsHardwareSkinning()) - return; - if (CVS->isAMDVertexShaderLayerUsable()) - { - loadProgram(SKINNED_MESH, GL_VERTEX_SHADER, "instanced_skinning_shadow.vert", - GL_FRAGMENT_SHADER, "instanced_shadowref.frag"); - } - else - { - loadProgram(SKINNED_MESH, 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(); }; // InstancedSkinnedRefShadowShader // ============================================================================ @@ -955,12 +442,12 @@ struct SkinnedSolid 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 enum InstanceType Instance; static const STK::Tuple FirstPassTextures; static const STK::Tuple SecondPassTextures; static const STK::Tuple<> ShadowTextures; static const STK::Tuple RSMTextures; -}; // struct SkinnedSolid +}; // SkinnedSolid // ---------------------------------------------------------------------------- struct SkinnedAlphaRef @@ -976,12 +463,12 @@ struct SkinnedAlphaRef 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 enum InstanceType Instance; static const STK::Tuple FirstPassTextures; static const STK::Tuple SecondPassTextures; static const STK::Tuple ShadowTextures; static const STK::Tuple RSMTextures; -}; // struct SkinnedAlphaRef +}; // SkinnedAlphaRef // ---------------------------------------------------------------------------- struct SkinnedNormalMat @@ -997,12 +484,12 @@ struct SkinnedNormalMat 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 enum InstanceType Instance; static const STK::Tuple FirstPassTextures; static const STK::Tuple SecondPassTextures; static const STK::Tuple<> ShadowTextures; static const STK::Tuple RSMTextures; -}; // struct SkinnedNormalMat +}; // SkinnedNormalMat // ---------------------------------------------------------------------------- struct SkinnedUnlitMat @@ -1018,12 +505,12 @@ struct SkinnedUnlitMat 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 enum InstanceType Instance; static const STK::Tuple FirstPassTextures; static const STK::Tuple SecondPassTextures; static const STK::Tuple ShadowTextures; static const STK::Tuple RSMTextures; -}; // struct SkinnedUnlitMat +}; // SkinnedUnlitMat // ---------------------------------------------------------------------------- struct DefaultMaterial @@ -1032,20 +519,20 @@ struct DefaultMaterial typedef InstancedObjectPass2Shader InstancedSecondPassShader; typedef InstancedShadowShader InstancedShadowPassShader; typedef CInstancedRSMShader InstancedRSMShader; - typedef Shaders::ObjectPass1Shader FirstPassShader; - typedef Shaders::ObjectPass2Shader SecondPassShader; + typedef ObjectPass1Shader FirstPassShader; + typedef ObjectPass2Shader SecondPassShader; typedef ShadowShader ShadowPassShader; typedef CRSMShader RSMShader; typedef ListMatDefault List; static const enum video::E_VERTEX_TYPE VertexType = video::EVT_STANDARD; static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_SOLID; - static const enum InstanceType Instance = InstanceTypeThreeTex; + static const enum InstanceType Instance; static const STK::Tuple FirstPassTextures; static const STK::Tuple SecondPassTextures; static const STK::Tuple<> ShadowTextures; static const STK::Tuple RSMTextures; -}; // struct DefaultMaterial +}; // DefaultMaterial // ---------------------------------------------------------------------------- struct AlphaRef @@ -1061,12 +548,12 @@ struct AlphaRef typedef ListMatAlphaRef List; static const enum video::E_VERTEX_TYPE VertexType = video::EVT_STANDARD; static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_ALPHA_TEST; - static const enum InstanceType Instance = InstanceTypeThreeTex; + static const enum InstanceType Instance; static const STK::Tuple FirstPassTextures; static const STK::Tuple SecondPassTextures; static const STK::Tuple ShadowTextures; static const STK::Tuple RSMTextures; -}; // struct AlphaRef +}; // AlphaRef // ---------------------------------------------------------------------------- struct SphereMap @@ -1075,7 +562,7 @@ struct SphereMap typedef InstancedSphereMapShader InstancedSecondPassShader; typedef InstancedShadowShader InstancedShadowPassShader; typedef CInstancedRSMShader InstancedRSMShader; - typedef Shaders::ObjectPass1Shader FirstPassShader; + typedef ObjectPass1Shader FirstPassShader; typedef SphereMapShader SecondPassShader; typedef ShadowShader ShadowPassShader; typedef CRSMShader RSMShader; @@ -1083,12 +570,12 @@ struct SphereMap static const enum video::E_VERTEX_TYPE VertexType = video::EVT_STANDARD; static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_SPHERE_MAP; - static const enum InstanceType Instance = InstanceTypeThreeTex; + static const enum InstanceType Instance; static const STK::Tuple FirstPassTextures; static const STK::Tuple SecondPassTextures; static const STK::Tuple<> ShadowTextures; static const STK::Tuple RSMTextures; -}; // struct SphereMap +}; // SphereMap // ---------------------------------------------------------------------------- struct UnlitMat @@ -1105,12 +592,12 @@ struct UnlitMat static const enum video::E_VERTEX_TYPE VertexType = video::EVT_STANDARD; static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_SOLID_UNLIT; - static const enum InstanceType Instance = InstanceTypeThreeTex; + static const enum InstanceType Instance; static const STK::Tuple FirstPassTextures; static const STK::Tuple SecondPassTextures; static const STK::Tuple ShadowTextures; static const STK::Tuple RSMTextures; -}; // struct UnlitMat +}; // UnlitMat // ---------------------------------------------------------------------------- struct GrassMat @@ -1127,7 +614,7 @@ struct GrassMat static const enum video::E_VERTEX_TYPE VertexType = video::EVT_STANDARD; static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_VEGETATION; - static const enum InstanceType Instance = InstanceTypeThreeTex; + static const enum InstanceType Instance; static const STK::Tuple FirstPassTextures; static const STK::Tuple SecondPassTextures; static const STK::Tuple ShadowTextures; @@ -1142,14 +629,14 @@ struct NormalMat typedef InstancedShadowShader InstancedShadowPassShader; typedef CInstancedRSMShader InstancedRSMShader; typedef NormalMapShader FirstPassShader; - typedef Shaders::ObjectPass2Shader SecondPassShader; + typedef ObjectPass2Shader SecondPassShader; typedef ShadowShader ShadowPassShader; typedef CRSMShader RSMShader; typedef ListMatNormalMap List; static const enum video::E_VERTEX_TYPE VertexType = video::EVT_TANGENTS; static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_NORMAL_MAP; - static const enum InstanceType Instance = InstanceTypeFourTex; + static const enum InstanceType Instance; static const STK::Tuple FirstPassTextures; static const STK::Tuple SecondPassTextures; static const STK::Tuple<> ShadowTextures; @@ -1163,7 +650,7 @@ struct DetailMat typedef InstancedDetailedObjectPass2Shader InstancedSecondPassShader; typedef InstancedShadowShader InstancedShadowPassShader; typedef CInstancedRSMShader InstancedRSMShader; - typedef Shaders::ObjectPass1Shader FirstPassShader; + typedef ObjectPass1Shader FirstPassShader; typedef DetailedObjectPass2Shader SecondPassShader; typedef ShadowShader ShadowPassShader; typedef CRSMShader RSMShader; @@ -1171,7 +658,7 @@ struct DetailMat static const enum video::E_VERTEX_TYPE VertexType = video::EVT_2TCOORDS; static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_DETAIL_MAP; - static const enum InstanceType Instance = InstanceTypeFourTex; + static const enum InstanceType Instance; static const STK::Tuple FirstPassTextures; static const STK::Tuple SecondPassTextures; static const STK::Tuple<> ShadowTextures; @@ -1183,20 +670,21 @@ struct SplattingMat { typedef InstancedObjectPass1Shader InstancedFirstPassShader; typedef InstancedShadowShader InstancedShadowPassShader; - typedef Shaders::ObjectPass1Shader FirstPassShader; + typedef ObjectPass1Shader FirstPassShader; typedef SplattingShader SecondPassShader; typedef ShadowShader ShadowPassShader; typedef SplattingRSMShader RSMShader; typedef ListMatSplatting List; static const enum video::E_VERTEX_TYPE VertexType = video::EVT_2TCOORDS; static const enum Material::ShaderType MaterialType - = Material::SHADERTYPE_SPLATTING; + = Material::SHADERTYPE_SPLATTING; static const STK::Tuple FirstPassTextures; - static const STK::Tuple SecondPassTextures; + static const STK::Tuple + SecondPassTextures; static const STK::Tuple<> ShadowTextures; - static const STK::Tuple RSMTextures; + static const STK::Tuple + RSMTextures; }; // SplattingMat - #endif // !SERVER_ONLY #endif // HEADER_MATERIAL_TYPE_HPP diff --git a/src/graphics/particle_emitter.cpp b/src/graphics/particle_emitter.cpp index dae6c5bdf..8150d0cde 100644 --- a/src/graphics/particle_emitter.cpp +++ b/src/graphics/particle_emitter.cpp @@ -26,7 +26,6 @@ #include "graphics/material.hpp" #include "graphics/material_manager.hpp" #include "graphics/particle_kind.hpp" -#include "graphics/shaders.hpp" #include "graphics/wind.hpp" #include "io/file_manager.hpp" #include "tracks/track.hpp" diff --git a/src/graphics/rtts.cpp b/src/graphics/rtts.cpp index 090bacd32..f247379b2 100644 --- a/src/graphics/rtts.cpp +++ b/src/graphics/rtts.cpp @@ -22,7 +22,7 @@ #include "config/user_config.hpp" #include "graphics/central_settings.hpp" #include "graphics/glwrap.hpp" -#include "graphics/shaders.hpp" +#include "graphics/materials.hpp" #include "utils/log.hpp" static GLuint generateRTT3D(GLenum target, size_t w, size_t h, size_t d, GLint internalFormat, GLint format, GLint type, unsigned mipmaplevel = 1) @@ -299,22 +299,22 @@ RTT::RTT(size_t width, size_t height) { uint64_t handle = glGetTextureSamplerHandleARB(getRenderTarget(RTT_DIFFUSE), - Shaders::ObjectPass2Shader::getInstance()->m_sampler_ids[0]); + ObjectPass2Shader::getInstance()->m_sampler_ids[0]); glMakeTextureHandleResidentARB(handle); m_prefilled_handles.push_back(handle); handle = glGetTextureSamplerHandleARB(getRenderTarget(RTT_SPECULAR), - Shaders::ObjectPass2Shader::getInstance()->m_sampler_ids[1]); + ObjectPass2Shader::getInstance()->m_sampler_ids[1]); glMakeTextureHandleResidentARB(handle); m_prefilled_handles.push_back(handle); handle = glGetTextureSamplerHandleARB(getRenderTarget(RTT_HALF1_R), - Shaders::ObjectPass2Shader::getInstance()->m_sampler_ids[2]); + ObjectPass2Shader::getInstance()->m_sampler_ids[2]); glMakeTextureHandleResidentARB(handle); m_prefilled_handles.push_back(handle); handle = glGetTextureSamplerHandleARB(getDepthStencilTexture(), - Shaders::ObjectPass2Shader::getInstance()->m_sampler_ids[3]); + ObjectPass2Shader::getInstance()->m_sampler_ids[3]); glMakeTextureHandleResidentARB(handle); m_prefilled_handles.push_back(handle); } diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index 5c623d329..13befde7a 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -273,31 +273,6 @@ void Shaders::check(const int num) } } // check -// ============================================================================ -// Solid Normal and depth pass shaders -Shaders::ObjectPass1Shader::ObjectPass1Shader() -{ - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "object_pass1.frag"); - assignUniforms("ModelMatrix", "InverseModelMatrix"); - assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); -} // ObjectPass1Shader - -// ============================================================================ -// Solid Lit pass shaders -Shaders::ObjectPass2Shader::ObjectPass2Shader() -{ - loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert", - GL_FRAGMENT_SHADER, "object_pass2.frag"); - assignUniforms("ModelMatrix", "texture_trans", "color_change"); - 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); -} // ObjectPass2Shader - // ============================================================================ Shaders::SkinnedTransparentShader::SkinnedTransparentShader() { diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index 57231d84b..7aa4f8f6c 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -137,23 +137,6 @@ public: public: TransparentFogShader(); }; // TransparentFogShader - // ======================================================================== - class ObjectPass1Shader : public TextureShader - { - public: - ObjectPass1Shader(); - }; // ObjectPass1Shader - - // ======================================================================== - class ObjectPass2Shader : public TextureShader < ObjectPass2Shader, 6, - core::matrix4, core::vector2df, - core::vector2df > - { - public: - ObjectPass2Shader(); - }; // ObjectPass2Shader - // ======================================================================== class SkinnedTransparentShader : public TextureShader #include diff --git a/src/graphics/stk_billboard.cpp b/src/graphics/stk_billboard.cpp index 573a0348b..92e9c5985 100644 --- a/src/graphics/stk_billboard.cpp +++ b/src/graphics/stk_billboard.cpp @@ -22,9 +22,9 @@ #include "graphics/irr_driver.hpp" #include "graphics/material.hpp" #include "graphics/material_manager.hpp" -#include "graphics/shaders.hpp" #include "graphics/shared_gpu_objects.hpp" #include "graphics/texture_manager.hpp" +#include "graphics/texture_shader.hpp" #include diff --git a/src/graphics/stk_mesh.cpp b/src/graphics/stk_mesh.cpp index 68519c590..127c2d9af 100644 --- a/src/graphics/stk_mesh.cpp +++ b/src/graphics/stk_mesh.cpp @@ -23,6 +23,7 @@ #include "graphics/central_settings.hpp" #include "graphics/irr_driver.hpp" #include "graphics/material_manager.hpp" +#include "graphics/materials.hpp" #include "graphics/shaders.hpp" #include "graphics/texture_manager.hpp" @@ -398,7 +399,7 @@ static void setTexture(GLMesh &mesh, unsigned i, bool is_srgb, { mesh.TextureHandles[i] = glGetTextureSamplerHandleARB( getTextureGLuint(mesh.textures[i]), - Shaders::ObjectPass1Shader::getInstance()->m_sampler_ids[0]); + ObjectPass1Shader::getInstance()->m_sampler_ids[0]); } if (!glIsTextureHandleResidentARB(mesh.TextureHandles[i])) { @@ -488,7 +489,7 @@ void initTexturesTransparent(GLMesh &mesh) { mesh.TextureHandles[0] = glGetTextureSamplerHandleARB( getTextureGLuint(mesh.textures[0]), - Shaders::ObjectPass1Shader::getInstance()->m_sampler_ids[0]); + ObjectPass1Shader::getInstance()->m_sampler_ids[0]); } if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0])) { diff --git a/src/graphics/stk_mesh_scene_node.cpp b/src/graphics/stk_mesh_scene_node.cpp index 77ffe2233..8246d8130 100644 --- a/src/graphics/stk_mesh_scene_node.cpp +++ b/src/graphics/stk_mesh_scene_node.cpp @@ -22,9 +22,10 @@ #include "graphics/central_settings.hpp" #include "graphics/irr_driver.hpp" #include "graphics/material_manager.hpp" +#include "graphics/materials.hpp" #include "graphics/render_info.hpp" #include "graphics/rtts.hpp" -#include "graphics/stk_mesh.hpp" +#include "graphics/shaders.hpp" #include "graphics/texture_manager.hpp" #include "graphics/vao_manager.hpp" #include "tracks/track.hpp" @@ -344,7 +345,7 @@ void STKMeshSceneNode::render() glDisable(GL_CULL_FACE); if (update_each_frame) updatevbo(); - Shaders::ObjectPass1Shader::getInstance()->use(); + ObjectPass1Shader::getInstance()->use(); // Only untextured for (unsigned i = 0; i < GLmeshes.size(); i++) { @@ -362,7 +363,7 @@ void STKMeshSceneNode::render() { mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), - Shaders::ObjectPass1Shader + ObjectPass1Shader ::getInstance()->m_sampler_ids[0]); } if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0])) @@ -370,12 +371,12 @@ void STKMeshSceneNode::render() glMakeTextureHandleResidentARB(mesh.TextureHandles[0]); insertTextureHandle(mesh.TextureHandles[0]); } - Shaders::ObjectPass1Shader::getInstance()->setTextureHandles(mesh.TextureHandles[0]); + ObjectPass1Shader::getInstance()->setTextureHandles(mesh.TextureHandles[0]); } else #endif - Shaders::ObjectPass1Shader::getInstance()->setTextureUnits(getTextureGLuint(mesh.textures[0])); - Shaders::ObjectPass1Shader::getInstance()->setUniforms(AbsoluteTransformation, invmodel); + ObjectPass1Shader::getInstance()->setTextureUnits(getTextureGLuint(mesh.textures[0])); + ObjectPass1Shader::getInstance()->setUniforms(AbsoluteTransformation, invmodel); assert(mesh.vao); glBindVertexArray(mesh.vao); glDrawElements(ptype, count, itype, 0); @@ -393,7 +394,7 @@ void STKMeshSceneNode::render() glDisable(GL_CULL_FACE); if (update_each_frame && !CVS->isDefferedEnabled()) updatevbo(); - Shaders::ObjectPass2Shader::getInstance()->use(); + ObjectPass2Shader::getInstance()->use(); // Only untextured for (unsigned i = 0; i < GLmeshes.size(); i++) { @@ -408,21 +409,21 @@ void STKMeshSceneNode::render() { GLuint64 DiffuseHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_DIFFUSE), - Shaders::ObjectPass2Shader + ObjectPass2Shader ::getInstance()->m_sampler_ids[0]); GLuint64 SpecularHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_SPECULAR), - Shaders::ObjectPass2Shader::getInstance()->m_sampler_ids[1]); + ObjectPass2Shader::getInstance()->m_sampler_ids[1]); GLuint64 SSAOHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_HALF1_R), - Shaders::ObjectPass2Shader::getInstance()->m_sampler_ids[2]); + ObjectPass2Shader::getInstance()->m_sampler_ids[2]); if (!mesh.TextureHandles[0]) mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), - Shaders::ObjectPass1Shader::getInstance()->m_sampler_ids[0]); + ObjectPass1Shader::getInstance()->m_sampler_ids[0]); if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0])) { glMakeTextureHandleResidentARB(mesh.TextureHandles[0]); @@ -432,7 +433,7 @@ void STKMeshSceneNode::render() if (!mesh.TextureHandles[1]) mesh.TextureHandles[1] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[1]), - Shaders::ObjectPass1Shader::getInstance()->m_sampler_ids[0]); + ObjectPass1Shader::getInstance()->m_sampler_ids[0]); if (!glIsTextureHandleResidentARB(mesh.TextureHandles[1])) { glMakeTextureHandleResidentARB(mesh.TextureHandles[1]); @@ -442,28 +443,28 @@ void STKMeshSceneNode::render() if (!mesh.TextureHandles[2]) mesh.TextureHandles[2] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[2]), - Shaders::ObjectPass1Shader::getInstance()->m_sampler_ids[0]); + ObjectPass1Shader::getInstance()->m_sampler_ids[0]); if (!glIsTextureHandleResidentARB(mesh.TextureHandles[2])) { glMakeTextureHandleResidentARB(mesh.TextureHandles[2]); insertTextureHandle(mesh.TextureHandles[2]); } - Shaders::ObjectPass2Shader::getInstance() + ObjectPass2Shader::getInstance() ->setTextureHandles(DiffuseHandle, SpecularHandle, SSAOHandle, mesh.TextureHandles[0], mesh.TextureHandles[1], mesh.TextureHandles[2]); } else #endif - Shaders::ObjectPass2Shader::getInstance()->setTextureUnits( + ObjectPass2Shader::getInstance()->setTextureUnits( irr_driver->getRenderTargetTexture(RTT_DIFFUSE), irr_driver->getRenderTargetTexture(RTT_SPECULAR), irr_driver->getRenderTargetTexture(RTT_HALF1_R), getTextureGLuint(mesh.textures[0]), getTextureGLuint(mesh.textures[1]), getTextureGLuint(mesh.textures[2])); - Shaders::ObjectPass2Shader::getInstance()->setUniforms(AbsoluteTransformation, + ObjectPass2Shader::getInstance()->setUniforms(AbsoluteTransformation, mesh.texture_trans, core::vector2df(0.0f, 0.0f)); assert(mesh.vao); @@ -535,7 +536,7 @@ void STKMeshSceneNode::render() if (!mesh.TextureHandles[0]) mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), - Shaders::ObjectPass1Shader::getInstance()->m_sampler_ids[0]); + ObjectPass1Shader::getInstance()->m_sampler_ids[0]); if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0])) { glMakeTextureHandleResidentARB(mesh.TextureHandles[0]); @@ -578,7 +579,7 @@ void STKMeshSceneNode::render() if (!mesh.TextureHandles[0]) mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), - Shaders::ObjectPass1Shader::getInstance()->m_sampler_ids[0]); + ObjectPass1Shader::getInstance()->m_sampler_ids[0]); if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0])) { glMakeTextureHandleResidentARB(mesh.TextureHandles[0]); @@ -602,5 +603,19 @@ void STKMeshSceneNode::render() } } +void STKMeshSceneNode::setIsDisplacement(bool v) +{ + isDisplacement = v; + for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) + { + scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); + if (!mb) + continue; + + if (isDisplacement) + mb->getMaterial().MaterialType = Shaders::getShader(ES_DISPLACE); + } +} + #endif // !SERVER_ONLY diff --git a/src/graphics/stk_mesh_scene_node.hpp b/src/graphics/stk_mesh_scene_node.hpp index ef4da1556..b741e83c3 100644 --- a/src/graphics/stk_mesh_scene_node.hpp +++ b/src/graphics/stk_mesh_scene_node.hpp @@ -20,7 +20,6 @@ #include "graphics/stk_mesh.hpp" -#include "graphics/shaders.hpp" #include "utils/ptr_vector.hpp" class RenderInfo; @@ -65,19 +64,7 @@ public: virtual void OnRegisterSceneNode(); virtual ~STKMeshSceneNode(); virtual bool isImmediateDraw() const { return immediate_draw; } - void setIsDisplacement(bool v) { - isDisplacement = v; - for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) - { - scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); - if (!mb) - continue; -#ifndef SERVER_ONLY - if (isDisplacement) - mb->getMaterial().MaterialType = Shaders::getShader(ES_DISPLACE); -#endif - } - } + void setIsDisplacement(bool v); virtual bool glow() const { return isGlow; } void setGlowColors(const video::SColor &c) { isGlow = true; glowcolor = c; } video::SColor getGlowColor() const { return glowcolor; } diff --git a/src/graphics/texture_manager.cpp b/src/graphics/texture_manager.cpp index 73ad87f03..8753c2719 100644 --- a/src/graphics/texture_manager.cpp +++ b/src/graphics/texture_manager.cpp @@ -21,7 +21,7 @@ #include "graphics/central_settings.hpp" #include "graphics/irr_driver.hpp" -#include "graphics/shaders.hpp" +#include "graphics/materials.hpp" #if defined(USE_GLES2) #define _IRR_COMPILE_WITH_OGLES2_ @@ -70,7 +70,7 @@ void resetTextureTable() { glMakeTextureHandleNonResidentARB(handle); } - Shaders::ObjectPass1Shader::getInstance()->recreateTrilinearSampler(0); + ObjectPass1Shader::getInstance()->recreateTrilinearSampler(0); texture_handles.clear(); } #endif diff --git a/src/graphics/vao_manager.hpp b/src/graphics/vao_manager.hpp index c02d19d43..c691b3161 100644 --- a/src/graphics/vao_manager.hpp +++ b/src/graphics/vao_manager.hpp @@ -26,7 +26,7 @@ #include #include -enum InstanceType +enum InstanceType : unsigned int { InstanceTypeThreeTex, InstanceTypeFourTex, diff --git a/src/tracks/graph.cpp b/src/tracks/graph.cpp index cc862cade..1ca3e6153 100644 --- a/src/tracks/graph.cpp +++ b/src/tracks/graph.cpp @@ -20,7 +20,6 @@ #include "config/user_config.hpp" #include "graphics/irr_driver.hpp" -#include "graphics/shaders.hpp" #include "graphics/render_target.hpp" #include "graphics/texture_manager.hpp" #include "graphics/vao_manager.hpp" From 989234a0bae6d3a8539debd606680869a42b5aca Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 23 Dec 2016 17:12:53 +0800 Subject: [PATCH 050/206] Clean up header part 2 --- src/graphics/command_buffer.cpp | 1 + src/graphics/command_buffer.hpp | 12 ------------ src/graphics/draw_calls.cpp | 4 ++-- src/graphics/draw_calls.hpp | 9 ++++++++- src/graphics/draw_policies.cpp | 1 + src/graphics/draw_policies.hpp | 4 +++- src/graphics/draw_tools.hpp | 2 -- src/graphics/geometry_passes.hpp | 2 ++ src/graphics/render_target.cpp | 1 + src/graphics/shader_based_renderer.cpp | 2 ++ src/graphics/shader_based_renderer.hpp | 1 + src/graphics/vao_manager.hpp | 17 ++++++++++++++++- 12 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/graphics/command_buffer.cpp b/src/graphics/command_buffer.cpp index fa41e86ed..d4d5de86b 100644 --- a/src/graphics/command_buffer.cpp +++ b/src/graphics/command_buffer.cpp @@ -19,6 +19,7 @@ #include "graphics/command_buffer.hpp" #include "graphics/central_settings.hpp" +#include "graphics/stk_mesh_scene_node.hpp" #include "utils/cpp2011.hpp" // ---------------------------------------------------------------------------- diff --git a/src/graphics/command_buffer.hpp b/src/graphics/command_buffer.hpp index 0fade2f85..565b2c7b2 100644 --- a/src/graphics/command_buffer.hpp +++ b/src/graphics/command_buffer.hpp @@ -24,23 +24,11 @@ #include "graphics/gl_headers.hpp" #include "graphics/material.hpp" #include "graphics/materials.hpp" -#include "graphics/render_info.hpp" -#include "graphics/stk_mesh_scene_node.hpp" #include "graphics/vao_manager.hpp" #include #include #include -typedef STK::Tuple InstanceSettings; - -struct InstanceList -{ - GLMesh *m_mesh; - std::vector m_instance_settings; -}; - -typedef std::unordered_map MeshMap; - // ---------------------------------------------------------------------------- /** Fill origin, orientation and scale attributes * \param node The scene node of the mesh diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index fc9a1ea35..764d69188 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -19,17 +19,17 @@ #include "graphics/draw_calls.hpp" #include "config/user_config.hpp" +#include "graphics/command_buffer.hpp" #include "graphics/draw_tools.hpp" #include "graphics/gpu_particles.hpp" #include "graphics/lod_node.hpp" #include "graphics/materials.hpp" +#include "graphics/render_info.hpp" #include "graphics/shadow_matrices.hpp" #include "graphics/shaders.hpp" #include "graphics/stk_animated_mesh.hpp" #include "graphics/stk_billboard.hpp" #include "graphics/stk_mesh.hpp" -#include "graphics/stk_mesh_scene_node.hpp" -#include "graphics/vao_manager.hpp" #include "tracks/track.hpp" #include "utils/profiler.hpp" diff --git a/src/graphics/draw_calls.hpp b/src/graphics/draw_calls.hpp index 707f42493..3735de43d 100644 --- a/src/graphics/draw_calls.hpp +++ b/src/graphics/draw_calls.hpp @@ -19,14 +19,21 @@ #define HEADER_DRAW_CALLS_HPP #ifndef SERVER_ONLY -#include "graphics/command_buffer.hpp" +#include "graphics/material.hpp" +#include "graphics/vao_manager.hpp" #include +#include #include +class GlowCommandBuffer; class ParticleSystemProxy; +class ReflectiveShadowMapCommandBuffer; class ShadowMatrices; +class ShadowCommandBuffer; +class SolidCommandBuffer; class STKAnimatedMesh; class STKBillboard; +class STKMeshCommon; class DrawCalls { diff --git a/src/graphics/draw_policies.cpp b/src/graphics/draw_policies.cpp index 210f82a51..4e52f8c63 100644 --- a/src/graphics/draw_policies.cpp +++ b/src/graphics/draw_policies.cpp @@ -18,6 +18,7 @@ #ifndef SERVER_ONLY #include "graphics/draw_policies.hpp" +#include "graphics/draw_calls.hpp" #include "graphics/draw_tools.hpp" #include "graphics/materials.hpp" diff --git a/src/graphics/draw_policies.hpp b/src/graphics/draw_policies.hpp index ff362440f..918c88101 100644 --- a/src/graphics/draw_policies.hpp +++ b/src/graphics/draw_policies.hpp @@ -20,8 +20,10 @@ #ifndef SERVER_ONLY -#include "graphics/draw_calls.hpp" +#include "graphics/abstract_renderer.hpp" +using namespace irr; +class DrawCalls; /** Rendering methods in this class only require * OpenGL3.2 functions */ diff --git a/src/graphics/draw_tools.hpp b/src/graphics/draw_tools.hpp index 095dd3c71..e44a81336 100644 --- a/src/graphics/draw_tools.hpp +++ b/src/graphics/draw_tools.hpp @@ -20,11 +20,9 @@ #include "graphics/shader.hpp" #include "graphics/irr_driver.hpp" -#include "graphics/render_info.hpp" #include "graphics/stk_mesh.hpp" #include "graphics/texture_manager.hpp" - // ---------------------------------------------------------------------------- /** Variadic template to draw a mesh (using OpenGL 3.2 function) * using specified shader with per mesh custom uniforms.*/ diff --git a/src/graphics/geometry_passes.hpp b/src/graphics/geometry_passes.hpp index fc82b35bf..afe5d866d 100644 --- a/src/graphics/geometry_passes.hpp +++ b/src/graphics/geometry_passes.hpp @@ -20,8 +20,10 @@ #ifndef HEADER_GEOMETRY_PASSES_HPP #define HEADER_GEOMETRY_PASSES_HPP +#include "graphics/central_settings.hpp" #include "graphics/draw_calls.hpp" #include "graphics/glwrap.hpp" +#include "graphics/irr_driver.hpp" #include "graphics/shadow_matrices.hpp" #include "utils/profiler.hpp" #include diff --git a/src/graphics/render_target.cpp b/src/graphics/render_target.cpp index b15c21004..39871507d 100644 --- a/src/graphics/render_target.cpp +++ b/src/graphics/render_target.cpp @@ -20,6 +20,7 @@ #include "graphics/2dutils.hpp" #include "graphics/glwrap.hpp" +#include "graphics/irr_driver.hpp" #include "graphics/rtts.hpp" #include "graphics/shader_based_renderer.hpp" diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index b2275ad04..4adba170b 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -26,12 +26,14 @@ #include "graphics/geometry_passes.hpp" #include "graphics/glwrap.hpp" #include "graphics/graphics_restrictions.hpp" +#include "graphics/irr_driver.hpp" #include "graphics/lod_node.hpp" #include "graphics/post_processing.hpp" #include "graphics/render_target.hpp" #include "graphics/rtts.hpp" #include "graphics/shaders.hpp" #include "graphics/skybox.hpp" +#include "graphics/stk_mesh_scene_node.hpp" #include "graphics/spherical_harmonics.hpp" #include "graphics/texture_manager.hpp" #include "items/item_manager.hpp" diff --git a/src/graphics/shader_based_renderer.hpp b/src/graphics/shader_based_renderer.hpp index 125e14be1..6f91e67d5 100644 --- a/src/graphics/shader_based_renderer.hpp +++ b/src/graphics/shader_based_renderer.hpp @@ -29,6 +29,7 @@ #include class AbstractGeometryPasses; +class Camera; class GL3RenderTarget; class RenderTarget; class RTT; diff --git a/src/graphics/vao_manager.hpp b/src/graphics/vao_manager.hpp index c691b3161..e0fd47f93 100644 --- a/src/graphics/vao_manager.hpp +++ b/src/graphics/vao_manager.hpp @@ -18,14 +18,18 @@ #ifndef VAOMANAGER_HPP #define VAOMANAGER_HPP -#include "gl_headers.hpp" +#include "graphics/gl_headers.hpp" #include "utils/singleton.hpp" +#include "utils/tuple.hpp" #include #include +#include #include #include #include +using namespace irr; + enum InstanceType : unsigned int { InstanceTypeThreeTex, @@ -36,6 +40,17 @@ enum InstanceType : unsigned int InstanceTypeCount, }; +typedef STK::Tuple InstanceSettings; + +struct GLMesh; +struct InstanceList +{ + GLMesh* m_mesh; + std::vector m_instance_settings; +}; +typedef std::unordered_map MeshMap; + #ifdef WIN32 #pragma pack(push, 1) #endif From 15d6c7207a10c4cef0d38c3a4014335530040bba Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 23 Dec 2016 19:22:30 +0800 Subject: [PATCH 051/206] Minor improvements for non-instanced shaders --- data/shaders/displace.vert | 2 +- data/shaders/grass_pass.vert | 2 +- data/shaders/object_pass.vert | 2 +- data/shaders/rhdebug.vert | 2 +- data/shaders/skinning.vert | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/data/shaders/displace.vert b/data/shaders/displace.vert index 8c4ce9805..d82ac8824 100644 --- a/data/shaders/displace.vert +++ b/data/shaders/displace.vert @@ -15,7 +15,7 @@ out vec2 uv_bis; out float camdist; void main() { - gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(Position, 1.); + gl_Position = ProjectionViewMatrix * ModelMatrix * vec4(Position, 1.); uv = Texcoord; uv_bis = SecondTexcoord; camdist = length(ViewMatrix * ModelMatrix * vec4(Position, 1.)); diff --git a/data/shaders/grass_pass.vert b/data/shaders/grass_pass.vert index 13d0ca96b..08d44fff6 100644 --- a/data/shaders/grass_pass.vert +++ b/data/shaders/grass_pass.vert @@ -28,7 +28,7 @@ void main() // affects "nor" which is later only * 0.1 by scattering new_inverse_model_matrix[3].xyz -= windDir * Color.r; - mat4 ModelViewProjectionMatrix = ProjectionMatrix * ViewMatrix * new_model_matrix; + mat4 ModelViewProjectionMatrix = ProjectionViewMatrix * new_model_matrix; mat4 TransposeInverseModelView = transpose(InverseViewMatrix * new_inverse_model_matrix); gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.); nor = (TransposeInverseModelView * vec4(Normal, 0.)).xyz; diff --git a/data/shaders/object_pass.vert b/data/shaders/object_pass.vert index c98c0c0a6..dcd6a3985 100644 --- a/data/shaders/object_pass.vert +++ b/data/shaders/object_pass.vert @@ -46,7 +46,7 @@ out vec4 color; void main(void) { color = Color.zyxw; - mat4 ModelViewProjectionMatrix = ProjectionMatrix * ViewMatrix * ModelMatrix; + mat4 ModelViewProjectionMatrix = ProjectionViewMatrix * ModelMatrix; mat4 TransposeInverseModelView = transpose(InverseModelMatrix * InverseViewMatrix); gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.); // Keep orthogonality diff --git a/data/shaders/rhdebug.vert b/data/shaders/rhdebug.vert index 1edc4a37d..26e7bb990 100644 --- a/data/shaders/rhdebug.vert +++ b/data/shaders/rhdebug.vert @@ -14,7 +14,7 @@ void main(void) float gz = int(gl_VertexID >> 9) & (resolution.z - 1); uvw = vec3(gx, gy, gz) / vec3(resolution); vec3 WorldPos = (2. * uvw - 1.) * extents; - gl_Position = ProjectionMatrix * ViewMatrix * RHMatrix * vec4(WorldPos, 1.); + gl_Position = ProjectionViewMatrix * RHMatrix * vec4(WorldPos, 1.); gl_PointSize = 500. / gl_Position.w; } \ No newline at end of file diff --git a/data/shaders/skinning.vert b/data/shaders/skinning.vert index 2652fc10e..e74fc508c 100644 --- a/data/shaders/skinning.vert +++ b/data/shaders/skinning.vert @@ -69,7 +69,7 @@ void main(void) skinned_bitangent += Weight[i] * single_bone_influenced_bitangent; } - gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * skinned_position; + gl_Position = ProjectionViewMatrix * ModelMatrix * skinned_position; // Keep orthogonality nor = (TransposeInverseModelView * skinned_normal).xyz; // Keep direction From 424b62552ee47db68869423999b24ef8d74f7f3a Mon Sep 17 00:00:00 2001 From: Deve Date: Fri, 23 Dec 2016 15:09:41 +0100 Subject: [PATCH 052/206] Fixed MLAA in GLES renderer. This function was used by Cand for his OpenGL 2.1 renderer. The round function is available since GLSL 1.3 (OpenGL 3.0), so there is no need to override it. If it will be needed in future, I suggest to change the name to round_stk or something similar. --- data/shaders/mlaa_blend2.frag | 5 ----- 1 file changed, 5 deletions(-) diff --git a/data/shaders/mlaa_blend2.frag b/data/shaders/mlaa_blend2.frag index 40ea9cfa1..3c598c567 100644 --- a/data/shaders/mlaa_blend2.frag +++ b/data/shaders/mlaa_blend2.frag @@ -56,11 +56,6 @@ float SearchYUp(vec2 texcoord) { return min(i - 1.5 + 2.0 * e, 2.0 * MAX_SEARCH_STEPS); } - -vec2 round(vec2 invec) { - return vec2(floor(abs(invec) + vec2(0.5)) * sign(invec)); -} - vec2 Area(vec2 distance, float e1, float e2) { // * By dividing by areaSize - 1.0 below we are implicitely offsetting to // always fall inside of a pixel From 8a88c9707b3858d9dfa2e9a2af5aa28f6e42f3a3 Mon Sep 17 00:00:00 2001 From: Deve Date: Fri, 23 Dec 2016 16:45:03 +0100 Subject: [PATCH 053/206] Fixed rendering when UBO is disabled --- src/graphics/shader.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/graphics/shader.cpp b/src/graphics/shader.cpp index ec3ac239e..89cf135f5 100644 --- a/src/graphics/shader.cpp +++ b/src/graphics/shader.cpp @@ -74,6 +74,9 @@ void ShaderBase::bypassUBO() const GLint PM = glGetUniformLocation(m_program, "ProjectionMatrix"); glUniformMatrix4fv(PM, 1, GL_FALSE, irr_driver->getProjMatrix().pointer()); + + GLint PVM = glGetUniformLocation(m_program, "ProjectionViewMatrix"); + glUniformMatrix4fv(PVM, 1, GL_FALSE, irr_driver->getProjViewMatrix().pointer()); GLint IVM = glGetUniformLocation(m_program, "InverseViewMatrix"); glUniformMatrix4fv(IVM, 1, GL_FALSE, irr_driver->getInvViewMatrix().pointer()); From 674e6170183f099f260df8fe406cbcca567913ec Mon Sep 17 00:00:00 2001 From: Deve Date: Fri, 23 Dec 2016 19:01:16 +0100 Subject: [PATCH 054/206] Allow to use isDirectory function outside of file manager class. It is used on android for extracting assets --- src/io/file_manager.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io/file_manager.hpp b/src/io/file_manager.hpp index efe9c3484..52f9ce723 100644 --- a/src/io/file_manager.hpp +++ b/src/io/file_manager.hpp @@ -97,7 +97,6 @@ private: bool checkAndCreateDirectory(const std::string &path); io::path createAbsoluteFilename(const std::string &f); void checkAndCreateConfigDir(); - bool isDirectory(const std::string &path) const; void checkAndCreateAddonsDir(); void checkAndCreateScreenshotDir(); void checkAndCreateReplayDir(); @@ -130,6 +129,7 @@ public: const std::string &getAddonsDir() const; std::string getAddonsFile(const std::string &name); void checkAndCreateDirForAddons(const std::string &dir); + bool isDirectory(const std::string &path) const; bool removeFile(const std::string &name) const; bool removeDirectory(const std::string &name) const; bool copyFile(const std::string &source, const std::string &dest); From 7b768043548d8086b52edbd334999ee2b3dd3277 Mon Sep 17 00:00:00 2001 From: Deve Date: Fri, 23 Dec 2016 23:36:39 +0100 Subject: [PATCH 055/206] Allow to unlock all tracks in config.xml. Can be used on android when only some tracks are included in the apk. --- src/challenges/story_mode_status.cpp | 4 ++++ src/config/user_config.hpp | 4 ++++ src/modes/overworld.cpp | 4 ++++ src/scriptengine/script_challenges.cpp | 21 ++++++++++++++------- src/states_screens/race_gui_overworld.cpp | 7 +++++++ 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/challenges/story_mode_status.cpp b/src/challenges/story_mode_status.cpp index fcefad1dd..bd1b83b4a 100644 --- a/src/challenges/story_mode_status.cpp +++ b/src/challenges/story_mode_status.cpp @@ -23,6 +23,7 @@ #include "challenges/challenge_data.hpp" #include "challenges/unlock_manager.hpp" #include "config/player_manager.hpp" +#include "config/user_config.hpp" #include "io/utf_writer.hpp" #include "io/xml_node.hpp" @@ -67,6 +68,9 @@ void StoryModeStatus::addStatus(ChallengeStatus *cs) //----------------------------------------------------------------------------- bool StoryModeStatus::isLocked(const std::string& feature) { + if (UserConfigParams::m_everything_unlocked) + return false; + return m_locked_features.find(feature)!=m_locked_features.end(); } // featureIsLocked diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index d71292b4b..a8621c700 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -891,6 +891,10 @@ namespace UserConfigParams PARAM_PREFIX BoolUserConfigParam m_artist_debug_mode PARAM_DEFAULT( BoolUserConfigParam(false, "artist_debug_mode", "Whether to enable track debugging features") ); + + PARAM_PREFIX BoolUserConfigParam m_everything_unlocked + PARAM_DEFAULT( BoolUserConfigParam(false, "everything_unlocked", + "Enable all karts and tracks") ); // TODO? implement blacklist for new irrlicht device and GUI PARAM_PREFIX std::vector m_blacklist_res; diff --git a/src/modes/overworld.cpp b/src/modes/overworld.cpp index 47a8c5046..674c5049d 100644 --- a/src/modes/overworld.cpp +++ b/src/modes/overworld.cpp @@ -244,6 +244,10 @@ void OverWorld::onFirePressed(Controller* who) const unsigned int val = challenge->getNumTrophies(); bool unlocked = (PlayerManager::getCurrentPlayer()->getPoints() >= val); + + if (UserConfigParams::m_everything_unlocked) + unlocked = true; + if (unlocked) { race_manager->setKartLastPositionOnOverworld(kart_xyz); diff --git a/src/scriptengine/script_challenges.cpp b/src/scriptengine/script_challenges.cpp index 5c391cd15..792b21697 100644 --- a/src/scriptengine/script_challenges.cpp +++ b/src/scriptengine/script_challenges.cpp @@ -20,6 +20,7 @@ #include "animations/three_d_animation.hpp" #include "challenges/unlock_manager.hpp" +#include "config/user_config.hpp" #include "graphics/central_settings.hpp" #include "graphics/irr_driver.hpp" #include "guiengine/engine.hpp" @@ -48,13 +49,6 @@ namespace Scripting * @{ */ - // -------------------------------------------------------------------- - /** Get number of challenges that were completed at any difficulty */ - int getCompletedChallengesCount() - { - return ::Track::getCurrentTrack()->getNumOfCompletedChallenges(); - } // getCompletedChallengesCount - // -------------------------------------------------------------------- /** Get total number of challenges */ int getChallengeCount() @@ -62,6 +56,16 @@ namespace Scripting return ::Track::getCurrentTrack()->getChallengeList().size(); } // getChallengeCount + // -------------------------------------------------------------------- + /** Get number of challenges that were completed at any difficulty */ + int getCompletedChallengesCount() + { + if (UserConfigParams::m_everything_unlocked) + return getChallengeCount(); + + return ::Track::getCurrentTrack()->getNumOfCompletedChallenges(); + } // getCompletedChallengesCount + // -------------------------------------------------------------------- int getChallengeRequiredPoints(std::string* challenge_name) { @@ -81,6 +85,9 @@ namespace Scripting // -------------------------------------------------------------------- bool isChallengeUnlocked(std::string* challenge_name) { + if (UserConfigParams::m_everything_unlocked) + return true; + const ChallengeData* challenge = unlock_manager->getChallengeData(*challenge_name); if (challenge == NULL) diff --git a/src/states_screens/race_gui_overworld.cpp b/src/states_screens/race_gui_overworld.cpp index 1c6106dba..e20452024 100644 --- a/src/states_screens/race_gui_overworld.cpp +++ b/src/states_screens/race_gui_overworld.cpp @@ -431,6 +431,9 @@ void RaceGUIOverworld::drawGlobalMiniMap() const unsigned int val = challenge->getNumTrophies(); bool unlocked = (PlayerManager::getCurrentPlayer()->getPoints() >= val); int state = (unlocked ? OPEN : LOCKED); + + if (UserConfigParams::m_everything_unlocked) + state = OPEN; const ChallengeStatus* c = PlayerManager::getCurrentPlayer() ->getChallengeStatus(challenges[n].m_challenge_id); @@ -475,6 +478,10 @@ void RaceGUIOverworld::drawGlobalMiniMap() const ChallengeData* challenge = unlock_manager->getChallengeData(challenges[n].m_challenge_id); const unsigned int val = challenge->getNumTrophies(); bool unlocked = (PlayerManager::getCurrentPlayer()->getPoints() >= val); + + if (UserConfigParams::m_everything_unlocked) + unlocked = true; + if (!unlocked) continue; } From 26bbffe8b0bb2781f2fabb07b9dfde6a9bcee6b0 Mon Sep 17 00:00:00 2001 From: Deve Date: Sat, 24 Dec 2016 01:26:18 +0100 Subject: [PATCH 056/206] Don't declare features that are used for SDSM, AZDO and compute shaders and that are not available in GLES renderer anyway. --- src/graphics/central_settings.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/graphics/central_settings.cpp b/src/graphics/central_settings.cpp index 56a267260..2aac1406f 100644 --- a/src/graphics/central_settings.cpp +++ b/src/graphics/central_settings.cpp @@ -222,13 +222,7 @@ void CentralVideoSettings::init() #else if (m_glsl == true) { - hasArraysOfArrays = true; hasTextureStorage = true; - hasTextureView = true; - hasBindlessTexture = true; - hasImageLoadStore = true; - hasAtomics = true; - hasSSBO = true; } if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_TEXTURE_FORMAT_BGRA8888) && From 6486d1548bc2fff42de2ed817aaf8b0c4ab9f015 Mon Sep 17 00:00:00 2001 From: Deve Date: Sat, 24 Dec 2016 02:07:53 +0100 Subject: [PATCH 057/206] Fixed clang compilation --- lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp | 10 +++++++--- lib/irrlicht/source/Irrlicht/CSkinnedMesh.h | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp index 429ef82b2..b4fcf2b64 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp @@ -1410,6 +1410,12 @@ void CSkinnedMesh::addJoints(core::array &jointChildSceneNodes, SkinnedLastFrame=false; } +bool CSkinnedMesh::sortJointInfluenceFunc(const JointInfluence& a, + const JointInfluence& b) +{ + return a.weight > b.weight; +} + void CSkinnedMesh::convertForSkinning() { if (HardwareSkinning) return; @@ -1440,9 +1446,7 @@ void CSkinnedMesh::convertForSkinning() { core::array this_influence; core::array reported_weight = wi[b][i]; - reported_weight.sort([] - (const JointInfluence& a, const JointInfluence& b) - { return a.weight > b.weight; }); + reported_weight.sort(sortJointInfluenceFunc); float remaining_weight = 1.0f; for (u32 j = 0; j < 4; j++) { diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h index 0dd3a43bf..0dd936f0d 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h @@ -200,6 +200,9 @@ private: core::vector3df& tangent, core::vector3df& binormal, core::vector3df& vt1, core::vector3df& vt2, core::vector3df& vt3, core::vector2df& tc1, core::vector2df& tc2, core::vector2df& tc3); + + static bool sortJointInfluenceFunc(const JointInfluence& a, + const JointInfluence& b); core::array *SkinningBuffers; //Meshbuffer to skin, default is to skin localBuffers From 6a142e8d2e46c7ae32e4afc0b2c47289a35520ad Mon Sep 17 00:00:00 2001 From: Benau Date: Sat, 24 Dec 2016 13:11:08 +0800 Subject: [PATCH 058/206] Allow animated models in track to have different animation --- lib/irrlicht/include/IAnimatedMeshSceneNode.h | 3 ++ .../Irrlicht/CAnimatedMeshSceneNode.cpp | 9 ++++ .../source/Irrlicht/CAnimatedMeshSceneNode.h | 10 ++++ src/modes/three_strikes_battle.cpp | 2 - src/tracks/model_definition_loader.cpp | 18 +++++++ src/tracks/track_object_presentation.cpp | 53 ++++++++++++++----- src/tracks/track_object_presentation.hpp | 7 +-- 7 files changed, 82 insertions(+), 20 deletions(-) diff --git a/lib/irrlicht/include/IAnimatedMeshSceneNode.h b/lib/irrlicht/include/IAnimatedMeshSceneNode.h index b18f34236..89c84d740 100644 --- a/lib/irrlicht/include/IAnimatedMeshSceneNode.h +++ b/lib/irrlicht/include/IAnimatedMeshSceneNode.h @@ -178,6 +178,9 @@ namespace scene \return The newly created clone of this node. */ virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) = 0; + virtual u32 getAnimationSetNum() = 0; + virtual void addAnimationSet(u32 start, u32 end) = 0; + virtual void useAnimationSet(u32 set_num) = 0; }; } // end namespace scene diff --git a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.cpp b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.cpp index a0bfc5b93..3d6b08aa5 100644 --- a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.cpp +++ b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.cpp @@ -992,6 +992,15 @@ ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* return newNode; } +void CAnimatedMeshSceneNode::useAnimationSet(u32 set_num) +{ + if (m_animation_set.empty()) + { + setFrameLoop(getStartFrame(), getEndFrame()); + return; + } + setFrameLoop(m_animation_set[set_num * 2], m_animation_set[set_num * 2 + 1]); +} } // end namespace scene } // end namespace irr diff --git a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h index d75fbf8d5..1ea8f5112 100644 --- a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h +++ b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h @@ -19,6 +19,8 @@ namespace scene class CAnimatedMeshSceneNode : public IAnimatedMeshSceneNode { + private: + core::array m_animation_set; public: //! constructor @@ -158,6 +160,14 @@ namespace scene \return The newly created clone of this node. */ virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); + virtual u32 getAnimationSetNum() { return m_animation_set.size() / 2; } + virtual void addAnimationSet(u32 start, u32 end) + { + m_animation_set.push_back(start); + m_animation_set.push_back(end); + } + virtual void useAnimationSet(u32 set_num); + protected: //! Get a static mesh for the current frame of this animated mesh diff --git a/src/modes/three_strikes_battle.cpp b/src/modes/three_strikes_battle.cpp index edb21c57f..00e78a1fd 100644 --- a/src/modes/three_strikes_battle.cpp +++ b/src/modes/three_strikes_battle.cpp @@ -101,8 +101,6 @@ void ThreeStrikesBattle::reset() 25.0f : 20.0f; const unsigned int kart_amount = (unsigned int)m_karts.size(); - - int idCamera = 0; for(unsigned int n=0; n(m_karts[n]->getController()) != NULL) diff --git a/src/tracks/model_definition_loader.cpp b/src/tracks/model_definition_loader.cpp index 852180e5f..1217e1a65 100644 --- a/src/tracks/model_definition_loader.cpp +++ b/src/tracks/model_definition_loader.cpp @@ -102,6 +102,24 @@ LODNode* ModelDefinitionLoader::instanciateAsLOD(const XMLNode* node, scene::ISc scene::IAnimatedMeshSceneNode* scene_node = irr_driver ->addAnimatedMesh(a_mesh, group[m].m_model_file, NULL, ri); + std::vector frames_start; + if (node) + node->get("frame-start", &frames_start); + + std::vector frames_end; + if (node) + node->get("frame-end", &frames_end); + + if (frames_start.empty() && frames_end.empty()) + { + frames_start.push_back(scene_node->getStartFrame()); + frames_end.push_back(scene_node->getEndFrame()); + } + assert(frames_start.size() == frames_end.size()); + for (unsigned int i = 0 ; i < frames_start.size() ; i++) + scene_node->addAnimationSet(frames_start[i], frames_end[i]); + scene_node->useAnimationSet(0); + m_track->handleAnimatedTextures(scene_node, *group[m].m_xml); lod_node->add(group[m].m_distance, scene_node, true); diff --git a/src/tracks/track_object_presentation.cpp b/src/tracks/track_object_presentation.cpp index a8c96c18f..ef4ca6bfe 100644 --- a/src/tracks/track_object_presentation.cpp +++ b/src/tracks/track_object_presentation.cpp @@ -314,6 +314,28 @@ TrackObjectPresentationLOD::~TrackObjectPresentationLOD() irr_driver->removeNode(m_node); } // TrackObjectPresentationLOD +// ---------------------------------------------------------------------------- +void TrackObjectPresentationLOD::reset() +{ + LODNode* ln = dynamic_cast(m_node); + if (ln) + { + for (scene::ISceneNode* node : ln->getAllNodes()) + { + scene::IAnimatedMeshSceneNode* a_node = + dynamic_cast(node); + if (a_node) + { + RandomGenerator rg; + int animation_set = 0; + if (a_node->getAnimationSetNum() > 0) + animation_set = rg.get(a_node->getAnimationSetNum()); + a_node->useAnimationSet(animation_set); + } + } + } +} // reset + // ---------------------------------------------------------------------------- TrackObjectPresentationMesh::TrackObjectPresentationMesh( const XMLNode& xml_node, @@ -481,8 +503,6 @@ void TrackObjectPresentationMesh::init(const XMLNode* xml_node, m_node = irr_driver->addMesh(m_mesh, m_model_file, parent, m_render_info); enabled = false; m_force_always_hidden = true; - m_frame_start = 0; - m_frame_end = 0; } else { @@ -490,8 +510,6 @@ void TrackObjectPresentationMesh::init(const XMLNode* xml_node, m_node = irr_driver->addMesh(m_mesh, m_model_file, parent, m_render_info); enabled = false; m_force_always_hidden = true; - m_frame_start = 0; - m_frame_end = 0; Track *track = Track::getCurrentTrack(); if (track && track && xml_node) track->addPhysicsOnlyNode(m_node); @@ -516,13 +534,23 @@ void TrackObjectPresentationMesh::init(const XMLNode* xml_node, m_model_file, parent, m_render_info); m_node = node; - m_frame_start = node->getStartFrame(); + std::vector frames_start; if (xml_node) - xml_node->get("frame-start", &m_frame_start); + xml_node->get("frame-start", &frames_start); - m_frame_end = node->getEndFrame(); + std::vector frames_end; if (xml_node) - xml_node->get("frame-end", &m_frame_end); + xml_node->get("frame-end", &frames_end); + + if (frames_start.empty() && frames_end.empty()) + { + frames_start.push_back(node->getStartFrame()); + frames_end.push_back(node->getEndFrame()); + } + assert(frames_start.size() == frames_end.size()); + for (unsigned int i = 0 ; i < frames_start.size() ; i++) + node->addAnimationSet(frames_start[i], frames_end[i]); + node->useAnimationSet(0); Track *track = Track::getCurrentTrack(); if (track && track && xml_node) @@ -542,9 +570,6 @@ void TrackObjectPresentationMesh::init(const XMLNode* xml_node, stkmesh->setIsDisplacement(displacing); #endif - m_frame_start = 0; - m_frame_end = 0; - Track *track = Track::getCurrentTrack(); if (track && xml_node) track->handleAnimatedTextures(m_node, *xml_node); @@ -593,7 +618,11 @@ void TrackObjectPresentationMesh::reset() // irrlicht's "setFrameLoop" is a misnomer, it just sets the first and // last frame, even if looping is disabled - a_node->setFrameLoop(m_frame_start, m_frame_end); + RandomGenerator rg; + int animation_set = 0; + if (a_node->getAnimationSetNum() > 0) + animation_set = rg.get(a_node->getAnimationSetNum()); + a_node->useAnimationSet(animation_set); } } // reset diff --git a/src/tracks/track_object_presentation.hpp b/src/tracks/track_object_presentation.hpp index a92d62cfd..2aa2e388e 100644 --- a/src/tracks/track_object_presentation.hpp +++ b/src/tracks/track_object_presentation.hpp @@ -207,6 +207,7 @@ public: ModelDefinitionLoader& model_def_loader, RenderInfo* ri); virtual ~TrackObjectPresentationLOD(); + virtual void reset() OVERRIDE; }; // ============================================================================ @@ -226,12 +227,6 @@ private: /** True if the object is in the skybox */ bool m_is_in_skybox; - /** Start frame of the animation to be played. */ - unsigned int m_frame_start; - - /** End frame of the animation to be played. */ - unsigned int m_frame_end; - std::string m_model_file; RenderInfo* m_render_info; From e62edcc89aee1bd5bd07c373206abf05809894d0 Mon Sep 17 00:00:00 2001 From: samuncle Date: Sat, 24 Dec 2016 19:16:39 -0500 Subject: [PATCH 059/206] Ground work for geometry detail option --- data/gui/custom_video_settings.stkgui | 8 ++++++++ src/config/user_config.hpp | 11 +++++++++++ src/states_screens/dialogs/custom_video_settings.cpp | 11 +++++++++++ 3 files changed, 30 insertions(+) diff --git a/data/gui/custom_video_settings.stkgui b/data/gui/custom_video_settings.stkgui index 35039a75a..3a0a1b9a8 100644 --- a/data/gui/custom_video_settings.stkgui +++ b/data/gui/custom_video_settings.stkgui @@ -173,6 +173,14 @@ + + +
+
+