2016-10-29 84 views
0

我将如何实现一个使用C与OpenGL的例程,使背景颜色很好地从一种颜色过渡到另一种颜色,然后再次返回,反复?我在调色板中的所有颜色都是3位精度。从0.000到1.000。颜色分量以均匀的时间到达第二种颜色变得复杂,更不用说调整转换速度了。我现在保持在0.001的状态并不错。OpenGL背景颜色推子

+0

哪些是你遇到问题的一部分?动画/定时,还是颜色混合? – genpfault

+0

@genpfault肯定的时机。只是它的基本算法。虽然我会继续努力。这实际上主要是逻辑的失败。我想也许有人会无聊地写下来,然后我可以理解它并学习或至少实现它。 –

回答

1

要回答genpfault的回答你的问题:

glm::mix(以及GLSL的一个),基本上只是做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; 
} 
+0

我试图做到这一点,但我得到一个编译错误:预期说明符 - 限定符列表之前'颜色'颜色():颜色(0,0,0)..........我不太熟悉c或C++(或结构体),但只有这个C++吗?我正在使用C.它是否容易适应? –

+0

应该是这样的更好 – Zouch

+0

我不得不在一堆东西前面加上严格的关键字,并修正了一个错字,但它的工作方式也非常漂亮。 Tyvm,你真了不起。现在尝试,并实际上融入理解......叹息... –

2
  1. 抓住当前时间&计算时间X毫秒到未来
  2. 每一帧看你是未来的时间(某处0%和100%,两者之间)
  3. 使用的百分比值接近在两种颜色之间进行插值
  4. 如果每帧当前时间超过目标时间,重置动画端点&会设置新的未来时间。

总之:

// 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使颜色插值代码非常简洁。

+0

我不能完全弄清楚如何实现不带glm的u变量和除了黑色和白色以外的颜色混合的颜色。循环也重复,但我宁愿它来回。但感谢这篇文章,我仍然从中得到了一些想法。 –

+0

另外我宁可不使用计时器来完成它。只是因为它似乎没有必要。 –

+0

不使用定时器的问题(例如,使用全局计数器代替增量)是动画的速度将与刷新速度相关。渲染速度越快,获得新帧的速度越快。 – Zouch