轉自:http://blog.csdn.net/panda1234lee/article/details/52098053
基本算法參考自《GLSL 做一個動態的火苗》
效果圖
我加了點自己的修改和解析,如下:
[cpp]view plaincopy
#ifdef?GL_ES
precision?mediumpfloat;
#endif
uniformfloattime;
constvec2?resolution?=?vec2(640.0,?640.0);
voidmain(void)
{
vec2?pos?=?-1.?+?2.*gl_FragCoord?/?resolution.xy;
pos?*=?vec2(resolution.x?/?resolution.y,?1.)?*?3.;
//?火苗的抖動
if(pos.y>-2.*4.2)
{
for(floatbaud?=?1.;?baud?<?9.;?baud?+=?1.)
{
pos.y?+=?0.2*sin(4.20*time/(1.+baud))/(1.+baud);
pos.x?+=?0.1*cos(pos.y/4.20+2.40*time/(1.+baud))/(1.+baud);
}
pos.y?+=?0.04*fract(sin(time*60.));
}
//?火苗外焰
vec3?color?=?vec3(0.,0.,0.);
floatp?=.004;
floaty?=?-pow(abs(pos.x),?4.2)/p;//?外焰的形狀,注意pos.x負數會被截斷
floatdir?=?abs(pos.y?-?y)*sin(.3);//?外焰的大小(擴大漸變區域)
//float?dir?=?abs(pos.y?-?y)*(0.01*sin(time)+0.07);
if(dir?<?0.7)
{
color.rg?+=?smoothstep(0.,1.,.75-dir);//?外焰顏色漸變
color.g?/=2.4;//?減點綠
}
color?*=?(0.2?+?abs(pos.y/4.2?+?4.2)/4.2);//?增加對比度
color?+=?pow(color.r,?1.1);//?加點紅
color?*=?cos(-0.5+pos.y*0.4);//?隱藏底部的顏色
//?火苗內焰
pos.y?+=?1.5;
vec3?dolor?=?vec3(0.,0.,0.0);
y?=?-pow(abs(pos.x),?4.2)/(4.2*p)*4.2;//?內焰的形狀,注意和外焰的次冪,越接近越不容易穿幫
dir?=?abs(pos.y?-?y)*sin(1.1);//?內焰的大小(擴大漸變區域)
if(dir?<?0.7)
{
dolor.bg?+=?smoothstep(0.,?1.,?.75-dir);//?內焰顏色漸變
dolor.g?/=2.4;
}
dolor?*=?(0.2?+?abs((pos.y/4.2+4.2))/4.2);
dolor?+=?pow(color.b,1.1);//?加點藍
dolor?*=?cos(-0.6+pos.y*0.4);
//dolor.rgb?-=?pow(length(dolor)/16.,?0.5);
color?=?(color+dolor)/2.;
gl_FragColor?=?vec4(vec3(color)?,?1.0?);
}
float y = -pow(abs(pos.x), 4.2)/p; // 外焰的形狀,注意pos.x負數會被截斷
float dir = abs(pos.y - y)*sin(.3); // 外焰的大小(擴大漸變區域)
dir的函數圖(pos.x∈(-1, 1), pos.y∈(-1, 1)如下所示: