initial diffuse lit sprite effect
parent
ae445d94d3
commit
47242e4f52
|
@ -0,0 +1,154 @@
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Kav
|
||||||
|
{
|
||||||
|
public class DiffuseLitSpriteEffect : Effect
|
||||||
|
{
|
||||||
|
EffectParameter textureParam;
|
||||||
|
|
||||||
|
EffectParameter ambientColorParam;
|
||||||
|
|
||||||
|
EffectParameter directionalLightDirectionParam;
|
||||||
|
EffectParameter directionalLightColorParam;
|
||||||
|
|
||||||
|
EffectParameter worldParam;
|
||||||
|
EffectParameter worldViewProjectionParam;
|
||||||
|
EffectParameter worldInverseTransposeParam;
|
||||||
|
|
||||||
|
Texture2D texture;
|
||||||
|
|
||||||
|
Vector3 ambientColor;
|
||||||
|
|
||||||
|
Vector3 directionalLightDirection;
|
||||||
|
Vector3 directionalLightColor;
|
||||||
|
|
||||||
|
Matrix world = Matrix.Identity;
|
||||||
|
Matrix view = Matrix.Identity;
|
||||||
|
Matrix projection = Matrix.Identity;
|
||||||
|
|
||||||
|
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
|
||||||
|
|
||||||
|
public Texture2D Texture
|
||||||
|
{
|
||||||
|
get { return texture; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
texture = value;
|
||||||
|
textureParam.SetValue(texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Matrix World
|
||||||
|
{
|
||||||
|
get { return world; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
world = value;
|
||||||
|
dirtyFlags |= EffectDirtyFlags.World | EffectDirtyFlags.WorldViewProj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Matrix View
|
||||||
|
{
|
||||||
|
get { return view; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
view = value;
|
||||||
|
dirtyFlags |= EffectDirtyFlags.WorldViewProj | EffectDirtyFlags.EyePosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Matrix Projection
|
||||||
|
{
|
||||||
|
get { return projection; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
projection = value;
|
||||||
|
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MaxPointLights { get; } = 8;
|
||||||
|
|
||||||
|
public Vector3 AmbientColor
|
||||||
|
{
|
||||||
|
get { return ambientColor; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
ambientColor = value;
|
||||||
|
ambientColorParam.SetValue(ambientColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PointLightCollection PointLights { get; private set; }
|
||||||
|
|
||||||
|
public Vector3 DirectionalLightDirection
|
||||||
|
{
|
||||||
|
get { return directionalLightDirection; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
directionalLightDirection = value;
|
||||||
|
directionalLightDirectionParam.SetValue(directionalLightDirection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 DirectionalLightColor
|
||||||
|
{
|
||||||
|
get { return directionalLightColor; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
directionalLightColor = value;
|
||||||
|
directionalLightColorParam.SetValue(directionalLightColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiffuseLitSpriteEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DiffuseLitSpriteEffect)
|
||||||
|
{
|
||||||
|
CacheEffectParameters();
|
||||||
|
|
||||||
|
PointLights = new PointLightCollection(
|
||||||
|
Parameters["PointLightPositions"],
|
||||||
|
Parameters["PointLightColors"],
|
||||||
|
MaxPointLights
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnApply()
|
||||||
|
{
|
||||||
|
if ((dirtyFlags & EffectDirtyFlags.World) != 0)
|
||||||
|
{
|
||||||
|
worldParam.SetValue(world);
|
||||||
|
|
||||||
|
Matrix.Invert(ref world, out Matrix worldInverse);
|
||||||
|
Matrix.Transpose(ref worldInverse, out Matrix worldInverseTranspose);
|
||||||
|
worldInverseTransposeParam.SetValue(worldInverseTranspose);
|
||||||
|
|
||||||
|
dirtyFlags &= ~EffectDirtyFlags.World;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0)
|
||||||
|
{
|
||||||
|
Matrix.Multiply(ref world, ref view, out Matrix worldView);
|
||||||
|
Matrix.Multiply(ref worldView, ref projection, out Matrix worldViewProj);
|
||||||
|
worldViewProjectionParam.SetValue(worldViewProj);
|
||||||
|
|
||||||
|
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CacheEffectParameters()
|
||||||
|
{
|
||||||
|
textureParam = Parameters["Texture"];
|
||||||
|
|
||||||
|
worldParam = Parameters["World"];
|
||||||
|
worldViewProjectionParam = Parameters["WorldViewProjection"];
|
||||||
|
worldInverseTransposeParam = Parameters["WorldInverseTranspose"];
|
||||||
|
|
||||||
|
ambientColorParam = Parameters["AmbientColor"];
|
||||||
|
|
||||||
|
directionalLightDirectionParam = Parameters["DirectionalLightDirection"];
|
||||||
|
directionalLightColorParam = Parameters["DirectionalLightColor"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
|
@ -0,0 +1,90 @@
|
||||||
|
#include "Macros.fxh" //from FNA
|
||||||
|
|
||||||
|
// Effect applies normalmapped lighting to a 2D sprite.
|
||||||
|
|
||||||
|
DECLARE_TEXTURE(Texture, 0);
|
||||||
|
DECLARE_TEXTURE(Normal, 1);
|
||||||
|
|
||||||
|
BEGIN_CONSTANTS
|
||||||
|
|
||||||
|
float AmbientColor _ps(c0) _cb(c0);
|
||||||
|
|
||||||
|
float3 PointLightPositions[8] _ps(c1) _cb(c1);
|
||||||
|
float3 PointLightColors[8] _ps(c9) _cb(c9);
|
||||||
|
|
||||||
|
float DirectionalLightDirection _ps(c17) _cb(c17);
|
||||||
|
float DirectionalLightColor _ps(c18) _cb(c18);
|
||||||
|
|
||||||
|
MATRIX_CONSTANTS
|
||||||
|
|
||||||
|
float4x4 WorldInverseTranspose _ps(c19) _cb(c19);
|
||||||
|
float4x4 World _vs(c0) _cb(c23);
|
||||||
|
float4x4 WorldViewProjection _vs(c4) _cb(c27);
|
||||||
|
|
||||||
|
END_CONSTANTS
|
||||||
|
|
||||||
|
struct VertexShaderInput
|
||||||
|
{
|
||||||
|
float4 Position : POSITION;
|
||||||
|
float2 TexCoord : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PixelShaderInput
|
||||||
|
{
|
||||||
|
float4 Position : SV_Position;
|
||||||
|
float2 TexCoord : TEXCOORD0;
|
||||||
|
float3 PositionWS : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
PixelShaderInput main_vs(VertexShaderInput input)
|
||||||
|
{
|
||||||
|
PixelShaderInput output;
|
||||||
|
|
||||||
|
output.TexCoord = input.TexCoord;
|
||||||
|
output.PositionWS = mul(input.Position, World).xyz;
|
||||||
|
output.Position = mul(input.Position, WorldViewProjection);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 main_ps(PixelShaderInput input) : COLOR0
|
||||||
|
{
|
||||||
|
// Look up the texture and normalmap values.
|
||||||
|
float4 tex = tex2D(TextureSampler, input.TexCoord);
|
||||||
|
float3 normal = tex2D(NormalSampler, input.TexCoord).xyz;
|
||||||
|
float3 normalWS = mul(normal, (float3x3)WorldInverseTranspose).xyz;
|
||||||
|
|
||||||
|
float3 lightColor = float3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
// point lights
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
float3 lightVec = PointLightPositions[i] - input.PositionWS;
|
||||||
|
float distance = length(lightVec);
|
||||||
|
|
||||||
|
float3 lightDir = normalize(lightVec);
|
||||||
|
float diffuse = max(dot(normalWS, lightDir), 0.0);
|
||||||
|
float3 attenuation = 1.0 / (distance * distance);
|
||||||
|
|
||||||
|
lightColor += diffuse * attenuation * PointLightColors[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// directional light
|
||||||
|
float directionalDiffuse = max(dot(normalWS, DirectionalLightDirection), 0.0);
|
||||||
|
lightColor += directionalDiffuse * DirectionalLightColor;
|
||||||
|
|
||||||
|
// ambient light
|
||||||
|
lightColor += AmbientColor;
|
||||||
|
|
||||||
|
// blend with sample
|
||||||
|
return tex * float4(lightColor, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Technique DiffuseLitSprite
|
||||||
|
{
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
VertexShader = compile vs_3_0 main_vs();
|
||||||
|
PixelShader = compile ps_3_0 main_ps();
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,6 +49,9 @@
|
||||||
<EmbeddedResource Include="Effects\FXB\SkyboxEffect.fxb">
|
<EmbeddedResource Include="Effects\FXB\SkyboxEffect.fxb">
|
||||||
<LogicalName>Kav.Resources.SkyboxEffect.fxb</LogicalName>
|
<LogicalName>Kav.Resources.SkyboxEffect.fxb</LogicalName>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Effects\FXB\DiffuseLitSpriteEffect.fxb">
|
||||||
|
<LogicalName>Kav.Resources.DiffuseLitSpriteEffect.fxb</LogicalName>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Models\UnitCube.glb">
|
<EmbeddedResource Include="Models\UnitCube.glb">
|
||||||
<LogicalName>Kav.Resources.UnitCube.glb</LogicalName>
|
<LogicalName>Kav.Resources.UnitCube.glb</LogicalName>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
|
|
@ -49,6 +49,9 @@
|
||||||
<EmbeddedResource Include="Effects\FXB\SkyboxEffect.fxb">
|
<EmbeddedResource Include="Effects\FXB\SkyboxEffect.fxb">
|
||||||
<LogicalName>Kav.Resources.SkyboxEffect.fxb</LogicalName>
|
<LogicalName>Kav.Resources.SkyboxEffect.fxb</LogicalName>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Effects\FXB\DiffuseLitSpriteEffect.fxb">
|
||||||
|
<LogicalName>Kav.Resources.DiffuseLitSpriteEffect.fxb</LogicalName>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Models\UnitCube.glb">
|
<EmbeddedResource Include="Models\UnitCube.glb">
|
||||||
<LogicalName>Kav.Resources.UnitCube.glb</LogicalName>
|
<LogicalName>Kav.Resources.UnitCube.glb</LogicalName>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
|
38
Renderer.cs
38
Renderer.cs
|
@ -33,7 +33,7 @@ namespace Kav
|
||||||
private LinearDepthEffect LinearDepthEffect { get; }
|
private LinearDepthEffect LinearDepthEffect { get; }
|
||||||
private Effect ToneMapEffect { get; }
|
private Effect ToneMapEffect { get; }
|
||||||
private SkyboxEffect SkyboxEffect { get; }
|
private SkyboxEffect SkyboxEffect { get; }
|
||||||
private BasicEffect BasicEffect { get; }
|
private DiffuseLitSpriteEffect DiffuseLitSpriteEffect { get; }
|
||||||
|
|
||||||
private RenderTarget2D gPosition { get; }
|
private RenderTarget2D gPosition { get; }
|
||||||
private RenderTarget2D gNormal { get; }
|
private RenderTarget2D gNormal { get; }
|
||||||
|
@ -160,7 +160,7 @@ namespace Kav
|
||||||
ToneMapEffect = new Effect(graphicsDevice, Resources.ToneMapEffect);
|
ToneMapEffect = new Effect(graphicsDevice, Resources.ToneMapEffect);
|
||||||
Deferred_ToonEffect = new Deferred_ToonEffect(GraphicsDevice);
|
Deferred_ToonEffect = new Deferred_ToonEffect(GraphicsDevice);
|
||||||
SkyboxEffect = new SkyboxEffect(GraphicsDevice);
|
SkyboxEffect = new SkyboxEffect(GraphicsDevice);
|
||||||
BasicEffect = new BasicEffect(GraphicsDevice);
|
DiffuseLitSpriteEffect = new DiffuseLitSpriteEffect(GraphicsDevice);
|
||||||
|
|
||||||
FullscreenTriangle = new VertexBuffer(GraphicsDevice, typeof(VertexPositionTexture), 3, BufferUsage.WriteOnly);
|
FullscreenTriangle = new VertexBuffer(GraphicsDevice, typeof(VertexPositionTexture), 3, BufferUsage.WriteOnly);
|
||||||
FullscreenTriangle.SetData(new VertexPositionTexture[3] {
|
FullscreenTriangle.SetData(new VertexPositionTexture[3] {
|
||||||
|
@ -245,7 +245,10 @@ namespace Kav
|
||||||
RenderTarget2D renderTarget,
|
RenderTarget2D renderTarget,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||||
IEnumerable<Sprite> sprites
|
IEnumerable<Sprite> sprites,
|
||||||
|
AmbientLight ambientLight,
|
||||||
|
IEnumerable<PointLight> pointLights,
|
||||||
|
DirectionalLight directionalLight
|
||||||
) {
|
) {
|
||||||
GraphicsDevice.SetRenderTarget(ColorRenderTarget);
|
GraphicsDevice.SetRenderTarget(ColorRenderTarget);
|
||||||
GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0);
|
GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0);
|
||||||
|
@ -254,20 +257,31 @@ namespace Kav
|
||||||
DepthRender(camera, modelTransforms);
|
DepthRender(camera, modelTransforms);
|
||||||
GraphicsDevice.Clear(ClearOptions.Target, new Color(0, 0, 0, 0), 1f, 0);
|
GraphicsDevice.Clear(ClearOptions.Target, new Color(0, 0, 0, 0), 1f, 0);
|
||||||
|
|
||||||
BasicEffect.View = camera.View;
|
DiffuseLitSpriteEffect.View = camera.View;
|
||||||
BasicEffect.Projection = camera.Projection;
|
DiffuseLitSpriteEffect.Projection = camera.Projection;
|
||||||
BasicEffect.TextureEnabled = true;
|
|
||||||
BasicEffect.VertexColorEnabled = true;
|
DiffuseLitSpriteEffect.DirectionalLightDirection =
|
||||||
|
directionalLight.Direction;
|
||||||
|
DiffuseLitSpriteEffect.DirectionalLightColor =
|
||||||
|
directionalLight.Color.ToVector3() * directionalLight.Intensity;
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
foreach (var pointLight in pointLights)
|
||||||
|
{
|
||||||
|
if (i > DiffuseLitSpriteEffect.MaxPointLights) { break; }
|
||||||
|
DiffuseLitSpriteEffect.PointLights[i] = pointLight;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var sprite in sprites)
|
foreach (var sprite in sprites)
|
||||||
{
|
{
|
||||||
if (sprite.BillboardConstraint == SpriteBillboardConstraint.None)
|
if (sprite.BillboardConstraint == SpriteBillboardConstraint.None)
|
||||||
{
|
{
|
||||||
BasicEffect.World = sprite.TransformMatrix;
|
DiffuseLitSpriteEffect.World = sprite.TransformMatrix;
|
||||||
}
|
}
|
||||||
else if (sprite.BillboardConstraint == SpriteBillboardConstraint.Horizontal)
|
else if (sprite.BillboardConstraint == SpriteBillboardConstraint.Horizontal)
|
||||||
{
|
{
|
||||||
BasicEffect.World = Matrix.CreateConstrainedBillboard(
|
DiffuseLitSpriteEffect.World = Matrix.CreateConstrainedBillboard(
|
||||||
sprite.Position,
|
sprite.Position,
|
||||||
camera.Position,
|
camera.Position,
|
||||||
Vector3.Up,
|
Vector3.Up,
|
||||||
|
@ -277,7 +291,7 @@ namespace Kav
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BasicEffect.World = Matrix.CreateConstrainedBillboard(
|
DiffuseLitSpriteEffect.World = Matrix.CreateConstrainedBillboard(
|
||||||
sprite.Position,
|
sprite.Position,
|
||||||
camera.Position,
|
camera.Position,
|
||||||
Vector3.Up,
|
Vector3.Up,
|
||||||
|
@ -286,7 +300,9 @@ namespace Kav
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpriteBatch.Begin(0, null, null, DepthStencilState.DepthRead, RasterizerState.CullNone, BasicEffect);
|
GraphicsDevice.Textures[1] = sprite.Texture;
|
||||||
|
|
||||||
|
SpriteBatch.Begin(0, null, null, DepthStencilState.DepthRead, RasterizerState.CullNone, DiffuseLitSpriteEffect);
|
||||||
SpriteBatch.Draw(
|
SpriteBatch.Draw(
|
||||||
sprite.Texture,
|
sprite.Texture,
|
||||||
Vector2.Zero,
|
Vector2.Zero,
|
||||||
|
|
13
Resources.cs
13
Resources.cs
|
@ -135,6 +135,18 @@ namespace Kav
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] DiffuseLitSpriteEffect
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (diffuseLitSpriteEffect == null)
|
||||||
|
{
|
||||||
|
diffuseLitSpriteEffect = GetResource("DiffuseLitSpriteEffect.fxb");
|
||||||
|
}
|
||||||
|
return diffuseLitSpriteEffect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static byte[] UnitCubeModel
|
public static byte[] UnitCubeModel
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -158,6 +170,7 @@ namespace Kav
|
||||||
private static byte[] simpleDepthEffect;
|
private static byte[] simpleDepthEffect;
|
||||||
private static byte[] linearDepthEffect;
|
private static byte[] linearDepthEffect;
|
||||||
private static byte[] skyboxEffect;
|
private static byte[] skyboxEffect;
|
||||||
|
private static byte[] diffuseLitSpriteEffect;
|
||||||
|
|
||||||
private static byte[] unitCubeModel;
|
private static byte[] unitCubeModel;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue