Estou trabalhando em um jogo no XNA 4 e recentemente mudei para uma implementação de sombreamento adiado seguindo este guia . Um estranho contorno branco está aparecendo nos meus modelos agora e não tenho certeza do que está causando isso. Eu pensei que talvez fosse uma falta de precisão no alvo de renderização normal ou no alvo de renderização em profundidade, mas aumentá-los para 64 bits (Rgba64) em vez de 32 (Cor) não ajudou. Também pensei que poderia haver algum problema com o cálculo especular, então tentei definir o especular como 0, mas isso também não ajudou. A depuração do pixel no PIX mostra que o valor difuso está sendo calculado como quase branco para esse pixel. Alguma ideia? Incluí uma imagem do problema abaixo; é mais fácil vê-la em tamanho real.
Pixel Shader:
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
input.ScreenPosition.xy /= input.ScreenPosition.w;
float2 texCoord = 0.5f * (float2(input.ScreenPosition.x, -input.ScreenPosition.y) + 1) - halfPixel;
float4 normalData = tex2D(normalSampler, texCoord);
//Transform normal back into [-1, 1] range
float3 normal = normalize(2.0f * normalData.xyz - 1.0f);
float specularPower = normalData.a;
float specularHardness = tex2D(colorSampler, texCoord).a * 255;
float depthVal = tex2D(depthSampler, texCoord).r;
//Compute screen-space position
float4 position = float4(input.ScreenPosition.xy, depthVal, 1.0f);
//Transform to world space
position = mul(position, InvertViewProjection);
position /= position.w;
//Surface-to-light vector
float3 lightVector = lightPosition - position;
float3 projectedTexCoords = position - lightPosition;
projectedTexCoords = mul(projectedTexCoords, float3x3(
float3(-1, 0, 0),
float3(0, 1, 0),
float3(0, 0, 1)));
float distanceToLight = length(lightVector) / lightRadius;
float shadow = ShadowContribution(projectedTexCoords, distanceToLight);
float attenuation = saturate(1.0f - distanceToLight);
lightVector = normalize(lightVector);
//Compute diffuse light
float normalDotLight = max(0, dot(normal, lightVector));
float3 diffuseLight = normalDotLight * Color.rgb;
float3 reflectionVector = normalize(reflect(-lightVector, normal));
float3 directionToCamera = normalize(cameraPosition - position);
float specularLight = specularPower * pow(saturate(dot(reflectionVector, directionToCamera)), specularHardness);
return shadow * attenuation * lightIntensity * float4(diffuseLight.rgb, specularLight);
}
Edit : Desculpe pelo JPG, o uploader da stackexchange fez isso por conta própria. Roy T: Na verdade, fiz referência à sua conversão de XNA4 do tutorial para as partes que mudaram de XNA3. Como não fiz grandes alterações no código, pensei que talvez esse bug existisse no original, mas era impossível ver com tantas luzes se movendo, então removi todas, exceto uma, e o bug apareceu novamente (veja perto do cotovelo do lagarto)
Aqui estão os conteúdos do GBuffer para a minha cena:
Buffer de cores: Buffer de profundidade : Buffer normal: Renderização final:
Edit2 :
Estou começando a suspeitar que o problema é CombineFinal.fx quando ele mostra o mapa de cores. Este é o cálculo para um pixel adequadamente colorido ao lado de um pixel branco:
diffuseColor : (0.435, 0.447, 0.412)
diffuseLight : (1.000, 1.000, 0.902)
light : (1.000, 1.000, 0.902, 0.000)
PixelShaderFunction : (0.435, 0.447, 0.371, 1.000)
specularLight : 0.000
E esta é a saída de um pixel branco incorretamente colorido diretamente ao lado:
diffuseColor : (0.824, 0.792, 0.741)
diffuseLight : (1.000, 1.000, 0.902)
light : (1.000, 1.000, 0.902, 0.000)
PixelShaderFunction : (0.824, 0.792, 0.669, 1.000)
specularLight : 0.000
O diffuseColor é a única diferença, e essa cor é obtida diretamente do mapa de cores. Talvez exista um pequeno erro no cálculo da coordenada de textura para a amostra?
Passe de iluminação: