How do I add an outline to a 2d concave polygon? - opengl-es

I'm successfully drawing the convex polys which make up the following white concave shape.
The orange color is my attempt to add a uniform outline around the white shape. As you can see it's not so uniform. On some edges the orange doesn't show at all.
Evidently using...
glScalef(1.1, 1.1, 0.0);
... to draw a slightly larger orange shape before I drew the white shape wasn't the way to go.
I just have a nagging feeling I'm missing a more simple way to do this.
Note that the white part is going to be mapped with a texture which has areas of transparency, so the orange part needs to be behind the white shapes too, not just surrounding them.
Also, I'm using a parallel projection matrix, that's why glScalef's z is set to 0.0 - reminds me there is no perspective scaling.
Any ideas? Thanks!

Nope, you wont be going anywhere with glScale in this case. Possible options are
a) construct an extruded polygon from the original one (possibly rounding sharp corners)
b) draw the polygon with GL_LINES and set glLineWidth to your desired outline width (in fact you might want to draw the outline with 2x width first)
The first approach will generate CPU load, the second one might slow down rendering significantly AFAIK.

You can displace your polygon in the 8 directions of the compass.
You can have a look at this link: http://simonschreibt.de/gat/cell-shading/
It's a nice trick, and might do the job

Unfortunately there is no simple way to get an outline of consistent width - you just have to do the maths:
For each edge: calculate the normal, scale to the desired width, and add to the edge vertices to get a line segment on the new expanded edge
Calculate the intersection of the lines through two adjacent segments to find the expanded vertex positions

A distinct answer from those offered to date, posted just for interest; if you're in GLES 2.0 have access to shaders then you could render the source polygon to a framebuffer with a texture bound as the colour renderbuffer, then do a second parse to write to the screen (so you're using the image of the white polygon as the input texture and running a post-processing pixel shader to every pixel on the screen) with a shader that obeys the following logic for an outline of thickness q:
if the input is white then output a white pixel
if the input pixel is black then sample every pixel within a radius of q from the current pixel; if any one of them is white then output an orange pixel, otherwise output a black pixel
In practise you'd spend an awful lot on texture sampling and probably turn that into the bottleneck. And they'd be mostly dependent reads, which are bad for the pipeline on lots of GPUs — including the PowerVR SGX that powers the overwhelming majority of OpenGL ES 2.0 devices.
EDIT: actually, you could speed this up substantially; if your radius is q then have the hardware generate mip maps for your framebuffer object, take the first one for which the output pixels are at least q by q in the source image. You've then essentially got a set of bins that'll be pure black if there were no bits of the polygon in that region and pure white if that area was entirely internal to the polygon. For each output fragment that you're considering might be on the border you can quite possibly just straight to a conclusion of definitely in or definitely out and beyond the border based on four samples of the mipmap.

Related

How to draw Bézier curves with Quartz with a quality equivalent to the default implementation?

I am drawing Bézier curves with my own code. Basically, I am computing a large number of points which I join with a CGPath. But even with the same line width, I can't achieve the same quality as the default implementation. The edge of the stroke is a bit blurry due to anti-aliasing. The stroke is not bad looking, but I notice that on Apple rendering, the anti-aliasing looks different; the width of the antialiasing zone (where the pixels are neither of the color of the stroke, nor the the color of the background) is lesser.
Spying a little with Instruments shows that UIBezierPath's stroke spends some time in libRIP, but I can't find what it is exactly.
I have drawn an ellipse myself, using sin, and cos operations. My ellipse looks as good as the original.
I know that there is a problem when drawing over an gradient. Is that the case in your case?
If you're plotting a large number of points, you might be getting darker anti-aliasing edges because you're over-plotting. I can't find a good image online to describe it, but if you plot from A -> B and then A -> B again, both lines might generate, say, 30% gray partial pixels, which will then be blended together resulting in 60% gray.
You may not think you're doing that, but if you have a high density of points then you might be ending up with overlapping components (and especially if you are plotting separate line segments you'll have your capping etc. overlapping).
Probably worth posting some sample code and screenshots taken with Pixie or xScope so we can see what's happening.

How to draw "glowing" line in OpenGL ES

Could you please share some code (any language) on how draw textured line (that would be smooth or have a glowing like effect, blue line, four points) consisting of many points like on attached image using OpenGL ES 1.0.
What I was trying was texturing a GL_LINE_STRIP with texture 16x16 or 1x16 pixels, but without any success.
In ES 1.0 you can use render-to-texture creatively to achieve the effect that you want, but it's likely to be costly in terms of fill rate. Gamasutra has an (old) article on how glow was achieved in the Tron 2.0 game — you'll want to pay particular attention to the DirectX 7.0 comments since that was, like ES 1.0, a fixed pipeline. In your case you probably want just to display the Gaussian image rather than mixing it with an original since the glow is all you're interested in.
My summary of the article is:
render all lines to a texture as normal, solid hairline lines. Call this texture the source texture.
apply a linear horizontal blur to that by taking the source texture you just rendered and drawing it, say, five times to another texture, which I'll call the horizontal blur texture. Draw one copy at an offset of x = 0 with opacity 1.0, draw two further copies — one at x = +1 and one at x = -1 — with opacity 0.63 and a final two copies — one at x = +2 and one at x = -2 with an opacity of 0.17. Use additive blending.
apply a linear vertical blur to that by taking the horizontal blur texture and doing essentially the same steps but with y offsets instead of x offsets.
Those opacity numbers were derived from the 2d Gaussian kernel on this page. Play around with them to affect the fall off towards the outside of your lines.
Note the extra costs involved here: you're ostensibly adding ten full-screen textured draws plus some framebuffer swapping. You can probably get away with fewer draws by using multitexturing. A shader approach would likely do the horizontal and vertical steps in a single pass.

Algorithm for "neon glow" graphics programming

I am searching for an article or tutorial that explains how one can draw primitive shapes (mainly simple lines) with a (neon) glow effect on them in the graphical output of a computer program. I do not want to do some sophisticated stuff like for example in modern first pirson shooters or alike. I am more in a search for a simple solution, like the lines in that picture: http://tjl.co/blog/wp-content/uploads/2009/05/NeonStripes.jpg -- but of course drawn by a computer program in my case.
The whole thing should run on a modern smart phone, so the hardware is a bit limited.
I do know a bit about OpenGL, but not too much, so unfortunately I am a bit lost here. Did some research on Google ("glow effect algoritm" and similar), but found either highly complex stuff for 3D games, or tutorials for Photoshop & co.
So what I would really need is an in-depth article on that subject, but not on a very advanced level. I hope thats even possible... I have just started with OpenGL, did some minor graphics programming in the past, but I am a long-year programmer now, so I would understand technical papers in general.
Does anyone of you know of such an article/paper/tutorial/anything?
Thanks in advance for all good advices!
Cheers!
Matthias
Its jus a bunch of lines with different brightness/transperency. Basically, if you want a glow effect for 1px line, in a size of 20 pixels, then you draw 41 lines with width of 1 px. The middle line is with your base colour, other lines get colours that gradiently go from base color to 100% transperency (like in your example) or darkest colour variant (if you have black background, no transparency).
That is it. :)
This isn't something I've ever done, but looking at your example, the basic approach I'd use to try and recreate it would be...
Start with an algorithm for drawing a filled shape large enough to include the original shape and the glow. For example, a rectangle becomes a slightly larger rectangle, but with rounded corners. An infinitessimally-wide line becomes a thickened line with semi-circular caps. Subtract out the original shape (and fill the pixels for that normally).
For each pixel in the glow, the colour depends on the shortest distance to any part of the original shape. This normally reduces to the distance to the nearest point on a line (e.g. one edge of a rectangle).
The distance is translated to a colour value using probably Hue-Saturation-Value or a similar colour scheme, as well as reducing alpha (increasing transparency). For neon glows, you probably want constant hue, decreasing brightness, maybe increasing saturation, and decreasing alpha.
Translate the HSV/whatever colour value to RGB for output. See this question.
EDIT - I should probably have said HSL rather than HSV - in HSL, if L is at it's maximum value, the resulting colour is always white. For HSV, that's only true if saturation is also at zero. See http://en.wikipedia.org/wiki/HSL_and_HSV
The real trick is that even on a phone these days, I'd guess you probably should use hardware (shaders) for this - sorry, I don't know how that's done.
The "painters algorithm" overlaying of gradually smaller shapes that others have described here is also a possibility, but (1) possibly slower, depending on implementation issues, and (2) you may need to draw to an off-screen buffer, with some special handling for the alpha channel, then blit back to the screen to handle the transparency correctly - if you need transparency, that is.
EDIT - Silly me. An alternative approach is to apply a blur to your original shape (in greyscale), but instead of writing out the blurred pixels directly, apply the colour-transformation to each blurred pixel value.
A blur is basically a weighted moving average. Technically, a finite impulse response filter is implemented using a convolution, but the maths for that is a tad awkward and if you just want "a blur" of about the right size, draw a grayscale circle of pixels as your "weights" image.
The blur in this case basically replaces the distance-from-shape calculation.
_____________________
| |
----|---------------------|-----> line
|_____________________|
gradient block
Break up your line into small non-overlapping blocks. Use whatever graphics primitive you have to draw a tilted rectangular gradient: the center is at 100% and the outer edge is at 0%.
Don't draw it on the image yet; you want to blend it with the image. Using regular transparency will just make it look like a random pipe or pole or something (unless you draw a white line, and your background is dark).
Here are two choices of blending mode:
color dodge: [blended pixel value] = (1-[overlay's pixel value]) / [bottom pixel value]
linear dodge: [blended pixel value] = max([overlay's pixel value]+[bottom pixel value], 1)
Then draw the line above the glow.
If you want to draw a curved "neon" line, simply draw it as a sequence of superimposed "neon dots" where each "neon dot" is a small circular image with transparency going from 0% at the origin to 100% at the edge of the circle.

Drawing Stippled Lines using OpenGL-ES

I have an application that draws 3-d map view marked up lines that show various features.
I am porting the map over to an OpenGL-ES architecture, but am having a bit of trouble working out how to display dashed lines.
Doing a lot of googling, I've found many references to the idea that drawing dashed lines and polygons were removed from OpenGL-ES as they can be easily emulated using textures triangles. That's great, but I can't find anyone that actually does this emulation and/or has a description of the steps involved.
An example, of one problem I have encountered trying to prototype out this concept is perspective squeezes my lines to invisible as they go towards the horizon. Using LINE_STRIP, this doesn't happen, and the lines remain a constant width in the map.
Any advice on how to achieve dashed constant width lines in a perspective view would be much appreciated.
I believe you can apply a texture to a line, not just a triangle. You'll need to set texture coordinates for each end of the line; the texture will be interpolated linearly along the line.
The effectiveness of this solution should be invariant of whether you use lines or line strips - line strips are just a way to create lines with fewer vertices.
There is one other problem: the tendency of the texture pattern to become compact as a line goes away from the camera. This happens because texture coordinate interpolation is perspective-correct even for lines (see section 3.5 of the GL spec).
There are two ways to get around this:
If you can calculate a "q" coordinate for your texture that undoes the perspective, you can restore screen-space texturing. This technique is probably too performance-expensive.
You can project the texture in eye space (e.g. glTexGen).
Texture coordinate generation is of course not available in GLES 1.1, but if you are using vertices by array, you can fake it by:
Setting your texture coordinate array to be your vertex coordinate array and
Using the texture matrix to "transform" the vertices.
The disadvantage of this technique is that the texture pattern will be in fixed screen space - that is, the texture won't run across the lines.
If all you want is to draw dashed lines, just change from GL_LINE_STRIP to GL_LINES. That way, open GL will connect vertices 1&2, 3&4, 5&6, but not 3&4, or 4&5 leaving spaces there. It will in essence be a half/half ratio dotted line-- the rough equivalent of glLineStipple(1, 0101);
IE: in the vertex array
[0,0,1,1,2,2,3,3,4,4,5,5,6,6]
OpenGL will connect (0,0) to (1,1), but will not connect (1,1) to (2,2) [whereas it would with GL_LINE_STRIP]. It will then connect (3,3) to (4,4), but NOT (4,4) to (5,5). The final connection will be (5,5) to (6,6).
This is what it looks like when I did it:
Dotted Lines on Android
The line is not 50/50 dotted/empty because in my case, it represents the position of a game entity each game frame-- and game frames are not necessarily all of equal length, thus the inconsistent line:space ratio.
The code looks like this to draw it:
public void draw(GL10 gl)
{
gl.glDisable(GL10.GL_TEXTURE_2D);
gl.glColor4f(color[0], color[1], color[2], color[3] / fade);
//pointsBuffer holds the points on the line
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, pointsBuffer);
gl.glDrawArrays(GL10.GL_LINES, 0, points.length/2);
gl.glEnable(GL10.GL_TEXTURE_2D);
}
An alternative idea to create a more intentionally patterned stipple would be to skip certain vertices by instead drawing with an indices array (glDrawElements). However, I don't have an example of that to show you. :/

Bresenham line algorithm (thickness)

I was wondering if anyone knew of any algorithm to draw a line with specific thickness, based on Bresenham's line algorithm or any similar.
On a second thought, I've been wondering about for each setPixel(x,y) I'd just draw a circle, e.g.:
filledCircle(x,y,thickness); for every x,y but that would of course be very slow. I also tried to use dictionary but that would fill the memory in no time. Check the pixels I'm about to draw on if they have the same color, but that's also not efficient enough for large brushes.
Perhaps I could somehow draw half circles depending on the angle?
Any input would be appreciated.
Thanks.
duplicate: how do I create a line of arbitrary thickness using Bresenham?
You cannot actually draw circles along the line. This approach is patented. :)
You can still read patent for inspiration.
I don't know what is commonly used, but it seems to me that you could use Bresenham for the 1-pixel-wide line, but extend it a set number of pixels vertically or horizonally. For instance, suppose your line is roughly 30 degrees away from the horizontal, and you want it to be four pixels wide. You calculate that the vertical thickness of the line should be five pixels. You run Bresenham, but for each pixel (x,y), you actually draw (x,y), (x,y+1), ... (x,y+4). And if you want the ends of the line to be rounded, draw a circle at each end.
For overkill, make a pixel map of the stylus (a circle or diagonal nib, or whatever), then draw a set of parallel Bresenham lines, one for each pixel in the stylus.
There are variations on Bresenhams which calculate pixel coverage, such as those used in the anti-grain geometry libraries; whether you want something that quality - you don't say what the output medium is, and most systems more capable than on-off LCDS support pens with thickness anyway.

Resources