Advertisement
Guest User

OceanBRDFShader

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