Model çevresinde garip beyaz anahat


19

XNA 4'te bir oyun üzerinde çalışıyorum ve son zamanlarda bu kılavuzu izleyerek ertelenmiş bir gölgeleme uygulamasına geçtim . Modellerimde garip bir beyaz anahat görünüyor ve buna neyin neden olduğundan emin değilim. Belki normal render hedefi veya derinlik render hedefi üzerinde bir hassasiyet eksikliği olduğunu düşündüm ama 32 (Renk) yerine 64 bit'e (Rgba64) yükseltmek yardımcı olmadı. Ben de speküler hesaplama ile ilgili bir sorun olabileceğini düşündüm bu yüzden 0 speküler ayarlamaya çalıştım ama bu da yardımcı olmadı. PIX'te pikselde hata ayıklama, dağınık değerin o piksel için neredeyse beyaz olarak hesaplandığını gösterir. Herhangi bir fikir? Aşağıdaki sorunun bir resmini ekledim, tam boyutta görmek daha kolay.

Piksel gölgelendirici:

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);
}

Düzenleme : JPG için üzgünüm, stackexchange'in yükleyicisi bunu kendi başına yaptı. Roy T: Aslında XNA3'ten değiştirilen parçalar için öğreticinin XNA4 dönüşümüne başvurdum. Kodda herhangi bir büyük değişiklik yapmadığım için belki de bu hatanın orijinalinde var olduğunu düşündüm, ancak etrafta hareket eden birçok ışıkla görmek imkansızdı, bu yüzden bir ışık hariç hepsini kaldırdım ve hata tekrar ortaya çıktı (bak kertenkelenin dirseğine yakın)

İşte sahnem için GBuffer içerikleri:

Renk Tamponu: Derinlik Tamponu: Normal Tampon: Son İşleme:

Edit2 :

Renk eşlemini örneklediğinde sorunun CombineFinal.fx olduğundan şüphelenmeye başlıyorum. Bu, beyaz bir pikselin hemen yanında uygun şekilde renkli bir pikselin hesaplanmasıdır:

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

Ve bu, hemen yanındaki yanlış renklendirilmiş beyaz bir pikselin çıktısıdır:

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 tek farktır ve bu renk doğrudan renk haritasından alınır. Belki de numuneden doku koordinatının hesaplanmasında küçük bir hata var mı?

Aydınlatma Geçişi:


4
Jpeg, ince bir grafik aksaklığı gösteren bir ekran görüntüsünü sıkıştırmayın. İnsanlar sorunu mükemmel üremede görmek isteyeceklerdir.
aaaaaaaaaaaa

Aslında, jpeg sıkıştırma aslında aksaklığı oldukça güzel bir şekilde geçirdiğini düşünüyorum, sadece bir piksel ve sadece belirli şeyler tekrar bir araya geldiğinde (Z derinliğinde büyük fark ve aydınlatma tüm piksellerde oldukça yüksek). İyi şanslar, ertelenmiş render işlemi oldukça tekniktir.
Valmond

2
Bunun yardımcı olup olmadığından emin değilim, ancak kodun / öğreticinin çok eski bir sürümünü kullanıyorsunuz, Catalin Zima'nın gerçek kodu / öğreticisi şu anda: catalinzima.com/tutorials/deferred-rendering-in-xna ve onaylanmış bir XNA4.0 sürüm burada bulunur: roy-t.nl/index.php/2010/12/28/…
Roy T.

Ayrıca, her zaman olduğu gibi, ertelenmiş oluşturmada hata ayıklama ile, tüm arabelleklerden ekran görüntüleri gönderebilir misiniz? Muhtemelen aydınlatma tamponundadır, ama başka bir şey olabilir.
Roy T.

İçgüdüm, algoritmanın bir kısmının tam olarak 90 derecelik bir açıyı işleme biçimiyle ilgili bir sorun olacağı, ancak daha sonra bakmak için işten sonra ode ile oynamak zorunda kalacağım.
Jordaan Mylonas

Yanıtlar:


4

Kendi ertelenmiş oluşturucuma başladığımda, modellerimin etrafında bu beyaz anahat ya da "halo" vardı. Sorun, oluşturma hedeflerinin üst üste binmesi için doku ofset değerinin doğru ayarlanmamış olmasıdır. Bazı dokuların ofset için -0,5 piksel yerine +0,5 piksele ayarlanması gerekiyordu.

Sadece doku ofsetlerinin bazılarının değerlerini düzelttikten sonra ana hatlar gitmişti. Büyük olasılıkla ışık gölgelendiricilerinden birinde.

Düzenleme: Bu arada ben de örnek bir şube olan Catalin Zima'nın öğretici öğrendim, bu yüzden çalışması gerekir.


Evet, işte bu. Işık gölgelendiricideki tüm koordinat örneklemesi için + halfPixel olarak değiştirdim ve hale artık gitti.
Telanor

0

Neler olup bittiğinden tam olarak emin değilim, ancak tekrar kontrol etmek için birkaç şey:

  1. G tamponlarını örneklerken doku filtrelemenin kapalı olduğundan emin olun - bilinear veya anizotropik veya başka bir şey yok.

  2. Doku koordinatlarına yarım piksel uzaklık eklediğinizi görüyorum; doğru olduğunu tekrar kontrol edin. Doğru ofsetin ne olması gerektiğini bilmek için XNA ile yeterince aşina değilim, ancak G tamponlarından birini örnekleyen ve sadece örnek çıktılar bir gölgelendirici yazarak kontrol edebilmelisiniz. Ardından, bunun arasında G-buffer'ı doğrudan ekranda görüntüleme arasında ileri geri dönün. Doğru ofsete sahipseniz, tek bir piksel bile fark görmemelisiniz.


Ben gitti ve GBuffer ile ilgili her şeyi POINT (filtre devre dışı bırakır? Varsayalım?) Ve hala aynı değiştirildi. İkinci noktanız hakkında, GBuffer'ın çıktısı doğrudan aynı olmazdı: sadece verileri çıkaran bir gölgelendirici mi yapıyorsunuz? Biraz daha ayrıntı verebilir misiniz?
Telanor

Peki, yukarıdaki G tamponunun ekran görüntülerini nasıl oluşturdunuz? Ben pikselleri G-buffer ekrandan (arka tampon) bire bir kopyalamak için yerleşik API işlevi bir tür çağırmak varsayalım? (XNA bilmiyorum, bu yüzden ne denir bilmiyorum.) Diyorum ki, yerleşik bire bir kopyalama işlevinin çıktısını yapmak için yazılmış bir piksel gölgelendiricinin çıktısı ile karşılaştırın bire bir kopya ... bu şekilde doku koordinatlarının tam olarak doğru olduğundan ve gerçekten bire bir örnekleme aldığınızdan emin olabilirsiniz .
Nathan Reed
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.