optimize PBR effect setters

PBR
cosmonaut 2020-08-04 01:14:45 -07:00
parent 4a5f0d4461
commit 39fec5062c
2 changed files with 84 additions and 51 deletions

14
Effects/EffectHelpers.cs Normal file
View File

@ -0,0 +1,14 @@
using System;
namespace Smuggler
{
[Flags]
internal enum EffectDirtyFlags
{
WorldViewProj = 1,
World = 2,
EyePosition = 4,
ShaderIndex = 8,
All = -1
}
}

View File

@ -83,6 +83,8 @@ namespace Smuggler
bool metallicRoughnessMapEnabled = false; bool metallicRoughnessMapEnabled = false;
bool normalMapEnabled = false; bool normalMapEnabled = false;
EffectDirtyFlags dirtyFlags= EffectDirtyFlags.All;
// FIXME: lazily set properties for performance // FIXME: lazily set properties for performance
public Matrix World public Matrix World
@ -91,15 +93,7 @@ namespace Smuggler
set set
{ {
world = value; world = value;
worldParam.SetValue(world); dirtyFlags |= EffectDirtyFlags.World | EffectDirtyFlags.WorldViewProj;
Matrix.Multiply(ref world, ref view, out Matrix worldView);
Matrix.Multiply(ref worldView, ref projection, out Matrix worldViewProj);
worldViewProjectionParam.SetValue(worldViewProj);
Matrix.Invert(ref world, out Matrix worldInverse);
Matrix.Transpose(ref worldInverse, out Matrix worldInverseTranspose);
worldInverseTransposeParam.SetValue(worldInverseTranspose);
} }
} }
@ -109,13 +103,7 @@ namespace Smuggler
set set
{ {
view = value; view = value;
dirtyFlags |= EffectDirtyFlags.WorldViewProj | EffectDirtyFlags.EyePosition;
Matrix.Multiply(ref world, ref view, out Matrix worldView);
Matrix.Multiply(ref worldView, ref projection, out Matrix worldViewProj);
worldViewProjectionParam.SetValue(worldViewProj);
Matrix.Invert(ref view, out Matrix inverseView);
eyePositionParam.SetValue(inverseView.Translation);
} }
} }
@ -125,10 +113,7 @@ namespace Smuggler
set set
{ {
projection = value; projection = value;
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
Matrix.Multiply(ref world, ref view, out Matrix worldView);
Matrix.Multiply(ref worldView, ref projection, out Matrix worldViewProj);
worldViewProjectionParam.SetValue(worldViewProj);
} }
} }
@ -185,7 +170,7 @@ namespace Smuggler
{ {
albedoTextureParam.SetValue(value); albedoTextureParam.SetValue(value);
albedoTextureEnabled = value != null; albedoTextureEnabled = value != null;
System.Console.WriteLine(albedoTextureEnabled); dirtyFlags |= EffectDirtyFlags.ShaderIndex;
} }
} }
@ -196,6 +181,7 @@ namespace Smuggler
{ {
normalTextureParam.SetValue(value); normalTextureParam.SetValue(value);
normalMapEnabled = value != null; normalMapEnabled = value != null;
dirtyFlags |= EffectDirtyFlags.ShaderIndex;
} }
} }
@ -218,6 +204,7 @@ namespace Smuggler
{ {
metallicRoughnessTextureParam.SetValue(value); metallicRoughnessTextureParam.SetValue(value);
metallicRoughnessMapEnabled = value != null; metallicRoughnessMapEnabled = value != null;
dirtyFlags |= EffectDirtyFlags.ShaderIndex;
} }
} }
@ -287,41 +274,73 @@ namespace Smuggler
return new PBREffect(this); return new PBREffect(this);
} }
// FIXME: do param applications here for performance
protected override void OnApply() protected override void OnApply()
{ {
int shaderIndex = 0; if ((dirtyFlags & EffectDirtyFlags.World) != 0)
{
worldParam.SetValue(world);
if (albedoTextureEnabled && metallicRoughnessMapEnabled && normalMapEnabled) Matrix.Invert(ref world, out Matrix worldInverse);
{ Matrix.Transpose(ref worldInverse, out Matrix worldInverseTranspose);
shaderIndex = 7; worldInverseTransposeParam.SetValue(worldInverseTranspose);
}
else if (metallicRoughnessMapEnabled && normalMapEnabled) dirtyFlags &= ~EffectDirtyFlags.World;
{
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); if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0)
{
Matrix.Multiply(ref world, ref view, out Matrix worldView);
Matrix.Multiply(ref worldView, ref projection, out Matrix worldViewProj);
worldViewProjectionParam.SetValue(worldViewProj);
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
}
if ((dirtyFlags & EffectDirtyFlags.EyePosition) != 0)
{
Matrix.Invert(ref view, out Matrix inverseView);
eyePositionParam.SetValue(inverseView.Translation);
dirtyFlags &= ~EffectDirtyFlags.EyePosition;
}
if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 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.ShaderIndex;
}
} }
void CacheEffectParameters(PBREffect cloneSource) void CacheEffectParameters(PBREffect cloneSource)