OpenGL 雾不出现

Posted

技术标签:

【中文标题】OpenGL 雾不出现【英文标题】:OpenGL Fog does not appear 【发布时间】:2015-11-27 10:11:12 【问题描述】:

我想创建一个包含一些线条的坐标系,并希望显示一个带有深度雾的窗口。

我的“雾代码”如下所示:

glEnable(GL_FOG);
float fogColor[4] = 0.8, 0.8, 0.8, 1;
glFogi(GL_FOG_MODE, GL_LINEAR);
glFogfv(GL_FOG_COLOR, fogColor); 
glFogf(GL_FOG_DENSITY,0.8); 
glHint(GL_FOG_HINT, GL_NICEST);
glFogf(GL_FOG_START,0.1); 
glFogf(GL_FOG_END,200);

并且被放置在我的主函数中(还不知道这是否会导致任何问题,但只是为了确定),就在 init() 调用之后和我的显示函数调用之前。

更新:

问题实际上非常简单:我的问题是,我只在GL_MODELVIEW-matrix 上工作,认为GL_PROJECTION-matrix 没有真正的区别。根据this article 和 Reto Koradi 的帖子,存在相当大的差异。我强烈建议阅读完整的文章,以更好地了解 OpenGL 背后的系统(对我帮助很大)。

更正后的代码(用于我的 init() 调用)将是:

void init2()

    glClearColor (1.0, 1.0, 1.0, 0.0); // set background color to white
    glMatrixMode(GL_PROJECTION); // switch to projection mode
    glLoadIdentity(); // initialize a projection matrix
    glOrtho(-300, 300, -300, 300, -800, 800); // map coordinates to the viewport 
    gluLookAt(2,2,10, 0,0,-0.5, 0,1,0);
    glMatrixMode(GL_MODELVIEW); // now switch to modelview mode

【问题讨论】:

这样的困难是一个很好的例子,说明看似简单的固定 GL 管道编程如何使事情变得不那么简单。像@datenwolf 我强烈建议您切换到现代 GL 并在片段着色器中逐像素混合雾,因为那时,GPU 将执行这些计算,您现在可以尝试手动执行以找到合适的用于调用固定管道函数的参数。 【参考方案1】:

雾方程的计算基于(引用自 OpenGL 2.1 规范)的值:

否则,如果雾源为 FRAGMENT DEPTH,则 c 是眼睛到片段中心的眼睛坐标距离(眼睛坐标中的 (0,0,0,1))。

FRAGMENT_DEPTH 是默认值,因此这适用于您的情况。眼睛坐标是指应用模型视图变换后的坐标。所以它是应用模型视图变换后与原点的距离。该规范还允许实现使用 z 坐标的绝对值,而不是与原点的距离。

对您的代码的一个小观察:GL_FOG_DENSITY 与模式是否为 GL_LINEAR 无关。它仅用于指数模式。

对于GL_LINEAR 模式,行为与您预期的差不多。原始片段颜色与雾色在GL_FOG_STARTGL_FOG_END 范围内线性混合。所以小于GL_FOG_START的都是原来的片段颜色,GL_FOG_END之后的都是雾的颜色,两者之间的值是两者之间的线性插值,雾的颜色逐渐变多,原始的片段颜色越来越少。

要获得好的结果,您必须使用 GL_FOG_STARTGL_FOG_END 值。如果你没有得到想要的,你可以从减少GL_FOG_END的值开始。

我查看了链接代码,发现了一个问题:您在 GL_MODELVIEW 矩阵模式下指定投影矩阵。您需要注意以正确的矩阵模式指定矩阵,即投影矩阵为GL_PROJECTION

混合矩阵模式不会对生成的顶点坐标产生不利影响,因为模型视图矩阵和投影矩阵都应用于顶点。因此,对于非常简单的使用,您有时可以避免使用错误的模式。但是一旦光照开始发挥作用,使用正确的矩阵模式就变得至关重要,因为光照计算是在应用模型-视图变换之后、投影变换之前完成的。

是的,正如其他人已经指出的那样,如果您编写自己的着色器,这实际上会变得更简单。我引用 OpenGL 2.1 规范的事实可能暗示这个功能已经过时了。

【讨论】:

我假设您正在谈论 glLoadIdentity(); 调用,但我认为它只是加载了当前转换矩阵的单位矩阵,而不管 GL_MODELVIEW GL_PROJECTION (评论来自以前的项目,很抱歉....)还是我弄错了?另外,问题是,即使使用 GL_LINEAR(这肯定会显示一些东西),我也确实没有看到任何区别 @dennlinger 矩阵模式的问题是你在GL_MODELVIEW 模式下调用glOrtho()。该调用需要在GL_PROJECTION 模式下进行。 这确实是问题所在。在GL_PROJECTION 中调用,然后切换到GL_MODELVIEW,它实际上显示了一些东西。再次感谢!我会将解决方案链接到原始帖子【参考方案2】:

与 OpenGL-1.1 所做的许多事情一样,雾是在每个顶点级别上计算的。因此,如果您有一条长线,只有两个点,则仅针对端点计算雾,然后在其间线性插值颜色。根据线条的对齐方式和使用的着色模式,这可能不会导致明显的雾化。

两种解决方案:

将线细分为几十个线段,以便在两个以上的点对雾进行采样。

改用片段着色器并计算其中的雾项。我建议这样做。

【讨论】:

GL_FOG_HINT 设置为GL_NICEST(在发布的代码中),每个片段都会评估雾。 @RetoKoradi: ...如果且仅当实现支持它时。来自参考:GL_FOG_HINT Indicates the accuracy of fog calculation. If per-pixel fog calculation is not efficiently supported by the GL implementation, hinting GL_DONT_CARE or GL_FASTEST can result in per-vertex calculation of fog effects. 首先,感谢您的快速回答。根据您的帖子,您是说我应该在起点和终点看到一些差异(因为我也画了坐标轴,所以至少应该有明显的差异)。但现在连这些都看不到。

以上是关于OpenGL 雾不出现的主要内容,如果未能解决你的问题,请参考以下文章

std::string 的声明导致 OpenGL 出现分段错误

OpenCV 2.2 窗口导致 OpenGL 出现问题

CSOL OpenGL与D3D哪个好?

SDL+OpenGL 程序没有出现在 linux 上

OpenGL 窗口立即关闭并出现错误 -1073740777 (0xc0000417)

立方体没有按预期使用openGL出现