带有 Blinn-Phong GLSL 着色器、点光源的奇怪结果

Posted

技术标签:

【中文标题】带有 Blinn-Phong GLSL 着色器、点光源的奇怪结果【英文标题】:Strange results w/ Blinn-Phong GLSL shader, point lights 【发布时间】:2011-09-20 13:01:17 【问题描述】:

我已经制作了一个 GLSL 着色器,用于在场景上进行逐像素 blinn phong 照明,但我在场景上投射的光线方面遇到了一些问题。每个灯光的效果似乎都有一个非常硬的边界(在随附的屏幕截图中,您可以在底部平面上看到灯光的边界 - 灯光(其世界位置相当于场景中悬挂的黑色球体)悬挂在上方飞机和法拉利模型,但由于某种原因,仅将光线适当地投射到/朝向/相机,而不是向前,远离相机。

我觉得我犯了一些错误/对眼睛方向如何影响 blinn phong 照明模型缺乏一些了解。我是否搞砸了我的计算,或者我根本不明白这个特定的照明模型应该如何工作?

我的着色器代码在这里:https://gist.github.com/1040417

效果截图:

【问题讨论】:

另外,作为问题的附加部分:我看到文字说效果的衰减需要按片段计算,我不明白,所以没有这样做。我所见过的衰减计算似乎都不是基于任何片段属性,因为距离计算和衰减项都在顶点着色器中可用。我是不是也在这里误会了什么? 【参考方案1】:

您对半向量的计算似乎是错误的。半向量是光线方向和视线方向(相机方向)之间的向量,也是眼睛方向影响光照的部分。但是由于您是在世界空间而不是在视图空间中计算光照,因此您不能只使用视图空间位置作为眼睛方向,而是需要将世界空间中的查看器/相机的位置作为着色器的输入。哦,别忘了在计算半向量之前对光向量进行归一化(还要对归一化的光向量进行插值)。所以替换

halfVectors[i] = normalize(lights.allLights[i].position + lightDirections[i]);

uniform vec3 viewerPos;
...
vec3 eyeDirection = normalize(viewerPos - worldPosition.xyz);
...
lightDirections[i] /= dist;
halfVectors[i] = normalize(eyeDirection + lightDirections[i]);

应该做的伎俩。眼睛方向不再需要变化,因为它在片段着色器中不需要(它隐式保存在半向量中)。

我不确定插值半向量是否与在片段着色器中插值眼睛方向和计算半向量的结果完全相同(这样你也可以省去许多变化)。但至少它现在应该可以工作了。

编辑:与衰减因子相同。由于它与光线的距离是非线性的,因此您可能不会得到与按片段计算它时完全相同的结果。但这可能是可以容忍的,具体取决于镶嵌质量。

【讨论】:

谢谢 - 我想我可能在视图空间与世界空间的问题上出了点问题,但我不知道如何解决它。使用这种方法,我仍然看到一个非常激烈的光边界,但它不再是一条精确的直线。 AFA 衰减因子,我将它移到片段着色器中 - 我对不同属性的工作方式有一个严重的误解。 @netshade 强烈的光边界也可能只是来自过于激进的衰减因素。虽然二次衰减在物理上是正确的,但不要太认真。 明白了。非常感谢您的帮助,非常感谢。

以上是关于带有 Blinn-Phong GLSL 着色器、点光源的奇怪结果的主要内容,如果未能解决你的问题,请参考以下文章

GLSL将颜色数据从片段着色器发送到顶点着色器似乎总是等于0

Python之OpenGL笔记(5):OpenGL着色器语言(GLSL)应用画三角形

使用 HLSL 和 D3D11 进行 Blinn-Phong 着色:点光源

GLSL 基本概念

GLSL 基本概念

第二篇: WebGL 着色器和GLSL