We're having some issues with our ray tracing in DirectX, especially with some serious banding issues with specular. With high specular power (above 8) banding starts. I'm wondering if this is an HDR/LDR issue or could be related to something else, such as normals or other vectors?
Look below for updates.
Here's the relevant shader code for Blinn-Phong on a sphere:
float3 hitPoint = thisRay.origin + thisRay.direction * bestHit.hitT; float3 normal = normalize(hitPoint - spheres[bestHit.hitID].center); float3 toLight = pointLights.position.xyz - hitPoint; float d = length(toLight); toLight = normalize(toLight); float diffuse = max(dot(normal, toLight), 0.0f); float3 v = normalize(thisRay.origin - hitPoint); float3 h = normalize(v + toLight); float spec = 0; if (diffuse > 0) spec = pow(max(dot(normal, h), 0.0f), specPower) * diffuse; output[threadID.xy] = spheres[bestHit.hitID].colour * diffuse + spheres[bestHit.hitID].specColour * spec;
specPower equals 8 in this image
specPower equals 9 in this image
Is this as simple as an HDR/LDR issue or is it somehow related to normal precision? I believe I have encountered this issue before in a deferred renderer where normals were of low precision and improperly packed/unpacked but in this case normals are generated on the fly and the whole thing is rendered directly to the backbuffer.
I would like to add to the above that triangles suffer the same artifact and they have their normal currently generated in the following way:
float3 normal = normalize(cross(triangles[bestHit.hitID].vertices - triangles[bestHit.hitID].vertices, triangles[bestHit.hitID].vertices - triangles[bestHit.hitID].vertices));
I'd say this makes it even more unlikely that the normal of the surface is the problem. The following image shows what happens when specPower reaches 2048.