Draw a comet tail on a spline with 4 control points in a fragment shader - opengl-es

I'm asking this to see what approach would someone take to achieve something like the following, in an OpenGL ES 2.0 fragment shader.
The use case is drawing a comet-type tail given 4 control points, on a Catmull–Rom spline.
The 4 points are given into the shader. p1 can be the middle of the canvas. A starting radius can also be provided, for the initial radius of the circle at p1.
Below are two rough images for illustrating the use case better.
This is how the tail should look (approximately) when the line is straight, with all the points on the same line.
This is how (approximately) the tail should look when the line is curved using the 4 points as control points.
Any ideas are appreciated.

Related

Fitting elliptical arcs to points or other curves

I'm struggling to fit an elliptical arc to some points. The points are either from line segments or all part of the same polyline or they are generated from a bezier curve. I basically have two issues:
I would like to fit an elliptical arc to the points if it is reasonable and i straight line if that is a better fit. I'm thinking about starting at the first point and then constructing a line and a ellip_arc to the next points. The one with the lowest error wins. Or something like that at least. The problem is that an ellipse has many free parameters as opposed to a straight line. So how could I fit an ellipse arc to the points? It also has to start and stop at the points.
Fitting seems to be easiest when the ellipse arc is parameterized. Even though I find it hard to define where to start and stop the arc. But, as output, I need to have the ellipse described like in SVG format (Center Point, Minor and Major Axis, rotation to x-axis etc. https://www.w3.org/TR/SVG2/paths.html#PathDataEllipticalArcCommands). I'm not sure how to convert to this representation, or maybe I can fit it like that?
see:
Circular approximation of polygon (or its part)
If you compute this for your curve samples from local change of radius and center you could group and estimate parts of curve that belongs to the same ellipse and also its eccentricity and or a,b semiaxises sizes , center and orientation to ease up your fitting... Even if not get the precise value it will be a start point and range for ellipse parameter fitting hugely improving speed and stability of fitting
Some of the ellipse parameters might be obtained directly if your data has enough large chunks of ellipses see:
Algorithms: Ellipse matching
Fitting SVG like parameters fully will be very slow easier would be to fit just the ellipses first (center,a,b,rotation) and then convert/fit to SVG form elliptic arc. See:
Converting an svg arc to lines
Express SVG arc as series of curves
And finally you can use any fitting algorithm my favorite is this one:
approximation search
I do not code in C# so I have no idea about any existing packages for tasks like this.

Triangle pattern GLSL shader

Is there any simple algorithm like Voronoi diagram to divide any rectangular plane to triangles, eventually, using # of pre-defined points.
To be honest, I have to write a very simple fragment shader like this.
Theoretically, this Voronoii shader could be 'upgraded' by Delaunay triangulation
but wanna find the more elegant solution.
The first thing that comes to my mind is to create n random points (with specific seed) to fill a cylinder volume. The triangle points will be intersection of lines between those points and plane going through the axis of cylinder. The animation would be simply done by rotating the plane ...
I see it something like this:
So the neighboring points should be interconnected with each other. Forming tetrahedrons that fills the volume of the cylinder. So create uniform tetrahedron grid and add random noise to the points position (with specific seed).
This whole task is very similar to rendering cross section of 4D mesh see:
4D rendering techniques
As the 4D simplex is also tetrahedron. The only diference is you are in 3D and cutting by 3D plane.
You can reverse-engineer this example shadertoy.com/view/MdfBzl
like I did. Thanks to mattz.

Clipping non-projection elements (orthographic)

I'd like to add "flying" (3D) arcs to my orthographic projection, as shown here, but with clipping instead of the fade effect. This seems difficult since the arcs are created independently of the projection. (Each arc is defined by three points obtained from the projection--the start, end, and great circle midpoint extended along a line from the center of the canvas--but the arc itself is drawn using "2D" cardinal interpolation on the corresponding points on the svg canvas.)
My first thought was that I might need to do some spherical geometry to get the coordinates where the clipping happens, but now I'm wondering if there's a more straightforward way to accomplish this (I'm new to D3).
This is what my map looks like without clipping:
I'm also very green to d3, but fortunately I'm also fresh from my own search for a decent solution for clipping flight lines in orthographic. The demo you link to is clever in more ways than one:
The arc is drawn from three points interpolated with a Catmull-Rom curve in the projected 2D coordinates that happens to visually approximate a true circular curve in 3D nicely
The line fades with proximity of either of its points to the clipping plane, as you've pointed out
Drawing the spline in the projected, 2D coordinates eliminates any option to split the line before projection and get visual smoothness for cheap, even if d3 had the functionality natively (which I haven't been able to find anyways). That means that interpolation will have to be a lot more manual.
My first thought was that I might need to do some spherical geometry to get the coordinates where the clipping happens, but now I'm wondering if there's a more straightforward way to accomplish this
I eventually settled with what I consider the most obvious option, which unfortunately you're aiming precisely to avoid:
Obtain the coordinates of the clipping point by the cross product of the current globe center with the normal to the great circle plane of the arc. Given your origin and destination Po and Pd respectively and the globe center C, you're looking for C x (Po x Pd) normalized
Interpolate coordinates between your origin and destination using something like d3.geoInterpolate
Project interpolated point at the right scale (read: elevation) above the ground for that fraction of the flight line
Draw one [smoothed] line from the origin to the clipping point along the interpolated points in between, and another from the clipping point to the destination, moving one accordingly to the background. Watch the cases where the whole line is in front or behind the clipping plane.
To figure out where in the flight path you need to splice your clipped point, you will probably need to compare the great angles of your clipping point to one end vs. end-to-end. Note also that performance takes a hit, but you may still be satisfied with the number of flight lines you've drawn in your example.

OpenGL ES GL_TRIANGLES gradient issue

I am trying to draw a area graph with a gradient. This is what I have right now.
If you look at the red-green graph, you will notice the gradient is does not look the way its supposed to.
EDIT: The gradient should be uniform like this:
I am using OpenGL ES 2.0 and GLKit to draw a bunch of charts. The chart is drawn using GL_TRIANGLES. I understand that the issue is that the gradient is being drawn for each triangle individually.
The only approach I can think of is to use a stencil buffer. I will draw the gradient in a big rectangle and clip it to this shape using the stencil. Is there a better way to do this? If not could you help me draw a stencil with specified points? I am new to OpenGL and not getting a good explanation on using stencil buffer.
You don't need a stencil buffer. I don't think more triangles will help, either — more likely that'd just cause you more confusion because you'd be assigning per-vertex colors to intermediate vertices and having to interpolate them yourself.
Your gradients are coming out that way because of how and where you assign vertex colors for interpolation. Notice the difference in colors between your output and the example of what you're looking for:
You've got 100% red at every vertex along the top edge of your graph, and 100% green at every vertex along the bottom edge. OpenGL interpolates colors linearly across the face of each triangle, which is why you've got more red in the shorter parts of your graph.
In the output you're looking for, the top of the graph starts out less red in the shorter parts, so that it makes a shorter transition to white in over shorter distance.
There are a few different ways to do this, but probably the easiest (for your plan of using GLKBaseEffect instead of writing your own shaders) might be to use a 1D texture for your gradient, and assign a texture coordinate to each vertex that's proportional to its Y coordinate on the graph, like so:
(The example coordinates in my diagram assume your graph vertices cover the range 0.0 to 1.0, but the point stands regardless: the vertical texture coordinate for each point should be a fraction of the graph's total height, between 0.0 and 1.0.)
Alternatively, you could look into drawing in two passes: First, draw the shape of your graph, then draw a quad (two triangles) covering the entire screen with your gradient, using the appropriate glBlendFunc so that it only draws over the area you've filled in with your graph shape.
OpenGL ES can do what you want but you need to increase the tessellation of your model. In other words, instead of using just a few large triangles, you need more and smaller triangles, with the vertex color changes spread over them evenly. This will give you better control over the gradients. Triangles are cheap on accelerated OpenGL ES, so even if you increase the number 100 times, it will not have much impact on performance.
You might also consider a different approach, where the entire graph is covered by a single texture which contains the gradient. That would be easier to implement.

Drawing aliased, pixel-perfect 1px splines (Catmull-Rom, specifically)

A brief background: I'm working on a web-based drawing application and need to draw 1px thick splines that pass through their control points.
The issue I'm struggling with is that I need to draw each of the pixels between p1 and p2 as if I were using a 1px pencil tool. So, no anti-aliasing and one pixel at a time. This needs to be done manually without the use of any line/curve library code as my brush system depends upon having a pixel coordinate to apply the brush tip to the canvas.
Essentially, I need to combine the one pixel stepping from something like the Bresenham algorithm with the coordinates returned by the Catmull-Rom equation. I'm having trouble because the Catmull-Rom points are not uniformly distributed (so I can't just say there should be 100 pixels in the curve and run the equation 100 times). I tried using an estimated starting value of the maximum of the X and Y deltas and filling in the gaps with Bresenham, but due to rounding I still end up with some "dirty" sections (ie. the line is clearly moving up and to the right but I still get two pixels with the same Y component, resulting in a "fat" section of the line).
I'm positive this has been solved because nearly every graphics program that draws splines has to support the clean pixel curves that I'm after. After quite a bit of math research, though, I'm a bit confused and still without a solution. Any advice?
EDIT: Here's an example of a curve that I might have to render:
Which might have an expected result looking like this (note that this is an estimate):
Using the Catmull-Rom spline equation, we need four points to create a segment. P0 and P3 are used as tangents for incoming and outgoing direction from the P1->P2 segment. With a Catmull-Rom spline, the blue section is all that gets interpolated as t moves from 0 to 1. P0 and P3 can be duplicated to ensure that the green portion gets rendered, so that is not an issue for me.
For simplicity's sake, I need to render the pixels on the curve between P1 and P2, given that I have tangents in the form of P0 and P3. I don't necessarily need to use Catmull-Rom splines, but they seem to be the right tool for this job being that control points must be passed through. The non-uniform distribution of interpolation points is what's throwing me for a loop.
EDIT2: Here's an example of what I mean when I say my resulting curve is dirty:
The red arrows point out a few locations where there should not be a pixel. This is occurring because the X and Y components of the coordinate that get calculated do not change at the same rate. So, when each of the components gets rounded (so I have an exact pixel location) it can be the case that either X or Y doesn't get bumped up because the calculated coordinate is, say, (42.4999, 50.98). Swapping the round for a floor or ceil doesn't solve the problem, as it just changes where it occurs.
Here you have a paper describing method for the re-parametrization of splines in order to get equally spaced points along the curve length. I think this can solve your problem if you can adapt it to Catmull-Rom curves (shouldn't be too difficult, I guess)

Resources