Hello, I’m currently messing for the first time with shaders and i’d like to experiment it on a game I’m working on with Monogame. Apparently there’s a few type of shaders and I’m most interested in post-processing (like this one) and 2d procedural generation (like this one). I have problems applying the first one to a texture in my game. Since Monogame needs HLSL and Shadertoy is GLSL, here is my convertion :
#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
float time;
sampler TexSampler : register(s0);
sampler texture1 = sampler_state
{
Texture = <textureToChrome>;
};
struct VertexShaderOutput
{
float4 Position : SV_POSITION;
float4 Color : COLOR0;
float2 texCoord : TEXCOORD0;
};
float4 PSMain(VertexShaderOutput input) : COLOR {
float2 uv = input.texCoord.xy;
float amount = 0.0;
amount = (1.0 + sin(time*6.0)) * 0.5;
amount *= 1.0 + sin(time*16.0) * 0.5;
amount *= 1.0 + sin(time*19.0) * 0.5;
amount *= 1.0 + sin(time*27.0) * 0.5;
amount = pow(amount, 3.0);
amount *= 0.05;
float3 col;
col.r = tex2D(texture1, float2(uv.x + amount, uv.y)).r;
col.g = tex2D(texture1, uv).g;
col.b = tex2D(texture1, float2(uv.x - amount, uv.y)).b;
col *= (1.0 - amount * 0.5);
return float4(col, 1.0);
}
technique ChromaticAberation
{
pass P0
{
PixelShader = compile PS_SHADERMODEL PSMain();
}
};
Let’s say I want to apply this shader on a texture I have in game, here’s my code with shader initialization, shader update and game draws :
public Effect shader_sky; //The procedural effect I know how to apply
public Effect shader_chromatic; //The chrome effect I need to know how to apply
protected override void LoadContent()
{
shader_sky = Content.Load<Effect>("Effects/Sky");
shader_chromatic = Content.Load<Effect>("Effects/ChromaticAberation");
}
protected override void Update(GameTime gameTime)
{
shader_sky.Parameters["time"].SetValue((float)gameTime.TotalGameTime.TotalSeconds);
shader_chromatic.Parameters["time"].SetValue((float)gameTime.TotalGameTime.TotalSeconds);
}
protected override void Draw(GameTime gameTime)
{
#region Draw the sky shader
spriteBatch.Begin(sortMode: SpriteSortMode.BackToFront,
blendState: BlendState.AlphaBlend,
samplerState: SamplerState.AnisotropicWrap,
rasterizerState: rasterizer,
transformMatrix: viewMatrix,
effect: shader_sky);
Texture2D background = new Texture2D(graphics.GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
background .SetData<Color>(new Color[] { Color.White});
spriteBatch.Draw(texture: background ,
destinationRectangle: wholeScreenRectangle,
layerDepth: 1f,
scale: new Vector2(brownBackgroundRatio),
color: Color.White,
effects: SpriteEffects.FlipVertically); //Flip because othewise the shader is reverse, I don't know why
spriteBatch.End();
#endregion
#region Draw the rest of the game
spriteBatch.Draw(player.texture,
player.position,
player.spriteStep,
player.color,
player.rotation,
player.origin,
player.scale,
player.spriteEffect, //Flip right or left
player.layerDepth);
/*
* And a bunch of other draws that don't need shaders
*/
#endregion
}
And now I don’t know how to apply the chromatic effect into the player’s sprite. I tried something like this before the draw and after :
shader_chromatic.Parameters["texture1"].SetValue(player.texture);
shader_chromatic.Techniques.First<EffectTechnique>().Passes.First<EffectPass>().Apply();
But it doesn’t work and feels like it’s not the right way to do this anyway. What I could do is the same as the shader_sky
(applying it on spriteBatch.Begin
) but how can the shader know where to apply the texture afterwards and do I really need to do something like :
Begin
Draw
End
Begin
Draw
End
//...Etc for each texture
If I want to apply shaders to different textures?
Also, to put a picture into line of codes, this is what it looks like for now, the blue/white background being successfully generated by the shader_sky and the player being the yellow character.
Thanks.