Compare commits
11 Commits
tiled_draw
...
main
Author | SHA1 | Date |
---|---|---|
cosmonaut | f5cdd0b566 | |
cosmonaut | 808d50ccc2 | |
cosmonaut | d537993530 | |
cosmonaut | 3338bf3b06 | |
cosmonaut | 16ecb5afa6 | |
cosmonaut | 51d7f3e772 | |
cosmonaut | 3a0aa8894d | |
cosmonaut | c468d6276d | |
cosmonaut | d476f254e4 | |
cosmonaut | 2ff5cb1ca5 | |
cosmonaut | 40ca0402d6 |
|
@ -0,0 +1,14 @@
|
|||
namespace Kav
|
||||
{
|
||||
public struct AtlasAnimation
|
||||
{
|
||||
public UVData[] Frames { get; }
|
||||
public int Framerate { get; }
|
||||
|
||||
public AtlasAnimation(UVData[] frames, int framerate)
|
||||
{
|
||||
Frames = frames;
|
||||
Framerate = framerate;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +1,32 @@
|
|||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Kav.Data
|
||||
{
|
||||
public struct MeshSpriteDrawData
|
||||
public struct MeshSpriteDrawData : IIndexDrawable, ICullable, ITransformable
|
||||
{
|
||||
public MeshSprite MeshSprite { get; }
|
||||
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(
|
||||
MeshSprite meshSprite,
|
||||
SpriteMesh meshSprite,
|
||||
Texture2D texture,
|
||||
Texture2D normal,
|
||||
SpriteBillboardConstraint billboardConstraint,
|
||||
Matrix transformMatrix,
|
||||
UVData offset
|
||||
) {
|
||||
MeshSprite = meshSprite;
|
||||
Texture = texture;
|
||||
Normal = normal;
|
||||
BillboardConstraint = billboardConstraint;
|
||||
TransformMatrix = transformMatrix;
|
||||
UVOffset = offset;
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Kav.Data
|
||||
namespace Kav
|
||||
{
|
||||
public struct UVData
|
||||
{
|
||||
|
|
|
@ -16,6 +16,9 @@ namespace Kav
|
|||
EffectParameter metallicParam;
|
||||
EffectParameter roughnessParam;
|
||||
|
||||
EffectParameter uvOffsetAndDimensionsParam;
|
||||
EffectParameter isSpriteParam;
|
||||
|
||||
EffectParameter numTextureRowsParam;
|
||||
EffectParameter numTextureColumnsParam;
|
||||
|
||||
|
@ -30,6 +33,11 @@ namespace Kav
|
|||
float metallic;
|
||||
float roughness;
|
||||
|
||||
Vector2 uvOffset;
|
||||
Vector2 subTextureDimensions;
|
||||
|
||||
bool isSprite = false;
|
||||
|
||||
int numTextureRows = 1;
|
||||
int numTextureColumns = 1;
|
||||
|
||||
|
@ -153,6 +161,36 @@ namespace Kav
|
|||
}
|
||||
}
|
||||
|
||||
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; }
|
||||
|
@ -210,6 +248,16 @@ namespace Kav
|
|||
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;
|
||||
|
@ -277,6 +325,9 @@ namespace Kav
|
|||
numTextureRowsParam = Parameters["NumTextureRows"];
|
||||
numTextureColumnsParam = Parameters["NumTextureColumns"];
|
||||
|
||||
uvOffsetAndDimensionsParam = Parameters["UVOffsetAndDimensions"];
|
||||
isSpriteParam = Parameters["IsSprite"];
|
||||
|
||||
shaderIndexParam = Parameters["PixelShaderIndex"];
|
||||
vertexShaderIndexParam = Parameters["VertexShaderIndex"];
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace Kav
|
|||
public DeferredPBR_PointLightEffect(DeferredPBR_PointLightEffect cloneSource) : base(cloneSource)
|
||||
{
|
||||
CacheEffectParameters();
|
||||
|
||||
|
||||
GPosition = cloneSource.GPosition;
|
||||
GAlbedo = cloneSource.GAlbedo;
|
||||
GNormal = cloneSource.GNormal;
|
||||
|
|
BIN
Effects/FXB/DeferredPBR_GBufferEffect.fxb (Stored with Git LFS)
BIN
Effects/FXB/DeferredPBR_GBufferEffect.fxb (Stored with Git LFS)
Binary file not shown.
BIN
Effects/FXB/DeferredPBR_PointLightEffect.fxb (Stored with Git LFS)
BIN
Effects/FXB/DeferredPBR_PointLightEffect.fxb (Stored with Git LFS)
Binary file not shown.
BIN
Effects/FXB/DiffuseLitSpriteEffect.fxb (Stored with Git LFS)
BIN
Effects/FXB/DiffuseLitSpriteEffect.fxb (Stored with Git LFS)
Binary file not shown.
BIN
Effects/FXB/PaletteCrushEffect.fxb (Stored with Git LFS)
BIN
Effects/FXB/PaletteCrushEffect.fxb (Stored with Git LFS)
Binary file not shown.
|
@ -4,6 +4,9 @@ DECLARE_TEXTURE(AlbedoTexture, 0);
|
|||
DECLARE_TEXTURE(NormalTexture, 1);
|
||||
DECLARE_TEXTURE(MetallicRoughnessTexture, 2);
|
||||
|
||||
float4 UVOffsetAndDimensions;
|
||||
float IsSprite;
|
||||
|
||||
BEGIN_CONSTANTS
|
||||
|
||||
float3 AlbedoValue _ps(c0) _cb(c0);
|
||||
|
@ -51,7 +54,11 @@ PixelInput main_vs(VertexInput input)
|
|||
|
||||
output.PositionWorld = mul(input.Position, World).xyz;
|
||||
output.NormalWorld = normalize(mul(input.Normal, World));
|
||||
output.TexCoord = input.TexCoord;
|
||||
|
||||
float2 texCoord;
|
||||
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);
|
||||
|
@ -60,7 +67,7 @@ PixelInput main_vs(VertexInput input)
|
|||
}
|
||||
|
||||
PixelInput instanced_vs(
|
||||
VertexInput input,
|
||||
VertexInput input,
|
||||
float3 Translation : TEXCOORD2,
|
||||
float2 UVOffset : TEXCOORD5
|
||||
) {
|
||||
|
@ -113,7 +120,7 @@ PixelOutput NonePS(PixelInput input)
|
|||
PixelOutput output;
|
||||
|
||||
output.gPosition = float4(input.PositionWorld, 1.0);
|
||||
output.gNormal = float4(normalize(input.NormalWorld), 1.0);
|
||||
output.gNormal = float4(normalize(input.NormalWorld), IsSprite);
|
||||
output.gAlbedo = float4(AlbedoValue, 1.0);
|
||||
output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0);
|
||||
|
||||
|
@ -125,10 +132,12 @@ PixelOutput AlbedoPS(PixelInput input)
|
|||
PixelOutput output;
|
||||
|
||||
output.gPosition = float4(input.PositionWorld, 1.0);
|
||||
output.gNormal = float4(normalize(input.NormalWorld), 1.0);
|
||||
output.gNormal = float4(normalize(input.NormalWorld), IsSprite);
|
||||
output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord);
|
||||
output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0);
|
||||
|
||||
if (output.gAlbedo.a == 0.0) { discard; }
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
@ -137,7 +146,7 @@ PixelOutput MetallicRoughnessPS(PixelInput input)
|
|||
PixelOutput output;
|
||||
|
||||
output.gPosition = float4(input.PositionWorld, 1.0);
|
||||
output.gNormal = float4(normalize(input.NormalWorld), 1.0);
|
||||
output.gNormal = float4(normalize(input.NormalWorld), IsSprite);
|
||||
output.gAlbedo = float4(AlbedoValue, 1.0);
|
||||
output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord);
|
||||
|
||||
|
@ -149,7 +158,7 @@ PixelOutput NormalPS(PixelInput input)
|
|||
PixelOutput output;
|
||||
|
||||
output.gPosition = float4(input.PositionWorld, 1.0);
|
||||
output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), 1.0);
|
||||
output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), IsSprite);
|
||||
output.gAlbedo = float4(AlbedoValue, 1.0);
|
||||
output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0);
|
||||
|
||||
|
@ -161,10 +170,12 @@ PixelOutput AlbedoMetallicRoughnessPS(PixelInput input)
|
|||
PixelOutput output;
|
||||
|
||||
output.gPosition = float4(input.PositionWorld, 1.0);
|
||||
output.gNormal = float4(normalize(input.NormalWorld), 1.0);
|
||||
output.gNormal = float4(normalize(input.NormalWorld), IsSprite);
|
||||
output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord);
|
||||
output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord);
|
||||
|
||||
if (output.gAlbedo.a == 0.0) { discard; }
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
@ -173,10 +184,12 @@ PixelOutput AlbedoNormalPS(PixelInput input)
|
|||
PixelOutput output;
|
||||
|
||||
output.gPosition = float4(input.PositionWorld, 1.0);
|
||||
output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), 1.0);
|
||||
output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), IsSprite);
|
||||
output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord);
|
||||
output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0);
|
||||
|
||||
if (output.gAlbedo.a == 0.0) { discard; }
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
@ -185,7 +198,7 @@ PixelOutput MetallicRoughnessNormalPS(PixelInput input)
|
|||
PixelOutput output;
|
||||
|
||||
output.gPosition = float4(input.PositionWorld, 1.0);
|
||||
output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), 1.0);
|
||||
output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), IsSprite);
|
||||
output.gAlbedo = float4(AlbedoValue, 1.0);
|
||||
output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord);
|
||||
|
||||
|
@ -197,10 +210,12 @@ PixelOutput AlbedoMetallicRoughnessNormalMapPS(PixelInput input)
|
|||
PixelOutput output;
|
||||
|
||||
output.gPosition = float4(input.PositionWorld, 1.0);
|
||||
output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), 1.0);
|
||||
output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), IsSprite);
|
||||
output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord);
|
||||
output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord);
|
||||
|
||||
if (output.gAlbedo.a == 0.0) { discard; }
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Assumes you are drawing a sphere!!
|
||||
|
||||
#include "Macros.fxh" //from FNA
|
||||
#include "Lighting.fxh"
|
||||
#include "Lighting.fxh"
|
||||
#include "Shadow.fxh"
|
||||
|
||||
DECLARE_TEXTURE(gPosition, 0);
|
||||
|
@ -13,7 +13,7 @@ DECLARE_CUBEMAP(shadowMap, 4);
|
|||
BEGIN_CONSTANTS
|
||||
|
||||
float3 EyePosition _ps(c0) _cb(c0);
|
||||
|
||||
|
||||
float3 PointLightPosition _ps(c1) _cb(c1);
|
||||
float3 PointLightColor _ps(c2) _cb(c2);
|
||||
|
||||
|
@ -42,7 +42,7 @@ PixelInput main_vs(VertexInput input)
|
|||
|
||||
output.Position = mul(input.Position, WorldViewProjection);
|
||||
output.ScreenPosition = output.Position;
|
||||
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
@ -78,19 +78,34 @@ float4 main_ps(PixelInput input) : SV_TARGET0
|
|||
{
|
||||
input.ScreenPosition.xy /= input.ScreenPosition.w;
|
||||
float2 texCoord = 0.5f * float2(input.ScreenPosition.x,-input.ScreenPosition.y) + 0.5f;
|
||||
|
||||
|
||||
float3 worldPosition = SAMPLE_TEXTURE(gPosition, texCoord).rgb;
|
||||
float3 normal = SAMPLE_TEXTURE(gNormal, texCoord).xyz;
|
||||
float4 normalSample = SAMPLE_TEXTURE(gNormal, texCoord);
|
||||
float3 normal = normalSample.xyz;
|
||||
float isSprite = normalSample.a;
|
||||
float3 albedo = SAMPLE_TEXTURE(gAlbedo, texCoord).rgb;
|
||||
float2 metallicRoughness = SAMPLE_TEXTURE(gMetallicRoughness, texCoord).rg;
|
||||
|
||||
return ComputeColor(
|
||||
worldPosition,
|
||||
normal,
|
||||
albedo,
|
||||
metallicRoughness.r,
|
||||
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
|
||||
|
|
|
@ -43,8 +43,8 @@ PixelShaderInput main_vs(VertexShaderInput input)
|
|||
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;
|
||||
texCoord.x = (input.TexCoord.x * UVOffsetAndDimensions.z) + UVOffsetAndDimensions.x;
|
||||
texCoord.y = (input.TexCoord.y * UVOffsetAndDimensions.w) + UVOffsetAndDimensions.y;
|
||||
output.TexCoord = texCoord;
|
||||
|
||||
return output;
|
||||
|
@ -98,6 +98,9 @@ float4 LightColor(float3 worldPosition, float3 worldNormal)
|
|||
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);
|
||||
|
@ -106,6 +109,9 @@ float4 WithoutNormalMap(PixelShaderInput input) : COLOR0
|
|||
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);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "Macros.fxh"
|
||||
|
||||
#define FLT_MAX 3.402823466e+38
|
||||
|
||||
DECLARE_TEXTURE(Texture, 0);
|
||||
DECLARE_TEXTURE(Palette, 1);
|
||||
|
||||
|
@ -40,11 +38,12 @@ float4 main_ps(PixelInput input) : SV_TARGET0
|
|||
float3 sampled_color = sampled.rgb;
|
||||
|
||||
float3 closest_color = float3(0, 0, 0);
|
||||
float closest_dist = FLT_MAX;
|
||||
float closest_dist = 100000;
|
||||
|
||||
for (int i = 0; i < PaletteWidth; i++)
|
||||
{
|
||||
float3 palette_color = SAMPLE_TEXTURE(Palette, float2(i / (float)PaletteWidth, 0));
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Kav
|
||||
{
|
||||
public interface ITransformable
|
||||
{
|
||||
Matrix TransformMatrix { get; }
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ using Microsoft.Xna.Framework.Graphics;
|
|||
|
||||
namespace Kav
|
||||
{
|
||||
public class MeshSprite : ICullable, IIndexDrawable
|
||||
public class SpriteMesh : ICullable, IIndexDrawable
|
||||
{
|
||||
public enum FlipOptions
|
||||
{
|
||||
|
@ -14,7 +14,6 @@ namespace Kav
|
|||
Both
|
||||
}
|
||||
|
||||
private static readonly int PixelScale = 40;
|
||||
private static readonly short[] Indices = new short[]
|
||||
{
|
||||
0,
|
||||
|
@ -25,21 +24,16 @@ namespace Kav
|
|||
2
|
||||
};
|
||||
|
||||
public Texture2D Texture { get; }
|
||||
public Texture2D Normal { get; }
|
||||
|
||||
public IndexBuffer IndexBuffer { get; }
|
||||
public VertexBuffer VertexBuffer { get; }
|
||||
public BoundingBox BoundingBox { get; }
|
||||
|
||||
public MeshSprite(
|
||||
public SpriteMesh(
|
||||
GraphicsDevice graphicsDevice,
|
||||
Texture2D texture,
|
||||
int width,
|
||||
int height,
|
||||
FlipOptions flipOptions
|
||||
) {
|
||||
Texture = texture;
|
||||
Normal = null;
|
||||
|
||||
IndexBuffer = new IndexBuffer(
|
||||
graphicsDevice,
|
||||
IndexElementSize.SixteenBits,
|
||||
|
@ -48,7 +42,7 @@ namespace Kav
|
|||
);
|
||||
IndexBuffer.SetData(Indices);
|
||||
|
||||
var vertexArray = GenerateVertexArray(Texture, flipOptions);
|
||||
var vertexArray = GenerateVertexArray(width, height, flipOptions);
|
||||
|
||||
VertexBuffer = new VertexBuffer(
|
||||
graphicsDevice,
|
||||
|
@ -61,38 +55,11 @@ namespace Kav
|
|||
BoundingBox = BoundingBox.CreateFromPoints(Positions(vertexArray));
|
||||
}
|
||||
|
||||
public MeshSprite(
|
||||
GraphicsDevice graphicsDevice,
|
||||
Texture2D texture,
|
||||
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)
|
||||
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;
|
||||
|
@ -112,20 +79,20 @@ namespace Kav
|
|||
yBottom = 0;
|
||||
}
|
||||
|
||||
result[0].Position = new Vector3(-texture.Width / 2, texture.Height / 2, 0) / PixelScale;
|
||||
result[0].Normal = new Vector3(0, 0, 1);
|
||||
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(texture.Width / 2, texture.Height / 2, 0) / PixelScale;
|
||||
result[1].Normal = new Vector3(0, 0, 1);
|
||||
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(-texture.Width / 2, -texture.Height / 2, 0) / PixelScale;
|
||||
result[2].Normal = new Vector3(0, 0, 1);
|
||||
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(texture.Width / 2, -texture.Height / 2, 0) / PixelScale;
|
||||
result[3].Normal = new Vector3(0, 0, 1);
|
||||
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;
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<RootNamespace>Kav</RootNamespace>
|
||||
<Authors>Evan Hemsley</Authors>
|
||||
<Copyright>Evan Hemsley 2020</Copyright>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<RootNamespace>Kav</RootNamespace>
|
||||
<Authors>Evan Hemsley</Authors>
|
||||
<Copyright>Evan Hemsley 2020</Copyright>
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
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; }
|
||||
}
|
||||
}
|
85
Renderer.cs
85
Renderer.cs
|
@ -125,7 +125,7 @@ namespace Kav
|
|||
) {
|
||||
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||
|
||||
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
||||
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
||||
GraphicsDevice.RasterizerState = RasterizerState.CullNone;
|
||||
GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
|
||||
GraphicsDevice.SamplerStates[1] = SamplerState.PointClamp;
|
||||
|
@ -168,14 +168,14 @@ namespace Kav
|
|||
continue;
|
||||
}
|
||||
|
||||
DiffuseLitSpriteEffect.NormalMapEnabled = data.MeshSprite.Normal != null;
|
||||
DiffuseLitSpriteEffect.NormalMapEnabled = data.Normal != null;
|
||||
|
||||
DiffuseLitSpriteEffect.World = matrix;
|
||||
DiffuseLitSpriteEffect.UVOffset = data.UVOffset.Offset;
|
||||
DiffuseLitSpriteEffect.SubTextureDimensions = data.UVOffset.Percentage;
|
||||
|
||||
GraphicsDevice.Textures[0] = data.MeshSprite.Texture;
|
||||
GraphicsDevice.Textures[1] = data.MeshSprite.Normal;
|
||||
GraphicsDevice.Textures[0] = data.Texture;
|
||||
GraphicsDevice.Textures[1] = data.Normal;
|
||||
|
||||
GraphicsDevice.SetVertexBuffer(data.MeshSprite.VertexBuffer);
|
||||
GraphicsDevice.Indices = data.MeshSprite.IndexBuffer;
|
||||
|
@ -196,6 +196,51 @@ 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(
|
||||
PerspectiveCamera camera,
|
||||
Matrix transform,
|
||||
|
@ -333,6 +378,21 @@ namespace Kav
|
|||
);
|
||||
}
|
||||
|
||||
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(
|
||||
RenderTarget2D renderTarget,
|
||||
PerspectiveCamera camera,
|
||||
|
@ -376,6 +436,7 @@ namespace Kav
|
|||
GraphicsDevice.BlendState = BlendState.Opaque;
|
||||
|
||||
Deferred_GBufferEffect.HardwareInstancingEnabled = true;
|
||||
Deferred_GBufferEffect.IsSprite = false;
|
||||
|
||||
Deferred_GBufferEffect.Albedo = drawable.Albedo;
|
||||
Deferred_GBufferEffect.Metallic = drawable.Metallic;
|
||||
|
@ -423,6 +484,7 @@ namespace Kav
|
|||
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
||||
GraphicsDevice.BlendState = BlendState.Opaque;
|
||||
|
||||
Deferred_GBufferEffect.IsSprite = false;
|
||||
Deferred_GBufferEffect.HardwareInstancingEnabled = false;
|
||||
Deferred_GBufferEffect.View = camera.View;
|
||||
Deferred_GBufferEffect.Projection = camera.Projection;
|
||||
|
@ -942,6 +1004,21 @@ namespace Kav
|
|||
return (containment == ContainmentType.Disjoint);
|
||||
}
|
||||
|
||||
private static IEnumerable<T> FrustumCull<T>(
|
||||
BoundingFrustum boundingFrustum,
|
||||
IEnumerable<T> cullableTransformables
|
||||
) where T : ICullable, ITransformable {
|
||||
foreach (var cullableTransformable in cullableTransformables)
|
||||
{
|
||||
var boundingBox = TransformedBoundingBox(cullableTransformable.BoundingBox, cullableTransformable.TransformMatrix);
|
||||
var containment = boundingFrustum.Contains(boundingBox);
|
||||
if (containment != ContainmentType.Disjoint)
|
||||
{
|
||||
yield return cullableTransformable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static BoundingBox TransformedBoundingBox(BoundingBox boundingBox, Matrix matrix)
|
||||
{
|
||||
var center = (boundingBox.Min + boundingBox.Max) / 2f;
|
||||
|
|
Loading…
Reference in New Issue