0

I've been following the book "Raytracing: The next week" by Peter Shirley. I have trouble implementing his perlin noise generator. I get results with a contrast that is way higher than his, and I'm not sure why.

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;
        }
    }
}

The above code is called in a Lambertian material.

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;
}

This code generates pictures like the one below: Faulty perlin noise image

The code should make something along the lines of this image: enter image description here

The relevant code from the book can be found on github. The differences are because of the additive nature of the book. Where did I go wrong?

EDIT: My code is on github aswell.

Herbstein
  • 309
  • 4
  • 12
  • 1
    You seem to be asking "can anyone spot something wrong with my (100 lines of) code?". That's not a great fit for SO - I would strongly suggest doing some initial comparative debugging to narrow down the problem. – Oliver Charlesworth Aug 14 '16 at 11:58
  • I've been stepping through this with the debugger for ~1 hour now. I simply can't find anything wrong, but I might be overlooking something simple. – Herbstein Aug 14 '16 at 12:00
  • 1
    Step through **both** implementations (ensuring you use the same RNG sequence) - as soon as they diverge, you know you've found your problem. – Oliver Charlesworth Aug 14 '16 at 12:01

0 Answers0