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:
Respuestas:
También tenía este contorno blanco o "halo" alrededor de mis modelos, cuando comencé con mi propio renderizador diferido. El problema era que el valor de compensación de textura para superponer los objetivos de renderizado no estaba configurado correctamente. Algunas texturas debían establecerse en +0.5 píxeles para el desplazamiento en lugar de -0.5 píxeles.
Fue solo después de ajustar los valores de algunas de las compensaciones de textura que los contornos desaparecieron. Lo más probable es que esté en uno de los sombreadores de iluminación.
Editar: por cierto, también aprendí del tutorial de Catalin Zima, que es una rama de su ejemplo, por lo que debería funcionar.
fuente
No estoy seguro exactamente de lo que está sucediendo, pero hay un par de cosas para verificar:
Asegúrese de que tiene el filtro de textura desactivado cuando muestree los tampones G, sin bilineal o anisotrópico ni nada.
Veo que está agregando un desplazamiento de medio píxel a las coordenadas de textura; verifica que eso sea correcto. No estoy lo suficientemente familiarizado con XNA para saber cuál debería ser el desplazamiento correcto, pero debería poder verificarlo escribiendo un sombreador que muestree uno de los G-buffers y solo muestre la muestra. Luego, avance y retroceda entre esto y muestre el G-buffer directamente en la pantalla. Si tiene el desplazamiento correcto, no debería ver diferencias, ni siquiera un solo píxel.
fuente