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

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:

  • Properties {
  • _MainTex (“Screen Texture”, 2D) = “white” {}
  • }

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

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.

1 Like

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 Unity - Manual: Writing Surface Shaders 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

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:

material.SetTexture("_TextureName", renderTexture);

Afterwards you of course have to call the Graphics.Blit with the material you set the texture for.
As easy as that :slight_smile:

2 Likes