【发布时间】:2014-03-28 15:05:37
【问题描述】:
Blinn-phong 着色...?
所以我遇到的问题是,如上图所示,我似乎无法让镜面高光平滑地着色。问题是沿面边缘的突然切断,这不应该发生。漫反射照明似乎工作得很好,它使用相同的插值。这是 blinn-phong 镜面高光的代码:
vec3 halfAngle = normalize(lightDirection.xyz + viewRay);
float blinnTerm = dot(normal.xyz, halfAngle);
blinnTerm = clamp(blinnTerm, 0.0f, 1.0f);
blinnTerm = pow(blinnTerm, 300.0f);
float specIntensity = intensity * blinnTerm;
vec4 specColour = specIntensity * specColour;
lightDirection 是恒定的,它无限远(即太阳)。至于 viewRay,它是在顶点着色器中计算的,使用投影矩阵:
viewRay = vec3(-(UV.x * 2.0f - 1.0f) / projection[0].x,
-(UV.y * 2.0f - 1.0f) / projection[1].y,
1.0f);
我正在使用延迟渲染,这是 UV 值的来源(渲染为全屏纹理)。
我唯一能想到的是正常插值不够平滑。但如果是这样的话,我将如何解决它? (我将法线存储为 16 位浮点数,但将其提高到 32 位并没有什么不同)。
【问题讨论】:
-
我认为您的 viewRay 计算可能已关闭。在我的延迟渲染器中,我从对象的世界位置(G 缓冲区纹理之一 - 你的 UV 是否也包含它?)和相机的世界位置(作为统一传入)计算视图矢量。然后在这些点之间进行简单的减法就可以得到视图向量。我不遵循您 viewRay 计算的逻辑,也不能说它是否应该工作。
-
我的第一个想法是法线没有以足够的精度存储,但我看到你已经涵盖了。您使用的是哪种视场?对于 300 高光功率,该高光看起来相当大。
-
@ArttuPeltonen viewRay 应该是正确的。基本上我正在做的是将剪辑空间坐标乘以逆透视矩阵以获得相机空间坐标。这让我可以使用深度信息来重建位置,从而节省内存带宽(要上传的纹理更少)。
-
@GuyRT 视野是 45 度,但我故意提高 specIntensity 以夸大问题。在我的回答中,它是相同的 300 项,只是……稍微低了一点。
标签: opengl glsl lighting normals specular