我一直在关注这本书" 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;
}
本书中的相关代码可在github找到。差异是因为本书的附加性质。我哪里出错了?