| @@ -249,14 +249,12 @@ vec3 fetchTapUnfiltered(ivec4 side, ivec2 ssC, vec3 tap, vec2 sideImageSize) { · 248 unmodified lines |
| 249 | 249 | return P; |
| 250 | 250 | } |
| 251 | 251 | |
| 252 | | −vec4 fetchTap(ivec4 side, ivec2 ssC, vec3 tap, vec2 sideImageSize) { |
| 253 | | − int mipLevel = evalMipFromRadius(tap.z * float(doFetchMips())); |
| 254 | | − |
| 255 | | − vec2 ssP = tap.xy + vec2(ssC); |
| 252 | +vec4 fetchTap(ivec4 side, vec2 tapPixelPos, float tapRadius, vec2 sideImageSize) { |
| 253 | + int mipLevel = evalMipFromRadius(tapRadius * float(doFetchMips())); |
| 256 | 254 | |
| 257 | 255 | // We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map. |
| 258 | 256 | // Manually clamp to the texture size because texelFetch bypasses the texture unit |
| 259 | | − vec2 tapUV = (vec2(ssP) + vec2(0.5)) / sideImageSize; |
| 257 | + vec2 tapUV = (tapPixelPos + vec2(0.5)) / sideImageSize; |
| 260 | 258 | vec2 fetchUV = vec2(tapUV.x + side.w * 0.5 * (side.x - tapUV.x), tapUV.y); |
| 261 | 259 | |
| 262 | 260 | vec4 P; |
| @@ -293,44 +291,21 @@ float evalVisibilitySSAO(in vec3 centerPosition, in vec3 centerNormal, in vec3 t · 30 unmodified lines |
| 293 | 291 | float computeHorizonFromTap(vec3 tapPositionES, vec3 fragPositionES, vec3 fragNormalES) { |
| 294 | 292 | vec3 deltaVec = tapPositionES - fragPositionES; |
| 295 | 293 | float distanceSquared = dot(deltaVec, deltaVec); |
| 296 | | − float horizon = dot(normalize(deltaVec), fragNormalES); |
| 294 | + float cosHorizonAngle = dot(normalize(deltaVec), fragNormalES); |
| 297 | 295 | float radiusFalloff = max(0.0, 1.0 - (distanceSquared / getRadius2())); |
| 298 | 296 | |
| 299 | | − horizon = max(0.0, (horizon - getFalloffAngle()) / (1.0 - getFalloffAngle())); |
| 300 | | − horizon *= radiusFalloff; |
| 301 | | − |
| 302 | | − return horizon; |
| 303 | | −} |
| 304 | | − |
| 305 | | −vec2 clampSearchVector(vec2 sideImageSize, vec2 shadedPixelPos, vec2 searchVec) { |
| 306 | | − vec2 clampedSearchVec = searchVec; |
| 307 | | − vec2 endPixel = shadedPixelPos + clampedSearchVec; |
| 297 | + cosHorizonAngle = max(0.0, (cosHorizonAngle - getFalloffAngle()) / (1.0 - getFalloffAngle())); |
| 298 | + cosHorizonAngle *= radiusFalloff; |
| 308 | 299 | |
| 309 | | − if (endPixel.x < 0) { |
| 310 | | − clampedSearchVec *= ((0-shadedPixelPos.x) / clampedSearchVec.x); |
| 311 | | − endPixel = shadedPixelPos + clampedSearchVec; |
| 312 | | − } |
| 313 | | − if (endPixel.x > (sideImageSize.x-1)) { |
| 314 | | − clampedSearchVec *= ((sideImageSize.x-1-shadedPixelPos.x) / clampedSearchVec.x); |
| 315 | | − endPixel = shadedPixelPos + clampedSearchVec; |
| 316 | | − } |
| 317 | | − if (endPixel.y < 0) { |
| 318 | | − clampedSearchVec *= ((0-shadedPixelPos.y) / clampedSearchVec.y); |
| 319 | | − endPixel = shadedPixelPos + clampedSearchVec; |
| 320 | | − } |
| 321 | | − if (endPixel.y > (sideImageSize.y-1)) { |
| 322 | | − clampedSearchVec *= ((sideImageSize.y-1-shadedPixelPos.y) / clampedSearchVec.y); |
| 323 | | − } |
| 324 | | − |
| 325 | | − return clampedSearchVec; |
| 300 | + return cosHorizonAngle; |
| 326 | 301 | } |
| 327 | 302 | |
| 328 | 303 | <@func computeHorizon()@> |
| 329 | | − if (tapPixelPos.x>=0 && tapPixelPos.y>=0 && tapPixelPos.x<sideImageSize.x && tapPixelPos.y<sideImageSize.y) { |
| 304 | + vec2 tapPixelPos = tapPixelOffset + shadedPixelPos; |
| 305 | + if (tapPixelPos.x<0 && tapPixelPos.y<0 && tapPixelPos.x>=sideImageSize.x && tapPixelPos.y>=sideImageSize.y) { |
| 330 | 306 | break; |
| 331 | 307 | } |
| 332 | | − vec3 tap = vec3(tapPixelPos, radius); |
| 333 | | − vec4 tapUVZ_mip = fetchTap(side, shadedPixelPos, tap, sideImageSize); |
| 308 | + vec4 tapUVZ_mip = fetchTap(side, tapPixelPos, radius, sideImageSize); |
| 334 | 309 | vec3 tapPositionES = evalEyePositionFromZeye(side.x, tapUVZ_mip.z, tapUVZ_mip.xy); |
| 335 | 310 | float tapCosHorizonAngle = computeHorizonFromTap(tapPositionES, fragPositionES, fragNormalES); |
| 336 | 311 | |
| @@ -338,26 +313,25 @@ vec2 clampSearchVector(vec2 sideImageSize, vec2 shadedPixelPos, vec2 searchVec) · 1 unmodified line |
| 338 | 313 | |
| 339 | 314 | <@endfunc@> |
| 340 | 315 | |
| 341 | | −#define SSAO_LINEAR_SAMPLING 1 |
| 316 | +#define SSAO_LINEAR_SEARCH_HORIZON 1 |
| 342 | 317 | |
| 343 | | −float computeHorizon(ivec4 side, ivec2 shadedPixelPos, vec2 sideImageSize, vec2 deltaTap, |
| 344 | | − vec3 fragPositionES, vec3 fragNormalES, vec2 searchVec) { |
| 318 | +float computeHorizon(ivec4 side, vec2 shadedPixelPos, vec2 sideImageSize, vec2 deltaTap, |
| 319 | + vec3 fragPositionES, vec3 fragNormalES, vec2 searchVec, float searchRadius) { |
| 345 | 320 | vec2 absSearchVec = abs(searchVec); |
| 346 | | − int stepCount = int(max(absSearchVec.x, absSearchVec.y)); |
| 321 | + int stepCount = int(ceil(max(absSearchVec.x, absSearchVec.y))); |
| 347 | 322 | float cosHorizonAngle = 0.0; |
| 348 | 323 | |
| 349 | 324 | if (stepCount>0) { |
| 350 | 325 | vec2 deltaPixelTap = searchVec / float(stepCount); |
| 351 | | − float searchRadius = length(searchVec); |
| 352 | 326 | float deltaRadius = searchRadius / float(stepCount); |
| 353 | | − vec2 tapPixelPos = vec2(0); |
| 327 | + vec2 tapPixelOffset = vec2(0); |
| 354 | 328 | |
| 355 | | −#if SSAO_LINEAR_SAMPLING |
| 329 | +#if SSAO_LINEAR_SEARCH_HORIZON |
| 356 | 330 | float radius = 0.0; |
| 357 | 331 | int stepIndex; |
| 358 | 332 | |
| 359 | 333 | for (stepIndex=0 ; stepIndex<stepCount ; stepIndex++) { |
| 360 | | − tapPixelPos += deltaPixelTap; |
| 334 | + tapPixelOffset += deltaPixelTap; |
| 361 | 335 | radius += deltaRadius; |
| 362 | 336 | |
| 363 | 337 | <$computeHorizon()$> |
| @@ -366,8 +340,8 @@ float computeHorizon(ivec4 side, ivec2 shadedPixelPos, vec2 sideImageSize, vec2 · 2 unmodified lines |
| 366 | 340 | float radius = deltaRadius; |
| 367 | 341 | float mipLevel = evalMipFromRadius(radius * float(doFetchMips())); |
| 368 | 342 | |
| 369 | | − while (radius<searchRadius) { |
| 370 | | − tapPixelPos += deltaPixelTap; |
| 343 | + while (radius<=searchRadius) { |
| 344 | + tapPixelOffset += deltaPixelTap; |
| 371 | 345 | |
| 372 | 346 | <$computeHorizon()$> |
| 373 | 347 | |
| @@ -384,16 +358,16 @@ float computeHorizon(ivec4 side, ivec2 shadedPixelPos, vec2 sideImageSize, vec2 · 10 unmodified lines |
| 384 | 358 | return cosHorizonAngle; |
| 385 | 359 | } |
| 386 | 360 | |
| 387 | | −float evalVisibilityHBAO(ivec4 side, ivec2 shadedPixelPos, vec2 sideImageSize, vec2 deltaTap, float diskPixelRadius, |
| 361 | +float evalVisibilityHBAO(ivec4 side, vec2 shadedPixelPos, vec2 sideImageSize, vec2 deltaTap, float diskPixelRadius, |
| 388 | 362 | vec3 fragPositionES, vec3 fragNormalES) { |
| 389 | 363 | vec2 searchVec = deltaTap * diskPixelRadius; |
| 390 | 364 | float obscurance; |
| 391 | 365 | |
| 392 | 366 | // Forward search for h1 |
| 393 | | − obscurance = computeHorizon(side, shadedPixelPos, sideImageSize, deltaTap, fragPositionES, fragNormalES, searchVec); |
| 367 | + obscurance = computeHorizon(side, shadedPixelPos, sideImageSize, deltaTap, fragPositionES, fragNormalES, searchVec, diskPixelRadius); |
| 394 | 368 | |
| 395 | 369 | // Backward search for h2 |
| 396 | | − obscurance += computeHorizon(side, shadedPixelPos, sideImageSize, deltaTap, fragPositionES, fragNormalES, -searchVec); |
| 370 | + obscurance += computeHorizon(side, shadedPixelPos, sideImageSize, deltaTap, fragPositionES, fragNormalES, -searchVec, diskPixelRadius); |
| 397 | 371 | |
| 398 | 372 | return obscurance * 0.5 / PI; |
| 399 | 373 | } |