Extraño contorno blanco alrededor del modelo

19

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:

Telanor
fuente
44
Por favor, no, no JPEG comprimir una captura de pantalla que muestra una falla gráfica sutil. La gente querrá ver el problema en una reproducción perfecta.
aaaaaaaaaaaa
Bueno, la compresión jpeg en realidad deja pasar el problema bastante bien, creo, solo un píxel y solo cuando se reúnen ciertas cosas (gran diferencia en la profundidad Z y la iluminación es (bastante) alta en todos los píxeles). Buena suerte, el renderizado diferido es bastante técnico.
Valmond
2
No estoy seguro de si ayuda, pero está utilizando una versión muy antigua del código / tutorial, el código / tutorial real de Catalin Zima ahora está en: catalinzima.com/tutorials/deferred-rendering-in-xna y un XNA4.0 sancionado la versión se encuentra aquí: roy-t.nl/index.php/2010/12/28/…
Roy T.
Además, como siempre con la depuración de la representación diferida, ¿podría publicar capturas de pantalla de todos los buffers? Probablemente esté en el búfer de iluminación, pero podría ser otra cosa.
Roy T.
Mi instinto es que será un problema con la forma en que parte del algoritmo maneja exactamente un ángulo de 90 grados, pero tendré que jugar con la oda después del trabajo para investigarlo más a fondo.
Jordaan Mylonas

Respuestas:

4

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.

ChrisC
fuente
Sí, eso fue todo. Lo cambié a + halfPixel para todo el muestreo de coordenadas en el sombreador de luz y el halo se ha ido ahora.
Telanor
0

No estoy seguro exactamente de lo que está sucediendo, pero hay un par de cosas para verificar:

  1. Asegúrese de que tiene el filtro de textura desactivado cuando muestree los tampones G, sin bilineal o anisotrópico ni nada.

  2. 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.

Nathan Reed
fuente
Fui y cambié todo lo relacionado con el GBuffer a POINT (supongo que deshabilita el filtrado?) Y sigue siendo el mismo. Acerca de su segundo punto, ¿no generaría el GBuffer directamente exactamente lo mismo: crear un sombreador que solo muestre los datos? ¿Puedes explicarlo un poco más?
Telanor
Bueno, ¿cómo generaste las capturas de pantalla del G-buffer de arriba? ¿Supongo que llama a algún tipo de función API incorporada, para copiar los píxeles uno a uno desde el G-buffer a la pantalla (back buffer)? (No sé XNA, así que no sé cómo se llamaría). Estoy diciendo, compare la salida de la función de copia uno a uno incorporada con la salida de un sombreador de píxeles escrito para hacer una copia uno a uno ... de esa manera puede estar seguro de que las coordenadas de textura son exactamente correctas y realmente está obteniendo un muestreo uno a uno.
Nathan Reed