Extending a Depth of Field shader

Hello,

I’ve been working with the depth of field effect from the GLSL_DoF2 example in openFrameworks:
http://encelo.netsons.org/programming/opengl

I got it converted over to an oF project, but am interested in extending it to support alpha transparency. Current the shader is using the alpha channel to store a “depth” value.

vertex shader:

  
  
uniform float focalDistance, focalRange;  
varying float Blur;  
void main(void)  
{  
	vec4 PosWV = gl_ModelViewMatrix * gl_Vertex;  
	Blur = clamp(abs(-PosWV.z - focalDistance) / focalRange, 0.0, 1.0);  
	gl_Position = ftransform();  
	gl_TexCoord[0] = gl_MultiTexCoord0;  
}  
  

fragment shader:

  
  
varying float Blur;  
uniform sampler2D Tex0;  
void main (void)  
{  
	gl_FragData[0] = vec4(texture2D(Tex0, gl_TexCoord[0].st).rgb, Blur);  
}  
  

after this is applied, a DoF blurred version of the scene is then created using the blur value stored in that and then composited with the original scene like this:

fragment shader:

  
  
uniform sampler2D Tex0, Tex1;  
void main (void)  
{  
	vec4 Fullres = texture2D(Tex0, gl_TexCoord[0].st);  
	vec4 Blurred = texture2D(Tex1, gl_TexCoord[1].st);  
	  
	// HLSL linear interpolation function  
	gl_FragColor = Fullres + Fullres.a * (Blurred - Fullres);  
}  
  

What I want to do is figure out how to change this pipeline to allow for alpha. I was thinking that perhaps I would need to use a separate texture instead of using the alpha value, or perhaps rendering the scene twice - once with alpha, once without.

I think if were given a just a nudge in the right direction I could figure it out, but am a bit lost on how to approach the problem.

Let me know if there is more relevant information that is not included and I can try to explain further.

Thanks!

I’ve never done anything like it before, but I’m pretty sure what you’ll want to look into is MRT (multiple render targets). I think you’ll want to look into glDrawBuffers and you’ll wind up with a frag shader that writes the color/alpha to the main buffer and a depth value to a separate buffer (in the same drawing pass). Again, no experience with MRT, but I imagine you could even set up the depth buffer to be a single channel floating point buffer or something which would be a lot better than an 8-bit alpha channel.

Hope that is a helpful nudge.

if you render to an FBO, you can attach a depth texture instead of a depth buffer.- Then you can simply bind it in the next pass and read the depth values back.

Anyways, the DOF effect wont properly work with transparent objects because the depth buffer only saves one depth value for each pixel. If you had transparent objects, you would need multiple depth values per fragment and still would not know wich to use afterwards. So generally if you have to read back depth from a texture or whatsoever transparency is a bad idea since you can only save one depth value per pixel.

There’s some info on how to deal with alpha blending here:
http://developer.amd.com/media/gpu-asse-…-fField.pdf

The article suggests the following:

1st pass - render to RGB only with blending enabled
2nd pass - render output of depth blur to destination alpha channel

So you would need multiple render passes for this (also to get a depth texture).

Thanks for the help guys, I’m going to dig into this and see if I can work it out.

In case anyone wants to take a crack at it as well I’m posting a simple project with the effect turned on.

I’ll let you know what I come up with, thanks!

(you will need to add textures to the textures folder)

glslDoFTest.zip

I got to a workable solution although it’s not ideal.

it uses two rendering passes like the article suggests. Moka was right in that it could potentially use the depth texture to the same affect, but right now this seemed simpler than changing the way the MSAA FOB’s are working.

If anyone wants to use or extend it further I’ll put it up here (textures included in this one)
http://jamesgeorge.org/uploads/glslDoFAlpha.zip

Thanks for the advice!

hi.
did you every get a chance to update this example to OF 007 ?
I am trying to make it use ofFbo and ofShader but get a bunch of errors when running.

thanks.

errors:
allocating FBO 0
OF: OF_LOG_ERROR: ofGetGlFormatAndType(): glInternalFormat not recognized returning glFormat as glInternalFormat
OF: OF_LOG_ERROR: FRAMEBUFFER_INCOMPLETE_ATTACHMENT
allocating FBO 1
OF: OF_LOG_ERROR: ofGetGlFormatAndType(): glInternalFormat not recognized returning glFormat as glInternalFormat
OF: OF_LOG_ERROR: FRAMEBUFFER_INCOMPLETE_ATTACHMENT
allocating FBO 2
OF: OF_LOG_ERROR: ofGetGlFormatAndType(): glInternalFormat not recognized returning glFormat as glInternalFormat
OF: OF_LOG_ERROR: FRAMEBUFFER_INCOMPLETE_ATTACHMENT
allocating FBO 3
OF: OF_LOG_ERROR: ofGetGlFormatAndType(): glInternalFormat not recognized returning glFormat as glInternalFormat
OF: OF_LOG_ERROR: FRAMEBUFFER_INCOMPLETE_ATTACHMENT
allocating FBO 4
OF: OF_LOG_ERROR: ofGetGlFormatAndType(): glInternalFormat not recognized returning glFormat as glInternalFormat
OF: OF_LOG_ERROR: FRAMEBUFFER_INCOMPLETE_ATTACHMENT

ok so i got this example working on OF007 but only when using the supplied ofxFBOMSTexture and ofxShader addons.

I was also wondering; how would i draw/ DOF blur anything other then the example cube? Ideally a 3D model.

thx.

Anyways, the DOF impact probably won’t effectively perform with obvious things because the level shield only preserves one level value for each pixel. If you had obvious things, you would need several level principles per fragment and still would not know wich to use afterwards. So usually if you have to study again level from a surface or at all visibility is a bad concept since you can only preserve one level value per pixel.