Estoy trabajando en un juego en XNA 4 y recientemente cambié a una implementación de sombreado diferido siguiendo esta guía . Un extraño contorno blanco aparece en mis modelos ahora y no estoy seguro de qué está causando esto. Pensé que tal vez era una falta de precisión en el objetivo de renderizado normal o el objetivo de renderizado de profundidad, pero aumentarlos a 64 bits (Rgba64) en lugar de 32 (Color) no ayudó. También pensé que podría ser un problema con el cálculo especular, así que intenté establecer el especular en 0, pero eso tampoco ayudó. La depuración del píxel en PIX muestra que el valor difuso se calcula como casi blanco para ese píxel. ¿Algunas ideas? Incluí una imagen del problema a continuación, es más fácil verlo a tamaño completo.
Sombreador de píxeles:
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);
}
Editar : Perdón por el JPG, el cargador de stackexchange lo hizo solo. Roy T: Realmente hice referencia a su conversión XNA4 del tutorial para las partes que cambiaron de XNA3. Como no hice grandes cambios en el código, pensé que tal vez este error existía en el original, pero era imposible de ver con tantas luces moviéndose, así que eliminé todas las luces menos una y el error volvió a aparecer (mira cerca del codo del lagarto)
Aquí están los contenidos de GBuffer para mi escena:
Color Buffer: Profundidad Buffer: Normal Buffer: Reproducción final:
Edit2 :
Estoy empezando a sospechar que el problema es CombineFinal.fx cuando muestrea el mapa de colores. Este es el cálculo para un píxel coloreado correctamente justo al lado de un píxel blanco:
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
Y esta es la salida de un píxel blanco de color incorrecto directamente al 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
DiffuseColor es la única diferencia, y este color se toma directamente del mapa de colores. ¿Quizás haya un ligero error en el cálculo de la coordenada de textura de la que se tomará la muestra?
Pase de iluminación: