没有出现 OpenGL 雾

OpenGL Fog does not appear

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

我的 "fog-code" 看起来像这样:

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-矩阵,认为 GL_PROJECTION- 矩阵没有真正的区别。根据 Reto Koradi 的 this article 和 post,两者之间存在相当大的差异。我强烈建议阅读全文以更好地理解 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
}

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

两种解决方案:

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

  • 改为使用片段着色器并计算其中的雾项。这就是我的建议。

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

Otherwise, if the fog source is FRAGMENT DEPTH, then c is the eye-coordinate distance from the eye, (0,0,0,1) in eye coordinates, to the fragment center.

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 规范的事实可能暗示此功能已过时且过时。