ich hab ein kleines problem mit dem Stencil Buffer.. dabei geht es aber nicht unbedingt um probleme mit den befehlen, sondern um eine Idee wie ich ein gewünschtes ergebnis erreiche.
Ich hab im Attachment ein Bild angehängt was das ganze etwas verdeutlichen soll. Die Schraffierten, rot umrandeten flächen im Bild sind Quads die ich in den StencilBuffer zeichne, in der reihenfolge 1, 2, 3 und dann das 4te.
Dateianhang:
stencil.png
Wenn ich das tue habe ich logischerweise am ende einen komplett weißen StencilBuffer, denn schon bei dem Quad von '1.' wird der komplette Bildschirm ausgefüllt.
Was ich aber gerne hätte ist ein ergebnis wie im Bild unter 'Result'.. sprich es soll von allen vorherigen Quads immer das kleinste den Stencil Bilden..
Im grunde müsste ich den Stencil komplett auf 0 leeren vor jedem Quad, aber dann das neue Quad nur da zeichnen wo der Stencil vor dem leeren 1 war - oder anders gesagt: Ich möchte nur dort in den StencilBuffer zeichnen wo er 1 ist, aber dannach alles wo ich nichts gezeichnet habe automatisch auf 0 setzen
Bei simplen Rechtecken könnte ich natürlich einfach 4 Rechtecke zeichnen welche den Stencil rings um mein Quad auf 0 setzen, aber bei mir geht es um recht komplexe Polygon Formen..
Hat irgendjemand eine Idee?
Aya~
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Was ich aber gerne hätte ist ein ergebnis wie im Bild unter 'Result'.. sprich es soll von allen vorherigen Quads immer das kleinste den Stencil Bilden..
Was verstehst du unter dem "kleinsten"? Bezüglich Fläche oder Umfang? In dem Fall würde dir der Stencilbuffer wahrscheinlich nicht weiter helfen. Die Fläche könnte man aber z.B. durch die Anzahl der Pixel approximieren. Die Anzahl der gerenderten Pixel kann man mit einem Occlusion Query zählen.
Mit dem Stencilbuffer wäre z.B. die Schnittmenge aller Polygone möglich. Also die Pixel die von allen Polygonen angefasst werden. Das geht ganz einfach: Der Stencilbuffer kann nicht nur 0 und 1, sondern der kann zählen (*). Mit jedem Polygon inkrementierst du den Stencilbuffer, am Ende zeichnest du alle Pixel bei denen der Wert im Stencil gleich der Anzahl der Polygone ist.
(*) auf modernen Grafikkarten üblicherweise von -128 bis 127. Ältere Karten können ggf. einen kleineren Bereich oder keine negativen Zahlen.
Die kenn ich.. hatte ich früher auch mal implementiert Aber das ist so lange schonwieder her, das mir das mit dem Incremental kram absolut nichmehr geläufig war ^^
Gibt es mittlerweile eigentlich schönere Methoden um die Geometrie des StencilSchattens zu berechnen? So vonwegen GeometryShader oder so..? Hab das damals recht schnell wieder verworfen gehabt, weil es mir einfach viel zu viel aufwand war diese Silhouetten-Geometry ständig zu berechnen etc..
Gibt es mittlerweile eigentlich schönere Methoden um die Geometrie des StencilSchattens zu berechnen?
Also das gängige Verfahren braucht nur den Vertexshader. Jede Kante wird aufgespalten und es werden zwei degenerierte Dreiecke eingefügt. Die beiden roten Kanten befinden sich also eigentlich übereinander. Wichtig: Die Vertices müssen aber wirklich mehrfach vorhanden sein, also nicht einfach via Indexbuffer machen!
Dateianhang:
stencil-shadow.png
Jeder Vertex erhält zudem die Normale des zugehörigen Dreiecks im Original-Mesh, also Face-Normalen statt Vertex-Normalen, aber pro Vertex gespeichert. Dadurch kannst du im Vertexshader für jeden Vertex entscheiden ob er nach hinten geschoben werden soll oder nicht. Da Stencil-Shadows sowieso sehr Füllratenlastig sind, fällt die Verarbeitung der zusätzlichen Dreiecke nicht ins Gewicht. Degenerierte Dreiecke werden von der Grafikkarte erkannt und nicht gezeichnet.
Mit dem Geometrieshader ist es möglich die notwendigen Dreiecke live zu erzeugen. Dafür werden aber Adjazenzinformationen benötigt, also zumindest ein spezieller Indexbuffer. Also 6 Vertices pro Dreieck die man dann im Geoemetryshader auch alle gleichzeitig angucken kann:
Dateianhang:
stencil-shadow2.png
Man überprüft also für jedes der 4 Dreiecke ob es Front- oder Backfacing ist. Wenn sich ein adjazentes Dreieck vom mittleren Dreieck unterscheidet wird ein Dreieck an der entsprechenden Kante eingefügt. Das zweite Dreieck wird generiert, wenn das entsprechende Nachbardreieck verarbeitet wird. Man muss sich natürlich eine Konvention ausdenken damit sich alles nahtlos zusammenfügt.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
So, jetzt müßte rein theoretisch doch der StencilBuffer links oben den wert 1 haben, und rechts daneben den wert 2. Denn das erste Quad erhöht den Stencil wert im Bereich von (0, 0, 100, 100) um 1 auf 1, und das zweite dann im bereich von (0, 0, 200, 100) wiederrum um 1.. die linken 100px dann von 1 auf 2, und die rechten 100px von 0 auf 1 - richtig?
scheint es so als würde der Stencil Buffer komplett ignoriert werden... es wird nicht nur dort gezeichnet wo der wert 2 im StencilBuffer steht, sondern überall.
Test wird bestanden wenn ( ref & mask) = ( stencil & mask).
Vielleicht solltest du mask lieber auf 255 statt auf 2 setzen. Die Maske wird bitweise UND verknüpft. Im Augenblick dürfte er eigentlich nur dort rendern wo der Stencil 0 ist, da 1 & 2 nun mal 0 ist.
Edit: Eine mögliche Fehlerquelle wäre der Z-Buffer. Ist es richtig das du diesen nicht löscht?
Was genau macht denn das GL_INCR..? Dachte das sei so vonwegen nach dem ersten Zeichenn ist der StencilWert 1, dann 2.. 3, 4.. etc.. wohl nicht?
Bzw wie sag ich ihm dann das er NUR da zeichnen soll, wo vorher 2 Quads im stencil gezeichnet wurden?
@DepthTest: Der ist die ganze zeit sowieso deaktiviert, sorry.. hab ich im beispiel nich mit angegeben.
EDIT: Aaahh! ich habe "mask" und "ref" vertauscht.. Ganz klappen tut es zwar noch nicht, aber das kann jetzt grad auch daran liegen das ich zum fehler finden soviel umgebastelt habe
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_EQUAL, 2, 0xFFFFFFFF); // 'ref' und 'mask' waren vertauscht // Wenn ich als 'ref' 0 angebe, wird alles gezeichnet ausser links oben die fläche beider Rechtecke. // Wenn ich als 'ref' 1 angebe, wird nur die linke oberer fläche beider Rechtecke gezeichnet // Wenn ich als 'ref' 2 angebe, wird garnichts gezeichnet...
// Irgendwas zeichnen...
glDisable(GL_STENCIL_TEST);
Hab im Code unten ein paar kommentare hingeschrieben. Kann es evtl sein das mein Wert im Stencil beim GL_INCR bei 1 geclampt ist?
Mitglieder in diesem Forum: 0 Mitglieder und 9 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.