没有出现 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_START
到 GL_FOG_END
范围内与雾颜色线性混合。所以小于GL_FOG_START
的都是原始片段颜色,GL_FOG_END
之后的都是雾色,两者之间的值是两者之间的线性插值,雾色逐渐变多,原始片段颜色逐渐变少。
要获得好的结果,您必须使用 GL_FOG_START
和 GL_FOG_END
值。如果你没有得到想要的那么多,你可以从减少 GL_FOG_END
.
的值开始
我查看了链接代码,注意到一个问题:您在 GL_MODELVIEW
矩阵模式下指定投影矩阵。您需要注意以正确的矩阵模式指定矩阵,投影矩阵为 GL_PROJECTION
。
混合矩阵模式不会对生成的顶点坐标产生不利影响,因为模型视图矩阵和投影矩阵都应用于顶点。因此,对于非常简单的使用,有时您可以使用错误的模式。但是一旦光照开始发挥作用,使用正确的矩阵模式就很关键了,因为光照计算是在应用模型-视图变换之后,但在投影变换之前完成的。
是的,正如其他人已经指出的那样,如果您编写自己的着色器,很多事情实际上会变得更简单。我引用 OpenGL 2.1 规范的事实可能暗示此功能已过时且过时。
我想创建一个包含一些线的坐标系,并想显示一个 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_START
到 GL_FOG_END
范围内与雾颜色线性混合。所以小于GL_FOG_START
的都是原始片段颜色,GL_FOG_END
之后的都是雾色,两者之间的值是两者之间的线性插值,雾色逐渐变多,原始片段颜色逐渐变少。
要获得好的结果,您必须使用 GL_FOG_START
和 GL_FOG_END
值。如果你没有得到想要的那么多,你可以从减少 GL_FOG_END
.
我查看了链接代码,注意到一个问题:您在 GL_MODELVIEW
矩阵模式下指定投影矩阵。您需要注意以正确的矩阵模式指定矩阵,投影矩阵为 GL_PROJECTION
。
混合矩阵模式不会对生成的顶点坐标产生不利影响,因为模型视图矩阵和投影矩阵都应用于顶点。因此,对于非常简单的使用,有时您可以使用错误的模式。但是一旦光照开始发挥作用,使用正确的矩阵模式就很关键了,因为光照计算是在应用模型-视图变换之后,但在投影变换之前完成的。
是的,正如其他人已经指出的那样,如果您编写自己的着色器,很多事情实际上会变得更简单。我引用 OpenGL 2.1 规范的事实可能暗示此功能已过时且过时。