testing instancing

main
cosmonaut 2020-12-07 15:51:45 -08:00
parent 8f570e04f0
commit 867d4d7f5d
10 changed files with 139 additions and 48 deletions

2
.vscode/tasks.json vendored
View File

@ -94,7 +94,7 @@
"env": { "env": {
"LD_LIBRARY_PATH": "./lib64", "LD_LIBRARY_PATH": "./lib64",
"DYLD_LIBRARY_PATH": "./osx", "DYLD_LIBRARY_PATH": "./osx",
"FNA3D_FORCE_DRIVER": "Vulkan" "FNA3D_FORCE_DRIVER": "OpenGL"
}, },
"cwd": "${workspaceFolder}/KavTest/bin/x64/Debug/net48" "cwd": "${workspaceFolder}/KavTest/bin/x64/Debug/net48"
}, },

2
FNA

@ -1 +1 @@
Subproject commit 1df9f588a701eefc4b55a0869cd5871be0124307 Subproject commit 7357a6f297fee33b7a8d5afddaca30480c591ba5

2
Kav

@ -1 +1 @@
Subproject commit 8b43e8f45ee6fa35f5c4d4924a62a3fcafe61301 Subproject commit bb694d3dbe47dcfcee6bfe3fb315587419ba8c0f

View File

@ -0,0 +1,6 @@
using Encompass;
namespace KavTest.Components
{
public struct InstancedCubeComponent : IComponent { }
}

View File

@ -6,10 +6,12 @@ namespace KavTest.Components
public struct ModelComponent : IComponent public struct ModelComponent : IComponent
{ {
public Model Model { get; } public Model Model { get; }
public bool Instanced { get; }
public ModelComponent(Model model) public ModelComponent(Model model, bool instanced)
{ {
Model = model; Model = model;
Instanced = instanced;
} }
} }
} }

View File

@ -19,7 +19,7 @@ namespace KavTest.Spawners
var entity = CreateEntity(); var entity = CreateEntity();
AddComponent(entity, new Transform3DComponent(message.Transform)); AddComponent(entity, new Transform3DComponent(message.Transform));
AddComponent(entity, new ModelComponent(RustyBallModel)); AddComponent(entity, new ModelComponent(RustyBallModel, true));
AddComponent(entity, new AngularVelocityComponent(message.AngularVelocity)); AddComponent(entity, new AngularVelocityComponent(message.AngularVelocity));
} }
} }

View File

@ -11,7 +11,7 @@ namespace KavTest.Spawners
var entity = CreateEntity(); var entity = CreateEntity();
AddComponent(entity, new Transform3DComponent(message.Transform)); AddComponent(entity, new Transform3DComponent(message.Transform));
AddComponent(entity, new ModelComponent(message.Model)); AddComponent(entity, new ModelComponent(message.Model, true));
} }
} }
} }

View File

@ -0,0 +1,9 @@
using Kav;
namespace KavTest
{
public class InstancedModelContainer
{
public MeshPart CubeModel { get; set; }
}
}

View File

@ -16,6 +16,7 @@ namespace KavTest
class KavTestGame : Game class KavTestGame : Game
{ {
GraphicsDeviceManager graphics; GraphicsDeviceManager graphics;
InstancedModelContainer InstancedModelContainer { get; } = new InstancedModelContainer();
WorldBuilder WorldBuilder { get; } = new WorldBuilder(); WorldBuilder WorldBuilder { get; } = new WorldBuilder();
World World { get; set; } 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( Texture2D.TextureDataFromStreamEXT(
File.OpenRead("Content/Skybox/front.jpg"), File.OpenRead("Content/Skybox/front.jpg"),
out var skyboxSize, out var skyboxSize,
@ -187,7 +192,7 @@ namespace KavTest
WorldBuilder.AddEngine(new StaticModelSpawner()); WorldBuilder.AddEngine(new StaticModelSpawner());
WorldBuilder.AddEngine(new DirectionalLightSpawner()); WorldBuilder.AddEngine(new DirectionalLightSpawner());
WorldBuilder.AddEngine(new MeshSpriteSpawner()); WorldBuilder.AddEngine(new MeshSpriteSpawner());
WorldBuilder.AddGeneralRenderer(new SceneRenderer(GraphicsDevice), 0); WorldBuilder.AddGeneralRenderer(new SceneRenderer(GraphicsDevice, InstancedModelContainer), 0);
// WorldBuilder.SendMessage(new RustyBallSpawnMessage( // WorldBuilder.SendMessage(new RustyBallSpawnMessage(
// new Transform3D(new Vector3(0, 0, 0)), // new Transform3D(new Vector3(0, 0, 0)),
@ -209,46 +214,51 @@ namespace KavTest
// rustyBallModel // rustyBallModel
// )); // ));
WorldBuilder.SendMessage(new StaticModelSpawnMessage( // WorldBuilder.SendMessage(new StaticModelSpawnMessage(
new Transform3D(new Vector3(0, -3, 0), Quaternion.Identity, new Vector3(10f, 1f, 10f)), // new Transform3D(new Vector3(0, -3, 0), Quaternion.Identity, new Vector3(10f, 1f, 10f)),
floorModel // floorModel
)); // ));
WorldBuilder.SendMessage(new StaticModelSpawnMessage( // WorldBuilder.SendMessage(new StaticModelSpawnMessage(
new Transform3D( // new Transform3D(
new Vector3(0, 1, 0), // new Vector3(0, 1, 0),
Quaternion.CreateFromAxisAngle( // Quaternion.CreateFromAxisAngle(
Vector3.Right, // Vector3.Right,
-Microsoft.Xna.Framework.MathHelper.PiOver2 // -Microsoft.Xna.Framework.MathHelper.PiOver2
), // ),
new Vector3(1f, 1f, 1f) // new Vector3(1f, 1f, 1f)
), // ),
redCylinderModel // redCylinderModel
)); // ));
WorldBuilder.SendMessage(new StaticModelSpawnMessage( // WorldBuilder.SendMessage(new StaticModelSpawnMessage(
new Transform3D( // new Transform3D(
new Vector3(-3, 1, 0), // new Vector3(-3, 1, 0),
Quaternion.CreateFromAxisAngle( // Quaternion.CreateFromAxisAngle(
Vector3.Right, // Vector3.Right,
-Microsoft.Xna.Framework.MathHelper.PiOver2 // -Microsoft.Xna.Framework.MathHelper.PiOver2
), // ),
new Vector3(1f, 1f, 1f) // new Vector3(1f, 1f, 1f)
), // ),
blueTorusModel // blueTorusModel
)); // ));
WorldBuilder.SendMessage(new StaticModelSpawnMessage( for (int i = -10; i < 10; i++)
new Transform3D( {
new Vector3(3, 1, 0), for (int j = -10; j < 10; j++)
Quaternion.CreateFromAxisAngle( {
Vector3.Right, for (int k = -10; k < 10; k++)
-Microsoft.Xna.Framework.MathHelper.PiOver2 {
), var entity = WorldBuilder.CreateEntity();
new Vector3(1f, 1f, 1f) WorldBuilder.SetComponent(entity, new Transform3DComponent(
), new Transform3D(
cubeModel new Vector3(i * 3, j * 3, k * 3)
)); )
));
WorldBuilder.SetComponent(entity, new InstancedCubeComponent());
}
}
}
WorldBuilder.SendMessage(new MeshSpriteSpawnMessage( WorldBuilder.SendMessage(new MeshSpriteSpawnMessage(
new Transform3D(new Vector3(3, 0, 11), Quaternion.CreateFromAxisAngle(Vector3.Up, (float)System.Math.PI), Vector3.One), new Transform3D(new Vector3(3, 0, 11), Quaternion.CreateFromAxisAngle(Vector3.Up, (float)System.Math.PI), Vector3.One),

View File

@ -13,6 +13,7 @@ namespace KavTest.Renderers
{ {
private GraphicsDevice GraphicsDevice { get; } private GraphicsDevice GraphicsDevice { get; }
private SpriteBatch SpriteBatch { get; } private SpriteBatch SpriteBatch { get; }
private InstancedModelContainer InstancedModelContainer { get; }
private Kav.Renderer Renderer { get; } private Kav.Renderer Renderer { get; }
@ -26,6 +27,24 @@ namespace KavTest.Renderers
private RenderTarget2D DeferredTarget { get; } private RenderTarget2D DeferredTarget { get; }
private RenderTarget2D BillboardTarget { get; } private RenderTarget2D BillboardTarget { get; }
private readonly Dictionary<Kav.MeshPart, List<Matrix>> InstanceMap = new Dictionary<MeshPart, List<Matrix>>();
private IEnumerable<Matrix> CubeTransforms
{
get
{
foreach (var entity in ReadEntitiesAsEnumerable<InstancedCubeComponent>())
{
if (HasComponent<Transform3DComponent>(entity))
{
var transformComponent = GetComponent<Transform3DComponent>(entity);
yield return transformComponent.Transform.TransformMatrix;
}
}
}
}
private IEnumerable<(Kav.Model, Matrix)> ModelTransforms private IEnumerable<(Kav.Model, Matrix)> ModelTransforms
{ {
get get
@ -117,9 +136,12 @@ namespace KavTest.Renderers
} }
} }
public SceneRenderer(GraphicsDevice graphicsDevice) public SceneRenderer(
{ GraphicsDevice graphicsDevice,
InstancedModelContainer instancedModelContainer
) {
GraphicsDevice = graphicsDevice; GraphicsDevice = graphicsDevice;
InstancedModelContainer = instancedModelContainer;
var renderDimensionsX = GraphicsDevice.PresentationParameters.BackBufferWidth; var renderDimensionsX = GraphicsDevice.PresentationParameters.BackBufferWidth;
var renderDimensionsY = GraphicsDevice.PresentationParameters.BackBufferHeight; var renderDimensionsY = GraphicsDevice.PresentationParameters.BackBufferHeight;
@ -220,11 +242,19 @@ namespace KavTest.Renderers
GraphicsDevice.SetRenderTargets(GBuffer); GraphicsDevice.SetRenderTargets(GBuffer);
GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0); GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0);
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
Renderer.GBufferRender( // Renderer.GBufferRender(
// GBuffer,
// camera,
// ModelTransforms
// );
Renderer.InstancedGBufferRender(
GBuffer, GBuffer,
camera, camera,
ModelTransforms InstancedModelContainer.CubeModel,
CubeTransforms
); );
GraphicsDevice.SetRenderTarget(DeferredTarget); GraphicsDevice.SetRenderTarget(DeferredTarget);
@ -299,5 +329,39 @@ namespace KavTest.Renderers
SpriteBatch.End(); SpriteBatch.End();
} }
} }
private void CollectInstances()
{
foreach (var list in InstanceMap.Values)
{
list.Clear();
}
foreach (var modelEntity in ReadEntities<ModelComponent>())
{
if (HasComponent<Transform3DComponent>(modelEntity))
{
var modelComponent = GetComponent<ModelComponent>(modelEntity);
if (modelComponent.Instanced)
{
var transformComponent = GetComponent<Transform3DComponent>(modelEntity);
foreach (var mesh in modelComponent.Model.Meshes)
{
foreach (var meshPart in mesh.MeshParts)
{
if (!InstanceMap.ContainsKey(meshPart))
{
InstanceMap.Add(meshPart, new List<Matrix>());
}
else
InstanceMap[meshPart].Add(transformComponent.Transform.TransformMatrix);
}
}
}
}
}
}
} }
} }