Smuggler/Effects/PBREffect.cs

161 lines
4.6 KiB
C#

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Smuggler
{
public struct PBRLight
{
public Vector3 direction;
public Vector3 radiance;
public PBRLight(Vector3 direction, Vector3 radiance)
{
this.direction = direction;
this.radiance = radiance;
}
}
public class PBRLightCollection
{
readonly EffectParameter directionParam;
readonly EffectParameter radianceParam;
private readonly Vector3[] directions = new Vector3[PBREffect.NUM_LIGHTS];
private readonly Vector3[] radiances = new Vector3[PBREffect.NUM_LIGHTS];
public PBRLightCollection(EffectParameter directionParam, EffectParameter radianceParam)
{
this.directionParam = directionParam;
this.radianceParam = radianceParam;
}
public PBRLightCollection(PBRLightCollection other)
{
for (int i = 0; i < PBREffect.NUM_LIGHTS; i++)
{
directions[i] = other.directions[i];
radiances[i] = other.radiances[i];
}
}
public PBRLight this[int index]
{
get
{
return new PBRLight(directions[index], radiances[index]);
}
set
{
directions[index] = value.direction;
radiances[index] = value.radiance;
directionParam.SetValue(directions);
radianceParam.SetValue(radiances);
}
}
}
public class PBREffect : Effect
{
public static readonly int NUM_LIGHTS = 3;
readonly EffectParameter viewProjectionParam;
readonly EffectParameter sceneRotationParam;
readonly EffectParameter eyePositionParam;
readonly EffectParameter specularTextureLevelsParam;
readonly EffectParameter albedoTextureParam;
Matrix world = Matrix.Identity;
Matrix view = Matrix.Identity;
Matrix projection = Matrix.Identity;
Vector3 eyePosition = Vector3.Zero;
int specularTextureLevels = 0;
public Matrix World
{
get { return world; }
set
{
world = value;
sceneRotationParam.SetValue(world);
}
}
public Matrix View
{
get { return view; }
set
{
view = value;
viewProjectionParam.SetValue(projection * view);
eyePositionParam.SetValue(Matrix.Invert(view).Backward);
}
}
public Matrix Projection
{
get { return projection; }
set
{
projection = value;
viewProjectionParam.SetValue(projection * view);
}
}
public PBRLightCollection Lights { get; }
public int SpecularTextureLevels
{
get { return specularTextureLevels; }
set
{
specularTextureLevels = value;
specularTextureLevelsParam.SetValue(specularTextureLevels);
}
}
public Texture2D AlbedoTexture
{
get { return albedoTextureParam.GetValueTexture2D(); }
set { albedoTextureParam.SetValue(value); }
}
public PBREffect(GraphicsDevice graphicsDevice, byte[] effectCode) : base(graphicsDevice, effectCode)
{
viewProjectionParam = Parameters["viewProjectionMatrix"];
sceneRotationParam = Parameters["sceneRotationMatrix"];
eyePositionParam = Parameters["eyePosition"];
specularTextureLevelsParam = Parameters["specularTextureLevels"];
Lights = new PBRLightCollection(Parameters["directions"], Parameters["radiance"]);
}
protected PBREffect(PBREffect cloneSource) : base(cloneSource)
{
viewProjectionParam = Parameters["viewProjectionMatrix"];
sceneRotationParam = Parameters["sceneRotationMatrix"];
eyePositionParam = Parameters["eyePosition"];
specularTextureLevelsParam = Parameters["specularTextureLevels"];
World = cloneSource.World;
View = cloneSource.View;
Projection = cloneSource.Projection;
Lights = new PBRLightCollection(cloneSource.Lights);
}
public override Effect Clone()
{
return new PBREffect(this);
}
// FIXME: do param applications here for performance
protected override void OnApply()
{
base.OnApply();
}
}
}