简体   繁体   中英

How can I make the faces of my cube smoothly transition between all colors of the rainbow?

I have a program in Visual Studio that is correctly rendering a 3D cube that is slowly spinning. I have a working FillTriangle() function that fills in the faces of the cube with any color whose hex code I enter as a parameter (for example, 0x00ae00ff for purple). I have set the color of each face to start at red (0xFF000000), and then I have a while loop in main() that updates the scene and draws new pixels every frame. I also have a Timer class that handles all sorts of time-related things, including the Update() method that updates things every frame. I want to make it so that the colors of the faces smoothly transitions from one color to the next, through every color of the rainbow, and I want it to loop and do it as long as the program is running. Right now, it is smoothly transitioning between a few colors before suddenly jumping to another color. For example, it might smoothly transition from yellow to orange to red, but then suddenly jump to green. Here is the code that is doing that right now:

...
main()
{
...
float d = 0.0f; //float for the timer to increment

 //screenPixels is the array of all pixels on the screen, numOfPixels is the number of pixels being displayed
 while(Update(screenPixels, numOfPixels))
 {
   ...
   timer.Signal(); //change in time between the last 2 signals
   d += timer.Delta(); //timer.Delta() is the average current time
   if(d > (1/30))    // 1 divided by number of frames
   {
     //Reset timer
     d = 0.0f;
     
     //Add to current pixel color being displayed
     pixelColor += 0x010101FF;
   }
   ...
 }
 ...
}

Is there a better way to approach this? Adding to the current pixel color was the first thing that came to my mind, and it's kind of working, but it keeps skipping colors for some reason.

That constant is going to overflow with each addition. Not just as a whole number, but across each component of the color spectrum: R, G, and B.

You need to break your pixelColor into separate Red, Green, and Blue colors and do math on each byte independently. And leave Alpha fixed at 255 (fully opaque). And check for overflow/underflow along the way. When you reach an overflow or underflow moment, just change direction from incrementing to decrementing.

Also, I wouldn't increment each component by the same value (1) on each step. With the same increment on R,G, and B, you'd just be adding "more white" to the color. If you want a more natural rainbow loop, we can do something like the following:

Change this:

 pixelColor += 0x010101FF;

To this:

 // I'm assuming pixelColor is RGBA

 int r = (pixelColor >> 24) & 0x0ff;
 int g = (pixelColor >> 16) & 0x0ff;
 int b = (pixelColor >> 8)  & 0x0ff;

 r = Increment(r, &redInc);
 r = Increment(g, &greenInc);
 g = Increment(g, &blueInc);

 pixelColor = (r << 24) | (g << 16) | (b << 8) | 0x0ff;

Where redInc, greenInc, and blueInc are defined and initialized outside your main while loop as follows:

int redInc = -1;
int greenInc = 2;
int blueInc = 4;

And the increment function is something like this:

 void Increment(int color, int* increment)  {
     color += *increment;
     if (color < 0) {
         color = 0;
         *increment = (rand() % 4 + 1);
     } else if (color > 255) {
         color = 255;
         *increment = -(rand() % 4 + 1);
     }
 }

That should cycle through the colors in a more natural fashion (from darker to brighter to darker again) with a bit of randomness so it's never the same pattern twice. You can play with the randomness by adjusting the initial colorInc constants at initialization time as well as how the *increment value gets updated in the Increment function.

If you see any weird color flickering, it's quite possible that you have the alpha byte in the wrong position. It might be the high byte, not the low byte. Similarly, some systems order the colors in the integer as RGBA. Others do ARGB. And quite possible RGB is flipped with BGR.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM