2016-04-06 3 views
2

Ich habe einen schönen Musik-Visualizer mit OpenGL in Java gebaut. Es sieht schon ziemlich ordentlich aus, aber ich habe darüber nachgedacht, etwas Nachbearbeitung hinzuzufügen. Zu der Zeit, sieht es wie folgt aus:OpenGL Bildschirm Nachbearbeitungseffekte

Something like this

Es gibt bereits einen Bildpuffer zum Aufzeichnen der Ausgabe, so habe ich die Textur bereits zur Verfügung. Jetzt frage ich mich, ob jemand eine Idee für einige Effekte hat. Der aktuelle Fragment-Shader sieht wie folgt aus:

#version 440 

in vec3 position_FS_in; 
in vec2 texCoords_FS_in; 


out vec4 out_Color; 

//the texture of the last Frame by now exactly the same as the output 
uniform sampler2D textureSampler; 

//available data: 
//the average height of the lines seen in the screenshot, ranging from 0 to 1 
uniform float mean; 
//the array of heights of the lines seen in the screenshot 
uniform float music[512]; 

void main() 
{ 
    vec4 texColor = texture(textureSampler, texCoords_FS_in); 
    //insert post processing here 
    out_Color = texColor; 
} 
+0

Ist das ein Spektrumanalysator am Boden?Ich war schon immer begeistert von der "Stimmabdruck" -Visualisierung, bei der Sie Scanlinien vom Spektrumanalysator scrollen und jedes Pixel auf die Größe dieses Punktes aus der FFT setzen. Es macht es einfach, die Noten in einem Song zu identifizieren. Es ist wirklich kein Post-Processing-Effekt, also habe ich nur kommentiert. – doug65536

+0

@ doug65536 Sorry, aber ich verstehe nicht wirklich, was Sie sagen. Sagen wir, ich habe die Musik [] berechnet, was soll ich damit machen, bevor ich sie in den Shader lade? Vielleicht ein Code, bitte? – Dynamitos

+0

Post-Processing-Effekte werden implementiert, indem aus dem Framebuffer gelesen wird und etwas basierend auf dem ursprünglichen Framebuffer über den ursprünglichen Framebuffer gemischt wird. Wussten Sie, dass [OpenGL Postprocessing] (https://de.wikibooks.org/wiki/OpenGL_Programming/Post-Processing) ein Tutorial sein soll? Du kannst nicht einfach postprocessing wo dein Kommentar ist. – doug65536

Antwort

2

Die meisten Post-Processing-Effekte mit der Zeit ändern, so ist es üblich, eine Uniform zu haben, die im Laufe der Zeit ändert. Zum Beispiel kann ein "welliger" Effekt durch das Versetzen von Texturkoordinaten unter Verwendung von sin(elapsedSec * wavyRadsPerSec + (PI * gl_FragCoord.y * 0.5 + 0.5) * wavyCyclesInFrame) erzeugt werden.

Einige "Postprocessing" -Effekte können sehr einfach ausgeführt werden, zum Beispiel, anstatt den Rückpuffer mit glClear zu löschen, können Sie einen nahezu schwarzen transparenten Quad über den gesamten Bildschirm mischen. Dies erzeugt einen Persistence-Effekt, bei dem die letzten Frames hinter dem aktuellen schwarz werden.

Eine Richtungsunschärfe kann implementiert werden, indem mehrere Abtastungen in verschiedenen Abständen von jedem Punkt genommen werden und die näheren stärker gewichtet und addiert werden. Wenn Sie die Bewegung eines Punkts relativ zur Kameraposition und -ausrichtung verfolgen, kann daraus eine Bewegungsunschärfe-Implementierung erstellt werden.

Farbtransformationen sind auch sehr einfach, behandeln Sie einfach das RGB, als ob sie die XYZ eines Vektors sind, und machen Sie interessante Transformationen darauf. Sepia und "psychedelische" Farben können auf diese Weise produziert werden.

Sie könnten es hilfreich finden, die Farbe in etwas wie HSV zu konvertieren, Transformationen für diese Darstellung durchzuführen und sie für den Framebuffer Write wieder in RGB umzuwandeln. Sie können beispielsweise den Farbton, die Sättigung, das Schwarz-Weiß-Bild oder die Farbsättigung gleichmäßig beeinflussen.

Ein Effekt "in den Abstand schmieren" kann durch Mischen des Framebuffers auf den Framebuffer durch Lesen von texcoord, das leicht von gl_FragCoord skaliert wird, wie texture(textureSampler, (gl_FragCoord * 1.01).xy), erfolgen.

In diesem Sinne sollten Sie diese Texturkoordinatenattribute nicht benötigen, können Sie gl_FragCoord verwenden, um herauszufinden, wo Sie auf dem Bildschirm sind, und verwenden Sie (eine angepasste Kopie von) für Ihren texture Aufruf.

Werfen Sie einen Blick auf einige Shader auf GLSLSandbox für Inspiration.

Ich habe a simple emulation of the trail effect auf GLSLSandbox getan. In der echten würde die Schleife nicht existieren, es würde eine Probe von einem kleinen Offset nehmen. Der "Loop" -Effekt würde von selbst passieren, da seine Eingabe die Ausgabe des letzten Frames enthält. Um eine Textur des letzten Bildes zu simulieren, habe ich es einfach gemacht, damit ich berechnen kann, was das andere Pixel ist. Sie würden die Textur für den letzten Frame lesen, anstatt etwas wie pixelAt aufzurufen, wenn Sie den Trail-Effekt ausführen.

Sie können die Welle anstelle meiner gefälschten Sinuswelle verwenden. Verwenden Sie die uv.x, um einen entsprechend skalierten Index auszuwählen.

GLSL

#ifdef GL_ES 
precision mediump float; 
#endif 

uniform float time; 
uniform vec2 mouse; 
uniform vec2 resolution; 
const float PI = 3.14159265358979323;// lol ya right, but hey, I memorized it 

vec4 pixelAt(vec2 uv) 
{ 
    vec4 result; 
    float thickness = 0.05; 
    float movementSpeed = 0.4; 
    float wavesInFrame = 5.0; 
    float waveHeight = 0.3; 
    float point = (sin(time * movementSpeed + 
       uv.x * wavesInFrame * 2.0 * PI) * 
       waveHeight); 
    const float sharpness = 1.40; 
    float dist = 1.0 - abs(clamp((point - uv.y)/thickness, -1.0, 1.0)); 
    float val; 
    float brightness = 0.8; 

    // All of the threads go the same way so this if is easy 
    if (sharpness != 1.0) 
     dist = pow(dist, sharpness); 

    dist *= brightness; 

    result = vec4(vec3(0.3, 0.6, 0.3) * dist, 1.0); 

    return result; 
} 

void main(void) { 

    vec2 fc = gl_FragCoord.xy; 
    vec2 uv  = fc/resolution - 0.5; 
    vec4 pixel; 

    pixel = pixelAt(uv); 

    // I can't really do postprocessing in this shader, so instead of 
    // doing the texturelookup, I restructured it to be able to compute 
    // what the other pixel might be. The real code would lookup a texel 
    // and there would be one sample at a small offset, the feedback 
    // replaces the loop. 
    const float e = 64.0, s = 1.0/e; 
    for (float i = 0.0; i < e; ++i) { 
     pixel += pixelAt(uv + (uv * (i*s))) * (0.3-i*s*0.325); 
    } 
    pixel /= 1.0; 

    gl_FragColor = pixel; 
} 
+0

Der Trail-Effekt wäre cool – elect

+0

Sieht super aus, irgendwelche Ideen für die Verwendung der Musikwellen oder der bedeuten? – Dynamitos

+0

@Dynamitos Ich habe einen Link zu einer GLSLSandbox-Emulation des Feedbacks hinzugefügt (ich kann kein echtes Feedback für den Trail-Effekt geben, also emulierte ich eine Textur-Suche). Die Welle könnte den "sin" -Ruf ersetzen, der "Punkt" berechnet, und der Mittelwert könnte vielleicht die Dicke der Linie etwas beeinflussen. – doug65536