major API refactor
parent
fe222e266f
commit
84601379b5
|
@ -0,0 +1,9 @@
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace Kav
|
||||||
|
{
|
||||||
|
public interface IHasWorldMatrix
|
||||||
|
{
|
||||||
|
Matrix World { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,28 +3,28 @@ using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
namespace Kav
|
namespace Kav
|
||||||
{
|
{
|
||||||
public class LinearDepthEffect : Effect
|
public class LinearDepthEffect : Effect, IHasWorldMatrix
|
||||||
{
|
{
|
||||||
EffectParameter modelParam;
|
EffectParameter worldParam;
|
||||||
EffectParameter modelViewProjectionParam;
|
EffectParameter worldViewProjectionParam;
|
||||||
EffectParameter lightPositionParam;
|
EffectParameter lightPositionParam;
|
||||||
EffectParameter farPlaneParam;
|
EffectParameter farPlaneParam;
|
||||||
|
|
||||||
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
|
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
|
||||||
|
|
||||||
Matrix model;
|
Matrix world;
|
||||||
Matrix view;
|
Matrix view;
|
||||||
Matrix projection;
|
Matrix projection;
|
||||||
|
|
||||||
public Vector3 LightPosition { get; set; }
|
public Vector3 LightPosition { get; set; }
|
||||||
public float FarPlane { get; set; }
|
public float FarPlane { get; set; }
|
||||||
|
|
||||||
public Matrix Model
|
public Matrix World
|
||||||
{
|
{
|
||||||
get { return model; }
|
get { return world; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
model = value;
|
world = value;
|
||||||
dirtyFlags |= EffectDirtyFlags.World;
|
dirtyFlags |= EffectDirtyFlags.World;
|
||||||
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
|
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
|
||||||
}
|
}
|
||||||
|
@ -60,16 +60,16 @@ namespace Kav
|
||||||
if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0)
|
if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0)
|
||||||
{
|
{
|
||||||
Matrix.Multiply(ref view, ref projection, out Matrix viewProjection);
|
Matrix.Multiply(ref view, ref projection, out Matrix viewProjection);
|
||||||
Matrix.Multiply(ref model, ref viewProjection, out Matrix worldViewProj);
|
Matrix.Multiply(ref world, ref viewProjection, out Matrix worldViewProj);
|
||||||
|
|
||||||
modelViewProjectionParam.SetValue(worldViewProj);
|
worldViewProjectionParam.SetValue(worldViewProj);
|
||||||
|
|
||||||
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
|
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dirtyFlags & EffectDirtyFlags.World) != 0)
|
if ((dirtyFlags & EffectDirtyFlags.World) != 0)
|
||||||
{
|
{
|
||||||
modelParam.SetValue(model);
|
worldParam.SetValue(world);
|
||||||
|
|
||||||
dirtyFlags &= ~EffectDirtyFlags.World;
|
dirtyFlags &= ~EffectDirtyFlags.World;
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,8 @@ namespace Kav
|
||||||
|
|
||||||
private void CacheEffectParameters()
|
private void CacheEffectParameters()
|
||||||
{
|
{
|
||||||
modelParam = Parameters["Model"];
|
worldParam = Parameters["Model"];
|
||||||
modelViewProjectionParam = Parameters["ModelViewProjection"];
|
worldViewProjectionParam = Parameters["ModelViewProjection"];
|
||||||
|
|
||||||
lightPositionParam = Parameters["LightPosition"];
|
lightPositionParam = Parameters["LightPosition"];
|
||||||
farPlaneParam = Parameters["FarPlane"];
|
farPlaneParam = Parameters["FarPlane"];
|
||||||
|
|
|
@ -3,23 +3,26 @@ using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
namespace Kav
|
namespace Kav
|
||||||
{
|
{
|
||||||
public class SimpleDepthEffect : Effect
|
public class SimpleDepthEffect : Effect, IHasWorldMatrix
|
||||||
{
|
{
|
||||||
EffectParameter modelViewProjectionParam;
|
EffectParameter worldParam;
|
||||||
|
EffectParameter viewProjectionParam;
|
||||||
|
EffectParameter vertexShaderIndexParam;
|
||||||
|
|
||||||
Matrix model;
|
Matrix world;
|
||||||
Matrix view;
|
Matrix view;
|
||||||
Matrix projection;
|
Matrix projection;
|
||||||
|
bool hardwareInstancingEnabled = false;
|
||||||
|
|
||||||
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
|
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
|
||||||
|
|
||||||
public Matrix Model
|
public Matrix World
|
||||||
{
|
{
|
||||||
get { return model; }
|
get { return world; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
model = value;
|
world = value;
|
||||||
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
|
dirtyFlags |= EffectDirtyFlags.World;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +32,7 @@ namespace Kav
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
view = value;
|
view = value;
|
||||||
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
|
dirtyFlags |= EffectDirtyFlags.ViewProj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +42,20 @@ namespace Kav
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
projection = value;
|
projection = value;
|
||||||
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
|
dirtyFlags |= EffectDirtyFlags.ViewProj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HardwareInstancingEnabled
|
||||||
|
{
|
||||||
|
get { return hardwareInstancingEnabled; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != hardwareInstancingEnabled)
|
||||||
|
{
|
||||||
|
hardwareInstancingEnabled = value;
|
||||||
|
dirtyFlags |= EffectDirtyFlags.VertexShaderIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,20 +66,39 @@ namespace Kav
|
||||||
|
|
||||||
protected override void OnApply()
|
protected override void OnApply()
|
||||||
{
|
{
|
||||||
if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0)
|
if ((dirtyFlags & EffectDirtyFlags.World) != 0)
|
||||||
|
{
|
||||||
|
worldParam.SetValue(world);
|
||||||
|
|
||||||
|
dirtyFlags &= ~EffectDirtyFlags.World;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((dirtyFlags & EffectDirtyFlags.ViewProj) != 0)
|
||||||
{
|
{
|
||||||
Matrix.Multiply(ref view, ref projection, out Matrix viewProjection);
|
Matrix.Multiply(ref view, ref projection, out Matrix viewProjection);
|
||||||
Matrix.Multiply(ref model, ref viewProjection, out Matrix worldViewProj);
|
viewProjectionParam.SetValue(viewProjection);
|
||||||
|
|
||||||
modelViewProjectionParam.SetValue(worldViewProj);
|
dirtyFlags &= ~EffectDirtyFlags.ViewProj;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
|
if ((dirtyFlags & EffectDirtyFlags.VertexShaderIndex) != 0)
|
||||||
|
{
|
||||||
|
int vertexShaderIndex = 0;
|
||||||
|
|
||||||
|
if (hardwareInstancingEnabled)
|
||||||
|
{
|
||||||
|
vertexShaderIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertexShaderIndexParam.SetValue(vertexShaderIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CacheEffectParameters()
|
private void CacheEffectParameters()
|
||||||
{
|
{
|
||||||
modelViewProjectionParam = Parameters["ModelViewProjection"];
|
worldParam = Parameters["World"];
|
||||||
|
viewProjectionParam = Parameters["ViewProjection"];
|
||||||
|
vertexShaderIndexParam = Parameters["VertexShaderIndex"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
434
Renderer.cs
434
Renderer.cs
|
@ -220,48 +220,145 @@ namespace Kav
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DepthRender(
|
// Renders a series of drawable-transform pairs using an effect that has a World matrix.
|
||||||
RenderTarget2D renderTarget,
|
// Effect must be pre-configured!!
|
||||||
|
public static void CullAndRenderIndexed<T, U>(
|
||||||
|
GraphicsDevice graphicsDevice,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms
|
IEnumerable<(T, Matrix)> drawableTransformPairs,
|
||||||
) {
|
U effect
|
||||||
GraphicsDevice.SetRenderTarget(renderTarget);
|
) where T : IIndexDrawable, ICullable where U : Effect, IHasWorldMatrix
|
||||||
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
{
|
||||||
|
|
||||||
var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
|
var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
|
||||||
|
|
||||||
foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms))
|
foreach (var (drawable, transform) in FrustumCull(boundingFrustum, drawableTransformPairs))
|
||||||
{
|
{
|
||||||
foreach (var modelMesh in model.Meshes)
|
effect.World = transform;
|
||||||
{
|
|
||||||
foreach (var meshPart in modelMesh.MeshParts)
|
|
||||||
{
|
|
||||||
SimpleDepthEffect.World = transform;
|
|
||||||
SimpleDepthEffect.View = camera.View;
|
|
||||||
SimpleDepthEffect.Projection = camera.Projection;
|
|
||||||
|
|
||||||
GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer);
|
RenderIndexed(
|
||||||
GraphicsDevice.Indices = meshPart.IndexBuffer;
|
graphicsDevice,
|
||||||
|
drawable,
|
||||||
foreach (var pass in SimpleDepthEffect.CurrentTechnique.Passes)
|
effect
|
||||||
{
|
|
||||||
pass.Apply();
|
|
||||||
|
|
||||||
GraphicsDevice.DrawIndexedPrimitives(
|
|
||||||
PrimitiveType.TriangleList,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
meshPart.VertexBuffer.VertexCount,
|
|
||||||
0,
|
|
||||||
meshPart.Triangles.Length
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public static void RenderIndexed<T, U>(
|
||||||
|
GraphicsDevice graphicsDevice,
|
||||||
|
T drawable,
|
||||||
|
U effect
|
||||||
|
) where T : IIndexDrawable where U : Effect
|
||||||
|
{
|
||||||
|
graphicsDevice.SetVertexBuffer(drawable.VertexBuffer);
|
||||||
|
graphicsDevice.Indices = drawable.IndexBuffer;
|
||||||
|
|
||||||
|
foreach (var pass in effect.CurrentTechnique.Passes)
|
||||||
|
{
|
||||||
|
pass.Apply();
|
||||||
|
|
||||||
|
graphicsDevice.DrawIndexedPrimitives(
|
||||||
|
PrimitiveType.TriangleList,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
drawable.VertexBuffer.VertexCount,
|
||||||
|
0,
|
||||||
|
drawable.IndexBuffer.IndexCount / 3
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SkyboxRender(
|
public static int FillAndSetBuffersForInstancing<T, V>(
|
||||||
|
GraphicsDevice graphicsDevice,
|
||||||
|
PerspectiveCamera camera,
|
||||||
|
T drawable,
|
||||||
|
IEnumerable<Matrix> transforms,
|
||||||
|
V[] vertexData,
|
||||||
|
DynamicVertexBuffer dynamicVertexBuffer
|
||||||
|
) where T : ICullable, IIndexDrawable where V : struct, IVertexType, IHasWorldMatrix
|
||||||
|
{
|
||||||
|
var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
|
||||||
|
|
||||||
|
int numInstances = 0;
|
||||||
|
foreach (var transform in FrustumCull(boundingFrustum, drawable, transforms))
|
||||||
|
{
|
||||||
|
vertexData[numInstances].World = transform;
|
||||||
|
numInstances += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numInstances == 0) { return 0; }
|
||||||
|
|
||||||
|
dynamicVertexBuffer.SetData(
|
||||||
|
vertexData,
|
||||||
|
0,
|
||||||
|
numInstances,
|
||||||
|
SetDataOptions.Discard
|
||||||
|
);
|
||||||
|
|
||||||
|
graphicsDevice.SetVertexBuffers(
|
||||||
|
drawable.VertexBuffer,
|
||||||
|
new VertexBufferBinding(dynamicVertexBuffer, 0, 1)
|
||||||
|
);
|
||||||
|
graphicsDevice.Indices = drawable.IndexBuffer;
|
||||||
|
|
||||||
|
return numInstances;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RenderInstanced<T, U>(
|
||||||
|
GraphicsDevice graphicsDevice,
|
||||||
|
T drawable,
|
||||||
|
U effect,
|
||||||
|
int numInstances
|
||||||
|
) where T : ICullable, IIndexDrawable where U : Effect
|
||||||
|
{
|
||||||
|
foreach (var pass in effect.CurrentTechnique.Passes)
|
||||||
|
{
|
||||||
|
pass.Apply();
|
||||||
|
|
||||||
|
graphicsDevice.DrawInstancedPrimitives(
|
||||||
|
PrimitiveType.TriangleList,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
drawable.VertexBuffer.VertexCount,
|
||||||
|
0,
|
||||||
|
drawable.IndexBuffer.IndexCount / 3,
|
||||||
|
numInstances
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: can probably make this static somehow
|
||||||
|
public void RenderFullscreenEffect(
|
||||||
|
Effect effect
|
||||||
|
) {
|
||||||
|
foreach (var pass in effect.CurrentTechnique.Passes)
|
||||||
|
{
|
||||||
|
pass.Apply();
|
||||||
|
GraphicsDevice.SetVertexBuffer(FullscreenTriangle);
|
||||||
|
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RenderDepth<T>(
|
||||||
|
RenderTarget2D renderTarget,
|
||||||
|
PerspectiveCamera camera,
|
||||||
|
IEnumerable<(T, Matrix)> drawableTransforms
|
||||||
|
) where T : ICullable, IIndexDrawable
|
||||||
|
{
|
||||||
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
|
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
||||||
|
|
||||||
|
SimpleDepthEffect.View = camera.View;
|
||||||
|
SimpleDepthEffect.Projection = camera.Projection;
|
||||||
|
|
||||||
|
CullAndRenderIndexed(
|
||||||
|
GraphicsDevice,
|
||||||
|
camera,
|
||||||
|
drawableTransforms,
|
||||||
|
SimpleDepthEffect
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RenderSkybox(
|
||||||
RenderTarget2D renderTarget,
|
RenderTarget2D renderTarget,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
TextureCube skybox
|
TextureCube skybox
|
||||||
|
@ -274,41 +371,29 @@ namespace Kav
|
||||||
|
|
||||||
var view = camera.View;
|
var view = camera.View;
|
||||||
view.Translation = Vector3.Zero;
|
view.Translation = Vector3.Zero;
|
||||||
SkyboxEffect.View = view;
|
|
||||||
|
|
||||||
|
SkyboxEffect.View = view;
|
||||||
SkyboxEffect.Projection = camera.Projection;
|
SkyboxEffect.Projection = camera.Projection;
|
||||||
|
|
||||||
GraphicsDevice.SetVertexBuffer(UnitCube.Meshes[0].MeshParts[0].VertexBuffer);
|
RenderIndexed(
|
||||||
GraphicsDevice.Indices = UnitCube.Meshes[0].MeshParts[0].IndexBuffer;
|
GraphicsDevice,
|
||||||
|
UnitCube.Meshes[0].MeshParts[0],
|
||||||
foreach (var pass in SkyboxEffect.CurrentTechnique.Passes)
|
SkyboxEffect
|
||||||
{
|
|
||||||
pass.Apply();
|
|
||||||
|
|
||||||
GraphicsDevice.DrawIndexedPrimitives(
|
|
||||||
PrimitiveType.TriangleList,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
UnitCube.Meshes[0].MeshParts[0].VertexBuffer.VertexCount,
|
|
||||||
0,
|
|
||||||
UnitCube.Meshes[0].MeshParts[0].Triangles.Length
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
GraphicsDevice.RasterizerState.CullMode = CullMode.CullCounterClockwiseFace;
|
GraphicsDevice.RasterizerState.CullMode = CullMode.CullCounterClockwiseFace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GBuffer binding must have 4 render targets.
|
/// GBuffer binding must have 4 render targets.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void InstancedGBufferRender<T>(
|
public void RenderGBufferInstanced<T>(
|
||||||
RenderTargetBinding[] gBuffer,
|
RenderTargetBinding[] gBuffer,
|
||||||
RenderTarget2D depthBuffer,
|
RenderTarget2D depthBuffer,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
T drawable,
|
T drawable,
|
||||||
IEnumerable<Matrix> transforms
|
IEnumerable<Matrix> transforms
|
||||||
) where T : ICullable, IIndexDrawable, IGBufferDrawable {
|
) where T : ICullable, IIndexDrawable, IGBufferDrawable {
|
||||||
int numInstances = 0;
|
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTargets(gBuffer);
|
GraphicsDevice.SetRenderTargets(gBuffer);
|
||||||
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
||||||
GraphicsDevice.BlendState = BlendState.Opaque;
|
GraphicsDevice.BlendState = BlendState.Opaque;
|
||||||
|
@ -326,132 +411,67 @@ namespace Kav
|
||||||
Deferred_GBufferEffect.View = camera.View;
|
Deferred_GBufferEffect.View = camera.View;
|
||||||
Deferred_GBufferEffect.Projection = camera.Projection;
|
Deferred_GBufferEffect.Projection = camera.Projection;
|
||||||
|
|
||||||
var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
|
var numInstances = FillAndSetBuffersForInstancing(
|
||||||
|
GraphicsDevice,
|
||||||
foreach (var transform in FrustumCull(boundingFrustum, drawable, transforms))
|
camera,
|
||||||
{
|
drawable,
|
||||||
GBufferInstanceVertices[numInstances].World = transform;
|
transforms,
|
||||||
numInstances += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numInstances == 0) { return; }
|
|
||||||
|
|
||||||
GBufferInstanceVertexBuffer.SetData(
|
|
||||||
GBufferInstanceVertices,
|
GBufferInstanceVertices,
|
||||||
0,
|
GBufferInstanceVertexBuffer
|
||||||
numInstances,
|
|
||||||
SetDataOptions.Discard
|
|
||||||
);
|
);
|
||||||
|
|
||||||
GraphicsDevice.SetVertexBuffers(
|
RenderInstanced(
|
||||||
drawable.VertexBuffer,
|
GraphicsDevice,
|
||||||
new VertexBufferBinding(GBufferInstanceVertexBuffer, 0, 1)
|
drawable,
|
||||||
);
|
Deferred_GBufferEffect,
|
||||||
GraphicsDevice.Indices = drawable.IndexBuffer;
|
|
||||||
|
|
||||||
foreach (var pass in Deferred_GBufferEffect.CurrentTechnique.Passes)
|
|
||||||
{
|
|
||||||
pass.Apply();
|
|
||||||
GraphicsDevice.DrawInstancedPrimitives(
|
|
||||||
PrimitiveType.TriangleList,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
drawable.VertexBuffer.VertexCount,
|
|
||||||
0,
|
|
||||||
drawable.IndexBuffer.IndexCount / 3,
|
|
||||||
numInstances
|
numInstances
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
|
// re-render to get depth
|
||||||
GraphicsDevice.SetRenderTarget(depthBuffer);
|
GraphicsDevice.SetRenderTarget(depthBuffer);
|
||||||
|
|
||||||
foreach (var pass in Deferred_GBufferEffect.CurrentTechnique.Passes)
|
RenderInstanced(
|
||||||
{
|
GraphicsDevice,
|
||||||
pass.Apply();
|
drawable,
|
||||||
GraphicsDevice.DrawInstancedPrimitives(
|
Deferred_GBufferEffect,
|
||||||
PrimitiveType.TriangleList,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
drawable.VertexBuffer.VertexCount,
|
|
||||||
0,
|
|
||||||
drawable.IndexBuffer.IndexCount / 3,
|
|
||||||
numInstances
|
numInstances
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//SimpleDepthEffect.HardwareInstancingEnabled = true;
|
public void RenderGBufferIndexed<T>(
|
||||||
//SimpleDepthEffect.View = camera.View;
|
|
||||||
//SimpleDepthEffect.Projection = camera.Projection;
|
|
||||||
|
|
||||||
//foreach (var pass in SimpleDepthEffect.CurrentTechnique.Passes)
|
|
||||||
//{
|
|
||||||
// pass.Apply();
|
|
||||||
|
|
||||||
// GraphicsDevice.DrawInstancedPrimitives(
|
|
||||||
// PrimitiveType.TriangleList,
|
|
||||||
// 0,
|
|
||||||
// 0,
|
|
||||||
// drawable.VertexBuffer.VertexCount,
|
|
||||||
// 0,
|
|
||||||
// drawable.IndexBuffer.IndexCount / 3,
|
|
||||||
// numInstances
|
|
||||||
// );
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GBufferRender(
|
|
||||||
RenderTargetBinding[] gBuffer,
|
RenderTargetBinding[] gBuffer,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms
|
IEnumerable<(T, Matrix)> drawableTransforms
|
||||||
) {
|
) where T : ICullable, IIndexDrawable, IGBufferDrawable {
|
||||||
GraphicsDevice.SetRenderTargets(gBuffer);
|
GraphicsDevice.SetRenderTargets(gBuffer);
|
||||||
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
||||||
GraphicsDevice.BlendState = BlendState.Opaque;
|
GraphicsDevice.BlendState = BlendState.Opaque;
|
||||||
|
|
||||||
var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
|
Deferred_GBufferEffect.HardwareInstancingEnabled = false;
|
||||||
|
|
||||||
foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms))
|
|
||||||
{
|
|
||||||
foreach (var modelMesh in model.Meshes)
|
|
||||||
{
|
|
||||||
foreach (var meshPart in modelMesh.MeshParts)
|
|
||||||
{
|
|
||||||
Deferred_GBufferEffect.World = transform;
|
|
||||||
Deferred_GBufferEffect.View = camera.View;
|
Deferred_GBufferEffect.View = camera.View;
|
||||||
Deferred_GBufferEffect.Projection = camera.Projection;
|
Deferred_GBufferEffect.Projection = camera.Projection;
|
||||||
|
|
||||||
|
var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
|
||||||
|
|
||||||
|
foreach (var (drawable, transform) in FrustumCull(boundingFrustum, drawableTransforms))
|
||||||
|
{
|
||||||
|
Deferred_GBufferEffect.World = transform;
|
||||||
|
|
||||||
Deferred_GBufferEffect.HardwareInstancingEnabled = false;
|
Deferred_GBufferEffect.HardwareInstancingEnabled = false;
|
||||||
|
|
||||||
Deferred_GBufferEffect.Albedo = meshPart.Albedo;
|
Deferred_GBufferEffect.Albedo = drawable.Albedo;
|
||||||
Deferred_GBufferEffect.Metallic = meshPart.Metallic;
|
Deferred_GBufferEffect.Metallic = drawable.Metallic;
|
||||||
Deferred_GBufferEffect.Roughness = meshPart.Roughness;
|
Deferred_GBufferEffect.Roughness = drawable.Roughness;
|
||||||
|
|
||||||
Deferred_GBufferEffect.AlbedoTexture = meshPart.AlbedoTexture;
|
Deferred_GBufferEffect.AlbedoTexture = drawable.AlbedoTexture;
|
||||||
Deferred_GBufferEffect.NormalTexture = meshPart.NormalTexture;
|
Deferred_GBufferEffect.NormalTexture = drawable.NormalTexture;
|
||||||
Deferred_GBufferEffect.MetallicRoughnessTexture = meshPart.MetallicRoughnessTexture;
|
Deferred_GBufferEffect.MetallicRoughnessTexture = drawable.MetallicRoughnessTexture;
|
||||||
|
|
||||||
GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer);
|
RenderIndexed(GraphicsDevice, drawable, Deferred_GBufferEffect);
|
||||||
GraphicsDevice.Indices = meshPart.IndexBuffer;
|
|
||||||
|
|
||||||
foreach (var pass in Deferred_GBufferEffect.CurrentTechnique.Passes)
|
|
||||||
{
|
|
||||||
pass.Apply();
|
|
||||||
|
|
||||||
GraphicsDevice.DrawIndexedPrimitives(
|
|
||||||
PrimitiveType.TriangleList,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
meshPart.VertexBuffer.VertexCount,
|
|
||||||
0,
|
|
||||||
meshPart.Triangles.Length
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AmbientLightRender(
|
public void RenderAmbientLight(
|
||||||
RenderTarget2D renderTarget,
|
RenderTarget2D renderTarget,
|
||||||
Texture2D gPosition,
|
Texture2D gPosition,
|
||||||
Texture2D gAlbedo,
|
Texture2D gAlbedo,
|
||||||
|
@ -465,25 +485,20 @@ namespace Kav
|
||||||
DeferredAmbientLightEffect.GAlbedo = gAlbedo;
|
DeferredAmbientLightEffect.GAlbedo = gAlbedo;
|
||||||
DeferredAmbientLightEffect.AmbientColor = ambientLight.Color.ToVector3();
|
DeferredAmbientLightEffect.AmbientColor = ambientLight.Color.ToVector3();
|
||||||
|
|
||||||
foreach (var pass in DeferredAmbientLightEffect.CurrentTechnique.Passes)
|
RenderFullscreenEffect(DeferredAmbientLightEffect);
|
||||||
{
|
|
||||||
pass.Apply();
|
|
||||||
GraphicsDevice.SetVertexBuffer(FullscreenTriangle);
|
|
||||||
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PointLightRender(
|
public void RenderPointLight<T>(
|
||||||
RenderTarget2D renderTarget,
|
RenderTarget2D renderTarget,
|
||||||
Texture2D gPosition,
|
Texture2D gPosition,
|
||||||
Texture2D gAlbedo,
|
Texture2D gAlbedo,
|
||||||
Texture2D gNormal,
|
Texture2D gNormal,
|
||||||
Texture2D gMetallicRoughness,
|
Texture2D gMetallicRoughness,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(T, Matrix)> modelTransforms,
|
||||||
PointLight pointLight
|
PointLight pointLight
|
||||||
) {
|
) where T : ICullable, IIndexDrawable {
|
||||||
RenderPointShadows(camera, modelTransforms, pointLight);
|
RenderPointShadows(PointShadowCubeMap, camera, modelTransforms, pointLight);
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(renderTarget);
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
||||||
|
@ -503,26 +518,21 @@ namespace Kav
|
||||||
|
|
||||||
DeferredPointLightEffect.FarPlane = 25f; // FIXME: magic value
|
DeferredPointLightEffect.FarPlane = 25f; // FIXME: magic value
|
||||||
|
|
||||||
foreach (var pass in DeferredPointLightEffect.CurrentTechnique.Passes)
|
RenderFullscreenEffect(DeferredPointLightEffect);
|
||||||
{
|
|
||||||
pass.Apply();
|
|
||||||
GraphicsDevice.SetVertexBuffer(FullscreenTriangle);
|
|
||||||
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DirectionalLightRender(
|
public void RenderDirectionalLight<T>(
|
||||||
RenderTarget2D renderTarget,
|
RenderTarget2D renderTarget,
|
||||||
Texture2D gPosition,
|
Texture2D gPosition,
|
||||||
Texture2D gAlbedo,
|
Texture2D gAlbedo,
|
||||||
Texture2D gNormal,
|
Texture2D gNormal,
|
||||||
Texture2D gMetallicRoughness,
|
Texture2D gMetallicRoughness,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(T, Matrix)> modelTransforms,
|
||||||
DirectionalLight directionalLight,
|
DirectionalLight directionalLight,
|
||||||
int numShadowCascades
|
int numShadowCascades
|
||||||
) {
|
) where T : ICullable, IIndexDrawable {
|
||||||
RenderDirectionalShadows(camera, modelTransforms, directionalLight, DeferredDirectionalLightEffect);
|
//RenderDirectionalShadows(camera, modelTransforms, directionalLight, DeferredDirectionalLightEffect);
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(renderTarget);
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
||||||
|
@ -554,27 +564,22 @@ namespace Kav
|
||||||
DeferredDirectionalLightEffect.ViewMatrix = camera.View;
|
DeferredDirectionalLightEffect.ViewMatrix = camera.View;
|
||||||
DeferredDirectionalLightEffect.EyePosition = camera.Position;
|
DeferredDirectionalLightEffect.EyePosition = camera.Position;
|
||||||
|
|
||||||
foreach (EffectPass pass in DeferredDirectionalLightEffect.CurrentTechnique.Passes)
|
RenderFullscreenEffect(DeferredDirectionalLightEffect);
|
||||||
{
|
|
||||||
pass.Apply();
|
|
||||||
GraphicsDevice.SetVertexBuffer(FullscreenTriangle);
|
|
||||||
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DirectionalLightToonRender(
|
public void RenderDirectionalLightToon<T>(
|
||||||
RenderTarget2D renderTarget,
|
RenderTarget2D renderTarget,
|
||||||
Texture2D gPosition,
|
Texture2D gPosition,
|
||||||
Texture2D gAlbedo,
|
Texture2D gAlbedo,
|
||||||
Texture2D gNormal,
|
Texture2D gNormal,
|
||||||
Texture2D gMetallicRoughness,
|
Texture2D gMetallicRoughness,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(T, Matrix)> modelTransforms,
|
||||||
DirectionalLight directionalLight,
|
DirectionalLight directionalLight,
|
||||||
int numShadowCascades,
|
int numShadowCascades,
|
||||||
bool ditheredShadows
|
bool ditheredShadows
|
||||||
) {
|
) where T : ICullable, IIndexDrawable {
|
||||||
RenderDirectionalShadows(camera, modelTransforms, directionalLight, Deferred_ToonEffect);
|
//RenderDirectionalShadows(camera, modelTransforms, directionalLight, Deferred_ToonEffect);
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(renderTarget);
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
||||||
|
@ -609,20 +614,15 @@ namespace Kav
|
||||||
|
|
||||||
Deferred_ToonEffect.ViewMatrix = camera.View;
|
Deferred_ToonEffect.ViewMatrix = camera.View;
|
||||||
|
|
||||||
foreach (EffectPass pass in Deferred_ToonEffect.CurrentTechnique.Passes)
|
RenderFullscreenEffect(Deferred_ToonEffect);
|
||||||
{
|
|
||||||
pass.Apply();
|
|
||||||
GraphicsDevice.SetVertexBuffer(FullscreenTriangle);
|
|
||||||
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderDirectionalShadows(
|
private void RenderDirectionalShadows<T>(
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||||
DirectionalLight directionalLight,
|
DirectionalLight directionalLight,
|
||||||
ShadowCascadeEffect effect
|
ShadowCascadeEffect effect
|
||||||
) {
|
) where T : ICullable, IIndexDrawable {
|
||||||
// render the individual shadow cascades
|
// render the individual shadow cascades
|
||||||
var previousFarPlane = camera.NearPlane;
|
var previousFarPlane = camera.NearPlane;
|
||||||
for (var i = 0; i < NumShadowCascades; i++)
|
for (var i = 0; i < NumShadowCascades; i++)
|
||||||
|
@ -739,26 +739,18 @@ namespace Kav
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderPointShadows(
|
private void RenderPointShadows<T>(
|
||||||
|
RenderTargetCube pointShadowCubeMap,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(T, Matrix)> modelTransforms,
|
||||||
PointLight pointLight
|
PointLight pointLight
|
||||||
) {
|
) where T : ICullable, IIndexDrawable {
|
||||||
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
||||||
GraphicsDevice.BlendState = BlendState.Opaque;
|
GraphicsDevice.BlendState = BlendState.Opaque;
|
||||||
|
|
||||||
LinearDepthEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
|
|
||||||
MathHelper.PiOver2,
|
|
||||||
1,
|
|
||||||
0.1f,
|
|
||||||
25f // FIXME: magic value
|
|
||||||
);
|
|
||||||
LinearDepthEffect.FarPlane = 25f;
|
|
||||||
LinearDepthEffect.LightPosition = pointLight.Position;
|
|
||||||
|
|
||||||
foreach (CubeMapFace face in Enum.GetValues(typeof(CubeMapFace)))
|
foreach (CubeMapFace face in Enum.GetValues(typeof(CubeMapFace)))
|
||||||
{
|
{
|
||||||
GraphicsDevice.SetRenderTarget(PointShadowCubeMap, face);
|
GraphicsDevice.SetRenderTarget(pointShadowCubeMap, face);
|
||||||
|
|
||||||
Vector3 targetDirection;
|
Vector3 targetDirection;
|
||||||
Vector3 targetUpDirection;
|
Vector3 targetUpDirection;
|
||||||
|
@ -805,36 +797,22 @@ namespace Kav
|
||||||
pointLight.Position + targetDirection,
|
pointLight.Position + targetDirection,
|
||||||
targetUpDirection
|
targetUpDirection
|
||||||
);
|
);
|
||||||
|
LinearDepthEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
|
||||||
var boundingFrustum = new BoundingFrustum(LinearDepthEffect.View * LinearDepthEffect.Projection);
|
MathHelper.PiOver2,
|
||||||
|
1,
|
||||||
foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms))
|
0.1f,
|
||||||
{
|
25f // FIXME: magic value
|
||||||
foreach (var modelMesh in model.Meshes)
|
);
|
||||||
{
|
LinearDepthEffect.FarPlane = 25f;
|
||||||
foreach (var meshPart in modelMesh.MeshParts)
|
|
||||||
{
|
LinearDepthEffect.LightPosition = pointLight.Position;
|
||||||
GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer);
|
|
||||||
GraphicsDevice.Indices = meshPart.IndexBuffer;
|
CullAndRenderIndexed(
|
||||||
|
GraphicsDevice,
|
||||||
LinearDepthEffect.Model = transform;
|
camera,
|
||||||
|
modelTransforms,
|
||||||
foreach (var pass in LinearDepthEffect.CurrentTechnique.Passes)
|
LinearDepthEffect
|
||||||
{
|
|
||||||
pass.Apply();
|
|
||||||
|
|
||||||
GraphicsDevice.DrawIndexedPrimitives(
|
|
||||||
PrimitiveType.TriangleList,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
meshPart.VertexBuffer.VertexCount,
|
|
||||||
0,
|
|
||||||
meshPart.Triangles.Length
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ using Microsoft.Xna.Framework.Graphics;
|
||||||
namespace Kav
|
namespace Kav
|
||||||
{
|
{
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
public struct GBufferInstanceVertex : IVertexType
|
public struct GBufferInstanceVertex : IVertexType, IHasWorldMatrix
|
||||||
{
|
{
|
||||||
VertexDeclaration IVertexType.VertexDeclaration
|
VertexDeclaration IVertexType.VertexDeclaration
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue