Thread: Blending two or more radial gradient fills

  1. #1
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158

    Cool Blending two or more radial gradient fills

    Hi all.
    I want to blend two gradients together. What I'm doing now is add their color values. The problem is that this creates a weird effect in the area where the fills intersect, when both have a value in the same color component. For example, two green fills show effect, but there's no problem with a green and a red one. See the images below.

    This code calculates each pixel color:
    Code:
    void PixelValue(int x, int y, unsigned char *pR, unsigned char *pG, unsigned char *pB)
    {
    int iR = 0, iG = 0, iB = 0;      // resulting pixel color to be returned
    
    // for each object, in this case only two:
    // iShapeX stands for the color of the current shape
    // iRadius is the radius of the current object
    // iDist is the distance to the object
    
            iR += (iDist>=iRadius) ? 0 : iShapeR * (iRadius-iDist) / iRadius;  //add up the color values of every object, 
            iG += (iDist>=iRadius) ? 0 : iShapeG * (iRadius-iDist) / iRadius;
            iB += (iDist>=iRadius) ? 0 : iShapeB * (iRadius-iDist) / iRadius;
    
    *pB = (unsigned char) min(iB, 255);
    *pG = (unsigned char) min(iG, 255);
    *pR = (unsigned char) min(iR, 255);
    }
    Is there anybody who knows what rule to use for this? I hope you understand how my code works. Thanks in advance.


    Edit: the only difference between the images below is the color of the rightmost gradient.
    Last edited by pronecracker; 05-18-2007 at 11:38 AM.

  2. #2
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    Process the color-averaging formula for gradients and process them back to front. That is, draw one of the radial gradients first, say the top left one, and once drawn in full, process the next one, the one on the top right. This is that formula, if you need it again.
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  3. #3
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158
    Will the Z-order make a difference?

  4. #4
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158
    I think I need a little help with implementing this. Say I calculated the pixel value taking into account only the first gradient, then I would average the color with that of the second. But if COLB is the color value of the second gradient and RATB is the distance to it, what is RATA?

  5. #5
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    The Z order does make a difference. Let's say you have a black background. A 1/2 transparent 00C000-colored object is nearest to the background and a 2/3 transparent FF0000-colored object in front. If in this order, you get 006000 then AA2000 afterwards. If you reverse the order, you get AA0000 first then 556000 afterwards. Thus Z-order does make a difference, quite substantial even.

    For radial gradients, you need to base the ratios on the distance from the center to the radius. The radius, for example is 256 pixels. The center has a distance of 0 from the center so it has full intensity, or 256 parts of the base color and 0 parts of the background. If you have the pixel 180 to the left and 40 upwards, you first need the distance from the center, and that's the pythagorean theorem: sqrt(180^2+110^2), which works out to about 210.9502311. You'd have 210.9502311 parts of the background color and "radius-210.9502311" parts of the base color (the foreground; which is 45.0497689). Perform the blend for these values. The value to divide by is just the radius, or 256. Basically, the formula is like this (note the striking similarity to the fog formula):

    (RGC*DFC+BGC*(GR-DFC))/GR

    RGC - radial gradient color
    DFC - distance from center (the 210.95 number)
    BGC - background color (the color of the pixel to be modified)
    GR - gradient radius (256 in my example)

    To get the DFC, you need to use the pythagorean theorem.
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  6. #6
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158
    Ofcourse. Thank you very much for refreshing my mind on that. My mistake was trying to include every object in the same calculation, I think

  7. #7
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158
    I suspect this is equivalent to drawing two radial red-to-transparent fills so that they intersect in GIMP.
    But GIMP also shows this ugly effect! Flash does too! Is there actually a way to avoid this?
    Last edited by pronecracker; 05-26-2007 at 03:29 PM.
    Don't call me stupid.

  8. #8
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    On second thought, I can see exactly why that's happening and it's actually mathematically correct. It may not sound right, but let's consider a few examples.

    Let's take a point where, 3/4 of the way to the outside edge, there is an intersection. Both radial circles are 00FF00 in color and the background is 000000. First, you'd get 004000 after the usual method then, since another 1/4 opaque 00FF00 color is applied, it jumps to 007000 which causes it to be brighter. Mathematically, it is correct like that. Using 1/3 (005500 then 008D00), 3/4 (00BF00 then 00EF00), or 1/16 (001000 then 001F00) all give the same effect.

    It works well with red on green (004000 then 403000) since the other color values are based on the background. If the background was white instead of black, you'd have BFFFBF then 8FFF8F. For 3/4 instead of 1/4, it'd be 40FF40 then 10FF10.

    How to work around the effect - the only fix possible that I can come up with is, for your higher-layered radial blur, set the pixel colors where the radial blurs would intersect to whatever the background is/was, then process accordingly. This should only apply if the alpha is not 0 (0 means fully transparent). It's the only thing I can come up with.
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Blending Problem
    By IdioticCreation in forum Game Programming
    Replies: 1
    Last Post: 02-16-2008, 06:13 PM
  2. Gradient fills
    By pronecracker in forum Windows Programming
    Replies: 5
    Last Post: 04-29-2007, 11:55 AM
  3. Alpha blending
    By SMurf in forum Game Programming
    Replies: 3
    Last Post: 08-29-2003, 06:50 PM