In che modo viene implementata la marchiatura a raggi di campo a distanza firmata per un mondo dinamico?


10

Penso di aver compreso le basi di Marched Ray Field Marching. Modella la tua scena con un mucchio di campi di distanza (come questi: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm ), quindi per ogni pixel che lanci un raggio, inizia dall'inizio del raggio , trova la distanza dall'oggetto più vicino in quel punto e incrementa il punto della distanza più vicina, fino a quando non colpisci qualcosa. Sono riuscito a fare un semplice renderer, ed è qui che si fermano la maggior parte delle descrizioni della tecnica.

Questo mi lascia con alcune domande su come SDF Ray Marching può essere utilizzato in uno scenario del mondo reale:

Domanda 1: In un gioco reale, la scena è generalmente complessa e caricata sulla CPU, con molti oggetti dinamici. Capisco l'abbattimento di occlusione di base (come gli octrees) e con il rendering poligonale, creerei un elenco (sulla CPU) di elementi nella vista frustrati da rendere.

Quindi, immagina di avere una scena molto complessa con molti personaggi e oggetti dinamici che si muovono sullo schermo, controllati dalla CPU. Come potrei trasmettere in streaming gli oggetti che voglio renderizzare sulla GPU ogni frame? Ogni esempio ha la scena hardcoded in GLSL. Qualcuno può condividere un esempio del livello che viene trasmesso allo shader in modo dinamico?

Domanda 2: In che modo gli oggetti possono avere più colori? Le funzioni di distanza restituiscono solo una distanza, ma in che modo le implementazioni comunemente restituiscono il colore? (ad esempio, colpisci una sfera rossa e non un cubo blu.) Se si trattasse di un'implementazione della CPU, potrei chiamare una funzione globale all'interno della funzione di distanza quando è un colpo per terminare il raggio laser e che potrebbe anche passare l'oggetto del colpo texture / colore. Ma come restituiresti il ​​colore o la trama dell'articolo in GLSL?

Grazie.

Risposte:


2

Questa è una risposta minima, ma volevo condividere le informazioni nel caso in cui non avessi una risposta migliore.

Per quanto riguarda il modo in cui i giochi reali usano la marcia dei raggi, di solito non lo fanno. Solo negli ultimi due anni i giochi hanno iniziato a raymarching del buffer di profondità per fare riflessioni sullo spazio dello schermo, ma nessun gioco di cui sono a conoscenza utilizza i raggi che marciano nel modo in cui descrivi - ancora?

Per l'altra domanda sui colori e simili, le persone comunemente associano materiali agli oggetti e usano le "coordinate di trama" del punto in cui il raggio colpisce l'oggetto per capire le proprietà del materiale in quel punto dell'oggetto. I materiali comuni includono cose come colore diffuso, intensità speculare, colore emissivo e indice di trasparenza / rifrazione.

Spero che sia almeno un aiuto per te! Potresti anche ottenere buone risposte dal sito di scambio di stack grafici.


2
"nessun gioco sono a conoscenza degli usi del ray marking nel modo in cui descrivi" L'imminente gioco di Media Molecule Dreams utilizza campi con distanza segnata per la creazione di contenuti generati dagli utenti, ma se capisco correttamente i campi vengono convertiti in una nuvola di punti per il rendering anziché essere raymarched direttamente. Questo articolo potrebbe avere alcune idee: dualshockers.com/2015/08/15/…
DMGregory

1
@DMGregory Nice, ma penso che non sia strettamente Ray Marching. Quindi il punto è ancora valido, i giochi di solito non usano il ray marching.
concept3d

1
Aggiornamento di questa discussione - il gioco imminente Claybook secondo come riferito rende le sue scene usando i raggi sparati direttamente attraverso i campi di distanza , piuttosto che convertirli prima in geometria convenzionale. Quindi il "ancora?" sembra essere stato confermato due anni dopo. :)
DMGregory

1

Attualmente sto sviluppando un motore di gioco che utilizza campi di distanza con segno come tecnica di rendering per visualizzare una geometria procedurale uniforme (generata per ora con primitivi semplici come quelli nel tuo link, cercando di implementare i frattali Julia e IFS in futuro). Dato che il mio motore è incentrato sulla generazione procedurale e deve definire le figure in modo da renderle amichevoli per i ray-marcher, immagino di essere in un buon posto per rispondere a questa domanda: P.

Per quanto riguarda lo streaming, la semplice soluzione è utilizzare un buffer tipizzato di qualche tipo e lanciarlo sulla GPU quando si desidera eseguire il ray-marking. Ogni elemento del buffer è un tipo complesso (ad es. Una struttura in C / C ++) e ogni tipo contiene elementi che definiscono quale funzione si dovrebbe usare per rappresentarlo, la sua posizione, rotazione, scala, ecc. E un colore medio. Il processo si semplifica quindi fino a:

  1. Abbatti la tua scena in un sottoinsieme gestibile (nota che l'abbattimento del frustum e l'abbattimento dell'occlusione sono comunque parzialmente eseguiti automaticamente dall'algoritmo di marcia del raggio)
  2. Passa il sottoinsieme nel buffer di input del rendering
  3. Passa il buffer alla GPU se non è già presente, quindi esegui il rendering della tua scena con il normale ray-marking tradizionale. Dovrai eseguire un tipo di ricerca per passaggio per valutare quale elemento nel buffer di input è più vicino a ciascun raggio per ogni iterazione del ray-marcher e dovrai applicare trasformazioni a entrambi i raggi (nel qual caso dovrai invertire le rotazioni delle figure prima che raggiungano la GPU) o le funzioni di distanza stesse (spostando l'origine della funzione per i cambi di posizione, regolando ad esempio le lunghezze dei lati cubi per i cambiamenti di scala, ecc.) L'approccio più semplice è semplicemente modificare i raggi prima li si passa alla funzione di distanza del nucleo attuale.

Per quanto riguarda i colori delle figure, ricorda che gli shader ti consentono di definire tipi complessi e primitivi;). Ciò ti consente di gettare tutto in una struttura in stile C, quindi passare quelle strutture indietro dalla tua funzione di distanza.

Nel mio motore, ogni struttura contiene una distanza, un colore e un ID che lo lega alla definizione della figura corrispondente nel buffer di input. Ogni ID viene dedotto dal contesto circostante della relativa funzione di distanza (poiché la mia funzione di mappatura scorre attraverso il buffer di input per trovare la figura più vicina a ciascun raggio per ogni passaggio, posso tranquillamente trattare il valore del contatore di loop quando viene chiamato ogni SDF come ID della figura per quella funzione), mentre i valori di distanza sono definiti usando un SDF core arbitrario (espoint - figure.pos per una sfera) e i colori sono definiti dal colore medio dell'elemento appropriato nel buffer delle figure (quindi perché è utile mantenere l'ID della figura attorno) o attraverso un colore procedurale ponderato rispetto alla media memorizzata (un esempio potrebbe essere prendere un conteggio di iterazioni per un certo punto sul Mandelbulb, mappando il tuo "colore medio" dallo spazio colore FP allo spazio colore intero, quindi usando il colore mappato come una tavolozza XOR 'confrontandolo con il conteggio iterazione).

Le trame procedurali sono un altro approccio, ma non le ho mai usate da solo. iq ha svolto molte ricerche in quell'area e pubblicato alcune interessanti dimostrazioni su Shadertoy, quindi potrebbe essere un modo per raccogliere alcune informazioni extra.

Indipendentemente dal fatto che il colore sia statico per ogni figura, generato proceduralmente o magicamente campionato da una trama procedurale, la logica di base è la stessa: figure astratte in una sorta di tipo complesso intermedio (ad esempio una struttura), memorizzare sia la distanza locale che locale colora un'istanza di quel tipo, quindi passa il tipo complesso come valore di ritorno dalla tua funzione di distanza. A seconda dell'implementazione, il colore di output può quindi passare direttamente allo schermo o seguire il punto di collisione nel codice di illuminazione.

Non so se quanto sopra fosse abbastanza chiaro o no, quindi non preoccuparti di chiedere se qualcosa non ha senso. Non posso davvero fornire alcun esempio di codice GLSL / pixel-shading poiché sto lavorando con HLSL e l'ombreggiatura del calcolo, ma sono felice di provare a ripassare tutto ciò che non ho scritto correttamente in primo luogo :).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.