http://www.cnblogs.com/tkgamegroup/p/4214081.html

这周学了好多。包括伪随机数。柏林噪声。
先说伪随机数。伪随机数我们用的是周期函数而不是那种由前一项乘一个超大的数取余数的方法。使用周期函数的好处就是可以让其随时间均匀变化。不过使用周期函数一定要保证周期非常长,不然就会出现重复的图样。
这是我在网上找到的一个伪随机函数:
cos(x * (12.9898) + y * (4.1414)) * 43758.5453
它使用x, y作为参数,刚好对应像素的坐标。(PS:发现好多GLSL的例子都用类似的随机函数,应该里面蕴含了什么数学吧。) 
这个函数的周期应该挺长的, 会发现在cos的后面还乘上了一个超大的数,这样可以达到不错的伪随机效果,不过还需要很重要的一步。
最终的随机函数是这样的:
fract(cos(x * (12.9898) + y * (4.1414)) * 43758.5453)
fract这个glsl预定义的函数的作用是返回小数部分,会达到非常不错的效果。
 
↑这是没有加上fract的结果,因为所有大于1的值都变成1了。(GL中像素的颜色值范围是0.0-1.0) 
 
↑这是加上fract的效果,看起来还不错是吧。
PS:
在想随机数的时候,我想人工智能是不是其实是可以实现的呢。因为智能可能就是对一个个小事件的反应,当这些对各种事情的反应多起来的时候,数量趋近于无穷,或者达到一个阀值,就会表现出智能。因为人类的大脑说不定也是这样,是不是也是对一个个小事件的反应呢,我想是的,大脑里面这种反应非常多,多到了一个阀值,所以才会变现出“智能”,而自由意志应该就是量子随机性造成的,而至于为什么不觉得这种随机不想是“随机”的呢,而想是可控的呢?因为这些随机性的东西都会经过一个个在大脑中设定好的程序,被这样处理过的信息之后,看起来就变得“有序”了。(稍后你会看到上面这些这样随机的图样,最终会变成一幅不错的图画)所以,人工智能终有一天是会实现的,只要不断地设定对各种事件的反应,让它看起来“好像是智能的样子呢”,当这种“好像是智能的样子呢”多起来的时候,达到了一个阀值,那么这个东西就是真正的智能了,这里可没有双引号。这里也稍微的用一下数学里面的极限思想了呢,0.999...这样无穷下去,数学上的结果就是1。不过目前想要达到这个阀值,需要的是非常高性能的计算机还有聪明的程序员,至少前者还不能实现,在未来20年之后,估计就能实现看起来非常智能的人工智能了。
哎呀,扯多了。

接下来是一个火焰特效,看起來像20年前的技術,哈哈。由浅入深嘛。慢慢地就会学到现代的技术了。

看起来还阔以吧。

不知道gif能不能播放,不过gif画质太渣了,还是不用gif了。你就想想这个火焰是会动的就行啦。

接下来是柏林噪声(Perlin噪声)了,Ken Perlin在1981年为电影创造了这种噪声,它可以模拟自然的云、火焰、水面等,为电影特效做出了功不可没的贡献,为此,他获得了“奥斯卡技术成就奖”。

Perlin噪声就是n个函数的叠加,这n个函数满足,下一个的频率是前一个的两倍,幅度是二分之一。而函数嘛,当然是选择我们上面的伪随机函数啦。

不过首先,我们要对屏幕的像素分组。我的分组是250*250个一组。 也就是这250*250个像素共享同一个随机的值。然后,对于每个小组,每个小组里面的像素,进行一次插值,(可以是线性插值(假如在A,,B两点间插值,t(0<=t<=1)是距离A的距离比例,那么t位置的值是(1
- t) * A + t * B,(1 - t)是插值函数),不过效果差,Perlin本人推荐 3 * t * t - 2 * t * t *
t,后来推荐..哎呦
这个好长,就不写出来了)二维的插值是这样的,首先取本小组的值和右边小组的值在x方向插值得到a,然后是下面小组的值和右下小组的值在x方向插值得到b,最后就是a和b在y方向插值得到最终结果。
glsl里面有预定义插值函数,线性的mix和平滑的smoothstep。

所以,代码看起来是这样的:

#define r 250
float noise(float x, float y)
{
int base_x = int(floor(x / r)); // 小组的x编号
int base_y = int(floor(y / r)); // 小组的y编号
x = fract(x / r); // 像素在小组内x方向的权值
y = fract(y / r); // 像素在小组内y方向的权值
float f_x = smoothstep(0, 1, x); // 平滑后的值
float f_y = smoothstep(0, 1, y); // 平滑后的值
return
mix(
mix(rand(float(base_x), float(base_y)), rand(float(base_x + 1), float(base_y)), f_x) // 第一次的x方向插值
,
mix(rand(float(base_x), float(base_y + 1)), rand(float(base_x + 1), float(base_y + 1)), f_x) // 第二次的x方向插值
,
f_y) // 最后的y方向插值
;

}

看起来是这样的:

哇..看起来好爽。

接下来就是Perlin噪声了, 请看代码:

float fbm(float x, float y)
 {
float total = 0.0, amplitude = 1.0;
for (int i = 0; i < 4; i++) // 4个函数叠加
{
total += noise(x, y) * amplitude; 
x += x;  // 频率乘以2
y += y;  // 频率乘以2
amplitude *= 0.5; // 幅度乘以二分之一
}
return total;

}

效果是这样的:

我已经看到了一点云的样子了呢。

接下来,加点颜色,你可以自由发挥,这里只是一个例子:

t = float(_t);
float z = fbm(gl_FragCoord.x - t * 100, gl_FragCoord.y - t * 100);
float x = fbm(gl_FragCoord.x + t * 60, gl_FragCoord.y - t * 40);
float c = fbm(gl_FragCoord.x - t * 70, gl_FragCoord.y - t * 80);
vec3 color1 = vec3(1.0, 0.9, 0.0);
vec3 color2 = vec3(1.0, 0.0, 0.0);
vec3 color3 = vec3(0.0, 0.0, 0.0);
vec3 color4 = vec3(0.2, 0.2, 0.2);
vec3 color5 = vec3(0.0, 0.0, 0.6);
vec3 color6 = vec3(0.0, 0.6, 0.0);

gl_FragColor = vec4(mix(color2, color1, z) + mix(color3, color4, x) - mix(color5, color6, c), 1.0); 
就可以达到火焰特效了,要更加逼真的效果就需要不断的尝试颜色的组合,或者加入数学知识。

对了,漏了最重要的一点,就是怎么向着色器里面传一个值。

用到的是uniform技术。

在glsl代码中,你只要这样:

uniform int _t;
 
就可以声明一个_t的uniform变量。uniform在一次渲染中值不会改变,所有着色器都可以访问这个值。程序也可以在每一帧时任意修改uniform的值。用这样的语句:

 
GLint location;
location = glGetUniformLocation(program, "_t");

glUniform1i(location, _t);

**以上参考:http://www.tuicool.com/articles/VFnAFbB。火焰特效是借鉴http://glslsandbox.com/里面的一个特效,不过原文的地址我忘了T T。

好了。周记完毕,在最后送一个小特效:

void main() 
{
vec3 color = vec3(0.0, 0.0, 0.0);
float angle = t * t * 0.1;
vec2 q;
q.x = p.x + cos(angle * 3.14 / 180) * 10;
q.y = p.y + sin(angle * 3.14 / 180) * 10;
float A = q.y - p.y;
float B = p.x - q.x;
float C = q.x * p.y - p.x * q.y;
float rate;
rate = A * gl_FragCoord.x + B * gl_FragCoord.y + C;
rate = rate * rate;
rate = rate / (A * A + B * B);
rate = 100 / rate;
color.x = rate * 0.0;
color.y += rate * 0.0;
color.z += rate * 0.8;
float x, y;
x = gl_FragCoord.x - 1366.0 / 2;
y = gl_FragCoord.y - 768.0 / 2;
rate = x * x + y * y;
rate = sqrt(rate);
int temp = _t % 20;
rate -= (temp * temp);
if(rate < 0)
rate = -rate;
rate *= rate;
rate = 100 / rate;
color.x = rate * 0.8;
color.y += rate * 0.0;
color.z += rate * 0.0;
gl_FragColor = vec4(color, 1.0);

}

[GLSL]着色器周记02——火焰特效 【转】的更多相关文章

  1. GLSL着色器,来玩

    对实现动画的前端同学们来说,canvas可以说是最自由,最能全面控制的一个动画实现载体.不但能通过javascript控制点.线.面的绘制,使用图片资源填充:还能改变输入参数作出交互动画,完全控制动画 ...

  2. GLSL 着色器程序

    除了使用Cg/HSL 着色器程序以外, OpenGL 着色器语言(GLSL)着色器可以直接书写shader. 然而,使用原生的GLSL只推荐作为测试使用,或者你清晰的知道你的目标平台是 Mac OS ...

  3. OpenGLES2.0着色器语言glsl

    OpenGLES2.0中是强制使用可编程的渲染管线的,使用的是glsl着色器语言,因为着色器语言是使用的GPU,即图形处理单元,而不是CPU,这样可以使CPU从繁重的几何计算和像素的处理中解脱出来了. ...

  4. 【OPENGL】第三篇 着色器基础(二)

    在这一小节,主要学习GLSL的基本数据类型以及控制结构.GLSL具备了C++和Java的很多特性,我们会先了解所有着色阶段共有的特性,再了解各个着色器的专属特性. 1.着色器的基本结构 一个着色器程序 ...

  5. DirectX11 With Windows SDK--02 顶点/像素着色器的创建、顶点缓冲区

    前言 由于在Direct3D 11中取消了固定管线,要想绘制图形必须要了解可编程渲染管线的流程,一个能绘制出图形的渲染管线最少需要有这两个可编程着色器:顶点着色器和像素着色器. 本章会直接跳过渲染管线 ...

  6. OpenGL学习脚印: uniform blocks在着色器中的使用 转自https://blog.csdn.net/wangdingqiaoit/article/details/52717963

    写在前面 目前,我们在着色器中要传递多个uniform变量时,总是使用多个uniform,然后在主程序中设置这些变量的值:同时如果要在多个shader之间共享变量,例如投影矩阵projection和视 ...

  7. OpenGL学习笔记(三)着色器

    目录 Shader是什么 GLSL 数据类型 输入与输出 顶点着色器向片段着色器发送数据 Uniform 制作三色渐变三角形 对着色器程序进行封装 参考资料:OpenGL中文翻译 Shader是什么 ...

  8. 对osg节点添加glsl特效(片断着色器FragmentShader)

    读取一个模型到节点node,然后想对node施加一些特效,这时可以只使用片段着色器 其中: gl_Color表示固定管线计算出来的颜色,包含光照效果 gl_TexCoord[]表示纹理坐标 unifo ...

  9. [OpenGL ES 02]OpenGL ES渲染管线与着色器

    [OpenGL ES 02]OpenGL ES渲染管线与着色器 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循"署名-非商业用途-保持一致"创 ...

随机推荐

  1. PHP生成随机字符串与唯一字符串

    代码如下: <?php /* * 生成随机字符串 * @param int $length 生成随机字符串的长度 * @param string $char 组成随机字符串的字符串 * @ret ...

  2. 基于node的前端页面实时更新。呦吼~

    学习了gulp,webpack后越发觉得前端开发万分的有趣,首当其冲的就是解决了狂按f5的尴尬. 当我们按下ctrl+s保存后页面自动更新了,我就觉得我f5键在隐隐的发笑. 1.node_npm_li ...

  3. bootstrap中如何多次使用一个摸态框

    /**弹出框设置**/ function showjcziimodal(url, width) { $("#jczii-modal").remove();//如果存在此Id的Mod ...

  4. css3玩转各种效果【资源】

    css3玩转各种按钮效果[资源] 点击下载 css3各种拐弯箭头-包括循环旋转 点击下载 不定期更新,下班了……

  5. 五十五 网络编程 UDP编程

    TCP是建立可靠连接,并且通信双方都可以以流的形式发送数据.相对TCP,UDP则是面向无连接的协议. 使用UDP协议时,不需要建立连接,只需要知道对方的IP地址和端口号,就可以直接发数据包.但是,能不 ...

  6. FastJson过滤掉不需要的返回字段

    /** * @Author:txp * @Description:过滤掉不需要返回的字段 * @Param: [src, clazz, args]` * @Data: 2017/10/10 9:10 ...

  7. Aras Innovator 11 sp2安装

    本文档记录Aras Innovator 11 sp2的安装过程 官方安装文档:http://www.aras.com/support/documentation/ Aras Innovator 11. ...

  8. 视频H5のVideo标签在微信里的坑和技巧

    随着 4G 的普遍以及 WiFi 的广泛使用,手机上的网速已经足够稳定和高速,以视频为主的 HTML5 也越来越普遍了,相比帧动画,视频的表现更加丰富,前段时间开发了一个以视频为主的移动端 HTML5 ...

  9. python版GetTickCount()

    time.clock() return the current processor time as a floating point number expressed in seconds. 即返回一 ...

  10. 对PDO的认识

    1.PDO(PHP Data Object)扩展为PHP定义了一个访问数据库的轻量.持久的接口.实现PDO接口的每一种数据库驱动都能以正则扩展的形式把各自的特色表现出来. 主要:PDO扩展只是一个抽象 ...