Talk about unity: GrabPass

https://blog.csdn.net/puppet_master/article/details/70199330
https://blog.csdn.net/qq_32468649/article/details/79992819

GrabPass
GrabPass is unity as we provide a very convenient feature, you can directly render the current screen contents to a map,
we can not render themselves to implement such a process map using this map directly in the shader.

GrabPass very simple to use, we write vertex fragment shader amount of time is required to write a pass, GrabPass is a pass, simply
unity to achieve a pass good for us.
We only need to pass in front of our normal plus a GrabPass {} on it.

The official document: https: //docs.unity3d.com/Manual/SL-GrabPass.html
two GrabPass wording on the first one is directly GrabPass {} wording, such an approach screenshots of the picture directly to save _GrabTexture system predefined map variables, we can directly access the map, but such an approach would lead to the use of each object GrabPass to conduct a screen capture operation!
Another is GrabPass { "TextureName"} wording, wherein a texture is TextureName our custom name, such an approach, using a Unity only for the first frame of each object name of the screen capture operation, after the you can reuse this mapping, the test needs to be done here.

Note that, when using GrabPass, we need to be extra careful to set the render queue object.
As said before, GrabPass commonly used to render transparent objects, although the instruction code does not include mixing, but we still need to object often
render queue Queue arranged to be transparent (i.e., "Queue" = "Transparent") . So as to ensure that when rendering the object, all opaque objects have already
been drawn on the screen, and thus get the correct screen image.

inline float4 ComputeGrabScreenPos (float4 pos) 
{
    #if UNITY_UV_STARTS_AT_TOP
    float scale = -1.0;
    #else
    float scale = 1.0;
    #endif
    float4 o = pos * 0.5f;
    o.xy = float2(o.x, o.y*scale) + o.w;
	#ifdef UNITY_SINGLE_PASS_STEREO
	    o.xy = TransformStereoScreenSpaceTex(o.xy, pos.w);
	#endif
    o.zw = pos.zw;
    return o;
}

This is passed homogeneous coordinates of the object, note the perspective division without coordinates. In the following manner:

v2f vert(appdata_base v) 
{
	v2f o;
	o.pos = UnityObjectToClipPos(v.vertex);
	o.grabPos = ComputeGrabScreenPos(o.pos);
	return o;
}
sampler2D _BackgroundTexture;
half4 frag(v2f i) : SV_Target
{
	half4 bgcolor = tex2Dproj(_BackgroundTexture, i.grabPos);
	return bgcolor*2;
}

In the previous blog post: https: //blog.csdn.net/wodownload2/article/details/102969154
There is a problem: The first way, you can not grab the map screen, displayed on a plane. Why is that?
Examples of binding in the figure:
Here Insert Picture Description
the camera to see the ball, then saw plane.
The sphere of the material is opaque, the use of a random sampling of shader texture on the line.
Our key is to look at what plane shader, shader code is as follows:

Shader "GrabPass"
{
	SubShader
	{
		GrabPass
		{
			"_BackgroundTexture"
		}
		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"

			struct v2f
			{
				float4 grabPos : TEXCOORD0;
				float4 pos : SV_POSITION;
			};

			v2f vert(appdata_base v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.grabPos = ComputeGrabScreenPos(o.pos);
				return o;
			}
			sampler2D _BackgroundTexture;
			half4 frag(v2f i) : SV_Target
			{
				half4 bgcolor = tex2Dproj(_BackgroundTexture, i.grabPos);
				return bgcolor/2;
			}
			ENDCG
		}
	}
}

Frame seen by the debugger:
Here Insert Picture Description
first draw a sphere, and then draw a plane, since the plane using a two pass: the first one is GrabPass, Pass is the second texture after sampling Grab.
And GrabPass located on a pass, he first performed Grab, in the implementation of the second sampling Pass.
As follows:
Here Insert Picture Description
so the second pass can grab the first pass of the map.

Here why our second pass of the fragment shader it is divided by 2? Because if not divided by 2, then things will not see any of it:
Here Insert Picture Description
this is why it?
Because the plane after conversion into the screen coordinate space, that is the one thing, but this one thing and grab the map color is the same. So I do not see anything,
there's two problems:
1, why the scene of plane do not see any thing, it is estimated that the scene view, the main camera and a camera is not the same problem.
2, frame debugger, do not see the captured picture
Here Insert Picture Description
so only manually displayed at a patch of view.

So the combination of all the above issues, we want to show grab the picture, is to use the following shader:

Shader "Unlit/GrabPass"
{
	SubShader {
		Tags { "Queue"="Transparent" "RenderType"="Opaque" }
		//抓取屏幕图像并存储在名为_GrabTex的纹理中
		GrabPass { "_GrabTex" }
 
		pass 
		{
			CGPROGRAM
 
			#pragma vertex vert
			#pragma fragment frag
	 
			#include "UnityCG.cginc"
	 
			sampler2D _GrabTex;
			float4 _GrabTex_ST;
	 
			struct a2v 
			{
				float4 vertex : POSITION;
				float4 texcoord : TEXCOORD0;
			};
	 
			struct v2f 
			{
				float4 pos : SV_POSITION;
				float2 uv : TEXCOORD0;
			};
			v2f vert(a2v v) 
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.texcoord, _GrabTex);
				return o;
			}
			fixed4 frag(v2f i) : SV_Target 
			{
				fixed3 color = tex2D(_GrabTex, i.uv).rgb;
				return fixed4(color, 1.0);
			}
			ENDCG
		}
	}
}

Or, as the official blog, like inverted color, color ie 1-sampling, the effect is as follows:
Here Insert Picture Description
you can see the color of the rectangle is black, and we use a fixed color rendering of the way:
Here Insert Picture Description
At this point, we already know this grabpass the principle and the caution point, over!

Published 610 original articles · won praise 96 · views 330 000 +

Guess you like

Origin blog.csdn.net/wodownload2/article/details/104372175