Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // XE Water.fx
- // MGE XE 0.11
- // Water functions (included by XE Main)
- // Enhanced Water Shader 2.1 Green-Blue
- // compatibility with MGE XE 0.11.0
- // removed random function for better performance
- // removed windfactor from addheight to prevent repetitive moving pattern in wave behavior
- // Requires: Exponential fog, Dynamic ripples set to 40
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------
- // Samplers, clamping mode
- sampler sampReflect = sampler_state { texture = <tex0>; minfilter = linear; magfilter = linear; mipfilter = none; addressu = clamp; addressv = clamp; };
- sampler sampRefract = sampler_state { texture = <tex2>; minfilter = linear; magfilter = linear; mipfilter = none; addressu = clamp; addressv = clamp; };
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------
- // Water constants
- static const float kDistantZBias = 5e-6;
- static const float _lightfactor = 1 - pow(1 - SunVis, 2);
- static const float3 _SunCollf = SunCol * _lightfactor;
- static const float _windfactor = (length (WindVec) + 1.5) / 120;
- static const float waterlevel = world[3][2];
- static const float cauststr = 0.05 * alpharef * saturate(0.75 * _lightfactor + 0.35 * length(FogCol2));
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------
- // Tweakables
- static const float watcolstr = 0.5; // water color brightness; default: 0.5
- static const float outlinestr = 0.08; // depth contour intensity; default: 0.08
- static const float regwavemult = 1; // controls height of regular water waves; default: 1
- static const float regwavewindmult = 30; // higher values increase wind influence on regular wave height; default: 30
- static const float heightwavemult = 2.5; // controls height of swell-like waves; default: 2.5
- static const float heightwavewindmult = 60; // higher values reduce height waves in inclement weather; default: 60
- static const float edgefoamstr = 1; // shore foam day strength; default: 1
- static const float edgefoamstrn = 0.3; // shore foam night and inclement weather strength; default: 0.3
- static const float wavefoamstrn = 0.795; // stormy weather wave foam strength; default: 0.795
- static const float swellwavefoamstr = 2; // surge-like foam strength; enable SWELL_FOAM to see this; default: 2
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------
- shared texture tex4, tex5;
- shared float3 rippleOrigin;
- shared float waveHeight;
- sampler sampRain = sampler_state { texture = <tex4>; minfilter = linear; magfilter = linear; mipfilter = linear; addressu = wrap; addressv = wrap; };
- sampler sampWave = sampler_state { texture = <tex5>; minfilter = linear; magfilter = linear; mipfilter = linear; bordercolor = 0; addressu = border; addressv = border; };
- static const float waveTexResolution = 512;
- static const float waveTexWorldSize = waveTexResolution * 2.5;
- static const float waveTexRcpRes = 1.0 / waveTexResolution;
- static const float playerWaveSize = 12.0 / waveTexWorldSize; // 12 world units radius
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------
- // Plug & Play features
- // Enables foam on water edges and on wave tips in stormy weather.
- #define FOAM
- // Enables swell-like height waves, monodirectional
- #define HEIGHT_WAVES
- // Enables waves in far normals
- // #define FAR_WAVE_NORMALS
- // Enables sewer waves in Vivec and Molag Mar, fps costly
- // #define SEWER_WAVES
- // Enables depth color, may cause visual artifacts with cells not currently loaded and cells not processed by distant land generator
- #define DEPTHCOLOR
- // wip, enables whitecap foam on swell waves for a surge-like effect
- // #define SWELL_FOAM
- // wip, currently not functional
- // #define SWELL_WAVE_NORMALS
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------
- // Static functions
- #ifdef SEWER_WAVES
- // Variation of harlanrm's Vivec and Molag Mar sewer waves, ported by abot, optimizations by vtastek
- // Sewer locations
- static const float2 wLoc[70] =
- {
- // Vivec
- { 19160, -86825}, { 46500, -81930}, { 31475, -104345}, { 32165, -76700}, { 19160, -81900}, { 20260, -80775}, { 20300, -87915}, { 24125, -80775},
- { 24225, -87915}, { 25275, -86700}, { 25275, -81850}, { 25550, -95230}, { 25550, -91390}, { 25550, -88840}, { 25550, -84940}, { 26300, -81750},
- { 26300, -77825}, { 26630, -89955}, { 26650, -96365}, { 26700, -83850}, { 27185, -90260}, { 27625, -82800}, { 27635, -76700}, { 31180, -96925},
- { 31200, -103770}, { 31540, -83850}, { 31615, -96365}, { 31765, -90260}, { 31895, -89955}, { 32150, -82800}, { 32675, -95020}, { 32675, -91785},
- { 32675, -88690}, { 32675, -85300}, { 32975, -95365}, { 32975, -91190}, { 32975, -89110}, { 32975, -84720}, { 33450, -81635}, { 33450, -77945},
- { 34095, -96365}, { 34120, -90260}, { 34175, -104345}, { 34480, -83850}, { 34585, -89955}, { 34640, -96925}, { 34695, -103770}, { 38500, -89955},
- { 38965, -96365}, { 38980, -83850}, { 39060, -90260}, { 40100, -95300}, { 40100, -91395}, { 40100, -88790}, { 40100, -84900}, { 40400, -86900},
- { 40400, -81955}, { 41350, -87915}, { 41475, -80775}, { 45300, -87915}, { 45480, -80775}, { 46500, -86790},
- // Molag Mar
- { 107090, -63820}, { 114215, -59905}, { 113110, -64890}, { 107090, -59875}, { 108085, -58800}, { 108110, -64890}, { 113170, -58800}, { 114215, -63780}
- };
- #endif
- float3 getFinalWaterNormal(float2 texcoord1, float2 texcoord2, float dist, float2 vertXY) : NORMAL
- {
- // Calculate the W texture coordinate based on the time that has passed
- float t = 0.315 * time;
- float3 far = float3(texcoord1 * 0.5, t * 0.5);
- float3 close1 = float3(texcoord2, t);
- float3 close2 = float3(texcoord1, t * 0.6);
- // Blend together the normals from different sized areas of the same texture
- float2 far_normal = tex3D(sampWater3d, far * 3).rg;
- far_normal += tex3D(sampWater3d, far).rg;
- far_normal *= 0.5;
- float2 close_normal = tex3D(sampWater3d, close1).rg;
- close_normal += tex3D(sampWater3d, close2).rg;
- close_normal *= 0.5;
- #ifdef DYNAMIC_RIPPLES
- // Blend normals from rain and player ripples
- close_normal.rg += tex2Dlod(sampRain, float4(texcoord2, 0, 0)).ba;
- close_normal.rg += tex2Dlod(sampWave, float4((vertXY - rippleOrigin) / waveTexWorldSize, 0, 0)).ba;
- #endif
- #ifdef FAR_WAVE_NORMALS
- //Big waves headed towards ghost gate, originally by harnlarnm
- float2 bwave = sin(fmod(sqrt(pow(length(vertXY-20000),2)+pow(length(vertXY-40000),2)),6144)/(6144/6.283185307) + time)/16;
- far_normal += bwave;
- #endif
- #ifdef SWELL_WAVE_NORMALS
- // wip, does not work properly, don't use
- float2 swellwave = sin(-vertXY/256 + 1.2 * time)/8;
- close_normal += swellwave;
- #endif
- #ifdef SEWER_WAVES
- //Add wave effect for each sewer location
- float d;
- float2 sewnorm = 0;
- for (int i=0; i<70; i++)
- {
- d = length(vertXY - wLoc[i]);
- sewnorm += sin(fmod(d,128)/20.371832716 - (time*1.2)) / max((d*d)/20480,4);
- }
- float interiorb = (SunCol > 0.003) ? 1 : 0;
- if(dist<7200)
- close_normal.rg += interiorb * sewnorm;
- #endif
- float2 normal_R = 2 * lerp(close_normal, far_normal, saturate(dist/11000)) - 1;
- return normalize(float3(normal_R, 0.295));
- }
- #ifndef FILTER_WATER_REFLECTION
- float3 getProjectedReflection(float4 tex)
- {
- return tex2Dproj(sampReflect, tex).rgb;
- }
- #else
- float3 getProjectedReflection(float4 tex)
- {
- float4 radius = 0.006 * saturate(0.11 + tex.w/6000) * tex.w * float4(1, rcpres.y/rcpres.x, 0, 0);
- float3 reflected = tex2Dproj(sampReflect, tex);
- reflected += tex2Dproj(sampReflect, tex + radius*float4(0.60, 0.10, 0, 0));
- reflected += tex2Dproj(sampReflect, tex + radius*float4(0.30, -0.21, 0, 0));
- reflected += tex2Dproj(sampReflect, tex + radius*float4(0.96, -0.03, 0, 0));
- reflected += tex2Dproj(sampReflect, tex + radius*float4(-0.40, 0.06, 0, 0));
- reflected += tex2Dproj(sampReflect, tex + radius*float4(-0.70, 0.18, 0, 0));
- reflected /= 6.0;
- return reflected.rgb;
- }
- #endif
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------
- // Water shader
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------
- // Dynamic waves
- struct WaveVertOut
- {
- float4 pos : POSITION;
- float2 texcoord : TEXCOORD0;
- };
- WaveVertOut WaveVS(float4 pos : POSITION, float2 texcoord : TEXCOORD0)
- {
- WaveVertOut OUT;
- OUT.pos = mul(pos, proj);
- OUT.texcoord = texcoord;
- return OUT;
- }
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------
- float4 WaveStepPS(float2 tex : TEXCOORD0) : COLOR0
- {
- // Texture content is now float16 in range [-1, 1]
- float4 tc = float4(tex, 0, 0);
- float4 c = tex2Dlod(sampRain, tc);
- float4 ret = {0, c.r, 0, 0};
- float4 n = {
- tex2D(sampRain, tc + float4(waveTexRcpRes, 0, 0, 0)).r,
- tex2D(sampRain, tc + float4(-waveTexRcpRes, 0, 0, 0)).r,
- tex2D(sampRain, tc + float4(0, waveTexRcpRes, 0, 0)).r,
- tex2D(sampRain, tc + float4(0, -waveTexRcpRes, 0, 0)).r
- };
- float4 n2 = {
- tex2D(sampRain, tc + float4(1.5 * waveTexRcpRes, 0, 0, 0)).r,
- tex2D(sampRain, tc + float4(-1.5 * waveTexRcpRes, 0, 0, 0)).r,
- tex2D(sampRain, tc + float4(0, 1.5 * waveTexRcpRes, 0, 0)).r,
- tex2D(sampRain, tc + float4(0, -1.5 * waveTexRcpRes, 0, 0)).r
- };
- // dampened discrete two-dimensional wave equation
- // red channel: u(t)
- // green channel: u(t - 1)
- // u(t + 1) = (1 - udamp) * u(t) + a * (nsum - 4 * u(t)) + (1 - vdamp) * (u(t) - u(t - 1))
- // = a * nsum + ((2 - udamp - vdamp) - 4 * a) * u(t) - (1 - vdamp) * u(t - 1);
- float nsum = n.x + n.y + n.z + n.w;
- ret.r = 0.14 * nsum + (1.96 - 0.56) * c.r - 0.98 * c.g;
- // calculate normal map
- ret.ba = 2 * (n.xy - n.zw) + 0.5 * (n2.xy - n2.zw);
- return ret;
- }
- float4 PlayerWavePS(float2 tex : TEXCOORD0) : COLOR0
- {
- float4 ret = tex2Dlod(sampRain, float4(tex, 0, 0));
- float wavesize = (1.0 + 0.055 * sin(16 * time) + 0.065 * sin(12.87645 * time)) * playerWaveSize;
- float displace = saturate(2 * abs(length(tex - rippleOrigin) / wavesize - 1));
- ret.rg = lerp(-1, ret.rg, displace);
- return ret;
- }
- struct WaterVertOut
- {
- float4 position : POSITION;
- float4 pos : TEXCOORD0;
- float4 texcoords : TEXCOORD1;
- float4 screenpos : TEXCOORD2;
- #ifdef DYNAMIC_RIPPLES
- float4 screenposclamp : TEXCOORD3;
- #endif
- };
- #ifndef DYNAMIC_RIPPLES
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------
- WaterVertOut WaterVS (in float4 pos : POSITION)
- {
- WaterVertOut OUT;
- // Add z bias to avoid fighting with MW ripples quads
- OUT.pos = mul(pos, world);
- OUT.pos.z -= 0.1;
- // Calculate various texture coordinates
- OUT.texcoords.xy = OUT.pos.xy / 2900;
- OUT.texcoords.zw = OUT.pos.xy / 427;
- OUT.position = mul(OUT.pos, view);
- OUT.position = mul(OUT.position, proj);
- // Match bias in distant land projection
- OUT.position.z *= 1.0 + kDistantZBias * step(nearViewRange, OUT.position.w);
- OUT.screenpos = float4(0.5 * (1 + rcpres) * OUT.position.w + float2(0.5, -0.5) * OUT.position.xy, OUT.position.zw);
- return OUT;
- }
- #else
- WaterVertOut WaterVS (in float4 pos : POSITION)
- {
- WaterVertOut OUT;
- // Move to world space
- OUT.pos = mul(pos, world);
- // Calculate various texture coordinates
- OUT.texcoords.xy = OUT.pos.xy / 2600;
- OUT.texcoords.zw = OUT.pos.xy / 440;
- // Apply vertex displacement
- float t = 0.325 * time;
- float height = tex3Dlod(sampWater3d, float4(OUT.pos.xy / 860, t, 0)).a;
- float height2 = tex3Dlod(sampWater3d, float4(OUT.pos.xy / 2800, t, 0)).a;
- float dist = length(EyePos.xyz - OUT.pos.xyz);
- float addheight = waveHeight * (lerp(height, height2, saturate(dist/8000)) - 0.5) * saturate(1 - dist/6400) * saturate(dist/200);
- addheight += (0.5 + regwavewindmult * 0.04) * lerp(height, height2, waveHeight);
- // Fade out wave height with distance to prevent flickering
- addheight = lerp(-1, addheight, fogMWScalar(dist*2));
- addheight *= regwavemult;
- OUT.pos.z += addheight;
- #ifdef HEIGHT_WAVES
- // Decrease height waves in inclement weather to keep peak fix intact
- float wdecrease = (heightwavemult - heightwavewindmult * _windfactor);
- float2 swell = wdecrease * waveHeight * (((sin(-OUT.pos.xy/256 + 1.75 * time)/8) + (sin(2.5 * -OUT.pos.xy/256 + 2.2 * time)/8) + (sin(3 * -OUT.pos.xy/256 + 1.4 * time)/8) + (sin(4.5 * -OUT.pos.xy/256 + 3 * time)/8))/4);
- OUT.pos.z += swell;
- #endif
- #ifdef HEIGHT_WAVES
- // Lower water plane to avoid peaking under
- OUT.pos.z += -(9 + heightwavemult + regwavemult + (0.5 * (addheight + swell)));
- #else
- // Lower water plane to avoid peaking under
- OUT.pos.z += -(7 + heightwavemult + regwavemult + (0.25 * addheight));
- #endif
- // Raise water plane to avoid peaking above
- // Waterlevel is 1.5 units wrong
- float wjump = step(EyePos.z - waterlevel + 1.5, 0.5);
- OUT.pos.z += wjump * 20;
- // Match bias in distant land projection
- OUT.position = mul(OUT.pos, view);
- OUT.position = mul(OUT.position, proj);
- OUT.position.z *= 1.0 + kDistantZBias * step(nearViewRange, OUT.position.w);
- OUT.screenpos = float4(0.5 * (1 + rcpres) * OUT.position.w + float2(0.5, -0.5) * OUT.position.xy, OUT.position.zw);
- // Clamp reflection point to be above surface
- float4 clampedPos = OUT.pos - float4(0, 0, abs(addheight), 0);
- clampedPos = mul(clampedPos, view);
- clampedPos = mul(clampedPos, proj);
- clampedPos.z *= 1.0 + kDistantZBias * step(nearViewRange, clampedPos.w);
- OUT.screenposclamp = float4(0.5 * (1 + rcpres) * clampedPos.w + float2(0.5, -0.5) * clampedPos.xy, clampedPos.zw);
- return OUT;
- }
- #endif
- float4 WaterPS(in WaterVertOut IN): COLOR0
- {
- #ifndef DYNAMIC_RIPPLES
- float4 screenpos = IN.screenpos;
- #else
- float4 screenpos = IN.screenposclamp;
- #endif
- // Calculate eye vector
- float3 EyeVec = IN.pos.xyz - EyePos.xyz;
- float dist = length(EyeVec);
- EyeVec /= dist;
- // Calculate water normal
- float3 normal = getFinalWaterNormal(IN.texcoords.xy, IN.texcoords.zw, dist * 0.65, IN.pos.xy);
- // Reflection/refraction pixel distortion factor, wind strength increases distortion
- float2 reffactor = 0.5 * (((_windfactor) * dist + 0.1) * normal.xy);
- // Distort refraction dependent on depth
- float4 newscrpos = IN.screenpos + float4(reffactor.yx, 0, 0);
- float depth = max(0, tex2Dproj(sampDepth, newscrpos).r - IN.screenpos.w);
- float wavedepth = max(0, tex2Dproj(sampDepth, newscrpos).r - IN.screenpos.w);
- // Define fog
- float4 fog = fogColour(EyeVec, dist);
- // Water color
- float3 green = float3(0.09, 0.22, 0.17);
- float3 blue = float3(0.07,0.13,0.29);
- float3 visgreen = float3(SunVis * 0.15, 0.4, SunVis * 0.3);
- float3 visblue = float3(0.1, SunVis * 0.15, 0.35);
- float3 gradient1 = lerp(green, visblue, SkyCol);
- float3 gradient2 = lerp(blue, visgreen, SunAmb);
- float3 watercolor = lerp(gradient2, gradient1, SkyCol * fog);
- watercolor = lerp(fog, SkyCol, watercolor);
- watercolor = 2 * lerp(0.1 + SunVis * (fog * SkyCol), watercolor, fogMWScalar(dist * SunVis));
- #ifdef DEPTHCOLOR
- float2 distortion = 0.5 * (((_windfactor) * dist + 0.1) * normal.xy);
- newscrpos = IN.screenpos + saturate(depth / 150) * float4(distortion.yx, 0, 0);
- float depthfix = max(0, tex2Dproj(sampDepth, newscrpos).r - IN.screenpos.w);
- watercolor += outlinestr * lerp(-1, watercolor, fogMWScalar(depthfix * 5) * SunVec);
- watercolor *= 1.25;
- #endif
- watercolor *= watcolstr;
- // Refraction
- float3 refracted = watercolor;
- float shorefactor = 0;
- float2 aber = reflect(EyeVec, normal).xy;
- #ifdef FOAM
- float edgefoam = 0;
- float wavefoam = 0;
- float swellwavefoam = 0;
- #endif
- // Avoid sampling deep water
- if(depth < 15000)
- {
- // Sample refraction texture
- newscrpos = IN.screenpos + saturate(depth / 150) * float4(reffactor.yx, 0, 0);
- // Add chromatic aberration
- refracted.r = tex2Dproj(sampRefract, newscrpos).r;
- refracted.g = tex2Dproj(sampRefract, newscrpos - float4(aber * 0.05, 0.0, 0.0)).g;
- refracted.b = tex2Dproj(sampRefract, newscrpos - float4(aber * 2 * 0.05, 0.0, 0.0)).b;
- // Get distorted depth
- depth = max(0, tex2Dproj(sampDepth, newscrpos).r - IN.screenpos.w);
- depth /= dot(EyeVec, float3(view[0][2], view[1][2], view[2][2]));
- wavedepth = tex2Dproj(sampDepth, newscrpos).r - IN.screenpos.w;
- wavedepth /= dot(EyeVec, float3(view[0][2], view[1][2], view[2][2]));
- // Small scale shoreline animation
- float wave = 50 * (0.99 - normal.z);
- depth += wave;
- float depthscale = saturate(exp(-depth / 800));
- shorefactor = pow(depthscale, 90);
- //-----------------------------------------------------------------
- // wonderfully bloated foam implementation
- #ifdef FOAM
- float wavefoamheightmin = waveHeight * -0.1;
- float wavefoamheightmax = waveHeight * 0.5;
- float curwaveheight = IN.pos.z + 10 - waterlevel;
- #ifdef SWELL_FOAM
- float swellwavefoamheightmin = waveHeight * -0.25;
- float swellwavefoamheightmax = waveHeight * 0.8;
- #endif
- float2 wavefoam_map = IN.pos.xy / 45;
- float3 wavefoam_col = tex3D(sampWater3d, float3(wavefoam_map, time));
- wavefoam_col = lerp(-1, wavefoam_col * 1.25, fog.a * 1.1);
- float wavefoam_mult = wavefoam_col.b * 0.5 + wavefoam_col.r * 0.25 + wavefoam_col.g * 0.25;
- #ifdef SWELL_FOAM
- float2 swellwavefoam_map = IN.pos.xy / 35;
- float3 swellwavefoam_col = tex3D(sampWater3d, float3(swellwavefoam_map, time * 1.2));
- float swellfader = fogMWScalar(dist * 6);
- swellwavefoam_col = lerp(-1, swellwavefoam_col, swellfader);
- float swellwavefoam_mult = swellwavefoam_col.b * 0.5 + swellwavefoam_col.r * 0.25 + swellwavefoam_col.g * 0.25;
- #endif
- float2 edgefoam_map = IN.pos.xy / 60;
- float3 edgefoam_col = tex3D(sampWater3d, float3(edgefoam_map,time*0.2));
- edgefoam_col = lerp(-1, edgefoam_col * 1.29, fog.a * 0.9);
- float edgefoam_mult = edgefoam_col.b * 0.4 + edgefoam_col.r * 0.3 + edgefoam_col.g * 0.3;
- float edgefoamfactor = pow(depthscale, 25);
- edgefoam += saturate( -5*pow(edgefoamfactor - 0.5,2) + 1) * 0.5;
- edgefoam = saturate(edgefoam);
- wavefoam = saturate((curwaveheight-wavefoamheightmin) / (wavefoamheightmax-wavefoamheightmin));
- wavefoam = saturate(wavefoam);
- #ifdef SWELL_FOAM
- swellwavefoam = saturate((curwaveheight-swellwavefoamheightmin) / (swellwavefoamheightmax-swellwavefoamheightmin));
- swellwavefoam = saturate(swellwavefoam);
- #endif
- if (edgefoam_mult > (1-edgefoam)) { edgefoam *= edgefoam_mult; }
- else { edgefoam *= edgefoam_mult/3; }
- if (wavefoam_mult > (1-wavefoam)) { wavefoam *= wavefoam_mult; }
- else { wavefoam *= wavefoam_mult/3; }
- #ifdef SWELL_FOAM
- if (swellwavefoam_mult > (1-swellwavefoam)) { swellwavefoam *= swellwavefoam_mult; }
- else { swellwavefoam *= swellwavefoam_mult/3; }
- #endif
- #endif
- //-----------------------------------------------------------------
- // Make transition between actual refraction image and depth color depending on water depth
- refracted = lerp(watercolor, refracted, 0.8 * depthscale + 0.2 * shorefactor);
- }
- // Sample reflection texture
- float3 reflected = getProjectedReflection(screenpos - float4(1.5 * reffactor.x, -abs(reffactor.y), 0, 0));
- // Dull reflection to avoid being too bright relative to sky, except for fading into an inscatter dominated horizon
- reflected *= 1 - 0.24 * saturate(2 * fog.a);
- // Smooth out high frequencies at a distance
- float3 adjustnormal = lerp(float3(0, 0, 0.1), normal, pow(saturate(1.05 * fog.a), 2));
- adjustnormal = lerp(adjustnormal, float3(0, 0, 1.0), (1 + EyeVec.z) * (1 - saturate(1 / (dist / 1300 + 6))));
- // Water cut feature, vtastek
- float wcut = smoothstep(0.09,0.1, dist/1200);
- wcut = (1 - saturate(abs(wcut*5))) * step(0.5,(1 - saturate(EyePos.z + 1)));
- wcut = 1 - saturate(wcut);
- float wcutdark = smoothstep(0.0889, 0.101, dist/1200) * step(0.5,(1 - saturate(EyePos.z + 1)));
- wcutdark = wcutdark * (wcutdark * -1 + 1);
- wcutdark = saturate(wcutdark*3);
- // Fresnel equation determines reflection/refraction
- float fresnel = dot(-EyeVec, adjustnormal);
- fresnel = 0.015 + pow(saturate(0.9988 - 0.28 * fresnel), 12);
- // darker, dynamic: fresnel = 0.015 + pow(saturate(0.9988 - 0.28 * fresnel), 16 + (8 * _lightfactor));
- float3 result = lerp(refracted, reflected, fresnel);
- // Specular lighting
- // This should use Blinn-Phong, but it doesn't work so well for area lights like the sun
- // Instead multiply and saturate to widen a Phong specular lobe which better simulates an area light
- float vdotr = dot(-EyeVec, reflect(-SunPos, normal));
- vdotr = saturate(1.0025 * vdotr);
- float3 spec = _SunCollf * (pow(vdotr, 200) + 0.07 * pow(vdotr, 30));
- spec = SunVis * lerp(1, spec, fogMWScalar(dist*0.4));
- result += 0.9 * spec * fog.a;
- //-----------------------------------------------------------------
- #ifdef FOAM
- if ( SunVis <= 0 ) {
- // calm weather + night
- if (_windfactor <= 0.0235) {
- result += saturate(edgefoam) * 0.1;
- result += saturate(wavefoam) * 0; // no wave foam in calm weather types
- #ifdef SWELL_FOAM
- result += saturate(swellwavefoam) * 0.5;
- #endif
- }
- // stormy weather + night
- else {
- result += saturate(edgefoam) * edgefoamstrn;
- result += saturate(wavefoam) * wavefoamstrn;
- #ifdef SWELL_FOAM
- result += saturate(swellwavefoam) * 0; // no swell wave foam in stormy weather
- #endif
- }
- }
- // shore foam daytime behavior, independent of wind strength
- else {
- result += (saturate(edgefoam * saturate(SkyCol.b)) * 0.3) * edgefoamstr;
- result += saturate(wavefoam) * 0; // no wave foam at daytime
- #ifdef SWELL_FOAM
- result += saturate(swellwavefoam) * swellwavefoamstr;
- #endif
- }
- #endif
- //-----------------------------------------------------------------
- // Smooth transition at shore line
- result = lerp(result, refracted, shorefactor * fog.a);
- // Note that both refraction and reflection textures were rendered fogged already
- // Prevent overly bright fogging of distant water edges
- float disfade = (1 + EyeVec.z) * (1 - saturate(1 / ( dist / 3000)));
- float fogfade = pow(saturate(lerp(1, fog.a, disfade)), 1.1);
- result = lerp(fog, result, fogfade);
- // Include water cut feature
- result = lerp(refracted, result, wcut);
- result = lerp(result, result * 0.1, wcutdark);
- return float4(result, 1);
- }
- float4 UnderwaterPS(in WaterVertOut IN): COLOR0
- {
- // Calculate eye vector
- float3 EyeVec = IN.pos.xyz - EyePos.xyz;
- float dist = length(EyeVec);
- EyeVec /= dist;
- // Special case fog, avoid fog offset
- float fog = saturate(exp(-dist / 4096));
- // Calculate water normal
- float3 normal = -getFinalWaterNormal(IN.texcoords.xy, IN.texcoords.zw, dist, IN.pos.xy);
- // Reflection / refraction pixel distortion factor, wind strength increases distortion
- float2 reffactor = 2 * (_windfactor * dist + 0.1) * normal.xy;
- // Distort refraction
- float4 newscrpos = IN.screenpos + float4(2 * -reffactor.xy, 0, 0);
- float3 refracted = tex2Dproj(sampRefract, newscrpos).rgb;
- refracted = lerp(FogCol2, refracted, exp(-dist / 500));
- // Sample reflection texture
- float3 reflected = getProjectedReflection(IN.screenpos - float4(2.1 * reffactor.x, -abs(reffactor.y), 0, 0));
- // Fresnel equation, including total internal reflection
- float fresnel = pow(saturate(1.12 - 0.65 * dot(-EyeVec, normal)), 8);
- float3 result = lerp(refracted, reflected, fresnel);
- // Sun refraction
- float refractsun = dot(-EyeVec, normalize(-SunPos + normal));
- float3 spec = _SunCollf * pow(refractsun, 6) * fog;
- return float4(result + spec, 1);
- }
- //------------------------------------------------------------
- // Caustics post-process
- DeferredOut CausticsVS(float4 pos : POSITION, float2 tex : TEXCOORD0, float2 ndc : TEXCOORD1)
- {
- DeferredOut OUT;
- // Fix D3D9 half pixel offset
- OUT.pos = float4(ndc.x - rcpres.x, ndc.y + rcpres.y, 0, 1);
- OUT.tex = float4(tex, 0, 0);
- // World space reconstruction vector
- OUT.eye = float3(view[0][2], view[1][2], view[2][2]);
- OUT.eye += (ndc.x / proj[0][0]) * float3(view[0][0], view[1][0], view[2][0]);
- OUT.eye += (ndc.y / proj[1][1]) * float3(view[0][1], view[1][1], view[2][1]);
- return OUT;
- }
- float4 CausticsPS(DeferredOut IN) : COLOR0
- {
- float3 c = tex2Dlod(sampBaseTex, IN.tex).rgb;
- float depth = tex2Dlod(sampDepthPoint, IN.tex).r;
- float fog = fogMWScalar(depth);
- clip(nearViewRange - depth);
- float3 uwpos = EyePos + IN.eye * depth;
- uwpos.z -= waterlevel - 20;
- float3 ddpx = ddx(uwpos - EyePos);
- float3 ddpy = ddy(uwpos - EyePos);
- float3 normal = normalize(cross(ddpx, ddpy));
- half fresnel = saturate(1.0 - dot(normal, IN.eye));
- fresnel = pow(fresnel, 5);
- clip(-uwpos.z);
- float3 sunray = uwpos - SunVec * (uwpos.z / SunVec.z);
- float caust = cauststr * 5 * tex3D(sampWater3d, float3(sunray.xy / 1104, 0.1 * time)).b;
- caust *= saturate(125 / depth * min(fwidth(sunray.x), fwidth(sunray.y)));
- c *= 1 + caust * saturate(exp(uwpos.z / 400)) * saturate(uwpos.z / -30) * fog;
- if(fresnel>0.9)
- discard;
- return float4(c, 1);
- }
Add Comment
Please, Sign In to add comment