Ich arbeite an einem Spiel in XNA 4 und bin kürzlich auf eine verzögerte Shading-Implementierung umgestiegen, die diesem Handbuch folgt . Auf meinen Modellen ist jetzt ein seltsamer weißer Umriss zu sehen, und ich bin nicht sicher, was dies verursacht. Ich dachte, es sei ein Mangel an Präzision beim normalen Rendern oder beim Tiefenrendern, aber die Erhöhung auf 64 Bit (Rgba64) anstelle von 32 Bit (Farbe) hat nicht geholfen. Ich dachte auch, es könnte ein Problem mit der Spiegelberechnung sein, also habe ich versucht, das Spiegelbild auf 0 zu setzen, aber das hat auch nicht geholfen. Das Debuggen des Pixels in PIX zeigt, dass der diffuse Wert für dieses Pixel als nahezu weiß berechnet wird. Irgendwelche Ideen? Ich habe unten ein Bild des Problems eingefügt. Es ist einfacher, es in voller Größe zu sehen.
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 : Sorry für das JPG, der Uploader von stackexchange hat das alleine gemacht. Roy T: Ich habe tatsächlich auf Ihre XNA4-Konvertierung des Tutorials für die Teile verwiesen, die von XNA3 geändert wurden. Da ich keine großen Änderungen am Code vorgenommen habe, dachte ich, dass dieser Fehler im Original existiert, aber bei so vielen Lichtern, die sich alle bewegen, einfach nicht zu sehen war. Also entfernte ich alle außer einem Licht und der Fehler tauchte wieder auf (siehe unten) in der Nähe des Ellbogens der Eidechse)
Hier sind die GBuffer-Inhalte für meine Szene:
Farbpuffer: Tiefenpuffer: Normalpuffer: Endpuffer:
Edit2 :
Ich beginne zu vermuten, dass das Problem CombineFinal.fx ist, wenn es die Farbkarte abtastet. Dies ist die Berechnung für ein richtig gefärbtes Pixel direkt neben einem weißen Pixel:
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
Und dies ist die Ausgabe eines falsch gefärbten weißen Pixels direkt daneben:
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
Die diffuseColor ist der einzige Unterschied, und diese Farbe wird direkt aus der Farbkarte übernommen. Möglicherweise liegt ein kleiner Fehler bei der Berechnung der Texturkoordinate vor, aus der abgetastet werden soll.
Lichtpass:
Antworten:
Ich hatte auch diesen weißen Umriss oder "Heiligenschein" um meine Modelle, als ich meinen eigenen verzögerten Renderer startete. Das Problem bestand darin, dass der Texturversatzwert zum Überlagern der Renderziele nicht korrekt eingerichtet wurde. Einige Texturen mussten für den Versatz auf +0,5 Pixel anstatt auf -0,5 Pixel eingestellt werden.
Erst nach dem Ändern der Werte einiger Textur-Offsets waren die Konturen verschwunden. Höchstwahrscheinlich ist es in einem der Lichtshader.
Bearbeiten: Übrigens habe ich auch aus Catalin Zimas Tutorial gelernt, das ein Zweig von Ihrem Beispiel ist, also sollte es funktionieren.
quelle
Ich bin mir nicht sicher, was genau los ist, aber ich muss ein paar Dinge überprüfen:
Stellen Sie sicher, dass die Texturfilterung deaktiviert ist, wenn Sie die G-Puffer abtasten - keine bilinearen oder anisotropen oder irgendetwas.
Ich sehe, dass Sie den Texturkoordinaten einen halben Pixelversatz hinzufügen. Überprüfen Sie noch einmal, ob das stimmt. Ich bin nicht mit XNA vertraut genug, um zu wissen, wie der richtige Versatz sein sollte, aber Sie sollten in der Lage sein, dies zu überprüfen, indem Sie einen Shader schreiben, der einen der G-Puffer abtastet und nur das Beispiel ausgibt. Blättern Sie dann zwischen diesen hin und her und zeigen Sie den G-Buffer direkt auf dem Bildschirm an. Wenn Sie den richtigen Versatz haben, sollten Sie keine Unterschiede sehen, nicht einmal ein einziges Pixel.
quelle