OpenGL: Combining glBlendFunc with glAccum - opengl

I've been working on a graphics project doing Depth of Field. The method is doing several passes, each rendering the scene with different near and far clipping-parameters, such that it renders different depth ranges at each pass.
The idea is to apply a blur kernel on each individual layer by rendering to a texture and doing the blur on a rendered quad (with the texture). This is all fairly basic stuff. As is working fine. However, the part I can't get working is the combining of the layers:
The color buffer is cleared with color4(0,0,0,0) before each pass is drawn. However, the accumulation does not seem to allow the usage of glBlendFunc such that it accumulates taking the alpha channel into account (i.e. glBlendFunc(GL_SRC_ALPHA, GL_SRC_ONE_MINUS_ALPHA)).
The question is then:
- Does the glBlendFunc affect the glAccum?
- If not, how can I work around this?
Based on the documentation, this doesn't seem to be the case as it is not mentioned, however it feels this is a very useful feature.
Regards,
R

Your question doesn't explain why you need blending and accum, so this answer may not be real useful. The accum buffer does not blend. But there are two routes that might be useful:
Most modern hardware can do "Separate" blending, so you can, for example, do an additive operation on the alpha channel while doing real blending on the framebuffer.
Many modern setups will let you render to multiple draw buffers at the same time, sometimes with separate blending modes.
So you might be able to use a second framebuffer via an FBO as sort of a "fake accum buffer", using a blending mode to "accumulate". If you can find a blending mode that is close enough to the accumulate operation you want, you might be able to take advantage of the blend equation.
Take a look at these GL extensions:
http://www.opengl.org/registry/specs/ARB/draw_buffers.txt
http://www.opengl.org/registry/specs/ARB/draw_buffers_blend.txt
http://www.opengl.org/registry/specs/EXT/draw_buffers2.txt

Related

A opengl texture transparent hack

I wish to make an opengl universal texture transparent hack for the DxWnd tool (an open-source program hosted o SourceForge). The hack should work for every program using opengl to render RGBA textures. DxWnd cah hook and redirect all calls from libraries, including opengl32.dll.
I've read and tried to implement all suggestions about making a texture transparent, including enabling GL_BLEND, disabling GL_CULL_FACE and setting glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). In addition, there's a routine that enforces the alpha bits of all texture pixels.
I expected that, once finished, the result should be a semi-transparent scene, but that doesn't happen.
For instance, the following is a 3d scene from gl hexen II:
and this is the final result, with some textures not transparent and most pixel colors lost:
Just to demonstrate that DxWnd is able to manipulate color pixels (so that this should not be the cause of the problem) this is the same scene with a filter that recolors every texture:
What could be the reason of the problem? How should I fix it? Please, be aware that since DxWnd is hooking a generic program, it may easily have to confront with opengl calls that have an opposite purpose!
What you want is not generally possible just from hooking onto some other application.
You may be able to force blending to be on. But correct transparent rendering is a fundamentally different task from rendering an opaque scene. Because alpha-blended transparency is based on doing per-triangle blending operations with the background, it only really works if you render everything in a back-to-front order.
But as far as the program is concerned, it thinks it is doing opaque rendering. So it's going to render in the order it sees fit to use. Which for more modern applications is probably front-to-back, to take advantage of early depth testing.
And that's the exact opposite order you need to make transparency work. And there's no generic way to control the order of rendering just by hooking onto a few OpenGL functions.
Furthermore, applications tend to try to avoid rendering parts of the scene that are obviously not visible. So if the application thinks that a particular room is not visible because the door to that room isn't visible, then the room and its contents won't be rendered. So even if you could get the order of rendering correct, you'd also need to make the program change what it renders in order to correctly see through stuff.
It should also be noted that doing alpha blending requires that the fragments being rendered have a useful alpha value. But most fragment computations for opaque surfaces will have an alpha value of 1.0. And thus: no blending. And, unless you're dealing with fixed-function OpenGL rendering, or you're willing to manually patch shaders to add your own alpha uniform values, there's no way to change this from outside of the application.

Can I carry out MSAA for deferred rendering by just rendering the geometry twice?

I have question about 3D rendering.
Deferred rendering is very powerful but popular for not being nice to MSAA.
I clearly see why, but I suddenly came up some idea to solve that.
It's simple : just do deferred rendering completely, and get screen image on texture. This texture(attached on framebuffer or whatever) is of course not-antialiased.
Here comes further processing : then next, draw full scene again but this time fragment shader looks up the exact same position on pre-rendered texture using texelFetch(). And output that. Done.
It's silly but I think it might work. If we draw the geometry again with deferred-rendered result as the output color, it means we re-render the scene with geometry.
So we can now provide super-sampled depth information, and the GPU will be able to perform MSAA with aliased color but super-sampled depth geometry. (It's similar with picking up only the 'center' of fragment and evaluating that on ordinary MSAA process).
I'm not sure whether this description makes sense or not. I tested using opengl, but doing that makes no difference with just deferred-rendering.
Does my idea work?
No, your idea does not work.
If you did not render the initial image with multisampling, reading from it later while doing multisampling will not magically create information that doesn't exist in that image.
In your method, every sample which corresponds to a particular pixel in the multisampled rendering will have the same color value. So if two primitives overlap in a pixel, writing to different samples, it won't matter, since both primitives will be generating the same color. All you would be doing is generating multiple different depth values within a pixel, and that doesn't actually contribute to an antialiased output (directly).

My own z-buffer

How I can make my own z-buffer for correct blending alpha channels? I'm using glsl.
I have only one idea. And this is use 2 "buffers", one of them storing depth-component and another color (with alpha channel). I don't need access to buffer in my program. I cant use uniform array because glsl have a restriction for the number of uniforms variables. I cant use FBO because behaviour for sometime writing and reading Frame Buffer is not defined (and dont working at any cards).
How I can resolve this problem?!
Or how to read actual real time z-buffer from glsl? (I mean for each fragment shader call z-buffer must be updated)
How I can make my own z-buffer for correct blending alpha channels?
That's not possible. For perfect order-independent transparency you must get rid of z-buffer and replace it with another mechanism for hidden surface removal.
With z-buffer there are two possible ways to tackle the problem.
Multi-layered z-buffer (impractical with hardware acceleration) - basically it'll store several layers of "depth" values and will use it for blending transparent surfaces. Will hog a lot of memory, and there will be maximum number of transparent overlayying surfaces, once you're over the limit, there will be artifacts.
Depth peeling (google it). Order independent transparency, but there's a limit for maximum number of "overlaying" transparent polygons per pixel. Can actually be implemented on hardware.
Both approaches will have a limit (maximum number of overlapping transparent polygons per pixel), once you go over the limit, scene will no longer render properly. Which means the whole thing rather useless.
What you could actually do (to get perfect solution) is to remove the zbuffer completely, and make a graphic rendering pipeline that will gather all polygons to be rendered, clip them, split them (when two polygons intersect), sort them and then paint them on screen in correct order to ensure that you'll get correct result. However, this is hard, and doing it with hardware acceleration is harder. I think (I'm not completely certain it happened) 5 ot 6 years ago some ATI GPU-related document mentioned that some of their cards could render correct scene with Z-Buffer disabled by enabling some kind of extension. However, they didn't say a thing about alpha-blending. I haven't heard about this feature since. Perhaps it didn't become popular and shared the fate of TruForm (forgotten). Also such rendering pipeline will not be able to some things that are possible on z-buffer
If it's order-independent transparencies you're after then the fundamental problem is that a depth buffer stores on depth per pixel but if you're composing a view of partially transparent geometry then more than one fragment contributes to each pixel.
If you were to solve the problem robustly you'd need an ordered list of depths per pixel, going back to the closest opaque fragment. You'd then walk the list in reverse order. In practice OpenGL doesn't do things like variably sized arrays so people achieve pretty much that by drawing their geometry in back-to-front order.
An alternative embodied by GL_SAMPLE_ALPHA_TO_COVERAGE is to switch to screen-door transparency, which is indistinguishable from real transparency either at a really high resolution or with multisampling. Ideally you'd do that stochastically, but that would void the OpenGL rule of repeatability. Nevertheless since you're in GLSL you can do it for yourself. Your sampler simply takes the input alpha and uses that as the probability that it'll output the final pixel. So grab a random value in the range 0.0 to 1.0 from somewhere and if it's greater than the alpha then discard the pixel. Always output with an alpha of 1.0 and just use the normal depth buffer. Answers like this say a bit more on what you can do to get randomish numbers in GLSL, and obviously you want to turn multisampling up as high as possible.
Eric Enderton has written a decent paper (which has a slide version) on stochastic order-independent transparency that goes alongside a DirectX implementation that's worth checking out.

Defining a custom Blend Function (OpenGL)

For implementing a physically accurate motion blur by actually rendering at intermediate locations, it seems that to do this correctly I need a special blending function. Additive blending would only work on a black background, and the standard "transparency" function (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) may look okay for small numbers of samples, but it is physically inaccurate because samples rendered at the end will contribute more to the resulting color.
The function I need has to produce a color which is the weighted average of the original and destination colors, depending on the number of samples covering a fragment. However I can generalize this to better account for rendering differences between samples: Suppose I am to render a blurred object n times. Treating color as a 3-vector, Let D be the color DEST - SRC. I want each render to add D/n to the source color.
Can this be done using the fixed-function pipeline? The glBlendFunc reference is rather cryptic, at least to me. It seems like this can be done either trivially or is impossible. It seems like I would want to set alpha to 1/n. For the behavior I just described, am I in need of a GL_DEST_MINUS_SRC_COLOR option?
I also have a related question: At which stage does this blending operation occur? Before or after the fragment shader program? Would i be able to access the source and destination colors in a fragment shader?
I know that one way to accomplish what I want is by using an accumulation buffer. I do not want to do this because it is a waste of memory and fillrate.
The solution I ended up using to implement my effect is a combination of additive blending and a render target that I access as a texture from the fragment shader.

Best way to do alpha blending with OpenGL?

I'm drawing 2D Polygons, actually I'm drawing lots of triangles and using GLUOrtho2D. I noticed that by zooming out I got much better frame rates. I realized I was maxing out the graphics card's fill rate, not drawing too many polygons as I had initially suspected. I think this is because I'm drawing lots of overlapping polygons and using
glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Is this the blend function I should be using? How could I minimize the filling given the nature of what I'm doing? I tried enabling the GL_DEPTH_TEST and Z ordered my polygons, but since I alpha blend, this won't help. What is the most efficient way of doing this sort of thing?
Thanks
I doubt using a different blend function would help. One generally chooses the correct blend function based on desired output, not performance.
Are all the polygons you render transparent/translucent? If not, it might help to separate the rendering of those apart from the opaque polygons you have and set the proper GL states accordingly.
Also are these textured polygons? You might be able to optimize your texture handling (ex: reduce context switches, use more efficient image formats, etc).
Finally, how are you rendering these triangles? If in immediate mode or using vertex arrays, consider using VBOs.
avoid alpha blending on as many triangles as possible. It adds up and yes, it gets really expensive. There is no magic high-performance blend function.
The only solution is "use less blending and more z-buffering"
Changing blend function leads only to changes in blending coefficients, but not in equation.
Anyways, modern videocards do not use hardcoded equations. You could try to write a pixel shader that satisfies your needs.
BTW, consider using VBO's for yours "lots of triangles" if you still don't.