SDL has no function like this, curious if anyone in the past has done it and wouldn't mind heading me in the right direction. I want to create a gradient between two colors to be reflected on the height of a rectangle.
-
3If it's just a horizontal or vertical linear gradient it's quite simple: interpolate between R1 and R2, G1 and G2 and B1 and B2. – Michael Dec 03 '13 at 10:37
-
For more generic renderings: http://stackoverflow.com/a/36504803/895245 – Ciro Santilli OurBigBook.com Apr 08 '16 at 16:36
2 Answers
Just make a loop over the desired y positions, in which you:
- Compute the desired color by interpolating between the gradient's endpoint colors.
- Call
SDL_SetRenderDrawColor()
to set the color. - Call
SDL_RenderDrawLine()
to draw a horizontal line at the current y position.

- 391,730
- 64
- 469
- 606
-
not exactly what I was doing, but certainly helped me get though. The bit about the position, clarified things for me. – j0h Nov 07 '15 at 04:45
-
I was actually pondering over this myself yesterday, and I had an amusing idea. If you set the renderer scaling to linear, you can scale a texture of just a couple pixels to whatever dimensions you want and get smooth interpolation between the colors - essentially, the hardware-accelerated texture filtering gives you gradients without the CPU having to lift a finger re: calculating them.
I tested this out and was able to create an arbitrary rectangle with different colors at each corner and smooth blending in between using only a four-pixel texture. The only gotcha I ran into was that, on my Windows machine, the texture interpolation blended towards grey at the edges and started the color part a little ways in. Fortunately, expanding the source texture from a 2x2 image to a 4x4 one and blitting from the center 2x2 square fixed this, reproducing the result I got on my Devuan machine.
Of course, this by itself only gives you gradients along the X or Y axes or the hypotenuse of your destination rectangle, but that's enough to work with, and I'm sure clever application of the rotation feature could give you gradients at any arbitrary angle. Here's the code:
// Set linear blending (haven't tried this with bilinear...)
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY,"1");
// Create a 4x4 texture to serve as the source for our gradient.
uint32_t * bgpixels;
SDL_Texture * background = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_STREAMING,4,4);
// Set up the gradient colors.
// Each 2x2 quadrant of the texture has a separate color:
// AABB
// AABB
// CCDD
// CCDD
SDL_LockTexture(background,NULL,(void**)(&bgpixels),&i);
bgpixels[0] = 0x0000ffff;
bgpixels[1] = 0x0000ffff;
bgpixels[2] = 0x00ff00ff;
bgpixels[3] = 0x00ff00ff;
bgpixels[4] = 0x0000ffff;
bgpixels[5] = 0x0000ffff;
bgpixels[6] = 0x00ff00ff;
bgpixels[7] = 0x00ff00ff;
bgpixels[8] = 0xff0000ff;
bgpixels[9] = 0xff0000ff;
bgpixels[10] = 0xffffffff;
bgpixels[11] = 0xffffffff;
bgpixels[12] = 0xff0000ff;
bgpixels[13] = 0xff0000ff;
bgpixels[14] = 0xffffffff;
bgpixels[15] = 0xffffffff;
SDL_UnlockTexture(background);
// Blit it into place with the renderer.
SDL_RenderCopy(renderer, // The SDL 2D renderer we're using
background, // The background texture
&(SDL_Rect){1,1,2,2}, // We blit from the center 2x2 square to avoid a
// quirk on the Windows version.
NULL); // The destination rectangle - just using the full
// target surface here.

- 101
- 1
- 4
-
Can you give a hint concerning the performance of your method against the accepted answer? (I know this may depend on (m)any H/W and driver details but moving the load to GPU should usually outperform any rendering done on CPU side on probably any common gaming PC and smartphone (with GLES).) – Scheff's Cat Aug 28 '18 at 11:19
-
I've never benchmarked it. As you say, I expect that using the hardware designed to do this general case very fast is going to be faster than doing it on a general-purpose CPU, but never assume, when it actually matters. Linear interpolation isn't too hard to do in software, if you want to test it; if you move the expensive operations out of the loop (tip: find the per-pixel delta value and repeatedly add, rather than doing multiply/divide for every pixel - for a 2D gradient, you need to find vertical deltas for each side and re-calculate the horizontal delta every line) it's quite simple. – commodorejohn Aug 30 '18 at 02:44
-
Calculations are not a problem. It's graphics calls that take most time. If the gradient is 512*512 pixels, then drawing it manually would require 512 fillrect calls. – Andrei Nikolaenko Feb 18 '21 at 13:16
-