作为大学任务的一部分,我必须在GLSL中实现Perlin噪音。我用这张幻灯片作为参考:
我的课程说我应该得到这样的东西:
不幸的是,当我运行我的代码时,我得到了这个:
通过在噪声值上加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);
}
答案 0 :(得分:1)
vec2 cell_vec = vec2((vec.x * width - x0y0.x) / cell_px, (vec.y * height - x0y0.y) / cell_px);
int
除以int
可以做奇怪的事情。您可以先尝试将cell_px
转换为float
。
答案 1 :(得分:0)
错误是由于向量方向相反引起的。您应该计算从拐角到点的向量,但是要计算从拐角到点的向量。
这将解决该问题:
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);