Book of Shaders 04 - 网格噪声:Worley Noise
0x00 思路
假设要生成 4 个网格,可以先在空间中指定 4 个特征点。对于每个像素点,计算它到最近特征点的距离,将这个距离当作结果值输出。
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
// 先指定 4 个特征点
vec2 point[4];
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);
// 计算像素点到 4 个特征点的最小距离
float m_dist = 1.0;
for (int i = 0; i < 4; i++) {
float dist = distance(st, point[i]);
m_dist = min(m_dist, dist);
}
// 输出结果
vec3 color = vec3(0.0);
color += m_dist;
gl_FragColor = vec4(color, 1.0);
}
效果展示:
0x01 优化
循环对着色器很不友好,遍历次数过多的循环会显著降低着色器的性能。在 Steven Worley 发表的一篇论文《A Cellular Texture Basis Function》中描述了优化的方法。我们可以将空间分割成网格,每个网格对应一个特征点,每个像素点只计算到相邻网格中的特征点的距离。这样,每个像素点就只需要计算到九个特征点的距离,它自身所在的网格的特征点和相邻的八个网格的特征点。
另外,还可以改用每个网格的整数坐标来构造随机的特征点。省去了手动指定特征点的麻烦,同时也带来了更多的随机性。
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
vec2 random2(vec2 pos) {
float x = dot(pos, vec2(127.1, 311.7));
float y = dot(pos, vec2(269.5, 183.3));
return fract(sin(vec2(x, y)) * 43758.5453);
}
void main() {
vec2 st = gl_FragCoord.xy / u_resolution.xy;
st *= 9.0;
vec2 i = floor(st);
vec2 f = fract(st);
float m_dist = 1.0;
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
// 相邻格子
vec2 neighbor = vec2(float(x), float(y));
// 生成随机特征点
vec2 point = random2(i + neighbor);
// 计算距离
float dist = length(neighbor + point - f);
// 更新最短距离
m_dist = min(m_dist, dist);
}
}
vec3 color = vec3(0.0);
color += m_dist;
gl_FragColor = vec4(color, 1.0);
}
效果展示:
0x02 扩展
Inigo Quilez 写了一篇文章,提出了他称之为 Voro Noise 的噪声,可以将常规噪声和网格噪声组合在一起。
在 Voro Noise 中,额外使用两个参数,不妨称之为 u 和 v。其中,u 用来决定最终的噪声更像常规噪声还是网格噪声,简单来说:当 u 接近 0 时,生成的噪声更接近常规噪声;当 u 接近 1 时,生成的噪声更接近网格噪声。v 提供类似常规噪声中的线性插值和网格噪声中最短距离值的功能(ps:最短距离的算法是非连续的,在 iq 的另一篇文章 Smooth Voronoi 中提供了解决这一问题的办法)。
// 初版插值方法。其中,64 是一个连续性比较好的值,详见 Smooth Voronoi 一文。
// float ww = pow( 1.0 - smoothstep(0.0, 1.414, sqrt(d)), 64.0 - 63.0 * v);
// 在初版基础上提高函数的阶数以获得更平滑的表现。
// 64.0 - 63.0 * v => 1.0 + 63.0 * pow(1.0 - v, 4.0)
float ww = pow( 1.0 - smoothstep(0.0, 1.414, sqrt(d)), 1.0 + 63.0 * pow(1.0 - v, 4.0));
完整代码:
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
vec3 random3( vec2 p ) {
float x = dot(p, vec2(127.1, 311.7));
float y = dot(p, vec2(269.5, 183.3));
float z = dot(p, vec2(419.2, 371.9));
return fract(sin(vec3(x, y, z)) * 43758.5453);
}
float voroNoise(in vec2 x, float u, float v ) {
vec2 i = floor(x);
vec2 f = fract(x);
float k = 1.0 + 63.0 * pow(1.0 - v, 4.0);
// 下面两个参数用于计算加权平均值,wa 统计总值,wt 统计总单位数
float wa = 0.0;
float wt = 0.0;
// 扩大搜索范围,进一步提高连续性
for (int y = -2; y <= 2; y++) {
for (int x = -2; x <= 2; x++) {
// 相邻格子
vec2 neighbor = vec2(float(x), float(y));
// 随机生成 point,其中 point.xy 表示特征点,point.z 表示该点的灰度值
vec3 point = random3(i + neighbor) * vec3(u, u, 1.0);
// 根据距离计算贡献值
float dist = length(neighbor - f + point.xy);
float ww = pow(1.0 - smoothstep(0.0, 1.414, dist), k);
wa += point.z * ww;
wt += ww;
}
}
return wa/wt;
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st *= 10.0;
// 用鼠标位置控制 voroNoise 中的 u 和 v
float n = voroNoise(st, u_mouse.x/u_resolution.x, u_mouse.y/u_resolution.y);
gl_FragColor = vec4(vec3(n), 1.0);
}
效果展示:
u 从 0 到 1
v 从 0 到 1
uv 一起变化
参考资料:
Book of Shaders 04 - 网格噪声:Worley Noise的更多相关文章
- 充分利用 UE4 中的噪声
转自:https://www.unrealengine.com/zh-CN/blog/getting-the-most-out-of-noise-in-ue4 UE4 推出基于材质的程序式噪声已经有一 ...
- perlin噪声
手贱去点了图形学里面的噪声课程,然后一个周末就交代在这上面了,还是有些云里雾里. 噪声就是给定一个输入变量,生成一个值在0~1范围内的伪随机变量的函数.在图形学中一般是输入一个坐标得到一个范围在0~1 ...
- 利用噪声构建美妙的 CSS 图形
在平时,我非常喜欢利用 CSS 去构建一些有意思的图形. 我们首先来看一个简单的例子.首先,假设我们实现一个 10x10 的格子: 此时,我们可以利用一些随机效果,优化这个图案.譬如,我们给它随机添加 ...
- SDR软件无线电知识要点(一)噪声系数与噪声因子
SDR软件无线电知识要点(一)噪声系数与噪声因子 信号质量如何评估 Noise Figure (NF) or sensitivity and Error Vector Magnitude (EVM) ...
- opencv:图像去噪(椒盐噪声)
#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...
- 【转】非常实用的高频PCB电路设计70问
1.如何选择PCB 板材? 选择PCB 板材必须在满足设计需求和可量产性及成本中间取得平衡点.设计需求包含电气和机构这两部分.通常在设计非常高速的 PCB 板子(大于 GHz 的频率)时这材质问题会比 ...
- 激活函数(ReLU, Swish, Maxout)
神经网络中使用激活函数来加入非线性因素,提高模型的表达能力. ReLU(Rectified Linear Unit,修正线性单元) 形式如下: \[ \begin{equation} f(x)= \b ...
- 翻译: 星球生成 II
翻译: 星球生成 II 本文翻译自Planet Generation - Part II 译者: FreeBlues 以下为译文: 概述 在前一章 我解释了如何为星球创建一个几何球体. 在本文中, 我 ...
- Peter Shirley-Ray Tracing The Next Week
Peter Shirley-Ray Tracing The Next Week(2016) 原著:Peter Shirley 英文原著地址 密码: urji 第二本书主要介绍了运动模糊,BVH(层次包 ...
随机推荐
- Ubuntu 20.04.1 安装软件和系统配置脚本
#!/bin/bash # https://launchpad.net/ubuntu # https://www.easyicon.net # https://download-chromium.ap ...
- 断言函数-RF
测试用例的目的是要验证一些操作否符合我们的预期结果,所以在测试用例中,断言函数是必不可少的一项.我们做的每一步操作都会有预期的结果,为了保证操作得到的结果符合预期,我们需要在测试用例中添加断言,来保证 ...
- pyinstaller库的简单使用 打包科赫雪花几何图形
pyinstaller 简单使用 (cmd命令行) pyinstaller -F <文件名.py> Pyinstaller库常用参数 参数 描述 -h 查看帮助 --clean 清理打包过 ...
- 程序员软件开发最好的IDE集成工具eclipse各个版本的详细介绍。详细介绍,送给初学者的朋友
对于刚接触软件开发的初学者,在下载eclipse时,对官网上面提供的各种版本的选择犹豫不决.下面将对常用的几个版本进行介绍. Eclipse版本 Eclipse Standard 该版本是eclips ...
- 攻防世界——web新手练习区解题记录<1>(1-4题)
web新手练习区一至四题 第一题view_source: 题目说右键不管用了,我们先获取在线场景来看一看,我们看到这样一个网页,并且右键确实点了没什么反应,而用到右键一般就是查看网页源码 用快捷键(F ...
- 为什么建议软件测试自学而不推荐去IT培训机构?浅谈IT培训机构存在的意义
原文地址:https://www.jianshu.com/p/447c65654e84 哥们别太天真啦,知乎上那些到处以大神自居,说培训机构各种神坑不靠谱的,绝对是无利不起早的,很多都是借着贬低别人来 ...
- Codeforece E. Anton and Permutation
主席树算贡献l,r中交换位置,算出>=rank(h) 和 <=rank(h) a[l],a[r] 先不统计 a[l]比a[r]大的话交换后ans-1,a[l]比a[r]小的话交换后ans- ...
- laravel5学习并搭建网站【更新至2020-09-03】
之前一直不清楚 php artisan 要如何使用,有朋友推荐使用phpstorm可以进行命令行执行, 现在发现其实如果真的不喜欢phpstorm的加载缓慢,可以试试计算机原有的命令行 记住需要跳转到 ...
- The Unique MST(最小生成树的唯一性判断)
Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spann ...
- RPC之总体架构
要完成一个高可用.高性能的RPC框架,需要对其架构的设计进行梳理,这里参考xxl-rpc框架,对整个项目进行梳理. 以上就是项目的整个构架,分为四个部分: 第一个是服务发布与引入,基于JDK动态代理以 ...