- Home /
Refraction Shader Problem
Ok soo... I think my Refraction Shader that is a modified version of the unity Pro Glass Refraction Shader does something wrong here.
in the shader there are descriptions that say it will grab the screen behind that object and then it will use the normal map of this object to refract that.
but it seems it grabs also the objects infront of that plane I use in my scene here.
but I only wanted that it just bends the back of that object... is there a way to fix this?
in the pictures you see a dodecahedron and a few units behind that there is the plane with the refraction shader on it that always faces the players camera. pictures are from farthest player position to closest position.
shader code is after the pictures!
// Per pixel bumped refraction.
// Uses a normal map to distort the image behind, and
// an additional texture to tint the color.
Shader "TEST_Shader/Refraction" {
Properties {
_BumpAmt ("Distortion", range (0,128)) = 10
_BumpMap ("Normalmap", 2D) = "bump" {}
}
Category {
// We must be transparent, so other objects are drawn before this one.
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "ForceNoShadowCasting"="True" "RenderType"="Transparent" }
SubShader {
Fog { Mode Off }
// This pass grabs the screen behind the object into a texture.
// We can access the result in the next pass as _GrabTexture
GrabPass
{
Name "BASE"
Tags { "LightMode" = "Always" }
}
// Main pass: Take the texture grabbed above and use the bumpmap to perturb it
// on to the screen
Pass
{
Name "BASE"
Tags { "LightMode" = "Always" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord: TEXCOORD0;
};
struct v2f {
float4 vertex : POSITION;
float4 uvgrab : TEXCOORD0;
float2 uvbump : TEXCOORD1;
};
float _BumpAmt;
float4 _BumpMap_ST;
v2f vert (appdata_t v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
#if UNITY_UV_STARTS_AT_TOP
float scale = -1.0;
#else
float scale = 1.0;
#endif
o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
o.uvgrab.zw = o.vertex.zw;
o.uvbump = TRANSFORM_TEX( v.texcoord, _BumpMap );
return o;
}
sampler2D _GrabTexture;
float4 _GrabTexture_TexelSize;
sampler2D _BumpMap;
half4 frag( v2f i ) : COLOR
{
// calculate perturbed coordinates
half2 bump = UnpackNormal(tex2D( _BumpMap, i.uvbump )).rg; // we could optimize this by just reading the x & y without reconstructing the Z
float2 offset = bump * _BumpAmt * _GrabTexture_TexelSize.xy;
i.uvgrab.xy = offset * i.uvgrab.z + i.uvgrab.xy;
half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
return col;
}
ENDCG
}
}
// ------------------------------------------------------------------
// Fallback for older cards and Unity non-Pro
SubShader {
Blend DstColor Zero
Pass {
Name "BASE"
SetTexture [_MainTex] { combine texture }
}
}
}
}
really no one any idea? please I just want to know is it possible and maybe how?
Answer by Kibsgaard · Feb 23, 2014 at 12:32 AM
I think behind is very misleading. It is more like before.
"GrabPass { }
will grab current screen contents into a texture. " GrabPass
That is, it will grab the entire screen at its current state. So anything rendered before:
"Tags { "Queue" = "Transparent" }
"
will be visible in the _GrabTexture
.
If there are any specific objects you don't want to be visible in the refraction, you could move them to after Transparent
in the render queue (might decrease performance slightly).
aaa. Ok that makes sense. Hmmm I have there an idea... but I think i dont know how to do this... I could maybe use the z depth to eli$$anonymous$$ate everything inbetween the camera and the object.... Soo I would need to know on which distance the object is or so...
can you please help me with that?
That could probably work.
You can maybe get some inspiration from here: http://chrismflynn.com/?p=147
it seems I cannot add a ZTest to the grabpass... so in other words my idea with the depth testing in the shader will not work because It will grab always everything that is rendered before the Transparent part... even if I would be able to block the geometry infront of the refraction I would probably end up with the skybox blending in.... Or am I wrong?
The Skybox's alpha is 0 as default, so that shouldn't be a problem. (You can change the color and transparancy of it on the camera)
You shuold be able to calculate the z-depth in the vertex shader and then pass it to the fragment shader, like Chris Flynn does.
Your answer
Follow this Question
Related Questions
Light Refraction, Glass, and Marbles 2 Answers
Glass Refraction Shader 2 Answers
Refractive glass shader 1 Answer
Need help rendering beer glass in unity... 0 Answers
Creating realistic lantern (glass) 0 Answers