Create Graphics library. (#316)

* Fix BoundingRect unit tests.

* Create `graphics` library.
This commit is contained in:
Lucas Girouard-Stranks
2016-11-27 22:51:59 +10:00
committed by Dylan Wilson
parent d1ffba93f2
commit d0c621d0dc
35 changed files with 139 additions and 71 deletions
@@ -0,0 +1,74 @@
using Microsoft.Xna.Framework.Graphics;
namespace MonoGame.Extended.Graphics.Effects
{
/// <summary>
/// An <see cref="Effect" /> that allows 2D objects, within a 3D context, to be represented on a 2D monitor.
/// </summary>
/// <seealso cref="Effect" />
/// <seealso cref="IMatrixChainEffect" />
public class DefaultEffect2D : MatrixChainEffect, ITexture2DEffect
{
private Texture2D _texture;
private bool _textureIsDirty;
private EffectParameter _textureParameter;
/// <summary>
/// Initializes a new instance of the <see cref="DefaultEffect2D" /> class.
/// </summary>
/// <param name="graphicsDevice">The graphics device.</param>
public DefaultEffect2D(GraphicsDevice graphicsDevice)
: base(graphicsDevice, EffectResource.DefaultEffect2D.Bytecode)
{
CacheEffectParameters();
}
/// <summary>
/// Initializes a new instance of the <see cref="DefaultEffect2D" /> class.
/// </summary>
/// <param name="cloneSource">The clone source.</param>
public DefaultEffect2D(Effect cloneSource)
: base(cloneSource)
{
CacheEffectParameters();
}
/// <summary>
/// Gets or sets the <see cref="Texture2D" />.
/// </summary>
/// <value>
/// The <see cref="Texture2D" />.
/// </value>
public Texture2D Texture
{
get { return _texture; }
set
{
_texture = value;
_textureIsDirty = true;
}
}
private void CacheEffectParameters()
{
_textureParameter = Parameters["TextureSampler+Texture"];
}
/// <summary>
/// Computes derived parameter values immediately before applying the effect.
/// </summary>
protected override bool OnApply()
{
var result = base.OnApply();
// ReSharper disable once InvertIf
if (_textureIsDirty)
{
_textureParameter.SetValue(_texture);
_textureIsDirty = false;
}
return result;
}
}
}
@@ -0,0 +1,75 @@
using System.IO;
using System.Reflection;
using Microsoft.Xna.Framework.Graphics;
namespace MonoGame.Extended.Graphics.Effects
{
/// <summary>
/// Reperesents the bytecode of an <see cref="Effect" /> that is encapsulated inside a compiled assembly.
/// </summary>
/// <remarks>
/// <para>
/// Files that are encapsulated inside a compiled assembly are commonly known as Manifiest or embedded resources.
/// Since embedded resources are added to the assembly at compiled time, they can not be accidentally deleted or
/// misplaced. However, if the file needs to be changed, the assembly will need to be re-compiled with the changed
/// file.
/// </para>
/// <para>
/// To add an embedded resource file to an assembly, first add it to the project and then change the Build Action
/// in the Properties of the file to <code>Embedded Resource</code>. The next time the project is compiled, the
/// compiler will add the file to the assembly as an embedded resource. The compiler adds namespace(s) to the
/// embedded resource so it matches with the path of where the file was added to the project.
/// </para>
/// </remarks>
public class EffectResource
{
/// <summary>
/// The <see cref="Effects.DefaultEffect2D" /> embedded into the MonoGame.Extended library.
/// </summary>
public static readonly EffectResource DefaultEffect2D =
new EffectResource("MonoGame.Extended.Graphics.Effects.Resources.DefaultEffect2D.mgfxo");
private readonly string _resourceName;
private volatile byte[] _bytecode;
/// <summary>
/// Initializes a new instance of the <see cref="EffectResource" /> class.
/// </summary>
/// <param name="resourceName">The name of the embedded resource. This must include the namespace(s).</param>
public EffectResource(string resourceName)
{
_resourceName = resourceName;
}
/// <summary>
/// Gets the bytecode of the <see cref="Effect" /> file.
/// </summary>
/// <value>
/// The bytecode of the <see cref="Effect" /> file.
/// </value>
public byte[] Bytecode
{
get
{
if (_bytecode != null)
return _bytecode;
lock (this)
{
if (_bytecode != null)
return _bytecode;
var assembly = typeof(EffectResource).GetTypeInfo().Assembly;
var stream = assembly.GetManifestResourceStream(_resourceName);
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
_bytecode = memoryStream.ToArray();
}
}
return _bytecode;
}
}
}
}
@@ -0,0 +1,54 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MonoGame.Extended.Graphics.Effects
{
/// <summary>
/// Defines an <see cref="Effect" /> that uses the standard chain of matrix transformations to represent a 3D object on
/// a 2D monitor.
/// </summary>
public interface IMatrixChainEffect
{
/// <summary>
/// Gets or sets the model-to-world <see cref="Matrix" />.
/// </summary>
/// <value>
/// The model-to-world <see cref="Matrix" />.
/// </value>
Matrix World { get; set; }
/// <summary>
/// Gets or sets the world-to-view <see cref="Matrix" />.
/// </summary>
/// <value>
/// The world-to-view <see cref="Matrix" />.
/// </value>
Matrix View { get; set; }
/// <summary>
/// Gets or sets the view-to-projection <see cref="Matrix" />.
/// </summary>
/// <value>
/// The view-to-projection <see cref="Matrix" />.
/// </value>
Matrix Projection { get; set; }
/// <summary>
/// Sets the model-to-world <see cref="Matrix" />.
/// </summary>
/// <param name="world">The model-to-world <see cref="Matrix" />.</param>
void SetWorld(ref Matrix world);
/// <summary>
/// Sets the world-to-view <see cref="Matrix" />.
/// </summary>
/// <param name="view">The world-to-view <see cref="Matrix" />.</param>
void SetView(ref Matrix view);
/// <summary>
/// Sets the view-to-projection <see cref="Matrix" />.
/// </summary>
/// <param name="projection">The view-to-projection <see cref="Matrix" />.</param>
void SetProjection(ref Matrix projection);
}
}
@@ -0,0 +1,18 @@
using Microsoft.Xna.Framework.Graphics;
namespace MonoGame.Extended.Graphics.Effects
{
/// <summary>
/// Defines an <see cref="Effect" /> that uses a <see cref="Texture2D" />.
/// </summary>
public interface ITexture2DEffect
{
/// <summary>
/// Gets or sets the <see cref="Texture2D" />.
/// </summary>
/// <value>
/// The <see cref="Texture2D" />.
/// </value>
Texture2D Texture { get; set; }
}
}
@@ -0,0 +1,134 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MonoGame.Extended.Graphics.Effects
{
/// <summary>
/// An <see cref="Effect" /> that uses the standard chain of matrix transformations to represent a 3D object on a 2D
/// monitor.
/// </summary>
/// <seealso cref="Effect" />
/// <seealso cref="IMatrixChainEffect" />
public abstract class MatrixChainEffect : Effect, IMatrixChainEffect
{
private Matrix _projection = Matrix.Identity;
private Matrix _view = Matrix.Identity;
private Matrix _world = Matrix.Identity;
private bool _worldViewProjectionIsDirty;
private EffectParameter _worldViewProjectionParameter;
/// <summary>
/// Initializes a new instance of the <see cref="MatrixChainEffect" /> class.
/// </summary>
/// <param name="graphicsDevice">The graphics device.</param>
/// <param name="effectCode">The effect code.</param>
protected MatrixChainEffect(GraphicsDevice graphicsDevice, byte[] effectCode)
: base(graphicsDevice, effectCode)
{
CacheEffectParameters();
}
/// <summary>
/// Initializes a new instance of the <see cref="MatrixChainEffect" /> class.
/// </summary>
/// <param name="cloneSource">The clone source.</param>
protected MatrixChainEffect(Effect cloneSource)
: base(cloneSource)
{
CacheEffectParameters();
}
/// <summary>
/// Gets or sets the model-to-world <see cref="Matrix" />.
/// </summary>
/// <value>
/// The model-to-world <see cref="Matrix" />.
/// </value>
public Matrix World
{
get { return _world; }
set { SetWorld(ref value); }
}
/// <summary>
/// Gets or sets the world-to-view <see cref="Matrix" />.
/// </summary>
/// <value>
/// The world-to-view <see cref="Matrix" />.
/// </value>
public Matrix View
{
get { return _view; }
set { SetView(ref value); }
}
/// <summary>
/// Gets or sets the view-to-projection <see cref="Matrix" />.
/// </summary>
/// <value>
/// The view-to-projection <see cref="Matrix" />.
/// </value>
public Matrix Projection
{
get { return _projection; }
set { SetProjection(ref value); }
}
/// <summary>
/// Sets the model-to-world <see cref="Matrix" />.
/// </summary>
/// <param name="world">The model-to-world <see cref="Matrix" />.</param>
public void SetWorld(ref Matrix world)
{
_world = world;
_worldViewProjectionIsDirty = true;
}
/// <summary>
/// Sets the world-to-view <see cref="Matrix" />.
/// </summary>
/// <param name="view">The world-to-view <see cref="Matrix" />.</param>
public void SetView(ref Matrix view)
{
_view = view;
_worldViewProjectionIsDirty = true;
}
/// <summary>
/// Sets the view-to-projection <see cref="Matrix" />.
/// </summary>
/// <param name="projection">The view-to-projection <see cref="Matrix" />.</param>
public void SetProjection(ref Matrix projection)
{
_projection = projection;
_worldViewProjectionIsDirty = true;
}
private void CacheEffectParameters()
{
_worldViewProjectionParameter = Parameters["WorldViewProjection"];
}
/// <summary>
/// Computes derived parameter values immediately before applying the effect.
/// </summary>
protected override bool OnApply()
{
base.OnApply();
// ReSharper disable once InvertIf
if (_worldViewProjectionIsDirty)
{
_worldViewProjectionIsDirty = false;
Matrix worldViewProjection;
Matrix.Multiply(ref _world, ref _view, out worldViewProjection);
Matrix.Multiply(ref worldViewProjection, ref _projection, out worldViewProjection);
_worldViewProjectionParameter.SetValue(worldViewProjection);
}
// in MonoGame 3.6 this method won't return anything; see https://github.com/MonoGame/MonoGame/pull/5090
return false;
}
}
}
@@ -0,0 +1,56 @@
// The matrix that transforms geometry in the vertex shader
float4x4 WorldViewProjection;
// The texture used for texture sampling in the pixel shader
Texture2D<float4> Texture;
// The sampler used for texture sampling in the pixel shader
SamplerState TextureSampler;
// The information layout used as input to the vertex shader. The actual information is passed to the GPU from the CPU
struct VertexShaderInput
{
float4 Position : POSITION0;
float4 Color : COLOR0;
float2 TexureCoordinate : TEXCOORD0;
};
// The information layout used as output from the vertex shader and input to the pixel shader
struct VertexShaderOutput
{
float4 Position : SV_Position;
float4 Color : COLOR0;
float2 TexureCoordinate : TEXCOORD0;
};
// The information layout used as output from the pixel shader. The actual information is what is displayed on screen
struct PixelShaderOutput
{
float4 Color : COLOR0;
};
// The vertex shader code that transforms render geometry. The input information is from the CPU
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
output.Position = mul(input.Position, WorldViewProjection);
output.Color = input.Color;
output.TexureCoordinate = input.TexureCoordinate;
return output;
}
// The pixel shader code that determines the final color of each pixel. The input information is the output of the vertex shader
PixelShaderOutput PixelShaderFunction(VertexShaderOutput input) : SV_Target0
{
PixelShaderOutput output;
output.Color = Texture.Sample(TextureSampler, input.TexureCoordinate) * input.Color;
return output;
}
// The technique; a collection of passes to be applied, each specifying the vertex and shader to use
technique
{
pass
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
@@ -0,0 +1,6 @@
:: Can only use 2MGFX.exe on Windows...
SET PATH=%PATH%;C:\Program Files (x86)\MSBuild\MonoGame\v3.0\Tools
2MGFX.exe %cd%\DefaultEffect2D.fx %cd%\DefaultEffect2D.mgfxo
pause