Sign in to follow this  
rabidh

OpenGL Pixel shaders and blending

Recommended Posts

Hi. I'm currently working on an engine for some sound-reactive visuals - the plan is to use pixel shaders as much as possible instead of the OpenGL fixed pipeline. I've hit a snag to do with blending though. I've been reading around and as far as I can see the output of a pixel shader always goes through the standard OpenGL Blending function (unless disabled). My problem is I want to be able to combine my output pixels with the framebuffer in other ways - specifically: DST = SRC+DST-0.5 I used to be able to do this just fine with the register combiners extension in OpenGL, but I don't think this will work with fragment shaders. So... Is there any way to load the destination colour into the pixel shader? This would be the ideal solution for me. The standard workaround seems to be to render to a texture first, and use that as an input. The whole reason I want the blend function above is for a particle system though, so thats not an option (i'd have to copy the texture back after each particle). Someone suggested that in DirectX you can render to a texture while sampling from that same texture - is there an equivalent in OpenGL (with PBuffers?). thanks in advance, - Gordon

Share this post


Link to post
Share on other sites
I think the only way is to render the framebuffer to the texture and use it in ps. There was a plan to include FB reading in GLSL but I don't know if it was ever implemented.
You can't render to a texture and sample it at the same time.

Share this post


Link to post
Share on other sites
Thanks! that just got me the magic phrase for google :)

http://www.beyond3d.com/forum/showthread.php?t=32477

It says (referring to 'GL 2.1 / GLSL 1.20):
Quote:
AFAICS, the new features/changes from OpenGL2.0 are in general rather modest:

* sRGB textures
* Centroid Mapping
* Shading-language "invariant" keyword
* It is no longer permitted to turn off perspective correction for plain gouraud shading
* Pixel Buffer Objects (which mainly provides mechanisms for asynchronous texture uploads and framebuffer reads, so that these operatiosn do not produce gigantic pipeline bubbles anymore)


I must admit I couldn't believe that 'GL wouldn't provide something as basic as that in PS - given that the hardware is obviously capable.

... now I just wonder if Cg is going to hack it (I wanted to use it so I could use the same shader for both DirectX and OpenGL)

edit: arg. Just read through most of http://www.opengl.org/registry/specs/ARB/GLSLangSpec.Full.1.20.6.pdf and I can't see a single mention of texture reads :(

edit2: can glBlendFunc and glBlendMode be used at the same time as fragment programs?

[Edited by - rabidh on August 18, 2006 1:04:50 PM]

Share this post


Link to post
Share on other sites
just went to post this and saw your post. They metion it, but not in a good way :(

1.10 Spec #59 from http://oss.sgi.com/projects/ogl-sample/registry/ARB/GLSLangSpec.Full.1.10.59.pdf:

23) Should the fragment shader be allowed to read the current location in the frame buffer?
DISCUSSION: It may be difficult to specify this properly while taking into account multisampling. It also may be quite difficult for hardware implementors to implement this capability, at least with reasonable performance. But this was one of the top two requested items after the original release of the shading language white paper. ISVs continue to tell us that they need this capability, and that it
must be high performance.
RESOLUTION: Yes. This is allowed, with strong cautions as to performance impacts.
REOPENED on December 10, 2002. There is too much concern about impact to performance and
impracticallity of implementation.
CLOSED on December 10, 2002.

43) What is definition of built-in derivative functions of gl_FB*?
...
Possible resolutions:
a) Don't allow gl_FB* read operations in the fragment processor. (This interacts with Issue (23).)
b) The built-in derivative functions are undefined if a gl_FB* is a parent of an expression. (The builtin
derivative functions are in some cases undefined within the body of a conditional or loop.)
Rejected resolutions:
c) Explicitly define the order which fragments are rasterized by OpenGL.
RESOLUTION: gl_FB* have been removed. Issue 23 has been reopened and closed as disallowing
frame buffer reads.
CLOSED on December 11, 2002.

bummer. It was looking promising for a while.

Share this post


Link to post
Share on other sites
Okay, to clear up a few things here:

* FB reads are not allowed in fragment shaders, because current hardware doesn't support them (it would create a huge performance problem). D3D doesn't offer them either.

* The only part of the hardware in the render pipeline that can read from the framebuffer is the blending stage.

* Register combiners could not access the framebuffer values either.

You can use FBOs (framebuffer objects) to render into a texture. Later on, you bind this texture as an input and do the blending in your fragment shader. Sampling a texture while rendering to it is theoretically possible, but will exhibit completely undefined behaviour on current hardware.

Share this post


Link to post
Share on other sites
Cheers Yann. Thinking about it I must have done the A+B-0.5 in the register combiner using textures :(

What exactly can I do in the blending stage while using pixel shaders? do glBlendMode/glBlendFunc still work as expected - I was pretty sure glBlendFunc didn't work for me.

Can I still do glBlendFunc(GL_ONE,GL_ONE) while using pixel shaders? What happens if I don't clamp the outputs of the pixel shader so I can get negative values out? (is it even possible?) Will that subtract from the destination surface?

Share this post


Link to post
Share on other sites
Quote:
Original post by rabidh
What exactly can I do in the blending stage while using pixel shaders? do glBlendMode/glBlendFunc still work as expected - I was pretty sure glBlendFunc didn't work for me.

Alpha blending is not dependent on the fragment shading model, it usually works as expected even when a fragment shader is enabled. I said 'usually', because behaviour is dependent on the destination surface type. When writing to a standard RGBA surface (such as the framebuffer), blending works exactly the same way as it does with the fixed function pipeline. However, when writing to a floating point target surface, blending might or might not be available, depending on your hardware. Although all the latest graphics chipsets from both NV and ATI now support floating point blending.

Quote:
Original post by rabidh
Can I still do glBlendFunc(GL_ONE,GL_ONE) while using pixel shaders?

Yes, sure.

Quote:

What happens if I don't clamp the outputs of the pixel shader so I can get negative values out? (is it even possible?) Will that subtract from the destination surface?

It depends on the type of target surface. When using a 32bit RGBA surface, then the values will be automatically clamped to the [0..1] range. When using a floating point surface, then negative values are possible, and will in fact subtract from the target surface.

Also, keep in mind that the blending stage has been extended multiple times in the past. This additional functionality is exposed as extensions. EXT_blend_subtract, for example. Or EXT_blend_func_separate, NV_blend_square, or EXT_blend_equation_separate. Maybe one of these will help you achieve the results you need (support for these extensions will vary amongst chipsets, though, so check your extension string).

Share this post


Link to post
Share on other sites
Quote:
Original post by rabidh
Can I still do glBlendFunc(GL_ONE,GL_ONE) while using pixel shaders?

Of course you can. Blending appears after pixel shading is done. Fell free to use all blending functions you like.

Quote:
What happens if I don't clamp the outputs of the pixel shader so I can get negative values out? (is it even possible?)

Most probably GPU will clamp it to the valid range [0; 1].

Cheers!

Share this post


Link to post
Share on other sites
Thanks for the replies everyone - that looks really promising.

Do I have to do anything special to allow negative values into the blendfunc when writing to a floating point buffer, or does it all just happen automatically?

From what I could gather NVidia card generally won't blend to 32 bit floating point buffers, but will to 16 bit ones. Whats the state of play for ATI? (specifically the 9600 - i have a feeling I may need an upgrade!)

Share this post


Link to post
Share on other sites
Quote:
Original post by Lord Faron
Radeon 9500-9800 doesn't support fp blending. I don't know about X series.


X800 doesn't either, X1800 and X1900 do however (i think it's only 16bit as well, I'll have to check)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this