OpenGL延迟渲染:点光源实现

OpenGL deferred rendering: point light implementation

我正在尝试使用 C# 和 OpenGL(使用 OpenTK)编写延迟渲染器。

但是不明白点光源的法线计算应该怎么实现

点光源片段着色器:

    vec2 texCoord = gl_FragCoord.xy / ScreenSize;

    vec3 pixelPos = texture2D(PositionBuffer,texCoord).xyz;
    vec3 pixelNormal = normalize(texture2D(NormalBuffer, texCoord).xyz);
    vec3 diffuseColor = texture2D(ColorBuffer, texCoord).xyz;

    vec3 toLight = LightCenter - pixelPos;

    浮点衰减 = clamp(1.0 - length(toLight)/LightRadius,0.0,1.0);

    toLight =归一化(toLight);

    float nDotL = max(dot(pixelNormal, toLight),0.0);

    vec3 diffuseLight = diffuseColor * nDotL;

    LightMap = LightIntensity * attenuation * vec4(diffuseLight,1.0);

结果:

看起来不错。但是光线是在一个10*10的平面上,光线的半径是5,所以光线应该几乎覆盖了这个表面。

我明白问题所在,只是不知道如何解决...

nDotL 的更多像素会更小,这导致 "artifact"。

如果我删除“* nDotL”部分,灯看起来像这样:

在这种情况下范围很好,但地板底部也被照亮了...

如果有人能告诉我如何解决这个问题,我将不胜感激。

Also the source code is here if it's needed.

结合衰减 + 漫反射时,闪电变暗是正常的。 因为它们不是 1.0(而是 0.0,1.0 之间的某个值),所以如果将两者相乘,您会得到更暗的结果。你应该增加光的强度。你可以做到

lightStrength / (ConstantDecay + distance*LinearDecay + distance*distance*CuadraticDecay). 

它会给你一个更柔和的衰减,并允许你增加光照效果以照亮更大的半径。

vec3 distance = toLight * (1.0 / LightRadius);
float attenuation = clamp(1 - dot(distance, distance), 0, 1);
attenuation = attenuation * attenuation;

使用这个 "formula" 它看起来像它应该的那样工作。