【OpenGL】Shader執行個體分析(七)- 雪花飄落效果,shader執行個體分析
轉寄請保持地址:http://blog.csdn.net/stalendp/article/details/40624603
研究了一個雪花飄落效果,感覺挺不錯的,分享給大家,效果如下:
代碼如下:
Shader "shadertoy/Flakes" { // https://www.shadertoy.com/view/4d2XzcProperties{iMouse ("Mouse Pos", Vector) = (100,100,0,0)iChannel0("iChannel0", 2D) = "white" {} iChannelResolution0 ("iChannelResolution0", Vector) = (100,100,0,0)} CGINCLUDE #include "UnityCG.cginc" #pragma target 3.0 #pragma glsl #define vec2 float2 #define vec3 float3 #define vec4 float4 #define mat2 float2x2 #define iGlobalTime _Time.y #define mod fmod #define mix lerp #define atan atan2 #define fract frac #define texture2D tex2D // 螢幕的尺寸 #define iResolution _ScreenParams // 螢幕中的座標,以pixel為單位 #define gl_FragCoord ((_iParam.srcPos.xy/_iParam.srcPos.w)*_ScreenParams.xy) #define PI2 6.28318530718 #define pi 3.14159265358979 #define halfpi (pi * 0.5) #define oneoverpi (1.0 / pi) fixed4 iMouse; sampler2D iChannel0; fixed4 iChannelResolution0; struct v2f { float4 pos : SV_POSITION; float4 srcPos : TEXCOORD0; }; // precision highp float; v2f vert(appdata_base v){ v2f o; o.pos = mul (UNITY_MATRIX_MVP, v.vertex); o.srcPos = ComputeScreenPos(o.pos); return o; } vec4 main(v2f _iParam); fixed4 frag(v2f _iParam) : COLOR0 { return main(_iParam); } vec4 main(v2f _iParam) { vec2 p = gl_FragCoord.xy/iResolution.xy; vec3 col = vec3(0,0,0); float dd = 150; for( int i=0; i<dd; i++ ) { float an = 6.2831*float(i)/dd; vec2 of = vec2( cos(an), sin(an) ) * (1.0+0.6*cos(7.0*an+iGlobalTime)) + vec2( 0.0, iGlobalTime ); col = max( col, texture2D( iChannel0, p + 20*of/iResolution.xy ).xyz ); col = max( col, texture2D( iChannel0, p + 5.0*of/iResolution.xy ).xyz ); } col = pow( col, vec3(1.0,2.0,3.0) ) * pow( 4.0*p.y*(1.0-p.y), 0.2); return vec4( col, 1.0 );} ENDCG SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma fragmentoption ARB_precision_hint_fastest ENDCG } } FallBack Off }程式碼分析:
1)七邊形雪花的繪製演算法具體代碼如下:
float dd = 150;for( int i=0; i<dd; i++ ){float an = 6.2831*float(i)/dd;vec2 of = vec2( cos(an), sin(an) ) * (1.0+0.6*cos(7.0*an+iGlobalTime)) + vec2( 0.0, iGlobalTime );col = max( col, texture2D( iChannel0, p + 20*of/iResolution.xy ).xyz );col = max( col, texture2D( iChannel0, p + 5.0*of/iResolution.xy ).xyz );}在理解這段代碼前,先理解怎麼畫一個圈,代碼如下:
float dd = 30;for( int i=0; i<dd; i++ ){float an = 6.2831*float(i)/dd;vec2 of = vec2( cos(an), sin(an) );col = max( col, texture2D( iChannel0, p + 20*of/iResolution.xy ).xyz );}然後再準備一張貼圖,圖片中間是一個白色像素,周圍都是黑色
效果如下:
這段代碼處於fragment shader中,意味著螢幕上每個點都會進行上述的演算法。具體如下,遍曆貼圖中該點周圍的點(上面的代碼中為距離該點為20單位的圓上的點),把周圍點中最亮的作為該點的顏色。 上面的貼圖有點特殊,只有一個點是白色,其餘點都是黑色的。那麼只有距離該點正好為20單位的點才會變成亮色,其餘的點都是黑色,如的結果。一句話總結上面演算法的效果:貼圖中的每一個“相對亮點”的周圍都會產生特定的圖形,圖形的亮度取決於該點的亮度。效果可以參考文末的圖片。
接下來理解這段代碼:
float dd = 150;for( int i=0; i<dd; i++ ){float an = 6.2831*float(i)/dd;vec2 of = vec2( cos(an), sin(an) ) * (1.0+0.7*cos(7.0*an));col = max( col, texture2D( iChannel0, p + 20*of/iResolution.xy ).xyz );//col = max( col, texture2D( iChannel0, p + 5.0*of/iResolution.xy ).xyz );}輸出結果如下:
a) 1.0+0.7*cos(7.0*an)的映像如下:
b)演算法中 of 向量的路徑為:
結果就很清晰了;其實這裡演算法和《【OpenGL】Shader執行個體分析(二)- Heart》中繪製心形的演算法很類似。
最後加上時間就可以實現動畫了:
vec2 of = vec2( cos(an), sin(an) ) * (1.0+0.6*cos(7.0*an+iGlobalTime)) + vec2( 0.0, iGlobalTime );
第一個iGlobalTime,用來控制雪花的旋轉,第二個iGlobalTime使雪花下落。
2)後期顏色等處理
這裡可以理解為一種postEffect處理,具體是如下的代碼貢獻的效果:
col = pow( col, vec3(1.0,2.0,3.0) ) * pow( 4.0*p.y*(1.0-p.y), 0.2);
a) pow(col, vec3(1.0, 2.0, 3.0)) 這句話使得顏色變成暖色調。col值的範圍為[0,1],對小數繼續pow運算,次數越高,該值越小。比如:0.5的1次方是0.5, 2次方為0.25, 3次方為0.125等;所以這句話的作用很明顯:red成份不變,green變小一些,blue變的更小。達到的效果,使得整體顏色會偏向暖色調。
b)pow(4.0*p.y*(1.0-p.y), 0.2) 使得螢幕上下兩邊變暗。
最後附上shader中用到的貼圖:
經過程式處理後,得到如下:
文章完畢,歡迎討論。
RenderMonkey 182 的 opengl 教程,我現在要做寫 shader,做一些 3D特效
找一下這本書《Shaders.for.Game.Programmers.and.Artists》,網上有。
OpenGL 21特效與Shader Moder 41有什不同,是不是所有顯卡都同時支援這兩種技術
shader model 4.1指的是4.1版的著色器。只有支援微軟的圖形介面DirectX10.1的顯卡才支援4.1版的著色器。ATI的HD3000和4000系列都支援,而GeForce系列的還沒有支援的,因為現在的遊戲基本上都只用到了4.0版的著色器,也就只支援DX10.0,所以對DX10.1的支援不是很必要 OpenGL(全寫Open Graphics Library)是個定義了一個跨程式設計語言、跨平台的編程介面的規格,它用於三維圖象(二維的亦可)。OpenGL是個專業的圖形程式介面,是一個功能強大,調用方便的底層圖形庫。OpenGL的前身是SGI公司為其圖形工作站開發的IRIS GL。IRIS GL是一個工業標準的3D圖形軟體介面,功能雖然強大但是移植性不好,於是SGI公司便在IRIS GL的基礎上開發了OpenGL。OpenGL的英文全稱是“Open Graphics Library”,顧名思義,OpenGL便是“開放的圖形程式介面”。
DirectX在家用市場全面領先,但在專業高端繪圖領域,OpenGL是不能被取代的主角
OpenGL 功能還是看你日常需要了~~ 當然有應該是比沒有好的~