Hi there,
I’ve been changing and improving the ocean shader (I posted on that thread too), but I’m no shader expert. It has to run for mobile so it has to be as fast and simple as possible. This is what I have so far and I’m sure it can be hugely improved for mobile. It runs at about 30fps on a Samsung galaxy 2 and about 7 fps on a nexus one. It has a few #if defined so I can add/remove some of the effects but it makes no performance improvements at all.
So any shader experts wants to give it a try?
(I also attach a picture of what the shader generates on screen of my samsung galaxy s2 ![]()
// Upgrade NOTE: now shader work on mobile
Shader "Mobile/OceanReflectionRefraction"
{
Properties
{
_SurfaceColor ("SurfaceColor", Color) = (1,1,1,1)
_WaterColor ("WaterColor", Color) = (1,1,1,1)
_Refraction ("Refraction (RGB)", 2D) = "white" {}
_Reflection ("Reflection (RGB)", 2D) = "white" {}
_Fresnel ("Fresnel (A) ", 2D) = "gray" {}
_Bump ("Bump (RGB)", 2D) = "bump" {}
_Foam ("Foam (RGB)", 2D) = "white" {}
_Size ("Size", Vector) = (1, 1, 1, 1)
_SunDir ("SunDir", Vector) = (0.3, -0.6, -1, 0)
_UseSpecular("Use Specular", Float) = 1.0
}
SubShader {
Tags {
"RenderType"="Opaque"
}
Lighting Off
Pass {
CGPROGRAM
#pragma multi_compile USE_REFRACTION USE_REFLECTION
#pragma exclude_renderers xbox360
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 pos : SV_POSITION;
float4 projTexCoord : TEXCOORD0;
float2 bumpTexCoord : TEXCOORD1;
float3 viewDir : TEXCOORD2;
float3 objSpaceNormal : TEXCOORD3;
float3 lightDir : TEXCOORD4;
float2 foamStrengthAndDistance : TEXCOORD5;
};
float4 _Size;
float4 _SunDir;
v2f vert (appdata_tan v)
{
v2f o;
o.bumpTexCoord.xy = v.vertex.xz/float2(_Size.x, _Size.z)*10;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.foamStrengthAndDistance.x = v.tangent.w;
o.foamStrengthAndDistance.y = clamp(o.pos.z, 0, 1.0);
float4 projSource = float4(v.vertex.x, 0.0, v.vertex.z, 1.0);
float4 tmpProj = mul( UNITY_MATRIX_MVP, projSource);
o.projTexCoord = tmpProj;
float3 objSpaceViewDir = ObjSpaceViewDir(v.vertex);
float3 binormal = cross( normalize(v.normal), normalize(v.tangent.xyz) );
float3x3 rotation = float3x3( v.tangent.xyz, binormal, v.normal );
o.objSpaceNormal = v.normal;
o.viewDir = normalize(mul(rotation, objSpaceViewDir));
o.lightDir = normalize(mul(rotation, float3(_SunDir.xyz)));
return o;
}
uniform fixed _UseSpecular;
sampler2D _Refraction;
sampler2D _Reflection;
sampler2D _Fresnel;
sampler2D _Bump;
sampler2D _Foam;
half4 _SurfaceColor;
half4 _WaterColor;
half4 frag (v2f i) : COLOR
{
// calculate the bump of the waves/water, i'm sure there is a better way to do it on the vertex section
half4 buv = half4(i.bumpTexCoord.x + _Time.x * 0.03, i.bumpTexCoord.y + _SinTime.x * 0.2, i.bumpTexCoord.x + _Time.y * 0.04, i.bumpTexCoord.y + _SinTime.y * 0.5);
half3 tangentNormal0 = (tex2D(_Bump, buv.xy).rgb * 2.0) - 1;
half3 tangentNormal1 = (tex2D(_Bump, buv.zw).rgb * 2.0) - 1;
half3 tangentNormal = normalize(tangentNormal0 + tangentNormal1);
float2 projTexCoord = 0.5 * i.projTexCoord.xy * float2(1, _ProjectionParams.x) / i.projTexCoord.w + float2(0.5, 0.5);
half4 result = half4(0, 0, 0, 1);
float2 bumpSampleOffset = i.objSpaceNormal.xz * 0.05 + tangentNormal.xy * 0.05;
#if defined(USE_REFLECTION)
half3 reflection = tex2D(_Reflection, projTexCoord.xy + bumpSampleOffset).rgb * _SurfaceColor.rgb;
#endif
#if defined(USE_REFRACTION)
half3 refraction = tex2D(_Refraction, projTexCoord.xy + bumpSampleOffset).rgb * _WaterColor.rgb;
#endif
// depending on the strengh (cresh of wave?) generate foam and the slowly fade it out
float foamStrength = i.foamStrengthAndDistance.x * 1.8;
half4 foam = clamp(tex2D(_Foam, i.bumpTexCoord.xy * 1.0) - 0.5, 0.0, 1.0) * foamStrength;
if (_UseSpecular > 0) {
float3 halfVec = normalize(i.viewDir - i.lightDir);
float specular = pow(max(dot(halfVec, tangentNormal.xyz), 0.0), 250.0);
#if defined(USE_REFLECTION) defined(USE_REFRACTION)
float fresnelLookup = dot(tangentNormal, i.viewDir);
float bias = 0.06;
float power = 4.0;
float fresnelTerm = bias + (1.0-bias)*pow(1.0 - fresnelLookup, power);
result.rgb = lerp(refraction, reflection, fresnelTerm) + clamp(foam.r, 0.0, 1.0) + specular;
#elif defined(USE_REFLECTION)
result.rgb = reflection + clamp(foam.r, 0.0, 1.0) + specular;
#elif defined(USE_REFRACTION)
result.rgb = refraction + clamp(foam.r, 0.0, 1.0) + specular;
#else
result.rgb = _WaterColor.rgb + clamp(foam.r, 0.0, 1.0) + specular;
#endif
} else {
#if defined(USE_REFLECTION) defined(USE_REFRACTION)
float fresnelLookup = dot(tangentNormal, i.viewDir);
float bias = 0.06;
float power = 4.0;
float fresnelTerm = bias + (1.0-bias)*pow(1.0 - fresnelLookup, power);
result.rgb = lerp(refraction, reflection, fresnelTerm) + clamp(foam.r, 0.0, 1.0);
#elif defined(USE_REFLECTION)
result.rgb = reflection + clamp(foam.r, 0.0, 1.0);
#elif defined(USE_REFRACTION)
result.rgb = refraction + clamp(foam.r, 0.0, 1.0);
#else
result.rgb = _WaterColor.rgb + clamp(foam.r, 0.0, 1.0);
#endif
}
// result.rgb = result.rgb;
// result.a = 1.0;
return result;
}
ENDCG
}
}
}
