From 19462868eafb978cdaeca14e0a36e1f870f8a8cf Mon Sep 17 00:00:00 2001 From: Yggdrasil75 Date: Wed, 28 Jan 2026 09:45:14 -0500 Subject: [PATCH] updated pnoise, added path tracing of lights. I got some more to do though. --- imgui | 2 +- util/grid/grid3eigen.hpp | 133 ++++++++++++++++++++--- util/noise/pnoise2.hpp | 228 +++++++++++++++++++-------------------- 3 files changed, 228 insertions(+), 135 deletions(-) diff --git a/imgui b/imgui index 23bd697..814c6a1 160000 --- a/imgui +++ b/imgui @@ -1 +1 @@ -Subproject commit 23bd697f053bd5cf24601ee3f29572c0a645bd8f +Subproject commit 814c6a194bcb1172df8b8ac9d6520ac0e77654dc diff --git a/util/grid/grid3eigen.hpp b/util/grid/grid3eigen.hpp index 048267a..adfef99 100644 --- a/util/grid/grid3eigen.hpp +++ b/util/grid/grid3eigen.hpp @@ -20,6 +20,7 @@ #endif constexpr int Dim = 3; +constexpr int maxBounces = 4; template class Octree { @@ -33,14 +34,16 @@ public: bool visible; float size; Eigen::Vector3f color; - ///TODO: dont add these just yet. bool light; - float emittance; //amount of light to emit + float emittance; float refraction; float reflection; - NodeData(const T& data, const PointType& pos, bool visible, Eigen::Vector3f color, float size = 0.01f, bool active = true) : - data(data), position(pos), active(active), visible(visible), color(color), size(size) {} + NodeData(const T& data, const PointType& pos, bool visible, Eigen::Vector3f color, float size = 0.01f, + bool active = true, bool light = false, float emittance = 0.0f, float refraction = 0.0f, + float reflection = 0.0f) : data(data), position(pos), active(active), visible(visible), + color(color), size(size), light(light), emittance(emittance), refraction(refraction), + reflection(reflection) {} }; struct OctreeNode { @@ -253,13 +256,34 @@ private: return true; } + float randomValueNormalDistribution(uint32_t& state) { + std::mt19937 gen(state); + state = gen(); + std::uniform_real_distribution dist(0.0f, 1.0f); + float θ = 2 * M_PI * dist(gen); + float ρ = sqrt(-2 * log(dist(gen))); + return ρ * cos(θ); + } + + PointType randomInHemisphere(const PointType& normal, uint32_t& state) { + float x = randomValueNormalDistribution(state); + float y = randomValueNormalDistribution(state); + float z = randomValueNormalDistribution(state); + return PointType(x,y,z).normalized(); + } + + float rgbToGrayscale(const Eigen::Vector3f& color) const { + return 0.2126f * color[0] + 0.7152f * color[1] + 0.0722f * color[2]; + } public: Octree(const PointType& minBound, const PointType& maxBound, size_t maxPointsPerNode=16, size_t maxDepth = 16) : root_(std::make_unique(minBound, maxBound)), maxPointsPerNode(maxPointsPerNode), maxDepth(maxDepth), size(0) {} - bool set(const T& data, const PointType& pos, bool visible, Eigen::Vector3f color, float size, bool active) { - auto pointData = std::make_shared(data, pos, visible, color, size, active); + bool set(const T& data, const PointType& pos, bool visible, Eigen::Vector3f color, float size, bool active, + bool light = false, float emittance = 0.0f, float refraction = 0.0f, float reflection = 0.0f) { + auto pointData = std::make_shared(data, pos, visible, color, size, active, + light, emittance, refraction, reflection); if (insertRecursive(root_.get(), pointData, 0)) { this->size++; return true; @@ -353,7 +377,87 @@ public: float tanfovy = tanHalfFov; float tanfovx = tanHalfFov * aspect; - const Eigen::Vector3f defaultColor(0.1f, 0.2f, 0.4f); + const Eigen::Vector3f defaultColor(0.01f, 0.01f, 0.01f); + float rayLength = std::numeric_limits::max(); + std::function traceRay = + [&](const PointType& rayOrig, const PointType& rayDir, int bounces, uint32_t& rngState) -> Eigen::Vector3f { + + if (bounces > maxBounces) return {0,0,0}; + + auto hits = voxelTraverse(rayOrig, rayDir, rayLength, true); + if (hits.empty() && bounces < 1) { + return defaultColor; + } else if (hits.empty()) { + return {0,0,0}; + } + + auto obj = hits[0]; + + PointType center = obj->position; + float radius = obj->size; + PointType L_vec = center - rayOrig; + float tca = L_vec.dot(rayDir); + float d2 = L_vec.dot(L_vec) - tca * tca; + float radius2 = radius * radius; + + float t = tca; + if (d2 <= radius2) { + float thc = std::sqrt(radius2 - d2); + t = tca - thc; + if (t < 0.001f) t = tca + thc; + } + + PointType hitPoint = rayOrig + rayDir * t; + PointType normal = (hitPoint - center).normalized(); + + Eigen::Vector3f finalColor = {0,0,0}; + + if (obj->light) { + return obj->color * obj->emittance; + } + + float refl = obj->reflection; + float refr = obj->refraction; + float diffuseProb = 1.0f - refl - refr; + + if (diffuseProb > 0.001f) { + PointType scatterDir = randomInHemisphere(normal, rngState); + + Eigen::Vector3f incomingLight = traceRay(hitPoint + normal * 0.002f, scatterDir, bounces + 1, rngState); + + finalColor += obj->color.cwiseProduct(incomingLight) * diffuseProb; + } + + if (refl > 0.001f) { + PointType rDir = (rayDir - 2.0f * rayDir.dot(normal) * normal).normalized(); + finalColor += traceRay(hitPoint + normal * 0.002f, rDir, bounces + 1, rngState) * refl; + } + + if (refr > 0.001f) { + float ior = 1.45f; + float η = 1.0f / ior; + float cosI = -normal.dot(rayDir); + PointType n_eff = normal; + + if (cosI < 0) { + cosI = -cosI; + n_eff = -normal; + η = ior; + } + + float k = 1.0f - η * η * (1.0f - cosI * cosI); + PointType nextDir; + if (k >= 0.0f) { + nextDir = (η * rayDir + (η * cosI - std::sqrt(k)) * n_eff).normalized(); + finalColor += traceRay(hitPoint - n_eff * 0.002f, nextDir, bounces + 1, rngState) * refr; + } else { + nextDir = (rayDir - 2.0f * rayDir.dot(n_eff) * n_eff).normalized(); + finalColor += traceRay(hitPoint + n_eff * 0.002f, nextDir, bounces + 1, rngState) * refr; + } + } + + return finalColor; + }; #pragma omp parallel for schedule(dynamic) collapse(2) for (int y = 0; y < height; ++y) { @@ -364,17 +468,18 @@ public: PointType rayDir = dir + (right * px) + (up * py); rayDir.normalize(); - std::vector> hits = voxelTraverse( - origin, rayDir, std::numeric_limits::max(), true); - Eigen::Vector3f color = hits.empty() ? defaultColor : hits[0]->color; + int pidx = (y * width + x); + uint32_t seed = pidx * 1973 + 9277; + int idx = pidx * channels; + + Eigen::Vector3f color = traceRay(origin, rayDir, 0, seed); color = color.cwiseMax(0.0f).cwiseMin(1.0f); - int idx = (y * width + x) * channels; switch(colorformat) { case frame::colormap::B: - colorBuffer[idx ] = static_cast(color.mean() * 255.0f); + colorBuffer[idx ] = static_cast(rgbToGrayscale(color) * 255.0f); break; case frame::colormap::RGB: colorBuffer[idx ] = static_cast(color[0] * 255.0f); @@ -446,10 +551,6 @@ public: if (leafNodes == 0) minPointsInLeaf = 0; double avgPointsPerLeaf = leafNodes > 0 ? (double)actualPoints / leafNodes : 0.0; - // Approximate memory usage (overhead of nodes + data payload) - // OctreeNode: bounds(24) + vector(24) + children array(8*8=64) + center(12) + bool(1) + padding ~ 128 bytes - // NodeData: T + Vec3f(12) + bool(1) + bool(1) + float(4) + Vec3f(12) + padding ~ 32+sizeof(T) - // SharedPtr overhead: ~16 bytes size_t nodeMem = totalNodes * sizeof(OctreeNode); size_t dataMem = actualPoints * (sizeof(NodeData) + 16); diff --git a/util/noise/pnoise2.hpp b/util/noise/pnoise2.hpp index 68d50db..13c7971 100644 --- a/util/noise/pnoise2.hpp +++ b/util/noise/pnoise2.hpp @@ -6,9 +6,7 @@ #include #include #include -#include "../vectorlogic/vec2.hpp" -#include "../vectorlogic/vec3.hpp" -#include "../vectorlogic/vec4.hpp" +#include "../../eigen/Eigen/Core" #include "../timing_decorator.hpp" class PNoise2 { @@ -16,6 +14,10 @@ private: std::vector permutation; std::default_random_engine rng; + using Vector2f = Eigen::Vector2f; + using Vector3f = Eigen::Vector3f; + using Vector4f = Eigen::Vector4f; + /// @brief Linear interpolation between two values /// @param t Interpolation factor [0,1] /// @param a1 First value @@ -38,34 +40,34 @@ private: /// @param v Hash value (0-3) /// @return One of four 2D gradient vectors /// @note Changing vectors affects noise pattern orientation - Vec2f GetConstantVector(int v) { + Vector2f GetConstantVector(int v) { int h = v & 3; - if (h == 0) return Vec2f(1,1); - else if (h == 1) return Vec2f(-1,1); - else if (h == 2) return Vec2f(-1,-1); - else return Vec2f(1,-1); + if (h == 0) return Vector2f(1,1); + else if (h == 1) return Vector2f(-1,1); + else if (h == 2) return Vector2f(-1,-1); + else return Vector2f(1,-1); } /// @brief Get constant gradient vector for 3D Perlin noise - /// @param v Hash value (0-7) - /// @return One of eight 3D gradient vectors + /// @param v Hash value (0-11) + /// @return One of twelve 3D gradient vectors /// @note Vector selection affects 3D noise patterns - Vec3ui8 GetConstantVector3(int v) { - int h = v & 7; + Vector3f GetConstantVector3(int v) { + int h = v & 11; switch(h) { - case 0: return Vec3ui8( 1, 1, 0); - case 1: return Vec3ui8(-1, 1, 0); - case 2: return Vec3ui8( 1,-1, 0); - case 3: return Vec3ui8(-1,-1, 0); - case 4: return Vec3ui8( 1, 0, 1); - case 5: return Vec3ui8(-1, 0, 1); - case 6: return Vec3ui8( 1, 0,-1); - case 7: return Vec3ui8(-1, 0,-1); - case 8: return Vec3ui8( 0, 1, 1); - case 9: return Vec3ui8( 0,-1, 1); - case 10: return Vec3ui8( 0, 1,-1); - case 11: return Vec3ui8( 0,-1,-1); - default: return Vec3ui8(0,0,0); + case 0: return Vector3f( 1, 1, 0); + case 1: return Vector3f(-1, 1, 0); + case 2: return Vector3f( 1,-1, 0); + case 3: return Vector3f(-1,-1, 0); + case 4: return Vector3f( 1, 0, 1); + case 5: return Vector3f(-1, 0, 1); + case 6: return Vector3f( 1, 0,-1); + case 7: return Vector3f(-1, 0,-1); + case 8: return Vector3f( 0, 1, 1); + case 9: return Vector3f( 0,-1, 1); + case 10: return Vector3f( 0, 1,-1); + case 11: return Vector3f( 0,-1,-1); + default: return Vector3f(0,0,0); } } @@ -101,16 +103,14 @@ private: /// @param point Input coordinate /// @return Normalized noise value in [0,1] range /// @note Useful for texture generation; changes affect output range - float normalizedNoise(const Vec2& point) { + float normalizedNoise(const Vector2f& point) { return (permute(point) + 1.0f) * 0.5f; } /// @brief Normalize 3D noise value from [-1,1] to [0,1] - /// @tparam T Coordinate type /// @param point Input coordinate /// @return Normalized noise value in [0,1] range - template - float normalizedNoise(const Vec3& point) { + float normalizedNoise(const Vector3f& point) { return (permute(point) + 1.0f) * 0.5f; } @@ -133,7 +133,7 @@ private: /// @return Blended noise value /// @note Changes affect multi-layer noise combinations float blendNoises(float noise1, float noise2, float blendFactor) { - return lerp(noise1, noise2, blendFactor); + return lerp(blendFactor, noise1, noise2); } /// @brief Add two noise values with clamping @@ -188,26 +188,24 @@ public: } /// @brief Generate 2D Perlin noise at given point - /// @tparam T Coordinate type (float, double, etc.) /// @param point 2D coordinate /// @return Noise value in [-1,1] range /// @note Core 2D noise function; changes affect all 2D noise outputs - template - float permute(Vec2 point) { + float permute(const Vector2f& point) { TIME_FUNCTION; - float x = static_cast(point.x); - float y = static_cast(point.y); + float x = point.x(); + float y = point.y(); int X = (int)floor(x); int xmod = X & 255; - int Y = (int)floor(point.y); + int Y = (int)floor(y); int ymod = Y & 255; - float xf = point.x - X; - float yf = point.y - Y; + float xf = x - X; + float yf = y - Y; - Vec2f BL = Vec2f(xf-0, yf-0); - Vec2f BR = Vec2f(xf-1, yf-0); - Vec2f TL = Vec2f(xf-0, yf-1); - Vec2f TR = Vec2f(xf-1, yf-1); + Vector2f BL(xf-0, yf-0); + Vector2f BR(xf-1, yf-0); + Vector2f TL(xf-0, yf-1); + Vector2f TR(xf-1, yf-1); int vBL = permutation[permutation[xmod+0]+ymod+0]; int vBR = permutation[permutation[xmod+1]+ymod+0]; @@ -225,34 +223,36 @@ public: float x1 = lerp(u, grad(vBL, xf, yf), grad(vBR, xf - 1, yf)); float x2 = lerp(u, grad(vTL, xf, yf - 1), grad(vTR, xf - 1, yf - 1)); float retval = lerp(v, x1, x2); - //std::cout << "returning: " << retval << std::endl; + return retval; } /// @brief Generate 3D Perlin noise at given point - /// @tparam T Coordinate type (float, double, etc.) /// @param point 3D coordinate /// @return Noise value in [-1,1] range - /// @note Core 3D noise function; changes affect all 3D noise outputs - template - float permute(Vec3 point) { + float permute(const Vector3f& point) { TIME_FUNCTION; - int X = (int)floor(point.x) & 255; - int Y = (int)floor(point.y) & 255; - int Z = (int)floor(point.z) & 255; - float xf = point.x - X; - float yf = point.y - Y; - float zf = point.z - Z; + float x = point.x(); + float y = point.y(); + float z = point.z(); + + int X = (int)floor(x) & 255; + int Y = (int)floor(y) & 255; + int Z = (int)floor(z) & 255; + float xf = x - X; + float yf = y - Y; + float zf = z - Z; - Vec3ui8 FBL = Vec3ui8(xf-0, yf-0, zf-0); - Vec3ui8 FBR = Vec3ui8(xf-1, yf-0, zf-0); - Vec3ui8 FTL = Vec3ui8(xf-0, yf-1, zf-0); - Vec3ui8 FTR = Vec3ui8(xf-1, yf-1, zf-0); + // Distance vectors from corners + Vector3f FBL(xf-0, yf-0, zf-0); + Vector3f FBR(xf-1, yf-0, zf-0); + Vector3f FTL(xf-0, yf-1, zf-0); + Vector3f FTR(xf-1, yf-1, zf-0); - Vec3ui8 RBL = Vec3ui8(xf-0, yf-0, zf-1); - Vec3ui8 RBR = Vec3ui8(xf-1, yf-0, zf-1); - Vec3ui8 RTL = Vec3ui8(xf-0, yf-1, zf-1); - Vec3ui8 RTR = Vec3ui8(xf-1, yf-1, zf-1); + Vector3f RBL(xf-0, yf-0, zf-1); + Vector3f RBR(xf-1, yf-0, zf-1); + Vector3f RTL(xf-0, yf-1, zf-1); + Vector3f RTR(xf-1, yf-1, zf-1); int vFBL = permutation[permutation[permutation[Z+0]+X+0]+Y+0]; int vFBR = permutation[permutation[permutation[Z+0]+X+1]+Y+0]; @@ -288,7 +288,6 @@ public: float retval = lerp(w, y1, y2); - //std::cout << "returning: " << retval << std::endl; return retval; } @@ -296,12 +295,12 @@ public: /// @param point 2D coordinate /// @return Noise value in [-1,1] range /// @note Different character than Perlin; changes affect value-based textures - float valueNoise(const Vec2& point) { - int xi = (int)std::floor(point.x); - int yi = (int)std::floor(point.y); + float valueNoise(const Vector2f& point) { + int xi = (int)std::floor(point.x()); + int yi = (int)std::floor(point.y()); - float tx = point.x - xi; - float ty = point.y - yi; + float tx = point.x() - xi; + float ty = point.y() - yi; int rx0 = xi & 255; int rx1 = (xi + 1) & 255; @@ -327,14 +326,14 @@ public: /// @brief Generate 3D value noise /// @param point 3D coordinate /// @return Noise value in [-1,1] range - float valueNoise(const Vec3& point) { - int xi = (int)std::floor(point.x); - int yi = (int)std::floor(point.y); - int zi = (int)std::floor(point.z); + float valueNoise(const Vector3f& point) { + int xi = (int)std::floor(point.x()); + int yi = (int)std::floor(point.y()); + int zi = (int)std::floor(point.z()); - float tx = point.x - xi; - float ty = point.y - yi; - float tz = point.z - zi; + float tx = point.x() - xi; + float ty = point.y() - yi; + float tz = point.z() - zi; int rx0 = xi & 255; int rx1 = (xi + 1) & 255; @@ -371,46 +370,43 @@ public: /// @brief Generate RGBA color from 3D noise with offset channels /// @param point 3D coordinate - /// @return Vec4ui8 containing RGBA noise values + /// @return Vector4f containing RGBA noise values /// @note Each channel uses different offset; changes affect color patterns - Vec4ui8 permuteColor(const Vec3& point) { + Vector4f permuteColor(const Vector3f& point) { TIME_FUNCTION; float noiseR = permute(point); - float noiseG = permute(point + Vec3(100.0f, 100.0f, 100.0f)); - float noiseB = permute(point + Vec3(200.0f, 200.0f, 200.0f)); - float noiseA = permute(point + Vec3(300.0f, 300.0f, 300.0f)); - // float rNormalized = (noiseR + 1.0f) * 0.5f; - // float gNormalized = (noiseG + 1.0f) * 0.5f; - // float bNormalized = (noiseB + 1.0f) * 0.5f; - // float aNormalized = (noiseA + 1.0f) * 0.5f; - // rNormalized = std::clamp(rNormalized, 0.0f, 1.0f); - // gNormalized = std::clamp(gNormalized, 0.0f, 1.0f); - // bNormalized = std::clamp(bNormalized, 0.0f, 1.0f); - // aNormalized = std::clamp(aNormalized, 0.0f, 1.0f); - uint8_t r = static_cast(noiseR * 255.0f); - uint8_t g = static_cast(noiseG * 255.0f); - uint8_t b = static_cast(noiseB * 255.0f); - uint8_t a = static_cast(noiseA * 255.0f); + float noiseG = permute(Vector3f(point + Vector3f(100.0f, 100.0f, 100.0f))); + float noiseB = permute(Vector3f(point + Vector3f(200.0f, 200.0f, 200.0f))); + float noiseA = permute(Vector3f(point + Vector3f(300.0f, 300.0f, 300.0f))); - return Vec4ui8(r, g, b, a); + float rNormalized = (noiseR + 1.0f) * 0.5f; + float gNormalized = (noiseG + 1.0f) * 0.5f; + float bNormalized = (noiseB + 1.0f) * 0.5f; + float aNormalized = (noiseA + 1.0f) * 0.5f; + + rNormalized = std::clamp(rNormalized, 0.0f, 1.0f); + gNormalized = std::clamp(gNormalized, 0.0f, 1.0f); + bNormalized = std::clamp(bNormalized, 0.0f, 1.0f); + aNormalized = std::clamp(aNormalized, 0.0f, 1.0f); + + return Vector4f(rNormalized, gNormalized, bNormalized, aNormalized); } /// @brief Generate fractal (octave) noise for natural-looking patterns - /// @tparam T Coordinate type /// @param point Input coordinate /// @param octaves Number of noise layers /// @param persistence Amplitude multiplier per octave /// @param lacunarity Frequency multiplier per octave /// @return Combined noise value /// @note Parameters control noise character: octaves=detail, persistence=roughness, lacunarity=frequency change - template - float fractalNoise(const Vec2& point, int octaves, float persistence, float lacunarity) { + float fractalNoise(const Vector2f& point, int octaves, float persistence, float lacunarity) { float total = 0.0f; float frequency = 1.f; float amplitude = 1.f; float maxV = 0.f; + Vector2f scaledPoint = point * frequency; for (int i = 0; i < octaves; i++) { - total += permute(point*frequency) * amplitude; + total += permute(scaledPoint) * amplitude; maxV += amplitude; amplitude *= persistence; frequency *= lacunarity; @@ -420,20 +416,19 @@ public: } /// @brief Generate 3D fractal (octave) noise - /// @tparam T Coordinate type /// @param point Input coordinate /// @param octaves Number of noise layers /// @param persistence Amplitude multiplier per octave /// @param lacunarity Frequency multiplier per octave /// @return Combined noise value - template - float fractalNoise(const Vec3& point, int octaves, float persistence, float lacunarity) { + float fractalNoise(const Vector3f& point, int octaves, float persistence, float lacunarity) { float total = 0.0f; float frequency = 1.f; float amplitude = 1.f; float maxV = 0.f; + Vector3f scaledPoint = point * frequency; for (int i = 0; i < octaves; i++) { - total += permute(point*frequency) * amplitude; + total += permute(scaledPoint) * amplitude; maxV += amplitude; amplitude *= persistence; frequency *= lacunarity; @@ -443,15 +438,13 @@ public: } /// @brief Generate turbulence noise (absolute value of octaves) - /// @tparam T Coordinate type /// @param point Input coordinate /// @param octaves Number of noise layers /// @return Turbulence noise value /// @note Creates swirling, turbulent patterns; changes affect visual complexity - template - float turbulence(const Vec2& point, int octaves) { + float turbulence(const Vector2f& point, int octaves) { float value = 0.0f; - Vec2f tempPoint = point.toFloat(); + Vector2f tempPoint = point; for (int i = 0; i < octaves; i++) { value += std::abs(permute(tempPoint)) / (1 << i); tempPoint *= 2.f; @@ -460,14 +453,13 @@ public: } /// @brief Generate 3D turbulence noise - /// @tparam T Coordinate type /// @param point Input coordinate /// @param octaves Number of noise layers /// @return Turbulence noise value - template - float turbulence(const Vec3& point, int octaves) { + float turbulence(const Vector3f& point, int octaves) { float value = 0.0f; - Vec3f tempPoint = point.toFloat(); + Vector3f tempPoint = point; + for (int i = 0; i < octaves; i++) { value += std::abs(permute(tempPoint)) / (1 << i); tempPoint *= 2.f; @@ -481,10 +473,10 @@ public: /// @param offset Weighting offset for ridge formation /// @return Ridged noise value /// @note Creates sharp ridge-like patterns; offset controls ridge prominence - float ridgedNoise(const Vec2& point, int octaves, float offset = 1.0f) { + float ridgedNoise(const Vector2f& point, int octaves, float offset = 1.0f) { float result = 0.f; float weight = 1.f; - Vec2 p = point; + Vector2f p = point; for (int i = 0; i < octaves; i++) { float signal = 1.f - std::abs(permute(p)); @@ -503,10 +495,10 @@ public: /// @param octaves Number of noise layers /// @param offset Weighting offset for ridge formation /// @return Ridged noise value - float ridgedNoise(const Vec3& point, int octaves, float offset = 1.0f) { + float ridgedNoise(const Vector3f& point, int octaves, float offset = 1.0f) { float result = 0.f; float weight = 1.f; - Vec3 p = point; + Vector3f p = point; for (int i = 0; i < octaves; i++) { float signal = 1.f - std::abs(permute(p)); @@ -525,13 +517,13 @@ public: /// @param octaves Number of noise layers /// @return Billow noise value /// @note Creates soft, billowy patterns like clouds - float billowNoise(const Vec2& point, int octaves) { + float billowNoise(const Vector2f& point, int octaves) { float value = 0.0f; float amplitude = 1.0f; float frequency = 1.0f; - + Vector2f scaledPoint = point * frequency; for (int i = 0; i < octaves; i++) { - value += std::abs(permute(point * frequency)) * amplitude; + value += std::abs(permute(scaledPoint)) * amplitude; amplitude *= 0.5f; frequency *= 2.0f; } @@ -543,13 +535,13 @@ public: /// @param point Input coordinate /// @param octaves Number of noise layers /// @return Billow noise value - float billowNoise(const Vec3& point, int octaves) { + float billowNoise(const Vector3f& point, int octaves) { float value = 0.0f; float amplitude = 1.0f; float frequency = 1.0f; - + Vector3f scaledPoint = point * frequency; for (int i = 0; i < octaves; i++) { - value += std::abs(permute(point * frequency)) * amplitude; + value += std::abs(permute(scaledPoint)) * amplitude; amplitude *= 0.5f; frequency *= 2.0f; }