Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice
  2. Ever participated in one our Game Jams? Want pointers on your project? Our Evangelists will be available on Friday to give feedback. Come share your games with us!
    Dismiss Notice

Help rendering sprite with custom shader.

Discussion in 'General Graphics' started by SelDraken, Mar 25, 2015.

  1. SelDraken


    Mar 25, 2015
    I will try to explain my situation as best as I can.

    I am coming from my own custom game engine, to unity.
    In my old project, I needed to duplicate the old technique of palette shifting. Loading an image with an 8 bit palette index instead of pixels, and a 256 color palette that they reference. Then in memory at runtime, you would shift around the colors in the palette table, and thus the pixels would appear to change colors.

    In my last opengl project, the only way this was possible was for me to create a custom shader, the shader took in 2 textures, the main texture was the graphic (sprite) image... each pixel in the sprite image was used as a color table index (though only using the 8bit red component), the second image was a 256x1 texture, with each pixel representing a color (this was the palette table). The shader, took the main texture, and displayed the color on screen that corresponded to the index pointing to the color in the 2nd texture.

    So in memory I was able to adjust the second texture, to shift colors around, and this would affect the final image.

    Converting the shader, I dont think will be so difficult. I am having trouble understanding 'where' to put my textures.
    For each character, it will have its own unique texture (sprite) and its own unique palette (256x1 texture). So for each 'render' of a character, I need to supply the main sprite texture, and the palette texture. How and where do I do this?

    Do I need to make a material for each character?
    Or can I use just 1 material, and only change the textures for each sprite character's render?

    And if it is the second, how do you specify... render this... change material... render this ... change material, etc...

    Also... if I want a 2d sprite to be rendered, but I want it on a quad, so it can move in 3d space (rotate, etc... sort of like paper mario) what gameobject or functions do I use to draw my sprites?

    Sorry this is so long winded, Im not good at explaining my problem.
    Thanks for any links or help.
  2. raja-bala


    Jul 11, 2012
    [Edited this based on @CaptainScience 's reply]

    If you want to use Unity's inbuilt rendering of your character(i.e., you don't want to control when your character is drawn), then, from what I understand, you will need a material for each character with the relevant textures assigned to the material (i.e. shader texture input). As @CaptainScience has explained (excellently) below, each time you change a property of a material, Unity creates a new instance behind the scenes. The drawback of this is the loss of batching and increased number of draw calls. As he suggests, using a shared material for all your characters with a texture atlas is a good way to get around it.

    From a content creation point, I don't know how easy/feasible that is. As a non-artist, I have no clue how texture atlases are created :(
    Last edited: Apr 6, 2015
    theANMATOR2b likes this.
  3. SelDraken


    Mar 25, 2015
    Thanks for the input, and yeah... I would be curious to see if that works as well, I'll update this if it works.
  4. smd863


    Jan 26, 2014
    If you're coming from OpenGL, think of a material as an encapsulation of a single graphics state. Any time you would use any "set" function to change the texture, shader, or shader parameter before submitting geometry you will need a new material. Remember, Unity is component based so the material component will do all that setting of state for you and the mesh renderer component will submit all the geometry (from the mesh filter component) to the GPU for rendering. You don't generally have to call any draw functions manually for most regular game objects.

    So every time you change a texture, shader, or parameter, you need a new material, and Unity will conveniently create a material instance for you behind the scenes when you change them on a specific object. However, that object won't batch with other objects using the same material any more. It will need its own draw call; you changed the required state to render that object. If you modify the "sharedMaterial" you won't create material instance, it will still batch with other objects, but any changes you make will affect all objects using that material. You are changing the shared state they are all using.

    If you have a lot of objects using the same textures, you can create a material manually and assign it to each of them so Unity can batch them together. If you are getting too many draw calls, you can take this farther and combine multiple objects' textures into a single texture atlas and assign one material to multiple types of objects. Unity can batch the draw calls a bit better, but you will lose some flexibility: you need to load the entire atlas whenever you need any individual texture inside it.
    raja-bala and theANMATOR2b like this.
  5. theANMATOR2b


    Jul 12, 2014
    Hey @CaptainScience - just a lurker here - but thanks a lot for the detailed (layman's term) explanation on the linkage/commonalities between editing materials, textures, batching and draw calls.
    Very helpful for future reference.

    Unity should hire you to increase the informative value of the documentation!