PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Grundlegendes Culling in aktuellen Engines


Simon
2003-04-08, 18:36:29
Hallo,

da ich demnächst eine neue Engine anfangen möchte, wollte ich mich vorher interessieren, was den momentan an Culling angebracht ist? Zielplattform ist eigentlich nur meine Radeon9700 oder halt GF3/4. Ich dachte eigentlich entweder an einen Octree, find ich zum Rendern aber nicht so toll oder eine Kombination aus Portal Engine für Innengeometrien und Patch-rendering für Außenszenarien. Später vielleicht noch Occlusion Culling.

Was haltet ihr davon? Irgendwelchen anderen Vorschläge oder Verbesserungen?


Danke und bye, Enrico


PS: Kennt jemand Vertex & Pixel Shader tuts für OpenGL?

Demirug
2003-04-08, 19:18:45
Zuerst mal solltest du möglichst nur auf Objektebene (> 130 Verticen) arbeiten. Kleiner Datenpackte lohnen in der Regel nicht weil dann oft der Overhead zu gross wird.

Ansonsten hat natürlich jedes Verfahren so seine Vor und Nachteile. Wenn man also eine möglichst flexibele Engine haben möchte baut man das Culling am besten nicht direkt in die untere ebene der Engine sonder in eine der höheren. Dadurch kann man bei Bedarf das ganze leicht austauschen und auch mehrer Verfahren leichter kombinieren.

Zum Thema Vertex und Pixelprocessing unter OpenGL schauts du am besten mal in den Entwicklerbereich von NVIDIA und ATI da das ganze ja immer noch sehr hersteller bezogen ist.

Simon
2003-04-08, 20:59:15
Originally posted by Demirug
Zuerst mal solltest du möglichst nur auf Objektebene (> 130 Verticen) arbeiten. Kleiner Datenpackte lohnen in der Regel nicht weil dann oft der Overhead zu gross wird.

Dann hab ich aber wieder das Problem, das ich viele API-calls habe und dauernd Daten über den Bus senden muss. Oder versteh ich da jetzt was falsch?

Originally posted by Demirug
Zum Thema Vertex und Pixelprocessing unter OpenGL schauts du am besten mal in den Entwicklerbereich von NVIDIA und ATI da das ganze ja immer noch sehr hersteller bezogen ist.
Ich dachte immer in meiner Naivität das gerade der Assemblercode dergleiche bei ATI und Nvidiakarten sein sollte ... Das die Extensions und Funktionen anders, hab ich mir schon gedacht, auch wenn das mit EXT_vertex_shader sich eigentlich erledigt haben sollte ...


danke und bye, Enrico

Demirug
2003-04-08, 21:45:56
Originally posted by Simon

Dann hab ich aber wieder das Problem, das ich viele API-calls habe und dauernd Daten über den Bus senden muss. Oder versteh ich da jetzt was falsch?

Scheinbar haben wir das aneinader vorbei geredet. Was ich sagen wollte ist das man beim Culling vorzugsweise auf einer hohen Ebene arbeiten soll. Also zum Beispiel um ein Object eine BoundingBox und dann nur die Box prüfen. Und eine solche Box sollte vorzugsweise mehr als 130 Verticens representieren welche mit den gleichen Einstellungen gerendert werden.

Ich dachte immer in meiner Naivität das gerade der Assemblercode dergleiche bei ATI und Nvidiakarten sein sollte ... Das die Extensions und Funktionen anders, hab ich mir schon gedacht, auch wenn das mit EXT_vertex_shader sich eigentlich erledigt haben sollte ...

danke und bye, Enrico

Bei OpenGL kocht halt jeder so sein eigens sübchen.

Inzwischen hat man sich aber immerhin auf eine gemeinsame Extension für Vertexshader und für Fliesspunkt Pixel Shader geinigt. Für die Pixelshader der DX( Karten hat aber jeder Hersteller leider seine eigene Extension.

Unregistered
2003-04-08, 22:30:34
mhh cool
grad ein Thread wo meine Fragen reinpassen :D

So nun zum Thema Octrees.
Und zwar hab ich meine Probleme mit, dass man ja eigentlich die Geometriedaten eines zuhörigen Objektes ja auseinanderreissen müsste. Nun könnte man die Objekte in übergeordneten Nodes speichern. Aber das dürfte doch ziemlich ineffizient werden.
Dann gibts ja noch die Sache mit den loose octrees. Aber da hab ich irgendwo meine Verständnisschwierigkeiten :/
Werden da die Würfel alle gleichmässig grösser gemacht, oder dynamisch je nach Gebrauch (allein der Gedanke macht mir Angst ;) ). Irgendwie hab ich damit aber irgendwo auch meine Schwierigkeiten, weil ich mir denke, dass man grade an den Grenzlinien der übergeordneten Nodes nicht mehr viel weiter runter kommt (Denkfehler von mir?).
Ich hat mir eigentlich noch was überlegt mit jedem End-Node einen Pointer auf das teilweise beinhaltete Objekt zu geben. Aber das wird verwaltungsmäßig ja dann auch auch irgendwo grausam....
Also Objekte (Polygone noch zu zerteilen macht wohl null Sinn) zerschnibbeln oder zusammenlassen?

Machen die Octress überhaupt bei beweglichen Objekten von der Performance her Sinn. Man muss zwar nur die betroffenen Nodes neu berechnen. Aber mir ist nicht klar, obs nicht mehr Sinn macht den Objekten gleich am Anfang ne Box zu geben und mit der einfach arbeitet....

Und vorallem wo macht das überhaupt Sinn?
Ist für Innenräume Portal Culling nicht wesentlich sinnvoller?

Schon thx :)

Simon
2003-04-08, 22:52:15
Originally posted by Unregistered
Und zwar hab ich meine Probleme mit, dass man ja eigentlich die Geometriedaten eines zuhörigen Objektes ja auseinanderreissen müsste. Nun könnte man die Objekte in übergeordneten Nodes speichern. Aber das dürfte doch ziemlich ineffizient werden.

das oder loose octrees

Originally posted by Unregistered
Dann gibts ja noch die Sache mit den loose octrees. Aber da hab ich irgendwo meine Verständnisschwierigkeiten :/
Werden da die Würfel alle gleichmässig grösser gemacht, oder dynamisch je nach Gebrauch (allein der Gedanke macht mir Angst ;) ). Irgendwie hab ich damit aber irgendwo auch meine Schwierigkeiten, weil ich mir denke, dass man grade an den Grenzlinien der übergeordneten Nodes nicht mehr viel weiter runter kommt (Denkfehler von mir?).

Also, loose octrees funktionieren folgendermaßen (AFAIR):
Man macht die Nodes um einen bestimmten Faktor t größer. Am besten soll es wohl bei t=2 funktionieren. Die nodes überlappen sich dann, so dass man da auch größere Objekte dort einsortieren kann.
Wenn's dich weiter interessiert, kann ich ja mal den Abschnitt aus "Real Time Rendering" dazu abtippen?!?

Originally posted by Unregistered
Ich hat mir eigentlich noch was überlegt mit jedem End-Node einen Pointer auf das teilweise beinhaltete Objekt zu geben. Aber das wird verwaltungsmäßig ja dann auch auch irgendwo grausam....
Also Objekte (Polygone noch zu zerteilen macht wohl null Sinn) zerschnibbeln oder zusammenlassen? Machen die Octress überhaupt bei beweglichen Objekten von der Performance her Sinn. Man muss zwar nur die betroffenen Nodes neu berechnen. Aber mir ist nicht klar, obs nicht mehr Sinn macht den Objekten gleich am Anfang ne Box zu geben und mit der einfach arbeitet....

Erm, so mach ich das. Alle Objekte befinden sich in p_objects. Zu jeder Node gehört eine Liste aus Integer, die angeben, welcher der Objects zu dieser Node gehören. Rendern geht dann folgendermaßen:

for(i=0; i < tmp->num_of_objects; i++)
render_object(g->p_objects[tmp->p_objects[i]]);

Geht eigentlich recht gut so :)
Überlappende Objekte werden vorher natürlich in neue aufgeteilt ;)
Zu beweglichen Objekten: Das Object startet in einer Node, d.h. eine Node hat den Index zu diesem Object. Aus der Bewegungsrichtung + -geschwindigkeit kann man nun berechnen, ob das Objekt die Anfangsnode verlässt oder nicht. Wenn nicht, dann gut. Wenn doch, kann aus dieser Berechnung die ungefähre Richtung der neuen Node entnehmen, dort brauch man dann nur den Index einsortieren und aus der alten Node löschen. Also nix mit Nodes neubauen :-P
Trivial ist das dann bei loose octrees

Originally posted by Unregistered
Und vorallem wo macht das überhaupt Sinn?

Z.B. wenn man Outdoor und Indoor miteinander kombinieren will ohne großen Aufwand. Oder nur für Outdoor, da ist Portal Culling doof, außer man nimmt anti-portale, ...

Originally posted by Unregistered
Ist für Innenräume Portal Culling nicht wesentlich sinnvoller?

Nur für Innenräume, ja


So, hoffe, da war nicht allzu viel falsch ;)

bye Enrico

Unregistered
2003-04-08, 23:12:07
Das Buch hab ich :P
Aber nicht ganze verstanden halt.
Am besten wird seit ich code mir das mal oder lass es mir die Tage nochmal durch den Kopf gehen, wenn ich mehr Ruhe hab :/

danke aber schonmal :)

Eine Frage hab ich aber noch.
Und zwar schreibst du, dass man keine neuen Nodes erzeugen muss. In in Tutorials die man im Netz findet (allerdings nicht im Buch Real-Time Rendering) wird immer gesagt die Nodes die nichts enthalten werden gelöscht. Das wäre aber doch grad bei dynamischen Szenen fatal?
Andererseits schleppt man sonst einen Haufen leerer Nodes mit sich rum, die man auch noch zu allem Überfluss unterteilen muss, da ja ein Objekt sich reinbewegen könnte. Vorallem wie weit geht man dann rekursiv?

Simon
2003-04-08, 23:33:50
Originally posted by Unregistered
Eine Frage hab ich aber noch.
Und zwar schreibst du, dass man keine neuen Nodes erzeugen muss. In in Tutorials die man im Netz findet (allerdings nicht im Buch Real-Time Rendering) wird immer gesagt die Nodes die nichts enthalten werden gelöscht. Das wäre aber doch grad bei dynamischen Szenen fatal?
Richtig, deswegen hat mein Octree von Anfang eine bestimmte Größe( d.h. Rekursionstiefe beim Erstellen). Nodes, die nichts enthalten, werden auch nicht gelöscht. Alle Objekte werden am Anfang so aufgeteilt, dass sie in die Nodes passen. Man muss bloß noch eine zweite if-Abfrage einfügen:
if(!tmp || tmp->num_of_objects<=0)
return;

Ich muss aber noch dazusagen, dass ich bis jetzt keine Lust hatte, mich intensiv mit dynamischen Szenen zu beschäftigen ...
Originally posted by Unregistered
Andererseits schleppt man sonst einen Haufen leerer Nodes mit sich rum, die man auch noch zu allem Überfluss unterteilen muss, da ja ein Objekt sich reinbewegen könnte. Vorallem wie weit geht man dann rekursiv?
Es wird zur Laufzeit nichts unterteilt und nix neu erstellt. Das einzigste, was ist, dass man ein bischen mit Variablen und Speicher rumspielen muss.
bischen pseudo code:

if(objekt_verlässt_node(tmp))
{
// Hier kann es eventuell sein, dass man das Modell ein bischen durch den Baum schicken muss, dürfte aber nicht allzu viel sein
Neue_node_bestimmen(index_vom_model);

index_des_models_löschen();
}
Neue_node_bestimmen(index_vom_model)
{
// model durch den Baum schicken, bis Node gefunden
tmp->p_objects = (int*) realloc(tmp->p_objects,sizeof(int));
tmp->p_objects[tmp->num_of_objects] = index_vom_model;
tmp->num_of_objects++;
}

Sollte so funktionieren ...

bye Enrico