Skip to content

Instantly share code, notes, and snippets.

@ruccho
Last active June 8, 2019 15:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ruccho/e5061f71b3af6499658f5a32210d329d to your computer and use it in GitHub Desktop.
Save ruccho/e5061f71b3af6499658f5a32210d329d to your computer and use it in GitHub Desktop.
2D simple water with reflection for Unity. Create empty GameObject with SpriteRenderer and attach the material and the script.
Shader "Effect/Water-R"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_NormalA("Normal A", 2D) = "" {}
_NormalAAmount("Normal A Amount", Range(0,100)) = 50
_NormalASpeed("Normal A Speed", Float) = 1.0
_NormalB("Normal B", 2D) = "" {}
_NormalBAmount("Normal B Amount", Range(0,100)) = 50
_NormalBSpeed("Normal B Speed", Float) = 1.0
_WaterHeight("Water Height", Float) = 0.5
_WaterWidth("Water Width", Float) = 0.5
_BGBlend("Background Blend", Range(0,1)) = 0.2
_Transparency("Transparency", Range(0,1)) = 0.2
_Multiplier("Multiplier", Color) = (0.2, 0.3, 0.33,1.0)
_Addend("Addend", Color) = (0.07,0.14,0.19,0.0)
_WaveSize("Wave Size in Pixel", Float) = 5.0
_WavePosFreq("Wave Frequency by Position", Float) = 146.08
_WaveTimeFreq("Wave Frequency by Time", Float) = 44.74
_WaveDistance("Wave Distance in Pixel", Float) = 128
_SurfaceColor("Surface Color", Color) = (0.14,0.21,0.37, 1.0)
_SurfaceWidth("Surface Width in Pixel", Float) = 2
_FadeDistance("Fade Distance in Pixel", Float) = 128
}
SubShader
{
Tags {
"Queue" = "Transparent"
"RenderType"="Transparent"
}
GrabPass{}
Cull Off
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
sampler2D _GrabTexture;
sampler2D _NormalA;
float4 _NormalA_ST;
float _NormalAAmount;
float _NormalASpeed;
sampler2D _NormalB;
float4 _NormalB_ST;
float _NormalBAmount;
float _NormalBSpeed;
float4 _GrabTexture_TexelSize;
float _WaterHeight;
float _WaterWidth;
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float3 pos : TEXCOORD0;
float2 uv : TEXCOORD1;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _BGBlend;
float _Transparency;
float4 _Multiplier;
float4 _Addend;
float _WaveSize;
float _WavePosFreq;
float _WaveTimeFreq;
float _WaveDistance;
float4 _SurfaceColor;
float _SurfaceWidth;
float _FadeDistance;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.pos = o.vertex.xyw;
o.pos.y *= _ProjectionParams.x;
o.uv = v.uv;
o.uv.y = o.uv.y * -1.0 + 1.0;
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
float verticalPixel2UV(float pixel, float screenHeight)
{
return pixel / screenHeight / _WaterHeight;
}
fixed4 frag (v2f i) : SV_Target
{
float screenHeight = _GrabTexture_TexelSize.w;
float screenWidth = _GrabTexture_TexelSize.z;
half2 uv_sc = i.pos.xy / i.pos.z * 0.5 + 0.5;
half2 uv = uv_sc;
half2 uvo;
uv.y += i.uv.y * _WaterHeight * 2;
float distUV = verticalPixel2UV(_WaveDistance, screenHeight);
uv.x += floor(sin(_Time * _WaveTimeFreq + -sqrt(i.uv.y * _WaterHeight) * _WavePosFreq ) * _WaveSize * max(0, i.uv.y * -(1/ distUV) + 1)) / screenWidth;
half2 offset;
offset.x = _Time;
offset.y = _Time;
float2 uv_normal_base = i.uv * half2(_WaterWidth, _WaterHeight) / half2(screenHeight, screenWidth) * 500;
fixed2 normalTexA = floor(UnpackNormal(tex2D(_NormalA, frac(uv_normal_base * _NormalA_ST.xy - offset * _NormalASpeed))).rg * _NormalAAmount);
normalTexA.r /= screenWidth;
normalTexA.g /= screenHeight;
fixed2 normalTexB = floor(UnpackNormal(tex2D(_NormalB, frac(uv_normal_base * _NormalB_ST.xy + offset * _NormalBSpeed))).rg * _NormalBAmount);
normalTexB.r /= screenWidth;
normalTexB.g /= screenHeight;
half2 normal = normalTexA + normalTexB;
uv += normal;
half2 normalDec = floor(normal * half2(screenWidth, screenHeight) * 0.2);
normalDec.r /= screenWidth;
normalDec.g /= screenHeight;
uv_sc += normalDec;
fixed4 bg = tex2D(_GrabTexture, uv_sc);
bg.a = 1;
float fadeDistUV = verticalPixel2UV(_FadeDistance, screenHeight);
float fade = saturate((1 - uv.y) * (1/fadeDistUV));
float surfaceDistUV = verticalPixel2UV(_SurfaceWidth, screenHeight);
float surface = step(i.uv.y, surfaceDistUV);
fixed4 col = tex2D(_GrabTexture, uv);
col *= fade;
col.a = (1 - _Transparency) + (col.r + col.g + col.b) / 3 * _Transparency;
col = lerp(col, bg, _BGBlend);
col *= _Multiplier;
col += _Addend;
col *= 1 - surface;
col += surface * _SurfaceColor;
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
using UnityEngine;
[RequireComponent(typeof(SpriteRenderer))]
public class Water_R : MonoBehaviour {
private SpriteRenderer SpriteRef;
private float TempWaterWidth;
private float TempWaterHeight;
[SerializeField]
private Camera MainCamera;
void Start () {
SpriteRef = GetComponent<SpriteRenderer>();
if (!MainCamera) MainCamera = Camera.main;
if (MainCamera) UpdateWaterHeight();
}
void Update ()
{
if (!MainCamera) MainCamera = Camera.main;
if(MainCamera)UpdateWaterHeight();
}
private void UpdateWaterHeight()
{
if (!SpriteRef) return;
float offset = MainCamera.WorldToViewportPoint(new Vector2(0,transform.position.y + transform.lossyScale.y)).y;
float orient = MainCamera.WorldToViewportPoint(new Vector2(0, transform.position.y)).y;
float size = offset - orient;
if (size != TempWaterHeight) {
TempWaterHeight = size;
SpriteRef.material.SetFloat("_WaterHeight", TempWaterHeight);
}
offset = MainCamera.WorldToViewportPoint(new Vector2(transform.position.x + transform.lossyScale.x,0)).x;
orient = MainCamera.WorldToViewportPoint(new Vector2(transform.position.x,0)).x;
size = offset - orient;
if (size != TempWaterWidth)
{
TempWaterWidth = size;
SpriteRef.material.SetFloat("_WaterWidth", TempWaterWidth);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment