SHARE
TWEET

Vtastek water shader

a guest Aug 26th, 2016 3,061 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // XE Water.fx
  2. // MGE XE 0.9
  3. // Water functions (included by XE Main)
  4.  
  5.  
  6. //------------------------------------------------------------
  7. // Samplers, clamping mode
  8.  
  9. sampler sampReflect = sampler_state { texture = <tex0>; minfilter = linear; magfilter = linear; mipfilter = none; addressu = clamp; addressv = clamp; };
  10. sampler sampRefract = sampler_state { texture = <tex2>; minfilter = linear; magfilter = linear; mipfilter = none; addressu = clamp; addressv = clamp; };
  11.  
  12. //------------------------------------------------------------
  13. // Water constants
  14.  
  15. static const float kDistantZBias = 5e-6;
  16. static const float _lightfactor = 1 - pow(1 - SunVis, 2);
  17. static const float3 _depthcolor = _lightfactor * SunCol * float3(0.03, 0.04, 0.05) + (2 * SkyCol + FogCol2) * float3(0.094, 0.22, 0.19);
  18. static const float3 _SunCollf = SunCol * _lightfactor;
  19. static const float _windfactor = (length (WindVec) + 1.5) / 140;
  20. static const float waterlevel = world[3][2];
  21. static const float cauststr = 0.05 * alpharef * saturate(0.75 * _lightfactor + 0.35 * length(FogCol2));
  22.  
  23. shared texture tex4, tex5;
  24. shared float3 rippleOrigin;
  25. shared float waveHeight;
  26.  
  27. sampler sampRain = sampler_state { texture = <tex4>; minfilter = linear; magfilter = linear; mipfilter = linear; addressu = wrap; addressv = wrap; };
  28. sampler sampWave = sampler_state { texture = <tex5>; minfilter = linear; magfilter = linear; mipfilter = linear; bordercolor = 0x80808080; addressu = border; addressv = border; };
  29.  
  30. static const float waveTexResolution = 512;
  31. static const float waveTexWorldSize = waveTexResolution * 2.5;
  32. static const float waveTexRcpRes = 1.0 / (waveTexResolution-1);
  33. static const float playerWaveSize = 12.0 / waveTexWorldSize; // 12 world units radius
  34.  
  35. //------------------------------------------------------------
  36. // Static functions
  37.  
  38. float3 getFinalWaterNormal(float2 texcoord1, float2 texcoord2, float dist, float2 vertXY) : NORMAL
  39. {
  40.     // Calculate the W texture coordinate based on the time that has passed
  41.     float t = 0.4 * time;
  42.     float3 w1 = float3(texcoord1, t);
  43.     float3 w2 = float3(texcoord2, t);
  44.     float3 w3 = float3(texcoord2 * 0.5, t);
  45.    
  46.     // Blend together the normals from different sized areas of the same texture
  47.     float2 far_normal = tex3D(sampWater3d, w1).rg;
  48.     float2 close_normal = tex3D(sampWater3d, w2).rg;
  49.     close_normal += tex3D(sampWater3d, w3).rg;
  50.     close_normal *= 0.5;
  51.    
  52.    
  53.  
  54. #ifdef DYNAMIC_RIPPLES
  55.     // Add rain and player ripples
  56.     close_normal.rg += tex2D(sampRain, texcoord2).ba - 0.5;
  57.     close_normal.rg += tex2D(sampWave, (vertXY - rippleOrigin) / waveTexWorldSize).ba * 2 - 1;
  58. #endif
  59.  
  60.     float2 normal_R = 2 * lerp(close_normal, far_normal, saturate(dist / 8000)) - 1;
  61.     return normalize(float3(normal_R, 0.3));
  62. }
  63.  
  64. #ifndef FILTER_WATER_REFLECTION
  65.  
  66. float3 getProjectedReflection(float4 tex)
  67. {
  68.     return tex2Dproj(sampReflect, tex).rgb;
  69. }
  70.  
  71. #else
  72.  
  73. float3 getProjectedReflection(float4 tex)
  74. {
  75.     float4 radius = 0.006 * saturate(0.11 + tex.w/6000) * tex.w * float4(1, rcpres.y/rcpres.x, 0, 0);
  76.    
  77.     float3 reflected = tex2Dproj(sampReflect, tex);
  78.     reflected += tex2Dproj(sampReflect, tex + radius*float4(0.60, 0.10, 0, 0));
  79.     reflected += tex2Dproj(sampReflect, tex + radius*float4(0.30, -0.21, 0, 0));
  80.     reflected += tex2Dproj(sampReflect, tex + radius*float4(0.96, -0.03, 0, 0));
  81.     reflected += tex2Dproj(sampReflect, tex + radius*float4(-0.40, 0.06, 0, 0));
  82.     reflected += tex2Dproj(sampReflect, tex + radius*float4(-0.70, 0.18, 0, 0));
  83.     reflected /= 6.0;
  84.    
  85.     return reflected.rgb;
  86. }
  87.  
  88. #endif
  89.  
  90. //------------------------------------------------------------
  91. // Water shader
  92.  
  93. struct WaterVertOut
  94. {
  95.     float4 position : POSITION;
  96.     float4 pos : TEXCOORD0;
  97.     float4 texcoords : TEXCOORD1;
  98.     float4 screenpos : TEXCOORD2;
  99. #ifdef DYNAMIC_RIPPLES
  100.     float4 screenposclamp : TEXCOORD3;
  101. #endif
  102. };
  103.  
  104. #ifndef DYNAMIC_RIPPLES
  105.  
  106. WaterVertOut WaterVS (in float4 pos : POSITION)
  107. {
  108.     WaterVertOut OUT;
  109.  
  110.     // Add z bias to avoid fighting with MW ripples quads
  111.     OUT.pos = mul(pos, world);
  112.     OUT.pos.z -= 0.1;
  113.  
  114.     // Calculate various texture coordinates
  115.     OUT.texcoords.xy = OUT.pos.xy / 3900;
  116.     OUT.texcoords.zw = OUT.pos.xy / 527;
  117.  
  118.     OUT.position = mul(OUT.pos, view);
  119.     OUT.position = mul(OUT.position, proj);
  120.  
  121.     // Match bias in distant land projection
  122.     OUT.position.z *= 1.0 + kDistantZBias * step(nearViewRange, OUT.position.w);
  123.    
  124.     OUT.screenpos = float4(0.5 * (1 + rcpres) * OUT.position.w + float2(0.5, -0.5) * OUT.position.xy, OUT.position.zw);
  125.  
  126.     return OUT;
  127. }
  128.  
  129. #else
  130.  
  131. WaterVertOut WaterVS (in float4 pos : POSITION)
  132. {
  133.     WaterVertOut OUT;
  134.    
  135.     // Move to world space
  136.     OUT.pos = mul(pos, world);
  137.  
  138.     // Calculate various texture coordinates
  139.     OUT.texcoords.xy = OUT.pos.xy / 1950;
  140.     OUT.texcoords.zw = OUT.pos.xy / 258;
  141.  
  142.     // Apply vertex displacement
  143.     float t = 0.4 * time;
  144.     float height = tex3Dlod(sampWater3d, float4(OUT.pos.xy / 1104, t, 0)).a;
  145.     float height2 = tex3Dlod(sampWater3d, float4(OUT.pos.xy / 3900, t, 0)).a;
  146.     float dist = length(EyePos.xyz - OUT.pos.xyz);
  147.  
  148.     float addheight = waveHeight * (lerp(height, height2, saturate(dist/8000)) - 0.5) * saturate(1 - dist/6400) * saturate(dist/200);
  149.     OUT.pos.z += addheight;
  150.  
  151.     // Match bias in distant land projection
  152.     OUT.position = mul(OUT.pos, view);
  153.     OUT.position = mul(OUT.position, proj);
  154.     OUT.position.z *= 1.0 + kDistantZBias * step(nearViewRange, OUT.position.w);
  155.     OUT.screenpos = float4(0.5 * (1 + rcpres) * OUT.position.w + float2(0.5, -0.5) * OUT.position.xy, OUT.position.zw);
  156.  
  157.     // Clamp reflection point to be above surface
  158.     float4 clampedPos = OUT.pos - float4(0, 0, abs(addheight), 0);
  159.     clampedPos = mul(clampedPos, view);
  160.     clampedPos = mul(clampedPos, proj);
  161.     clampedPos.z *= 1.0 + kDistantZBias * step(nearViewRange, clampedPos.w);
  162.     OUT.screenposclamp = float4(0.5 * (1 + rcpres) * clampedPos.w + float2(0.5, -0.5) * clampedPos.xy, clampedPos.zw);
  163.    
  164.     return OUT;
  165. }
  166. #endif
  167.  
  168. float4 WaterPS(in WaterVertOut IN): COLOR0
  169. {
  170.     // Calculate eye vector
  171.     float3 EyeVec = IN.pos.xyz - EyePos.xyz;
  172.     float dist = length(EyeVec);
  173.     EyeVec /= dist;
  174.  
  175.     // Define fog
  176.     float4 fog = fogColour(EyeVec, dist);
  177.     float3 depthcolor = fogApply(_depthcolor, fog);
  178.     //float3 depthcolor = fogApply(exp(-float3(1.22, 1.2, 1.8)*1), fog); // + float3(0.169,0.346,0.52)*0.1;
  179.    
  180.     // Calculate water normal
  181.     float3 normal = getFinalWaterNormal(IN.texcoords.xy, IN.texcoords.zw, dist, IN.pos.xy);
  182.  
  183.     // Reflection/refraction pixel distortion factor, wind strength increases distortion
  184.     float2 reffactor = (_windfactor * dist + 0.1) * normal.xy;
  185.  
  186.     // Distort refraction dependent on depth
  187.     float4 newscrpos = IN.screenpos + float4(reffactor.yx, 0, 0);
  188.     float depth = max(0, tex2Dproj(sampDepth, newscrpos).r - IN.screenpos.w);
  189.  
  190.     // Refraction
  191.     float3 refracted = depthcolor;
  192.     float shorefactor = 0;
  193.     float2 aber = reflect(EyeVec, normal).xy;
  194.     float dpcop = 0;
  195.     float3 ssw = 0;
  196.     float depthscale2 = 0;
  197.     // Avoid sampling deep water
  198.     if(depth < 8000)
  199.     {
  200.         // Sample refraction texture
  201.         newscrpos = IN.screenpos + saturate(depth / 100) * float4(reffactor.yx, 0.0, 0.0);
  202.         refracted.r = tex2Dproj(sampRefract, newscrpos).r;
  203.         refracted.g = tex2Dproj(sampRefract, newscrpos - float4(aber * 0.04, 0.0, 0.0)).g;
  204.         refracted.b = tex2Dproj(sampRefract, newscrpos - float4(aber * 2 * 0.04, 0.0, 0.0)).b;
  205.         // Get distorted depth
  206.         depth = max(0, tex2Dproj(sampDepth, newscrpos).r - IN.screenpos.w);
  207.         depth /= dot(EyeVec, float3(view[0][2], view[1][2], view[2][2]));
  208.  
  209.         // Small scale shoreline animation
  210.         depth += 300 * (0.95 - normal.z);
  211.         ssw = saturate(((IN.pos.z+10) / waveHeight)) * float3(0.32,0.51,0.3);
  212.         float depthscale = saturate(exp(-depth / (1600)));
  213.         depthscale2 = saturate(exp(-depth / (3200)));
  214.        
  215.        
  216.         depthscale2 = (depthscale + ssw * 5);
  217.        
  218.         dpcop = depthscale;
  219.         shorefactor = pow(depthscale, 90);
  220.  
  221.         // Make transition between actual refraction image and depth color depending on water depth
  222.         refracted = lerp(depthcolor, refracted, 0.8 * depthscale + 0.2 * shorefactor);
  223.     }
  224.    
  225.     //return refracted.rgbr;
  226.     // Sample reflection texture
  227. #ifndef DYNAMIC_RIPPLES
  228.     float4 screenpos = IN.screenpos;
  229. #else
  230.     float4 screenpos = IN.screenposclamp;
  231. #endif
  232.     float3 reflected = getProjectedReflection(screenpos - float4(2.1 * reffactor.x, -abs(reffactor.y), 0, 0));
  233.  
  234.     // Dull reflection to avoid being too bright relative to sky,
  235.     // except for fading into an inscatter dominated horizon
  236.     reflected *= 1 - 0.16 * saturate(2 * fog.a);
  237.  
  238.     // Smooth out high frequencies at a distance
  239.     float3 adjustnormal = lerp(float3(0, 0, 0.1), normal, pow(saturate(1.05 * fog.a), 2));
  240.     adjustnormal = lerp(adjustnormal, float3(0, 0, 1.0), (1 + EyeVec.z) * (1 - saturate(1 / (dist / 1000 + 1))));
  241.  
  242.     // Fresnel equation determines reflection/refraction
  243.     float fresnel = dot(-EyeVec, pow(adjustnormal,4));
  244.     fresnel = 0.02 + pow(saturate(0.9988 - 0.38 * fresnel), 16);
  245.     //fresnel = 1 - 0.02 + pow((2*(fresnel-0.23 - 0.5)),5)*0.2 * -1.0;
  246.     //1 - 0.02 + (2*(x-0.23))^5 *0.2
  247.    
  248.     float lum = dot(float3(0.27, 0.54, 0.19), refracted.rgb);
  249.     float topbright = 1.0 - (1.0 - lum) * (1.0 - dpcop);
  250.  
  251.     //return depthscale2.xxxx;
  252.     float3 dark1 = float3(0.039,0.074,0.101);
  253.     float3 light1 = float3(0.13,0.18,0.16);
  254.     float3 dark2 = float3(0.01,0.08,0.16);
  255.     float3 light2 = float3(0.09,0.18,0.203)*6;
  256.     light2 = lerp(light2, 3.00, dpcop);
  257.    
  258.     float3 refracteddark  = lerp(dark1, light1, lum)*3;
  259.     float3 refractedlight = lerp(dark2, light2, dpcop);
  260.     refracteddark = saturate(refracteddark);
  261.     refractedlight = saturate(refractedlight); 
  262.     float3 tint = lerp(refracteddark, refractedlight, SunAmb * 0.13 + _SunCollf);
  263.     //return refracted.rgbr;
  264.     refracted *= tint;
  265.    
  266.     //refracted += ssw * refracted * 3.3;
  267.    
  268.     //return float4(refracted, 1);
  269.     //reflected = pow(reflected,1.2) * 1.33;
  270.     // float3 result = refracted * 1.1 +  saturate((pow(reflected,2) * 4 - 0.2) * fresnel);
  271.    
  272.     // float lum = dot(float3(0.27, 0.54, 0.19), result.rgb);
  273.  
  274.     // Mix with luminance to avoid oversaturated single channels
  275.     //reflected = saturate(lerp(lum, reflected, 0.8) - 0.3)  * 3 ;
  276.     refracted = pow(saturate(refracted), 2.2);
  277.     reflected = pow(saturate(reflected * 1.1), 2.2);
  278.    
  279.     float3 result = lerp(refracted, reflected, fresnel);
  280.     //float3 result = lerp(0, 1, fresnel);
  281.     result = exp( -1.0 / ( 2.72 * result + 0.08 ) );
  282.        
  283.     result = pow(result, 1/2.2);
  284.    
  285.     //return float4(refracted, 1);
  286.     //float3 result = lerp(refracted, reflected * 0.98, 0.02 + 1.1 * saturate(fresnel + 0.3 * (pow(reflected, 3) * 3 - 0.8)));
  287.     //return fresnel.xxxx;
  288.     //float lum = dot(float3(0.27, 0.54, 0.19), result.rgb);
  289.     //result = result * (1.0 - exp(lum * 8.0))/(lum);
  290.      
  291.  
  292.     // + saturate(1-fresnel) * SkyCol * 0.05);
  293.     //return float4(result, 1);
  294.     //result = max(0.0, result - 0.004);
  295.     //result = (result * (6.2 * result + 0.5)) / (result * (6.2 * result + 1.7) + 0.06);
  296.    
  297.     // Specular lighting
  298.     // This should use Blinn-Phong, but it doesn't work so well for area lights like the sun
  299.     // Instead multiply and saturate to widen a Phong specular lobe which better simulates an area light
  300.     float vdotr = dot(-EyeVec, reflect(-SunPos, normal));
  301.     vdotr = saturate(1.0025 * vdotr);
  302.     float3 spec = _SunCollf * (pow(vdotr, 170)); //+ 0.07 * pow(vdotr, 4));
  303.     //spec = 1 / (1 + spec*16);
  304.     result += spec * 2 * fog.a;
  305.    
  306.    
  307.  
  308.     // Smooth transition at shore line
  309.     result = lerp(result, refracted, shorefactor * fog.a);
  310.    
  311.     // Note that both refraction and reflection textures were rendered fogged already
  312.     result = fogApply(result.rgb, fog);
  313.     return float4(result.rgb, 1);
  314. }
  315.  
  316. float4 UnderwaterPS(in WaterVertOut IN): COLOR0
  317. {
  318.     // Calculate eye vector
  319.     float3 EyeVec = IN.pos.xyz - EyePos.xyz;
  320.     float dist = length(EyeVec);
  321.     EyeVec /= dist;
  322.  
  323.     // Special case fog, avoid fog offset
  324.     float fog = saturate(exp(-dist / 4096));
  325.    
  326.     // Calculate water normal
  327.     float3 normal = -getFinalWaterNormal(IN.texcoords.xy, IN.texcoords.zw, dist, IN.pos.xy);
  328.  
  329.     // Reflection / refraction pixel distortion factor, wind strength increases distortion
  330.     float2 reffactor = 2 * (_windfactor * dist + 0.1) * normal.xy;
  331.  
  332.     // Distort refraction
  333.     float4 newscrpos = IN.screenpos + float4(2 * -reffactor.xy, 0, 0);
  334.     float3 refracted = tex2Dproj(sampRefract, newscrpos).rgb;
  335.     refracted = lerp(FogCol2, refracted, exp(-dist / 500));
  336.  
  337.     // Sample reflection texture
  338.     float3 reflected = getProjectedReflection(IN.screenpos - float4(2.1 * reffactor.x, -abs(reffactor.y), 0, 0));
  339.  
  340.     // Fresnel equation, including total internal reflection
  341.     float fresnel = pow(saturate(1.12 - 0.65 * dot(-EyeVec, normal)), 8);
  342.     float3 result = lerp(refracted, reflected, fresnel);
  343.  
  344.     // Sun refraction
  345.     float refractsun = dot(-EyeVec, normalize(-SunPos + normal));
  346.     float3 spec = _SunCollf * pow(refractsun, 6) * fog;
  347.  
  348.     return float4(result + spec, 1);
  349. }
  350.  
  351. //------------------------------------------------------------
  352. // Caustics post-process
  353.  
  354. DeferredOut CausticsVS(float4 pos : POSITION, float2 tex : TEXCOORD0, float2 ndc : TEXCOORD1)
  355. {
  356.     DeferredOut OUT;
  357.    
  358.     // Fix D3D9 half pixel offset    
  359.     OUT.pos = float4(ndc.x - rcpres.x, ndc.y + rcpres.y, 0, 1);
  360.     OUT.tex = float4(tex, 0, 0);
  361.    
  362.     // World space reconstruction vector
  363.     OUT.eye = float3(view[0][2], view[1][2], view[2][2]);
  364.     OUT.eye += (ndc.x / proj[0][0]) * float3(view[0][0], view[1][0], view[2][0]);
  365.     OUT.eye += (ndc.y / proj[1][1]) * float3(view[0][1], view[1][1], view[2][1]);
  366.     return OUT;
  367. }
  368.  
  369. float4 CausticsPS(DeferredOut IN) : COLOR0
  370. {
  371.     float3 c = tex2Dlod(sampBaseTex, IN.tex).rgb;
  372.     float depth = tex2Dlod(sampDepthPoint, IN.tex).r;
  373.     float fog = fogMWScalar(depth);
  374.  
  375.     clip(nearViewRange - depth);
  376.  
  377.     float3 uwpos = EyePos + IN.eye * depth;
  378.     uwpos.z -= waterlevel;
  379.     clip(-uwpos.z);
  380.  
  381.     float3 sunray = uwpos - SunVec * (uwpos.z / SunVec.z);
  382.     float caust = cauststr * 5 * tex3D(sampWater3d, float3(sunray.xy / 1104, 0.4 * time)).b;
  383.     caust *= saturate(125 / depth * min(fwidth(sunray.x), fwidth(sunray.y)));
  384.     c *= 1 + (caust - 0.3) * saturate(exp(uwpos.z / 400)) * saturate(uwpos.z / -30) * fog;
  385.    
  386.     return float4(c, 1);
  387. }
  388.  
  389.  
  390. //------------------------------------------------------------
  391. // Dynamic waves
  392.  
  393. struct WaveVertOut
  394. {
  395.     float4 pos : POSITION;
  396.     float2 texcoord : TEXCOORD0;
  397. };
  398.  
  399. WaveVertOut WaveVS(float4 pos : POSITION, float2 texcoord : TEXCOORD0)
  400. {
  401.     WaveVertOut OUT;
  402.     OUT.pos = mul(pos, proj);
  403.     OUT.texcoord = texcoord;
  404.     return OUT;
  405. }
  406.  
  407. //------------------------------------------------------------
  408.  
  409. float4 WaveStepPS(float2 Tex : TEXCOORD0) : COLOR0
  410. {
  411.     float4 c = 2 * tex2D(sampRain, Tex) - 1;
  412.     float4 ret = {0, c.r, 0, 0};
  413.    
  414.     float4 n = {
  415.         tex2D(sampRain, Tex + float2(waveTexRcpRes, 0)).r,
  416.         tex2D(sampRain, Tex + float2(-waveTexRcpRes, 0)).r,
  417.         tex2D(sampRain, Tex + float2(0, waveTexRcpRes)).r,
  418.         tex2D(sampRain, Tex + float2(0, -waveTexRcpRes)).r
  419.     };
  420.     float4 n2 = {
  421.         tex2D(sampRain, Tex + float2(1.5 * waveTexRcpRes, 0)).r,
  422.         tex2D(sampRain, Tex + float2(-1.5 * waveTexRcpRes, 0)).r,
  423.         tex2D(sampRain, Tex + float2(0, 1.5 * waveTexRcpRes)).r,
  424.         tex2D(sampRain, Tex + float2(0, -1.5 * waveTexRcpRes)).r
  425.     };
  426.    
  427.     // expand normal
  428.     n = 2 * n - 1;
  429.    
  430.     // dampened discrete two-dimensional wave equation
  431.     // red channel: u(t)
  432.     // green channel: u(t - 1)
  433.     // u(t + 1) = (1 - udamp) * u(t) + a * (nsum - 4 * u(t)) + (1 - vdamp) * (u(t) - u(t - 1))
  434.     //        = a * nsum + ((2 - udamp - vdamp) - 4 * a) * u(t) - (1 - vdamp) * u(t - 1);
  435.     float nsum = n.x + n.y + n.z + n.w;
  436.     ret.r = 0.14 * nsum + (1.96 - 0.56) * c.r - 0.98 * c.g;
  437.    
  438.     // calculate normal map
  439.     ret.ba = 2 * (n.xy - n.zw) + (n2.xy - n2.zw);
  440.     ret = 0.5 * ret + 0.5;
  441.    
  442.     return ret;
  443. }
  444.  
  445. float4 PlayerWavePS(float2 Tex : TEXCOORD0) : COLOR0
  446. {
  447.     float4 ret = tex2D(sampRain, Tex);
  448.     float wavesize = (1.0 + 0.055 * sin(16 * time) + 0.065 * sin(12.87645 * time)) * playerWaveSize;
  449.     ret.rg *= saturate(2 * abs(length(Tex - rippleOrigin) / wavesize - 1));
  450.     return ret;
  451. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top