【问题标题】:2D perlin noise appears to be boxy2D 柏林噪声似乎是四四方方的
【发布时间】:2020-02-21 19:05:32
【问题描述】:

我似乎在 2d 输入上得到了方正的柏林噪声地形。

我一直在关注这个https://www.shadertoy.com/view/4tGSzW,它使用 WebGL 而不是 opengl。我已经用范围为 0.0 到 1.0 的浮点数组替换了从一些样本纹理中获取的渐变方法。

#version 330 core
out vec4 FragColor;


uniform float gradient[256];

float fade(float t)
{
    return t*t*t*(t*(t*6.0-15.0)+10.0);
}


vec2 grad(vec2 p){
    vec2 v = vec2(gradient[int(p.x)&255],gradient[int(p.y)&255]);
    return normalize(v.xy*2.0 - vec2(1.0));
}

float noise(vec2 p){
    vec2 p0 = floor(p);
    vec2 p1 = p0 + vec2(1.0,0.0);
    vec2 p2 = p0 + vec2(0.0,1.0);
    vec2 p3 = p0 + vec2(1.0,1.0);

    vec2 g0 = grad(p0);
    vec2 g1 = grad(p1);
    vec2 g2 = grad(p2);
    vec2 g3 = grad(p3);

    float t0 = p.x - p0.x;
    float fade_t0 = fade(t0);
    float t1 = p.y - p0.y;
    float fade_t1 = fade(t1);

    float p0p1 = (1.0-fade_t0)*dot(g0,(p-p0)) + fade_t0*dot(g1,(p-p1));
    float p2p3 = (1.0-fade_t0)*dot(g2,(p-p2)) + fade_t0*dot(g3,(p-p3));

    return ((1.0-fade_t1)*p0p1 + fade_t1*p2p3);
}


void main()
{
    float n = noise(vec2(gl_FragCoord.x,gl_FragCoord.y)/64.0)*1.0 +
              noise(vec2(gl_FragCoord.x,gl_FragCoord.y)/32.0) * 0.5 +
              noise(vec2(gl_FragCoord.x,gl_FragCoord.y)/16.0) * 0.25 +
              noise(vec2(gl_FragCoord.x,gl_FragCoord.y)/8.0) * 0.125;


    FragColor = vec4(vec3(n*0.5+0.5),1.0);

}

Boxy perlin noise Image being generated

【问题讨论】:

  • 你能张贴一张你的噪音看起来如何的照片吗?
  • @Kalle Halvarsson 完成

标签: opengl glsl shader procedural-programming


【解决方案1】:

shadertoy 版本中的源纹理是二维的,由 256*256 随机像素和多个颜色通道组成。 此外,当在原始grad 函数中查找纹理时,像素会根据纹理缩小过滤器进行插值,这可能是GL_LINEAR

vec2 grad(vec2 p) {
  const float texture_width = 256.0;
  vec4 v = texture(iChannel0, vec2(p.x / texture_width, p.y / texture_width));
   return normalize(v.xy*2.0 - vec2(1.0));
}

您的统一数组只有 256 个不同的值,并且在您的 grad 函数中没有模拟纹素之间的插值:

vec2 grad(vec2 p){
   vec2 v = vec2(gradient[int(p.x)&255],gradient[int(p.y)&255]);
   return normalize(v.xy*2.0 - vec2(1.0));
}

使用Random noise functions并将噪声函数的返回值解释为角度(噪声*2*PI)来计算grad()的返回值:

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

vec2 grad(vec2 p){
    float a = rand(p) * 2.0 * 3.1415926;
    return vec2(cos(a), sin(a)); 
}

或者使用统一数组生成随机值

vec2 grad(vec2 p){

    ivec2 i00 = ivec2(int(p.x)&255, int(p.y)&255); 
    vec2  f   = floor(p); 

    float vx = mix(gradient[i00.x], gradient[i00.x+1], f.x);
    float vy = mix(gradient[i00.y], gradient[i00.y+1], f.y);

    float a = (vx + vy) * 3.141529;
    return vec2(cos(a), sin(a)); 
}

【讨论】:

  • 感谢您的解决方案,我得到了想要的结果。但是在这里我认为这不是插值导致四四方方的噪音的原因,因为我总是将 floor(vec2) 作为输入传递给 grad。我生成的值是否不够随机或其他原因?
  • @ashish 正如我在答案的第一句话中提到的 “shadertoy 版本中的源纹理是二维的,由 256*256 随机像素和多个颜色通道组成。[.. .] 你的统一数组只有 256 个不同的值"
  • 所以理论上如果有一个 256*256 随机像素值的统一数组(对于 vec2 的两个组件中的每一个),它应该使用旧方法吗?
  • @ashish 当然。但请注意 256*256 浮点数超出了(默认)统一块大小的限制。正确的解决方案是使用纹理(或随机噪声函数)。
  • 好的,现在我明白了。我从 256 个浮点数中为 x 和 y 分量挑选值,这使得所谓的随机值不是随机的,因为 x 水平重复或 y 垂直重复,因此呈现四四方方的外观。谢谢。
猜你喜欢
  • 2012-01-29
  • 1970-01-01
  • 2016-05-30
  • 2021-04-29
  • 1970-01-01
  • 2017-11-04
  • 1970-01-01
  • 1970-01-01
  • 2013-09-16
相关资源
最近更新 更多