实现Blinn-Phong着色模型的问题

The*_*can 3 java 3d graphics vector-graphics

我做了这个非常简单,完美的工作,Phong Relflection模型的实现(还没有实现的氛围,但现在不打扰我).功能应该是自我解释.

/**
 * 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我需要使它适应成为Blinn-Phong照明模型

我使用了来自hearn和baker的公式,遵循伪代码并尝试根据几种语言的维基百科文章多次实现它但它从未起作用.我只是没有镜面反射,或者它们太弱和/或位于错误的位置和/或颜色错误.

从众多错误的实现中,我发布了一些似乎已经错误的小代码.所以我计算我的Half Way矢量和我的新镜面反射光如下:

Vec3 H = Vec3.mul(Vec3.add(L.normalize(), V), Vec3.add(L.normalize(), V).length());
float specularLight = Vec3.dot(H, N);
Run Code Online (Sandbox Code Playgroud)

由于这些变化很小,它应该已经有效(maby没有正确的强度,但基本上应该是正确的).但结果是错误的.

这是两个图像.离开它应该如何正确渲染和正确渲染.

对 错误

如果我降低光泽因子,你可以在右上方看到一点镜面光: 较低的光泽

尽管如此,我理解Phong照明的概念以及简化的更高性能的blinn phong,我正在尝试几天并且无法让它发挥作用.任何帮助都是适当的.

编辑:

我意识到通过一个错误的这个回答,我感到mutiplying |L+V|,而不是计算H.我改deviding这样当它划分:

Vec3 H = Vec3.mul(Vec3.add(L.normalize(), V), 1/Vec3.add(L.normalize(), V).length());
Run Code Online (Sandbox Code Playgroud)

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

DIV

如果我提高镜面常数并降低光泽度你可以用一种错误的方式更清楚地看到效果:

DIV2

然而,这种划分只是规范化.

我想我错过了一步.因为这样的公式对我来说没有意义.

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

H到N的投影远小于V到R.如果你想象改变图像中的矢量V,当观察矢量"在左侧"时角度是相同的.走向右边时变得越来越不同.

我将整个投影乘以2变成类似的东西(并且孔点是为了避免计算R).尽管如此,我还没有读过任何关于我将要尝试的事情......

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

我想我正在弄乱其他东西,因为反思只是在错误的地方.但是什么?

编辑:现在我在维基百科上读到N/H的角度实际上是近似的一半或V/R. 为了弥补我应该将我的光度指数乘以4而不是我的投影.如果我这样做,我最终没有可见的镜面光.

The*_*can 5

弄清楚了!

我不得不否定查看向量.