图形学 Cellular Noise
前言
本篇重点如何实现Cellular Noise
定义
- Cellular Noise基于Voronoi图生成,其外观就像是一个个紧挨着的细胞,因而得名Cellular Noise。而Voronoi图的定义是由一组连续多边形组成,多边形的形成由其内部的控制点来控制,按照最邻近原则划分平面,即每个多边形都代表平面上离其内部控制点最近的区域
用途
- 可用于模拟地表、水面的焦散、卷积云、爬行动物的皮肤等
实现
从迭代开始
-
在shader中迭代即是for循环,需要注意的是:迭代的次数必须是固定的,并不接受动态次数
-
在上面说过Cellular Noise是基于距离实现的,而这个距离是指一个特征点集最近的点的距离
-
假设现在有四个特征点,求它的距离场可能的实现如下
void mainImage( out vec4 fragColor, in vec2 fragCoord ) { // Normalized pixel coordinates (from 0 to 1) vec2 uv = fragCoord/iResolution.xy; // 进行拉伸处理 uv.x *= iResolution.x / iResolution.y; // Time varying pixel color vec3 col = vec3(0.f); // cell position vec2 point[5]; point[0] = vec2(0.83,0.75); point[1] = vec2(0.60,0.07); point[2] = vec2(0.28,0.64); point[3] = vec2(0.31,0.26); point[4] = iMouse.xy / iResolution.xy; float minDistance = 1.f; // get min distance for(int i = 0; i < 5; ++i) { float dist = distance(uv, point[i]); minDistance = min(dist, minDistance); } col += minDistance; // Output to screen fragColor = vec4(col,1.0); }
划分空间
-
上面这种策略虽然行得通,但性能不高,并没有充分发挥GPU并行架构的特点。一个可行的方案是将整个空间划分为多个网格——对uv进行缩放
现在我已uv坐标作为color进行输出,可以得到以下结果
如果对uv放大3倍并对其运用fract()求得小数部分,会得到以下结果
这就是所谓的划分空间:将原本一个空间,划分为九个,大大提高shader性能
-
对于Cellular Noise,不能延用之前使用的方案。现在每个网格对应一个特征点,计算目标像素点到九个特征点的最近距离
可能的实现如下vec2 random2 (vec2 p) { return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453); } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { // Normalized pixel coordinates (from 0 to 1) vec2 uv = fragCoord/iResolution.xy; // 进行拉伸处理 uv.x *= iResolution.x / iResolution.y; uv *= 3.f; vec2 uvI = floor(uv); vec2 uvF = fract(uv); // Time varying pixel color vec3 col = vec3(0.f); float minDistance = 1.f; // 计算目标点到九个特征点的距离 for(int i = -1; i <= 1; ++i) { for(int j = -1; j <= 1; ++j) { // 目标特征点 vec2 neighbor = vec2(float(i), float(j)); vec2 point = random2(uvI + neighbor); // calc min distance float dist = length(point - uvF + neighbor); minDistance = min(minDistance, dist); } } col += minDistance; // Draw cell center col += 1.-step(.02, minDistance); // Output to screen fragColor = vec4(col,1.0); }
reference
https://zhuanlan.zhihu.com/p/94632440
https://iquilezles.org/articles/smoothvoronoi/
https://thebookofshaders.com/12/
https://en.wikipedia.org/wiki/Cellular_noise