Estamos tendo alguns problemas com o nosso traçado de raios no DirectX, especialmente com alguns problemas sérios de faixas com o especular. Com alta potência especular (acima de 8), começa a formação de faixas. Gostaria de saber se este é um problema de HDR / LDR ou pode estar relacionado a outra coisa, como normais ou outros vetores?
ATUALIZAR
Veja abaixo as atualizações.
Aqui está o código de sombreamento relevante para Blinn-Phong em uma 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 é igual a 8 nesta imagem
specPower é igual a 9 nesta imagem
Isso é tão simples quanto um problema de HDR / LDR ou está de alguma forma relacionado à precisão normal? Acredito que já encontrei esse problema antes em um renderizador diferido, onde os normais eram de baixa precisão e embalados / descompactados incorretamente, mas, neste caso, os normais são gerados em tempo real e tudo é renderizado diretamente no backbuffer.
Atualização 1
Gostaria de acrescentar que os triângulos sofrem o mesmo artefato e que eles têm seu normal gerado atualmente da seguinte maneira:
float3 normal = normalize(cross(triangles[bestHit.hitID].vertices[1] - triangles[bestHit.hitID].vertices[0],
triangles[bestHit.hitID].vertices[2] - triangles[bestHit.hitID].vertices[0]));
Eu diria que isso torna ainda mais improvável que o normal da superfície seja o problema. A imagem a seguir mostra o que acontece quando o specPower chega a 2048.
spec
diretamente, e também max(dot(normal, h), 0.0f)
. Procure esse retorno para um valor 1 em qualquer cálculo.
float3 h = normalize( reflect(toLight,normal) );
, espec = pow(dot(v, h) * 0.5 + 0.5, specPower) * diffuse;