specular 就是按照 pdf 版实验文档上给出的公式写的。
Vector3f specular = ks.cwiseProduct(attenuated_light) *
std::pow(std::max(0.0f, normal.dot(half_vec)), material.shininess);
我在计算 half_vec 时,lightDirection 和 viewDirection 都是先做了归一化后,再相加,然后再次做归一化处理。
但是 result 不论加上还是不加 specular,其最终渲染的结果都是一样的(都是没有高光),好像 specular 没有起到应用的作用。
下面是渲染得到图片:
不知道是哪里出问题了,还请学长们和各位同学教教我 orz
补充一张截图,result 只输出 specular,下面是渲染结果:
roland
(李昌洲)
2
那说明同学你计算出的 specular 应该等于 0,请在中间的步骤输出一下计算 specular 需要的中间变量,看看是哪一步得到了错误的结果导致最后的结果为 0
根据学长的提示,我打印出了计算 specular 需要的中间变量。
其中的 attenuated_light 按照下列公式计算:
Eigen::Vector3f attenuated_light = light.intensity / distance_square * Eigen::Vector3f(1, 1, 1);
截图中的 normalized_normal 和 normalized_halfVector 点乘后得到结果很小,在经过 10 次方后变成了一个几乎为 0 的数。
请问学长,我使用的公式是否有误?
另外,传入 phong_fragment_shader 函数的变量是否相机坐标系中经过插值的三角形顶点和法线?
我试着将光源设置到 (1,1,1) 以及更小时,计算得到的 specular 始终很小。
单输出 specular 的渲染结果,也跟之前一样是一片漆黑。
但输出 ambient+diffuse+specular 时,渲染结果如下图:
输出的 result 几乎只有 diffuse 在做贡献。
不好意思,学长。我可能是太笨了,没有理解您所说的计算距离时某个向量没有归一化。
我所使用的计算距离的公式如下:
float distance = (light.position - payload.world_pos).norm();
// payload.world_pos 相机坐标系/世界坐标系 插值后的坐标都尝试过
实际上就是 lightDir 取模。我不清楚哪个向量需要归一化。如果我理解有误,请您指出来。
tropher
5
感谢 roland 学长和 KON 同学的回答。
我发现问题是出在法线的计算上,于是做出了更改。
但是渲染结果出现了下面的问题:
原本是高光的地方变成了黑色。
然后我打印出了像素点的 result,也就是 rgb 值。发现本应是白色的像素点,它的 rgb 值却大于 255。
然后我使用 if 语句,把所有 rbg 值大于 255 的像素点的颜色全部赋值为 255。得到了如下结果:
请问我能否把原本应该是白色的,却因为 rgb 值大于 255 的像素点的颜色赋值为 255,这样算是作弊吗?
另外附上分别只有 ambient,diffuse,specular 的三张渲染图:
ambient
diffuse
specular