我的3D柏林噪声中Z轴上出现伪影的原因是什么?

时间:2019-05-26 23:40:38

标签: c++ perlin-noise

我目前正在使用C ++进行3D Perlin噪声实现,当我将其可视化为通过此代码所定义的3D体积的2D切片的视频时,只有一个八度音阶时,会出现奇怪的块状伪像:

undefined

上述程序中的每个图像都是视频中的一帧。显示此问题输出的视频(已通过ffmpeg转换为视频)可在以下位置找到:https://youtu.be/f7NxYo8U7TQ。 Youtube在该视频中添加了一些压缩伪像,这些压缩伪像在程序的输出中不存在。

如上面的视频中清楚所示,随着切片沿Z轴移动,会出现正方形伪像:Perlin Noise with Artifacts。根据制作的平面切片(例如XZ或ZY),伪像的性质会稍有变化。似乎在将一个渲染的八度音阶的频率翻转后,它们变得更糟。

这是什么原因?

Octave.h:

#include <png++/png.hpp>
#include <memory>
#include <string>

#include "Octave.h"

constexpr unsigned IMAGE_SIZE = 512;

std::string numberToString(unsigned n, unsigned digits);

int main() {
    std::mt19937_64 rnd(0);
    auto octave = std::make_unique<Octave>(&rnd, 32, 1); //make_unique because Octave objects are too big to fit on the stack

    for(unsigned z=0;z<625;++z){
        std::cout << z << "/625" << std::endl;
        png::image<png::rgb_pixel> image(IMAGE_SIZE, IMAGE_SIZE);
        for(unsigned x=0;x<IMAGE_SIZE;++x){
            for(unsigned y=0;y<IMAGE_SIZE;++y){
                unsigned brightness = (octave->noise(x, z*(64.0/300.0), y)*.5+.5)*255;
                image[y][x] = png::rgb_pixel(brightness, brightness, brightness);
            }
        }
        image.write("output/perlin-" + numberToString(z, 4) + ".png");
    }


    return 0;
}

std::string numberToString(unsigned n, unsigned digits){
    std::string string = std::to_string(n);
    while(string.length() < digits){
        string = "0" + string;
    }
    return string;
}

Octave.cpp:

#pragma once

#include <array>
#include <random>

class Octave{
public:
    Octave(std::mt19937_64 *rnd, double frequency, double amplitude);
    double noise(double x, double y, double z);

private:
    static constexpr int PERMUTATION_TABLE_PART_SIZE = 1000000;
    static constexpr int PERMUTATION_TABLE_PART_COUNT = 3;
    static constexpr int PERMUTATION_TABLE_SIZE = PERMUTATION_TABLE_PART_SIZE*PERMUTATION_TABLE_PART_COUNT;
    std::array<int, PERMUTATION_TABLE_SIZE> m_permutationTable;
    double m_frequency, m_amplitude;

    double influence(int x, int y, int z, double distanceX, double distanceY, double distanceZ);

    inline static double square(double d) { return d*d; }
    inline static double vectorLength(double x, double y, double z);
    inline static double interpolate(double a, double b, double x);

};

1 个答案:

答案 0 :(得分:0)

我确定了问题。我在计算floatZ-1时忘记做influence6