shading opengl glsl blur

opengl - deferred shading



¿Cómo uso un sombreador GLSL para aplicar un desenfoque radial a una escena completa? (1)

Tengo un sombreador de desenfoque radial en GLSL, que toma una textura, le aplica un desenfoque radial y le da el resultado a la pantalla. Esto funciona muy bien, hasta ahora.

El problema es que esto aplica el desenfoque radial a la primera textura en la escena. Pero lo que realmente quiero hacer es aplicar este desenfoque a toda la escena.

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

// 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 ); }


Básicamente, esto se denomina "procesamiento posterior" porque está aplicando un efecto (aquí: desenfoque radial) a toda la escena una vez que se procesa.

Así que sí, tienes razón: la buena forma de postprocesamiento es:

  • crear una textura NPOT del tamaño de una pantalla ( GL_TEXTURE_RECTANGLE ),
  • Crea un FBO, ponle la textura.
  • configura este FBO en activo, renderiza la escena
  • deshabilita el FBO, dibuja un quad de pantalla completa con la textura del FBO.

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

Por lo tanto, debe aplicar el desenfoque radial solo después de que se haya procesado toda la escena y el sombreado de fragmentos para el fragmento (x, y) sea capaz de leer cualquier píxel de la escena. Esta es la razón por la que necesitas 2 etapas de renderizado para eso.