OpenGL背景颜色推子

时间:2016-10-29 04:42:15

标签: c opengl

如何使用C和OpenGL实现一个例程,使背景颜色从一种颜色转换到另一种颜色,然后重复一次又一次?我调色板中的所有颜色都是3位精度。从0.000到1.000。使颜色分量以均匀的时序到达第二种颜色变得复杂,更不用说调整转换速度了。我现在保持0.001可以。

2 个答案:

答案 0 :(得分:2)

  1. 抓住当前时间&计算未来X毫秒的时间
  2. 每一帧都会看到你与未来时间的接近程度(介于0%和100%之间)
  3. 使用百分比值在两种颜色之间进行插值
  4. 如果每帧当前时间超过目标时间,请重置动画端点&设定一个新的未来时间。
  5. 所有在一起:

    // 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;
}