Compare commits

...

1 Commits

Author SHA1 Message Date
cosmonaut b66f3a750a started spotlight effect 2020-10-20 13:59:19 -07:00
9 changed files with 281 additions and 10 deletions

View File

@ -0,0 +1,79 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
public class DeferredPBR_SpotLightEffect : Effect
{
EffectParameter gPositionParam;
EffectParameter gAlbedoParam;
EffectParameter gNormalParam;
EffectParameter gMetallicRoughnessParam;
EffectParameter shadowMapParam;
EffectParameter eyePositionParam;
EffectParameter lightPositionParam;
EffectParameter lightDirectionParam;
EffectParameter lightColorParam;
EffectParameter lightCutoffParam;
EffectParameter farPlaneParam;
public Texture2D GPosition { get; set; }
public Texture2D GAlbedo { get; set; }
public Texture2D GNormal { get; set; }
public Texture2D GMetallicRoughness { get; set; }
public TextureCube ShadowMap { get; set; }
public Vector3 EyePosition { get; set; }
public Vector3 LightPosition { get; set; }
public Vector3 LightDirection { get; set; }
public Vector3 LightColor { get; set; }
public float LightCutoff { get; set; } //could be named lightangle?
public float FarPlane { get; set; }
public DeferredPBR_SpotLightEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DeferredPBR_SpotLightEffect)
{
CacheEffectParameters();
}
protected override void OnApply()
{
gPositionParam.SetValue(GPosition);
gAlbedoParam.SetValue(GAlbedo);
gNormalParam.SetValue(GNormal);
gMetallicRoughnessParam.SetValue(GMetallicRoughness);
shadowMapParam.SetValue(ShadowMap);
eyePositionParam.SetValue(EyePosition);
lightPositionParam.SetValue(LightPosition);
lightDirectionParam.SetValue(LightDirection);
lightColorParam.SetValue(LightColor);
lightCutoffParam.SetValue(LightCutoff);
farPlaneParam.SetValue(FarPlane);
}
private void CacheEffectParameters()
{
gPositionParam = Parameters["gPosition"];
gAlbedoParam = Parameters["gAlbedo"];
gNormalParam = Parameters["gNormal"];
gMetallicRoughnessParam = Parameters["gMetallicRoughness"];
shadowMapParam = Parameters["shadowMap"];
eyePositionParam = Parameters["EyePosition"];
lightPositionParam = Parameters["LightPosition"];
lightDirectionParam = Parameters["LightDirection"];
lightColorParam = Parameters["LightColor"];
lightCutoffParam = Parameters["LightCutoff"];
farPlaneParam = Parameters["FarPlane"];
}
}
}

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

Binary file not shown.

View File

@ -68,7 +68,6 @@ float4 ComputeColor(
float3 color = ComputeLight(L, radiance, F0, V, N, albedo, metallic, roughness, shadow);
return float4(color, 1.0);
//return float4(shadow, shadow, shadow, 1.0);
}
float4 main_ps(PixelInput input) : SV_TARGET0

View File

@ -0,0 +1,109 @@
#include "Macros.fxh" //from FNA
#include "Lighting.fxh"
#include "Shadow.fxh"
DECLARE_TEXTURE(gPosition, 0);
DECLARE_TEXTURE(gAlbedo, 1);
DECLARE_TEXTURE(gNormal, 2);
DECLARE_TEXTURE(gMetallicRoughness, 3);
DECLARE_CUBEMAP(shadowMap, 4);
BEGIN_CONSTANTS
float3 EyePosition _ps(c0) _cb(c0);
float3 LightPosition _ps(c1) _cb(c1);
float3 LightDirection _ps(c2) _cb(c2);
float3 LightColor _ps(c3) _cb(c3);
float LightCutoff _ps(c4) _cb(c4);
float FarPlane _ps(c5) _cb(c5);
MATRIX_CONSTANTS
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;
}
// Pixel Shader
float4 ComputeColor(
float3 worldPosition,
float3 worldNormal,
float3 albedo,
float metallic,
float roughness
) {
float3 V = normalize(EyePosition - worldPosition);
float3 N = normalize(worldNormal);
float3 F0 = float3(0.04, 0.04, 0.04);
F0 = lerp(F0, albedo, metallic);
float3 lightDir = LightPosition - worldPosition;
float3 L = normalize(lightDir);
float distance = length(lightDir);
float attenuation = 1.0 / (distance * distance);
float3 radiance = LightColor * attenuation;
//float shadow = HardPointShadow(worldPosition, N, L, PointLightPosition, SAMPLER(shadowMap), FarPlane);
float3 color = ComputeLight(L, radiance, F0, V, N, albedo, metallic, roughness, 1.0);
return float4(color, 1.0);
}
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;
float2 metallicRoughness = SAMPLE_TEXTURE(gMetallicRoughness, input.TexCoord).rg;
float3 lightDir = normalize(LightPosition - worldPosition);
float theta = dot(lightDir, normalize(-LightDirection));
if (theta > LightCutoff)
{
return ComputeColor(
worldPosition,
normal,
albedo,
metallicRoughness.r,
metallicRoughness.g
);
}
else
{
return float4(0.0, 0.0, 0.0, 1.0);
}
}
Technique DeferredPBR_Point
{
Pass
{
VertexShader = compile vs_3_0 main_vs();
PixelShader = compile ps_3_0 main_ps();
}
}

View File

@ -24,6 +24,9 @@
<EmbeddedResource Include="Effects\FXB\DeferredPBR_DirectionalLightEffect.fxb">
<LogicalName>Kav.Resources.DeferredPBR_DirectionalLightEffect.fxb</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\DeferredPBR_SpotLightEffect.fxb">
<LogicalName>Kav.Resources.DeferredPBR_SpotLightEffect.fxb</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\DeferredPBR_GBufferEffect.fxb">
<LogicalName>Kav.Resources.DeferredPBR_GBufferEffect.fxb</LogicalName>
</EmbeddedResource>

View File

@ -27,6 +27,9 @@
<EmbeddedResource Include="Effects\FXB\DeferredPBR_GBufferEffect.fxb">
<LogicalName>Kav.Resources.DeferredPBR_GBufferEffect.fxb</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\DeferredPBR_SpotLightEffect.fxb">
<LogicalName>Kav.Resources.DeferredPBR_SpotLightEffect.fxb</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\ToneMapEffect.fxb">
<LogicalName>Kav.Resources.ToneMapEffect.fxb</LogicalName>
</EmbeddedResource>

22
Lights/SpotLight.cs Normal file
View File

@ -0,0 +1,22 @@
using Microsoft.Xna.Framework;
namespace Kav
{
public struct SpotLight
{
public Vector3 Position { get; }
public Vector3 Direction { get; }
public Color Color { get; }
public float Intensity { get; }
public float Cutoff { get; }
public SpotLight(Vector3 position, Vector3 direction, Color color, float intensity, float cutoff)
{
Position = position;
Direction = direction;
Color = color;
Intensity = intensity;
Cutoff = cutoff;
}
}
}

View File

@ -28,6 +28,7 @@ namespace Kav
private DeferredPBR_AmbientLightEffect DeferredAmbientLightEffect { get; }
private DeferredPBR_PointLightEffect DeferredPointLightEffect { get; }
private DeferredPBR_DirectionalLightEffect DeferredDirectionalLightEffect { get; }
private DeferredPBR_SpotLightEffect DeferredSpotLightEffect { get; }
private Deferred_ToonEffect Deferred_ToonEffect { get; }
private SimpleDepthEffect SimpleDepthEffect { get; }
private LinearDepthEffect LinearDepthEffect { get; }
@ -156,6 +157,7 @@ namespace Kav
DeferredPointLightEffect = new DeferredPBR_PointLightEffect(GraphicsDevice);
DeferredDirectionalLightEffect = new DeferredPBR_DirectionalLightEffect(GraphicsDevice);
DeferredDirectionalLightEffect.ShadowMapSize = ShadowMapSize;
DeferredSpotLightEffect = new DeferredPBR_SpotLightEffect(GraphicsDevice);
ToneMapEffect = new Effect(graphicsDevice, Resources.ToneMapEffect);
Deferred_ToonEffect = new Deferred_ToonEffect(GraphicsDevice);
SkyboxEffect = new SkyboxEffect(GraphicsDevice);
@ -193,7 +195,7 @@ namespace Kav
foreach (var pointLight in pointLights)
{
PointLightRender(camera, modelTransforms, pointLight);
PointLightRender(modelTransforms, pointLight);
}
DirectionalLightRender(camera, modelTransforms, directionalLight);
@ -208,9 +210,10 @@ namespace Kav
public void DeferredToonRender(
PerspectiveCamera camera,
IEnumerable<(Model, Matrix)> modelTransforms,
AmbientLight ambientLight,
AmbientLight? ambientLight,
IEnumerable<PointLight> pointLights,
DirectionalLight directionalLight,
IEnumerable<SpotLight> spotLights,
DirectionalLight? directionalLight,
TextureCube skybox
) {
GBufferRender(camera, modelTransforms);
@ -222,12 +225,22 @@ namespace Kav
DepthRender(camera, modelTransforms);
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
AmbientLightRender(ambientLight);
if (ambientLight.HasValue)
{
AmbientLightRender(ambientLight.Value);
}
foreach (var pointLight in pointLights)
{
PointLightRender(camera, modelTransforms, pointLight);
PointLightRender(modelTransforms, pointLight);
}
foreach (var spotLight in spotLights)
{
SpotLightRender(modelTransforms, spotLight);
}
if (directionalLight.HasValue)
{
DirectionalLightToonRender(camera, modelTransforms, directionalLight.Value);
}
DirectionalLightToonRender(camera, modelTransforms, directionalLight);
SkyboxRender(camera, skybox);
GraphicsDevice.SetRenderTarget(null);
@ -373,11 +386,10 @@ namespace Kav
}
private void PointLightRender(
PerspectiveCamera camera,
IEnumerable<(Model, Matrix)> modelTransforms,
PointLight pointLight
) {
RenderPointShadows(camera, modelTransforms, pointLight);
RenderPointShadows(modelTransforms, pointLight);
GraphicsDevice.SetRenderTarget(ColorRenderTarget);
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
@ -403,6 +415,35 @@ namespace Kav
}
}
private void SpotLightRender(
IEnumerable<(Model, Matrix)> modelTransforms,
SpotLight spotLight
) {
GraphicsDevice.SetRenderTarget(ColorRenderTarget);
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
GraphicsDevice.BlendState = BlendState.Additive;
DeferredSpotLightEffect.GPosition = gPosition;
DeferredSpotLightEffect.GAlbedo = gAlbedo;
DeferredSpotLightEffect.GNormal = gNormal;
DeferredSpotLightEffect.GMetallicRoughness = gMetallicRoughness;
DeferredSpotLightEffect.LightPosition = spotLight.Position;
DeferredSpotLightEffect.LightDirection = spotLight.Direction;
DeferredSpotLightEffect.LightColor =
spotLight.Color.ToVector3() * spotLight.Intensity;
DeferredSpotLightEffect.LightCutoff = spotLight.Cutoff;
DeferredSpotLightEffect.FarPlane = 25f; // FIXME: magic value
foreach (var pass in DeferredSpotLightEffect.CurrentTechnique.Passes)
{
pass.Apply();
GraphicsDevice.SetVertexBuffer(FullscreenTriangle);
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
}
}
private void DirectionalLightRender(
PerspectiveCamera camera,
IEnumerable<(Model, Matrix)> modelTransforms,
@ -617,7 +658,6 @@ namespace Kav
}
private void RenderPointShadows(
PerspectiveCamera camera,
IEnumerable<(Model, Matrix)> modelTransforms,
PointLight pointLight
) {

View File

@ -39,6 +39,18 @@ namespace Kav
}
}
public static byte[] DeferredPBR_SpotLightEffect
{
get
{
if (spotLightEffect == null)
{
spotLightEffect = GetResource("DeferredPBR_SpotLightEffect.fxb");
}
return spotLightEffect;
}
}
public static byte[] DeferredPBR_GBufferEffect
{
get
@ -150,6 +162,7 @@ namespace Kav
private static byte[] ambientLightEffect;
private static byte[] pointLightEffect;
private static byte[] directionalLightEffect;
private static byte[] spotLightEffect;
private static byte[] gBufferEffect;
private static byte[] toneMapEffect;
private static byte[] deferredToonEffect;