new mesh sprite and diffuse lit sprite system
parent
60ebb19e24
commit
ca6c91446e
|
@ -5,8 +5,6 @@ namespace Kav
|
||||||
{
|
{
|
||||||
public class DiffuseLitSpriteEffect : Effect
|
public class DiffuseLitSpriteEffect : Effect
|
||||||
{
|
{
|
||||||
EffectParameter textureParam;
|
|
||||||
|
|
||||||
EffectParameter ambientColorParam;
|
EffectParameter ambientColorParam;
|
||||||
|
|
||||||
EffectParameter directionalLightDirectionParam;
|
EffectParameter directionalLightDirectionParam;
|
||||||
|
@ -16,7 +14,12 @@ namespace Kav
|
||||||
EffectParameter worldViewProjectionParam;
|
EffectParameter worldViewProjectionParam;
|
||||||
EffectParameter worldInverseTransposeParam;
|
EffectParameter worldInverseTransposeParam;
|
||||||
|
|
||||||
|
EffectParameter shaderIndexParam;
|
||||||
|
|
||||||
Texture2D texture;
|
Texture2D texture;
|
||||||
|
Texture2D normal;
|
||||||
|
|
||||||
|
bool normalMapEnabled = false;
|
||||||
|
|
||||||
Vector3 ambientColor;
|
Vector3 ambientColor;
|
||||||
|
|
||||||
|
@ -29,13 +32,16 @@ namespace Kav
|
||||||
|
|
||||||
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
|
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
|
||||||
|
|
||||||
public Texture2D Texture
|
public bool NormalMapEnabled
|
||||||
{
|
{
|
||||||
get { return texture; }
|
get { return normalMapEnabled; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
texture = value;
|
if (normalMapEnabled != value)
|
||||||
textureParam.SetValue(texture);
|
{
|
||||||
|
normalMapEnabled = value;
|
||||||
|
dirtyFlags |= EffectDirtyFlags.ShaderIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,12 +141,22 @@ namespace Kav
|
||||||
|
|
||||||
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
|
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0)
|
||||||
|
{
|
||||||
|
int shaderIndex = 0;
|
||||||
|
|
||||||
|
if (normalMapEnabled)
|
||||||
|
{
|
||||||
|
shaderIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
shaderIndexParam.SetValue(shaderIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CacheEffectParameters()
|
private void CacheEffectParameters()
|
||||||
{
|
{
|
||||||
textureParam = Parameters["Texture"];
|
|
||||||
|
|
||||||
worldParam = Parameters["World"];
|
worldParam = Parameters["World"];
|
||||||
worldViewProjectionParam = Parameters["WorldViewProjection"];
|
worldViewProjectionParam = Parameters["WorldViewProjection"];
|
||||||
worldInverseTransposeParam = Parameters["WorldInverseTranspose"];
|
worldInverseTransposeParam = Parameters["WorldInverseTranspose"];
|
||||||
|
@ -149,6 +165,8 @@ namespace Kav
|
||||||
|
|
||||||
directionalLightDirectionParam = Parameters["DirectionalLightDirection"];
|
directionalLightDirectionParam = Parameters["DirectionalLightDirection"];
|
||||||
directionalLightColorParam = Parameters["DirectionalLightColor"];
|
directionalLightColorParam = Parameters["DirectionalLightColor"];
|
||||||
|
|
||||||
|
shaderIndexParam = Parameters["ShaderIndex"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
BIN
Effects/FXB/DiffuseLitSpriteEffect.fxb (Stored with Git LFS)
BIN
Effects/FXB/DiffuseLitSpriteEffect.fxb (Stored with Git LFS)
Binary file not shown.
|
@ -1,90 +0,0 @@
|
||||||
#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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
#include "Macros.fxh" //from FNA
|
||||||
|
|
||||||
|
// Effect applies normalmapped lighting to a 2D sprite.
|
||||||
|
|
||||||
|
DECLARE_TEXTURE(Texture, 0);
|
||||||
|
DECLARE_TEXTURE(Normal, 1);
|
||||||
|
|
||||||
|
BEGIN_CONSTANTS
|
||||||
|
|
||||||
|
float3 AmbientColor _ps(c0) _cb(c0);
|
||||||
|
|
||||||
|
float3 PointLightPositions[8] _ps(c1) _cb(c1);
|
||||||
|
float3 PointLightColors[8] _ps(c9) _cb(c9);
|
||||||
|
|
||||||
|
float3 DirectionalLightDirection _ps(c17) _cb(c17);
|
||||||
|
float3 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;
|
||||||
|
float3 Normal : NORMAL;
|
||||||
|
float2 TexCoord : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PixelShaderInput
|
||||||
|
{
|
||||||
|
float4 Position : SV_Position;
|
||||||
|
float2 TexCoord : TEXCOORD0;
|
||||||
|
float3 NormalWS : TEXCOORD1;
|
||||||
|
float3 PositionWS : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
PixelShaderInput main_vs(VertexShaderInput input)
|
||||||
|
{
|
||||||
|
PixelShaderInput output;
|
||||||
|
|
||||||
|
output.Position = mul(input.Position, WorldViewProjection);
|
||||||
|
output.TexCoord = input.TexCoord;
|
||||||
|
output.NormalWS = mul(input.Normal, (float3x3)WorldInverseTranspose).xyz;
|
||||||
|
output.PositionWS = mul(input.Position, World).xyz;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Easy trick to get tangent-normals to world-space to keep PBR code simplified.
|
||||||
|
float3 GetNormalFromMap(float3 worldPos, float2 texCoords, float3 normal)
|
||||||
|
{
|
||||||
|
float3 tangentNormal = SAMPLE_TEXTURE(Normal, texCoords).xyz * 2.0 - 1.0;
|
||||||
|
|
||||||
|
float3 Q1 = ddx(worldPos);
|
||||||
|
float3 Q2 = ddy(worldPos);
|
||||||
|
float2 st1 = ddx(texCoords);
|
||||||
|
float2 st2 = ddy(texCoords);
|
||||||
|
|
||||||
|
float3 N = normalize(normal);
|
||||||
|
float3 T = normalize(Q1*st2.y - Q2*st1.y);
|
||||||
|
float3 B = -normalize(cross(N, T));
|
||||||
|
float3x3 TBN = float3x3(T, B, N);
|
||||||
|
|
||||||
|
return normalize(mul(tangentNormal, TBN));
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 LightColor(float3 worldPosition, float3 worldNormal)
|
||||||
|
{
|
||||||
|
float3 lightColor = float3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
// point lights
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
float3 lightVec = PointLightPositions[i] - worldPosition;
|
||||||
|
float distance = length(lightVec);
|
||||||
|
|
||||||
|
float3 lightDir = normalize(lightVec);
|
||||||
|
float diffuse = max(dot(worldNormal, lightDir), 0.0);
|
||||||
|
float3 attenuation = 1.0 / (distance * distance);
|
||||||
|
|
||||||
|
lightColor += diffuse * attenuation * PointLightColors[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// directional light
|
||||||
|
float directionalDiffuse = max(dot(worldNormal, DirectionalLightDirection), 0.0);
|
||||||
|
lightColor += directionalDiffuse * DirectionalLightColor;
|
||||||
|
|
||||||
|
// ambient light
|
||||||
|
lightColor += AmbientColor;
|
||||||
|
|
||||||
|
return float4(lightColor, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 WithoutNormalMap(PixelShaderInput input) : COLOR0
|
||||||
|
{
|
||||||
|
float4 tex = SAMPLE_TEXTURE(Texture, input.TexCoord);
|
||||||
|
float3 normalWS = normalize(input.NormalWS);
|
||||||
|
|
||||||
|
return tex * LightColor(input.PositionWS, normalWS);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 WithNormalMap(PixelShaderInput input) : COLOR0
|
||||||
|
{
|
||||||
|
float4 tex = SAMPLE_TEXTURE(Texture, input.TexCoord);
|
||||||
|
float3 normalWS = GetNormalFromMap(input.PositionWS, input.TexCoord, input.NormalWS);
|
||||||
|
|
||||||
|
return tex * LightColor(input.PositionWS, normalWS);
|
||||||
|
}
|
||||||
|
|
||||||
|
PixelShader PSArray[2] =
|
||||||
|
{
|
||||||
|
compile ps_3_0 WithoutNormalMap(),
|
||||||
|
compile ps_3_0 WithNormalMap()
|
||||||
|
};
|
||||||
|
|
||||||
|
int PSIndices[2] =
|
||||||
|
{
|
||||||
|
0, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
int ShaderIndex = 0;
|
||||||
|
|
||||||
|
Technique DiffuseLitSprite
|
||||||
|
{
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
VertexShader = compile vs_3_0 main_vs();
|
||||||
|
PixelShader = (PSArray[PSIndices[ShaderIndex]]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Kav
|
||||||
|
{
|
||||||
|
public class MeshSprite
|
||||||
|
{
|
||||||
|
private static readonly int PixelScale = 40;
|
||||||
|
|
||||||
|
public IndexBuffer IndexBuffer { get; }
|
||||||
|
public VertexBuffer VertexBuffer { get; }
|
||||||
|
|
||||||
|
public Texture2D Texture { get; }
|
||||||
|
public Texture2D Normal { get; }
|
||||||
|
public SpriteBillboardConstraint BillboardConstraint { get; }
|
||||||
|
|
||||||
|
public MeshSprite(
|
||||||
|
GraphicsDevice graphicsDevice,
|
||||||
|
Texture2D texture,
|
||||||
|
SpriteBillboardConstraint billboardConstraint
|
||||||
|
) {
|
||||||
|
Texture = texture;
|
||||||
|
Normal = null;
|
||||||
|
BillboardConstraint = billboardConstraint;
|
||||||
|
|
||||||
|
IndexBuffer = new IndexBuffer(
|
||||||
|
graphicsDevice,
|
||||||
|
IndexElementSize.SixteenBits,
|
||||||
|
6,
|
||||||
|
BufferUsage.WriteOnly
|
||||||
|
);
|
||||||
|
IndexBuffer.SetData(GenerateIndexArray());
|
||||||
|
|
||||||
|
VertexBuffer = new VertexBuffer(
|
||||||
|
graphicsDevice,
|
||||||
|
typeof(VertexPositionNormalTexture),
|
||||||
|
4,
|
||||||
|
BufferUsage.WriteOnly
|
||||||
|
);
|
||||||
|
VertexBuffer.SetData(GenerateVertexArray(Texture));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MeshSprite(
|
||||||
|
GraphicsDevice graphicsDevice,
|
||||||
|
Texture2D texture,
|
||||||
|
Texture2D normal,
|
||||||
|
SpriteBillboardConstraint billboardConstraint
|
||||||
|
) {
|
||||||
|
Texture = texture;
|
||||||
|
Normal = normal;
|
||||||
|
BillboardConstraint = billboardConstraint;
|
||||||
|
|
||||||
|
IndexBuffer = new IndexBuffer(
|
||||||
|
graphicsDevice,
|
||||||
|
IndexElementSize.SixteenBits,
|
||||||
|
6,
|
||||||
|
BufferUsage.WriteOnly
|
||||||
|
);
|
||||||
|
IndexBuffer.SetData(GenerateIndexArray());
|
||||||
|
|
||||||
|
VertexBuffer = new VertexBuffer(
|
||||||
|
graphicsDevice,
|
||||||
|
typeof(VertexPositionNormalTexture),
|
||||||
|
4,
|
||||||
|
BufferUsage.WriteOnly
|
||||||
|
);
|
||||||
|
VertexBuffer.SetData(GenerateVertexArray(Texture));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static short[] GenerateIndexArray()
|
||||||
|
{
|
||||||
|
short[] result = new short[6];
|
||||||
|
result[0] = 0;
|
||||||
|
result[1] = 1;
|
||||||
|
result[2] = 2;
|
||||||
|
result[3] = 1;
|
||||||
|
result[4] = 3;
|
||||||
|
result[5] = 2;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static VertexPositionNormalTexture[] GenerateVertexArray(Texture2D texture)
|
||||||
|
{
|
||||||
|
VertexPositionNormalTexture[] result = new VertexPositionNormalTexture[4];
|
||||||
|
|
||||||
|
result[0].Position = new Vector3(-texture.Width / 2, texture.Height / 2, 0) / PixelScale;
|
||||||
|
result[0].Normal = new Vector3(0, 0, -1);
|
||||||
|
result[0].TextureCoordinate = new Vector2(0, 0);
|
||||||
|
|
||||||
|
result[1].Position = new Vector3(texture.Width / 2, texture.Height / 2, 0) / PixelScale;
|
||||||
|
result[1].Normal = new Vector3(0, 0, -1);
|
||||||
|
result[1].TextureCoordinate = new Vector2(1, 0);
|
||||||
|
|
||||||
|
result[2].Position = new Vector3(-texture.Width / 2, -texture.Height / 2, 0) / PixelScale;
|
||||||
|
result[2].Normal = new Vector3(0, 0, -1);
|
||||||
|
result[2].TextureCoordinate = new Vector2(0, 1);
|
||||||
|
|
||||||
|
result[3].Position = new Vector3(texture.Width / 2, -texture.Height / 2, 0) / PixelScale;
|
||||||
|
result[3].Normal = new Vector3(0, 0, -1);
|
||||||
|
result[3].TextureCoordinate = new Vector2(1, 1);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
93
Renderer.cs
93
Renderer.cs
|
@ -183,7 +183,7 @@ namespace Kav
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||||
AmbientLight ambientLight,
|
AmbientLight ambientLight,
|
||||||
IEnumerable<PointLight> pointLights,
|
IEnumerable<PointLight> pointLights,
|
||||||
DirectionalLight directionalLight
|
DirectionalLight? directionalLight
|
||||||
) {
|
) {
|
||||||
GBufferRender(camera, modelTransforms);
|
GBufferRender(camera, modelTransforms);
|
||||||
|
|
||||||
|
@ -199,7 +199,10 @@ namespace Kav
|
||||||
PointLightRender(camera, modelTransforms, pointLight);
|
PointLightRender(camera, modelTransforms, pointLight);
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectionalLightRender(camera, modelTransforms, directionalLight);
|
if (directionalLight.HasValue)
|
||||||
|
{
|
||||||
|
DirectionalLightRender(camera, modelTransforms, directionalLight.Value);
|
||||||
|
}
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(renderTarget);
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, ToneMapEffect);
|
SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, ToneMapEffect);
|
||||||
|
@ -213,7 +216,7 @@ namespace Kav
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||||
AmbientLight ambientLight,
|
AmbientLight ambientLight,
|
||||||
IEnumerable<PointLight> pointLights,
|
IEnumerable<PointLight> pointLights,
|
||||||
DirectionalLight directionalLight,
|
DirectionalLight? directionalLight,
|
||||||
TextureCube skybox
|
TextureCube skybox
|
||||||
) {
|
) {
|
||||||
GBufferRender(camera, modelTransforms);
|
GBufferRender(camera, modelTransforms);
|
||||||
|
@ -230,7 +233,12 @@ namespace Kav
|
||||||
{
|
{
|
||||||
PointLightRender(camera, modelTransforms, pointLight);
|
PointLightRender(camera, modelTransforms, pointLight);
|
||||||
}
|
}
|
||||||
DirectionalLightToonRender(camera, modelTransforms, directionalLight);
|
|
||||||
|
if (directionalLight.HasValue)
|
||||||
|
{
|
||||||
|
DirectionalLightToonRender(camera, modelTransforms, directionalLight.Value);
|
||||||
|
}
|
||||||
|
|
||||||
SkyboxRender(camera, skybox);
|
SkyboxRender(camera, skybox);
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(renderTarget);
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
|
@ -239,16 +247,16 @@ namespace Kav
|
||||||
SpriteBatch.End();
|
SpriteBatch.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
// billboards sprites into the scene
|
// TODO: we could make this a lot more efficient probably
|
||||||
// FIXME: we can frustum cull the sprites probably
|
// draws mesh sprites with a forward rendered diffuse lighting technique
|
||||||
public void BillboardSpriteRender(
|
public void MeshSpriteRender(
|
||||||
RenderTarget2D renderTarget,
|
RenderTarget2D renderTarget,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||||
IEnumerable<Sprite> sprites,
|
IEnumerable<(MeshSprite, Matrix)> meshSpriteTransforms,
|
||||||
AmbientLight ambientLight,
|
AmbientLight ambientLight,
|
||||||
IEnumerable<PointLight> pointLights,
|
IEnumerable<PointLight> pointLights,
|
||||||
DirectionalLight directionalLight
|
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);
|
||||||
|
@ -257,16 +265,29 @@ 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);
|
||||||
|
|
||||||
|
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
||||||
|
GraphicsDevice.RasterizerState = RasterizerState.CullNone;
|
||||||
|
GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
|
||||||
|
GraphicsDevice.SamplerStates[1] = SamplerState.PointClamp;
|
||||||
|
GraphicsDevice.BlendState = BlendState.AlphaBlend;
|
||||||
|
|
||||||
DiffuseLitSpriteEffect.View = camera.View;
|
DiffuseLitSpriteEffect.View = camera.View;
|
||||||
DiffuseLitSpriteEffect.Projection = camera.Projection;
|
DiffuseLitSpriteEffect.Projection = camera.Projection;
|
||||||
|
|
||||||
DiffuseLitSpriteEffect.AmbientColor =
|
DiffuseLitSpriteEffect.AmbientColor =
|
||||||
ambientLight.Color.ToVector3();
|
ambientLight.Color.ToVector3();
|
||||||
|
|
||||||
DiffuseLitSpriteEffect.DirectionalLightDirection =
|
if (directionalLight.HasValue)
|
||||||
directionalLight.Direction;
|
{
|
||||||
DiffuseLitSpriteEffect.DirectionalLightColor =
|
DiffuseLitSpriteEffect.DirectionalLightDirection =
|
||||||
directionalLight.Color.ToVector3() * directionalLight.Intensity;
|
directionalLight.Value.Direction;
|
||||||
|
DiffuseLitSpriteEffect.DirectionalLightColor =
|
||||||
|
directionalLight.Value.Color.ToVector3() * directionalLight.Value.Intensity;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DiffuseLitSpriteEffect.DirectionalLightColor = Vector3.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
foreach (var pointLight in pointLights)
|
foreach (var pointLight in pointLights)
|
||||||
|
@ -276,26 +297,28 @@ namespace Kav
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var sprite in sprites)
|
foreach (var (sprite, transform) in meshSpriteTransforms)
|
||||||
{
|
{
|
||||||
|
DiffuseLitSpriteEffect.NormalMapEnabled = sprite.Normal != null;
|
||||||
|
|
||||||
if (sprite.BillboardConstraint == SpriteBillboardConstraint.None)
|
if (sprite.BillboardConstraint == SpriteBillboardConstraint.None)
|
||||||
{
|
{
|
||||||
DiffuseLitSpriteEffect.World = sprite.TransformMatrix;
|
DiffuseLitSpriteEffect.World = transform;
|
||||||
}
|
}
|
||||||
else if (sprite.BillboardConstraint == SpriteBillboardConstraint.Horizontal)
|
else if (sprite.BillboardConstraint == SpriteBillboardConstraint.Horizontal)
|
||||||
{
|
{
|
||||||
DiffuseLitSpriteEffect.World = Matrix.CreateConstrainedBillboard(
|
DiffuseLitSpriteEffect.World = Matrix.CreateConstrainedBillboard(
|
||||||
sprite.Position,
|
transform.Translation,
|
||||||
camera.Position,
|
camera.Position,
|
||||||
Vector3.Up,
|
Vector3.Up,
|
||||||
camera.Forward,
|
camera.Forward,
|
||||||
camera.Position - sprite.Position
|
camera.Position - transform.Translation
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DiffuseLitSpriteEffect.World = Matrix.CreateConstrainedBillboard(
|
DiffuseLitSpriteEffect.World = Matrix.CreateConstrainedBillboard(
|
||||||
sprite.Position,
|
transform.Translation,
|
||||||
camera.Position,
|
camera.Position,
|
||||||
Vector3.Up,
|
Vector3.Up,
|
||||||
null,
|
null,
|
||||||
|
@ -303,24 +326,27 @@ namespace Kav
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsDevice.Textures[1] = sprite.Texture;
|
GraphicsDevice.Textures[0] = sprite.Texture;
|
||||||
|
GraphicsDevice.Textures[1] = sprite.Normal;
|
||||||
|
|
||||||
SpriteBatch.Begin(0, null, null, DepthStencilState.DepthRead, RasterizerState.CullNone, DiffuseLitSpriteEffect);
|
GraphicsDevice.SetVertexBuffer(sprite.VertexBuffer);
|
||||||
SpriteBatch.Draw(
|
GraphicsDevice.Indices = sprite.IndexBuffer;
|
||||||
sprite.Texture,
|
|
||||||
Vector2.Zero,
|
foreach (var pass in DiffuseLitSpriteEffect.CurrentTechnique.Passes)
|
||||||
null,
|
{
|
||||||
Color.White,
|
pass.Apply();
|
||||||
sprite.Rotation,
|
|
||||||
sprite.Origin,
|
GraphicsDevice.DrawIndexedPrimitives(
|
||||||
sprite.Scale / new Vector2(sprite.Texture.Width, -sprite.Texture.Height),
|
PrimitiveType.TriangleList,
|
||||||
0,
|
0,
|
||||||
0
|
0,
|
||||||
);
|
sprite.VertexBuffer.VertexCount,
|
||||||
SpriteBatch.End();
|
0,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(renderTarget);
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
GraphicsDevice.Clear(new Color(0, 0, 0, 0));
|
GraphicsDevice.Clear(new Color(0, 0, 0, 0));
|
||||||
SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null);
|
SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null);
|
||||||
|
@ -558,6 +584,7 @@ namespace Kav
|
||||||
Deferred_ToonEffect.DitheredShadows = false;
|
Deferred_ToonEffect.DitheredShadows = false;
|
||||||
|
|
||||||
Deferred_ToonEffect.EyePosition = camera.Position;
|
Deferred_ToonEffect.EyePosition = camera.Position;
|
||||||
|
|
||||||
Deferred_ToonEffect.DirectionalLightDirection = directionalLight.Direction;
|
Deferred_ToonEffect.DirectionalLightDirection = directionalLight.Direction;
|
||||||
Deferred_ToonEffect.DirectionalLightColor =
|
Deferred_ToonEffect.DirectionalLightColor =
|
||||||
directionalLight.Color.ToVector3() * directionalLight.Intensity;
|
directionalLight.Color.ToVector3() * directionalLight.Intensity;
|
||||||
|
|
Loading…
Reference in New Issue