I am not sure, but maybe like this? Code (csharp): Shader "New Shader" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG // Grab the screen behind the object into _GrabTexture, using default values GrabPass { } // Render the object with the texture generated above. Pass { SetTexture [_GrabTexture] { combine texture } } } FallBack "Diffuse" }
i also want to know. i know that we can sample the grab texture use _GrabTexture. the key point is calculate the grab texture uv from the the screenPos uvgrab = screenPos.xy * scale + offset but i don't know how to calculate the scale and offset. anyone know more?
i get it now. float2 grabTexcoord = IN.screenPos.xy / IN.screenPos.w; grabTexcoord.y = 1.0f - grabTexcoord.y; half4 background = tex2D(_GrabTexture, grabTexcoord); then you can get the background color;
old thread but whatever, the question is wether "it's possible to use GrabPass Texture in unity 3.0 surface shader and How to ?" and that question hasn't been answered, In this thread and others people seem to say yes, and then give an example of a shader that has both a grabpass and a surface shader in it, but NOT a surface shader that uses a grabpass texture. From my experience it seems that a grabpasstexture can only be accessed in a pass, and a surface shader can't be in a pass. So I don't see how a grabpass can be used in a surface shader. Please correct me if I'm wrong, because I'd love to know how make it work. Urgh, writing shaders in itself is fun and all, but not how badly documented it all is, which makes it more trial and error than anything. (which makes it all extremely frustrating)
Luckily, this actually IS documented, and I confirm that it works. So you can sample _GrabTexture, like a regular texture (Although you'll probably want to use tex2Dproj) It's like it's science
This shader uses a grab texture and applies it at the same screen position (for learning purposes) Code (csharp): Shader "Custom/GrabShader" { SubShader { // Draw ourselves after all opaque geometry Tags { "Queue" = "Transparent" } // Grab the screen behind the object into _MyGrabTexture GrabPass { "_MyGrabTexture" } CGPROGRAM #pragma surface surf Lambert vertex:vert #pragma debug sampler2D _MainTex; sampler2D _MyGrabTexture; struct Input { float4 grabUV; }; void vert (inout appdata_full v, out Input o) { float4 hpos = mul (UNITY_MATRIX_MVP, v.vertex); o.grabUV = ComputeGrabScreenPos(hpos); } void surf (Input IN, inout SurfaceOutput o) { o.Albedo = tex2Dproj( _MyGrabTexture, UNITY_PROJ_COORD(IN.grabUV)); } ENDCG } } P.S. The documentation does not explain how to combine surface shaders with grab pass. The quoted paragraph only says that GrabPass might be also used without parameter...
I have ofcourse already read the documentation, but what you're saying isn't a surface shader that uses a grabpass texture, which is what I was talking about: Exactly I could swear that's exactly what I've tried. hm, I'll go see what I did wrong
Besides showing that grabpass can be used without a parameter, it also hints at the fact that the resulting texture is available to further passes. Surface shaders create their own passes, that's why you can still use the grabpass texture in a surface shader. Perhaps that could be clearer in the documentation. The ability to create functions used in the vertex shader, with surface shaders, which you need to calculate the uv coordinates, isn't mentioned all that much either, I guess.
Hi, I'm also having a bit of trouble with this. I tried to grab the current screen content using GrabPass and then apply the resulting _GrabTexture to a plane object. Using proper texture coordinates and no other color/lighting should render the plane completely transparent, right? The following works as expected: Code (csharp): GrabPass {} Pass { SetTexture [_GrabTexture] { combine texture } } The result of the above code is this (which is correct, as you only see the objects in the background): However, when I try to reconstruct this exact behaviour using a SurfaceShader, I have no success in rendering the _GrabTexture fully transparent, which is quite strange in my opinion: Code (csharp): GrabPass {} CGPROGRAM #pragma surface surf Lambert vertex:vert alpha sampler2D _GrabTexture; struct Input { float4 grabUV; }; void vert (inout appdata_full v, out Input o) { float4 hpos = mul (UNITY_MATRIX_MVP, v.vertex); o.grabUV = ComputeGrabScreenPos(hpos); } void surf (Input IN, inout SurfaceOutput o) { o.Albedo = tex2Dproj(_GrabTexture, UNITY_PROJ_COORD(IN.grabUV));; o.Alpha = 1.0; } ENDCG Using this snippet gives me the following result, which is obviously incorrect as the plane is clearly visible: My approach is almost identical to the above example from BIG BUG. I think the only difference is, he's grabing the screen content into a named texture while I'm using the _GrabTexture directly. Nevertheless using his shader gives me the exact same result. I'm puzzled. How do you properly use GrabPass for later use inside a surface shader? I'd really appreciate any hints. Attached you find a unitypackage that illustrates the issue. cheers
Output it to o.Emission instead. The scene that has been rendered onto the plane was already lit, so you want to avoid the lighting calculations performed on o.Albedo.
Yeah the original code shows a transparent but still lit material. If you don't need any lighting calculation you could use a regular shader instead of a surface shader as this would be more efficient.