1
\$\begingroup\$

I am new to shaders and HLSL so bare with me on this one.

I have a 2D tile map in my game and want to create a mini-map, at first I was just copying all the data from one sprite batch to another and rendering it in a smaller camera. This obviously has a performance issue.

So I want to make a mini-map that is composed of coloured pixels depending on what is in that particular cell.

I have a basic shader going at the moment that converts tex coordinates to pixel position but now I need a way to determine what color to set it. My instant decision was to simply pass in a 2d array of colors and grab the color using the x and y coordinate of the pixel, this crashed lol.

Here is what I have so far for the shader:

sampler s0;

// The width and height of the texture being sampled
int width, height;

float4 PixelShaderFunction(float2 coords : TEXCOORD0) : COLOR0
{
    float4 color = tex2D(s0, coords);
    // Covert the tex coordinates to pixel coordinates
    int2 tc = int2(width * coords.x, height * coords.y);

    // Here I need to do some sort of check or something?

    return color;
}

technique Technique1
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

How can I pass the color data to the pixel shader so it knows what color to set each pixel? I already know how to pass data but not sure how I can represent that data to pass it.

My map is every changing and units are moving around constantly, so the data will be passed in almost every frame.

\$\endgroup\$
  • \$\begingroup\$ "This obviously has a performance issue." Have you proven this? \$\endgroup\$ – William Mariager Feb 26 '15 at 11:29
  • \$\begingroup\$ Well given the fact my frame rate gets sliced in half when I render the mini-map, I guess so? lol. This might be due to my method, as all I am doing is rendering the map again but at a smaller scale. The actual map rendering is not optimized, but the mini-map with the current system will ALWAYS render everything (unlike the world camera which has culling). \$\endgroup\$ – Gibbo Feb 26 '15 at 11:32
  • \$\begingroup\$ That's good to know. Just making sure you're not optimizing prematurely. ;) \$\endgroup\$ – William Mariager Feb 26 '15 at 11:38
1
\$\begingroup\$

I think it's bad idea pass tile map to shader. Match better will be just create bitmap and initialize colors pixel-by-pixel. Create bitmap with same size as your tilemap has and then draw part of them.

Create minimap bitmap:

 Bitmap miniMapBitmap = new Bitmap(worldWidth, worldHeight);
    for (int x = 0; x < worldWidth; x++)
    {
        for (int y = 0; y < worldHeight; y++)
        {
            miniMapBitmap.SetPixel(x, y, GetMiniMapColor(x, y)); // place for conditions :D
        }
    }

Create Texture2D from bitmap:

Texture2D miniMapTexture = null;
using (MemoryStream stream = new MemoryStream() )
{
    bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
    stream.Seek(0, SeekOrigin.Begin);
    miniMapTexture = Texture2D.FromFile(GraphicsDevice, stream);
}

Draw part of minimap texture corresponding to visible tiles (for example):

spritebatch.Draw(
    miniMapTexture,
    miniMapPosition,
    new Rectangle(cameraOffsetX, cameraOffsetY, screenWidth, screenHeight),
    Color.White);
\$\endgroup\$
0
\$\begingroup\$

In my game, I do this by setting UVS in vertex data and drawing a mesh for the map using texture coords from the vertex data. Basically:

  • Create a tile map that is the same aspect ratio as the sprite sheet you are using to draw your current tile map; where each pixel represents a tile.
  • Pass this to the shader.
  • Create a vertex buffer that is just a mesh representing your tile map. You can do this either by creating a mesh grid filled with triangles, or by drawing the map as a point set.
  • Each vertex's UV coordinates are defined by its tile type.
  • The fragment shader looks up into the tile map color sheet to determine what color to draw.
  • Render the entire thing to a render target with an orthographic camera. The contents of the render target are now your mini-map.

Technically, you only need to render this once each time the map changes, but I render it every frame in my game so I can do things like have a 3D effect, or have animated bits of the mini-map.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.