Search Unity

Shader with arbitrary number of passes

Discussion in 'Shaders' started by TheAlchemist42, Apr 18, 2008.

  1. TheAlchemist42

    TheAlchemist42

    Joined:
    Apr 17, 2008
    Posts:
    68
    Hi everyone. I am very very new to shader scripting, so please bear with me. I have a model that needs, at runtime, to have textures added to it.

    Think of a human torso wearing a t-shirt. The user has buttons in the interface to change the shirt... for instance, it may be different colors, and/or a logo may be added and/or the sleeves may be different colors, etc.

    I have found that I can write a shader that has multiple passes. The 1st is just the plain white t-shirt texture. Then the later passes are additive overlays to add in the other parts (which I have as 32 bit PNG files). This is the shader so far:

    Code (csharp):
    1.  
    2. Shader "Test Shader" {
    3.     Properties {
    4.         _Color ("Main Color", Color) = (1,1,1,1)
    5.         _MainTex ("Base (RGB)", 2D) = "white" {}
    6.         _OverlayTex1 ("Overlay1 (RGBA)", 2D) = "black" {}
    7.         _OverlayTex2 ("Overlay2 (RGBA)", 2D) = "black" {}
    8.         _BumpMap ("Bump (RGB) Illumin (A)", 2D) = "bump" {}
    9.     }
    10.    
    11.     SubShader
    12.     {
    13.         Pass
    14.         {
    15.             Blend Off
    16.             SetTexture [_MainTex] { combine texture }
    17.         }
    18.            
    19.         Pass
    20.         {
    21.             Blend SrcAlpha OneMinusSrcAlpha
    22.             SetTexture [_OverlayTex1] { combine texture }
    23.         }  
    24.  
    25.         Pass
    26.         {
    27.             Blend SrcAlpha OneMinusSrcAlpha
    28.             SetTexture [_OverlayTex2] { combine texture }
    29.         }      
    30.     }
    31.     FallBack "Diffuse", 1
    32. }
    33.  
    That is all fine as long as I want only 2 levels of overlays and I want to supply the blend textures in the editor.

    What I want is to define which overlays are added at runtime. There may be more than 2. There may be less. The number of overlays is arbitrary, and will be defined by the user's choices. There is no functional maximum to the number of overlays that will be needed (my actual program is much more advanced than the t-shirt example)

    I don't want to make a shader with 100 overlay passes and swap out the ones I need at runtime.

    Is there a way to add a repeat loop into the shader that cycles through a list of overlays and only adds the ones I need? Or am I going about this completely wrong?

    Thanks for any help!
     
  2. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    I don't have a direct solution to your problem... but overlaying those textures each time the model is drawn on the screen would be very inefficient. Why not create a single "composite" texture; and whenever user changes something, recompute that texture (that is, manually blend the textures)?

    This manual blending could be done in several ways:

    1. Use render textures. From a script; clear it, and blend in the textures in a loop (set texture on the small blending material; SetPass() on that material; draw quad). This would be fast and quite easy.

    2. Blend textures on the CPU, using GetPixels() and SetPixels(). It will be somewhat slower, a bit more work and GetPixels() currently does not work if input textures are DXT compressed.