美文网首页
(AR)获取摄像头的画面并将其设置为模型贴图之无敌陀螺大回环之实

(AR)获取摄像头的画面并将其设置为模型贴图之无敌陀螺大回环之实

作者: OneMore2018 | 来源:发表于2017-09-29 11:34 被阅读47次

    在说之前,先来说说涂涂乐,涂涂乐的原理也类似于获取摄像头的画面,并且通过shader设置捕捉的画面的某一部分为模型的贴图来实现的。

    首先是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

    }

    }

    }

    然后是代码部分:

    // 设置模型贴图

    public void SetTexture()    {        

    // 在ARCamera下新建TextureCamera来捕捉画面,参数要和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;        

    //只开启ARBackground层(这里是为了让该摄像头只获取ARCamra下的Background所拍到的画面)        

    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;        

    // 设置MVP矩阵       

     GetComponentInChildren().material.SetMatrix("_MATRIX_MVP", MVP);

    }

    上面方法中有个hasSet布尔值,这里设置为true的目的是为了在Update函数中实时获取摄像头的画面,保证每帧都渲染相同的贴图,否则会出现获取到贴图后,摄像头晃动时模型的贴图发生变化。

    所以当hasSet为true时,在Update中也需要重新再设置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);

    }

    }

    最终效果如下图所示

    效果展示

    哇哈哈,是不是很酷炫!

    喜欢的话请点个赞哦~~

    相关文章

      网友评论

          本文标题:(AR)获取摄像头的画面并将其设置为模型贴图之无敌陀螺大回环之实

          本文链接:https://www.haomeiwen.com/subject/nlxiextx.html