Colby Ray - 1 month ago 25
C Question

How would I implement a routine using C with OpenGL to make the background color transition nicely from one color to another and then back again, repeatedly? All the colors I have in my palette are of 3 digit precision. From 0.000 to 1.000. It gets complex to have the color components arrive at the second color in uniform timing, let alone adjusting the transition speed. Which I'm fine with keeping at 0.001 for now.

`glm::mix` (as well as GLSL's one) basically just does linear interpolation. In code that could mean something like

``````struct Color
{
float r, g, b;
};

Color lerp(Color a, Color b, float t)
{
Color c;
c.r = (1-t)*a.r + t*b.r;
c.g = (1-t)*a.g + t*b.g;
c.b = (1-t)*a.b + t*b.b;

return c;
}
``````

Now, a common function to use to get back some back and forth effect is the cosine function.

The cosine gives you a value between -1 and 1, so you might want to scale it between 0 and 1. This can be done using

``````float t = cos(x) * 0.5 + 0.5; // *0.5 gets to [-0.5, 0.5], +0.5 gets to [0,1]
``````

And you use this `t` to compute your color. The `x` can be the current time multiplied by some value that helps you control the speed of the interpolation.

EDIT: Using gpenfault's code as a starting point, you can do this kind of stuff (if it poses any problem I remove it) :

``````// g++ main.cpp -lglut -lGL
#include <GL/glut.h>
#include <cmath>

int dstTime = 0; // milliseconds

struct Color
{
float r, g, b;
};

Color makeColor(float r, float g, float b)
{
Color c = { r, g, b };
return c;
};

Color lerp(Color a, Color b, float t)
{
Color c;
c.r = (1-t)*a.r + t*b.r;
c.g = (1-t)*a.g + t*b.g;
c.b = (1-t)*a.b + t*b.b;

return c;
}

void display()
{
const int curTime = glutGet( GLUT_ELAPSED_TIME );

// figure out how far along duration we are, between 0.0 and 1.0
const float t = std::cos(float(curTime) * 0.001) * 0.5 + 0.5;

// interpolate between two colors
Color curColor = lerp(makeColor(0.0, 0.0, 0.0), makeColor(1.0, 1.0, 1.0), t);

glClearColor( curColor.r, curColor.g, curColor.b, 1 );
glClear( GL_COLOR_BUFFER_BIT );
glutSwapBuffers();
}

void timer( int value )
{
glutPostRedisplay();
glutTimerFunc( 16, timer, 0 );
}

int main( int argc, char** argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 400,400 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
return 0;
}
``````
Source (Stackoverflow)