basic toon shading + controllable ambient light setting

pull/3/head
cosmonaut 2020-10-01 14:52:19 -07:00
parent 66d4e5bf6e
commit 565be374bb
12 changed files with 240 additions and 30 deletions

View File

@ -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"];
}
}
}

View File

@ -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"];
}
}
}

Binary file not shown.

BIN
Effects/FXB/Deferred_ToonEffect.fxb (Stored with Git LFS) Normal file

Binary file not shown.

View File

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

View File

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

View File

@ -30,6 +30,9 @@
<EmbeddedResource Include="Effects\FXB\ToneMapEffect.fxb">
<LogicalName>Kav.Resources.ToneMapEffect.fxb</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\Deferred_ToonEffect.fxb">
<LogicalName>Kav.Resources.Deferred_ToonEffect.fxb</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\DeferredPBREffect.fxb">
<LogicalName>Kav.Resources.DeferredPBREffect.fxb</LogicalName>
</EmbeddedResource>

View File

@ -30,6 +30,9 @@
<EmbeddedResource Include="Effects\FXB\ToneMapEffect.fxb">
<LogicalName>Kav.Resources.ToneMapEffect.fxb</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\Deferred_ToonEffect.fxb">
<LogicalName>Kav.Resources.Deferred_ToonEffect.fxb</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\DeferredPBREffect.fxb">
<LogicalName>Kav.Resources.DeferredPBREffect.fxb</LogicalName>
</EmbeddedResource>

14
Lights/AmbientLight.cs Normal file
View File

@ -0,0 +1,14 @@
using Microsoft.Xna.Framework;
namespace Kav
{
public struct AmbientLight
{
public Color Color { get; set; }
public AmbientLight(Color color)
{
Color = color;
}
}
}

View File

@ -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
{

View File

@ -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<PointLight> 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,

View File

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