Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 3 123 LastLast
Results 1 to 10 of 24

Thread: Depth Of Field

  1. #1
    Intern Contributor
    Join Date
    Dec 2002
    Posts
    69

    Depth Of Field

    I'm interested in implementing the depth of field effect very broadly described in a tutorial on this page:- http://realtimecg.gamedev-pt.net/tutorials.html
    There's not a lot of implementation detail in there, so I've a few questions.
    (1) Do I use the depth_texture extension to extract the depth buffer into the texture?
    (2) How do I get these depth values into the alpha of the 'sharp' texture?
    (3) Would it be wise to use the sgi automatic mipmapping extension to generate the 'blurred' texture?

    Thanks for any light you can shed.

  2. #2
    Advanced Member Frequent Contributor
    Join Date
    Oct 2000
    Location
    Belgium
    Posts
    857

    Re: Depth Of Field

    (1) Yes.
    (2) You don't. Just bind the depth texture to an unused unit and set up a GL_INTERPOLATE combine mode to output LERP(sharp, blurry, depth).
    (3) That's certainly the easiest way to do it. You should be able to get higher quality blurs by doing them yourself, though, but that's probably also more expensive.

    -- Tom

  3. #3
    Intern Contributor
    Join Date
    Dec 2002
    Posts
    69

    Re: Depth Of Field

    Thanks for your reply, Tom!

    So I'll need 3 texture units in total?! 0=sharptexture,1=blurredtexture,2=depthtexture
    ?

    Just to clear something up, here's an extract from the tutorial:-

    Tutorial:-
    The algoritm is simple.
    Render your scene into a texture.
    When you do this, you must compute the depth distance of your pixel to a Focus Plane, and save
    it in the alpha channel of the texture.
    Make a copy of that texture. Lets call it the in focus texture.
    Blur the original texture. Lets call it the out of focus texture.
    Now render a quad with the size of your screen, with the 2 textures aplied.
    I think that you have checked out whats the trick by now!
    (bear in mind I'm going to be rendering into the framebuffer, not a texture (I think the tutorial is based around d3d)).
    Is there no way I can get around this usage of the alpha/computing focal plane distance per vertex etc.?
    I want to have the freedom to do fancy shader stuff, and have the depth of field as a post render process without relying on stuff accumulated during the render...

    [This message has been edited by KuriousOrange (edited 01-23-2003).]

  4. #4
    Advanced Member Frequent Contributor
    Join Date
    Oct 2000
    Location
    Belgium
    Posts
    857

    Re: Depth Of Field

    The effect is completely independent of your normal rendering. The only thing you have to "accumulate" during rendering is the Z buffer.

    You can do all the fancy shading you want, then when your frame is finished, you read back the color and depth buffers into textures. Then you create the blurred version of the color buffer, so you have a total of three textures. You bind all three of them, draw a single fullscreen quad, and you're done.

    What you seem to be missing is that the depth values are only converted to alpha values during the rendering of this fullscreen quad. This is achieved by setting the GL_DEPTH_TEXTURE_MODE_ARB texture parameter to GL_ALPHA. None of this requires any modifications to your normal rendering operations.

    -- Tom

  5. #5
    Intern Contributor
    Join Date
    Dec 2002
    Posts
    69

    Re: Depth Of Field

    But how do you calculate the distance from the focus plane? Surely this is done per vertex and then interpolated across the triangle?

    I've had a stab at trying to do this without having to compute the distance at renderscene time...please tell me what you think:-

    Code :
    void initialisation()
    {
    	// bind sharp tex id
    	glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, viewportwidth, viewportheight, 0);
     
    	// somehow compute a blurred version
     
    	// bind depth tex id
    	glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, viewportwidth, viewportheight, 0);
    }
     
    void render()
    {
    	// render scene
     
    	// bind sharp tex id
    	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, viewportwidth, viewportheight);
     
    	// somehow compute a blurred version
     
    	// bind depth tex id
    	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, viewportwidth, viewportheight);
     
    	// clear colour/depth buffer
     
    	// bind sharp texture to unit 0
    	// bind blurry texture to unit 1
    	// bind depth texture to unit 2
     
    	// enable register combiner program (shown below)
    	// set const0 of register combiner to some value between 0 and 1
     
    	// render screen size quad
     
    	// swap buffers
    }
     
     
    //////////////////////////////////////////////////
    // nvparse Register Combiner
     
    // tex0 = sharp texture
    // tex1 = blur texture
    // tex2 = depth texture
    // const0 = depth of focal plane
     
    // subtract focal plane depth from depth texture depth to
    // give distance from focal plane
    {
    	rgb
    	{
    		discard = tex2;
    		discard = negate(const0);
    		spare0 = sum();
    	}
    }
     
    out.rgb = lerp(tex0, tex1, unsigned(spare0));
    out.a = unsigned_invert(zero);

  6. #6
    Intern Contributor
    Join Date
    Dec 2002
    Posts
    69

    Re: Depth Of Field

    By the way, it's also occurred to me that one could add a heat haze effect by introducing a 4th texture (scrolled/scaled/rotated using the texture matrix) to peturb the focal plane constant perpixel! I think that might look very smart!

  7. #7
    Intern Contributor
    Join Date
    Dec 2002
    Posts
    69

    Re: Depth Of Field

    If someone could please tell me if my code is bollocks, or am I barking up the right tree?
    I'm not at a graphics proficient PC at the moment, so can't test it myself.
    I'm not that sure how I can get the blurred texture (without having to do it on the CPU). If I let opengl generate a set of mipmaps automatically, how do I specificy that I want mipmap level 0 to bind to unit 0, and mipmap level 3 (say) to unit 1 ? Is there anyway I can select the mipmap in the register combiners or something? (if so, then I'd only need 2 texture units)...

  8. #8
    Advanced Member Frequent Contributor
    Join Date
    May 2001
    Location
    France
    Posts
    768

    Re: Depth Of Field

    You can't select the mipmap into the register combiners. Register combiners apply after texture access.

    If you want to get different levels of mipmaps, the EXT_texture_lod_bias can do it. The spec is at : http://oss.sgi.com/projects/ogl-samp...e_lod_bias.txt

    You don't really need 3 texture units. You can use a single texture object : RGB component stores RGB values of the framebuffer (that will be blurred by the mipmap) and the ALPHA component of the texture stores the DEPTH component.

  9. #9
    Intern Contributor
    Join Date
    Dec 2002
    Posts
    69

    Re: Depth Of Field

    Ah! I knew I was missing something...
    texture_lod_bias!
    Right, so I can copysubimage the colour buffer into a texture with automipmap on, and then bind that single texture object to 2 texture units, but set the lod_bias differently for the 2 units, therefore giving me a sharp and a blury texture!
    Good.

    vincoof, when you say it can be done with a single texture, I'm confused. I put to you the same question I put to Tom - you're not taking into account the 'distance from focal plane' thing...in other words, we're not really interested in the depth fragments directly, just in their depth in relation to a reference depth value (the depth of the focal plane).. How do you solve this in your own apps? Where do you calculate the distance from focal plane?

  10. #10
    Senior Member OpenGL Guru
    Join Date
    Mar 2001
    Posts
    2,704

    Re: Depth Of Field

    Because the framebuffer already contains the sharp piece, you don't need to put that in a texture. It would seem that "all" you need to do is to overlay the framebuffer (using GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA blending) with the blurred texture, assuming distance-from-focus-plane is in ALPHA.

    I don't think packing color and alpha into the same texture is going to be all that efficient, because it requires re-shuffling and splicing of data that doesn't come pre-spliced. Also, you probably want blur on the texture when you access it for color, but not when you access it for depth (== alpha).

    With the right set-up, you might be able to get depth into alpha using a fragment program or register combiner set-up in the frame buffer, although I don't know if this will actually help you much.
    "If you can't afford to do something right,
    you'd better make sure you can afford to do it wrong!"

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •