Moin,
mir sind beim Rumprobieren zwei allgemeine Fragen zur
Graphikprogrammierung gekommen.
1: Wird jedes Bild (oder Frame) komplett neu gezeichnet? In Java benutze
ich für 2D-Graphik die paint()-Funktion, die jedes Mal die ganze Fläche
leert und dann jedes Objekte neu zeichnet. Wird das in der 3D-Graphik
auch so gemacht? Ich stelle mir das ziemlich ineffektiv vor, wenn ein
Objekt geändert wird, alles neu zu zeichnen. Aber andererseits weiß ich
nicht, wie es allgemeingültig sonst gehen könnte.
2: Wer übernimmt das Zeichnen der Objekte in der 3D-Graphik? Gibt es
eine einzige paint()-Funktion, die alle Objekte selber zeichnet oder hat
jedes Objekt seine eigene paint()-Funktion, die von der 'obersten'
Funktion zyklisch aufgerufen wird?
Als Beispiel, was ich meine, sollen 2D Rechtecke und Elipsen gezeichnet
werden. Das könnte man auf zwei Arten lösen. Entweder die
paint()-Funktion bekommt eine Liste aller Rechtecke und Kreise und macht
dann sowas wie
for Alle Rechtecke
ZeichneRechteck(i.x,i.y,i.Höhe,i.Breite);
for Alle Elipsen
ZeichneElipse(i.x,i.y,i.Höhe,i.Breite);
oder die Funktion ruft die paint()-Funktion jedes Objekts auf
for Alle Rechtecke
Rechteck[i].paint();
for Alle Kreise
Elipse_[i].paint();
Der Unterschied ist, dass im ersten Fall die paint()-Funktion alle
Objekte zeichnen kann, während sie im zweiten Fall nur nacheinander die
Objekte aufruft, die sich daraufhin selber zeichnen.
Wie wird das im Allgemeinen zum Beispiel bei Spielen gemacht?
Die Fragen beziehen sich auf die Hochsprachenprogrammierung, zum
Beispiel mit DirectX oder OpenGL, nicht auf die Hardwareebene.
Dussel schrieb:> Moin,> mir sind beim Rumprobieren zwei allgemeine Fragen zur> Graphikprogrammierung gekommen.>> 1: Wird jedes Bild (oder Frame) komplett neu gezeichnet? In Java benutze> ich für 2D-Graphik die paint()-Funktion, die jedes Mal die ganze Fläche> leert und dann jedes Objekte neu zeichnet. Wird das in der 3D-Graphik> auch so gemacht? Ich stelle mir das ziemlich ineffektiv vor, wenn ein> Objekt geändert wird, alles neu zu zeichnen.
Wenn ein Objekt geändert wird, dann kennt man auch den Bereich am Bild,
der sich durch diese Änderung verändert (das klingt jetzt banal, ist es
auch). Logischerweise kann sich daher auch nur bei den Objekten an der
Darstellung was ändern (die können zb verdeckt werden oder aus der
Verdeckung auftauchen), die ihr Bild in diesem Bereich haben. Daher
genügt es, wenn man nur alle Objekte in diesem Bereich neu zeichnet.
Du sollt nicht den Box-Test ausser acht lassen.
Der ist ein wichtiger Anlaufpunkt um Dinge zu beschleunigen. Grob gesagt
geht es nicht darum den Bereich bis ins letzte Detail zu kennen, sondern
es genügt zu wissen, in welchem Rechteck (eben der 'Box') ein Objekt am
Bild abgebildet wird.
Wenn man keine inverse Information hat um aus dem Bild wieder auf die
dargestellten Objekte in einem Pixel zu schliessen, dann dreht man das
eben um.
Man malt im Prinzip wieder das komplette Bild, wobei man Objekte, deren
Box im Bild gar nicht im bewussten Bereich (der Invalidate-Box) liegen
übergehen kann und nicht durch die Malroutine durch muss. Denn ihr
Abbild liegt ja im Bild bereits vor und ändert sich auch nicht.
> 2: Wer übernimmt das Zeichnen der Objekte in der 3D-Graphik? Gibt es> eine einzige paint()-Funktion, die alle Objekte selber zeichnet oder hat> jedes Objekt seine eigene paint()-Funktion, die von der 'obersten'> Funktion zyklisch aufgerufen wird?
Kannst du machen wie du willst.
Letzten Endes mündet aber alles in den zentralen System-Malroutinen. Das
eine ist eben die Objektorientierte Sichtweise (Objekte malen sich unter
zuhilfenahme der System-Malroutinen selber) das andere ist mehr die
traditionelle Sichtweise, die benutzt wurde ehe OOP in Mode kam.
> Als Beispiel, was ich meine, sollen 2D Rechtecke und Elipsen gezeichnet> werden. Das könnte man auf zwei Arten lösen. Entweder die> paint()-Funktion bekommt eine Liste aller Rechtecke und Kreise und macht> dann sowas wie>> for Alle Rechtecke> ZeichneRechteck(i.x,i.y,i.Höhe,i.Breite);> for Alle Elipsen> ZeichneElipse(i.x,i.y,i.Höhe,i.Breite);>> oder die Funktion ruft die paint()-Funktion jedes Objekts auf>> for Alle Rechtecke> Rechteck[i].paint();> for Alle Kreise> Elipse_[i].paint();
No
1
for all objects
2
object[i].paint();
und das object weiss selber wie 'paint' geht.
Vorteil: der 'Verwalter' muss nichts weiter wissen, als das es objecte
gibt und dass die sich selber malen können. Rechtecke und Ellipsen
interessieren ihn nicht und brauchen ihn auch nicht zu interessieren.
Was du gemacht hast, ist einfach nur Funktionsaufrufe ein wenig hin und
herschieben. Das ändert aber konzeptionell nichts bzw. nicht viel.
Julian V. schrieb:> Fang dort mal an zu lesen. Vielleicht hilft dir das.
Danke, aber da geht es ja darum, wie die Objekte gezeichnet werden und
nicht wodurch.
Karl Heinz schrieb:> No for all objects> object[i].paint();>> und das object weiss selber wie das geht.
Stimmt, klar. Das war ich gedanklich noch beim ersten Beispiel.
Karl Heinz schrieb:> Logischerweise kann sich daher auch nur bei den Objekten an der> Darstellung was ändern […] die ihr Bild in diesem Bereich haben. Daher> genügt es, wenn man nur alle Objekte in diesem Bereich neu zeichnet.
Muss man das bei DirectX oder OpenGL von Hand bestimmen oder machen die
das automatisch?
Karl Heinz schrieb:> Letzten Endes mündet aber alles in den zentralen System-Malroutinen.
Das ist klar. Irgendeine Funktion muss 'die Fäden in der Hand haben'.
Karl Heinz schrieb:> Das eine ist eben die Objektorientierte Sichtweise
Das ist dann wohl auch die heute gebräuchlichere.
Erstmal noch Dank für die Antworten.
Julian V. schrieb:> Da du konkret nach OpenGl fragst: http://www.opengl-tutorial.org/>> Schau dir einfach mal den Code dort an.
OpenGL-Tutorials habe ich natürlich schon gelesen (das Verlinkte noch
nicht), aber in den meisten steht nur, wie man es grundsätzlich macht
und nicht, wie man es schön/gut macht.
Ich werde es mir trotzdem nochmal ansehen ;-)
Dussel schrieb:> OpenGL-Tutorials habe ich natürlich schon gelesen
Wobei OpenGL ja wohl demnächst, jedenfalls für Linux, von GLnext bzw.
Vulkan abgelöst werden soll?
Zu Deinen anderen Fragen: 2D oder 3D macht natürlich schon einen großen
Unterschied. Ebenso ob man für 2D Hardwarebeschleunigung hat. Ohne
Hardwarebescheunigung, etwa mit Cairo, ist es schon recht langsam, wenn
man jeweils alles neu zeichnet. Für meinen Schaltplaneditor habe ich
daher für jedes Element eine Bounding-Box und versuche immer nur den
Bereich zu Zeichnen, der verändert wurde. Aber leider ist das nicht ganz
trivial -- wenn man etwa Schatten für angehobene Elemente hat, oder wenn
etwa Linien dicker gemacht werden. Da kann die Box dann plötzlich zu
klein sein. Es kommt also auf den Einzelfall an. Und wenn Du wirklich
ein echter Dussel bist, dann würde ich einfach alles mit OpenGl jeweils
neu Zeichnen, dann ist bei weitem am Einfachsten. Wobei -- wenn die
Grafik interaktiv ist, dann hat man ja eh Boxen für die Elemente, etwa
damit man sie greifen kann. Und bei Cairo habe ich eben sehr gute
Qualität, etwa auch Beziere-Kurven, und viele Backends wie etwa PDF.
Alternative hätte man aber auch Canvas Frameworks verwenden können, etwa
Clutter oder Qt GraphicsView.
Dussel schrieb:> for Alle Rechtecke> ZeichneRechteck(i.x,i.y,i.Höhe,i.Breite);> for Alle Elipsen> ZeichneElipse(i.x,i.y,i.Höhe,i.Breite);>> oder die Funktion ruft die paint()-Funktion jedes Objekts auf>> for Alle Rechtecke> Rechteck[i].paint();> for Alle Kreise> Elipse_[i].paint();
Oder schöner:
Foreach(r : rectangles) rectangleRenderer.render(r)
Analog dann für Kreise. Hat den Vorteil daß weder das Objekt noch der
Renderer unnötig ueberladen sind. Das Rechteck kennt nur seine Position
und Größe, der Rechteck-Renderer kann nur Rechtecke zeichnen hat aber
nichts mit der Logik eines Rechteck es am Hut. Somit gibt es eine
saubere Trennung von Geschäftslogik und Darstellung. Der Hauptrenderer
ruft einfach für alle Objekte die spezifischen Renderer auf.
mop schrieb:> Oder schöner:
Das geht so in die Richtung, wie man es vor 20 Jahren mitten im OOP Hype
gelernt hat. Sieht zunächst ganz nett aus. Nur Rechteck hat eben auch
Farbe, Linienstil, Schraffur und mehr. Die ganzen Parameter werden dann
stets neu gesetzt. Wobei man bei OO ja eher ein allgemeines
Grafik-Element hat, dass dann jeweils seine Draw() Methode aufruft,
mop schrieb:> nichts mit der Logik eines Rechteck es am Hut. Somit gibt es eine> saubere Trennung von Geschäftslogik und Darstellung. Der Hauptrenderer> ruft einfach für alle Objekte die spezifischen Renderer auf.
Und dann noch mal abstrahieren.
Der Hauptrenderer soll nicht wissen, welche Objekte es gibt.
Ein spezifischer Renderer solle sich daher beim Programmstart
registrieren und dabei mitteilen für welche Objekte er benutzt werden
kann.
Und jetzt wird das System dann plötzlich schon recht aufwändig. Hat aber
den Vorteil, dass man zur Laufzeit (zb per DLL) neue Objekttypen
'nachschieben' kann. DLL für Bezier-Patches vorhanden, dann laden und
die entsprechenden Objekte registrieren und schon kann das Graphiksystem
auch mit Bezier Patches umgehen. Ok, ganz so einfach ist es dann auch
wieder nicht, aber es geht schon mal in die Richtung.
Salewski, Stefan schrieb:> mop schrieb:>> Oder schöner:>> Das geht so in die Richtung, wie man es vor 20 Jahren mitten im OOP Hype> gelernt hat. Sieht zunächst ganz nett aus. Nur Rechteck hat eben auch> Farbe, Linienstil, Schraffur und mehr. Die ganzen Parameter werden dann> stets neu gesetzt.
Nicht unbedingt.
So ein Objekt rendert sich ja nicht im luftleeren Raum sondern in einer
Umgebung, einem Canvas. Den kriegt die paint Methode natürlich mit und
wenn da der Pen schon gesetzt ist, dann wird er vom Objekt nicht neu
gesetzt.
Und natürlich gibt es für jedes Objekt dann mehrere Zeichenmethoden.
Eine die aufgerufen wird, wenn es sich normal zeichnen soll. Und eine
die aufgerufen wird, wenn es sich selektiert zeichnen soll. Wobei man in
letzterm Fall dann dem Objekt auch noch mitgeben kann, ob es bei einer
Mehrfachselektion das hauptselektierte oder das nebenselektierte Objekt
ist. Letzters ist zb interessant, wenn es zb Verfahren gibt, um mehrere
Objekt nach einem ganz bestimmten Objekt auszurichten (zb alle
selektierten Rechtecke an der linken Kante untereinanderstellen. Oder
alle selektierten gleich breit machen)
Alles in allem funktioniert aber ein OOP Ansatz hier schon nicht
schlecht.
Mein Standard 2D-Editor ist eine Sammlung von Objekten, die ich je nach
Anforderungen zusammenkopiere und so den Editor konfiguriere.
Da gibt es graphische Primitiva, Renderer, Werkzeuge, Operationen (der
unterschied zwischen Operation und Werkzeug ist: Bei einer Operation
wird zuerst selektiert und dann die Aktion ausgeführt, bei einem
Werkzeug wird erst das Werkzeug angewählt und durch anklicken der
Objekte wird die Aktion auf das jeweilige Objekt angewendet), Aktionen
(Werkzeuge und Operationen handeln das GUI aus, Aktionen implemetieren
die Manipulation), natürlich einen Malkontext, es gibt eine
Propertyliste, in der jedes Objekt seine Eigenschaften auf Anforderung
reingeben kann, enstprechende GUI Elemente die dem Benutzer eine
Propertyliste zum Bearbeiten geben, Do/Undo Manager der Aktionen
zwischenspeichert und bei Bedarf wieder rückgängig machen kann, etc.
etc.
Jedes Primitiv muss ein paar Operationen unterstützen, wie zb malen,
Punkt zur Selektion auswerten, Selektiert sein, auf File laden, vom File
speichern. Dinge wie Schnittpunkte hab ich so gelöst, dass es eigene
Routinen gibt, die Schnittpunkte zwischen Primtivtypen berechnen können.
Das ist ein Punkt an dem Mehrfach-polymorphe Aufrufe schmerzlich
vermisst werden. C++ kann das nicht (Smalltalk könnte das). Der
klassische Ansatz, mit einer weiterleitung über virtuelle Funktionen
funktioniert leider nicht so gut. Hat man 10 unterschiedliche
Primtivtypen, dann artet das in ein Chaos aus
1
PointListLine::Intersect(Primitiv*with)
2
{
3
returnwith->Intersect(this);
4
}
5
6
PointListLine::Intersect(Line*with)
7
{
8
...
9
}
10
11
PointListLine::Intersect(Circle*with)
12
{
13
....
14
}
15
16
PointListLine::Intersect(Rectangle*with)
17
{
18
....
19
}
20
21
....
und das ganze dann noch mal für Circle und Rectangle in allen noch nicht
behandelten Kombinationen. (Und vor allen Dingen zieht man sich in die
Basisklasse das Wissen rein, welche abgeleiteteten Klassen es gibt). Das
artet aus. Vor allen Dingen, wenn dann noch weitere Tpen dazukommen.
Letzten Endes war eine map aus einem std::pair aus den Datentypen und
einem Funktionspointer dann doch einfacher, die zur behandelnden
Funktion führt.
Zur Lufzeit wird der effektive Runtime Typ der beiden Objekte
festgestellt und aus der map der entsprechende Funktionspointer geholt
falls einer existiert.
Arbeit ist das alles natürlich schon. Die jetzige Struktur ist auch
nicht über Nacht gewachsen sondern nach und nach entstanden und wurde
immer wieder verändert. Genau da wird OOP dann richtig schön: Man kann
einzelne Teilsysteme recht leicht durch eine ganz andere Implementierung
oder eine andere Strategie ersetzen, ohne dass gleich erst mal alles
zusammenbricht. So eine Klassenhierarchie ist nicht in Stein gemeisselt
und kann und darf verändert werden, wenn man in der laufenden Arbeit
drauf kommt, dass man nur krampfhaft damit programmieren kann.
Dussel schrieb:> 1: Wird jedes Bild (oder Frame) komplett neu gezeichnet?
Wenn man beliebig viel Rechenpower verblasen darf für beliebig einfache
Bildchen, kann man das machen.
Hat man wenig Rechenleistung und will flimmern vermeiden, zeichnet man
in eine Bitmap und kopiert dann komplett um.
Weiss man, welcher Teilbereich betroffen ist, zeichnet man gar nur diese
Regiom.
> 2: Wer übernimmt das Zeichnen der Objekte in der 3D-Graphik?
Häufig hat man eine Datenstruktur, die den Bildschirmaufbau beschreibt,
ob nun 2d oder 3d.
Da kann man die Funktionen, die die Daten ändern, schön trennen von der
Funktion, die sie zeichnet. Funktionen, die ändern, tragen gleich die
Änderungsregion ein, in der sich im Bild was geändert haben könnte.
Normalerweise iteriert die durch die Elemente und zeichnet jedes wenn es
im sichtbaren Bereich liegt "zeichne dich".
Windows macht das sehr schön: Wenn sich was ändert (Menü schliesst sich
und deckt damit mehrere Fenster mit Elementen auf) wird das zur
Invalid-Region hinzugefügt, und dann, wenn alles erledigt ist, kommt ein
PAINT das jedes darin befindliche Element und Fenster auffordert, sich
selbst zu zeichnen. So vermeidet man die Probleme, die man mit
fortlaufenden Operationen hat "muss ich jetzt schon neu zeichnen oder
wird das sowieso gleich wieder verworfen".
Karl Heinz schrieb:> und das ganze dann noch mal für Circle und Rectangle in allen noch nicht> behandelten Kombinationen.
Daher unterstützen schlauere Graphiksysteme Regionen, das sind Flächen
bestehend aus Begrenzungen jeder Form, von Linie bis Kreisbogen.
Dann werden zuerst alle Elemente zusammen in eine Region gefasst
(Union), und dann die Schnittmenge gebildet.
Hier wurde ja jetzt viel geschrieben und ich habe mir noch nicht alles
durchgelesen.
Aber nur noch mal um es klarzustellen, beide Fragen bezogen sich auf die
3D-Programmierung. Das Beispiel mit den Rechtecken und Kreisen habe ich
nur gebracht, weil ich da weiß, wie es geht und wissen wollte, wie das
in 3D gemacht wird.
Wenn man zum Beispiel etwas hinter der Kamera zeichnet, erkennen die
Graphikbibliotheken das dann und zeichnen es gar nicht oder wird das
gezeichnet und erst wenn die 3D-Szene auf den Bildschirm projiziert
wird, wird das Objekt weggelassen?
Ich weiß, das man im Allgemeinen mit der Angabe der Ecken Polygone im
Raum zeichnen kann, aber ich weiß nicht, wie das dann intern umgesetzt
wird, dass das 3D-Polygon 2D auf den Bildschirm projiziert wird. Deshalb
auch die Frage.
3D Anwendungen funktionieren (oder funktionierten einmal) meistens nach
folgendem schema:
1) Grafik/Physik/Sound library initialisieren (
opengl,opencl/physix,openal | directx,opencl/physix,directsound )
2) Objekte laden, umfast folgendes:
a) Laden von verteces und indices (Geometrie)
b) Vorausberechnungen für umboxen, umshären, etc.
c) Laden von Animationen (Keyframes, Skelett)
d) Laden benötigter shader (Vertex-,Fragment-,Tesselation- shader,
etc. Auch mehrere verschiedene davon.)
e) Laden von Texturen (Color-,Shadow-,Light-,Bump-,Normal-Map)
f) Sonstiges, opencl programme für physik, etc.
3) Erstellen Mehrerer threads oder einer Main loop für:
1) Rendering
2) Collision detection
3) Physik
4) Nachladen von daten, Speichern von daten, etc.
4) cleanup, alles wieder freigeben
Das Rendering:
Meistens wird Doublebuffering eingesetzt. Es wird der nicht sichtbare
buffer bemahlt, und die Buffer dan ausgetauscht.
Beim Rendering werden haufig mehrere Rendering passes durchlaufen,
meistens für:
1) Zeichnen des Schattens in eine Textur und/oder den Stancil buffer
2) Generieren von Reflektionstexturen (kann häufig vermieden werden
durch statische cube maps/shadow maps)
3) Rendern der Scene unter verwendung der Resourcen der Vorherigen
rendering passes
Vor einem Render pass werden normalerweise andere shader geladen und
eventuel parameter wie die Model-/View-matrix geändert.
Welche Objekte werden Gerendert?
Die Geometrie von Objekte besteht aus Dreiecken, die aus je 3 Verteces
(eckpunkte) bestehen. Alle komponenten des Vertex (Position,Farbe,etc.)
können in unterschiedlichen buffern liegen, werden aber durch den selben
Index referenziert.
Mithilfe der Verteces des Objekts kann immer die Umbox, Umsphäre, etc.
berechnen, und in der software manuell entscheiden welche Objekte
gezeichnet werden sollen.
Wann wird ein Dreiecke gezeichnet?
Folgendes übernimmt die Graphik pipeline der graka oder die Grafics
library:
1) Wenn mindestens ein Punkt des Dreiecks inerhalb der Clipping planes
ist, wird es gezeichnet. Normalerweise gibt es eine
Oben,Unten,Links,Rechts,Vorne und Hinten, sowie Benutzerdefinierte.
2) Wenn die Reihenfolge der verteces des Dreiecks korreckt ist.
(front/back face culling)
Wann werden die Fragmente (Bildpunkte) eines Dreiecks gezechnet?
Folgendes übernimmt die Graphics library:
1) Wenn die Bildpunkte im Viewport liegen.
2) Wenn die z-koordinate des fragments einen höheren, bzw. kleineren
wert als dass im depth buffer hat und dieser aktiviert wurde.
3) Wenn im Fragmentshader das Fragment nicht verworfen wurde.
Worauf muss beim zeichnen im bezug auf Performance geachtet werden?
1) Möglichst wenige Aufrufe von Grafiklibraryfunktionen. Die sind
langsam.
2) Daten einmal mit VBO auf grafigkarte, diese möglichst selten oder
garnicht ändern und immer wieder verwenden. Animationen mittels Texturen
und instancing realisieren, um die langsame Übertragung vieler
Zeichenbefehle und neuer Indexvariabelverte zu Vermeiden.
3) Sichtbarkeitsberechnungen von Objekten zuerst ungefähr und nur bei
bedarf genauer. Im zweifelsfall keine.
4) Paralelisierbare berechnungen auf graka (opencl/shader) auslagern.
Das ist jetzt nur eine ungefäre unvolständige beschreibung. Gillt nicht
für alle und nur für Rasterizer. Dinge wie Raytraceing sind eine andere
geschichte.
Es sollte nur einen überblick geben.
Um die Ursprüngliche frage zu Beantworten, was denn nun neu gezeichnet
wird: Normalerweise alles, wobei das der anwendung überlassen wird. 2D
sachen über der 3D Scene werden mit Viewport und Stanciltest meistens
anders behandelt, also seltener und nur die Geänderten Bereiche
gezeichnet (ausser diese sind transparent, dann muss man sich zwischen
neuzeichnen oder nur Änderungen nach textur/renderbuffer zeichnen
entscheiden).
Das Zeichnen macht die Grafigkarte mithilfe der Shader.
Daniel A. schrieb:> ungefäre unvolständige beschreibung.
Nun hast Du Deinen gesammten Vorrat an Rechtschreibfehlern verbraucht.
Ich kann Dir aber noch ein paar abgeben, oben findest Du schon mal die
Bezier-Kurve mit einem e zu viel am Ende.
Ach was, gerade bei der 3D Programmierung ist da keine Gefahr.
Wenn man es mit OO als Selbstzweck übertreibt, wird die Engine
unbrauchbar träge. Wenn man die OO Daten-Methoden Kapselung nicht
benutzt, wird es ein Gestrüpp, was sich nicht mehr debuggen lässt.
LOLer schrieb:> Salewski, Stefan schrieb:>> http://harmful.cat-v.org/software/OO_programming/
Oder der:
" “The problem with object-oriented languages is they’ve got all this
implicit environment that they carry around with them. You wanted a
banana but what you got was a gorilla holding the banana and the entire
jungle.” – Joe Armstrong"
LOL
> and the entire jungle
Dieses Problem hat man in der 3D Grafik sowieso. Man kommt nur auf eine
brauchbare Geschwindigkeit, wenn die Module interne Daten anderer Module
weiterverwenden.
Es gibt eigentlich gar kein Rechteck.paint(). Die Informationen für
Kamera, Clipping, Sichtbarkeit, Dreiecksnetze, Beleuchtung... werden
durch das gesamte System durch gereicht.
Die Arbeit wird dann nicht dort gemacht, wo es selbstverständlich
erscheint. Durchaus üblich, ein Teil der Sichtbarkeitsprüfung wird im 3D
Modell gemacht, der andere Teil nach der Rasterung.
Bei animierter Grafik wird es dann noch schlimmer. So weit wie möglich
benutzt die Hauptschleife interne Informationen aus der Render-Pipeline.
MaWin schrieb:> Karl Heinz schrieb:>> und das ganze dann noch mal für Circle und Rectangle in allen noch nicht>> behandelten Kombinationen.>> Daher unterstützen schlauere Graphiksysteme Regionen, das sind Flächen> bestehend aus Begrenzungen jeder Form, von Linie bis Kreisbogen.>> Dann werden zuerst alle Elemente zusammen in eine Region gefasst> (Union), und dann die Schnittmenge gebildet.
Ich bin im CAD tätig. Da helfen mir Regionen nicht viel. Denn ich hab
Einzellinien, ich hab Kreisbögen, ich hab .... und ich muss mit denen
auch geometrische Operationen machen. Ich komm also nicht umhin den
genauen Typ des Elements zu kennen.