I saw this last night but i was too tired to respond.
Yes If you wish to bypass the hidef profile, you would need to make a couple minor alterations.
First you will need to add a vertex shader.
You will need to pass a spritebatch like projection matrix to that vertex shader.
Here is a altered example with the vertex shader added.
FxClipTextShader.Fx
// FxClipTextShader. with vertex shader
//
// This is can be used with spritebatch.
// Normally you can use spritebatches vertex shader and just use a pixel shader.
// Here we use the vertex shader too.
//
float4 VisibleBounds;
float4x4 WorldViewProjection;
Texture2D Texture : register(t0);
sampler TextureSampler : register(s0)
{
Texture = (Texture);
};
struct VertexShaderInput
{
float4 Position : POSITION0;
float4 Color : COLOR0;
float2 TexureCoordinate : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : SV_Position;
float4 Color : COLOR0;
float2 TexureCoordinate : TEXCOORD0;
float3 Position3D : TEXCOORD1;
};
struct PixelShaderOutput
{
float4 Color : COLOR0;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
output.Position3D = input.Position;
output.Position = mul(input.Position, WorldViewProjection);
output.Color = input.Color;
output.TexureCoordinate = input.TexureCoordinate;
return output;
}
PixelShaderOutput PixelShaderFunction(VertexShaderOutput input)
{
PixelShaderOutput output;
float4 col = tex2D(TextureSampler, input.TexureCoordinate) * input.Color;
float2 pos = input.Position3D.xy;
float dx = (pos.x - VisibleBounds.x) * (VisibleBounds.z - pos.x);
float dy = (pos.y - VisibleBounds.y) * (VisibleBounds.w - pos.y);
clip((sign(dx) + sign(dy)) - 0.001f);// change the if into a expression, clip is really a if else anyways
output.Color = col;
return output;
}
technique ClipTextBounds
{
pass
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
Game1 Implementation.
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace ClipTextShader
{
/// <summary>
/// This is a gl project should work for dx too.
/// </summary>
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Effect effect;
SpriteFont font;
string message = "";
Rectangle boundryRectangle;
public static Texture2D dotTexture;
Matrix projection;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 600;
graphics.ApplyChanges();
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
// load up your stuff
font = Content.Load<SpriteFont>("MgFont");
// load up your effect;
effect = Content.Load<Effect>("FxClipTextShader");
// set the current tequnique in your shader
effect.CurrentTechnique = effect.Techniques["ClipTextBounds"];
// create your projection matrix that is the same as spritebatches.
projection = CreateSpiteBatchProjection(true);
// set that to your effect as well
effect.Parameters["WorldViewProjection"].SetValue(projection);
// make a message
message =
" Ok so well need a projection matrix like spritebatch well create and set it probably just once to the shader so we just do that in load. " +
"\n We add a method that handles makeing that spritebatch like matrix so we dont have to worry about it later CreateSpiteBatchProjection(...). " +
"\n In my case i did this test on open gl so i had to set the bool for it to true in that method. " +
"\n We make a couple minor alterations to the pixel shader primarily we use that projection matrix and pass the world positions thru the vertex shader." +
"\n We also set the matrix in begin to null that matrix is really for the world and view but were bypassing it with our own vertex shader." +
"\n +\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+"
;
dotTexture = TextureDotCreate(GraphicsDevice);
}
/// <summary>
/// When using your own vertex shader with spritebatch things will get a little trickier because you have to handle the projection and viewport changes.
/// https://github.com/MonoGame/MonoGame/blob/develop/MonoGame.Framework/Graphics/SpriteBatch.cs
/// </summary>
public Matrix CreateSpiteBatchProjection(bool NeedsHalfPixelOffset)
{
var projection = Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 0, -1f);
if (NeedsHalfPixelOffset)
{
projection.M41 += -0.5f * projection.M11;
projection.M42 += -0.5f * projection.M22;
}
return projection;
}
public Texture2D TextureDotCreate(GraphicsDevice device)
{
Color[] data = new Color[1];
data[0] = new Color(255, 255, 255, 255);
Texture2D tex = new Texture2D(device, 1, 1);
tex.SetData<Color>(data);
return tex;
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Moccasin);
// set the cliping bounds
boundryRectangle = new Rectangle(100, 100, 200, 200);
effect.Parameters["VisibleBounds"].SetValue(GetVector4SbRectangle(boundryRectangle));
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.PointClamp, DepthStencilState.Default, RasterizerState.CullNone, effect, null);
effect.CurrentTechnique.Passes[0].Apply();
spriteBatch.Draw(dotTexture, boundryRectangle, Color.White);
spriteBatch.Draw(font.Texture, new Vector2(200, 250), Color.LightGray);
spriteBatch.DrawString(font, message, new Vector2(100f, 100f), Color.MonoGameOrange);
spriteBatch.End();
base.Draw(gameTime);
}
// we dont need that flip now i think.
public Vector4 GetVector4SbRectangle(Rectangle r)
{
return new Vector4(r.Left, (r.Top), r.Right, (r.Bottom));
}
}
}
I suppose you could do all sorts of little effects as well like fade based on distance from the edge or recolor pixels based on distance or whatever. But for just clipping the scissors thing is really easy.