球体光线追踪 - 镜面高光
Sphere raytracing - specular highlights
我在为我的球体设置正确的光照模型时遇到了一些问题。具体来说,我无法正确获得球体的镜面高光。这是我在光线追踪球体时看到的:
现在,镜面高光看起来应该更像这样:
据我了解,照明模型(对于这些漫反射球体)如下所示:
其中cr是球体的颜色,ca是光的环境分量,c l是光的颜色,n
是球体交点处的法线,l
是光的方向,cp是镜面高光的颜色,e
是eye/Look从,r
是球体表面的反射向量,指数中的p
指的是 phong constant/exponent(tight/loose 光线如何)。
这是我的过程:
public Color calculateIlluminationModel(Vector normal, Scene scene)
{
//c = cr * ca + cr * cl * max(0, n \dot l)) + cl * cp * max(0, e \dot r)^p
Vector lightSourceColor = getColorVector(scene.getLight().getLightColor()); //cl
Vector diffuseReflectanceColor = getColorVector(getMaterialColor()); //cr
Vector ambientColor = getColorVector(scene.getLight().getAmbientLightColor()); //ca
Vector specularHighlightColor = getColorVector(getSpecularHighlight()); //cp
Vector directionToLight = scene.getLight().getDirectionToLight(); //l
Vector reflectionVector = normal.multiply(2).multiply(normal.crossProduct(directionToLight)).subtract(directionToLight); //r = 2n(n \dot l) - l
Vector ambientTerm = diffuseReflectanceColor.multiply(ambientColor);
double angleBetweenLightAndNormal = directionToLight.dotProduct(normal);
Vector diffuseTerm = diffuseReflectanceColor.multiply(lightSourceColor).multiply(Math.max(0, angleBetweenLightAndNormal));
Vector phongTerm = lightSourceColor.multiply(specularHighlightColor).multiply(Math.pow(Math.max(0, scene.getCameraSettings().getLookFrom().dotProduct(reflectionVector)), (double) getPhongConstant()));
return getVectorColor(ambientTerm.add(diffuseTerm).add(phongTerm));
}
请注意,在这种情况下,phong 项的眼睛分量是相机的视角,即 (0, 0, 1),光线的方向是 (1, 0, 0)。
知道为什么我的镜面高光位于球体的顶部而不是面向光的方向吗?
如果我泄露了您需要帮助我的任何重要细节,请告诉我。
应根据表面法线和入射光线方向计算反射矢量,而不是像现在这样根据光线方向计算。
这一行有问题:
Vector reflectionVector = normal.multiply(2).multiply(normal.crossProduct(directionToLight)).subtract(directionToLight); //r = 2n(n \dot l) - l
不是取法线和光线方向之间的点积,而是取 normal.crossProduct(directionToLight)
叉积,这会给你一个垂直于你想要的向量的向量,给你您在上面看到的错误。
因此,您应该
Vector reflectionVector = normal.multiply(2).multiply(normal.dotProduct(directionToLight)).subtract(directionToLight); //r = 2n(n \dot l) - l
我在为我的球体设置正确的光照模型时遇到了一些问题。具体来说,我无法正确获得球体的镜面高光。这是我在光线追踪球体时看到的:
现在,镜面高光看起来应该更像这样:
据我了解,照明模型(对于这些漫反射球体)如下所示:
其中cr是球体的颜色,ca是光的环境分量,c l是光的颜色,n
是球体交点处的法线,l
是光的方向,cp是镜面高光的颜色,e
是eye/Look从,r
是球体表面的反射向量,指数中的p
指的是 phong constant/exponent(tight/loose 光线如何)。
这是我的过程:
public Color calculateIlluminationModel(Vector normal, Scene scene)
{
//c = cr * ca + cr * cl * max(0, n \dot l)) + cl * cp * max(0, e \dot r)^p
Vector lightSourceColor = getColorVector(scene.getLight().getLightColor()); //cl
Vector diffuseReflectanceColor = getColorVector(getMaterialColor()); //cr
Vector ambientColor = getColorVector(scene.getLight().getAmbientLightColor()); //ca
Vector specularHighlightColor = getColorVector(getSpecularHighlight()); //cp
Vector directionToLight = scene.getLight().getDirectionToLight(); //l
Vector reflectionVector = normal.multiply(2).multiply(normal.crossProduct(directionToLight)).subtract(directionToLight); //r = 2n(n \dot l) - l
Vector ambientTerm = diffuseReflectanceColor.multiply(ambientColor);
double angleBetweenLightAndNormal = directionToLight.dotProduct(normal);
Vector diffuseTerm = diffuseReflectanceColor.multiply(lightSourceColor).multiply(Math.max(0, angleBetweenLightAndNormal));
Vector phongTerm = lightSourceColor.multiply(specularHighlightColor).multiply(Math.pow(Math.max(0, scene.getCameraSettings().getLookFrom().dotProduct(reflectionVector)), (double) getPhongConstant()));
return getVectorColor(ambientTerm.add(diffuseTerm).add(phongTerm));
}
请注意,在这种情况下,phong 项的眼睛分量是相机的视角,即 (0, 0, 1),光线的方向是 (1, 0, 0)。
知道为什么我的镜面高光位于球体的顶部而不是面向光的方向吗?
如果我泄露了您需要帮助我的任何重要细节,请告诉我。
应根据表面法线和入射光线方向计算反射矢量,而不是像现在这样根据光线方向计算。
这一行有问题:
Vector reflectionVector = normal.multiply(2).multiply(normal.crossProduct(directionToLight)).subtract(directionToLight); //r = 2n(n \dot l) - l
不是取法线和光线方向之间的点积,而是取 normal.crossProduct(directionToLight)
叉积,这会给你一个垂直于你想要的向量的向量,给你您在上面看到的错误。
因此,您应该
Vector reflectionVector = normal.multiply(2).multiply(normal.dotProduct(directionToLight)).subtract(directionToLight); //r = 2n(n \dot l) - l