opengl_fragment.glsl 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. uniform sampler2D baseTexture;
  2. uniform vec3 dayLight;
  3. uniform vec4 skyBgColor;
  4. uniform float fogDistance;
  5. uniform vec3 eyePosition;
  6. // The cameraOffset is the current center of the visible world.
  7. uniform vec3 cameraOffset;
  8. uniform float animationTimer;
  9. #ifdef ENABLE_DYNAMIC_SHADOWS
  10. // shadow texture
  11. uniform sampler2D ShadowMapSampler;
  12. // shadow uniforms
  13. uniform vec3 v_LightDirection;
  14. uniform float f_textureresolution;
  15. uniform mat4 m_ShadowViewProj;
  16. uniform float f_shadowfar;
  17. uniform float f_shadow_strength;
  18. uniform vec4 CameraPos;
  19. uniform float xyPerspectiveBias0;
  20. uniform float xyPerspectiveBias1;
  21. varying float adj_shadow_strength;
  22. varying float cosLight;
  23. varying float f_normal_length;
  24. varying vec3 shadow_position;
  25. varying float perspective_factor;
  26. #endif
  27. varying vec3 vNormal;
  28. varying vec3 vPosition;
  29. // World position in the visible world (i.e. relative to the cameraOffset.)
  30. // This can be used for many shader effects without loss of precision.
  31. // If the absolute position is required it can be calculated with
  32. // cameraOffset + worldPosition (for large coordinates the limits of float
  33. // precision must be considered).
  34. varying vec3 worldPosition;
  35. varying lowp vec4 varColor;
  36. #ifdef GL_ES
  37. varying mediump vec2 varTexCoord;
  38. #else
  39. centroid varying vec2 varTexCoord;
  40. #endif
  41. varying vec3 eyeVec;
  42. varying float nightRatio;
  43. varying float vIDiff;
  44. const float fogStart = FOG_START;
  45. const float fogShadingParameter = 1.0 / (1.0 - fogStart);
  46. #ifdef ENABLE_DYNAMIC_SHADOWS
  47. // assuming near is always 1.0
  48. float getLinearDepth()
  49. {
  50. return 2.0 * f_shadowfar / (f_shadowfar + 1.0 - (2.0 * gl_FragCoord.z - 1.0) * (f_shadowfar - 1.0));
  51. }
  52. vec3 getLightSpacePosition()
  53. {
  54. return shadow_position * 0.5 + 0.5;
  55. }
  56. // custom smoothstep implementation because it's not defined in glsl1.2
  57. // https://docs.gl/sl4/smoothstep
  58. float mtsmoothstep(in float edge0, in float edge1, in float x)
  59. {
  60. float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
  61. return t * t * (3.0 - 2.0 * t);
  62. }
  63. #ifdef COLORED_SHADOWS
  64. // c_precision of 128 fits within 7 base-10 digits
  65. const float c_precision = 128.0;
  66. const float c_precisionp1 = c_precision + 1.0;
  67. float packColor(vec3 color)
  68. {
  69. return floor(color.b * c_precision + 0.5)
  70. + floor(color.g * c_precision + 0.5) * c_precisionp1
  71. + floor(color.r * c_precision + 0.5) * c_precisionp1 * c_precisionp1;
  72. }
  73. vec3 unpackColor(float value)
  74. {
  75. vec3 color;
  76. color.b = mod(value, c_precisionp1) / c_precision;
  77. color.g = mod(floor(value / c_precisionp1), c_precisionp1) / c_precision;
  78. color.r = floor(value / (c_precisionp1 * c_precisionp1)) / c_precision;
  79. return color;
  80. }
  81. vec4 getHardShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  82. {
  83. vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy).rgba;
  84. float visibility = step(0.0, realDistance - texDepth.r);
  85. vec4 result = vec4(visibility, vec3(0.0,0.0,0.0));//unpackColor(texDepth.g));
  86. if (visibility < 0.1) {
  87. visibility = step(0.0, realDistance - texDepth.b);
  88. result = vec4(visibility, unpackColor(texDepth.a));
  89. }
  90. return result;
  91. }
  92. #else
  93. float getHardShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  94. {
  95. float texDepth = texture2D(shadowsampler, smTexCoord.xy).r;
  96. float visibility = step(0.0, realDistance - texDepth);
  97. return visibility;
  98. }
  99. #endif
  100. #if SHADOW_FILTER == 2
  101. #define PCFBOUND 2.0 // 5x5
  102. #define PCFSAMPLES 25
  103. #elif SHADOW_FILTER == 1
  104. #define PCFBOUND 1.0 // 3x3
  105. #define PCFSAMPLES 9
  106. #else
  107. #define PCFBOUND 0.0
  108. #define PCFSAMPLES 1
  109. #endif
  110. #ifdef COLORED_SHADOWS
  111. float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  112. {
  113. vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy);
  114. float depth = max(realDistance - texDepth.r, realDistance - texDepth.b);
  115. return depth;
  116. }
  117. #else
  118. float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  119. {
  120. float texDepth = texture2D(shadowsampler, smTexCoord.xy).r;
  121. float depth = realDistance - texDepth;
  122. return depth;
  123. }
  124. #endif
  125. #define BASEFILTERRADIUS 1.0
  126. float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  127. {
  128. // Return fast if sharp shadows are requested
  129. if (PCFBOUND == 0.0 || SOFTSHADOWRADIUS <= 0.0)
  130. return 0.0;
  131. vec2 clampedpos;
  132. float y, x;
  133. float depth = getHardShadowDepth(shadowsampler, smTexCoord.xy, realDistance);
  134. // A factor from 0 to 1 to reduce blurring of short shadows
  135. float sharpness_factor = 1.0;
  136. // conversion factor from shadow depth to blur radius
  137. float depth_to_blur = f_shadowfar / SOFTSHADOWRADIUS / xyPerspectiveBias0;
  138. if (depth > 0.0 && f_normal_length > 0.0)
  139. // 5 is empirical factor that controls how fast shadow loses sharpness
  140. sharpness_factor = clamp(5 * depth * depth_to_blur, 0.0, 1.0);
  141. depth = 0.0;
  142. float world_to_texture = xyPerspectiveBias1 / perspective_factor / perspective_factor
  143. * f_textureresolution / 2.0 / f_shadowfar;
  144. float world_radius = 0.2; // shadow blur radius in world float coordinates, e.g. 0.2 = 0.02 of one node
  145. return max(BASEFILTERRADIUS * f_textureresolution / 4096.0, sharpness_factor * world_radius * world_to_texture * SOFTSHADOWRADIUS);
  146. }
  147. #ifdef POISSON_FILTER
  148. const vec2[64] poissonDisk = vec2[64](
  149. vec2(0.170019, -0.040254),
  150. vec2(-0.299417, 0.791925),
  151. vec2(0.645680, 0.493210),
  152. vec2(-0.651784, 0.717887),
  153. vec2(0.421003, 0.027070),
  154. vec2(-0.817194, -0.271096),
  155. vec2(-0.705374, -0.668203),
  156. vec2(0.977050, -0.108615),
  157. vec2(0.063326, 0.142369),
  158. vec2(0.203528, 0.214331),
  159. vec2(-0.667531, 0.326090),
  160. vec2(-0.098422, -0.295755),
  161. vec2(-0.885922, 0.215369),
  162. vec2(0.566637, 0.605213),
  163. vec2(0.039766, -0.396100),
  164. vec2(0.751946, 0.453352),
  165. vec2(0.078707, -0.715323),
  166. vec2(-0.075838, -0.529344),
  167. vec2(0.724479, -0.580798),
  168. vec2(0.222999, -0.215125),
  169. vec2(-0.467574, -0.405438),
  170. vec2(-0.248268, -0.814753),
  171. vec2(0.354411, -0.887570),
  172. vec2(0.175817, 0.382366),
  173. vec2(0.487472, -0.063082),
  174. vec2(0.355476, 0.025357),
  175. vec2(-0.084078, 0.898312),
  176. vec2(0.488876, -0.783441),
  177. vec2(0.470016, 0.217933),
  178. vec2(-0.696890, -0.549791),
  179. vec2(-0.149693, 0.605762),
  180. vec2(0.034211, 0.979980),
  181. vec2(0.503098, -0.308878),
  182. vec2(-0.016205, -0.872921),
  183. vec2(0.385784, -0.393902),
  184. vec2(-0.146886, -0.859249),
  185. vec2(0.643361, 0.164098),
  186. vec2(0.634388, -0.049471),
  187. vec2(-0.688894, 0.007843),
  188. vec2(0.464034, -0.188818),
  189. vec2(-0.440840, 0.137486),
  190. vec2(0.364483, 0.511704),
  191. vec2(0.034028, 0.325968),
  192. vec2(0.099094, -0.308023),
  193. vec2(0.693960, -0.366253),
  194. vec2(0.678884, -0.204688),
  195. vec2(0.001801, 0.780328),
  196. vec2(0.145177, -0.898984),
  197. vec2(0.062655, -0.611866),
  198. vec2(0.315226, -0.604297),
  199. vec2(-0.780145, 0.486251),
  200. vec2(-0.371868, 0.882138),
  201. vec2(0.200476, 0.494430),
  202. vec2(-0.494552, -0.711051),
  203. vec2(0.612476, 0.705252),
  204. vec2(-0.578845, -0.768792),
  205. vec2(-0.772454, -0.090976),
  206. vec2(0.504440, 0.372295),
  207. vec2(0.155736, 0.065157),
  208. vec2(0.391522, 0.849605),
  209. vec2(-0.620106, -0.328104),
  210. vec2(0.789239, -0.419965),
  211. vec2(-0.545396, 0.538133),
  212. vec2(-0.178564, -0.596057)
  213. );
  214. #ifdef COLORED_SHADOWS
  215. vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  216. {
  217. float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
  218. if (radius < 0.1) {
  219. // we are in the middle of even brightness, no need for filtering
  220. return getHardShadowColor(shadowsampler, smTexCoord.xy, realDistance);
  221. }
  222. vec2 clampedpos;
  223. vec4 visibility = vec4(0.0);
  224. float scale_factor = radius / f_textureresolution;
  225. int samples = (1 + 1 * int(SOFTSHADOWRADIUS > 1.0)) * PCFSAMPLES; // scale max samples for the soft shadows
  226. samples = int(clamp(pow(4.0 * radius + 1.0, 2.0), 1.0, float(samples)));
  227. int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-samples)));
  228. int end_offset = int(samples) + init_offset;
  229. for (int x = init_offset; x < end_offset; x++) {
  230. clampedpos = poissonDisk[x] * scale_factor + smTexCoord.xy;
  231. visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
  232. }
  233. return visibility / samples;
  234. }
  235. #else
  236. float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  237. {
  238. float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
  239. if (radius < 0.1) {
  240. // we are in the middle of even brightness, no need for filtering
  241. return getHardShadow(shadowsampler, smTexCoord.xy, realDistance);
  242. }
  243. vec2 clampedpos;
  244. float visibility = 0.0;
  245. float scale_factor = radius / f_textureresolution;
  246. int samples = (1 + 1 * int(SOFTSHADOWRADIUS > 1.0)) * PCFSAMPLES; // scale max samples for the soft shadows
  247. samples = int(clamp(pow(4.0 * radius + 1.0, 2.0), 1.0, float(samples)));
  248. int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-samples)));
  249. int end_offset = int(samples) + init_offset;
  250. for (int x = init_offset; x < end_offset; x++) {
  251. clampedpos = poissonDisk[x] * scale_factor + smTexCoord.xy;
  252. visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
  253. }
  254. return visibility / samples;
  255. }
  256. #endif
  257. #else
  258. /* poisson filter disabled */
  259. #ifdef COLORED_SHADOWS
  260. vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  261. {
  262. float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
  263. if (radius < 0.1) {
  264. // we are in the middle of even brightness, no need for filtering
  265. return getHardShadowColor(shadowsampler, smTexCoord.xy, realDistance);
  266. }
  267. vec2 clampedpos;
  268. vec4 visibility = vec4(0.0);
  269. float x, y;
  270. float bound = (1 + 0.5 * int(SOFTSHADOWRADIUS > 1.0)) * PCFBOUND; // scale max bound for soft shadows
  271. bound = clamp(0.5 * (4.0 * radius - 1.0), 0.5, bound);
  272. float scale_factor = radius / bound / f_textureresolution;
  273. float n = 0.0;
  274. // basic PCF filter
  275. for (y = -bound; y <= bound; y += 1.0)
  276. for (x = -bound; x <= bound; x += 1.0) {
  277. clampedpos = vec2(x,y) * scale_factor + smTexCoord.xy;
  278. visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
  279. n += 1.0;
  280. }
  281. return visibility / max(n, 1.0);
  282. }
  283. #else
  284. float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
  285. {
  286. float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance);
  287. if (radius < 0.1) {
  288. // we are in the middle of even brightness, no need for filtering
  289. return getHardShadow(shadowsampler, smTexCoord.xy, realDistance);
  290. }
  291. vec2 clampedpos;
  292. float visibility = 0.0;
  293. float x, y;
  294. float bound = (1 + 0.5 * int(SOFTSHADOWRADIUS > 1.0)) * PCFBOUND; // scale max bound for soft shadows
  295. bound = clamp(0.5 * (4.0 * radius - 1.0), 0.5, bound);
  296. float scale_factor = radius / bound / f_textureresolution;
  297. float n = 0.0;
  298. // basic PCF filter
  299. for (y = -bound; y <= bound; y += 1.0)
  300. for (x = -bound; x <= bound; x += 1.0) {
  301. clampedpos = vec2(x,y) * scale_factor + smTexCoord.xy;
  302. visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
  303. n += 1.0;
  304. }
  305. return visibility / max(n, 1.0);
  306. }
  307. #endif
  308. #endif
  309. #endif
  310. #if ENABLE_TONE_MAPPING
  311. /* Hable's UC2 Tone mapping parameters
  312. A = 0.22;
  313. B = 0.30;
  314. C = 0.10;
  315. D = 0.20;
  316. E = 0.01;
  317. F = 0.30;
  318. W = 11.2;
  319. equation used: ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F
  320. */
  321. vec3 uncharted2Tonemap(vec3 x)
  322. {
  323. return ((x * (0.22 * x + 0.03) + 0.002) / (x * (0.22 * x + 0.3) + 0.06)) - 0.03333;
  324. }
  325. vec4 applyToneMapping(vec4 color)
  326. {
  327. color = vec4(pow(color.rgb, vec3(2.2)), color.a);
  328. const float gamma = 1.6;
  329. const float exposureBias = 5.5;
  330. color.rgb = uncharted2Tonemap(exposureBias * color.rgb);
  331. // Precalculated white_scale from
  332. //vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
  333. vec3 whiteScale = vec3(1.036015346);
  334. color.rgb *= whiteScale;
  335. return vec4(pow(color.rgb, vec3(1.0 / gamma)), color.a);
  336. }
  337. #endif
  338. void main(void)
  339. {
  340. vec3 color;
  341. vec2 uv = varTexCoord.st;
  342. vec4 base = texture2D(baseTexture, uv).rgba;
  343. // If alpha is zero, we can just discard the pixel. This fixes transparency
  344. // on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa,
  345. // and also on GLES 2, where GL_ALPHA_TEST is missing entirely.
  346. #ifdef USE_DISCARD
  347. if (base.a == 0.0)
  348. discard;
  349. #endif
  350. #ifdef USE_DISCARD_REF
  351. if (base.a < 0.5)
  352. discard;
  353. #endif
  354. color = base.rgb;
  355. vec4 col = vec4(color.rgb * varColor.rgb, 1.0);
  356. col.rgb *= vIDiff;
  357. #ifdef ENABLE_DYNAMIC_SHADOWS
  358. if (f_shadow_strength > 0.0) {
  359. float shadow_int = 0.0;
  360. vec3 shadow_color = vec3(0.0, 0.0, 0.0);
  361. vec3 posLightSpace = getLightSpacePosition();
  362. float distance_rate = (1.0 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 10.0));
  363. if (max(abs(posLightSpace.x - 0.5), abs(posLightSpace.y - 0.5)) > 0.5)
  364. distance_rate = 0.0;
  365. float f_adj_shadow_strength = max(adj_shadow_strength-mtsmoothstep(0.9,1.1, posLightSpace.z),0.0);
  366. if (distance_rate > 1e-7) {
  367. #ifdef COLORED_SHADOWS
  368. vec4 visibility;
  369. if (cosLight > 0.0 || f_normal_length < 1e-3)
  370. visibility = getShadowColor(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
  371. else
  372. visibility = vec4(1.0, 0.0, 0.0, 0.0);
  373. shadow_int = visibility.r;
  374. shadow_color = visibility.gba;
  375. #else
  376. if (cosLight > 0.0 || f_normal_length < 1e-3)
  377. shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
  378. else
  379. shadow_int = 1.0;
  380. #endif
  381. shadow_int *= distance_rate;
  382. shadow_int = clamp(shadow_int, 0.0, 1.0);
  383. }
  384. // turns out that nightRatio falls off much faster than
  385. // actual brightness of artificial light in relation to natual light.
  386. // Power ratio was measured on torches in MTG (brightness = 14).
  387. float adjusted_night_ratio = pow(max(0.0, nightRatio), 0.6);
  388. // Apply self-shadowing when light falls at a narrow angle to the surface
  389. // Cosine of the cut-off angle.
  390. const float self_shadow_cutoff_cosine = 0.14;
  391. if (f_normal_length != 0 && cosLight < self_shadow_cutoff_cosine) {
  392. shadow_int = max(shadow_int, 1 - clamp(cosLight, 0.0, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine);
  393. shadow_color = mix(vec3(0.0), shadow_color, min(cosLight, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine);
  394. }
  395. shadow_int *= f_adj_shadow_strength;
  396. // calculate fragment color from components:
  397. col.rgb =
  398. adjusted_night_ratio * col.rgb + // artificial light
  399. (1.0 - adjusted_night_ratio) * ( // natural light
  400. col.rgb * (1.0 - shadow_int * (1.0 - shadow_color)) + // filtered texture color
  401. dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight
  402. }
  403. #endif
  404. #if ENABLE_TONE_MAPPING
  405. col = applyToneMapping(col);
  406. #endif
  407. // Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?),
  408. // the fog will only be rendered correctly if the last operation before the
  409. // clamp() is an addition. Else, the clamp() seems to be ignored.
  410. // E.g. the following won't work:
  411. // float clarity = clamp(fogShadingParameter
  412. // * (fogDistance - length(eyeVec)) / fogDistance), 0.0, 1.0);
  413. // As additions usually come for free following a multiplication, the new formula
  414. // should be more efficient as well.
  415. // Note: clarity = (1 - fogginess)
  416. float clarity = clamp(fogShadingParameter
  417. - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
  418. col = mix(skyBgColor, col, clarity);
  419. col = vec4(col.rgb, base.a);
  420. gl_FragColor = col;
  421. }