Tenemos algunos problemas con nuestro trazado de rayos en DirectX, especialmente con algunos problemas serios de bandas con especular. Con alta potencia especular (por encima de 8) comienza el anillado. Me pregunto si este es un problema HDR / LDR o podría estar relacionado con otra cosa, como las normales u otros vectores.
ACTUALIZAR
Mire abajo para actualizaciones.
Aquí está el código de sombreador relevante para Blinn-Phong en una esfera:
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 es igual a 8 en esta imagen
specPower es igual a 9 en esta imagen
¿Es tan simple como un problema HDR / LDR o está relacionado de alguna manera con la precisión normal? Creo que he encontrado este problema antes en un renderizador diferido donde las normales eran de baja precisión y estaban empaquetadas / desempaquetadas incorrectamente, pero en este caso las normales se generan sobre la marcha y todo se procesa directamente en el backbuffer.
Actualización 1
Me gustaría agregar a lo anterior que los triángulos sufren el mismo artefacto y actualmente tienen su normal generado de la siguiente manera:
float3 normal = normalize(cross(triangles[bestHit.hitID].vertices[1] - triangles[bestHit.hitID].vertices[0],
triangles[bestHit.hitID].vertices[2] - triangles[bestHit.hitID].vertices[0]));
Diría que esto hace que sea aún más improbable que la normalidad de la superficie sea el problema. La siguiente imagen muestra lo que sucede cuando specPower alcanza 2048.
spec
directamente, y también max(dot(normal, h), 0.0f)
. Busque este retorno a un valor 1 en cualquier cálculo.
float3 h = normalize( reflect(toLight,normal) );
, yspec = pow(dot(v, h) * 0.5 + 0.5, specPower) * diffuse;