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