Search Unity

Is it possible for a global variable to contain a different value per camera?

Discussion in 'Shaders' started by gigazelle, Sep 3, 2020.

  1. gigazelle

    gigazelle

    Joined:
    May 6, 2017
    Posts:
    13
    I have a URP project that I've set up, and have created several shaders using the Shader Graph. Each of these shaders have a boolean in common that I toggle to change how things are rendered (e.g. heat vision). This allows me to have a bunch of different shaders (one for water, one for tri-planar, one for transparency, etc) and all I need to do to swap vision is a single SetGlobalFloat call.

    This setup works flawlessly for a single camera setup. However, I would like to introduce the concept of split-screen to my game, where one side of the screen has one global float value (normal rendering), and the other side of the screen has a different global float value (heat vision). Is this possible?

    If this is not possible, it sounds like I will need to separate my shaders into their respective float variants (normal shader and heat vision shader); however, that would make rendering with multiple shaders (tri-planar, water, etc.) much more complicated.

    What would be a recommended workflow here?
     
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,546
    gigazelle likes this.
  3. Oxeren

    Oxeren

    Joined:
    Aug 14, 2013
    Posts:
    121
    gigazelle likes this.
  4. gigazelle

    gigazelle

    Joined:
    May 6, 2017
    Posts:
    13
    Thank you both! Learning about
    OnPreRender
    got me on a trail towards
    beginCameraRendering
    , which has me on the right track. It looks like I just need to register a function once, instead of including its own
    OnPreRender
    script attached to my camera.

    Following that trail has led me to ScriptableRenderContext.SetupCameraProperties, which I may or may not need if I can get the global floats working.
     
  5. gigazelle

    gigazelle

    Joined:
    May 6, 2017
    Posts:
    13
    Got it working without needing SetupCameraProperties - thanks so much for pointing me in the right direction! This is the (simplified) script that I used in case anyone else runs into the same issue:

    Code (CSharp):
    1. using UnityEngine.Rendering;
    2.  
    3. public class ExampleSplitscreen : MonoBehaviour {
    4.   int shaderToggle;
    5.   void Start() {
    6.     // Register the function to beginCameraRendering. Only register this once, regardless of how many cameras exist
    7.     RenderPipelineManager.beginCameraRendering += HandleVision;
    8.   }
    9.   void HandleVision(ScriptableRenderContext context, Camera camera) {
    10.     // Check for which camera it's running against, and handle logic accordingly
    11.     if(camera == camera1) shaderToggle = 0;
    12.     else shaderToggle = 1;
    13.     Shader.SetGlobalFloat("vision", shaderToggle);
    You'd then have an unexposed boolean in your shader that handles the rendering differences (only variables that aren't exposed can be manipulated using scripts).
     
    najati, athenspire and Invertex like this.