您好,登錄后才能下訂單哦!
這篇文章主要介紹OpenGL Shader如何實現(xiàn)彩色光圈效果,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
具體內(nèi)容如下
研究了一個彩色光圈效果,效果如下:
代碼如下:
Shader "shadertoy/TotalNoob" { //https://www.shadertoy.com/view/XdlSDs Properties{ 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 // mod = sign*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 = (2.0*gl_FragCoord.xy-iResolution.xy)/iResolution.y; float tau = 3.1415926535*2.0; float a = atan(p.x,p.y); float r = length(p)*0.75; vec2 uv = vec2(a/tau,r); //get the color float xCol = (uv.x - (iGlobalTime / 3.0)) * 3.0; xCol = sign(xCol)*fmod(xCol, 3.0); vec3 horColour = vec3(0.25, 0.25, 0.25); if (xCol < 1.0) { horColour.r += 1.0 - xCol; horColour.g += xCol; } else if (xCol < 2.0) { xCol -= 1.0; horColour.g += 1.0 - xCol; horColour.b += xCol; } else { xCol -= 2.0; horColour.b += 1.0 - xCol; horColour.r += xCol; } // draw color beam uv = (2.0 * uv) - 1.0; float beamWidth = (0.7+0.5*cos(uv.x*10.0*tau*0.15*clamp(floor(5.0 + 10.0*cos(iGlobalTime)), 0.0, 10.0))) * abs(1.0 / (30.0 * uv.y)); vec3 horBeam = vec3(beamWidth,beamWidth,beamWidth); vec4 gl_FragColor = vec4((( horBeam)* horColour ), 1.0); return gl_FragColor; } ENDCG SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma fragmentoption ARB_precision_hint_fastest ENDCG } } FallBack Off }
代碼分析
代碼分兩部分,顏色 * 光圈,如下圖:
* =
彩色的算法
代碼如下:
vec2 p = (2.0*gl_FragCoord.xy-iResolution.xy)/iResolution.y; float tau = 3.1415926535*2.0; float a = atan(p.x,p.y); float r = length(p)*0.75; vec2 uv = vec2(a/tau,r); //get the color float xCol = (uv.x - (iGlobalTime / 3.0)) * 3.0; xCol = mod(xCol, 3.0); vec3 horColour = vec3(0.25, 0.25, 0.25); if (xCol < 1.0) { horColour.r += 1.0 - xCol; horColour.g += xCol; } else if (xCol < 2.0) { xCol -= 1.0; horColour.g += 1.0 - xCol; horColour.b += xCol; } else { xCol -= 2.0; horColour.b += 1.0 - xCol; horColour.r += xCol; }
這段代碼是寫在fragment shader中的,也就是說,每個像素點的渲染都會調(diào)用這段代碼。
a) vec2 p = (2.0*gl_FragCoord.xy-iResolution.xy)/iResolution.y;
p表示把當前的坐標軸縮小到原來的1/2,原點移動到屏幕中間,并把x,y軸的坐標范圍縮小到1左右的值(即p的y軸范圍在-1到1之間,x軸的范圍也在附近);
b)float a = atan(p.x, p.y);
a表示p點繞原點的角度,范圍為[-π,π];所以uv.x = a/tau的范圍為[-1/2, 1/2];
float xCol = (uv.x - (iGlobalTime / 3.0)) * 3.0; xCol=mod(xCol, 3)的范圍為 [0,3]
c) xCol經(jīng)過上面處理,其范圍為[0,3]; 現(xiàn)在把這個范圍平均分成3份,每一份做一個顏色的混合:
[0,1]:Red和Green混合;[1,2]:Green和Blue混合;[2,3]:Blue和Red混合。
光圈的算法
a)畫光圈
式子:abs(1.0 / (30.0*uv.y))
知識:在shader中,如果color的值為負數(shù),則認為是0,不顯示該顏色。
uv變量中uv.y表示點到原點的距離,值的范圍為 [0, ]
a-1) uv = (2.0 * uv) - 1.0; 先把uv縮小到原來的1/2,然后向外移動1單位。uv.y的值為[-1/2, ];由于負值color不被顯示,如下圖A:
a-2) 1.0/(30.0* uv.y); 縮小到原來的1/30,并做個倒數(shù),如下圖B
a-3) abs(1.0/(30.0* uv.y)); 然后做個絕對值,如下圖C
=》=》
畫光圈的算法和《【OpenGL】Shader實例分析(一)-Wave》中畫線的算法很類似。
b)光圈動畫
式子:(0.7+0.5*cos(uv.x*10.0*tau*0.15*clamp(floor(5.0 + 10.0*cos(iGlobalTime)), 0.0, 10.0)))
為了方便,把上面的式子分解如下:
式1:float tt = 5.0 + 10.0*cos(iGlobalTime);
式2:float param = clamp(floor(tt), 0.0, 10.0);
式3:float beamWidth = (0.7+0.5*cos(uv.x*pi*param));
我們把beamWidth作為顏色輸出;
先理解式3,如果當param為0,、1、2、3、10時,分別參考下圖:
=》 =》=》 =》
式2的作用,把tt的值做一個包裝,使其為0到10之間的整數(shù)
式1的作用,起周期作用,值域為[-5,15]; 其值如左下圖所示; 又由于式2做了clamp,把大于10和小于0的值去掉,最終的動畫如右下圖所示:
====》
把光圈和顏色整合起來就看到了和文章開頭的動畫一樣的效果了。
最后吧所有的效果整合起來,如下圖:
【彩色】 => 【彩色旋轉(zhuǎn)】 =》【彩色旋轉(zhuǎn)+動畫】 =》【彩色旋轉(zhuǎn)+動畫+光圈】
=》=》=》
以上是“OpenGL Shader如何實現(xiàn)彩色光圈效果”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。