diff --git a/CUE4Parse b/CUE4Parse index 462e5efd..39ba4c7f 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 462e5efd764e97256d123685f37be621f5787fcc +Subproject commit 39ba4c7fcd9e058dbe33d8fec7cddb00763ace33 diff --git a/FModel/Resources/default.frag b/FModel/Resources/default.frag index 29b9f84d..34a2225c 100644 --- a/FModel/Resources/default.frag +++ b/FModel/Resources/default.frag @@ -8,7 +8,7 @@ in vec3 fPos; in vec3 fNormal; in vec3 fTangent; in vec2 fTexCoords; -in float fTexLayer; +flat in int fTexLayer; in vec4 fColor; struct Texture @@ -98,7 +98,7 @@ out vec4 FragColor; int LayerToIndex() { - return clamp(int(fTexLayer), 0, uUvCount - 1); + return clamp(fTexLayer, 0, uUvCount - 1); } vec4 SamplerToVector(sampler2D s, vec2 coords) diff --git a/FModel/Resources/default.vert b/FModel/Resources/default.vert index 3d530a5b..97e564c7 100644 --- a/FModel/Resources/default.vert +++ b/FModel/Resources/default.vert @@ -4,10 +4,10 @@ layout (location = 1) in vec3 vPos; layout (location = 2) in vec3 vNormal; layout (location = 3) in vec3 vTangent; layout (location = 4) in vec2 vTexCoords; -layout (location = 5) in float vTexLayer; -layout (location = 6) in vec4 vColor; -layout (location = 7) in vec4 vBoneIds; -layout (location = 8) in vec4 vBoneWeights; +layout (location = 5) in int vTexLayer; +layout (location = 6) in float vColor; +layout (location = 7) in vec4 vBoneInfluence; +layout (location = 8) in vec4 vBoneInfluenceExtra; layout (location = 9) in mat4 vInstanceMatrix; layout (location = 13) in vec3 vMorphTargetPos; layout (location = 14) in vec3 vMorphTargetTangent; @@ -30,9 +30,23 @@ out vec3 fPos; out vec3 fNormal; out vec3 fTangent; out vec2 fTexCoords; -out float fTexLayer; +flat out int fTexLayer; out vec4 fColor; +vec4 unpackARGB(int color) +{ + float a = float((color >> 24) & 0xFF); + float r = float((color >> 16) & 0xFF); + float g = float((color >> 8) & 0xFF); + float b = float((color >> 0) & 0xFF); + return vec4(r, g, b, a); +} + +vec2 unpackBoneIDsAndWeights(int packedData) +{ + return vec2(float((packedData >> 16) & 0xFFFF), float(packedData & 0xFFFF)); +} + void main() { vec4 bindPos = vec4(mix(vPos, vMorphTargetPos, uMorphTime), 1.0); @@ -44,18 +58,24 @@ void main() vec4 finalTangent = vec4(0.0); if (uIsAnimated) { - for(int i = 0 ; i < 4; i++) + vec4 boneInfluences[2]; + boneInfluences[0] = vBoneInfluence; + boneInfluences[1] = vBoneInfluenceExtra; + for (int i = 0; i < 2; i++) { - int boneIndex = int(vBoneIds[i]); - if(boneIndex < 0) break; + for(int j = 0 ; j < 4; j++) + { + vec2 boneInfluence = unpackBoneIDsAndWeights(int(boneInfluences[i][j])); + int boneIndex = int(boneInfluence.x); + float weight = boneInfluence.y; - mat4 boneMatrix = uFinalBonesMatrix[boneIndex] * inverse(uRestBonesMatrix[boneIndex]); - mat4 inverseBoneMatrix = transpose(inverse(boneMatrix)); - float weight = vBoneWeights[i]; + mat4 boneMatrix = uFinalBonesMatrix[boneIndex] * inverse(uRestBonesMatrix[boneIndex]); + mat4 inverseBoneMatrix = transpose(inverse(boneMatrix)); - finalPos += boneMatrix * bindPos * weight; - finalNormal += inverseBoneMatrix * bindNormal * weight; - finalTangent += inverseBoneMatrix * bindTangent * weight; + finalPos += boneMatrix * bindPos * weight; + finalNormal += inverseBoneMatrix * bindNormal * weight; + finalTangent += inverseBoneMatrix * bindTangent * weight; + } } } else @@ -72,5 +92,5 @@ void main() fTangent = vec3(transpose(inverse(vInstanceMatrix)) * finalTangent); fTexCoords = vTexCoords; fTexLayer = vTexLayer; - fColor = vColor; + fColor = unpackARGB(int(vColor)); } diff --git a/FModel/Resources/outline.vert b/FModel/Resources/outline.vert index ffb85c6c..a7049e5e 100644 --- a/FModel/Resources/outline.vert +++ b/FModel/Resources/outline.vert @@ -2,8 +2,8 @@ layout (location = 1) in vec3 vPos; layout (location = 2) in vec3 vNormal; -layout (location = 7) in vec4 vBoneIds; -layout (location = 8) in vec4 vBoneWeights; +layout (location = 7) in vec4 vBoneInfluence; +layout (location = 8) in vec4 vBoneInfluenceExtra; layout (location = 9) in mat4 vInstanceMatrix; layout (location = 13) in vec3 vMorphTargetPos; @@ -22,6 +22,11 @@ uniform mat4 uProjection; uniform float uMorphTime; uniform bool uIsAnimated; +vec2 unpackBoneIDsAndWeights(int packedData) +{ + return vec2(float((packedData >> 16) & 0xFFFF), float(packedData & 0xFFFF)); +} + void main() { vec4 bindPos = vec4(mix(vPos, vMorphTargetPos, uMorphTime), 1.0); @@ -31,16 +36,22 @@ void main() vec4 finalNormal = vec4(0.0); if (uIsAnimated) { - for(int i = 0 ; i < 4; i++) + vec4 boneInfluences[2]; + boneInfluences[0] = vBoneInfluence; + boneInfluences[1] = vBoneInfluenceExtra; + for(int i = 0 ; i < 2; i++) { - int boneIndex = int(vBoneIds[i]); - if(boneIndex < 0) break; + for(int j = 0; j < 4; j++) + { + vec2 boneInfluence = unpackBoneIDsAndWeights(int(boneInfluences[i][j])); + int boneIndex = int(boneInfluence.x); + float weight = boneInfluence.y; - mat4 boneMatrix = uFinalBonesMatrix[boneIndex] * inverse(uRestBonesMatrix[boneIndex]); - float weight = vBoneWeights[i]; + mat4 boneMatrix = uFinalBonesMatrix[boneIndex] * inverse(uRestBonesMatrix[boneIndex]); - finalPos += boneMatrix * bindPos * weight; - finalNormal += transpose(inverse(boneMatrix)) * bindNormal * weight; + finalPos += boneMatrix * bindPos * weight; + finalNormal += transpose(inverse(boneMatrix)) * bindNormal * weight; + } } } else diff --git a/FModel/Resources/picking.vert b/FModel/Resources/picking.vert index 7d267c0c..15194254 100644 --- a/FModel/Resources/picking.vert +++ b/FModel/Resources/picking.vert @@ -1,8 +1,8 @@ #version 460 core layout (location = 1) in vec3 vPos; -layout (location = 7) in vec4 vBoneIds; -layout (location = 8) in vec4 vBoneWeights; +layout (location = 7) in vec4 vBoneInfluence; +layout (location = 8) in vec4 vBoneInfluenceExtra; layout (location = 9) in mat4 vInstanceMatrix; layout (location = 13) in vec3 vMorphTargetPos; @@ -20,6 +20,11 @@ uniform mat4 uProjection; uniform float uMorphTime; uniform bool uIsAnimated; +vec2 unpackBoneIDsAndWeights(int packedData) +{ + return vec2(float((packedData >> 16) & 0xFFFF), float(packedData & 0xFFFF)); +} + void main() { vec4 bindPos = vec4(mix(vPos, vMorphTargetPos, uMorphTime), 1.0); @@ -27,12 +32,19 @@ void main() vec4 finalPos = vec4(0.0); if (uIsAnimated) { - for(int i = 0 ; i < 4; i++) + vec4 boneInfluences[2]; + boneInfluences[0] = vBoneInfluence; + boneInfluences[1] = vBoneInfluenceExtra; + for(int i = 0 ; i < 2; i++) { - int boneIndex = int(vBoneIds[i]); - if(boneIndex < 0) break; + for(int j = 0; j < 4; j++) + { + vec2 boneInfluence = unpackBoneIDsAndWeights(int(boneInfluences[i][j])); + int boneIndex = int(boneInfluence.x); + float weight = boneInfluence.y; - finalPos += uFinalBonesMatrix[boneIndex] * inverse(uRestBonesMatrix[boneIndex]) * bindPos * vBoneWeights[i]; + finalPos += uFinalBonesMatrix[boneIndex] * inverse(uRestBonesMatrix[boneIndex]) * bindPos * weight; + } } } else finalPos = bindPos; diff --git a/FModel/Views/Snooper/Buffers/VertexArrayObject.cs b/FModel/Views/Snooper/Buffers/VertexArrayObject.cs index 820d1885..6bf24c12 100644 --- a/FModel/Views/Snooper/Buffers/VertexArrayObject.cs +++ b/FModel/Views/Snooper/Buffers/VertexArrayObject.cs @@ -26,7 +26,8 @@ public class VertexArrayObject : IDisposable where TVer switch (type) { case VertexAttribPointerType.Int: - GL.VertexAttribIPointer(index, count, VertexAttribIntegerType.Int, vertexSize * _sizeOfVertex, (IntPtr) (offset * _sizeOfVertex)); + case VertexAttribPointerType.UnsignedInt: + GL.VertexAttribIPointer(index, count, (VertexAttribIntegerType) type, vertexSize * _sizeOfVertex, offset * _sizeOfVertex); break; default: GL.VertexAttribPointer(index, count, type, false, vertexSize * _sizeOfVertex, offset * _sizeOfVertex); diff --git a/FModel/Views/Snooper/Models/UModel.cs b/FModel/Views/Snooper/Models/UModel.cs index 6bff5537..8e6fa3d1 100644 --- a/FModel/Views/Snooper/Models/UModel.cs +++ b/FModel/Views/Snooper/Models/UModel.cs @@ -20,6 +20,7 @@ namespace FModel.Views.Snooper.Models; public class VertexAttribute { public int Size; + public VertexAttribPointerType Type; public bool Enabled; } @@ -28,18 +29,18 @@ public abstract class UModel : IRenderableModel protected const int LodLevel = 0; private readonly UObject _export; - private readonly List _vertexAttributes = new() - { - new VertexAttribute { Size = 1, Enabled = false }, // VertexIndex - new VertexAttribute { Size = 3, Enabled = true }, // Position - new VertexAttribute { Size = 3, Enabled = false }, // Normal - new VertexAttribute { Size = 3, Enabled = false }, // Tangent - new VertexAttribute { Size = 2, Enabled = false }, // UV - new VertexAttribute { Size = 1, Enabled = false }, // TextureLayer - new VertexAttribute { Size = 4, Enabled = false }, // Colors - new VertexAttribute { Size = 4, Enabled = false }, // BoneIds - new VertexAttribute { Size = 4, Enabled = false } // BoneWeights - }; + private readonly List _vertexAttributes = + [ + new VertexAttribute { Size = 1, Type = VertexAttribPointerType.Int, Enabled = false }, // VertexIndex + new VertexAttribute { Size = 3, Type = VertexAttribPointerType.Float, Enabled = true }, // Position + new VertexAttribute { Size = 3, Type = VertexAttribPointerType.Float, Enabled = false }, // Normal + new VertexAttribute { Size = 3, Type = VertexAttribPointerType.Float, Enabled = false }, // Tangent + new VertexAttribute { Size = 2, Type = VertexAttribPointerType.Float, Enabled = false }, // UV + new VertexAttribute { Size = 1, Type = VertexAttribPointerType.Float, Enabled = false }, // TextureLayer + new VertexAttribute { Size = 1, Type = VertexAttribPointerType.Float, Enabled = false }, // Colors + new VertexAttribute { Size = 4, Type = VertexAttribPointerType.Float, Enabled = false }, // BoneIds + new VertexAttribute { Size = 4, Type = VertexAttribPointerType.Float, Enabled = false } // BoneWeights + ]; public int Handle { get; set; } public BufferObject Ebo { get; set; } @@ -149,24 +150,20 @@ public abstract class UModel : IRenderableModel if (HasVertexColors) { - var color = lod.VertexColors[i]; - Vertices[baseIndex + count++] = color.R; - Vertices[baseIndex + count++] = color.G; - Vertices[baseIndex + count++] = color.B; - Vertices[baseIndex + count++] = color.A; + Vertices[baseIndex + count++] = lod.VertexColors[i].ToPackedARGB(); } if (vert is CSkelMeshVertex skelVert) { - var weightsHash = skelVert.UnpackWeights(); - Vertices[baseIndex + count++] = skelVert.Bone[0]; - Vertices[baseIndex + count++] = skelVert.Bone[1]; - Vertices[baseIndex + count++] = skelVert.Bone[2]; - Vertices[baseIndex + count++] = skelVert.Bone[3]; - Vertices[baseIndex + count++] = weightsHash[0]; - Vertices[baseIndex + count++] = weightsHash[1]; - Vertices[baseIndex + count++] = weightsHash[2]; - Vertices[baseIndex + count++] = weightsHash[3]; + int max = skelVert.Influences.Count; + for (int j = 0; j < 8; j++) + { + var boneID = j < max ? skelVert.Influences[j].Bone : (short) 0; + var weight = j < max ? skelVert.Influences[j].RawWeight : (byte) 0; + + // Pack bone ID and weight + Vertices[baseIndex + count++] = (boneID << 16) | weight; + } } } @@ -197,8 +194,9 @@ public abstract class UModel : IRenderableModel if (i != 5 || !broken) { - Vao.VertexAttributePointer((uint) i, attribute.Size, i == 0 ? VertexAttribPointerType.Int : VertexAttribPointerType.Float, VertexSize, offset); + Vao.VertexAttributePointer((uint) i, attribute.Size, attribute.Type, VertexSize, offset); } + offset += attribute.Size; }