Pull in STORM-1921, STORM-1927, STORM-1928: improved Dof, SSAO, and Fog fixes by Tofu Buzzard

master
Cinders 2013-01-20 07:18:35 -07:00
parent cef6b73a90
commit 569f9cf88a
11 changed files with 101 additions and 86 deletions

View File

@ -1200,6 +1200,9 @@ Tofu Buzzard
SH-2477
STORM-1684
STORM-1819
STORM-1921
STORM-1927
STORM-1928
Tony Kembia
Torben Trautman
TouchaHoney Perhaps

View File

@ -3078,7 +3078,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>10.0</real>
<real>20.0</real>
</map>
<key>CameraFNumber</key>
@ -10550,7 +10550,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.7</real>
<real>0.5</real>
</map>
<key>RenderSpotLightsInNondeferred</key>

View File

@ -72,24 +72,23 @@ void main()
vec3 pos = getPosition(tc).xyz;
vec4 ccol = texture2DRect(lightMap, tc).rgba;
vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
vec2 dlt = kern_scale * delta / (vec2(1.0)+norm.xy*norm.xy);
dlt /= max(-pos.z*dist_factor, 1.0);
vec2 defined_weight = getKern(0).xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
vec4 col = defined_weight.xyxx * ccol;
// relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances
float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005;
float pointplanedist_tolerance_pow2 = pos.z*-0.001;
// perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large
float tc_mod = 0.5*(tc.x + tc.y); // mod(tc.x+tc.y,2)
tc_mod -= floor(tc_mod);
tc_mod *= 2.0;
vec2 tc_v = fract(0.5 * tc.xy); // we now have floor(mod(tc,2.0))*0.5
float tc_mod = 2.0 * abs(tc_v.x - tc_v.y); // diff of x,y makes checkerboard
tc += ( (tc_mod - 0.5) * getKern(1).z * dlt * 0.5 );
for (int i = 1; i < 4; i++)
{
vec2 samptc = tc + getKern(i).z*dlt;
vec2 samptc = (tc + getKern(i).z * dlt);
vec3 samppos = getPosition(samptc).xyz;
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
if (d*d <= pointplanedist_tolerance_pow2)
@ -100,7 +99,7 @@ void main()
}
for (int i = 1; i < 4; i++)
{
vec2 samptc = tc - getKern(i).z*dlt;
vec2 samptc = (tc - getKern(i).z * dlt);
vec3 samppos = getPosition(samptc).xyz;
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
if (d*d <= pointplanedist_tolerance_pow2)
@ -111,7 +110,7 @@ void main()
}
col /= defined_weight.xyxx;
col.y *= col.y;
col.y *= col.y; // delinearize SSAO effect post-blur
frag_color = col;
}

View File

@ -75,23 +75,20 @@ void dofSampleNear(inout vec4 diff, inout float w, float min_sc, vec2 tc)
void main()
{
vec2 tc = vary_fragcoord.xy;
vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
{
float w = 1.0;
float sc = (diff.a*2.0-1.0)*max_cof;
float w = 1.0;
float PI = 3.14159265358979323846264;
const float PI = 3.14159265358979323846264;
// sample quite uniformly spaced points within a circle, for a circular 'bokeh'
if (sc > 0.5)
{
while (sc > 0.5)
{
int its = int(max(1.0,(sc*3.7)));
int its = int(max(1.0,(sc*PI)));
for (int i=0; i<its; ++i)
{
float ang = sc+i*2*PI/its; // sc is added for rotary perturbance
@ -100,7 +97,7 @@ void main()
// you could test sample coords against an interesting non-circular aperture shape here, if desired.
dofSampleNear(diff, w, sc, vary_fragcoord.xy + vec2(samp_x,samp_y));
}
sc -= 1.0;
sc -= 2.0;
}
}
else if (sc < -0.5)
@ -108,7 +105,7 @@ void main()
sc = abs(sc);
while (sc > 0.5)
{
int its = int(max(1.0,(sc*3.7)));
int its = int(max(1.0,(sc*PI)));
for (int i=0; i<its; ++i)
{
float ang = sc+i*2*PI/its; // sc is added for rotary perturbance
@ -117,7 +114,7 @@ void main()
// you could test sample coords against an interesting non-circular aperture shape here, if desired.
dofSample(diff, w, sc, vary_fragcoord.xy + vec2(samp_x,samp_y));
}
sc -= 1.0;
sc -= 2.0;
}
}

View File

@ -203,6 +203,13 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
//increase ambient when there are more clouds
vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5;
//haze color
setAdditiveColor(
vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
+ (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
+ tmpAmbient)));
/* decrease value and saturation (that in HSV, not HSL) for occluded areas
* // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
* // The following line of code performs the equivalent of:
@ -213,12 +220,6 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
*/
tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
//haze color
setAdditiveColor(
vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
+ (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
+ tmpAmbient)));
//brightness of surface both sunlight and ambient
setSunlitColor(vec3(sunlight * .5));
setAmblitColor(vec3(tmpAmbient * .25));

View File

@ -62,11 +62,8 @@ vec4 getPosition(vec2 pos_screen)
return pos;
}
//calculate decreases in ambient lighting when crowded out (SSAO)
float calcAmbientOcclusion(vec4 pos, vec3 norm)
vec2 getKern(int i)
{
float ret = 1.0;
vec2 kern[8];
// exponentially (^2) distant occlusion samples spread around origin
kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
@ -78,40 +75,54 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm)
kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
return kern[i];
}
//calculate decreases in ambient lighting when crowded out (SSAO)
float calcAmbientOcclusion(vec4 pos, vec3 norm)
{
vec2 pos_screen = vary_fragcoord.xy;
vec3 pos_world = pos.xyz;
vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
// We treat the first sample as the origin, which definitely doesn't obscure itself thanks to being visible for sampling in the first place.
float points = 1.0;
float angle_hidden = 0.0;
int points = 0;
float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
// use a kernel scale that diminishes with distance.
// a scale of less than 32 is just wasting good samples, though.
float scale = max(32.0, min(ssao_radius / -pos.z, ssao_max_radius));
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations unrolling?)
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
for (int i = 0; i < 8; i++)
{
vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
vec3 samppos_world = getPosition(samppos_screen).xyz;
vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
vec3 diff = pos_world - samppos_world;
float dist2 = dot(diff, diff);
// if sample is out-of-screen then give it no weight by continuing
if (any(lessThan(samppos_screen.xy, vec2(0.0, 0.0))) ||
any(greaterThan(samppos_screen.xy, vec2(screen_res.xy)))) continue;
// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
// --> solid angle shrinking by the square of distance
//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
//(k should vary inversely with # of samples, but this is taken care of later)
vec3 samppos_world = getPosition(samppos_screen).xyz;
angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
vec3 diff = samppos_world - pos.xyz;
// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
points = points + int(diff.z > -1.0);
if (diff.z < ssao_factor && diff.z != 0.0)
{
float dist = length(diff);
float angrel = max(0.0, dot(norm.xyz, diff/dist));
float distrel = 1.0/(1.0+dist*dist);
float samplehidden = min(angrel, distrel);
angle_hidden += (samplehidden);
points += 1.0;
}
}
angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
angle_hidden /= points;
ret = (1.0 - (float(points != 0) * angle_hidden));
float rtn = (1.0 - angle_hidden);
return min(ret, 1.0);
return (rtn * rtn);
}
void main()

View File

@ -151,8 +151,8 @@ void main()
//spec *= shadow;
//color.rgb += spec * specular;
//color.rgb = atmosTransport(color.rgb);
//color.rgb = scaleSoftClip(color.rgb);
color.rgb = atmosTransport(color.rgb);
color.rgb = scaleSoftClip(color.rgb);
//color.a = spec * sunAngle2;
//wavef.z *= 0.1f;

View File

@ -85,7 +85,7 @@ void main()
pos.w = 1.0;
pos = modelview_matrix*pos;
calcAtmospherics(pos.xyz);
calcAtmospherics(view.xyz);
//pass wave parameters to pixel shader
vec2 bigWave = (v.xy) * vec2(0.04,0.04) + d1 * time * 0.055;

View File

@ -81,8 +81,7 @@ void main()
pos.w = 1.0;
pos = modelview_matrix*pos;
calcAtmospherics(pos.xyz);
calcAtmospherics(view.xyz);
//pass wave parameters to pixel shader
vec2 bigWave = (v.xy) * vec2(0.04,0.04) + d1 * time * 0.055;

View File

@ -205,7 +205,13 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
//increase ambient when there are more clouds
vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5;
/* decrease value and saturation (that in HSV, not HSL) for occluded areas
//haze color
setAdditiveColor(
vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
+ (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
+ tmpAmbient)));
/* decrease value and saturation (that in HSV, not HSL) for occluded areas
* // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
* // The following line of code performs the equivalent of:
* float ambAlpha = tmpAmbient.a;
@ -215,12 +221,6 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
*/
tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
//haze color
setAdditiveColor(
vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
+ (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
+ tmpAmbient)));
//brightness of surface both sunlight and ambient
setSunlitColor(vec3(sunlight * .5));
setAmblitColor(vec3(tmpAmbient * .25));

View File

@ -98,62 +98,68 @@ vec2 getKern(int i)
//calculate decreases in ambient lighting when crowded out (SSAO)
float calcAmbientOcclusion(vec4 pos, vec3 norm)
{
float ret = 1.0;
vec2 pos_screen = vary_fragcoord.xy;
vec3 pos_world = pos.xyz;
vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
// We treat the first sample as the origin, which definitely doesn't obscure itself thanks to being visible for sampling in the first place.
float points = 1.0;
float angle_hidden = 0.0;
float points = 0;
float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
// use a kernel scale that diminishes with distance.
// a scale of less than 32 is just wasting good samples, though.
float scale = max(32.0, min(ssao_radius / -pos.z, ssao_max_radius));
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
for (int i = 0; i < 8; i++)
{
vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
// if sample is out-of-screen then give it no weight by continuing
if (any(lessThan(samppos_screen.xy, vec2(0.0, 0.0))) ||
any(greaterThan(samppos_screen.xy, vec2(screen_res.xy)))) continue;
vec3 samppos_world = getPosition(samppos_screen).xyz;
vec3 diff = pos_world - samppos_world;
float dist2 = dot(diff, diff);
vec3 diff = samppos_world - pos.xyz;
// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
// --> solid angle shrinking by the square of distance
//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
//(k should vary inversely with # of samples, but this is taken care of later)
if (diff.z < ssao_factor // only use sample if it's near enough
&& diff.z != 0.0 // Z is very quantized at distance, this lessens noise and eliminates dist==0
)
{
float dist = length(diff);
float angrel = max(0.0, dot(norm.xyz, diff/dist)); // how much the origin faces the sample
float distrel = 1.0/(1.0+dist*dist); // 'closeness' of origin to sample
float funky_val = (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) ? 1.0 : 0.0;
angle_hidden = angle_hidden + funky_val * min(1.0/dist2, ssao_factor_inv);
// origin is obscured by this sample according to how directly the origin is facing the sample and how close the sample is. It has to score high on both to be a good occluder. (a*d) seems the most intuitive way to score, but min(a,d) gives a less localized effect...
float samplehidden = min(angrel, distrel);
// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
float diffz_val = (diff.z > -1.0) ? 1.0 : 0.0;
points = points + diffz_val;
angle_hidden += (samplehidden);
points += 1.0;
}
}
angle_hidden = min(ssao_factor*angle_hidden/points, 1.0);
angle_hidden = angle_hidden / points;
float points_val = (points > 0.0) ? 1.0 : 0.0;
ret = (1.0 - (points_val * angle_hidden));
float rtn = (1.0 - angle_hidden);
ret = max(ret, 0.0);
return min(ret, 1.0);
return (rtn * rtn);
}
float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
{
vec2 recip_shadow_res = 1.0 / shadow_res.xy;
stc.xyz /= stc.w;
stc.z += shadow_bias;
stc.x = floor(stc.x*shadow_res.x + fract(pos_screen.y*0.666666666))/shadow_res.x;
stc.x = floor(stc.x*shadow_res.x + fract(pos_screen.y*0.666666666)) * recip_shadow_res.x;
float cs = shadow2D(shadowMap, stc.xyz).x;
float shadow = cs;
shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0*recip_shadow_res.x, 1.5*recip_shadow_res.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0*recip_shadow_res.x, -1.5*recip_shadow_res.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0*recip_shadow_res.x, 1.5*recip_shadow_res.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0*recip_shadow_res.x, -1.5*recip_shadow_res.y, 0.0)).x;
return shadow*0.2;
}
@ -167,8 +173,7 @@ float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_scr
float cs = shadow2D(shadowMap, stc.xyz).x;
float shadow = cs;
vec2 off = 1.0/proj_shadow_res;
off.y *= 1.5;
vec2 off = vec2(1.0, 1.5) / proj_shadow_res.xy;
shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x;