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