mirror of
https://github.com/4sval/FModel.git
synced 2026-04-25 07:21:54 -05:00
using SSBOs for unlimited bones
This commit is contained in:
parent
1ca18c3958
commit
9da407ea39
|
|
@ -11,7 +11,6 @@ public static class Constants
|
||||||
|
|
||||||
public const float SCALE_DOWN_RATIO = 0.01F;
|
public const float SCALE_DOWN_RATIO = 0.01F;
|
||||||
public const int SAMPLES_COUNT = 4;
|
public const int SAMPLES_COUNT = 4;
|
||||||
public const int MAX_BONE_UNIFORM = 250;
|
|
||||||
|
|
||||||
public const string WHITE = "#DAE5F2";
|
public const string WHITE = "#DAE5F2";
|
||||||
public const string GRAY = "#BBBBBB";
|
public const string GRAY = "#BBBBBB";
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,10 @@ layout (location = 14) in vec3 vMorphTargetTangent;
|
||||||
uniform mat4 uView;
|
uniform mat4 uView;
|
||||||
uniform mat4 uProjection;
|
uniform mat4 uProjection;
|
||||||
uniform float uMorphTime;
|
uniform float uMorphTime;
|
||||||
uniform mat4 uFinalBonesMatrix[250];
|
layout(std430, binding = 1) buffer layoutName
|
||||||
|
{
|
||||||
|
mat4 uFinalBonesMatrix[];
|
||||||
|
};
|
||||||
|
|
||||||
out vec3 fPos;
|
out vec3 fPos;
|
||||||
out vec3 fNormal;
|
out vec3 fNormal;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,10 @@ uniform mat4 uView;
|
||||||
uniform vec3 uViewPos;
|
uniform vec3 uViewPos;
|
||||||
uniform mat4 uProjection;
|
uniform mat4 uProjection;
|
||||||
uniform float uMorphTime;
|
uniform float uMorphTime;
|
||||||
uniform mat4 uFinalBonesMatrix[250];
|
layout(std430, binding = 1) buffer layoutName
|
||||||
|
{
|
||||||
|
mat4 uFinalBonesMatrix[];
|
||||||
|
};
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,10 @@ layout (location = 13) in vec3 vMorphTargetPos;
|
||||||
uniform mat4 uView;
|
uniform mat4 uView;
|
||||||
uniform mat4 uProjection;
|
uniform mat4 uProjection;
|
||||||
uniform float uMorphTime;
|
uniform float uMorphTime;
|
||||||
uniform mat4 uFinalBonesMatrix[250];
|
layout(std430, binding = 1) buffer layoutName
|
||||||
|
{
|
||||||
|
mat4 uFinalBonesMatrix[];
|
||||||
|
};
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,13 @@ public class BufferObject<TDataType> : IDisposable where TDataType : unmanaged
|
||||||
GL.BindBuffer(_bufferTarget, _handle);
|
GL.BindBuffer(_bufferTarget, _handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void BindBufferBase(int index)
|
||||||
|
{
|
||||||
|
if (_bufferTarget != BufferTarget.ShaderStorageBuffer)
|
||||||
|
throw new ArgumentException("BindBufferBase is not allowed for anything but Shader Storage Buffers");
|
||||||
|
GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, index, _handle);
|
||||||
|
}
|
||||||
|
|
||||||
public void Unbind()
|
public void Unbind()
|
||||||
{
|
{
|
||||||
GL.BindBuffer(_bufferTarget, 0);
|
GL.BindBuffer(_bufferTarget, 0);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using CUE4Parse_Conversion.Animations;
|
using CUE4Parse_Conversion.Animations;
|
||||||
using CUE4Parse.UE4.Assets.Exports.Animation;
|
using CUE4Parse.UE4.Assets.Exports.Animation;
|
||||||
using CUE4Parse.UE4.Objects.UObject;
|
using CUE4Parse.UE4.Objects.UObject;
|
||||||
|
using FModel.Views.Snooper.Buffers;
|
||||||
using FModel.Views.Snooper.Shading;
|
using FModel.Views.Snooper.Shading;
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace FModel.Views.Snooper.Models.Animations;
|
namespace FModel.Views.Snooper.Models.Animations;
|
||||||
|
|
@ -17,12 +20,15 @@ public struct BoneIndice
|
||||||
|
|
||||||
public class Skeleton : IDisposable
|
public class Skeleton : IDisposable
|
||||||
{
|
{
|
||||||
|
private int _handle;
|
||||||
|
private BufferObject<Matrix4x4> _ssbo;
|
||||||
|
|
||||||
public readonly USkeleton UnrealSkeleton;
|
public readonly USkeleton UnrealSkeleton;
|
||||||
public readonly bool IsLoaded;
|
public readonly bool IsLoaded;
|
||||||
|
|
||||||
public readonly Dictionary<string, BoneIndice> BonesIndicesByLoweredName;
|
public readonly Dictionary<string, BoneIndice> BonesIndicesByLoweredName;
|
||||||
public readonly Dictionary<int, Transform> BonesTransformByIndex;
|
public readonly Dictionary<int, Transform> BonesTransformByIndex;
|
||||||
public readonly Dictionary<int, Matrix4x4> InvertedBonesMatrixByIndex;
|
public readonly Matrix4x4[] InvertedBonesMatrixByIndex;
|
||||||
|
|
||||||
public Animation Anim;
|
public Animation Anim;
|
||||||
public bool HasAnim => Anim != null;
|
public bool HasAnim => Anim != null;
|
||||||
|
|
@ -31,7 +37,7 @@ public class Skeleton : IDisposable
|
||||||
{
|
{
|
||||||
BonesIndicesByLoweredName = new Dictionary<string, BoneIndice>();
|
BonesIndicesByLoweredName = new Dictionary<string, BoneIndice>();
|
||||||
BonesTransformByIndex = new Dictionary<int, Transform>();
|
BonesTransformByIndex = new Dictionary<int, Transform>();
|
||||||
InvertedBonesMatrixByIndex = new Dictionary<int, Matrix4x4>();
|
InvertedBonesMatrixByIndex = Array.Empty<Matrix4x4>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Skeleton(FPackageIndex package, FReferenceSkeleton referenceSkeleton) : this()
|
public Skeleton(FPackageIndex package, FReferenceSkeleton referenceSkeleton) : this()
|
||||||
|
|
@ -55,6 +61,7 @@ public class Skeleton : IDisposable
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
InvertedBonesMatrixByIndex = new Matrix4x4[BonesIndicesByLoweredName.Count];
|
||||||
foreach (var boneIndices in BonesIndicesByLoweredName.Values)
|
foreach (var boneIndices in BonesIndicesByLoweredName.Values)
|
||||||
{
|
{
|
||||||
var bone = referenceSkeleton.FinalRefBonePose[boneIndices.Index];
|
var bone = referenceSkeleton.FinalRefBonePose[boneIndices.Index];
|
||||||
|
|
@ -84,16 +91,23 @@ public class Skeleton : IDisposable
|
||||||
Anim = new Animation(this, anim, rotationOnly);
|
Anim = new Animation(this, anim, rotationOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetUniform(Shader shader, float deltaSeconds = 0f, bool update = false)
|
public void Setup()
|
||||||
|
{
|
||||||
|
_handle = GL.CreateProgram();
|
||||||
|
_ssbo = new BufferObject<Matrix4x4>(InvertedBonesMatrixByIndex, BufferTarget.ShaderStorageBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Render(float deltaSeconds = 0f, bool update = false)
|
||||||
{
|
{
|
||||||
if (!IsLoaded) return;
|
if (!IsLoaded) return;
|
||||||
|
|
||||||
|
_ssbo.BindBufferBase(1);
|
||||||
|
|
||||||
if (!HasAnim)
|
if (!HasAnim)
|
||||||
{
|
{
|
||||||
foreach (var boneIndex in BonesTransformByIndex.Keys)
|
foreach (var boneIndex in BonesTransformByIndex.Keys)
|
||||||
{
|
{
|
||||||
if (boneIndex >= Constants.MAX_BONE_UNIFORM)
|
_ssbo.Update(boneIndex, Matrix4x4.Identity);
|
||||||
break;
|
|
||||||
shader.SetUniform($"uFinalBonesMatrix[{boneIndex}]", Matrix4x4.Identity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -101,22 +115,20 @@ public class Skeleton : IDisposable
|
||||||
if (update) Anim.Update(deltaSeconds);
|
if (update) Anim.Update(deltaSeconds);
|
||||||
foreach (var boneIndex in BonesTransformByIndex.Keys)
|
foreach (var boneIndex in BonesTransformByIndex.Keys)
|
||||||
{
|
{
|
||||||
if (boneIndex >= Constants.MAX_BONE_UNIFORM)
|
_ssbo.Update(boneIndex, InvertedBonesMatrixByIndex[boneIndex] * Anim.InterpolateBoneTransform(boneIndex));
|
||||||
break;
|
|
||||||
if (!InvertedBonesMatrixByIndex.TryGetValue(boneIndex, out var invertMatrix))
|
|
||||||
throw new ArgumentNullException($"no inverse matrix for bone '{boneIndex}'");
|
|
||||||
|
|
||||||
shader.SetUniform($"uFinalBonesMatrix[{boneIndex}]", invertMatrix * Anim.InterpolateBoneTransform(boneIndex));
|
|
||||||
}
|
}
|
||||||
if (update) Anim.CheckForNextSequence();
|
if (update) Anim.CheckForNextSequence();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ssbo.Unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
BonesIndicesByLoweredName.Clear();
|
BonesIndicesByLoweredName.Clear();
|
||||||
BonesTransformByIndex.Clear();
|
BonesTransformByIndex.Clear();
|
||||||
InvertedBonesMatrixByIndex.Clear();
|
|
||||||
Anim?.Dispose();
|
Anim?.Dispose();
|
||||||
|
|
||||||
|
GL.DeleteProgram(_handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -348,6 +348,7 @@ public class Model : IDisposable
|
||||||
Materials[i].Setup(options, broken ? 1 : UvCount);
|
Materials[i].Setup(options, broken ? 1 : UvCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HasSkeleton) Skeleton.Setup();
|
||||||
if (HasMorphTargets)
|
if (HasMorphTargets)
|
||||||
{
|
{
|
||||||
for (uint morph = 0; morph < Morphs.Length; morph++)
|
for (uint morph = 0; morph < Morphs.Length; morph++)
|
||||||
|
|
@ -382,7 +383,7 @@ public class Model : IDisposable
|
||||||
|
|
||||||
_vao.Bind();
|
_vao.Bind();
|
||||||
shader.SetUniform("uMorphTime", MorphTime);
|
shader.SetUniform("uMorphTime", MorphTime);
|
||||||
if (HasSkeleton) Skeleton.SetUniform(shader, deltaSeconds, !outline);
|
if (HasSkeleton) Skeleton.Render(deltaSeconds, !outline);
|
||||||
if (!outline)
|
if (!outline)
|
||||||
{
|
{
|
||||||
shader.SetUniform("uUvCount", UvCount);
|
shader.SetUniform("uUvCount", UvCount);
|
||||||
|
|
@ -413,7 +414,7 @@ public class Model : IDisposable
|
||||||
|
|
||||||
_vao.Bind();
|
_vao.Bind();
|
||||||
shader.SetUniform("uMorphTime", MorphTime);
|
shader.SetUniform("uMorphTime", MorphTime);
|
||||||
if (HasSkeleton) Skeleton.SetUniform(shader);
|
if (HasSkeleton) Skeleton.Render();
|
||||||
|
|
||||||
foreach (var section in Sections)
|
foreach (var section in Sections)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -452,7 +452,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
|
||||||
if (model.HasSkeleton)
|
if (model.HasSkeleton)
|
||||||
{
|
{
|
||||||
Layout("Skeleton");ImGui.Text($" : {model.Skeleton.UnrealSkeleton.Name}");
|
Layout("Skeleton");ImGui.Text($" : {model.Skeleton.UnrealSkeleton.Name}");
|
||||||
Layout("Bones");ImGui.Text($" : x{model.Skeleton.InvertedBonesMatrixByIndex.Count}");
|
Layout("Bones");ImGui.Text($" : x{model.Skeleton.InvertedBonesMatrixByIndex.Length}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user