PageRenderTime 22ms CodeModel.GetById 13ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 1ms

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

https://bitbucket.org/lindenlab/viewer-beta/
text | 258 lines | 206 code | 52 blank | 0 comment | 0 complexity | c9ceb804a7aaccf3b19fe840b4ff63e9 MD5 | raw file
  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 
 25
 26
 27#extension GL_ARB_texture_rectangle : enable
 28#extension GL_ARB_texture_multisample : enable
 29
 30//class 2 -- shadows and SSAO
 31
 32uniform sampler2DMS depthMap;
 33uniform sampler2DMS normalMap;
 34uniform sampler2DRectShadow shadowMap0;
 35uniform sampler2DRectShadow shadowMap1;
 36uniform sampler2DRectShadow shadowMap2;
 37uniform sampler2DRectShadow shadowMap3;
 38uniform sampler2DShadow shadowMap4;
 39uniform sampler2DShadow shadowMap5;
 40uniform sampler2D noiseMap;
 41
 42// Inputs
 43uniform mat4 shadow_matrix[6];
 44uniform vec4 shadow_clip;
 45uniform float ssao_radius;
 46uniform float ssao_max_radius;
 47uniform float ssao_factor;
 48uniform float ssao_factor_inv;
 49
 50varying vec2 vary_fragcoord;
 51varying vec4 vary_light;
 52
 53uniform mat4 inv_proj;
 54uniform vec2 screen_res;
 55uniform vec2 shadow_res;
 56uniform vec2 proj_shadow_res;
 57
 58uniform float shadow_bias;
 59uniform float shadow_offset;
 60
 61uniform float spot_shadow_bias;
 62uniform float spot_shadow_offset;
 63
 64vec4 getPosition(ivec2 pos_screen, int sample)
 65{
 66	float depth = texelFetch(depthMap, pos_screen, sample).r;
 67	vec2 sc = vec2(pos_screen.xy)*2.0;
 68	sc /= screen_res;
 69	sc -= vec2(1.0,1.0);
 70	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
 71	vec4 pos = inv_proj * ndc;
 72	pos /= pos.w;
 73	pos.w = 1.0;
 74	return pos;
 75}
 76
 77//calculate decreases in ambient lighting when crowded out (SSAO)
 78float calcAmbientOcclusion(vec4 pos, vec3 norm, int sample)
 79{
 80	float ret = 1.0;
 81
 82	vec2 kern[8];
 83	// exponentially (^2) distant occlusion samples spread around origin
 84	kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
 85	kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
 86	kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
 87	kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
 88	kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
 89	kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
 90	kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
 91	kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
 92
 93	vec2 pos_screen = vary_fragcoord.xy;
 94	vec3 pos_world = pos.xyz;
 95	vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
 96		
 97	float angle_hidden = 0.0;
 98	int points = 0;
 99		
100	float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
101		
102	// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
103	for (int i = 0; i < 8; i++)
104	{
105		ivec2 samppos_screen = ivec2(pos_screen + scale * reflect(kern[i], noise_reflect));
106		vec3 samppos_world = getPosition(samppos_screen, sample).xyz; 
107			
108		vec3 diff = pos_world - samppos_world;
109		float dist2 = dot(diff, diff);
110			
111		// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
112		// --> solid angle shrinking by the square of distance
113		//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
114		//(k should vary inversely with # of samples, but this is taken care of later)
115			
116		angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
117			
118		// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" 
119		points = points + int(diff.z > -1.0);
120	}
121		
122	angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
123		
124	ret = (1.0 - (float(points != 0) * angle_hidden));
125	
126	return min(ret, 1.0);
127}
128
129float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
130{
131	stc.xyz /= stc.w;
132	stc.z += shadow_bias*scl;
133	
134	float cs = shadow2DRect(shadowMap, stc.xyz).x;
135	float shadow = cs;
136
137	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs);
138	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs);
139	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs);
140	shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs);
141			
142	return shadow/5.0;
143	
144	//return shadow;
145}
146
147float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl)
148{
149	stc.xyz /= stc.w;
150	stc.z += spot_shadow_bias*scl;
151	
152	float cs = shadow2D(shadowMap, stc.xyz).x;
153	float shadow = cs;
154
155	vec2 off = 1.5/proj_shadow_res;
156	
157	shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs);
158	shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs);
159	shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs);
160	shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs);
161	
162			
163	return shadow/5.0;
164	
165	//return shadow;
166}
167
168void main() 
169{
170	vec2 pos_screen = vary_fragcoord.xy;
171	ivec2 itc = ivec2(pos_screen);
172	vec4 fcol = vec4(0,0,0,0);
173
174	for (int i = 0; i < samples; i++)
175	{
176		vec4 pos = getPosition(itc, i);
177	
178		vec4 nmap4 = texelFetch(normalMap, itc, i);
179		nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm
180		float displace = nmap4.w;
181		vec3 norm = nmap4.xyz;
182	
183		float shadow = 1.0;
184		float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
185
186		vec3 shadow_pos = pos.xyz + displace*norm;
187		vec3 offset = vary_light.xyz * (1.0-dp_directional_light);
188	
189		vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0);
190	
191		if (spos.z > -shadow_clip.w)
192		{	
193			if (dp_directional_light == 0.0)
194			{
195				// 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
196				shadow = 0.0;
197			}
198			else
199			{
200				vec4 lpos;
201			
202				if (spos.z < -shadow_clip.z)
203				{
204					lpos = shadow_matrix[3]*spos;
205					lpos.xy *= shadow_res;
206					shadow = pcfShadow(shadowMap3, lpos, 0.25);
207					shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
208				}
209				else if (spos.z < -shadow_clip.y)
210				{
211					lpos = shadow_matrix[2]*spos;
212					lpos.xy *= shadow_res;
213					shadow = pcfShadow(shadowMap2, lpos, 0.5);
214				}
215				else if (spos.z < -shadow_clip.x)
216				{
217					lpos = shadow_matrix[1]*spos;
218					lpos.xy *= shadow_res;
219					shadow = pcfShadow(shadowMap1, lpos, 0.75);
220				}
221				else
222				{
223					lpos = shadow_matrix[0]*spos;
224					lpos.xy *= shadow_res;
225					shadow = pcfShadow(shadowMap0, lpos, 1.0);
226				}
227		
228				// take the most-shadowed value out of these two:
229				//  * the blurred sun shadow in the light (shadow) map
230				//  * an unblurred dot product between the sun and this norm
231				// the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
232				shadow = min(shadow, dp_directional_light);
233			
234			}
235		}
236		else
237		{
238			// more distant than the shadow map covers
239			shadow = 1.0;
240		}
241	
242		
243		fcol[0] += shadow;
244		fcol[1] += calcAmbientOcclusion(pos, norm, i);
245
246		spos.xyz = shadow_pos+offset*spot_shadow_offset;
247	
248		//spotlight shadow 1
249		vec4 lpos = shadow_matrix[4]*spos;
250		fcol[2] += pcfShadow(shadowMap4, lpos, 0.8); 
251	
252		//spotlight shadow 2
253		lpos = shadow_matrix[5]*spos;
254		fcol[3] += pcfShadow(shadowMap5, lpos, 0.8); 
255	}
256		
257	gl_FragColor = fcol / samples;
258}