diff --git a/shaders/fog_inject.comp b/shaders/fog_inject.comp index 394a80b0..5e65646d 100644 --- a/shaders/fog_inject.comp +++ b/shaders/fog_inject.comp @@ -172,13 +172,14 @@ vec3 lamp_scattering(light_s lamp, vec3 start, vec3 direction, float span, float if (dot(lamp.pos - nearest, lamp.pos - nearest) < 9.0 * width * width) { // a lamp within a few cells of the ray: the light of the cell is taken along four rays spread over the cell, so it - // doesn't depend on which side of the lamp the ray of this frame passes + // doesn't depend on which side of the lamp the ray of this frame passes, and the points along the rays are staggered, + // eight along the cell, where the cone changes the most (its tip) vec3 across = normalize(cross(direction, vec3(0.0, 1.0, 0.0) + vec3(1e-4, 0.0, 0.0))); vec3 up = cross(across, direction); for (int k = 0; k < 4; k++) { vec2 shift = (vec2(float(k & 1), float(k >> 1)) - 0.5) * 0.5 * width; - sum += lamp_segment(lamp, cone, start + across * shift.x + up * shift.y, direction, span, width, part); + sum += lamp_segment(lamp, cone, start + across * shift.x + up * shift.y, direction, span, width, fract(part + 0.25 * float(k))); } return sum * 0.25; } diff --git a/shaders/fog_integrate.comp b/shaders/fog_integrate.comp index aae20476..a824217f 100644 --- a/shaders/fog_integrate.comp +++ b/shaders/fog_integrate.comp @@ -1,7 +1,9 @@ // the fog volume of the main view, second pass: the light and extinction of the cells (fog_inject.comp) added up along the rays // of the view, front to back, into what the fog adds and lets through from the camera to the far side of every slice // (apply_fog.glsl). the light of a cell is integrated over its length as Hillaire (2015) does it, so it doesn't grow with -// the size of the cell +// the size of the cell. the light of the cells is taken with the light of their neighbours across the view, a 3x3 tent filter +// (four fetches of the linear filter): every cell is sampled at a point of its own in a frame, and what is left of that after +// the blending over frames differs from cell to cell, which the filter evens out. the history keeps the cells unfiltered #include @@ -35,6 +37,12 @@ void main() float span = (back - front) * stretch; front = back; vec4 cell = texelFetch(fog_scattering, ivec3(column, slice), 0); + float depthcoord = (float(slice) + 0.5) / float(grid.z); + vec2 texel = 1.0 / vec2(grid.xy); + cell.rgb = 0.25 * (textureLod(fog_scattering, vec3(coords + vec2(-0.5, -0.5) * texel, depthcoord), 0.0).rgb + + textureLod(fog_scattering, vec3(coords + vec2(0.5, -0.5) * texel, depthcoord), 0.0).rgb + + textureLod(fog_scattering, vec3(coords + vec2(-0.5, 0.5) * texel, depthcoord), 0.0).rgb + + textureLod(fog_scattering, vec3(coords + vec2(0.5, 0.5) * texel, depthcoord), 0.0).rgb); float extinction = max(cell.a, 1e-7); float through = exp(-extinction * span); light += transmittance * cell.rgb * ((1.0 - through) / extinction);