如何使用C和OpenGL实现一个例程,使背景颜色从一种颜色转换到另一种颜色,然后重复一次又一次?我调色板中的所有颜色都是3位精度。从0.000到1.000。使颜色分量以均匀的时序到达第二种颜色变得复杂,更不用说调整转换速度了。我现在保持0.001可以。
答案 0 :(得分:2)
所有在一起:
// g++ main.cpp -lglut -lGL
#include <GL/glut.h>
// http://glm.g-truc.net/
#include <glm/glm.hpp>
int dstTime = 0; // milliseconds
glm::vec3 begColor( 0.0f, 0.0f, 0.0f );
glm::vec3 endColor( 1.0f, 1.0f, 1.0f );
void display()
{
const int duration = 3000; // milliseconds
const int curTime = glutGet( GLUT_ELAPSED_TIME );
if( curTime > dstTime )
{
// reset animation parameters
dstTime = curTime + duration;
// swap colors
const glm::vec3 tmpColor = begColor;
begColor = endColor;
endColor = tmpColor;
}
// figure out how far along duration we are, between 0.0 and 1.0
const float u = ( curTime + duration - dstTime ) / (float)duration;
// interpolate between two colors
const glm::vec3 curColor = glm::mix( begColor, endColor, u );
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;
}
编辑:对不起C ++,GLM使颜色插值代码非常简洁。
答案 1 :(得分:1)
回答关于genpfault的回答的问题:
glm::mix
(以及GLSL&#39;}基本上只是linear interpolation。代码可能意味着
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;
}
现在,用于取回某些来回效果的常用功能是cosine function。
余弦为您提供介于-1和1之间的值,因此您可能希望将其缩放到0和1之间。这可以使用
完成float t = cos(x) * 0.5 + 0.5; // *0.5 gets to [-0.5, 0.5], +0.5 gets to [0,1]
然后使用此t
来计算颜色。 x
可以是当前时间乘以某个值,可以帮助您控制插值的速度。
编辑: 使用gpenfault的代码作为起点,你可以做这种事情(如果它有任何问题我删除它):
// 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;
}