PageRenderTime 55ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl

https://bitbucket.org/lindenlab/viewer-beta/
Unknown | 277 lines | 223 code | 54 blank | 0 comment | 0 complexity | 225c57643e04db8afed4b350a8590986 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file sunLightSSAOF.glsl
  3. * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  4. * Second Life Viewer Source Code
  5. * Copyright (C) 2007, Linden Research, Inc.
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation;
  10. * version 2.1 of the License only.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  22. * $/LicenseInfo$
  23. */
  24. #extension GL_ARB_texture_rectangle : enable
  25. #ifdef DEFINE_GL_FRAGCOLOR
  26. out vec4 gl_FragColor;
  27. #endif
  28. //class 2 -- shadows and SSAO
  29. uniform sampler2DRect depthMap;
  30. uniform sampler2DRect normalMap;
  31. uniform sampler2DRectShadow shadowMap0;
  32. uniform sampler2DRectShadow shadowMap1;
  33. uniform sampler2DRectShadow shadowMap2;
  34. uniform sampler2DRectShadow shadowMap3;
  35. uniform sampler2DShadow shadowMap4;
  36. uniform sampler2DShadow shadowMap5;
  37. uniform sampler2D noiseMap;
  38. // Inputs
  39. uniform mat4 shadow_matrix[6];
  40. uniform vec4 shadow_clip;
  41. uniform float ssao_radius;
  42. uniform float ssao_max_radius;
  43. uniform float ssao_factor;
  44. uniform float ssao_factor_inv;
  45. VARYING vec2 vary_fragcoord;
  46. uniform mat4 inv_proj;
  47. uniform vec2 screen_res;
  48. uniform vec2 shadow_res;
  49. uniform vec2 proj_shadow_res;
  50. uniform vec3 sun_dir;
  51. uniform float shadow_bias;
  52. uniform float shadow_offset;
  53. uniform float spot_shadow_bias;
  54. uniform float spot_shadow_offset;
  55. vec4 getPosition(vec2 pos_screen)
  56. {
  57. float depth = texture2DRect(depthMap, pos_screen.xy).r;
  58. vec2 sc = pos_screen.xy*2.0;
  59. sc /= screen_res;
  60. sc -= vec2(1.0,1.0);
  61. vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
  62. vec4 pos = inv_proj * ndc;
  63. pos /= pos.w;
  64. pos.w = 1.0;
  65. return pos;
  66. }
  67. vec2 getKern(int i)
  68. {
  69. vec2 kern[8];
  70. // exponentially (^2) distant occlusion samples spread around origin
  71. kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
  72. kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
  73. kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
  74. kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
  75. kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
  76. kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
  77. kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
  78. kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
  79. return kern[i];
  80. }
  81. //calculate decreases in ambient lighting when crowded out (SSAO)
  82. float calcAmbientOcclusion(vec4 pos, vec3 norm)
  83. {
  84. float ret = 1.0;
  85. vec2 pos_screen = vary_fragcoord.xy;
  86. vec3 pos_world = pos.xyz;
  87. vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
  88. float angle_hidden = 0.0;
  89. float points = 0;
  90. float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
  91. // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
  92. for (int i = 0; i < 8; i++)
  93. {
  94. vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
  95. vec3 samppos_world = getPosition(samppos_screen).xyz;
  96. vec3 diff = pos_world - samppos_world;
  97. float dist2 = dot(diff, diff);
  98. // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
  99. // --> solid angle shrinking by the square of distance
  100. //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
  101. //(k should vary inversely with # of samples, but this is taken care of later)
  102. float funky_val = (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) ? 1.0 : 0.0;
  103. angle_hidden = angle_hidden + funky_val * min(1.0/dist2, ssao_factor_inv);
  104. // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
  105. float diffz_val = (diff.z > -1.0) ? 1.0 : 0.0;
  106. points = points + diffz_val;
  107. }
  108. angle_hidden = min(ssao_factor*angle_hidden/points, 1.0);
  109. float points_val = (points > 0.0) ? 1.0 : 0.0;
  110. ret = (1.0 - (points_val * angle_hidden));
  111. ret = max(ret, 0.0);
  112. return min(ret, 1.0);
  113. }
  114. float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
  115. {
  116. stc.xyz /= stc.w;
  117. stc.z += shadow_bias*scl;
  118. float cs = shadow2DRect(shadowMap, stc.xyz).x;
  119. float shadow = cs;
  120. shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs);
  121. shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs);
  122. shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs);
  123. shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs);
  124. return shadow/5.0;
  125. //return shadow;
  126. }
  127. float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl)
  128. {
  129. stc.xyz /= stc.w;
  130. stc.z += spot_shadow_bias*scl;
  131. float cs = shadow2D(shadowMap, stc.xyz).x;
  132. float shadow = cs;
  133. vec2 off = 1.5/proj_shadow_res;
  134. shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs);
  135. shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs);
  136. shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs);
  137. shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs);
  138. return shadow/5.0;
  139. //return shadow;
  140. }
  141. void main()
  142. {
  143. vec2 pos_screen = vary_fragcoord.xy;
  144. //try doing an unproject here
  145. vec4 pos = getPosition(pos_screen);
  146. vec4 nmap4 = texture2DRect(normalMap, pos_screen);
  147. nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm
  148. float displace = nmap4.w;
  149. vec3 norm = nmap4.xyz;
  150. /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
  151. {
  152. gl_FragColor = vec4(0.0); // doesn't matter
  153. return;
  154. }*/
  155. float shadow = 1.0;
  156. float dp_directional_light = max(0.0, dot(norm, sun_dir.xyz));
  157. vec3 shadow_pos = pos.xyz + displace*norm;
  158. vec3 offset = sun_dir.xyz * (1.0-dp_directional_light);
  159. vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0);
  160. if (spos.z > -shadow_clip.w)
  161. {
  162. if (dp_directional_light == 0.0)
  163. {
  164. // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup
  165. shadow = 0.0;
  166. }
  167. else
  168. {
  169. vec4 lpos;
  170. if (spos.z < -shadow_clip.z)
  171. {
  172. lpos = shadow_matrix[3]*spos;
  173. lpos.xy *= shadow_res;
  174. shadow = pcfShadow(shadowMap3, lpos, 0.25);
  175. shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
  176. }
  177. else if (spos.z < -shadow_clip.y)
  178. {
  179. lpos = shadow_matrix[2]*spos;
  180. lpos.xy *= shadow_res;
  181. shadow = pcfShadow(shadowMap2, lpos, 0.5);
  182. }
  183. else if (spos.z < -shadow_clip.x)
  184. {
  185. lpos = shadow_matrix[1]*spos;
  186. lpos.xy *= shadow_res;
  187. shadow = pcfShadow(shadowMap1, lpos, 0.75);
  188. }
  189. else
  190. {
  191. lpos = shadow_matrix[0]*spos;
  192. lpos.xy *= shadow_res;
  193. shadow = pcfShadow(shadowMap0, lpos, 1.0);
  194. }
  195. // take the most-shadowed value out of these two:
  196. // * the blurred sun shadow in the light (shadow) map
  197. // * an unblurred dot product between the sun and this norm
  198. // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
  199. shadow = min(shadow, dp_directional_light);
  200. //lpos.xy /= lpos.w*32.0;
  201. //if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1)
  202. //{
  203. // shadow = 0.0;
  204. //}
  205. }
  206. }
  207. else
  208. {
  209. // more distant than the shadow map covers
  210. shadow = 1.0;
  211. }
  212. gl_FragColor[0] = shadow;
  213. gl_FragColor[1] = calcAmbientOcclusion(pos, norm);
  214. spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0);
  215. //spotlight shadow 1
  216. vec4 lpos = shadow_matrix[4]*spos;
  217. gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8);
  218. //spotlight shadow 2
  219. lpos = shadow_matrix[5]*spos;
  220. gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8);
  221. //gl_FragColor.rgb = pos.xyz;
  222. //gl_FragColor.b = shadow;
  223. }