I was learning about rendering and coding shaders or effects in Monogame, and have learned the basics of adding color and shaping functions in my shaders thanks to the resources I found online.
From what I have learned so far,I have to type "*effect: my_effect" in the Spritebatch.Begin() parameter then add the following in the Draw method of the program:
(CODE WORKS FINE)
_spriteBatch.Begin(effect:my_effect);
_spriteBatch.Draw(my_Texture2D, my_Rectangle, Color);
_spriteBatch.End();
The code above worked fine, it was nice. The problem shows up when I added a Vector2 in the Draw parameter and all of a sudden the shader was not rendering correctly:
(CODE THAT DOESN'T WORK FINE)
_spriteBatch.Begin(effect:my_effect);
_spriteBatch.Draw(my_Texture2D, my_Rectangle, my_Vector2, Color);
_spriteBatch.End();
I hope there is someone that can help, I would appreciate it.
Here is the code below (for context):
public class Game1 : Game
{
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
Rectangle boxus;
Texture2D color;
Effect first_effect;
Vector2 magi;
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
magi = new Vector2(0, 0);
boxus = new Rectangle(0,0, 100, 100);
color = new Texture2D(GraphicsDevice, 1, 1);
first_effect = Content.Load<Effect>("Shader");
color.SetData<Color>(new Color[] { Color.White});
base.Initialize();
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
}
protected override void Update(GameTime gameTime)
{
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
_spriteBatch.Begin(effect:first_effect);
_spriteBatch.Draw(color,magi,boxus, Color.White);
_spriteBatch.End();
base.Draw(gameTime);
}
}
Not great:
Great:
Edit: Here is my custom shader code below:
#if OPENGL
#define SV_POSITION POSITION
#define VS_SHADERMODEL vs_3_0
#define PS_SHADERMODEL ps_3_0
#else
#define VS_SHADERMODEL vs_4_0_level_9_1
#define PS_SHADERMODEL ps_4_0_level_9_1
#endif
Texture2D SpriteTexture;
sampler2D SpriteTextureSampler = sampler_state
{
Texture = <SpriteTexture>;
};
struct VertexShaderOutput
{
float4 Position : SV_POSITION;
float4 Color : COLOR0;
float2 TextureCoordinates : TEXCOORD0;
};
float4 MainPS(VertexShaderOutput input) : COLOR
{
float col = tex2D(SpriteTextureSampler, input.TextureCoordinates) * input.Color;
float shape_function = step(input.TextureCoordinates.x, sqrt(input.TextureCoordinates.y));
float3 colorzz = float3(0.9, 0.5, 0.2);
//THE MIX FUNCITON
colorzz = colorzz * (1 - step(0.5, input.TextureCoordinates.y)) + float3(0.0, 0.3, 0.9) * step(0.5, input.TextureCoordinates.y);
float4 output = float4(colorzz * shape_function, 1.0);
return col * output;
}
technique SpriteDrawing
{
pass P0
{
PixelShader = compile PS_SHADERMODEL MainPS();
}
};
just as you mentioned, multiply texCoords
Added some additional code to move the sprite
The problem stems from the 2 different used Draw(...) methods of SpriteBatch.
The first one defines a destination rectangle, meaning your texture is 'stretched' to the given rectangle in the target framebuffer, hence a 100 x 100 rect at position 0, 0.
public void Draw(Texture2D texture, Rectangle destinationRectangle, Color color) {...}
The second Draw function you used instead takes a rectangle to define which part of the source texture should be drawn and at which position in the target framebuffer:
public void Draw(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color) {...}
Because of that, it assumed a 100 x 100 rect in the source texture (size 1 x 1 px), leading to a 100 times stretched Sqrt function.
I think, for your case, you could use this one:
public void Draw(Texture2D texture, Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color) {...}
Here x, y of the destination rectangle then would be the actual final position in the target framebuffer and your source rectangle would be new(0,0,1,1)
Hope this helps, let me know if you need more information. Ctrl-Click on the Draw function leads you to the SpriteBatch class where you can see all the different Draw function alternatives.
Edit 1:
First, you can adjust the value range however you like inside of the shader by multiplying the tex coord values or if int is sufficient by sending a source rectangle like this: new(-1,-1,2,2) (! untested).
Second, you might get everything you need by using this function (scale is your final size):
public void Draw(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) {...}