Hello,
I want to generate multiple tilesheets with different terrain textures at game initialize.
Terrains
Master tilesheet
Border tilesheet
Using masking I blend each terrain with the master tile to create 3 different terrains. After that a border with masking is also added and the tilesheet is saved using RenderTarget.
Okay, the issue is that the code works, but running it creates a drop in FPS. (Note that the tilesheet saving is only called once)
I don’t know if monogame is having trouble to cache a few tilesheets or if I’m allocating huge amounts of unused memory. Any help or suggestions will be appreciated.
The TileCache Static Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
namespace BuildTest
{
static class TileCache
{
private static GraphicsDevice graphicsDevice = Asset.GraphicsDevice;
private static Texture2D[] terrains;
private static Texture2D texture;
private static Texture2D textureMask;
private static Texture2D textureShaderColor;
private static Texture2D textureShader;
private static Vector2[] sourcePos;
private static RenderTarget2D renderTarget;
private static Matrix projection;
private static AlphaTestEffect alphaEffect1;
private static AlphaTestEffect alphaEffect2;
public static Texture2D Terrain(int id)
{
return terrains[id];
}
private static Dictionary<int, Texture2D> terrainShaders;
public static bool IsCached { get; set; }
public static void Initialize(Vector2[] _sourcePos, Texture2D _texture, Texture2D _textureMask)
{
//Shaders
terrainShaders = new Dictionary<int, Texture2D>
{
[0] = new SolidColorTexture(graphicsDevice, Color.Transparent),
[1] = new SolidColorTexture(graphicsDevice, Color.White),
[2] = new SolidColorTexture(graphicsDevice, new Color(113, 89, 60, 255)),
[3] = new SolidColorTexture(graphicsDevice, new Color(157, 234, 128, 255)),
};
//Setting the different terrains
sourcePos = _sourcePos;
//Setting the textures
texture = _texture;
textureMask = _textureMask;
textureShader = Asset.GetTexture("textures/tilesheet/maskshader_01");
textureShaderColor = new SolidColorTexture(graphicsDevice, Color.White);
//setting the terrain array size
terrains = new Texture2D[sourcePos.Length];
//Projection
projection = Matrix.CreateOrthographicOffCenter(0, textureMask.Width, textureMask.Height, 0, 0, 1);
//Render
renderTarget = new RenderTarget2D(graphicsDevice, textureMask.Width, textureMask.Height, false, graphicsDevice.PresentationParameters.BackBufferFormat, DepthFormat.Depth24Stencil8);
//Stencils
alphaEffect1 = new AlphaTestEffect(graphicsDevice)
{
AlphaFunction = CompareFunction.Equal,
ReferenceAlpha = 127
};
alphaEffect1.Projection = projection;
alphaEffect2 = new AlphaTestEffect(graphicsDevice)
{
AlphaFunction = CompareFunction.Greater,
ReferenceAlpha = 130
};
alphaEffect2.Projection = projection;
}
private static void Shader(GameTime gameTime, SpriteBatch sb)
{
sb.Draw(textureShader, new Vector2(0, 0), Color.White);
}
private static void ShaderColor(SpriteBatch sb, int key)
{
sb.Draw(terrainShaders[key], new Rectangle(0, 0, textureShader.Width, textureShader.Height), Color.White);
}
private static void Mask(GameTime gameTime, SpriteBatch sb)
{
sb.Draw(textureMask, new Vector2(0, 0), Color.White);
}
private static void DrawSurface(SpriteBatch sb, int key)
{
for (int x = 0; x < textureMask.Width / TileMap.tileWidth; x++)
{
for (int y = 0; y < textureMask.Height / TileMap.tileHeight; y++)
{
sb.Draw(texture, new Vector2(x * TileMap.tileWidth, y * TileMap.tileHeight), new Rectangle((int)sourcePos[key].X, (int)sourcePos[key].Y, TileMap.tileWidth, TileMap.tileHeight), Color.White);
}
}
}
private static void ResetDraw()
{
graphicsDevice.SetRenderTarget(null);
graphicsDevice.DepthStencilState = new DepthStencilState() { DepthBufferEnable = true };
graphicsDevice.SetRenderTarget(renderTarget);
graphicsDevice.Clear(Color.Transparent);
}
public static void Cache(GameTime gameTime, SpriteBatch spriteBatch)
{
for (int i = 0; i < sourcePos.Length; i++)
{
ResetDraw();
//First masking
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, TileMap.AlwaysStencilState, null, alphaEffect1);
Mask(gameTime, spriteBatch);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, alphaEffect2);
Mask(gameTime, spriteBatch);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, TileMap.EqualStencilState, null, null);
DrawSurface(spriteBatch, i);
spriteBatch.End();
Texture2D saveMasking = new Texture2D(graphicsDevice, textureMask.Width, textureMask.Height);
Color[] Maskdata = new Color[textureMask.Width * textureMask.Height];
renderTarget.GetData(Maskdata);
saveMasking.SetData(Maskdata);
ResetDraw();
//Shaders
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, TileMap.AlwaysStencilState, null, alphaEffect1);
Shader(gameTime, spriteBatch);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, alphaEffect2);
Shader(gameTime, spriteBatch);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, TileMap.EqualStencilState, null, null);
ShaderColor(spriteBatch, i);
spriteBatch.End();
Texture2D saveShader = new Texture2D(graphicsDevice, textureMask.Width, textureMask.Height);
Color[] shaderData = new Color[textureMask.Width * textureMask.Height];
renderTarget.GetData(shaderData);
saveShader.SetData(shaderData);
ResetDraw();
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null);
spriteBatch.Draw(saveMasking, new Vector2(0, 0), Color.White);
spriteBatch.Draw(saveShader, new Vector2(0, 0), Color.White);
spriteBatch.End();
terrains[i] = new Texture2D(graphicsDevice, textureMask.Width, textureMask.Height);
Color[] data = new Color[textureMask.Width * textureMask.Height];
renderTarget.GetData(data);
terrains[i].SetData(data);
graphicsDevice.SetRenderTarget(null);
}
renderTarget.Dispose();
renderTarget = null;
}
}
}