also mein Problem ist folgendes: Ich zeichne mehrere farbige flächen (keine Texturen, sondern farbige quads) übereinander. Diese werden additiv geblendet also gl_one, gl_one.
Das klappt auch ohne Probleme. Doch nun wäre es schön wenn ich "hinter" diese Flächen einen Hintergrund zeichne, den man nur durch die scharzen Stellen von dem obrigen gennanten sieht.
Also eine kleine Tabelle, wie es sein soll:
Hintergrund | Flächen (alle zusammen) | --> gesamt
-----------------------------
X (steht für Farbe) | schwarz --> X
X | rot --> rot
X | blau --> blau
X | grün --> grün
X | weiß --> weiß
Zurzeit mache ich es so, dass ich die farbigen Flächen vor einem Schwarzen hintergrund mit gl_one, gl_one blende.
Ich kann anscheinend nicht vorher den "Hintergrund" (der druchscheinen soll) zeichnen, da ich ja nicht die farbigen Flächen additiv mit dem "Hintergrund" verrechnen will.
Und wie ich es hinbekomme, dass er nachher zeichnet und halt nur die schwarzen stellen überschreibt und sonst alles unberührt lässt, habe ich noch nicht herausgefunden.
Habt ihr eine Lösung?
Gruß Alexander
PS: Falls es wichtig ist: Ich zeichne 2d und verwende den TiefenTest.
_________________ "Weil", so schließt er messerscharf,
"nicht sein kann, was nicht sein darf."
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Na ja. Du hast einen kleinen Denkfehler in deiner Logik. Wenn du sagst, dass du die Farben addieren willst, dann trifft das für alle Farben zu und nicht nur für Schwarz. Bei GL_ONE, GL_ONE, werden die Farbwerte addiert. Schwarz + Schwarz bleibt logischerweise dann schwarz. Aber Rot und blauer Grund ergeben Violett.
Das Sinnvollste und Einfachste so etwas zu lösen ist über den Alphakanal in der Textur. Dazu müsstest du erst einmal durch die Pixel der Textur gehen und dann alle Pixel die schwarz sind entsprechend im Alphakanal mit 0 oder falls nicht, dann mit 255 setzen. Ideal wäre es, wenn dein Texturenloader so etwas direkt könnte. Welchen Loader benutzt du denn dafür? Bzw kannst du das auch in deinen Bildern verankern. Also direkt in einem Grafikprogramm. Das geht auch.
Alternativ ginge so etwas natürlich auch mit Shadern aber das wäre ein bisschen wie wenn man mit Spatzen auf Kanonen schießen würde.
ehmmm ich glaube ich habe keinen Fehler. Vielleicht habe ich es aber auch nicht ganz so klar ausgedrückt. (alles farbige Quad-Strips)
ich habe (sagen wir mal 5) " farbige flächen" und diese sollen per additivier farbmischung gemischt werden. (d.h. gl_one, gl_one)
Das klappt ja auch.
Doch nun möchte ich die Flächen die schwarz in diesem gesamtbild sind, durch (die farben) einer weiteren Quad-strip fläche ersetzten.
Ich könnte es natürlich so machen, dass ich die Flächen die schwarz in diesem gesamtbild sind mit alpha =0 belege und dann die "Hintergrundfläche" einfach dahinter setzten und mit gl_one_minus_dst_alpha , gl_one blende.
EDIT: Wenn ich darüber nachdenke ist es doch nicht soo aufwendig....
Doch meine Frage ist: gibt es noch einen einfacheren weg, die schwarzen flächen zu überschreiben? (dann kann ich mir überall die alpha werte sparen)
_________________ "Weil", so schließt er messerscharf,
"nicht sein kann, was nicht sein darf."
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Warum zeichnest du die schwarzen Flächen denn dann überhaupt?
Ich würde das auf jeden fall so lösen:
Erstmal wird ja der Framebuffer geleert, der sollte schwarz sein.
Dann aktiviere ich den Alphatest und dazu die glAlphaFunc(GL_EQUAL, 0.0);, sodass alles, was Alpha 0.0 garnicht erst gezeichnet wird (ergo auch nicht im Tiefenpuffer landet).
Danach alle Quads zeichnen und nur die schwarzen Quads erhalten ein Alpha von 0.0, sodass die übergangen werden.
Nach dem Zeichnen den Alphatest wieder deaktivieren.
Dann kannst du ganz normal den Hintergrund hinter deine Quads zeichnen. Weil die schwarzen Quads den Tiefenpuffer nicht beeinflusst haben, besteht der Hintergrund da den Tiefentest und wird gezeichnet.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
hmmm habe ich das richtig verstanden?
-den alpha wert in die farbe einbetten (abhängig von der Intensität der Farbe)
- durch den alpha test (kannte ich noch nicht) die Quads mit Alpha=0 nicht zeichnen lassen (würde man doch eh nicht sehen (mit blending).. oder ist das wegen der geschwindigkeit?)
- den hintergrund dahinter zeichnen
fertig...
hmm ok ich möchte natürlich auch einen übergang zwischen schwarz und nicht schwarz haben... klappt das mit dem alpha test?
ok so hatte ich mir das (allerdings ohne alpha test) auch gedacht...
komme ich wohl nicht drumherum....
Danke für eure Hilfe
Gruß Alexander
_________________ "Weil", so schließt er messerscharf,
"nicht sein kann, was nicht sein darf."
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Ah... von dem Übergang hast du nichts gesagt, den bekommst du mit dem Alphatest nicht hin, der kennt nur "geht" oder "geht nicht" (wie auch die anderen Tests, wie Scissortest, Tiefentest und Stenciltest).
Hmm... Für den Übergang... Genau, das könnte klappen:
Du machst es genauso wie ich es beschrieben habe, nur ohne Alphatest. Die schwarzen Vertices erhalten ein Alpha von 0 und die anderen ein Alpha von 1. Dann blendest du das weiterhin additiv. Danach zeichnest du den Hintergrund darüber, und zwar mit glBlendFunc(GL_ONE_MINUST_DST_ALPHA, GL_DST_ALPHA);. Das sollte dafür sorgen, dass es so aussieht, als ob du den vorher dahintergezeichnet hast, nur halt mit "normalem" anstatt additivem Blending.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
jetzt ergibt sich dass problem, dass anscheinend nach glLoadIdentity; der schwarze Hintergrund anscheinend den Alpha Wert 1 hat.
Wenn ich nun die farbigen Quads mit glone, glone drüber blende, haben diese auch den Alpha Wert 1 und ich kann somit nicht mehr den hintergrund "dahinterzeichnen"....
Wie bekomme ich es hin, dass bei glLoadIdentity; der gesamte leere Raum dahinter den Alpha Wert 0 hat?
Oder hat das schwarze nichts bei glLoadIdentity immer Alpha=0?
EDIT: ahhh ich habe glClearColor gefunden.. kannte ich noch nicht.... probiere es aus...
EDIT2: hmmm neee das ist es doch nicht.... seltsam... ich muss noch ausprobieren.....
_________________ "Weil", so schließt er messerscharf,
"nicht sein kann, was nicht sein darf."
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
glLoadIdentity hat nichts mit Farbe zu tun. Es dient dazu um die aktuelle Matrix eines der 3 Matrixstacks auf eine Initialmatrix zu setzen. Die Treiber können intern natürlich noch irgendwelche "Dinge" tun aber wenn die bei glLoadIdentity irgendwas an der Farbe drehen gehört denen der Computer weggenommen. Sollte mich als ziemlich wundern.
Zu deinem Problem. DST_ALPHA ist meiner Meinung nach nicht unbedingt ungefährlich. Denn DST_ALPHA ist der Alphakanal des Framebuffers. Der wird aber in vielen Fällen von Hause aus gar nicht erstellt. Ich meine NVidia lässt den selbst unter 32 Bit Farbtiefe weg außer man hat ihn explizit angegeben was bei der dglOpenGL aber nicht der Fall/möglich ist. Und bei Farbtiefen unter 32 Bit muss man ihn immer angeben. Aber selbst wenn es angegeben ist muss man auch überprüfen ob der Treiber tatsächlich ein entsprechendes Format gewählt hat. Diese Auswahl mit Farbtiefe und Tiefenbuffer beim Erstellen des RCs sind nur Richtwerte. Was der Treiber macht kann man überprüfen aber es liegt vollends in dessen Hand. Wie das bei älteren oder nicht ganz so toll unterstützten Grafikkarten aussieht ist aber auch wieder eine andere Sache.
Ich muss aber gestehen mir fehlt gerade ein bisschen die nötige Vorstellungskraft um deinem Problem richtig folgen zu können. Könntest du evtl. mal ein Bild anhängen.
ehmmm ich habe natürlich
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
gemeint... sorry
hmmmm... ok ich erkläre das Problem mal so gut es geht. Wie schon oben gesagt habe ich mehrere (hier 2) QuadStrip Flächen die mit additiven blandig übereinander gelegt werden (Bild1). (Die schwarzen flächen haben den alpha wert 0)
Dann möchte ich "davor" noch ein farbigen Quadstrip (Bild2) legen, dass nur bei alpha=0 Flächen erscheinen soll. Also mit alpha blending...
Das ist mir theoretisch alles klar, doch leider scheint es so zu sein, dass die alpha werte von den überlagerten Flächen (Bild1) nicht gespeichert werden.... sehr seltsam.....
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
glClear klingt logischer. Aber glClear(GL_COLOR_BUFFER_BIT) löscht den RGB(A) Anteil des Framebuffers. Bzw. die Werte werden mit denen aus glClearColor überschrieben. Wobei die bei glClearColor aber auf 0-1 normiert sind.
Warum du nur das Bild 1 siehst. Entweder hast du Probleme mit dem Alphakanal des Framebuffers. Oder aber dein Aufruf von Box.OglColor setzt keinen Alphawert. Denn ich habe bei der Funktion 3 Paramater gezählt.
Mit meiner Frage nach Bildern etc habe ich aber gemeinerweise eigentlich auf etwas anderes abgesehen gehabt. Und zwar wollte ich nicht das aktuelle Problem verstehen sondern verstehen was du eigentlich genau vor hast. Denn oftmals gibt es bei OpenGL nicht nur einen Weg wie man etwas lösen kann. Oder manchmal ist ein anderer Weg viel einfacher. Mal sehen ob ich verstanden habe was du machen willst? Du hast 2 Wertebereiche bei denen du die Intensität mittels einer Farbe (rot oder blau) darstellst. Und diese Beiden sollen zur gleichen Zeit dargestellt werden. Aktuell hast du das gelöst indem du jeweils 1 QuadStrip von einer zur anderen Seite zeichnest. Der Punkteabstand dürfte vermutlich bei 1 Pixel liegen. Da QuadStrips aber normal nicht undurchsichtig sind müsst du sie addaptiv Blenden da sonst der Letzte immer alles überschreiben würde. Das sehe ich doch richtig, oder?
Wie wäre es mit einem anderen pragmatischeren Ansatz? Ich weiß allerdings nicht wie viele verschiedene Wertegruppen du da gleichzeitig darstellen möchtest? Aber bereits bei zweien hast du das Problem, dass du die Farben auf der Leinwand mischen musst. Und wie du siehst bringt das durchaus Probleme mit sich. Für OpenGL ist es gleich ob es nun für dich Hintergrund oder Vordergrund ist. Ich würde dir da besser empfehlen die Farben vorher zu mischen und dann nur eine resultierende Farbe aufzutragen.
Also das du beim Zeichnen der Wertegruppen diese selber innerhalb deines Programmes addierst und die resultierende Farbe dann einfach zum Zeichnen benutzt. Dann hast du nur noch eine Ebene und kannst so zeichnen wie es für OpenGL typisch ist. Erst Hintergrund und der Vordergrund wird normal drüber geblendet. Dann hast du auch keine Notwendigkeit auf einen Alphakanal im Framebuffer was unter anderem einiges an Speicher sparrt und die Kompatibilität erhöht.
Wenn du das Ganze dann noch mit einer 1D Textur kombinierst kommst du mit lediglich 2-3 Quads aus. Wie ich das aber genau meine erzähle ich dir wenn du daran interesse haben solltest.
- ich will bis maximal 255 dieser Quadstrip Lagen übereinanderlegen... ber meistens so 1-10....
Und ich MUSS das opengl Blending (additiv) benutzen, da ich mein Programm demnächst (wenn ich alle bisherigen probleme gelöst habe) um etwas erweitern will, was das ganze zu einem wirklichen 2D Quadstrip macht, was dann nicht mehr eigentlich 1 D ist.
Deshalb kann ich es nicht programmintern addieren.... 1d wäre das ja noch möglich.....
Zitat:
Entweder hast du Probleme mit dem Alphakanal des Framebuffers
hmmm wie meinst du das?
_________________ "Weil", so schließt er messerscharf,
"nicht sein kann, was nicht sein darf."
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Zitat:
Zitat:
Entweder hast du Probleme mit dem Alphakanal des Framebuffers
hmmm wie meinst du das?
Ich will damit sagen, dass es sein kann, dass dein Framebuffer gar keinen Alphakanal hat. Der aber zum Auslesen zwangsweise benötigt wird. So wie ich das in meinen Beiträgen weiter oben schon beschrieben habe. Die Treiber müssen den Alpha nicht automatisch erstellen. Und selbst wenn er angegeben ist müssen sie ihn nicht erstellen.
Zukunftspläne. Ich sage es ja nur ungern. Aber ich wage zu bezweifeln, dass das so klappt wie du dir das gerade denkst. Denn dann kann die Anzahl der Polygone zu einem großen Problem werden. Nur mal als Beispiel. Eine Fläche die 512x512 groß ist. Was schon nicht übermäßig groß ist. Dafür bräuchtest du rund 260.000 Vierecke was 520.000 Dreiecken entspricht. Dann rechne das ganze mal 10 bzw. mal 100. Bei 100 kommst du in Größenordnungen wo nicht ganz aktuelle Systeme mit aktuellen techniken schon mal 1 Sekunde am Zeichnen sind. Und das müsste so bei jedem OnPaint des Fensters durchgeführt werden.
Alternativ kannst du auch so etwas wie ein FrameBufferObjekt oder PixelBuffer benutzen. Bei diesen kannst du dann auch problemlos einen Alphakanal mit erstellen lassen und es als Textur benutzen. Diese Textur müsstest du nicht bei jedem OnPaint des Fensters neu zeichnen. Und du könntest sie ganz normal auf deinen Hintergrund blenden. Ist in etwa auch gleich zu dem als wie es intern berechnet würde. Nur das intern dann ein Zwischenschritt in OpenGL wäre.
Alternativ um deine Polygonanzahl zu senken kannst auch eine einzelne Fläche mit einer Alphatextur benutzen. Die Fläche zeichnest du mit deiner Farbe und in einem 2D ByteArray hast du Werte von 0-255 eingetragen die die Sichtbarkeit der Stelle regulieren. Das was du jetzt über einzelne Vertices geregelt hast wären dann Bytes in dem 1D/2D Array. Diese Flächen könntest du dann Addaptiv in dein FBO oder PixelBuffer zeichnen.
Ich will auf keinen Fall deine Motivation bremsen! Nur ich denke aktuell ist es einfacher an der Zeichnerei etwas zu verändern als wie wenn du das schon ewig anders machst. Und ich denke, dass du da später auf jeden Fall Probleme bekommen würdest. Und sei es nur, dass es langsamer ist als es sein müsste.
hmmm du hast natürlich Recht.....
hmm das tutorial zu Framebufferobject ist doch weit über meinem derzeitigen Wissensstand.... da habe ich ja was vor mir....
und PixelBuffer ist anscheinend ja nicht plattformunabhängig, was ich ja mit lazarus und opengl gerade erreichen möchte....
Wie kann ich erstmal den Alpha Kanal erstellen lassen? Oder nachprüfen ob er da ist?
_________________ "Weil", so schließt er messerscharf,
"nicht sein kann, was nicht sein darf."
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Zu PixelBuffer gibt es wohl auch etwas ähnliches für Linux. Aber das wurde bisher noch nicht im Header eingepflegt entsprechend kannst du raten wie oft es bisher benutzt wurde.
Aber stimmt du benutzt ja Lazarus für dein Projekt. Da schau mal in die Datei glwin32wglcontext.pas in die Methode LOpenGLCreateContext. Dort wird ChoosePixelFormat aufgerufen. Der pfd deran ChoosePixelFormat übergeben wird hat auch ein Feld was AlphaSize oder so heißt. Dort solltest du eine 8 eintragen. Zum Überprüfen musst du nach ChoosePixelFormat die Methode DescribePixelFormat aufrufen. Als Parameter musst du das PixelFormat und einen pfd angeben. Wenn die Methode zurück kommt stehen im pfd die Formateigenschaften des Formates.
Für Linux müsstest du entsprechendes in der Datei glgtkglxcontext.pas machen. Nur, dass du da nicht ChoosePixelFormat und DescribePixelFormat benutzen kannst, da diese zur WindowsAPI gehören. Was dann dort benutzt werden muss kann ich dir aber nicht sagen.
FBOs sind Platformunabhängig aber leider auch recht neu was die Unterstützung auf älterer Hardware wohl nicht begünstigen wird.
Mitglieder in diesem Forum: 0 Mitglieder und 2 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.