ยูทิลิตี้ของรัศมีกำลังสองและรัศมีกำลังสองอินเวอร์สสำหรับการคำนวณแสงคืออะไร?


16

ในหนึ่งในสไลด์จาก PowerPoint "DirectX 11 Rendering in Battlefield 3" ฉันสังเกตเห็นรหัส folowing:

struct Light {
    float3 pos; float sqrRadius;
    float3 color; float invSqrRadius;
}

ฉันไม่เข้าใจว่าทำไมพวกเขาถึงจัดเก็บรัศมีกำลังสองและแม้แต่อินเวอร์สสแควร์สแควร์ (ซึ่งฉันเชื่อว่าเป็นรัศมี 1 กำลังสอง) แทนที่จะเก็บรัศมี พวกเขาใช้ข้อมูลนี้ในการคำนวณอย่างไร ยิ่งไปกว่านั้นแล้วไฟทรงกรวยและไฟเส้นคืออะไร? struct นี้จะต้องมีเฉพาะสำหรับไฟจุดฉันไม่เห็นมันทำงานได้สำหรับประเภทอื่น - มีข้อมูลไม่เพียงพอ ถึงกระนั้นฉันก็ชอบที่จะรู้ว่าพวกเขาใช้สี่เหลี่ยมนั้นและ InvSquare อย่างไร

ปรับปรุง:ตกลงฉันได้รับมันในที่สุด

นี่คือสมการการลดทอนแสงแบบคลาสสิกซึ่งหาได้ง่ายในเน็ต:

float3 lightVector = lightPosition - surfacePosition;

float attenuation = saturate(1 - length(lightVector)/lightRadius);

มันค่อนข้างมีราคาแพงเช่นเดียวกับlength(lightVector)การทำสิ่งนี้:

length(lightVector) = sqrt(dot(lightVector, lightVector);

ยิ่งไปกว่านั้นการดำเนินงานของแผนก(/lightRadius)ก็มีค่าใช้จ่ายค่อนข้างสูง

แทนที่จะคำนวณการลดทอนแสงด้วยวิธีนี้คุณสามารถคำนวณด้วยวิธีต่อไปนี้ซึ่งจะเร็วกว่ามาก:

attenuation = saturate(1 - dot(lightVector, lightVector)*invRadiusSqr);

โดยที่ invRadiusSqr สามารถคำนวณล่วงหน้าได้ที่ระดับ CPU และส่งผ่านเป็นค่าคงที่ shader

ยิ่งไปกว่านั้นคุณจะได้รับการลดทอนของแสงแบบสมการกำลังสอง (แทนที่จะเป็นเส้นตรงในกรณีเดิม) ซึ่งดียิ่งขึ้นเนื่องจากแสง IRL แสดงให้เห็นว่ามีการตกหล่นแบบสมการกำลังสอง

ขอบคุณทุกคนสำหรับความช่วยเหลือของคุณ!


13
การขยายความ. Shaders อยู่ในแนวเดียวกัน 16bytes และถ้าคุณดูที่การจัดรูปแบบโค้ดคุณจะเห็นว่ามันจะถูกบรรจุในสอง float4 ทำไมไม่จัดเก็บสิ่งที่มีประโยชน์เมื่อคุณจะเอามันออกมาจากแคช?
Tordin

คำตอบ:


23

นี่เป็นเพียงการเพิ่มประสิทธิภาพอย่างหนึ่งเนื่องจากinvSqrRadius = 1/SqrRadiusแทนที่จะคำนวณรัศมีผกผันสแควร์สำหรับแต่ละแสงทุกครั้งที่ทำการแคชเหตุผลก็คือการแบ่งมักจะเป็นการดำเนินการ "ช้า" อย่างน้อยเมื่อเปรียบเทียบกับการคูณ

การเพิ่มประสิทธิภาพนี้มีความเกี่ยวข้องโดยเฉพาะ:

  • เมื่อการดำเนินการเสร็จสิ้นเป็นจำนวนมากครั้งสำหรับแต่ละแสงดังนั้นการแคชค่าจะเพิ่มรอบ CPU / GPU พิเศษ
  • และสมมติว่าเวลาเข้าถึงหน่วยความจำสำหรับการอ่านค่าจริงเร็วกว่าการคำนวณใหม่

เกี่ยวกับวิธีการใช้งานฉันไม่แน่ใจเกี่ยวกับการใช้งานเฉพาะของพวกเขา แต่เกี่ยวกับ1/sqrRadiusสิ่งนี้ใช้สำหรับการลดทอนแสงการตกและการคัดออก นอกจากนี้ยังเป็นที่เกี่ยวข้องกับทิศทางและปอตไลท์ที่แตกต่างกันเฉพาะในกรณีของปอตไลท์คือการที่คุณจำเป็นต้องคำนวณปัจจัยปอตไลท์หลังจากที่ ใช้ลดทอน เกี่ยวกับแสงทิศทางเช่นดวงอาทิตย์มันมักจะไม่มีการลดทอนหรือตกหล่นดังนั้นฉันเดาว่ามันจะถูกละเว้น

[แก้ไข] เพียงเพื่อเพิ่มรายละเอียดเพิ่มเติมมันไม่ใช่ข้อมูลที่ไม่เกี่ยวข้อง การฉายรังสีแบบแสงสามารถคำนวณได้โดยใช้สมการต่อไปนี้:

E = Phi / 4 * pi * rSqr;

ที่ไหน

Eคือพื้นที่ความหนาแน่นของฟลักซ์

พีเป็นฟลักซ์ความกระจ่างใส

4 * pi * rSqrคือพื้นที่ผิวของทรงกลม

สมการนี้อธิบายว่าทำไมปริมาณพลังงานที่ได้รับลดลงด้วยระยะห่างกำลังสอง

อีกจุดหนึ่งคือคุณจำเป็นต้องคำนวณระยะห่างระหว่างจุดยอดและแสงเพื่อคำนวณการกระจายแสงในจุดยอดที่เฉพาะเจาะจง (ค่านี้ไม่น่าจะถูกแคช) จุดสุดยอดสามารถเข้าหรือออกจากช่วงแสงที่นำเราไปสู่จุดต่อไป ที่Radius Squareมีประโยชน์สำหรับการเลือกสรร

ถ้าคุณต้องการตัวอย่างในทางปฏิบัติสำหรับการคำนวณ falloff แสงและการเลือกสรรนี้เป็นประโยชน์อย่างยิ่งในการปูกระเบื้อง renderers รอการตัดบัญชีตามที่นี่เป็นตัวอย่างหนึ่ง


สาปคุณเอาชนะฉัน 7 วินาที! ;) (และด้วยคำตอบที่ครอบคลุมยิ่งขึ้นเช่นกัน!)
Trevor Powell

ขอบคุณสำหรับความคิดเห็นอย่างละเอียดโดยเฉพาะสำหรับลิงค์! จากสิ่งที่ฉันเข้าใจจากลิงค์หลัง Battlefield 3 ไม่ได้เก็บรัศมี แต่ระยะทางที่แท้จริงระหว่างแหล่งกำเนิดแสงและตัวรับแสงใช่ไหม? นั่นคือค่า "d" ที่ใช้ในบทความ
cubrman

@cubrman ยากที่จะคาดเดาโดยไม่เห็นรหัส ฉันเดาว่ามันคือ radiusSqr แบบผกผัน และสมการที่ใช้อาจแตกต่างจากบทความอย่างมาก
concept3d

แต่บอกฉันหน่อยว่าคุณจะใช้รัศมีแสงกลับด้านเปลือยในการคำนวณแสงได้อย่างไร ทุกแหล่งที่ฉันพบบนเน็ตบอกฉันว่าฉันต้องการค้นหาระยะทางระหว่างพื้นผิวที่รับและแหล่งกำเนิดแสงหารด้วยรัศมีแสงเดิมและแบ่งผลลัพธ์ออกเป็นสองส่วน คุณจะใช้รัศมีกำลังสองหรือ invSqrRadius ที่ไหน ดูเหมือนว่าฉันจะไม่เกี่ยวข้องกับข้อมูลอย่างสมบูรณ์
cubrman

1
@cubrman อัปเดตคำตอบ
concept3d

6

invSqrRadius ไม่ได้เป็น 1 - sqrRadius; มันคือ 1 / sqrRadius

หมายความว่าคุณสามารถคูณด้วย invSqrRadius แทนที่จะหารด้วย sqrRadius (โดยทั่วไปการหารจะแพงกว่าการคูณ)


6

คำตอบอื่น ๆ ที่นี่จัดการกับรัศมีจตุรัสผกผัน แต่ฉันจะดูรัศมียกกำลังสองแทน (ซึ่งแนวคิด 3d สัมผัส แต่ฉันเชื่อว่ามันสมควรได้รับการอภิปรายเพิ่มเติม)

สิ่งที่สี่เหลี่ยมที่มีประโยชน์คือการเปรียบเทียบระยะทาง เรารู้ว่าการคำนวณระยะห่างระหว่างจุดสองจุดเกี่ยวข้องกับสแควร์รูทและสแควร์รูทนั้นมีราคาแพงในการคำนวณ แต่ถ้าทั้งหมดที่เราต้องการจะทำคือการเปรียบเทียบระยะทาง (เพื่อหาว่าอันไหนน้อยกว่าหรือมากกว่า ผล) เราสามารถโยนสแควร์รูทออกได้

ถ้า sqrt (x)> sqrt (y) ก็เป็นเช่นนั้นว่า x> y

สำหรับแสงรัศมีกำลังสองเท่ากับระยะห่างระหว่างจุดศูนย์กลางของแสงกับขอบเขตสูงสุด - แน่นอน

สำหรับการคำนวณแสงนี้สามารถใช้สำหรับเคสที่มีขนาดใหญ่ หากระยะห่างระหว่างจุดที่คุณกำลังส่องสว่างและจุดศูนย์กลางของแสง (กำลังสอง) มากกว่ารัศมีกำลังสองจุดนั้นจะไม่มีแสงสว่างและคุณไม่จำเป็นต้องคำนวณส่วนที่เหลือของคุณ นี่เป็นเพียงการหาค่าเหมาะที่สุด (เป็นเรื่องธรรมดามาก) - เราสามารถใช้รัศมีกำลังสองเพื่อทำการเปรียบเทียบระยะทางโดยไม่ต้องใช้รากที่มีราคาแพงและในราคาเพียงแค่การลบและผลิตภัณฑ์ดอท

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


ดังนั้นถ้าฉันเข้าใจคุณอย่างถูกต้องรหัสจะเป็น: ถ้า (dot ((lightPos - surfacePos), (lightPos - surfacePos))> lightRadiusSqr) ไม่ได้ให้แสงสว่างใช่ไหม?
cubrman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.