OpenGL中的振荡颜色

Posted

技术标签:

【中文标题】OpenGL中的振荡颜色【英文标题】:Oscilating colors in OpenGL 【发布时间】:2015-05-17 02:02:41 【问题描述】:

我正在尝试从 OGLSuperbible 中完成一些 OpenGL 中的基本示例。基本上,我要让背景从红色变为橙色,再变为绿色并返回。

这是我正在使用的代码:

typedef float F32;

void Example1::Render(void) 
time += 0.20f;
const GLfloat color[] =  (F32)sin(time) * 0.5f + 0.5f,
                          (F32)cos(time) * 0.5f + 0.5f,
                           0.0f, 1.0f ;
glClearBufferfv(GL_COLOR, 0, color);

我有一个精确的计时器,可以测量最后一帧的增量时间,但是,只要我调用sincos 函数时,只要小于1,它只会使屏幕保持绿色。但是,如果我硬编码要更改的值,就像我所做的那样,如果我将它增加1 或更多,它会在颜色之间快速闪烁(就像狂欢一样)。我不确定为什么这些函数不适用于浮点数。我正在使用 Visual Studio,并包含 math.h 标头。有没有人见过这样的东西?

更新:根据建议,我对代码进行了一些尝试。我通过添加以下内容使程序具有我正在寻找的效果:

测试我的代码,我手动输入以下内容:

在构造函数中:

Example1(void): red(0.0f), green(1.0f), interval(0.002f), redUp(true), greenUp(false).....

在渲染循环中

if (red >= 1.0f)  redUp = false; 
else if (red <= 0.0f)  redUp = true; 

if (green >= 1.0f)  greenUp = false; 
else if (green <= 0.0f)  greenUp = true; 

if (redUp)  red += interval; 
else  red -= interval; 

if (greenUp)  green += interval; 
else  green -= interval; 

const GLfloat color[] =  red, green, 0.0f, 1.0f ;

它做了它应该做的,但是使用浮点数的 sin 和 cos 函数没有改变。我很困惑为什么,我假设给 sin 和 cos 作为时间的浮点值会起作用。我曾尝试手动计算时间,手动将其增加 1/60 秒,但每当我使用小于 1.0f 的 sin 和 cos 时,它只会保持绿色。

【问题讨论】:

F32是浮点类型的别名吗? 是的。对不起,我没有包括那个。这是定义: typedef float F32; 【参考方案1】:

您的时间间隔似乎太大了。如果您只是假设您以 60fps 的速度运行(如果您不限制它可能有数百个),那么增量时间应该是每帧 0.01667 (1/60) 秒。每帧增加 0.2(尤其是刷新率超过 60fps 时)会导致频闪。

如果您使用的是 C++11,我建议您使用 Chrono 库并获取要使用的确切数字。这在this post 中有详细记录。

使用实际时间后,请记住 sincos 采用弧度,而不是度数。范围仅为 [0, 2PI),因此除了仅传入您的 time 变量外,还可以将其乘以一些小因子并使用该数字:

time += 0.01667f;
F32 adjustedTime = time * 0.02; // OcillationSpeed
const GLfloat color[] =  (F32)sin( adjustedTime ) * 0.5f + 0.5f,
                          (F32)cos( adjustedTime ) * 0.5f + 0.5f,
                          ...

另外,我不知道你是否忽略了将它添加到这个问题中,但不要忘记在设置清晰颜色后调用glClear(GL_COLOR_BUFFER_BIT);

【讨论】:

感谢您的建议,我已经尝试了您的想法,但屏幕仍然保持相同的颜色。当我添加一个断点,然后查看值时,它看起来像是因为帧之间的颜色漂移不足以实际改变颜色。颜色最终约为 (0.55, .99, 0.0) 和 (0.59, 0.99. 0.0)。我确定我只是不明白这里的某些内容,您看到实际颜色最终与您的代码一起出现了什么?还是您尝试过? 如果假设 60 fps 动画,从 (0.55, 0.99, 0.0) 到 (0.59, 0.99, 0.00) 的变化在视觉上是非常快的。 我觉得我错过了一些大事。当我运行程序时,打开的窗口保持绿色,如果时间小于 1。如果它大于 1,那么我会得到闪烁的效果。有人看到我错过了什么吗?我确信我的想法是错误的。 @MaxwellMiller: 你的time 变量实际上是浮点类型吗? 是的,我已经将它作为双精度和浮点数进行了尝试。即使作为双精度或浮点数,如果值等于 1.0f,它会迅速改变颜色,但如果值小于 1.0f,包括 0.999999f,那么它只是保持绿色,完全不改变.我真的不明白。【参考方案2】:

我认为您需要通过 glutSwapBuffers(); 刷新屏幕; 我有这段代码,我可以毫无困难地更改背景颜色:

void RenderScene(void)
    
    // Clear the window with current clearing color
    //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

        time+=0.2;
        const GLfloat color[]=sin(time)*0.5f+0.5f,cos(time)*0.5f+0.5f,0.0f,1.0f;
        glClearBufferfv(GL_COLOR,0,color);
    GLfloat vRed[] =  1.0f, 0.0f, 0.0f, 1.0f ;
    shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
    triangleBatch.Draw();



    // Perform the buffer swap to display back buffer

    glutSwapBuffers();
    

我得到了这些结果

【讨论】:

我实际上是在我的主循环中调用交换缓冲区,尽管我确实认为这是问题所在。下面我有解决我的问题的方法,但我很感激你的洞察力。【参考方案3】:

感谢所有输入。经过大量挖掘,我能够找到我的问题所在。我认为这是合乎逻辑的,但事实并非如此。这是一个语法错误。这是产生与您看到的相同结果的代码:

    const GLfloat color[] =  F32(sin(curTime)) * 0.5f + 0.5f,
                          F32(cos(curTime)) * 0.5f + 0.5f,
                          0.0f, 1.0f ;
glClearBufferfv(GL_COLOR, 0, color);

区别在于使用 (F32)sin.... 或 F32(sin(...我已经为 F32 类型设置了,我之所以这样做,是因为 Jason Gregory 在一本名为 Game Engine Architecture 的书中提出了一些建议。无论如何,感谢您与我一起完成它。

【讨论】:

以上是关于OpenGL中的振荡颜色的主要内容,如果未能解决你的问题,请参考以下文章

在xcode中替换openGl绘图中的特定颜色?

OpenGL颜色混合原理

OpenGL中的调色板动画

OpenGL背景颜色推子

OpenGL 颜色插值

如何在OpenGL中反转纹理颜色