How to create a fill effect? I have an irregular closed shape created using:
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
(.......)
glVertexPointer(2, GL_FLOAT, 0, vertexBuffer);
glDrawArrays(GL_POINTS, 0, vertexCount);
(.......)
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
Now I would like to have an "fill/paint bucket" effect like in photoshop. The background inside the shape is white (for example) and by clicking inside the shape I want to change the color to red or green.
Can somebody give me some hints, please.
So you render a set of points and want OpenGL to "magically" fill the enclosed region. That's not possible. OpenGL doesn't realize that these points enclose some region. You don't even draw a line strip, it's just a set of points. Even a human has to put in a reasonable effort of thinking to see that the points "enclose" a region, let aside a computer, or just a simple interface for drawing points, lines and triangles onto the screen.
Instead of drawing points, just draw a polygon (use GL_POLYGON or GL_TRIANGLE_FAN instead of GL_POINTS). But if the enclosed region is non-convex that won't work in all cases. What you always have to realize is, that OpenGL is nothing more than a drawing API. It just draws points, lines and triangles to screen. Yes, with fancy effects, but all in all it just draws simple primitives. It doesn't manage any underlying graphics scene or something. The moment a primitive (like a single point, line or triangle) has been drawn, OpenGL doesn't remember it anymore.
What you want to achieve (given you at least change the point set to a line loop that really encloses a region), is not to be achieved by simple means. In the simplest case you need some kind of flood fill algorithm that fills the region you enclosed by the lines. But for this you don't profit from OpenGL in any way, as this requires you to analyse the image on the CPU and set individual pixels. And neither can shaders do this in a simple (or any?) way.
Related
I have a WebGL scene that wants to draw both point and line primitives, and am wondering: Is it possible to draw multiple WebGL primitives inside a single draw call?
My hunch is this is not possible, but WebGL is constantly surprising me with tricks one can do to accomplish strange edge cases, and searching has not let me confirm whether this is possible or not.
I'd be grateful for any insight others can offer on this question.
You can't draw WebGL lines, points, and triangles in the same draw call. You can generate points and lines from triangles and then just draw triangles in one draw call that happens to have triangles that make points and triangles that draw lines and triangles that draw other stuff all one draw call.
Not a good example but for fun here's a vertex shader than generates points and lines from triangles on the fly.
There's also this for an example of making lines from triangles
How creative you want to get with your shaders vs doing things on the CPU is up to you but it's common to draw lines with triangles as the previous article points out since WebGL lines can generally only be a single pixel thick.
It's also common to draw points with triangles since
WebGL is only required to support points of size 1
By drawing with triangles that limit is removed
WebGL points are always aligned with the screen
Triangle based points are far more flexible. You can rotate the point for example and or orient them in 3D. Here's a bunch of points made from triangles
Triangle based points can be scaled in 3D with no extra work
In other words a triangle based point in 3d space will scale with distance from the camera using standard 3D math. A WebGL point requires you to compute the size the point should be so you can set gl_PointSize and so requires extra work if you want it to scale with the scene.
It's not common to mix points, lines, and triangles in a single draw call but it's not impossible by any means.
I would like to set the width of a line that I'm drawing in Metal. I can set the size of a point with point_size as explained here:
https://developer.apple.com/library/prerelease/ios/documentation/Metal/Reference/MTLRenderCommandEncoder_Ref/index.html
But, I'm not sure how it works with lines.
Short answer would be there is no way to control line width in the same way as a point size in Metal. Even in OpenGL graphics API, the function to do this (which used to exist as gllinewidth function) is now deprecated.
An option would be to draw the line as a quad (a box), with two triangles. This would let you control the width of the line.
If you want to stick to the line primitive itself, for some particular reason, the equivalent OpenGL question has been asked on StackOverflow already as seen here. The shader can be simple translated to Metal shading API.
If you're dead set on using lines instead of drawing a 2D box with two rectangles you can draw multiple lines next to each other. You can do that by drawing the same two vertices multiple times with one drawPrimitives call, just increase the instanceCount to simulate the thickness and then in your vertex shader function you could use your vertex_id and a modulus operation or some other type of logic to translate the position of the line to simulate thickness. This will probably be a lot easier than trying to do something fancy in a fragment shader.
If you are drawing multiple lines, multiply your instanceCount by the thickness you want and adjust your vertex shader function logic to place those additional lines next to each other.
I experimented with this and found this to be a pretty cumbersome process. As you need additional math to position the extra lines to thicken correctly. For example if you're drawing a horizontal line and want to increase thickness by two you'd want to modify the y value, but if it's vertical you'd want to modify the x. Drawing at an angle gets more complicated. You'll also run into issues trying to match lengths with widths if you're attempting to draw shapes.
I think it's much better to just draw two triangles to make a rectangle to fake a line. The math will be much easier and simpler to understand.
In Geometry, Euclid's lines do not have any width, they only have length, the width they get during drawing is simply for representation. So while I think lines may be good for debugging and development, like for displaying vectors or creating a grid to see scale, they're not what you want if you're trying to style them to present them to users. In that case it's the wrong tool for the job.
I'm drawing triangles with only x and y coordinates per vertex:
glVertexPointer(2, GL_FLOAT, 0, vertices);
Sometimes when I draw a triangle over another triangle they seem to be coplanar and the surface jerks because they share the exact same surface in space.
Is there a way of saying "OpenGL, I want that you draw this triangle on top of whatever is below it" without using 3D coordinates, or do I have to enable depth test and use 3D coordinates to control a Z-index?
If you want to render the triangle just on top of whatever was in the framebuffer before, you can just disable the depth test entirely. But if you need some custom ordering different from draw order, then you won't get around adding additional depth information (in the form of a 3rd z-coordinate). There is no way to say to OpenGL "render the following stuff but with the z-coordinate collectively set to some value". You can either say "render the follwing stuff on top of whatever is there" or "render the following stuff on whatever depth results from its transformed vertices".
I am trying to draw a series of squares in XNA. I am looking at all these articles about TriangleStrips and DynamicVertexBuffers. But, not sure where to begin.
Current step
I am able to draw 1 square using VertexPositionColor, TriangleList and indices. Now I want to draw a series of squares with varying colors.
End Goal
Something to keep in mind is the number of such squares that I would like to be able to draw, eventually. If we assume a 5px width, on a 1920x1080 screen, we can calculate the number of squares to be (1920 * 1080) / 25 = 82944.
Any pointers on how to accomplish this would be great!
Generally, you can draw more squares in the same way you draw the first one. However, there will be a significant loss in performance.
Instead, you can add all triangles to one vertex buffer / index buffer. You already are able to draw two triangles as a triangle list. You should be able to easily adjust this routine to draw more than two triangles. Just add the according vertices and indices to the buffers and modify the draw call.
If you need vertices at the same position with different colors, you need to add two vertices to the buffer.
This way, the performance loss is very little, because you draw everything with only one draw call. Although the amount of triangles should be no problem for most graphic cards, some smaller or older ones can get into trouble. If so, you should consider changing your drawing strategy. Maybe it is not even necessary to draw that much triangles. But you can think about that, if the resulting performance is too low...
If you don't care about 3D, just 2D - you can use SpriteBatch to draw squares/rectangles on the screen. This will handle batching all the vertex/index buffer management for you.
I have a concave polygon I need to draw in OpenGL.
The polygon is defined as a list of points which form its exterior ring, and a list of lists-of-points that define its interior rings (exclusion zones).
I can already deal with the exclusion zones, so a solution for how to draw a polygon without interior rings will be good too.
A solution with Boost.Geometry will be good, as I already use it heavily in my application.
I need this to work on the iPhone, namely OpenGL ES (the older version with fixed pipeline).
How can I do that?
Try OpenGL's tessellation facilities. You can use it to convert a complex polygon into a set of triangles, which you can render directly.
EDIT (in response to comment): OpenGL ES doesn't support tessellation functions. In this case, and if the polygon is static data, you could generate the tessellation offline using OpenGL on your desktop or notebook computer.
If the shape is dynamic, then you are out of luck with OpenGL ES. However, there are numerous libraries (e.g., CGAL) that will perform the same function.
It's a bit complicated, and resource-costly method, but any concave polygon can be drawn with the following steps (note this methos works surely on flat polygons, but I also assume you try to draw on flat surface, or in 2D orthogonal mode):
enable stencil test, use glStencilFunc(GL_ALWAYS,1,0xFFFF)
disable color mask to oprevent unwanted draws: glColorMask(0,0,0,0)
I think you have the vertices in an array of double, or in other form (strongly recommended as this method draws the same polygon multiple times, but using glList or glBegin-glEnd can be used as well)
set glStencilOp(GL_KEEP,GL_KEEP,GL_INCR)
draw the polygon as GL_TRIANGLE_FAN
Now on the stencil layer, you have bits set >0 where triangles of polygon were drawn. The trick is, that all the valid polygon area is filled with values having mod2=1, this is because the triangle fan drawing sweeps along polygon surface, and if the selected triangle has area outside the polygon, it will be drawn twice (once at the current sequence, then on next drawings when valid areas are drawn) This can happens many times, but in all cases, pixels outside the polygon are drawn even times, pixels inside are drawn odd times.
Some exceptions can happen, when order of pixels cause outside areas not to be drawn again. To filter these cases, the reverse directioned vertex array must be drawn (all these cases work properly when order is switched):
- set glStencilFunc(GL.GL_EQUAL,1,1) to prevent these errors happen in reverse direction (Can draw only areas inside the polygon drawn at first time, so errors happening in the other direction won't apperar, logically this generates the intersectoin of the two half-solution)
- draw polygon in reverse order, keeping glStencilFunc to increase sweeped pixel values
Now we have a correct stencil layer with pixel_value%2=1 where the pixel is truly inside the polygon. The last step is to draw the polygon itself:
- set glColorMask(1,1,1,1) to draw visible polygon
- keep glStencilFunc(GL_EQUAL,1,1) to draw the correct pixels
- draw polygon in the same mode (vertex arrays etc.), or if you draw without lighting/texturing, a single whole-screen-rectangle can be also drawn (faster than drawing all the vertices, and only the valid polygon pixels will be set)
If everything goes well, the polygon is correctly drawn, make sure that after this function you reset the stencil usage (stencil test) and/or clear stencil buffer if you also use it for another purpose.
Check out glues, which has tessellation functions that can handle concave polygons.
I wrote a java classe for a small graphical library that do exacly what you are looking for, you can check it here :
https://github.com/DzzD/TiGL/blob/main/android/src/fr/dzzd/tigl/PolygonTriangulate.java
It receive as input two float arrays (vertices & uvs) and return the same vertices and uvs reordered and ready to be drawn as a list of triangles.
If you want to exclude a zone (or many) you can simply connect your two polygones (the main one + the hole) in one by connecting them by a vertex, you will end with only one polygone that can be triangulate like any other with the same function.
Like this :
To better understand zoomed it will look like :
Finally it is just a single polygon.