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