Search Unity

Post Effect render texture shader Y flipping issue...

Discussion in 'Shaders' started by seowen1, Aug 20, 2019.

  1. seowen1

    seowen1

    Joined:
    Feb 22, 2018
    Posts:
    11
    Hi all...

    Having issues with a post effect shader... It seems that whenever I apply this shader as a render texture shader to a more than one camera, the resulting image flips on the Y coordinates, and it appears upside down.

    Here's my shader:

    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2.  
    3. Shader "Custom/HighlightShaderPostEffect"
    4. {
    5.     Properties
    6.     {
    7.         _MainTex("Main Texture",2D)="black"{}
    8.         _SceneTex("Scene Texture",2D)="black"{}
    9.         _GlowColor("Glow Color",Color)=(0,1,0,1)
    10.         _GlowSize("Glow Size", Float)=20
    11.     }
    12.     SubShader
    13.     {
    14.         Pass
    15.         {
    16.             CGPROGRAM
    17.    
    18.             sampler2D _MainTex;
    19.             //<SamplerName>_TexelSize is a float2 that says how much screen space a texel occupies.
    20.             float2 _MainTex_TexelSize;
    21.             float _GlowSize;
    22.             #pragma vertex vert
    23.             #pragma fragment frag
    24.             #include "UnityCG.cginc"
    25.            
    26.             struct v2f
    27.             {
    28.                 float4 pos : SV_POSITION;
    29.                 float2 uvs : TEXCOORD0;
    30.             };
    31.            
    32.             v2f vert (appdata_base v)
    33.             {
    34.                 v2f o;
    35.                
    36.                 //Despite the fact that we are only drawing a quad to the screen, Unity requires us to multiply vertices by our MVP matrix, presumably to keep things working when inexperienced people try copying code from other shaders.
    37.                 o.pos = UnityObjectToClipPos(v.vertex);
    38.                
    39.                 //Also, we need to fix the UVs to match our screen space coordinates. There is a Unity define for this that should normally be used.
    40.                 o.uvs = o.pos.xy / 2 + 0.5;
    41.                
    42.                 return o;
    43.             }
    44.            
    45.            
    46.             half frag(v2f i) : COLOR
    47.             {
    48.                 //split texel size into smaller words
    49.                 float TX_x=_MainTex_TexelSize.x;
    50.                 //and a final intensity that increments based on surrounding intensities.
    51.                 float ColorIntensityInRadius;
    52.                 //for every iteration we need to do horizontally
    53.                 [loop]for(int k=0;k<floor(_GlowSize);k+=1)
    54.                 {
    55.                     //increase our output color by the pixels in the area
    56.                     ColorIntensityInRadius+=tex2Dlod(
    57.                                                     _MainTex,
    58.                                                     float4(i.uvs.x,i.uvs.y,0,0)+float4((k-_GlowSize/2)*TX_x,0,0,0)).r/ _GlowSize;
    59.                 }
    60.                 //output some intensity of teal
    61.                 return ColorIntensityInRadius;
    62.             }
    63.            
    64.             ENDCG
    65.         }
    66.         //end pass  
    67.        
    68.         GrabPass{}
    69.        
    70.         Pass
    71.         {
    72.             CGPROGRAM
    73.             sampler2D _MainTex;
    74.             sampler2D _SceneTex;
    75.             half4 _GlowColor;
    76.             float _GlowSize;
    77.            
    78.             //we need to declare a sampler2D by the name of "_GrabTexture" that Unity can write to during GrabPass{}
    79.             sampler2D _GrabTexture;
    80.             //<SamplerName>_TexelSize is a float2 that says how much screen space a texel occupies.
    81.             float2 _GrabTexture_TexelSize;
    82.             #pragma vertex vert
    83.             #pragma fragment frag
    84.             #include "UnityCG.cginc"
    85.            
    86.             struct v2f
    87.             {
    88.                 float4 pos : SV_POSITION;
    89.                 float2 uvs : TEXCOORD0;
    90.             };
    91.            
    92.             v2f vert (appdata_base v)
    93.             {
    94.                 v2f o;
    95.                
    96.                 //Despite the fact that we are only drawing a quad to the screen, Unity requires us to multiply vertices by our MVP matrix, presumably to keep things working when inexperienced people try copying code from other shaders.
    97.                 o.pos=UnityObjectToClipPos(v.vertex);
    98.                 //Also, we need to fix the UVs to match our screen space coordinates. There is a Unity define for this that should normally be used.
    99.                 o.uvs = o.pos.xy / 2 + 0.5;
    100.  
    101.                 // On D3D when AA is used, the main texture & scene depth texture
    102.                 // will come out in different vertical orientations.
    103.                 // So flip sampling of the texture when that is the case (main texture
    104.                 // texel size will have negative Y).
    105.                 #if UNITY_UV_STARTS_AT_TOP
    106.                 if (_GrabTexture_TexelSize.y < 0)
    107.                         o.uvs.y = 1-o.uvs.y;
    108.                 #endif
    109.                
    110.                 return o;
    111.             }
    112.            
    113.            
    114.             half4 frag(v2f i) : COLOR
    115.             {
    116.                 //split texel size into smaller words
    117.                 float TX_y=_GrabTexture_TexelSize.y;
    118.                 //and a final intensity that increments based on surrounding intensities.
    119.                 half ColorIntensityInRadius=0;
    120.                 //if something already exists underneath the fragment (in the original texture), discard the fragment.
    121.                 //if(tex2D(_MainTex,i.uvs.xy).r>0)
    122.                 //{
    123.                 //    return tex2D(_SceneTex,float2(i.uvs.x,i.uvs.y));
    124.                 //}
    125.                 //for every iteration we need to do vertically
    126.                 [loop]for(int j=0;j< floor(_GlowSize);j+=1)
    127.                 {
    128.                     //increase our output color by the pixels in the area
    129.                     ColorIntensityInRadius+= tex2Dlod(
    130.                                                     _GrabTexture,
    131.                                                     float4(i.uvs.x,1-i.uvs.y,0,0)+float4(0,(j-_GlowSize/2)*TX_y,0,0)).r/ _GlowSize;
    132.                 }
    133.                 //this is alpha blending, but we can't use HW blending unless we make a third pass, so this is probably cheaper.
    134.                 half4 outcolor = ColorIntensityInRadius * _GlowColor * 2    +   (1-ColorIntensityInRadius)*tex2D(_SceneTex,float2(i.uvs.x,i.uvs.y));
    135.                 return outcolor;
    136.             }
    137.            
    138.             ENDCG
    139.         }
    140.         //end pass  
    141.     }
    142.     //end subshader
    143. }
    144. //end shader
    And here's the C# code applied to the cameras:

    Code (CSharp):
    1. void OnRenderImage(RenderTexture source, RenderTexture destination) {
    2.  
    3.         if (cameraComp != null) {
    4.  
    5.             //make the temporary rendertexture
    6.             RenderTexture TempRT = new RenderTexture(source.width, source.height, 0, RenderTextureFormat.R8);
    7.  
    8.             //put it to video memory
    9.             TempRT.Create();
    10.  
    11.             //set the camera's target texture when rendering
    12.             cameraComp.targetTexture = TempRT;
    13.  
    14.             //render all objects this camera can render, but with our custom shader.
    15.             cameraComp.RenderWithShader(highlightShader, "");
    16.  
    17.             highlightMaterial.SetTexture("_SceneTex", source);
    18.  
    19.             //copy the temporary RT to the final image
    20.             Graphics.Blit(TempRT, destination, highlightMaterial);
    21.  
    22.             //release the temporary RT
    23.             TempRT.Release();
    24.  
    25.         }
    26.     }
    It all seems to work fine, except that if I'm using more than one camera rendering to the screen with this method... Any ideas?