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": {
"LD_LIBRARY_PATH": "./lib64",
"DYLD_LIBRARY_PATH": "./osx",
"FNA3D_FORCE_DRIVER": "Vulkan"
"FNA3D_FORCE_DRIVER": "OpenGL"
},
"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 Model Model { get; }
public bool Instanced { get; }
public ModelComponent(Model model)
public ModelComponent(Model model, bool instanced)
{
Model = model;
Instanced = instanced;
}
}
}

View File

@ -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));
}
}

View File

@ -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));
}
}
}

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
{
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),

View File

@ -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<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
{
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<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);
}
}
}
}
}
}
}
}