Voxel rendering
-
Hi Volkz!
Als ich die Screenshots von Id-Tech-6 und deren Voxel-Renderer gesehen habe, stand ich mit offenen Mund und großen Augen vor dem Bildschirm, ja ich hab praktisch schon gesabbert, so faziniert war ich davon.
Da mich das nun brennend interessiert, wollte ich mich erstmal selbst an einen schlichten Software Voxel Renderer versuchen, nur für übungszwecke, damit ich mich dem Thema annähern kann. Ich habe ein wenig im Internet über Volume Rendering schlau gemacht und viel Mathematisches Zeug gelesen, das ich noch nicht (Bin erst in der 12ten) so richtig verstehe oder einfach nur zu faul bin es zu verstehen.
Meine Gedanken sind nun folgene:
Ich habe ersteinmal eine Basis Voxel klasse, der einfachheit 'class AveVoxel' genannt. Diese hält die Position im Raum, also X, Y und Z Koordinaten, die Farbe, also R, G und B, das A lasse ich erstmal weg, und schließlich noch einen Ausdehnungswert 'Radius'. Die Voxel werden dann Mathematisch als Kugeln behandelt. Jeder Voxel kann wiederum weitere Untervoxel haben, die Anzahl ist erstmal auf 4 beschränkt. Diese Voxel sollten in der Regel niemals größer oder außerhalb der Vatervoxels liegen.
Dem Renderer kann ich nun ganz viele Voxel verpassen, die er dann speichert. Außerdem übergebe ich diesem eine Cameraposition und die richtung in die die Camera schaut.
Gerendert wird dann mit Raytracing (Ich hoffe ich verwechsel das jetzt nicht mit Raycasting). Von jedem Pixel aus werden nun Orthogonal (Das mit dem 3D kommt dann noch) Rays ausgeschickt. Wenn das Ray nun auf einen Voxel Trifft, wird erstmal geschaut ob einer dieser Untervoxel nicht besser das Pixel abdeckt, usw ... bis schließlich das passende Voxel gefunden ist, und der Pixel an dieser Stelle die Farbe des Voxels bekommt.
Wie gesagt möchte ich das ganze erstmal als software renderer umsetzen, doch ist es nicht ausgeschlossen, das in naher zukunft, falls es mit gelingen sollte, auch für die echtzeitgrafik mit CUDA oder anderen Hilfsmitteln tauglich zu machen. Meine Frage an euch ist, ob ich darauf aufbauen kann, oder ob ich ganz falsche Ansätze verfolge?
-
du machst dir das schwerer als es ist.
voxel sind punkte im punkteraum (voxelspace bzw voxel volume).
ein einfacher voxelraum ist:enum{VOLUME_WIDTH=128}; enum{VOLUME_HEIGHT=128}; enum{VOLUME_DEPTH=128}; typedef int voxel; voxel VoxelVolume[VOLUME_WIDTH*VOLUME_HEIGHT*VOLUME_DEPTH];
das war es auch schon.
pro voxel steht dann die farbe, leere voxel sind voll transparent, bzw 0.
beim raytracen/raycasten gehst du nun voxel fuer voxel vom voxelspace durch und pruefst ob da ein sichtbarer voxel ist, wenn je, zeichnest du die farbe als pixel auf den bildschirm und falls nicht, gehst du einen voxel weiter (im einfachsten fall gehst du in festen schritten weiter.
es gibt dabei viele methoden voxelvolumes darzustellen, im medizinischen werden andere methoden benutzt als es id software macht. auch liegen die daten anders vor, aber ich denke du willst erstmal den ersten schritt finden und da ist die oben beschriebene ein einfacher einstieg.
hatte damit auch ein wenig rumgespielt
kleine stadt: http://www.rapso.de/ranz/vox/030.png
das model von id software: http://www.rapso.de/ranz/vox/035.png (nicht von den farben irrefuehren lassen, das model ist so hoch aufgeloest wie id software das machte, ich habe leider nicht die texturen bekommen, sondern nur das model und deswegen pro 50x50 voxel eine farbe anhand der z-tiefe vergeben, deswegen sieht das aus wie holz fasern... in etwa..)
-
Wow, könnte ich das Model auch haben? Will mir nicht unbedingt ein eigenes Voxel'n ^^
enum{VOLUME_WIDTH=128}; enum{VOLUME_HEIGHT=128}; enum{VOLUME_DEPTH=128}; typedef int voxel; voxel VoxelVolume[VOLUME_WIDTH*VOLUME_HEIGHT*VOLUME_DEPTH];
Aber ist das nicht ein bischen übertrieben, wenn man 128*128*128*4Byte nur für ein Voxel benötigt? Das kann man doch sicherlich eleganter speichern?
//Edit:
Ahso, jetzt verstehen ... Das Voxelvolume besteht selbst aus so vielen Voxeln, und dieses VoxelVolumen könnte dann z.B. sowas sein wie ein Mesh, wie man es bei den Polygonen kennt.
Aber das läßt sich doch bestimmt in nen anständigen Octree speichern? Arbeitet man im Voxelspace eigentlich nurnoch mit Integern, also Ganzen zahlen, oder schon mit Floats? Denn das wäre hier ja eigentlich soooo nicht mehr nötig?
Und wie könnte man ein Volume dann rotieren?
-
Potatoman schrieb:
Ahso, jetzt verstehen ... Das Voxelvolume besteht selbst aus so vielen Voxeln, und dieses VoxelVolumen könnte dann z.B. sowas sein wie ein Mesh, wie man es bei den Polygonen kennt.
Aber das läßt sich doch bestimmt in nen anständigen Octree speichern?
erst implementieren, dann optimieren
Arbeitet man im Voxelspace eigentlich nurnoch mit Integern, also Ganzen zahlen, oder schon mit Floats?
was auch immer du fuer besser erachtest, implementierungen sind unterschiedlich
Denn das wäre hier ja eigentlich soooo nicht mehr nötig?
sowohl float als auch int als auch irgendwas anderes was dir gefaellt (eigene ray oder line klasse oder so) ist ok, das ist dir ueberlassen.
Und wie könnte man ein Volume dann rotieren?
indem du die camera entgegengesetzt rotierst, aber eigentlich rotiert man ein volume nicht. es ist ein statisches gebilde. deswegen hat john carmack (gruendder von ID software) auch gesagt dass sie animationen weiterhin mit polygonmodellen machen werden.
-
Braucht ein Voxel nicht auch noch eine Ausdehnung?
-
this->that schrieb:
Braucht ein Voxel nicht auch noch eine Ausdehnung?
Wenn ich das richtig verstehe, ist ein Voxel ein Pixel in 3D. Da gibt es einfach keine Ausdehnung.
-
Gewissermaßen hat es ja schon ne ausdehnung. Wenn ich dem Volume sage es hat eine Tiefe von 128 besteht dieses aus 128 Schichten in der Tiefe wobei jeder Voxel eine Ausdehnung von 1³ hat.
Was ich mich aber grad frage ist, wie ich es nun mit der kollision mache. Benutzt man einfach ein Ray das man vom Bildschirm aus abschießt, oder ein Viewfrustum, das für jedes Pixel gebildet wird?
Und wie testet man dann generell die Kollision? Werden die Voxel dann als AA-Bounding Boxes behandelt?
-
@this->that
die ausdehnung ist dann 1/128 vom volume pro achse (bezogen auf mein beispiel oben)kollision ist
const static voxel EMPTY = 0; if(VoxelVolume[x+y*VOLUME_WIDTH+z*VOLUME_WIDTH*VOLUME_HEIGHT]!=EMPTY) { //collision }
zu raycasting in 2.5D gibt es massig tutorials
http://www.permadi.com/tutorial/raycast/index.html
http://www.student.kuleuven.be/~m0216922/CG/raycasting.html
in medizin:
http://www.daimi.au.dk/~trier/?page_id=98jetzt nur noch in 3d implementieren und tadaaa
-
const static voxel EMPTY = 0; if(VoxelVolume[x+y*VOLUME_WIDTH+z*VOLUME_WIDTH*VOLUME_HEIGHT]!=EMPTY) { //collision }
Ja so erkenne ich ob das Voxel leer ist oder nicht, aber wie schaut es nun mit der eigentlichen kollision aus. Ich muss ja für jedes Pixel ein Ray schießen und auf Kollision mit einem Voxel prüfen. Nun ist aber die Frage, als was man nun ein Voxel betrachtet. Ich kann mir grad nur so vorstellen, das jedes Voxel eben eine Bounding Box ist, und das Ray auf kollision mit dem Voxel geprüft wird. Aber das ist vermutlich viel zu langsam?
-
Potatoman schrieb:
... wie schaut es nun mit der eigentlichen kollision aus....
steht in den links
-
rapso schrieb:
das model von id software: http://www.rapso.de/ranz/vox/035.png (nicht von den farben irrefuehren lassen, das model ist so hoch aufgeloest wie id software das machte, ich habe leider nicht die texturen bekommen, sondern nur das model und deswegen pro 50x50 voxel eine farbe anhand der z-tiefe vergeben, deswegen sieht das aus wie holz fasern... in etwa..)
Gibts das frei verfügbar oder woher hattest du das?
-
TyRoXx schrieb:
this->that schrieb:
Braucht ein Voxel nicht auch noch eine Ausdehnung?
Wenn ich das richtig verstehe, ist ein Voxel ein Pixel in 3D. Da gibt es einfach keine Ausdehnung.
Ich würde sagen: jain,.. nach definition ja, aber wenn ich mich grob an den c't artikel über raytracing erinnere, wird der raum in verschiedene quader geteilt, ein unterquader hat dann die eigenschaft ein voxel zu sein, leer zu sein oder aus verschiedene weitere unterquader zu bestehen. Das hilft die Speichergröße zu reduzieren etc. pepe....
Software lösungen habe ich in vielen links gesehen, aber gibt es die möglichkeit auch hardware beschleunigt dies auf den bildschirm zu legen? (á la openGL?)
Seid gegrüßt
-
Potatoman schrieb:
...Ich muss ja für jedes Pixel ein Ray schießen und auf Kollision mit einem Voxel prüfen. Nun ist aber die Frage, als was man nun ein Voxel betrachtet. Ich kann mir grad nur so vorstellen, das jedes Voxel eben eine Bounding Box ist, und das Ray auf kollision mit dem Voxel geprüft wird. Aber das ist vermutlich viel zu langsam?
Du könntest dir erstmal einen Octree oder sowas basteln, so das du ganze Areale gleich ausschliessen kannst in denen ohnehin nur "Luft" drin ist
Mit der Ray-Voxel Prüfung beginnst du dann im ersten nicht-leeren Quader den der Strahl durchquert. Hab das selbst noch nie gemacht, aber so in der Art stell ich mir das vor
Und ja: Ein Voxel ist gewissermaßen eine Bounding Box - ein "volumetric pixel" halt
-
ich habe mal auch noch ne frage, da das thema mich auch interessiert:
Nehmen wir an ich hätte aus voxel mir ne sphäre gebastelt, seitlich trifft licht auf diese. Nun müsste über die Orthogonale der reflexionswinkel bestimmt werden. Voxel sind doch aber Achteckige (infinitisimal kleine) Volumina mit "harten" kannten. Wie kann da der "richtige" Reflexionswinkel berechnet werden? Oder wird über die "möglich" benachbarten voxel eine ebene gefittet um dann über den tangentialraum die nötigen informationen zu ziehen?
Über links bin ich auch dankbar
greetz
-
Ein Voxel kann auch sowas wie eine Normale speichern
-
zeusosc schrieb:
ich habe mal auch noch ne frage, da das thema mich auch interessiert:
Nehmen wir an ich hätte aus voxel mir ne sphäre gebastelt, seitlich trifft licht auf diese. Nun müsste über die Orthogonale der reflexionswinkel bestimmt werden. Voxel sind doch aber Achteckige (infinitisimal kleine) Volumina mit "harten" kannten. Wie kann da der "richtige" Reflexionswinkel berechnet werden? Oder wird über die "möglich" benachbarten voxel eine ebene gefittet um dann über den tangentialraum die nötigen informationen zu ziehen?
Über links bin ich auch dankbar
greetz
Mann kann z.B. über den gradient die richtung der normalen ausrechnen, das ist aber eher für volumen und nicht direkt voxeldaten. Kann mir aber vorstellen dass man da ähnliches machen kann. (halbwissen und so)