Compare commits

..

1 Commits

Author SHA1 Message Date
cosmonaut 40b5d71bfe trying to do tiled draws 2020-12-10 16:02:13 -08:00
32 changed files with 217 additions and 601 deletions

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

35
Data/MeshPartDrawData.cs Normal file
View File

@ -0,0 +1,35 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Kav.Data
{
public struct MeshPartDrawData : IGBufferDrawable, IUVDrawable, ICullable, IIndexDrawable
{
public MeshPart MeshPart { get; }
public Matrix TransformMatrix { get; }
public UVData UVData { get; }
public BoundingBox BoundingBox => MeshPart.BoundingBox;
public IndexBuffer IndexBuffer => MeshPart.IndexBuffer;
public VertexBuffer VertexBuffer => MeshPart.VertexBuffer;
public Vector3 Albedo => MeshPart.Albedo;
public float Metallic => MeshPart.Metallic;
public float Roughness => MeshPart.Roughness;
public Texture2D AlbedoTexture => MeshPart.AlbedoTexture;
public Texture2D NormalTexture => MeshPart.NormalTexture;
public Texture2D MetallicRoughnessTexture => MeshPart.MetallicRoughnessTexture;
public MeshPartDrawData(
MeshPart meshPart,
Matrix transformMatrix,
UVData uvData
) {
MeshPart = meshPart;
TransformMatrix = transformMatrix;
UVData = uvData;
}
}
}

View File

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

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,6 +1,6 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
namespace Kav namespace Kav.Data
{ {
public struct UVData public struct UVData
{ {
@ -15,5 +15,10 @@ namespace Kav
Percentage = subTextureDimensions / atlasDimensions; Percentage = subTextureDimensions / atlasDimensions;
Offset = positionInAtlas / atlasDimensions; Offset = positionInAtlas / atlasDimensions;
} }
public Vector4 ToVector4()
{
return new Vector4(Offset.X, Offset.Y, Percentage.X, Percentage.Y);
}
} }
} }

View File

@ -12,17 +12,12 @@ namespace Kav
EffectParameter normalTextureParam; EffectParameter normalTextureParam;
EffectParameter metallicRoughnessTextureParam; EffectParameter metallicRoughnessTextureParam;
EffectParameter uvOffsetAndDimensionsParam;
EffectParameter albedoParam; EffectParameter albedoParam;
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,13 +28,7 @@ namespace Kav
float metallic; float metallic;
float roughness; float roughness;
Vector2 uvOffset; Vector4 uvData;
Vector2 subTextureDimensions;
bool isSprite = false;
int numTextureRows = 1;
int numTextureColumns = 1;
bool albedoTextureEnabled = false; bool albedoTextureEnabled = false;
bool metallicRoughnessMapEnabled = false; bool metallicRoughnessMapEnabled = false;
@ -141,54 +130,15 @@ namespace Kav
} }
} }
public int NumTextureRows public Vector4 UVData
{ {
get { return numTextureRows; } get { return uvData; }
set set
{ {
numTextureRows = value; uvData = value;
numTextureRowsParam.SetValue(numTextureRows); uvOffsetAndDimensionsParam.SetValue(uvData);
}
} }
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 public bool HardwareInstancingEnabled
@ -248,28 +198,6 @@ namespace Kav
dirtyFlags &= ~EffectDirtyFlags.ViewProj; dirtyFlags &= ~EffectDirtyFlags.ViewProj;
} }
if ((dirtyFlags & EffectDirtyFlags.UVOrDimensions) != 0)
{
uvOffsetAndDimensionsParam.SetValue(new Vector4(
UVOffset.X, UVOffset.Y,
SubTextureDimensions.X, SubTextureDimensions.Y
));
dirtyFlags &= ~EffectDirtyFlags.UVOrDimensions;
}
if ((dirtyFlags & EffectDirtyFlags.VertexShaderIndex) != 0)
{
int vertexShaderIndex = 0;
if (hardwareInstancingEnabled)
{
vertexShaderIndex = 1;
}
vertexShaderIndexParam.SetValue(vertexShaderIndex);
}
if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0) if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0)
{ {
int shaderIndex = 0; int shaderIndex = 0;
@ -322,14 +250,9 @@ namespace Kav
metallicParam = Parameters["MetallicValue"]; metallicParam = Parameters["MetallicValue"];
roughnessParam = Parameters["RoughnessValue"]; roughnessParam = Parameters["RoughnessValue"];
numTextureRowsParam = Parameters["NumTextureRows"];
numTextureColumnsParam = Parameters["NumTextureColumns"];
uvOffsetAndDimensionsParam = Parameters["UVOffsetAndDimensions"]; uvOffsetAndDimensionsParam = Parameters["UVOffsetAndDimensions"];
isSpriteParam = Parameters["IsSprite"];
shaderIndexParam = Parameters["PixelShaderIndex"]; shaderIndexParam = Parameters["PixelShaderIndex"];
vertexShaderIndexParam = Parameters["VertexShaderIndex"];
} }
} }
} }

View File

@ -33,8 +33,7 @@ namespace Kav
Matrix view = Matrix.Identity; Matrix view = Matrix.Identity;
Matrix projection = Matrix.Identity; Matrix projection = Matrix.Identity;
Vector2 uvOffset; Vector4 uvData;
Vector2 subTextureDimensions;
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
@ -115,23 +114,13 @@ namespace Kav
} }
} }
public Vector2 UVOffset public Vector4 UVData
{ {
get { return uvOffset; } get { return uvData; }
set set
{ {
uvOffset = value; uvData = value;
dirtyFlags |= EffectDirtyFlags.UVOrDimensions; dirtyFlags |= EffectDirtyFlags.UVData;
}
}
public Vector2 SubTextureDimensions
{
get { return subTextureDimensions; }
set
{
subTextureDimensions = value;
dirtyFlags |= EffectDirtyFlags.UVOrDimensions;
} }
} }
@ -168,14 +157,11 @@ namespace Kav
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj; dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
} }
if ((dirtyFlags & EffectDirtyFlags.UVOrDimensions) != 0) if ((dirtyFlags & EffectDirtyFlags.UVData) != 0)
{ {
uvOffsetAndDimensionsParam.SetValue(new Vector4( uvOffsetAndDimensionsParam.SetValue(uvData);
UVOffset.X, UVOffset.Y,
SubTextureDimensions.X, SubTextureDimensions.Y
));
dirtyFlags &= ~EffectDirtyFlags.UVOrDimensions; dirtyFlags &= ~EffectDirtyFlags.UVData;
} }
if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0) if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0)

View File

@ -11,7 +11,7 @@ namespace Kav
VertexShaderIndex = 8, VertexShaderIndex = 8,
PixelShaderIndex = 16, PixelShaderIndex = 16,
ViewProj = 32, ViewProj = 32,
UVOrDimensions = 64, UVData = 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/PaletteCrushEffect.fxb (Stored with Git LFS)

Binary file not shown.

View File

@ -4,32 +4,31 @@ DECLARE_TEXTURE(AlbedoTexture, 0);
DECLARE_TEXTURE(NormalTexture, 1); DECLARE_TEXTURE(NormalTexture, 1);
DECLARE_TEXTURE(MetallicRoughnessTexture, 2); DECLARE_TEXTURE(MetallicRoughnessTexture, 2);
float3 AlbedoValue;
float MetallicValue;
float RoughnessValue;
float4 UVOffsetAndDimensions; float4 UVOffsetAndDimensions;
float IsSprite;
BEGIN_CONSTANTS float4x4 World;
float4x4 ViewProjection;
float3 AlbedoValue _ps(c0) _cb(c0);
float MetallicValue _ps(c1) _cb(c1);
float RoughnessValue _ps(c2) _cb(c2);
int NumTextureRows _vs(c9) _cb(c3);
int NumTextureColumns _vs(c10) _cb(c4);
MATRIX_CONSTANTS
float4x4 World _vs(c0) _cb(c7);
float4x4 ViewProjection _vs(c4) _cb(c11);
END_CONSTANTS
struct VertexInput struct VertexInput
{ {
float4 Position : POSITION; float3 Position : POSITION;
float3 Normal : NORMAL; float3 Normal : NORMAL;
float2 TexCoord : TEXCOORD; float2 TexCoord : TEXCOORD;
}; };
struct VertexInstancedInput
{
float3 Position : POSITION;
float3 Normal : NORMAL;
float2 TexCoord : TEXCOORD0;
float3 Translation : TEXCOORD2;
float2 UVData : TANGENT;
};
struct PixelInput struct PixelInput
{ {
float4 Position : SV_POSITION; float4 Position : SV_POSITION;
@ -56,8 +55,8 @@ PixelInput main_vs(VertexInput input)
output.NormalWorld = normalize(mul(input.Normal, World)); output.NormalWorld = normalize(mul(input.Normal, World));
float2 texCoord; float2 texCoord;
texCoord.x = (input.TexCoord.x * UVOffsetAndDimensions.z) + UVOffsetAndDimensions.x; texCoord.x = (input.TexCoord.x / UVOffsetAndDimensions.z) + UVOffsetAndDimensions.x;
texCoord.y = (input.TexCoord.y * UVOffsetAndDimensions.w) + UVOffsetAndDimensions.y; texCoord.y = (input.TexCoord.y / UVOffsetAndDimensions.w) + UVOffsetAndDimensions.y;
output.TexCoord = texCoord; output.TexCoord = texCoord;
float4x4 worldViewProjection = mul(World, ViewProjection); float4x4 worldViewProjection = mul(World, ViewProjection);
@ -67,9 +66,7 @@ PixelInput main_vs(VertexInput input)
} }
PixelInput instanced_vs( PixelInput instanced_vs(
VertexInput input, VertexInstancedInput input
float3 Translation : TEXCOORD2,
float2 UVOffset : TEXCOORD5
) { ) {
PixelInput output; PixelInput output;
@ -77,7 +74,7 @@ PixelInput instanced_vs(
float4(1, 0, 0, 0), float4(1, 0, 0, 0),
float4(0, 1, 0, 0), float4(0, 1, 0, 0),
float4(0, 0, 1, 0), float4(0, 0, 1, 0),
float4(Translation.x, Translation.y, Translation.z, 1) float4(input.Translation.x, input.Translation.y, input.Translation.z, 1)
); );
float4x4 worldViewProjection = mul(world, ViewProjection); float4x4 worldViewProjection = mul(world, ViewProjection);
@ -86,9 +83,9 @@ PixelInput instanced_vs(
output.NormalWorld = mul(input.Normal, world); output.NormalWorld = mul(input.Normal, world);
float2 texCoord; float2 texCoord;
texCoord.x = (input.TexCoord.x / NumTextureColumns + UVOffset.x); texCoord.x = (input.TexCoord.x / 8) + input.UVData.x;
texCoord.y = (input.TexCoord.y / NumTextureRows + UVOffset.y); texCoord.y = (input.TexCoord.y / 1) + input.UVData.y;
output.TexCoord = texCoord; output.TexCoord = input.TexCoord;
output.Position = mul(input.Position, worldViewProjection); output.Position = mul(input.Position, worldViewProjection);
@ -120,7 +117,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 +129,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 +141,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 +153,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 +165,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 +177,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 +189,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 +201,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(),
@ -258,7 +234,7 @@ Technique GBuffer
{ {
Pass Pass
{ {
VertexShader = (VSArray[VSIndices[VertexShaderIndex]]); VertexShader = compile vs_3_0 instanced_vs();
PixelShader = (PSArray[PSIndices[PixelShaderIndex]]); PixelShader = (PSArray[PSIndices[PixelShaderIndex]]);
} }
} }

View File

@ -80,24 +80,10 @@ float4 main_ps(PixelInput input) : SV_TARGET0
float2 texCoord = 0.5f * float2(input.ScreenPosition.x,-input.ScreenPosition.y) + 0.5f; float2 texCoord = 0.5f * float2(input.ScreenPosition.x,-input.ScreenPosition.y) + 0.5f;
float3 worldPosition = SAMPLE_TEXTURE(gPosition, texCoord).rgb; float3 worldPosition = SAMPLE_TEXTURE(gPosition, texCoord).rgb;
float4 normalSample = SAMPLE_TEXTURE(gNormal, texCoord); float3 normal = SAMPLE_TEXTURE(gNormal, texCoord).xyz;
float3 normal = normalSample.xyz;
float isSprite = normalSample.a;
float3 albedo = SAMPLE_TEXTURE(gAlbedo, texCoord).rgb; float3 albedo = SAMPLE_TEXTURE(gAlbedo, texCoord).rgb;
float2 metallicRoughness = SAMPLE_TEXTURE(gMetallicRoughness, texCoord).rg; float2 metallicRoughness = SAMPLE_TEXTURE(gMetallicRoughness, texCoord).rg;
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( return ComputeColor(
worldPosition, worldPosition,
normal, normal,
@ -105,7 +91,6 @@ float4 main_ps(PixelInput input) : SV_TARGET0
metallicRoughness.r, metallicRoughness.r,
metallicRoughness.g metallicRoughness.g
); );
}
} }
Technique DeferredPBR_Point Technique DeferredPBR_Point

View File

@ -43,8 +43,8 @@ PixelShaderInput main_vs(VertexShaderInput input)
output.PositionWS = mul(input.Position, World).xyz; output.PositionWS = mul(input.Position, World).xyz;
float2 texCoord; float2 texCoord;
texCoord.x = (input.TexCoord.x * UVOffsetAndDimensions.z) + UVOffsetAndDimensions.x; texCoord.x = (input.TexCoord.x / UVOffsetAndDimensions.z) + UVOffsetAndDimensions.x;
texCoord.y = (input.TexCoord.y * UVOffsetAndDimensions.w) + UVOffsetAndDimensions.y; texCoord.y = (input.TexCoord.y / UVOffsetAndDimensions.w) + UVOffsetAndDimensions.y;
output.TexCoord = texCoord; output.TexCoord = texCoord;
return output; return output;
@ -98,9 +98,6 @@ float4 LightColor(float3 worldPosition, float3 worldNormal)
float4 WithoutNormalMap(PixelShaderInput input) : COLOR0 float4 WithoutNormalMap(PixelShaderInput input) : COLOR0
{ {
float4 tex = SAMPLE_TEXTURE(Texture, input.TexCoord); float4 tex = SAMPLE_TEXTURE(Texture, input.TexCoord);
if (tex.a == 0.0) { discard; }
float3 normalWS = normalize(input.NormalWS); float3 normalWS = normalize(input.NormalWS);
return tex * LightColor(input.PositionWS, normalWS); return tex * LightColor(input.PositionWS, normalWS);
@ -109,9 +106,6 @@ float4 WithoutNormalMap(PixelShaderInput input) : COLOR0
float4 WithNormalMap(PixelShaderInput input) : COLOR0 float4 WithNormalMap(PixelShaderInput input) : COLOR0
{ {
float4 tex = SAMPLE_TEXTURE(Texture, input.TexCoord); float4 tex = SAMPLE_TEXTURE(Texture, input.TexCoord);
if (tex.a == 0.0) { discard; }
float3 normalWS = GetNormalFromMap(input.PositionWS, input.TexCoord, input.NormalWS); float3 normalWS = GetNormalFromMap(input.PositionWS, input.TexCoord, input.NormalWS);
return tex * LightColor(input.PositionWS, normalWS); return tex * LightColor(input.PositionWS, normalWS);

View File

@ -1,5 +1,7 @@
#include "Macros.fxh" #include "Macros.fxh"
#define FLT_MAX 3.402823466e+38
DECLARE_TEXTURE(Texture, 0); DECLARE_TEXTURE(Texture, 0);
DECLARE_TEXTURE(Palette, 1); DECLARE_TEXTURE(Palette, 1);
@ -38,12 +40,11 @@ float4 main_ps(PixelInput input) : SV_TARGET0
float3 sampled_color = sampled.rgb; float3 sampled_color = sampled.rgb;
float3 closest_color = float3(0, 0, 0); float3 closest_color = float3(0, 0, 0);
float closest_dist = 100000; float closest_dist = FLT_MAX;
for (int i = 0; i < PaletteWidth; i++) for (int i = 0; i < PaletteWidth; i++)
{ {
float texX = (i / (float)PaletteWidth); float3 palette_color = SAMPLE_TEXTURE(Palette, float2(i / (float)PaletteWidth, 0));
float3 palette_color = SAMPLE_TEXTURE(Palette, float2(texX, 0));
float dist = distance(palette_color, sampled_color); float dist = distance(palette_color, sampled_color);
if (dist < closest_dist) if (dist < closest_dist)
{ {

View File

@ -5,5 +5,6 @@ namespace Kav
public interface ICullable public interface ICullable
{ {
BoundingBox BoundingBox { get; } BoundingBox BoundingBox { get; }
Matrix TransformMatrix { get; }
} }
} }

View File

@ -1,3 +1,4 @@
using Kav.Data;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
@ -12,8 +13,5 @@ namespace Kav
Texture2D AlbedoTexture { get; } Texture2D AlbedoTexture { get; }
Texture2D NormalTexture { get; } Texture2D NormalTexture { get; }
Texture2D MetallicRoughnessTexture { get; } Texture2D MetallicRoughnessTexture { get; }
int NumTextureRows { get; }
int NumTextureColumns { get; }
} }
} }

View File

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

View File

@ -0,0 +1,9 @@
using Kav.Data;
namespace Kav
{
public interface IUVDrawable
{
UVData UVData { 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 : IIndexDrawable, IGBufferDrawable, IHasVertexPositions
{ {
public IndexBuffer IndexBuffer { get; } public IndexBuffer IndexBuffer { get; }
public VertexBuffer VertexBuffer { get; } public VertexBuffer VertexBuffer { get; }
@ -38,9 +38,6 @@ namespace Kav
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

@ -4,7 +4,7 @@ using Microsoft.Xna.Framework.Graphics;
namespace Kav namespace Kav
{ {
public class SpriteMesh : ICullable, IIndexDrawable public class MeshSprite : IIndexDrawable
{ {
public enum FlipOptions public enum FlipOptions
{ {
@ -14,6 +14,7 @@ namespace Kav
Both Both
} }
private static readonly int PixelScale = 40;
private static readonly short[] Indices = new short[] private static readonly short[] Indices = new short[]
{ {
0, 0,
@ -24,16 +25,21 @@ namespace Kav
2 2
}; };
public Texture2D Texture { get; }
public Texture2D Normal { get; }
public IndexBuffer IndexBuffer { get; } public IndexBuffer IndexBuffer { get; }
public VertexBuffer VertexBuffer { get; } public VertexBuffer VertexBuffer { get; }
public BoundingBox BoundingBox { get; } public BoundingBox BoundingBox { get; }
public SpriteMesh( public MeshSprite(
GraphicsDevice graphicsDevice, GraphicsDevice graphicsDevice,
int width, Texture2D texture,
int height,
FlipOptions flipOptions FlipOptions flipOptions
) { ) {
Texture = texture;
Normal = null;
IndexBuffer = new IndexBuffer( IndexBuffer = new IndexBuffer(
graphicsDevice, graphicsDevice,
IndexElementSize.SixteenBits, IndexElementSize.SixteenBits,
@ -42,7 +48,7 @@ namespace Kav
); );
IndexBuffer.SetData(Indices); IndexBuffer.SetData(Indices);
var vertexArray = GenerateVertexArray(width, height, flipOptions); var vertexArray = GenerateVertexArray(Texture, flipOptions);
VertexBuffer = new VertexBuffer( VertexBuffer = new VertexBuffer(
graphicsDevice, graphicsDevice,
@ -55,11 +61,38 @@ namespace Kav
BoundingBox = BoundingBox.CreateFromPoints(Positions(vertexArray)); BoundingBox = BoundingBox.CreateFromPoints(Positions(vertexArray));
} }
private static VertexPositionNormalTexture[] GenerateVertexArray(int pixelWidth, int pixelHeight, FlipOptions flipOptions) public MeshSprite(
{ GraphicsDevice graphicsDevice,
var width = pixelWidth / (float)40; Texture2D texture,
var height = pixelHeight / (float)40; Texture2D normal,
FlipOptions flipOptions
) {
Texture = texture;
Normal = normal;
IndexBuffer = new IndexBuffer(
graphicsDevice,
IndexElementSize.SixteenBits,
6,
BufferUsage.WriteOnly
);
IndexBuffer.SetData(Indices);
var vertexArray = GenerateVertexArray(Texture, flipOptions);
VertexBuffer = new VertexBuffer(
graphicsDevice,
typeof(VertexPositionNormalTexture),
4,
BufferUsage.WriteOnly
);
VertexBuffer.SetData(vertexArray);
BoundingBox = BoundingBox.CreateFromPoints(Positions(vertexArray));
}
private static VertexPositionNormalTexture[] GenerateVertexArray(Texture2D texture, FlipOptions flipOptions)
{
VertexPositionNormalTexture[] result = new VertexPositionNormalTexture[4]; VertexPositionNormalTexture[] result = new VertexPositionNormalTexture[4];
var xLeft = 0; var xLeft = 0;
@ -79,20 +112,20 @@ namespace Kav
yBottom = 0; yBottom = 0;
} }
result[0].Position = new Vector3(-width / 2, height / 2, 0); result[0].Position = new Vector3(-texture.Width / 2, texture.Height / 2, 0) / PixelScale;
result[0].Normal = new Vector3(0, 0, -1); result[0].Normal = new Vector3(0, 0, 1);
result[0].TextureCoordinate = new Vector2(xLeft, yTop); result[0].TextureCoordinate = new Vector2(xLeft, yTop);
result[1].Position = new Vector3(width / 2, height / 2, 0); result[1].Position = new Vector3(texture.Width / 2, texture.Height / 2, 0) / PixelScale;
result[1].Normal = new Vector3(0, 0, -1); result[1].Normal = new Vector3(0, 0, 1);
result[1].TextureCoordinate = new Vector2(xRight, yTop); result[1].TextureCoordinate = new Vector2(xRight, yTop);
result[2].Position = new Vector3(-width / 2, -height / 2, 0); result[2].Position = new Vector3(-texture.Width / 2, -texture.Height / 2, 0) / PixelScale;
result[2].Normal = new Vector3(0, 0, -1); result[2].Normal = new Vector3(0, 0, 1);
result[2].TextureCoordinate = new Vector2(xLeft, yBottom); result[2].TextureCoordinate = new Vector2(xLeft, yBottom);
result[3].Position = new Vector3(width / 2, -height / 2, 0); result[3].Position = new Vector3(texture.Width / 2, -texture.Height / 2, 0) / PixelScale;
result[3].Normal = new Vector3(0, 0, -1); result[3].Normal = new Vector3(0, 0, 1);
result[3].TextureCoordinate = new Vector2(xRight, yBottom); result[3].TextureCoordinate = new Vector2(xRight, yBottom);
return result; return result;

View File

@ -2,7 +2,7 @@ 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; }

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>

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>

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

View File

@ -125,7 +125,7 @@ namespace Kav
) { ) {
GraphicsDevice.SetRenderTarget(renderTarget); GraphicsDevice.SetRenderTarget(renderTarget);
GraphicsDevice.DepthStencilState = DepthStencilState.Default; GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
GraphicsDevice.RasterizerState = RasterizerState.CullNone; GraphicsDevice.RasterizerState = RasterizerState.CullNone;
GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
GraphicsDevice.SamplerStates[1] = SamplerState.PointClamp; GraphicsDevice.SamplerStates[1] = SamplerState.PointClamp;
@ -159,23 +159,17 @@ namespace Kav
var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection); var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
foreach (var data in meshSpriteDrawDatas) foreach (var data in FrustumCull(boundingFrustum, meshSpriteDrawDatas))
{ {
var matrix = BillboardTransforms(camera, data.TransformMatrix, data.BillboardConstraint); var matrix = BillboardTransforms(camera, data.TransformMatrix, data.BillboardConstraint);
if (FrustumCull(boundingFrustum, data.MeshSprite, matrix)) DiffuseLitSpriteEffect.NormalMapEnabled = data.MeshSprite.Normal != null;
{
continue;
}
DiffuseLitSpriteEffect.NormalMapEnabled = data.Normal != null;
DiffuseLitSpriteEffect.World = matrix; DiffuseLitSpriteEffect.World = matrix;
DiffuseLitSpriteEffect.UVOffset = data.UVOffset.Offset; DiffuseLitSpriteEffect.UVData = data.UVData.ToVector4();
DiffuseLitSpriteEffect.SubTextureDimensions = data.UVOffset.Percentage;
GraphicsDevice.Textures[0] = data.Texture; GraphicsDevice.Textures[0] = data.MeshSprite.Texture;
GraphicsDevice.Textures[1] = data.Normal; GraphicsDevice.Textures[1] = data.MeshSprite.Normal;
GraphicsDevice.SetVertexBuffer(data.MeshSprite.VertexBuffer); GraphicsDevice.SetVertexBuffer(data.MeshSprite.VertexBuffer);
GraphicsDevice.Indices = data.MeshSprite.IndexBuffer; GraphicsDevice.Indices = data.MeshSprite.IndexBuffer;
@ -196,51 +190,6 @@ namespace Kav
} }
} }
public void RenderMeshSpriteGBuffer(
RenderTargetBinding[] gBuffer,
PerspectiveCamera camera,
IEnumerable<MeshSpriteDrawData> meshSpriteDrawDatas,
DepthStencilState depthStencilState
) {
GraphicsDevice.SetRenderTargets(gBuffer);
GraphicsDevice.RasterizerState = RasterizerState.CullNone;
GraphicsDevice.DepthStencilState = depthStencilState;
GraphicsDevice.BlendState = BlendState.AlphaBlend;
Deferred_GBufferEffect.HardwareInstancingEnabled = false;
Deferred_GBufferEffect.IsSprite = true;
Deferred_GBufferEffect.View = camera.View;
Deferred_GBufferEffect.Projection = camera.Projection;
var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
foreach (var data in meshSpriteDrawDatas)
{
var matrix = BillboardTransforms(camera, data.TransformMatrix, data.BillboardConstraint);
if (FrustumCull(boundingFrustum, data.MeshSprite, matrix))
{
continue;
}
Deferred_GBufferEffect.World = matrix;
Deferred_GBufferEffect.UVOffset = data.UVOffset.Offset;
Deferred_GBufferEffect.SubTextureDimensions = data.UVOffset.Percentage;
Deferred_GBufferEffect.Albedo = Color.White.ToVector3();
Deferred_GBufferEffect.Metallic = 0f;
Deferred_GBufferEffect.Roughness = 1f;
Deferred_GBufferEffect.AlbedoTexture = data.Texture;
Deferred_GBufferEffect.NormalTexture = data.Normal;
Deferred_GBufferEffect.MetallicRoughnessTexture = null;
RenderIndexed(GraphicsDevice, data, Deferred_GBufferEffect);
}
}
private static Matrix BillboardTransforms( private static Matrix BillboardTransforms(
PerspectiveCamera camera, PerspectiveCamera camera,
Matrix transform, Matrix transform,
@ -277,13 +226,13 @@ namespace Kav
public static void CullAndRenderIndexed<T, U>( public static void CullAndRenderIndexed<T, U>(
GraphicsDevice graphicsDevice, GraphicsDevice graphicsDevice,
BoundingFrustum boundingFrustum, BoundingFrustum boundingFrustum,
IEnumerable<(T, Matrix)> drawableTransformPairs, IEnumerable<T> drawables,
U effect U effect
) where T : IIndexDrawable, ICullable where U : Effect, IHasWorldMatrix ) where T : IIndexDrawable, ICullable where U : Effect, IHasWorldMatrix
{ {
foreach (var (drawable, transform) in FrustumCull(boundingFrustum, drawableTransformPairs)) foreach (var drawable in FrustumCull(boundingFrustum, drawables))
{ {
effect.World = transform; effect.World = drawable.TransformMatrix;
RenderIndexed( RenderIndexed(
graphicsDevice, graphicsDevice,
@ -361,7 +310,7 @@ namespace Kav
public void RenderDepthIndexed<T>( public void RenderDepthIndexed<T>(
RenderTarget2D renderTarget, RenderTarget2D renderTarget,
PerspectiveCamera camera, PerspectiveCamera camera,
IEnumerable<(T, Matrix)> drawableTransforms IEnumerable<T> drawables
) where T : ICullable, IIndexDrawable ) where T : ICullable, IIndexDrawable
{ {
GraphicsDevice.SetRenderTarget(renderTarget); GraphicsDevice.SetRenderTarget(renderTarget);
@ -373,26 +322,11 @@ namespace Kav
CullAndRenderIndexed( CullAndRenderIndexed(
GraphicsDevice, GraphicsDevice,
new BoundingFrustum(camera.View * camera.Projection), new BoundingFrustum(camera.View * camera.Projection),
drawableTransforms, drawables,
SimpleDepthEffect SimpleDepthEffect
); );
} }
public void RenderDepthIndexed<T>(
RenderTarget2D renderTarget,
PerspectiveCamera camera,
T drawable,
DepthStencilState depthStencilState
) where T : IIndexDrawable {
GraphicsDevice.SetRenderTarget(renderTarget);
GraphicsDevice.DepthStencilState = depthStencilState;
SimpleDepthEffect.View = camera.View;
SimpleDepthEffect.Projection = camera.Projection;
RenderIndexed(GraphicsDevice, drawable, SimpleDepthEffect);
}
public void RenderSkybox( public void RenderSkybox(
RenderTarget2D renderTarget, RenderTarget2D renderTarget,
PerspectiveCamera camera, PerspectiveCamera camera,
@ -436,15 +370,11 @@ namespace Kav
GraphicsDevice.BlendState = BlendState.Opaque; GraphicsDevice.BlendState = BlendState.Opaque;
Deferred_GBufferEffect.HardwareInstancingEnabled = true; Deferred_GBufferEffect.HardwareInstancingEnabled = true;
Deferred_GBufferEffect.IsSprite = false;
Deferred_GBufferEffect.Albedo = drawable.Albedo; Deferred_GBufferEffect.Albedo = drawable.Albedo;
Deferred_GBufferEffect.Metallic = drawable.Metallic; Deferred_GBufferEffect.Metallic = drawable.Metallic;
Deferred_GBufferEffect.Roughness = drawable.Roughness; Deferred_GBufferEffect.Roughness = drawable.Roughness;
Deferred_GBufferEffect.NumTextureRows = drawable.NumTextureRows;
Deferred_GBufferEffect.NumTextureColumns = drawable.NumTextureColumns;
Deferred_GBufferEffect.AlbedoTexture = drawable.AlbedoTexture; Deferred_GBufferEffect.AlbedoTexture = drawable.AlbedoTexture;
Deferred_GBufferEffect.NormalTexture = drawable.NormalTexture; Deferred_GBufferEffect.NormalTexture = drawable.NormalTexture;
Deferred_GBufferEffect.MetallicRoughnessTexture = drawable.MetallicRoughnessTexture; Deferred_GBufferEffect.MetallicRoughnessTexture = drawable.MetallicRoughnessTexture;
@ -478,22 +408,21 @@ namespace Kav
public void RenderGBufferIndexed<T>( public void RenderGBufferIndexed<T>(
RenderTargetBinding[] gBuffer, RenderTargetBinding[] gBuffer,
PerspectiveCamera camera, PerspectiveCamera camera,
IEnumerable<(T, Matrix)> drawableTransforms IEnumerable<T> drawables
) where T : ICullable, IIndexDrawable, IGBufferDrawable { ) where T : ICullable, IIndexDrawable, IUVDrawable, IGBufferDrawable {
GraphicsDevice.SetRenderTargets(gBuffer); GraphicsDevice.SetRenderTargets(gBuffer);
GraphicsDevice.DepthStencilState = DepthStencilState.Default; GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.BlendState = BlendState.Opaque; GraphicsDevice.BlendState = BlendState.Opaque;
Deferred_GBufferEffect.IsSprite = false;
Deferred_GBufferEffect.HardwareInstancingEnabled = false; Deferred_GBufferEffect.HardwareInstancingEnabled = false;
Deferred_GBufferEffect.View = camera.View; Deferred_GBufferEffect.View = camera.View;
Deferred_GBufferEffect.Projection = camera.Projection; Deferred_GBufferEffect.Projection = camera.Projection;
var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection); var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
foreach (var (drawable, transform) in FrustumCull(boundingFrustum, drawableTransforms)) foreach (var drawable in FrustumCull(boundingFrustum, drawables))
{ {
Deferred_GBufferEffect.World = transform; Deferred_GBufferEffect.World = drawable.TransformMatrix;
Deferred_GBufferEffect.HardwareInstancingEnabled = false; Deferred_GBufferEffect.HardwareInstancingEnabled = false;
@ -501,6 +430,8 @@ namespace Kav
Deferred_GBufferEffect.Metallic = drawable.Metallic; Deferred_GBufferEffect.Metallic = drawable.Metallic;
Deferred_GBufferEffect.Roughness = drawable.Roughness; Deferred_GBufferEffect.Roughness = drawable.Roughness;
Deferred_GBufferEffect.UVData = drawable.UVData.ToVector4();
Deferred_GBufferEffect.AlbedoTexture = drawable.AlbedoTexture; Deferred_GBufferEffect.AlbedoTexture = drawable.AlbedoTexture;
Deferred_GBufferEffect.NormalTexture = drawable.NormalTexture; Deferred_GBufferEffect.NormalTexture = drawable.NormalTexture;
Deferred_GBufferEffect.MetallicRoughnessTexture = drawable.MetallicRoughnessTexture; Deferred_GBufferEffect.MetallicRoughnessTexture = drawable.MetallicRoughnessTexture;
@ -746,7 +677,7 @@ namespace Kav
public void RenderDirectionalShadowsIndexed<T>( public void RenderDirectionalShadowsIndexed<T>(
DirectionalShadowMapData shadowMapData, DirectionalShadowMapData shadowMapData,
IEnumerable<(T, Matrix)> drawableTransforms IEnumerable<T> drawableTransforms
) where T : ICullable, IIndexDrawable { ) where T : ICullable, IIndexDrawable {
// render the individual shadow cascades // render the individual shadow cascades
for (var i = 0; i < shadowMapData.NumShadowCascades; i++) for (var i = 0; i < shadowMapData.NumShadowCascades; i++)
@ -762,7 +693,7 @@ namespace Kav
private void RenderDirectionalShadowMapIndexed<T>( private void RenderDirectionalShadowMapIndexed<T>(
DirectionalShadowMapData shadowMapData, DirectionalShadowMapData shadowMapData,
int shadowCascadeIndex, int shadowCascadeIndex,
IEnumerable<(T, Matrix)> drawableTransforms IEnumerable<T> drawables
) where T : ICullable, IIndexDrawable { ) where T : ICullable, IIndexDrawable {
GraphicsDevice.SetRenderTarget(shadowMapData.ShadowMaps[shadowCascadeIndex]); GraphicsDevice.SetRenderTarget(shadowMapData.ShadowMaps[shadowCascadeIndex]);
GraphicsDevice.DepthStencilState = DepthStencilState.Default; GraphicsDevice.DepthStencilState = DepthStencilState.Default;
@ -774,7 +705,7 @@ namespace Kav
CullAndRenderIndexed( CullAndRenderIndexed(
GraphicsDevice, GraphicsDevice,
new BoundingFrustum(SimpleDepthEffect.View * SimpleDepthEffect.Projection), new BoundingFrustum(SimpleDepthEffect.View * SimpleDepthEffect.Projection),
drawableTransforms, drawables,
SimpleDepthEffect SimpleDepthEffect
); );
} }
@ -825,7 +756,7 @@ namespace Kav
public void RenderPointShadowMapIndexed<T>( public void RenderPointShadowMapIndexed<T>(
RenderTargetCube pointShadowCubeMap, RenderTargetCube pointShadowCubeMap,
IEnumerable<(T, Matrix)> modelTransforms, IEnumerable<T> drawables,
PointLight pointLight PointLight pointLight
) where T : ICullable, IIndexDrawable { ) where T : ICullable, IIndexDrawable {
GraphicsDevice.DepthStencilState = DepthStencilState.Default; GraphicsDevice.DepthStencilState = DepthStencilState.Default;
@ -893,7 +824,7 @@ namespace Kav
CullAndRenderIndexed( CullAndRenderIndexed(
GraphicsDevice, GraphicsDevice,
new BoundingFrustum(LinearDepthEffect.View * LinearDepthEffect.Projection), new BoundingFrustum(LinearDepthEffect.View * LinearDepthEffect.Projection),
modelTransforms, drawables,
LinearDepthEffect LinearDepthEffect
); );
} }
@ -905,7 +836,7 @@ namespace Kav
VertexBuffer instanceVertexBuffer, VertexBuffer instanceVertexBuffer,
int numInstances, int numInstances,
PointLight pointLight PointLight pointLight
) where T : ICullable, IIndexDrawable ) where T : IIndexDrawable
{ {
GraphicsDevice.DepthStencilState = DepthStencilState.Default; GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.BlendState = BlendState.Opaque; GraphicsDevice.BlendState = BlendState.Opaque;
@ -979,42 +910,17 @@ namespace Kav
} }
} }
private static IEnumerable<(T, Matrix)> FrustumCull<T>(
BoundingFrustum boundingFrustum,
IEnumerable<(T, Matrix)> cullableTransforms
) where T : ICullable {
foreach (var (cullable, transform) in cullableTransforms)
{
var boundingBox = TransformedBoundingBox(cullable.BoundingBox, transform);
var containment = boundingFrustum.Contains(boundingBox);
if (containment != ContainmentType.Disjoint)
{
yield return (cullable, transform);
}
}
}
private static bool FrustumCull<T>(
BoundingFrustum boundingFrustum,
T cullable,
Matrix transform
) where T : ICullable {
var boundingBox = TransformedBoundingBox(cullable.BoundingBox, transform);
var containment = boundingFrustum.Contains(boundingBox);
return (containment == ContainmentType.Disjoint);
}
private static IEnumerable<T> FrustumCull<T>( private static IEnumerable<T> FrustumCull<T>(
BoundingFrustum boundingFrustum, BoundingFrustum boundingFrustum,
IEnumerable<T> cullableTransformables IEnumerable<T> cullables
) where T : ICullable, ITransformable { ) where T : ICullable {
foreach (var cullableTransformable in cullableTransformables) foreach (var cullable in cullables)
{ {
var boundingBox = TransformedBoundingBox(cullableTransformable.BoundingBox, cullableTransformable.TransformMatrix); var boundingBox = TransformedBoundingBox(cullable.BoundingBox, cullable.TransformMatrix);
var containment = boundingFrustum.Contains(boundingBox); var containment = boundingFrustum.Contains(boundingBox);
if (containment != ContainmentType.Disjoint) if (containment != ContainmentType.Disjoint)
{ {
yield return cullableTransformable; yield return cullable;
} }
} }
} }

View File

@ -12,7 +12,7 @@ namespace Kav
public static VertexDeclaration PositionTextureOffsetInstanceDeclaration = new VertexDeclaration public static VertexDeclaration PositionTextureOffsetInstanceDeclaration = new VertexDeclaration
( (
new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.TextureCoordinate, 2), new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.TextureCoordinate, 2),
new VertexElement(12, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 5) new VertexElement(12, VertexElementFormat.Vector4, VertexElementUsage.Tangent, 0)
); );
} }
} }

View File

@ -16,16 +16,16 @@ namespace Kav
} }
public Vector3 Translation { get; set; } public Vector3 Translation { get; set; }
public Vector2 UVOffset { get; set; } public Vector4 UVData { get; set; }
public static readonly VertexDeclaration VertexDeclaration; public static readonly VertexDeclaration VertexDeclaration;
public PositionTextureOffsetInstanceVertex( public PositionTextureOffsetInstanceVertex(
Vector3 translation, Vector3 translation,
Vector2 uvOffset Vector4 uvData
) { ) {
Translation = translation; Translation = translation;
UVOffset = uvOffset; UVData = uvData;
} }
} }
} }