Drawing gradient

Programming, for all ages and all languages.
Post Reply
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Drawing gradient

Post by BrightLight »

This is not a OSDev-specific question, so I put it in general programming.
How do I draw a gradient? For example in CSS:

Code: Select all

background-image: linear-gradient(#000000,#FFFFFF);
How would I draw this same gradient with a specific width and height? Any algorithms?
You know your OS is advanced when you stop using the Intel programming guide as a reference.
Octocontrabass
Member
Member
Posts: 5513
Joined: Mon Mar 25, 2013 7:01 pm

Re: Drawing gradient

Post by Octocontrabass »

As the name suggests, a linear gradient is calculated using a linear equation. You can consider the position within the gradient as the X coordinate, and the intensity of the color as the Y coordinate, then solve for a linear equation that describes the intensity of that color component for each location along the gradient. You'll need to solve three times, one for each color component.

I'm intentionally ignoring things like gamma correction and perceptual linearity for the sake of a simple explanation.
shmx
Member
Member
Posts: 68
Joined: Sat Jan 16, 2016 10:43 am

Re: Drawing gradient

Post by shmx »

This is very easy. :)

Code: Select all

void DrawGradientRectandgle(int XS, int YS, int XE, int YE, int C1, int C2)
{
    int x, y;
    int r1 = (C1 & 0xFF0000) >> 16;
    int r2 = (C2 & 0xFF0000) >> 16;
    int g1 = (C1 & 0x00FF00) >> 8;
    int g2 = (C2 & 0x00FF00) >> 8;
    int b1 = C1 & 0x0000FF;
    int b2 = C2 & 0x0000FF;
    int h = abs(YE - YS);
    double d_r = (double)(r2 - r1) / h;
    double d_g = (double)(g2 - g1) / h;
    double d_b = (double)(b2 - b1) / h;
    double cur_r = r1, cur_g = g1, cur_b = b1;
    for(y = YS; y <= YE; y++)
    {
        for(x = XS; x <= XE; x++)
            SetPixel(x, y, RGB((int)cur_r, (int)cur_g, (int)cur_b));
        cur_r += d_r;
        cur_g += d_g;
        cur_b += d_b;
    }
}
Note: This is a simple algorithm but not effective.
Last edited by shmx on Mon Feb 29, 2016 2:12 pm, edited 1 time in total.
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: Drawing gradient

Post by SpyderTL »

Essentially, you are doing a linear interpolation (LERP) on each component of your value. In your case, R/G/B. So each of these components will have a minimum value and a maximum value, and a factor between 0.0 and 1.0 to produce an output value.

If Min = { 0.0, 0.0, 0.0 } and Max = { 1.0, 0.5, 0.25 }, then Lerp(Min, Max, 0.5) will return { 0.5, 0.25, 0.125 }.

Just do that for each pixel, and multiply the result by { 255, 255, 255 } if you want a 24-bit value...

It's possible to do the math using integer only calculations, but it's more involved.

Rectangles (top, bottom, left, right) are easier to calculate than triangles (p1, p2, p3). For triangles, you have to interpolate once per scan line to get the min value, and again to get the max value, then once per pixel between the min and max to interpolate every pixel using the interpolated min and max values. This is essentially how all 3d graphics rendering works.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Drawing gradient

Post by Combuster »

Basic fundamentals: Bresenham. Note that instead of it being presented as a line drawing algorithm (give all pairs from x0,y0 to x1,y1), you can use it for any other form of interpolation as well (for example, x0,r0 to x1,r1)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: Drawing gradient

Post by BrightLight »

Thanks, all, for your explanations!
You know your OS is advanced when you stop using the Intel programming guide as a reference.
Post Reply