diff --git a/Effects/DeferredPBR_AmbientLightEffect.cs b/Effects/DeferredPBR_AmbientLightEffect.cs
index f1d5e31..8595426 100644
--- a/Effects/DeferredPBR_AmbientLightEffect.cs
+++ b/Effects/DeferredPBR_AmbientLightEffect.cs
@@ -1,3 +1,4 @@
+using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Kav
@@ -8,9 +9,13 @@ namespace Kav
EffectParameter gPositionParam;
EffectParameter gAlbedoParam;
+ EffectParameter ambientColorParam;
+
public Texture2D GPosition { get; set; }
public Texture2D GAlbedo { get; set; }
+ public Vector3 AmbientColor { get; set; }
+
public DeferredPBR_AmbientLightEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DeferredPBR_AmbientLightEffect)
{
CacheEffectParameters();
@@ -20,12 +25,14 @@ namespace Kav
{
gPositionParam.SetValue(GPosition);
gAlbedoParam.SetValue(GAlbedo);
+ ambientColorParam.SetValue(AmbientColor);
}
void CacheEffectParameters()
{
- gPositionParam = Parameters["gPosition"];
- gAlbedoParam = Parameters["gAlbedo"];
+ gPositionParam = Parameters["gPosition"];
+ gAlbedoParam = Parameters["gAlbedo"];
+ ambientColorParam = Parameters["AmbientLightColor"];
}
}
}
diff --git a/Effects/Deferred_ToonEffect.cs b/Effects/Deferred_ToonEffect.cs
new file mode 100644
index 0000000..5b2cca3
--- /dev/null
+++ b/Effects/Deferred_ToonEffect.cs
@@ -0,0 +1,47 @@
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+namespace Kav
+{
+ public class Deferred_ToonEffect : Effect
+ {
+ EffectParameter gPositionParam;
+ EffectParameter gAlbedoParam;
+ EffectParameter gNormalParam;
+
+ EffectParameter eyePositionParam;
+ EffectParameter directionalLightDirectionParam;
+
+ public Texture2D GPosition { get; set; }
+ public Texture2D GAlbedo { get; set; }
+ public Texture2D GNormal { get; set; }
+
+ public Vector3 EyePosition { get; set; }
+ public Vector3 DirectionalLightDirection { get; set; }
+
+ public Deferred_ToonEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.Deferred_ToonEffect)
+ {
+ CacheEffectParameters();
+ }
+
+ protected override void OnApply()
+ {
+ gPositionParam.SetValue(GPosition);
+ gAlbedoParam.SetValue(GAlbedo);
+ gNormalParam.SetValue(GNormal);
+
+ eyePositionParam.SetValue(EyePosition);
+ directionalLightDirectionParam.SetValue(DirectionalLightDirection);
+ }
+
+ void CacheEffectParameters()
+ {
+ gPositionParam = Parameters["gPosition"];
+ gAlbedoParam = Parameters["gAlbedo"];
+ gNormalParam = Parameters["gNormal"];
+
+ eyePositionParam = Parameters["EyePosition"];
+ directionalLightDirectionParam = Parameters["DirectionalLightDirection"];
+ }
+ }
+}
diff --git a/Effects/FXB/DeferredPBR_AmbientLightEffect.fxb b/Effects/FXB/DeferredPBR_AmbientLightEffect.fxb
index 62de278..a439c6a 100644
--- a/Effects/FXB/DeferredPBR_AmbientLightEffect.fxb
+++ b/Effects/FXB/DeferredPBR_AmbientLightEffect.fxb
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0ea0cb071a1e53fec5058fae9919d376e408d33cd3de9485d42e1ebcbee85546
-size 1016
+oid sha256:244ded9c443bc10e538958075cabd14d2b066b9fd0743186ce620823380cb488
+size 1168
diff --git a/Effects/FXB/Deferred_ToonEffect.fxb b/Effects/FXB/Deferred_ToonEffect.fxb
new file mode 100644
index 0000000..1dbb741
--- /dev/null
+++ b/Effects/FXB/Deferred_ToonEffect.fxb
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e49380a4f06e418f7056355d4b1426aa62d1025734c643c12ee9501c8a3d59b1
+size 1568
diff --git a/Effects/HLSL/DeferredPBR_AmbientLightEffect.fx b/Effects/HLSL/DeferredPBR_AmbientLightEffect.fx
index 4144c8d..6c6e173 100644
--- a/Effects/HLSL/DeferredPBR_AmbientLightEffect.fx
+++ b/Effects/HLSL/DeferredPBR_AmbientLightEffect.fx
@@ -3,6 +3,12 @@
DECLARE_TEXTURE(gPosition, 0);
DECLARE_TEXTURE(gAlbedo, 1);
+BEGIN_CONSTANTS
+
+float3 AmbientLightColor _ps(c0) _cb(c0);
+
+END_CONSTANTS
+
struct VertexInput
{
float4 Position : POSITION;
@@ -29,7 +35,7 @@ float4 ComputeColor(
float3 worldPosition,
float3 albedo
) {
- float3 color = float3(0.03, 0.03, 0.03) * albedo;
+ float3 color = AmbientLightColor * albedo;
return float4(color, 1.0);
}
diff --git a/Effects/HLSL/Deferred_ToonEffect.fx b/Effects/HLSL/Deferred_ToonEffect.fx
new file mode 100644
index 0000000..7423236
--- /dev/null
+++ b/Effects/HLSL/Deferred_ToonEffect.fx
@@ -0,0 +1,60 @@
+#include "Macros.fxh"
+
+DECLARE_TEXTURE(gPosition, 0);
+DECLARE_TEXTURE(gAlbedo, 1);
+DECLARE_TEXTURE(gNormal, 2);
+
+BEGIN_CONSTANTS
+
+float3 EyePosition _ps(c0) _cb(c0);
+
+float3 DirectionalLightDirection _ps(c1) _cb(c1);
+float3 AmbientLightColor _ps(c2) _cb(c2);
+
+END_CONSTANTS
+
+struct VertexInput
+{
+ float4 Position : POSITION;
+ float2 TexCoord : TEXCOORD;
+};
+
+struct PixelInput
+{
+ float4 Position : SV_POSITION;
+ float2 TexCoord : TEXCOORD0;
+};
+
+PixelInput main_vs(VertexInput input)
+{
+ PixelInput output;
+
+ output.Position = input.Position;
+ output.TexCoord = input.TexCoord;
+
+ return output;
+}
+
+float4 main_ps(PixelInput input) : SV_TARGET0
+{
+ float3 worldPosition = SAMPLE_TEXTURE(gPosition, input.TexCoord).rgb;
+ float3 normal = SAMPLE_TEXTURE(gNormal, input.TexCoord).xyz;
+ float3 albedo = SAMPLE_TEXTURE(gAlbedo, input.TexCoord).rgb;
+
+ float3 V = normalize(EyePosition - worldPosition);
+ float3 L = normalize(DirectionalLightDirection);
+ float3 N = normalize(normal);
+ float NdotL = dot(N, L);
+
+ float lightIntensity = (NdotL > 0.0) ? 1.0 : 0.0;
+ return float4(albedo * (lightIntensity, 1.0);
+}
+
+Technique Deferred_Toon
+{
+ Pass
+ {
+ VertexShader = compile vs_3_0 main_vs();
+ PixelShader = compile ps_3_0 main_ps();
+ }
+}
diff --git a/Kav.Core.csproj b/Kav.Core.csproj
index 327d7bb..b018e72 100644
--- a/Kav.Core.csproj
+++ b/Kav.Core.csproj
@@ -30,6 +30,9 @@
Kav.Resources.ToneMapEffect.fxb
+
+ Kav.Resources.Deferred_ToonEffect.fxb
+
Kav.Resources.DeferredPBREffect.fxb
diff --git a/Kav.Framework.csproj b/Kav.Framework.csproj
index 2b2dd4f..c2d9079 100644
--- a/Kav.Framework.csproj
+++ b/Kav.Framework.csproj
@@ -30,6 +30,9 @@
Kav.Resources.ToneMapEffect.fxb
+
+ Kav.Resources.Deferred_ToonEffect.fxb
+
Kav.Resources.DeferredPBREffect.fxb
diff --git a/Lights/AmbientLight.cs b/Lights/AmbientLight.cs
new file mode 100644
index 0000000..94bb42e
--- /dev/null
+++ b/Lights/AmbientLight.cs
@@ -0,0 +1,14 @@
+using Microsoft.Xna.Framework;
+
+namespace Kav
+{
+ public struct AmbientLight
+ {
+ public Color Color { get; set; }
+
+ public AmbientLight(Color color)
+ {
+ Color = color;
+ }
+ }
+}
diff --git a/Lights/DirectionalLight.cs b/Lights/DirectionalLight.cs
index a22ab33..985745f 100644
--- a/Lights/DirectionalLight.cs
+++ b/Lights/DirectionalLight.cs
@@ -4,9 +4,9 @@ namespace Kav
{
public struct DirectionalLight
{
- public Vector3 Direction { get; set; }
- public Color Color { get; set; }
- public float Intensity { get; set; }
+ public Vector3 Direction { get; }
+ public Color Color { get; }
+ public float Intensity { get; }
public Matrix View
{
diff --git a/Renderer.cs b/Renderer.cs
index 63b34e5..5978274 100644
--- a/Renderer.cs
+++ b/Renderer.cs
@@ -24,6 +24,7 @@ namespace Kav
private DeferredPBR_AmbientLightEffect DeferredAmbientLightEffect { get; }
private DeferredPBR_PointLightEffect DeferredPointLightEffect { get; }
private DeferredPBR_DirectionalLightEffect DeferredDirectionalLightEffect { get; }
+ private Deferred_ToonEffect Deferred_ToonEffect { get; }
private SimpleDepthEffect SimpleDepthEffect { get; }
private Effect ToneMapEffect { get; }
@@ -136,6 +137,7 @@ namespace Kav
DeferredDirectionalLightEffect = new DeferredPBR_DirectionalLightEffect(GraphicsDevice);
DeferredDirectionalLightEffect.ShadowMapSize = ShadowMapSize;
ToneMapEffect = new Effect(graphicsDevice, Resources.ToneMapEffect);
+ Deferred_ToonEffect = new Deferred_ToonEffect(GraphicsDevice);
FullscreenTriangle = new VertexBuffer(GraphicsDevice, typeof(VertexPositionTexture), 3, BufferUsage.WriteOnly);
FullscreenTriangle.SetData(new VertexPositionTexture[3] {
@@ -150,11 +152,62 @@ namespace Kav
public void DeferredRender(
PerspectiveCamera camera,
IEnumerable<(Model, Matrix)> modelTransforms,
+ AmbientLight ambientLight,
IEnumerable pointLights,
DirectionalLight directionalLight
) {
- // g-buffer pass
+ GBufferRender(camera, modelTransforms);
+ GraphicsDevice.SetRenderTarget(ColorRenderTarget);
+ GraphicsDevice.Clear(Color.Black);
+
+ AmbientLightRender(ambientLight);
+
+ DeferredPointLightEffect.EyePosition = camera.Position;
+
+ foreach (var pointLight in pointLights)
+ {
+ PointLightRender(pointLight);
+ }
+
+ DirectionalLightRender(camera, modelTransforms, directionalLight);
+
+ GraphicsDevice.SetRenderTarget(null);
+ GraphicsDevice.Clear(Color.Black);
+ SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, ToneMapEffect);
+ SpriteBatch.Draw(ColorRenderTarget, Vector2.Zero, Color.White);
+ SpriteBatch.End();
+ }
+
+ public void DeferredToonRender(
+ PerspectiveCamera camera,
+ IEnumerable<(Model, Matrix)> modelTransforms,
+ AmbientLight ambientLight,
+ DirectionalLight directionalLight
+ ) {
+ GBufferRender(camera, modelTransforms);
+
+ GraphicsDevice.SetRenderTarget(ColorRenderTarget);
+ GraphicsDevice.Clear(Color.Black);
+
+ AmbientLightRender(ambientLight);
+
+ Deferred_ToonEffect.GPosition = gPosition;
+ Deferred_ToonEffect.GAlbedo = gAlbedo;
+ Deferred_ToonEffect.GNormal = gNormal;
+ DirectionalLightToonRender(camera, directionalLight);
+
+ GraphicsDevice.SetRenderTarget(null);
+ GraphicsDevice.Clear(Color.Black);
+ SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, ToneMapEffect);
+ SpriteBatch.Draw(ColorRenderTarget, Vector2.Zero, Color.White);
+ SpriteBatch.End();
+ }
+
+ private void GBufferRender(
+ PerspectiveCamera camera,
+ IEnumerable<(Model, Matrix)> modelTransforms
+ ) {
GraphicsDevice.SetRenderTargets(GBuffer);
GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0);
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
@@ -192,14 +245,17 @@ namespace Kav
}
}
}
+ }
+ private void AmbientLightRender(AmbientLight ambientLight)
+ {
GraphicsDevice.SetRenderTarget(ColorRenderTarget);
- GraphicsDevice.Clear(Color.Black);
GraphicsDevice.BlendState = BlendState.Additive;
GraphicsDevice.DepthStencilState = DepthStencilState.None;
DeferredAmbientLightEffect.GPosition = gPosition;
DeferredAmbientLightEffect.GAlbedo = gAlbedo;
+ DeferredAmbientLightEffect.AmbientColor = ambientLight.Color.ToVector3();
foreach (var pass in DeferredAmbientLightEffect.CurrentTechnique.Passes)
{
@@ -207,26 +263,6 @@ namespace Kav
GraphicsDevice.SetVertexBuffer(FullscreenTriangle);
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
}
-
- DeferredPointLightEffect.EyePosition = camera.Position;
-
- foreach (var pointLight in pointLights)
- {
- PointLightRender(pointLight);
- }
-
- DirectionalLightRender(camera, modelTransforms, directionalLight);
- // return;
- // GraphicsDevice.SetRenderTarget(null);
- // SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
- // SpriteBatch.Draw(DirectionalRenderTarget, Vector2.Zero, Color.White);
- // SpriteBatch.End();
-
- GraphicsDevice.SetRenderTarget(null);
- GraphicsDevice.Clear(Color.Black);
- SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, ToneMapEffect);
- SpriteBatch.Draw(ColorRenderTarget, Vector2.Zero, Color.White);
- SpriteBatch.End();
}
private void PointLightRender(PointLight pointLight)
@@ -313,6 +349,24 @@ namespace Kav
}
}
+ private void DirectionalLightToonRender(
+ PerspectiveCamera camera,
+ DirectionalLight directionalLight
+ ) {
+ Deferred_ToonEffect.EyePosition = camera.Position;
+ Deferred_ToonEffect.DirectionalLightDirection = directionalLight.Direction;
+
+ GraphicsDevice.SetRenderTarget(ColorRenderTarget);
+ GraphicsDevice.BlendState = BlendState.Additive;
+
+ foreach (EffectPass pass in Deferred_ToonEffect.CurrentTechnique.Passes)
+ {
+ pass.Apply();
+ GraphicsDevice.SetVertexBuffer(FullscreenTriangle);
+ GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
+ }
+ }
+
private void RenderShadowMap(
PerspectiveCamera camera,
IEnumerable<(Model, Matrix)> modelTransforms,
diff --git a/Resources.cs b/Resources.cs
index 7791eaa..9badc01 100644
--- a/Resources.cs
+++ b/Resources.cs
@@ -63,6 +63,18 @@ namespace Kav
}
}
+ public static byte[] Deferred_ToonEffect
+ {
+ get
+ {
+ if (deferredToonEffect == null)
+ {
+ deferredToonEffect = GetResource("Deferred_ToonEffect");
+ }
+ return deferredToonEffect;
+ }
+ }
+
public static byte[] DeferredPBREffect
{
get
@@ -104,6 +116,7 @@ namespace Kav
private static byte[] directionalLightEffect;
private static byte[] gBufferEffect;
private static byte[] toneMapEffect;
+ private static byte[] deferredToonEffect;
private static byte[] deferredPBREffect;
private static byte[] pbrEffect;
private static byte[] simpleDepthEffect;