Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Trying to understand sprite shader

Discussion in 'Shaders' started by theness_, Jun 1, 2016.

  1. theness_

    theness_

    Joined:
    May 6, 2015
    Posts:
    7
    Sorry for this noobish question but I didn't find any decent tutorial and I'm trying to understand some of Unity built-in shaders.

    For example, this Sprite/Diffuse shader taken from Unity source:

    Code (CSharp):
    1. Shader "Sprite/Diffuse"
    2. {
    3.         Properties
    4.         {
    5.             [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
    6.             _Color("Tint", Color) = (1,1,1,1)
    7.             [MaterialToggle] PixelSnap("Pixel snap", Float) = 0
    8.         }
    9.  
    10.         SubShader
    11.         {
    12.             Tags
    13.             {
    14.                 "Queue" = "Transparent"
    15.                 "IgnoreProjector" = "True"
    16.                 "RenderType" = "Transparent"
    17.                 "PreviewType" = "Plane"
    18.                 "CanUseSpriteAtlas" = "True"
    19.             }
    20.  
    21.             Cull Off
    22.             Lighting Off
    23.             ZWrite Off
    24.             Blend One OneMinusSrcAlpha
    25.  
    26.             CGPROGRAM
    27. #pragma surface surf Lambert vertex:vert nofog keepalpha
    28. #pragma multi_compile _ PIXELSNAP_ON
    29. #pragma shader_feature ETC1_EXTERNAL_ALPHA
    30.  
    31.         sampler2D _MainTex;
    32.         fixed4 _Color;
    33.         sampler2D _AlphaTex;
    34.  
    35.         struct Input
    36.         {
    37.             float2 uv_MainTex;
    38.             fixed4 color;
    39.         };
    40.  
    41.         void vert(inout appdata_full v, out Input o)
    42.         {
    43. #if defined(PIXELSNAP_ON)
    44.             v.vertex = UnityPixelSnap(v.vertex);
    45. #endif
    46.             UNITY_INITIALIZE_OUTPUT(Input, o);
    47.             o.color = v.color * _Color;
    48.         }
    49.  
    50.         fixed4 SampleSpriteTexture(float2 uv)
    51.         {
    52.             fixed4 color = tex2D(_MainTex, uv);
    53.  
    54. #if ETC1_EXTERNAL_ALPHA
    55.             color.a = tex2D(_AlphaTex, uv).r;
    56. #endif //ETC1_EXTERNAL_ALPHA
    57.  
    58.             return color;
    59.         }
    60.  
    61.         void surf(Input IN, inout SurfaceOutput o)
    62.         {
    63.             fixed4 c = SampleSpriteTexture(IN.uv_MainTex) * IN.color;
    64.             o.Albedo = c.rgb * c.a;
    65.             o.Alpha = c.a;
    66.         }
    67.         ENDCG
    68.         }
    69.  
    70.             Fallback "Transparent/VertexLit"
    71.     }
    72.  
    Where is the actual Pass definition? I assume its imported maybe from this line -

    #pragma surface surf Lambert vertex:vert nofog keepalpha

    But where do I actually find the passes code if I want to change it?

    And another thing I didn't find was the output z-index (for z-ordering). I thought it was supposed to be in the vert program, but I don't see it in the function output and not sure how I can add / affect it.

    Thanks,
     
  2. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    When an object is rendered, it uses the first subshader it is able to use in the shader. A subshader will (by default) use every pass in the subshader. Any code that is in a subshader, but outside the pass will apply to every pass in the shader. Therefore, any code you can put in a pass may be put in the subshader instead. Without any defined "pass", the subshader is treated as a single pass.

    Put your pass code right inside the subshader.

    There is none. Sprites will render on top or behind each other based on their draw order. Unity treats sprites like transparent objects, and Unity draws transparent objects from back to front.

    The line "ZWrite Off" tells you that this subshader does not write to the depth buffer, so no "z information" is stored.


    Any questions? I can help you get the effect you're going for with more info.
     
    Simon-O and theness_ like this.
  3. theness_

    theness_

    Joined:
    May 6, 2015
    Posts:
    7
    Hi Gambit MSplitz,

    Thank you for the info but I need some more :)

    Thanks, that explains why there are no passes. But it still looks like not enough, I mean, this shader support lighting, I would expect multiple passes for that (at least 1 "base" pass with ambient and then additive pass that will be rendered per light). Am I right? If so, where are those passes?

    That does look like it from the code, however, I experimented with sprites and 3d meshes and sprites appear to act just like a quad (or billboard). they do have z-index beyond just rendering order. I even removed this line:

    Code (CSharp):
    1. Fallback "Transparent/VertexLit"
    In case its just falls back to a different shader, but it isn't. You can see in this image I posted for another question: http://forum.unity3d.com/attachments/problem_explained-jpg.187404/

    PS. my settings are for 3d project, if that changes anything.

    So any idea of how the sprite z-order and how I find that code? That's the part that confuse me atm..

    Thanks :)

    Edit: Just noticed this part:

    What I'm trying to do is detailed here:

    http://forum.unity3d.com/threads/problem-with-z-order-when-combining-sprites-and-3d-meshes.408175/

    I could easily do it with the default sprite shader, but the Shader/Diffuse one is very different and much less intuitive for me. :/
     
    Last edited: Jun 1, 2016
  4. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    Unity sorts transparent objects so farther away objects are rendered first, and closer objects are rendered over them. This may appear like depth sorting using the z-axis, but it's really just painters algorithm. The sprite probably samples depth so that it appears behind 3D objects using depth, but the shader has the line "ZWrite Off" which means it will not write depth information, and nothing drawn after it can appear behind it because of depth.


    Anyway, I actually saw that forum post the other day. I'm afraid I don't know how to get that effect because you need to sort/cull the objects differently based on their relative position to each other.

    I do have an idea, but it's a bit experimental. Basically you want the knight to sort above surfaces that face the opposite direction as the camera. If you remove the y component of the camera forward, normalize that vector and dot it with the surface normal of the block's pixel in the pixel shader, the product will be negative if the wall is facing the opposite direction of the camera. Any wall pixel that is facing the opposite direction as the camera should be rendered below the player.

    Feel free to ask more questions
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,238
    Surface shaders are short hand versions of shaders with much of the complexity hidden behind a shader generator. You can see the "real" shader by selecting the shader and clicking on "show generated shader". Now you'll see all those passes you're expecting and you can copy that code into a shader file and modify it if you need something special. Most of the time it's possible to do what you want with out.
     
  6. theness_

    theness_

    Joined:
    May 6, 2015
    Posts:
    7
    Thanks, I've read a lot about shaders and material in Unity and your answers helped a lot.
    I understand what I need now :) Got myself a good-enough shader working.