Search Unity

Grabpass gets darker when multiple instances of shader are in view.

Discussion in 'Shaders' started by hadynlander, Aug 29, 2016.

  1. hadynlander

    hadynlander

    Joined:
    Jan 24, 2014
    Posts:
    41
    I've been working on a modified "standard" shader that relies on grabpass, and I've come across a weird issue whereby the grabpass texture seems to darken for all instances of a shader except the one which is farthest from the camera, as visible here:

    GrabpassIssue.png

    Here's a quick, bare-bones version of the shader, which exhibits the same behavior:

    Code (CSharp):
    1. Shader "Custom/NewSurfaceShader" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    6.         _Metallic ("Metallic", Range(0,1)) = 0.0
    7.     }
    8.     SubShader {
    9.         Tags {"Queue" = "Transparent" "RenderType"="Transparent"}
    10.         LOD 200
    11.  
    12.         GrabPass{ }
    13.  
    14.         CGPROGRAM
    15.         // Physically based Standard lighting model, and enable shadows on all light types
    16.         #pragma surface surf Standard fullforwardshadows vertex:vert
    17.  
    18.         // Use shader model 3.0 target, to get nicer looking lighting
    19.         #pragma target 3.0
    20.  
    21.         sampler2D _MainTex;
    22.  
    23.         struct Input {
    24.             float4 grabPos : TEXCOORD0;
    25.             float4 screenPos : TEXCOORD1;
    26.             float2 uv_MainTex;
    27.         };
    28.  
    29.         half _Glossiness;
    30.         half _Metallic;
    31.         fixed4 _Color;
    32.         sampler2D _GrabTexture;
    33.  
    34.         void vert (inout appdata_full v, out Input o){
    35.               UNITY_INITIALIZE_OUTPUT(Input,o);          
    36.               o.grabPos = ComputeGrabScreenPos(UnityObjectToClipPos(v.vertex));
    37.               o.screenPos = ComputeScreenPos(mul(UNITY_MATRIX_MVP, v.vertex));
    38.         }
    39.  
    40.         void surf (Input IN, inout SurfaceOutputStandard o) {
    41.             fixed4 c = tex2Dproj(_GrabTexture, IN.grabPos);
    42.             o.Albedo = c.rgb;
    43.             o.Metallic = _Metallic;
    44.             o.Smoothness = _Glossiness;
    45.         }
    46.         ENDCG
    47.     }
    48.     FallBack "Diffuse"
    49. }
    I don't suppose anyone has any idea as to what might be going wrong? Any help/advice would be much appreciated!

    Cheers,
    Hadyn
     
  2. hadynlander

    hadynlander

    Joined:
    Jan 24, 2014
    Posts:
    41
    Update!

    It seems that ambient lighting is at the heart of the issue - it's only being applied to the farthest instance. I can disable it to ensure that they're all uniformly lit, but ideally I'd like to have it apply correctly to all instances, if anyone has any ideas?
     
  3. AlanMattano

    AlanMattano

    Joined:
    Aug 22, 2013
    Posts:
    1,501
    Just one Idea to help: Is just one theory but probably is wrong. Looking to the screenshot and not looking the code, looks like is correct. Is making an average: Big surface, darken, smaller more brightness because the number of rays are equal (the amount of dots). In other words, if you expand the white surface, it will became more darker because the light is the same amount (and in a bigger surface will be less shinny). Since farther, the surface is more equal to the white surface and closest more dissipated (and darker). If is far away there is no surface distortion and if near there is more distortion (is correct). But just a theory that feels wrong because there is no transition. Or the shader is making a distance average to all the surface.
     
    hadynlander likes this.
  4. hadynlander

    hadynlander

    Joined:
    Jan 24, 2014
    Posts:
    41
    Thanks for the input. It's an interesting idea, but as you say I don't think it's what's causing the problem in this case. I didn't describe this particularly well in my original post, but the surface instantly flicks to being brighter or darker when you rotate the camera - so as soon as the farthest surface goes off the edge of the screen, the second farthest one instantly brightens; rotate the camera back the other way, and it instantly darkens as soon as the more distant surface comes back into view.

    In light of the info I discovered in my last update, the most accurate way I could describe the problem would be to say something like "ambient light only applies to the farthest instance of the grabpass-enabled standard shader". I'd update the title of my post to that, but I don't think these forums allow titles to be edited(?).
     
  5. AlanMattano

    AlanMattano

    Joined:
    Aug 22, 2013
    Posts:
    1,501
    As alternative to work around the problem; I do not know if is posible to use grabpass inside shaderforge. If is posible then can be useful for debugging.