addshadow.frag 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * Copyright (C) 2020, Inria
  3. * GRAPHDECO research group, https://team.inria.fr/graphdeco
  4. * All rights reserved.
  5. *
  6. * This software is free for non-commercial, research and evaluation use
  7. * under the terms of the LICENSE.md file.
  8. *
  9. * For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
  10. */
  11. #version 420
  12. #define SHADOWPOWER_METHOD_ESTIM 1
  13. #define SHADOWPOWER_METHOD_3D 2
  14. #define SHADOWPOWER_METHOD_ESTIM_NONLINEAR 3
  15. #define SHADOWPOWER_METHOD SHADOWPOWER_METHOD_ESTIM
  16. layout(binding = 0) uniform sampler2D tex;
  17. layout(binding = 1) uniform sampler2D firstPassRT; /// \todo TODO: use ping pong buffering to update it with the last add
  18. uniform mat4 in_inv_proj;
  19. uniform vec2 in_image_size;
  20. layout(location= 0) out vec4 out_color;
  21. in vec2 tex_coord;
  22. //const float blurSize = 1.0 / 1000.0;
  23. const float constFgAdditionalOffset = -0.02; // note it should not be linear because of near/far+proj
  24. const float constSmoothShadowDistAtten = 8.0;
  25. vec3 unproject(vec3 xyd, mat4 inv_proj) {
  26. vec4 pxl = vec4(xyd,1.0)*vec4(2.0)-vec4(1.0); // [0,1] -> [-1,1]
  27. vec4 obj = inv_proj * pxl; // unproject
  28. return (obj.xyz/obj.w);
  29. }
  30. float smoothShadowDist( float dist01 )
  31. {
  32. float v = 1.0 - max(0.0, min(1.0, dist01) );
  33. return exp(log(v)*constSmoothShadowDistAtten);
  34. }
  35. void main(void) {
  36. //===========================================================================//
  37. // //
  38. // Adding Shadow //
  39. // //
  40. //===========================================================================//
  41. {
  42. const float scanSizeX = (1.0 / in_image_size.x)*4.0; /// \todo TODO: should be split into H and W and use image size
  43. const float scanSizeY = (1.0 / in_image_size.y)*4.0; /// \todo TODO: should be split into H and W and use image size
  44. vec4 bg = texture(firstPassRT,tex_coord); // background color
  45. vec4 fg = texture(tex,tex_coord); // foreground color (object to add)
  46. float bgDepth = bg.a;
  47. float outDepth = bgDepth;
  48. float fgDepth = fg.a+constFgAdditionalOffset;
  49. // By default set output values using bg
  50. out_color = vec4(bg.rgb, 1.0);
  51. //out_color = vec4(bg.a, 0.0, 0.0, 1.0);
  52. //gl_FragDepth = bgDepth;
  53. bool fgIsEmpty = (fg.r == 0 && fg.g == 0 && fg.b == 0);
  54. /// gl_FragDepth = 0;
  55. if (fgIsEmpty == false)
  56. {
  57. out_color = vec4(fg.rgb, (bgDepth <= fgDepth)? 0.0 : 1.0);
  58. //fgDepth = bgDepth;
  59. outDepth = (bgDepth <= fgDepth)? bgDepth : fgDepth;
  60. //gl_FragDepth = fgDepth;
  61. /// out_color = vec4(fg.a, 0.0, 0.0, 1.0);
  62. }
  63. else
  64. {
  65. // Scan for non-empty pixels for determining the power
  66. // of the shadow.
  67. // 'non-empty' pixels are FULL black pixels
  68. const int scanItCount = 8;
  69. const int maxScanablePixels = (scanItCount*2 + 1)*(scanItCount*2 + 1);
  70. const float maxAxisX = (scanItCount*2 + 1)*scanSizeX;
  71. const float maxAxisY = (scanItCount*2 + 1)*scanSizeY;
  72. const float maxScanDist = maxAxisX*maxAxisX + maxAxisY*maxAxisY;
  73. float nearestDist = maxScanDist*2.0;//maxScanDist + 1.0;
  74. float nearestXs = 1.0;
  75. float nearestYs = 1.0;
  76. float nearestDepth = 0.0;
  77. float averageBgDepth = 0.0;
  78. float nonEmptyPixelFound = 0;
  79. for (int x = -scanItCount; x <= scanItCount; x++)
  80. {
  81. for (int y = -scanItCount; y <= scanItCount; y++)
  82. {
  83. float xs = x*scanSizeX;
  84. float ys = y*scanSizeY;
  85. float dist = (xs*xs + ys*ys);
  86. vec4 color = texture(tex, vec2(tex_coord.x+xs, tex_coord.y+ys));
  87. float sampleDepth = color.a+constFgAdditionalOffset;
  88. averageBgDepth += sampleDepth;
  89. if ( (color.r == 0 && color.g == 0 && color.b == 0) == false
  90. //// [A] this one will cause you trouble with object in front of your shadow caster
  91. // )
  92. //// [B] this one will prevent you from casting shadow in front of your object
  93. //// but visually, you can make it fly a bit and it look like the under is in front
  94. && sampleDepth <= bgDepth )
  95. //// [C] this one is the best in fidelity but requires a call to texture(...)
  96. // && sampleDepth <= texture(firstPassRT, vec2(tex_coord.x+xs, tex_coord.y+ys)).a)
  97. {
  98. if (dist < nearestDist)
  99. {
  100. nearestXs = xs;
  101. nearestYs = ys;
  102. // nearestDist = dist;
  103. // nearestDepth = sampleDepth;
  104. }
  105. //nearestXs = min(xs, nearestXs);
  106. //nearestYs = min(ys, nearestYs); // note that stored nearestXs/Ys might stores an unexisting coordinate pair
  107. nearestDist = min(nearestDist, dist);
  108. nearestDepth += sampleDepth;//max(nearestDepth, sampleDepth);
  109. ++nonEmptyPixelFound;
  110. averageBgDepth -= sampleDepth; // cancel this in this case
  111. }
  112. }
  113. }
  114. nearestDepth = nearestDepth/float(nonEmptyPixelFound);
  115. averageBgDepth = averageBgDepth/float(maxScanablePixels-nonEmptyPixelFound);
  116. //if (nearestDist > 0)
  117. {
  118. // Compute the shadow power
  119. float shadowPower = 1.0;
  120. float ratioNonEmptyPixelFound = float(nonEmptyPixelFound) / float(maxScanablePixels);
  121. // influence of the caster size
  122. shadowPower *= smoothstep(0.0, 0.5, ratioNonEmptyPixelFound);
  123. //if (nonEmptyPixelFound < 100)
  124. // shadowPower = 0.0;
  125. //shadowPower *= max(0.0, min(1.0, nonEmptyPixelFound/minPixelCaster ));
  126. // Dev Note for improving things
  127. // There are two way to implement the influence of the shadow caster/receiver distance.
  128. // [3d solution]
  129. // - one is to unproject both points and measure their distance in 3d world unit
  130. // [estim solution]
  131. // - another one is roughly estimate the effect
  132. #if SHADOWPOWER_METHOD == SHADOWPOWER_METHOD_ESTIM_NONLINEAR
  133. // [estim solution]
  134. // influence of the distance to the object that cast this shadow (slightly improve but not enough)
  135. //shadowPower *= smoothShadowDist(nearestDist/maxScanDist);
  136. // influence of the depth distance
  137. const float maxDiffDepth = 0.04;//0.15; // because it's nonlinear, it will react differently depending on Z (and your dataset clipping planes's near/far)
  138. float diffDepth = bgDepth-nearestDepth;
  139. diffDepth = diffDepth / maxDiffDepth;
  140. float depthFactor = clamp(diffDepth, 0.0, 1.0);
  141. shadowPower *= (1.0 - depthFactor);
  142. #endif
  143. #if SHADOWPOWER_METHOD == SHADOWPOWER_METHOD_ESTIM
  144. // [estim solution]
  145. // influence of the distance to the object that cast this shadow (slightly improve but not enough)
  146. //shadowPower *= smoothShadowDist(nearestDist/maxScanDist);
  147. // influence of the depth distance
  148. const float maxDist = 0.4; // in world unit
  149. vec3 bg2dPos = vec3(tex_coord.xy, bgDepth);
  150. vec3 bg3dPos = unproject(bg2dPos, in_inv_proj);
  151. vec3 caster2dPos = vec3(vec2(tex_coord.x+nearestXs, tex_coord.y+nearestYs), nearestDepth);
  152. vec3 caster3dPos = unproject(caster2dPos, in_inv_proj);
  153. float line = abs(caster3dPos.z-bg3dPos.z);
  154. float factorDist = 1.0 - max(0.0, min(1.0, line/maxDist) );
  155. shadowPower *= factorDist;
  156. #endif
  157. #if SHADOWPOWER_METHOD == SHADOWPOWER_METHOD_3D
  158. // [3d solution]
  159. // influence of the shadow receiver distance
  160. const float maxDist = 0.25; // in world unit
  161. const float maxDistSqr = maxDist*maxDist;
  162. vec3 bg2dPos = vec3(tex_coord.xy, bgDepth);
  163. vec3 bg3dPos = unproject(bg2dPos, in_inv_proj);
  164. vec3 caster2dPos = vec3(vec2(tex_coord.x+nearestXs, tex_coord.y+nearestYs), nearestDepth);
  165. vec3 caster3dPos = unproject(caster2dPos, in_inv_proj);
  166. vec3 line = caster3dPos-bg3dPos;
  167. float distSqr = line.x*line.x + line.y*line.y + line.z*line.z;
  168. float factorDist = 1.0 - max(0.0, min(1.0, distSqr/maxDistSqr) );
  169. shadowPower *= factorDist;
  170. #endif
  171. out_color = vec4(0, 0, 0, shadowPower / 1.5);
  172. // //out_color = vec4(fgZ/10.0, 0, 0, 1.0);
  173. // float nearPlane = 3.23569;
  174. // float farPlane = 17.1543;
  175. // //bgZ = (bg2dPos.z * bg2dPos.w - nearPlane) / (farPlane - nearPlane);
  176. // out_color = vec4(bg2dPos.z/farPlane, 0, 0, 1.0);
  177. //out_color = vec4(bgDepth, 0, 0, 1.0);
  178. //gl_FragDepth = nearestDepth;
  179. //gl_FragDepth = bgDepth + constFgAdditionalOffset - 1;
  180. float newDepth = bgDepth;// + constFgAdditionalOffset;
  181. outDepth = (newDepth <= bgDepth)? newDepth : bgDepth;
  182. }
  183. // if (nearestDist < 1.0)
  184. // {
  185. // out_color = vec4(nearestDepth, 0.0, 0.0, 1.0);
  186. // gl_FragDepth = 0;
  187. // }
  188. }
  189. // Simulate BLEND function (GL_ONE_MINUS_SRC_ALPHA)
  190. //out_color = vec4(bg.xyz + out_color.xyz/out_color.a, gl_FragDepth);
  191. out_color = vec4(bg.xyz*(1.0 - out_color.a) + out_color.xyz*out_color.a, outDepth);
  192. //gl_FragDepth = outDepth;
  193. //out_color = bg;
  194. }
  195. }