- Home /
Question by
Jackv949 · Sep 25, 2017 at 08:26 AM ·
2dshadersshader programmingwaterreflection
Grabpass 2D water reflection, UV issue
Hi there, I'm trying to get a 2D water effect working by modifying the standard assets glass refractive shader to support reflections.
So far it is almost working, except it is reflecting around the centre of the screen (which makes sense considering I am just flipping the texture on line 77 "o.uvscreen.xy = (float2(o.vertex.x, o.vertex.y -scale) + o.vertex.w) 0.5"). This is an issue since the reflections move when the camera moves. Is there any way I can get the texture to reflect around the surface of the water instead?
Example:
Shader code:
// Per pixel bumped refraction.
// Uses a normal map to distort the image behind, and
// an additional texture to tint the color.
Shader "Custom/Water" {
Properties {
_MainTex ("Tint Texture", 2D) = "white" {}
_Color ("Tint Color", Color) = (1,1,1,1)
_BumpAmt ("Distortion", range (0,128)) = 10
_BumpMap ("Normalmap", 2D) = "bump" {}
_SpeedX ("Speed X", Float) = 1.0
_SpeedY ("Speed Y", Float) = 1.0
_Reflection("Reflection Intensity", range(0, 1.0)) = 1.0
}
Category {
// We must be transparent, so other objects are drawn before this one.
Tags { "Queue"="Transparent" "RenderType"="Opaque" }
ZWrite Off
SubShader {
// 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 multi_compile_fog
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord: TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
float4 uvgrab : TEXCOORD0;
float2 uvbump : TEXCOORD1;
float2 uvmain : TEXCOORD2;
float4 uvscreen : TEXCOORD3;
UNITY_FOG_COORDS(3)
};
float _BumpAmt;
float4 _BumpMap_ST;
float4 _MainTex_ST;
float _SpeedX;
float _SpeedY;
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.vertex.xy, _BumpMap );
o.uvmain = TRANSFORM_TEX( v.texcoord, _MainTex );
o.uvscreen.xy = (float2(o.vertex.x, o.vertex.y * -scale) + o.vertex.w) * 0.5;
o.uvscreen.zw = o.vertex.zw;
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
sampler2D _GrabTexture;
float4 _GrabTexture_TexelSize;
sampler2D _BumpMap;
sampler2D _MainTex;
float4 _Color;
float _Reflection;
half4 frag (v2f i) : SV_Target
{
fixed2 offsetUV = fixed2(_SpeedX * _Time.y, _SpeedY * _Time.y);
// calculate perturbed coordinates
half2 bump = UnpackNormal(tex2D( _BumpMap, i.uvbump + offsetUV )).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;
//Refraction texture
half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
//Tint
col *= tex2D(_MainTex, i.uvmain);
col *= _Color;
//Reflection Texture
col += tex2Dproj(_GrabTexture, UNITY_PROJ_COORD(i.uvscreen)) * _Reflection;
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
// ------------------------------------------------------------------
// Fallback for older cards and Unity non-Pro
SubShader {
Blend DstColor Zero
Pass {
Name "BASE"
SetTexture [_MainTex] { combine texture }
}
}
}
}
example.gif
(167.4 kB)
Comment