draw zero alpha pixels in g buffer

sprite_light_experimental
cosmonaut 2020-12-12 00:17:10 -08:00
parent c468d6276d
commit 3a0aa8894d
6 changed files with 126 additions and 5 deletions

View File

@ -3,7 +3,7 @@ using Microsoft.Xna.Framework.Graphics;
namespace Kav.Data namespace Kav.Data
{ {
public struct MeshSpriteDrawData public struct MeshSpriteDrawData : IIndexDrawable, ICullable, ITransformable
{ {
public SpriteMesh MeshSprite { get; } public SpriteMesh MeshSprite { get; }
public Texture2D Texture { get; } public Texture2D Texture { get; }
@ -12,6 +12,10 @@ namespace Kav.Data
public Matrix TransformMatrix { get; } public Matrix TransformMatrix { get; }
public UVData UVOffset { get; } public UVData UVOffset { get; }
public IndexBuffer IndexBuffer => MeshSprite.IndexBuffer;
public VertexBuffer VertexBuffer => MeshSprite.VertexBuffer;
public BoundingBox BoundingBox => MeshSprite.BoundingBox;
public MeshSpriteDrawData( public MeshSpriteDrawData(
SpriteMesh meshSprite, SpriteMesh meshSprite,
Texture2D texture, Texture2D texture,

View File

@ -16,6 +16,8 @@ namespace Kav
EffectParameter metallicParam; EffectParameter metallicParam;
EffectParameter roughnessParam; EffectParameter roughnessParam;
EffectParameter uvOffsetAndDimensionsParam;
EffectParameter numTextureRowsParam; EffectParameter numTextureRowsParam;
EffectParameter numTextureColumnsParam; EffectParameter numTextureColumnsParam;
@ -30,6 +32,9 @@ namespace Kav
float metallic; float metallic;
float roughness; float roughness;
Vector2 uvOffset;
Vector2 subTextureDimensions;
int numTextureRows = 1; int numTextureRows = 1;
int numTextureColumns = 1; int numTextureColumns = 1;
@ -153,6 +158,26 @@ 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 HardwareInstancingEnabled public bool HardwareInstancingEnabled
{ {
get { return hardwareInstancingEnabled; } get { return hardwareInstancingEnabled; }
@ -210,6 +235,16 @@ 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) if ((dirtyFlags & EffectDirtyFlags.VertexShaderIndex) != 0)
{ {
int vertexShaderIndex = 0; int vertexShaderIndex = 0;
@ -277,6 +312,8 @@ namespace Kav
numTextureRowsParam = Parameters["NumTextureRows"]; numTextureRowsParam = Parameters["NumTextureRows"];
numTextureColumnsParam = Parameters["NumTextureColumns"]; numTextureColumnsParam = Parameters["NumTextureColumns"];
uvOffsetAndDimensionsParam = Parameters["UVOffsetAndDimensions"];
shaderIndexParam = Parameters["PixelShaderIndex"]; shaderIndexParam = Parameters["PixelShaderIndex"];
vertexShaderIndexParam = Parameters["VertexShaderIndex"]; vertexShaderIndexParam = Parameters["VertexShaderIndex"];
} }

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

Binary file not shown.

View File

@ -4,6 +4,8 @@ DECLARE_TEXTURE(AlbedoTexture, 0);
DECLARE_TEXTURE(NormalTexture, 1); DECLARE_TEXTURE(NormalTexture, 1);
DECLARE_TEXTURE(MetallicRoughnessTexture, 2); DECLARE_TEXTURE(MetallicRoughnessTexture, 2);
float4 UVOffsetAndDimensions;
BEGIN_CONSTANTS BEGIN_CONSTANTS
float3 AlbedoValue _ps(c0) _cb(c0); float3 AlbedoValue _ps(c0) _cb(c0);
@ -51,7 +53,11 @@ PixelInput main_vs(VertexInput input)
output.PositionWorld = mul(input.Position, World).xyz; output.PositionWorld = mul(input.Position, World).xyz;
output.NormalWorld = normalize(mul(input.Normal, World)); 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); float4x4 worldViewProjection = mul(World, ViewProjection);
output.Position = mul(input.Position, worldViewProjection); output.Position = mul(input.Position, worldViewProjection);
@ -60,7 +66,7 @@ PixelInput main_vs(VertexInput input)
} }
PixelInput instanced_vs( PixelInput instanced_vs(
VertexInput input, VertexInput input,
float3 Translation : TEXCOORD2, float3 Translation : TEXCOORD2,
float2 UVOffset : TEXCOORD5 float2 UVOffset : TEXCOORD5
) { ) {
@ -129,6 +135,8 @@ PixelOutput AlbedoPS(PixelInput input)
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;
} }
@ -165,6 +173,8 @@ PixelOutput AlbedoMetallicRoughnessPS(PixelInput input)
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;
} }
@ -177,6 +187,8 @@ PixelOutput AlbedoNormalPS(PixelInput input)
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;
} }
@ -201,6 +213,8 @@ PixelOutput AlbedoMetallicRoughnessNormalMapPS(PixelInput input)
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;
} }

View File

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

View File

@ -196,6 +196,48 @@ namespace Kav
} }
} }
public void RenderMeshSpriteGBuffer(
RenderTargetBinding[] gBuffer,
PerspectiveCamera camera,
IEnumerable<MeshSpriteDrawData> meshSpriteDrawDatas
) {
GraphicsDevice.SetRenderTargets(gBuffer);
GraphicsDevice.RasterizerState = RasterizerState.CullNone;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.BlendState = BlendState.AlphaBlend;
Deferred_GBufferEffect.HardwareInstancingEnabled = false;
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,
@ -942,6 +984,21 @@ namespace Kav
return (containment == ContainmentType.Disjoint); 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) private static BoundingBox TransformedBoundingBox(BoundingBox boundingBox, Matrix matrix)
{ {
var center = (boundingBox.Min + boundingBox.Max) / 2f; var center = (boundingBox.Min + boundingBox.Max) / 2f;