ฉันจะใช้เทคนิคการเรนเดอร์อะไรในการวาดเอฟเฟกต์เงาของการ์ดในเกมการ์ด


13

อัลกอริทึมการแรเงาประเภทใดที่อาจใช้สร้างเงาเช่นนี้ ป้อนคำอธิบายรูปภาพที่นี่

สิ่งที่ฉันทำคล้ายกัน แต่ทั้งหมดนั้นทำด้วย 2D drawing API ที่ขับเคลื่อนโดย OpenGL ดังนั้นจึงไม่มีพิกัด Z

นอกจากนี้สำหรับมือของฉันเองฉันอยากได้ความรู้สึกแบบที่เห็นที่นี่: ป้อนคำอธิบายรูปภาพที่นี่

ฉันไม่แน่ใจว่าจะทำอย่างไรให้ได้ร่มเงาดูใกล้เคียง

จำนวนบัตรถูกผูกไว้กับการเปลี่ยนแปลงและไพ่ถูกโยนลงบนโต๊ะดังนั้นฉันจึงไม่สามารถใช้แผนที่แสงทุกประเภท

ฉันควรมองหาอัลกอริทึมประเภทใด (นอกเหนือจากความพร่ามัวที่ฉันรู้ว่าต้องทำ)

ขอบคุณ

ปรับปรุง

ฉันทำเกมการ์ด 2D ฉันต้องการเพิ่มออฟเซ็ทเงาจากการ์ดเล็กน้อยเช่น:

ป้อนคำอธิบายรูปภาพที่นี่

วิธีที่ฉันคิดว่าจะทำคือ:

  • รักษาพื้นผิวที่มีขนาดเท่ากับ backbuffer
  • วาดสี่เหลี่ยมสีเข้มเป็นการ์ดชั่วคราวเพื่อพื้นผิวนั้น

  • เบลอพื้นผิวนั้น

  • วาดไพ่ของฉันลงบนพื้นผิวนั้น
  • เพิ่มแสงสว่างบนการ์ด
  • วาดเนื้อนี้ไปที่ backbuffer

คำถามของฉันคือ:

  • นี่เป็นวิธีที่ถูกต้องหรือไม่

  • มีวิธีทำโดยไม่ทำให้พื้นผิว (รักษาบิตแมป
    ใหญ่เป็น backbuffer)?

  • จะปลอดภัยหรือไม่ที่จะสันนิษฐานว่าขนาดพื้นผิวสูงสุดจะไม่
    เกินจากขนาดของแบ็คบุฟเฟอร์? (สิ่งที่ฉันหมายถึงคือถ้า backbuffer
    เป็น 2000x3000 แล้วมันปลอดภัยที่จะบอกว่าฉันสามารถสร้างพื้นผิวใน
    หน่วยความจำวิดีโอขนาดนั้นหรือไม่

ขอบคุณ


1
ประเด็นด้านสุนทรียภาพในประเด็นที่สองของคุณ: เป็นไปไม่ได้จริง ๆ ถ้าคุณถือไพ่เหล่านั้นในมือของคุณ การ์ดที่กดติดกันไม่ทำให้เกิดเงาซึ่งกันและกัน ไม่เว้นแต่คุณกำลังถือจำนวนมากของพวกเขา คุณไม่สามารถถือไพ่ในแบบที่ปรากฎในภาพนั้นได้ การ์ดเหล่านั้นดูเหมือนว่าพวกมันถูกคั่นด้วยหลายมิลลิเมตร พวกเขาไม่ได้แบนต่อกัน ฉันแค่ไม่กังวลหรอก
Nicol Bolas

คำตอบ:


18

ฉันคิดว่าทุกคนให้วิธีที่ซับซ้อนเกินไปในการแก้ปัญหานี้

ป้อนคำอธิบายรูปภาพที่นี่

อย่างแรกเรามีการ์ด (หรืออะไรก็ตามที่คุณต้องการวาด) ซึ่งอธิบายโดย (ก) ต่อไปเรานำสำเนาของมันมาเติมให้เป็นสีดำและเรียกใช้ gaussian blur (b) ทั้งหมดนี้เกิดขึ้นใน photoshop หรือเครื่องมือศิลปะที่คุณชื่นชอบ

ถัดไปในเกมเมื่อเราต้องการวาดไพ่อันดับแรกให้วาดภาพสีดำเบลอด้วยการผสมผสานแบบหลายจุด (หรืออัลฟ่า) ชดเชยในทิศทางที่เล็กน้อยแล้ววาดการ์ดบนนั้น voila

สำหรับเล่ห์เหลี่ยมเพิ่มเติมคุณสามารถสลับระหว่างการเรนเดอร์และการเรนเดอร์การ์ดเพื่อให้ได้เอฟเฟกต์เช่น (d) หรือวาดเงาทั้งหมดก่อนแล้วจึงเลือกไพ่เช่นใน (e) (ฉันระบายสีการ์ดในเคส (e) เพื่อแสดงว่า ยังแยกกันอยู่ =)

นอกจากนี้ยังเป็นการดีที่สุดที่จะไม่ใช้สีดำบริสุทธิ์ (หรืออัลฟ่าแบบเต็ม) สำหรับเงาเพื่อสร้างเงาที่ละเอียดและโปร่งใสมากขึ้น


2
+1 สำหรับการทำเงานอกเกม นอกจากนี้คุณยังสามารถก้าวไปอีกขั้นหนึ่งและปรับตำแหน่งที่วางเงา a หากมีแสงในฉาก
FrenchyNZ

+1, ภาพประกอบที่ดี นอกจากนี้ในกรณี E คุณสามารถใช้การแรเงาสีเข้มบนโต๊ะและกึ่งสว่างบนการ์ดที่มีลายฉลุ ว่าจะมีความซับซ้อนมากขึ้น แต่ผลที่ได้จะยิ่งดีกว่า :)
Kromster

2

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

ส่วนที่สองดูเหมือน SSAO (การบดบังพื้นที่หน้าจอโดยรอบ) เทคนิคนั้นต้องการพิกัด Z อย่างไรก็ตามถ้าคุณไม่มีมุมที่แตกต่างกันระหว่างไพ่ (ซึ่งเป็นสิ่งที่ฉันคาดเดาว่าคุณไม่มีบัฟเฟอร์ Z) คุณอาจจะทำการประมาณที่ดีโดยการแสดงเงาเงา (เช่นอันแรก) สำหรับแต่ละ บัตร การแสดงอาจจะยุ่งยากเล็กน้อย แต่ - เครื่องบินทุกลำจะต้องมีช่องอัลฟาเบลอสำหรับระนาบทั้งหมดที่อยู่เหนือมันและหากมีการ์ดจำนวนมากบนโต๊ะ


SSAO overkill =) เป็นการยากมากที่จะบอกว่าเทคนิคการใช้ shadowing ใดโดยไม่เห็นตัวอย่างภาพเคลื่อนไหว หากการ์ดอยู่ในลำดับนั้นเสมอและเว้นระยะห่างกันมันจะง่ายที่สุดในการแสดงเงาล่วงหน้าก่อน แต่คุณจะไม่มีทางรู้ว่าจะเห็นเกมกำลังเล่นอยู่
Patrick Hughes

0

คุณไม่สามารถทำแผนที่เงาได้หรือไม่? ทำให้ฉากเป็น fbo บันทึกเฉพาะค่าความลึกและทำการตรวจสอบค่าความลึกปกติใน shader เพื่อดูว่าเงาควรถูกเรนเดอร์หรือไม่


ฉันไม่ได้ใช้ Z Buffer ไม่มี 'ความลึก'
jmasterx

0

กระบวนการต่อไปนี้ไม่ต้องการเป้าหมายการเรนเดอร์นอกจอ อย่างไรก็ตามในการทำเช่นนั้นก็จะได้รับความต้องการที่โต๊ะจะวาดครั้งแรก หรืออย่างน้อยจะไม่มีการวาดพิกเซลที่ตารางจะครอบคลุมก่อนที่จะวาดตาราง นอกจากนี้ยังต้องการให้ตารางนั้นเป็นหนึ่งเดียวส่วนที่ไม่ทับซ้อนกัน: รูปภาพ

นอกจากนี้ framebuffer ของคุณต้องการส่วนประกอบอัลฟา

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

    ค่า 0.0 ในภาพหมายถึงไม่มีเงา ค่า 1.0 ในภาพหมายถึงเงาทั้งหมด นั่นคือมืดสนิททั้งหมด คุณอาจต้องการค่า 0.5 หรือมากกว่านั้นเป็นสีที่มืดที่สุดของคุณ

  2. ล้างหน้าจอดังกล่าวว่าอัลฟาถูกตั้งค่าเป็นศูนย์

  3. ก่อนที่จะเรนเดอร์อะไรก็ตาม (หรืออย่างน้อยก็อะไรก็ตามที่จะแสดงผล "ใต้" ตาราง) สำหรับการ์ดแต่ละใบจะทำการเรนเดอร์แบบฟัซซี่ออฟเซ็ตจากตำแหน่งจริงของการ์ด ผลลัพธ์สีโดย shader ควรเป็นการกำหนดค่าการผสมผสานสำหรับสิ่งนี้ (ใน OpenGL parlance):

    glBlendEquation(GL_MAX);

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

    คุณควรใช้มาสก์การเขียนสีเพื่อปิดการเขียนสี

  4. แสดงตาราง เมื่อทำเช่นนั้นควรตั้งค่าการผสมดังนี้:

    glBlendEquation(GL_ADD);
    glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO);

หากข้อ จำกัด นั้นเข้มงวดเกินไปสำหรับคุณคุณต้องใช้การแสดงผลเป้าหมาย สิ่งนี้ทำได้ดังนี้:

  1. สร้างภาพเงาของการ์ดเหมือนเมื่อก่อน

  2. ขั้นแรกให้แสดงเงา ผูกเงา framebuffer (ซึ่งจะต้องเป็นภาพแชนเนลเดียวเท่านั้นหากฮาร์ดแวร์ของคุณสามารถแสดงผลเป็นหนึ่งในนั้น) ล้างค่าเป็นศูนย์

  3. สำหรับแต่ละการ์ดให้เรนเดอร์อิมเมจเงาของการ์ดแล้วชดเชยเช่นเคย Shader ของคุณควรเขียนค่าเดียวกันกับองค์ประกอบทั้งสี่ของสีเอาต์พุต glBlendEquation(GL_MAX)ผสมผสานโหมดอีกครั้งควรจะเป็น

  4. สลับกลับไปที่กรอบบัฟเฟอร์ปกติ วาดทุกสิ่งที่คุณต้องการให้เป็นเงา

  5. ตอนนี้วาดรูปสี่เหลี่ยมเต็มหน้าจอด้วยเงาที่เราเรนเดอร์ Shader ควรจัดเก็บเท็กเซลที่ดึงมาจากภาพเงาในอัลฟาของเอาท์พุท RGB ไม่เกี่ยวข้อง โหมดผสมผสานควรเป็น:

    glBlendEquation(GL_ADD);
    glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);

ในวิธีแรกฉันคิดว่าคุณลืมขั้นตอนที่ 5: ปิดการใช้งานการผสมและแสดงบัตร นอกจากนี้ยังเป็นที่น่าสังเกตว่าวิธีแรกไม่อนุญาตให้คุณรับเงาระหว่างการ์ดอย่างที่เห็นในภาพหน้าจอที่สองของ OP
Nathan Reed

@NathanReed: ฉันคิดว่าเขารู้วิธีที่จะปิดสิ่งต่าง ๆ ด้วยตัวเอง นอกจากนี้ "เงาระหว่างการ์ด" ก็ไม่มีเหตุผลใด ๆ ตามที่ฉันชี้ให้เห็นในความคิดเห็นภายใต้คำถาม
Nicol Bolas

1
มันอาจไม่ได้เป็นตัวแทนของวิธีการที่คุณถือบัตรจริง แต่มันดูดี! มันไม่ได้ "สมเหตุสมผล" สำหรับไพ่ที่จะลอยอยู่เหนือโต๊ะเหมือนที่พวกเขาทำในนัดแรก ...
Nathan Reed

0

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

การโทรจะเป็น:

glEnable (GL_STENCIL_TEST);
glStencilFunc (GL_EQUAL, 1, 2);
glStencilOp (GL_KEEP, GL_KEEP, GL_INCR);

// draw shadow textures

glDisable (GL_STENCIL_TEST);

ครั้งเดียวที่สิ่งนี้อาจทำให้เกิดปัญหาคือถ้าคุณมีขอบเบลอสองอันที่ซ้อนทับกันเล็กน้อย ไม่อย่างนั้นมันไม่ต้องการอะไรแปลกไปกว่าสิ่งที่ OpenGL 1.1 เสนอพื้นฐานและจะทำงานกับฮาร์ดแวร์ทั้งหมด (คาดว่าอาจเป็นการ์ด 3DFX รุ่นเก่าซึ่งฉันคิดว่าคุณไม่กังวลเกี่ยวกับการสนับสนุน ... )

ทางเลือกที่สองที่ควรทำงานได้ดีมากในเกมที่ไม่มีประสิทธิภาพที่สำคัญคือ glCopyTexSubImage2D มันจะทำงานกับพื้นผิวที่เล็กกว่า backbuffer ด้วยและรองรับได้ดีกับฮาร์ดแวร์ทั้งหมด (เป็นส่วนหนึ่งของ OpenGL 1.1 และ Doom 3 ใช้มันดังนั้นคุณสามารถคาดหวังว่าการสนับสนุนจะดีมาก)

การตั้งค่าพื้นฐานจะเป็นดังนี้:

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

มันควรจะทำงานได้ดีมากมันเป็น GPU ที่เข้มข้นกว่าวิธี stencil buffer เล็กน้อย แต่จัดการกรณีซ้อนทับอย่างถูกต้องและ - อย่างที่ฉันบอก - ฉันคิดว่าเกมอย่างคุณจะมีพลัง GPU ในการเผาแม้ในระดับต่ำสุด บัตร

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.