fix value and fractal noise
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#ifndef PNOISE_CPP
|
||||||
|
#define PNOISE_CPP
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@@ -7,6 +8,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "./pnoise2.hpp"
|
#include "./pnoise2.hpp"
|
||||||
|
#include "../timing_decorator.hpp"
|
||||||
#include "../../imgui/imgui.h"
|
#include "../../imgui/imgui.h"
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
@@ -110,6 +112,7 @@ inline float sampleNoiseLayer(PNoise2& gen, NoiseType type, Eigen::Vector2f poin
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void updateNoiseTexture(NoisePreviewState& state) {
|
inline void updateNoiseTexture(NoisePreviewState& state) {
|
||||||
|
TIME_FUNCTION;
|
||||||
if (state.textureId == 0) glGenTextures(1, &state.textureId);
|
if (state.textureId == 0) glGenTextures(1, &state.textureId);
|
||||||
|
|
||||||
state.pixelBuffer.resize(state.width * state.height * 3);
|
state.pixelBuffer.resize(state.width * state.height * 3);
|
||||||
@@ -120,24 +123,19 @@ inline void updateNoiseTexture(NoisePreviewState& state) {
|
|||||||
|
|
||||||
for (int x = 0; x < state.width; ++x) {
|
for (int x = 0; x < state.width; ++x) {
|
||||||
|
|
||||||
// 1. Initial Coordinate
|
|
||||||
float nx = (x + state.offset[0]);
|
float nx = (x + state.offset[0]);
|
||||||
float ny = (y + state.offset[1]);
|
float ny = (y + state.offset[1]);
|
||||||
Eigen::Vector2f point(nx, ny);
|
Eigen::Vector2f point(nx, ny);
|
||||||
|
|
||||||
float finalValue = 0.0f;
|
float finalValue = 0.0f;
|
||||||
|
|
||||||
// 2. Process Layer Stack
|
|
||||||
for (const auto& layer : state.layers) {
|
for (const auto& layer : state.layers) {
|
||||||
if (!layer.enabled) continue;
|
if (!layer.enabled) continue;
|
||||||
|
|
||||||
// Adjust coordinate frequency for this layer
|
|
||||||
Eigen::Vector2f samplePoint = point * layer.scale;
|
Eigen::Vector2f samplePoint = point * layer.scale;
|
||||||
|
|
||||||
// Cheat seed offset
|
|
||||||
samplePoint += Eigen::Vector2f((float)layer.seedOffset * 10.5f, (float)layer.seedOffset * -10.5f);
|
samplePoint += Eigen::Vector2f((float)layer.seedOffset * 10.5f, (float)layer.seedOffset * -10.5f);
|
||||||
|
|
||||||
// Special Case: Coordinate Mutators
|
|
||||||
if (layer.blend == BlendMode::DomainWarp) {
|
if (layer.blend == BlendMode::DomainWarp) {
|
||||||
if (layer.type == NoiseType::CurlNoise) {
|
if (layer.type == NoiseType::CurlNoise) {
|
||||||
Eigen::Vector2f flow = generator.curlNoise(samplePoint);
|
Eigen::Vector2f flow = generator.curlNoise(samplePoint);
|
||||||
@@ -150,7 +148,6 @@ inline void updateNoiseTexture(NoisePreviewState& state) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standard Arithmetic Layers
|
|
||||||
float nVal = sampleNoiseLayer(generator, layer.type, samplePoint, layer);
|
float nVal = sampleNoiseLayer(generator, layer.type, samplePoint, layer);
|
||||||
|
|
||||||
switch (layer.blend) {
|
switch (layer.blend) {
|
||||||
@@ -175,7 +172,6 @@ inline void updateNoiseTexture(NoisePreviewState& state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Normalize for display
|
|
||||||
float norm = std::tanh(finalValue);
|
float norm = std::tanh(finalValue);
|
||||||
norm = (norm + 1.0f) * 0.5f;
|
norm = (norm + 1.0f) * 0.5f;
|
||||||
norm = std::clamp(norm, 0.0f, 1.0f);
|
norm = std::clamp(norm, 0.0f, 1.0f);
|
||||||
@@ -223,16 +219,13 @@ inline void drawNoiseLab(NoisePreviewState& noiseState) {
|
|||||||
|
|
||||||
ImGui::BeginChild("LayersScroll", ImVec2(0, 300), true);
|
ImGui::BeginChild("LayersScroll", ImVec2(0, 300), true);
|
||||||
|
|
||||||
// Layer List
|
|
||||||
for (int i = 0; i < noiseState.layers.size(); ++i) {
|
for (int i = 0; i < noiseState.layers.size(); ++i) {
|
||||||
NoiseLayer& layer = noiseState.layers[i];
|
NoiseLayer& layer = noiseState.layers[i];
|
||||||
|
|
||||||
ImGui::PushID(i);
|
ImGui::PushID(i);
|
||||||
|
|
||||||
// Header
|
|
||||||
bool open = ImGui::CollapsingHeader(layer.name, ImGuiTreeNodeFlags_DefaultOpen);
|
bool open = ImGui::CollapsingHeader(layer.name, ImGuiTreeNodeFlags_DefaultOpen);
|
||||||
|
|
||||||
// Context menu to move/delete
|
|
||||||
if (ImGui::BeginPopupContextItem()) {
|
if (ImGui::BeginPopupContextItem()) {
|
||||||
if (ImGui::MenuItem("Move Up", nullptr, false, i > 0)) {
|
if (ImGui::MenuItem("Move Up", nullptr, false, i > 0)) {
|
||||||
std::swap(noiseState.layers[i], noiseState.layers[i-1]);
|
std::swap(noiseState.layers[i], noiseState.layers[i-1]);
|
||||||
@@ -265,19 +258,16 @@ inline void drawNoiseLab(NoisePreviewState& noiseState) {
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::InputText("##name", layer.name, 32);
|
ImGui::InputText("##name", layer.name, 32);
|
||||||
|
|
||||||
// Type and Blend
|
|
||||||
const char* types[] = { "Perlin", "Value", "Fractal", "Turbulence", "Ridged", "Billow", "White", "Worley", "Voronoi", "Crystal", "Domain Warp", "Curl" };
|
const char* types[] = { "Perlin", "Value", "Fractal", "Turbulence", "Ridged", "Billow", "White", "Worley", "Voronoi", "Crystal", "Domain Warp", "Curl" };
|
||||||
const char* blends[] = { "Add", "Subtract", "Multiply", "Min", "Max", "Replace", "Domain Warp (Coord)" };
|
const char* blends[] = { "Add", "Subtract", "Multiply", "Min", "Max", "Replace", "Domain Warp (Coord)" };
|
||||||
|
|
||||||
if (ImGui::Combo("Type", (int*)&layer.type, types, IM_ARRAYSIZE(types))) changed = true;
|
if (ImGui::Combo("Type", (int*)&layer.type, types, IM_ARRAYSIZE(types))) changed = true;
|
||||||
if (ImGui::Combo("Blend", (int*)&layer.blend, blends, IM_ARRAYSIZE(blends))) changed = true;
|
if (ImGui::Combo("Blend", (int*)&layer.blend, blends, IM_ARRAYSIZE(blends))) changed = true;
|
||||||
|
|
||||||
// Common Params
|
|
||||||
if (ImGui::SliderFloat("Scale", &layer.scale, 0.0001f, 0.2f, "%.5f")) changed = true;
|
if (ImGui::SliderFloat("Scale", &layer.scale, 0.0001f, 0.2f, "%.5f")) changed = true;
|
||||||
if (ImGui::SliderFloat("Strength/Weight", &layer.strength, 0.0f, 5.0f)) changed = true;
|
if (ImGui::SliderFloat("Strength/Weight", &layer.strength, 0.0f, 5.0f)) changed = true;
|
||||||
if (ImGui::SliderInt("Seed Offset", &layer.seedOffset, 0, 100)) changed = true;
|
if (ImGui::SliderInt("Seed Offset", &layer.seedOffset, 0, 100)) changed = true;
|
||||||
|
|
||||||
// Conditional Params
|
|
||||||
if (layer.type == NoiseType::Fractal || layer.type == NoiseType::Turbulence ||
|
if (layer.type == NoiseType::Fractal || layer.type == NoiseType::Turbulence ||
|
||||||
layer.type == NoiseType::Ridged || layer.type == NoiseType::Billow) {
|
layer.type == NoiseType::Ridged || layer.type == NoiseType::Billow) {
|
||||||
|
|
||||||
@@ -300,14 +290,14 @@ inline void drawNoiseLab(NoisePreviewState& noiseState) {
|
|||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
// Preview
|
|
||||||
ImGui::Text("Preview Output");
|
ImGui::Text("Preview Output");
|
||||||
ImGui::Image((void*)(intptr_t)noiseState.textureId, ImVec2((float)noiseState.width, (float)noiseState.height));
|
ImGui::Image((void*)(intptr_t)noiseState.textureId, ImVec2((float)noiseState.width, (float)noiseState.height));
|
||||||
|
|
||||||
// Auto update logic
|
|
||||||
if (changed || noiseState.needsUpdate) {
|
if (changed || noiseState.needsUpdate) {
|
||||||
updateNoiseTexture(noiseState);
|
updateNoiseTexture(noiseState);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -86,6 +86,19 @@ private:
|
|||||||
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Gradient function for 2D only Perlin noise
|
||||||
|
/// @param hash Hash value for gradient selection
|
||||||
|
/// @param x X coordinate
|
||||||
|
/// @param y Y coordinate
|
||||||
|
/// @return Dot product of gradient vector and distance vector
|
||||||
|
/// @note Core of Perlin noise; changes affect basic noise character
|
||||||
|
inline static float grad2(int hash, float x, float y) {
|
||||||
|
int h = hash & 15;
|
||||||
|
float u = h < 8 ? x : y;
|
||||||
|
float v = h < 4 ? y : ((h == 12 || h == 14) ? x : 0.0f);
|
||||||
|
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Initialize permutation table with shuffled values
|
/// @brief Initialize permutation table with shuffled values
|
||||||
/// @note Called on construction; changing seed or shuffle affects all noise patterns
|
/// @note Called on construction; changing seed or shuffle affects all noise patterns
|
||||||
void initializePermutation() {
|
void initializePermutation() {
|
||||||
@@ -237,11 +250,6 @@ public:
|
|||||||
int vTL = permutation[permutation[xmod+0]+ymod+1];
|
int vTL = permutation[permutation[xmod+0]+ymod+1];
|
||||||
int vTR = permutation[permutation[xmod+1]+ymod+1];
|
int vTR = permutation[permutation[xmod+1]+ymod+1];
|
||||||
|
|
||||||
// float dBL = BL.dot(GetConstantVector(vBL));
|
|
||||||
// float dBR = BR.dot(GetConstantVector(vBR));
|
|
||||||
// float dTL = TL.dot(GetConstantVector(vTL));
|
|
||||||
// float dTR = TR.dot(GetConstantVector(vTR));
|
|
||||||
|
|
||||||
float u = fade(xf);
|
float u = fade(xf);
|
||||||
float v = fade(yf);
|
float v = fade(yf);
|
||||||
|
|
||||||
@@ -289,16 +297,6 @@ public:
|
|||||||
int vRTL = permutation[permutation[permutation[Z+1]+X+0]+Y+1];
|
int vRTL = permutation[permutation[permutation[Z+1]+X+0]+Y+1];
|
||||||
int vRTR = permutation[permutation[permutation[Z+1]+X+1]+Y+1];
|
int vRTR = permutation[permutation[permutation[Z+1]+X+1]+Y+1];
|
||||||
|
|
||||||
// float dFBL = FBL.dot(GetConstantVector3(vFBL));
|
|
||||||
// float dFBR = FBR.dot(GetConstantVector3(vFBR));
|
|
||||||
// float dFTL = FTL.dot(GetConstantVector3(vFTL));
|
|
||||||
// float dFTR = FTR.dot(GetConstantVector3(vFTR));
|
|
||||||
|
|
||||||
// float dRBL = RBL.dot(GetConstantVector3(vRBL));
|
|
||||||
// float dRBR = RBR.dot(GetConstantVector3(vRBR));
|
|
||||||
// float dRTL = RTL.dot(GetConstantVector3(vRTL));
|
|
||||||
// float dRTR = RTR.dot(GetConstantVector3(vRTR));
|
|
||||||
|
|
||||||
float u = fade(xf);
|
float u = fade(xf);
|
||||||
float v = fade(yf);
|
float v = fade(yf);
|
||||||
float w = fade(zf);
|
float w = fade(zf);
|
||||||
@@ -342,8 +340,8 @@ public:
|
|||||||
float sx = fade(tx);
|
float sx = fade(tx);
|
||||||
float sy = fade(ty);
|
float sy = fade(ty);
|
||||||
|
|
||||||
float nx0 = lerp(c00, c10, sx);
|
float nx0 = lerp(sy, c00, c10);
|
||||||
float nx1 = lerp(c01, c11, sx);
|
float nx1 = lerp(sx, c01, c11);
|
||||||
|
|
||||||
return lerp(nx0, nx1, sy);
|
return lerp(nx0, nx1, sy);
|
||||||
}
|
}
|
||||||
@@ -382,15 +380,15 @@ public:
|
|||||||
float sy = fade(ty);
|
float sy = fade(ty);
|
||||||
float sz = fade(tz);
|
float sz = fade(tz);
|
||||||
|
|
||||||
float nx00 = lerp(c000, c100, sx);
|
float nx00 = lerp(sx, c000, c100);
|
||||||
float nx10 = lerp(c010, c110, sx);
|
float nx10 = lerp(sx, c010, c110);
|
||||||
float nx01 = lerp(c001, c101, sx);
|
float nx01 = lerp(sx, c001, c101);
|
||||||
float nx11 = lerp(c011, c111, sx);
|
float nx11 = lerp(sx, c011, c111);
|
||||||
|
|
||||||
float ny0 = lerp(nx00, nx10, sy);
|
float ny0 = lerp(sy, nx00, nx10);
|
||||||
float ny1 = lerp(nx01, nx11, sy);
|
float ny1 = lerp(sy, nx01, nx11);
|
||||||
|
|
||||||
return lerp(ny0, ny1, sz);
|
return lerp(sz, ny0, ny1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Generate RGBA color from 3D noise with offset channels
|
/// @brief Generate RGBA color from 3D noise with offset channels
|
||||||
@@ -424,20 +422,18 @@ public:
|
|||||||
/// @param lacunarity Frequency multiplier per octave
|
/// @param lacunarity Frequency multiplier per octave
|
||||||
/// @return Combined noise value
|
/// @return Combined noise value
|
||||||
/// @note Parameters control noise character: octaves=detail, persistence=roughness, lacunarity=frequency change
|
/// @note Parameters control noise character: octaves=detail, persistence=roughness, lacunarity=frequency change
|
||||||
float fractalNoise(const Vector2f& point, int octaves, float persistence, float lacunarity) {
|
float fractalNoise(const Vector2f& point, int octaves, float persistence = 0.5, float lacunarity = 2.0) {
|
||||||
float total = 0.0f;
|
|
||||||
float frequency = 1.f;
|
float frequency = 1.f;
|
||||||
float amplitude = 1.f;
|
float amplitude = 1.f;
|
||||||
float maxV = 0.f;
|
float maxV = 0.f;
|
||||||
Vector2f scaledPoint = point * frequency;
|
|
||||||
for (int i = 0; i < octaves; i++) {
|
for (int i = 0; i < octaves; i++) {
|
||||||
total += permute(scaledPoint) * amplitude;
|
Vector2f scaledPoint = point * frequency;
|
||||||
maxV += amplitude;
|
maxV += permute(scaledPoint) * amplitude;
|
||||||
amplitude *= persistence;
|
amplitude *= persistence;
|
||||||
frequency *= lacunarity;
|
frequency *= lacunarity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return total / maxV;
|
return maxV;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Generate 3D fractal (octave) noise
|
/// @brief Generate 3D fractal (octave) noise
|
||||||
@@ -446,20 +442,18 @@ public:
|
|||||||
/// @param persistence Amplitude multiplier per octave
|
/// @param persistence Amplitude multiplier per octave
|
||||||
/// @param lacunarity Frequency multiplier per octave
|
/// @param lacunarity Frequency multiplier per octave
|
||||||
/// @return Combined noise value
|
/// @return Combined noise value
|
||||||
float fractalNoise(const Vector3f& point, int octaves, float persistence, float lacunarity) {
|
float fractalNoise(const Vector3f& point, int octaves, float persistence = 0.5, float lacunarity = 2.0) {
|
||||||
float total = 0.0f;
|
|
||||||
float frequency = 1.f;
|
float frequency = 1.f;
|
||||||
float amplitude = 1.f;
|
float amplitude = 1.f;
|
||||||
float maxV = 0.f;
|
float maxV = 0.f;
|
||||||
Vector3f scaledPoint = point * frequency;
|
|
||||||
for (int i = 0; i < octaves; i++) {
|
for (int i = 0; i < octaves; i++) {
|
||||||
total += permute(scaledPoint) * amplitude;
|
Vector3f scaledPoint = point * frequency;
|
||||||
maxV += amplitude;
|
maxV += permute(scaledPoint) * amplitude;
|
||||||
amplitude *= persistence;
|
amplitude *= persistence;
|
||||||
frequency *= lacunarity;
|
frequency *= lacunarity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return total / maxV;
|
return maxV;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Generate turbulence noise (absolute value of octaves)
|
/// @brief Generate turbulence noise (absolute value of octaves)
|
||||||
@@ -599,17 +593,14 @@ public:
|
|||||||
for (int y = -1; y <= 1; y++) {
|
for (int y = -1; y <= 1; y++) {
|
||||||
for (int x = -1; x <= 1; x++) {
|
for (int x = -1; x <= 1; x++) {
|
||||||
Vector2f neighbor(x, y);
|
Vector2f neighbor(x, y);
|
||||||
// Get random point inside the neighbor cell
|
|
||||||
Vector2f pointInCell = hashVector(Vector2f(p + neighbor));
|
Vector2f pointInCell = hashVector(Vector2f(p + neighbor));
|
||||||
|
|
||||||
// Vector from current pixel to that point
|
|
||||||
Vector2f diff = neighbor + pointInCell - f;
|
Vector2f diff = neighbor + pointInCell - f;
|
||||||
|
|
||||||
float dist = diff.norm();
|
float dist = diff.norm();
|
||||||
if (dist < minDist) minDist = dist;
|
if (dist < minDist) minDist = dist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return minDist; // Usually clamped or inverted for visuals
|
return minDist;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Worley Noise 3D
|
/// @brief Worley Noise 3D
|
||||||
@@ -650,7 +641,7 @@ public:
|
|||||||
Vector2f neighbor(x, y);
|
Vector2f neighbor(x, y);
|
||||||
Vector2f pointInCell = hashVector(Vector2f(p + neighbor));
|
Vector2f pointInCell = hashVector(Vector2f(p + neighbor));
|
||||||
Vector2f diff = neighbor + pointInCell - f;
|
Vector2f diff = neighbor + pointInCell - f;
|
||||||
float dist = diff.squaredNorm(); // Faster than norm
|
float dist = diff.squaredNorm();
|
||||||
if (dist < minDist) {
|
if (dist < minDist) {
|
||||||
minDist = dist;
|
minDist = dist;
|
||||||
cellID = p + neighbor;
|
cellID = p + neighbor;
|
||||||
@@ -668,8 +659,8 @@ public:
|
|||||||
Vector2f p = Vector2f(floor(point.x()), floor(point.y()));
|
Vector2f p = Vector2f(floor(point.x()), floor(point.y()));
|
||||||
Vector2f f = Vector2f(point.x() - p.x(), point.y() - p.y());
|
Vector2f f = Vector2f(point.x() - p.x(), point.y() - p.y());
|
||||||
|
|
||||||
float d1 = 10.0f; // Closest
|
float d1 = 10.0f;
|
||||||
float d2 = 10.0f; // 2nd Closest
|
float d2 = 10.0f;
|
||||||
|
|
||||||
for (int y = -1; y <= 1; y++) {
|
for (int y = -1; y <= 1; y++) {
|
||||||
for (int x = -1; x <= 1; x++) {
|
for (int x = -1; x <= 1; x++) {
|
||||||
@@ -717,16 +708,13 @@ public:
|
|||||||
/// @return Divergence-free vector field (useful for particle simulation)
|
/// @return Divergence-free vector field (useful for particle simulation)
|
||||||
/// @note Calculated via finite difference curl of a potential field
|
/// @note Calculated via finite difference curl of a potential field
|
||||||
Vector2f curlNoise(const Vector2f& point) {
|
Vector2f curlNoise(const Vector2f& point) {
|
||||||
float e = 0.01f; // Epsilon
|
float n1 = permute(Vector2f(point + Vector2f(0, EPSILON)));
|
||||||
float n1 = permute(Vector2f(point + Vector2f(0, e)));
|
float n2 = permute(Vector2f(point + Vector2f(0, -EPSILON)));
|
||||||
float n2 = permute(Vector2f(point + Vector2f(0, -e)));
|
float n3 = permute(Vector2f(point + Vector2f(EPSILON, 0)));
|
||||||
float n3 = permute(Vector2f(point + Vector2f(e, 0)));
|
float n4 = permute(Vector2f(point + Vector2f(-EPSILON, 0)));
|
||||||
float n4 = permute(Vector2f(point + Vector2f(-e, 0)));
|
|
||||||
|
|
||||||
float dx = (n3 - n4) / (2.0f * e);
|
float dx = (n3 - n4) / (2.0f * EPSILON);
|
||||||
float dy = (n1 - n2) / (2.0f * e);
|
float dy = (n1 - n2) / (2.0f * EPSILON);
|
||||||
|
|
||||||
// Curl of scalar field in 2D is (d/dy, -d/dx)
|
|
||||||
return Vector2f(dy, -dx).normalized();
|
return Vector2f(dy, -dx).normalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -735,14 +723,10 @@ public:
|
|||||||
/// @return Divergence-free vector field
|
/// @return Divergence-free vector field
|
||||||
/// @note Uses 3 offsets of Perlin noise as Vector Potential
|
/// @note Uses 3 offsets of Perlin noise as Vector Potential
|
||||||
Vector3f curlNoise(const Vector3f& point) {
|
Vector3f curlNoise(const Vector3f& point) {
|
||||||
float e = 0.01f;
|
Vector3f dx(EPSILON, 0.0f, 0.0f);
|
||||||
|
Vector3f dy(0.0f, EPSILON, 0.0f);
|
||||||
|
Vector3f dz(0.0f, 0.0f, EPSILON);
|
||||||
|
|
||||||
Vector3f dx(e, 0.0f, 0.0f);
|
|
||||||
Vector3f dy(0.0f, e, 0.0f);
|
|
||||||
Vector3f dz(0.0f, 0.0f, e);
|
|
||||||
|
|
||||||
// We need a vector potential (3 uncorrelated noise values)
|
|
||||||
// We reuse permuteColor's logic but keep it local to avoid overhead
|
|
||||||
auto potential = [&](const Vector3f& p) -> Vector3f {
|
auto potential = [&](const Vector3f& p) -> Vector3f {
|
||||||
return Vector3f(
|
return Vector3f(
|
||||||
permute(p),
|
permute(p),
|
||||||
@@ -759,12 +743,12 @@ public:
|
|||||||
Vector3f p_dz_m = potential(point - dz);
|
Vector3f p_dz_m = potential(point - dz);
|
||||||
|
|
||||||
// Finite difference
|
// Finite difference
|
||||||
float dFz_dy = (p_dy_p.z() - p_dy_m.z()) / (2.0f * e);
|
float dFz_dy = (p_dy_p.z() - p_dy_m.z()) / (2.0f * EPSILON);
|
||||||
float dFy_dz = (p_dz_p.y() - p_dz_m.y()) / (2.0f * e);
|
float dFy_dz = (p_dz_p.y() - p_dz_m.y()) / (2.0f * EPSILON);
|
||||||
float dFx_dz = (p_dz_p.x() - p_dz_m.x()) / (2.0f * e);
|
float dFx_dz = (p_dz_p.x() - p_dz_m.x()) / (2.0f * EPSILON);
|
||||||
float dFz_dx = (p_dx_p.z() - p_dx_m.z()) / (2.0f * e);
|
float dFz_dx = (p_dx_p.z() - p_dx_m.z()) / (2.0f * EPSILON);
|
||||||
float dFy_dx = (p_dx_p.y() - p_dx_m.y()) / (2.0f * e);
|
float dFy_dx = (p_dx_p.y() - p_dx_m.y()) / (2.0f * EPSILON);
|
||||||
float dFx_dy = (p_dy_p.x() - p_dy_m.x()) / (2.0f * e);
|
float dFx_dy = (p_dy_p.x() - p_dy_m.x()) / (2.0f * EPSILON);
|
||||||
|
|
||||||
return Vector3f(
|
return Vector3f(
|
||||||
dFz_dy - dFy_dz,
|
dFz_dy - dFy_dz,
|
||||||
|
|||||||
Reference in New Issue
Block a user