2011-01-02 8 views
16

Ich habe einen radialen Unschärfe-Shader in GLSL, der eine Textur nimmt, eine radiale Unschärfe darauf anwendet und das Ergebnis auf dem Bildschirm darstellt. Das funktioniert bisher sehr gut.Wie verwende ich einen GLSL-Shader, um eine radiale Unschärfe auf eine ganze Szene anzuwenden?

Das Problem ist, dass dies die radiale Unschärfe auf die erste Textur in der Szene anwendet. Aber was ich eigentlich machen möchte, ist, diese Unschärfe auf die Szene ganz anzuwenden.

Was ist der beste Weg, um diese Funktionalität zu erreichen? Kann ich dies nur mit Shadern machen, oder muss ich die Szene zuerst in eine Textur rendern (in OpenGL) und dann diese Textur zur weiteren Verarbeitung an den Shader übergeben?

// Vertex shader 

varying vec2 uv; 

void main(void) 
{ 
    gl_Position = vec4(gl_Vertex.xy, 0.0, 1.0); 
    gl_Position = sign(gl_Position); 
    uv = (vec2(gl_Position.x, - gl_Position.y) + vec2(1.0))/vec2(2.0); 
} 


// Fragment shader 

uniform sampler2D tex; 
varying vec2 uv; 
const float sampleDist = 1.0; 
const float sampleStrength = 2.2; 

void main(void) 
{ 
    float samples[10]; 
    samples[0] = -0.08; 
    samples[1] = -0.05; 
    samples[2] = -0.03; 
    samples[3] = -0.02; 
    samples[4] = -0.01; 
    samples[5] = 0.01; 
    samples[6] = 0.02; 
    samples[7] = 0.03; 
    samples[8] = 0.05; 
    samples[9] = 0.08; 

    vec2 dir = 0.5 - uv; 
    float dist = sqrt(dir.x*dir.x + dir.y*dir.y); 
    dir = dir/dist; 

    vec4 color = texture2D(tex,uv); 
    vec4 sum = color; 

    for (int i = 0; i < 10; i++) 
     sum += texture2D(tex, uv + dir * samples[i] * sampleDist); 

    sum *= 1.0/11.0; 
    float t = dist * sampleStrength; 
    t = clamp(t ,0.0,1.0); 

    gl_FragColor = mix(color, sum, t); 
} 

alt text

Antwort

16

Diese im Grunde genannt wird "Post-Processing", weil Sie einen Effekt anwenden möchten (hier: Radial Blur) auf die gesamte Szene nach es ist gerendert

Also ja, du hast Recht: der gute Weg für die Nachbearbeitung ist:

  • eine Bildschirm-Größe NPOT Textur (GL_TEXTURE_RECTANGLE) erstellen,
  • ein FBO schaffen, bringt die Textur
  • setzen Sie diesen FBO auf aktiv, rendern Sie die Szene
  • deaktivieren Sie die FBO, zeichnen Sie ein Vollbild-Quad mit der FBO-Textur.

wie für die „Warum“, der Grund dafür ist einfach: die Szene parallel wiedergegeben wird (das Fragment-Shader unabhängig für viele Pixel ausgeführt wird). Um eine radiale Unschärfe für Pixel (x, y) zu erzielen, müssen Sie zunächst die Pixelwerte der umgebenden Pixel vor der Unschärfe kennen. Und diese sind im ersten Durchgang nicht verfügbar, da sie nur in der Zwischenzeit gerendert werden.

Daher müssen Sie die radiale Unschärfe nur anwenden, nachdem die gesamte Szene gerendert wurde, und Fragment Shader für Fragment (x, y) kann jedes Pixel aus der Szene lesen. Aus diesem Grund benötigen Sie 2 Rendering-Stufen.

+0

vielen dank, das hat wirklich sehr geholfen! –