Kav/Effects/DeferredPBR_GBufferEffect.cs

322 lines
9.2 KiB
C#

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
public class DeferredPBR_GBufferEffect : Effect, TransformEffect
{
EffectParameter worldParam;
EffectParameter viewProjectionParam;
EffectParameter albedoTextureParam;
EffectParameter normalTextureParam;
EffectParameter metallicRoughnessTextureParam;
EffectParameter albedoParam;
EffectParameter metallicParam;
EffectParameter roughnessParam;
EffectParameter uvOffsetAndDimensionsParam;
EffectParameter numTextureRowsParam;
EffectParameter numTextureColumnsParam;
EffectParameter vertexShaderIndexParam;
EffectParameter shaderIndexParam;
Matrix world = Matrix.Identity;
Matrix view = Matrix.Identity;
Matrix projection = Matrix.Identity;
Vector3 albedo;
float metallic;
float roughness;
Vector2 uvOffset;
Vector2 subTextureDimensions;
int numTextureRows = 1;
int numTextureColumns = 1;
bool albedoTextureEnabled = false;
bool metallicRoughnessMapEnabled = false;
bool normalMapEnabled = false;
bool hardwareInstancingEnabled = false;
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
public Matrix World
{
get { return world; }
set
{
world = value;
dirtyFlags |= EffectDirtyFlags.World;
}
}
public Matrix View
{
get { return view; }
set
{
view = value;
dirtyFlags |= EffectDirtyFlags.ViewProj | EffectDirtyFlags.EyePosition;
}
}
public Matrix Projection
{
get { return projection; }
set
{
projection = value;
dirtyFlags |= EffectDirtyFlags.ViewProj;
}
}
public Vector3 Albedo
{
get { return albedo; }
set
{
albedo = value;
albedoParam.SetValue(albedo);
}
}
public float Metallic
{
get { return metallic; }
set
{
metallic = value;
metallicParam.SetValue(metallic);
}
}
public float Roughness
{
get { return roughness; }
set
{
roughness = value;
roughnessParam.SetValue(roughness);
}
}
public Texture2D AlbedoTexture
{
get { return albedoTextureParam.GetValueTexture2D(); }
set
{
albedoTextureParam.SetValue(value);
albedoTextureEnabled = value != null;
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex;
}
}
public Texture2D NormalTexture
{
get { return normalTextureParam.GetValueTexture2D(); }
set
{
normalTextureParam.SetValue(value);
normalMapEnabled = value != null;
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex;
}
}
public Texture2D MetallicRoughnessTexture
{
get { return metallicRoughnessTextureParam.GetValueTexture2D(); }
set
{
metallicRoughnessTextureParam.SetValue(value);
metallicRoughnessMapEnabled = value != null;
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex;
}
}
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 HardwareInstancingEnabled
{
get { return hardwareInstancingEnabled; }
set
{
if (value != hardwareInstancingEnabled)
{
hardwareInstancingEnabled = value;
dirtyFlags |= EffectDirtyFlags.VertexShaderIndex;
}
}
}
public DeferredPBR_GBufferEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DeferredPBR_GBufferEffect)
{
CacheEffectParameters();
}
protected DeferredPBR_GBufferEffect(DeferredPBR_GBufferEffect cloneSource) : base(cloneSource)
{
CacheEffectParameters();
World = cloneSource.World;
View = cloneSource.View;
Projection = cloneSource.Projection;
AlbedoTexture = cloneSource.AlbedoTexture;
NormalTexture = cloneSource.NormalTexture;
MetallicRoughnessTexture = cloneSource.MetallicRoughnessTexture;
Albedo = cloneSource.Albedo;
Metallic = cloneSource.Metallic;
Roughness = cloneSource.Roughness;
}
public override Effect Clone()
{
return new DeferredPBR_GBufferEffect(this);
}
protected override void OnApply()
{
if ((dirtyFlags & EffectDirtyFlags.World) != 0)
{
worldParam.SetValue(world);
dirtyFlags &= ~EffectDirtyFlags.World;
}
if ((dirtyFlags & EffectDirtyFlags.ViewProj) != 0)
{
Matrix.Multiply(ref view, ref projection, out Matrix viewProj);
viewProjectionParam.SetValue(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)
{
int shaderIndex = 0;
if (albedoTextureEnabled && metallicRoughnessMapEnabled && normalMapEnabled)
{
shaderIndex = 7;
}
else if (metallicRoughnessMapEnabled && normalMapEnabled)
{
shaderIndex = 6;
}
else if (albedoTextureEnabled && normalMapEnabled)
{
shaderIndex = 5;
}
else if (albedoTextureEnabled && metallicRoughnessMapEnabled)
{
shaderIndex = 4;
}
else if (normalMapEnabled)
{
shaderIndex = 3;
}
else if (metallicRoughnessMapEnabled)
{
shaderIndex = 2;
}
else if (albedoTextureEnabled)
{
shaderIndex = 1;
}
shaderIndexParam.SetValue(shaderIndex);
dirtyFlags &= ~EffectDirtyFlags.PixelShaderIndex;
}
}
void CacheEffectParameters()
{
worldParam = Parameters["World"];
viewProjectionParam = Parameters["ViewProjection"];
albedoTextureParam = Parameters["AlbedoTexture"];
normalTextureParam = Parameters["NormalTexture"];
metallicRoughnessTextureParam = Parameters["MetallicRoughnessTexture"];
albedoParam = Parameters["AlbedoValue"];
metallicParam = Parameters["MetallicValue"];
roughnessParam = Parameters["RoughnessValue"];
numTextureRowsParam = Parameters["NumTextureRows"];
numTextureColumnsParam = Parameters["NumTextureColumns"];
uvOffsetAndDimensionsParam = Parameters["UVOffsetAndDimensions"];
shaderIndexParam = Parameters["PixelShaderIndex"];
vertexShaderIndexParam = Parameters["VertexShaderIndex"];
}
}
}