opengl_fragment.glsl 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_OPAQUE || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_BASIC || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT)
  2. #define MATERIAL_WAVING_LIQUID 1
  3. #endif
  4. uniform sampler2D baseTexture;
  5. uniform vec3 dayLight;
  6. uniform lowp vec4 fogColor;
  7. uniform float fogDistance;
  8. uniform float fogShadingParameter;
  9. // The cameraOffset is the current center of the visible world.
  10. uniform highp vec3 cameraOffset;
  11. uniform vec3 cameraPosition;
  12. uniform float animationTimer;
  13. #ifdef ENABLE_DYNAMIC_SHADOWS
  14. // shadow texture
  15. uniform sampler2D ShadowMapSampler;
  16. // shadow uniforms
  17. uniform vec3 v_LightDirection;
  18. uniform float f_textureresolution;
  19. uniform mat4 m_ShadowViewProj;
  20. uniform float f_shadowfar;
  21. uniform float f_shadow_strength;
  22. uniform vec4 CameraPos;
  23. uniform float xyPerspectiveBias0;
  24. uniform float xyPerspectiveBias1;
  25. uniform vec3 shadow_tint;
  26. varying float adj_shadow_strength;
  27. varying float cosLight;
  28. varying float f_normal_length;
  29. varying vec3 shadow_position;
  30. varying float perspective_factor;
  31. #endif
  32. varying vec3 vNormal;
  33. varying vec3 vPosition;
  34. // World position in the visible world (i.e. relative to the cameraOffset.)
  35. // This can be used for many shader effects without loss of precision.
  36. // If the absolute position is required it can be calculated with
  37. // cameraOffset + worldPosition (for large coordinates the limits of float
  38. // precision must be considered).
  39. varying vec3 worldPosition;
  40. varying lowp vec4 varColor;
  41. #ifdef GL_ES
  42. varying mediump vec2 varTexCoord;
  43. #else
  44. centroid varying vec2 varTexCoord;
  45. #endif
  46. varying highp vec3 eyeVec;
  47. varying float nightRatio;
  48. #ifdef ENABLE_DYNAMIC_SHADOWS
  49. #if (defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS) && ENABLE_WAVING_WATER)
  50. vec4 perm(vec4 x)
  51. {
  52. return mod(((x * 34.0) + 1.0) * x, 289.0);
  53. }
  54. // Corresponding gradient of snoise
  55. vec3 gnoise(vec3 p){
  56. vec3 a = floor(p);
  57. vec3 d = p - a;
  58. vec3 dd = 6.0 * d * (1.0 - d);
  59. d = d * d * (3.0 - 2.0 * d);
  60. vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0);
  61. vec4 k1 = perm(b.xyxy);
  62. vec4 k2 = perm(k1.xyxy + b.zzww);
  63. vec4 c = k2 + a.zzzz;
  64. vec4 k3 = perm(c);
  65. vec4 k4 = perm(c + 1.0);
  66. vec4 o1 = fract(k3 * (1.0 / 41.0));
  67. vec4 o2 = fract(k4 * (1.0 / 41.0));
  68. vec4 o3 = o2 * d.z + o1 * (1.0 - d.z);
  69. vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x);
  70. vec4 dz1 = (o2 - o1) * dd.z;
  71. vec2 dz2 = dz1.yw * d.x + dz1.xz * (1.0 - d.x);
  72. vec2 dx = (o3.yw - o3.xz) * dd.x;
  73. return vec3(
  74. dx.y * d.y + dx.x * (1. - d.y),
  75. (o4.y - o4.x) * dd.y,
  76. dz2.y * d.y + dz2.x * (1. - d.y)
  77. );
  78. }
  79. vec2 wave_noise(vec3 p, float off) {
  80. return (gnoise(p + vec3(0.0, 0.0, off)) * 0.4 + gnoise(2.0 * p + vec3(0.0, off, off)) * 0.2 + gnoise(3.0 * p + vec3(0.0, off, off)) * 0.225 + gnoise(4.0 * p + vec3(-off, off, 0.0)) * 0.2).xz;
  81. }
  82. #endif
  83. // assuming near is always 1.0
  84. float getLinearDepth()
  85. {
  86. return 2.0 * f_shadowfar / (f_shadowfar + 1.0 - (2.0 * gl_FragCoord.z - 1.0) * (f_shadowfar - 1.0));
  87. }
  88. vec3 getLightSpacePosition()
  89. {
  90. return shadow_position * 0.5 + 0.5;
  91. }
  92. // custom smoothstep implementation because it's not defined in glsl1.2
  93. // https://docs.gl/sl4/smoothstep
  94. float mtsmoothstep(in float edge0, in float edge1, in float x)
  95. {
  96. float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
  97. return t * t * (3.0 - 2.0 * t);
  98. }
  99. float shadowCutoff(float x) {
  100. #if defined(ENABLE_TRANSLUCENT_FOLIAGE) && MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES
  101. return mtsmoothstep(0.0, 0.002, x);
  102. #else
  103. return step(0.0, x);
  104. #endif
  105. }
  106. #ifdef COLORED_SHADOWS
  107. // c_precision of 128 fits within 7 base-10 digits
  108. const float c_precision = 128.0;
  109. const float c_precisionp1 = c_precision + 1.0;
  110. float packColor(vec3 color)
  111. {
  112. return floor(color.b * c_precision + 0.5)
  113. + floor(color.g * c_precision + 0.5) * c_precisionp1
  114. + floor(color.r * c_precision + 0.5) * c_precisionp1 * c_precisionp1;
  115. }
  116. vec3 unpackColor(float value)
  117. {
  118. vec3 color;
  119. color.b = mod(value, c_precisionp1) / c_precision;
  120. color.g = mod(floor(value / c_precisionp1), c_precisionp1) / c_precision;
  121. color.r = floor(value / (c_precisionp1 * c_precisionp1)) / c_precision;
  122. return color;
  123. }
  124. vec4 getHardShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  125. {
  126. vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy).rgba;
  127. float visibility = shadowCutoff(realDistance - texDepth.r);
  128. vec4 result = vec4(visibility, vec3(0.0,0.0,0.0));//unpackColor(texDepth.g));
  129. if (visibility < 0.1) {
  130. visibility = shadowCutoff(realDistance - texDepth.b);
  131. result = vec4(visibility, unpackColor(texDepth.a));
  132. }
  133. return result;
  134. }
  135. #else
  136. float getHardShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  137. {
  138. float texDepth = texture2D(shadowsampler, smTexCoord.xy).r;
  139. float visibility = shadowCutoff(realDistance - texDepth);
  140. return visibility;
  141. }
  142. #endif
  143. #if SHADOW_FILTER == 2
  144. #define PCFBOUND 2.0 // 5x5
  145. #define PCFSAMPLES 25
  146. #elif SHADOW_FILTER == 1
  147. #define PCFBOUND 1.0 // 3x3
  148. #define PCFSAMPLES 9
  149. #else
  150. #define PCFBOUND 0.0
  151. #define PCFSAMPLES 1
  152. #endif
  153. #ifdef COLORED_SHADOWS
  154. float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  155. {
  156. vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy);
  157. float depth = max(realDistance - texDepth.r, realDistance - texDepth.b);
  158. return depth;
  159. }
  160. #else
  161. float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  162. {
  163. float texDepth = texture2D(shadowsampler, smTexCoord.xy).r;
  164. float depth = realDistance - texDepth;
  165. return depth;
  166. }
  167. #endif
  168. #define BASEFILTERRADIUS 1.0
  169. float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  170. {
  171. // Return fast if sharp shadows are requested
  172. if (PCFBOUND == 0.0 || SOFTSHADOWRADIUS <= 0.0)
  173. return 0.0;
  174. vec2 clampedpos;
  175. float y, x;
  176. float depth = getHardShadowDepth(shadowsampler, smTexCoord.xy, realDistance);
  177. // A factor from 0 to 1 to reduce blurring of short shadows
  178. float sharpness_factor = 1.0;
  179. // conversion factor from shadow depth to blur radius
  180. float depth_to_blur = f_shadowfar / SOFTSHADOWRADIUS / xyPerspectiveBias0;
  181. if (depth > 0.0 && f_normal_length > 0.0)
  182. // 5 is empirical factor that controls how fast shadow loses sharpness
  183. sharpness_factor = clamp(5.0 * depth * depth_to_blur, 0.0, 1.0);
  184. depth = 0.0;
  185. float world_to_texture = xyPerspectiveBias1 / perspective_factor / perspective_factor
  186. * f_textureresolution / 2.0 / f_shadowfar;
  187. float world_radius = 0.2; // shadow blur radius in world float coordinates, e.g. 0.2 = 0.02 of one node
  188. return max(BASEFILTERRADIUS * f_textureresolution / 4096.0, sharpness_factor * world_radius * world_to_texture * SOFTSHADOWRADIUS);
  189. }
  190. #ifdef POISSON_FILTER
  191. const vec2[64] poissonDisk = vec2[64](
  192. vec2(0.170019, -0.040254),
  193. vec2(-0.299417, 0.791925),
  194. vec2(0.645680, 0.493210),
  195. vec2(-0.651784, 0.717887),
  196. vec2(0.421003, 0.027070),
  197. vec2(-0.817194, -0.271096),
  198. vec2(-0.705374, -0.668203),
  199. vec2(0.977050, -0.108615),
  200. vec2(0.063326, 0.142369),
  201. vec2(0.203528, 0.214331),
  202. vec2(-0.667531, 0.326090),
  203. vec2(-0.098422, -0.295755),
  204. vec2(-0.885922, 0.215369),
  205. vec2(0.566637, 0.605213),
  206. vec2(0.039766, -0.396100),
  207. vec2(0.751946, 0.453352),
  208. vec2(0.078707, -0.715323),
  209. vec2(-0.075838, -0.529344),
  210. vec2(0.724479, -0.580798),
  211. vec2(0.222999, -0.215125),
  212. vec2(-0.467574, -0.405438),
  213. vec2(-0.248268, -0.814753),
  214. vec2(0.354411, -0.887570),
  215. vec2(0.175817, 0.382366),
  216. vec2(0.487472, -0.063082),
  217. vec2(0.355476, 0.025357),
  218. vec2(-0.084078, 0.898312),
  219. vec2(0.488876, -0.783441),
  220. vec2(0.470016, 0.217933),
  221. vec2(-0.696890, -0.549791),
  222. vec2(-0.149693, 0.605762),
  223. vec2(0.034211, 0.979980),
  224. vec2(0.503098, -0.308878),
  225. vec2(-0.016205, -0.872921),
  226. vec2(0.385784, -0.393902),
  227. vec2(-0.146886, -0.859249),
  228. vec2(0.643361, 0.164098),
  229. vec2(0.634388, -0.049471),
  230. vec2(-0.688894, 0.007843),
  231. vec2(0.464034, -0.188818),
  232. vec2(-0.440840, 0.137486),
  233. vec2(0.364483, 0.511704),
  234. vec2(0.034028, 0.325968),
  235. vec2(0.099094, -0.308023),
  236. vec2(0.693960, -0.366253),
  237. vec2(0.678884, -0.204688),
  238. vec2(0.001801, 0.780328),
  239. vec2(0.145177, -0.898984),
  240. vec2(0.062655, -0.611866),
  241. vec2(0.315226, -0.604297),
  242. vec2(-0.780145, 0.486251),
  243. vec2(-0.371868, 0.882138),
  244. vec2(0.200476, 0.494430),
  245. vec2(-0.494552, -0.711051),
  246. vec2(0.612476, 0.705252),
  247. vec2(-0.578845, -0.768792),
  248. vec2(-0.772454, -0.090976),
  249. vec2(0.504440, 0.372295),
  250. vec2(0.155736, 0.065157),
  251. vec2(0.391522, 0.849605),
  252. vec2(-0.620106, -0.328104),
  253. vec2(0.789239, -0.419965),
  254. vec2(-0.545396, 0.538133),
  255. vec2(-0.178564, -0.596057)
  256. );
  257. #ifdef COLORED_SHADOWS
  258. vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  259. {
  260. float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
  261. if (radius < 0.1) {
  262. // we are in the middle of even brightness, no need for filtering
  263. return getHardShadowColor(shadowsampler, smTexCoord.xy, realDistance);
  264. }
  265. vec2 clampedpos;
  266. vec4 visibility = vec4(0.0);
  267. float scale_factor = radius / f_textureresolution;
  268. int samples = (1 + 1 * int(SOFTSHADOWRADIUS > 1.0)) * PCFSAMPLES; // scale max samples for the soft shadows
  269. samples = int(clamp(pow(4.0 * radius + 1.0, 2.0), 1.0, float(samples)));
  270. int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-samples)));
  271. int end_offset = int(samples) + init_offset;
  272. for (int x = init_offset; x < end_offset; x++) {
  273. clampedpos = poissonDisk[x] * scale_factor + smTexCoord.xy;
  274. visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
  275. }
  276. return visibility / samples;
  277. }
  278. #else
  279. float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  280. {
  281. float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
  282. if (radius < 0.1) {
  283. // we are in the middle of even brightness, no need for filtering
  284. return getHardShadow(shadowsampler, smTexCoord.xy, realDistance);
  285. }
  286. vec2 clampedpos;
  287. float visibility = 0.0;
  288. float scale_factor = radius / f_textureresolution;
  289. int samples = (1 + 1 * int(SOFTSHADOWRADIUS > 1.0)) * PCFSAMPLES; // scale max samples for the soft shadows
  290. samples = int(clamp(pow(4.0 * radius + 1.0, 2.0), 1.0, float(samples)));
  291. int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-samples)));
  292. int end_offset = int(samples) + init_offset;
  293. for (int x = init_offset; x < end_offset; x++) {
  294. clampedpos = poissonDisk[x] * scale_factor + smTexCoord.xy;
  295. visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
  296. }
  297. return visibility / samples;
  298. }
  299. #endif
  300. #else
  301. /* poisson filter disabled */
  302. #ifdef COLORED_SHADOWS
  303. vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  304. {
  305. float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
  306. if (radius < 0.1) {
  307. // we are in the middle of even brightness, no need for filtering
  308. return getHardShadowColor(shadowsampler, smTexCoord.xy, realDistance);
  309. }
  310. vec2 clampedpos;
  311. vec4 visibility = vec4(0.0);
  312. float x, y;
  313. float bound = (1 + 0.5 * int(SOFTSHADOWRADIUS > 1.0)) * PCFBOUND; // scale max bound for soft shadows
  314. bound = clamp(0.5 * (4.0 * radius - 1.0), 0.5, bound);
  315. float scale_factor = radius / bound / f_textureresolution;
  316. float n = 0.0;
  317. // basic PCF filter
  318. for (y = -bound; y <= bound; y += 1.0)
  319. for (x = -bound; x <= bound; x += 1.0) {
  320. clampedpos = vec2(x,y) * scale_factor + smTexCoord.xy;
  321. visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
  322. n += 1.0;
  323. }
  324. return visibility / max(n, 1.0);
  325. }
  326. #else
  327. float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  328. {
  329. float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
  330. if (radius < 0.1) {
  331. // we are in the middle of even brightness, no need for filtering
  332. return getHardShadow(shadowsampler, smTexCoord.xy, realDistance);
  333. }
  334. vec2 clampedpos;
  335. float visibility = 0.0;
  336. float x, y;
  337. float bound = (1 + 0.5 * int(SOFTSHADOWRADIUS > 1.0)) * PCFBOUND; // scale max bound for soft shadows
  338. bound = clamp(0.5 * (4.0 * radius - 1.0), 0.5, bound);
  339. float scale_factor = radius / bound / f_textureresolution;
  340. float n = 0.0;
  341. // basic PCF filter
  342. for (y = -bound; y <= bound; y += 1.0)
  343. for (x = -bound; x <= bound; x += 1.0) {
  344. clampedpos = vec2(x,y) * scale_factor + smTexCoord.xy;
  345. visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
  346. n += 1.0;
  347. }
  348. return visibility / max(n, 1.0);
  349. }
  350. #endif
  351. #endif
  352. #endif
  353. void main(void)
  354. {
  355. vec3 color;
  356. vec2 uv = varTexCoord.st;
  357. vec4 base = texture2D(baseTexture, uv).rgba;
  358. // If alpha is zero, we can just discard the pixel. This fixes transparency
  359. // on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa,
  360. // and also on GLES 2, where GL_ALPHA_TEST is missing entirely.
  361. #ifdef USE_DISCARD
  362. if (base.a == 0.0)
  363. discard;
  364. #endif
  365. #ifdef USE_DISCARD_REF
  366. if (base.a < 0.5)
  367. discard;
  368. #endif
  369. color = base.rgb;
  370. vec4 col = vec4(color.rgb * varColor.rgb, 1.0);
  371. #ifdef ENABLE_DYNAMIC_SHADOWS
  372. // Fragment normal, can differ from vNormal which is derived from vertex normals.
  373. vec3 fNormal = vNormal;
  374. if (f_shadow_strength > 0.0) {
  375. float shadow_int = 0.0;
  376. vec3 shadow_color = vec3(0.0, 0.0, 0.0);
  377. vec3 posLightSpace = getLightSpacePosition();
  378. float distance_rate = (1.0 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 10.0));
  379. if (max(abs(posLightSpace.x - 0.5), abs(posLightSpace.y - 0.5)) > 0.5)
  380. distance_rate = 0.0;
  381. float f_adj_shadow_strength = max(adj_shadow_strength - mtsmoothstep(0.9, 1.1, posLightSpace.z),0.0);
  382. if (distance_rate > 1e-7) {
  383. #ifdef COLORED_SHADOWS
  384. vec4 visibility;
  385. if (cosLight > 0.0 || f_normal_length < 1e-3)
  386. visibility = getShadowColor(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
  387. else
  388. visibility = vec4(1.0, 0.0, 0.0, 0.0);
  389. shadow_int = visibility.r;
  390. shadow_color = visibility.gba;
  391. #else
  392. if (cosLight > 0.0 || f_normal_length < 1e-3)
  393. shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
  394. else
  395. shadow_int = 1.0;
  396. #endif
  397. shadow_int *= distance_rate;
  398. shadow_int = clamp(shadow_int, 0.0, 1.0);
  399. }
  400. // turns out that nightRatio falls off much faster than
  401. // actual brightness of artificial light in relation to natual light.
  402. // Power ratio was measured on torches in MTG (brightness = 14).
  403. float adjusted_night_ratio = pow(max(0.0, nightRatio), 0.6);
  404. float shadow_uncorrected = shadow_int;
  405. // Apply self-shadowing when light falls at a narrow angle to the surface
  406. // Cosine of the cut-off angle.
  407. const float self_shadow_cutoff_cosine = 0.035;
  408. if (f_normal_length != 0 && cosLight < self_shadow_cutoff_cosine) {
  409. shadow_int = max(shadow_int, 1 - clamp(cosLight, 0.0, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine);
  410. shadow_color = mix(vec3(0.0), shadow_color, min(cosLight, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine);
  411. #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES || MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS)
  412. // Prevents foliage from becoming insanely bright outside the shadow map.
  413. shadow_uncorrected = mix(shadow_int, shadow_uncorrected, clamp(distance_rate * 4.0 - 3.0, 0.0, 1.0));
  414. #endif
  415. }
  416. shadow_int *= f_adj_shadow_strength;
  417. // calculate fragment color from components:
  418. col.rgb =
  419. adjusted_night_ratio * col.rgb + // artificial light
  420. (1.0 - adjusted_night_ratio) * ( // natural light
  421. col.rgb * (1.0 - shadow_int * (1.0 - shadow_color) * (1.0 - shadow_tint)) + // filtered texture color
  422. dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight
  423. vec3 reflect_ray = -normalize(v_LightDirection - fNormal * dot(v_LightDirection, fNormal) * 2.0);
  424. vec3 viewVec = normalize(worldPosition + cameraOffset - cameraPosition);
  425. // Water reflections
  426. #if (defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS) && ENABLE_WAVING_WATER)
  427. vec3 wavePos = worldPosition * vec3(2.0, 0.0, 2.0);
  428. float off = animationTimer * WATER_WAVE_SPEED * 10.0;
  429. wavePos.x /= WATER_WAVE_LENGTH * 3.0;
  430. wavePos.z /= WATER_WAVE_LENGTH * 2.0;
  431. // This is an analogous method to the bumpmap, except we get the gradient information directly from gnoise.
  432. vec2 gradient = wave_noise(wavePos, off);
  433. fNormal = normalize(normalize(fNormal) + vec3(gradient.x, 0., gradient.y) * WATER_WAVE_HEIGHT * abs(fNormal.y) * 0.25);
  434. reflect_ray = -normalize(v_LightDirection - fNormal * dot(v_LightDirection, fNormal) * 2.0);
  435. float fresnel_factor = dot(fNormal, viewVec);
  436. float brightness_factor = 1.0 - adjusted_night_ratio;
  437. // A little trig hack. We go from the dot product of viewVec and normal to the dot product of viewVec and tangent to apply a fresnel effect.
  438. fresnel_factor = clamp(pow(1.0 - fresnel_factor * fresnel_factor, 8.0), 0.0, 1.0) * 0.8 + 0.2;
  439. col.rgb *= 0.5;
  440. vec3 reflection_color = mix(vec3(max(fogColor.r, max(fogColor.g, fogColor.b))), fogColor.rgb, f_shadow_strength);
  441. // Sky reflection
  442. col.rgb += reflection_color * pow(fresnel_factor, 2.0) * 0.5 * brightness_factor;
  443. vec3 water_reflect_color = 12.0 * dayLight * fresnel_factor * mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0)) * max(1.0 - shadow_uncorrected, 0.0);
  444. // This line exists to prevent ridiculously bright reflection colors.
  445. water_reflect_color /= clamp(max(water_reflect_color.r, max(water_reflect_color.g, water_reflect_color.b)) * 0.375, 1.0, 400.0);
  446. col.rgb += water_reflect_color * f_adj_shadow_strength * brightness_factor;
  447. #endif
  448. #if (defined(ENABLE_NODE_SPECULAR) && !defined(MATERIAL_WAVING_LIQUID))
  449. // Apply specular to blocks.
  450. if (dot(v_LightDirection, vNormal) < 0.0) {
  451. float intensity = 2.0 * (1.0 - (base.r * varColor.r));
  452. const float specular_exponent = 5.0;
  453. const float fresnel_exponent = 4.0;
  454. col.rgb +=
  455. intensity * dayLight * (1.0 - nightRatio) * (1.0 - shadow_uncorrected) * f_adj_shadow_strength *
  456. pow(max(dot(reflect_ray, viewVec), 0.0), fresnel_exponent) * pow(1.0 - abs(dot(viewVec, fNormal)), specular_exponent);
  457. }
  458. #endif
  459. #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES) && defined(ENABLE_TRANSLUCENT_FOLIAGE)
  460. // Simulate translucent foliage.
  461. col.rgb += 4.0 * dayLight * base.rgb * normalize(base.rgb * varColor.rgb * varColor.rgb) * f_adj_shadow_strength * pow(max(-dot(v_LightDirection, viewVec), 0.0), 4.0) * max(1.0 - shadow_uncorrected, 0.0);
  462. #endif
  463. }
  464. #endif
  465. // Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?),
  466. // the fog will only be rendered correctly if the last operation before the
  467. // clamp() is an addition. Else, the clamp() seems to be ignored.
  468. // E.g. the following won't work:
  469. // float clarity = clamp(fogShadingParameter
  470. // * (fogDistance - length(eyeVec)) / fogDistance), 0.0, 1.0);
  471. // As additions usually come for free following a multiplication, the new formula
  472. // should be more efficient as well.
  473. // Note: clarity = (1 - fogginess)
  474. float clarity = clamp(fogShadingParameter
  475. - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
  476. float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b);
  477. // Prevent zero division.
  478. if (fogColorMax < 0.0000001) fogColorMax = 1.0;
  479. // For high clarity (light fog) we tint the fog color.
  480. // For this to not make the fog color artificially dark we need to normalize using the
  481. // fog color's brightest value. We then blend our base color with this to make the fog.
  482. col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity);
  483. col = vec4(col.rgb, base.a);
  484. gl_FragData[0] = col;
  485. }