- Timestamp:
- 02/19/09 12:05:56 (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/ssao.cg
r3319 r3320 156 156 157 157 158 /** The ssao shader returning the an intensity value between 0 and 1 159 This version of the ssao shader uses the dotproduct between pixel and 160 sample normal as weight. 158 /** The ssao shader returning the an intensity value between 0 and 1. 159 This version of the ssao shader uses the dotproduct between 160 pixel-to-sample direction and sample normal as weight. 161 162 The algorithm works like the following: 163 1) Check in a circular area around the current position. 164 2) Shoot vectors to the positions there, and check the angle to these positions. 165 3) Summing up these angles gives an estimation of the occlusion at the current position. 161 166 */ 162 167 float3 ssao2(fragment IN, … … 172 177 float3 tr, 173 178 float3 viewDir, 174 sampler2D normalTex, 175 float sampleIntensity 179 float convergence, 180 float sampleIntensity, 181 bool isMovingObject, 182 sampler2D normalTex 176 183 ) 177 184 { 178 185 float total_ao = .0f; 186 float validSamples = .0f; 179 187 float numSamples = .0f; 180 float validSamples = .0f;181 188 182 189 for (int i = 0; i < NUM_SAMPLES; ++ i) 183 190 { 184 const float2 offset = samples[i]; 185 186 #if 1 191 float2 offset; 192 187 193 //////////////////// 188 //-- add random noise: reflect around random normal vector (rather slow!) 189 190 const float2 mynoise = tex2Dlod(noiseTex, float4(IN.texCoord * 4.0f, 0, 0)).xy; 191 const float2 offsetTransformed = myreflect(offset, mynoise); 192 #else 193 const float2 offsetTransformed = offset; 194 #endif 194 //-- add random noise: reflect around random normal vector 195 //-- (affects performance for some reason!) 196 197 if (convergence < SSAO_CONVERGENCE_THRESHOLD) 198 { 199 float2 mynoise = tex2Dlod(noiseTex, float4(IN.texCoord * 4.0f, 0, 0)).xy; 200 //offset = myreflect(samples[i], mynoise); 201 offset = myrotate(samples[i], mynoise.x); 202 } 203 else 204 { 205 offset = samples[i]; 206 } 207 195 208 // weight with projected coordinate to reach similar kernel size for near and far 196 //const float2 texcoord = IN.texCoord.xy + offsetTransformed * scaleFactor + jitter; 197 const float2 texcoord = IN.texCoord.xy + offsetTransformed * scaleFactor; 198 199 //if ((texcoord.x <= 1.0f) && (texcoord.x >= 0.0f) && (texcoord.y <= 1.0f) && (texcoord.y >= 0.0f)) ++ numSamples; 200 float4 sampleColor = tex2Dlod(colors, float4(texcoord, 0, 0)); 201 209 const float2 texcoord = IN.texCoord.xy + offset * scaleFactor; 210 211 const float4 sampleColor = tex2Dlod(colors, float4(texcoord, .0f, .0f)); 202 212 const float3 samplePos = ReconstructSamplePos(sampleColor.w, texcoord, bl, br, tl, tr); 213 214 215 //////////////// 216 //-- compute contribution of sample using the direction and angle 217 218 float3 dirSample = samplePos - centerPosition; 219 220 //const float minDist = 9e-1f; 221 const float minDist = 1e-2f; 222 223 //const float sqrLen = max(SqrLen(dirSample), minDist); 224 //const float lengthToSample = sqrt(sqrLen); 225 const float lengthToSample = max(length(dirSample), minDist); 226 227 dirSample /= lengthToSample; // normalize 228 229 // angle between current normal and direction to sample controls AO intensity. 230 float cosAngle = dot(dirSample, normal); 231 203 232 // the normal of the current sample 204 233 const float3 sampleNormal = tex2Dlod(normalTex, float4(texcoord, 0, 0)).xyz; 205 234 206 207 ////////////////208 //-- compute contribution of sample using the direction and angle209 210 float3 dirSample = samplePos - centerPosition;211 212 const float sqrLen = max(SqrLen(dirSample), 1e-2f);213 const float lengthToSample = sqrt(sqrLen);214 //const float lengthToSample = max(length(dirSample), 1e-6f);215 216 dirSample /= lengthToSample; // normalize217 218 235 // angle between current normal and direction to sample controls AO intensity. 219 float cosAngle = .5f + dot(sampleNormal, -normal) * 0.5f;220 // use binary decision to cull samples that are behind current shading point221 cosAngle *= step(0.0f, dot(dirSample, normal));222 223 const float aoContrib = sampleIntensity / sqrLen; 236 float cosAngle2 = .5f + dot(sampleNormal, -normal) * 0.5f; 237 238 //const float aoContrib = sampleIntensity / sqrLen; 239 const float aoContrib = sampleIntensity / lengthToSample; 240 224 241 //const float aoContrib = (1.0f > lengthToSample) ? occlusionPower(9e-2f, DISTANCE_SCALE + lengthToSample): .0f; 225 226 total_ao += cosAngle * aoContrib; 242 total_ao += max(cosAngle, .0f) * aoContrib * cosAngle2; 243 244 ++ numSamples; 227 245 228 246 // check if the samples have been valid in the last frame 229 validSamples += (1.0f - step(1.0f, lengthToSample)) * sampleColor.x; 230 231 ++ numSamples; 232 } 233 247 // only mark sample as invalid if in the last / current frame 248 // they possibly have any influence on the ao 249 250 const float changeFactor = sampleColor.y; 251 const float pixelValid = sampleColor.x; 252 253 // hack: 254 // we check if the sample could have been near enough 255 // to the current pixel or if the angle is small enough 256 // to have any influence in the current or last frame 257 #if 1 258 const float tooFarAway = step(0.5f, lengthToSample - changeFactor); 259 if (pixelValid < 2.0f) 260 validSamples = max(validSamples, pixelValid * (1.0f - tooFarAway) * step(-0.1f, cosAngle)); 261 else 262 validSamples = max(validSamples, pixelValid); 263 #else 264 validSamples = max(validSamples, pixelValid); 265 #endif 266 267 #ifdef USE_GTX 268 // we can bail out early and use a minimal #samples) 269 // if some conditions are met as long as the hardware supports it 270 if (numSamples >= MIN_SAMPLES) 271 { 272 //break; 273 // if the pixel belongs to a static object and all the samples stay valid in the current frame 274 if (!isMovingObject && (validSamples < 1.0f) && (convergence > NUM_SAMPLES)) break; 275 // if the pixel belongs to a dynamic object but the #accumulated samples for this pixel is sufficiently high 276 // (=> there was no discontinuity recently) 277 //else if (isMovingObject && (convergence > SSAO_CONVERGENCE_THRESHOLD)) break; 278 //else if (isMovingObject && (convergence > NUM_SAMPLES * 5)) break; 279 } 280 #endif 281 } 282 283 // "normalize" ao contribution 234 284 total_ao /= numSamples; 235 285 … … 238 288 // => compensate for this (on the other hand, projected sampling area could be larger!) 239 289 const float viewCorrection = 1.0f + VIEW_CORRECTION_SCALE * max(dot(viewDir, normal), 0.0f); 240 total_ao += cosAngle * aoContrib * viewCorrection; 241 290 total_ao *= viewCorrection; 242 291 #endif 243 292 244 return float3(max(0.0f, 1.0f - total_ao), validSamples, numSamples); 293 //return float3(total_ao, validSamples, numSamples); 294 return float3(min(1.0f, total_ao), validSamples, numSamples); 245 295 } 246 296 … … 450 500 if (eyeSpaceDepth < DEPTH_THRESHOLD) 451 501 { 452 ao = ssao(IN, colors, noiseTex, samples, normal, eyeSpacePos.xyz, scaleFactor, bl, br, tl, tr, normalize(viewDir), oldWeight, sampleIntensity, isMovingObject); 502 //ao = ssao(IN, colors, noiseTex, samples, normal, eyeSpacePos.xyz, scaleFactor, bl, br, tl, tr, normalize(viewDir), oldWeight, sampleIntensity, isMovingObject); 503 ao = ssao2(IN, colors, noiseTex, samples, normal, eyeSpacePos.xyz, scaleFactor, bl, br, tl, tr, normalize(viewDir), oldWeight, sampleIntensity, isMovingObject, normals); 453 504 //ao = ssao2(IN, colors, noiseTex, samples, normal, eyeSpacePos.xyz, scaleFactor, bl, br, tl, tr, normalize(viewDir), normals, sampleIntensity); 454 505 }
Note: See TracChangeset
for help on using the changeset viewer.