Sign in to follow this  

Gradient filling algorithm

This topic is 2958 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm looking to fill an array of pixels (or use a Pixel Shader) so I can fill any 2D polygon with a linear gradient. I'd like to be able to specify an angle for the gradient, and the colors to use to make the gradient. Any help?

Share this post


Link to post
Share on other sites
Sorry for the confusion. When I said "Pixel Shader", I was trying to say that if someone implemented a gradient filling using a pixel shader, I could use that. Or if someone had an idea of how to do it with a pixel shader, I could use that. I could do with either the pixel shader help, or the algorithm help. It was an open-ended question because either one will do.

In my shader code, I first sent in two colors, the min/max y, and the (x,y) position to the vertex shader. Then, I sent the two colors, the min/max y, and the y position to the pixel shader. I was able to achieve a simple a left-to-right and top-to-bottom gradient, but only with two colors, and not at any angle.

I then tried to implement a "disecting-line" technique in code (not using a Pixel Shader). So, find the mid-point of the polygon, and then extend a line outwards from the midpoint disecting it into two pieces. The angle of the line would be from the X-axis. However, I wasn't able to figure out where to go from there.

I was hoping there would be some kind of mapping function that I could call like "ColorAt(int x, int y)" that would take into account the angle, and the colors I wanted to use.

In short, I would like help with an algorithm I could use to fill an array of pixels, OR pixel shader code.

Share this post


Link to post
Share on other sites
A linear gradient takes the form

f(x,y) = dot((u,v), (x,y)) + b

for some fixed vector (u,v) and scalar offset b. The gradient will change in the direction of the vector (u,v).

Now, suppose you are given a unit vector (u',v'). By iterating over the vertices of your polygon, you can determine which vertex (vx,vy) minimizes dot((u',v'),(vx,vy)), and which one maximizes it.

Now, (u,v)=k(u',v') for some scalar k. Given the information about maximizing and minimizing vertices, you need only solve for,
- k
- b
to set the maximum and minimum colors at the maximizing and minimizing vertices, respectively.

Just do this on paper; it's not hard. This will give you the function to use, which you can evaluate by hand at each pixel using the pixel-shader approach.

--------

Alternatively, compute the AABB for your polygon, rotated at the correct angle. Render the polygon to the stencil buffer; then draw the AABB with appropriate stencil test options set, and vertex colors as desired to achieve your gradient.

Share this post


Link to post
Share on other sites
You could do this without any pixels shaders and no per pixel math ops at all.
A gradient is just a one dimensional texture IMO.

Just calculate the scalar value per vertex on the CPU and use as U coordinate for a 2x1 pixel sized texture, set clamping and bilinear interpolation and there you have it.

Making more complex gradients (with many colors etc) just requires you to create a slightly bigger texture, i.e 4 evenly spaced colors would need a 4x1 texture etc.

My 2c

Share this post


Link to post
Share on other sites
Quote:
Original post by eq
Just calculate the scalar value per vertex on the CPU and use as U coordinate for a 2x1 pixel sized texture, set clamping and bilinear interpolation and there you have it.


I think we have a winner...

Share this post


Link to post
Share on other sites
Thank you! Thank you! Thank you! I love that I was given a function, AND a method to do it without a pixel shader. I will be implementing both over the next few days. I've been looking for help for weeks now and I couldn't wrap my mind around it myself. Thank you :).

Share this post


Link to post
Share on other sites

This topic is 2958 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this