OpenGL:使用着色器通过使用预先计算的颜色图来创建顶点照明?

Posted

技术标签:

【中文标题】OpenGL:使用着色器通过使用预先计算的颜色图来创建顶点照明?【英文标题】:OpenGL: Using shaders to create vertex lighting by using pre-calculated colormap? 【发布时间】:2010-11-19 16:01:26 【问题描述】:

首先,我对着色器能做什么知之甚少,而且我对制作顶点光照非常感兴趣。我正在尝试使用 3d 颜色图,用于计算世界该位置的顶点颜色,并使用颜色图中的附近颜色插入颜色。

我不能使用典型的 OpenGL 光照,因为它可能太慢了,而且我需要渲染很多光照。我将首先在颜色图中“渲染”灯光,然后我可以手动映射使用颜色图中相应颜色绘制的每个顶点。

...或者我可以以某种方式自动化这个过程,所以我不必自己更改顶点的颜色值,但是着色器也许可以为我做这件事?

问题是……这可能吗?如果是的话:我需要知道什么才能使它成为可能?

编辑:请注意,我还需要有效地更新光照贴图,而不关心光照贴图的大小,因此应该只在我想要更新的光照贴图的特定部分进行更新.

【问题讨论】:

【参考方案1】:

几乎听起来你想要做的是将灯光渲染到你的颜色贴图,然后使用你的颜色贴图作为纹理,但不是贴花模式,而是将其设置为调制模式,所以它是与现有颜色相乘,而不是仅仅替换它。

这有一点不同:它不仅会影响顶点,还会映射到各个片段(本质上是像素)。

编辑:我想到的不是 3D 纹理——而是立方体贴图。基本上,创建一个围绕“世界”中所有事物的虚拟立方体。为该立方体的每个面创建一个 2D 纹理。将您的颜色渲染到立方体贴图。然后,为顶点着色,您(实际上)从中心向外延伸一条射线,穿过顶点,到达立方体。您在立方体贴图上点击的像素会为您提供该顶点的照明颜色。

更新应该是相对有效的——你有顶部、底部、前面等的正常 2D 纹理,你可以根据需要更新它们。

【讨论】:

我不需要像素着色,只需要更改 GL_QUADS 的 4 个角,因为那样会更快。创建 3d 纹理听起来像是与旧卡的兼容性问题......有没有办法以某种方式将我生成的数据与着色器一起使用? 另外,此光照贴图必须有效更新,请参阅我的编辑。 立方体贴图嗯...但我需要它像 3d 纹理一样工作,事实上我将使用的颜色图至少有 257x257x257 不同的颜色,所以我可以在世界中间为单个多边形着色用相应的颜色。如果它在这 256 个立方体中的两个之间,它将插入颜色。现在我开始认为,当我扩展世界大小时,使用这种颜色图会变得臃肿...... 257x257x257 将使用至少 67MB 内存:/ 但是在运行时计算颜色会很慢......使用 GL_LIGHT[0-7] ?【参考方案2】:

如果您不能使用固定函数管道功能,那么执行每个顶点光照的最佳方法应该是在顶点着色器中对每个顶点进行所有光照计算,然后当您将它传递给片段着色器时,它将是正确的插在脸上。

在使用大量光源时处理性能问题的另一种方法是使用deferred rendering,因为它只会对实际可见的几何图形进行光照计算。

【讨论】:

但是我所有的灯光都是可见的,没有优化的可能性来减少灯光数量。 是的,但是延迟渲染的优化不是为了减少灯光数量(为什么会有不可见的灯光?),而是通过仅计算可见的几何图形来减少灯光计算。正常渲染可能会花费大量时间计算顶点/片段上的光照,这些顶点/片段可能由于前面的其他几何体而最终不会显示。 啊,我明白了,是的,我正在考虑这一点,但我也不想重新计算每帧照明的每个对象......只有当它们的位置发生变化或灯光发生变化时。我也不需要任何反射或任何复杂的东西,只需要彩色顶点。【参考方案3】:

这是可能的,但在当前硬件上无效。

您希望将光量渲染为 3d 纹理。光栅化器在 2D 表面上工作,因此您的体积必须沿其中一个轴拆分。可以通过以下方式之一进行拆分:

每个拆分都有不同的绘制调用 实例化绘制,基于 glInstanceID 的图层选择(需要几何着色器) 几何着色器中的分支直接来自单个绘制调用

为了实现它,我建议阅读 GL-3 规范和示例。这并不容易,对于复杂场景的结果也不会足够快。

【讨论】:

以上是关于OpenGL:使用着色器通过使用预先计算的颜色图来创建顶点照明?的主要内容,如果未能解决你的问题,请参考以下文章

初识OpenGL 片段着色器(Fragment Shader)

初识OpenGL 片段着色器(Fragment Shader)

如何使用 OpenGL 和 GLSL 改变颜色(C++)?

OpenGL ES(一.概念)

此顶点着色器中的统一浮动不起作用

VAO 不使用着色器渲染颜色