- Implemented the SkinnedEffect class (not tested yet, sample will come soon)

- Optimizations in the SpriteBatch and SpriteFont classes
This commit is contained in:
SND\AstrorEnales_cp 2012-09-11 13:51:20 +00:00
parent 8b735c16c2
commit 7350ca3d3a
10 changed files with 879 additions and 706 deletions

View File

@ -67,6 +67,8 @@ namespace ANX.Framework.Graphics
{ {
this.width = width; this.width = width;
this.height = height; this.height = height;
OneOverWidth = 1f / width;
OneOverHeight = 1f / height;
base.levelCount = 1; base.levelCount = 1;
base.format = SurfaceFormat.Color; base.format = SurfaceFormat.Color;

View File

@ -1,34 +1,189 @@
#region Using Statements
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ANX.Framework.NonXNA; using ANX.Framework.NonXNA;
using ANX.Framework.Graphics; using ANX.Framework.NonXNA.Development;
#endregion // Using Statements
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license // For details see: http://anxframework.codeplex.com/license
namespace ANX.Framework.Graphics namespace ANX.Framework.Graphics
{ {
[PercentageComplete(100)]
[TestState(TestStateAttribute.TestState.Untested)]
[Developer("AstrorEnales")]
public class SkinnedEffect : Effect, IEffectMatrices, IEffectLights, IEffectFog public class SkinnedEffect : Effect, IEffectMatrices, IEffectLights, IEffectFog
{ {
public const int MaxBones = 72;
#region Private
private Matrix world;
private Matrix view;
private Matrix projection;
private bool preferPerPixelLighting;
private bool isFogEnabled;
private Vector3 diffuseColor;
private Vector3 specularColor;
private Vector3 fogColor;
private Vector3 emissiveColor;
private Vector3 ambientLightColor;
private Matrix[] bones;
private int weightsPerBone;
#endregion
#region Public
public float FogEnd { get; set; }
public float FogStart { get; set; }
public Texture2D Texture { get; set; }
public float Alpha { get; set; }
public float SpecularPower { get; set; }
public DirectionalLight DirectionalLight0 { get; private set; }
public DirectionalLight DirectionalLight1 { get; private set; }
public DirectionalLight DirectionalLight2 { get; private set; }
public int WeightsPerVertex
{
get
{
return weightsPerBone;
}
set
{
if (value != 1 && value != 2 && value != 4)
throw new ArgumentOutOfRangeException("Weights per bone only allows 1, 2 or 4 as value!");
weightsPerBone = value;
}
}
public bool PreferPerPixelLighting
{
get { return preferPerPixelLighting; }
set
{
preferPerPixelLighting = value;
SelectTechnique();
}
}
public Matrix Projection
{
get { return projection; }
set { projection = value; }
}
public Matrix View
{
get { return view; }
set { view = value; }
}
public Matrix World
{
get { return world; }
set { world = value; }
}
public Vector3 AmbientLightColor
{
get { return ambientLightColor; }
set { ambientLightColor = value; }
}
public bool LightingEnabled
{
get { return true; }
set
{
if (value == false)
throw new NotSupportedException("SkinnedEffect without Lighting isn't supported!");
}
}
public Vector3 FogColor
{
get { return fogColor; }
set { fogColor = value; }
}
public bool FogEnabled
{
get { return isFogEnabled; }
set
{
isFogEnabled = value;
SelectTechnique();
}
}
public Vector3 DiffuseColor
{
get { return diffuseColor; }
set { diffuseColor = value; }
}
public Vector3 EmissiveColor
{
get { return emissiveColor; }
set { emissiveColor = value; }
}
public Vector3 SpecularColor
{
get { return specularColor; }
set { specularColor = value; }
}
#endregion
#region Constructor
public SkinnedEffect(GraphicsDevice graphics) public SkinnedEffect(GraphicsDevice graphics)
: base(graphics, GetByteCode(), GetSourceLanguage()) : base(graphics, GetByteCode(), GetSourceLanguage())
{ {
throw new NotImplementedException(); world = Matrix.Identity;
view = Matrix.Identity;
projection = Matrix.Identity;
FogStart = 0f;
FogEnd = 1f;
Alpha = 1f;
diffuseColor = Vector3.One;
ambientLightColor = Vector3.One;
emissiveColor = Vector3.One;
specularColor = Vector3.One;
SpecularPower = 16f;
WeightsPerVertex = 4;
CreateLights(null);
DirectionalLight0.Enabled = true;
bones = new Matrix[MaxBones];
for (int index = 0; index < MaxBones; index++)
bones[index] = Matrix.Identity;
SelectTechnique();
} }
protected SkinnedEffect(SkinnedEffect cloneSource) protected SkinnedEffect(SkinnedEffect cloneSource)
: base(cloneSource) : base(cloneSource)
{ {
throw new NotImplementedException(); world = cloneSource.world;
view = cloneSource.view;
projection = cloneSource.projection;
preferPerPixelLighting = cloneSource.preferPerPixelLighting;
isFogEnabled = cloneSource.isFogEnabled;
diffuseColor = cloneSource.diffuseColor;
specularColor = cloneSource.specularColor;
fogColor = cloneSource.fogColor;
emissiveColor = cloneSource.emissiveColor;
ambientLightColor = cloneSource.ambientLightColor;
FogEnd = cloneSource.FogEnd;
FogStart = cloneSource.FogStart;
Texture = cloneSource.Texture;
SpecularPower = cloneSource.SpecularPower;
Alpha = cloneSource.Alpha;
WeightsPerVertex = cloneSource.WeightsPerVertex;
for (int index = 0; index < MaxBones; index++)
bones[index] = cloneSource.bones[index];
CreateLights(cloneSource);
SelectTechnique();
} }
#endregion
#region GetByteCode #region GetByteCode
private static byte[] GetByteCode() private static byte[] GetByteCode()
@ -46,245 +201,186 @@ namespace ANX.Framework.Graphics
} }
#endregion #endregion
#region Clone
public override Effect Clone() public override Effect Clone()
{ {
return new SkinnedEffect(this); return new SkinnedEffect(this);
} }
#endregion
public const int MaxBones = 72; #region CreateLights
private void CreateLights(SkinnedEffect cloneSource)
public bool PreferPerPixelLighting {
{ DirectionalLight0 = new DirectionalLight(Parameters["DirLight0Direction"], Parameters["DirLight0DiffuseColor"],
get null, (cloneSource != null) ? cloneSource.DirectionalLight0 : null);
{ DirectionalLight1 = new DirectionalLight(Parameters["DirLight1Direction"], Parameters["DirLight1DiffuseColor"],
throw new NotImplementedException(); null, (cloneSource != null) ? cloneSource.DirectionalLight1 : null);
} DirectionalLight2 = new DirectionalLight(Parameters["DirLight2Direction"], Parameters["DirLight2DiffuseColor"],
set null, (cloneSource != null) ? cloneSource.DirectionalLight2 : null);
{ }
throw new NotImplementedException(); #endregion
}
}
public Matrix Projection
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public Matrix View
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public Matrix World
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
#region EnableDefaultLighting
public void EnableDefaultLighting() public void EnableDefaultLighting()
{ {
throw new NotImplementedException(); LightingEnabled = true;
} ambientLightColor = new Vector3(0.05333332f, 0.09882354f, 0.1819608f);
public Vector3 AmbientLightColor DirectionalLight0.Direction = new Vector3(-0.5265408f, -0.5735765f, -0.6275069f);
{ DirectionalLight0.DiffuseColor = new Vector3(1f, 0.9607844f, 0.8078432f);
get DirectionalLight0.SpecularColor = DirectionalLight0.DiffuseColor;
{ DirectionalLight0.Enabled = true;
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public DirectionalLight DirectionalLight0 DirectionalLight1.Direction = new Vector3(0.7198464f, 0.3420201f, 0.6040227f);
{ DirectionalLight1.DiffuseColor = new Vector3(0.9647059f, 0.7607844f, 0.4078432f);
get { throw new NotImplementedException(); } DirectionalLight1.SpecularColor = Vector3.Zero;
} DirectionalLight1.Enabled = true;
public DirectionalLight DirectionalLight1 DirectionalLight2.Direction = new Vector3(0.4545195f, -0.7660444f, 0.4545195f);
{ DirectionalLight2.DiffuseColor = new Vector3(0.3231373f, 0.3607844f, 0.3937255f);
get { throw new NotImplementedException(); } DirectionalLight2.SpecularColor = DirectionalLight2.DiffuseColor;
} DirectionalLight2.Enabled = true;
public DirectionalLight DirectionalLight2
{
get { throw new NotImplementedException(); }
}
public bool LightingEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public Vector3 FogColor
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public bool FogEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public float FogEnd
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public float FogStart
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public Texture2D Texture
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public int WeightsPerVertex
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public Vector3 DiffuseColor
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public Vector3 EmissiveColor
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public Vector3 SpecularColor
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public float SpecularPower
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public float Alpha
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
} }
#endregion
#region GetBoneTransforms
public Matrix[] GetBoneTransforms(int count) public Matrix[] GetBoneTransforms(int count)
{ {
throw new NotImplementedException(); if (count <= 0)
} throw new ArgumentOutOfRangeException("count");
if (count > 72)
throw new ArgumentException("The maximum number of allowed bones for the SkinnedEffect is " + MaxBones + "!");
var result = new Matrix[MaxBones];
for (int index = 0; index < MaxBones; index++)
{
result[index] = bones[index];
}
return result;
}
#endregion
#region SetBoneTransforms
public void SetBoneTransforms(Matrix[] boneTransforms) public void SetBoneTransforms(Matrix[] boneTransforms)
{ {
throw new NotImplementedException(); if (boneTransforms == null || boneTransforms.Length == 0)
throw new ArgumentNullException("boneTransforms");
if (boneTransforms.Length > 72)
throw new ArgumentException("The maximum number of allowed bones for the SkinnedEffect is " + MaxBones + "!");
for (int index = 0; index < MaxBones; index++)
bones[index] = index < boneTransforms.Length ? boneTransforms[index] : Matrix.Identity;
} }
#endregion
#region PreBindSetParameters
internal override void PreBindSetParameters()
{
Matrix worldView;
Matrix.Multiply(ref world, ref view, out worldView);
Matrix wvp;
Matrix.Multiply(ref worldView, ref projection, out wvp);
Parameters["WorldViewProj"].SetValue(wvp);
SetLightingMatrices();
SetMaterialColor();
Parameters["Bones"].SetValue(bones);
Parameters["FogColor"].SetValue(fogColor);
Parameters["SpecularPower"].SetValue(SpecularPower);
Parameters["SpecularColor"].SetValue(specularColor);
if (Texture != null)
Parameters["Texture"].SetValue(Texture);
if (isFogEnabled)
SetFogVector(ref worldView);
else
Parameters["FogVector"].SetValue(Vector4.Zero);
SelectTechnique();
}
#endregion
#region SelectTechnique
private void SelectTechnique()
{
string name = "";
if (WeightsPerVertex == 1)
name = "OneBone";
else if (WeightsPerVertex == 2)
name = "TwoBones";
else if (WeightsPerVertex == 4)
name = "FourBones";
bool oneLight = DirectionalLight1.Enabled == false && DirectionalLight2.Enabled == false;
if (preferPerPixelLighting)
name += "PixelLighting";
else if (oneLight)
name += "OneLight";
else
name += "VertexLighting";
if (isFogEnabled == false)
name += "NoFog";
CurrentTechnique = Techniques[name];
}
#endregion
#region SetLightingMatrices
private void SetLightingMatrices()
{
Matrix worldInverse;
Matrix.Invert(ref world, out worldInverse);
Matrix worldInverseTranspose;
Matrix.Transpose(ref worldInverse, out worldInverseTranspose);
Parameters["World"].SetValue(world);
Parameters["WorldInverseTranspose"].SetValue(worldInverseTranspose);
Matrix viewInverse;
Matrix.Invert(ref view, out viewInverse);
Parameters["EyePosition"].SetValue(viewInverse.Translation);
}
#endregion
#region SetMaterialColor
private void SetMaterialColor()
{
Vector4 diffuse;
diffuse.X = diffuseColor.X * Alpha;
diffuse.Y = diffuseColor.Y * Alpha;
diffuse.Z = diffuseColor.Z * Alpha;
diffuse.W = Alpha;
Vector3 emissive;
emissive.X = (emissiveColor.X + ambientLightColor.X * diffuseColor.X) * Alpha;
emissive.Y = (emissiveColor.Y + ambientLightColor.Y * diffuseColor.Y) * Alpha;
emissive.Z = (emissiveColor.Z + ambientLightColor.Z * diffuseColor.Z) * Alpha;
Parameters["DiffuseColor"].SetValue(diffuse);
Parameters["EmissiveColor"].SetValue(emissive);
}
#endregion
#region SetFogVector
private void SetFogVector(ref Matrix worldView)
{
if (FogStart == FogEnd)
{
Parameters["FogVector"].SetValue(new Vector4(0f, 0f, 0f, 1f));
return;
}
float fogFactor = 1f / (FogStart - FogEnd);
Vector4 value;
value.X = worldView.M13 * fogFactor;
value.Y = worldView.M23 * fogFactor;
value.Z = worldView.M33 * fogFactor;
value.W = (worldView.M43 + FogStart) * fogFactor;
Parameters["FogVector"].SetValue(value);
}
#endregion
} }
} }

View File

@ -1,10 +1,8 @@
#region Using Statements
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using ANX.Framework.NonXNA; using ANX.Framework.NonXNA;
using ANX.Framework.NonXNA.Development;
#endregion // Using Statements
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.
@ -12,11 +10,14 @@ using ANX.Framework.NonXNA;
namespace ANX.Framework.Graphics namespace ANX.Framework.Graphics
{ {
[PercentageComplete(100)]
[TestState(TestStateAttribute.TestState.Untested)]
[Developer("Glatzemann, AstrorEnales")]
public class SpriteBatch : GraphicsResource public class SpriteBatch : GraphicsResource
{ {
#region Private Members
private const int InitialBatchSize = 1024; private const int InitialBatchSize = 1024;
#region Private
private Effect spriteBatchEffect; private Effect spriteBatchEffect;
private bool hasBegun; private bool hasBegun;
private SpriteSortMode currentSortMode; private SpriteSortMode currentSortMode;
@ -43,8 +44,7 @@ namespace ANX.Framework.Graphics
private static TextureComparer textureComparer = new TextureComparer(); private static TextureComparer textureComparer = new TextureComparer();
private static FrontToBackComparer frontToBackComparer = new FrontToBackComparer(); private static FrontToBackComparer frontToBackComparer = new FrontToBackComparer();
private static BackToFrontComparer backToFrontComparer = new BackToFrontComparer(); private static BackToFrontComparer backToFrontComparer = new BackToFrontComparer();
#endregion
#endregion // Private Members
#region Constructor #region Constructor
public SpriteBatch(GraphicsDevice graphicsDevice) public SpriteBatch(GraphicsDevice graphicsDevice)
@ -55,44 +55,56 @@ namespace ANX.Framework.Graphics
base.GraphicsDevice = graphicsDevice; base.GraphicsDevice = graphicsDevice;
var renderSystemCreator = AddInSystemFactory.Instance.GetDefaultCreator<IRenderSystemCreator>(); var renderSystemCreator = AddInSystemFactory.Instance.GetDefaultCreator<IRenderSystemCreator>();
this.spriteBatchEffect = new Effect(graphicsDevice, renderSystemCreator.GetShaderByteCode(NonXNA.PreDefinedShader.SpriteBatch), renderSystemCreator.GetStockShaderSourceLanguage); this.spriteBatchEffect = new Effect(graphicsDevice,
renderSystemCreator.GetShaderByteCode(NonXNA.PreDefinedShader.SpriteBatch),
renderSystemCreator.GetStockShaderSourceLanguage);
this.spriteInfos = new SpriteInfo[InitialBatchSize]; this.spriteInfos = new SpriteInfo[InitialBatchSize];
this.InitializeIndexBuffer(InitialBatchSize); this.InitializeIndexBuffer(InitialBatchSize);
this.InitializeVertexBuffer(); this.InitializeVertexBuffer();
} }
#endregion #endregion
#region Begin-Method #region Begin
public void Begin() public void Begin()
{ {
Begin(SpriteSortMode.Texture, null, null, null, null, null, Matrix.Identity); Begin(SpriteSortMode.Texture, null, null, null, null, null);
} }
public void Begin(SpriteSortMode sortMode, BlendState blendState) public void Begin(SpriteSortMode sortMode, BlendState blendState)
{ {
Begin(sortMode, blendState, null, null, null, null, Matrix.Identity); Begin(sortMode, blendState, null, null, null, null);
} }
public void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState) public void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState,
DepthStencilState depthStencilState, RasterizerState rasterizerState)
{ {
Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, null, Matrix.Identity); Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, null);
} }
public void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect) public void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState,
{ DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect)
Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect, Matrix.Identity);
}
public void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect, Matrix transformMatrix)
{
if (this.hasBegun == true)
{ {
if (hasBegun == true)
throw new Exception("End() has to be called before a new SpriteBatch can be started with Begin()"); throw new Exception("End() has to be called before a new SpriteBatch can be started with Begin()");
hasBegun = true;
this.currentSortMode = sortMode;
this.blendState = blendState;
this.samplerState = samplerState;
this.depthStencilState = depthStencilState;
this.rasterizerState = rasterizerState;
this.effect = effect;
this.transformMatrix = Matrix.Identity;
} }
public void Begin(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState,
DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect, Matrix transformMatrix)
{
if (hasBegun == true)
throw new Exception("End() has to be called before a new SpriteBatch can be started with Begin()");
hasBegun = true; hasBegun = true;
this.currentSortMode = sortMode; this.currentSortMode = sortMode;
@ -104,150 +116,186 @@ namespace ANX.Framework.Graphics
this.effect = effect; this.effect = effect;
this.transformMatrix = transformMatrix; this.transformMatrix = transformMatrix;
} }
#endregion
#endregion // Begin-Method #region Draw
public void Draw(Texture2D texture, Rectangle destinationRectangle, Color color)
#region Draw-Method
public void Draw (Texture2D texture, Rectangle destinationRectangle, Color color)
{ {
Draw(texture, new Vector2(destinationRectangle.X, destinationRectangle.Y), new Vector2(destinationRectangle.Width, destinationRectangle.Height), null, color, Vector2.Zero, 0.0f, 0.0f, Vector2.One, SpriteEffects.None); Draw(texture, new Vector2(destinationRectangle.X, destinationRectangle.Y), new Vector2(destinationRectangle.Width,
destinationRectangle.Height), null, color, Vector2.Zero, 0f, 0f, Vector2.One, SpriteEffects.None);
} }
public void Draw (Texture2D texture, Rectangle destinationRectangle, Nullable<Rectangle> sourceRectangle, Color color) public void Draw(Texture2D texture, Rectangle destinationRectangle, Nullable<Rectangle> sourceRectangle, Color color)
{ {
Draw(texture, new Vector2(destinationRectangle.X, destinationRectangle.Y), new Vector2(destinationRectangle.Width, destinationRectangle.Height), sourceRectangle, color, Vector2.Zero, 0.0f, 0.0f, Vector2.One, SpriteEffects.None); Draw(texture, new Vector2(destinationRectangle.X, destinationRectangle.Y), new Vector2(destinationRectangle.Width,
destinationRectangle.Height), sourceRectangle, color, Vector2.Zero, 0f, 0f, Vector2.One, SpriteEffects.None);
} }
public void Draw(Texture2D texture, Rectangle destinationRectangle, Nullable<Rectangle> sourceRectangle, Color color, Single rotation, Vector2 origin, SpriteEffects effects, Single layerDepth) public void Draw(Texture2D texture, Rectangle destinationRectangle, Nullable<Rectangle> sourceRectangle, Color color,
Single rotation, Vector2 origin, SpriteEffects effects, Single layerDepth)
{ {
Draw(texture, new Vector2(destinationRectangle.X, destinationRectangle.Y), new Vector2(destinationRectangle.Width, destinationRectangle.Height), sourceRectangle, color, origin, layerDepth, rotation, Vector2.One, effects); Draw(texture, new Vector2(destinationRectangle.X, destinationRectangle.Y), new Vector2(destinationRectangle.Width,
destinationRectangle.Height), sourceRectangle, color, origin, layerDepth, rotation, Vector2.One, effects);
} }
public void Draw(Texture2D texture, Vector2 position, Color color) public void Draw(Texture2D texture, Vector2 position, Color color)
{ {
Draw(texture, position, new Vector2(texture.Width, texture.Height), null, color, Vector2.Zero, 0.0f, 0.0f, Vector2.One, SpriteEffects.None); Draw(texture, position, new Vector2(texture.Width, texture.Height), null, color, Vector2.Zero, 0f, 0f, Vector2.One,
SpriteEffects.None);
} }
public void Draw(Texture2D texture, Vector2 position, Nullable<Rectangle> sourceRectangle, Color color) public void Draw(Texture2D texture, Vector2 position, Nullable<Rectangle> sourceRectangle, Color color)
{ {
Vector2 size = sourceRectangle.HasValue ? new Vector2(sourceRectangle.Value.Width, sourceRectangle.Value.Height) : new Vector2(texture.Width, texture.Height); Vector2 size = sourceRectangle.HasValue ?
Draw(texture, position, size, sourceRectangle, color, Vector2.Zero, 0.0f, 0.0f, Vector2.One, SpriteEffects.None); new Vector2(sourceRectangle.Value.Width, sourceRectangle.Value.Height) :
new Vector2(texture.Width, texture.Height);
Draw(texture, position, size, sourceRectangle, color, Vector2.Zero, 0f, 0f, Vector2.One, SpriteEffects.None);
} }
public void Draw(Texture2D texture, Vector2 position, Nullable<Rectangle> sourceRectangle, Color color, Single rotation, Vector2 origin, Single scale, SpriteEffects effects, Single layerDepth) public void Draw(Texture2D texture, Vector2 position, Nullable<Rectangle> sourceRectangle, Color color, Single rotation,
Vector2 origin, Single scale, SpriteEffects effects, Single layerDepth)
{ {
Vector2 size = sourceRectangle.HasValue ? new Vector2(sourceRectangle.Value.Width, sourceRectangle.Value.Height) : new Vector2(texture.Width, texture.Height); Vector2 size = sourceRectangle.HasValue ?
new Vector2(sourceRectangle.Value.Width, sourceRectangle.Value.Height) :
new Vector2(texture.Width, texture.Height);
Draw(texture, position, size, sourceRectangle, color, origin, layerDepth, rotation, new Vector2(scale), effects); Draw(texture, position, size, sourceRectangle, color, origin, layerDepth, rotation, new Vector2(scale), effects);
} }
public void Draw(Texture2D texture, Vector2 position, Nullable<Rectangle> sourceRectangle, Color color, Single rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, Single layerDepth) public void Draw(Texture2D texture, Vector2 position, Nullable<Rectangle> sourceRectangle, Color color, Single rotation,
Vector2 origin, Vector2 scale, SpriteEffects effects, Single layerDepth)
{ {
Vector2 size = sourceRectangle.HasValue ? new Vector2(sourceRectangle.Value.Width, sourceRectangle.Value.Height) : new Vector2(texture.Width, texture.Height); Vector2 size = sourceRectangle.HasValue ?
new Vector2(sourceRectangle.Value.Width, sourceRectangle.Value.Height) :
new Vector2(texture.Width, texture.Height);
Draw(texture, position, size, sourceRectangle, color, origin, layerDepth, rotation, scale, effects); Draw(texture, position, size, sourceRectangle, color, origin, layerDepth, rotation, scale, effects);
} }
#endregion
#endregion // Draw-Method #region DrawOptimizedText
internal void DrawOptimizedText(Texture2D texture, Vector2 position, ref Rectangle sourceRectangle, ref Color color,
float rotation, Vector2 scale, SpriteEffects effects, float layerDepth)
{
Vector2 size = new Vector2(sourceRectangle.Width, sourceRectangle.Height);
Draw(texture, position, size, sourceRectangle, color, Vector2.Zero, layerDepth, rotation, scale, effects);
}
#region DrawString-Method internal void DrawOptimizedText(Texture2D texture, Vector2 position, ref Rectangle sourceRectangle, ref Color color)
{
if (hasBegun == false)
throw new InvalidOperationException("Begin() must be called before Draw()");
if (texture == null)
throw new ArgumentNullException("texture");
ResizeIfNeeded();
Vector2 bottomRight;
bottomRight.X = position.X + sourceRectangle.Width;
bottomRight.Y = position.Y + sourceRectangle.Height;
SpriteInfo currentSprite = spriteInfos[currentBatchPosition];
currentSprite.Corners = new Vector2[]
{
position,
new Vector2(bottomRight.X, position.Y),
bottomRight,
new Vector2(position.X, bottomRight.Y)
};
currentSprite.Tint = color;
currentSprite.texture = texture;
currentSprite.topLeftUV.X = sourceRectangle.X * texture.OneOverWidth;
currentSprite.topLeftUV.Y = sourceRectangle.Y * texture.OneOverHeight;
currentSprite.bottomRightUV.X = (sourceRectangle.X + sourceRectangle.Width) * texture.OneOverWidth;
currentSprite.bottomRightUV.Y = (sourceRectangle.Y + sourceRectangle.Height) * texture.OneOverHeight;
currentSprite.origin = Vector2.Zero;
currentSprite.rotation = 0f;
currentSprite.layerDepth = 1f;
spriteInfos[currentBatchPosition] = currentSprite;
currentBatchPosition++;
if (this.currentSortMode == SpriteSortMode.Immediate)
{
BatchRender(0, 1);
Flush();
}
}
#endregion
#region DrawString
public void DrawString(SpriteFont font, String text, Vector2 position, Color color) public void DrawString(SpriteFont font, String text, Vector2 position, Color color)
{ {
if (font == null) if (font == null)
{
throw new ArgumentNullException("font"); throw new ArgumentNullException("font");
}
if (text == null) if (text == null)
{
throw new ArgumentNullException("text"); throw new ArgumentNullException("text");
font.DrawString(text, this, position, color);
} }
font.DrawString(ref text, this, position, color, Vector2.One, Vector2.Zero, 0.0f, 1.0f, SpriteEffects.None); public void DrawString(SpriteFont font, StringBuilder text, Vector2 position, Color color)
}
public void DrawString(SpriteFont font, String text, Vector2 position, Color color, Single rotation, Vector2 origin, Single scale, SpriteEffects effects, Single layerDepth)
{ {
if (font == null) if (font == null)
{
throw new ArgumentNullException("font"); throw new ArgumentNullException("font");
}
if (text == null) if (text == null)
{
throw new ArgumentNullException("text"); throw new ArgumentNullException("text");
font.DrawString(text.ToString(), this, position, color);
} }
font.DrawString(ref text, this, position, color, new Vector2(scale), origin, rotation, layerDepth, effects); public void DrawString(SpriteFont font, String text, Vector2 position, Color color, Single rotation, Vector2 origin,
} Single scale, SpriteEffects effects, Single layerDepth)
public void DrawString(SpriteFont font, String text, Vector2 position, Color color, Single rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, Single layerDepth)
{ {
if (font == null) if (font == null)
{
throw new ArgumentNullException("font"); throw new ArgumentNullException("font");
}
if (text == null) if (text == null)
{
throw new ArgumentNullException("text"); throw new ArgumentNullException("text");
font.DrawString(text, this, position, color, new Vector2(scale), origin, rotation, layerDepth, effects);
} }
font.DrawString(ref text, this, position, color, scale, origin, rotation, layerDepth, effects); public void DrawString(SpriteFont font, String text, Vector2 position, Color color, Single rotation, Vector2 origin,
} Vector2 scale, SpriteEffects effects, Single layerDepth)
public void DrawString (SpriteFont font, StringBuilder text, Vector2 position, Color color)
{ {
if (font == null) if (font == null)
{
throw new ArgumentNullException("font"); throw new ArgumentNullException("font");
}
if (text == null) if (text == null)
{
throw new ArgumentNullException("text"); throw new ArgumentNullException("text");
font.DrawString(text, this, position, color, scale, origin, rotation, layerDepth, effects);
} }
DrawString(font, text.ToString(), position, color); public void DrawString(SpriteFont font, StringBuilder text, Vector2 position, Color color, Single rotation,
} Vector2 origin, Single scale, SpriteEffects effects, Single layerDepth)
public void DrawString (SpriteFont font, StringBuilder text, Vector2 position, Color color, Single rotation, Vector2 origin, Single scale, SpriteEffects effects, Single layerDepth)
{ {
if (font == null) if (font == null)
{
throw new ArgumentNullException("font"); throw new ArgumentNullException("font");
}
if (text == null) if (text == null)
{
throw new ArgumentNullException("text"); throw new ArgumentNullException("text");
font.DrawString(text.ToString(), this, position, color, new Vector2(scale), origin, rotation, layerDepth, effects);
} }
DrawString(font, text.ToString(), position, color, rotation, origin, scale, effects, layerDepth); public void DrawString(SpriteFont font, StringBuilder text, Vector2 position, Color color, Single rotation,
} Vector2 origin, Vector2 scale, SpriteEffects effects, Single layerDepth)
public void DrawString (SpriteFont font, StringBuilder text, Vector2 position, Color color, Single rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, Single layerDepth)
{ {
if (font == null) if (font == null)
{
throw new ArgumentNullException("font"); throw new ArgumentNullException("font");
}
if (text == null) if (text == null)
{
throw new ArgumentNullException("text"); throw new ArgumentNullException("text");
}
DrawString(font, text.ToString(), position, color, rotation, origin, scale, effects, layerDepth); font.DrawString(text.ToString(), this, position, color, scale, origin, rotation, layerDepth, effects);
} }
#endregion
#endregion // DrawString-Method
#region End #region End
public void End() public void End()
{ {
if (hasBegun == false) if (hasBegun == false)
{
throw new Exception("Begin() has to be called before End()"); throw new Exception("Begin() has to be called before End()");
}
hasBegun = false; hasBegun = false;
@ -256,17 +304,11 @@ namespace ANX.Framework.Graphics
if (currentBatchPosition > 0) if (currentBatchPosition > 0)
{ {
if (this.currentSortMode == SpriteSortMode.Texture) if (this.currentSortMode == SpriteSortMode.Texture)
{
Array.Sort<SpriteInfo>(spriteInfos, 0, currentBatchPosition, textureComparer); Array.Sort<SpriteInfo>(spriteInfos, 0, currentBatchPosition, textureComparer);
}
else if (this.currentSortMode == SpriteSortMode.BackToFront) else if (this.currentSortMode == SpriteSortMode.BackToFront)
{
Array.Sort<SpriteInfo>(spriteInfos, 0, currentBatchPosition, backToFrontComparer); Array.Sort<SpriteInfo>(spriteInfos, 0, currentBatchPosition, backToFrontComparer);
}
else if (this.currentSortMode == SpriteSortMode.FrontToBack) else if (this.currentSortMode == SpriteSortMode.FrontToBack)
{
Array.Sort<SpriteInfo>(spriteInfos, 0, currentBatchPosition, frontToBackComparer); Array.Sort<SpriteInfo>(spriteInfos, 0, currentBatchPosition, frontToBackComparer);
}
int startOffset = 0; int startOffset = 0;
Texture2D lastTexture = spriteInfos[0].texture; Texture2D lastTexture = spriteInfos[0].texture;
@ -287,55 +329,70 @@ namespace ANX.Framework.Graphics
} }
#endregion #endregion
private void Draw(Texture2D texture, Vector2 topLeft, Vector2 destinationSize, Rectangle? sourceRectangle, Color tint, Vector2 origin, float layerDepth, float rotation, Vector2 scale, SpriteEffects effects) #region ResizeIfNeeded
private void ResizeIfNeeded()
{ {
if (hasBegun == false)
{
throw new InvalidOperationException("Begin() must be called before Draw()");
}
if (texture == null)
{
throw new ArgumentNullException("texture");
}
if (currentBatchPosition >= spriteInfos.Length) if (currentBatchPosition >= spriteInfos.Length)
{ {
int newSize = spriteInfos.Length * 2; int newSize = spriteInfos.Length * 2;
Array.Resize<SpriteInfo>(ref spriteInfos, newSize); Array.Resize<SpriteInfo>(ref spriteInfos, newSize);
InitializeIndexBuffer(newSize); InitializeIndexBuffer(newSize);
} }
}
#endregion
Vector2 bottomRight = topLeft + (destinationSize * scale); #region Draw
private void Draw(Texture2D texture, Vector2 topLeft, Vector2 destinationSize, Rectangle? sourceRectangle,
Color tint, Vector2 origin, float layerDepth, float rotation, Vector2 scale, SpriteEffects effects)
{
if (hasBegun == false)
throw new InvalidOperationException("Begin() must be called before Draw()");
spriteInfos[currentBatchPosition].Corners = new Vector2[] { topLeft, new Vector2(bottomRight.X, topLeft.Y), bottomRight, new Vector2(topLeft.X, bottomRight.Y) }; if (texture == null)
throw new ArgumentNullException("texture");
spriteInfos[currentBatchPosition].Tint = tint; ResizeIfNeeded();
spriteInfos[currentBatchPosition].texture = texture;
Vector2 bottomRight = new Vector2(topLeft.X + (destinationSize.X * scale.X),
topLeft.Y + (destinationSize.Y * scale.Y));
SpriteInfo currentSprite = spriteInfos[currentBatchPosition];
currentSprite.Corners = new Vector2[]
{
topLeft,
new Vector2(bottomRight.X, topLeft.Y),
bottomRight,
new Vector2(topLeft.X, bottomRight.Y)
};
currentSprite.Tint = tint;
currentSprite.texture = texture;
if (sourceRectangle.HasValue) if (sourceRectangle.HasValue)
{ {
spriteInfos[currentBatchPosition].topLeftUV = new Vector2(sourceRectangle.Value.X / (float)texture.Width, sourceRectangle.Value.Y / (float)texture.Height); currentSprite.topLeftUV.X = sourceRectangle.Value.X * texture.OneOverWidth;
spriteInfos[currentBatchPosition].bottomRightUV = new Vector2((sourceRectangle.Value.X + sourceRectangle.Value.Width) / (float)texture.Width, (sourceRectangle.Value.Y + sourceRectangle.Value.Height) / (float)texture.Height); currentSprite.topLeftUV.Y = sourceRectangle.Value.Y * texture.OneOverHeight;
currentSprite.bottomRightUV.X = (sourceRectangle.Value.X + sourceRectangle.Value.Width) * texture.OneOverWidth;
currentSprite.bottomRightUV.Y = (sourceRectangle.Value.Y + sourceRectangle.Value.Height) * texture.OneOverHeight;
} }
else else
{ {
spriteInfos[currentBatchPosition].topLeftUV = Vector2.Zero; currentSprite.topLeftUV = Vector2.Zero;
spriteInfos[currentBatchPosition].bottomRightUV = Vector2.One; currentSprite.bottomRightUV = Vector2.One;
} }
if ((effects & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally) if ((effects & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally)
{ {
float tempY = spriteInfos[currentBatchPosition].bottomRightUV.Y; float tempY = currentSprite.bottomRightUV.Y;
spriteInfos[currentBatchPosition].bottomRightUV.Y = spriteInfos[currentBatchPosition].topLeftUV.Y; currentSprite.bottomRightUV.Y = currentSprite.topLeftUV.Y;
spriteInfos[currentBatchPosition].topLeftUV.Y = tempY; currentSprite.topLeftUV.Y = tempY;
} }
if ((effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically) if ((effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically)
{ {
float tempX = spriteInfos[currentBatchPosition].bottomRightUV.X; float tempX = currentSprite.bottomRightUV.X;
spriteInfos[currentBatchPosition].bottomRightUV.X = spriteInfos[currentBatchPosition].topLeftUV.X; currentSprite.bottomRightUV.X = currentSprite.topLeftUV.X;
spriteInfos[currentBatchPosition].topLeftUV.X = tempX; currentSprite.topLeftUV.X = tempX;
} }
if (rotation != 0f) if (rotation != 0f)
@ -348,17 +405,22 @@ namespace ANX.Framework.Graphics
Vector2 transformVector; Vector2 transformVector;
Vector2 result; Vector2 result;
float offsetX = topLeft.X + origin.X;
float offsetY = topLeft.Y + origin.Y;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
transformVector = spriteInfos[currentBatchPosition].Corners[i] - topLeft - origin; transformVector.X = currentSprite.Corners[i].X - offsetX;
transformVector.Y = currentSprite.Corners[i].Y - offsetY;
Vector2.Transform(ref transformVector, ref this.cachedRotationMatrix, out result); Vector2.Transform(ref transformVector, ref this.cachedRotationMatrix, out result);
spriteInfos[currentBatchPosition].Corners[i] = result + topLeft + origin; currentSprite.Corners[i].X = result.X + offsetX;
currentSprite.Corners[i].Y = result.Y + offsetY;
} }
} }
spriteInfos[currentBatchPosition].origin = origin; currentSprite.origin = origin;
spriteInfos[currentBatchPosition].rotation = rotation; currentSprite.rotation = rotation;
spriteInfos[currentBatchPosition].layerDepth = layerDepth; currentSprite.layerDepth = layerDepth;
spriteInfos[currentBatchPosition] = currentSprite;
currentBatchPosition++; currentBatchPosition++;
@ -368,19 +430,17 @@ namespace ANX.Framework.Graphics
Flush(); Flush();
} }
} }
#endregion
#region BatchRender
private void BatchRender(int offset, int count) private void BatchRender(int offset, int count)
{ {
int vertexCount = count * 4; int vertexCount = count * 4;
if (this.vertices == null) if (this.vertices == null)
{
this.vertices = new VertexPositionColorTexture[vertexCount]; this.vertices = new VertexPositionColorTexture[vertexCount];
}
else if (this.vertices.Length < vertexCount) else if (this.vertices.Length < vertexCount)
{
Array.Resize<VertexPositionColorTexture>(ref this.vertices, vertexCount); Array.Resize<VertexPositionColorTexture>(ref this.vertices, vertexCount);
}
int vertexPos = 0; int vertexPos = 0;
for (int i = offset; i < offset + count; i++) for (int i = offset; i < offset + count; i++)
@ -416,25 +476,32 @@ namespace ANX.Framework.Graphics
GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertexCount, 0, count * 2); GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertexCount, 0, count * 2);
} }
#endregion
#region Flush
private void Flush() private void Flush()
{ {
currentBatchPosition = 0; currentBatchPosition = 0;
} }
#endregion
#region InitializeIndexBuffer
private void InitializeIndexBuffer(int size) private void InitializeIndexBuffer(int size)
{ {
int indexCount = size * 6; int indexCount = size * 6;
if (this.indexBuffer == null) if (this.indexBuffer == null)
{ {
this.indexBuffer = new DynamicIndexBuffer(this.GraphicsDevice, IndexElementSize.SixteenBits, indexCount, BufferUsage.WriteOnly); this.indexBuffer = new DynamicIndexBuffer(this.GraphicsDevice, IndexElementSize.SixteenBits, indexCount,
BufferUsage.WriteOnly);
this.indexBuffer.ContentLost += new EventHandler<EventArgs>(indexBuffer_ContentLost); this.indexBuffer.ContentLost += new EventHandler<EventArgs>(indexBuffer_ContentLost);
} }
SetIndexData(indexCount); SetIndexData(indexCount);
} }
#endregion
#region indexBuffer_ContentLost
private void indexBuffer_ContentLost(object sender, EventArgs e) private void indexBuffer_ContentLost(object sender, EventArgs e)
{ {
if (this.indexBuffer != null) if (this.indexBuffer != null)
@ -446,10 +513,12 @@ namespace ANX.Framework.Graphics
InitializeIndexBuffer(InitialBatchSize); InitializeIndexBuffer(InitialBatchSize);
} }
#endregion
#region SetIndexData
private void SetIndexData(int indexCount) private void SetIndexData(int indexCount)
{ {
short[] indices = new short[indexCount]; var indices = new ushort[indexCount];
int baseIndex; int baseIndex;
int baseArrayIndex; int baseArrayIndex;
@ -458,26 +527,31 @@ namespace ANX.Framework.Graphics
baseIndex = i * 4; baseIndex = i * 4;
baseArrayIndex = baseIndex + i + i; baseArrayIndex = baseIndex + i + i;
indices[baseArrayIndex] = (short)baseIndex; indices[baseArrayIndex] = (ushort)baseIndex;
indices[baseArrayIndex + 1] = (short)(baseIndex + 1); indices[baseArrayIndex + 1] = (ushort)(baseIndex + 1);
indices[baseArrayIndex + 2] = (short)(baseIndex + 2); indices[baseArrayIndex + 2] = (ushort)(baseIndex + 2);
indices[baseArrayIndex + 3] = (short)baseIndex; indices[baseArrayIndex + 3] = (ushort)baseIndex;
indices[baseArrayIndex + 4] = (short)(baseIndex + 2); indices[baseArrayIndex + 4] = (ushort)(baseIndex + 2);
indices[baseArrayIndex + 5] = (short)(baseIndex + 3); indices[baseArrayIndex + 5] = (ushort)(baseIndex + 3);
} }
this.indexBuffer.SetData<short>(indices); this.indexBuffer.SetData<ushort>(indices);
} }
#endregion
#region InitializeVertexBuffer
private void InitializeVertexBuffer() private void InitializeVertexBuffer()
{ {
if (this.vertexBuffer == null) if (this.vertexBuffer == null)
{ {
this.vertexBuffer = new DynamicVertexBuffer(this.GraphicsDevice, typeof(VertexPositionColorTexture), InitialBatchSize * 4, BufferUsage.WriteOnly); this.vertexBuffer = new DynamicVertexBuffer(this.GraphicsDevice, typeof(VertexPositionColorTexture),
this.vertexBuffer.ContentLost += new EventHandler<EventArgs>(vertexBuffer_ContentLost); InitialBatchSize * 4, BufferUsage.WriteOnly);
this.vertexBuffer.ContentLost += vertexBuffer_ContentLost;
} }
} }
#endregion
#region vertexBuffer_ContentLost
private void vertexBuffer_ContentLost(object sender, EventArgs e) private void vertexBuffer_ContentLost(object sender, EventArgs e)
{ {
this.currentBatchPosition = 0; this.currentBatchPosition = 0;
@ -491,15 +565,18 @@ namespace ANX.Framework.Graphics
InitializeVertexBuffer(); InitializeVertexBuffer();
} }
#endregion
#region SetRenderStates
private void SetRenderStates() private void SetRenderStates()
{ {
GraphicsDevice.BlendState = this.blendState != null ? this.blendState : BlendState.AlphaBlend; GraphicsDevice.BlendState = blendState != null ? blendState : BlendState.AlphaBlend;
GraphicsDevice.DepthStencilState = this.depthStencilState != null ? this.depthStencilState : DepthStencilState.None; GraphicsDevice.DepthStencilState = depthStencilState != null ? depthStencilState : DepthStencilState.None;
GraphicsDevice.RasterizerState = this.rasterizerState != null ? this.rasterizerState : RasterizerState.CullCounterClockwise; GraphicsDevice.RasterizerState = rasterizerState != null ? rasterizerState : RasterizerState.CullCounterClockwise;
GraphicsDevice.SamplerStates[0] = this.samplerState != null ? this.samplerState : SamplerState.LinearClamp; GraphicsDevice.SamplerStates[0] = samplerState != null ? samplerState : SamplerState.LinearClamp;
if (cachedTransformMatrix == null || GraphicsDevice.Viewport.Width != viewportWidth || GraphicsDevice.Viewport.Height != viewportHeight) if (cachedTransformMatrix == null || GraphicsDevice.Viewport.Width != viewportWidth ||
GraphicsDevice.Viewport.Height != viewportHeight)
{ {
this.viewportWidth = GraphicsDevice.Viewport.Width; this.viewportWidth = GraphicsDevice.Viewport.Width;
this.viewportHeight = GraphicsDevice.Viewport.Height; this.viewportHeight = GraphicsDevice.Viewport.Height;
@ -518,13 +595,17 @@ namespace ANX.Framework.Graphics
cachedTransformMatrix.M42 -= cachedTransformMatrix.M22; cachedTransformMatrix.M42 -= cachedTransformMatrix.M22;
} }
this.spriteBatchEffect.Parameters["MatrixTransform"].SetValue(this.transformMatrix * cachedTransformMatrix); Matrix result;
Matrix.Multiply(ref transformMatrix, ref cachedTransformMatrix, out result);
this.spriteBatchEffect.Parameters["MatrixTransform"].SetValue(result);
spriteBatchEffect.NativeEffect.Apply(GraphicsDevice); spriteBatchEffect.NativeEffect.Apply(GraphicsDevice);
GraphicsDevice.Indices = this.indexBuffer; GraphicsDevice.Indices = this.indexBuffer;
GraphicsDevice.SetVertexBuffer(this.vertexBuffer); GraphicsDevice.SetVertexBuffer(this.vertexBuffer);
} }
#endregion
#region Dispose
public override void Dispose() public override void Dispose()
{ {
if (this.spriteBatchEffect != null) if (this.spriteBatchEffect != null)
@ -550,19 +631,18 @@ namespace ANX.Framework.Graphics
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion
private class TextureComparer : IComparer<SpriteInfo> private class TextureComparer : IComparer<SpriteInfo>
{ {
public int Compare(SpriteInfo x, SpriteInfo y) public int Compare(SpriteInfo x, SpriteInfo y)
{ {
if (x.texture.GetHashCode() > y.texture.GetHashCode()) int hash1 = x.texture.GetHashCode();
{ int hash2 = y.texture.GetHashCode();
if (hash1 > hash2)
return -1; return -1;
} else if (hash1 < hash2)
else if (x.texture.GetHashCode() < y.texture.GetHashCode())
{
return 1; return 1;
}
return 0; return 0;
} }
@ -573,13 +653,9 @@ namespace ANX.Framework.Graphics
public int Compare(SpriteInfo x, SpriteInfo y) public int Compare(SpriteInfo x, SpriteInfo y)
{ {
if (x.layerDepth > y.layerDepth) if (x.layerDepth > y.layerDepth)
{
return 1; return 1;
}
else if (x.layerDepth < y.layerDepth) else if (x.layerDepth < y.layerDepth)
{
return -1; return -1;
}
return 0; return 0;
} }
@ -590,17 +666,12 @@ namespace ANX.Framework.Graphics
public int Compare(SpriteInfo x, SpriteInfo y) public int Compare(SpriteInfo x, SpriteInfo y)
{ {
if (x.layerDepth > y.layerDepth) if (x.layerDepth > y.layerDepth)
{
return -1; return -1;
}
else if (x.layerDepth < y.layerDepth) else if (x.layerDepth < y.layerDepth)
{
return 1; return 1;
}
return 0; return 0;
} }
} }
} }
} }

View File

@ -1,9 +1,8 @@
#region Using Statements
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Text; using System.Text;
#endregion // Using Statements using ANX.Framework.NonXNA.Development;
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.
@ -11,173 +10,195 @@ using System.Text;
namespace ANX.Framework.Graphics namespace ANX.Framework.Graphics
{ {
[PercentageComplete(100)]
[TestState(TestStateAttribute.TestState.Untested)]
[Developer("Glatzemann, AstrorEnales")]
public sealed class SpriteFont public sealed class SpriteFont
{ {
#region Private Members #region Private
private Texture2D texture; private Texture2D texture;
private List<Rectangle> glyphs; private Rectangle[] glyphs;
private List<Rectangle> cropping; private Rectangle[] cropping;
private List<char> characterMap; private List<char> characterMap;
private int lineSpacing; private Vector3[] kernings;
private float horizontalSpacing;
private List<Vector3> kerning;
private char? defaultCharacter; private char? defaultCharacter;
private ReadOnlyCollection<Char> characters; Vector2 topLeft;
Vector2 position;
#endregion
#endregion // Private Members #region Public
public ReadOnlyCollection<Char> Characters { get; private set; }
public ReadOnlyCollection<Char> Characters public int LineSpacing { get; set; }
{ public float Spacing { get; set; }
get { return characters; }
}
public char? DefaultCharacter public char? DefaultCharacter
{ {
get { return defaultCharacter; } get { return defaultCharacter; }
set set
{ {
if (value.HasValue && !this.characterMap.Contains(value.Value)) if (value.HasValue && this.characterMap.Contains(value.Value) == false)
{
throw new NotSupportedException("Character is not in used font"); throw new NotSupportedException("Character is not in used font");
}
this.defaultCharacter = value; this.defaultCharacter = value;
} }
} }
#endregion
public int LineSpacing #region Constructor
{ internal SpriteFont(Texture2D texture, List<Rectangle> glyphs, List<Rectangle> cropping, List<char> charMap,
get { return lineSpacing; }
set { lineSpacing = value; }
}
public float Spacing
{
get { return horizontalSpacing; }
set { horizontalSpacing = value; }
}
internal SpriteFont(
Texture2D texture, List<Rectangle> glyphs, List<Rectangle> cropping, List<char> charMap,
int lineSpacing, float horizontalSpacing, List<Vector3> kerning, char? defaultCharacter) int lineSpacing, float horizontalSpacing, List<Vector3> kerning, char? defaultCharacter)
{ {
this.texture = texture; this.texture = texture;
this.glyphs = glyphs; this.glyphs = glyphs.ToArray();
this.cropping = cropping; this.cropping = cropping.ToArray();
this.characterMap = charMap; this.characterMap = charMap;
this.lineSpacing = lineSpacing; this.LineSpacing = lineSpacing;
this.horizontalSpacing = horizontalSpacing; this.Spacing = horizontalSpacing;
this.kerning = kerning; this.kernings = kerning.ToArray();
this.defaultCharacter = defaultCharacter; this.defaultCharacter = defaultCharacter;
this.characters = new ReadOnlyCollection<char>(characterMap); Characters = new ReadOnlyCollection<char>(characterMap);
} }
#endregion
#region MeasureString
public Vector2 MeasureString(string text) public Vector2 MeasureString(string text)
{ {
if (text == null) if (text == null)
{
throw new ArgumentNullException("text"); throw new ArgumentNullException("text");
}
return InternalMeasure(ref text); return InternalMeasure(text);
} }
public Vector2 MeasureString(StringBuilder text) public Vector2 MeasureString(StringBuilder text)
{ {
if (text == null) if (text == null)
{
throw new ArgumentNullException("text"); throw new ArgumentNullException("text");
}
String cachedText = text.ToString(); return InternalMeasure(text.ToString());
return InternalMeasure(ref cachedText);
} }
#endregion
internal void DrawString(ref String text, SpriteBatch spriteBatch, Vector2 textPos, Color color, Vector2 scale, Vector2 origin, float rotation, float layerDepth, SpriteEffects effects) #region DrawString
internal void DrawString(string text, SpriteBatch spriteBatch, Vector2 textPos, Color color, Vector2 scale,
Vector2 origin, float rotation, float layerDepth, SpriteEffects effects)
{ {
Matrix transformation = Matrix.CreateRotationZ(rotation) * Matrix.CreateTranslation(-origin.X * scale.X, -origin.Y * scale.Y, 0f); Matrix rotationMatrix;
Matrix.CreateRotationZ(rotation, out rotationMatrix);
Matrix translationMatrix;
Matrix.CreateTranslation(-origin.X * scale.X, -origin.Y * scale.Y, 0f, out translationMatrix);
Matrix transformation;
Matrix.Multiply(ref rotationMatrix, ref translationMatrix, out transformation);
topLeft.X = topLeft.Y = 0f;
int horizontalFlipModifier = 1; int horizontalFlipModifier = 1;
float width = 0f; float width = 0f;
Vector2 topLeft = new Vector2(); bool flipVertically = (effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically;
bool firstCharacterInLine = true; bool flipHorizontally = (effects & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally;
if ((effects & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally) if (flipHorizontally)
{ {
topLeft.X = width = this.InternalMeasure(ref text).X * scale.X; topLeft.X = width = InternalMeasure(text).X * scale.X;
horizontalFlipModifier = -1; horizontalFlipModifier = -1;
} }
if ((effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically) if (flipVertically)
{ topLeft.Y = (InternalMeasure(text).Y - LineSpacing) * scale.Y;
topLeft.Y = (this.InternalMeasure(ref text).Y - this.lineSpacing) * scale.Y;
}
bool firstCharacterInLine = true;
for (int i = 0; i < text.Length; i++) for (int i = 0; i < text.Length; i++)
{ {
char currentCharacter = text[i]; char currentCharacter = text[i];
switch (currentCharacter) if (currentCharacter == '\r')
{ continue;
case '\r':
break;
case '\n': if (currentCharacter == '\n')
{
firstCharacterInLine = true; firstCharacterInLine = true;
topLeft.X = width; topLeft.X = width;
if ((effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically) float factor = LineSpacing * scale.Y;
{ topLeft.Y += flipVertically ? -factor : factor;
topLeft.Y -= this.lineSpacing * scale.Y; continue;
} }
else
{
topLeft.Y += this.lineSpacing * scale.Y;
}
break;
default:
{
int characterIndex = GetIndexForCharacter(currentCharacter); int characterIndex = GetIndexForCharacter(currentCharacter);
Vector3 kerning = this.kerning[characterIndex]; Vector3 kerning = kernings[characterIndex];
Rectangle glyphRect = this.glyphs[characterIndex]; Rectangle croppingRect = cropping[characterIndex];
Rectangle croppingRect = this.cropping[characterIndex];
if (firstCharacterInLine) if (firstCharacterInLine)
{
kerning.X = Math.Max(kerning.X, 0f); kerning.X = Math.Max(kerning.X, 0f);
}
else else
{ topLeft.X += (Spacing * scale.X) * horizontalFlipModifier;
topLeft.X += (this.Spacing * scale.X) * horizontalFlipModifier;
}
topLeft.X += (kerning.X * scale.X) * horizontalFlipModifier; topLeft.X += (kerning.X * scale.X) * horizontalFlipModifier;
if ((effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically) if (flipVertically)
{ croppingRect.Y = (LineSpacing - glyphs[characterIndex].Height) - croppingRect.Y;
croppingRect.Y = (this.lineSpacing - glyphRect.Height) - croppingRect.Y;
} if (flipHorizontally)
if ((effects & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally)
{
croppingRect.X -= croppingRect.Width; croppingRect.X -= croppingRect.Width;
}
Vector2 position = Vector2.Transform(topLeft + (new Vector2(croppingRect.X, croppingRect.Y) * scale), transformation); position.X = topLeft.X + (croppingRect.X * scale.X);
spriteBatch.Draw(this.texture, position + textPos, glyphRect, color, rotation, Vector2.Zero, scale, effects, layerDepth); position.Y = topLeft.Y + (croppingRect.Y * scale.Y);
Vector2 result;
Vector2.Transform(ref position, ref transformation, out result);
result.X += textPos.X;
result.Y += textPos.Y;
spriteBatch.DrawOptimizedText(texture, result, ref glyphs[characterIndex], ref color, rotation, scale,
effects, layerDepth);
firstCharacterInLine = false; firstCharacterInLine = false;
topLeft.X += ((kerning.Y + kerning.Z) * scale.X) * horizontalFlipModifier; topLeft.X += ((kerning.Y + kerning.Z) * scale.X) * horizontalFlipModifier;
break;
}
} }
} }
#endregion
#region DrawString
internal void DrawString(string text, SpriteBatch spriteBatch, Vector2 textPos, Color color)
{
topLeft.X = topLeft.Y = 0f;
bool firstCharacterInLine = true;
for (int i = 0; i < text.Length; i++)
{
char currentCharacter = text[i];
if (currentCharacter == '\r')
continue;
if (currentCharacter == '\n')
{
firstCharacterInLine = true;
topLeft.X = 0f;
topLeft.Y += LineSpacing;
continue;
} }
private Vector2 InternalMeasure(ref String text) int characterIndex = GetIndexForCharacter(currentCharacter);
Vector3 kerning = kernings[characterIndex];
Rectangle croppingRect = cropping[characterIndex];
if (firstCharacterInLine)
kerning.X = Math.Max(kerning.X, 0f);
else
topLeft.X += Spacing;
topLeft.X += kerning.X;
position.X = topLeft.X + croppingRect.X + textPos.X;
position.Y = topLeft.Y + croppingRect.Y + textPos.Y;
spriteBatch.DrawOptimizedText(texture, position, ref glyphs[characterIndex], ref color);
firstCharacterInLine = false;
topLeft.X += kerning.Y + kerning.Z;
}
}
#endregion
#region InternalMeasure
private Vector2 InternalMeasure(string text)
{ {
if (text.Length < 1) if (text.Length < 1)
{
return Vector2.Zero; return Vector2.Zero;
}
Vector2 size = Vector2.Zero; Vector2 size = Vector2.Zero;
size.Y = this.lineSpacing; size.Y = this.LineSpacing;
float maxWidth = 0f; float maxWidth = 0f;
int currentCharacter = 0; int currentCharacter = 0;
float z = 0f; float z = 0f;
@ -186,11 +207,8 @@ namespace ANX.Framework.Graphics
for (int i = 0; i < text.Length; i++) for (int i = 0; i < text.Length; i++)
{ {
char currentChar = text[i]; char currentChar = text[i];
if (currentChar == '\r') if (currentChar == '\r')
{
continue; continue;
}
if (currentChar == '\n') if (currentChar == '\n')
{ {
@ -198,33 +216,32 @@ namespace ANX.Framework.Graphics
z = 0f; z = 0f;
maxWidth = Math.Max(size.X, maxWidth); maxWidth = Math.Max(size.X, maxWidth);
size = Vector2.Zero; size = Vector2.Zero;
size.Y = this.lineSpacing; size.Y = LineSpacing;
firstCharacterInLine = true; firstCharacterInLine = true;
currentCharacter++; currentCharacter++;
continue;
} }
else
{ int currentCharIndex = GetIndexForCharacter(currentChar);
int currentCharIndex = this.GetIndexForCharacter(currentChar); Vector3 kerning = kernings[currentCharIndex];
Vector3 kerning = this.kerning[currentCharIndex];
if (firstCharacterInLine) if (firstCharacterInLine)
{
kerning.X = Math.Max(kerning.X, 0f); kerning.X = Math.Max(kerning.X, 0f);
}
else else
{
size.X += this.Spacing + z; size.X += this.Spacing + z;
}
size.X += kerning.X + kerning.Y; size.X += kerning.X + kerning.Y;
z = kerning.Z; z = kerning.Z;
size.Y = Math.Max(size.Y, (float)this.cropping[currentCharIndex].Height); size.Y = Math.Max(size.Y, (float)cropping[currentCharIndex].Height);
firstCharacterInLine = false; firstCharacterInLine = false;
} }
}
size.Y += currentCharacter * this.lineSpacing; size.Y += currentCharacter * LineSpacing;
size.X = Math.Max(Math.Max(z, 0) + size.X, maxWidth); size.X = Math.Max(Math.Max(z, 0) + size.X, maxWidth);
return size; return size;
} }
#endregion
#region GetIndexForCharacter
private int GetIndexForCharacter(char character) private int GetIndexForCharacter(char character)
{ {
int currentIndex = 0; int currentIndex = 0;
@ -235,28 +252,20 @@ namespace ANX.Framework.Graphics
while (currentIndex <= upperBound) while (currentIndex <= upperBound)
{ {
searchPos = currentIndex + ((upperBound - currentIndex) >> 1); searchPos = currentIndex + ((upperBound - currentIndex) >> 1);
testChar = this.characterMap[searchPos]; testChar = characterMap[searchPos];
if (testChar == character) if (testChar == character)
{
return searchPos; return searchPos;
}
else if (testChar > character) else if (testChar > character)
{
upperBound = searchPos - 1; upperBound = searchPos - 1;
}
else else
{
currentIndex = searchPos + 1; currentIndex = searchPos + 1;
} }
}
if (this.defaultCharacter.HasValue) if (defaultCharacter.HasValue)
{ return GetIndexForCharacter(defaultCharacter.Value);
return this.GetIndexForCharacter(this.defaultCharacter.Value);
}
throw new ArgumentException("character not found"); throw new ArgumentException("character not found");
} }
#endregion
} }
} }

View File

@ -8,16 +8,13 @@ namespace ANX.Framework.Graphics
{ {
internal struct SpriteInfo internal struct SpriteInfo
{ {
//public Vector2 TopLeft;
//public Vector2 BottomRight;
public Vector2[] Corners; public Vector2[] Corners;
public Color Tint; public Color Tint;
public Texture2D texture; public Texture2D texture;
public Single rotation; public float rotation;
public Vector2 origin; public Vector2 origin;
public Single layerDepth; public float layerDepth;
public Vector2 topLeftUV; public Vector2 topLeftUV;
public Vector2 bottomRightUV; public Vector2 bottomRightUV;

View File

@ -16,6 +16,9 @@ namespace ANX.Framework.Graphics
protected internal int width; protected internal int width;
protected internal int height; protected internal int height;
internal float OneOverWidth;
internal float OneOverHeight;
private INativeTexture2D nativeTexture2D; private INativeTexture2D nativeTexture2D;
private INativeTexture2D NativeTexture2D private INativeTexture2D NativeTexture2D
{ {
@ -66,6 +69,8 @@ namespace ANX.Framework.Graphics
{ {
this.width = width; this.width = width;
this.height = height; this.height = height;
OneOverWidth = 1f / width;
OneOverHeight = 1f / height;
base.levelCount = 1; base.levelCount = 1;
base.format = SurfaceFormat.Color; base.format = SurfaceFormat.Color;
@ -79,6 +84,9 @@ namespace ANX.Framework.Graphics
{ {
this.width = width; this.width = width;
this.height = height; this.height = height;
OneOverWidth = 1f / width;
OneOverHeight = 1f / height;
// TODO: pass the mipmap parameter to the creation of the texture to let the graphics card generate mipmaps! // TODO: pass the mipmap parameter to the creation of the texture to let the graphics card generate mipmaps!
base.levelCount = 1; base.levelCount = 1;
base.format = format; base.format = format;
@ -91,6 +99,8 @@ namespace ANX.Framework.Graphics
{ {
this.width = width; this.width = width;
this.height = height; this.height = height;
OneOverWidth = 1f / width;
OneOverHeight = 1f / height;
base.levelCount = mipCount; base.levelCount = mipCount;
base.format = format; base.format = format;

View File

@ -16,9 +16,6 @@ namespace ANX.Framework.Graphics
public class VertexBuffer : GraphicsResource, IGraphicsResource public class VertexBuffer : GraphicsResource, IGraphicsResource
{ {
#region Private #region Private
private VertexDeclaration vertexDeclaration;
private int vertexCount;
private BufferUsage bufferUsage;
private INativeVertexBuffer nativeVertexBuffer; private INativeVertexBuffer nativeVertexBuffer;
#endregion #endregion
@ -29,55 +26,31 @@ namespace ANX.Framework.Graphics
{ {
get get
{ {
if (this.nativeVertexBuffer == null) if (nativeVertexBuffer == null)
{
CreateNativeBuffer(); CreateNativeBuffer();
}
return this.nativeVertexBuffer; return nativeVertexBuffer;
} }
} }
public BufferUsage BufferUsage public BufferUsage BufferUsage { get; private set; }
{ public int VertexCount { get; private set; }
get public VertexDeclaration VertexDeclaration { get; private set; }
{
return this.bufferUsage;
}
}
public int VertexCount
{
get
{
return this.vertexCount;
}
}
public VertexDeclaration VertexDeclaration
{
get
{
return this.vertexDeclaration;
}
}
#endregion #endregion
#region Constructor #region Constructor
public VertexBuffer(GraphicsDevice graphicsDevice, Type vertexType, public VertexBuffer(GraphicsDevice graphicsDevice, Type vertexType, int vertexCount, BufferUsage usage)
int vertexCount, BufferUsage usage) : this(graphicsDevice, VertexTypeHelper.GetDeclaration(vertexType), vertexCount, usage)
: this(graphicsDevice, VertexBuffer.TypeToVertexDeclaration(vertexType),
vertexCount, usage)
{ {
} }
public VertexBuffer(GraphicsDevice graphicsDevice, public VertexBuffer(GraphicsDevice graphicsDevice, VertexDeclaration vertexDeclaration, int vertexCount,
VertexDeclaration vertexDeclaration, int vertexCount, BufferUsage usage) BufferUsage usage)
: base(graphicsDevice) : base(graphicsDevice)
{ {
this.vertexCount = vertexCount; VertexCount = vertexCount;
this.vertexDeclaration = vertexDeclaration; VertexDeclaration = vertexDeclaration;
this.bufferUsage = usage; BufferUsage = usage;
base.GraphicsDevice.ResourceCreated += GraphicsDevice_ResourceCreated; base.GraphicsDevice.ResourceCreated += GraphicsDevice_ResourceCreated;
base.GraphicsDevice.ResourceDestroyed += GraphicsDevice_ResourceDestroyed; base.GraphicsDevice.ResourceDestroyed += GraphicsDevice_ResourceDestroyed;
@ -120,17 +93,16 @@ namespace ANX.Framework.Graphics
#region CreateNativeBuffer #region CreateNativeBuffer
private void CreateNativeBuffer() private void CreateNativeBuffer()
{ {
this.nativeVertexBuffer = var creator = AddInSystemFactory.Instance.GetDefaultCreator<IRenderSystemCreator>();
AddInSystemFactory.Instance.GetDefaultCreator<IRenderSystemCreator>().CreateVertexBuffer(GraphicsDevice, this, vertexDeclaration, vertexCount, bufferUsage); this.nativeVertexBuffer = creator.CreateVertexBuffer(GraphicsDevice, this, VertexDeclaration, VertexCount,
BufferUsage);
} }
#endregion #endregion
#region GetData #region GetData
public void GetData<T>(int offsetInBytes, T[] data, int startIndex, public void GetData<T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride) where T : struct
int elementCount, int vertexStride) where T : struct
{ {
NativeVertexBuffer.GetData(offsetInBytes, data, startIndex, NativeVertexBuffer.GetData(offsetInBytes, data, startIndex, elementCount, vertexStride);
elementCount, vertexStride);
} }
public void GetData<T>(T[] data) where T : struct public void GetData<T>(T[] data) where T : struct
@ -138,19 +110,16 @@ namespace ANX.Framework.Graphics
NativeVertexBuffer.GetData(data); NativeVertexBuffer.GetData(data);
} }
public void GetData<T>(T[] data, int startIndex, int elementCount) public void GetData<T>(T[] data, int startIndex, int elementCount) where T : struct
where T : struct
{ {
NativeVertexBuffer.GetData(data, startIndex, elementCount); NativeVertexBuffer.GetData(data, startIndex, elementCount);
} }
#endregion #endregion
#region SetData #region SetData
public void SetData<T>(int offsetInBytes, T[] data, int startIndex, public void SetData<T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride) where T : struct
int elementCount, int vertexStride) where T : struct
{ {
NativeVertexBuffer.SetData(GraphicsDevice, offsetInBytes, data, NativeVertexBuffer.SetData(GraphicsDevice, offsetInBytes, data, startIndex, elementCount, vertexStride);
startIndex, elementCount, vertexStride);
} }
public void SetData<T>(T[] data) where T : struct public void SetData<T>(T[] data) where T : struct
@ -164,19 +133,6 @@ namespace ANX.Framework.Graphics
} }
#endregion #endregion
#region TypeToVertexDeclaration
private static VertexDeclaration TypeToVertexDeclaration(Type t)
{
IVertexType vt = Activator.CreateInstance(t) as IVertexType;
if (vt != null)
{
return vt.VertexDeclaration;
}
return null;
}
#endregion
#region Dispose #region Dispose
public override void Dispose() public override void Dispose()
{ {
@ -186,16 +142,17 @@ namespace ANX.Framework.Graphics
nativeVertexBuffer = null; nativeVertexBuffer = null;
} }
if (vertexDeclaration != null)
{
// do not dispose the VertexDeclaration here, because it's only a reference // do not dispose the VertexDeclaration here, because it's only a reference
vertexDeclaration = null; if (VertexDeclaration != null)
} VertexDeclaration = null;
} }
protected override void Dispose([MarshalAs(UnmanagedType.U1)] bool disposeManaged) protected override void Dispose([MarshalAs(UnmanagedType.U1)] bool disposeManaged)
{ {
throw new NotImplementedException(); if (disposeManaged)
{
Dispose();
}
} }
#endregion #endregion
} }

View File

@ -2,6 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using ANX.Framework.Graphics; using ANX.Framework.Graphics;
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license
namespace ANX.Framework.NonXNA.RenderSystem namespace ANX.Framework.NonXNA.RenderSystem
{ {
internal static class VertexTypeHelper internal static class VertexTypeHelper
@ -14,7 +18,17 @@ namespace ANX.Framework.NonXNA.RenderSystem
if (rememberedInstances.ContainsKey(type) == false) if (rememberedInstances.ContainsKey(type) == false)
rememberedInstances.Add(type, Activator.CreateInstance<T>()); rememberedInstances.Add(type, Activator.CreateInstance<T>());
return rememberedInstances[type].VertexDeclaration; var result = rememberedInstances[type];
return result != null ? result.VertexDeclaration : null;
}
public static VertexDeclaration GetDeclaration(Type type)
{
if (rememberedInstances.ContainsKey(type) == false)
rememberedInstances.Add(type, Activator.CreateInstance(type) as IVertexType);
var result = rememberedInstances[type];
return result != null ? result.VertexDeclaration : null;
} }
} }
} }

View File

@ -21,11 +21,18 @@ namespace TextRendering
SpriteFont debugFont; SpriteFont debugFont;
int fps = 60;
int fpsCount = 0;
float fpsTimer = 0f;
public Game1() public Game1()
{ {
graphics = new GraphicsDeviceManager(this); graphics = new GraphicsDeviceManager(this);
graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings); graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings);
Content.RootDirectory = "SampleContent"; Content.RootDirectory = "SampleContent";
IsFixedTimeStep = false;
graphics.SynchronizeWithVerticalRetrace = false;
} }
void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e) void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
@ -55,6 +62,15 @@ namespace TextRendering
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit(); this.Exit();
fpsCount++;
fpsTimer += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (fpsTimer >= 1f)
{
fpsTimer -= 1f;
fps = fpsCount;
fpsCount = 0;
}
base.Update(gameTime); base.Update(gameTime);
} }
@ -63,7 +79,7 @@ namespace TextRendering
GraphicsDevice.Clear(Color.CornflowerBlue); GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.FrontToBack, null); spriteBatch.Begin(SpriteSortMode.FrontToBack, null);
spriteBatch.DrawString(this.debugFont, "Hello World!", new Vector2(100, 100), Color.White); spriteBatch.DrawString(this.debugFont, "Hello World! FPS: " + fps, new Vector2(100, 100), Color.White);
spriteBatch.DrawString(this.debugFont, "This screen is powered by the ANX.Framework!\r\nsecond line", new Vector2(100, 100 + this.debugFont.LineSpacing), Color.Black, 0.0f, new Vector2(1, -1), Vector2.One, SpriteEffects.None, 0.0f); spriteBatch.DrawString(this.debugFont, "This screen is powered by the ANX.Framework!\r\nsecond line", new Vector2(100, 100 + this.debugFont.LineSpacing), Color.Black, 0.0f, new Vector2(1, -1), Vector2.One, SpriteEffects.None, 0.0f);
spriteBatch.DrawString(this.debugFont, "This screen is powered by the ANX.Framework!\r\nsecond line", new Vector2(100, 100 + this.debugFont.LineSpacing), Color.Red, 0.0f, Vector2.Zero, Vector2.One, SpriteEffects.None, 1.0f); spriteBatch.DrawString(this.debugFont, "This screen is powered by the ANX.Framework!\r\nsecond line", new Vector2(100, 100 + this.debugFont.LineSpacing), Color.Red, 0.0f, Vector2.Zero, Vector2.One, SpriteEffects.None, 1.0f);

View File

@ -11,6 +11,7 @@ namespace TextRendering
static void Main(string[] args) static void Main(string[] args)
{ {
//AddInSystemFactory.Instance.SetPreferredSystem(AddInType.RenderSystem, "OpenGL3"); //AddInSystemFactory.Instance.SetPreferredSystem(AddInType.RenderSystem, "OpenGL3");
AddInSystemFactory.Instance.SetPreferredSystem(AddInType.RenderSystem, "DirectX10");
//AddInSystemFactory.Instance.SetPreferredSystem(AddInType.RenderSystem, "DirectX11"); //AddInSystemFactory.Instance.SetPreferredSystem(AddInType.RenderSystem, "DirectX11");
using (Game1 game = new Game1()) using (Game1 game = new Game1())