iOS Metal line width - ios

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.

Related

WebGL: Draw different geometric primitives within same draw call?

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.

Polygon(Quad) to Square Cells

I am really having a problem with this.
I have a polygon (a quad) which can be any shape. When my mouse is inside the polygon I need to find the x,y values of where my mouse is (inside the quad) as though the poygon were are perfect square. Further explanation; I have a 32x32 texture applied to the polygon and I need to know the x,y of the texture that the mouse is over.
I have some code that works for most shapes but which breaks if TR.Y is less than TL.y for instance.
I have some pretty simple code that tests whether the cursor is inside the polygon (via two triangle tests). But I cannot figure out how to use this to generate an x,y of a virtual square projection.
This problem is killing me. What is the name of operation i am trying to perform? Does anyone know of an explanation where the equations are presented in code form (any kind of code) (rather than just mathematical notation?). Any kind of help would be so appreciated.
I am on the verge of doing a 2nd render with specially formatted textures (each pixel having a unique value) so that I can just colour test to get an approximate x,y match (and precision is something that can be compromised here without causing too much trouble) - but then I will have to work around the DX Lib's attempt to blend and smooth the special texture as it is warped to fill the quad)
**Edit: Code that works for many quad shapes
It depends on method - how the texture is drawn at this quad.
If it uses perspective transform Square=>Quad, you have to use matrix of inverse transform Quad=>Square. Short article
For linear interpolation approach see this page

iOS: CGPath Line Drawing with dynamic width

I want to draw a line with dynamic width as shown in attached picture. What should be the best approach for this. ?
Updated:
My task is to draw line on finger move. And the line width is changes as speed of swipe is change. both (Line width and finger swipe speed) are directly proportional .
As the image you posted doesn't has any consistent height-width proportion to calculate and change, i doubt this cannot be achieved.
In other solution you can draw a line of fixed pixel say 2 pixel and based on drawn length inflate the width if line till center and then again start deflate from center point to end point.
You need to see the difference between x coordinates otherwise if a sine wave is drawn with high nodes the line width will overlap each other.
Edited : This link might be of your interest then.You can modify it according to your need, its in cocos2d.
There is no direct support for variable thickness curves in iOS (or Mac OS for that matter.) The cocos2d project looks like a good approach.
There is also no support for soft-edged curves who's edges are feathered to transparent. I've thought about implementing a similar approach to the one outlined in the Cocos link using OpenGL. This would be a good application for a vertex shader, since it would take advantage of the parallel vertex processing and vector math available in shaders.
Take a look at this article Smooth Freehand Drawing. It might be helpfull.
You can manipulate with control points of
[path addCurveToPoint:pts[3] controlPoint1:pts[1] controlPoint2:pts[2]];
and fill the area between two bezierPaths. I am not sure if it will work, but you can try if you dont find anything else.

XNA Drawing a series of squares

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.

Drawing a concave polygon in OpenGL

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.

Resources