how to get _GrabTexture in surface shader?

GrabPass can only be used in vertex fragment shader…
So if I write surface shader.how do i get _GrabTexture???

Actually you don’t have to do anything fancy :slight_smile:
Simply place the

GrabPass { }

in the SubShader. The surface shader creates its own passes, which will work fine in combination with the grabpass.

[Edit] I see that this is your second post about the issue within a day. Which isn’t very useful, because people who reply can’t build upon the answers of others. Also, it’s a bit rude.
But I know that it can be a bit tricky to figure this stuff out, so I’ll try to make an example.

Here is an example of using GrabPass in a Surface shader. It is based on a water refraction shader, which in turn was based on FX/Glass/Stained BumpDistort, which is a “Per pixel bumped refraction”. Now that I turned into an example, it isn’t useful for either of those, unfortunately, because it uses worldNormals for simplicity, and the refraction code assumes the normals are usable as uv coordinates.

There are some more functional examples on this forum, so try searching for “GrabPass in Surface Shader”

This is very similar to a shader I used to understand the concepts, by commenting out stuff I didn’t understand to see what effects they had, and rewriting things to check if I understood them correctly.

To make GrabPass useful, you don’t just need the image data, but you also need to be able to project it correctly onto the geometry you’re drawing it on. They explain that very well in this article.

Hopefully this helps you understand the basics.

Shader "Learning/GrabPassTest" {
	Properties {
		_Refraction ("Refraction", Float) = 10
	}
	SubShader {
		Tags { "Queue"="Transparent"}
		GrabPass { }
		
		CGPROGRAM
		#pragma surface surf Lambert vertex:UvStuff

		float _Refraction;
		
		sampler2D _GrabTexture;
		float4 _GrabTexture_TexelSize;// Automagically set to the TexelSize of the GrabTexture (xy = dimensions of texel, .zw = resolution of texture.)

		struct Input {
			float4 projection : TEXCOORD;// Semantics are wonderful, when you remember which shader profile you're working in, and how the data flows
			float3 worldNormal;// Set through SurfaceShader Magic
		};
		
		
		// Simplified refraction, similar to the built-in one
		float4 calculateRefraction(in float3 worldNormal, in float4 projection){
			float2 normal = worldNormal.xz;
			float2 uvOffset = normal * _Refraction * _GrabTexture_TexelSize.xy;
			uvOffset *= projection.z;// More refraction, further away from the camera? 
			
			float4 refractionCoordinates = projection;// I really can't remember why I needed a copy... Probably debugging or something
            refractionCoordinates.xy = projection.xy + uvOffset;
            
			return tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(refractionCoordinates));
		}		

		void surf (Input IN, inout SurfaceOutput o) {
			o.Emission = calculateRefraction(IN.worldNormal, IN.projection);
		}
		
		
		//=====================================================================
		// VERTEX STUFF FROM HERE ON DOWN. STUFF IS THE TECHNICAL TERM AND I WILL STICK TO IT.
		// FUN FACT: This is only placed below the surface shader, instead of above,
		// to emphasize the connection between the input struct and the surface shader more obvious		
		
		// Calculate Projection for Refraction Grabpass Texture Lookup:
		float4 calcRefrProj(in float4 vertexPos){		
			// calculate the position of this vertex on screen, as usual:
			float4 vertScreenPos = mul(UNITY_MATRIX_MVP, vertexPos);
			
			// On D3D when AA is used, the main texture  scene depth texture
			// will come out in different vertical orientations.
			// So flip sampling of the texture when that is the case (main texture
			// texel size will have negative Y).
			#if UNITY_UV_STARTS_AT_TOP
				if (_GrabTexture_TexelSize.y < 0)float scale = -1.0;
				else float scale = 1.0;
			#else
				float scale = 1.0;
			#endif
			vertScreenPos.y *= scale;
			
			return (vertScreenPos * 0.5) + (0.5 * vertScreenPos.w);// Apply Bias and Scale Matrix to move to [0,1]: What do we call it now, Texture Space? It's similar to Normalized Device space I guess
		}	
		
		void UvStuff(inout appdata_full v, out Input o){
			o.projection = calcRefrProj(v.vertex);
		}
		
		
		ENDCG
	}
}

Obviously, I’m still learning about this stuff too, so if anyone spots big problems, I’m very interested to hear about those. If you want to see a more compact version, definitely check out the shaders in the Standard Assets/Glass Reflection (Pro Only) package.