Search Unity

Get texture from fragment/vertex passes?

Discussion in 'Shaders' started by Hybridizer, Nov 20, 2017.

  1. Hybridizer

    Hybridizer

    Joined:
    Feb 3, 2015
    Posts:
    18
    I'm trying to get the effect of optic glass (old car headlights, etc) for my own uses. I had thought about using GrabPass to achieve it, and lo and behold Unity already had just what I wanted: Bumped Distortion. Perfect. Except it's only part of what I want. It has the optic effect, but now I need to write the Surface aspect of it, namely tinting, decals, and emission. I understand how to do all these on surface shaders, but that doesn't help with optics. So my question is:

    How do I use a previous fragment/vertex pass's computed image as a texture for a Surface shader?

    For reference, here's the full Bumped Distortion shader:
    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2.  
    3. Shader "FX/Glass/Stained BumpDistort" {
    4. Properties {
    5.      _BumpAmt  ("Distortion", range (0,128)) = 10
    6.      _MainTex ("Tint Color (RGB)", 2D) = "white" {}
    7.      _BumpMap ("Normalmap", 2D) = "bump" {}
    8. }
    9. Category {
    10.      // We must be transparent, so other objects are drawn before this one.
    11.      Tags { "Queue"="Transparent" "RenderType"="Opaque" }
    12.      SubShader {
    13.          // This pass grabs the screen behind the object into a texture.
    14.          // We can access the result in the next pass as _GrabTexture
    15.          GrabPass {
    16.              Name "BASE"
    17.              Tags { "LightMode" = "Always" }
    18.          }
    19.      
    20.          // Main pass: Take the texture grabbed above and use the bumpmap to perturb it
    21.          // on to the screen
    22.          Pass {
    23.              Name "BASE"
    24.              Tags { "LightMode" = "Always" }
    25.          
    26. CGPROGRAM
    27. #pragma vertex vert
    28. #pragma fragment frag
    29. #pragma multi_compile_fog
    30. #include "UnityCG.cginc"
    31. struct appdata_t {
    32.      float4 vertex : POSITION;
    33.      float2 texcoord: TEXCOORD0;
    34. };
    35. struct v2f {
    36.      float4 vertex : SV_POSITION;
    37.      float4 uvgrab : TEXCOORD0;
    38.      float2 uvbump : TEXCOORD1;
    39.      float2 uvmain : TEXCOORD2;
    40.      UNITY_FOG_COORDS(3)
    41. };
    42. float _BumpAmt;
    43. float4 _BumpMap_ST;
    44. float4 _MainTex_ST;
    45. v2f vert (appdata_t v)
    46. {
    47.      v2f o;
    48.      o.vertex = UnityObjectToClipPos(v.vertex);
    49.      #if UNITY_UV_STARTS_AT_TOP
    50.      float scale = -1.0;
    51.      #else
    52.      float scale = 1.0;
    53.      #endif
    54.      o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
    55.      o.uvgrab.zw = o.vertex.zw;
    56.      o.uvbump = TRANSFORM_TEX( v.texcoord, _BumpMap );
    57.      o.uvmain = TRANSFORM_TEX( v.texcoord, _MainTex );
    58.      UNITY_TRANSFER_FOG(o,o.vertex);
    59.      return o;
    60. }
    61. sampler2D _GrabTexture;
    62. float4 _GrabTexture_TexelSize;
    63. sampler2D _BumpMap;
    64. sampler2D _MainTex;
    65. half4 frag (v2f i) : SV_Target
    66. {
    67.      // calculate perturbed coordinates
    68.      half2 bump = UnpackNormal(tex2D( _BumpMap, i.uvbump )).rg; // we could optimize this by just reading the x & y without reconstructing the Z
    69.      float2 offset = bump * _BumpAmt * _GrabTexture_TexelSize.xy;
    70.      i.uvgrab.xy = offset * i.uvgrab.z + i.uvgrab.xy;
    71.  
    72.      half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
    73.      half4 tint = tex2D(_MainTex, i.uvmain);
    74.      col *= tint;
    75.      UNITY_APPLY_FOG(i.fogCoord, col);
    76.      return col;
    77. }
    78. ENDCG
    79.          }
    80.      }
    81.      // ------------------------------------------------------------------
    82.      // Fallback for older cards and Unity non-Pro
    83.      SubShader {
    84.          Blend DstColor Zero
    85.          Pass {
    86.              Name "BASE"
    87.              SetTexture [_MainTex] {    combine texture }
    88.          }
    89.      }
    90. }
    91. }

    In my own edit (not show here) I have added the surface aspect, but it just overwrites the previous passes. As far as I can tell, I want to access the final Col element of the final pass of the above code, and apply it as the initial Albedo for the surface shader.

    Is this even possible?

    PS. I'm mildly experienced in shaders, not a total noob but near that end of the spectrum, for reference.
     
    Last edited: Nov 20, 2017
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352