2011-01-02 17 views
16

Tengo un sombreado de desenfoque radial en GLSL, que toma una textura, le aplica un desenfoque radial y muestra el resultado en la pantalla. Esto funciona muy bien, hasta ahora.¿Cómo uso un sombreador GLSL para aplicar un desenfoque radial a una escena completa?

El problema es que esto se aplica el desenfoque radial a la primera textura en la escena. Pero lo que realmente quiero hacer es aplicar esta imagen borrosa a la escena completa .

¿Cuál es la mejor manera de lograr esta funcionalidad? ¿Puedo hacer esto solo con sombreadores, o tengo que renderizar la escena primero en una textura (en OpenGL) y luego pasar esta textura al sombreador para su posterior procesamiento?

// 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

Respuesta

16

Básicamente, esto se llama "post-procesamiento" porque va a aplicar un efecto (en este caso la falta de definición radial) a toda la escena después es prestado

Así que sí, tienes razón: es el buen camino para el post-procesamiento es:

  • crear una textura NPOT tamaño de pantalla (GL_TEXTURE_RECTANGLE),
  • crear un FBO, fije la textura de es
  • establece este FBO en activo, renderiza la escena
  • desactiva el FBO, dibuja un cuadrante de pantalla completa con la textura del FBO.

En cuanto al "por qué", la razón es simple: la escena se representa en paralelo (el fragmento de sombreado se ejecuta de forma independiente para muchos píxeles). Para hacer un desenfoque radial para píxel (x, y), primero necesita conocer los valores de píxel de preinyección de los píxeles circundantes. Y esos no están disponibles en el primer pase, porque solo se están entregando mientras tanto.

Por lo tanto, se debe aplicar el desenfoque radial sólo después se procesa toda la escena y fragment shader de fragmento (x, y) es capaz de leer cualquier pixel de la escena. Esta es la razón por la cual necesita 2 etapas de renderizado para eso.

+0

muchas gracias, ¡eso realmente ayudó mucho! –

Cuestiones relacionadas