mirror of
https://github.com/sampletext32/ParkanPlayground.git
synced 2026-08-15 02:57:49 +04:00
push
This commit is contained in:
@@ -29,6 +29,14 @@ public static class Extensions
|
|||||||
return BinaryPrimitives.ReadUInt16LittleEndian(buf);
|
return BinaryPrimitives.ReadUInt16LittleEndian(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static short ReadInt16LittleEndian(this Stream fs)
|
||||||
|
{
|
||||||
|
Span<byte> buf = stackalloc byte[2];
|
||||||
|
fs.ReadExactly(buf);
|
||||||
|
|
||||||
|
return BinaryPrimitives.ReadInt16LittleEndian(buf);
|
||||||
|
}
|
||||||
|
|
||||||
public static float ReadFloatLittleEndian(this Stream fs)
|
public static float ReadFloatLittleEndian(this Stream fs)
|
||||||
{
|
{
|
||||||
Span<byte> buf = stackalloc byte[4];
|
Span<byte> buf = stackalloc byte[4];
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
public record Quaternion(float X, float Y, float Z, float W);
|
public record Quaternion(float X, float Y, float Z, float W);
|
||||||
|
|
||||||
public record UShortQuaternion(ushort X, ushort Y, ushort Z, ushort W)
|
public record UShortQuaternion(short W, short X, short Y, short Z)
|
||||||
{
|
{
|
||||||
public Quaternion ToRegular()
|
public Quaternion ToRegular()
|
||||||
{
|
{
|
||||||
|
|||||||
+4
-4
@@ -26,10 +26,10 @@ public static class Msh0x08
|
|||||||
mshFs.ReadFloatLittleEndian()),
|
mshFs.ReadFloatLittleEndian()),
|
||||||
mshFs.ReadFloatLittleEndian(),
|
mshFs.ReadFloatLittleEndian(),
|
||||||
new UShortQuaternion(
|
new UShortQuaternion(
|
||||||
mshFs.ReadUInt16LittleEndian(),
|
mshFs.ReadInt16LittleEndian(),
|
||||||
mshFs.ReadUInt16LittleEndian(),
|
mshFs.ReadInt16LittleEndian(),
|
||||||
mshFs.ReadUInt16LittleEndian(),
|
mshFs.ReadInt16LittleEndian(),
|
||||||
mshFs.ReadUInt16LittleEndian()
|
mshFs.ReadInt16LittleEndian()
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ public static unsafe class PrimitiveMeshes
|
|||||||
BufferUsageARB.StaticDraw);
|
BufferUsageARB.StaticDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint stride = 6 * sizeof(float);
|
const uint stride = 9 * sizeof(float);
|
||||||
|
|
||||||
gl.EnableVertexAttribArray(0);
|
gl.EnableVertexAttribArray(0);
|
||||||
gl.VertexAttribPointer(
|
gl.VertexAttribPointer(
|
||||||
@@ -246,6 +246,16 @@ public static unsafe class PrimitiveMeshes
|
|||||||
stride,
|
stride,
|
||||||
(void*)(3 * sizeof(float)));
|
(void*)(3 * sizeof(float)));
|
||||||
|
|
||||||
|
gl.EnableVertexAttribArray(2);
|
||||||
|
gl.VertexAttribPointer(
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
VertexAttribPointerType.Float,
|
||||||
|
false,
|
||||||
|
stride,
|
||||||
|
(void*)(6 * sizeof(float))
|
||||||
|
);
|
||||||
|
|
||||||
gl.BindVertexArray(0);
|
gl.BindVertexArray(0);
|
||||||
|
|
||||||
return new GpuMesh(gl, vao, vbo, ebo, (uint)indices.Length, primitiveType);
|
return new GpuMesh(gl, vao, vbo, ebo, (uint)indices.Length, primitiveType);
|
||||||
|
|||||||
@@ -0,0 +1,156 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Numerics;
|
||||||
|
using Common;
|
||||||
|
using MshLib;
|
||||||
|
using Quaternion = System.Numerics.Quaternion;
|
||||||
|
using Vector3 = System.Numerics.Vector3;
|
||||||
|
|
||||||
|
namespace NResUI.Rendering.Viewport.Msh;
|
||||||
|
|
||||||
|
public static class MshRestPoseBuilder
|
||||||
|
{
|
||||||
|
public static IReadOnlyList<MshPieceRestPose> BuildRestPose(Msh0x01.Msh0x01Component nodesComponent, List<Msh0x08.AnimationDescriptor> animationDescriptors)
|
||||||
|
{
|
||||||
|
var nodeList = nodesComponent.Nodes;
|
||||||
|
var animationList = animationDescriptors;
|
||||||
|
|
||||||
|
var poses = new MshPieceRestPose[nodeList.Count];
|
||||||
|
var state = new byte[nodeList.Count];
|
||||||
|
|
||||||
|
for (var nodeIndex = 0; nodeIndex < nodeList.Count; nodeIndex++)
|
||||||
|
BuildNodePose(nodeIndex, nodeList, animationList, poses, state);
|
||||||
|
|
||||||
|
return poses;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Matrix4x4 BuildNodePose(
|
||||||
|
int nodeIndex,
|
||||||
|
List<Msh0x01.Node> nodes,
|
||||||
|
List<Msh0x08.AnimationDescriptor> animationDescriptors,
|
||||||
|
MshPieceRestPose[] poses,
|
||||||
|
byte[] state)
|
||||||
|
{
|
||||||
|
if (state[nodeIndex] == 2)
|
||||||
|
return poses[nodeIndex].MeshSpaceTransform;
|
||||||
|
|
||||||
|
if (state[nodeIndex] == 1)
|
||||||
|
{
|
||||||
|
// Broken/cyclic parent chain. Keep this node local so the viewer remains usable.
|
||||||
|
return Matrix4x4.Identity;
|
||||||
|
}
|
||||||
|
state[nodeIndex] = 1;
|
||||||
|
|
||||||
|
var node = nodes[nodeIndex]!;
|
||||||
|
var parentIndex = GetParentIndex(node);
|
||||||
|
var fallbackKeyframeIndex = GetFallbackKeyframeIndex(node);
|
||||||
|
var hasFallbackPose = fallbackKeyframeIndex >= 0 && fallbackKeyframeIndex < animationDescriptors.Count;
|
||||||
|
|
||||||
|
// var localTransform = Matrix4x4.Identity;
|
||||||
|
Matrix4x4 localTransform;
|
||||||
|
if (hasFallbackPose)
|
||||||
|
{
|
||||||
|
localTransform = BuildTransformFromAnimationDescriptor(animationDescriptors[fallbackKeyframeIndex]!);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
localTransform = Matrix4x4.Identity;
|
||||||
|
|
||||||
|
Console.WriteLine($"Node {nodeIndex} has no fallback");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parentIndex == -1)
|
||||||
|
{
|
||||||
|
localTransform.Translation = Vector3.Zero;
|
||||||
|
|
||||||
|
Console.WriteLine($"Node {nodeIndex} has no parent");
|
||||||
|
}
|
||||||
|
|
||||||
|
var meshSpaceTransform = localTransform;
|
||||||
|
if (parentIndex >= 0 && parentIndex < nodes.Count && parentIndex != nodeIndex)
|
||||||
|
{
|
||||||
|
var parentTransform = BuildNodePose(parentIndex, nodes, animationDescriptors, poses, state);
|
||||||
|
meshSpaceTransform = localTransform * parentTransform;
|
||||||
|
}
|
||||||
|
|
||||||
|
poses[nodeIndex] = new MshPieceRestPose(
|
||||||
|
NodeIndex: nodeIndex,
|
||||||
|
ParentIndex: parentIndex,
|
||||||
|
FallbackKeyframeIndex: fallbackKeyframeIndex,
|
||||||
|
HasFallbackPose: hasFallbackPose,
|
||||||
|
LocalTransform: localTransform,
|
||||||
|
MeshSpaceTransform: meshSpaceTransform);
|
||||||
|
|
||||||
|
state[nodeIndex] = 2;
|
||||||
|
return meshSpaceTransform;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetParentIndex(Msh0x01.Node node)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(node.ParentIndexOrMinusOne);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
var rawParent = Convert.ToUInt16(node.ParentIndexOrLink);
|
||||||
|
return rawParent == ushort.MaxValue ? -1 : rawParent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetFallbackKeyframeIndex(Msh0x01.Node node)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var value = Convert.ToUInt16(node.FallbackKey0x08);
|
||||||
|
return value == ushort.MaxValue ? -1 : value;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Matrix4x4 BuildTransformFromAnimationDescriptor(Msh0x08.AnimationDescriptor descriptor)
|
||||||
|
{
|
||||||
|
var position = ToSystemVector3(descriptor.Position);
|
||||||
|
var rotation = ToSystemQuaternion(descriptor.Rotation);
|
||||||
|
|
||||||
|
var matrix = Matrix4x4.CreateFromQuaternion(rotation);
|
||||||
|
matrix.Translation = position;
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector3 ToSystemVector3(dynamic vector)
|
||||||
|
{
|
||||||
|
return new Vector3(
|
||||||
|
Convert.ToSingle(vector.X),
|
||||||
|
Convert.ToSingle(vector.Y),
|
||||||
|
Convert.ToSingle(vector.Z));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Quaternion ToSystemQuaternion(UShortQuaternion packedQuaternion)
|
||||||
|
{
|
||||||
|
// MSH 0x08 stores quaternion as W, X, Y, Z.
|
||||||
|
// System.Numerics.Quaternion constructor expects X, Y, Z, W.
|
||||||
|
|
||||||
|
var q = new Quaternion(
|
||||||
|
packedQuaternion.X / 32767f,
|
||||||
|
packedQuaternion.Y / 32767f,
|
||||||
|
packedQuaternion.Z / 32767f,
|
||||||
|
packedQuaternion.W / 32767f
|
||||||
|
);
|
||||||
|
|
||||||
|
if (q.LengthSquared() < 1e-8f)
|
||||||
|
return Quaternion.Identity;
|
||||||
|
|
||||||
|
return Quaternion.Normalize(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly record struct MshPieceRestPose(
|
||||||
|
int NodeIndex,
|
||||||
|
int ParentIndex,
|
||||||
|
int FallbackKeyframeIndex,
|
||||||
|
bool HasFallbackPose,
|
||||||
|
Matrix4x4 LocalTransform,
|
||||||
|
Matrix4x4 MeshSpaceTransform);
|
||||||
@@ -49,6 +49,9 @@ public static class MshViewportLoader
|
|||||||
var positions = Msh0x03.ReadComponent(fs, archive);
|
var positions = Msh0x03.ReadComponent(fs, archive);
|
||||||
var indices = Msh0x06.ReadComponent(fs, archive);
|
var indices = Msh0x06.ReadComponent(fs, archive);
|
||||||
var batches = Msh0x0D.ReadComponent(fs, archive);
|
var batches = Msh0x0D.ReadComponent(fs, archive);
|
||||||
|
var animationDescriptors = Msh0x08.ReadComponent(fs, archive);
|
||||||
|
var restPoses = MshRestPoseBuilder.BuildRestPose(nodes, animationDescriptors);
|
||||||
|
var mshToViewportTransform = Matrix4x4.CreateRotationX(-MathF.PI * 0.5f);
|
||||||
var names = TryReadNames(fs, archive);
|
var names = TryReadNames(fs, archive);
|
||||||
|
|
||||||
var pieces = new List<ViewportPiece>();
|
var pieces = new List<ViewportPiece>();
|
||||||
@@ -56,6 +59,7 @@ public static class MshViewportLoader
|
|||||||
for (var nodeIndex = 0; nodeIndex < nodes.Nodes.Count; nodeIndex++)
|
for (var nodeIndex = 0; nodeIndex < nodes.Nodes.Count; nodeIndex++)
|
||||||
{
|
{
|
||||||
var node = nodes.Nodes[nodeIndex];
|
var node = nodes.Nodes[nodeIndex];
|
||||||
|
var restPose = restPoses[nodeIndex];
|
||||||
var slotIndex = node.ResolveSlotIndex(DefaultModelState, DefaultLod);
|
var slotIndex = node.ResolveSlotIndex(DefaultModelState, DefaultLod);
|
||||||
if (slotIndex == ushort.MaxValue)
|
if (slotIndex == ushort.MaxValue)
|
||||||
continue;
|
continue;
|
||||||
@@ -72,24 +76,24 @@ public static class MshViewportLoader
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
var name = ResolvePieceName(names, nodeIndex);
|
var name = ResolvePieceName(names, nodeIndex);
|
||||||
var parentIndex = node.ParentIndexOrMinusOne;
|
|
||||||
|
|
||||||
pieces.Add(new ViewportPiece(
|
pieces.Add(new ViewportPiece(
|
||||||
id: nodeIndex,
|
id: nodeIndex,
|
||||||
name: name,
|
name: name,
|
||||||
mesh: meshBuildResult.Mesh,
|
mesh: meshBuildResult.Mesh,
|
||||||
localTransform: Matrix4x4.Identity,
|
localTransform: restPose.MeshSpaceTransform * mshToViewportTransform,
|
||||||
boundsMin: meshBuildResult.BoundsMin,
|
boundsMin: meshBuildResult.BoundsMin,
|
||||||
boundsMax: meshBuildResult.BoundsMax,
|
boundsMax: meshBuildResult.BoundsMax,
|
||||||
debugInfo: new ViewportPieceDebugInfo
|
debugInfo: new ViewportPieceDebugInfo
|
||||||
{
|
{
|
||||||
SourceKind = "MSH 0x01 piece",
|
SourceKind = "MSH 0x01 piece",
|
||||||
SourcePieceIndex = nodeIndex,
|
SourcePieceIndex = nodeIndex,
|
||||||
SourceParentIndex = parentIndex,
|
SourceParentIndex = restPose.ParentIndex,
|
||||||
GeometrySlotIndex = slotIndex,
|
GeometrySlotIndex = slotIndex,
|
||||||
Msh01Flags = (uint)node.Flags,
|
Msh01Flags = (uint)node.Flags,
|
||||||
BatchCount = meshBuildResult.BatchCount,
|
BatchCount = meshBuildResult.BatchCount,
|
||||||
TriangleCount = meshBuildResult.TriangleCount
|
TriangleCount = meshBuildResult.TriangleCount,
|
||||||
|
FallbackKeyframeIndex = restPose.FallbackKeyframeIndex,
|
||||||
|
HasRestPose = restPose.HasFallbackPose
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,9 +139,19 @@ public static class MshViewportLoader
|
|||||||
if (!IsValidTriangle(positions.Count, vertexIndex0, vertexIndex1, vertexIndex2))
|
if (!IsValidTriangle(positions.Count, vertexIndex0, vertexIndex1, vertexIndex2))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
AddTriangleVertex(positions[vertexIndex0], color, vertices, outIndices, ref boundsMin, ref boundsMax);
|
var p0 = ToNumericsVector3(positions[vertexIndex0]);
|
||||||
AddTriangleVertex(positions[vertexIndex1], color, vertices, outIndices, ref boundsMin, ref boundsMax);
|
var p1 = ToNumericsVector3(positions[vertexIndex1]);
|
||||||
AddTriangleVertex(positions[vertexIndex2], color, vertices, outIndices, ref boundsMin, ref boundsMax);
|
var p2 = ToNumericsVector3(positions[vertexIndex2]);
|
||||||
|
|
||||||
|
var normal = Vector3.Cross(p1 - p0, p2 - p0);
|
||||||
|
if (normal.LengthSquared() < 1e-8f)
|
||||||
|
normal = Vector3.UnitY;
|
||||||
|
else
|
||||||
|
normal = Vector3.Normalize(normal);
|
||||||
|
|
||||||
|
AddTriangleVertex(p0, color, normal, vertices, outIndices, ref boundsMin, ref boundsMax);
|
||||||
|
AddTriangleVertex(p1, color, normal, vertices, outIndices, ref boundsMin, ref boundsMax);
|
||||||
|
AddTriangleVertex(p2, color, normal, vertices, outIndices, ref boundsMin, ref boundsMax);
|
||||||
triangleCount++;
|
triangleCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,13 +163,20 @@ public static class MshViewportLoader
|
|||||||
return new PieceMeshBuildResult(mesh, boundsMin, boundsMax, batchCount, triangleCount);
|
return new PieceMeshBuildResult(mesh, boundsMin, boundsMax, batchCount, triangleCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Vector3 ToNumericsVector3(Common.Vector3 position)
|
||||||
|
{
|
||||||
|
return new Vector3(position.X, position.Y, position.Z);
|
||||||
|
}
|
||||||
|
|
||||||
private static void AddTriangleVertex(
|
private static void AddTriangleVertex(
|
||||||
Common.Vector3 position,
|
Vector3 position,
|
||||||
Vector3 color,
|
Vector3 color,
|
||||||
|
Vector3 normal,
|
||||||
List<float> vertices,
|
List<float> vertices,
|
||||||
List<uint> indices,
|
List<uint> indices,
|
||||||
ref Vector3 boundsMin,
|
ref Vector3 boundsMin,
|
||||||
ref Vector3 boundsMax)
|
ref Vector3 boundsMax
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var vertexIndex = (uint)(vertices.Count / 6);
|
var vertexIndex = (uint)(vertices.Count / 6);
|
||||||
|
|
||||||
@@ -165,6 +186,9 @@ public static class MshViewportLoader
|
|||||||
vertices.Add(color.X);
|
vertices.Add(color.X);
|
||||||
vertices.Add(color.Y);
|
vertices.Add(color.Y);
|
||||||
vertices.Add(color.Z);
|
vertices.Add(color.Z);
|
||||||
|
vertices.Add(normal.X);
|
||||||
|
vertices.Add(normal.Y);
|
||||||
|
vertices.Add(normal.Z);
|
||||||
|
|
||||||
indices.Add(vertexIndex);
|
indices.Add(vertexIndex);
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,11 @@ public sealed unsafe class ShaderProgram
|
|||||||
_gl.UniformMatrix4(location, 1, false, (float*)&matrix);
|
_gl.UniformMatrix4(location, 1, false, (float*)&matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetVector3(int location, Vector3 value)
|
||||||
|
{
|
||||||
|
_gl.Uniform3(location, value.X, value.Y, value.Z);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetVector4(int location, Vector4 value)
|
public void SetVector4(int location, Vector4 value)
|
||||||
{
|
{
|
||||||
_gl.Uniform4(location, value.X, value.Y, value.Z, value.W);
|
_gl.Uniform4(location, value.X, value.Y, value.Z, value.W);
|
||||||
|
|||||||
@@ -9,5 +9,8 @@ public sealed class ViewportPieceDebugInfo
|
|||||||
public int BatchCount { get; init; }
|
public int BatchCount { get; init; }
|
||||||
public int TriangleCount { get; init; }
|
public int TriangleCount { get; init; }
|
||||||
|
|
||||||
|
public int FallbackKeyframeIndex { get; init; } = -1;
|
||||||
|
public bool HasRestPose { get; init; }
|
||||||
|
|
||||||
public string SourceKind { get; init; } = "MSH";
|
public string SourceKind { get; init; } = "MSH";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,10 @@ public sealed class ViewportRenderer
|
|||||||
private GpuMesh? _unitWireBoxMesh;
|
private GpuMesh? _unitWireBoxMesh;
|
||||||
private GpuMesh? _axesMesh;
|
private GpuMesh? _axesMesh;
|
||||||
|
|
||||||
private int _meshMvpLocation;
|
private int _modelLocation;
|
||||||
|
private int _mvpLocation;
|
||||||
|
private int _lightDirectionLocation;
|
||||||
|
|
||||||
private int _outlineMvpLocation;
|
private int _outlineMvpLocation;
|
||||||
private int _outlineColorLocation;
|
private int _outlineColorLocation;
|
||||||
|
|
||||||
@@ -44,8 +47,7 @@ public sealed class ViewportRenderer
|
|||||||
_framebuffer.BindForRender();
|
_framebuffer.BindForRender();
|
||||||
|
|
||||||
_gl.Enable(EnableCap.DepthTest);
|
_gl.Enable(EnableCap.DepthTest);
|
||||||
_gl.Enable(EnableCap.CullFace);
|
_gl.Disable(EnableCap.CullFace);
|
||||||
_gl.CullFace(TriangleFace.Back);
|
|
||||||
|
|
||||||
_gl.ClearColor(0.12f, 0.13f, 0.15f, 1.0f);
|
_gl.ClearColor(0.12f, 0.13f, 0.15f, 1.0f);
|
||||||
_gl.ClearStencil(0);
|
_gl.ClearStencil(0);
|
||||||
@@ -66,7 +68,6 @@ public sealed class ViewportRenderer
|
|||||||
_gl.PolygonMode(TriangleFace.FrontAndBack, PolygonMode.Fill);
|
_gl.PolygonMode(TriangleFace.FrontAndBack, PolygonMode.Fill);
|
||||||
_framebuffer.Resolve();
|
_framebuffer.Resolve();
|
||||||
|
|
||||||
_gl.Disable(EnableCap.CullFace);
|
|
||||||
_gl.Disable(EnableCap.DepthTest);
|
_gl.Disable(EnableCap.DepthTest);
|
||||||
_gl.Disable(EnableCap.StencilTest);
|
_gl.Disable(EnableCap.StencilTest);
|
||||||
_gl.UseProgram(0);
|
_gl.UseProgram(0);
|
||||||
@@ -96,14 +97,12 @@ public sealed class ViewportRenderer
|
|||||||
var mvp = model * view * projection;
|
var mvp = model * view * projection;
|
||||||
|
|
||||||
_gl.Disable(EnableCap.StencilTest);
|
_gl.Disable(EnableCap.StencilTest);
|
||||||
_gl.Disable(EnableCap.CullFace);
|
|
||||||
_gl.PolygonMode(TriangleFace.FrontAndBack, PolygonMode.Fill);
|
_gl.PolygonMode(TriangleFace.FrontAndBack, PolygonMode.Fill);
|
||||||
|
|
||||||
_meshShader.Use();
|
_meshShader.Use();
|
||||||
_meshShader.SetMatrix4(_meshMvpLocation, mvp);
|
_meshShader.SetMatrix4(_mvpLocation, mvp);
|
||||||
grid.Mesh.Draw();
|
grid.Mesh.Draw();
|
||||||
|
|
||||||
_gl.Enable(EnableCap.CullFace);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawScene(
|
private void DrawScene(
|
||||||
@@ -166,7 +165,6 @@ public sealed class ViewportRenderer
|
|||||||
throw new InvalidOperationException("Viewport debug resources are not initialized.");
|
throw new InvalidOperationException("Viewport debug resources are not initialized.");
|
||||||
|
|
||||||
_gl.Disable(EnableCap.StencilTest);
|
_gl.Disable(EnableCap.StencilTest);
|
||||||
_gl.Disable(EnableCap.CullFace);
|
|
||||||
_gl.Disable(EnableCap.DepthTest);
|
_gl.Disable(EnableCap.DepthTest);
|
||||||
_gl.PolygonMode(TriangleFace.FrontAndBack, PolygonMode.Fill);
|
_gl.PolygonMode(TriangleFace.FrontAndBack, PolygonMode.Fill);
|
||||||
_gl.LineWidth(2.0f);
|
_gl.LineWidth(2.0f);
|
||||||
@@ -203,7 +201,6 @@ public sealed class ViewportRenderer
|
|||||||
|
|
||||||
_gl.LineWidth(1.0f);
|
_gl.LineWidth(1.0f);
|
||||||
_gl.Enable(EnableCap.DepthTest);
|
_gl.Enable(EnableCap.DepthTest);
|
||||||
_gl.Enable(EnableCap.CullFace);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawPiece(
|
private void DrawPiece(
|
||||||
@@ -248,8 +245,13 @@ public sealed class ViewportRenderer
|
|||||||
|
|
||||||
var mvp = model * view * projection;
|
var mvp = model * view * projection;
|
||||||
|
|
||||||
|
var lightDirection = Vector3.Normalize(new Vector3(-0.35f, -0.75f, -0.55f));
|
||||||
|
|
||||||
_meshShader.Use();
|
_meshShader.Use();
|
||||||
_meshShader.SetMatrix4(_meshMvpLocation, mvp);
|
_meshShader.SetMatrix4(_mvpLocation, mvp);
|
||||||
|
_meshShader.SetMatrix4(_modelLocation, model);
|
||||||
|
_meshShader.SetVector3(_lightDirectionLocation, lightDirection);
|
||||||
|
|
||||||
mesh.Draw();
|
mesh.Draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,14 +281,18 @@ public sealed class ViewportRenderer
|
|||||||
|
|
||||||
layout (location = 0) in vec3 aPosition;
|
layout (location = 0) in vec3 aPosition;
|
||||||
layout (location = 1) in vec3 aColor;
|
layout (location = 1) in vec3 aColor;
|
||||||
|
layout (location = 2) in vec3 aNormal;
|
||||||
|
|
||||||
|
uniform mat4 uModel;
|
||||||
uniform mat4 uMvp;
|
uniform mat4 uMvp;
|
||||||
|
|
||||||
out vec3 vColor;
|
out vec3 vColor;
|
||||||
|
out vec3 vNormalWorld;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vColor = aColor;
|
vColor = aColor;
|
||||||
|
vNormalWorld = mat3(transpose(inverse(uModel))) * aNormal;
|
||||||
gl_Position = uMvp * vec4(aPosition, 1.0);
|
gl_Position = uMvp * vec4(aPosition, 1.0);
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
@@ -295,11 +301,26 @@ public sealed class ViewportRenderer
|
|||||||
#version 330 core
|
#version 330 core
|
||||||
|
|
||||||
in vec3 vColor;
|
in vec3 vColor;
|
||||||
|
in vec3 vNormalWorld;
|
||||||
|
|
||||||
|
uniform vec3 uLightDirectionWorld;
|
||||||
|
|
||||||
out vec4 FragColor;
|
out vec4 FragColor;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
FragColor = vec4(vColor, 1.0);
|
vec3 normal = normalize(vNormalWorld);
|
||||||
|
|
||||||
|
// Useful when backface display is enabled.
|
||||||
|
if (!gl_FrontFacing)
|
||||||
|
normal = -normal;
|
||||||
|
|
||||||
|
vec3 lightDir = normalize(-uLightDirectionWorld);
|
||||||
|
|
||||||
|
float diffuse = max(dot(normal, lightDir), 0.0);
|
||||||
|
float lighting = 0.35 + diffuse * 0.65;
|
||||||
|
|
||||||
|
FragColor = vec4(vColor * lighting, 1.0);
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
@@ -329,9 +350,13 @@ public sealed class ViewportRenderer
|
|||||||
""";
|
""";
|
||||||
|
|
||||||
_meshShader = new ShaderProgram(_gl, meshVertexShaderSource, meshFragmentShaderSource, "Viewport mesh");
|
_meshShader = new ShaderProgram(_gl, meshVertexShaderSource, meshFragmentShaderSource, "Viewport mesh");
|
||||||
_outlineShader = new ShaderProgram(_gl, outlineVertexShaderSource, outlineFragmentShaderSource, "Viewport outline");
|
_outlineShader = new ShaderProgram(_gl, outlineVertexShaderSource, outlineFragmentShaderSource,
|
||||||
|
"Viewport outline");
|
||||||
|
|
||||||
|
_modelLocation = _meshShader.GetUniformLocation("uModel");
|
||||||
|
_mvpLocation = _meshShader.GetUniformLocation("uMvp");
|
||||||
|
_lightDirectionLocation = _meshShader.GetUniformLocation("uLightDirectionWorld");
|
||||||
|
|
||||||
_meshMvpLocation = _meshShader.GetUniformLocation("uMvp");
|
|
||||||
_outlineMvpLocation = _outlineShader.GetUniformLocation("uMvp");
|
_outlineMvpLocation = _outlineShader.GetUniformLocation("uMvp");
|
||||||
_outlineColorLocation = _outlineShader.GetUniformLocation("uColor");
|
_outlineColorLocation = _outlineShader.GetUniformLocation("uColor");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user