unity3d的斜邊分屏實現

昨天看到蠻牛上有個練手的文章,要求是實現unity斜邊分屏,就是將屏幕分成兩個三角形,分別顯示兩個照相機顯示的內容,有些端遊也出現過,而且網上也好像沒有這樣的例子,覺得有趣,就寫了一個早上,實現了它,先上效果圖:


上面的例子中,兩個照相機對準的是同一個立方體,觸摸右下角的區域則旋轉立方體,觸摸左上角則移動立方體,達到了簡單的分屏控制效果。


簡單說一下步驟:

1,創建兩個照相機,一個作爲主要相機。另外一個輔助相機是需要取得他的targettexture,;

2,在主相機中重寫OnRenderImage方法;

3,創建一個材質,賦予一個shader,然後將此材質通過上述2中的OnRenderImage方法輸出到最終顯示。shader的作用爲使得主相機的texture和輔助相機的targettexture根據需要顯示在屏幕中的兩個區域;

4,根據屏幕分辨率以及鼠標座標,判斷出鼠標處於哪部分區域,執行旋轉或移動。


下面來詳細實現一下以上步驟:

給Main Camera添加一個腳本,腳本代碼如下:

using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour {
    public Camera cam;
    public Material mat;

	// Use this for initialization
	void Start () {
	    
	}
	
	// Update is called once per frame
	void Update () {
	
	}

    void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        if (cam.targetTexture == null)
        {
            cam.targetTexture = new RenderTexture(cam.pixelWidth, cam.pixelHeight, 0); //根據主相機的寬高創建一個同樣寬高的紋理,記錄輔助相機的圖像
        }
        mat.SetTexture("_OtherTex", cam.targetTexture);//傳入輔助相機的紋理,shader中用到,具體見下面的shader代碼
		Graphics.Blit(src, dest, mat);
    }
}

shader代碼如下:

Shader "Custom/Shader" {
	Properties {
		_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}//主相機的紋理
		_OtherTex ("Other Tex", 2D) = "white" {}<span style="white-space:pre">	</span>//輔助相機的紋理
	}


	SubShader {
	Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
	LOD 100
	
	Cull Off<span style="white-space:pre">	</span>
	Blend Off<span style="white-space:pre">	</span>//關閉混合
	Pass {  
		CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata_t {
				float4 vertex : POSITION;
				float2 texcoord : TEXCOORD0;
			};

			struct v2f {
				float4 vertex : SV_POSITION;
				half2 texcoord : TEXCOORD0;
			};

			sampler2D _MainTex;
			sampler2D _OtherTex;
			float4 _MainTex_ST;
			
			v2f vert (appdata_t v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				half2 otherTexcoord = half2(i.texcoord.x, 1 - i.texcoord.y);<span style="white-space:pre">	</span>//本人也不清楚爲什麼外面傳進來的rendertexture的紋理座標的y會相反,所以自己動手用1來減去
				fixed4 col = tex2D(_MainTex, i.texcoord)*ceil(i.texcoord.x + i.texcoord.y - 1) + tex2D(_OtherTex, otherTexcoord)*ceil(1 - i.texcoord.x - i.texcoord.y);

				return col;
			}
		ENDCG
	}
}
	FallBack "Diffuse"
}
上面的shader的核心代碼
fixed4 col = tex2D(_MainTex, i.texcoord)*ceil(i.texcoord.x + i.texcoord.y - 1) + tex2D(_OtherTex, otherTexcoord)*ceil(1 - i.texcoord.x - i.texcoord.y);
以上代碼分爲兩部分,其實本質是依靠y = -x + 1這個公式來實現,需要點高中數學知識


經過上面兩部,圖形就已經爲最終效果了,下面來實現分屏控制:

工程裏創建一個空對象ControlObj(上圖中有),給它添加代碼,代碼如下:

using UnityEngine;
using System.Collections;

public class Control : MonoBehaviour {
    public Transform obj;
	// Use this for initialization
    Vector2 mousePos;
    float screenWidth = Screen.width;
    float screenHeight = Screen.height;
	void Start () {
	    
	}
	
	// Update is called once per frame
	void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            mousePos = Input.mousePosition;
            //Debug.Log("按下左鍵" + mousePos);
        }

        if (Input.GetMouseButton(0))
        {
            Debug.Log("移動左鍵");
            //按照區域判斷是移動還是旋轉
            float x = mousePos.x / screenWidth;
            float y = mousePos.y / screenHeight;
            if (y < x) updateObjRotation(); 
            else updateObjPosition();
        }
        
        if (Input.GetMouseButtonUp(0))
        {
            Debug.Log("鬆開左鍵");
        }
	}

    void updateObjRotation()
    {
        Debug.Log("更新物體旋轉");
        obj.rotation = Quaternion.AngleAxis(1, Vector3.up) * obj.rotation;
    }

    void updateObjPosition()
    {   
        Debug.Log("更新物體位置");
        obj.position = new Vector3(obj.position.x + 0.03f, obj.position.y, obj.position.z);
    }
}

核心代碼爲:

<span style="white-space:pre">	</span>    //按照區域判斷是移動還是旋轉
            float x = mousePos.x / screenWidth;
            float y = mousePos.y / screenHeight;
            if (y < x) updateObjRotation(); 
            else updateObjPosition();
這是使用了y = x這個公式;

由此大功告成

發佈了39 篇原創文章 · 獲贊 17 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章