Motion-Blur: Unterschied zwischen den Versionen
(Realisierung in OpenGL und Beispielcode) |
K (→Ein leuchtender Punkt) |
||
(2 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
− | Motion Blur ist üblicherweise kein Effekt den man macht weil er schön ist, sondern ein Effekt der bei der Übertragung von digitalen Bildern zum menschlichen Auge eine Art Vermittlungsrolle spielt. | + | Motion Blur ist üblicherweise kein Effekt, den man macht weil er schön ist, sondern ein Effekt, der bei der Übertragung von digitalen Bildern zum menschlichen Auge eine Art Vermittlungsrolle spielt. |
== Biologische Grundlagen == | == Biologische Grundlagen == | ||
− | Das menschliche Auge nimmt etwa 25 Bilder je Sekunde wahr. Im Unterschied zur Computergrafik sind dies jedoch keine Momentaufnahmen sondern eine Art Aufsummierung aller Lichtreize die während dieser 1/25 Sekunde entstanden sind. | + | {{Hinweis|Mehr zu den biologischen Grundlagen und warum Motion-Blur trotzdem nicht die endgültige Lösung ist (und sogar zum Problem werden kann), erfahrt ihr im Artikel [[Framerate]].}} |
+ | Das menschliche Auge nimmt etwa 25 Bilder je Sekunde wahr. Im Unterschied zur Computergrafik sind dies jedoch keine Momentaufnahmen sondern eine Art Aufsummierung aller Lichtreize, die während dieser 1/25 Sekunde entstanden sind. | ||
=== Ein leuchtender Punkt === | === Ein leuchtender Punkt === | ||
− | Nehmen wir als Beispiel einen schwarzen Hintergrund. Über diesen schwarzen Hintergrund wandert (verhältnismäßig schnell) ein Licht. In der Computergrafik wenn wir beispielsweise 60 Frames pro Sekunde darstellen können würden wir 60 Momentaufnahmen darstellen, wobei in diesen Momentaufnahmen die Bewegung des Lichtpunktes keine Rolle spielen würde. Das menschliche Auge hingegen erhält nicht 25 Momentaufnahmen, sondern eine analoge Darstellung des Lichtsignales. Dieses analoge Lichtsignal wird nun (wie bereits erwähnt) während der gesamten 1/25 Sekunde aufsummiert und als solches an das Gehirn übertragen. Somit sehen wir nicht einzelne Momentaufnahmen des Lichtes sondern den gesamten Weg den das Licht zurückgelegt hat. | + | [[Bild:Ball_verwischt.png|right|gerahmt|Eine verwischte kreisförmige Lichquelle auf schwarzem Hintergrund.|200x113px]] |
+ | Nehmen wir als Beispiel einen schwarzen Hintergrund. Über diesen schwarzen Hintergrund wandert (verhältnismäßig schnell) ein Licht. In der Computergrafik, wenn wir beispielsweise 60 [[FPS|Frames pro Sekunde]] darstellen können, würden wir 60 Momentaufnahmen darstellen, wobei in diesen Momentaufnahmen die Bewegung des Lichtpunktes keine Rolle spielen würde. Das menschliche Auge hingegen erhält nicht 25 Momentaufnahmen, sondern eine analoge Darstellung des Lichtsignales. Dieses analoge Lichtsignal wird nun (wie bereits erwähnt) während der gesamten 1/25 Sekunde aufsummiert und als solches an das Gehirn übertragen. Somit sehen wir nicht einzelne Momentaufnahmen des Lichtes sondern den gesamten Weg, den das Licht zurückgelegt hat. | ||
Wenn wir die Tatsache annehmen, dass wir nur 25 Bilder je Sekunde sehen, so können wir dies durch ein sehr einfaches Experiment nachvollziehen: | Wenn wir die Tatsache annehmen, dass wir nur 25 Bilder je Sekunde sehen, so können wir dies durch ein sehr einfaches Experiment nachvollziehen: | ||
− | Begebt euch in einen möglichst dunklen Raum und vollführt mit einem Licht ( | + | Begebt euch in einen möglichst dunklen Raum und vollführt mit einem Licht (z.B. Feuerzeug) verhältnismäßig schnelle Bewegungen. Ihr könnt nun den gesamten Weg sehen, den die Lichtquelle zurückgelegt hat. |
== Technische Umsetzung == | == Technische Umsetzung == | ||
=== Filme === | === Filme === | ||
− | Wenn ihr euch einen Film anseht, so scheinen die Bewegungen üblicherweise realer als in einem Computerspiel. Wenn ihr euch ein Standbild eines Filmes anseht so wird | + | Wenn ihr euch einen Film anseht, so scheinen die Bewegungen üblicherweise realer als in einem Computerspiel. Wenn ihr euch ein Standbild eines Filmes anseht, so wird klar, weshalb dies der Fall ist. Der Film besitzt üblicherweise zwar nur 25 Bilder je Sekunde, jedoch besitzen diese Bilder (gleich zum menschlichen Auge) die aufsummierte Helligkeit der 1/25 Sekunde, was in einem Standbild durch Streifen sichtbar wird. Diese Streifen kann man nun als Idealfall von Motion Blur ansehen. |
=== Computergrafik === | === Computergrafik === | ||
− | In der Computergrafik stellt man üblicherweise Standbilder dar. Es wäre enorm aufwändig die Berechnungen durchzuführen welche Farbe und welche Helligkeit ein Pixel haben würde, | + | In der Computergrafik stellt man üblicherweise Standbilder dar. Es wäre enorm aufwändig, die Berechnungen durchzuführen, welche Farbe und welche Helligkeit ein Pixel haben würde, wenn er die letzte 1/25 Sekunde darstellen würde und nicht nur eine Momentaufnahme. Glücklicherweise ist der Mensch nicht ganz so wählerisch und begnügt sich auch mit etwas besseren Darstellungen seiner Wirklichkeit, somit ist es um einiges besser, wenn man beispielsweise 60 Momentaufnahmen je Sekunde besitzt als wenn man nur 25 Momentaufnahmen besitzt. |
== Motion Blur in der Praxis == | == Motion Blur in der Praxis == | ||
− | Motion Blur ist also ein Effekt der das menschliche Auge möglichst zufriedenstellen soll. Bei verhältnismäßig langsamen Geschwindigkeiten (oder aber bei sehr | + | Motion Blur ist also ein Effekt, der das menschliche Auge möglichst zufriedenstellen soll. Bei verhältnismäßig langsamen Geschwindigkeiten (oder aber bei sehr hoher Framerate) hat Motion Blur kaum bis keine Auswirkungen. Erst bei höheren Geschwindigkeiten kann Motion Blur sinnvoll eingesetzt werden. Hier geht es jedoch teilweise nicht nur darum, allein das Standbild durch grafische Effekte zu verbessern, sondern im Idealfall geht es darum, für jedes Pixel die vergangene 1/25 Sekunde zu beachten. |
− | In Filmen sehen wir Motion Blur dann, wenn enorm hohe Geschwindigkeiten dargestellt werden sollen (annähernd Lichtgeschwindigkeit in Science Fiction Filmen). Obwohl ich weder ein Physiker noch ein Biologe bin, kann ich guten Gewissens behaupten, dass wir ein Raumschiff welches mit (annähernd) Lichtgeschwindigkeit an uns vorbei fliegt wohl so gut wie gar nicht sehen würden, da es nur einen sehr sehr kleinen Bruchteil einer 1/25 Sekunde sichtbar wäre ... einzige Ausnahme wäre natürlich wenn es enorm hell wäre, wodurch dieser sehr kleine Bruchteil viel bei der Aufsummierung der 1/25 Sekunde ausmachen könnte. | + | In Filmen sehen wir Motion Blur dann, wenn enorm hohe Geschwindigkeiten dargestellt werden sollen (annähernd Lichtgeschwindigkeit in Science Fiction Filmen). Obwohl ich weder ein Physiker noch ein Biologe bin, kann ich guten Gewissens behaupten, dass wir ein Raumschiff welches mit (annähernd) Lichtgeschwindigkeit an uns vorbei fliegt wohl so gut wie gar nicht sehen würden, da es nur einen sehr sehr kleinen Bruchteil einer 1/25 Sekunde sichtbar wäre ... einzige Ausnahme wäre natürlich, wenn es enorm hell wäre, wodurch dieser sehr kleine Bruchteil viel bei der Aufsummierung der 1/25 Sekunde ausmachen könnte. |
− | In der Computergrafik bezieht sich Motion Blur üblicherweise ausschließlich auf Momentaufnahmen wo die aktuelle Geschwindigkeit beachtet wird, oder aber die vorangegangenen Frames | + | In der Computergrafik bezieht sich Motion Blur üblicherweise ausschließlich auf Momentaufnahmen, wo die aktuelle Geschwindigkeit beachtet wird, oder aber die vorangegangenen Frames ebenfalls einen Einfluss besitzen. |
== Realisierung in OpenGL == | == Realisierung in OpenGL == | ||
Zeile 32: | Zeile 34: | ||
# (Bildschirm-)Textur erzeugen [winwidth x winheight] und initialisieren. | # (Bildschirm-)Textur erzeugen [winwidth x winheight] und initialisieren. | ||
# Bildschirm und Tiefenpuffer löschen | # Bildschirm und Tiefenpuffer löschen | ||
− | |||
# Szene rendern | # Szene rendern | ||
+ | # Textur ( im [[glOrtho | Orthomodus]] ) geblendet auf die Szene zeichnen ( mit Alphawert von z.B. 0.98, abhängig von Framerate, nicht in Depth-Buffer schreiben ) | ||
# [[glCopyTexSubImage2D]] und weiter bei Schritt 2. | # [[glCopyTexSubImage2D]] und weiter bei Schritt 2. | ||
Zeile 63: | Zeile 65: | ||
{ | { | ||
... | ... | ||
− | |||
− | |||
//Szene rendern | //Szene rendern | ||
+ | beginMotionBlur(); | ||
endMotionBlur(); | endMotionBlur(); | ||
... | ... | ||
Zeile 73: | Zeile 74: | ||
void beginMotionBlur() | void beginMotionBlur() | ||
{ | { | ||
− | |||
− | |||
− | |||
glEnable( GL_TEXTURE_2D ); | glEnable( GL_TEXTURE_2D ); | ||
+ | glEnable( GL_BLEND ); | ||
+ | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); | ||
+ | |||
+ | glDepthMask( false ); | ||
+ | |||
+ | //Motion-Faktor als Alpha-Faktor übergeben, Wert abhängig von Framerate ( z.B. 0.98 ) | ||
+ | glColor4d( 1.0f, 1.0f, 1.0f, decay ); | ||
+ | |||
+ | //Motion-Textur über Szene blenden | ||
glBindTexture( GL_TEXTURE_2D, theMotionTex ); | glBindTexture( GL_TEXTURE_2D, theMotionTex ); | ||
− | + | screenQuad( winwidth, winheight ); | |
− | + | ||
− | + | glDepthMask( true ); | |
+ | |||
+ | glDisable( GL_BLEND ); | ||
glDisable( GL_TEXTURE_2D ); | glDisable( GL_TEXTURE_2D ); | ||
− | |||
} | } | ||
Zeile 136: | Zeile 144: | ||
{| | {| | ||
− | |[[Bild: | + | |[[Bild:Motionblur.png|framed|Szene mit aktiviertem Motion-Blur.]] |
|} | |} | ||
+ | |||
+ | == Demo == | ||
+ | |||
+ | [http://algoria.de/opengl/demos/motionblur.jnlp Demo] ''(mit Quellen)'' |
Aktuelle Version vom 4. Dezember 2013, 16:11 Uhr
Motion Blur ist üblicherweise kein Effekt, den man macht weil er schön ist, sondern ein Effekt, der bei der Übertragung von digitalen Bildern zum menschlichen Auge eine Art Vermittlungsrolle spielt.
Inhaltsverzeichnis
Biologische Grundlagen
Mehr zu den biologischen Grundlagen und warum Motion-Blur trotzdem nicht die endgültige Lösung ist (und sogar zum Problem werden kann), erfahrt ihr im Artikel Framerate. |
Das menschliche Auge nimmt etwa 25 Bilder je Sekunde wahr. Im Unterschied zur Computergrafik sind dies jedoch keine Momentaufnahmen sondern eine Art Aufsummierung aller Lichtreize, die während dieser 1/25 Sekunde entstanden sind.
Ein leuchtender Punkt
Nehmen wir als Beispiel einen schwarzen Hintergrund. Über diesen schwarzen Hintergrund wandert (verhältnismäßig schnell) ein Licht. In der Computergrafik, wenn wir beispielsweise 60 Frames pro Sekunde darstellen können, würden wir 60 Momentaufnahmen darstellen, wobei in diesen Momentaufnahmen die Bewegung des Lichtpunktes keine Rolle spielen würde. Das menschliche Auge hingegen erhält nicht 25 Momentaufnahmen, sondern eine analoge Darstellung des Lichtsignales. Dieses analoge Lichtsignal wird nun (wie bereits erwähnt) während der gesamten 1/25 Sekunde aufsummiert und als solches an das Gehirn übertragen. Somit sehen wir nicht einzelne Momentaufnahmen des Lichtes sondern den gesamten Weg, den das Licht zurückgelegt hat.
Wenn wir die Tatsache annehmen, dass wir nur 25 Bilder je Sekunde sehen, so können wir dies durch ein sehr einfaches Experiment nachvollziehen:
Begebt euch in einen möglichst dunklen Raum und vollführt mit einem Licht (z.B. Feuerzeug) verhältnismäßig schnelle Bewegungen. Ihr könnt nun den gesamten Weg sehen, den die Lichtquelle zurückgelegt hat.
Technische Umsetzung
Filme
Wenn ihr euch einen Film anseht, so scheinen die Bewegungen üblicherweise realer als in einem Computerspiel. Wenn ihr euch ein Standbild eines Filmes anseht, so wird klar, weshalb dies der Fall ist. Der Film besitzt üblicherweise zwar nur 25 Bilder je Sekunde, jedoch besitzen diese Bilder (gleich zum menschlichen Auge) die aufsummierte Helligkeit der 1/25 Sekunde, was in einem Standbild durch Streifen sichtbar wird. Diese Streifen kann man nun als Idealfall von Motion Blur ansehen.
Computergrafik
In der Computergrafik stellt man üblicherweise Standbilder dar. Es wäre enorm aufwändig, die Berechnungen durchzuführen, welche Farbe und welche Helligkeit ein Pixel haben würde, wenn er die letzte 1/25 Sekunde darstellen würde und nicht nur eine Momentaufnahme. Glücklicherweise ist der Mensch nicht ganz so wählerisch und begnügt sich auch mit etwas besseren Darstellungen seiner Wirklichkeit, somit ist es um einiges besser, wenn man beispielsweise 60 Momentaufnahmen je Sekunde besitzt als wenn man nur 25 Momentaufnahmen besitzt.
Motion Blur in der Praxis
Motion Blur ist also ein Effekt, der das menschliche Auge möglichst zufriedenstellen soll. Bei verhältnismäßig langsamen Geschwindigkeiten (oder aber bei sehr hoher Framerate) hat Motion Blur kaum bis keine Auswirkungen. Erst bei höheren Geschwindigkeiten kann Motion Blur sinnvoll eingesetzt werden. Hier geht es jedoch teilweise nicht nur darum, allein das Standbild durch grafische Effekte zu verbessern, sondern im Idealfall geht es darum, für jedes Pixel die vergangene 1/25 Sekunde zu beachten.
In Filmen sehen wir Motion Blur dann, wenn enorm hohe Geschwindigkeiten dargestellt werden sollen (annähernd Lichtgeschwindigkeit in Science Fiction Filmen). Obwohl ich weder ein Physiker noch ein Biologe bin, kann ich guten Gewissens behaupten, dass wir ein Raumschiff welches mit (annähernd) Lichtgeschwindigkeit an uns vorbei fliegt wohl so gut wie gar nicht sehen würden, da es nur einen sehr sehr kleinen Bruchteil einer 1/25 Sekunde sichtbar wäre ... einzige Ausnahme wäre natürlich, wenn es enorm hell wäre, wodurch dieser sehr kleine Bruchteil viel bei der Aufsummierung der 1/25 Sekunde ausmachen könnte.
In der Computergrafik bezieht sich Motion Blur üblicherweise ausschließlich auf Momentaufnahmen, wo die aktuelle Geschwindigkeit beachtet wird, oder aber die vorangegangenen Frames ebenfalls einen Einfluss besitzen.
Realisierung in OpenGL
Standardmässig wurde Motion Blur in OpenGL mit dem Akkumulationspuffer realisiert, der jedoch nicht sehr schnell ist. Eine schnellere Methode arbeitet mit einer Bildschirmtextur und funktioniert folgendermassen :
- (Bildschirm-)Textur erzeugen [winwidth x winheight] und initialisieren.
- Bildschirm und Tiefenpuffer löschen
- Szene rendern
- Textur ( im Orthomodus ) geblendet auf die Szene zeichnen ( mit Alphawert von z.B. 0.98, abhängig von Framerate, nicht in Depth-Buffer schreiben )
- glCopyTexSubImage2D und weiter bei Schritt 2.
Beispielcode ( C )
void initMotionBlur()
{
//Textur in Bildschirmgrösse
int texSize = WINWIDTH * WINHEIGHT * 3;
float* motionTex = new float[texSize];
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures( 1, &theMotionTex );
glBindTexture( GL_TEXTURE_2D, theMotionTex );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WINWIDTH, WINHEIGHT, 0, GL_RGB, GL_FLOAT, motionTex);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
//Modulate-Modus, um Textur mit glColor zu mischen
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
delete [] motionTex;
}
...
void display()
{
...
//Szene rendern
beginMotionBlur();
endMotionBlur();
...
}
void beginMotionBlur()
{
glEnable( GL_TEXTURE_2D );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glDepthMask( false );
//Motion-Faktor als Alpha-Faktor übergeben, Wert abhängig von Framerate ( z.B. 0.98 )
glColor4d( 1.0f, 1.0f, 1.0f, decay );
//Motion-Textur über Szene blenden
glBindTexture( GL_TEXTURE_2D, theMotionTex );
screenQuad( winwidth, winheight );
glDepthMask( true );
glDisable( GL_BLEND );
glDisable( GL_TEXTURE_2D );
}
void endMotionBlur()
{
//Bildschirm zurück in Textur kopieren
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, theMotionTex );
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, WINWIDTH, WINHEIGHT);
glDisable( GL_TEXTURE_2D );
}
void screenQuad()
{
beginInfoScreen( WINWIDTH, WINHEIGHT );
glBegin(GL_QUADS);
glTexCoord2i( 0, 0 );
glVertex2i( 0, 0 );
glTexCoord2i( 1, 0 );
glVertex2i( WINWIDTH, 0 );
glTexCoord2i( 1, 1 );
glVertex2i( WINWIDTH, WINHEIGHT );
glTexCoord2i( 0, 1 );
glVertex2i( 0, WINHEIGHT );
glEnd();
endInfoScreen();
}
void beginInfoScreen( int winwidth, int winheight )
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, winwidth, 0, winheight);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
}
void endInfoScreen()
{
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
...
Demo
Demo (mit Quellen)