当前位置:网站首页>【零基础】充分理解WebGL(八)
【零基础】充分理解WebGL(八)
2022-07-24 16:39:00 【前端码农小王】
在上一节里我们聊了随机,随机是模拟世界的无序和不可预测性。
然而实际上,真正的大自然在无序中孕育着秩序。空气看似无序的扰动,产生了气流,气流汇聚形成季风;水波看似无序,然而产生水流,形成河流、洋流;岩石的生长看似无序,但形成山脉,连绵不断……随机无处不在,秩序也无处不在。
这次褐蚁来到故地,只是觅食途中偶然路过而已。它来到孤峰脚下,用触须摸了摸这顶天立地的存在,发现孤峰的表面坚硬光滑,但能爬上去,于是它向上爬去。没有什么目的,只是那小小的简陋神经网络中的一次随机扰动所致。这扰动随处可见,在地面的每一株小草和草叶上的每一粒露珠中,在天空中的每一片云和云后的每一颗星辰上……扰动都是无目的的,但巨量的无目的扰动汇集在一起,目的就出现了。 —— 《三体II 黑暗森林》
为了比较真实地模拟大自然,我们在随机中引入秩序,把无序与秩序结合在一起,就形成了噪声。
噪声
我们还是通过两段代码来理解如何从随机到噪声。
float random(vec2 co)
{float a = 12.9898;float b = 78.233;float c = 43758.5453;float dt= dot(co.xy ,vec2(a,b));float sn= mod(dt,3.14);return fract(sin(sn) * c);
}
float random(float i) {return random(vec2(i));
}
void main() {vec2 st = gl_FragCoord.xy / dd_resolution;st.x *= 15.0;float i = floor(st.x);float f = fract(st.x);float d = random(i); FragColor.rgb = step(st.y, d) * vec3(1.0);FragColor.a = 1.0;
}
上面这段代码是我们上一节学到的随机,我们利用它来绘制出高低不平的白色条纹。
https://code.juejin.cn/pen/7116322958267645960
接下来,我们修改一下main函数,对相邻两个随机区间之间进行平滑插值:
void main() {vec2 st = gl_FragCoord.xy / dd_resolution;st.x *= 15.0;float i = floor(st.x);float f = fract(st.x);float d = mix(random(i), random(i + 1.0), f * f * (3.0 - 2.0 * f));FragColor.rgb = step(st.y, d) * vec3(1.0);FragColor.a = 1.0;
}
这样就形成下面的效果,这种效果就叫做噪声。
https://code.juejin.cn/pen/7116328502009266212
注意这里我们用了三次平滑曲线 f * f * (3.0 - 2.0 * f),这是一种数学技巧,我们也可以用glsl内置函数smoothstep,把
float d = mix(random(i), random(i + 1.0), f * f * (3.0 - 2.0 * f));
改成
float d = mix(random(i), random(i + 1.0), smoothstep(0.0, 1.0, f));
结果是一样的。
二维噪声
上面这个是一维噪声函数,我们可以将它扩展到二维:
float random(vec2 co)
{float a = 12.9898;float b = 78.233;float c = 43758.5453;float dt= dot(co.xy ,vec2(a,b));float sn= mod(dt,3.14);return fract(sin(sn) * c);
}
highp float noise(vec2 st) {vec2 i = floor(st);vec2 f = fract(st);vec2 u = f * f * (3.0 - 2.0 * f);return mix( mix( random( i + vec2(0.0,0.0) ), random( i + vec2(1.0,0.0) ), u.x),mix( random( i + vec2(0.0,1.0) ), random( i + vec2(1.0,1.0) ), u.x), u.y);
}
如上面的代码,我们对二维随机向量的x、y方向分别进行线性插值然后叠加,就形成了二维噪声。
void main() {vec2 st = gl_FragCoord.xy / dd_resolution;st *= 10.0;vec2 idx = floor(st);float d = noise(st);FragColor.rgb = vec3(d);FragColor.a = 1.0;
}
https://code.juejin.cn/pen/7116394433972535310
噪声与生成艺术
利用噪声,我们可以生成一些有趣的纹理,比如随机条纹:
float lines(in vec2 pos, float b){float scale = 10.0;pos *= scale;return smoothstep(0.0, 0.5 + b * 0.5, abs((sin(pos.x * 3.1415) + b * 2.0)) * 0.5);
}
vec2 rotate(vec2 v0, float ang) {float sinA = sin(ang);float cosA = cos(ang);mat3 m = mat3(cosA, -sinA, 0, sinA, cosA, 0, 0, 0, 1);return (m * vec3(v0, 1.0)).xy;
}
uniform vec2 dd_resolution;
uniform float dd_time;
void main() {vec2 st = gl_FragCoord.yx / dd_resolution;st *= vec2(10.0, 3.0);st = rotate(st, noise(st + 0.1 * dd_time));float d = lines(st, 0.5);FragColor.rgb = 1.0 - vec3(d);FragColor.a = 1.0;
}
https://code.juejin.cn/pen/7116400660739784740
还有水滴效果:
void main() {vec2 st = mix(vec2(-10, -10), vec2(10, 10), gl_FragCoord.xy / dd_resolution);float d = distance(st, vec2(0));d *= noise(dd_time + st);d = smoothstep(0.0, 1.0, d) - step(1.0, d);FragColor.rgb = vec3(d);FragColor.a = 1.0;
}
https://code.juejin.cn/pen/7116403493702729735
雾状
我们将二维噪声按照与自身放大叠加若干次,可以得到更加平滑的雾状效果:
float d = 0.5 * noise(st);st *= 2.0;d += 0.25 * noise(st);st *= 2.0;d += 0.125 * noise(st);st *= 2.0;d += 0.0625 * noise(st);st *= 2.0;d += 0.0375 * noise(st);
https://code.juejin.cn/pen/7116420173304692766
我们可以将它封装成如下函数:
#ifndef OCTAVES
#define OCTAVES 6
#endif
float mist(vec2 st) {//Initial valuesfloat value = 0.0;float amplitude = 0.5;float frequency = 0.0;// Loop of octavesfor(int i = 0; i < OCTAVES; i++) {value += amplitude * noise(st);st *= 2.0;amplitude *= 0.5;}return value;
}
如上面的代码,我们按照每次放大一倍的效果将噪声叠加6次,然后通过很简单的方法就可以实现类似于空中俯瞰的效果:
void main() {vec2 st = gl_FragCoord.xy / dd_resolution;st.x += random(vec2(dd_randseed0)) + 0.1 * dd_time; FragColor.rgb = hsb2rgb(vec3(mist(st), 1.0, 1.0));FragColor.a = 1.0;
}
https://code.juejin.cn/pen/7116404135674511367
其他噪声函数
除了上面常规的二维噪声函数(被称为Value Noise),常用的噪声函数还有Gradient Noise和Simplex Noise等等,
Gradient Noise基于随机的二维向量来插值:
vec2 grad( ivec2 z )// replace this anything that returns a random vector
{// 2D to 1D(feel free to replace by some other)int n = z.x+z.y*11111;// Hugo Elias hash (feel free to replace by another one)n = (n<<13)^n;n = (n*(n*n*15731+789221)+1376312589)>>16;
#if 0// simple random vectorsreturn vec2(cos(float(n)),sin(float(n)));#else// Perlin style vectorsn &= 7;vec2 gr = vec2(n&1,n>>1)*2.0-1.0;return ( n>=6 ) ? vec2(0.0,gr.x) : ( n>=4 ) ? vec2(gr.x,0.0) :gr;
#endif
}
float noise( in vec2 p )
{ivec2 i = ivec2(floor( p )); vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f); // feel free to replace by a quintic smoothstep insteadreturn mix( mix( dot( grad( i+ivec2(0,0) ), f-vec2(0.0,0.0) ), dot( grad( i+ivec2(1,0) ), f-vec2(1.0,0.0) ), u.x),mix( dot( grad( i+ivec2(0,1) ), f-vec2(0.0,1.0) ), dot( grad( i+ivec2(1,1) ), f-vec2(1.0,1.0) ), u.x), u.y);
}
注意,上面的Gradient Noise 实现演示了另一种获得随机数的思路(还记得上一节课我们使用sin函数的小数位来构造随机?),即使用哈希算法来构造随机数:
n = (n<<13)^n;
n = (n*(n*n*15731+789221)+1376312589)>>16;
另外,除了使用四边形网格插值的二维噪声,Simplex Noise基于三角网格插值,与四边形插值相比,三角网格插值需要计算的点更少了,这样自然大大降低了计算量,从而提升了渲染性能。
//
// Description : GLSL 2D simplex noise function
//Author : Ian McEwan, Ashima Arts
//Maintainer : ijm
// Lastmod : 20110822 (ijm)
// License :
//Copyright (C) 2011 Ashima Arts. All rights reserved.
//Distributed under the MIT License. See LICENSE file.
//https://github.com/ashima/webgl-noise
//
float noise(vec2 v) {// Precompute values for skewed triangular gridconst vec4 C = vec4(0.211324865405187,// (3.0-sqrt(3.0))/6.00.366025403784439,// 0.5*(sqrt(3.0)-1.0)-0.577350269189626,// -1.0 + 2.0 * C.x0.024390243902439);// 1.0 / 41.0// First corner (x0)vec2 i= floor(v + dot(v, C.yy));vec2 x0 = v - i + dot(i, C.xx);// Other two corners (x1, x2)vec2 i1 = vec2(0.0);i1 = (x0.x > x0.y)? vec2(1.0, 0.0):vec2(0.0, 1.0);vec2 x1 = x0.xy + C.xx - i1;vec2 x2 = x0.xy + C.zz;// Do some permutations to avoid// truncation effects in permutationi = mod289(i);vec3 p = permute(permute( i.y + vec3(0.0, i1.y, 1.0))+ i.x + vec3(0.0, i1.x, 1.0 ));vec3 m = max(0.5 - vec3(dot(x0,x0),dot(x1,x1),dot(x2,x2)), 0.0);m = m*m ;m = m*m ;// Gradients://41 pts uniformly over a line, mapped onto a diamond//The ring size 17*17 = 289 is close to a multiple//of 41 (41*7 = 287)vec3 x = 2.0 * fract(p * C.www) - 1.0;vec3 h = abs(x) - 0.5;vec3 ox = floor(x + 0.5);vec3 a0 = x - ox;// Normalise gradients implicitly by scaling m// Approximation of: m *= inversesqrt(a0*a0 + h*h);m *= 1.79284291400159 - 0.85373472095314 * (a0*a0+h*h);// Compute final noise value at Pvec3 g = vec3(0.0);g.x= a0.x* x0.x+ h.x* x0.y;g.yz = a0.yz * vec2(x1.x,x2.x) + h.yz * vec2(x1.y,x2.y);return 130.0 * dot(m, g);
}
边栏推荐
- 2019q1 global smartphone shipments: Huawei vivo increased significantly, while Apple plummeted 30.2%!
- Enter a URL to this page to show it. What happened in this process?
- With notes: printing order of synchronous, asynchronous, micro task and macro task
- [technology] online seat selection demo of uniapp
- QT keyboard event (II) -- long press the key to trigger the event event repeatedly, and the problem is solved
- EF data migration
- Leetcode:162. looking for peak [two points looking for peak]
- 我们为什么要推出Getaverse?
- Meeting OA project progress (I)
- [leetcode]38. counting - problem solving (execution time beat 91%, memory consumption beat 97%)
猜你喜欢
随机推荐
My first blog
Unity camera free movement control
会议OA项目进度(二)
[leetcode]75. color classification - problem solving (execution time beat 90%, memory consumption beat 78%)
Servlet framework (servlet+jsp) + addition, deletion, modification and query + paging implemented by MySQL (function package student information entry, addition, deletion, modification and query of st
1184. 公交站间的距离
JUC源码学习笔记3——AQS等待队列和CyclicBarrier,BlockingQueue
15、ARM嵌入式系统:如何用PC调试单板
Analysis of double pointer sliding window method and solution of leetcode related problems
ZCMU--5023: 家庭划分(C语言)
期盼已久全平台支持-开源IM项目OpenIM之uniapp更新
MySQL basic commands
709. Convert to lowercase letters
thinkphp3.2.5无法跳转到外部链接
[Nanjing Agricultural University] information sharing of postgraduate entrance examination and re examination
Meeting OA project progress (I)
Envi5.3 open GF-1 WFV data
With regard to performance testing, dry goods hit "suggestions collection"
Duplicate content in lookup table
JS simulation realizes the principles of call, apply, bind and new








![Leetcode:162. looking for peak [two points looking for peak]](/img/77/64b7c9bf1aebc2a0ab82218ddfff62.png)