PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : WPF3D und teilweise durchsichtige Objekte


Elemental
2010-02-05, 08:51:27
Hallo zusammen,
ich bastel gerade an meinem ersten WPF3D Programm, welches PCBs (Printed Circuit Boards) anzeigen soll.

Ist nichts grossartiges, meistens nur ein grüner Würfel für die Leiterplatte und ein paar graue Würfel und Zylinder für die Bauteile.
Soweit funktioniert auch alles wunderbar.
Allerdings können einzelne Bauteile auf "auslassen" gesetzt sein, d.h. sie werdem beim Bestückvorgang der Leiterplatte nicht gesetzt. Solche Bauteile zeichne in rot, mit einem Alpha-Wert von 100, d.h. leicht durchsichtig.

Was ich nun nicht verstehe ist, dass die ausgelassen Bauteile zwar alle durchsichtig gezeichnet werden, aber nicht bei allen sieht man die Bauteile, die "dahinter" sind.
Ich hänge mal einen Screenshot mit an, damit ersichtlich wird, was ich meine.

Weiss jemand, woran das liegt? Evtl. an der Reihenfolge, in der die Objekte zum Viewport3D hinzugefügt werden?

mfG
Elemental

Neomi
2010-02-05, 11:18:02
WPF3D habe ich selbst noch nicht benutzt, aber das Problem ist eindeutig klar. Wie du schon selbst erkannt hast, ist es die Reihenfolge. Du zeichnest die transparenten Bauteile mit ZWrites an und im gleichen Durchlauf wie die soliden. Warum das nicht wie gewünscht funktionieren kann, sollte klar sein, wenn du dir den Ablauf in der Grafikpipeline ansiehst.

Dein Problem läßt sich lösen, indem du erst alle soliden Bauteile zeichnest und erst dann die transparenten, die dafür von hinten nach vorne sortiert. ZWrites kannst du dann auch ausschalten, wenn es an die transparenten Bauteile geht.

PS: Würfel haben gleiche Kantenlängen in allen Richtungen, was du meinst sind Quader.

Gast
2010-02-05, 11:46:27
Hi,

dein Problem läst sich ohne Weiteres nicht ohne Sortierung der Objekte
lösen, falls das Standard-Modell für Transparenz angenommen wird
(C_screen = C_object*alpha + C_background*(1-alpha)). Dieses Modell
ist leider nicht transitiv, d.h. die Reihenfolge der Zeichenoperationen
lässt sich nicht vertauschen.

Du kannst das Sotieren aber durch einen einfachen Trick vermeiden:
1. Zuerst werden alle soliden Objekte mit ZWrite=TRUE gezeichnet.
2. Dann werden alle transparenten Objekte mit ZWrite=FALSE
gezeichnet: Die Farbe der Objekte wird mit einem alpha multipliziert
und von der Hintergrundfarbe (inkl. sol. Objekte) subtrahiert
("transparente Objekte machen Bild dunkler")
3: Alle Transparenten Objekte werden erneut gezeichnet, diesmal
wird die Farbe allerdings mit einem beta multipliziert und zur
Hintergrundfarbe hinzuADDIERT!.

Diese Modell ist transitiv (wegen der Transitivität der Addition):
C_final = C_back - a1*C1 - a2*C2 + b1*C1 + b2*C2


Die Alpha's (kann mehrere geben) sorgen also für "Verdunklung",
die Beta's für "Erhellung". Entspricht zwar nicht dem Standardmodell,
lässt aber viele Spielereien zu. Und in der Praxis ist der Trick auch
nicht so leicht erkennbar.

Implementierung: Unter OpenGL als auch unter Dirtect3D läst sich
der Transparenzmodus manigfaltig verändern, manche einfachen
3D-Schnittstellen erlauben aber den obigen Trick nicht (leider).


Ich habe selber mal eine 3D-Hochhaus-App geschrieben, in der ich
einzelne Zimmer Solid und den Rest transparent dargestellt habe;
sah mehr als nur befriedigend gut aus.


Gruss

Jörg

thinzuaddiert
Problem mit

Elemental
2010-02-05, 11:49:04
Danke für die Erklärung.

Ich habe noch einen anderen Workaround für mich gefunden: Ich verwende für die ausgelassenen Bauteile jetzt kein DiffuseMaterial, sondern ein EmissiveMaterial.
So erscheinen die Quader auch durchsichtig, obwohl ich einen SolidColorBrush verwende und den Alpha-Wert nicht runtersetze.
Und da sind dann auch die Bauteile "hinter" den durchsichtigen sichtbar, unabhängig von der Reihenfolge :)

edit:
Z-Write kann man afaik bei WPF3D nicht konfigurieren.


http://www.windows-tech.info/11/c9060a4af6e77187.php

The z-buffer

When an alpha blended polygon is drawn, it writes its depth values into the z-buffer. Because of this, polygons rendered behind the alpha blended polygon will be occluded during the z-test during rendering, and there will be no resulting color contribution. Lower level 3D APIs (OpenGL and D3D) allow z-test and z-write to be disabled arbitrarily, though we chose not to expose that level of granular control in Avalon 3D for version 1.



These are problems inherent to all major 3D APIs. Typically with major 3D APIs, a scene is most optimally rendered in the following way:

1. All opaque polygons are rendered in close -> far order to get the maximum occlusion performance boost. (the order isn't critical here)
2. All transparent polygons are sorted and then rendered in far -> order (for proper alpha blending; order is critical)



To get around the issue in Avalon 3D, you can use emissive materials (rather than alpha blended diffuse materials). Emissive materials use a purely additive blend function, and addition is fully commutative. Also, we are disabling z-write for all materials with an additive blend function (emissive and specular). This means that they won't have to be sorted. This isn't in any public builds yet but should be eventually.

The one caveat is that the output doesn't look the same as it would with true alpha blending. Overlapping colors are simply added. It's vastly better than the alternative, however, and would work very well in the scenario you've described.

Neomi
2010-02-05, 12:21:44
edit:
Z-Write kann man afaik bei WPF3D nicht konfigurieren.

Ist auch nicht nötig, sondern optional für bessere Performance. Genau wie die Sortierung von vorne nach hinten bei den soliden Teilen. Bei dem Workload sollte das aber keine Rolle spielen.

Erst alle soliden Teile zeichnen, Reihenfolge egal. Dazu alle Teile durchgehen, die soliden direkt zeichnen und die transparenten in eine Liste stecken für später. Die Liste wird dann sortiert, um die Bauteile darin von hinten nach vorne zu zeichnen. Und schon hast du ein brauchbares Ergebnis, während die Variante mit dem Emissive-Material doch schon sehr unschön ist. Übrigens sparst du dir in der Variante nur die Sortierung innerhalb der unsoliden Teile, hinter die soliden Teile schieben mußt du die jetzt additiv gezeichneten aber trotzdem. Deine momentane Variante ist nach wie vor fehlerhaft.

Elemental
2010-02-05, 12:40:12
OK, erst die soliden Bauteile zeichnen ist kein Problem. Aber wie mach ich das mit der Sortierung der transparenten?

Da müsste ich ja irgendwie an die Z-Werte der Bauteile dran kommen, aber nicht die Z-Werte, wie ich sie beim setzten auf die Leiterplatte selber festlege, sondern nachdem die Transformationen um X-, Y- und Z-Achse ruchgeführt wurden. Ob das irgendwie funktioniert?

edit:
Also wenn man zuerst die soliden zeichnet und für die transparenten wieder ein DiffuseMaterial verwendet, dann sieht das ganze jetzt schon ganz gut aus.
Danke! :)

Neomi
2010-02-05, 15:28:34
Aber wie mach ich das mit der Sortierung der transparenten?

Deine aktuelle Variante sieht ja schon ganz ordentlich aus. Zumindest in dem gezeigten Bild, in dem sich allerdings keine transparenten Bauteile überlappen. Für den Fall könnte die Sortierung noch optisch was rausholen. Falls du diesen letzten Schliff noch machen willst...

Sortiert wird natürlich auf der CPU. Als Vergleichswert benötigst du pro Objekt wahlweise die Tiefe in Kamerarichtung oder die Entfernung (bzw. das Entfernungsquadrat, spart eine Wurzel pro Objekt) zur Kamera. Vom Objekt kannst du den Mittelpunkt heranziehen, etwas komplizierter evtl. den Eckpunkt oder noch aufwändiger sogar den Punkt der Oberfläche mit der geringsten Distanz. Da sich immer Sonderfälle konstruieren lassen, die jede vereinfachte Regel aushebeln oder eine "korrekte" Sortierung gleich ganz unmöglich machen, reicht eigentlich eine simple Variante. Meine Wahl wäre das Entfernungsquadrat zwischen Objektmittelpunkt und Kameraposition.