图形学中的噪声入门

一、白噪声

白噪声常与伪随机数一起使用。这样,固定的输入就会产出固定的随机数输出,最终渲染出来的纹理也会是固定的,但又具备随机的视觉效果。

常用的白噪声随机产生函数如下:

float random = dot(vec in , vec const);

使用输入向量和一个任意向量点乘,即可得到一个随机的结果;

在OpenGL中使用:

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform float u_time;

float rand(vec2 vec){
    float random = dot(vec , vec2(-12.000,20.820));
    random = fract(random);
    return random;
}

void main() {
    vec2 uv = gl_FragCoord.xy/u_resolution.yy;
    vec3 color = vec3(rand(uv));
    gl_FragColor = vec4(color,1.0);
}

得到的噪声图:

可以看到两个向量点乘投影形成的条带。一点也不均匀。

解决方法是对点积后的结果取正弦,然后乘上一个大数,将其小数点移后几位,得到更为随机分布的小数。

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform float u_time;

float rand(vec2 vec){
    float random = sin(dot(vec, vec2(12.9898,78.233))) * 43758.5453;
    random = fract(random);
    return random;
}

void main() {
    vec2 uv = gl_FragCoord.xy/u_resolution.yy;
    vec3 color = vec3(rand(uv));
    gl_FragColor = vec4(color,1.0);
}

得到的噪声如下:

注意这里取的

vec2(12.9898,78.233)
和43758.5453;

都是前辈们总结下来的经验数,可以得到很好的白噪声图。

二、细胞

分割为细胞的方法就是纹理坐标乘上对应的倍数,简单高效。

void main() {
    vec2 uv = gl_FragCoord.xy/u_resolution.yy;
    uv  = uv * 10.0;

    vec3 color = vec3(fract(uv),1.0);
    gl_FragColor = vec4(color,1.0);
}

得到的效果图:

为每个细胞赋上不同的颜色:

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;

float rand2dTo1d(vec2 value ,vec2 randvec2 )
{
    vec2 dotDir = randvec2;
    vec2 smallValue = sin(value);
    float random = dot(smallValue, dotDir);
    random = fract(sin(random) * 143758.5453);
    return random;
}

vec2 rand2dto2d(vec2 value){
     return vec2(
        rand2dTo1d(value, vec2(12.989, 78.233)),
        rand2dTo1d(value, vec2(39.346, 11.135))
    );
}

void main() {
    vec2 uv = gl_FragCoord.xy/u_resolution.yy;
    vec2 st  = uv * 10.0;

    vec3 color = vec3(rand2dto2d(floor(st)),1.0);
    gl_FragColor = vec4(color,1.0);
}

得到的图片:

这里使用了前面提到的白噪声公式来为细胞产出不同的颜色。

三、柏林噪声

白噪声很好,但是它不具备连续性。

柏林噪声可以很好地解决这个问题。

使用一维柏林噪声:

使用一维的白噪声生成灰度图

float rand1dTo1d(float value){
    float mutator = 0.546;
    float random = fract(sin(value + mutator) * 143758.5453);
    return random;
}

void main() {
    vec2 uv = gl_FragCoord.xy/u_resolution.yy;

    vec3 color = vec3(rand1dTo1d( floor(uv.x * 30.)));
    gl_FragColor = vec4(color,1.0);
}

得到:

将其压缩成线:

float rand1dTo1d(float value){
    float mutator = 0.546;
    float random = fract(sin(value + mutator) * 143758.5453);
    return random;
}

void main() {
    vec2 uv = gl_FragCoord.xy/u_resolution.yy;

    //移到中心
    uv -= vec2(0.5);
    vec2 st = uv * 6.;

    float noise = rand1dTo1d( floor(st.x));
      //取噪声与纹理y坐标距离  //在 dist-> 0时画线,
    float dist = abs(noise - st.y);

  //抗锯齿
    vec3 color = vec3(smoothstep(0, fwidth(st.y), dist));

    gl_FragColor = vec4(color,1.0);
}

得到:

为了让值连续,取其小数部分进行插值,修改noise如下:

//插值
    float noise = mix(rand1dTo1d( floor(st.x)), rand1dTo1d(ceil(st.x)), fract(st.x));

得到的图如下:

这时使用的插值因子是

st.x

得到的结果并不平滑,我们应该使用缓动公式插值,常见的公式是

更改,如下:

    //插值
    float x = fract(st.x);
    float t= 6.*pow(x,5.) - 15.*pow(x,4.)+10.*pow(x,3.);
    float noise = mix(rand1dTo1d( floor(st.x)), rand1dTo1d(ceil(st.x)), fract(t));

得到的图如下:

此时,一个连续的一维的噪声就生成了。

下面应用到二维:

一张纹理图片中,直观输入就是uv,一个vec2变量。

原文地址:https://www.cnblogs.com/Afuness/p/11553174.html

时间: 2024-10-12 03:09:20

图形学中的噪声入门的相关文章

图形学中的贴图采样、走样与反走样等

计算机图形学中不可避免的会涉及到图像分析与处理的相关知识,前些时间也重温了下常用到的采样.重建以及纹理贴图等内容,并对其中的走样与反走样有了更多的认识,这里小结一下. 1. 基本问题 信号的采样与重建过程中首先面临着两个基本的问题: 给定一个连续的信号g(x)以及它的离散采样信号gs(x),能否通过gs(x)来完整的描述g(x) 的信息: 如果可以,如何通过gs(x)来重建出原始信号g(x). 这些通过对信息进行频域的分析即可得到相应的结论. 2. 采样 将一处于空间域(或时域)内的信号向频域进

【图形学】谈谈噪声

写在前面 很早就想学习和整理下噪声,稍微接触过图形学的人大概都听到过噪声,然后就会发现有各种噪声,Perlin噪声,Worley噪声,分形(fractal)噪声等等.尤其是Perlin噪声,一搜资料发现大家说的各不相同,更加不明所以.我也总是困惑,后来发现还是要相信wiki和paper. 这篇文章在于总结上面这些常见的噪声(即图形学中常见的程序噪声),它们是什么,怎么算出来的,以及一些应用.文章里的所有代码可以在我的Shadertoy上找到: 什么是噪声 在图形学中,我们使用噪声就是为了把一些随

Spring中IoC的入门实例

Spring中IoC的入门实例 Spring的模块化是很强的,各个功能模块都是独立的,我们可以选择的使用.这一章先从Spring的IoC开始.所谓IoC就是一个用XML来定义生成对象的模式,我们看看如果来使用的. 数据模型 1.如下图所示有三个类,Human(人类)是接口,Chinese(中国人)是一个子类,American(美国人)是另外一个子类. 源代码如下: package cn.com.chengang.spring;public interface Human {void eat();

计算机视觉和图形学中的摄像机内参数矩阵详解【转】

计算机视觉和图形学中的摄像机内参数矩阵详解[转] 在计算机视觉和图形学中都有“摄像机内参数矩阵”这个概念,其含义大致相同,但在实际使用过程中,这两个矩阵却相差甚远.在增强现实中,为了使计算机绘制的虚拟物体和真实环境图像对其,需要令虚拟摄像机的内参数和真实摄像机的内参数相一致.因此,理解这两个内参数矩阵的详细含义和算法很重要. 在计算机视觉中,摄像机内参数矩阵可以表示为: 其中 f 为摄像机的焦距,单位一般是mm,dx,dy 为像元尺寸,u0,v0 为图像中心.由此可以计算出摄像机纵向视场角有:

计算机图形学中的种子填充算法c++程序实现

种子填充其实很简单,计算机图形学中介绍的使用栈,感觉作者是不是脑子进水了,直接使用一个队列用广搜就可以了啊,但是我就懒得写了,直接一个递归算了,有兴趣的同学自己试一试 #include<graphics.h>#include<conio.h>  #include<stdio.h>#include<math.h>int Graph[500][500] ; void scanline_seed_fill(int color,int sx,int sy){ Gra

js中的正则表达式入门

js中的正则表达式入门 什么是正则表达式呢? 正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个字符串是否含有某种子串.将匹配的子串做替换或者从某个字符串中取出符合某个条件的子串等. 说白了正则表达式就是处理字符串的,我们可以用它来处理一些复杂的字符串. 为什么要学习正则表达式 我们直接用一个例子来说明 //找出这个字符串中的所有数字 var str = 'abc123de45fgh6789qqq111'; //方法1 function findNum

PHP中使用curl入门教程

curl和libcurl的区别简介 https://www.jb51.net/article/68750.htm curl官网 https://curl.haxx.se/ PHP中使用curl入门教程 https://www.jb51.net/article/68763.htm PHP中使用curl的步骤 在PHP中,可以使用curl完成各种各样的功能,如抓取网页,文件的上传/下载.模拟登录等.但是这些功能的实现都是基于四个步骤完成的,所以curl的使用并不复杂. 使用curl时,主要分为以下四

PHP5中PDO的入门教程

PDO(PHP Data Object) 是PHP 5新出来的东西,在PHP 5.5中,更是强烈推荐使用PDO来处理数据库,将把所有的数据库扩展移到了PECL,那么默认就是没有了我们喜爱的php_mysql.dll之类的了,那怎么办捏,我们只有与时俱进了,我就小试了一把PDO.(本文只是入门级的,高手可以略过,呵呵) [PDO是啥] PDO是PHP5新加入的一个重大功能,因为在PHP5以前的PHP4/PHP3都是一堆的数据库扩展来跟各个数据库的连接和处理,什么 php_mysql.dll.php

计算机图形学中的经常使用模型

今天在网上搜了一下图形学里面比較经常使用的模型.认为挺有意思,把它们收集起来,总结一下. 1.Lena/Lenna 这个模型是一个美女,名字叫Lena,是1972年11月<Playboy>(国内译为:花花公子)杂志的一个插图. 不知道花花公子杂志为何物的请自己去百度. Lena是瑞典人.依据英语标准发音,译为Lenna. 以下来张截图: 花花公子中的原图:http://www.ee.cityu.edu.hk/~lmpo/lenna/len_full.jpg 1973年6月.美国南加州大学的信号