Contour blanc étrange autour du modèle

19

Je travaille sur un jeu dans XNA 4 et je suis récemment passé à une implémentation d'ombrage différé en suivant ce guide . Un étrange contour blanc apparaît maintenant sur mes modèles et je ne suis pas sûr de ce qui cause cela. Je pensais que c'était peut-être un manque de précision sur la cible de rendu normale ou la cible de rendu en profondeur, mais les augmenter à 64 bits (Rgba64) au lieu de 32 (Couleur) n'a pas aidé. J'ai également pensé que cela pourrait être un problème avec le calcul spéculaire, j'ai donc essayé de mettre le spéculaire à 0, mais cela n'a pas aidé non plus. Le débogage du pixel dans PIX montre que la valeur diffuse est calculée comme presque blanche pour ce pixel. Des idées? J'ai inclus une photo du problème ci-dessous, il est plus facile de le voir en taille réelle.

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 : Désolé pour le JPG, l'uploader de stackexchange l'a fait tout seul. Roy T: J'ai effectivement référencé votre conversion XNA4 du tutoriel pour les parties qui ont changé de XNA3. Comme je n'ai pas apporté de modifications majeures au code, j'ai pensé que ce bug existait peut-être dans l'original mais était tout simplement impossible à voir avec autant de lumières qui se déplaçaient, alors j'ai supprimé toutes les lampes sauf une et le bug est réapparu (regardez près du coude du lézard)

Voici le contenu de GBuffer pour ma scène:

Tampon de couleurs: Tampon de profondeur : Tampon normal: Rendu final:

Edit2 :

Je commence à soupçonner que le problème est CombineFinal.fx lorsqu'il échantillonne la carte de couleurs. Voici le calcul d'un pixel correctement coloré juste à côté d'un pixel blanc:

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

Et voici la sortie d'un pixel blanc mal coloré juste à côté:

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

La couleur diffuse est la seule différence, et cette couleur est prise directement à partir de la carte des couleurs. Peut-être y a-t-il une légère erreur dans le calcul de la coordonnée de texture à échantillonner?

Pass d'éclairage:

Telanor
la source
4
S'il vous plaît non pas compresser jpeg une capture d'écran montrant un glitch graphique subtil. Les gens voudront voir le problème dans une reproduction parfaite.
aaaaaaaaaaaa
Eh bien, je pense que la compression jpeg laisse passer le problème assez bien, un pixel seulement et seulement lorsque certaines choses sont réunies (grand diff en profondeur Z et l'éclairage est (assez) élevé sur tous les pixels). Bonne chance, le rendu différé est assez technique.
Valmond
2
Je ne sais pas si cela aide, mais vous utilisez une très ancienne version du code / tutoriel, le code / tutoriel réel de Catalin Zima est maintenant sur: catalinzima.com/tutorials/deferred-rendering-in-xna et un XNA4.0 sanctionné la version se trouve ici: roy-t.nl/index.php/2010/12/28/…
Roy T.
Comme toujours avec le débogage du rendu différé, pourriez-vous publier des captures d'écran de tous les tampons? C'est probablement dans le tampon d'éclairage, mais ça pourrait être autre chose.
Roy T.
Mon instinct est que ce sera un problème avec la façon dont une partie de l'algorithme gère exactement un angle de 90 degrés, mais je devrai jouer avec l'ode après le travail pour approfondir la question.
Jordaan Mylonas

Réponses:

4

J'avais aussi ce contour blanc ou "halo" autour de mes modèles, quand j'ai commencé sur mon propre rendu différé. Le problème était que la valeur de décalage de texture pour superposer les cibles de rendu n'était pas configurée correctement. Certaines textures devaient être définies sur +0,5 pixels pour le décalage au lieu de -0,5 pixels.

Ce n'est qu'après avoir modifié les valeurs de certains décalages de texture que les contours ont disparu. C'est probablement dans l'un des shaders d'éclairage.

Edit: d'ailleurs, j'ai également appris du tutoriel de Catalin Zima qui est une branche de votre exemple, donc cela devrait fonctionner.

ChrisC
la source
Ouais, c'était tout. Je l'ai changé en + halfPixel pour tout l'échantillonnage de coordonnées dans le shader de lumière et le halo a disparu maintenant.
Telanor
0

Je ne sais pas exactement ce qui se passe, mais deux ou trois choses à vérifier:

  1. Assurez-vous que le filtrage de texture est désactivé lors de l'échantillonnage des tampons G - pas bilinéaire ou anisotrope ou quoi que ce soit.

  2. Je vois que vous ajoutez un décalage d'un demi-pixel aux coordonnées de la texture; revérifiez que c'est vrai. Je ne connais pas assez bien XNA pour savoir quel devrait être le bon décalage, mais vous devriez pouvoir le vérifier en écrivant un shader qui échantillonne l'un des G-buffers et sort juste l'échantillon. Basculez ensuite d'avant en arrière entre cela et affichez le G-buffer directement à l'écran. Si vous avez le bon décalage, vous ne devriez voir aucune différence, pas même un seul pixel.

Nathan Reed
la source
Je suis allé changer tout ce qui concerne le GBuffer en POINT (je suppose que cela désactive le filtrage?) Et c'est toujours le même. À propos de votre deuxième point, la sortie directe du GBuffer ne serait-elle pas exactement la même: créer un shader qui ne fait que sortir les données? Pouvez-vous nous en dire un peu plus à ce sujet?
Telanor
Eh bien, comment avez-vous généré les captures d'écran du G-buffer ci-dessus? Je suppose que vous appelez une sorte de fonction API intégrée, pour copier les pixels un à un du tampon G vers l'écran (tampon arrière)? (Je ne connais pas XNA donc je ne sais pas comment il s'appellerait.) Je dis, comparez la sortie de la fonction de copie un-à-un intégrée à la sortie d'un pixel shader écrit pour faire une copie un à un ... de cette façon, vous pouvez être sûr que les coordonnées de la texture sont exactement correctes et vous obtenez vraiment un échantillonnage un à un.
Nathan Reed