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: