Sto lavorando a un gioco in XNA 4 e di recente sono passato a un'implementazione differita dell'ombreggiatura seguendo questa guida . Una strana sagoma bianca sta comparendo sui miei modelli ora e non sono sicuro di cosa stia causando. Ho pensato che forse fosse una mancanza di precisione sul target di rendering normale o sul target di rendering di profondità, ma aumentarli a 64 bit (Rgba64) anziché 32 (Color) non ha aiutato. Ho anche pensato che potesse essere un problema con il calcolo speculare, quindi ho provato a impostare lo speculare su 0, ma non ha aiutato neanche. Il debug del pixel in PIX mostra che il valore diffuso viene calcolato come quasi bianco per quel pixel. Qualche idea? Ho incluso una foto del problema qui sotto, è più facile vederlo a grandezza naturale.
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);
}
Modifica : mi dispiace per il JPG, l'autore del caricamento di stackexchange lo ha fatto da solo. Roy T: In realtà ho fatto riferimento alla tua conversione XNA4 del tutorial per le parti che sono cambiate da XNA3. Dal momento che non ho apportato grandi modifiche al codice, ho pensato che forse questo bug esistesse nell'originale, ma era impossibile vederlo con così tante luci che si muovevano, quindi ho rimosso tutte le luci tranne una e il bug è apparso di nuovo (guarda vicino al gomito della lucertola)
Ecco i contenuti di GBuffer per la mia scena:
Buffer di colore: Buffer di profondità : Buffer normale: Rendering finale:
Modifica2 :
Sto iniziando a sospettare che il problema sia CombineFinal.fx quando campiona la mappa dei colori. Questo è il calcolo per un pixel adeguatamente colorato proprio accanto a un pixel bianco:
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
E questo è l'output di un pixel bianco di colore improprio direttamente accanto ad esso:
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 è l'unica differenza e questo colore viene preso direttamente dalla mappa dei colori. Forse c'è un leggero errore nel calcolo delle coordinate della trama da campionare?
Pass illuminazione: