XNA Creators Club Online
Page 1 of 1 (9 items)
Sort Posts: Previous Next

A good way to use effects...

Last post 19/02/2009 15:21 by Martin Caine. 8 replies.
  • 17/02/2009 12:21

    A good way to use effects...

    Hi,
    I'm fairly new to shaders, and would like some how on the best way to implement them.  I've read heaps of tutorials on how to put a texture on a model using an effect, but no good way of how to implement the effect. 

    An example of what I mean...

    I am trying to render a chess board. 

    For each tile,
    If it is the selected tile, I want to blend the tiles texture with a selected tile texture,

    or if it's a tile where there's a possible move, I want to blend the tile and the possible move texture

    etc.

    Do I do something like...


                foreach (ModelMesh boardMesh in m_board.Meshes) 
                { 
                    foreach (ModelMeshPart meshPart in boardMesh.MeshParts) 
                    { 
                        //check if tile 
                        if (isTile) 
                        { 
                            if ((x + y) % 2 == 0) 
                            { 
                                m_tileEffect.Parameters["myTexture"].SetValue(Game.Content.Load<Texture>(@"Models\WhiteTile")); 
                            } 
                            else 
                            { 
                                m_tileEffect.Parameters["myTexture"].SetValue(Game.Content.Load<Texture>(@"Models\BlackTile")); 
                            } 
                             
                            if (tile == m_selectedTile) 
                            { 
                                //Add a second texture to effect 
                            } 
                            else if (tile == m_possibleMoveTile) 
                            { 
                                //Add a second texture to effect 
                            } 
                            meshPart.Effect = m_tileEffect; 
                        } 
     
                        meshPart.Effect.Parameters["Projection"].SetValue(m_camera.ProjectionMatrix); 
                        meshPart.Effect.Parameters["View"].SetValue(m_camera.ViewMatrix); 
                        meshPart.Effect.Parameters["World"].SetValue(boardTransforms[boardMesh.ParentBone.Index] * m_boardWorld); 
                    } 



    (I have mixed a little pseudo code in there, but I want help more with structure than syntax)

    This seems stupid to me (as I'm sure it does to you :).  What if I wanted to use 2 completely different effects for selected tiles and possible move tiles, or possible attack tiles etc. 

    What if I wanted a slightly different texture for each tile?  Using this approach I would need a switch statement with 64 parts (8 * 8).

    Instead of having the tiles in the boards mesh, should I have them as seperate onjects and have an effect for each tile?

    Any other suggestions?

    Thanks heaps.
  • 17/02/2009 13:33 In reply to

    Re: A good way to use effects...

    What you ideally want to do is have a single draw call to draw the gameboard with all textures in the correct position I assume. This would be much more efficient than multiple draw calls for each individual tile.

    What you could perhaps do is combine all of your textures into a single large texture (say 2048x2048 which would then hold 16x 256x256 textures (black piece, white piece, and 14 overlays)).

    Then by passing an extra Vector2 to your shader you can specify two variables indicating which of the two cells in the texture to use for shading.

    So if you pass .X as 0 and .Y as 7 you'd be applying the first cell from the texture and the 8th (2nd row 4th column).

    Your pixel shader would then recalculate the UV supplied using the specified parameters and would map the correct portion of the textures to each triangle (so 0,0 for cell 0 would still be 0,0, and 0,0 for cell 7 would be recalculated to be 0.25, 0.75).


    Now, to do all of this I would create a vertexarray containing 4 vertices for each tile on the gameboard (which would have an indexbuffer linked to it too, and would be fed into DrawIndexedPrimitives). To modify which overlay texture you want displayed on a particular tile you would modify the additional parameters in the 4 elements of the vertexarray that correspond to that tile.

    So say I had an array of MyVertexStructure[256] (4 vertices per tile), I would modify the structures held in positions 0-3 before calling DrawIndexedPrimitives which would then use the modified values to render the correct overlay texture.


    I hope that makes sense to you.. I can see it in my head but I'm finding it hard to explain, I was just trying to think of a method where you would not need to specify different textures per tile and where a single effects file would render the whole board in one go.
    Retroburn Game Studios
    XBoxArt.com - Now includes box art from Community games, Arcade games and Retail 360 games!
  • 17/02/2009 15:57 In reply to

    Re: A good way to use effects...

    Or you could do what I have just done in my newest game.

    Create two objects in your favorite 3D package, the board, and a squashed cube the same size as a single square on the board.

    Draw the board as a single object.

    When you want to display a square as being selected, put a copy of the square object at the correct location but slightly above the board.
    Render this with an alpha blended texture.

    Why do it this way?

    1) You can do it all with basiceffect, you don't need to write a shader
    2) When it comes to move resolution, you can use standard picking techniques against the squares and ignore the board
    3) If your game has multiple valid moves, you can just add more squares
    4) You can use the same picking routines to find a selected game piece instead of a selected square
    5) The board can be as complex as you like, with nice textures, etc
    6) When you start to add shadows in as well you can find your selected square approach causing you problems in the shader (you can run out of registers)

    It's just another way of doing it, but I can testify how clean and fast the code ends up with this approach

    The only down side I have found is that you must do ray->game piece collisions first, from some view points you can get false results if you do it the other way around.


    Information is not knowledge, knowledge is not wisdom, wisdom is not truth, truth is not beauty, beauty is not love, love is not music, music is the best! Wisdom is the domain of the Wis (which is extinct).
  • 17/02/2009 23:30 In reply to

    Re: A good way to use effects...

    Thanks guys.  I'm going to try Bytrix's way though because this isn't actually a chess game, it just uses a chess style board, and I will need to move and deform and move individual tiles, so having one large model for the board wont work for me.

    I was following you Bytrix up until the last little bit, but I think I get the idea.  I'll give that a crack when I get home tonight.

    Cheers
  • 18/02/2009 8:30 In reply to

    Re: A good way to use effects...

    Just to help you understand what I was meaning (and this will actually come in useful on one of my own games too) I'll put together a little demo today and upload it for you to see how I would do it.
    Retroburn Game Studios
    XBoxArt.com - Now includes box art from Community games, Arcade games and Retail 360 games!
  • 18/02/2009 8:53 In reply to

    Re: A good way to use effects...

    Thanks heaps.  That would be awesome.
  • 18/02/2009 13:02 In reply to

    Re: A good way to use effects...

    Here's a little example. It uses a single texture but samples it up to 3 times in the pixel shader to apply different sections to each tile (note the blending isn't right but this is just a proof of concept anyway):



    http://www.bytrix.org/chessboard.zip

    [Edit]Just to let you know there does seem to be a little bug in the pixel shader, I just compiled this test at home and it doesn't display correctly on my Nvidia 9600, but if I move it to the other monitor (onboard Nvidia 7100 it renders fine). It looks like it's trying to sample the texture even though it shouldn't be on certain tiles:

    Retroburn Game Studios
    XBoxArt.com - Now includes box art from Community games, Arcade games and Retail 360 games!
  • 19/02/2009 2:04 In reply to

    Re: A good way to use effects...

    Thanks mate,  your a legend. 

    I'll give this a go when I get home tonight.  I've had a quick look at the code though, and it's pretty much exactly what I need. 

  • 19/02/2009 15:21 In reply to

    Re: A good way to use effects...

    I don't suppose anyone can see what the bug is with my pixel shader in that example? It's annoying me as I can't see what's wrong with it. It only corrupts on my high end 9600 but displays fine on the lower end onboard graphics and my work PC.
    Retroburn Game Studios
    XBoxArt.com - Now includes box art from Community games, Arcade games and Retail 360 games!
Page 1 of 1 (9 items) Previous Next