这周学了好多。包括伪随机数。柏林噪声。 接下来是一个次时代的火焰特效,所谓次时代就是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方向插值得到最终结果。 所以,代码看起来是这样的: #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; 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
时间: 2024-10-15 14:38:42
[GLSL]着色器周记02的相关文章
[GLSL]着色器周记02——火焰特效 【转】
http://www.cnblogs.com/tkgamegroup/p/4214081.html 这周学了好多.包括伪随机数.柏林噪声.先说伪随机数.伪随机数我们用的是周期函数而不是那种由前一项乘一个超大的数取余数的方法.使用周期函数的好处就是可以让其随时间均匀变化.不过使用周期函数一定要保证周期非常长,不然就会出现重复的图样.这是我在网上找到的一个伪随机函数:cos(x * (12.9898) + y * (4.1414)) * 43758.5453它使用x, y作为参数,刚好对应像素的坐标
[GLSL]着色器周记01!
我决定开个新坑了.以后每周五更新.这是GLSL的学习周记!GLSL就是OPENGL SHADER LANGUAGE的简称,就是着色器语言.着色器是一种交给显卡运行的小程序,这种小程序可以用GLSL来写,写好后交给OPENGL编译,就可以在显卡上运行了. 那么问题来了!为什么要给显卡运行呢?显卡是一种特殊的处理器,有核心,有寄存器,还有内存,不过对比CPU,最大的特点就是显卡的核心更多.多多少呢?一般CPU有4-8个核心,而显卡则是100个左右的核心!不过由于造价还有空间的限制,显卡的某些功能会被
[GLSL]着色器周记03
懒惰的一周~http://www.cnblogs.com/easymind223/archive/2012/07/05/2578231.htmlhttp://glslsandbox.com/e#21606.0↑根据它们的指导做出来的Mandelbrot集~ #version 440 #define r 300.0 uniform int _t; vec2 center = vec2(1366.0 / 2.0, 768.0 / 2.0); void main() { vec2 c = vec2((
第4章:缓冲区、着色器、GLSL
原文链接: http://www.rastertek.com/gl40tut04.html Tutorial 4: Buffers, Shaders, and GLSL This tutorial will be the introduction to writing vertex and pixel shaders in OpenGL 4.0. It will also be the introduction to using vertex and index buffers in OpenG
OpenGLES2.0着色器语言glsl
OpenGLES2.0中是强制使用可编程的渲染管线的,使用的是glsl着色器语言,因为着色器语言是使用的GPU,即图形处理单元,而不是CPU,这样可以使CPU从繁重的几何计算和像素的处理中解脱出来了.这就加大了处理的速度. 下面的这篇教程是转载的.原文地址如下,感谢作者manyou http://www.apkbus.com/blog-99192-39382.html 一.着色语言基础 数据类型概述 1. 标量 标量也被称为"无向量"其值只有大小,并不具有方向.标量之间的运算遵循简单的
OpenGL中使用着色器
OpenGL中使用GLSL着色器步骤 GLSL既适用于顶点着色器,也适用于片段着色器. 使用着色器对象的步骤: 1.创建着色器对象: GLuint glCreateShader(GLenum type); //创建一个着色器对象,type值必须是GL_VERTEX_SHADER或GL_FRAGMENT_SHADER.error返回0 2.把着色器的源码与着色器对象相关联: glShaderSource(GLuint shader, GLsizei count, const GLChar** st
OpenGL学习笔记5:着色器
初识着色器语言 变量和数据类型 可用的数据类型只有4种:有符号整数,无符号整数,浮点数,布尔值. OpenGL着色语言中没有指针和字符串或字符.返回值可以为void. 向量类型 所有4种基本数据类型都可以存储在二维.三维或者四维向量中: OpenGL着色语言向量数据类型 类型 描述 vec2,vec3,vec4 2分量.3分量和4分量浮点向量 ivec2,ivec3,ivec4 2分量.3分量和4分量整数向量 uvec2,uvec3,uvec4 2分量.3分量和4分量无符号整数向量 bvec2,
WebGL 着色器语言(GLSL ES)
1.类型转换内置函数 转换/函数/描述 转换为整形数/int(float)/将浮点数的小数部分删去,转换为整形数(比如,将3.14转换为3) 转换为整形数/intl(bool)/true被转换为1,false被转换为0 转换为浮点数/float(int)/将整形数转换为浮点数(比如,将8转换为8.0) 转换为浮点数/float(bool)/true被转换为1.0,false被转换为0.0 转换为布尔值/bool(int)/0被转换为false,其他非0倍转换为true 转换为布尔值/0.0被转换
OpenGL学习日记-2015.3.5——Hello glsl(着色器)
过年前忍不住买了本新版的OpenGL编程指南,主要的目的还是为了系统的学习着色器编程,另外就是接触新版的OpenGL技术和思想.看了几页,就过年了QAQ.回来后也是各种不在状态,不想上班,不想工作,不想写代码...昨天终于强迫自己继续看书,也找回了些状态. 书本基础知识的全面性和权威性就不用说了,不过这个源代码就....这第一个例子照着代码来抄结果...我想应该是原来的代码一个参数错了,折腾了半天,代码分析是详说.主要是分析代码,有什么说什么,并没有全面的说明着色器的基本内容,想着在着色器的基础