Skip to content

Commit

Permalink
Split the index buffer by accessor
Browse files Browse the repository at this point in the history
  • Loading branch information
pzgulyas committed Feb 15, 2023
1 parent c7fbf27 commit 05ffc63
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Source/ORTS.Common/ConsistGenerator.cs
Expand Up @@ -94,7 +94,7 @@ public static Stream GetConsist(string requestedPath)
GltfVisualTestRun = true;

var models = Directory.EnumerateFileSystemEntries(baseDir, "*.*", SearchOption.AllDirectories)
.Where(f => !f.Contains(Path.Combine(baseDir, "2.0")) && (f.EndsWith(".gltf") || f.EndsWith(".glb")))
.Where(f => !f.Contains(Path.Combine(baseDir, "2.0")) && !f.Contains(Path.Combine(baseDir, "1.0")) && (f.EndsWith(".gltf") || f.EndsWith(".glb")))
.Select(f => Path.GetFileNameWithoutExtension(f))
.Concat(Directory.EnumerateDirectories(Path.Combine(baseDir, "2.0")))
.Where((m, n) => Path.GetFileName(m) == (Path.GetFileNameWithoutExtension(requestedPath).Split('&').ElementAtOrDefault(1) ?? Path.GetFileName(m)) &&
Expand Down
9 changes: 5 additions & 4 deletions Source/RunActivity/Content/SceneryShader.fx
Expand Up @@ -58,6 +58,7 @@ float OverlayScale;
#define MAX_LIGHTS 20
#define MAX_BONES 50
#define CLEARCOAT
static const bool HasTangents = true; // true: tangents are calculated per-vertex, false: tangents are calculated per-pixel

float4x4 Bones[MAX_BONES]; // model -> world [max number of bones]
float4 BaseColorFactor; // glTF linear color multiplier
Expand Down Expand Up @@ -743,8 +744,8 @@ float3 _PSGetNormal(in VERTEX_OUTPUT_PBR In, bool hasTangents, float normalScale

if (hasNormalMap)
{
float3 tex_dx = ddx(float3(In.TexCoords.xy, 0.0));
float3 tex_dy = ddy(float3(In.TexCoords.xy, 0.0));
float3 tex_dx = ddx(float3(-In.TexCoords.xy, 0.0));
float3 tex_dy = ddy(float3(-In.TexCoords.xy, 0.0));
float3 t = (tex_dy.y * pos_dx - tex_dx.y * pos_dy) / (tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y);

if (hasTangents)
Expand Down Expand Up @@ -955,7 +956,7 @@ float4 PSPbr(in VERTEX_OUTPUT_PBR In, bool isFrontFace : SV_IsFrontFace) : COLOR
float3 specularEnvironmentR0 = specularColor.rgb;
float3 specularEnvironmentR90 = float3(1.0, 1.0, 1.0) * reflectance90;

float3 n = _PSGetNormal(In, true, NormalScale, Normal, TextureCoordinates1.z, isFrontFace);
float3 n = _PSGetNormal(In, HasTangents, NormalScale, Normal, TextureCoordinates1.z, isFrontFace);
float3 v = normalize(-In.RelPosition.xyz);

float NdotV = abs(dot(n, v)) + 0.001;
Expand Down Expand Up @@ -987,7 +988,7 @@ float4 PSPbr(in VERTEX_OUTPUT_PBR In, bool isFrontFace : SV_IsFrontFace) : COLOR
clearcoatRoughnessSq = clearcoatAlphaRoughness * clearcoatAlphaRoughness;

// TODO: implement clearcoat texturepacking for being able to check whether the clearcoat normal is the same as the base normal
clearcoatNormal = _PSGetNormal(In, true, ClearcoatNormalScale, ClearcoatNormal, TextureCoordinates2.z, isFrontFace);
clearcoatNormal = _PSGetNormal(In, HasTangents, ClearcoatNormalScale, ClearcoatNormal, TextureCoordinates2.z, isFrontFace);
clearcoatNdotV = abs(dot(clearcoatNormal, v)) + 0.001;

float3 Fr = max((float3)(1.0 - clearcoatRoughness), f0) - f0;
Expand Down
40 changes: 23 additions & 17 deletions Source/RunActivity/Viewer3D/GltfShape.cs
Expand Up @@ -380,7 +380,7 @@ public GltfDistanceLevel(GltfShape shape, int lodId, Gltf gltfFile, string gltfF
Accessors.Clear();
// For interleaved data, multiple vertexElements and multiple accessors will be in a single vertexBuffer.
// For non-interleaved data, we create a distinct vertexBuffer for each accessor.
// A bufferView may consist of a series of (non-interleaved) accessors of POSITION:NORMAL:POSITION:NORMAL:POSITION:NORMAL etc.
// A bufferView may consist of a series of (non-interleaved) accessors of POSITION:NORMAL:POSITION:NORMAL:POSITION:NORMAL etc. (See: 2CylinderEngine)
// Also e.g. TEXCOORDS_0 and TEXCOORDS_1 may refer to the same accessor.
do
{
Expand Down Expand Up @@ -432,22 +432,29 @@ public GltfDistanceLevel(GltfShape shape, int lodId, Gltf gltfFile, string gltfF
.SelectMany(m => m.Primitives)
.OrderBy(p => gltfFile.Accessors?.ElementAtOrDefault(p.Indices ?? -1)?.ByteOffset ?? -1)
.GroupBy(p => gltfFile.Accessors?.ElementAtOrDefault(p.Indices ?? -1)?.BufferView ?? -1)
.Where(i => i.Key != -1 && !IndexBuffers.ContainsKey(i.Key));
.Where(i => i.Key != -1);

foreach (var indexBufferView in indexBufferViews)
{
var accessor = gltfFile.Accessors?.ElementAtOrDefault((int)indexBufferView.First().Indices);
var bufferView = gltfFile.BufferViews?.ElementAtOrDefault(indexBufferView.Key);
var componentSizeInBytes = GetComponentSizeInBytes(accessor.ComponentType);
var indexBuffer = new IndexBuffer(shape.Viewer.GraphicsDevice, GetIndexElementSize(accessor.ComponentType), bufferView.ByteLength / componentSizeInBytes, BufferUsage.None);

// 8 bit indices are unsupported in MonoGame, so we must convert them to 16 bits. GetIndexElementSize() reports twice the length automatically.
if (accessor.ComponentType == Accessor.ComponentTypeEnum.UNSIGNED_BYTE)
indexBuffer.SetData(BinaryBuffers[bufferView.Buffer].Skip(bufferView.ByteOffset).Take(bufferView.ByteLength).Select(b => (ushort)b).ToArray());
else
indexBuffer.SetData(BinaryBuffers[bufferView.Buffer], bufferView.ByteOffset, bufferView.ByteLength);
// Both uint and ushort type indices may exist in a single bufferView, so byteStride is not constant. (See: ToyCar)
// In MonoGame we cannot create a hybrid buffer, so creating the buffer on a per-accessor basis.
foreach (var p in indexBufferView)
{
if (IndexBuffers.ContainsKey((int)p.Indices))
continue;
var accessor = gltfFile.Accessors?.ElementAtOrDefault((int)p.Indices);
var bufferView = gltfFile.BufferViews?.ElementAtOrDefault(indexBufferView.Key);
var componentSizeInBytes = GetComponentSizeInBytes(accessor.ComponentType);
var indexBuffer = new IndexBuffer(shape.Viewer.GraphicsDevice, GetIndexElementSize(accessor.ComponentType), accessor.Count, BufferUsage.None);

// 8 bit indices are unsupported in MonoGame, so we must convert them to 16 bits. GetIndexElementSize() reports twice the length automatically in this case.
if (accessor.ComponentType == Accessor.ComponentTypeEnum.UNSIGNED_BYTE)
indexBuffer.SetData(BinaryBuffers[bufferView.Buffer].Skip(bufferView.ByteOffset + accessor.ByteOffset).Take(accessor.Count * componentSizeInBytes).Select(b => (ushort)b).ToArray());
else
indexBuffer.SetData(BinaryBuffers[bufferView.Buffer], bufferView.ByteOffset + accessor.ByteOffset, accessor.Count * componentSizeInBytes);

IndexBuffers.Add(indexBufferView.Key, indexBuffer);
IndexBuffers.Add((int)p.Indices, indexBuffer);
}
}

var hierarchy = Enumerable.Repeat(-1, gltfFile.Nodes.Length).ToArray();
Expand Down Expand Up @@ -1103,8 +1110,8 @@ public GltfSubObject(MeshPrimitive meshPrimitive, string name, int hierarchyInde

if (gltfFile.Accessors.ElementAtOrDefault(meshPrimitive.Indices ?? -1) is var accessor && accessor != null)
{
indexBufferSet.IndexBuffer = distanceLevel.IndexBuffers[(int)accessor.BufferView];
indexBufferSet.PrimitiveOffset = accessor.ByteOffset / distanceLevel.GetComponentSizeInBytes(accessor.ComponentType);
indexBufferSet.IndexBuffer = distanceLevel.IndexBuffers[(int)meshPrimitive.Indices];
indexBufferSet.PrimitiveOffset = 0;
indexCount = accessor.Count;
options |= SceneryMaterialOptions.PbrHasIndices;
}
Expand Down Expand Up @@ -1322,8 +1329,7 @@ static Vector4[] CalculateTangents(Span<ushort> indices, Span<Vector3> vertexPos
var w2 = vertexTexture[i2];
var w3 = vertexTexture[i3];

// Need to invert the normal map Y coordinates to pass the test
// https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/NormalTangentTest
// Need to invert the normal map Y coordinates to pass the NormalTangentTest
w1.Y = -w1.Y;
w2.Y = -w2.Y;
w3.Y = -w3.Y;
Expand Down

0 comments on commit 05ffc63

Please sign in to comment.