2D 柏林噪声似乎是四四方方的
2D perlin noise appears to be boxy
我似乎在 2d 输入上得到四四方方的 perlin 噪声地形。
我一直在关注这个 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
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,将噪声函数的return值解释为一个角度(噪声*2*PI),计算出grad()
的return值:
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));
}
我似乎在 2d 输入上得到四四方方的 perlin 噪声地形。
我一直在关注这个 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
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,将噪声函数的return值解释为一个角度(噪声*2*PI),计算出grad()
的return值:
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));
}