1
\$\begingroup\$

I have created an object that is comprised of two bezier curves (constructed of an identical finite segments equal to a variable named resolution). The two curves are then tessellated and filled in with a shader.

I would like to adjust shading within it based on a pixel's position relative to the object's coordinates (ie. a stripe along the middle would follow the curvature of the bezier curves.

My current approach simply breaks down the curve into a finite number of segments and then colors each pixel depending on its proximity, although this does not work because the scene will lag with even one of these objects if it has a resolution of 40+. Even if I could go to some arbitrarily large resolution, I am still unsure of how to "dynamically" color a pixel depending on it's relative height within the polygon. If there were a function to find the x or y coordinate relative to the curve's geometry (I assume normals play a role) then I would be pleased, because even if I did optimize my code as it is it is: it would not be seamless and I would have to have an arbitrarily and wastefully high resolution to guarantee a good look.

An algorithm that's reasonably efficient for 2> pixel accuracy for about 500,000 pixels worst-case scenario would also be equally helpful in place of a function that spits out an exact answer. I am more concerned about the effect being consistent than it being accurate as it is for visual purposes.

Polygon with unmodified x-axis shown:

Polygon with original axis

Polygon with modified x-axis modified, f(x):

Polygon with modified axis

It is quite easy to brute force the solution by simply lerping between the curves A and B and filling them in until the entire polygon is filled, but a solution would require a function that would go backwards, translating each pixel coordinate into a point along an intermediary bezier curve as shown in f(x), ultimately letting me call f(x, y) to get the x, y within the polygon's space so that an image would fit exactly to the curvature of the bezier curves.

If the solution is significantly more simple with a quadratic bezier curve then I may go for that instead, as I am unsure if cubic is necessary.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Questions about geometry often benefit from a visual aide like a diagram or screenshot. I'd recommend adding one to help get users up to speed quickly, which will help get you more accurate answers, faster. \$\endgroup\$
    – DMGregory
    Commented Aug 1, 2023 at 10:47
  • \$\begingroup\$ If you need just filling the color between two bezier curves u can make if statements to find if the pixel is between two curves ( if(pixel.y>bezier.bottom.y(where bezier.bottom.x==pixel.x)&&pixel.y<bezier.top.y((where bezier.top.x==pixel.x)))pixel.color=red;)Similar way u can filling the color any other space relative to your two curves. I think it is not very expensive should work if you find formula to get Y from bezier curve when you know only X. \$\endgroup\$
    – Bogdan
    Commented Aug 1, 2023 at 19:27
  • \$\begingroup\$ Actually you can find Y of x based on x =Lerp(P0.x,P2.x, t); x = p0.x+(p2.x-p0.x)*t ; t=(x-p0.x)/(p2.x-p0.x); when you use this t in bezier curve u get X and Y coords where X==x; \$\endgroup\$
    – Bogdan
    Commented Aug 1, 2023 at 19:58
  • \$\begingroup\$ @DMGregory good idea, I will update my question with a visual soon. Thank you for the suggestion. \$\endgroup\$
    – Magikarp
    Commented Aug 2, 2023 at 20:37

1 Answer 1

0
\$\begingroup\$

There is the formula to find Y and Z coord based on X value: t = (X-Pstart.x)/(Pend.x-Pstart.x);

you get the Bezier(t) Point where Bezier(t).X==X;

\$\endgroup\$
5
  • \$\begingroup\$ This works correctly if and only if the Bezier maintains constant velocity along the x axis over the whole interval (ie. it's a lerp on thwt axis, even if it bends in others). The relation does not hold in the general case with arbitrary control and anchor points. (I worked on a AAA engine whose code falsely assumed it would hold, leading to all sorts of subtle bugs!) \$\endgroup\$
    – DMGregory
    Commented Aug 1, 2023 at 20:21
  • \$\begingroup\$ Here's an example of a case where it does not hold: consider the quadratic Bézier curve A(0, 1) B(1,1) C(1,0). Let's try to find y when x = 0.5. If t = (x - A.x)/(C.x - A.x) then t = 0.5. But at t = 0.5 the cuve passes through (0.75, 0.75), which does not match the x = 0.5 we wanted. In fact the exact point we pass through depends on the choice of B, so a formula for t that includes only A and C cannot be correct for all curves. The problem only gets worse in higher orders or more dimensions. \$\endgroup\$
    – DMGregory
    Commented Aug 2, 2023 at 1:56
  • \$\begingroup\$ @DMGregory I should specify that I am working in 2d space, although I wonder what the margin of error would be depending on differences in magnitudes between the two points. Or even better, if I could just add another layer interpolation. I wonder if multiplying the t-value by difference in magnitudes times the t-value would correct the answer by any noticeable amount (ie. interpolated_t = t * abs(control1 - control2)) \$\endgroup\$
    – Magikarp
    Commented Aug 2, 2023 at 22:39
  • \$\begingroup\$ Alternatively, I can test to see how much the accuracy varies. If it's within a couple pixels then I may look into limiting factora that would increase variance. \$\endgroup\$
    – Magikarp
    Commented Aug 2, 2023 at 22:59
  • \$\begingroup\$ Because the true coordinate depends on control point B, by moving that point we can make the error arbitrarily large. I'm sure we can find better solutions to meet your needs, but I'm hoping to see that diagram first to be sure that I have an accurate understanding of what those needs are. \$\endgroup\$
    – DMGregory
    Commented Aug 2, 2023 at 23:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .