Skip to content

Commit c21efac

Browse files
committed
VertexInputDescriptor can generate VertexInputBindingDescriptors per VertexType
1 parent 6765f26 commit c21efac

File tree

7 files changed

+179
-40
lines changed

7 files changed

+179
-40
lines changed

src/EngineKit/Graphics/GraphicsPipelineBuilder.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ public IGraphicsPipelineBuilder WithVertexInput(VertexInputDescriptor vertexInpu
5555
return this;
5656
}
5757

58+
public IGraphicsPipelineBuilder WithVertexAttributesForVertexType(VertexType vertexType)
59+
{
60+
_graphicsPipelineDescriptor.VertexInput = VertexInputDescriptor.ForVertexType(vertexType);
61+
return this;
62+
}
63+
5864
public IGraphicsPipelineBuilder WithShadersFromFiles(
5965
string vertexShaderFilePath,
6066
string fragmentShaderFilePath)

src/EngineKit/Graphics/IGraphicsPipelineBuilder.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ IGraphicsPipelineBuilder WithShadersFromStrings(
1313
string fragmentShaderSource);
1414

1515
IGraphicsPipelineBuilder WithVertexInput(VertexInputDescriptor vertexInputDescriptor);
16+
17+
IGraphicsPipelineBuilder WithVertexAttributesForVertexType(VertexType vertexType);
1618

1719
IGraphicsPipelineBuilder WithTopology(
1820
PrimitiveTopology primitiveTopology,

src/EngineKit/Graphics/MeshLoaders/SharpGltfMeshLoader.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ private void ProcessNode(ICollection<MeshPrimitive> meshPrimitives, Node node, I
237237

238238
var meshPrimitive = new MeshPrimitive(meshName);
239239
meshPrimitive.Transform = node.WorldMatrix.ToMatrix();
240-
meshPrimitive.MaterialName = primitive.Material?.Name ?? (primitive.Material == null ? "M_NotFound" : materials.ElementAt(primitive.Material.LogicalIndex)?.Name) ?? "M_NotFound";
240+
meshPrimitive.MaterialName = primitive.Material?.Name ?? (primitive.Material == null ? Material.MaterialNotFoundName : materials.ElementAt(primitive.Material.LogicalIndex)?.Name) ?? Material.MaterialNotFoundName;
241241
meshPrimitive.BoundingBox = BoundingBox.FromPoints(positions.ToArray());
242242

243243
var vertexType = GetVertexTypeFromVertexAccessorNames(primitive!.VertexAccessors!.Keys.ToList());
@@ -269,10 +269,11 @@ private void ProcessNode(ICollection<MeshPrimitive> meshPrimitives, Node node, I
269269

270270
for (var i = 0; i < positions.Length; i++)
271271
{
272-
var position = Vector3.TransformPosition(positions[i], meshPrimitive.Transform);
273-
//var position = positions[i];
274-
var normal = Vector3.TransformDirection(normals[i], meshPrimitive.Transform);
275-
//var normal = normals[i];//Vector3.TransformDirection(normals[i], meshPrimitive.Transform);
272+
//var position = Vector3.TransformPosition(positions[i], meshPrimitive.Transform);
273+
ref var position = ref positions[i];
274+
//var normal = Vector3.TransformDirection(normals[i], meshPrimitive.Transform);
275+
ref var normal = ref normals[i];
276+
276277
var realTangentXyz = new Vector3(realTangents[i].X, realTangents[i].Y, realTangents[i].Z);
277278
var realTangent = new Vector4(realTangentXyz, realTangents[i].W);
278279

src/EngineKit/Graphics/MeshPrimitive.cs

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ public int Stride
6969
VertexType.Unknown => 0,
7070
VertexType.Position => 12,
7171
VertexType.PositionColor => 24,
72-
VertexType.PositionColorNormal => 36,
73-
VertexType.PositionColorNormalUv => 44,
7472
VertexType.PositionColorUv => 32,
7573
VertexType.PositionNormal => 24,
7674
VertexType.PositionNormalUv => 32,
@@ -118,6 +116,7 @@ public static MeshPrimitive Combine(params MeshPrimitive[] meshPrimitives)
118116
return combinedMeshPrimitive;
119117
}
120118

119+
//public Span<VertexPositionNormalUvTangent> GetVertices()
121120
public VertexPositionNormalUvTangent[] GetVertices()
122121
{
123122
if (!RealTangents.Any())
@@ -244,25 +243,6 @@ public void AddPositionColor(
244243
VertexType = VertexType.PositionColor;
245244
}
246245

247-
public void AddPositionColorNormal(
248-
Vector3 position,
249-
Vector3 color,
250-
Vector3 normal)
251-
{
252-
AddVertex(position, color, normal, tangent: null);
253-
VertexType = VertexType.PositionColorNormal;
254-
}
255-
256-
public void AddPositionColorNormalUv(
257-
Vector3 position,
258-
Vector3 color,
259-
Vector3 normal,
260-
Vector2 uv)
261-
{
262-
AddVertex(position, color, normal, uv, tangent: null);
263-
VertexType = VertexType.PositionColorNormalUv;
264-
}
265-
266246
public void AddPositionNormal(
267247
Vector3 position,
268248
Vector3 normal)
Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
1+
using EngineKit.Mathematics;
2+
13
namespace EngineKit.Graphics;
24

35
public readonly struct PooledMesh
46
{
5-
public readonly uint IndexCount;
6-
7-
public readonly uint IndexOffset;
8-
9-
public readonly int VertexCount;
10-
11-
public readonly int VertexOffset;
12-
13-
public readonly string? MaterialName;
14-
15-
public PooledMesh(uint indexCount, uint indexOffset, int vertexCount, int vertexOffset, string? materialName)
7+
public PooledMesh(uint indexCount, uint indexOffset, int vertexCount, int vertexOffset, Vector3 aabbMax, Vector3 aabbMin, string? materialName)
168
{
9+
AabbMax = aabbMax;
10+
AabbMin = aabbMin;
1711
IndexCount = indexCount;
1812
IndexOffset = indexOffset;
1913
VertexCount = vertexCount;
2014
VertexOffset = vertexOffset;
2115
MaterialName = materialName;
2216
}
17+
18+
public readonly Vector3 AabbMax;
19+
20+
public readonly Vector3 AabbMin;
21+
22+
public readonly uint IndexCount;
23+
24+
public readonly uint IndexOffset;
25+
26+
public readonly int VertexCount;
27+
28+
public readonly int VertexOffset;
29+
30+
public readonly string? MaterialName;
2331
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,151 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Runtime.InteropServices;
5+
using EngineKit.Mathematics;
6+
using ImGuiNET;
7+
using Num = System.Numerics;
8+
19
namespace EngineKit.Graphics;
210

311
public readonly record struct VertexInputDescriptor(VertexInputBindingDescriptor[] VertexBindingDescriptors, Label Label)
412
{
13+
private static readonly IDictionary<VertexType, VertexInputDescriptor> _vertexTypeToVertexInputDescriptorMapping;
14+
private static readonly IDictionary<Type, bool> _fieldTypeToNormalizedMapping;
15+
private static readonly IDictionary<Type, int> _fieldTypeToComponentCountMapping;
16+
private static readonly IDictionary<Type, DataType> _fieldTypeToDataTypeMapping;
17+
518
public readonly VertexInputBindingDescriptor[] VertexBindingDescriptors = VertexBindingDescriptors;
619

720
public readonly Label Label = Label;
21+
22+
static VertexInputDescriptor()
23+
{
24+
_fieldTypeToComponentCountMapping = new Dictionary<Type, int>
25+
{
26+
{ typeof(float), 1 },
27+
{ typeof(Vector2), 2 },
28+
{ typeof(Num.Vector2), 2},
29+
{ typeof(Vector3), 3 },
30+
{ typeof(Num.Vector3), 3},
31+
{ typeof(Vector4), 4 },
32+
{ typeof(Num.Vector4), 4},
33+
{ typeof(uint), 4 }
34+
};
35+
_fieldTypeToDataTypeMapping = new Dictionary<Type, DataType>
36+
{
37+
{ typeof(float), DataType.Float },
38+
{ typeof(Vector2), DataType.Float },
39+
{ typeof(Num.Vector2), DataType.Float },
40+
{ typeof(Vector3), DataType.Float },
41+
{ typeof(Num.Vector3), DataType.Float },
42+
{ typeof(Vector4), DataType.Float },
43+
{ typeof(Num.Vector4), DataType.Float },
44+
{ typeof(uint), DataType.UnsignedByte }
45+
};
46+
_fieldTypeToNormalizedMapping = new Dictionary<Type, bool>
47+
{
48+
{ typeof(float), false },
49+
{ typeof(Vector2), false },
50+
{ typeof(Num.Vector2), false },
51+
{ typeof(Vector3), false },
52+
{ typeof(Num.Vector3), false },
53+
{ typeof(Vector4), false },
54+
{ typeof(Num.Vector4), false },
55+
{ typeof(uint), true }
56+
};
57+
_vertexTypeToVertexInputDescriptorMapping = new Dictionary<VertexType, VertexInputDescriptor>
58+
{
59+
{ VertexType.Position, BuildVertexInputDescriptorFor<VertexPosition>() },
60+
{ VertexType.PositionColor, BuildVertexInputDescriptorFor<VertexPositionColor>() },
61+
{ VertexType.PositionColorUv, BuildVertexInputDescriptorFor<VertexPositionColorUv>() },
62+
{ VertexType.PositionNormal, BuildVertexInputDescriptorFor<VertexPositionNormal>() },
63+
{ VertexType.PositionNormalUv, BuildVertexInputDescriptorFor<VertexPositionNormalUv>() },
64+
{ VertexType.PositionNormalUvTangent, BuildVertexInputDescriptorFor<VertexPositionNormalUvTangent>() },
65+
{ VertexType.Default, BuildVertexInputDescriptorFor<VertexPositionNormalUvTangent>() },
66+
{ VertexType.ImGui, BuildVertexInputDescriptorFor<ImDrawVert>() }
67+
};
68+
}
69+
70+
public static VertexInputDescriptor ForVertexType(VertexType vertexType)
71+
{
72+
if (_vertexTypeToVertexInputDescriptorMapping.TryGetValue(vertexType, out var vertexInputDescriptor))
73+
{
74+
return vertexInputDescriptor;
75+
}
76+
77+
throw new ArgumentOutOfRangeException($"VertexType {vertexType} has no vertex input descriptor mapping");
78+
}
79+
80+
private static VertexInputDescriptor BuildVertexInputDescriptorFor<TVertexType>()
81+
{
82+
var vertexType = typeof(TVertexType);
83+
var vertexTypeAttributes = vertexType.GetFields();
84+
var vertexInputBindingDescriptors = vertexTypeAttributes.Select((vertexTypeAttribute, index) =>
85+
{
86+
var binding = 0u;
87+
var location = GetLocationFromFieldName(vertexTypeAttribute.Name);
88+
var dataType = GetDataTypeFromFieldType(vertexTypeAttribute.FieldType);
89+
var componentCount = GetComponentCountFromFieldType(vertexTypeAttribute.FieldType);
90+
var offset = (uint)Marshal.OffsetOf<TVertexType>(vertexTypeAttribute.Name);
91+
var isNormalized = GetNormalizedFromFieldType(vertexTypeAttribute.FieldType);
92+
93+
return new VertexInputBindingDescriptor(location, binding, dataType, componentCount, offset, isNormalized);
94+
});
95+
return new VertexInputDescriptor(vertexInputBindingDescriptors.ToArray(), vertexType.Name);
96+
}
97+
98+
private static uint GetLocationFromFieldName(string fieldName)
99+
{
100+
return fieldName switch
101+
{
102+
"Position" => 0u,
103+
"Color" => 1u,
104+
"Normal" => 2u,
105+
"Uv" => 3u,
106+
"Tangent" => 4u,
107+
_ => GetLocationFromFieldNameForImGui(fieldName)
108+
};
109+
}
110+
111+
private static uint GetLocationFromFieldNameForImGui(string fieldName)
112+
{
113+
return fieldName.ToLower() switch
114+
{
115+
"pos" => 0u,
116+
"uv" => 1u,
117+
"col" => 2u,
118+
_ => throw new ArgumentOutOfRangeException(nameof(fieldName), fieldName, null)
119+
};
120+
}
121+
122+
private static bool GetNormalizedFromFieldType(Type fieldType)
123+
{
124+
if (_fieldTypeToNormalizedMapping.TryGetValue(fieldType, out var isNormalized))
125+
{
126+
return isNormalized;
127+
}
128+
129+
throw new ArgumentOutOfRangeException($"FieldType {fieldType.Name} has no normalized mapping");
130+
}
131+
132+
private static DataType GetDataTypeFromFieldType(Type fieldType)
133+
{
134+
if (_fieldTypeToDataTypeMapping.TryGetValue(fieldType, out var dataType))
135+
{
136+
return dataType;
137+
}
138+
139+
throw new ArgumentOutOfRangeException($"FieldType {fieldType.Name} has no data type mapping");
140+
}
141+
142+
private static int GetComponentCountFromFieldType(Type fieldType)
143+
{
144+
if (_fieldTypeToComponentCountMapping.TryGetValue(fieldType, out var componentCount))
145+
{
146+
return componentCount;
147+
}
148+
149+
throw new ArgumentOutOfRangeException($"FieldType {fieldType.Name} has no component count mapping");
150+
}
8151
}

src/EngineKit/Graphics/VertexType.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ public enum VertexType
77
ImGui,
88
Position,
99
PositionColor,
10-
PositionColorNormal,
11-
PositionColorNormalUv,
1210
PositionColorUv,
1311
PositionNormal,
1412
PositionNormalUv,
1513
PositionNormalUvTangent,
1614
PositionUv,
17-
}
15+
}
16+

0 commit comments

Comments
 (0)