2017年5月27日 星期六

lava shader code example

http://irrnetcp.proboards.com/thread/2/lava-shader-hlsl

上一篇有提到當時 Google 大神引導我到一篇超佛心 post,
讓我看到我大腦一直無法解開的 optimized lava shader solution 難題!
就像佛心大大分享一身功夫完全不求回報一樣。
都提到了我就順便就我理解的部份說明一下 lava shader 的運作流程。

但先說明我的數學也很爛,
所以直到現在還是有幾行關鍵的 condition 看不懂 XD
既然是要分享我註解就盡量寫中文好了
不過我是預設讀者看的懂 gpu shader code就是囉。

我所理解的有限,有人發現我寫錯的可以打我臉 XD
當然歡迎有緣佛心大大來教我我也不懂的地方 XD

code snippets (HLSL)
===================================================
float4x4 mWorldViewProj; // World * View * Projection transformation
struct VS_OUTPUT
{
float4 Position : POSITION; // vertex position
float2 TexCoord : TEXCOORD0; // tex coords
};
// vertex shader 沒做任何特別的事情
VS_OUTPUT vertexMain( in float4 vPosition : POSITION,
float2 texCoord : TEXCOORD0 )
{
VS_OUTPUT Output;
// transform position to clip space
Output.Position = mul(vPosition, mWorldViewProj);
Output.TexCoord = texCoord;
return Output;
}

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;
}
===================================================

所以這個 shader 需要準備什麼貼圖呢
tex0 : noise(rgba),雖然我的解釋中提到它被我當成 normal map,但事實上r , g, b, a各 channel 都只準備了各自不同地 4 方連續 Perlin noise pattern,而其中 r, g, b 之後主要去影響的是擾動變形;a 則是炎漿的亮度曝光效果主要影響因子。

tex1 : lava,也需要是 4 方連續的 pattern。

沒有留言:

張貼留言