楼主:
riveranb (River)
2017-05-27 20:01:36去年在网络上看到很佛心的人分享一个 lava shader
今天刚好在整理这一部份写成blog
就分享来这里
因为也有几行关键的数学判断我看不懂
所以希望板上的大神如果愿意的话帮我解惑一下 XD
另外觉得我有写错的部份也可以交流讨论讨论
http://riveragamer.blogspot.tw/2017/05/lava-shader-code.html
shader codes的话就跳过vertex shader
只贴fragment shader
(排版不佳伤眼, 不好意思XD)
=====================================
struct PS_OUTPUT
{
float4 RGBColor : COLOR0; // Pixel color
};
float time;
sampler2D tex0;
sampler2D tex1;
PS_OUTPUT pixelMain( float2 TexCoord : TEXCOORD0,
float4 Position : POSITION )
{
PS_OUTPUT Output;
// tex0 是作者准备的noise map, 作者将它视为normal map去应用
float4 noise = tex2D( tex0, TexCoord ); // sample color map
// 计算 2 组UV位移分量, 时间参数在此代入影响
float2 T1 = TexCoord + float2(1.5,-1.5)*time*0.02;
float2 T2 = TexCoord + float2(-0.5,2.0)*time*0.01;
// noise.xyz 分别代表tangent space(我译为切线空间)中的x, z, y轴分量
// (xz平面视为水平面)
// T1.xy = noize.xy * 2 + T1.xy;
// 也就是noise空间的 xz 水平位移量影响T1
T1.x += (noise.x)*2.0;
T1.y += (noise.y)*2.0;
// T2.xy = noize.yz * 2 + T2.xy;
// 也就是noize空间的 yz 垂直面位移量影响T2
T2.x += (noise.y)*0.2;
T2.y += (noise.z)*0.2;
// 由T1再次对 tex0 (noise map)做fetch,
// 取得T1扰动影响后alpha结果 (p = noise.a)
float p = tex2D( tex0, T1*2.0).a;
// 以T2由 tex1 (lava炎浆贴图) 去取得炎浆的原色
float4 col = tex2D( tex1, T2*2.0 );
// 神奇的数学来了, 我头开始痛惹
// col 被 p * 2 影响后再加上自身 col * col - 0.1,
// 明显是一个高亮度曝光的动作
float4 temp = col*(float4(p,p,p,p)*2.0)+(col*col-0.1);
// 这 3 个 if condition 我真的无法解释 = =,
// 但最关键的就在这辣rrrrr
if(temp.r > 1.0 ) { temp.bg += clamp(temp.r-2.0,0.0,100.0); }
if(temp.g > 1.0 ) { temp.rb += temp.g-1.0; }
if(temp.b > 1.0 ) { temp.rg += temp.b-1.0; }
// Jobs done. QQ
Output.RGBColor = temp;
return Output;
}
temp分量初始值会在[0.0, 2.9]之间感觉剩下的程式是在把数值正规化到[0.0 1.0]之间可是感觉作者magic number用有点随便...像temp.r - 2.0是[-1.0 0.9]之间的值,算[-1.0 1.0]好了没必要用100.0f去clamp这个值呀...除非我误会了什么如果你单纯写temp.rgb = normalize(temp.rgb)会变如何?如果效果差不多,那应该就是作者想要在正规化的途中多掺入一些"搅和"如果是这样,那就除了本人解释以外,旁人真的只能猜了原作用另一层流动速度不同的噪声来曝光各取样点考量不知为和,不知为何不直接采用两层流动速度不同的perlin noise octave做additive blending因为那个demo影片看起来效果跟这个方法好像差不多或许两个方法之间有不明显的差异,真好奇...