Compare commits

..

No commits in common. "main" and "sprites" have entirely different histories.

56 changed files with 715 additions and 2552 deletions

View File

@ -10,32 +10,23 @@ namespace Kav
public Vector3 Position { get; } public Vector3 Position { get; }
public Vector3 Forward { get; } public Vector3 Forward { get; }
public Vector3 Up { get; } public Vector3 Up { get; }
public Vector3 Right { get; }
public float FieldOfView { get; } public float FieldOfView { get; }
public float AspectRatio { get; } public float AspectRatio { get; }
public float NearPlane { get; } public float NearPlane { get; }
public float FarPlane { get; } public float FarPlane { get; }
public PerspectiveCamera( public PerspectiveCamera(Vector3 position, Vector3 forward, Vector3 up, float fieldOfView, float aspectRatio, float nearPlane, float farPlane)
Vector3 position, {
Vector3 forward,
Vector3 up,
float fieldOfView,
float aspectRatio,
float nearPlane,
float farPlane
) {
Position = position; Position = position;
Forward = forward; Forward = forward;
Up = up; Up = up;
Right = Vector3.Cross(forward, up);
View = Matrix.CreateLookAt(Position, Position + Forward, Up); View = Matrix.CreateLookAt(Position, Position + Forward, Up);
FieldOfView = fieldOfView; FieldOfView = fieldOfView;
AspectRatio = aspectRatio; AspectRatio = aspectRatio;
NearPlane = nearPlane; NearPlane = nearPlane;
FarPlane = farPlane; FarPlane = farPlane;
Projection = Matrix.CreatePerspectiveFieldOfView(FieldOfView, AspectRatio, NearPlane, FarPlane); Projection = Matrix.CreatePerspectiveFieldOfView(FieldOfView, AspectRatio, NearPlane, FarPlane);
} }
} }

View File

@ -1,14 +0,0 @@
namespace Kav
{
public struct AtlasAnimation
{
public UVData[] Frames { get; }
public int Framerate { get; }
public AtlasAnimation(UVData[] frames, int framerate)
{
Frames = frames;
Framerate = framerate;
}
}
}

View File

@ -1,63 +0,0 @@
using System.Collections.Generic;
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
public class InstanceData<T> where T : struct, IVertexType
{
public T[] InstanceDataArray { get; }
public DynamicVertexBuffer VertexBuffer { get; }
public int InstanceCount { get; private set; }
public InstanceData(GraphicsDevice graphicsDevice, int size)
{
InstanceDataArray = new T[size];
VertexBuffer = new DynamicVertexBuffer(
graphicsDevice,
typeof(T),
size,
BufferUsage.WriteOnly
);
InstanceCount = 0;
}
public void AddAndSetData(IEnumerable<T> data)
{
InstanceCount = 0;
foreach (var datum in data)
{
AddData(datum);
}
if (InstanceCount == 0) { throw new System.Exception(); }
SetData();
}
public void AddData(T datum)
{
InstanceDataArray[InstanceCount] = datum;
InstanceCount += 1;
}
public void SetData()
{
if (InstanceCount > 0)
{
VertexBuffer.SetData(
InstanceDataArray,
0,
InstanceCount,
SetDataOptions.NoOverwrite
);
}
}
public void Clear()
{
InstanceCount = 0;
}
}
}

View File

@ -1,35 +0,0 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Kav.Data
{
public struct MeshSpriteDrawData : IIndexDrawable, ICullable, ITransformable
{
public SpriteMesh MeshSprite { get; }
public Texture2D Texture { get; }
public Texture2D Normal { get; }
public SpriteBillboardConstraint BillboardConstraint { get; }
public Matrix TransformMatrix { get; }
public UVData UVOffset { get; }
public IndexBuffer IndexBuffer => MeshSprite.IndexBuffer;
public VertexBuffer VertexBuffer => MeshSprite.VertexBuffer;
public BoundingBox BoundingBox => MeshSprite.BoundingBox;
public MeshSpriteDrawData(
SpriteMesh meshSprite,
Texture2D texture,
Texture2D normal,
SpriteBillboardConstraint billboardConstraint,
Matrix transformMatrix,
UVData offset
) {
MeshSprite = meshSprite;
Texture = texture;
Normal = normal;
BillboardConstraint = billboardConstraint;
TransformMatrix = transformMatrix;
UVOffset = offset;
}
}
}

View File

@ -1,96 +0,0 @@
using Kav.Data;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
using System.IO;
namespace Kav
{
public struct TextureAtlasSlice
{
public int X { get; }
public int Y { get; }
public int W { get; }
public int H { get; }
public UVData UVData { get; }
// for use with tiling
public Vector2 TiledUVOffset { get; }
public TextureAtlasSlice(int x, int y, int w, int h, int totalW, int totalH)
{
X = x;
Y = y;
W = w;
H = h;
UVData = new UVData(new Vector2(x, y), new Vector2(w, h), new Vector2(totalW, totalH));
TiledUVOffset = new Vector2(x / (float)totalW, y / (float)totalH);
}
}
public class TextureAtlas
{
public Texture2D Texture { get; }
protected List<string> Names { get; } = new List<string>();
protected Dictionary<string, TextureAtlasSlice> Slices { get; } = new Dictionary<string, TextureAtlasSlice>();
public TextureAtlas(GraphicsDevice graphicsDevice, FileInfo atlasMetadataFile)
{
var atlasData = CrunchAtlasReader.ReadTextureAtlas(atlasMetadataFile);
var textureData = atlasData.Textures[0];
using var stream = File.OpenRead(Path.Combine(atlasMetadataFile.DirectoryName, textureData.Name + ".png"));
Texture = Texture2D.FromStream(graphicsDevice, stream);
foreach (var slice in textureData.Images)
{
Names.Add(slice.N);
Slices.Add(
slice.N,
new TextureAtlasSlice(
slice.X,
slice.Y,
slice.W,
slice.H,
Texture.Width,
Texture.Height
)
);
}
}
public TextureAtlasSlice Lookup(string name)
{
return Slices[name];
}
public string Name(int index)
{
return Names[index];
}
public int Count()
{
return Names.Count;
}
}
// Assumes all subimages are the same size
public class TiledTextureAtlas : TextureAtlas
{
public int NumRows { get; }
public int NumColumns { get; }
public TiledTextureAtlas(GraphicsDevice graphicsDevice, FileInfo atlasMetadataFile) : base(graphicsDevice, atlasMetadataFile)
{
var subImageSlice = Slices[Names[0]];
NumRows = Texture.Height / subImageSlice.H;
NumColumns = Texture.Width / subImageSlice.W;
}
}
}

View File

@ -1,19 +0,0 @@
using Microsoft.Xna.Framework;
namespace Kav
{
public struct UVData
{
public Vector2 Offset { get; }
public Vector2 Percentage { get; }
public UVData(
Vector2 positionInAtlas,
Vector2 subTextureDimensions,
Vector2 atlasDimensions
) {
Percentage = subTextureDimensions / atlasDimensions;
Offset = positionInAtlas / atlasDimensions;
}
}
}

View File

@ -1,59 +0,0 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
public class DirectionalShadowMapData
{
public static readonly int MAX_SHADOW_CASCADES = 4;
public RenderTarget2D[] ShadowMaps { get; }
public Matrix[] LightSpaceViews { get; }
public Matrix[] LightSpaceProjections { get; }
public float[] CascadeFarPlanes { get; }
public int ShadowMapSize { get; }
public int NumShadowCascades { get; }
internal DirectionalShadowMapData(
GraphicsDevice graphicsDevice,
int shadowMapSize,
int numCascades
) {
ShadowMapSize = shadowMapSize;
NumShadowCascades = (int)MathHelper.Clamp(numCascades, 1, MAX_SHADOW_CASCADES);
LightSpaceViews = new Matrix[4];
LightSpaceProjections = new Matrix[4];
ShadowMaps = new RenderTarget2D[NumShadowCascades];
for (var i = 0; i < NumShadowCascades; i++)
{
ShadowMaps[i] = new RenderTarget2D(
graphicsDevice,
shadowMapSize,
shadowMapSize,
false,
SurfaceFormat.Single,
DepthFormat.Depth24,
0,
RenderTargetUsage.PreserveContents
);
}
CascadeFarPlanes = new float[MAX_SHADOW_CASCADES];
}
public void Clear(GraphicsDevice graphicsDevice)
{
foreach (var shadowMap in ShadowMaps)
{
graphicsDevice.SetRenderTarget(shadowMap);
graphicsDevice.Clear(Color.White);
}
}
}
}

View File

@ -1,9 +0,0 @@
using Microsoft.Xna.Framework;
namespace Kav
{
public interface IHasTranslation
{
Vector3 Translation { get; set; }
}
}

View File

@ -1,9 +0,0 @@
using Microsoft.Xna.Framework;
namespace Kav
{
public interface IHasWorldMatrix
{
Matrix World { get; set; }
}
}

View File

@ -74,6 +74,32 @@ namespace Kav
); );
} }
protected DeferredPBREffect(DeferredPBREffect cloneSource) : base(cloneSource)
{
GPosition = cloneSource.GPosition;
GAlbedo = cloneSource.GAlbedo;
GNormal = cloneSource.GNormal;
GMetallicRoughness = cloneSource.GMetallicRoughness;
EyePosition = cloneSource.EyePosition;
PointLights = new PointLightCollection(
Parameters["LightPositions"],
Parameters["PositionLightColors"],
MaxPointLights
);
for (int i = 0; i < MaxPointLights; i++)
{
PointLights[i] = cloneSource.PointLights[i];
}
}
public override Effect Clone()
{
return new DeferredPBREffect(this);
}
protected override void OnApply() protected override void OnApply()
{ {
gPositionParam.SetValue(GPosition); gPositionParam.SetValue(GPosition);

View File

@ -6,7 +6,8 @@ namespace Kav
public class DeferredPBR_GBufferEffect : Effect, TransformEffect public class DeferredPBR_GBufferEffect : Effect, TransformEffect
{ {
EffectParameter worldParam; EffectParameter worldParam;
EffectParameter viewProjectionParam; EffectParameter worldViewProjectionParam;
EffectParameter worldInverseTransposeParam;
EffectParameter albedoTextureParam; EffectParameter albedoTextureParam;
EffectParameter normalTextureParam; EffectParameter normalTextureParam;
@ -16,13 +17,6 @@ namespace Kav
EffectParameter metallicParam; EffectParameter metallicParam;
EffectParameter roughnessParam; EffectParameter roughnessParam;
EffectParameter uvOffsetAndDimensionsParam;
EffectParameter isSpriteParam;
EffectParameter numTextureRowsParam;
EffectParameter numTextureColumnsParam;
EffectParameter vertexShaderIndexParam;
EffectParameter shaderIndexParam; EffectParameter shaderIndexParam;
Matrix world = Matrix.Identity; Matrix world = Matrix.Identity;
@ -33,18 +27,9 @@ namespace Kav
float metallic; float metallic;
float roughness; float roughness;
Vector2 uvOffset;
Vector2 subTextureDimensions;
bool isSprite = false;
int numTextureRows = 1;
int numTextureColumns = 1;
bool albedoTextureEnabled = false; bool albedoTextureEnabled = false;
bool metallicRoughnessMapEnabled = false; bool metallicRoughnessMapEnabled = false;
bool normalMapEnabled = false; bool normalMapEnabled = false;
bool hardwareInstancingEnabled = false;
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
@ -54,7 +39,7 @@ namespace Kav
set set
{ {
world = value; world = value;
dirtyFlags |= EffectDirtyFlags.World; dirtyFlags |= EffectDirtyFlags.World | EffectDirtyFlags.WorldViewProj;
} }
} }
@ -64,7 +49,7 @@ namespace Kav
set set
{ {
view = value; view = value;
dirtyFlags |= EffectDirtyFlags.ViewProj | EffectDirtyFlags.EyePosition; dirtyFlags |= EffectDirtyFlags.WorldViewProj | EffectDirtyFlags.EyePosition;
} }
} }
@ -74,7 +59,7 @@ namespace Kav
set set
{ {
projection = value; projection = value;
dirtyFlags |= EffectDirtyFlags.ViewProj; dirtyFlags |= EffectDirtyFlags.WorldViewProj;
} }
} }
@ -115,7 +100,7 @@ namespace Kav
{ {
albedoTextureParam.SetValue(value); albedoTextureParam.SetValue(value);
albedoTextureEnabled = value != null; albedoTextureEnabled = value != null;
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; dirtyFlags |= EffectDirtyFlags.ShaderIndex;
} }
} }
@ -126,7 +111,7 @@ namespace Kav
{ {
normalTextureParam.SetValue(value); normalTextureParam.SetValue(value);
normalMapEnabled = value != null; normalMapEnabled = value != null;
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; dirtyFlags |= EffectDirtyFlags.ShaderIndex;
} }
} }
@ -137,70 +122,7 @@ namespace Kav
{ {
metallicRoughnessTextureParam.SetValue(value); metallicRoughnessTextureParam.SetValue(value);
metallicRoughnessMapEnabled = value != null; metallicRoughnessMapEnabled = value != null;
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; dirtyFlags |= EffectDirtyFlags.ShaderIndex;
}
}
public int NumTextureRows
{
get { return numTextureRows; }
set
{
numTextureRows = value;
numTextureRowsParam.SetValue(numTextureRows);
}
}
public int NumTextureColumns
{
get { return numTextureColumns; }
set
{
numTextureColumns = value;
numTextureColumnsParam.SetValue(numTextureColumns);
}
}
public Vector2 UVOffset
{
get { return uvOffset; }
set
{
uvOffset = value;
dirtyFlags |= EffectDirtyFlags.UVOrDimensions;
}
}
public Vector2 SubTextureDimensions
{
get { return subTextureDimensions; }
set
{
subTextureDimensions = value;
dirtyFlags |= EffectDirtyFlags.UVOrDimensions;
}
}
public bool IsSprite
{
get { return isSprite; }
set
{
isSprite = value;
isSpriteParam.SetValue(isSprite ? 1f : 0f);
}
}
public bool HardwareInstancingEnabled
{
get { return hardwareInstancingEnabled; }
set
{
if (value != hardwareInstancingEnabled)
{
hardwareInstancingEnabled = value;
dirtyFlags |= EffectDirtyFlags.VertexShaderIndex;
}
} }
} }
@ -237,40 +159,30 @@ namespace Kav
{ {
worldParam.SetValue(world); worldParam.SetValue(world);
Matrix.Invert(ref world, out Matrix worldInverse);
Matrix.Transpose(ref worldInverse, out Matrix worldInverseTranspose);
worldInverseTransposeParam.SetValue(worldInverseTranspose);
dirtyFlags &= ~EffectDirtyFlags.World; dirtyFlags &= ~EffectDirtyFlags.World;
} }
if ((dirtyFlags & EffectDirtyFlags.ViewProj) != 0) if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0)
{ {
Matrix.Multiply(ref view, ref projection, out Matrix viewProj); Matrix.Multiply(ref world, ref view, out Matrix worldView);
viewProjectionParam.SetValue(viewProj); Matrix.Multiply(ref worldView, ref projection, out Matrix worldViewProj);
worldViewProjectionParam.SetValue(worldViewProj);
dirtyFlags &= ~EffectDirtyFlags.ViewProj; dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
} }
if ((dirtyFlags & EffectDirtyFlags.UVOrDimensions) != 0) if ((dirtyFlags & EffectDirtyFlags.EyePosition) != 0)
{ {
uvOffsetAndDimensionsParam.SetValue(new Vector4( Matrix.Invert(ref view, out Matrix inverseView);
UVOffset.X, UVOffset.Y,
SubTextureDimensions.X, SubTextureDimensions.Y
));
dirtyFlags &= ~EffectDirtyFlags.UVOrDimensions; dirtyFlags &= ~EffectDirtyFlags.EyePosition;
} }
if ((dirtyFlags & EffectDirtyFlags.VertexShaderIndex) != 0) if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0)
{
int vertexShaderIndex = 0;
if (hardwareInstancingEnabled)
{
vertexShaderIndex = 1;
}
vertexShaderIndexParam.SetValue(vertexShaderIndex);
}
if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0)
{ {
int shaderIndex = 0; int shaderIndex = 0;
@ -305,14 +217,15 @@ namespace Kav
shaderIndexParam.SetValue(shaderIndex); shaderIndexParam.SetValue(shaderIndex);
dirtyFlags &= ~EffectDirtyFlags.PixelShaderIndex; dirtyFlags &= ~EffectDirtyFlags.ShaderIndex;
} }
} }
void CacheEffectParameters() void CacheEffectParameters()
{ {
worldParam = Parameters["World"]; worldParam = Parameters["World"];
viewProjectionParam = Parameters["ViewProjection"]; worldViewProjectionParam = Parameters["WorldViewProjection"];
worldInverseTransposeParam = Parameters["WorldInverseTranspose"];
albedoTextureParam = Parameters["AlbedoTexture"]; albedoTextureParam = Parameters["AlbedoTexture"];
normalTextureParam = Parameters["NormalTexture"]; normalTextureParam = Parameters["NormalTexture"];
@ -322,14 +235,7 @@ namespace Kav
metallicParam = Parameters["MetallicValue"]; metallicParam = Parameters["MetallicValue"];
roughnessParam = Parameters["RoughnessValue"]; roughnessParam = Parameters["RoughnessValue"];
numTextureRowsParam = Parameters["NumTextureRows"]; shaderIndexParam = Parameters["ShaderIndex"];
numTextureColumnsParam = Parameters["NumTextureColumns"];
uvOffsetAndDimensionsParam = Parameters["UVOffsetAndDimensions"];
isSpriteParam = Parameters["IsSprite"];
shaderIndexParam = Parameters["PixelShaderIndex"];
vertexShaderIndexParam = Parameters["VertexShaderIndex"];
} }
} }
} }

View File

@ -18,8 +18,6 @@ namespace Kav
EffectParameter farPlaneParam; EffectParameter farPlaneParam;
EffectParameter worldViewProjectionParam;
public Texture2D GPosition { get; set; } public Texture2D GPosition { get; set; }
public Texture2D GAlbedo { get; set; } public Texture2D GAlbedo { get; set; }
public Texture2D GNormal { get; set; } public Texture2D GNormal { get; set; }
@ -33,42 +31,6 @@ namespace Kav
public float FarPlane { get; set; } public float FarPlane { get; set; }
Matrix world = Matrix.Identity;
Matrix view = Matrix.Identity;
Matrix projection = Matrix.Identity;
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
public Matrix World
{
get { return world; }
set
{
world = value;
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
}
}
public Matrix View
{
get { return view; }
set
{
view = value;
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
}
}
public Matrix Projection
{
get { return projection; }
set
{
projection = value;
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
}
}
public DeferredPBR_PointLightEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DeferredPBR_PointLightEffect) public DeferredPBR_PointLightEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DeferredPBR_PointLightEffect)
{ {
CacheEffectParameters(); CacheEffectParameters();
@ -77,7 +39,7 @@ namespace Kav
public DeferredPBR_PointLightEffect(DeferredPBR_PointLightEffect cloneSource) : base(cloneSource) public DeferredPBR_PointLightEffect(DeferredPBR_PointLightEffect cloneSource) : base(cloneSource)
{ {
CacheEffectParameters(); CacheEffectParameters();
GPosition = cloneSource.GPosition; GPosition = cloneSource.GPosition;
GAlbedo = cloneSource.GAlbedo; GAlbedo = cloneSource.GAlbedo;
GNormal = cloneSource.GNormal; GNormal = cloneSource.GNormal;
@ -111,13 +73,6 @@ namespace Kav
pointLightColorParam.SetValue(PointLightColor); pointLightColorParam.SetValue(PointLightColor);
farPlaneParam.SetValue(FarPlane); farPlaneParam.SetValue(FarPlane);
if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0)
{
worldViewProjectionParam.SetValue(world * view * projection);
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
}
} }
void CacheEffectParameters() void CacheEffectParameters()
@ -134,8 +89,6 @@ namespace Kav
pointLightColorParam = Parameters["PointLightColor"]; pointLightColorParam = Parameters["PointLightColor"];
farPlaneParam = Parameters["FarPlane"]; farPlaneParam = Parameters["FarPlane"];
worldViewProjectionParam = Parameters["WorldViewProjection"];
} }
} }
} }

View File

@ -1,210 +0,0 @@
using Kav.Data;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
public class DiffuseLitSpriteEffect : Effect
{
EffectParameter ambientColorParam;
EffectParameter directionalLightDirectionParam;
EffectParameter directionalLightColorParam;
EffectParameter uvOffsetAndDimensionsParam;
EffectParameter worldParam;
EffectParameter worldViewProjectionParam;
EffectParameter worldInverseTransposeParam;
EffectParameter shaderIndexParam;
Texture2D texture;
Texture2D normal;
bool normalMapEnabled = false;
Vector3 ambientColor;
Vector3 directionalLightDirection;
Vector3 directionalLightColor;
Matrix world = Matrix.Identity;
Matrix view = Matrix.Identity;
Matrix projection = Matrix.Identity;
Vector2 uvOffset;
Vector2 subTextureDimensions;
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
public bool NormalMapEnabled
{
get { return normalMapEnabled; }
set
{
if (normalMapEnabled != value)
{
normalMapEnabled = value;
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex;
}
}
}
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 Vector2 UVOffset
{
get { return uvOffset; }
set
{
uvOffset = value;
dirtyFlags |= EffectDirtyFlags.UVOrDimensions;
}
}
public Vector2 SubTextureDimensions
{
get { return subTextureDimensions; }
set
{
subTextureDimensions = value;
dirtyFlags |= EffectDirtyFlags.UVOrDimensions;
}
}
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;
}
if ((dirtyFlags & EffectDirtyFlags.UVOrDimensions) != 0)
{
uvOffsetAndDimensionsParam.SetValue(new Vector4(
UVOffset.X, UVOffset.Y,
SubTextureDimensions.X, SubTextureDimensions.Y
));
dirtyFlags &= ~EffectDirtyFlags.UVOrDimensions;
}
if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0)
{
int shaderIndex = 0;
if (normalMapEnabled)
{
shaderIndex = 1;
}
shaderIndexParam.SetValue(shaderIndex);
}
}
private void CacheEffectParameters()
{
worldParam = Parameters["World"];
worldViewProjectionParam = Parameters["WorldViewProjection"];
worldInverseTransposeParam = Parameters["WorldInverseTranspose"];
ambientColorParam = Parameters["AmbientColor"];
directionalLightDirectionParam = Parameters["DirectionalLightDirection"];
directionalLightColorParam = Parameters["DirectionalLightColor"];
uvOffsetAndDimensionsParam = Parameters["UVOffsetAndDimensions"];
shaderIndexParam = Parameters["ShaderIndex"];
}
}
}

View File

@ -8,10 +8,7 @@ namespace Kav
WorldViewProj = 1, WorldViewProj = 1,
World = 2, World = 2,
EyePosition = 4, EyePosition = 4,
VertexShaderIndex = 8, ShaderIndex = 8,
PixelShaderIndex = 16,
ViewProj = 32,
UVOrDimensions = 64,
All = -1 All = -1
} }
} }

BIN
Effects/FXB/DeferredPBR_GBufferEffect.fxb (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Effects/FXB/DiffuseLitSpriteEffect.fxb (Stored with Git LFS)

Binary file not shown.

BIN
Effects/FXB/LinearDepthEffectInstanced.fxb (Stored with Git LFS)

Binary file not shown.

BIN
Effects/FXB/PaletteCrushEffect.fxb (Stored with Git LFS)

Binary file not shown.

BIN
Effects/FXB/SimpleDepthEffect.fxb (Stored with Git LFS)

Binary file not shown.

BIN
Effects/FXB/SimpleDepthEffectInstanced.fxb (Stored with Git LFS)

Binary file not shown.

View File

@ -4,22 +4,17 @@ DECLARE_TEXTURE(AlbedoTexture, 0);
DECLARE_TEXTURE(NormalTexture, 1); DECLARE_TEXTURE(NormalTexture, 1);
DECLARE_TEXTURE(MetallicRoughnessTexture, 2); DECLARE_TEXTURE(MetallicRoughnessTexture, 2);
float4 UVOffsetAndDimensions;
float IsSprite;
BEGIN_CONSTANTS BEGIN_CONSTANTS
float3 AlbedoValue _ps(c0) _cb(c0); float3 AlbedoValue _ps(c0) _cb(c0);
float MetallicValue _ps(c1) _cb(c1); float MetallicValue _ps(c1) _cb(c1);
float RoughnessValue _ps(c2) _cb(c2); float RoughnessValue _ps(c2) _cb(c2);
int NumTextureRows _vs(c9) _cb(c3);
int NumTextureColumns _vs(c10) _cb(c4);
MATRIX_CONSTANTS MATRIX_CONSTANTS
float4x4 World _vs(c0) _cb(c7); float4x4 World _vs(c0) _cb(c7);
float4x4 ViewProjection _vs(c4) _cb(c11); float4x4 WorldInverseTranspose _vs(c4) _cb(c11);
float4x4 WorldViewProjection _vs(c8) _cb(c15);
END_CONSTANTS END_CONSTANTS
@ -27,7 +22,7 @@ struct VertexInput
{ {
float4 Position : POSITION; float4 Position : POSITION;
float3 Normal : NORMAL; float3 Normal : NORMAL;
float2 TexCoord : TEXCOORD; float2 TexCoord : TEXCOORD0;
}; };
struct PixelInput struct PixelInput
@ -53,44 +48,9 @@ PixelInput main_vs(VertexInput input)
PixelInput output; PixelInput output;
output.PositionWorld = mul(input.Position, World).xyz; output.PositionWorld = mul(input.Position, World).xyz;
output.NormalWorld = normalize(mul(input.Normal, World)); output.NormalWorld = mul(input.Normal, (float3x3)WorldInverseTranspose).xyz;
output.TexCoord = input.TexCoord;
float2 texCoord; output.Position = mul(input.Position, WorldViewProjection);
texCoord.x = (input.TexCoord.x * UVOffsetAndDimensions.z) + UVOffsetAndDimensions.x;
texCoord.y = (input.TexCoord.y * UVOffsetAndDimensions.w) + UVOffsetAndDimensions.y;
output.TexCoord = texCoord;
float4x4 worldViewProjection = mul(World, ViewProjection);
output.Position = mul(input.Position, worldViewProjection);
return output;
}
PixelInput instanced_vs(
VertexInput input,
float3 Translation : TEXCOORD2,
float2 UVOffset : TEXCOORD5
) {
PixelInput output;
float4x4 world = float4x4(
float4(1, 0, 0, 0),
float4(0, 1, 0, 0),
float4(0, 0, 1, 0),
float4(Translation.x, Translation.y, Translation.z, 1)
);
float4x4 worldViewProjection = mul(world, ViewProjection);
output.PositionWorld = mul(input.Position, world);
output.NormalWorld = mul(input.Normal, world);
float2 texCoord;
texCoord.x = (input.TexCoord.x / NumTextureColumns + UVOffset.x);
texCoord.y = (input.TexCoord.y / NumTextureRows + UVOffset.y);
output.TexCoord = texCoord;
output.Position = mul(input.Position, worldViewProjection);
return output; return output;
} }
@ -120,7 +80,7 @@ PixelOutput NonePS(PixelInput input)
PixelOutput output; PixelOutput output;
output.gPosition = float4(input.PositionWorld, 1.0); output.gPosition = float4(input.PositionWorld, 1.0);
output.gNormal = float4(normalize(input.NormalWorld), IsSprite); output.gNormal = float4(normalize(input.NormalWorld), 1.0);
output.gAlbedo = float4(AlbedoValue, 1.0); output.gAlbedo = float4(AlbedoValue, 1.0);
output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0); output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0);
@ -132,12 +92,10 @@ PixelOutput AlbedoPS(PixelInput input)
PixelOutput output; PixelOutput output;
output.gPosition = float4(input.PositionWorld, 1.0); output.gPosition = float4(input.PositionWorld, 1.0);
output.gNormal = float4(normalize(input.NormalWorld), IsSprite); output.gNormal = float4(normalize(input.NormalWorld), 1.0);
output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord); output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord);
output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0); output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0);
if (output.gAlbedo.a == 0.0) { discard; }
return output; return output;
} }
@ -146,7 +104,7 @@ PixelOutput MetallicRoughnessPS(PixelInput input)
PixelOutput output; PixelOutput output;
output.gPosition = float4(input.PositionWorld, 1.0); output.gPosition = float4(input.PositionWorld, 1.0);
output.gNormal = float4(normalize(input.NormalWorld), IsSprite); output.gNormal = float4(normalize(input.NormalWorld), 1.0);
output.gAlbedo = float4(AlbedoValue, 1.0); output.gAlbedo = float4(AlbedoValue, 1.0);
output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord); output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord);
@ -158,7 +116,7 @@ PixelOutput NormalPS(PixelInput input)
PixelOutput output; PixelOutput output;
output.gPosition = float4(input.PositionWorld, 1.0); output.gPosition = float4(input.PositionWorld, 1.0);
output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), IsSprite); output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), 1.0);
output.gAlbedo = float4(AlbedoValue, 1.0); output.gAlbedo = float4(AlbedoValue, 1.0);
output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0); output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0);
@ -170,12 +128,10 @@ PixelOutput AlbedoMetallicRoughnessPS(PixelInput input)
PixelOutput output; PixelOutput output;
output.gPosition = float4(input.PositionWorld, 1.0); output.gPosition = float4(input.PositionWorld, 1.0);
output.gNormal = float4(normalize(input.NormalWorld), IsSprite); output.gNormal = float4(normalize(input.NormalWorld), 1.0);
output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord); output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord);
output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord); output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord);
if (output.gAlbedo.a == 0.0) { discard; }
return output; return output;
} }
@ -184,12 +140,10 @@ PixelOutput AlbedoNormalPS(PixelInput input)
PixelOutput output; PixelOutput output;
output.gPosition = float4(input.PositionWorld, 1.0); output.gPosition = float4(input.PositionWorld, 1.0);
output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), IsSprite); output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), 1.0);
output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord); output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord);
output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0); output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0);
if (output.gAlbedo.a == 0.0) { discard; }
return output; return output;
} }
@ -198,7 +152,7 @@ PixelOutput MetallicRoughnessNormalPS(PixelInput input)
PixelOutput output; PixelOutput output;
output.gPosition = float4(input.PositionWorld, 1.0); output.gPosition = float4(input.PositionWorld, 1.0);
output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), IsSprite); output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), 1.0);
output.gAlbedo = float4(AlbedoValue, 1.0); output.gAlbedo = float4(AlbedoValue, 1.0);
output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord); output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord);
@ -210,28 +164,13 @@ PixelOutput AlbedoMetallicRoughnessNormalMapPS(PixelInput input)
PixelOutput output; PixelOutput output;
output.gPosition = float4(input.PositionWorld, 1.0); output.gPosition = float4(input.PositionWorld, 1.0);
output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), IsSprite); output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), 1.0);
output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord); output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord);
output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord); output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord);
if (output.gAlbedo.a == 0.0) { discard; }
return output; return output;
} }
VertexShader VSArray[2] =
{
compile vs_3_0 main_vs(),
compile vs_3_0 instanced_vs()
};
int VSIndices[2] =
{
0, 1
};
int VertexShaderIndex = 0;
PixelShader PSArray[8] = PixelShader PSArray[8] =
{ {
compile ps_3_0 NonePS(), compile ps_3_0 NonePS(),
@ -252,13 +191,13 @@ int PSIndices[8] =
0, 1, 2, 3, 4, 5, 6, 7 0, 1, 2, 3, 4, 5, 6, 7
}; };
int PixelShaderIndex = 0; int ShaderIndex = 0;
Technique GBuffer Technique GBuffer
{ {
Pass Pass
{ {
VertexShader = (VSArray[VSIndices[VertexShaderIndex]]); VertexShader = compile vs_3_0 main_vs();
PixelShader = (PSArray[PSIndices[PixelShaderIndex]]); PixelShader = (PSArray[PSIndices[ShaderIndex]]);
} }
} }

View File

@ -1,7 +1,5 @@
// Assumes you are drawing a sphere!!
#include "Macros.fxh" //from FNA #include "Macros.fxh" //from FNA
#include "Lighting.fxh" #include "Lighting.fxh"
#include "Shadow.fxh" #include "Shadow.fxh"
DECLARE_TEXTURE(gPosition, 0); DECLARE_TEXTURE(gPosition, 0);
@ -13,7 +11,7 @@ DECLARE_CUBEMAP(shadowMap, 4);
BEGIN_CONSTANTS BEGIN_CONSTANTS
float3 EyePosition _ps(c0) _cb(c0); float3 EyePosition _ps(c0) _cb(c0);
float3 PointLightPosition _ps(c1) _cb(c1); float3 PointLightPosition _ps(c1) _cb(c1);
float3 PointLightColor _ps(c2) _cb(c2); float3 PointLightColor _ps(c2) _cb(c2);
@ -21,28 +19,27 @@ BEGIN_CONSTANTS
MATRIX_CONSTANTS MATRIX_CONSTANTS
float4x4 WorldViewProjection _vs(c0) _cb(c4);
END_CONSTANTS END_CONSTANTS
struct VertexInput struct VertexInput
{ {
float4 Position : POSITION; float4 Position : POSITION;
float2 TexCoord : TEXCOORD;
}; };
struct PixelInput struct PixelInput
{ {
float4 Position : SV_POSITION; float4 Position : SV_POSITION;
float4 ScreenPosition : TEXCOORD0; float2 TexCoord : TEXCOORD0;
}; };
PixelInput main_vs(VertexInput input) PixelInput main_vs(VertexInput input)
{ {
PixelInput output; PixelInput output;
output.Position = mul(input.Position, WorldViewProjection); output.Position = input.Position;
output.ScreenPosition = output.Position; output.TexCoord = input.TexCoord;
return output; return output;
} }
@ -76,36 +73,18 @@ float4 ComputeColor(
float4 main_ps(PixelInput input) : SV_TARGET0 float4 main_ps(PixelInput input) : SV_TARGET0
{ {
input.ScreenPosition.xy /= input.ScreenPosition.w; float3 worldPosition = SAMPLE_TEXTURE(gPosition, input.TexCoord).rgb;
float2 texCoord = 0.5f * float2(input.ScreenPosition.x,-input.ScreenPosition.y) + 0.5f; 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 worldPosition = SAMPLE_TEXTURE(gPosition, texCoord).rgb; return ComputeColor(
float4 normalSample = SAMPLE_TEXTURE(gNormal, texCoord); worldPosition,
float3 normal = normalSample.xyz; normal,
float isSprite = normalSample.a; albedo,
float3 albedo = SAMPLE_TEXTURE(gAlbedo, texCoord).rgb; metallicRoughness.r,
float2 metallicRoughness = SAMPLE_TEXTURE(gMetallicRoughness, texCoord).rg; metallicRoughness.g
);
if (isSprite == 1.0)
{
float3 lightDir = PointLightPosition - worldPosition;
float3 L = normalize(lightDir);
float distance = length(lightDir);
float attenuation = 1.0 / (distance * distance);
float3 radiance = PointLightColor * attenuation;
return float4(albedo * radiance * 0.1, 1.0);
}
else
{
return ComputeColor(
worldPosition,
normal,
albedo,
metallicRoughness.r,
metallicRoughness.g
);
}
} }
Technique DeferredPBR_Point Technique DeferredPBR_Point

View File

@ -1,140 +0,0 @@
#include "Macros.fxh" //from FNA
// Effect applies normalmapped lighting to a 2D sprite.
DECLARE_TEXTURE(Texture, 0);
DECLARE_TEXTURE(Normal, 1);
float3 AmbientColor;
float3 PointLightPositions[8];
float3 PointLightColors[8];
float3 DirectionalLightDirection;
float3 DirectionalLightColor;
float4 UVOffsetAndDimensions;
float4x4 WorldInverseTranspose;
float4x4 World;
float4x4 WorldViewProjection;
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.NormalWS = normalize(mul(input.Normal, (float3x3)WorldInverseTranspose));
output.PositionWS = mul(input.Position, World).xyz;
float2 texCoord;
texCoord.x = (input.TexCoord.x * UVOffsetAndDimensions.z) + UVOffsetAndDimensions.x;
texCoord.y = (input.TexCoord.y * UVOffsetAndDimensions.w) + UVOffsetAndDimensions.y;
output.TexCoord = texCoord;
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);
if (tex.a == 0.0) { discard; }
float3 normalWS = normalize(input.NormalWS);
return tex * LightColor(input.PositionWS, normalWS);
}
float4 WithNormalMap(PixelShaderInput input) : COLOR0
{
float4 tex = SAMPLE_TEXTURE(Texture, input.TexCoord);
if (tex.a == 0.0) { discard; }
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]]);
}
}

View File

@ -1,55 +0,0 @@
#include "Macros.fxh"
BEGIN_CONSTANTS
float4x4 ViewProjection _vs(c4) _cb(c4);
float3 LightPosition _ps(c0) _cb(c8);
float FarPlane _ps(c1) _cb(c9);
END_CONSTANTS
struct VertexShaderInput
{
float4 Position : POSITION;
};
struct VertexShaderOutput
{
float4 Position : SV_Position;
float3 PositionWorld : TEXCOORD0;
};
VertexShaderOutput instanced_vs(VertexShaderInput input, float3 Translation : TEXCOORD2)
{
VertexShaderOutput output;
float4x4 world = float4x4(
float4(1, 0, 0, 0),
float4(0, 1, 0, 0),
float4(0, 0, 1, 0),
float4(Translation.x, Translation.y, Translation.z, 1)
);
float4x4 worldViewProjection = mul(world, ViewProjection);
output.Position = mul(input.Position, worldViewProjection);
output.Position.x *= -1; // otherwise cube map render will be horizontally flipped
output.PositionWorld = mul(input.Position, world);
return output;
}
float4 main_ps(VertexShaderOutput input) : SV_TARGET0
{
float lightDistance = length(input.PositionWorld - LightPosition);
lightDistance /= FarPlane;
return float4(lightDistance, 0.0, 0.0, 0.0);
}
Technique SimpleDepth
{
Pass
{
VertexShader = compile vs_3_0 instanced_vs();
PixelShader = compile ps_3_0 main_ps();
}
}

View File

@ -1,65 +0,0 @@
#include "Macros.fxh"
DECLARE_TEXTURE(Texture, 0);
DECLARE_TEXTURE(Palette, 1);
BEGIN_CONSTANTS
int PaletteWidth _ps(c0) _cb(c0);
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
{
float4 sampled = SAMPLE_TEXTURE(Texture, input.TexCoord);
float3 sampled_color = sampled.rgb;
float3 closest_color = float3(0, 0, 0);
float closest_dist = 100000;
for (int i = 0; i < PaletteWidth; i++)
{
float texX = (i / (float)PaletteWidth);
float3 palette_color = SAMPLE_TEXTURE(Palette, float2(texX, 0));
float dist = distance(palette_color, sampled_color);
if (dist < closest_dist)
{
closest_dist = dist;
closest_color = palette_color;
}
}
return float4(closest_color, sampled.a);
}
Technique PaletteCrush
{
Pass
{
VertexShader = compile vs_3_0 main_vs();
PixelShader = compile ps_3_0 main_ps();
}
}

View File

@ -2,10 +2,9 @@
BEGIN_CONSTANTS BEGIN_CONSTANTS
MATRIX_CONSTANTS float4x4 ModelViewProjection _vs(c0) _cb(c0);
float4x4 World _vs(c0) _cb(c0); MATRIX_CONSTANTS
float4x4 ViewProjection _vs(c4) _cb(c4);
END_CONSTANTS END_CONSTANTS
@ -16,7 +15,7 @@ struct VertexShaderInput
struct VertexShaderOutput struct VertexShaderOutput
{ {
float4 Position : SV_POSITION; float4 Position : SV_Position;
float Depth : TEXCOORD0; float Depth : TEXCOORD0;
}; };
@ -24,8 +23,7 @@ VertexShaderOutput main_vs(VertexShaderInput input)
{ {
VertexShaderOutput output; VertexShaderOutput output;
float4x4 worldViewProjection = mul(World, ViewProjection); output.Position = mul(input.Position, ModelViewProjection);
output.Position = mul(input.Position, worldViewProjection);
output.Depth = output.Position.z / output.Position.w; output.Depth = output.Position.z / output.Position.w;
return output; return output;

View File

@ -1,45 +0,0 @@
float4x4 ViewProjection;
struct VertexShaderInput
{
float4 Position : POSITION;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float4 ProjectedPosition : TEXCOORD0;
};
VertexShaderOutput instanced_vs(VertexShaderInput input, float3 Translation : TEXCOORD2)
{
VertexShaderOutput output;
float4x4 world = float4x4(
float4(1, 0, 0, 0),
float4(0, 1, 0, 0),
float4(0, 0, 1, 0),
float4(Translation.x, Translation.y, Translation.z, 1)
);
float4x4 worldViewProjection = mul(world, ViewProjection);
output.Position = mul(input.Position, worldViewProjection);
output.ProjectedPosition = output.Position;
return output;
}
float4 main_ps(VertexShaderOutput input) : COLOR0
{
return float4(input.ProjectedPosition.z / input.ProjectedPosition.w, 0.0, 0.0, 0.0);
}
Technique SimpleDepth
{
Pass
{
VertexShader = compile vs_3_0 instanced_vs();
PixelShader = compile ps_3_0 main_ps();
}
}

View File

@ -3,28 +3,28 @@ using Microsoft.Xna.Framework.Graphics;
namespace Kav namespace Kav
{ {
public class LinearDepthEffect : Effect, IHasWorldMatrix public class LinearDepthEffect : Effect
{ {
EffectParameter worldParam; EffectParameter modelParam;
EffectParameter worldViewProjectionParam; EffectParameter modelViewProjectionParam;
EffectParameter lightPositionParam; EffectParameter lightPositionParam;
EffectParameter farPlaneParam; EffectParameter farPlaneParam;
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
Matrix world; Matrix model;
Matrix view; Matrix view;
Matrix projection; Matrix projection;
public Vector3 LightPosition { get; set; } public Vector3 LightPosition { get; set; }
public float FarPlane { get; set; } public float FarPlane { get; set; }
public Matrix World public Matrix Model
{ {
get { return world; } get { return model; }
set set
{ {
world = value; model = value;
dirtyFlags |= EffectDirtyFlags.World; dirtyFlags |= EffectDirtyFlags.World;
dirtyFlags |= EffectDirtyFlags.WorldViewProj; dirtyFlags |= EffectDirtyFlags.WorldViewProj;
} }
@ -60,16 +60,16 @@ namespace Kav
if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0) if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0)
{ {
Matrix.Multiply(ref view, ref projection, out Matrix viewProjection); Matrix.Multiply(ref view, ref projection, out Matrix viewProjection);
Matrix.Multiply(ref world, ref viewProjection, out Matrix worldViewProj); Matrix.Multiply(ref model, ref viewProjection, out Matrix worldViewProj);
worldViewProjectionParam.SetValue(worldViewProj); modelViewProjectionParam.SetValue(worldViewProj);
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj; dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
} }
if ((dirtyFlags & EffectDirtyFlags.World) != 0) if ((dirtyFlags & EffectDirtyFlags.World) != 0)
{ {
worldParam.SetValue(world); modelParam.SetValue(model);
dirtyFlags &= ~EffectDirtyFlags.World; dirtyFlags &= ~EffectDirtyFlags.World;
} }
@ -80,8 +80,8 @@ namespace Kav
private void CacheEffectParameters() private void CacheEffectParameters()
{ {
worldParam = Parameters["Model"]; modelParam = Parameters["Model"];
worldViewProjectionParam = Parameters["ModelViewProjection"]; modelViewProjectionParam = Parameters["ModelViewProjection"];
lightPositionParam = Parameters["LightPosition"]; lightPositionParam = Parameters["LightPosition"];
farPlaneParam = Parameters["FarPlane"]; farPlaneParam = Parameters["FarPlane"];

View File

@ -1,67 +0,0 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
public class LinearDepthEffectInstanced : Effect
{
EffectParameter viewProjectionParam;
EffectParameter lightPositionParam;
EffectParameter farPlaneParam;
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
Matrix view;
Matrix projection;
public Vector3 LightPosition { get; set; }
public float FarPlane { get; set; }
public Matrix View
{
get { return view; }
set
{
view = value;
dirtyFlags |= EffectDirtyFlags.ViewProj;
}
}
public Matrix Projection
{
get { return projection; }
set
{
projection = value;
dirtyFlags |= EffectDirtyFlags.ViewProj;
}
}
public LinearDepthEffectInstanced(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.LinearDepthEffectInstanced)
{
CacheEffectParameters();
}
protected override void OnApply()
{
if ((dirtyFlags & EffectDirtyFlags.ViewProj) != 0)
{
Matrix.Multiply(ref view, ref projection, out Matrix viewProjection);
viewProjectionParam.SetValue(viewProjection);
dirtyFlags &= ~EffectDirtyFlags.ViewProj;
}
lightPositionParam.SetValue(LightPosition);
farPlaneParam.SetValue(FarPlane);
}
private void CacheEffectParameters()
{
viewProjectionParam = Parameters["ViewProjection"];
lightPositionParam = Parameters["LightPosition"];
farPlaneParam = Parameters["FarPlane"];
}
}
}

View File

@ -130,7 +130,7 @@ namespace Kav
{ {
albedoTextureParam.SetValue(value); albedoTextureParam.SetValue(value);
albedoTextureEnabled = value != null; albedoTextureEnabled = value != null;
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; dirtyFlags |= EffectDirtyFlags.ShaderIndex;
} }
} }
@ -141,7 +141,7 @@ namespace Kav
{ {
normalTextureParam.SetValue(value); normalTextureParam.SetValue(value);
normalMapEnabled = value != null; normalMapEnabled = value != null;
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; dirtyFlags |= EffectDirtyFlags.ShaderIndex;
} }
} }
@ -164,7 +164,7 @@ namespace Kav
{ {
metallicRoughnessTextureParam.SetValue(value); metallicRoughnessTextureParam.SetValue(value);
metallicRoughnessMapEnabled = value != null; metallicRoughnessMapEnabled = value != null;
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; dirtyFlags |= EffectDirtyFlags.ShaderIndex;
} }
} }
@ -197,6 +197,45 @@ namespace Kav
); );
} }
protected PBREffect(PBREffect cloneSource) : base(cloneSource)
{
CacheEffectParameters();
World = cloneSource.World;
View = cloneSource.View;
Projection = cloneSource.Projection;
PointLights = new PointLightCollection(
Parameters["LightPositions"],
Parameters["PositionLightColors"],
MaxPointLights
);
for (int i = 0; i < MaxPointLights; i++)
{
PointLights[i] = cloneSource.PointLights[i];
}
AlbedoTexture = cloneSource.AlbedoTexture;
NormalTexture = cloneSource.NormalTexture;
EmissionTexture = cloneSource.EmissionTexture;
OcclusionTexture = cloneSource.OcclusionTexture;
MetallicRoughnessTexture = cloneSource.MetallicRoughnessTexture;
EnvDiffuseTexture = cloneSource.EnvDiffuseTexture;
BRDFLutTexture = cloneSource.BRDFLutTexture;
EnvSpecularTexture = cloneSource.EnvSpecularTexture;
Albedo = cloneSource.Albedo;
Metallic = cloneSource.Metallic;
Roughness = cloneSource.Roughness;
AO = cloneSource.AO;
}
public override Effect Clone()
{
return new PBREffect(this);
}
protected override void OnApply() protected override void OnApply()
{ {
if ((dirtyFlags & EffectDirtyFlags.World) != 0) if ((dirtyFlags & EffectDirtyFlags.World) != 0)
@ -227,7 +266,7 @@ namespace Kav
dirtyFlags &= ~EffectDirtyFlags.EyePosition; dirtyFlags &= ~EffectDirtyFlags.EyePosition;
} }
if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0) if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0)
{ {
int shaderIndex = 0; int shaderIndex = 0;
@ -262,7 +301,7 @@ namespace Kav
shaderIndexParam.SetValue(shaderIndex); shaderIndexParam.SetValue(shaderIndex);
dirtyFlags &= ~EffectDirtyFlags.PixelShaderIndex; dirtyFlags &= ~EffectDirtyFlags.ShaderIndex;
} }
} }

View File

@ -1,51 +0,0 @@
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
public class PaletteCrushEffect : Effect
{
EffectParameter textureParam;
EffectParameter paletteParam;
EffectParameter paletteWidthParam;
Texture2D texture;
Texture2D palette;
int paletteWidth;
public Texture2D Texture
{
get { return texture; }
set
{
texture = value;
textureParam.SetValue(texture);
}
}
public Texture2D Palette
{
get { return palette; }
set
{
palette = value;
paletteWidth = palette.Width;
paletteParam.SetValue(palette);
paletteWidthParam.SetValue(paletteWidth);
}
}
public PaletteCrushEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.PaletteCrushEffect)
{
CacheEffectParameters();
}
void CacheEffectParameters()
{
textureParam = Parameters["Texture"];
paletteParam = Parameters["Palette"];
paletteWidthParam = Parameters["PaletteWidth"];
}
}
}

View File

@ -7,24 +7,41 @@ namespace Kav
{ {
private readonly Vector3[] positions; private readonly Vector3[] positions;
private readonly Vector3[] colors; private readonly Vector3[] colors;
private readonly float[] intensities;
readonly EffectParameter lightPositionsParam; readonly EffectParameter lightPositionsParam;
readonly EffectParameter lightColorsParam; readonly EffectParameter lightColorsParam;
public PointLightCollection(EffectParameter lightPositionsParam, EffectParameter lightColorsParam, int maxLights) public PointLightCollection(EffectParameter lightPositionsParam, EffectParameter lightColorsParam, int maxLights)
{ {
positions = new Vector3[maxLights]; this.positions = new Vector3[maxLights];
colors = new Vector3[maxLights]; this.colors = new Vector3[maxLights];
this.intensities = new float[maxLights];
this.lightPositionsParam = lightPositionsParam; this.lightPositionsParam = lightPositionsParam;
this.lightColorsParam = lightColorsParam; this.lightColorsParam = lightColorsParam;
} }
public PointLight this[int i] public PointLight this[int i]
{ {
get
{
var color = colors[i] / intensities[i];
return new PointLight(
positions[i],
new Color(
color.X,
color.Y,
color.Z,
1f
),
intensities[i]
);
}
set set
{ {
positions[i] = value.Position; positions[i] = value.Position;
colors[i] = value.Color.ToVector3() * value.Radius; colors[i] = value.Color.ToVector3() * value.Intensity;
intensities[i] = value.Intensity;
lightPositionsParam.SetValue(positions); lightPositionsParam.SetValue(positions);
lightColorsParam.SetValue(colors); lightColorsParam.SetValue(colors);
} }

View File

@ -3,24 +3,23 @@ using Microsoft.Xna.Framework.Graphics;
namespace Kav namespace Kav
{ {
public class SimpleDepthEffect : Effect, IHasWorldMatrix public class SimpleDepthEffect : Effect
{ {
EffectParameter worldParam; EffectParameter modelViewProjectionParam;
EffectParameter viewProjectionParam;
Matrix world; Matrix model;
Matrix view; Matrix view;
Matrix projection; Matrix projection;
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
public Matrix World public Matrix Model
{ {
get { return world; } get { return model; }
set set
{ {
world = value; model = value;
dirtyFlags |= EffectDirtyFlags.World; dirtyFlags |= EffectDirtyFlags.WorldViewProj;
} }
} }
@ -30,7 +29,7 @@ namespace Kav
set set
{ {
view = value; view = value;
dirtyFlags |= EffectDirtyFlags.ViewProj; dirtyFlags |= EffectDirtyFlags.WorldViewProj;
} }
} }
@ -40,7 +39,7 @@ namespace Kav
set set
{ {
projection = value; projection = value;
dirtyFlags |= EffectDirtyFlags.ViewProj; dirtyFlags |= EffectDirtyFlags.WorldViewProj;
} }
} }
@ -51,26 +50,20 @@ namespace Kav
protected override void OnApply() protected override void OnApply()
{ {
if ((dirtyFlags & EffectDirtyFlags.World) != 0) if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0)
{
worldParam.SetValue(world);
dirtyFlags &= ~EffectDirtyFlags.World;
}
if ((dirtyFlags & EffectDirtyFlags.ViewProj) != 0)
{ {
Matrix.Multiply(ref view, ref projection, out Matrix viewProjection); Matrix.Multiply(ref view, ref projection, out Matrix viewProjection);
viewProjectionParam.SetValue(viewProjection); Matrix.Multiply(ref model, ref viewProjection, out Matrix worldViewProj);
dirtyFlags &= ~EffectDirtyFlags.ViewProj; modelViewProjectionParam.SetValue(worldViewProj);
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
} }
} }
private void CacheEffectParameters() private void CacheEffectParameters()
{ {
worldParam = Parameters["World"]; modelViewProjectionParam = Parameters["ModelViewProjection"];
viewProjectionParam = Parameters["ViewProjection"];
} }
} }
} }

View File

@ -1,56 +0,0 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
public class SimpleDepthEffectInstanced : Effect
{
EffectParameter viewProjectionParam;
Matrix view;
Matrix projection;
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
public Matrix View
{
get { return view; }
set
{
view = value;
dirtyFlags |= EffectDirtyFlags.ViewProj;
}
}
public Matrix Projection
{
get { return projection; }
set
{
projection = value;
dirtyFlags |= EffectDirtyFlags.ViewProj;
}
}
public SimpleDepthEffectInstanced(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.SimpleDepthEffectInstanced)
{
CacheEffectParameters();
}
protected override void OnApply()
{
if ((dirtyFlags & EffectDirtyFlags.ViewProj) != 0)
{
Matrix.Multiply(ref view, ref projection, out Matrix viewProjection);
viewProjectionParam.SetValue(viewProjection);
dirtyFlags &= ~EffectDirtyFlags.ViewProj;
}
}
private void CacheEffectParameters()
{
viewProjectionParam = Parameters["ViewProjection"];
}
}
}

View File

@ -1,9 +0,0 @@
namespace Kav
{
public enum SpriteBillboardConstraint
{
None,
Horizontal,
Full
}
}

View File

@ -1,9 +0,0 @@
using Microsoft.Xna.Framework;
namespace Kav
{
public interface ICullable
{
BoundingBox BoundingBox { get; }
}
}

View File

@ -1,19 +0,0 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
public interface IGBufferDrawable
{
Vector3 Albedo { get; }
float Metallic { get; }
float Roughness { get; }
Texture2D AlbedoTexture { get; }
Texture2D NormalTexture { get; }
Texture2D MetallicRoughnessTexture { get; }
int NumTextureRows { get; }
int NumTextureColumns { get; }
}
}

View File

@ -1,9 +0,0 @@
using Microsoft.Xna.Framework;
namespace Kav
{
public interface IHasVertexPositions
{
Vector3[] Positions { get; }
}
}

View File

@ -1,10 +0,0 @@
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
public interface IIndexDrawable
{
VertexBuffer VertexBuffer { get; }
IndexBuffer IndexBuffer { get; }
}
}

View File

@ -1,9 +0,0 @@
using Microsoft.Xna.Framework;
namespace Kav
{
public interface ITransformable
{
Matrix TransformMatrix { get; }
}
}

View File

@ -3,7 +3,7 @@ using Microsoft.Xna.Framework.Graphics;
namespace Kav namespace Kav
{ {
public class MeshPart : IIndexDrawable, IGBufferDrawable, ICullable, IHasVertexPositions public class MeshPart
{ {
public IndexBuffer IndexBuffer { get; } public IndexBuffer IndexBuffer { get; }
public VertexBuffer VertexBuffer { get; } public VertexBuffer VertexBuffer { get; }
@ -11,36 +11,33 @@ namespace Kav
public Vector3[] Positions { get; } public Vector3[] Positions { get; }
public BoundingBox BoundingBox { get; } public BoundingBox BoundingBox { get; }
private Texture2D albedoTexture = null; private Texture2D albedoTexture = null;
private Texture2D normalTexture = null; private Texture2D normalTexture = null;
private Texture2D metallicRoughnessTexture = null; private Texture2D metallicRoughnessTexture = null;
public Texture2D AlbedoTexture public Texture2D AlbedoTexture
{ {
get { return DisableAlbedoMap ? null : albedoTexture; } get { return DisableAlbedoMap ? null : albedoTexture; }
set { albedoTexture = value; } set { albedoTexture = value; }
} }
public Texture2D NormalTexture public Texture2D NormalTexture
{ {
get { return DisableNormalMap ? null : normalTexture; } get { return DisableNormalMap ? null : normalTexture; }
set { normalTexture = value; } set { normalTexture = value; }
} }
public Texture2D MetallicRoughnessTexture public Texture2D MetallicRoughnessTexture
{ {
get { return DisableMetallicRoughnessMap ? null : metallicRoughnessTexture; } get { return DisableMetallicRoughnessMap ? null : metallicRoughnessTexture; }
set { metallicRoughnessTexture = value; } set { metallicRoughnessTexture = value; }
} }
public Vector3 Albedo { get; set; } = Vector3.One; public Vector3 Albedo { get; set; } = Vector3.One;
public float Metallic { get; set; } = 0.5f; public float Metallic { get; set; } = 0.5f;
public float Roughness { get; set; } = 0.5f; public float Roughness { get; set; } = 0.5f;
public int NumTextureRows { get; set; } = 1;
public int NumTextureColumns { get; set; } = 1;
public bool DisableAlbedoMap { get; set; } = false; public bool DisableAlbedoMap { get; set; } = false;
public bool DisableNormalMap { get; set; } = false; public bool DisableNormalMap { get; set; } = false;
public bool DisableMetallicRoughnessMap { get; set; } = false; public bool DisableMetallicRoughnessMap { get; set; } = false;

View File

@ -2,14 +2,14 @@ using Microsoft.Xna.Framework;
namespace Kav namespace Kav
{ {
public class Model : ICullable public class Model
{ {
public Mesh[] Meshes { get; } public Mesh[] Meshes { get; }
public BoundingBox BoundingBox { get; } public BoundingBox BoundingBox { get; }
public Color Albedo public Color Albedo
{ {
set set
{ {
foreach (var mesh in Meshes) foreach (var mesh in Meshes)
{ {
@ -32,7 +32,7 @@ namespace Kav
meshPart.Metallic = value; meshPart.Metallic = value;
} }
} }
} }
} }
public float Roughness public float Roughness
@ -46,7 +46,7 @@ namespace Kav
meshPart.Roughness = value; meshPart.Roughness = value;
} }
} }
} }
} }
public Model(Mesh[] meshes) public Model(Mesh[] meshes)
@ -83,7 +83,7 @@ namespace Kav
} }
} }
} }
public void DisableMetallicRoughnessMaps() public void DisableMetallicRoughnessMaps()
{ {
foreach (var mesh in Meshes) foreach (var mesh in Meshes)

View File

@ -10,48 +10,30 @@ namespace Kav
public Vector2 Origin { get; } public Vector2 Origin { get; }
public float Rotation { get; } public float Rotation { get; }
public Vector2 Scale { get; } public Vector2 Scale { get; }
public SpriteBillboardConstraint BillboardConstraint { get; }
public Matrix TransformMatrix { get; }
public Sprite( public Sprite(
Texture2D texture, Texture2D texture,
Vector3 position, Vector3 position,
Vector2 origin, Vector2 origin,
float rotation, float rotation,
Vector2 scale, Vector2 scale
SpriteBillboardConstraint billboardConstraint = SpriteBillboardConstraint.None
) { ) {
Texture = texture; Texture = texture;
Position = position; Position = position;
Origin = origin; Origin = origin;
Rotation = rotation; Rotation = rotation;
Scale = scale; Scale = scale;
BillboardConstraint = billboardConstraint;
TransformMatrix = ConstructTransformMatrix(Position, Scale);
} }
public Sprite( public Sprite(
Texture2D texture, Texture2D texture,
Vector3 position, Vector3 position
SpriteBillboardConstraint billboardConstraint = SpriteBillboardConstraint.None
) { ) {
Texture = texture; Texture = texture;
Position = position; Position = position;
Origin = Vector2.Zero; Origin = Vector2.Zero;
Rotation = 0; Rotation = 0f;
Scale = Vector2.One; Scale = Vector2.One;
BillboardConstraint = billboardConstraint;
TransformMatrix = ConstructTransformMatrix(Position, Scale);
}
private static Matrix ConstructTransformMatrix(
Vector3 position,
Vector2 scale
) {
return
Matrix.CreateTranslation(position) *
Matrix.CreateScale(scale.X, scale.Y, 1);
} }
} }
} }

View File

@ -1,109 +0,0 @@
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
public class SpriteMesh : ICullable, IIndexDrawable
{
public enum FlipOptions
{
None,
Horizontal,
Vertical,
Both
}
private static readonly short[] Indices = new short[]
{
0,
1,
2,
1,
3,
2
};
public IndexBuffer IndexBuffer { get; }
public VertexBuffer VertexBuffer { get; }
public BoundingBox BoundingBox { get; }
public SpriteMesh(
GraphicsDevice graphicsDevice,
int width,
int height,
FlipOptions flipOptions
) {
IndexBuffer = new IndexBuffer(
graphicsDevice,
IndexElementSize.SixteenBits,
6,
BufferUsage.WriteOnly
);
IndexBuffer.SetData(Indices);
var vertexArray = GenerateVertexArray(width, height, flipOptions);
VertexBuffer = new VertexBuffer(
graphicsDevice,
typeof(VertexPositionNormalTexture),
4,
BufferUsage.WriteOnly
);
VertexBuffer.SetData(vertexArray);
BoundingBox = BoundingBox.CreateFromPoints(Positions(vertexArray));
}
private static VertexPositionNormalTexture[] GenerateVertexArray(int pixelWidth, int pixelHeight, FlipOptions flipOptions)
{
var width = pixelWidth / (float)40;
var height = pixelHeight / (float)40;
VertexPositionNormalTexture[] result = new VertexPositionNormalTexture[4];
var xLeft = 0;
var xRight = 1;
var yTop = 0;
var yBottom = 1;
if (flipOptions == FlipOptions.Horizontal || flipOptions == FlipOptions.Both)
{
xLeft = 1;
xRight = 0;
}
if (flipOptions == FlipOptions.Vertical || flipOptions == FlipOptions.Both)
{
yTop = 1;
yBottom = 0;
}
result[0].Position = new Vector3(-width / 2, height / 2, 0);
result[0].Normal = new Vector3(0, 0, -1);
result[0].TextureCoordinate = new Vector2(xLeft, yTop);
result[1].Position = new Vector3(width / 2, height / 2, 0);
result[1].Normal = new Vector3(0, 0, -1);
result[1].TextureCoordinate = new Vector2(xRight, yTop);
result[2].Position = new Vector3(-width / 2, -height / 2, 0);
result[2].Normal = new Vector3(0, 0, -1);
result[2].TextureCoordinate = new Vector2(xLeft, yBottom);
result[3].Position = new Vector3(width / 2, -height / 2, 0);
result[3].Normal = new Vector3(0, 0, -1);
result[3].TextureCoordinate = new Vector2(xRight, yBottom);
return result;
}
private static IEnumerable<Vector3> Positions(IEnumerable<VertexPositionNormalTexture> vertices)
{
foreach (var vertex in vertices)
{
yield return vertex.Position;
}
}
}
}

View File

@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8.0</LangVersion>
<RootNamespace>Kav</RootNamespace> <RootNamespace>Kav</RootNamespace>
<Authors>Evan Hemsley</Authors> <Authors>Evan Hemsley</Authors>
<Copyright>Evan Hemsley 2020</Copyright> <Copyright>Evan Hemsley 2020</Copyright>
@ -44,30 +43,15 @@
<EmbeddedResource Include="Effects\FXB\SimpleDepthEffect.fxb"> <EmbeddedResource Include="Effects\FXB\SimpleDepthEffect.fxb">
<LogicalName>Kav.Resources.SimpleDepthEffect.fxb</LogicalName> <LogicalName>Kav.Resources.SimpleDepthEffect.fxb</LogicalName>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\SimpleDepthEffectInstanced.fxb">
<LogicalName>Kav.Resources.SimpleDepthEffectInstanced.fxb</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\LinearDepthEffect.fxb"> <EmbeddedResource Include="Effects\FXB\LinearDepthEffect.fxb">
<LogicalName>Kav.Resources.LinearDepthEffect.fxb</LogicalName> <LogicalName>Kav.Resources.LinearDepthEffect.fxb</LogicalName>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\LinearDepthEffectInstanced.fxb">
<LogicalName>Kav.Resources.LinearDepthEffectInstanced.fxb</LogicalName>
</EmbeddedResource>
<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="Effects\FXB\PaletteCrushEffect.fxb">
<LogicalName>Kav.Resources.PaletteCrushEffect.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>
<EmbeddedResource Include="Models\UnitSphere.glb">
<LogicalName>Kav.Resources.UnitSphere.glb</LogicalName>
</EmbeddedResource>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,14 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8.0</LangVersion>
<RootNamespace>Kav</RootNamespace> <RootNamespace>Kav</RootNamespace>
<Authors>Evan Hemsley</Authors> <Authors>Evan Hemsley</Authors>
<Copyright>Evan Hemsley 2020</Copyright> <Copyright>Evan Hemsley 2020</Copyright>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<AssemblyName>Kav</AssemblyName> <AssemblyName>Kav</AssemblyName>
<Platforms>x64;x86</Platforms> <Platforms>x64</Platforms>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -44,30 +43,15 @@
<EmbeddedResource Include="Effects\FXB\SimpleDepthEffect.fxb"> <EmbeddedResource Include="Effects\FXB\SimpleDepthEffect.fxb">
<LogicalName>Kav.Resources.SimpleDepthEffect.fxb</LogicalName> <LogicalName>Kav.Resources.SimpleDepthEffect.fxb</LogicalName>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\SimpleDepthEffectInstanced.fxb">
<LogicalName>Kav.Resources.SimpleDepthEffectInstanced.fxb</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\LinearDepthEffect.fxb"> <EmbeddedResource Include="Effects\FXB\LinearDepthEffect.fxb">
<LogicalName>Kav.Resources.LinearDepthEffect.fxb</LogicalName> <LogicalName>Kav.Resources.LinearDepthEffect.fxb</LogicalName>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Effects\FXB\LinearDepthEffectInstanced.fxb">
<LogicalName>Kav.Resources.LinearDepthEffectInstanced.fxb</LogicalName>
</EmbeddedResource>
<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="Effects\FXB\PaletteCrushEffect.fxb">
<LogicalName>Kav.Resources.PaletteCrushEffect.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>
<EmbeddedResource Include="Models\UnitSphere.glb">
<LogicalName>Kav.Resources.UnitSphere.glb</LogicalName>
</EmbeddedResource>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,55 +1,18 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
namespace Kav namespace Kav
{ {
public sealed class PointLight : IDisposable public struct PointLight
{ {
public Vector3 Position { get; } public Vector3 Position { get; }
public Color Color { get; } public Color Color { get; }
public float Radius { get; } public float Intensity { get; }
public BoundingSphere BoundingSphere { get; } public PointLight(Vector3 position, Color color, float intensity = 1f)
{
public RenderTargetCube ShadowMap { get; }
public PointLight(
GraphicsDevice graphicsDevice,
Vector3 position,
Color color,
float radius,
int shadowMapSize
) {
Position = position; Position = position;
Color = color; Color = color;
Radius = radius; Intensity = intensity;
BoundingSphere = new BoundingSphere(position, Radius);
ShadowMap = new RenderTargetCube(
graphicsDevice,
shadowMapSize,
false,
SurfaceFormat.Single,
DepthFormat.Depth24,
0,
RenderTargetUsage.PreserveContents
);
var currentRTs = graphicsDevice.GetRenderTargets();
foreach (CubeMapFace face in Enum.GetValues(typeof(CubeMapFace)))
{
graphicsDevice.SetRenderTarget(ShadowMap, face);
graphicsDevice.Clear(Color.White);
}
graphicsDevice.SetRenderTargets(currentRTs);
}
public void Dispose()
{
ShadowMap.Dispose();
} }
} }
} }

View File

@ -1,18 +0,0 @@
using System.IO;
using System.Text.Json;
namespace Kav
{
public static class CrunchAtlasReader
{
static JsonSerializerOptions options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
public static CrunchTextureAtlasData ReadTextureAtlas(FileInfo file)
{
return JsonSerializer.Deserialize<CrunchTextureAtlasData>(File.ReadAllText(file.FullName), options);
}
}
}

View File

@ -1,22 +0,0 @@
namespace Kav
{
public struct CrunchTextureAtlasData
{
public CrunchTextureAtlasTextureData[] Textures { get; set; }
}
public struct CrunchTextureAtlasTextureData
{
public string Name { get; set; }
public CrunchTextureAtlasImageData[] Images { get; set; }
}
public struct CrunchTextureAtlasImageData
{
public string N { get; set; }
public int X { get; set; }
public int Y { get; set; }
public int W { get; set; }
public int H { get; set; }
}
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -111,18 +111,6 @@ namespace Kav
} }
} }
public static byte[] SimpleDepthEffectInstanced
{
get
{
if (simpleDepthEffectInstanced == null)
{
simpleDepthEffectInstanced = GetResource("SimpleDepthEffectInstanced.fxb");
}
return simpleDepthEffectInstanced;
}
}
public static byte[] LinearDepthEffect public static byte[] LinearDepthEffect
{ {
get get
@ -135,18 +123,6 @@ namespace Kav
} }
} }
public static byte[] LinearDepthEffectInstanced
{
get
{
if (linearDepthEffectInstanced == null)
{
linearDepthEffectInstanced = GetResource("LinearDepthEffectInstanced.fxb");
}
return linearDepthEffectInstanced;
}
}
public static byte[] SkyboxEffect public static byte[] SkyboxEffect
{ {
get get
@ -159,30 +135,6 @@ namespace Kav
} }
} }
public static byte[] DiffuseLitSpriteEffect
{
get
{
if (diffuseLitSpriteEffect == null)
{
diffuseLitSpriteEffect = GetResource("DiffuseLitSpriteEffect.fxb");
}
return diffuseLitSpriteEffect;
}
}
public static byte[] PaletteCrushEffect
{
get
{
if (paletteCrushEffect == null)
{
paletteCrushEffect = GetResource("PaletteCrushEffect.fxb");
}
return paletteCrushEffect;
}
}
public static byte[] UnitCubeModel public static byte[] UnitCubeModel
{ {
get get
@ -195,18 +147,6 @@ namespace Kav
} }
} }
public static byte[] UnitSphereModel
{
get
{
if (unitSphereModel == null)
{
unitSphereModel = GetResource("UnitSphere.glb");
}
return unitSphereModel;
}
}
private static byte[] ambientLightEffect; private static byte[] ambientLightEffect;
private static byte[] pointLightEffect; private static byte[] pointLightEffect;
private static byte[] directionalLightEffect; private static byte[] directionalLightEffect;
@ -216,15 +156,10 @@ namespace Kav
private static byte[] deferredPBREffect; private static byte[] deferredPBREffect;
private static byte[] pbrEffect; private static byte[] pbrEffect;
private static byte[] simpleDepthEffect; private static byte[] simpleDepthEffect;
private static byte[] simpleDepthEffectInstanced;
private static byte[] linearDepthEffect; private static byte[] linearDepthEffect;
private static byte[] linearDepthEffectInstanced;
private static byte[] skyboxEffect; private static byte[] skyboxEffect;
private static byte[] diffuseLitSpriteEffect;
private static byte[] paletteCrushEffect;
private static byte[] unitCubeModel; private static byte[] unitCubeModel;
private static byte[] unitSphereModel;
private static byte[] GetResource(string name) private static byte[] GetResource(string name)
{ {

View File

@ -1,18 +0,0 @@
using Microsoft.Xna.Framework;
namespace Kav.Utils
{
public static class QuaternionUtils
{
// assumes that the input vectors are normalized and orthogonal
public static Quaternion LookAt(in Vector3 forward, in Vector3 up)
{
Matrix orientation = Matrix.Identity;
orientation.Forward = forward;
orientation.Right = Vector3.Normalize(Vector3.Cross(forward, up));
orientation.Up = Vector3.Cross(orientation.Right, forward);
return Quaternion.CreateFromRotationMatrix(orientation);
}
}
}

View File

@ -1,18 +0,0 @@
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
public static class VertexDeclarations
{
public static VertexDeclaration PositionInstanceDeclaration = new VertexDeclaration
(
new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.TextureCoordinate, 2)
);
public static VertexDeclaration PositionTextureOffsetInstanceDeclaration = new VertexDeclaration
(
new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.TextureCoordinate, 2),
new VertexElement(12, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 5)
);
}
}

View File

@ -1,31 +0,0 @@
using System.Runtime.InteropServices;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct PositionTextureOffsetInstanceVertex : IVertexType
{
VertexDeclaration IVertexType.VertexDeclaration
{
get
{
return VertexDeclarations.PositionTextureOffsetInstanceDeclaration;
}
}
public Vector3 Translation { get; set; }
public Vector2 UVOffset { get; set; }
public static readonly VertexDeclaration VertexDeclaration;
public PositionTextureOffsetInstanceVertex(
Vector3 translation,
Vector2 uvOffset
) {
Translation = translation;
UVOffset = uvOffset;
}
}
}