SDF Vernietigbaar Terrein en Realtime Deformatie

EN NL ES PT-BR


Vernietigbare omgevingen zijn een van de moeilijkste problemen in game-rendering. Een traditionele mesh moet opnieuw worden getrianguleerd wanneer het oppervlak verandert, wat duur is en onvoorspelbare driehoekstellingen creëert. SDF’s gaan op natuurlijke wijze met vernietiging om omdat het uithakken van een gat gewoon een CSG-subtractie is, één operatie op een scalair veld. Dit artikel behandelt de uithakoperatie, hoe de SDF-boom schaalt naarmate deformaties zich ophopen, de Marching Cubes-extractiestap die het veld terugzet naar driehoeken, en de hybride benaderingen die engines in de praktijk gebruiken.

Voor de CSG-operators en de basis van sphere tracing, begin met het Signed Distance Fields overzicht . Voor de engine-brede context, zie SDF’s in game-ontwikkeling .

Kraters Uithakken met CSG-Subtractie

Wanneer een explosie een bolvormig stuk terrein verwijdert, werkt de SDF bij met één enkele operatie:

float crateredTerrainSDF(vec3 p) {
    float terrain = terrainBaseSDF(p);
    float crater = sphereSDF(p, explosionCenter, explosionRadius);
    return max(terrain, -crater);  // CSG subtraction
}

Het max(a, -b)-patroon trekt volume B af van volume A. Elk punt dat zich zowel binnen het terrein als binnen de explosiebol bevond, is nu buiten (de afstand wordt positief), waardoor een gat ontstaat precies waar de explosie plaatsvond. De update kost één extra primitieve per explosie, geen volledige hertriangulatie.

Een uitgewerkt voorbeeld toont de subtractie die op echte waarden werkt. Neem een vlak terrein waar de basis-SDF het vlak dterrain(p)=pyd_{\text{terrain}}(\mathbf{p}) = p_y is (negatief onder het oppervlak, positief erboven) en een explosie gecentreerd op (0,2,0)(0, -2, 0) met straal 3. De krater-SDF is p(0,2,0)3\|\mathbf{p} - (0, -2, 0)\| - 3.

Test drie punten:

  • (0,0.5,0)(0, -0.5, 0): terrein =0.5= -0.5 (1,5 eenheden onder het oppervlak), krater =(0,1.5,0)3=1.5= \|(0, 1.5, 0)\| - 3 = -1.5 (binnen de explosie). Gecombineerd: max(0.5,1.5)=1.5\max(-0.5, 1.5) = 1.5. Het punt dat vroeger vaste grond was, is nu 1,5 eenheden buiten het terrein. Het is weggehakt.
  • (0,0.5,0)(0, 0.5, 0): terrein =0.5= 0.5, krater =(0,2.5,0)3=0.5= \|(0, 2.5, 0)\| - 3 = -0.5. Gecombineerd: max(0.5,0.5)=0.5\max(0.5, 0.5) = 0.5. Nog steeds op het oppervlak, ongewijzigd.
  • (2,0.2,0)(2, 0.2, 0): terrein =0.2= 0.2, krater =(2,2.2,0)3=2.9733=0.027= \|(2, 2.2, 0)\| - 3 = 2.973 - 3 = -0.027. Gecombineerd: max(0.2,0.027)=0.2\max(0.2, 0.027) = 0.2. Net buiten de rand van de explosie, ongewijzigd.

Het eerste punt is het uithakken zelf: grond die vast was, is nu leeg. De andere twee tonen dat onaangetast terrein zijn exacte afstandswaarden behoudt, zodat het gecombineerde veld overal een geldige SDF blijft, behalve waar de bol het terrein overlapt.

Dit schaalt naar meerdere opeenvolgende deformaties. Elke nieuwe krater voegt één term toe aan de SDF-expressie. Na 50 explosies is de SDF een boom met 51 primitieven (1 basisterrein + 50 subtractie-operaties), en het evalueren ervan op een punt kost 51 primitieve afstandsberekeningen. Dat is lineaire groei in het aantal deformatiegebeurtenissen, maar constant per evaluatie, zonder mesh-topologie om te onderhouden. Wanneer veel kraters overlappen, blijft de boom correct omdat elke max-term een punt alleen maar meer buiten maakt, wat precies de semantiek van materiaal verwijderen is.

Mesh-Extractie voor Rendering

SDF-gebaseerd terrein moet nog steeds driehoeken worden voor de rasterisatiepijplijn, tenzij je volledig met ray marching rendert. De standaardbrug is Marching Cubes, die een iso-oppervlak extraheert uit een gesampeld scalair veld. Omdat de SDF het oppervlak codeert als de zero level set, extraheert Marching Cubes op natuurlijke wijze een driehoeksmesh die de huidige terreinvorm benadert.

De volledige pijplijn ziet er als volgt uit:

  1. Onderhoud een basisterrein-SDF, mogelijk gesampeld uit een heightmap of procedurele ruis.
  2. Pas CSG-subtractie toe voor elke deformatiegebeurtenis (explosies, graven, bouwen).
  3. Sample de gecombineerde SDF op een 3D-grid rond het gedeformeerde gebied.
  4. Voer Marching Cubes uit op die samples om een driehoeksmesh te produceren.
  5. Upload de mesh naar de GPU voor rasterisatie.

Stappen 3 tot en met 5 worden elke frame herhaald in het getroffen gebied, maar het grid is meestal klein (64³ of 128³) en de extractie is snel genoeg voor realtime gebruik. Games zoals Astroneer en Deep Rock Galactic gebruiken variaties van deze pijplijn voor hun vernietigbare terrein.

Twee afstembeslissingen domineren de extractiekwaliteit. De eerste is gridresolutie: de resolutie verdubbelen vermenigvuldigt het aantal samples met 8 in 3D, dus de gridgrootte is een direct geheugen- en tijdbudget. De tweede is waar het grid leeft: alleen rond het gedeformeerde gebied extraheren houdt de kosten begrensd, ongeacht hoe groot het level is, terwijl elke frame de hele wereld opnieuw extraheren niet schaalt. De afwegingen van sampling en interpolatie zijn dezelfde als die voorgebakken signed distance fields beheersen; het Marching Cubes -hub behandelt het extractie-algoritme zelf.

Hybride Benaderingen

Niet elk vernietigbaar oppervlak heeft een volledige volumetrische SDF nodig. Een veelvoorkomende hybride is om terrein weer te geven als een 2D-heightfield met een 2D-SDF die overhang- en grot-informatie codeert. Het heightfield behandelt het primaire oppervlak tegen lage kosten, en de SDF behandelt concave kenmerken en tunnels die een heightfield niet kan weergeven.

Een andere hybride slaat de deformatiegeschiedenis op als een lijst van afgetrokken primitieven (bollen, blokken, capsules) en evalueert ze tijdens runtime alleen waar nodig. Ver van deformatie evalueert het basisterrein snel. Nabij deformaties voegen de extra CSG-termen kosten toe, maar alleen in de regio’s waar detail hoog is. Dit is hetzelfde principe als de SDF-boom uit de uithaksectie, maar met de boom lui gehouden: primitieven worden alleen geraadpleegd wanneer een query in hun begrenzingsregio terechtkomt.

De hybride die het meest in uitgebrachte games voorkomt combineert al deze: een heightfield voor het brede terrein, een klein volumetrisch SDF-volume voor de regio rond actieve deformaties, en een lijst van deformatiegebeurtenissen die kan worden afgespeeld om beide representaties opnieuw op te bouwen wanneer het level wordt opgeslagen of geladen.

Samenvatting

Vernietiging is waar de representationele sterktes van de SDF het netst op een rij staan:

  • Uithakken is een CSG-subtractie, max(terrain, -crater), die precies het geëxplodeerde volume verwijdert en overal elders een geldig afstandsveld blijft.
  • Schaalbaarheid is lineair in het aantal deformatiegebeurtenissen en constant per evaluatie, zonder mesh-topologie om te herstellen.
  • Rendering extraheert driehoeken opnieuw met Marching Cubes uit een klein grid rond het gedeformeerde gebied.
  • Hybrides combineren heightfields, luie deformatielijsten en volumetrische SDF’s om de kosten evenredig te houden met de werkelijke schade.

Hetzelfde veld dat het uitgehakte terrein opslaat, beantwoordt ook de botsingsquery’s die spelers erin afvuren, en de schaduw- en AO-passes die het verlichten.