在說(shuō)之前,先來(lái)說(shuō)說(shuō)涂涂樂(lè)痕钢,涂涂樂(lè)的原理也類(lèi)似于獲取攝像頭的畫(huà)面图柏,并且通過(guò)shader設(shè)置捕捉的畫(huà)面的某一部分為模型的貼圖來(lái)實(shí)現(xiàn)的。
首先是shader部分:
Shader "Custom/CameraTargetPatch" {
Properties {
_MainTex("Texture", 2D) = "white" { }
}
SubShader{
Pass{
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4x4 _MATRIX_MVP;
float _yScale;
float _xScale;
struct v2f {
float4? pos : SV_POSITION;
float2? uv : TEXCOORD0;
};
v2f vert(appdata_base v){
v2f o;
float4 uvTmp;
// calculate new uv in camera image
uvTmp = mul(_MATRIX_MVP, float4(v.texcoord.x-0.5f,v.texcoord.y-0.5f,0,1));
uvTmp.x = uvTmp.x/uvTmp.w;
uvTmp.y = uvTmp.y/uvTmp.w;
uvTmp.z = uvTmp.z/uvTmp.w;
// some swap for different coordinate system
uvTmp.x = (uvTmp.x + 1.0f)/2.0f;
uvTmp.y = (uvTmp.y + 1.0f)/2.0f;
o.uv = uvTmp.xy;
//The position of the vertex should not be frozen, so use
//the standard UNITY_MATRIX_MVP matrix for that.
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
half4 frag(v2f i) : COLOR{
half4 texcol = tex2D(_MainTex, i.uv);
return texcol;
}
ENDCG
}
}
}
然后是代碼部分:
// 設(shè)置模型貼圖
public void SetTexture()? ? {? ? ? ??
// 在ARCamera下新建TextureCamera來(lái)捕捉畫(huà)面任连,參數(shù)要和arcamera保持一直? ? ? ??
cameraObj = new GameObject("TextureCamera");? ? ? ??
cameraObj.transform.SetParent(NewFarmSceneControl.Instance.arCameraTran);? ? ? ??
cameraObj.transform.localPosition = Vector3.zero;? ? ? ??
cameraObj.transform.localRotation = Quaternion.identity;? ? ? ?
?cameraObj.transform.localScale = Vector3.one;? ? ? ??
Camera renderCamera = cameraObj.AddComponent();? ? ? ?
?renderCamera.fieldOfView = NewFarmSceneControl.Instance.ARCamera.fieldOfView;? ? ? ??
renderCamera.clearFlags = CameraClearFlags.SolidColor;? ? ? ??
renderCamera.farClipPlane = 2000.0f;? ? ? ??
renderCamera.nearClipPlane = 0.05f;? ? ? ??
//只開(kāi)啟ARBackground層(這里是為了讓該攝像頭只獲取ARCamra下的Background所拍到的畫(huà)面)? ? ? ??
renderCamera.cullingMask = LayerMask.GetMask("ARBackground");? ? ? ?
?RenderTexture renderTexture = new RenderTexture(Screen.width / 2, Screen.height / 2, 0);? ? ? ?
?renderCamera.targetTexture = renderTexture;? ? ? ??
GetComponentInChildren().material.mainTexture = renderTexture;? ? ? ??
hasSet = true;? ? ? ?
?P = GL.GetGPUProjectionMatrix(renderCamera.projectionMatrix, false);? ? ? ?
?V = renderCamera.worldToCameraMatrix;? ? ? ??
GetComponentInChildren().material.SetFloat("_xScale", 1.0f);? ? ? ??
GetComponentInChildren().material.SetFloat("_yScale", 1.0f);? ? ? ??
if (boxPosTran == null)? ? ? ? {? ? ? ? ? ? boxPosTran = transform.FindChild("BoxPos");? ? ? ? }? ? ? ?
?// 獲取模型的本地到世界的矩陣變換? ? ? ?
?M = boxPosTran.localToWorldMatrix;? ? ? ?
?MVP = P * V * M;? ? ? ??
// 設(shè)置MVP矩陣? ? ? ?
?GetComponentInChildren().material.SetMatrix("_MATRIX_MVP", MVP);
}
上面方法中有個(gè)hasSet布爾值蚤吹,這里設(shè)置為true的目的是為了在Update函數(shù)中實(shí)時(shí)獲取攝像頭的畫(huà)面,保證每幀都渲染相同的貼圖,否則會(huì)出現(xiàn)獲取到貼圖后裁着,攝像頭晃動(dòng)時(shí)模型的貼圖發(fā)生變化繁涂。
所以當(dāng)hasSet為true時(shí),在Update中也需要重新再設(shè)置MVP矩陣
void Update () {? ? ? ??
if (hasSet)? ? ? ? {? ? ? ? ? ?
?P = GL.GetGPUProjectionMatrix(NewFarmSceneControl.Instance.ARCamera.projectionMatrix, false);? ? ? ? ??
?V = NewFarmSceneControl.Instance.ARCamera.worldToCameraMatrix;? ? ? ? ? ?
?GetComponentInChildren().material.SetFloat("_xScale", 1.0f);? ? ? ? ? ??
GetComponentInChildren().material.SetFloat("_yScale", 1.0f);? ? ? ? ? ?
?M = boxPosTran.localToWorldMatrix;? ? ? ? ? ??
MVP = P * V * M;? ? ? ? ? ?
?GetComponentInChildren().material.SetMatrix("_MATRIX_MVP", MVP);
}
}
最終效果如下圖所示
哇哈哈二驰,是不是很酷炫扔罪!
喜歡的話(huà)請(qǐng)點(diǎn)個(gè)贊哦~~