float hash(vec3 p)
{
float h=dot(p,vec3(327.73333,10675.23857,1736.4243589));
return fract(sin(h)*42387.2355837);
}
float noise3D(vec3 p,float res)
{
p*=res;
vec3 i=floor(mod(p,res));
vec3 f=fract(p);
vec3 u=f*f*(3.0-2.0*f);
float y1=mix(mix(hash(i),hash(i+vec3(1.,0.,0.)),u.x),
mix(hash(i+vec3(0.,1.,0.)),hash(i+vec3(1.,1.,0.)),u.x),
u.y);
float y2=mix(mix(hash(i+vec3(0.,0.,1.)),hash(i+vec3(1.,0.,1.)),u.x),
mix(hash(i+vec3(0.,1.,1.)),hash(i+vec3(1.,1.,1.)),u.x),
u.y);
return mix(y1,y2,u.z)*2.-1.;
}
float snoise3D(vec3 uv, float res)
{
const vec3 s = vec3(1e0, 1e2, 1e3);

uv *= res;

vec3 uv0 = floor(mod(uv, res))*s;
vec3 uv1 = floor(mod(uv+vec3(1.), res))*s;

vec3 f = fract(uv); f = f*f*(3.0-2.0*f);

vec4 v = vec4(uv0.x+uv0.y+uv0.z, uv1.x+uv0.y+uv0.z,
uv0.x+uv1.y+uv0.z, uv1.x+uv1.y+uv0.z);

vec4 r = fract(sin(v*1e-1)*1e3);
float r0 = mix(mix(r.x, r.y, f.x), mix(r.z, r.w, f.x), f.y);

r = fract(sin((v + uv1.z - uv0.z)*1e-1)*1e3);//这里补z部分
float r1 = mix(mix(r.x, r.y, f.x), mix(r.z, r.w, f.x), f.y);

return mix(r0, r1, f.z)*2.-1.;
}

对比s版本 上面是很朴素的版本 对每个地方都hash随机 最后mix

s版本则是抓住重点  一开始就构造了uv0 uv1 然后构造出一个v

里面实际上是 i+0 0 0    1 0 0    0 1 0    1 1 0 然后fract一次就是随机一次 然后mix一次得到一个y1 再fract得到y2

最后在mix(y1,y2,z)这明显很优秀嘛