I have a question about FBO and glBlendFunc?

Hi good guy:
Now I was really confused by the FBO and glBlendFunc!
Who can tell me whether glBlendFunc can direct operate FBO, blending to FBO and result still send to FBO not framebuffer?
the detail is that when I bind a FBO ,all blending operation will done to the FBO, not framebuffer before bind!
I know implenting complicated blending in shader, but my blending is simple ,so I want to implenting using glBlendFunc!
who can give me some help ?

thanks advanced!

spring
And what did you expect to see???
It is quite evident, that if you are working with FBO, then you must forget about your screen framebuffer. Or think about screen framebuffer as of framebuffer with number zero.
If you want to blend with something rendered before - so save it to texture and draw full-screen quad to blend with it.

Who can tell me whether glBlendFunc can direct operate FBO, blending to FBO and result still send to FBO not framebuffer?
If you have bound an FBO, then you are rendering to the FBO, whether blending is enabled or not. If you have bound an FBO, then the standard framebuffer for the context is not bound and will therefore not be affected by rendering commands. That’s the entire point of binding an FBO.

If you want to render to the FBO, then you bind it. If you want to render to the framebuffer, then you unbind the FBO.

You can’t half-blend, where you do the read for the blend from the FBO but write the blended result to the context framebuffer.

Complex answers and I think the question was simple :slight_smile:

If you render to FBO, nothing happens in main framebuffer. You can use blending when rendering to FBO - it will not interact with the main framebuffer in any way.

You can meet some limitations when rendering to textures. For example - some cards do not support blending when rendering to FLOAT16 textures. Only GeForce 6/7/8 and Radeon X1k/X2k can do that.
It’s even worse with FLOAT32 textures.

What Jackis and Korval also say is that no matter if you render to FBO or main framebuffer you can’t read the value of pixel you currently render to. Framebuffers are write-only, except for hardware blending and glReadPixels.

Originally posted by k_szczech:

What Jackis and Korval also say is that no matter if you render to FBO or main framebuffer you can’t read the value of pixel you currently render to. Framebuffers are write-only, except for hardware blending and glReadPixels.

hmm, are you 100% sure? i’ve done some quick tests doing “manual” blending inside a pixel shader (aka read & write the same fbo) and it just works; zero artifacts and no performance penalty compared to glBlendFunc :slight_smile:
(tested on gf 6/7/8)

From the FBO specification

4.4.3  Rendering When an Image of a Bound Texture Object is Also
Attached to the Framebuffer
Special precautions need to be taken to avoid attaching a texture
image to the currently bound framebuffer while the texture object is
currently bound and enabled for texturing.  Doing so could lead to
the creation of a "feedback loop" between the writing of pixels by
the GL's rendering operations and the simultaneous reading of those
same pixels when used as texels in the currently bound texture.  In
this scenario, the framebuffer will be considered framebuffer
complete (see section 4.4.4), but the values of fragments rendered
while in this state will be undefined.  The values of texture
samples may be undefined as well, as described in section 3.8.8.
Specifically, the values of rendered fragments are undefined if all
of the following conditions are true:
    - an image from texture object <T> is attached to the currently
      bound framebuffer at attachment point <A>, and
    - the texture object <T> is currently bound to a texture unit
      <U>, and
    - the current fixed-function texture state or programmable
      vertex and/or fragment processing state makes it possible(*)
      to sample from the texture object <T> bound to texture unit
      <U>
while either of the following conditions are true:
    - the value of TEXTURE MIN FILTER for texture object <T> is
      NEAREST or LINEAR, and the value of
      FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT for attachment point
      <A> is equal to the value of TEXTURE_BASE_LEVEL for the
      texture object <T>, or
    - the value of TEXTURE_MIN_FILTER for texture object <T> is one
      of NEAREST_MIPMAP_NEAREST, NEAREST_MIPMAP LINEAR, LINEAR
      MIPMAP_NEAREST, or LINEAR_MIPMAP_LINEAR, and the value of
      FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT for attachment point
      <A> is within the the range specified by the current values of
      TEXTURE_BASE_LEVEL to q, inclusive, for the texture object
      <T>.  (q is defined in the Mipmapping discussion of section
      3.8.8),
(*) For the purpose of this discussion, we consider it "possible"
    to sample from the texture object <T>  bound to texture unit <U>"
    if any of the following are true:
    - programmable vertex and fragment processing is disabled
      and the target of texture object <T> is enabled according
      to the texture target precedence rules of section 3.8.15,
      or
    - if FRAGMENT_PROGRAM_ARB is enabled and the currently bound 
      fragment program contains any instructions that
      sample from the texture object <T> bound to <U>, 
      or
    - if the active fragment or vertex shader contains
      any instructions that might sample from the texture object <T> bound 
      to <U> if even those instructions might only be executed
      conditionally.
Note that if TEXTURE_BASE_LEVEL and TEXTURE_MAX_LEVEL exclude any
levels containing image(s) attached to the currently bound
framebuffer, then the above conditions will not be met, (i.e., the
above rule will not cause the values of rendered fragments to be
undefined.)

thanks komat, but that still doesn’t explain why it works as long as i sample the texture on a 1:1 basis
(write exactly to the same position i read from)

cheers

/edit

it’s not a lucky driver bug either, tested on 8x.xx, 93.71, 94.42, 97.xx, 155.xx

Originally posted by ze moo:
thanks komat, but that still doesn’t explain why it works as long as i sample the texture on a 1:1 basis
(write exactly to the same position i read from)

It appears to work because in this particular case the combination of the sampling pattern, rendered geometry and hw implementation caused the undefined value to be what you expect.

For different hw or different rendering commands, the result might be incorrect. For example because old value of texel is found in texture cache or read was done before the corresponding write finished. The driver and hw does nothing to guarantee correct ordering of operations.

“Undefined” doesn’t mean “wrong”. It means - it can be good or it can be wrong.
In your case you read a pixel that was written some time ago (in previous frame?), so the probability that texture is not in cache memory, and therefore must be read from main memory is high.
On a GPU with more cache memory or different memory management rules the probability may be low.
That’s why this value is “undefined” - because you can get correct result with some platform-dependent probability.

Yes, I know, that SOMETIMES reading from the same texture what you are rendering to works correctly, but it’s not the common situation, and spec said that it’s bad to do that :slight_smile:

BTW, on XBox we can read pixel color and depth while rendering to it )) So I think we shall see the same soon on consumer graphics hardware too :slight_smile:

thanks for the clarification.

turning on “generate shader portability errors” inside the nv driver actually gives the expected “undefined” behaviour.

wild guess:
maybe it’s some nv-specific extension (like the ton of cg-related stuff inside nvidia’s glsl implementation) :slight_smile:

Originally posted by ze moo:
[quote]Originally posted by k_szczech:

What Jackis and Korval also say is that no matter if you render to FBO or main framebuffer you can’t read the value of pixel you currently render to. Framebuffers are write-only, except for hardware blending and glReadPixels.

hmm, are you 100% sure? i’ve done some quick tests doing “manual” blending inside a pixel shader (aka read & write the same fbo) and it just works; zero artifacts and no performance penalty compared to glBlendFunc :slight_smile:
(tested on gf 6/7/8)
[/QUOTE]Bulldink. You are saying with glBlendFunc you lose performance but doing the blending in a shader, yuo don’t?

Originally posted by V-man:
Bulldink. You are saying with glBlendFunc you lose performance but doing the blending in a shader, yuo don’t?
huh?
i just said that “manual” blending inside a shader & glBlendfunc perform equally (there’s no difference performance wise)