ich erzeuge mir eine Kugel mit gluSphere und lege eine sonnenartige Textur drauf. Funktioniert alles gut, aber die Kugel sieht wie ein Planet aus. Daher muss die Kugel zu einer Sonne gemacht werden. Ich denke hierfür sind Shader eigentlich ideal. Doch welche Algorithmen bräuchte ich denn überhaupt um so etwas zu schaffen ? Ich habe da mathematisch in meinem jungen Alter leider noch nicht viel Ahnung von. Habt ihr irgendwelche Vorschläge ? Ist etwas blöd, denn ob man das nun mit Shader oder ohne löst ist mir an sich egal, aber in irgendein Unterforum muss dieses Thema rein, je nach Themenentwicklung muss man halt mal schauen wohin mit dem Thema - denn die Lösung zählt.
_________________ Denn wer nur schweigt, weil er Konflikte scheut, der macht Sachen, die er hinterher bereut. Und das ist verkehrt, denn es ist nicht so schwer, jeden Tag zu tun als ob's der letzte wär’. Und du schaust mich an und fragst ob ich das kann. Und ich denk, ich werd' mich ändern irgendwann. _________________Farin Urlaub - Bewegungslos
Das habe ich mir heute schon zig mal durchgelesen. Die Lösung der Texturenverschiebung ist nicht mein Ziel in dieser Form. Es ist einfach immer noch zu leblos finde ich. Und beim Bloom scheitert es scheinbar doch etwas an meinen Fähigkeiten. Aber auch mit Bloom sähe der Stern ruhend aus, was er aber nicht ist. Man muss sich ach überlegen, dass die Sonne sich viel langsamer als der Rest dreht, man also die Bewegungen so gut wie gar nicht wahrnimmt. Daher wirken die Planeten besser als die Sonne, da sie sich relativ schnell drehen und um die Sonne rotieren.
Alle Lichtquellen der Szene (z.B. Sonne) normal rendern. Alle anderen Objekte schwarz rendern oder alternativ mit
Code:
gl.blendFunc(gl.CONSTANT_COLOR, gl.ZERO);
gl.blendColor(factor,factor,factor,1.0);
rendern. factor ist bei mir 0.8. In meinem Fall sorgt das dafür das die Planeten leicht glühen, aber nicht so stark wie die Sonne. Den Sky (bei mir Sterne) sollte man nicht rendern, wird sonst unscharf. In dem Fall muss die Clear-Farbe schwarz sein.
Framebuffer kopieren und als Bildschirmfüllendes Quad mit einem Blur-Shader (="Weichzeichner") rendern. Je stärker der Weicherzeichner desto stärker der Effekt. In meinem Fall wende ich diesen Shader 6-fach hintereinander an, das ist schneller als einmal bluren mit größerem Radius. Der Shader greift genau zwischen den Texeln auf die Textur zu und erhält so den Durchschnitt aus vier Texeln mit einem Zugriff.
Code:
varyingvec2 vTexCoord;
uniformsampler2D uScene;
uniformvec2 uPixelSize;// Größe eines Pixels in Texturkoordinaten
void main(){
vec2 shift[13];
shift[0]=vec2(-1.5,-3.5);
shift[1]=vec2(1.5,-3.5);
shift[2]=vec2(-3.5,-1.5);
shift[3]=vec2(-1.5,-1.5);
shift[4]=vec2(1.5,-1.5);
shift[5]=vec2(3.5,-1.5);
shift[6]=vec2(0.0,0.0);
shift[7]=vec2(-3.5,1.5);
shift[8]=vec2(-1.5,1.5);
shift[9]=vec2(1.5,1.5);
shift[10]=vec2(3.5,1.5);
shift[11]=vec2(-1.5,3.5);
shift[12]=vec2(1.5,3.5);
gl_FragColor=vec4(0,0,0,0);
for(int i=0; i<13; i++){
vec2 coord = vTexCoord +(shift[i]* uPixelSize);
gl_FragColor+=texture2D(uScene, coord);
}
gl_FragColor/=13.0;
gl_FragColor.a=1.0;
}
Framebuffer wieder kopieren und in einer Textur sichern.
Color- und Depth-Buffer clearen.
Szene normal rendern.
Den eben gesicherten Framebuffer mit
Code:
glBlendFunc(GL_ONE, GL_ONE);
auf die Szene addieren.
Alternativen:
Statt den Framebuffer mit glCopyTexSubImage2D zu kopieren kann man auch FrameBufferObjects (FBO) verwenden.
Wenn man FBOs verwendet, kann man statt dem bluren auch eine kleinere Auflösung als die der Szene wählen um einen Blur-Effekt zu erreichen.
Würde ein FBO ohne Shader auch so gut aussehen ? Es sieht wirklich toll aus, großes Lob an dieser Stelle von mir Aber ich sammel mal wirklich meine Fragen, ich überlege schon lange und kriege einfach vieles nicht geklärt: Punkt 1 ist relativ klar denke ich, glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); und fertig. Genügt es für Punkt 2 nicht sogar schon, die Texturen wegzulassen ? Oder wäre das dann ein anderes "schwarz" ? Ich denke andauernd, so müsste es sein, mit dem Blenden:
Code:
// Sonne
glPushMatrix;
...
glPopMatrix;
glBlendFunc(GL_CONSTANT_COLOR, GL_ZERO);
glBlendColor(0.8,0.8,0.8,1.0);
// Merkur
glPushMatrix;
...
glPopMatrix;
Aber eigentlich ist das doch totaler Irsinn. Es ist so grauenhaft, ich wusste das mal, aber habe wohl vieles wieder verlernt. Ich verstehe auch Deine Idee, aber kann es einfach nicht umsetzen. Außerdem meckert der Compiler seltsamerweise rum, er kenne GL_CONSTANT_COLOR nicht. Naja, laut dem Wiki existiert die Konstante aber. Im nächsten Schritt würde man also die Sonne zeichnen aber mehrfach den Shader drüberjagen ? Der Rest ist dann aber klar, geht auch aus der Grundidee schon hervor. Also verstanden habe ich es schon, aber bin echt zu blöd das umzusetzen - fordere aber auf keinen Fall eine Komplettlösung, falls das so rüberkommt - gerade um wieder reinzukommen sollte ich das alles selbst schreiben, nur ein paar Hinweise wären ganz gut.
Punkt 1 ist relativ klar denke ich, glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
Vom Prinzip ja, aber sofern du den Stencil-Buffer nicht verwendest, solltest du diesen ebenfalls leeren. Der Tiefenbuffer teilt sich ja mit dem Stencilbuffer immer ein Byte. Bringt aber so wenig das du den Performance-Unterschied wahrscheinlich nicht bemerken wirst
Zitat:
Oder wäre das dann ein anderes "schwarz" ?
Wie du das schwarz machst ist egal. Reichen würde ein Shader mit gl_FragColor = vec4(0,0,0,1). Ich empfehle dir aber die glBlendColor-Variante zu nehmen, wie du in deinem gezeigten Code auch schon korrekt machst. Das gibt auch den Planeten ein besseres aussehen und ist sogar noch leichter zu implementieren, weil du ja einfach normal renderst, nur eben etwas dunkler.
Zitat:
Außerdem meckert der Compiler seltsamerweise rum, er kenne GL_CONSTANT_COLOR nicht.
Laut Wiki gibt es GL_CONSTANT_COLOR "erst" seit OpenGL 1.4.
Zitat:
Im nächsten Schritt würde man also die Sonne zeichnen aber mehrfach den Shader drüberjagen ?
Du renderst die Szene insgesamt zweimal. Zuerst produzierst du eine Textur in der nur die Lichtquellen sichtbar sind. Alles andere wird schwarz (oder dunkler, siehe oben) gerendert, damit verdeckte Lichtquellen auch korrekt verdeckt werden. Diese Textur wird dann durch einen Weichzeichner gejagt. Du renderst also ein Quad mit dieser Textur und dem Weichzeichner-Shader und jagst das Ergebnis wieder durch. Das ganze ein paar mal bis du das Ergebnis weich genug findest. Dann wird die Szene nochmal ganz normal gerendert und die Ergebnis-Textur wird auf die Szene addiert. Dafür renderst du wieder ein Quad.
Zitat:
Würde ein FBO ohne Shader auch so gut aussehen ?
Wenn das FBO eine kleinere Auflösung als die Szene hat muss die Textur ja später beim rendern vergrößert werden. Wenn du sagen wir 1/4 oder 1/8 der Szenenauflösung verwendest, erreichst du bereits eine gewisse Unschärfe. Wie gut das aussieht kann ich nicht sagen, es könnten aber Artefakte auftreten. Also man könnte die einzelnen Pixel sehen. Diesen Artefakten könnte man aber wieder durch einen Weichzeichner-Shader entgegen wirken. Da Füllrate bei diesem Effekt die wesentliche Limitierung ist dürfte eine kleinere Textur einen großen Performance-Schub bringen. Wenn die Textur 1/4 kleiner ist, bedeutet das 1/16 der Texturzugriffe und zudem weniger Durchgänge beim Weichzeichner. Vermutlich ist das also die beste Lösung. Ich konnte das bei meinen UC aber bisher nicht einbauen, da Firefox/Minefield bisher keine FBOs unterstützt.
Ich habe keine Ahnung was SDLSurfaces sind, aber wahrscheinlich kann man die benutzen. Trotzdem, wenn du FBOs hast, solltest du die benutzen. Ich bezweifele auch, dass ich im Browser an SDL komme
Habe mich für FBO entschieden, wenn das so viel schneller ist, lohnt es sich bestimmt. Ich habe einfach mal versucht die Idee umzusetzen. Da ich mit FBOs bisher noch nichts zu tun hatte, musste ich mich erstmal damit auseinandersetzen. Dabei ist folgendes rausgekommen. Nun entsteht insgesamt ein graues Dreieck welches hinter den Planeten/der Sonne liegt. So erfolgreich sieht es noch nicht aus, aber immerhin sieht man überhaupt mal eine Veränderung. Was ich mich auch die ganze Zeit schon frage: Wo muss nun das Glowergebnis skaliert werden ? Im FBO, bei der Textur ? Wenn im FBO, wäre dann die Stelle mit der Setzung des Viewports in der Render (Zeile 60) die richtige ? (Hat bisher nichts gebracht wenn man dort den Viewport vergrößert.) Ich denke mal da sind noch einige Fehler drinnen die ich nicht sehe.
Hm, habe Z nun abgestellt, weiterhin ein graues Dreieck. Den Weichzeichner bau ich möglichst erst später ein, will lieber erstmal dass alles mit dem FBO klappt. Habe den letzten Codeteil einfach erweitert:
Und was das Clearen betrifft: Ich habe das in die Prozedur Zeichne ausgelagert, welcher für FBO und normal insgesamt zweimal ausgeführt wird (Siehe Code oben).
Code:
procedure TSolar.Zeichne;
...
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
Eine Idee, warum ich immer noch ein graues Dreieck zeichne ? Im Anhang mal ein einfacher Screenshot. Das Grau ist eventuell auf den ersten Blick nicht zu sehen, hängt auch vom Monitor etwas ab. Bei einem guten sieht man es sofort, bei einem älteren vielleicht nicht so gut. (Hatte schon den Fall, dass ein sehr helles, strahlendes Hintergrundbild von mir woanders total abgedunkelt und leblos dargestellt wurde.) Jedenfalls ist der untere Punkt des Dreiecks direkt unter der Sonne. Habe außerdem einiges weggeschnitten, damit die Datei nicht zu groß wird.
Der Shader im Wiki scheint wohl vollkommen an mir vorbeigegangen zu sein. Habe mich natürlich schon vor dem Erstellen dieses Themas umgeschaut, aber den nicht gefunden. Sehr interessant. Werde den dann auf alle Fälle testen, aber ich denke es ist einfacher im Endeffekt, erstmal die aktuell noch bestehenden Probleme zu beseitigen.
Wahrscheinlich renderst du das Quad falsch: Setze die Z-Koordinate mal auf 0, nicht auf -1. In DrawTexture wird die Z-Koordinate negiert, Absicht? Wenn ich das richtig im Kopf habe geht der sichtbare Bereich von 0 bis 1, nicht von -1 bis 1. Bin mir aber gerade nicht sicher.
Es ist nicht ganz ersichtlich wie deine ModelView und Projectionmatrix aussieht. Du kannst aber beides auf "Identity" setzen und diese Koordinaten verwenden:
Code:
glVertex3f(-1.0, 1.0, 0.0);
glVertex3f(-1.0, -1.0, 0.0);
glVertex3f( 1.0, 1.0, 0.0);
glVertex3f( 1.0, -1.0, 0.0);
Zitat:
Der Shader im Wiki scheint wohl vollkommen an mir vorbeigegangen zu sein.
Den hat Skeptiker auch erst gestern Abend eingestellt.
Ich habe die Modelmatrix und Projektionsmatrix, wenn ich es richtig sehe, schon bei der Initialisierung auf Identity gesetzt. Habe Deinen Code mal getestet, man sieht deutlich einen Unterschied. Nun sieht man ein Quadrat welches die Sonne umfasst und durch diese hindurchgeht. Habe dann auch gleich mal den Shader soweit getestet. Allerdings kann man leider immer noch keinen wirklichen Effekt sehen. Das Quadrat ist mit und ohne Shader einfach grau gefärbt. Hier mal der aktuelle entscheidende Renderausschnit:
Code:
// FBO befüllen
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
glPushAttrib(GL_VIEWPORT_BIT);
glViewPort(0,0, SCREEN_WIDTH, SCREEN_HEIGHT);
glUseProgramObjectARB(Shader);
Zeichne;
glUseProgramObjectARB(0);
// Normal rendern
glPopAttrib;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
Zeichne;
// FBO-Textur additiv blenden
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glBindTexture(GL_TEXTURE_2D, FBOTex);
glBegin(GL_QUADS);
glTexCoord2f(1,0);
glVertex3f(-1.0,1.0,0.0);
glTexCoord2f(0,0);
glVertex3f(-1.0,-1.0,0.0);
glTexCoord2f(0,1);
glVertex3f(1.0,1.0,0.0);
glTexCoord2f(1,1);
glVertex3f(1.0,-1.0,0.0);
glEnd;
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
Meine Shaderladeroutine entspricht fast exakt dieser. Der wohl einzige Unterschied besteht in der Variablenverwaltung, bei mir muss man das ProgramObject selbst erstellen und als Variable übergeben. Aber ansonsten identisch. Hier mal das aktuelle Ergebnis, diesmal extrem beschnitten, ich will nicht mit jedem Beitrag so extrem viel Platz verschwenden. Auf dem Bild ist der Shader nach dem eben geposteten Code an. Habe das Gefühl, im FBO würde alles anders gerendert als beabsichtigt.
Der Fragementshader wird ja einmal pro Pixel ausgeführt, dürfte es daher nicht schneller sein, zwei seperate Shader für Horizontal und Vertikal zu verwenden, weil ja IFs auf Uniforms angeblich so langsam sind. Gerade, wenn texWidth + Hight der Bildschirmauflösung entspricht. Wäre es nicht auch theoretisch perfomanter die for-Schleife abzuwickeln?
Mitglieder in diesem Forum: 0 Mitglieder und 4 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.