From 867d4d7f5df48947fb9afcbd60ed9151e19d25ff Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Mon, 7 Dec 2020 15:51:45 -0800 Subject: [PATCH] testing instancing --- .vscode/tasks.json | 2 +- FNA | 2 +- Kav | 2 +- KavTest/Components/InstancedCubeComponent.cs | 6 ++ KavTest/Components/ModelComponent.cs | 4 +- KavTest/Engines/Spawners/RustyBallSpawner.cs | 2 +- .../Engines/Spawners/StaticModelSpawner.cs | 2 +- KavTest/InstancedModelContainer.cs | 9 ++ KavTest/KavTestGame.cs | 86 +++++++++++-------- KavTest/Renderers/SceneRenderer.cs | 72 +++++++++++++++- 10 files changed, 139 insertions(+), 48 deletions(-) create mode 100644 KavTest/Components/InstancedCubeComponent.cs create mode 100644 KavTest/InstancedModelContainer.cs diff --git a/.vscode/tasks.json b/.vscode/tasks.json index afc23db..ba9d5a3 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -94,7 +94,7 @@ "env": { "LD_LIBRARY_PATH": "./lib64", "DYLD_LIBRARY_PATH": "./osx", - "FNA3D_FORCE_DRIVER": "Vulkan" + "FNA3D_FORCE_DRIVER": "OpenGL" }, "cwd": "${workspaceFolder}/KavTest/bin/x64/Debug/net48" }, diff --git a/FNA b/FNA index 1df9f58..7357a6f 160000 --- a/FNA +++ b/FNA @@ -1 +1 @@ -Subproject commit 1df9f588a701eefc4b55a0869cd5871be0124307 +Subproject commit 7357a6f297fee33b7a8d5afddaca30480c591ba5 diff --git a/Kav b/Kav index 8b43e8f..bb694d3 160000 --- a/Kav +++ b/Kav @@ -1 +1 @@ -Subproject commit 8b43e8f45ee6fa35f5c4d4924a62a3fcafe61301 +Subproject commit bb694d3dbe47dcfcee6bfe3fb315587419ba8c0f diff --git a/KavTest/Components/InstancedCubeComponent.cs b/KavTest/Components/InstancedCubeComponent.cs new file mode 100644 index 0000000..64a1580 --- /dev/null +++ b/KavTest/Components/InstancedCubeComponent.cs @@ -0,0 +1,6 @@ +using Encompass; + +namespace KavTest.Components +{ + public struct InstancedCubeComponent : IComponent { } +} diff --git a/KavTest/Components/ModelComponent.cs b/KavTest/Components/ModelComponent.cs index 6711d09..b86ee48 100644 --- a/KavTest/Components/ModelComponent.cs +++ b/KavTest/Components/ModelComponent.cs @@ -6,10 +6,12 @@ namespace KavTest.Components public struct ModelComponent : IComponent { public Model Model { get; } + public bool Instanced { get; } - public ModelComponent(Model model) + public ModelComponent(Model model, bool instanced) { Model = model; + Instanced = instanced; } } } diff --git a/KavTest/Engines/Spawners/RustyBallSpawner.cs b/KavTest/Engines/Spawners/RustyBallSpawner.cs index 1bd5dd9..52199c9 100644 --- a/KavTest/Engines/Spawners/RustyBallSpawner.cs +++ b/KavTest/Engines/Spawners/RustyBallSpawner.cs @@ -19,7 +19,7 @@ namespace KavTest.Spawners var entity = CreateEntity(); AddComponent(entity, new Transform3DComponent(message.Transform)); - AddComponent(entity, new ModelComponent(RustyBallModel)); + AddComponent(entity, new ModelComponent(RustyBallModel, true)); AddComponent(entity, new AngularVelocityComponent(message.AngularVelocity)); } } diff --git a/KavTest/Engines/Spawners/StaticModelSpawner.cs b/KavTest/Engines/Spawners/StaticModelSpawner.cs index 772d3e3..ca6af83 100644 --- a/KavTest/Engines/Spawners/StaticModelSpawner.cs +++ b/KavTest/Engines/Spawners/StaticModelSpawner.cs @@ -11,7 +11,7 @@ namespace KavTest.Spawners var entity = CreateEntity(); AddComponent(entity, new Transform3DComponent(message.Transform)); - AddComponent(entity, new ModelComponent(message.Model)); + AddComponent(entity, new ModelComponent(message.Model, true)); } } } diff --git a/KavTest/InstancedModelContainer.cs b/KavTest/InstancedModelContainer.cs new file mode 100644 index 0000000..5b05822 --- /dev/null +++ b/KavTest/InstancedModelContainer.cs @@ -0,0 +1,9 @@ +using Kav; + +namespace KavTest +{ + public class InstancedModelContainer + { + public MeshPart CubeModel { get; set; } + } +} diff --git a/KavTest/KavTestGame.cs b/KavTest/KavTestGame.cs index ca6e354..3348fd9 100644 --- a/KavTest/KavTestGame.cs +++ b/KavTest/KavTestGame.cs @@ -16,6 +16,7 @@ namespace KavTest class KavTestGame : Game { GraphicsDeviceManager graphics; + InstancedModelContainer InstancedModelContainer { get; } = new InstancedModelContainer(); WorldBuilder WorldBuilder { get; } = new WorldBuilder(); World World { get; set; } @@ -119,6 +120,10 @@ namespace KavTest ) ); + InstancedModelContainer.CubeModel = cubeModel.Meshes[0].MeshParts[0]; + InstancedModelContainer.CubeModel.Albedo = Color.Blue.ToVector3(); + InstancedModelContainer.CubeModel.DisableAlbedoMap = true; + Texture2D.TextureDataFromStreamEXT( File.OpenRead("Content/Skybox/front.jpg"), out var skyboxSize, @@ -187,7 +192,7 @@ namespace KavTest WorldBuilder.AddEngine(new StaticModelSpawner()); WorldBuilder.AddEngine(new DirectionalLightSpawner()); WorldBuilder.AddEngine(new MeshSpriteSpawner()); - WorldBuilder.AddGeneralRenderer(new SceneRenderer(GraphicsDevice), 0); + WorldBuilder.AddGeneralRenderer(new SceneRenderer(GraphicsDevice, InstancedModelContainer), 0); // WorldBuilder.SendMessage(new RustyBallSpawnMessage( // new Transform3D(new Vector3(0, 0, 0)), @@ -209,46 +214,51 @@ namespace KavTest // rustyBallModel // )); - WorldBuilder.SendMessage(new StaticModelSpawnMessage( - new Transform3D(new Vector3(0, -3, 0), Quaternion.Identity, new Vector3(10f, 1f, 10f)), - floorModel - )); + // WorldBuilder.SendMessage(new StaticModelSpawnMessage( + // new Transform3D(new Vector3(0, -3, 0), Quaternion.Identity, new Vector3(10f, 1f, 10f)), + // floorModel + // )); - WorldBuilder.SendMessage(new StaticModelSpawnMessage( - new Transform3D( - new Vector3(0, 1, 0), - Quaternion.CreateFromAxisAngle( - Vector3.Right, - -Microsoft.Xna.Framework.MathHelper.PiOver2 - ), - new Vector3(1f, 1f, 1f) - ), - redCylinderModel - )); + // WorldBuilder.SendMessage(new StaticModelSpawnMessage( + // new Transform3D( + // new Vector3(0, 1, 0), + // Quaternion.CreateFromAxisAngle( + // Vector3.Right, + // -Microsoft.Xna.Framework.MathHelper.PiOver2 + // ), + // new Vector3(1f, 1f, 1f) + // ), + // redCylinderModel + // )); - WorldBuilder.SendMessage(new StaticModelSpawnMessage( - new Transform3D( - new Vector3(-3, 1, 0), - Quaternion.CreateFromAxisAngle( - Vector3.Right, - -Microsoft.Xna.Framework.MathHelper.PiOver2 - ), - new Vector3(1f, 1f, 1f) - ), - blueTorusModel - )); + // WorldBuilder.SendMessage(new StaticModelSpawnMessage( + // new Transform3D( + // new Vector3(-3, 1, 0), + // Quaternion.CreateFromAxisAngle( + // Vector3.Right, + // -Microsoft.Xna.Framework.MathHelper.PiOver2 + // ), + // new Vector3(1f, 1f, 1f) + // ), + // blueTorusModel + // )); - WorldBuilder.SendMessage(new StaticModelSpawnMessage( - new Transform3D( - new Vector3(3, 1, 0), - Quaternion.CreateFromAxisAngle( - Vector3.Right, - -Microsoft.Xna.Framework.MathHelper.PiOver2 - ), - new Vector3(1f, 1f, 1f) - ), - cubeModel - )); + for (int i = -10; i < 10; i++) + { + for (int j = -10; j < 10; j++) + { + for (int k = -10; k < 10; k++) + { + var entity = WorldBuilder.CreateEntity(); + WorldBuilder.SetComponent(entity, new Transform3DComponent( + new Transform3D( + new Vector3(i * 3, j * 3, k * 3) + ) + )); + WorldBuilder.SetComponent(entity, new InstancedCubeComponent()); + } + } + } WorldBuilder.SendMessage(new MeshSpriteSpawnMessage( new Transform3D(new Vector3(3, 0, 11), Quaternion.CreateFromAxisAngle(Vector3.Up, (float)System.Math.PI), Vector3.One), diff --git a/KavTest/Renderers/SceneRenderer.cs b/KavTest/Renderers/SceneRenderer.cs index 8b27c18..41bdd11 100644 --- a/KavTest/Renderers/SceneRenderer.cs +++ b/KavTest/Renderers/SceneRenderer.cs @@ -13,6 +13,7 @@ namespace KavTest.Renderers { private GraphicsDevice GraphicsDevice { get; } private SpriteBatch SpriteBatch { get; } + private InstancedModelContainer InstancedModelContainer { get; } private Kav.Renderer Renderer { get; } @@ -26,6 +27,24 @@ namespace KavTest.Renderers private RenderTarget2D DeferredTarget { get; } private RenderTarget2D BillboardTarget { get; } + private readonly Dictionary> InstanceMap = new Dictionary>(); + + private IEnumerable CubeTransforms + { + get + { + foreach (var entity in ReadEntitiesAsEnumerable()) + { + if (HasComponent(entity)) + { + var transformComponent = GetComponent(entity); + + yield return transformComponent.Transform.TransformMatrix; + } + } + } + } + private IEnumerable<(Kav.Model, Matrix)> ModelTransforms { get @@ -117,9 +136,12 @@ namespace KavTest.Renderers } } - public SceneRenderer(GraphicsDevice graphicsDevice) - { + public SceneRenderer( + GraphicsDevice graphicsDevice, + InstancedModelContainer instancedModelContainer + ) { GraphicsDevice = graphicsDevice; + InstancedModelContainer = instancedModelContainer; var renderDimensionsX = GraphicsDevice.PresentationParameters.BackBufferWidth; var renderDimensionsY = GraphicsDevice.PresentationParameters.BackBufferHeight; @@ -220,11 +242,19 @@ namespace KavTest.Renderers GraphicsDevice.SetRenderTargets(GBuffer); GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0); + GraphicsDevice.DepthStencilState = DepthStencilState.Default; - Renderer.GBufferRender( + // Renderer.GBufferRender( + // GBuffer, + // camera, + // ModelTransforms + // ); + + Renderer.InstancedGBufferRender( GBuffer, camera, - ModelTransforms + InstancedModelContainer.CubeModel, + CubeTransforms ); GraphicsDevice.SetRenderTarget(DeferredTarget); @@ -299,5 +329,39 @@ namespace KavTest.Renderers SpriteBatch.End(); } } + + private void CollectInstances() + { + foreach (var list in InstanceMap.Values) + { + list.Clear(); + } + + foreach (var modelEntity in ReadEntities()) + { + if (HasComponent(modelEntity)) + { + var modelComponent = GetComponent(modelEntity); + if (modelComponent.Instanced) + { + var transformComponent = GetComponent(modelEntity); + + foreach (var mesh in modelComponent.Model.Meshes) + { + foreach (var meshPart in mesh.MeshParts) + { + if (!InstanceMap.ContainsKey(meshPart)) + { + InstanceMap.Add(meshPart, new List()); + } + else + + InstanceMap[meshPart].Add(transformComponent.Transform.TransformMatrix); + } + } + } + } + } + } } }