我完成了Phong Relflection Model的这个非常简单,完美的实现(目前还没有实现氛围,但这暂时不打扰我)。功能应能自我解释。

/**
 * Implements the classic Phong illumination Model using a reflected light
 * vector.
 */
public class PhongIllumination implements IlluminationModel {

    @RGBParam(r = 0, g = 0, b = 0)
    public Vec3 ambient;

    @RGBParam(r = 1, g = 1, b = 1)
    public Vec3 diffuse;

    @RGBParam(r = 1, g = 1, b = 1)
    public Vec3 specular;

    @FloatParam(value = 20, min = 1, max = 200.0f)
    public float shininess;

    /*
     * Calculate the intensity of light reflected to the viewer .
     *
     * @param P = The surface position expressed in world coordinates.
     *
     * @param V = Normalized viewing vector from surface to eye in world
     * coordinates.
     *
     * @param N = Normalized normal vector at surface point in world
     * coordinates.
     *
     * @param surfaceColor = surfaceColor Color of the surface at the current
     * position.
     *
     * @param lights = The active light sources in the scene.
     *
     * @return Reflected light intensity I.
     */
    public Vec3 shade(Vec3 P, Vec3 V, Vec3 N, Vec3 surfaceColor, Light lights[]) {
        Vec3 surfaceColordiffused = Vec3.mul(surfaceColor, diffuse);
        Vec3 totalintensity = new Vec3(0, 0, 0);
        for (int i = 0; i < lights.length; i++) {
            Vec3 L = lights[i].calcDirection(P);
            N = N.normalize();
            V = V.normalize();
            Vec3 R = Vec3.reflect(L, N); // reflection vector
            float diffuseLight = Vec3.dot(N, L);
            float specularLight = Vec3.dot(V, R);
            if (diffuseLight > 0) {
                totalintensity = Vec3.add(Vec3.mul(Vec3.mul(
                        surfaceColordiffused, lights[i].calcIntensity(P)),
                        diffuseLight), totalintensity);
                if (specularLight > 0) {

                    Vec3 Il = lights[i].calcIntensity(P);

                    Vec3 Ilincident = Vec3.mul(Il, Math.max(0.0f, Vec3
                            .dot(N, L)));

                    Vec3 intensity = Vec3.mul(Vec3.mul(specular, Ilincident),
                            (float) Math.pow(specularLight, shininess));

                    totalintensity = Vec3.add(totalintensity, intensity);
                }

            }
        }
        return totalintensity;
    }
}

现在我需要调整它以使其成为Blinn-Phong illumination model

我使用了来自listener和baker的公式,遵循伪代码,并尝试根据多种语言的Wikipedia文章多次实施该公式,但是它从未成功。
我只是没有镜面反射,或者它们是如此微弱和/或位于错误的位置和/或具有错误的颜色。

从众多错误的实现中,我发布了一些似乎已经错误的小代码。
所以我像这样计算我的Half Way向量和新的镜面反射光:
Vec3 H = Vec3.mul(Vec3.add(L.normalize(), V), Vec3.add(L.normalize(), V).length());
float specularLight = Vec3.dot(H, N);

通过这些更改,它应该已经可以工作(妈妈的强度不正确,但基本上应该是正确的)。但是结果是错误的。

这是两个图像。左图应如何正确呈现,右图如何呈现。


如果我降低亮度因子,您会在右上方看到一些镜面反射光:

虽然我了解Phong照明的概念,但我也了解了Blinn Phong简化后的性能更高的适应性,我已经尝试了好几天,但无法使其正常工作。任何帮助都可以申请。

编辑:

我通过this answer意识到了一个错误,即我在计算H时是通过|L+V|而不是通过除以它来除名的。我改为这样做:
Vec3 H = Vec3.mul(Vec3.add(L.normalize(), V), 1/Vec3.add(L.normalize(), V).length());

不幸的是,这并没有太大变化。结果如下:

如果我增加镜面常数并降低光泽度,则可以以一种错误的错误方式更清楚地看到效果:

但是,该划分只是标准化。

我想我错过了一步。因为这样的公式对我来说毫无意义。

如果您看这张照片:http://en.wikipedia.org/wiki/File:Blinn-Phong_vectors.svg

从H到N的投影远小于从V到R的投影。如果您想象改变图片中的向量V,则当观看向量位于“左侧”时,角度相同。并在向右移动时变得越来越不同。

我个人将整个投影乘以2来得到类似的结果(孔点是避免计算R)。虽然我什么都没读,但是我要尝试一下...

结果:镜面光的强度太大(白色区域),并且位置仍然错误。

我想我搞砸了其他事情,因为反射只是在错误的地方。但是呢

编辑:现在我在维基百科上阅读了笔记,其中N / H的角度实际上约为V / R的一半。为了弥补这一点,我应该将光泽指数乘以4而不是投影。如果我这样做,我最终将看不到任何镜面反射光。

最佳答案

弄清楚了!

我不得不否定观看向量。

09-28 07:44