Space curvature bending in Unity3D as Post Effect/Image Effect

315 Views Asked by At

I'm trying to archieve a chilindrical effect like this on Unity3D:

enter image description here

But every solution is using material based shader, sadly I must have a Post Process effect or an Image Effect, for these reasons:

  • One map out of 30 needs to use this effect and there are many materials that are shared between them...
  • Every solution is vertex based. I've done some experiments but I have models with different polygon count, this means that the effect would create visual artifacts (but this can by fixed by editing the 3d models eventually).
  • I'm at an advanced stage of development.

Do you think it's possible to create a simple effect (even a fake one) that moves the pixels downwards/upwards based on the distance to the camera? (I assume I need to use the depth map)

I've tried very hard but I had no success, the effect doesn't do anything or just won't compile :(

This is the best I could come up with, the grayscale in the frag method is only to check if the shader is working, but once I define the Vert function the grayscale disappears and the shader does nothing.

Shader "Hidden/Custom/WorldCurvature"
{
HLSLINCLUDE

    #include "Packages/com.unity.postprocessing/PostProcessing/Shaders/StdLib.hlsl"

    TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);
    float _Bend;
    
    struct Attributes
    {
        float4 vertex : POSITION;
        float2 texcoord : TEXCOORD0;
    };
    
    struct Varyings
    {
        float4 vertex : SV_POSITION;
        float2 texcoord : TEXCOORD0;
    };

    float4 Frag(Varyings i) : SV_Target
    {
        float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord);
        float luminance = dot(color.rgb, float3(0.2126729, 0.7151522, 0.0721750));
        color.rgb = lerp(color.rgb, luminance.xxx, _Bend.xxx);
        return color;
    }  
    
    Varyings Vert(Attributes v)
    {
        Varyings o;
        float4 vv = mul(unity_ObjectToWorld, v.vertex );
        vv.xyz -= _WorldSpaceCameraPos.xyz;
        vv = float4( 0.0f, (vv.x * vv.x) * - _Bend, 0.0f, 0.0f );
        v.vertex += mul(unity_WorldToCamera, vv);
        o.vertex = mul(unity_WorldToCamera, vv);
        o.texcoord = v.texcoord;
        return o;
    }

ENDHLSL

SubShader
{
    Cull Off ZWrite Off ZTest Always

    Pass
    {
        HLSLPROGRAM

            #pragma vertex Vert
            #pragma fragment Frag

        ENDHLSL
    }
}
}

I've done another experiment but I think it would only work in a 2D environment, here the image stops once I activate the image effect:

Shader "Hidden/Custom/CylinderImageEffect" {
 Properties {
     _MainTex ("Texture", 2D) = "white" {}
 }

 SubShader {
     Cull Off ZWrite Off ZTest Always

     Pass {
         CGPROGRAM
         #pragma vertex vert
         #pragma fragment frag

         #include "UnityCG.cginc"

         struct v2f {
             float4 vertex : SV_POSITION;
             float2 uv : TEXCOORD0;
         };

        v2f vert( appdata_img v ) 
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.uv = v.texcoord.xy;
            return o;
        } 

         sampler2D _MainTex;

         fixed4 frag (v2f i) : SV_Target {
             i.uv.x = 1 - acos(i.uv.x * 2 - 1) / 3.14159265;
             return tex2D(_MainTex, i.uv);
         }
         ENDCG
     }
 }
 }
0

There are 0 best solutions below