OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Mar 19, 2024 3:22 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Drawing gradient
PostPosted: Mon Feb 29, 2016 1:37 pm 
Offline
Member
Member
User avatar

Joined: Sat Dec 27, 2014 9:11 am
Posts: 901
Location: Maadi, Cairo, Egypt
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:
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.


Top
 Profile  
 
 Post subject: Re: Drawing gradient
PostPosted: Mon Feb 29, 2016 1:55 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5069
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.


Top
 Profile  
 
 Post subject: Re: Drawing gradient
PostPosted: Mon Feb 29, 2016 2:08 pm 
Offline
Member
Member

Joined: Sat Jan 16, 2016 10:43 am
Posts: 68
This is very easy. :)
Code:
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.

Top
 Profile  
 
 Post subject: Re: Drawing gradient
PostPosted: Mon Feb 29, 2016 2:10 pm 
Offline
Member
Member
User avatar

Joined: Sun Sep 19, 2010 10:05 pm
Posts: 1074
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


Top
 Profile  
 
 Post subject: Re: Drawing gradient
PostPosted: Tue Mar 01, 2016 6:08 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9301
Location: On the balcony, where I can actually keep 1½m distance
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 ]


Top
 Profile  
 
 Post subject: Re: Drawing gradient
PostPosted: Tue Mar 01, 2016 11:30 am 
Offline
Member
Member
User avatar

Joined: Sat Dec 27, 2014 9:11 am
Posts: 901
Location: Maadi, Cairo, Egypt
Thanks, all, for your explanations!

_________________
You know your OS is advanced when you stop using the Intel programming guide as a reference.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group