Pracuję nad grą w XNA 4 i niedawno przeszedłem na implementację odroczonego cieniowania zgodnie z tym przewodnikiem . Na moich modelach pojawia się dziwny biały kontur i nie jestem pewien, co to powoduje. Pomyślałem, że może to brak precyzji w normalnym celu renderowania lub celu renderowania głębokości, ale zwiększenie ich do 64 bitów (Rgba64) zamiast 32 (Kolor) nie pomogło. Pomyślałem również, że może to być problem z obliczeniami zwierciadlanymi, więc spróbowałem ustawić zwierciadło na 0, ale to też nie pomogło. Debugowanie piksela w systemie PIX pokazuje, że wartość rozproszona jest obliczana jako prawie biała dla tego piksela. Jakieś pomysły? Poniżej zamieściłem zdjęcie problemu, łatwiej zobaczyć go w pełnym rozmiarze.
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);
}
Edycja : Przepraszamy za plik JPG, program do przesyłania Stackexchange zrobił to sam. Roy T: Właściwie odniosłem się do twojej konwersji XNA4 samouczka dla części, które zmieniły się z XNA3. Ponieważ nie wprowadziłem żadnych dużych zmian w kodzie, pomyślałem, że może ten błąd istniał w oryginale, ale było po prostu niemożliwe do zobaczenia z tyloma światłami, które się poruszały, więc usunąłem wszystkie oprócz jednego światła i błąd pojawił się ponownie (patrz w pobliżu łokcia jaszczurki)
Oto zawartość GBuffer dla mojej sceny:
Bufor kolorów: Bufor głębi: Bufor normalny: Ostateczne renderowanie:
Edycja2 :
Zaczynam podejrzewać, że problemem jest CombineFinal.fx podczas próbkowania mapy kolorów. To jest obliczenie prawidłowo kolorowego piksela tuż obok białego piksela:
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
I to jest wynik z niewłaściwie zabarwionego białego piksela bezpośrednio obok niego:
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 jest jedyną różnicą, a ten kolor jest pobierany bezpośrednio z mapy kolorów. Być może podczas obliczania współrzędnej tekstury, z której pobierana jest próbka, występuje niewielki błąd?
Karnet oświetleniowy:
Odpowiedzi:
Miałem też ten biały kontur lub „aureolę” wokół moich modeli, kiedy zacząłem na własnym odroczonym rendererze. Problem polegał na tym, że wartość przesunięcia tekstury dla nakładania celów renderowania nie została poprawnie skonfigurowana. Niektóre tekstury musiały być ustawione na +0,5 pikseli dla przesunięcia zamiast -0,5 pikseli.
Dopiero po poprawieniu wartości niektórych przesunięć tekstur kontury zniknęły. Najprawdopodobniej jest w jednym z shaderów oświetlenia.
Edycja: przy okazji nauczyłem się również z samouczka Catalin Zima, który jest gałęzią twojego przykładu, więc powinien działać.
źródło
Nie jestem pewien, co się właściwie dzieje, ale kilka rzeczy do sprawdzenia:
Upewnij się, że masz wyłączone filtrowanie tekstur podczas próbkowania buforów G - bez dwuliniowych, anizotropowych ani nic.
Widzę, że dodajesz przesunięcie o pół piksela do współrzędnych tekstury; dokładnie sprawdź, czy to prawda. Nie znam wystarczająco XNA, aby wiedzieć, jakie powinno być właściwe przesunięcie, ale powinieneś być w stanie to sprawdzić, pisząc moduł cieniujący, który próbkuje jeden z buforów G i po prostu wysyła próbkę. Następnie przewijaj w tę iz powrotem, wyświetlając bufor G bezpośrednio na ekranie. Jeśli masz prawidłowe przesunięcie, nie powinieneś widzieć żadnych różnic, nawet jednego piksela.
źródło