Advertisement
Guest User

OceanWhiteCaps.shader

a guest
Aug 5th, 2014
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.84 KB | None | 0 0
  1. // Real-time Realistic Ocean Lighting using Seamless Transitions from Geometry to BRDF
  2. // Copyright (c) 2009 INRIA
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions
  7. // are met:
  8. // 1. Redistributions of source code must retain the above copyright
  9. // notice, this list of conditions and the following disclaimer.
  10. // 2. Redistributions in binary form must reproduce the above copyright
  11. // notice, this list of conditions and the following disclaimer in the
  12. // documentation and/or other materials provided with the distribution.
  13. // 3. Neither the name of the copyright holders nor the names of its
  14. // contributors may be used to endorse or promote products derived from
  15. // this software without specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  21. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  27. // THE POSSIBILITY OF SUCH DAMAGE.
  28. //
  29. // Author: Eric Bruneton
  30. //
  31. // Modified and ported to Unity by Justin hawkins 04/06/2013
  32.  
  33. Shader "Ocean/OceanWhiteCaps"
  34. {
  35. SubShader
  36. {
  37.  
  38. Pass
  39. {
  40. Tags { "RenderType"="Opaque" }
  41.  
  42. CGPROGRAM
  43. #include "UnityCG.cginc"
  44. #pragma target 4.0
  45. #pragma vertex vert
  46. #pragma fragment frag
  47. #include "Atmosphere.cginc"
  48.  
  49. uniform sampler2D _Map0, _Map1, _Map2, _Map3, _Map4;
  50. uniform sampler2D _SkyMap, _Foam0, _Foam1;
  51. uniform sampler3D _Variance;
  52. sampler2D_float _CameraDepthTexture; // Edgeblend Stuff
  53. uniform float4 _GridSizes, _Choppyness;
  54. uniform float3 _SeaColor;
  55. uniform float _MaxLod, _LodFadeDist, _WhiteCapStr;
  56.  
  57. struct v2f
  58. {
  59. float4 pos : SV_POSITION;
  60. float3 worldPos : TEXCOORD;
  61. };
  62.  
  63. v2f vert(appdata_base v)
  64. {
  65. float3 worldPos = mul(_Object2World, v.vertex).xyz;
  66.  
  67. float dist = clamp(distance(_WorldSpaceCameraPos.xyz, worldPos) / _LodFadeDist, 0.0, 1.0);
  68. float lod = _MaxLod * dist;
  69. //lod = 0.0;
  70.  
  71. float2 uv = worldPos.xz;
  72.  
  73. v.vertex.y += tex2Dlod(_Map0, float4(uv/_GridSizes.x, 0, lod)).x;
  74. v.vertex.y += tex2Dlod(_Map0, float4(uv/_GridSizes.y, 0, lod)).y;
  75. v.vertex.y += tex2Dlod(_Map0, float4(uv/_GridSizes.z, 0, lod)).z;
  76. v.vertex.y += tex2Dlod(_Map0, float4(uv/_GridSizes.w, 0, lod)).w;
  77.  
  78. v.vertex.xz += tex2Dlod(_Map3, float4(uv/_GridSizes.x, 0, lod)).xy * _Choppyness.x;
  79. v.vertex.xz += tex2Dlod(_Map3, float4(uv/_GridSizes.y, 0, lod)).zw * _Choppyness.y;
  80. v.vertex.xz += tex2Dlod(_Map4, float4(uv/_GridSizes.z, 0, lod)).xy * _Choppyness.z;
  81. v.vertex.xz += tex2Dlod(_Map4, float4(uv/_GridSizes.w, 0, lod)).zw * _Choppyness.w;
  82.  
  83. v2f OUT;
  84. OUT.worldPos = mul(_Object2World, v.vertex).xyz;
  85. OUT.pos = mul(UNITY_MATRIX_MVP, v.vertex);
  86. return OUT;
  87. }
  88.  
  89. float meanFresnel(float cosThetaV, float sigmaV)
  90. {
  91. return pow(1.0 - cosThetaV, 5.0 * exp(-2.69 * sigmaV)) / (1.0 + 22.7 * pow(sigmaV, 1.5));
  92. }
  93.  
  94. // V, N in world space
  95. float MeanFresnel(float3 V, float3 N, float2 sigmaSq)
  96. {
  97. float2 v = V.xz; // view direction in wind space
  98. float2 t = v * v / (1.0 - V.y * V.y); // cos^2 and sin^2 of view direction
  99. float sigmaV2 = dot(t, sigmaSq); // slope variance in view direction
  100. return meanFresnel(dot(V, N), sqrt(sigmaV2));
  101. }
  102.  
  103. // assumes x>0
  104. float erfc(float x)
  105. {
  106. return 2.0 * exp(-x * x) / (2.319 * x + sqrt(4.0 + 1.52 * x * x));
  107. }
  108.  
  109. float erf(float x)
  110. {
  111. float a = 0.140012;
  112. float x2 = x*x;
  113. float ax2 = a*x2;
  114. return sign(x) * sqrt( 1.0 - exp(-x2*(4.0/M_PI + ax2)/(1.0 + ax2)) );
  115. }
  116.  
  117. float Lambda(float cosTheta, float sigmaSq)
  118. {
  119. float v = cosTheta / sqrt((1.0 - cosTheta * cosTheta) * (2.0 * sigmaSq));
  120. return max(0.0, (exp(-v * v) - v * sqrt(M_PI) * erfc(v)) / (2.0 * v * sqrt(M_PI)));
  121. //return (exp(-v * v)) / (2.0 * v * sqrt(M_PI)); // approximate, faster formula
  122. }
  123.  
  124. // L, V, N, Tx, Ty in world space
  125. float ReflectedSunRadiance(float3 L, float3 V, float3 N, float3 Tx, float3 Ty, float2 sigmaSq)
  126. {
  127. float3 H = normalize(L + V);
  128. float zetax = dot(H, Tx) / dot(H, N);
  129. float zetay = dot(H, Ty) / dot(H, N);
  130.  
  131. float zL = dot(L, N); // cos of source zenith angle
  132. float zV = dot(V, N); // cos of receiver zenith angle
  133. float zH = dot(H, N); // cos of facet normal zenith angle
  134. float zH2 = zH * zH;
  135.  
  136. float p = exp(-0.5 * (zetax * zetax / sigmaSq.x + zetay * zetay / sigmaSq.y)) / (2.0 * M_PI * sqrt(sigmaSq.x * sigmaSq.y));
  137.  
  138. float tanV = atan2(dot(V, Ty), dot(V, Tx));
  139. float cosV2 = 1.0 / (1.0 + tanV * tanV);
  140. float sigmaV2 = sigmaSq.x * cosV2 + sigmaSq.y * (1.0 - cosV2);
  141.  
  142. float tanL = atan2(dot(L, Ty), dot(L, Tx));
  143. float cosL2 = 1.0 / (1.0 + tanL * tanL);
  144. float sigmaL2 = sigmaSq.x * cosL2 + sigmaSq.y * (1.0 - cosL2);
  145.  
  146. float fresnel = 0.02 + 0.98 * pow(1.0 - dot(V, H), 5.0);
  147.  
  148. zL = max(zL, 0.01);
  149. zV = max(zV, 0.01);
  150.  
  151. return fresnel * p / ((1.0 + Lambda(zL, sigmaL2) + Lambda(zV, sigmaV2)) * zV * zH2 * zH2 * 4.0);
  152.  
  153. }
  154.  
  155. // V, N, Tx, Ty in world space
  156. float2 U(float2 zeta, float3 V, float3 N, float3 Tx, float3 Ty)
  157. {
  158. float3 f = normalize(float3(-zeta, 1.0)); // tangent space
  159. float3 F = f.x * Tx + f.y * Ty + f.z * N; // world space
  160. float3 R = 2.0 * dot(F, V) * F - V;
  161. return R.xz / (1.0 + R.y);
  162. }
  163.  
  164. // V, N, Tx, Ty in world space;
  165. float3 MeanSkyRadiance(float3 V, float3 N, float3 Tx, float3 Ty, float2 sigmaSq)
  166. {
  167. float4 result;
  168.  
  169. const float eps = 0.001;
  170. float2 u0 = U(float2(0,0), V, N, Tx, Ty);
  171. float2 dux = 2.0 * (U(float2(eps, 0.0), V, N, Tx, Ty) - u0) / eps * sqrt(sigmaSq.x);
  172. float2 duy = 2.0 * (U(float2(0.0, eps), V, N, Tx, Ty) - u0) / eps * sqrt(sigmaSq.y);
  173.  
  174. result = tex2D(_SkyMap, u0 * (0.5 / 1.1) + 0.5, dux * (0.5 / 1.1), duy * (0.5 / 1.1));
  175.  
  176. //if texture2DLod and texture2DGrad are not defined, you can use this (no filtering):
  177. //result = tex2D(_SkyMap, u0 * (0.5 / 1.1) + 0.5);
  178.  
  179. return result.rgb;
  180. }
  181.  
  182. float whitecapCoverage(float epsilon, float mu, float sigma2) {
  183. return 0.5*erf((0.5*sqrt(2.0)*(epsilon-mu)*(1.0/sqrt(sigma2)))) + 0.5;
  184. }
  185.  
  186. float4 frag(v2f IN) : COLOR
  187. {
  188.  
  189. float2 uv = IN.worldPos.xz;
  190.  
  191. float2 slope = float2(0,0);
  192. slope += tex2D(_Map1, uv/_GridSizes.x).xy;
  193. slope += tex2D(_Map1, uv/_GridSizes.y).zw;
  194. slope += tex2D(_Map2, uv/_GridSizes.z).xy;
  195. slope += tex2D(_Map2, uv/_GridSizes.w).zw;
  196.  
  197. float3 V = normalize(_WorldSpaceCameraPos-IN.worldPos);
  198.  
  199. float3 N = normalize(float3(-slope.x, 1.0, -slope.y));
  200.  
  201. if (dot(V, N) < 0.0) {
  202. N = reflect(N, V); // reflects backfacing normals
  203. }
  204.  
  205. float Jxx, Jxy, Jyy, Jyx;
  206.  
  207. Jxx = ddx(uv.x);
  208. Jxy = ddy(uv.x);
  209. Jyx = ddx(uv.y);
  210. Jyy = ddy(uv.y);
  211. float A = Jxx * Jxx + Jyx * Jyx;
  212. float B = Jxx * Jxy + Jyx * Jyy;
  213. float C = Jxy * Jxy + Jyy * Jyy;
  214. const float SCALE = 10.0;
  215. float ua = pow(A / SCALE, 0.25);
  216. float ub = 0.5 + 0.5 * B / sqrt(A * C);
  217. float uc = pow(C / SCALE, 0.25);
  218. float2 sigmaSq = tex3D(_Variance, float3(ua, ub, uc)).xy;
  219.  
  220. sigmaSq = max(sigmaSq, 2e-5);
  221.  
  222. float3 Ty = normalize(float3(0.0, N.z, -N.y));
  223. float3 Tx = cross(Ty, N);
  224.  
  225. float fresnel = 0.02 + 0.98 * MeanFresnel(V, N, sigmaSq);
  226.  
  227. float3 Lsun = SunRadiance(_WorldSpaceCameraPos);
  228. float3 Esky = SkyIrradiance(_WorldSpaceCameraPos);
  229.  
  230. float3 col = float3(0,0,0);
  231.  
  232. col += ReflectedSunRadiance(SUN_DIR, V, N, Tx, Ty, sigmaSq) * Lsun;
  233.  
  234. col += MeanSkyRadiance(V, N, Tx, Ty, sigmaSq) * fresnel;
  235.  
  236. float3 Lsea = _SeaColor * Esky / M_PI;
  237. col += Lsea * (1.0 - fresnel);
  238.  
  239. // extract mean and variance of the jacobian matrix determinant
  240. float2 jm1 = tex2D(_Foam0, uv/_GridSizes.x).xy;
  241. float2 jm2 = tex2D(_Foam0, uv/_GridSizes.y).zw;
  242. float2 jm3 = tex2D(_Foam1, uv/_GridSizes.z).xy;
  243. float2 jm4 = tex2D(_Foam1, uv/_GridSizes.w).zw;
  244. float2 jm = jm1+jm2+jm3+jm4;
  245. float jSigma2 = max(jm.y - (jm1.x*jm1.x + jm2.x*jm2.x + jm3.x*jm3.x + jm4.x*jm4.x), 0.0);
  246.  
  247. // get coverage
  248. float W = whitecapCoverage(_WhiteCapStr,jm.x,jSigma2);
  249.  
  250. // compute and add whitecap radiance
  251. float3 l = (Lsun * (max(dot(N, SUN_DIR), 0.0)) + Esky) / M_PI;
  252. float3 R_ftot = float3(W * l * 0.4);
  253. col += R_ftot;
  254.  
  255.  
  256. // EDGE BLEND
  257. half4 edgeBlendFactors = half4(1.0, 0.0, 0.0, 0.0);
  258.  
  259. half depth = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(IN.screenPos));
  260. depth = LinearEyeDepth(depth);
  261. edgeBlendFactors = saturate(_InvFadeParemeter * (depth-IN.screenPos.w));
  262. edgeBlendFactors.y = 1.0-edgeBlendFactors.y;
  263. col.rgb += (edgeBlendFactors.y + saturate(i.viewInterpolator.w));
  264.  
  265. return float4(hdr(col),1.0);
  266. }
  267.  
  268. ENDCG
  269.  
  270. }
  271. }
  272. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement