updated pnoise, added path tracing of lights. I got some more to do though.
This commit is contained in:
2
imgui
2
imgui
Submodule imgui updated: 23bd697f05...814c6a194b
@@ -20,6 +20,7 @@
|
||||
#endif
|
||||
|
||||
constexpr int Dim = 3;
|
||||
constexpr int maxBounces = 4;
|
||||
|
||||
template<typename T>
|
||||
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<float> 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<OctreeNode>(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<NodeData>(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<NodeData>(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<float>::max();
|
||||
std::function<Eigen::Vector3f(const PointType&, const PointType&, int, uint32_t&)> 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<std::shared_ptr<NodeData>> hits = voxelTraverse(
|
||||
origin, rayDir, std::numeric_limits<float>::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<uint8_t>(color.mean() * 255.0f);
|
||||
colorBuffer[idx ] = static_cast<uint8_t>(rgbToGrayscale(color) * 255.0f);
|
||||
break;
|
||||
case frame::colormap::RGB:
|
||||
colorBuffer[idx ] = static_cast<uint8_t>(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);
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <random>
|
||||
#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<int> 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<float>& 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<typename T>
|
||||
float normalizedNoise(const Vec3<T>& 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<typename T>
|
||||
float permute(Vec2<T> point) {
|
||||
float permute(const Vector2f& point) {
|
||||
TIME_FUNCTION;
|
||||
float x = static_cast<float>(point.x);
|
||||
float y = static_cast<float>(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<typename T>
|
||||
float permute(Vec3<T> 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();
|
||||
|
||||
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);
|
||||
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 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);
|
||||
// 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);
|
||||
|
||||
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<float>& 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<float>& 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<float>& point) {
|
||||
Vector4f permuteColor(const Vector3f& point) {
|
||||
TIME_FUNCTION;
|
||||
float noiseR = permute(point);
|
||||
float noiseG = permute(point + Vec3<float>(100.0f, 100.0f, 100.0f));
|
||||
float noiseB = permute(point + Vec3<float>(200.0f, 200.0f, 200.0f));
|
||||
float noiseA = permute(point + Vec3<float>(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<uint8_t>(noiseR * 255.0f);
|
||||
uint8_t g = static_cast<uint8_t>(noiseG * 255.0f);
|
||||
uint8_t b = static_cast<uint8_t>(noiseB * 255.0f);
|
||||
uint8_t a = static_cast<uint8_t>(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<typename T>
|
||||
float fractalNoise(const Vec2<T>& 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<typename T>
|
||||
float fractalNoise(const Vec3<T>& 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<typename T>
|
||||
float turbulence(const Vec2<T>& 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<typename T>
|
||||
float turbulence(const Vec3<T>& 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<float>& 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<float> 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<float>& 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<float> 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<float>& 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<float>& 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user