当前位置:网站首页>【零基础】充分理解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);
}
边栏推荐
- 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
- Meeting OA project progress (I)
- 我们为什么要推出Getaverse?
- TCP协议调试工具TcpEngine V1.3.0使用教程
- Why should we launch getaverse?
- Win10 download address
- [leetcode]38. counting - problem solving (execution time beat 91%, memory consumption beat 97%)
- Envi grid resampling
- Jenkins CLI 命令详解
- Codeforces round 690 (Div. 3) C. unique number conventional solution
猜你喜欢

Envi SHP to ROI and mask the grid

Envi5.3 open GF-1 WFV data

期盼已久全平台支持-开源IM项目OpenIM之uniapp更新

Meeting OA project progress (II)

Long awaited full platform support - Open Source im project uniapp update of openim

leetcode:162. 寻找峰值【二分寻找峰值】

Using native JS to realize magnifying glass function

VSCode如何鼠标滚轮放大界面

我们为什么要推出Getaverse?

Jing Wei PS tutorial: basic part a
随机推荐
EventLoop event loop mechanism
Why should we launch getaverse?
【技术】uniapp之聊天室 demo
Meeting OA project progress (II)
804. Unique Morse code word
Simply use MySQL index
图片浏览器?Qt也可以实现!
MODIS data WGet Download
Mcd12q1 data shows multiple classifications in envi
Princeton calculus reader 02 Chapter 1 -- composition of functions, odd and even functions, function images
TCP协议调试工具TcpEngine V1.3.0使用教程
EF miscellaneous
Jupyter uses tips
Cache penetration, cache breakdown, cache avalanche differences and solutions [easy to understand]
Summary of experience in using.Net test framework xUnit, mstest, specflow
[leetcode]38. counting - problem solving (execution time beat 91%, memory consumption beat 97%)
ArcGIS layer annotation display
Getting started with arcpy
ARP 入门
What is the difference between cookies, localstorage and sessionstorage?