OpenGL背景颜色推子
Posted
技术标签:
【中文标题】OpenGL背景颜色推子【英文标题】:OpenGL Background color fader 【发布时间】:2016-10-29 04:42:14 【问题描述】:我将如何使用 C 和 OpenGL 实现一个例程,以使背景颜色从一种颜色很好地过渡到另一种颜色,然后再返回,重复?我调色板中的所有颜色都是 3 位精度。从 0.000 到 1.000。让颜色分量以统一的时间到达第二种颜色变得很复杂,更不用说调整过渡速度了。我现在可以将其保持在 0.001。
【问题讨论】:
您在哪个部分遇到了问题?动画/时间,还是颜色混合? @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;
【讨论】:
我正在尝试执行此操作,但出现编译错误:预期的 specifier-qualifier-list before 'Color' Color():Color(0,0,0) ... .......我对c或c++(或结构)不太熟悉,但这只是c++吗?我用的是 C,它容易适应吗? 应该这样更好 我不得不在一堆东西前面添加严格的关键字并修复一个错字,但它也可以很好地使用不同的颜色。 Tyvm,你太棒了。现在尝试并真正融入理解......叹息...... 很高兴为您提供帮助。如果这回答了您的问题,请将答案标记为接受,以帮助其他人更轻松地找到答案!【参考方案2】:-
获取当前时间并计算未来 X 毫秒的时间
每一帧都显示您与未来时间的距离(在 0% 到 100% 之间)
使用百分比值在两种颜色之间进行插值
如果每帧当前时间超过目标时间,请重置动画端点并设置新的未来时间。
大家一起:
// 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 使颜色插值代码非常简洁。
【讨论】:
我不太明白如何在没有 glm 的情况下使用 u 变量以及除了黑白之外的颜色来实现颜色混合。循环也会重复,但我宁愿它来回走动。但是感谢您的帖子,我仍然从中得到了一些想法。 我也不想使用计时器来完成它。只是因为它似乎没有必要。 不使用计时器的问题(例如,使用您递增的全局计数器)是动画的速度将与刷新速度有关。渲染和获得新帧的速度越快,动画就会越快。以上是关于OpenGL背景颜色推子的主要内容,如果未能解决你的问题,请参考以下文章