Sub pixel drawing with opengl - c++

I am drawing lots of small black rectangles to the white screen and as they move about and zoom it doesn't look very graceful.
How can I draw them so if the edge lies between pixels, the pixels will be grey rather than black?

Sub-pixel rendering is actually more complicated than regular anti-aliasing. If you're using a display with pixels in RGB format, then a gray shape ending halfway through a pixel might be rendered as yellow or as cyan, depending on which side of the pixel the shape lies. This can look strange when the resulting image is not drawn in native resolution or on a display with a different layout than expected, but otherwise it can look quite nice.
Here is a sample of sub-pixel rendering applied to text; the left panel is color, the center panel is the displayed version of the color, and the right panel is the perceived brightness. Notice that accuracy in hue is exchanged for accuracy in brightness.
One approach might be to render each channel separately, each slightly offset in rendering space by the appropriate amount, so that the combined image is in full color. Each of the channels must be the same resolution as the resulting image; each channel is rendered with anti-aliasing the same way as the original would have been, except the other colors are ignored. Once the channels are created, they can be combined with simple addition. I don't know of a "pure" solution like the glEnable/glHint versions available for normal anti-aliasing, but it may exist or may in the future.

glEnable(GL_SMOOTH); should do it.

What you are effectively asking for is anti-aliasing,and there are numerous ways of doing it. One way is summarized in this gamedev topic: http://www.gamedev.net/topic/107637-glenablegl_polygon_smooth/.
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_POINT_SMOOTH, GL_NICEST);
glHint(GL_LINE_SMOOTH, GL_NICEST);
glHint(GL_POLYGON_SMOOTH, GL_NICEST);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);

Related

Filling GL_LINE_STRIP gaps when thickness > 1 destroys transparency

I am using GL_LINE_STRIP and glLineWidth to draw lines.
However, this leads to gaps between the single, straight segments of the strip.
I had mitigated the problem by using Catmull-Rom Splines and thus the segments where smooth enough to not notice the gaps anymore:
But now I noticed the gaps are different depending on the OpenGL implementation. Mesa introduces larger gaps than my graphic card, notice the gaps in the upper part and how the lower part with much smaller segments is noticeably darker due to more gaps:
Please note that image 1 and 2 are the same render code, the opacity is 255 in both cases, just the used opengl32.dll differs.
I then added the drawing of every joint as point:
glBegin(GL_LINE_STRIP);
for (auto p : interpolatedPoints) {
glVertex2f(p.x, p.y);
}
glEnd();
glBegin(GL_POINTS);
for (auto p : interpolatedPoints) {
glVertex2f(p.x, p.y);
}
glEnd();
This works for opacity 255 but not if I want to reduce the objects transparency. What happens then, is that the transparent point overlays the transparent line strip, thus increasing the opacity especially in areas with very short strips:
Solution 1: Polyline quadstrip
Ditching GL_LINE_STRIP altogether and triangulate the line strip ourselves seems the solution here but this looks like a larger rewrite for me - either I need a new shader or I need to calculate the triangles.
Solution 2: Blending
Wanting to avoid the rewrite, I was wondering: can blending solve the issue? Currently I use
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Is there a blending configuration which would prevent the points to add on the alpha channels of the lines? I tried some other constants here but I had no success. Please note also that the black background in the screenshots may not be black at all but contain other objects and textures which should be "correctly" overlayed by the semi-transparent line.
As a potential easy fix, you could try setting glHint(GL_LINE_SMOOTH_HINT, GL_NICEST) and see if that helps.
If you want your lines to look nice when drawn transparently, I suggest drawing all your lines onto a separate framebuffer than the rest of your scene, reusing the same depth buffer, and with full opacity. Then draw the lines framebuffer onto the rest-of-your-scene framebuffer with partial transparency.

OpenGL bitmap alpha buffer

I have two RGBA images (simple 2D raster of type GL_UNSIGNED_BYTE, not textures or anything) of the same scene, one sharp, one blurred. With the blurred image displayed, I need to create an effect where the sharp image shows through in one or more (possibly overlapping) circular areas, smoothly blending with the background blurred image around the edges of the circles. I used to do the following.
Call this at the initialization:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
For every circle, make a copy of the sharp image, assign new values for their alpha components, starting from 255 at the center of the circle, reducing it to 0 towards the edges. Then rendered them one by one with glDrawPixels(), starting from the blurred image. It works, but as the number of those circular areas grows, it is getting noticeably slow.
I was thinking of using some alpha buffers (don't know the correct term), so that I create a small image with a cut out alpha circle in the middle, render its alpha component at one or several places of the framebuffer, then somehow blend the blurred image and the sharp image with those pre-rendered alpha values. So I wrote this in my display() function:
//render the alpha-mask first, at one place for now
GLfloat rp[4];
glGetFloatv(GL_CURRENT_RASTER_POSITION, rp);
glRasterPos2f(0.2f, 0.2f); //just some arbitrary coordinates on the screen
glColorMask(false, false, false, true); //think I only need the alpha-channel
glBlendFunc(GL_ONE, GL_ZERO);
glDrawPixels(sharp_mask_width, sharp_mask_height, GL_RGBA, GL_UNSIGNED_BYTE, alpha_mask);
//render the blurred image, blending the the previously rendered alpha
glRasterPos2f(rp[0], rp[1]);
glColorMask(true, true, true, true); //all channels
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA); //make a hole where alpha mask had the maximum alpha
glDrawPixels(g_width, g_height, GL_RGBA, GL_UNSIGNED_BYTE, imageDataBlurred);
glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
glDrawPixels(g_width, g_height, GL_RGBA, GL_UNSIGNED_BYTE, imageDataSharp);
glFlush();
It seems I don't understand something important about all this blending stuff, because nothing is rendered at all, all I get is an empty screen. All I got is an effect remotely similar to what I need, messing with glBlendFunc parameters and blending rgb-s instead of alpha-s.
How, if at all, can it be done?
I know I will probably burn in hell for using outdated OpenGL in the year 2015, when programmable shaders rule the world and cure cancer, but if possible I'd much prefer an answer describing how to do it in old style OpenGL, so I don't have to change that crap of a legacy program too much...

How can I blend two colours to a mix of them in OpenGL?

I'm rendering both a blue and a red line (in the context of an anaglyph). When the red line and blue line overlap I want a purple color to be rendered instead of the line in front.
I am using OpenGL. Some of the code I have tried so far is this:
glBlendFunc(GL_ONE, GL_DST_ALPHA);
This causes the overlap to render white, and the line appears as follows:
I thought maybe using an RGB scale factor on top of this blend would be the right thing to do.
So I tried using the glBlendFuncSeparate which takes parameters:
Source Factor RGB
Destination Factor RGB
Source Factor Alpha
Destination Factor Alpha
I could not find parameters which made this work for me.
I also attempted using glBlendEquation with an additive equation, but didn't notice any success in that method.
How do I produce a function which successfully blends the two lines into a purple color?
Edit:
I've noticed that glBlendFunc(GL_ONE, GL_DST_ALPHA) does perform some blending to produce intermediate colors (the actual lines are just nonsensical here, it was just to display some blending).
I'm rendering both a blue and a red line (in the context of an anaglyph)
Not the answer you expect, but the answer you need: The usual approach to render anaglyph images in OpenGL is not to use blending. Blending is hard enough to get right, you don't want to mess things up further with the anaglyph part.
There are two commonly used methods:
Rendering each view into a FBO attached texture and combining them in a postprocessing step.
using glColorMask to select the active color channels for each rendering step.
I think for now you're good with the color mask method: Do it as following:
display:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glViewport(…)
# prepare left view
setup_left_view_projection()
glColorMask(1,0,0, 1); # red is commonly used for the left eye
draw_scene()
glClear(GL_DEPTH_BUFFER_BIT) # clear the depth buffer (and just the depth buffer!)
# prepare right view
setup_right_view_projection()
glColorMask(0,1,1, 1); # cyan is commonly used for the right eye
draw_scene()
The typical blend function is glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);; note that the final color changes according to the draw order.
Blend functions are not so obvious, so a graphical representation sometimes is better; check out for example this site.

is there any conflict between GL_DEPTH_TEST and alpha blending in openGL?

I'm drawing some "2D" pictures.
Let's say, pic A in the background draw first, pic B in foreground draw later than A.
and there are some transparent area in B.
So when i enable GL_DEPTH_TEST, B should cover A but those transparent area.
the actual result i got here is strange, the B did cover A, but the transparent area show the very background instead of A which it should be.
i use
glFrustum as GL_PROJECTION,
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA),
glDepthFunc(GL_LEQUAL)
is there some settings i missing or what?
There shouldn't be any conflict of the sort you discuss. The depth buffer can hold only one depth per pixel, so transparency can be an issue because it's not really accurate to say that each pixel is composed of data from a single depth.
The net effect is that if you draw something partially transparent then try to draw something behind it, the depth buffer says not to draw. So while you should be able to see the thing behind, you can't.
In your case, what you're seeing would be expected behaviour if you were drawing B (in the foreground) and then A (in the background). Is it possible some aspect of your code is giving you an unexpected drawing order?

OpenGL Alpha blending with wrong color

I am trying to create a simple ray tracer. I have a perspective view which shows the rays visibly for debugging purposes.
In my example screenshot below I have a single white sphere to be raytraced and a green sphere representing the eye.
Rays are drawn as lines with
glLineWidth(10.0f)
If a ray misses the sphere it is given color glColor4ub(100,100,100,100);
in my initialization code I have the following:
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_SRC_ALPHA);
You can see in the screen shot that for some reason, the rays passing between the perspective view point and the sphere are being color blended with the axis line behind the sphere, rather than with the sphere itself.
Here is a screenshot:
Can anyone explain what I am doing wrong here?
Thanks!!
Is it a possibility you cast those rays before you draw the sphere?
Then if Z-buffer is enabled, the sphere's fragments simply won't be rendered, as those parts of rays are closer. When you are drawing something semi-transparent (using blending), you should watch the order you draw things carefully.
In fact I think you cannot use Z-buffer in any sensible way together with ray-tracing process. You'll have to track Z-order manually. While we are at it OpenGL might not be the best API to visualize ray-tracing process. (It will do so possibly much slower than pure software ray-tracer)
You dont need the glAlphaFunc, disable it.
Light rays should be blended by adding to the buffer: glBlendFunc(GL_ONE, GL_ONE) (for premultiplied alpha, which you chose.
Turn off depth buffer writing (not testing) when rendering the rays: glDepthMask(GL_FALSE)
Render the rays last.
AlphaTest is only for discarding fragments - not for blending them. Check the spec
By using it, you are telling OpenGL that you want it to throw away the pixels instead of drawing them, so you won't can any transparent blending. The most common blending function is
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); You can also check out the OpenGL Transparency FAQ.