Guest User

Enhanced Water Shader 2.1 Green-Blue

a guest
May 18th, 2019
2,980
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.66 KB | None | 0 0
  1. // XE Water.fx
  2. // MGE XE 0.11
  3. // Water functions (included by XE Main)
  4.  
  5. // Enhanced Water Shader 2.1 Green-Blue
  6. // compatibility with MGE XE 0.11.0
  7. // removed random function for better performance
  8. // removed windfactor from addheight to prevent repetitive moving pattern in wave behavior
  9.  
  10. // Requires: Exponential fog, Dynamic ripples set to 40
  11.  
  12. //-----------------------------------------------------------------------------------------------------------------------------------------------------------
  13. // Samplers, clamping mode
  14.  
  15. sampler sampReflect = sampler_state { texture = <tex0>; minfilter = linear; magfilter = linear; mipfilter = none; addressu = clamp; addressv = clamp; };
  16. sampler sampRefract = sampler_state { texture = <tex2>; minfilter = linear; magfilter = linear; mipfilter = none; addressu = clamp; addressv = clamp; };
  17.  
  18. //-----------------------------------------------------------------------------------------------------------------------------------------------------------
  19. // Water constants
  20.  
  21. static const float kDistantZBias = 5e-6;
  22. static const float _lightfactor = 1 - pow(1 - SunVis, 2);
  23. static const float3 _SunCollf = SunCol * _lightfactor;
  24. static const float _windfactor = (length (WindVec) + 1.5) / 120;
  25. static const float waterlevel = world[3][2];
  26. static const float cauststr = 0.05 * alpharef * saturate(0.75 * _lightfactor + 0.35 * length(FogCol2));
  27.  
  28. //-----------------------------------------------------------------------------------------------------------------------------------------------------------
  29. // Tweakables
  30.  
  31. static const float watcolstr = 0.5; // water color brightness; default: 0.5
  32. static const float outlinestr = 0.08; // depth contour intensity; default: 0.08
  33.  
  34. static const float regwavemult = 1; // controls height of regular water waves; default: 1
  35. static const float regwavewindmult = 30; // higher values increase wind influence on regular wave height; default: 30
  36. static const float heightwavemult = 2.5; // controls height of swell-like waves; default: 2.5
  37. static const float heightwavewindmult = 60; // higher values reduce height waves in inclement weather; default: 60
  38.  
  39. static const float edgefoamstr = 1; // shore foam day strength; default: 1
  40. static const float edgefoamstrn = 0.3; // shore foam night and inclement weather strength; default: 0.3
  41. static const float wavefoamstrn = 0.795; // stormy weather wave foam strength; default: 0.795
  42. static const float swellwavefoamstr = 2; // surge-like foam strength; enable SWELL_FOAM to see this; default: 2
  43.  
  44. //-----------------------------------------------------------------------------------------------------------------------------------------------------------
  45.  
  46. shared texture tex4, tex5;
  47. shared float3 rippleOrigin;
  48. shared float waveHeight;
  49.  
  50. sampler sampRain = sampler_state { texture = <tex4>; minfilter = linear; magfilter = linear; mipfilter = linear; addressu = wrap; addressv = wrap; };
  51. sampler sampWave = sampler_state { texture = <tex5>; minfilter = linear; magfilter = linear; mipfilter = linear; bordercolor = 0; addressu = border; addressv = border; };
  52.  
  53. static const float waveTexResolution = 512;
  54. static const float waveTexWorldSize = waveTexResolution * 2.5;
  55. static const float waveTexRcpRes = 1.0 / waveTexResolution;
  56. static const float playerWaveSize = 12.0 / waveTexWorldSize; // 12 world units radius
  57.  
  58. //-----------------------------------------------------------------------------------------------------------------------------------------------------------
  59. // Plug & Play features
  60.  
  61. // Enables foam on water edges and on wave tips in stormy weather.
  62. #define FOAM
  63.  
  64. // Enables swell-like height waves, monodirectional
  65. #define HEIGHT_WAVES
  66.  
  67. // Enables waves in far normals
  68. // #define FAR_WAVE_NORMALS
  69.  
  70. // Enables sewer waves in Vivec and Molag Mar, fps costly
  71. // #define SEWER_WAVES
  72.  
  73. // Enables depth color, may cause visual artifacts with cells not currently loaded and cells not processed by distant land generator
  74. #define DEPTHCOLOR
  75.  
  76. // wip, enables whitecap foam on swell waves for a surge-like effect
  77. // #define SWELL_FOAM
  78.  
  79. // wip, currently not functional
  80. // #define SWELL_WAVE_NORMALS
  81.  
  82. //-----------------------------------------------------------------------------------------------------------------------------------------------------------
  83. // Static functions
  84.  
  85. #ifdef SEWER_WAVES
  86. // Variation of harlanrm's Vivec and Molag Mar sewer waves, ported by abot, optimizations by vtastek
  87.  
  88. // Sewer locations
  89. static const float2 wLoc[70] =
  90. {
  91. // Vivec
  92. { 19160, -86825}, { 46500, -81930}, { 31475, -104345}, { 32165, -76700}, { 19160, -81900}, { 20260, -80775}, { 20300, -87915}, { 24125, -80775},
  93. { 24225, -87915}, { 25275, -86700}, { 25275, -81850}, { 25550, -95230}, { 25550, -91390}, { 25550, -88840}, { 25550, -84940}, { 26300, -81750},
  94. { 26300, -77825}, { 26630, -89955}, { 26650, -96365}, { 26700, -83850}, { 27185, -90260}, { 27625, -82800}, { 27635, -76700}, { 31180, -96925},
  95. { 31200, -103770}, { 31540, -83850}, { 31615, -96365}, { 31765, -90260}, { 31895, -89955}, { 32150, -82800}, { 32675, -95020}, { 32675, -91785},
  96. { 32675, -88690}, { 32675, -85300}, { 32975, -95365}, { 32975, -91190}, { 32975, -89110}, { 32975, -84720}, { 33450, -81635}, { 33450, -77945},
  97. { 34095, -96365}, { 34120, -90260}, { 34175, -104345}, { 34480, -83850}, { 34585, -89955}, { 34640, -96925}, { 34695, -103770}, { 38500, -89955},
  98. { 38965, -96365}, { 38980, -83850}, { 39060, -90260}, { 40100, -95300}, { 40100, -91395}, { 40100, -88790}, { 40100, -84900}, { 40400, -86900},
  99. { 40400, -81955}, { 41350, -87915}, { 41475, -80775}, { 45300, -87915}, { 45480, -80775}, { 46500, -86790},
  100. // Molag Mar
  101. { 107090, -63820}, { 114215, -59905}, { 113110, -64890}, { 107090, -59875}, { 108085, -58800}, { 108110, -64890}, { 113170, -58800}, { 114215, -63780}
  102. };
  103.  
  104. #endif
  105.  
  106. float3 getFinalWaterNormal(float2 texcoord1, float2 texcoord2, float dist, float2 vertXY) : NORMAL
  107. {
  108. // Calculate the W texture coordinate based on the time that has passed
  109. float t = 0.315 * time;
  110. float3 far = float3(texcoord1 * 0.5, t * 0.5);
  111. float3 close1 = float3(texcoord2, t);
  112. float3 close2 = float3(texcoord1, t * 0.6);
  113.  
  114. // Blend together the normals from different sized areas of the same texture
  115. float2 far_normal = tex3D(sampWater3d, far * 3).rg;
  116. far_normal += tex3D(sampWater3d, far).rg;
  117. far_normal *= 0.5;
  118.  
  119. float2 close_normal = tex3D(sampWater3d, close1).rg;
  120. close_normal += tex3D(sampWater3d, close2).rg;
  121. close_normal *= 0.5;
  122.  
  123. #ifdef DYNAMIC_RIPPLES
  124.  
  125. // Blend normals from rain and player ripples
  126. close_normal.rg += tex2Dlod(sampRain, float4(texcoord2, 0, 0)).ba;
  127. close_normal.rg += tex2Dlod(sampWave, float4((vertXY - rippleOrigin) / waveTexWorldSize, 0, 0)).ba;
  128.  
  129. #endif
  130.  
  131. #ifdef FAR_WAVE_NORMALS
  132.  
  133. //Big waves headed towards ghost gate, originally by harnlarnm
  134. float2 bwave = sin(fmod(sqrt(pow(length(vertXY-20000),2)+pow(length(vertXY-40000),2)),6144)/(6144/6.283185307) + time)/16;
  135. far_normal += bwave;
  136.  
  137. #endif
  138.  
  139. #ifdef SWELL_WAVE_NORMALS
  140.  
  141. // wip, does not work properly, don't use
  142. float2 swellwave = sin(-vertXY/256 + 1.2 * time)/8;
  143. close_normal += swellwave;
  144.  
  145. #endif
  146.  
  147. #ifdef SEWER_WAVES
  148.  
  149. //Add wave effect for each sewer location
  150. float d;
  151. float2 sewnorm = 0;
  152.  
  153. for (int i=0; i<70; i++)
  154. {
  155. d = length(vertXY - wLoc[i]);
  156. sewnorm += sin(fmod(d,128)/20.371832716 - (time*1.2)) / max((d*d)/20480,4);
  157. }
  158.  
  159. float interiorb = (SunCol > 0.003) ? 1 : 0;
  160.  
  161. if(dist<7200)
  162. close_normal.rg += interiorb * sewnorm;
  163.  
  164. #endif
  165.  
  166. float2 normal_R = 2 * lerp(close_normal, far_normal, saturate(dist/11000)) - 1;
  167. return normalize(float3(normal_R, 0.295));
  168. }
  169.  
  170. #ifndef FILTER_WATER_REFLECTION
  171.  
  172. float3 getProjectedReflection(float4 tex)
  173. {
  174. return tex2Dproj(sampReflect, tex).rgb;
  175. }
  176.  
  177. #else
  178.  
  179. float3 getProjectedReflection(float4 tex)
  180. {
  181. float4 radius = 0.006 * saturate(0.11 + tex.w/6000) * tex.w * float4(1, rcpres.y/rcpres.x, 0, 0);
  182.  
  183. float3 reflected = tex2Dproj(sampReflect, tex);
  184. reflected += tex2Dproj(sampReflect, tex + radius*float4(0.60, 0.10, 0, 0));
  185. reflected += tex2Dproj(sampReflect, tex + radius*float4(0.30, -0.21, 0, 0));
  186. reflected += tex2Dproj(sampReflect, tex + radius*float4(0.96, -0.03, 0, 0));
  187. reflected += tex2Dproj(sampReflect, tex + radius*float4(-0.40, 0.06, 0, 0));
  188. reflected += tex2Dproj(sampReflect, tex + radius*float4(-0.70, 0.18, 0, 0));
  189. reflected /= 6.0;
  190.  
  191. return reflected.rgb;
  192. }
  193.  
  194. #endif
  195.  
  196. //-----------------------------------------------------------------------------------------------------------------------------------------------------------
  197. // Water shader
  198.  
  199. //-----------------------------------------------------------------------------------------------------------------------------------------------------------
  200. // Dynamic waves
  201.  
  202. struct WaveVertOut
  203. {
  204. float4 pos : POSITION;
  205. float2 texcoord : TEXCOORD0;
  206. };
  207.  
  208. WaveVertOut WaveVS(float4 pos : POSITION, float2 texcoord : TEXCOORD0)
  209. {
  210. WaveVertOut OUT;
  211. OUT.pos = mul(pos, proj);
  212. OUT.texcoord = texcoord;
  213. return OUT;
  214. }
  215.  
  216. //-----------------------------------------------------------------------------------------------------------------------------------------------------------
  217.  
  218. float4 WaveStepPS(float2 tex : TEXCOORD0) : COLOR0
  219. {
  220. // Texture content is now float16 in range [-1, 1]
  221. float4 tc = float4(tex, 0, 0);
  222. float4 c = tex2Dlod(sampRain, tc);
  223. float4 ret = {0, c.r, 0, 0};
  224.  
  225. float4 n = {
  226. tex2D(sampRain, tc + float4(waveTexRcpRes, 0, 0, 0)).r,
  227. tex2D(sampRain, tc + float4(-waveTexRcpRes, 0, 0, 0)).r,
  228. tex2D(sampRain, tc + float4(0, waveTexRcpRes, 0, 0)).r,
  229. tex2D(sampRain, tc + float4(0, -waveTexRcpRes, 0, 0)).r
  230. };
  231. float4 n2 = {
  232. tex2D(sampRain, tc + float4(1.5 * waveTexRcpRes, 0, 0, 0)).r,
  233. tex2D(sampRain, tc + float4(-1.5 * waveTexRcpRes, 0, 0, 0)).r,
  234. tex2D(sampRain, tc + float4(0, 1.5 * waveTexRcpRes, 0, 0)).r,
  235. tex2D(sampRain, tc + float4(0, -1.5 * waveTexRcpRes, 0, 0)).r
  236. };
  237.  
  238. // dampened discrete two-dimensional wave equation
  239. // red channel: u(t)
  240. // green channel: u(t - 1)
  241. // u(t + 1) = (1 - udamp) * u(t) + a * (nsum - 4 * u(t)) + (1 - vdamp) * (u(t) - u(t - 1))
  242. // = a * nsum + ((2 - udamp - vdamp) - 4 * a) * u(t) - (1 - vdamp) * u(t - 1);
  243. float nsum = n.x + n.y + n.z + n.w;
  244. ret.r = 0.14 * nsum + (1.96 - 0.56) * c.r - 0.98 * c.g;
  245.  
  246. // calculate normal map
  247. ret.ba = 2 * (n.xy - n.zw) + 0.5 * (n2.xy - n2.zw);
  248. return ret;
  249. }
  250.  
  251. float4 PlayerWavePS(float2 tex : TEXCOORD0) : COLOR0
  252. {
  253. float4 ret = tex2Dlod(sampRain, float4(tex, 0, 0));
  254. float wavesize = (1.0 + 0.055 * sin(16 * time) + 0.065 * sin(12.87645 * time)) * playerWaveSize;
  255. float displace = saturate(2 * abs(length(tex - rippleOrigin) / wavesize - 1));
  256. ret.rg = lerp(-1, ret.rg, displace);
  257. return ret;
  258. }
  259.  
  260. struct WaterVertOut
  261. {
  262. float4 position : POSITION;
  263. float4 pos : TEXCOORD0;
  264. float4 texcoords : TEXCOORD1;
  265. float4 screenpos : TEXCOORD2;
  266.  
  267. #ifdef DYNAMIC_RIPPLES
  268.  
  269. float4 screenposclamp : TEXCOORD3;
  270.  
  271. #endif
  272.  
  273. };
  274.  
  275. #ifndef DYNAMIC_RIPPLES
  276.  
  277. //-----------------------------------------------------------------------------------------------------------------------------------------------------------
  278.  
  279. WaterVertOut WaterVS (in float4 pos : POSITION)
  280. {
  281. WaterVertOut OUT;
  282.  
  283. // Add z bias to avoid fighting with MW ripples quads
  284. OUT.pos = mul(pos, world);
  285. OUT.pos.z -= 0.1;
  286.  
  287. // Calculate various texture coordinates
  288. OUT.texcoords.xy = OUT.pos.xy / 2900;
  289. OUT.texcoords.zw = OUT.pos.xy / 427;
  290.  
  291. OUT.position = mul(OUT.pos, view);
  292. OUT.position = mul(OUT.position, proj);
  293.  
  294. // Match bias in distant land projection
  295. OUT.position.z *= 1.0 + kDistantZBias * step(nearViewRange, OUT.position.w);
  296.  
  297. OUT.screenpos = float4(0.5 * (1 + rcpres) * OUT.position.w + float2(0.5, -0.5) * OUT.position.xy, OUT.position.zw);
  298.  
  299. return OUT;
  300. }
  301.  
  302. #else
  303.  
  304. WaterVertOut WaterVS (in float4 pos : POSITION)
  305. {
  306. WaterVertOut OUT;
  307.  
  308. // Move to world space
  309. OUT.pos = mul(pos, world);
  310.  
  311. // Calculate various texture coordinates
  312. OUT.texcoords.xy = OUT.pos.xy / 2600;
  313. OUT.texcoords.zw = OUT.pos.xy / 440;
  314.  
  315. // Apply vertex displacement
  316. float t = 0.325 * time;
  317. float height = tex3Dlod(sampWater3d, float4(OUT.pos.xy / 860, t, 0)).a;
  318. float height2 = tex3Dlod(sampWater3d, float4(OUT.pos.xy / 2800, t, 0)).a;
  319. float dist = length(EyePos.xyz - OUT.pos.xyz);
  320.  
  321. float addheight = waveHeight * (lerp(height, height2, saturate(dist/8000)) - 0.5) * saturate(1 - dist/6400) * saturate(dist/200);
  322. addheight += (0.5 + regwavewindmult * 0.04) * lerp(height, height2, waveHeight);
  323.  
  324. // Fade out wave height with distance to prevent flickering
  325. addheight = lerp(-1, addheight, fogMWScalar(dist*2));
  326. addheight *= regwavemult;
  327. OUT.pos.z += addheight;
  328.  
  329. #ifdef HEIGHT_WAVES
  330.  
  331. // Decrease height waves in inclement weather to keep peak fix intact
  332. float wdecrease = (heightwavemult - heightwavewindmult * _windfactor);
  333.  
  334. 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);
  335. OUT.pos.z += swell;
  336.  
  337. #endif
  338.  
  339. #ifdef HEIGHT_WAVES
  340.  
  341. // Lower water plane to avoid peaking under
  342. OUT.pos.z += -(9 + heightwavemult + regwavemult + (0.5 * (addheight + swell)));
  343.  
  344. #else
  345.  
  346. // Lower water plane to avoid peaking under
  347. OUT.pos.z += -(7 + heightwavemult + regwavemult + (0.25 * addheight));
  348.  
  349. #endif
  350.  
  351. // Raise water plane to avoid peaking above
  352. // Waterlevel is 1.5 units wrong
  353. float wjump = step(EyePos.z - waterlevel + 1.5, 0.5);
  354. OUT.pos.z += wjump * 20;
  355.  
  356. // Match bias in distant land projection
  357. OUT.position = mul(OUT.pos, view);
  358. OUT.position = mul(OUT.position, proj);
  359. OUT.position.z *= 1.0 + kDistantZBias * step(nearViewRange, OUT.position.w);
  360. OUT.screenpos = float4(0.5 * (1 + rcpres) * OUT.position.w + float2(0.5, -0.5) * OUT.position.xy, OUT.position.zw);
  361.  
  362. // Clamp reflection point to be above surface
  363. float4 clampedPos = OUT.pos - float4(0, 0, abs(addheight), 0);
  364. clampedPos = mul(clampedPos, view);
  365. clampedPos = mul(clampedPos, proj);
  366. clampedPos.z *= 1.0 + kDistantZBias * step(nearViewRange, clampedPos.w);
  367. OUT.screenposclamp = float4(0.5 * (1 + rcpres) * clampedPos.w + float2(0.5, -0.5) * clampedPos.xy, clampedPos.zw);
  368.  
  369. return OUT;
  370. }
  371. #endif
  372.  
  373. float4 WaterPS(in WaterVertOut IN): COLOR0
  374. {
  375.  
  376. #ifndef DYNAMIC_RIPPLES
  377.  
  378. float4 screenpos = IN.screenpos;
  379.  
  380. #else
  381.  
  382. float4 screenpos = IN.screenposclamp;
  383.  
  384. #endif
  385.  
  386. // Calculate eye vector
  387. float3 EyeVec = IN.pos.xyz - EyePos.xyz;
  388. float dist = length(EyeVec);
  389. EyeVec /= dist;
  390.  
  391. // Calculate water normal
  392. float3 normal = getFinalWaterNormal(IN.texcoords.xy, IN.texcoords.zw, dist * 0.65, IN.pos.xy);
  393.  
  394. // Reflection/refraction pixel distortion factor, wind strength increases distortion
  395. float2 reffactor = 0.5 * (((_windfactor) * dist + 0.1) * normal.xy);
  396.  
  397. // Distort refraction dependent on depth
  398. float4 newscrpos = IN.screenpos + float4(reffactor.yx, 0, 0);
  399. float depth = max(0, tex2Dproj(sampDepth, newscrpos).r - IN.screenpos.w);
  400. float wavedepth = max(0, tex2Dproj(sampDepth, newscrpos).r - IN.screenpos.w);
  401.  
  402. // Define fog
  403. float4 fog = fogColour(EyeVec, dist);
  404.  
  405. // Water color
  406. float3 green = float3(0.09, 0.22, 0.17);
  407. float3 blue = float3(0.07,0.13,0.29);
  408.  
  409. float3 visgreen = float3(SunVis * 0.15, 0.4, SunVis * 0.3);
  410. float3 visblue = float3(0.1, SunVis * 0.15, 0.35);
  411.  
  412. float3 gradient1 = lerp(green, visblue, SkyCol);
  413. float3 gradient2 = lerp(blue, visgreen, SunAmb);
  414.  
  415. float3 watercolor = lerp(gradient2, gradient1, SkyCol * fog);
  416.  
  417. watercolor = lerp(fog, SkyCol, watercolor);
  418. watercolor = 2 * lerp(0.1 + SunVis * (fog * SkyCol), watercolor, fogMWScalar(dist * SunVis));
  419.  
  420. #ifdef DEPTHCOLOR
  421.  
  422. float2 distortion = 0.5 * (((_windfactor) * dist + 0.1) * normal.xy);
  423.  
  424. newscrpos = IN.screenpos + saturate(depth / 150) * float4(distortion.yx, 0, 0);
  425. float depthfix = max(0, tex2Dproj(sampDepth, newscrpos).r - IN.screenpos.w);
  426.  
  427. watercolor += outlinestr * lerp(-1, watercolor, fogMWScalar(depthfix * 5) * SunVec);
  428. watercolor *= 1.25;
  429.  
  430. #endif
  431.  
  432. watercolor *= watcolstr;
  433.  
  434. // Refraction
  435. float3 refracted = watercolor;
  436. float shorefactor = 0;
  437. float2 aber = reflect(EyeVec, normal).xy;
  438.  
  439. #ifdef FOAM
  440.  
  441. float edgefoam = 0;
  442. float wavefoam = 0;
  443. float swellwavefoam = 0;
  444.  
  445. #endif
  446.  
  447. // Avoid sampling deep water
  448. if(depth < 15000)
  449. {
  450. // Sample refraction texture
  451. newscrpos = IN.screenpos + saturate(depth / 150) * float4(reffactor.yx, 0, 0);
  452.  
  453. // Add chromatic aberration
  454. refracted.r = tex2Dproj(sampRefract, newscrpos).r;
  455. refracted.g = tex2Dproj(sampRefract, newscrpos - float4(aber * 0.05, 0.0, 0.0)).g;
  456. refracted.b = tex2Dproj(sampRefract, newscrpos - float4(aber * 2 * 0.05, 0.0, 0.0)).b;
  457.  
  458. // Get distorted depth
  459. depth = max(0, tex2Dproj(sampDepth, newscrpos).r - IN.screenpos.w);
  460. depth /= dot(EyeVec, float3(view[0][2], view[1][2], view[2][2]));
  461. wavedepth = tex2Dproj(sampDepth, newscrpos).r - IN.screenpos.w;
  462. wavedepth /= dot(EyeVec, float3(view[0][2], view[1][2], view[2][2]));
  463.  
  464. // Small scale shoreline animation
  465. float wave = 50 * (0.99 - normal.z);
  466. depth += wave;
  467.  
  468. float depthscale = saturate(exp(-depth / 800));
  469. shorefactor = pow(depthscale, 90);
  470.  
  471. //-----------------------------------------------------------------
  472. // wonderfully bloated foam implementation
  473.  
  474. #ifdef FOAM
  475.  
  476. float wavefoamheightmin = waveHeight * -0.1;
  477. float wavefoamheightmax = waveHeight * 0.5;
  478. float curwaveheight = IN.pos.z + 10 - waterlevel;
  479.  
  480. #ifdef SWELL_FOAM
  481.  
  482. float swellwavefoamheightmin = waveHeight * -0.25;
  483. float swellwavefoamheightmax = waveHeight * 0.8;
  484.  
  485. #endif
  486.  
  487. float2 wavefoam_map = IN.pos.xy / 45;
  488. float3 wavefoam_col = tex3D(sampWater3d, float3(wavefoam_map, time));
  489. wavefoam_col = lerp(-1, wavefoam_col * 1.25, fog.a * 1.1);
  490. float wavefoam_mult = wavefoam_col.b * 0.5 + wavefoam_col.r * 0.25 + wavefoam_col.g * 0.25;
  491.  
  492. #ifdef SWELL_FOAM
  493.  
  494. float2 swellwavefoam_map = IN.pos.xy / 35;
  495. float3 swellwavefoam_col = tex3D(sampWater3d, float3(swellwavefoam_map, time * 1.2));
  496. float swellfader = fogMWScalar(dist * 6);
  497. swellwavefoam_col = lerp(-1, swellwavefoam_col, swellfader);
  498. float swellwavefoam_mult = swellwavefoam_col.b * 0.5 + swellwavefoam_col.r * 0.25 + swellwavefoam_col.g * 0.25;
  499.  
  500. #endif
  501.  
  502. float2 edgefoam_map = IN.pos.xy / 60;
  503. float3 edgefoam_col = tex3D(sampWater3d, float3(edgefoam_map,time*0.2));
  504. edgefoam_col = lerp(-1, edgefoam_col * 1.29, fog.a * 0.9);
  505. float edgefoam_mult = edgefoam_col.b * 0.4 + edgefoam_col.r * 0.3 + edgefoam_col.g * 0.3;
  506. float edgefoamfactor = pow(depthscale, 25);
  507.  
  508. edgefoam += saturate( -5*pow(edgefoamfactor - 0.5,2) + 1) * 0.5;
  509. edgefoam = saturate(edgefoam);
  510.  
  511. wavefoam = saturate((curwaveheight-wavefoamheightmin) / (wavefoamheightmax-wavefoamheightmin));
  512. wavefoam = saturate(wavefoam);
  513.  
  514. #ifdef SWELL_FOAM
  515.  
  516. swellwavefoam = saturate((curwaveheight-swellwavefoamheightmin) / (swellwavefoamheightmax-swellwavefoamheightmin));
  517. swellwavefoam = saturate(swellwavefoam);
  518.  
  519. #endif
  520.  
  521. if (edgefoam_mult > (1-edgefoam)) { edgefoam *= edgefoam_mult; }
  522. else { edgefoam *= edgefoam_mult/3; }
  523.  
  524. if (wavefoam_mult > (1-wavefoam)) { wavefoam *= wavefoam_mult; }
  525. else { wavefoam *= wavefoam_mult/3; }
  526.  
  527. #ifdef SWELL_FOAM
  528.  
  529. if (swellwavefoam_mult > (1-swellwavefoam)) { swellwavefoam *= swellwavefoam_mult; }
  530. else { swellwavefoam *= swellwavefoam_mult/3; }
  531.  
  532. #endif
  533.  
  534. #endif
  535.  
  536. //-----------------------------------------------------------------
  537.  
  538. // Make transition between actual refraction image and depth color depending on water depth
  539. refracted = lerp(watercolor, refracted, 0.8 * depthscale + 0.2 * shorefactor);
  540. }
  541.  
  542. // Sample reflection texture
  543. float3 reflected = getProjectedReflection(screenpos - float4(1.5 * reffactor.x, -abs(reffactor.y), 0, 0));
  544.  
  545. // Dull reflection to avoid being too bright relative to sky, except for fading into an inscatter dominated horizon
  546. reflected *= 1 - 0.24 * saturate(2 * fog.a);
  547.  
  548. // Smooth out high frequencies at a distance
  549. float3 adjustnormal = lerp(float3(0, 0, 0.1), normal, pow(saturate(1.05 * fog.a), 2));
  550. adjustnormal = lerp(adjustnormal, float3(0, 0, 1.0), (1 + EyeVec.z) * (1 - saturate(1 / (dist / 1300 + 6))));
  551.  
  552. // Water cut feature, vtastek
  553. float wcut = smoothstep(0.09,0.1, dist/1200);
  554. wcut = (1 - saturate(abs(wcut*5))) * step(0.5,(1 - saturate(EyePos.z + 1)));
  555. wcut = 1 - saturate(wcut);
  556.  
  557. float wcutdark = smoothstep(0.0889, 0.101, dist/1200) * step(0.5,(1 - saturate(EyePos.z + 1)));
  558. wcutdark = wcutdark * (wcutdark * -1 + 1);
  559. wcutdark = saturate(wcutdark*3);
  560.  
  561. // Fresnel equation determines reflection/refraction
  562. float fresnel = dot(-EyeVec, adjustnormal);
  563. fresnel = 0.015 + pow(saturate(0.9988 - 0.28 * fresnel), 12);
  564. // darker, dynamic: fresnel = 0.015 + pow(saturate(0.9988 - 0.28 * fresnel), 16 + (8 * _lightfactor));
  565.  
  566. float3 result = lerp(refracted, reflected, fresnel);
  567.  
  568. // Specular lighting
  569. // This should use Blinn-Phong, but it doesn't work so well for area lights like the sun
  570. // Instead multiply and saturate to widen a Phong specular lobe which better simulates an area light
  571. float vdotr = dot(-EyeVec, reflect(-SunPos, normal));
  572. vdotr = saturate(1.0025 * vdotr);
  573. float3 spec = _SunCollf * (pow(vdotr, 200) + 0.07 * pow(vdotr, 30));
  574. spec = SunVis * lerp(1, spec, fogMWScalar(dist*0.4));
  575.  
  576. result += 0.9 * spec * fog.a;
  577.  
  578. //-----------------------------------------------------------------
  579. #ifdef FOAM
  580.  
  581. if ( SunVis <= 0 ) {
  582.  
  583. // calm weather + night
  584. if (_windfactor <= 0.0235) {
  585. result += saturate(edgefoam) * 0.1;
  586. result += saturate(wavefoam) * 0; // no wave foam in calm weather types
  587. #ifdef SWELL_FOAM
  588. result += saturate(swellwavefoam) * 0.5;
  589. #endif
  590. }
  591.  
  592. // stormy weather + night
  593. else {
  594. result += saturate(edgefoam) * edgefoamstrn;
  595. result += saturate(wavefoam) * wavefoamstrn;
  596. #ifdef SWELL_FOAM
  597. result += saturate(swellwavefoam) * 0; // no swell wave foam in stormy weather
  598. #endif
  599. }
  600. }
  601.  
  602. // shore foam daytime behavior, independent of wind strength
  603. else {
  604. result += (saturate(edgefoam * saturate(SkyCol.b)) * 0.3) * edgefoamstr;
  605. result += saturate(wavefoam) * 0; // no wave foam at daytime
  606. #ifdef SWELL_FOAM
  607. result += saturate(swellwavefoam) * swellwavefoamstr;
  608. #endif
  609. }
  610.  
  611. #endif
  612. //-----------------------------------------------------------------
  613.  
  614. // Smooth transition at shore line
  615. result = lerp(result, refracted, shorefactor * fog.a);
  616.  
  617. // Note that both refraction and reflection textures were rendered fogged already
  618.  
  619. // Prevent overly bright fogging of distant water edges
  620. float disfade = (1 + EyeVec.z) * (1 - saturate(1 / ( dist / 3000)));
  621. float fogfade = pow(saturate(lerp(1, fog.a, disfade)), 1.1);
  622. result = lerp(fog, result, fogfade);
  623.  
  624. // Include water cut feature
  625. result = lerp(refracted, result, wcut);
  626. result = lerp(result, result * 0.1, wcutdark);
  627. return float4(result, 1);
  628. }
  629.  
  630. float4 UnderwaterPS(in WaterVertOut IN): COLOR0
  631. {
  632. // Calculate eye vector
  633. float3 EyeVec = IN.pos.xyz - EyePos.xyz;
  634. float dist = length(EyeVec);
  635. EyeVec /= dist;
  636.  
  637. // Special case fog, avoid fog offset
  638. float fog = saturate(exp(-dist / 4096));
  639.  
  640. // Calculate water normal
  641. float3 normal = -getFinalWaterNormal(IN.texcoords.xy, IN.texcoords.zw, dist, IN.pos.xy);
  642.  
  643. // Reflection / refraction pixel distortion factor, wind strength increases distortion
  644. float2 reffactor = 2 * (_windfactor * dist + 0.1) * normal.xy;
  645.  
  646. // Distort refraction
  647. float4 newscrpos = IN.screenpos + float4(2 * -reffactor.xy, 0, 0);
  648. float3 refracted = tex2Dproj(sampRefract, newscrpos).rgb;
  649. refracted = lerp(FogCol2, refracted, exp(-dist / 500));
  650.  
  651. // Sample reflection texture
  652. float3 reflected = getProjectedReflection(IN.screenpos - float4(2.1 * reffactor.x, -abs(reffactor.y), 0, 0));
  653.  
  654. // Fresnel equation, including total internal reflection
  655. float fresnel = pow(saturate(1.12 - 0.65 * dot(-EyeVec, normal)), 8);
  656. float3 result = lerp(refracted, reflected, fresnel);
  657.  
  658. // Sun refraction
  659. float refractsun = dot(-EyeVec, normalize(-SunPos + normal));
  660. float3 spec = _SunCollf * pow(refractsun, 6) * fog;
  661.  
  662. return float4(result + spec, 1);
  663. }
  664.  
  665. //------------------------------------------------------------
  666. // Caustics post-process
  667.  
  668. DeferredOut CausticsVS(float4 pos : POSITION, float2 tex : TEXCOORD0, float2 ndc : TEXCOORD1)
  669. {
  670. DeferredOut OUT;
  671.  
  672. // Fix D3D9 half pixel offset
  673. OUT.pos = float4(ndc.x - rcpres.x, ndc.y + rcpres.y, 0, 1);
  674. OUT.tex = float4(tex, 0, 0);
  675.  
  676. // World space reconstruction vector
  677. OUT.eye = float3(view[0][2], view[1][2], view[2][2]);
  678. OUT.eye += (ndc.x / proj[0][0]) * float3(view[0][0], view[1][0], view[2][0]);
  679. OUT.eye += (ndc.y / proj[1][1]) * float3(view[0][1], view[1][1], view[2][1]);
  680. return OUT;
  681. }
  682.  
  683. float4 CausticsPS(DeferredOut IN) : COLOR0
  684. {
  685. float3 c = tex2Dlod(sampBaseTex, IN.tex).rgb;
  686. float depth = tex2Dlod(sampDepthPoint, IN.tex).r;
  687. float fog = fogMWScalar(depth);
  688.  
  689. clip(nearViewRange - depth);
  690.  
  691. float3 uwpos = EyePos + IN.eye * depth;
  692. uwpos.z -= waterlevel - 20;
  693.  
  694. float3 ddpx = ddx(uwpos - EyePos);
  695. float3 ddpy = ddy(uwpos - EyePos);
  696. float3 normal = normalize(cross(ddpx, ddpy));
  697.  
  698. half fresnel = saturate(1.0 - dot(normal, IN.eye));
  699. fresnel = pow(fresnel, 5);
  700.  
  701. clip(-uwpos.z);
  702.  
  703. float3 sunray = uwpos - SunVec * (uwpos.z / SunVec.z);
  704. float caust = cauststr * 5 * tex3D(sampWater3d, float3(sunray.xy / 1104, 0.1 * time)).b;
  705. caust *= saturate(125 / depth * min(fwidth(sunray.x), fwidth(sunray.y)));
  706. c *= 1 + caust * saturate(exp(uwpos.z / 400)) * saturate(uwpos.z / -30) * fog;
  707.  
  708. if(fresnel>0.9)
  709. discard;
  710. return float4(c, 1);
  711. }
Add Comment
Please, Sign In to add comment