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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章