【问题标题】:GLSL 2D Perlin noise looking weirdGLSL 2D Perlin 噪声看起来很奇怪
【发布时间】:2017-09-04 14:28:45
【问题描述】:

作为大学作业的一部分,我必须在 GLSL 中实现 Perlin 噪声。我用这张幻灯片作为参考:

还有这个wikipedia article

我的课程说我应该得到这样的东西:

不幸的是,我在运行代码时得到了这个:

通过在噪声值上加上 0.5,我得到了这个:

在我看来很奇怪的是,从一个单元格到另一个单元格的插值似乎不能很好地工作。好像插值函数没有 C2 连续性。这很奇怪,因为我用于插值的函数 f 确实具有此属性。你知道这个问题可能来自哪里吗?

这是我的片段着色器代码:

#version 330

in vec2 uv;

out vec3 color;

uniform int width;
uniform int height;

float simple_rand(vec2 co) {
    return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
}

vec2 rand(vec2 co) {
    float angle = 3.141592654 * 2 * simple_rand(co);
    return vec2(sin(angle), cos(angle));
}

// mix function as described in the slides
float lerp(float x, float y, float alpha) {
    return (1 - alpha) * x + alpha * y;
}

// interpolation function as described in the slides
float f(float t) {
    return t*t*t * (t * (6.0*t - 15.0) + 10.0);
}

vec3 noise(vec2 vec) {
    // number of pixels per cell
    int cell_px = 50;

    // get coordinates of current cell corners and calculate random gradients
    // GRID coordinates
    int cx = int(floor(vec.x * width / cell_px));
    int cy = int(floor(vec.y * height / cell_px));
    // ABSOLUTE coordinates
    vec2 x0y0 = vec2(cx*cell_px, cy*cell_px);
    vec2 x1y1 = vec2(x0y0.x + cell_px, x0y0.y + cell_px);
    vec2 x0y1 = vec2(x0y0.x, x1y1.y);
    vec2 x1y0 = vec2(x1y1.x, x0y0.y);

    // vec translated to inner cell coordinates, relative to x0y0, must be between 0 and 1
    vec2 cell_vec = vec2((vec.x * width - x0y0.x) / cell_px, (vec.y * height - x0y0.y) / cell_px);

    // compute difference vectors
    vec2 a = vec2(cell_vec);
    vec2 b = vec2(1.0 - cell_vec.x, cell_vec.y);
    vec2 c = vec2(cell_vec.x, 1.0 - cell_vec.y);
    vec2 d = vec2(1.0 - cell_vec.x, 1.0 - cell_vec.y);

    // dot products to get scalar values from the corners
    float s = dot(rand(x0y0), a);
    float t = dot(rand(x1y0), b);
    float u = dot(rand(x0y1), c);
    float v = dot(rand(x1y1), d);

    float st_ = lerp(s, t, f(cell_vec.x));
    float uv_ = lerp(u, v, f(cell_vec.x));
    float noise = lerp(st_, uv_, f(cell_vec.y));

    return vec3(noise);
}

void main() {
    color = noise(uv);
}

【问题讨论】:

    标签: glsl fragment-shader noise perlin-noise


    【解决方案1】:

    vec2 cell_vec = vec2((vec.x * width - x0y0.x) / cell_px, (vec.y * height - x0y0.y) / cell_px);

    int 除以int 会做一些奇怪的事情。您可以先尝试将cell_px 转换为float

    【讨论】:

      【解决方案2】:

      错误来自于翻转向量的方向。您应该计算从角到点的向量,但是您正在计算从点到角的向量。

      这将解决它:

      vec2 a = vec2(cell_vec);
      vec2 b = vec2(cell_vec.x, -1.0+cell_vec.y);
      vec2 c = vec2(-1.0+cell_vec.x, cell_vec.y);
      vec2 d = vec2(-1.0 + cell_vec.x, -1.0 + cell_vec.y);
      

      【讨论】:

        猜你喜欢
        • 2015-03-20
        • 2011-08-01
        • 2015-08-16
        • 2014-08-17
        • 1970-01-01
        • 1970-01-01
        • 2021-07-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多