0

我正在开发一个延迟着色程序,现在我必须在场景中设置 50 种不同的灯光。为此,我使用以下代码随机生成其属性(位置、漫反射颜色、镜面反射颜色):

void FBORender::BuildLights()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(0.0, 0.1);

    for (int i = 0; i < NUM_LIGHTS; i++)
    {
        float dc_r = (float) dis(gen);
        float dc_g = (float) dis(gen);
        float dc_b = (float) dis(gen);

        printf("%f\n", dc_r);

        float lp_x = (float)(rand() % 40 - 20);
        float lp_y = (float)(rand() % 100 + 10);
        float lp_z = (float)(rand() % 40 - 20);

        DC[i * NUM_LIGHTS] = dc_r;
        DC[i * NUM_LIGHTS + 1] = dc_g;
        DC[i * NUM_LIGHTS + 2] = dc_b;

        LP[i * NUM_LIGHTS] = lp_x;
        LP[i * NUM_LIGHTS + 1] = lp_y;
        LP[i * NUM_LIGHTS + 2] = lp_z;
    }
}

但是,我不太确定如何使用多盏灯进行照明。有人说环境光应该等于漫反射光,而镜面光应该是白色的。

调整我必须执行 Phong 照明的着色器,我有这个:

#version 410 core

#define numLights 5

uniform sampler2D tDiffuse; 
uniform sampler2D tPosition;
uniform sampler2D tNormals;

uniform vec4 specularColor;
uniform vec3 diffuseColor[numLights];
uniform vec3 vLightPosition[numLights];

in vec2 texCoord;

out vec4 fragColor;


void main( void )
{
    vec3 tex = texture( tDiffuse, texCoord.st ).xyz;
    vec3 vPosition = texture( tPosition, texCoord.st ).xyz;
    vec3 vNormal = normalize( texture( tNormals, texCoord.st ).xyz * 2 - 1 );

    vec3 vVaryingNormal = vNormal;

    for (int i = 0; i < numLights; i++)
    {
        vec3 vVaryingLightDir = normalize( vLightPosition[i] - vPosition );

        float diff = max( 0.0, dot( normalize( vVaryingNormal ), normalize( vVaryingLightDir ) ) );
        vec4 partialColor = diff * vec4(diffuseColor[i], 1.0);
        partialColor = vec4( mix( partialColor.rgb, tex, 0.5 ), partialColor.a );
        partialColor += vec4( diffuseColor[i], 1.0 );
        vec3 vReflection = normalize( reflect( -normalize( vVaryingLightDir ), normalize( vVaryingNormal )));
        float spec = max( 0.0, dot( normalize( vVaryingNormal ), vReflection ));
        if( diff != 0 )
        {
            float fSpec = pow( spec, 128.0 );
            partialColor.rgb += vec3( fSpec, fSpec, fSpec );
        }

        fragColor += partialColor;
    }
}

但是,我得到了丑陋的结果(如果不是错的话),如下图所示:

在此处输入图像描述 在此处输入图像描述

这个结果只使用了 2 盏灯。由于我必须使用 50,我认为我将看到的只是一个白屏......

4

2 回答 2

1

在延迟渲染中,您通常单独渲染每个灯光,然后让 GPU 将结果混合在一起。这降低了着色器的复杂性。

让我们仔细看看您的照明计算。

partialColor = vec4( mix( partialColor.rgb, tex, 0.5 ), partialColor.a );

嗯...这条线应该做什么?那时,partialColor包含漫反射颜色(假设为白色材质)。如果你真的想通过混合来计算材质颜色(这看起来有点奇怪),你应该在之后进行着色:

vec3 materialColor = mix( vec3(1.0, 1.0, 1.0), tex, 0.5 );
vec4 partialColor = vec4(diffuseColor[i] * diff * materialColor, 1.0);

代码中的下一行:

partialColor += vec4( diffuseColor[i], 1.0 );

我不知道这应该做什么。离开它。

下一行:

vec3 vReflection = normalize( reflect( -normalize( vVaryingLightDir ), normalize( vVaryingNormal )));
float spec = max( 0.0, dot( normalize( vVaryingNormal ), vReflection ));

您正在混合 Phong 和 Blinn-Phong。Phong 需要反射光矢量和眼睛矢量的点积。Blinn-Phong 需要法线与光和眼向量之间的半向​​量的点积。

下一行:

partialColor.rgb += vec3( fSpec, fSpec, fSpec );

这应该乘以灯光的镜面反射颜色。此外,diff != 0.0您应该检查,而不是检查spec > 0

如果您仍然遇到问题,请关闭镜面反射照明并查看漫反射照明是否正确。

此外,您的灯光看起来有点亮。浅色的期望值为(0.05, 0.05, 0.05)。其中 50 个总共是(2.5, 2.5, 2.5),这比白光要亮得多。

于 2015-05-26T20:52:09.537 回答
0

我没有看到任何基于距离的计算,但这是必需的,否则场景中的所有内容都会以相同的方式受到每个灯光的影响。

有不同的方法来计算基于距离的灯光,最常见的是反平方根,它基本上是:

 intensity = 1 / sqrt(distance * distance)

您还可以在 GameDev 上查看这篇文章。当然,如果您使用 PBS(基于物理的着色;例如:虚幻引擎 4 着色),您可以获得更好的外观。

于 2015-05-26T20:15:08.190 回答