Stiamo riscontrando alcuni problemi con il nostro ray tracing in DirectX, in particolare con alcuni gravi problemi di banding con speculare. Con alta potenza speculare (sopra 8) inizia la fasciatura. Mi chiedo se questo è un problema di HDR / LDR o potrebbe essere correlato a qualcos'altro, come normali o altri vettori?
AGGIORNARE
Guarda sotto per gli aggiornamenti.
Ecco il codice shader rilevante per Blinn-Phong su una sfera:
float3 hitPoint = thisRay.origin + thisRay.direction * bestHit.hitT;
float3 normal = normalize(hitPoint - spheres[bestHit.hitID].center);
float3 toLight = pointLights[0].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 è uguale a 8 in questa immagine
specPower è uguale a 9 in questa immagine
È semplice come un problema di HDR / LDR o è in qualche modo correlato alla normale precisione? Credo di aver già riscontrato questo problema in un renderer differito in cui le normali erano di bassa precisione e impacchettate / disimballate in modo improprio ma in questo caso le normali vengono generate al volo e il tutto viene reso direttamente al backbuffer.
Aggiornamento 1
Vorrei aggiungere a quanto sopra che i triangoli subiscono lo stesso artefatto e hanno il loro normale attualmente generato nel modo seguente:
float3 normal = normalize(cross(triangles[bestHit.hitID].vertices[1] - triangles[bestHit.hitID].vertices[0],
triangles[bestHit.hitID].vertices[2] - triangles[bestHit.hitID].vertices[0]));
Direi che questo rende ancora più improbabile che la normale superficie sia il problema. L'immagine seguente mostra cosa succede quando specPower raggiunge il 2048.
spec
direttamente e anche max(dot(normal, h), 0.0f)
. Cerca questo ritorno a un valore 1 in entrambi i calcoli.
float3 h = normalize( reflect(toLight,normal) );
, espec = pow(dot(v, h) * 0.5 + 0.5, specPower) * diffuse;