Search Unity

Blit(source, dest, mat): how does source bind to texture in shader?

Discussion in 'Image Effects' started by csofranz, Jun 27, 2017.

  1. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    It seems I'm missing an essential piece of Information, and would appreciate some help as to where I can reqad up on this.

    I have written a couple of shaders for my materials, and they all work exactly as I want them. Makes me feel great. Now I'm tasked with something that should be simple, but for the life of me, I can't figure out the glue between the two.

    Let's say I have a shader that, under Properties defines a texture for my material:

    1. Properties {
    2. _MainTex ("Screen Texture", 2D) = "white" {}
    3. }

    I can Access this fine, and when using this with a material, I can apply all kinds of nice effects on my mesh.

    Now I want to use this same shader for a camera (Image) effect. The docs say all I Need to do is invoke Blit in OnRenderImage with source, dest, and a material that contains the shader I want.

    I do that, and it works - but I don't know why. It shouldn't. At least not without first setting the _MainTex property to source. And yet, even though I don't, it works. Why? Phrased differently: what I do not understand - nor where this is explained - is how "source" is bound to "_MainTex". Is this just black Magic, or is there any documentation I can look up where it is explained which properties Blit sets up, and how it does it? Are there reserved names? I feel I'm missing an essential step in my understanding of Image effects, and feel exceedingly uneasy handing this off without property understanding what is going on under the Hood.

    Any pointers? I believe I have read all the chapters in ShaderLab, but evidently I have missed an essential one.

    Thanks,
    -ch
     
  2. equalsequals

    equalsequals

    Joined:
    Sep 27, 2010
    Posts:
    154
    When you call Graphics.Blit you have 3 overloads:

    [From Docs]
    public static void Blit(Texture source, RenderTexture dest);
    public static void Blit(Texture source, RenderTexture dest, Material mat, int pass = -1);
    public static void Blit(Texture source, Material mat, int pass = -1);

    In these overloads, you have 2 in which you supply a Material, and one which you do not. In the event that you do not supply a Material, a Material with "Hidden/BlitCopy" Shader is used.

    What I can speculate is that inside of Blit, Unity is simply taking the 'source' Texture and injecting it into the Property for '_MainTex' for you.
     
    Yazaa likes this.
  3. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    Thanks for chipping in, equalsequals. The probelm is that I, too, have speculated about this, but I need to understand this. Here's why:

    Let's say I have *two* textures defined, that I wish lerp between: the sceen and an Image of a high-score table. How does unity know which is which? Will Unity bind the first texture it finds in my code to the sceen? The second? Just how does it find the texture it replaces with the screen image? There must be a very simple way, something I simply missed in the docs - I doubt that Unity engages in runtime code analytics to find and semantically derive a texture variable just to fill with a sceen Image. I could conjecture that it merely connects the a default texture in the Input vector - but then I need to find that parameter. Note that the documentation at https://docs.unity3d.com/Manual/SL-SurfaceShaders.html implies that there is something like a texture in there, but does not actually state so, nor describe their Interface.

    This is quite vexing to me, as not understanding what I'm doing runs counter to my sense of professionalism.

    Can anyone help me out? I

    Thanks,
    -ch
     
  4. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Graphics.Blit maps source on _MainTex. If you want to add another texture in your shader you can simply add another property as you are used to. If you want to add a texture in OnRenderImage, you have to call:

    Code (CSharp):
    1. material.SetTexture("_TextureName", renderTexture);
    https://docs.unity3d.com/ScriptReference/Material.SetTexture.html
    Afterwards you of course have to call the Graphics.Blit with the material you set the texture for.
    As easy as that :)
     
    exitshadow and blablaalb like this.