opengl - Converting 2D Noise to 3D -
i've started experimenting noise (simple perlin noise), , have run slight problem animating it. far come i've across awesome looking 3d noise (https://github.com/ashima/webgl-noise) use in project understood nothing of, , bunch of tutorials explain how create simple 2d noise.
for 2d noise, used following fragment shader:
uniform sampler2d al_tex; varying vec4 varying_pos; //actual coords varying vec2 varying_texcoord; //normalized coords uniform float time; float rand(vec2 co) { return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453); } float ease(float p) { return 3*p*p - 2*p*p*p; } float cnoise(vec2 p, int wavelength) { int ix1 = (int(varying_pos.x) / wavelength) * wavelength; int iy1 = (int(varying_pos.y) / wavelength) * wavelength; int ix2 = (int(varying_pos.x) / wavelength) * wavelength + wavelength; int iy2 = (int(varying_pos.y) / wavelength) * wavelength + wavelength; float x1 = ix1 / 1280.0f; float y1 = iy1 / 720.0f; float x2 = ix2 / 1280.0f; float y2 = iy2 / 720.0f; float xoffset = (varying_pos.x - ix1) / wavelength; float yoffset = (varying_pos.y - iy1) / wavelength; xoffset = ease(xoffset); yoffset = ease(yoffset); float t1 = rand(vec2(x1, y1)); float t2 = rand(vec2(x2, y1)); float t3 = rand(vec2(x2, y2)); float t4 = rand(vec2(x1, y2)); float tt1 = mix(t1, t2, xoffset); float tt2 = mix(t4, t3, xoffset); return mix(tt1, tt2, yoffset); } void main() { float t = 0; int minfreq = 0; int noiterations = 8; (int = 0; < noiterations; i++) t += cnoise(varying_texcoord, int(pow(2, + minfreq))) / pow(2, noiterations - i); gl_fragcolor = vec4(vec3(t), 1); }
the result got this:
now, want animate time. first thought change rand function take vec3 instead of vec2, , change cnoise function accordingly, interpolate values in z direction too. goal in mind, made this:
sampler2d al_tex; varying vec4 varying_pos; varying vec2 varying_texcoord; uniform float time; float rand(vec3 co) { return fract(sin(dot(co, vec3(12.9898, 78.2332, 58.5065))) * 43758.5453); } float ease(float p) { return 3*p*p - 2*p*p*p; } float cnoise(vec3 pos, int wavelength) { ivec3 ipos1 = (ivec3(pos) / wavelength) * wavelength; //the first value i'll sample interpolate ivec3 ipos2 = ipos1 + wavelength; //the second value vec3 transpercent = (pos - ipos1) / wavelength; //transition percent - float in [0-1) indicating how of each of above values contribute final result transpercent.x = ease(transpercent.x); transpercent.y = ease(transpercent.y); transpercent.z = ease(transpercent.z); float t1 = rand(vec3(ipos1.x, ipos1.y, ipos1.z)); float t2 = rand(vec3(ipos2.x, ipos1.y, ipos1.z)); float t3 = rand(vec3(ipos2.x, ipos2.y, ipos1.z)); float t4 = rand(vec3(ipos1.x, ipos2.y, ipos1.z)); float t5 = rand(vec3(ipos1.x, ipos1.y, ipos2.z)); float t6 = rand(vec3(ipos2.x, ipos1.y, ipos2.z)); float t7 = rand(vec3(ipos2.x, ipos2.y, ipos2.z)); float t8 = rand(vec3(ipos1.x, ipos2.y, ipos2.z)); float tt1 = mix(t1, t2, transpercent.x); float tt2 = mix(t4, t3, transpercent.x); float tt3 = mix(t5, t6, transpercent.x); float tt4 = mix(t8, t7, transpercent.x); float tt5 = mix(tt1, tt2, transpercent.y); float tt6 = mix(tt3, tt4, transpercent.y); return mix(tt5, tt6, transpercent.z); } float fbm(vec3 p) { float t = 0; int noiterations = 8; (int = 0; < noiterations; i++) t += cnoise(p, int(pow(2, i))) / pow(2, noiterations - i); return t; } void main() { vec3 p = vec3(varying_pos.xy, time); float t = fbm(p); gl_fragcolor = vec4(vec3(t), 1); }
however, on doing this, animation feels... strange. it's though i'm watching slideshow of perlin noise slides, individual slides fading in. other perlin noise examples have tried (like https://github.com/ashima/webgl-noise) animated time - can see being animated, , don't feel images fading in, , not being animated. know use webgl-noise shader, want make 1 myself, , reason, i'm failing miserably. tell me going wrong, or suggest me on how can animate time?
you should proably include z in sin function:
float rand(vec3 co) { return fract(sin(dot(co.xy ,vec2(12.9898,78.233)) + co.z) * 43758.5453); }
apparently random numbers prime numbers. avoid patterns in noise. found prime number, 94418953, , included in sin/dot function. try this:
float rand(vec3 co) { return fract(sin(dot(co.xyz ,vec3(12.9898,78.233, 9441.8953))) * 43758.5453); }
edit: don't take account wavelength on z axis. means iterations have same interpolation distance. in other words, fade effect you're describing. try calculating z same way calculate x , y:
int iz1 = (int(p.z) / wavelength) * wavelength; int iz2 = (int(p.z) / wavelength) * wavelength + wavelength; float z1 = iz1 / 720.0f; float z2 = iz2 / 720.0f; float zoffset = (varying_pos.z - iz1) / wavelength;
this means z value variate same rate y will. if want scale 0 1 should proably multiply z 720 before passing noise function.
Comments
Post a Comment