[Solved] - Loading Shader - Generated colors from shader!

Hello everyone,

I really have written own simple Tutorial:

RB blog looks outdated.

I really want improve but I can’t understand why does MonoGame force to require EffectPass ?

  1. Initalizing Game // Like simple create MonoGame’s project with DesktopGL
  2. Drawing triangles
  3. Rendering indicesbuffer
  4. Loading Shaders “PROBLEM WITH COLORS PASSING TO VERTICES
    5 …

How do I load shader and shader should pass color to verticesData? I really don’t understand about FNA-Template because it used only texture. but for me no texture. Only vertices should pass with shader of custom color.

It’s not clear if your trying to do this with your own shader or monogames.
However per your rendering a indice buffer in this link.
rendering a indice buffer

The following changes allow vertex color with the built in monogame basic effect shader.

    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        VertexBuffer vertexBuffer;
        IndexBuffer indexBuffer;

        BasicEffect basicEffect;

        Matrix world = Matrix.Identity;
        Matrix view = Matrix.Identity;
        Matrix projection = Matrix.Identity;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            Window.Title = "Tutorial 03 - Rendering indicesbuffers";

            base.Initialize();
        }

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

            // you need a vertex definition that allows each vertice to be shaded.
            VertexPositionColor[] vertices = new VertexPositionColor[4];
            vertices[0] = new VertexPositionColor(new Vector3(-0.5f, 0.5f, 0f), Color.Red);
            vertices[1] = new VertexPositionColor(new Vector3(-0.5f, -0.5f, 0f), Color.Blue);
            vertices[2] = new VertexPositionColor(new Vector3(0.5f, -0.5f, 0f), Color.Green);
            vertices[3] = new VertexPositionColor(new Vector3(0.5f, 0.5f, 0f), Color.Yellow);

            vertexBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), 6, BufferUsage.WriteOnly);
            vertexBuffer.SetData<VertexPositionColor>(vertices);

            short[] indices = new short[6];
            // primitive # 1
            indices[0] = 0; indices[1] = 1; indices[2] = 2;
            // primitive # 2
            indices[3] = 2; indices[4] = 3; indices[5] = 0;

            indexBuffer = new IndexBuffer(graphics.GraphicsDevice, typeof(short), indices.Length, BufferUsage.WriteOnly);
            indexBuffer.SetData(indices);
        }

        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.CornflowerBlue);

            basicEffect.World = world;
            basicEffect.View = view;
            basicEffect.Projection = projection;
            // In basic effect tell it to use the vertice colors.
            basicEffect.VertexColorEnabled = true;

            GraphicsDevice.SetVertexBuffer(vertexBuffer);
            GraphicsDevice.Indices = indexBuffer;

            RasterizerState rasterizerState = new RasterizerState();
            rasterizerState.CullMode = CullMode.None;
            GraphicsDevice.RasterizerState = rasterizerState;

            foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
            {
                pass.Apply();
                // note ... this draws both primitives
                GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, indexBuffer.IndexCount /3);
            }

            base.Draw(gameTime);
        }
    }

Just so were clear this is monogames basic effect built in shader.
To use your own shader you have to add/create a new effect with the content pipeline tool.
Then edit the file load and use that effect, not the basic effect.

If you want to do this in your own shader and are having difficulty post your current code.

Really it is impossible but I want get colors from loading shader to passing vertices.

Why do I need VertexPositionColor?

But I want understand how does FNA Template make 4 different colors into spriteBatch. But for basicEffect not? How do I fix for native colors from loading shader.

// EDIT: Like MonoGame Github Example but I can not find where is passing parameter in Game1.cs

https://github.com/MonoGame/MonoGame/blob/develop/Test/Assets/Effects/RainbowH.fx

Thank you.

Why do I need VertexPositionColor?

You don’t with the example you just posted which is actually really a bad idea.
You did with your previous question.
Also you seem to be asking one thing then showing code for other things.

As for what you just posted
.
Yes you would probably want to make your own shader to do this.

However im still a little unclear on what exactly you want to do.
SpriteBatch can accept your shader and use it.
Or you can manually draw quads like in your example code.
Do you want to do this with spriteBatch or not ?

Also this example is a absolutely horrible way to do what is being shown.
Shaders don’t like all those if’'s and especially don’t like the if else logic chain set up.
That fx will give a rainbow but it will be a set of solid bars.

Further those colors are shader constants you wouldn’t need to pass them in to a custom effect.
They are already in that shader.
If you wanted to pass them you would define them as soo.
float4 red;
float4 orange;
float4 yellow;
ect… ect…
Then you could pass the colors for each via…
myExampleEffect.Parameters[“red”].SetValue( new Color(1f,0f,0f,1f) );
myExampleEffect.Parameters[“orange”].SetValue(Color.Orange);
myExampleEffect.Parameters[“yellow”].SetValue(Color.Yellow);

And no.
You cant pass those into or set them in BasicEffect as that is not part of basic effect.
It’s just some terrible random shader someone made up, probably as a test for something else.

Anyways just to be clear.

You make your own shader by first double clicking the pipline tool.
The orange icon.

You’'ll see the something like this but empty.
https://i0.wp.com/darkgenesis.zenithmoon.com/wp-content/uploads/2016/08/image_thumb-1.png?resize=244%2C195

Right click on the content then select ‘add new item’
pick a ‘effect’ name it (e.g. ‘MyEffect’)
save and then build all.

While your in there right click on the file and open it up for editing… later on.

Go to your Game1 class.
At the top add a global Effect reference
Effect myEffect;
in LoadContent load it like so.
myEffect = Content.Load("myEffect);
from here changes you make to the file will be rebuilt with rebuild all.

Now you need to edit the shader.

Inside the effect file is a pre-made shader you should see the following.
This is were you add that shader stuff.

#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

matrix WorldViewProjection;

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float4 Color : COLOR0;
};

struct VertexShaderOutput
{
    float4 Position : SV_POSITION;
    float4 Color : COLOR0;
};

VertexShaderOutput MainVS(in VertexShaderInput input)
{
    VertexShaderOutput output = (VertexShaderOutput)0;

    output.Position = mul(input.Position, WorldViewProjection);
    output.Color = input.Color;

    return output;
}

float4 MainPS(VertexShaderOutput input) : COLOR
{
    return input.Color;
}

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

If you want to use it with sprite batch you have to pass in your effect to spritebatch begin(.,.,., ).
Or just draw it the way you were trying to in the previous example code and use your effect to do it.

Good idea but

I have problem with float4 Position : POSITION0

It can’t pass for “float”

But why does it not work like OpenTK’s VertexShader/FragmentShader
Example:
private const string VertexSource =
@"#version 450 core
in vec3 position;
out vec3 colour;

    void main()
    {
        gl_Position = vec4(position, 1.0);
        colour = vec3(position.x + 0.5, 1.0, position.y + 0.5);
    }";

private const string FragmentSource =
    @"#version 450 core
    in vec3 colour;
    out vec4 out_color;

    void main()
    {
        out_color = vec4(colour, 1.0);
    }";

Result:

Did you see like this
out_color = vec4(colour, 1.0);
It is like output.Color = float4(input.Color);

Is it correct or wrong?

#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

matrix WorldViewProjection;

struct VertexShaderInput
{
	float4 Position : POSITION0;
	float4 Color : COLOR0;
};

struct VertexShaderOutput
{
	float4 Position : SV_POSITION;
	float4 Color : COLOR0;
};

VertexShaderOutput MainVS(in VertexShaderInput input)
{
	VertexShaderOutput output = (VertexShaderOutput)0;

	output.Position = input.Position;
	output.Color = float4(input.Position.x + 0.5f, 1.0f, input.Position.y + 0.5f, 1.0f);

	return output;
}

float4 MainPS(VertexShaderOutput output) : COLOR
{
	VertexShaderInput input = (VertexShaderInput)0;
	output.Color = float4(input.Color);
	return output.Color;
}

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

I really want to magic colors from loading shader.

MonoGame Content Pipeline said successful compilation.

How do I pass effect to parameter?

It is like output.Color = float4(input.Color);

Is it correct or wrong?

output.Color = input.Color;

//How do I pass effect to parameter?
How do I pass a parameter into my effect?

If you wanted to pass them you would define them as soo in your shader.

matrix WorldViewProjection;

float4 red;
float4 orange;
float4 yellow;
//ect… ect…

Then you could pass the colors for each in game via…

myEffect.Parameters[“red”].SetValue( new Color(1f,0f,0f,1f) );
myEffect.Parameters[“orange”].SetValue(Color.Orange);
myEffect.Parameters[“yellow”].SetValue(Color.Yellow);

Thanks for resolve my problem but rectangle is impossible black.

Shader.fx

#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

matrix WorldViewProjection;

struct VertexShaderInput
{
	float4 Position : POSITION0;
	float4 Color : COLOR0;
};

struct VertexShaderOutput
{
	float4 Position : SV_POSITION;
	float4 Color : COLOR0;
};

VertexShaderOutput MainVS(in VertexShaderInput input)
{
	VertexShaderOutput output = (VertexShaderOutput)0;

	output.Position = mul(input.Position, WorldViewProjection);
	output.Color = float4(input.Position.x + 0.5f, 1.0f, input.Position.y + 0.5f, 1.0f);

	return output;
}

float4 MainPS(VertexShaderOutput output) : COLOR
{
	VertexShaderInput input = (VertexShaderInput)0;
	output.Color = input.Color;
	return output.Color;
}

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

Game1.cs

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

namespace Tutorial_04
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        VertexBuffer vertexBuffer;
        IndexBuffer indexBuffer;

        VertexPosition[] vertices;
        BasicEffect basicEffect;
        Effect effect;

        Matrix world = Matrix.Identity;
        Matrix view = Matrix.Identity;
        Matrix projection = Matrix.Identity;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            Window.Title = "Tutorial 04 - Loading shaders";

            base.Initialize();
        }

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

            vertices = new VertexPosition[4];

            vertices[0] = new VertexPosition(new Vector3(-0.5f, 0.5f, 0f));
            vertices[1] = new VertexPosition(new Vector3(-0.5f, -0.5f, 0f));
            vertices[2] = new VertexPosition(new Vector3(0.5f, -0.5f, 0f));
            vertices[3] = new VertexPosition(new Vector3(0.5f, 0.5f, 0f));

            vertexBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPosition), 6, BufferUsage.WriteOnly);
            vertexBuffer.SetData<VertexPosition>(vertices);

            short[] indices = new short[6];
            indices[0] = 0; indices[1] = 1; indices[2] = 2;
            indices[3] = 2; indices[4] = 3; indices[5] = 0;

            indexBuffer = new IndexBuffer(graphics.GraphicsDevice, typeof(short), indices.Length, BufferUsage.WriteOnly);
            indexBuffer.SetData(indices);

            effect = Content.Load<Effect>("Shader");
        }

        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.CornflowerBlue);

            basicEffect.World = world;
            basicEffect.View = view;
            basicEffect.Projection = projection;
            basicEffect.VertexColorEnabled = true;
            effect.Parameters["WorldViewProjection"].SetValue(world);

            GraphicsDevice.SetVertexBuffer(vertexBuffer);
            GraphicsDevice.Indices = indexBuffer;

            RasterizerState rasterizerState = new RasterizerState();
            rasterizerState.CullMode = CullMode.None;
            GraphicsDevice.RasterizerState = rasterizerState;

            foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
            {
                pass.Apply();
                GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleStrip, 0, 0, 4);
            }

            base.Draw(gameTime);
        }
    }
}

Result:

But where are 4 different colors???

Only black color?

// I have tried to replace VertexPosition with VertexPositionColor

Than it is same result like this:

It is really impossible. Because MonoGame can’t magic generated colors from loaded shader. I think MonoGame need fix like OpenTK. I think MonoGame is bug because it looks only black. Is it correct or wrong if it has bug?

You need to declare the floats consts if they are to be used in the vertex shader i think.

#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

matrix WorldViewProjection;
static const float4 MyRed = float4(1.0f, 0.0f, 0.0f, 1.0f);

struct VertexShaderInput
{
	float4 Position : POSITION0;
	float4 Color : COLOR0;
};

struct VertexShaderOutput
{
	float4 Position : SV_POSITION;
	float4 Color : COLOR0;
};

VertexShaderOutput MainVS(in VertexShaderInput input)
{
	VertexShaderOutput output = (VertexShaderOutput)0;

	output.Position = input.Position;
	output.Color = float4(input.Position.x + 0.5f, 1.0f, input.Position.y + 0.5f, 1.0f);
        output.Color = MyRed;
	return output;
}

float4 MainPS(VertexShaderOutput output) : COLOR
{
   VertexShaderInput input = (VertexShaderInput)0;
   float4 col;
   // in pixel shader
   //col = MyRed;
   // in vertex shader
   col = input.Color; // woops edit my bad
   return col;
}

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

How??? For me nothing sees :frowning: Please explain I have current version MonoGame 3.7 / 3.6 ???

ah woops hold on my bad again gimme a second lol you probably need to return a float4 not a color.

Edit:
Try that really quick
im not testing your code directly just a equivillent on my side so im eyeballing it.

If that doesn’t work just zip your project and post a link.

Download my zip file with Tutorial 01 to Tutorial 04

Download hosting from Mega.nz!

PS: Why do you not check gitter.im I have written many messages to MonoGame’s Gitter.im

PS: Do not publish other! It is my own credit sorry because I have to prepare…

Im not sure if you mangled up a reference or what is going on with that project. It kinda does help though if you actually add the important stuff.

PS: Do not publish other! It is my own credit sorry because I have to prepare…

I’ll delete it.

The code works though here is a stand alone test case just like the first one i posted except with a shader and a few changes. The first test with basic effect is in there as well.

.
.

.
.

PS: Why do you not check gitter.im I have written many messages to MonoGame’s Gitter.im

You mean here ?
http://www.monogame.net/news/

Thank you for help !

So sadly effect can’t generate 4 different colors from loaded shader into VertexPosition/VertexPositionColor.

I can’t believe that MonoGame can’t throw generated colors from shader into vertices.

That is why OpenTK wan. MonoGame lost :confused:

@MonoGame Team,
Please fix generated colors from shader throws only black color.

You remember because I have tried OpenTK and it throws awesome generated 4 different colors into vertices like position.X and position.Y than it happens like “generated colors”

OpenTK has not problem with generated colors.
MonoGame uses manual with VertexPositionColor = WTF?
MonoGame need load generated colors from shader like this:
struct VertexShaderInput
{
float4 Position : POSITION0;
float3 Color : COLOR0;
};

struct VertexShaderOutput
{
	float4 Position : SV_POSITION;
	float4 Color : COLOR0;
};

VertexShaderOutput MainVS(in VertexShaderInput input)
{
	VertexShaderOutput output = (VertexShaderOutput)0;

	output.Position = input.Position;
	output.Color = float4(input.Position.x + 0.5f, 1.0f, input.Position.y + 0.5f, 1.0f);
	return output;
}

float4 MainPS(VertexShaderOutput output) : COLOR
{
	VertexShaderInput input = (VertexShaderInput)0;
	output.Color = float4(input.Color, 1.0f);
	return output.Color;
}

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

Thanks I wish MonoGame should fix or add new feature “generated colors” from loading shaders if you use like my made OpenTK-Radiant-effect rectangle

Maybe you need to actually you know look at the link with the project i made for you ?.

I made you a picture too its titled Mr Impossible.

The impossible ?

Oh no wait…

Trivial…

#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

matrix WorldViewProjection;

static const float4 MyRed = float4(1.0f, 0.0f, 0.0f, 1.0f);
static const float4 MyBlue = float4(0.0f, 0.0f, 1.0f, 1.0f);

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float4 Color : COLOR0;
};

struct VertexShaderOutput
{
    float4 Position : SV_POSITION;
    float4 Color : COLOR0;
};

VertexShaderOutput MainVS(in VertexShaderInput input)
{
    VertexShaderOutput output = (VertexShaderOutput)0;
    float4 pos = mul(input.Position, WorldViewProjection);
    output.Position = pos;
    
    float4 col = (pos.x * MyRed) + pos.x * (1.0f - MyBlue);
    output.Color = col;

    return output;
}

float4 MainPS(VertexShaderOutput input) : COLOR
{
    //return MyRed; // works
    return input.Color; // use vertex shader
}

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

.
.
Now you can figure out for yourself how to align actual positions you send in with matrix identity model space x,y coordinates to u,v color coordinates that range from 0 to 1

Seriously when your going to spam that chat room about how its impossible try opentk and drop videos of people writting bad code. Then you don’t even try the example project that works. After you hijack a thread.

It gets on my nerves and starts to make me wonder, why your trying to make a tutorial.

1 Like

Hello my dear @willmotil

Thanks I don’t know because your code from downloaded zip was clean and I can’t find because my code looks like “doesn’t work”.

That is why your test from Game2 with filling red it means I try to replace my generated color now.

It works now. Thank you and I’m sorry for my problem! Now it resolved. Thank you for help!

Result:

It is really original. Wow! Thanks!

Spam??? For what? But I didn’t say spammers because I really want they understand if MonoGame and OpenTK are very close same like Vector3, Matrix and GraphicsDevice etc…

I am sorry. I will respect that. I didn’t hjack everything.
Remember that in Gitter

```
Code block
```

Thank you I will “solved” in my thread