warning x3206 implicit truncation of vector type

  1. float Percentage;
  1. sampler TextureSampler: register(s0);
  2. float4 PixelShaderFunction(float2 Tex: TEXCOORD0) : COLOR0
  3. {
  4. float4 Color = tex2D(TextureSampler, Tex);
  5. float r = Color.r;
  6. float g = Color.g;
  7. float b = Color.b;
  8. Color.rgb = dot(Color.rgb, float3(0.7 * Percentage, 0.59 * Percentage, 0.11 * Percentage));
  9. r = r - (r - Color.rgb) * Percentage;
  10. g = g - (g - Color.rgb) * Percentage;
  11. b = b - (b - Color.rgb) * Percentage;
  12. Color.r = r;
  13. Color.g = g;
  14. Color.b = b;
  1. return Color;
  2. }
  1. technique tech
  2. {
  3. pass Pass1
  4. {
  5.   PixelShader = compile ps_4_0_level_9_1 
    
  6.   PixelShaderFunction();
    
  7. }
  8. }

I’ve been knocking around shaders in monogame and found this example. but it shows me a warning
"warning x3206 (13,2 - 37) implicit truncation of vector type
"warning x3206 (14,2 - 38) implicit truncation of vector type
“warning x3206 (15,2 - 37) implicit truncation of vector type”

Lines in 2MGFX shaders are incorrect, so sometimes you get the error in line 13 but it’s in another line. https://github.com/MonoGame/MonoGame/issues/4437

That said, the warning is telling you that a vector is being truncated implicitly, which means that in this example, you have a float3 that is being converted to float and it’s probably an error.

In the line 10 you have r = r - (r - Color.rgb) * Percentage;
Color.rgb is a float3 and the variable receiving the value ® is a float. So the compiler is truncating Color.rgb into Color.r.

The “correct code” should be:

r = r - (r - Color.r) * Percentage; g = g - (g - Color.g) * Percentage; b = b - (b - Color.b) * Percentage;

that code can be optimized though

2 Likes
  1. Another issue, when I turn on the shader. I get only cornflowerblue screen without the player sprite.

  2. using Microsoft.Xna.Framework;

  3. using Microsoft.Xna.Framework.Graphics;

  4. using System;

  5. using System.Collections.Generic;

  6. using System.Linq;

  7. using System.Text;

  8. using System.Threading.Tasks;

  9. namespace MonoGameTanks

  10. {

  11. public class Entity
    
  12. {
    
  13.     public Texture2D tex;
    
  14.     private Vector2 pos;
    
  15.     public Entity(Texture2D texure, Vector2 vec)
    
  16.     {
    
  17.         this.tex = texure;
    
  18.         this.pos = vec;
    
  19.     }
    
  20.     public void Update()
    
  21.     {
    
  22.         this.pos.X += 1;
    
  23.     }
    
  24.     public void Draw(SpriteBatch sb)
    
  25.     {
    
  26.         sb.Draw(this.tex, this.pos, Color.White);
    
  27.     }
    
  28. }
    
  29. }


  1. public class Game1 : Game
    
  2. {
    
  3.     GraphicsDeviceManager graphics;
    
  4.     SpriteBatch spriteBatch;
    
  5.     public float x = 1.0f;
    
  6.     public Entity player;
    
  7.     public Effect grayScaleEffect;
    
  8.     public float percent;
    
  9.     float percantscale = 0.01f;
    
  10.     public Game1()
    
  11.     {
    
  12.         graphics = new GraphicsDeviceManager(this);
    
  13.         graphics.PreferredBackBufferHeight = 768;
    
  14.         graphics.PreferredBackBufferWidth = 1024;
    
  15.         Content.RootDirectory = "Content";
    
  16.         IsMouseVisible = true;
    
  17.     }
    
  18.     protected override void Initialize()
    
  19.     {
    
  20.         base.Initialize();
    
  21.     }
    
  22.     protected override void LoadContent()
    
  23.     {
    
  24.         spriteBatch = new SpriteBatch(GraphicsDevice);
    
  25.         player = new Entity(Content.Load<Texture2D>("spaceship"), new Vector2(100, 100));
    
  26.         grayScaleEffect = Content.Load<Effect>("shader");
    
  27.         percent = 10.0f;
    
  28.     }
    
  29.     protected override void UnloadContent()
    
  30.     {
    
  31.     }
    
  32.     protected override void Update(GameTime gameTime)
    
  33.     {
    
  34.         if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
    
  35.             Exit();
    
  36.         player.Update();
    
  37.         if (percent > 0)
    
  38.         {
    
  39.             percent -= percantscale;
    
  40.             grayScaleEffect.Parameters["Percentage"].SetValue(percent);
    
  41.         }
    
  42.         if (Keyboard.GetState().IsKeyDown(Keys.Space))
    
  43.         {
    
  44.             if (percent <= 0)
    
  45.             {
    
  46.                 percent = 10.0f;
    
  47.             }
    
  48.         }
    
  49.         base.Update(gameTime);
    
  50.     }
    
  51.     protected override void Draw(GameTime gameTime)
    
  52.     {
    
  53.          GraphicsDevice.Clear(Color.CornflowerBlue); 
    
  54.          spriteBatch.Begin(0, null, null, null, null, grayScaleEffect);
    
  55.          player.Draw(spriteBatch);
    
  56.          spriteBatch.End();
    
  57.          base.Draw(gameTime);
    
  58.     }
    
  59. }

// plain old grey scale is this.

float4 Color = tex2D(TextureSampler, Tex);
Color.rgb = (Color.r + Color.g + Color.b) / 3.0f;
return Color;

// the magic values are just supposed to make it look better.

Color.rgb = Color.rgb * float3(0.7f, 0.59f, 0.11f);
Color.rgb = (Color.r + Color.g + Color.b) * 0.333f;

As for the texture it’ s probably just simpler to have you look at a full shader used with spritebatch.

At the least you need to have your pixel shader input match the vertex shader output

struct VertexShaderOutput
{
    float4 Position : SV_Position;
    float4 Color : COLOR0;
    float2 TexureCoordinate : TEXCOORD0;
}

PixelShaderOutput PixelShaderFunction(VertexShaderOutput input)
{
    PixelShaderOutput output;
    float4 col = tex2D(TextureSampler, input.TexureCoordinate) * input.Color;

// ect...
1 Like

I don’t know why, but I’ve tried this tutorial tutorial and I still can’t get the sprite drawn on the screen, only cornflowerblue bg.I’ve used the grayscale shader from the tutorial.

Are you just trying to do a greyscale shader ?

Yes, I’m. I’ve thought the first example was a bit complicated with the “percentage”.

I think i already redid that example for someone but hold on ill just write out a shader for spritebatch im on my laptop its super slow.

1 Like

Sorry my little laptop is chugging.

// the pixel shader.

#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 percent;

//Texture2D Texture : register(t0);
sampler2D TextureSampler : register(s0)
{
    Texture = (Texture);
};

float4 MainPS(float4 position : SV_Position, float4 color : COLOR0, float2 TextureCoordinates : TEXCOORD0) : COLOR0
{
    float4 col = tex2D(TextureSampler, TextureCoordinates)* color;
    col.rgb = (col.r + col.g + col.b) / 3.0f * percent;
    return col;
}

technique BasicColorDrawing
{
    pass P0
    {
        PixelShader = compile PS_SHADERMODEL MainPS();
    }
};

// game1

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace HowToPixelShaderWithSpriteBatch
{

    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D texture;
        Effect effect;

        float percent = 1.0f;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }
        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            texture = Content.Load < Texture2D >("rabbit");
            effect = Content.Load<Effect>("ShaderForSpriteBatch");
            effect.CurrentTechnique = effect.Techniques["BasicColorDrawing"];

            //effect.Parameters["Texture"].SetValue(texture);
        }

        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();

            if (Keyboard.GetState().IsKeyDown(Keys.Space))
            {
                percent -= .01f;
                if (percent <= 0)
                    percent = 1.0f;
            }
            effect.Parameters["percent"].SetValue(percent);

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null, effect, null);
            spriteBatch.Draw(texture, new Rectangle(0, 0, 300, 300), Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

I have a example here as well for doing alpha effects.

1 Like

Hi, thank you for your help. The shader is working now.
What’s the purpose of this line: grayScaleEffect.CurrentTechnique.Passes[0].Apply(); ? Do I need to use it in the main draw method?
And is there a difference between applying shaders to a screen or objects?

What’s the purpose of this line: grayScaleEffect.CurrentTechnique.Passes[0].Apply(); ?

This line tells the shader to set the targeted pass for drawing. Shaders can have more then one pass in a technique. In this case…

The effect is grayScaleEffect
The technique to apply changes to is the current one
The particular pass is set to [0]. // safe if you only have one pass.

Some shaders can have more then one pass.

For example the one im working on right now is a two pass shader the apply call is used from game one to make sure both passes execute when triangles are drawn.

This is on the shader.

technique Create360DegreeShadowDepth
{
    pass Pass0
    {
        VertexShader = compile VS_SHADERMODEL
            Create360DegreeShadowDepthVertexShaderPass0();
        PixelShader = compile PS_SHADERMODEL
            Create360DegreeShadowDepthPixelShader();
    }
    pass Pass1
    {
        VertexShader = compile VS_SHADERMODEL
            Create360DegreeShadowDepthVertexShaderPass1();
        PixelShader = compile PS_SHADERMODEL
            Create360DegreeShadowDepthPixelShader();
    }
}

When i draw it i make sure both passes execute like so by looping thru all the passes.

This is in game1 or the class file that i call to it from.

        public void DrawAllParts(GraphicsDevice gd, Effect effect)
        {
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                gd.DrawUserPrimitives(PrimitiveType.TriangleList, vertexArray, 0, vertexArray.Length /3, VertexPositionPositionLightIndexNormal.VertexDeclaration);
            }
        }

While this doesn’t use spritebatch what spritebatch does is basically the same thing with extra sauce.

And is there a difference between applying shaders to a screen or objects?

No however when you are drawing sprites the area affected on screen is limited to the destination area you are drawing to so then too is the effect.

It is possible to draw a screen sized rectangle that will allow the pixel shader to affect everything on screen.

Absolutely and this is done often.

This is the primary reason RenderTargets are useful. You can draw everything to them then use them as if they are a big texture for a final draw with a pixel shader at the end. Which is drawing the RenderTarget to the backbuffer in one draw.

1 Like