Wir haben einige Probleme mit unserer Raytracing-Funktion in DirectX, insbesondere mit einigen schwerwiegenden Banding-Problemen mit Specular. Bei hoher Spiegelkraft (über 8) beginnt die Streifenbildung. Ich frage mich, ob dies ein HDR / LDR-Problem ist oder mit etwas anderem in Verbindung gebracht werden könnte, beispielsweise mit Normalen oder anderen Vektoren.
AKTUALISIEREN
Suchen Sie unten nach Updates.
Hier ist der relevante Shader-Code für Blinn-Phong auf einer Kugel:
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 entspricht in diesem Bild 8
specPower entspricht in diesem Bild 9
Ist das so einfach wie ein HDR / LDR-Problem oder hängt es irgendwie mit normaler Präzision zusammen? Ich glaube, ich bin auf dieses Problem bereits bei einem verzögerten Renderer gestoßen, bei dem Normalen von geringer Genauigkeit waren und nicht ordnungsgemäß verpackt / entpackt wurden. In diesem Fall werden Normalen jedoch im laufenden Betrieb generiert und das Ganze direkt in den Backbuffer gerendert.
Update 1
Ich möchte dem oben Gesagten hinzufügen, dass Dreiecke das gleiche Artefakt aufweisen und ihre Normalen derzeit auf folgende Weise erzeugt werden:
float3 normal = normalize(cross(triangles[bestHit.hitID].vertices[1] - triangles[bestHit.hitID].vertices[0],
triangles[bestHit.hitID].vertices[2] - triangles[bestHit.hitID].vertices[0]));
Ich würde sagen, dies macht es noch unwahrscheinlicher, dass die Normalität der Oberfläche das Problem ist. Das folgende Bild zeigt, was passiert, wenn specPower 2048 erreicht.
spec
direkt und auch auszugeben max(dot(normal, h), 0.0f)
. Suchen Sie in beiden Berechnungen nach dieser Rückkehr zu einem Wert von 1.
float3 h = normalize( reflect(toLight,normal) );
undspec = pow(dot(v, h) * 0.5 + 0.5, specPower) * diffuse;