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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Gravitational Lensing Shader Help

Discussion in 'Shaders' started by jalowry0328, Sep 13, 2018.

  1. jalowry0328

    jalowry0328

    Joined:
    Jan 20, 2018
    Posts:
    2
    I have this shader (which works really well) that I got from this tutorial:



    The only problem I have with it is that it also distorts things in front of the black hole (Like the particle system I have around it)

    Here's a picture:


    Another example of a star that is between the camera and the black hole:


    What I would like to have is only what is behind the black hole to be distorted and leave the particle system unaffected in front of it, so the particles that pass in front of the black hole don't dip down like they are, rather they just continue straight and cut the black part in half, if that makes sense. I don't have much experience with shaders at all outside of this tutorial, so some guidance would be greatly appreciated!

    Here's the script and the shader I'm using for this effect:

    The Script:
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. [RequireComponent(typeof(Camera))]
    7. public class BlackHoleEffect : MonoBehaviour {
    8.  
    9.     //public settings
    10.     public Shader shader;
    11.     public Transform blackHole;
    12.     public float ratio;
    13.     public float radius;
    14.  
    15.     //private settings
    16.     Camera cam;
    17.     Material _material;
    18.  
    19.     Material material
    20.     {
    21.         get {
    22.             if (_material == null)
    23.             {
    24.                 _material = new Material(shader);
    25.                 _material.hideFlags = HideFlags.HideAndDontSave;
    26.             }
    27.             return _material;
    28.         }
    29.     }
    30.  
    31.     void OnEnable()
    32.     {
    33.         cam = GetComponent<Camera>();
    34.         ratio = 1f / cam.aspect;
    35.     }
    36.  
    37.     void OnDisable()
    38.     {
    39.         if (_material)
    40.         {
    41.             DestroyImmediate(_material);
    42.         }
    43.     }
    44.  
    45.     Vector3 wtsp;
    46.     Vector2 pos;
    47.  
    48.     void OnRenderImage(RenderTexture source, RenderTexture destination)
    49.     {
    50.         if (shader && material && blackHole)
    51.         {
    52.             wtsp = cam.WorldToScreenPoint(blackHole.position);
    53.  
    54.             if (wtsp.z > 0)
    55.             {
    56.                 pos = new Vector2(wtsp.x / cam.pixelWidth, (wtsp.y / cam.pixelHeight));
    57.                 _material.SetVector("_Position", pos);
    58.                 _material.SetFloat("_Ratio", ratio);
    59.                 _material.SetFloat("_Rad", radius);
    60.                 _material.SetFloat("_Distance", Vector3.Distance(blackHole.position, transform.position));
    61.  
    62.                 Graphics.Blit(source, destination, material);
    63.             }
    64.         }
    65.     }
    66. }
    67.  
    The Shader:
    Code (CSharp):
    1.  
    2. Shader "Hidden/BlackHoleShader"
    3. {
    4.     Properties
    5.     {
    6.         _MainTex ("Texture", 2D) = "white" {}
    7.     }
    8.     SubShader
    9.     {
    10.         // No culling or depth
    11.         Cull Off ZWrite Off ZTest Always
    12.  
    13.         Pass
    14.         {
    15.             CGPROGRAM
    16.             #pragma vertex vert
    17.             #pragma fragment frag
    18.             #pragma fragmentoption ARB_precision_hint_fastest
    19.          
    20.             #include "UnityCG.cginc"
    21.          
    22.             uniform sampler2D _MainTex;
    23.             uniform float2 _Position;
    24.             uniform float _Rad;
    25.             uniform float _Ratio;
    26.             uniform float _Distance;
    27.  
    28.             struct v2f {
    29.                 float4 pos : POSITION;
    30.                 float2 uv : TEXCOORD0;
    31.             };
    32.  
    33.             v2f vert(appdata_img v){
    34.                 v2f o;
    35.                 o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    36.                 o.uv = v.texcoord;
    37.                 return o;
    38.             }
    39.  
    40.             fixed4 frag(v2f i) : COLOR{
    41.                 float2 offset = i.uv - _Position;
    42.                 float2 ratio = { _Ratio, 1 };
    43.                 float rad = length(offset / ratio);
    44.                 float deformation = 1 / pow(rad * pow(_Distance, 0.5), 2) * _Rad * 0.1;
    45.  
    46.                 offset = offset * (1 - deformation);
    47.                 offset += _Position;
    48.  
    49.                 half4 res = tex2D(_MainTex, offset);
    50.  
    51.                 if (rad * _Distance < _Rad) {
    52.                     res = half4( 0, 0, 0, 1 );
    53.                 }
    54.  
    55.                 return res;
    56.  
    57.             }
    58.  
    59.             ENDCG
    60.         }
    61.     }
    62. }
    63.  
    64.  
     
    Last edited: Sep 13, 2018
  2. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    6,466
    So that would be the equivalent to glass distortion shader, without looking too deeply I think you have a black hole as a post process, so it applies to the entire screen, what you want is to have an object (quad) that is looked through and apply the black hole effect. Which mean grabpass or equivalent (I haven't updated on that part).

    Or another solution is to apply the shader by discriminating using the depth buffer, but you will have artefact for part that are distorted and behind rendered geometry ( and thus are invisible).
     
    Amarnath5261 likes this.
  3. jalowry0328

    jalowry0328

    Joined:
    Jan 20, 2018
    Posts:
    2
    Ah I know what you mean, I actually was using a quad with a glass shader on it but it was flickering I think due to the particle system I have around it. I'll try it again and see if I did something wrong.
     
  4. phbprogramming

    phbprogramming

    Joined:
    Apr 24, 2020
    Posts:
    1
    Did you ever find a solution to this problem? I am experiencing the same thing with a similar shader that warps the pixels but with a different deformation calculation, but I only want to do it for items that are behind the point I'm calculating for the warp.