Tinting doesn't work with immediate mode.

spriteBatch.Begin(sortMode: SpriteSortMode.Immediate,
                        blendState: BlendState.AlphaBlend,
                        samplerState: SamplerState.PointClamp, 
                        /*null,
                        null,
                        null,*/
                        transformMatrix: cam.get_transformation(graphics.GraphicsDevice));

It always draws as white. Can I fix this somehow?

Update: it is the same for setting color of sprites.

Narrowed it down to the problem being immediate mode. Not sure what to do about it.

Immediate mode means whatever you draw will be rendered (either to a RenderTarget or to the back buffer) immediately. Can you post the code showing what you’re drawing?

spriteBatch.Begin(sortMode: SpriteSortMode.Immediate,
                        blendState: BlendState.AlphaBlend,
                        samplerState: SamplerState.PointClamp, 
                        /*null,
                        null,
                        null,*/
                        transformMatrix: cam.get_transformation(graphics.GraphicsDevice));

            world.Draw(gameTime.ElapsedGameTime.Milliseconds / 1000.0f, graphics, spriteBatch, cam, gameObjects, player, world); // mesh / sprites

            gameDebug.Draw(spriteBatch, Pathfinder);

            spriteBatch.DrawString(GameGlobals.PixFont, "Whyyy???? :(", new Vector2(500, 500), Color.Red);

            spriteBatch.End();

Can you post a screenshot of what it’s currently outputting, and can you narrow down the code? The code here is too broad to identify an issue; what’s going on inside world.Draw?

The draw code is bit complex, but it boils down to drawing a mesh, then sprites over it then mesh over it, etc. It is a layered tiled map kind of thing.

The mesh drawing at lowest level is this:

public void Draw(float dt, GraphicsDeviceManager graphicsManager, Camera2D camera)
        {
            foreach (EffectPass pass in Effect.CurrentTechnique.Passes)
            {
                pass.Apply();

                graphicsManager.GraphicsDevice.DrawUserIndexedPrimitives
                    <VertexPositionNormalTexture>(
                    PrimitiveType.TriangleList,
                    Vertices, 0, Vertices.Length,
                    Indexes, 0, Indexes.Length / 3);
            }
        }

World draw looks like this:

public void Draw(float dt, GraphicsDeviceManager graphics, SpriteBatch spriteBatch, Camera2D cam, List<IEntity> gameObjects, Player player, TiledWorld world)
        {
            //Debug.WriteLine(gameObjects.Count);

            for(int groups = 0; groups < TiledChunk.GroupCount; groups++)
            {
                if (player.WorldLevel >= groups)
                {
                    DrawGroup(groups, dt, graphics, cam);
                }
                else if (world.HideTopLevels == false)
                {
                    DrawGroup(groups, dt, graphics, cam);
                }

                for (int j = 0; j < gameObjects.Count; j++)
                {
                    if(gameObjects[j].GetType() == typeof(Player))
                    {
                        if (gameObjects[j].GetWorldLevel() == groups)
                        {
                            gameObjects[j].Draw(spriteBatch);
                        }
                    }
                    else
                    if (gameObjects[j].GetWorldLevel() == groups)
                    {
                        if(gameObjects[j].GetWorldLevel() > player.WorldLevel)
                        {
                            if(world.HideTopLevels == false)
                            {
                                gameObjects[j].Draw(spriteBatch);
                            }
                        }
                        else
                        {
                            gameObjects[j].Draw(spriteBatch);
                        }
                    }
                }
            }
        }

I dont know why, but on my win10 when doing PrtScr, if the game is windowed, itll paste it as all white, and if it is fullscreen, it will make a screenshot of whats behind the game window at the moment.

But all there would be to see from screenshots is that tinting doesn’t work at all, for text or sprites, they are always drawn in their original colors, no matter if I pass Color.Blue or anything else to it.

It looks like there’s a lot going on in your code, so I would comment out parts and see where the problem lies. Is it only the text and sprites experiencing this issue, or do the meshes have problems as well?

One potential problem I see is that you’re beginning the SpriteBatch, which sets up the GraphicsDevice’s states, then overriding those states when applying your Effects for drawing the meshes. In Immediate mode, the new states would take effect immediately, which is likely why it’s causing the problem. It may be preferable to start and end the SpriteBatch calls when you do and don’t need to draw sprites, respectively, rather than handle one begin at the start of everything.

This leads to another question: do you need Immediate mode for a particular reason? No batching occurs with it, so you will be incurring a performance cost.

It is just text and sprites and just tinting is what doesn’t work.

It would be either immediate mode or ~15 different spriteBatch.Begin/End. There are this many groups that compose a chunk of the world, allowing for few groups being displayed at once, think Ultima Online. And each group has 4 layers.

Is it possible to set back the state right after calling mesh draw? This is all I do to the effect:

Effect.World = World;
        Effect.View = GameGlobals.View;
    Effect.Projection = GameGlobals.Projection;
    Effect.TextureEnabled = true;
    Effect.Texture = Spritesheet;

Are you using any effects for the sprites? Based off the initial SpriteBatch.Begin, it doesn’t look like it. You will have to manually reset the GraphicsDevice’s states rather than the Effect’s. You can set the BlendState, DepthStencilState, RasterizerState back to what they were before drawing the models. It might be easiest to call End then Begin again to achieve this.

Managing the draw calls with SpriteBatch is more work, but the performance benefits are worth it. Once this is working with Immediate, I highly recommend looking into batching your sprites and text together.

The main reason I avoided having a lot of Being/End is because I’ve seen people write that it is inefficient. Would this be better choice here than having immediate mode?

It’s true that it’s better to have as few Begin/End calls as possible to batch sprites and text, but Immediate mode doesn’t batch at all; it’s equivalent to calling Begin/End each time a sprite or text is drawn. It would be more performant to use another SpriteSortMode that works for your project once everything is working right.

To briefly answer your question: yes.

Ok, now I understand how batching works in monogame.
Switching from Immediate to other fixed the tinting issue.

Now just as a side issue, the DrawUserIndexedPrimitives is using a lot of CPU time, is there a way to speed it up?

I don’t have much experience using it, but I’d say pass as many vertices as you can to it. The call should take up more CPU time than average operations since it’s submitting the information to the GPU. Do you have profiling results?

To me it sounds like your game is processing a lot and may need to employ some optimization techniques (ex. culling), but correct me if I’m wrong.