Features:
- Efficient shader optimized for mobile devices
- Realtime refraction of anything on opposite side of water plane
- Sin blend between 2 normal maps for smooth normal animation
- UV Panning normal maps
- Reflection Cubemap
- Renders in Opaque queue with no expensive transparency cost
- Separate settings for fog over and under water
- Separate settings for far clip planes over and under water (quality)
- Controls for Transparency, RefractionFactor, ReflectionFactor, RenderTextureSize, Tiling, FogSettings, etc
Here's some more screenshots and a video: (Sorry for bad quality)
And here's the relevent vertex and surface shaders (in CG):
void vert (inout appdata_full v, out Input o) { fixed4 epos = mul(UNITY_MATRIX_MV, v.vertex ); o.eyeZ = -epos.z; o.ref = mul( _TextureMatrix, epos ); o.viewDir = ObjSpaceViewDir( v.vertex ); } void surf (Input IN, inout SurfaceOutput o) { //Normal map with uv pan based on time: fixed4 speed = _Speed * _Time; fixed2 UV_Pan0 = IN.uv_Normal + speed.xy; fixed2 UV_Pan1 = IN.uv_Normal + speed.yx; fixed4 normA = fixed4(UnpackNormal( tex2D(_Normal,UV_Pan0.xy)).xyz, 1.0 ); fixed4 normB = fixed4(UnpackNormal( tex2D(_Normal2,UV_Pan1.xy)).xyz, 1.0); fixed4 norm = lerp( normA, normB, (sin( _Time.x * _SinNormalSpeed ) * 0.8 + 1) * 0.5 ); norm = normalize( norm ); //Refract uvs of refractionTexture in xy fixed4 uv2 = IN.ref; fixed2 refractUVs =_RefractionFactor * norm.xy; uv2.xy += refractUVs; //calculate fresnel factor for hiding refraction at sheer angle: fixed fresnel = saturate( dot( normalize( IN.viewDir ), norm.xzy )); fresnel = 1.0 - pow( fresnel, _FresnelFactor ) + 0.5; //lookup projected refractionTexture: half4 refr = _Color * tex2Dproj( _RefractionTexture, UNITY_PROJ_COORD(uv2) ); //lookup reflected cubemap texture: half4 refl = _ReflectionFactor * texCUBE( _ReflectionCube, WorldReflectionVector( IN, norm)); //linear fog falloff half fogAmount = (IN.eyeZ - _FogStart) / _FogEnd; //lerp between reflection and refraction, using fresnel: half4 color = lerp( refl, refr, saturate( _Transparency * fresnel) ); //lerp btwn color and fog based on fogamount color = lerp( color, saturate(_SurfaceFogColor + norm.x), saturate(fogAmount) ); //unlit so assign to emission o.Emission = color; o.Albedo = 0.0; o.Gloss = 0.0; o.Alpha = 0.0; o.Specular = 0.0; }
-K
hi Katlan,
ReplyDeleteI tried to find this shader as you said you would upload it on Asset Store, but it is not there yet. I am working on a fish tank based project and I am dying to get the screen-space reflection-refraction working on mobile platforms. I am no CG coder, but I think this is what I exactly needed. Can you please share this with me or at least tell me how I would go about it? I also bought hard surface shaders standard, which has the screen-space reflection-refraction shader, but it is unbelievably slow even on iPhone5. Please help.
Regards,
Rohan
Hey Rohan, I'm just back to blogging, so I apologize for not responding earlier. I have not posted to the Asset Store (turns out, it's a lot of work!), but will consider posting the files here. I prefer not to, as I like to encourage people to do some work on their own. In this case, all the relevant code is above, so with a bit of work, you can recreate the files yourself.
DeleteDo you have any ideas on how to prevent refraction of objects above the water ? I am not using reflection or fog.
ReplyDeleteIf you set _RefractionFactor to 1 it should turn off Refraction completely. If you want to do it on a per-object basis, it's a bit more complex and you'd lose some performance. You'd have to make the shader a transparent shader, render only what you want refracted into _RefractionTexture, then render the water plane, with all refracted objects off, and all unrefracted objects on.
DeleteUnfortunately, shaders are somewhat single-use. They excel when they're efficient. But with efficiency, you lose flexibility. So my shader would need some tweaking to get per-layer/object refraction.