Skip to content

Commit

Permalink
Remove instancing, for now, to simplify render pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
tgjones committed Dec 25, 2017
1 parent 277dc91 commit b7dc4ea
Show file tree
Hide file tree
Showing 15 changed files with 153 additions and 386 deletions.
6 changes: 4 additions & 2 deletions src/OpenSage.Game/Graphics/Effects/MeshMaterial.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Runtime.InteropServices;
using System.Numerics;
using System.Runtime.InteropServices;

namespace OpenSage.Graphics.Effects
{
Expand All @@ -11,8 +12,9 @@ protected MeshMaterial(Effect effect)
}

[StructLayout(LayoutKind.Sequential)]
public struct SkinningConstants
public struct MeshConstants
{
public Matrix4x4 World;
public bool SkinningEnabled;
public uint NumBones;
}
Expand Down
2 changes: 1 addition & 1 deletion src/OpenSage.Game/Graphics/MeshComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public sealed class MeshComponent : RenderableComponent

internal override void BuildRenderList(RenderList renderList)
{
renderList.AddInstancedRenderItem(Mesh, this);
Mesh.BuildRenderList(renderList, this);
}
}
}
10 changes: 2 additions & 8 deletions src/OpenSage.Game/Graphics/MeshVertex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,12 @@ public struct TexCoords
new VertexAttributeDescription("BLENDINDICES", 0, VertexFormat.UInt, 48, 0),

new VertexAttributeDescription("TEXCOORD", 0, VertexFormat.Float2, 0, 1),
new VertexAttributeDescription("TEXCOORD", 1, VertexFormat.Float2, 8, 1),

new VertexAttributeDescription("TEXCOORD", 2, VertexFormat.Float4, 0, 2),
new VertexAttributeDescription("TEXCOORD", 3, VertexFormat.Float4, 16, 2),
new VertexAttributeDescription("TEXCOORD", 4, VertexFormat.Float4, 32, 2),
new VertexAttributeDescription("TEXCOORD", 5, VertexFormat.Float4, 48, 2),
new VertexAttributeDescription("TEXCOORD", 1, VertexFormat.Float2, 8, 1)
},
new[]
{
new VertexLayoutDescription(InputClassification.PerVertexData, 52),
new VertexLayoutDescription(InputClassification.PerVertexData, 16),
new VertexLayoutDescription(InputClassification.PerInstanceData, 64)
new VertexLayoutDescription(InputClassification.PerVertexData, 16)
});
}
}
2 changes: 1 addition & 1 deletion src/OpenSage.Game/Graphics/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public Entity CreateEntity()
{
// Add skinned mesh component to root model entity,
// not bone entity.
result.Components.Add(new SkinnedMeshComponent
result.Components.Add(new MeshComponent
{
Mesh = mesh
});
Expand Down
94 changes: 72 additions & 22 deletions src/OpenSage.Game/Graphics/ModelMesh.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using OpenSage.Graphics.Effects;
using OpenSage.Graphics.Rendering;
using OpenSage.Mathematics;
using System.Numerics;
using OpenSage.Graphics.Cameras;

namespace OpenSage.Graphics
{
Expand All @@ -24,7 +26,10 @@ public sealed class ModelMesh : GraphicsObject
private readonly Buffer<MeshVertex.Basic> _vertexBuffer;
private readonly Buffer<ushort> _indexBuffer;

private readonly Buffer<MeshMaterial.SkinningConstants> _skinningConstantsBuffer;
private readonly ConstantBuffer<MeshMaterial.MeshConstants> _meshConstantsBuffer;

private readonly Buffer<Matrix4x3> _skinningBuffer;
private readonly Matrix4x3[] _skinningBones;

private readonly Effect _effect;

Expand Down Expand Up @@ -80,14 +85,19 @@ public ModelMesh(
indices,
BufferBindFlags.IndexBuffer));

_skinningConstantsBuffer = AddDisposable(Buffer<MeshMaterial.SkinningConstants>.CreateStatic(
graphicsDevice,
new MeshMaterial.SkinningConstants
{
SkinningEnabled = isSkinned,
NumBones = numBones
},
BufferBindFlags.ConstantBuffer));
_meshConstantsBuffer = AddDisposable(new ConstantBuffer<MeshMaterial.MeshConstants>(graphicsDevice));
_meshConstantsBuffer.Value.SkinningEnabled = isSkinned;
_meshConstantsBuffer.Value.NumBones = numBones;

if (isSkinned)
{
_skinningBuffer = AddDisposable(Buffer<Matrix4x3>.CreateDynamicArray(
graphicsDevice,
(int) numBones,
BufferBindFlags.ShaderResource));

_skinningBones = new Matrix4x3[numBones];
}

foreach (var materialPass in materialPasses)
{
Expand All @@ -96,7 +106,7 @@ public ModelMesh(
MaterialPasses = materialPasses;
}

internal void BuildRenderList(RenderList renderList, RenderInstanceData instanceData)
internal void BuildRenderList(RenderList renderList, MeshComponent mesh)
{
if (Hidden)
{
Expand All @@ -116,18 +126,19 @@ internal void BuildRenderList(RenderList renderList, RenderInstanceData instance

if (filteredMaterialPasses.Count > 0)
{
renderList.AddRenderItem(new InstancedRenderItem(
instanceData,
_effect,
renderList.AddRenderItem(new RenderItem(
mesh,
filteredMaterialPasses[0].MeshParts[0].Material, // TODO
pipelineStateHandle,
(commandEncoder, e, h, _) =>
(commandEncoder, e, h, c) =>
{
Draw(
commandEncoder,
_effect,
h,
filteredMaterialPasses,
instanceData);
mesh,
c);
}));
}
}
Expand All @@ -138,16 +149,56 @@ private void Draw(
Effect effect,
EffectPipelineStateHandle pipelineStateHandle,
IEnumerable<ModelMeshMaterialPass> materialPasses,
RenderInstanceData instanceData)
MeshComponent renderable,
CameraComponent camera)
{
commandEncoder.SetVertexBuffer(2, instanceData.WorldBuffer);

if (Skinned)
{
effect.SetValue("SkinningBuffer", instanceData.SkinningBuffer);
var bones = renderable.Entity.GetComponent<ModelComponent>().Bones;

for (var i = 0; i < NumBones; i++)
{
// Bone matrix should be relative to root bone transform.
var rootBoneMatrix = bones[0].LocalToWorldMatrix;
var boneMatrix = bones[i].LocalToWorldMatrix;

var boneMatrixRelativeToRoot = boneMatrix * Matrix4x4Utility.Invert(rootBoneMatrix);

boneMatrixRelativeToRoot.ToMatrix4x3(out _skinningBones[i]);
}

_skinningBuffer.SetData(_skinningBones);

effect.SetValue("SkinningBuffer", _skinningBuffer);
}

Matrix4x4 world;
if (CameraOriented)
{
var localToWorldMatrix = renderable.Transform.LocalToWorldMatrix;

var viewInverse = Matrix4x4Utility.Invert(camera.View);
var cameraPosition = viewInverse.Translation;

var toCamera = Vector3.Normalize(Vector3.TransformNormal(
cameraPosition - renderable.Transform.WorldPosition,
renderable.Transform.WorldToLocalMatrix));

toCamera.Z = 0;

var cameraOrientedRotation = Matrix4x4.CreateFromQuaternion(QuaternionUtility.CreateRotation(Vector3.UnitX, toCamera));

world = cameraOrientedRotation * localToWorldMatrix;
}
else
{
world = renderable.Transform.LocalToWorldMatrix;
}

_meshConstantsBuffer.Value.World = world;
_meshConstantsBuffer.Update();

effect.SetValue("SkinningConstants", _skinningConstantsBuffer);
effect.SetValue("MeshConstants", _meshConstantsBuffer.Buffer);

commandEncoder.SetVertexBuffer(0, _vertexBuffer);

Expand All @@ -166,10 +217,9 @@ private void Draw(

effect.Apply(commandEncoder);

commandEncoder.DrawIndexedInstanced(
commandEncoder.DrawIndexed(
PrimitiveType.TriangleList,
meshPart.IndexCount,
instanceData.NumInstances,
_indexBuffer,
meshPart.StartIndex);
}
Expand Down
32 changes: 32 additions & 0 deletions src/OpenSage.Game/Graphics/Rendering/Culler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Collections.Generic;

namespace OpenSage.Graphics.Rendering
{
internal sealed class Culler
{
public void Cull(List<RenderItem> items, RenderContext context)
{
foreach (var renderItem in items)
{
renderItem.Visible = true;

if (renderItem.Renderable.IsAlwaysVisible)
{
continue;
}

if (!renderItem.Renderable.Entity.VisibleInHierarchy)
{
renderItem.Visible = false;
continue;
}

if (!context.Camera.BoundingFrustum.Intersects(renderItem.Renderable.BoundingBox))
{
renderItem.Visible = false;
continue;
}
}
}
}
}
Loading

0 comments on commit b7dc4ea

Please sign in to comment.