Perlin噪声发生器产生高对比度噪声

时间:2016-08-14 11:56:20

标签: c# math raytracing perlin-noise

我一直在关注这本书" Raytracing:下周"彼得雪莉。我无法实现他的perlin噪音发生器。我得到的结果的对比度比他高,我不知道为什么。

namespace SharpRays.Utilities {
    using System;
    using System.Collections.Generic;
    using System.Numerics;

    using static Core.Random;

    internal class Perlin {
        private static Vector3[] ranvec;
        private static int[] perm_x;
        private static int[] perm_y;
        private static int[] perm_z;

        public Perlin() {
            ranvec = PerlinGenerate();
            perm_x = PerlinGeneratePerm();
            perm_y = PerlinGeneratePerm();
            perm_z = PerlinGeneratePerm();
        }

        public float Noise(Vector3 p) {
            var u = p.X - (float)Math.Floor(p.X);
            var v = p.Y - (float)Math.Floor(p.Y);
            var w = p.Z - (float)Math.Floor(p.Z);
            var i = (int)Math.Floor(p.X);
            var j = (int)Math.Floor(p.Y);
            var k = (int)Math.Floor(p.Z);
            var c = new Vector3[2, 2, 2];
            for (var di = 0; di < 2; di++) {
                for (var dj = 0; dj < 2; dj++) {
                    for (var dk = 0; dk < 2; dk++) {
                        c[di, dj, dk] = ranvec[perm_x[(i + di) & 255] ^ perm_y[(j + dj) & 255] ^ perm_z[(k + dk) & 255]];
                    }
                }
            }
            var interp = PerlinInterp(c, u, v, w);
            return interp;
        }

        public float Turb(Vector3 p, int depth = 7) {
            var accum = 0f;
            var tempP = p;
            var weight = 1f;
            for (int i = 0; i < depth; i++) {
                accum += weight * Noise(tempP);
                weight *= 0.5f;
                tempP *= 2;
            }

            return Math.Abs(accum);
        }

        private static float PerlinInterp(Vector3[,,] c, float u, float v, float w) {
            var uu = u * u * (3 - 2 * u);
            var vv = v * v * (3 - 2 * v);
            var ww = w * w * (3 - 2 * w);
            var accum = 0f;
            for (var i = 0; i < 2; i++) {
                for (var j = 0; j < 2; j++) {
                    for (var k = 0; k < 2; k++) {
                        var weightV = new Vector3(u - i, v - j, w - k);
                        accum += (i * uu + (1 - i) * (1 - uu)) * (j * vv + (1 - j) * (1 - vv)) * (k * ww + (1 - k) * (1 - ww)) * Vector3.Dot(c[i, j, k], weightV);
                    }
                }
            }

            return accum;
        }

        private static Vector3[] PerlinGenerate() {
            var p = new Vector3[256];
            for (var i = 0; i < p.Length; i++) {
                p[i] = Vector3.Normalize(new Vector3(-1 + (2 * RandomFloat()), -1 + (2 * RandomFloat()), -1 + (2 * RandomFloat())));
            }
            return p;
        }

        private static void Permute(IList<int> p) {
            for (var i = p.Count - 1; i > 0; i--) {
                var target = (int)(RandomFloat() * (i + 1));
                var tmp = p[i];
                p[i] = p[target];
                p[target] = tmp;
            }
        }

        private static int[] PerlinGeneratePerm() {
            var p = new int[256];
            for (var i = 0; i < 256; i++) {
                p[i] = i;
            }
            Permute(p);
            return p;
        }
    }
}

上述代码在Lambertian材质中调用。

public bool Scatter(Ray r, HitRecord rec, out Vector3 attenuation, out Ray scattered) {                                      // Vector3
            var target = rec.P + rec.Normal + RandomInUnitSphere();
            scattered = new Ray(rec.P, target - rec.P, r.Time);
            attenuation = Albedo.Value(0, 0, rec.P);
            return true;
}

此代码生成如下图片: Faulty perlin noise image

代码应该沿着这张图片的方向做出一些事情: enter image description here

本书中的相关代码可在github找到。差异是因为本书的附加性质。我哪里出错了?

编辑:My code is on github aswell.

0 个答案:

没有答案