161 lines
4.6 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|