2 คะแนน โดย GN⁺ 2025-02-08 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ในเกมที่สามารถขุดและถมภูมิประเทศได้ ทะเลสาบ แม่น้ำ และแอ่งน้ำต้องไหลออกตามขอบเขตใหม่ได้ จึงจำเป็นต้องมี การจำลองน้ำแบบกริด ที่เร็วและเสถียร
  • เป้าหมายคือโมเดลความสูงแบบ 2D ที่ใช้กริดเดียวกับภูมิประเทศในสเกลประมาณ 1 เมตร พร้อมคุณสมบัติรักษาปริมาณน้ำ ควบคุมเสถียรภาพได้ และมีต้นทุนการอัปเดตแบบเชิงเส้น
  • Smoothed Particle Hydrodynamics และ Stable Fluids ต่างก็เหมาะกับของไหลอนุภาคความละเอียดสูงและปริมาตรของไหลแบบปิดตามลำดับ จึงไม่ตรงกับโจทย์การจัดการผิวน้ำอิสระบนภูมิประเทศอย่างรวดเร็ว
  • วิธี virtual pipes ที่เลือกใช้ จะเก็บความสูงของน้ำและการไหลระหว่างเซลล์ไว้บน staggered grid แล้วประมวลผลการเร่งการไหล การสเกลการไหลออก และการอัปเดตคอลัมน์น้ำด้วยลูปบนอาร์เรย์ 2D เพียงไม่กี่ชุด
  • เมื่อใช้ dt และ g ที่เหมาะสม จะได้ผลลัพธ์ที่ดูเหมือนน้ำ แต่ยังมีข้อจำกัดคือไม่มี ความเฉื่อย และการแพร่ของความเร็ว ทำให้กระแสน้ำที่ไหลเร็วไม่ส่งต่อเข้าไปในทะเลสาบได้อย่างต่อเนื่อง

ทำไมน้ำจึงยากในเกมที่แก้ไขภูมิประเทศได้

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

จุดที่วิธีแก้ง่าย ๆ ยังไม่พอ

  • ทางเลี่ยงที่เป็นไปได้ เช่น ตรึงน้ำไว้ที่ตำแหน่งเริ่มต้น มองว่าทุกอย่างที่ต่ำกว่าระดับหนึ่งคือน้ำ จำกัดไม่ให้ขุดลึกเกินไป หรือใช้โมเดลการไหลแบบง่ายสไตล์ Minecraft หรือ Dwarf Fortress
  • วิธีเหล่านี้ใช้เป็นทางเลือกได้ แต่ถ้าจะใช้เป็นโมเดลหลักก็เรียบง่ายเกินไปหรือให้ความรู้สึกเป็นบล็อกมากเกินไป
  • โมเดลของ Dwarf Fortress ใกล้เคียงกว่าวิธีอื่น แต่ถูกออกแบบโดยมี 3D เป็นพื้นฐาน ขณะที่ปัญหาที่ต้องการแก้ส่วนใหญ่คือ น้ำบนภูมิประเทศแบบ 2D
  • Timberborn ใช้โมเดลประเภทเดียวกับที่กล่าวถึงที่นี่

เงื่อนไขของการจำลองที่ต้องการ

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

ความไม่ตรงกันกับการจำลองของไหลแบบเดิม

  • Smoothed Particle Hydrodynamics ให้ผลลัพธ์ของไหลความละเอียดสูงที่น่าทึ่ง แต่ต่างจากปัญหาที่ต้องการในที่นี้
    • อนุภาคน้ำขนาด 1 เมตรอาจดูเหมือนลูกโป่งน้ำ
    • หากทำให้อณูเล็กลง ต้นทุนด้านประสิทธิภาพจะสูงขึ้น
    • เป้าหมายไม่ใช่ความสมจริงระดับสูง แต่เป็นโมเดลที่เร็วและดูน่าเชื่อ
  • Stable Fluids ของ Jos Stam ใกล้เคียงกับโมเดลที่จัดการปริมาตรที่เต็มไปด้วยของไหล เช่น ถังปิด
    • ต่างจากปัญหาการจัดการ ผิวน้ำอิสระ บนภูมิประเทศโดยตรง
    • บางขั้นตอนต้องแก้ sparse linear system แบบวนซ้ำ ซึ่งมีต้นทุนสูง
    • เป็นแนวทางที่แก้สมการ Navier-Stokes ทั้งชุด ขณะที่สิ่งที่ต้องการที่นี่คือ shallow water equations

Shallow water equations และการเลือกกริด

  • Shallow water equations เป็นแนวทางที่เฉลี่ยชั้นน้ำนิ่งในแนวดิ่งบนภูมิประเทศ แล้วจัดการเป็นสมการ 2D
  • คำว่า “Shallow” หมายถึงสมมติฐานว่าขนาดในแนวดิ่งของคอลัมน์น้ำเล็กกว่าระยะในแนวนอนที่สนใจมาก
    • เช่น ความลึกของแม่น้ำมีตั้งแต่ไม่กี่เมตรถึงหลายสิบเมตร ขณะที่ระยะที่สนใจอยู่ในระดับกิโลเมตร
  • collocated grid แบบทั่วไปจะเก็บความสูงของน้ำและความเร็วไว้ในเซลล์เดียวกัน แต่ในการจำลองพลศาสตร์ของไหลอาจเกิดปัญหาได้
    • หากดิสครีไทซ์อนุพันธ์อันดับหนึ่งแบบตรงไปตรงมา อาจเกิดอคติของทิศทางหรือความไม่เสถียร
    • ถ้ามีการไหลเข้าจากซ้ายขวาและไหลออกทางบนล่างภายในเซลล์เดียวกัน อาจเกิดความขัดแย้งที่ดูเหมือนความเร็วรวมเป็น 0
  • Staggered grid จะเก็บค่าประเภทความสูงของน้ำหรือความหนาแน่นไว้ในเซลล์ ส่วนความเร็วหรือการไหลจะเก็บไว้ที่ขอบระหว่างเซลล์
    • อาร์เรย์ความสูงของน้ำขนาด N x N
    • อาร์เรย์การไหลแกน X ขนาด (N+1) x N
    • อาร์เรย์การไหลแกน Y ขนาด N x (N+1)

วิธี Virtual pipes

  • Virtual pipes เป็นวิธีที่มองว่าเซลล์น้ำเชื่อมต่อกันด้วยท่อเสมือน แล้วคำนวณการไหลจากแนวคิดนั้น
  • หนึ่งในงานวิจัยที่อ้างอิงยังรองรับคอลัมน์น้ำหลายระดับและการเชื่อมต่อแนวดิ่ง ส่วนอีกงานเน้น hydraulic erosion เป็นหลัก แต่ที่นี่ตัดเป้าหมายนั้นออกไป
  • ค่าที่ต้องเก็บมี 3 ค่า
    • water: ความสูงของคอลัมน์น้ำในแต่ละเซลล์
    • flowX: การไหลรวมของน้ำระหว่างเซลล์ที่ติดกันในแนวนอน
    • flowY: การไหลรวมของน้ำระหว่างเซลล์ที่ติดกันในแนวตั้ง
  • เก็บ การไหล (flow, flux) แทนความเร็ว
    • การไหลอาจมองได้ว่าเป็นปริมาตรของน้ำที่ผ่านต่อหนึ่งหน่วยเวลา
    • การไหลระหว่างเซลล์ว่างสามารถกำหนดเป็น 0 ได้อย่างเป็นธรรมชาติ
    • ความเร็วคือการนำการไหลหารด้วยพื้นที่หน้าตัด ดังนั้นเมื่อแทบไม่มีน้ำอาจเกิดปัญหา 0/0 หรือปัญหาเรื่องค่าขีดขั้นต่ำได้

3 ขั้นตอนของหนึ่งสเต็ป

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

    • หากความสูงของน้ำในเซลล์ติดกันสองเซลล์ต่างกัน การไหลจะถูกเร่งจากฝั่งที่สูงไปยังฝั่งที่ต่ำ
    • อัปเดตการไหลบนขอบภายในในทิศ X และ Y โดยใช้ g, dt, dx, dy
    • พื้นที่หน้าตัด A ของท่อเสมือนถูกใช้ร่วมกับ g เท่านั้น ดังนั้นในงานแบบง่ายสามารถมองว่าไปรวมอยู่ใน g ได้
    • สามารถเพิ่มแรงเสียดทานได้ด้วยการลดการไหลลงทุกสเต็ป
    • งานวิจัยแนะนำค่าสัมประสิทธิ์ pow(friction, dt)
    • เพื่อให้ใช้ค่าที่เข้าใจง่ายกว่า อาจใช้ pow(1-friction, dt) ได้
    • มองว่า friction=0 คือแรงเสียดทานสูงสุดที่ลบการไหลเดิมออกทั้งหมด ส่วน friction=1 คือไม่มีแรงเสียดทาน
    • ยิ่ง dt มาก การจำลองจะยิ่งเร็ว แต่ก็อาจไม่เสถียรขึ้น
    • ในการจำลองของไหล Courant-Friedrichs-Lewy condition มีความสำคัญ
    • ในทางปฏิบัติต้องลด dt ลงจนกว่าจะเสถียร โดยค่าที่ใช้คือประมาณ 0.001~0.01
  • อัปเดตคอลัมน์น้ำ

    • แต่ละเซลล์จะดูการไหล 4 ทิศรอบตัวแล้วเพิ่มหรือลดน้ำ
    • flowX(x,y) และ flowY(x,y) ที่ไหลเข้าจากซ้ายและด้านล่างจะถูกบวกเข้าไป
    • flowX(x+1,y) และ flowY(x,y+1) ที่ไหลออกทางขวาและด้านบนจะถูกลบออก
    • นี่คือขั้นตอนที่ย้ายน้ำจริงระหว่างเซลล์ตามค่าการไหลที่คำนวณไว้
  • สเกลการไหลออก

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

ภูมิประเทศ เงื่อนไขขอบเขต และการจัดการความหนืด

  • ภูมิประเทศถูกสะท้อนเข้าไปในขั้นเร่งการไหล โดยใช้ ระดับผิวน้ำ แทนความสูงของคอลัมน์น้ำ
    • ระดับผิวน้ำ = terrain(x,y) + water(x,y)
    • เซลล์ที่ภูมิประเทศสูง แม้มีความสูงคอลัมน์น้ำเท่ากันก็จะมีผิวสูงกว่าและทำให้น้ำเคลื่อนได้
  • เงื่อนไขขอบเขตถูกกำหนดโดยนัยผ่านค่าการไหลที่ขอบ
    • flowX(0,y), flowX(N,y), flowY(x,0), flowY(x,N) คือค่าที่ขอบเขต
    • หากตั้งเป็น 0 จะทำงานเหมือนกำแพง
    • ค่าไหลเข้าจะเติมน้ำ ส่วนค่าไหลออกจะนำน้ำออก
    • สำหรับน้ำบนภูมิประเทศ ขอบเขตแบบ น้ำไหลออก ที่ปล่อยให้น้ำหายไปตรงขอบแผนที่อาจดูเป็นธรรมชาติ
    • ส่วนที่แม่น้ำตัดผ่านขอบสามารถตั้งเป็นขอบเขตไหลเข้าเพื่อให้น้ำในแม่น้ำไหลต่อเนื่องได้
  • ต้องตั้งค่าการไหลที่ขอบใหม่ทุกครั้งตอนเริ่มแต่ละสเต็ปของการจำลอง
    • เพราะขั้นสเกลการไหลออกอาจเปลี่ยนค่าการไหลที่ขอบจนทำให้ขอบเขตไหลออกกลายเป็นเหมือนกำแพง
  • ในงานวิจัยยังมีพจน์ ความหนืด ที่ลดการไหลตามความสูงของน้ำ
    • แนวคิดคือชั้นน้ำบางจะเคลื่อนที่ได้ยากกว่าเพราะแรงภายใน ส่วนชั้นน้ำหนาจะเคลื่อนที่ได้อิสระกว่า
    • อาจมีประโยชน์กับสิ่งอย่างการไหลของแมกมา
    • ไม่ได้ใช้กับน้ำ และในสเกลภูมิประเทศใหญ่ ๆ ผลของความหนืดแทบไม่มีนัยสำคัญ

ลำดับการติดตั้งใช้งานและรูปแบบประสิทธิภาพ

  • โค้ดทั้งหมดมีลำดับดังนี้
    • เริ่มต้นค่าการไหลที่ขอบ
    • คำนวณค่าสัมประสิทธิ์แรงเสียดทาน pow(1-friction, dt) ล่วงหน้า
    • เร่งการไหลแกน X
    • เร่งการไหลแกน Y
    • สเกลการไหลออกเพื่อป้องกันปริมาณน้ำติดลบ
    • อัปเดตคอลัมน์น้ำ
  • การจำลองเกือบทั้งหมดจบลงด้วย 4 ลูป ที่วิ่งผ่านอาร์เรย์ 2D ไม่กี่ชุดและสมการง่าย ๆ
  • โค้ดอัปเดต C++ แบบเต็มดูได้ที่ water_2d.cpp
  • ตัวอย่างวิดีโอมาจาก WebGPU water simulator ที่เผยแพร่เมื่อไม่กี่วันก่อน โดยอนุภาคในวิดีโอมีไว้เพื่อการแสดงผลเท่านั้นและไม่ได้มีส่วนร่วมในการจำลอง
  • หากหาค่า dt และ g ที่เหมาะสมได้ ผลลัพธ์จะดูเสถียร ตรงตามเงื่อนไขที่ต้องการ และดูเหมือนน้ำ

ข้อจำกัดที่ยังเหลืออยู่

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

การขยายไปยังกริดหกเหลี่ยมและสามเหลี่ยม

  • เกมเป้าหมายไม่ได้ใช้กริดสี่เหลี่ยม แต่ใช้ กริดสามเหลี่ยม แบบสม่ำเสมอ
  • กริดสามเหลี่ยมสามารถมองได้ว่าเป็น dual ของกริดหกเหลี่ยม
    • หากเชื่อมจุดศูนย์กลางของหกเหลี่ยมที่อยู่ติดกัน จะได้กริดสามเหลี่ยมแบบสม่ำเสมอ
    • คล้ายกับรูปแบบในบทความ hexagonal grids ของ Red Blob Games ที่ใช้ axial coordinate system กับกริดคู่ของทิศทาง hex แบบ pointy-top
  • กริดสามเหลี่ยมก็สามารถเก็บในอาร์เรย์ 2D ทั่วไปที่เอียงเล็กน้อยได้
  • ความสูงของคอลัมน์น้ำถูกเก็บไว้ที่จุดยอดของกริดเพื่อให้เรนเดอร์ผิวน้ำได้ง่าย
  • การไหลแบ่งออกเป็น 3 ทิศ
    • การไหลแกน X
    • การไหลแกน Y
    • การไหลแกน Z
  • สำหรับกริดจุดยอดขนาด N x N จะใช้อาร์เรย์ดังนี้
    • อาร์เรย์การไหล X ขนาด (N+1) x N
    • อาร์เรย์การไหล Y ขนาด N x (N+1)
    • อาร์เรย์การไหล Z ขนาด (N+1) x (N+1) โดยไม่ใช้ค่าที่มุมล่างซ้ายและมุมขวาบน
  • เมื่อเทียบกับกริดสี่เหลี่ยม เพียงเพิ่มการไหลแกน Z เข้าไปในเงื่อนไขขอบเขต การเร่งการไหล การสเกลการไหลออก และการอัปเดตน้ำ
  • ส่วนที่ยากที่สุดคืออย่าให้อินเด็กซ์ผิด
  • โค้ด C++ สำหรับกริดสามเหลี่ยมและหกเหลี่ยมดูได้ที่ water_2d_hex.cpp
  • วิธีนี้อาจมีความเป็น isotropic มากกว่ากริดสี่เหลี่ยมเล็กน้อย

1 ความคิดเห็น

 
GN⁺ 2025-02-08
ความคิดเห็นจาก Hacker News
  • มีวิดีโอ Coding Adventure ที่นำเสนออีกแนวทางหนึ่งในการจัดการกับ การจำลองของไหล
    Rendering Fluids: https://www.youtube.com/watch?v=kOkfC5fLfgE
    I Tried Putting my Fluid Simulation on a Planet: https://www.youtube.com/watch?v=8nIB7e_eds4&t=817s
    GitHub: https://github.com/SebLague/Fluid-Sim?tab=readme-ov-file

  • หนึ่งในเหตุผลที่ การจำลองอุทกวิทยา ในเกมที่ใช้การสร้างแบบ procedural นั้นยาก คือเมื่อมีน้ำสะสม มันจะส่งผลต่อช่องรอบ ๆ และผลนั้นก็จะแพร่ต่อไปยังช่องรอบ ๆ อื่น ๆ อย่างต่อเนื่อง
    การสร้างแบบ procedural มักเหมาะกับการทำแบบขนาน แต่ในพื้นที่ไร้ขอบเขตซึ่งดูเหมือนเป็นจุดที่ต้องการการทำแบบขนานมากที่สุด กลับทำให้การคำนวณแบบนี้ทำขนานได้อย่างถูกต้องได้ยาก
    ไม่ค่อยเห็นหัวข้อนี้ถูกสำรวจมากนัก และในบรรดาคนที่ทำงานที่เกี่ยวข้อง ชอบ https://nickmcd.me เป็นพิเศษ ภูมิประเทศแบบ procedural ที่เคยเห็นมานั้นถือว่าดีเป็นอันดับต้น ๆ
    อย่างไรก็ตาม งานนั้นก็ยังถูกจำกัดพื้นที่เพราะการออกแบบการจำลอง วิธีแก้ที่เป็นไปได้ซึ่งดูดีที่สุดคือสร้าง ขอบเขตลุ่มน้ำ ที่แตกไม่ได้แบบ procedural ก่อน แล้วจึงจำลองทั้งลุ่มน้ำพร้อมกันแบบขนาน
    เป็นปัญหาที่น่าสนใจมาก แต่เกินขอบเขตความรู้ของตัวเอง จึงอยู่ในมุมผู้สังเกตเป็นหลัก

    • ถ้าสนใจ ลองค้นหา “ขอบเขตอิทธิพล” และ “ขอบเขตการพึ่งพา” ที่พูดถึงในสาขาการแก้ สมการเชิงอนุพันธ์ย่อย ดู
      หมายถึงบริเวณที่สามารถส่งผลต่อค่าของจุดใดจุดหนึ่ง และบริเวณที่ค่าของจุดนั้นสามารถส่งผลต่อได้ ซึ่งเชื่อมโยงกับสิ่งที่กล่าวไว้ด้านบนโดยตรง ในบางกรณีสามารถรู้บริเวณเหล่านั้นล่วงหน้าได้
    • พูดจริง ๆ ว่า https://nickmcd.me คุ้มค่ามากที่จะเข้าไปดู ยอดเยี่ยมจริง ๆ
    • เป็นคำถามที่น่าสนใจ น่าจะทำได้ถ้าวางขอบเขตรอบแต่ละพื้นที่ และสมมติ ความเร็วสูงสุด ที่ผลกระทบจะแพร่ได้ หรือก็คือ causality
      เช่น ถ้าต้องการจำลองช่วงเวลา 10 ชั่วโมง ก็วางขอบเขตกว้าง 10 ช่องกริด คำนวณ 10 ขั้นในแต่ละพื้นที่ จากนั้นซิงก์สถานะขอบเขตกับการจำลองขอบเขตอื่น ๆ ที่คำนวณแบบขนาน แล้วทำซ้ำ
    • แปลกใจที่รู้ว่า Nick อายุแค่ 25 ปี
  • ออกนอกประเด็นเล็กน้อย แต่นึกถึงส่วนในบทความที่บอกว่าต้องปรับแต่งภูมิประเทศเพื่อเก็บทรัพยากร
    เคยคิดมาตลอดว่า Animal Crossing จัดการเรื่องนี้ได้ค่อนข้างฉลาดและมีประสิทธิภาพโดยไม่ต้องปรับแต่งภูมิประเทศ เมื่อตัดต้นไม้ก็ได้ท่อนไม้ออกมา แต่มีจำนวนจำกัดและโดยพื้นฐานแล้วจะมีช่วงคูลดาวน์
    ให้ความรู้สึกของ feedback และทรัพยากรที่มีจำกัดได้โดยไม่ต้องใช้การปรับแต่งภูมิประเทศที่มีต้นทุนสูง แน่นอนว่าไม่ได้เหมาะกับทุกเกม และเหมาะกับแผนที่ขนาดเล็กมากกว่า แต่ก็ควรพิจารณา ถ้าเกมไม่ได้จำเป็นต้องใช้จริง ๆ หลายครั้งการไม่ปรับแต่งภูมิประเทศอาจดีกว่า

    • ในบทความก็พูดถึงกลยุทธ์แบบนั้นในรูปของ ก้อนหินแร่ทองคำ ที่วางอยู่รอบ ๆ
      ในฐานะวิธีแจกทรัพยากรก็ถือเป็นมาตรฐาน แต่คูลดาวน์ไม่ได้แก้ปัญหาทรัพยากรไม่จำกัด แค่ทำให้ช้าลง และยังค่อนข้างน่าเบื่อกับมีอิทธิพลน้อย
  • เป็นบทความที่เจาะหัวข้อนี้ได้อย่างเรียบร้อย และดีใจที่พูดถึง Timberborn
    ช่วงนี้ติดเกมนั้นมาก ถ้ายังไม่เคยลอง ขอแนะนำอย่างยิ่ง การไหลของน้ำที่อิงฟิสิกส์เหมือนเป็นตัวละครอีกตัวในเกม และการหาวิธีกักน้ำเพื่อใช้กับเครื่องยนต์และส่งไปยังแปลงเพาะปลูกคือแกนหลักของ gameplay loop

  • สนุกและทำออกมาได้ดีจริง ๆ ความเสี่ยงใหญ่ที่สุดตอนพัฒนาอะไรแบบนี้คือการเสียเวลาเป็นชั่วโมง ๆ ไปกับการปรับพารามิเตอร์เพราะมัวแต่มองผลลัพธ์สวย ๆ
    นึกถึงตอนปี 2011 ที่เคยทำ พลศาสตร์ของไหลบน GPU เองสำหรับงานวิจัย เป็นของไหลที่ไหลบนพื้นผิว กล่าวคือเลือดที่ไหลบนเนื้อเยื่อ จำลองเป็น 2D ก่อน แล้วฉายขึ้นไปบน mesh โดยคำนึงถึงแรงโน้มถ่วงและความชันของพื้นผิว
    อัปโหลดวิดีโอสั้น ๆ ไว้บน YouTube ด้วย: https://youtu.be/4vGrNc-GGW8

  • เจ๋งมาก
    เมื่อเร็ว ๆ นี้ได้ทดลองไอเดียคล้าย ๆ กันด้วยความช่วยเหลือจาก o3-mini-high อธิบายไอเดียอัลกอริทึมให้มัน แล้วมันก็ implement และ render เป็น 3D โดยไม่ต้องแทรกแซงด้วยมือ แต่ใส่พรอมป์หลายครั้ง
    https://3d-water-sim.netlify.app/
    ยังไม่สมบูรณ์แบบ เพราะหยุดไปก่อนตอนกำลังลองปรับ แต่ทุกครั้งที่วนซ้ำก็ดีขึ้นค่อนข้างมาก สิ่งที่น่าสนใจคือ สำหรับการสร้างภูมิประเทศ มันไม่ได้ไปดึงจากที่อย่าง CDN แต่ implement เวอร์ชันที่ทำงานได้ของ Perlin noise ตั้งแต่ต้นอย่างถูกต้อง

    • เวลาทดลองแบบนี้ อยากรู้ว่าเป้าหมายคือความสนุกหรือการเรียนรู้ ถ้าเป้าหมายคือการเรียนรู้ ก็อยากรู้ด้วยว่ายังรู้สึกว่าการอ่านบทความนี้มีคุณค่าอยู่ไหม แม้จะไม่ได้ implement ด้วยตัวเอง
      เป็นคำถามเรื่องความต่างระหว่างการเดินทางกับจุดหมาย
  • ส่วนที่บทความบอกว่า “โมเดลนี้ไม่มีความเฉื่อยและการแพร่กระจายของความเร็ว แม้น้ำที่ไหลเร็วจะไหลเข้าสู่ทะเลสาบ ก็จะไม่แพร่ต่อเข้าไปด้านในทะเลสาบ แต่กระจายออกทุกทิศทางโดยละเลยความเฉื่อยที่สะสมไว้ หากระดับน้ำเท่ากัน กระแสน้ำขนานสองสายที่ไหลสวนทางกันก็อาจไม่โต้ตอบกันเลย” นั้น น่าจะแก้ได้ด้วยการเฉลี่ยกับลูกศรการไหลรอบข้าง 6 อันที่มีทิศทางเดียวกัน
    คือให้น้ำหนักมากกับลูกศรด้านหน้าและด้านหลัง และให้น้ำหนักน้อยกับลูกศรด้านข้าง เช่น เมื่อมีลูกศรแบบนี้
    -a-> -b->
    -c-> -d-> -e->
    -f-> -g->
    New_d = d * (1 - 2*.1 - 4*.01) + (c+e).1 + (a+b+f+b).01
    ในที่นี้ .1 และ .01 เป็นค่าน้ำหนักที่ตั้งขึ้นเอง จึงต้องปรับแต่ง และอาจใส่เลขยกกำลังเหมือนที่ใช้ลดการสั่นได้ด้วย หากรวมค่าสัมประสิทธิ์นั้นเข้าไป ก็อาจเป็นแบบนี้
    New_d = d * (1 - 2*.1 - 4*.01 - .001) + (c+e).1 + (a+b+f+b).01

    • วิธีแก้ที่ถูกต้องดูเหมือนจะใกล้เคียงกับการเพิ่ม กริดสำหรับอนุพันธ์อันดับสอง อีกชุดหนึ่งที่สอดคล้องกับกริดเดิม
      grid 0: ความสูงของน้ำในแต่ละช่อง
      grid 1: การไหลของน้ำที่แต่ละขอบ หรือก็คืออนุพันธ์อันดับหนึ่ง
      grid 2: ความเร่งของน้ำในแต่ละช่อง หรือก็คืออนุพันธ์อันดับสอง
      เป็นโครงสร้างที่แต่ละกริดเป็นกริดคู่ของกริดก่อนหน้าและเก็บค่าอนุพันธ์ของมันไว้ จริง ๆ แล้วอาจไม่จำเป็นต้องจัดการข้อมูลขอบเป็นพิเศษ แค่วางข้อมูลที่จุดยอดแล้วประมวลผลเป็นกริดคู่อย่างเดียวก็น่าจะได้ การไหลตามขอบสามารถอนุมานได้จากผลรวมของการไหลที่จุดยอดทั้งสองด้านของขอบนั้น
      ดังนั้นจึงอัปเดตความสูงของของไหลด้วยการไหล จากนั้นอัปเดตความเร่งตามว่ามวลของของไหลไหลเข้ามาในช่องมากเท่าใดด้วยความเร็วเท่าใด แล้วจึงอัปเดตการไหลจากความเร่งและความสูงของของไหลปัจจุบัน ผมไม่ค่อยรู้พลศาสตร์ของไหล แต่ในมุมมองของการจำลองเชิงตัวเลขก็ดูถูกต้อง และยังทำให้การไหลแนวทแยงเป็นไปได้ด้วย
    • วิธีนั้นทำลาย การอนุรักษ์โมเมนตัม หากต้องการการไหลที่สมจริง ต้องใช้สมการความต่อเนื่องเพื่อรักษาพลังงานของการไหล และให้แรงเฉือนสลายตัวและแพร่กระจายเป็นวอร์เท็กซ์
      อย่างที่บทความบอก ภาระการคำนวณจะเพิ่มขึ้นมาก ดังนั้นควรพิจารณาก่อนว่ากรณีใช้งานจริงต้องการความสมจริงระดับนั้นหรือไม่
  • เป็นผลงานหยาบ ๆ ที่ทำขึ้นเมื่อหลายปีก่อนเพราะสงสัย: https://aperocky.com/hydrosim/
    ก่อนที่โปรเจกต์ส่วนตัวนี้จะถูกเก็บเข้าชั้นแช่เย็น ผมยังหาวิธีจัดการ การกัดเซาะ ไม่ได้ ชอบที่ผู้เขียนพูดถึงส่วนนี้และแนบสมการมาด้วย

  • เมื่อไม่นานมานี้ได้เปิดเผยสิ่งที่คล้ายกัน มีทั้งการสร้าง heightfield แบบสุ่ม การเคลื่อนย้ายตะกอน และการกัดเซาะ: https://github.com/Ono-Sendai/terraingen

  • คุณสามารถลองเล่น การจำลองน้ำท่วม เพื่อการศึกษาที่นักพัฒนาฝีมือเยี่ยมของบริษัทเราทำขึ้นเป็นส่วนหนึ่งของโปรเจกต์วิจัยได้
    https://flood.concord.org/
    ถ้าต้องการเห็นผลชัด ๆ ต้องเปลี่ยนค่าของโมเดลในแถบเครื่องมือด้านล่าง
    เป็นการจำลองแบบเซลล์ที่คำนวณค่าของช่องใน WebGL โดยอิงจากช่องข้างเคียง เชดเดอร์ที่ทำการคำนวณนั้นอยู่ที่นี่
    https://github.com/concord-consortium/flooding-model/blob/ma...