呈現的效果大概是如此。
--
實作測試(滑鼠左鍵點擊場景)
--
Metrix旋轉的公式(詳細內容請參考http://en.wikipedia.org/wiki/Rotation_matrix)
逆時針
順時針
所以基本上先計算出θ角度,接著再做旋轉計算,以求得翻頁折角那個部分的材質旋轉後的Matrix,所以θ角度就用簡單的三角函數運算,因為已經有直角三角形的兩邊長,所以直接用atan(y/x)來取得θ角。
已經有θ角了之後就可以用上面的公式來計算,這邊是順時針旋轉所以使用第二個公式:
float2x2 rotationMatrix = float2x2( cos, sin, -sin, cos); ,而因為我需要轉到折角的位置,所以事實上是要轉兩倍的θ角。
計算完並且翻轉過後就是到時候要做為折角使用的座標,接著就使用簡單的判別式就好,有原點的座標同時也有兩個端點的座標,就可以由 y=ax+b 得到兩條線段,然後只要是在這兩線段夾的範圍內,就把材質轉換為剛剛逆轉的材質。
float invert = (_AmountY-(1-newTip.y))/abs(_AmountY-(1-newTip.y)); if(pos.y-pos.x*((newTip.y-(1-_AmountY))/newTip.x) > 0 && invert*(pos.y-pos.x*(newTip.y/(newTip.x-(1-_AmountX)))) > 0) texColor = invertTexColor;
最後只有這樣的話還有點小問題,右上角會沒有缺口,所以直接把右上角的部分切掉就好了。
float2 newHypotenuse = float2((coord.x-_AmountX)/(1-_AmountX), (coord.y-_AmountY)/(1-_AmountY)); clip ((1-newHypotenuse.y)-newHypotenuse.x);
到這邊就完成了,之後只要調整AmountX跟AmountY來調整折的位置就好,同時使用Color跟Colo2來改變前後的顏色,避免顏色類似看不出差異。
完整Shader Code
Shader "Custom/NewShader" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _Color ("Color", Color) = (1,1,1,1) _Color2 ("Color 2", Color) = (1,1,1,1) _AmountX ("Amount X", Range (-1,1)) = 0 _AmountY ("Amount Y", Range (-1,1)) = 0 } SubShader { Pass { Cull Off Lighting Off Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 3.0 uniform sampler2D _MainTex; uniform float _AmountX; uniform float _AmountY; uniform float4 _Color; uniform float4 _Color2; struct vertexInput { float4 vertex : POSITION; float4 texcoord : TEXCOORD0; }; struct vertexOutput { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; float2 rotateUV : TEXCOORD1; float2 tipPos : TEXCOORD2; }; vertexOutput vert(vertexInput input) { vertexOutput output; output.uv = input.texcoord; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); float hypotenuse = length(float2(1-_AmountX,1-_AmountY)); float theta = atan((1-_AmountY)/(1-_AmountX)); float h = ((1-_AmountX)*(1-_AmountY))/hypotenuse; output.tipPos = float2(h*2*sin(theta), h*2*cos(theta)); float s = sin ( theta*2 ); float c = cos ( theta*2 ); float2x2 rotationMatrix = float2x2( c, s, -s, c); float2 invertInput = float2(output.uv.x-(1-output.tipPos.x), output.uv.y-(1-output.tipPos.y)); float2 rotateUV = mul( invertInput, rotationMatrix ); rotateUV.y = -rotateUV.y; output.rotateUV = rotateUV; return output; } half4 frag(vertexOutput input) : COLOR { float4 texColor = tex2D(_MainTex, input.uv) * _Color; float4 invertTexColor = tex2D(_MainTex, input.rotateUV) * _Color2; float2 coord = input.uv.xy; float2 newTip = input.tipPos; float2 pos = float2(coord.x-(1-newTip.x), coord.y-(1-newTip.y)); float invert = (_AmountY-(1-newTip.y))/abs(_AmountY-(1-newTip.y)); if(pos.y-pos.x*((newTip.y-(1-_AmountY))/newTip.x) > 0 && invert*(pos.y-pos.x*(newTip.y/(newTip.x-(1-_AmountX)))) > 0) texColor = invertTexColor; float2 newHypotenuse = float2((coord.x-_AmountX)/(1-_AmountX), (coord.y-_AmountY)/(1-_AmountY)); clip ((1-newHypotenuse.y)-newHypotenuse.x); return texColor; } ENDCG } } Fallback "Diffuse" }
2014/4/16 22:07 修個小bug,漏掉幾個字
如果有任何想法歡迎提出。
No comments:
Post a Comment