Shader技巧之实现单/双鱼眼全景球转换
发表于2018-11-15
这篇文章给大家分享下使用shader的技巧,利用shader实现单/双鱼眼到全景图转换。
单鱼眼最终效果:
思路
将x坐标当作弧度取tan,y坐标为半径转换
源代码:
Shader "QQ/TexConvert/SingleFishEyeSimple" { Properties { _MainTex("Texture", 2D) = "white" {} _Lerp("lerp",Range(0,1)) = 1 _Radius("radius",Range(0.0,1.0)) = 0.5 [Toggle] _Hint("show hint", float) = 0 } SubShader { Tags { "RenderType" = "Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; uniform sampler2D _MainTex; uniform float4 _MainTex_ST; uniform float _Lerp; uniform float _Radius; uniform float _Hint; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag(v2f i) : SV_Target { i.uv = abs(i.uv) % 1.0; float th = i.uv.x * UNITY_PI * 2; float ta = tan(th); float2 uv0 = float2(cos(th)*ta*_Radius, sin(th) / ta*_Radius)*(1 - i.uv.y) + 0.5; fixed4 col = tex2D(_MainTex, lerp(i.uv, uv0, _Lerp), 0, 0); if (_Hint > 0) { if (length(i.uv - float2(0.5, 0.5)) < _Radius) col += fixed4(uv0, 0, 1); } return col; } ENDCG } } }
双鱼眼最终效果
思路
将平面坐标转换到球面坐标
将球面坐标转换为经纬度
取经纬度的二维坐标
源代码:
Shader"QQ/DoubleFishEyeSimple" { Properties { _MainTex("Texture",2D)="white"{} _Lerp("lerp",Range(0,1))=1 _Radius("radius",Range(0.0,1.0))=0.5 _Blend("blend",Range(0,1))=0.1 [Toggle]_Hint("showhint",float)=0 } SubShader { Tags{"RenderType"="Opaque"} LOD100 Pass { CGPROGRAM #pragmavertexvert #pragmafragmentfrag #include"UnityCG.cginc" structappdata { float4vertex:POSITION; float2uv:TEXCOORD0; }; structv2f { float2uv:TEXCOORD0; float4vertex:SV_POSITION; }; uniformsampler2D_MainTex; uniformfloat4_MainTex_ST; uniformfloat_Lerp; uniformfloat_Radius; uniformfloat_Blend; uniformfloat_Hint; v2fvert(appdatav) { v2fo; o.vertex=UnityObjectToClipPos(v.vertex); o.uv=TRANSFORM_TEX(v.uv,_MainTex); returno; } float3pts(float2uv,floatr) { uv=(uv/1.0-0.5)*UNITY_PI; returnr*float3(sin(uv.x)*cos(uv.y),sin(uv.y),cos(uv.x)*cos(uv.y)); } float2stp(float3s,floatr) { floatt=atan2(s.y,s.x); floatp=atan2(sqrt(s.x*s.x+s.y*s.y),s.z); float_r=r*2*p/UNITY_PI; return_r*float2(cos(t),sin(t)); } float2ptstp(float2uv,floatr,float2o) { float3s=pts(uv,_Radius); float2_uv=stp(s,_Radius); _uv.x/=2; return_uv+=o; } fixed4frag(v2fi):SV_Target { i.uv=abs(i.uv)%1.0; float2uv=float2((i.uv.x%0.5)/0.5,i.uv.y); floatm=_Blend+1; float2_uv=float2(uv.x/m,uv.y); float2uv0=ptstp(_uv,_Radius,float2(i.uv.x>0.5?0.75:0.25,0.5)); fixed4col=tex2D(_MainTex,lerp(i.uv,uv0,_Lerp),0,0); if(_Blend>0.0) { m=1-1/m; if(_uv.x<m) { float2uv1=ptstp(_uv-float2(1+m,0),_Radius,float2(i.uv.x>0.5?0.25:0.75,0.5)); fixed4_col=tex2D(_MainTex,lerp(i.uv,uv1,_Lerp),0,0); col=lerp(col,_col,(m-_uv.x)/m); } } if(_Hint>0) { float2s0=uv-float2(0.5,0.5); if(length(s0)<_Radius) col+=fixed4(0.5,0,0,1); } returncol; } ENDCG } } }