1

我正在编写一个 GLSL 程序,作为在 Maya(一个闭源 3D 应用程序)内部运行的插件的一部分。我的插件将自定义几何图形呈现到应用程序呈现其默认多边形几何图形的相同图像缓冲区中。该应用程序使用 OpenGL 固定管道进行照明和着色,但我使用 GLSL 来渲染自定义几何体和材质。

我的问题是,我想在我的着色器中模仿固定管道灯的行为。应用程序定义了gl_LightSource制服中的灯光,我希望它们在分配给我的自定义几何图形时具有与分配给应用程序的默认多边形几何图形时相同的方向、强度等。

这些gl_LightSource字段有明确的记录,但我找不到关于固定管道如何解释这些字段的明确文档。有很多关于如何在 GLSL 中对点/定向/聚光灯进行编码的示例,但它们似乎并不完全模仿固定管道。例如,如果应用程序定义了它们的混合,您如何确定灯光是点光、定向光还是聚光灯?可以在不在我的着色器中引入过多分支的情况下处理混合光类型吗?

简而言之,是否有任何关于固定功能管道如何评估的权威文档或示例gl_LightSource

4

3 回答 3

2

我的问题是,我想模仿片段着色器中固定管道灯的行为。

那么这是你的第一个问题,因为“固定管道灯”是在顶点处理器中实现的,而不是每个片段。

简而言之,是否有任何关于固定功能管道如何评估 gl_LightSource 的权威文档或示例?

是的。它被称为“OpenGL 图形系统:规范”。它可以在 OpenGL Registry 上下载;你想要兼容性配置文件。4.2 兼容性规范的第 2.13 节涵盖了用于照明的所有数学运算。只需将其转换为 GLSL 代码。

请注意,您将无法完全模仿固定功能管道。也就是说,没有办法保证基于着色器的光照和固定功能光照之间的不变性。你会得到一些接近的东西,但不是二进制相同的值。

可以在不在我的着色器中引入过多分支的情况下处理混合光类型吗?

你如何定义“过度”?您将需要分支,因为 OpenGL 的光照方程涉及条件逻辑。

这通常是人们不只是在着色器中重新实现 GL 光照的部分原因。如果您只编写 GLSL,而不是使用数据驱动的方法,则效率会高得多。

于 2012-06-26T18:33:01.487 回答
1

在OpenGL ES 2.0 Programming Guide中有完整的实现固定功能管线的顶点着色器源代码。(请注意,固定功能管线只是逐顶点光照,因此光照计算不需要片段着色器。)

我相信当 OpenGL 驱动程序处于固定功能模式时,它会在内部使用这个顶点着色器。请查看本书的第 8 章,顶点着色器。

它定义了一个具有以下属性的灯光结构;

  1. 位置,
  2. 环境色彩,
  3. 漫反射颜色,
  4. 高光颜色,
  5. 现货方向,
  6. 衰减因子(常数、线性、二次),
  7. 现货指数,
  8. 光斑截止角,
  9. ComputeDistanceAttanuation (bool)

并且,每个灯光都在函数lighting_equation()中进行处理。

于 2012-06-27T23:59:29.443 回答
0

这是我根据OpenGL规范文档提出的:

#version 410 compatibility

vec3 incedentLight (in gl_LightSourceParameters light, in vec3 position)
{
    if (light.position.w == 0) {
        return normalize (-light.position.xyz);
    } else {
        vec3 offset = position - light.position.xyz;
        float distance = length (offset);
        vec3 direction = normalize (offset);
        float intensity;
        if (light.spotCutoff <= 90.) {
            float spotCos = dot (direction, normalize (light.spotDirection));
            intensity = pow (spotCos, light.spotExponent) *
                    step (light.spotCosCutoff, spotCos);
        } else {
            intensity = 1.;
        }
        intensity /= light.constantAttenuation +
                light.linearAttenuation * distance +
                light.quadraticAttenuation * distance * distance;
        return intensity * direction;
    }
}

根据我对 GLSL 的了解,分支应该是相当有效的,因为它只依赖于统一变量。

于 2012-07-05T20:06:48.147 回答