โครงร่างสีขาวแปลก ๆ รอบตัวแบบ


19

ฉันกำลังทำงานกับเกมใน XNA 4 และฉันเพิ่งเปลี่ยนไปใช้การแรเงาที่รอการตัดบัญชีตามคู่มือนี้ มีโครงร่างสีขาวแปลก ๆ ปรากฏขึ้นในแบบจำลองของฉันในตอนนี้และฉันไม่แน่ใจว่าเกิดจากอะไร ฉันคิดว่าบางทีการขาดความแม่นยำของเป้าหมายการเรนเดอร์ปกติหรือการเรนเดอร์เป้าหมายแบบลึก แต่การเพิ่มพวกมันเป็น 64 บิต (Rgba64) แทนที่จะเป็น 32 (สี) ไม่ได้ช่วยอะไรเลย ฉันก็คิดว่ามันอาจจะมีปัญหากับการคำนวณแบบ specular ดังนั้นฉันจึงลองตั้ง specular เป็น 0 แต่นั่นก็ไม่ได้ช่วยเช่นกัน การดีบักพิกเซลใน PIX แสดงว่าค่าการกระจายกำลังถูกคำนวณเป็นสีขาวเกือบสำหรับพิกเซลนั้น ความคิดใด ๆ ฉันรวมรูปภาพของปัญหาไว้ด้านล่างแล้วจะเห็นได้ง่ายขนาดเต็ม

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

แก้ไข : ขออภัยเกี่ยวกับ JPG ผู้อัปโหลดของ stackexchange ทำเช่นนั้นด้วยตนเอง Roy T: จริงๆแล้วฉันอ้างอิงการแปลง XNA4 ของคุณสำหรับการสอนเกี่ยวกับชิ้นส่วนที่เปลี่ยนจาก XNA3 เนื่องจากฉันไม่ได้ทำการเปลี่ยนแปลงครั้งใหญ่กับรหัสฉันคิดว่าอาจมีข้อผิดพลาดนี้อยู่ในต้นฉบับ แต่เป็นไปไม่ได้ที่จะเห็นด้วยแสงจำนวนมากเคลื่อนที่ไปมาดังนั้นฉันจึงลบออกทั้งหมดยกเว้นหนึ่งไฟและข้อผิดพลาดปรากฏขึ้นอีกครั้ง ใกล้ข้อศอกของจิ้งจก)

นี่คือเนื้อหาของ GBuffer สำหรับฉากของฉัน:

Color Buffer: Depth Buffer: Normal Buffer: Final Render:

แก้ไข 2 :

ฉันเริ่มสงสัยว่าปัญหาคือ CombineFinal.fx เมื่อมันตัวอย่างแผนที่สี นี่คือการคำนวณสำหรับพิกเซลสีที่เหมาะสมติดกับพิกเซลสีขาว:

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

และนี่คือผลลัพธ์จากพิกเซลสีขาวที่มีสีไม่ถูกต้องติดกับ:

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 เป็นความแตกต่างเพียงอย่างเดียวและสีนี้จะนำมาจากแผนที่สีโดยตรง อาจมีข้อผิดพลาดเล็กน้อยในการคำนวณพิกัดของพื้นผิวที่ต้องการตัวอย่างจาก?

แสงสว่างผ่าน:


4
กรุณาอย่า jpeg ไม่บีบอัดภาพหน้าจอที่แสดงข้อผิดพลาดกราฟิกเล็กน้อย ผู้คนจะต้องการเห็นปัญหาในการสืบพันธุ์ที่สมบูรณ์แบบ
aaaaaaaaaaaa

การบีบอัด jpeg จริง ๆ ช่วยให้ความผิดพลาดค่อนข้างดีฉันคิดว่าหนึ่งพิกเซลเท่านั้นและเมื่อบางสิ่งรวมกัน (ความแตกต่างใหญ่ในความลึก Z และแสงค่อนข้างสูงสำหรับพิกเซลทั้งหมด) โชคดีการเรนเดอร์นั้นค่อนข้างเป็นเรื่องเทคนิค
Valmond

2
ไม่แน่ใจว่ามันช่วยได้หรือไม่ แต่คุณใช้โค้ด / การสอนเวอร์ชันเก่ามากโค้ด / การสอนที่แท้จริงของ Catalin Zima อยู่ที่: catalinzima.com/tutorials/deferred-rendering-in-xnaและ Catalina Zima รุ่นตั้งอยู่ที่นี่: roy-t.nl/index.php/2010/12/28/…
Roy T.

และเช่นเคยกับการดีบักการเรนเดอร์ที่เลื่อนออกไปคุณสามารถโพสต์ภาพหน้าจอจากบัฟเฟอร์ทั้งหมดได้หรือไม่ มันอาจอยู่ในบัฟเฟอร์แสง แต่มันอาจเป็นอย่างอื่น
รอยต.

สัญชาตญาณของฉันคือมันจะเป็นปัญหากับวิธีที่ส่วนหนึ่งของอัลกอริทึมจัดการกับมุม 90 องศาอย่างแน่นอน แต่ฉันจะต้องเล่นกับบทกวีหลังเลิกงานเพื่อดูเพิ่มเติม
Jordaan Mylonas

คำตอบ:


4

ฉันมีโครงร่างสีขาวหรือ "รัศมี" รอบ ๆ โมเดลของฉันด้วยเมื่อฉันเริ่มใช้โหมดแสดงภาพที่เลื่อนออกไป ปัญหาคือค่าการชดเชยพื้นผิวสำหรับการวางซ้อนเป้าหมายการแสดงผลไม่ได้ตั้งค่าอย่างถูกต้อง พื้นผิวบางอย่างจำเป็นต้องตั้งค่าเป็น +0.5 พิกเซลสำหรับออฟเซ็ตแทนที่จะเป็น -0.5 พิกเซล

มันเป็นเพียงหลังจากการปรับแต่งค่าของบางส่วนของพื้นผิวที่ชดเชยที่เค้าร่างไป เป็นไปได้มากว่ามันเป็นหนึ่งในโคมไฟ

แก้ไข: โดยวิธีการที่ฉันได้เรียนรู้จากการกวดวิชาของ Catalin Zima ซึ่งเป็นสาขาจากตัวอย่างของคุณดังนั้นจึงควรใช้งานได้


ใช่นั่นแหละ ฉันเปลี่ยนเป็น + halfPixel สำหรับการสุ่มพิกัดทั้งหมดใน light shader และรัศมีนั้นหายไปแล้ว
Telanor

0

ฉันไม่แน่ใจว่าเกิดอะไรขึ้น แต่มีสองสิ่งที่ต้องตรวจสอบอีกครั้ง:

  1. ตรวจสอบให้แน่ใจว่าคุณได้ปิดการกรองพื้นผิวเมื่อสุ่มตัวอย่าง G-buffers - ไม่มีไบนินอร์หรือแอนไอโซโทรปิกหรืออะไรก็ได้

  2. ฉันเห็นว่าคุณเพิ่มออฟเซ็ตครึ่งพิกเซลลงในพิกัดพื้นผิว ตรวจสอบอีกครั้งว่าถูกต้อง ฉันไม่คุ้นเคยกับ XNA มากพอที่จะรู้ว่า offset ควรเป็นอะไร แต่คุณควรตรวจสอบมันด้วยการเขียน shader ที่สุ่มตัวอย่างหนึ่งใน G-buffers และแค่เอาท์พุทตัวอย่าง จากนั้นพลิกไปมาระหว่างสิ่งนี้และแสดง G-buffer บนหน้าจอโดยตรง หากคุณมีการชดเชยที่ถูกต้องคุณจะไม่เห็นความแตกต่างเลยแม้แต่พิกเซลเดียว


ฉันไปและเปลี่ยนแปลงทุกอย่างที่เกี่ยวข้องกับ GBuffer เป็น POINT (ฉันคิดว่าปิดการใช้งานการกรองหรือไม่) และยังคงเหมือนเดิม เกี่ยวกับจุดที่สองของคุณจะไม่ส่งออก GBuffer โดยตรงเหมือนกัน: สร้าง shader ที่เพิ่งส่งออกข้อมูลหรือไม่ คุณช่วยอธิบายเพิ่มเติมอีกเล็กน้อยได้ไหม?
Telanor

คุณสร้างภาพหน้าจอของ G-buffer ด้านบนได้อย่างไร ฉันคิดว่าคุณเรียกฟังก์ชั่น API ในตัวเพื่อคัดลอกพิกเซลแบบหนึ่งต่อหนึ่งจาก G-buffer ไปยังหน้าจอ (บัฟเฟอร์ด้านหลัง)? (ฉันไม่รู้ XNA ดังนั้นฉันไม่รู้ว่ามันจะถูกเรียกว่าอะไร) ฉันกำลังพูดว่าเปรียบเทียบเอาท์พุทของฟังก์ชั่นการถ่ายเอกสารแบบหนึ่งต่อหนึ่งกับเอาต์พุตของตัวแปลงพิกเซลที่เขียนขึ้นเพื่อทำ สำเนาแบบหนึ่งต่อหนึ่ง ... วิธีการที่คุณสามารถมั่นใจได้เนื้อพิกัดถูกต้องตรงและคุณจริงๆจะได้รับหนึ่งต่อหนึ่งการสุ่มตัวอย่าง
Nathan Reed
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.