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.
fuente
float3 h = normalize( reflect(toLight,normal) );
, yspec = pow(dot(v, h) * 0.5 + 0.5, specPower) * diffuse;
spec
directamente, y tambiénmax(dot(normal, h), 0.0f)
. Busque este retorno a un valor 1 en cualquier cálculo.Respuestas:
Parece un problema con la implementación de la función pow en esta GPU en particular.
Cuando sospeche un error en una función matemática, reemplace la función matemática por su equivalente, por ejemplo, reemplace:
Con el error que se muestra en specPower = 9.0, codifíquelo
O
Si el problema desaparece, esto significa que probablemente haya un error de flujo inferior en la función pow con respecto al exponente en esta GPU o controlador.
Lo que puede hacer como solución alternativa , suponiendo que el cálculo del sombreador de fragmentos se realice internamente con flotadores de 16 bits. Si calculo esto bien, deberías hacer
Podría ser 32768 u 8192: podría estar apagado un bit o la GPU podría estar usando más o menos precisión. para pow (x, 9.0), la sujeción sería pow (max (temp, 0.3401975), 9.0) Los valores de X por debajo de esto desbordarían el rango de exponente (+15 a -14) de los puntos flotantes IEEE de 16 bits (de nuevo, estoy suponiendo que esto es lo que usa la GPU).
del código de rosetta ( http://rosettacode.org/wiki/Nth_root#C.2B.2B )
Tendrá que calcular esto en la CPU y alimentar el valor de manera uniforme: la GPU probablemente tendrá el mismo problema de precisión si calcula esto directamente en el sombreador.
Si puede confirmar esto, intente ponerse en contacto con el equipo de controladores de GPU con un código fuente de sombreador de muestra que reproduzca el problema, proporcione la versión exacta del controlador, el sistema operativo y la revisión del modelo de GPU, un ejecutable podría ayudar, pero no lo envíe como su correo electrónico lo hará. quedar atrapado en el verificador de virus / spam. Simplemente construya uno y conserve una copia en caso de que soliciten un ejecutable de muestra preconstruido. Como cortesía, deles la oportunidad de arreglarlo antes de nombrarlo públicamente. Podría ser simplemente un error de optimización en su compilador de sombreadores que solo ocurre con su sombreador en particular. Puede tomar un tiempo (meses) ponerse en contacto con ellos, estos muchachos a menudo carecen de personal.
fuente