美文网首页
EaayAR2.1/Vuforia涂涂乐2,长方形

EaayAR2.1/Vuforia涂涂乐2,长方形

作者: 萧非子 | 来源:发表于2017-11-24 15:54 被阅读49次

    //截图赋值,移走图片,涂色还在,长方形识别图,UV是正方形
    //模型使用shander-ScanTex
    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    //加入UI命名空间
    //扫描识别,脚本挂载在PlaneA上,planeA为ImageTarget子物体,大小一样,为长方形,纹理为Vuforia上传的长方形纹理,
    public class Scanning_PlaneA : MonoBehaviour {
    public GameObject Img_Scan;
    //储存识别框图片
    public GameObject Img_Sucess;
    //储存识别成功图片
    //public GameObject Model1;
    //储存地球模型
    //public GameObject Model2;
    //储存地球框架模型
    public GameObject PlaneB;
    //储存面板B
    public Material Green_Mate;
    //申请材质变量储存绿色的材质
    public Material Red_Mate;
    //申请材质变量储存红色材质
    public Material Tran_Mate;
    //申请材质变量储存透明材质

    private bool HasRe=false;
    //申请布尔变量来确定是否已经识别
    private CanvasScaler CanS;
    //申请变量储存UI屏幕自适度的缩放组件
    
    private float X_Sc;
    //申请浮点型类型的变量储存实际的缩放比例
    
    //记录扫描框的范围
    private Vector2 TopLeft_UI;
    //记录扫描框左上角的坐标
    //“private”申请类型为私有
    private Vector2 BottomLeft_UI;
    //记录扫描框左下角的坐标
    private Vector2 TopRight_UI;
    //记录扫描框右上角的坐标
    private Vector2 BottomRight_UI;
    //记录扫描框右下角的坐标
    
    //记录面片的世界坐标
    private Vector3 TopLeft_Pl_W;
    //记录面片左上角的世界坐标
    private Vector3 BottomLeft_Pl_W;
    //记录面片左下角的世界坐标
    private Vector3 TopRight_Pl_W;
    //记录面片右上角的世界坐标
    private Vector3 BottomRight_Pl_W;
    //记录面片右下角的世界坐标
    
    //记录面片的屏幕坐标
    private Vector2 TopLeft_Pl_Sc;
    //记录面片左上角的屏幕坐标
    private Vector2 BottomLeft_Pl_Sc;
    //记录面片坐下角的屏幕坐标
    private Vector2 TopRight_Pl_Sc;
    //记录面片右上角的屏幕坐标
    private Vector2 BottomRight_Pl_Sc;
    //记录面片右下角的屏幕坐标
    
    private Vector2 PlaneWH;
    //记录面片的宽高
    //面片为ImageTarget的子物体,大小和ImageTarget一样大,面片的纹理和ImageTarget一样。
    public float ImageTargetScale;
    //父级目标识别ImageTarget缩放系数
    public float PlaneScale;
    //Plane缩放系数
    
    //脚本刚开始运行的时候调用一次
    void Start () {
        
        CanS = GameObject.Find ("Canvas").gameObject.GetComponent<CanvasScaler> ();
        //获取控制屏幕自适度的组件
    
        X_Sc = Screen.width / CanS.referenceResolution.x;
        //获取实际的缩放比例
    }
    
    //每一帧都调用
    void Update () {
    
        //计算了扫描框四个点的坐标位置,“*X_Sc"是屏幕自适度的缩放比例,这样才能获取真正运行时UI图片的宽高
        TopLeft_UI = new Vector2 (Screen.width-400*X_Sc,Screen.height+300*X_Sc)*0.5f;
        //给扫描框左上角的坐标赋值
        //"Screen.width-400,Screen.height+300" 屏幕的宽度减去扫描框的宽度,屏幕的高度减去扫描框的高度
        BottomLeft_UI=new Vector2(Screen.width-400*X_Sc,Screen.height-300*X_Sc)*0.5f;
        //给扫描框左下角的坐标赋值
        TopRight_UI=new Vector2(Screen.width+400*X_Sc,Screen.height+300*X_Sc)*0.5f;
        //给扫描框右上角的坐标赋值
        BottomRight_UI=new Vector2(Screen.width+400*X_Sc,Screen.height-300*X_Sc)*0.5f;
        //给扫描框右下角的坐标赋值
    
        //PlaneWH = new Vector2 (gameObject.GetComponent<MeshFilter>().mesh.bounds.size.x*1*0.1f,gameObject.GetComponent<MeshFilter>().mesh.bounds.size.z*1*0.064f)*0.5f;
        PlaneWH = new Vector2(gameObject.GetComponent<MeshFilter>().mesh.bounds.size.x * ImageTargetScale * PlaneScale, gameObject.GetComponent<MeshFilter>().mesh.bounds.size.z * ImageTargetScale * PlaneScale) * 0.5f;
    
        //获取面片的宽高的一半
        //"gameObject.GetComponent<MeshFilter>().mesh.bounds.size.x"获取面片X方向的宽度
        //"*5"是因为开始获取到的长宽是模型本身的长宽,而场景中我们有缩放因素,父级物体(ImageTarget)放大了1f倍,自身缩小到了0.1,因此获取实际宽高需要再乘以0.5
    
        //获取面片四个点的世界坐标
        TopLeft_Pl_W = gameObject.transform.parent.position + new Vector3 (-PlaneWH.x,0,PlaneWH.y);
        //获取面片左上角的世界坐标
        //"gameObject.transform.parent.position"物体的父级物体的世界坐标
        //"new Vector2 (-PlaneWH.x,PlaneWH.y)"向左上方偏移的量
        BottomLeft_Pl_W = gameObject.transform.parent.position + new Vector3 (-PlaneWH.x,0,-PlaneWH.y);
        //获取面片左下角的世界坐标
        TopRight_Pl_W = gameObject.transform.parent.position + new Vector3 (PlaneWH.x,0,PlaneWH.y);
        //获取面片右上角的世界坐标
        BottomRight_Pl_W = gameObject.transform.parent.position + new Vector3 (PlaneWH.x,0,-PlaneWH.y);
        //获取面片右下角的世界坐标
    
    
        //获取面片的屏幕坐标
        TopLeft_Pl_Sc=Camera.main.WorldToScreenPoint(TopLeft_Pl_W);
        //获取面片左上角的屏幕坐标
        //Camera.main.WorldToScreenPoint(Vector3()); 将世界坐标转化为屏幕坐标
        BottomLeft_Pl_Sc=Camera.main.WorldToScreenPoint(BottomLeft_Pl_W );
        //获取面片左下角的屏幕坐标
        TopRight_Pl_Sc=Camera.main.WorldToScreenPoint(TopRight_Pl_W);
        //获取面片右上角的屏幕坐标
        BottomRight_Pl_Sc=Camera.main.WorldToScreenPoint(BottomRight_Pl_W );
        //获取面片右下角的屏幕坐标
    
        //判断面片是否在扫描框范围内
        if(TopLeft_Pl_Sc.x>TopLeft_UI.x&&TopLeft_Pl_Sc.y<TopLeft_UI.y&&BottomLeft_Pl_Sc.x>BottomLeft_UI.x&&BottomLeft_Pl_Sc.y>BottomLeft_UI.y&&TopRight_Pl_Sc.x<TopRight_UI.x&&TopRight_Pl_Sc.y<TopLeft_UI.y&&BottomRight_Pl_Sc.x<BottomRight_UI.x&&BottomRight_Pl_Sc.y>BottomRight_UI.y){
        //当面片完全处于扫描框范围内时 执行以下代码
            if(HasRe==false){
            //如果尚未识别
               gameObject.GetComponent<Renderer>().material=Green_Mate;
               //将脚本所附着的物体(面片)的材质变为绿色材质
               StartCoroutine("SuccessUI");
               //调用显示识别成功图片的延迟函数
               StartCoroutine("ScreenShot");
               //调用截图的延迟函数
               HasRe=true;
               //已经识别
            }
            
        }else{
        //当面片并非完全处于扫描框范围内时  执行以下代码
            gameObject.GetComponent<Renderer>().material=Red_Mate;
            //将脚本所附着的物体(面片)的材质变为红色材质
            HasRe=false;
            //识别状态设置为未识别
        }   
    }
    
    //显示识别成功图片的延迟函数
    IEnumerator SuccessUI (){
        yield return new WaitForSeconds (0.5f);
        //延迟0.5秒
        Img_Sucess.SetActive(true);
        //激活提示识别成功的图片
        gameObject.GetComponent<Renderer>().material=Tran_Mate;
        //给面片材质赋值为透明材质,除去截图时的影响
        Img_Scan.SetActive(false);
        //扫描框取消
    }
    
    //截图的延迟函数
    IEnumerator ScreenShot(){
        yield return new WaitForSeconds (2.0f);
        //延迟2秒
        if(HasRe==true){
        //当处于识别状态的时候才执行截图函数
        gameObject.GetComponent<Renderer>().material=Tran_Mate;
            //给面片材质赋值为透明材质,除去截图时的影响
            ////Earth.SetActive(true);
            //////地球模型显示出来
            ////EarthFrame.SetActive(true);
            //////地球模型框架显示出来
            //Earth.GetComponent<ScreenShot>().ScreenShot_Button();
            //调用地球模型上截图脚本的截图函数
            PlaneB.GetComponent<ScreenShot_PlaneB>().ScreenShot_Button();
    
        }
    }
    

    }
    ///////////////////////////////////////////////////////////////////////////////////
    using UnityEngine;
    using System.Collections;
    //屏幕截图,脚本挂载在PlaneB上,PlaneB,为ImageTarget子物体,为正方形,长与ImageTarget一样,纹理为3D模型(正方形)UV纹理,正方形=长方形+空白
    public class ScreenShot_PlaneB : MonoBehaviour {
    public GameObject Model1;
    //申请公有变量储存要赋予贴图的模型
    //public GameObject Model2;
    //储存地球仪配件模型
    public GameObject PlaneA;
    //储存面片A,ImageTarget的子物体平面,和ImageTarget一样大小,识别时,显示红色,识别成功后,显示绿色
    public GameObject PlaneB;
    //储存面片B,ImageTarget的子物体平面,和ImageTarget一样的长,为正方形,和ImageTarget一样的(长方形)纹理贴图,
    //屏幕截图,从他身上截图和Image一样的长方形纹理,正方形内(长方形以外部分为空)

    private int ScreenWidth;
    //申请私有int型变量 记录屏幕的宽
    private int ScreenHeight;
    //申请私有int型变量 记录屏幕的高
    private Texture2D TextureShot;
    //申请Texture2D型变量 用来储存屏幕截图
    
    private Vector2 PlaneWH;
    //记录面片A的宽高
    
    //记录面片的世界坐标
    private Vector3 TopLeft_Pl_W;
    //记录面片左上角的世界坐标
    private Vector3 BottomLeft_Pl_W;
    //记录面片左下角的世界坐标
    private Vector3 TopRight_Pl_W;
    //记录面片右上角的世界坐标
    private Vector3 BottomRight_Pl_W;
    //记录面片右下角的世界坐标
    
    public float ImageTargetScale;
    //父级目标识别ImageTarget缩放系数
    public float PlaneScale;
    //Plane缩放系数
    
    void Start () {
        ScreenWidth = Screen.width;
        //获取屏幕的宽
        ScreenHeight=Screen.height;
        //获取屏幕的高
    
        TextureShot = new Texture2D (ScreenWidth,ScreenHeight,TextureFormat.RGB24,false);
        // 标准格式 : Texture2D(int width,int height,TextureFormat format,bool mipmap);
        // “int width,int height,” 纹理的宽高
        //"TextureFormat format" 纹理的模式 RGB24 RGBA32等模式 
        //"bool mipmap"mipmap是一种分级纹理  在屏幕中显示大小不同时候给予不同级别的纹理 这里不使用
    
        Model1.GetComponent<Renderer>().enabled = false;
       // Model2.GetComponent<Renderer>().enabled = false;
        //隐藏模型
        //??透明脚本不管用??
    
    
    }
    //截图函数
    public void ScreenShot_Button(){
    
        PlaneWH = new Vector2 (PlaneB.GetComponent<MeshFilter>().mesh.bounds.size.x* ImageTargetScale * PlaneScale, PlaneB.GetComponent<MeshFilter>().mesh.bounds.size.z* ImageTargetScale * PlaneScale) *0.5f;
        //获取面片的宽高的一半;*0.5;
        //"gameObject.GetComponent<MeshFilter>().mesh.bounds.size.x"获取面片X方向的宽度
        //"*M*N"是因为开始获取到的长宽是模型本身的长宽,而场景中我们有缩放因素,父级物体(ImageTarget)放大了n倍,自身缩小到了m,因此获取实际宽高需要再乘以m*n
    
        //获取面片四个点的世界坐标
        TopLeft_Pl_W = PlaneB.transform.parent.position + new Vector3 (-PlaneWH.x,0,PlaneWH.y);
        //获取面片左上角的世界坐标
        //"gameObject.transform.parent.position"物体的父级物体的世界坐标
        //"new Vector2 (-PlaneWH.x,PlaneWH.y)"向左上方偏移的量
        BottomLeft_Pl_W = PlaneB.transform.parent.position + new Vector3 (-PlaneWH.x,0,-PlaneWH.y);
        //获取面片左下角的世界坐标
        TopRight_Pl_W = PlaneB.transform.parent.position + new Vector3 (PlaneWH.x,0,PlaneWH.y);
        //获取面片右上角的世界坐标
        BottomRight_Pl_W = PlaneB.transform.parent.position + new Vector3 (PlaneWH.x,0,-PlaneWH.y);
        //获取面片右下角的世界坐标
    
        //将截图时识别图四个角的世界坐标信息传递给Shader
        Model1.GetComponent<Renderer>().material.SetVector("_Uvpoint1",new Vector4(TopLeft_Pl_W.x,TopLeft_Pl_W.y,TopLeft_Pl_W.z,1f));
        //将左上角的世界坐标传递给Shader ,其中1f是否了凑齐四位浮点数 ,用来进行后续的矩阵变换操作
        Model1.GetComponent<Renderer>().material.SetVector("_Uvpoint2",new Vector4(BottomLeft_Pl_W.x,BottomLeft_Pl_W.y,BottomLeft_Pl_W.z,1f));
        Model1.GetComponent<Renderer>().material.SetVector("_Uvpoint3",new Vector4(TopRight_Pl_W.x,TopRight_Pl_W.y,TopRight_Pl_W.z,1f));
        Model1.GetComponent<Renderer>().material.SetVector("_Uvpoint4",new Vector4(BottomRight_Pl_W.x,BottomRight_Pl_W.y,BottomRight_Pl_W.z,1f));
    
        //将截图时识别图四个角的世界坐标信息传递给Shader
        //Model2.GetComponent<Renderer>().material.SetVector("_Uvpoint1",new Vector4(TopLeft_Pl_W.x,TopLeft_Pl_W.y,TopLeft_Pl_W.z,1f));
        //将左上角的世界坐标传递给Shader ,其中1f是否了凑齐四位浮点数 ,用来进行后续的矩阵变换操作
        //Model2.GetComponent<Renderer>().material.SetVector("_Uvpoint2",new Vector4(BottomLeft_Pl_W.x,BottomLeft_Pl_W.y,BottomLeft_Pl_W.z,1f));
        //Model2.GetComponent<Renderer>().material.SetVector("_Uvpoint3",new Vector4(TopRight_Pl_W.x,TopRight_Pl_W.y,TopRight_Pl_W.z,1f));
        //Model2.GetComponent<Renderer>().material.SetVector("_Uvpoint4",new Vector4(BottomRight_Pl_W.x,BottomRight_Pl_W.y,BottomRight_Pl_W.z,1f));
    
        Matrix4x4 P = GL.GetGPUProjectionMatrix (Camera.main.projectionMatrix,false);
        //获取截图时GPU的投影矩阵
        Matrix4x4 V=Camera.main.worldToCameraMatrix;
        //获取截图时世界坐标到相机的矩阵
        Matrix4x4 VP=P*V;
        //储存两个矩阵的乘积
        Model1.GetComponent<Renderer>().material.SetMatrix("_VP",VP);
        //将截图时的矩阵转换信息传递给Shader
        //Model2.GetComponent<Renderer>().material.SetMatrix("_VP",VP);
        //将截图时的矩阵转换信息传递给Shader
    
        TextureShot.ReadPixels (new Rect(0,0,ScreenWidth,ScreenHeight),0,0);
        //获取屏幕的像素信息 
        //第一个"0,0"获取屏幕像素的起始点
        //“ScreenWidth,ScreenHeight”获取屏幕像素的范围
        //第二个“0,0” 填充texture2D时填充的坐标
    
        TextureShot.Apply ();
        //确认之前对Texture2D进行的修改
    
        Model1.GetComponent<Renderer>().enabled = true;
        //Model2.GetComponent<Renderer>().enabled = true;
        //显示模型
    
        Model1.GetComponent<Renderer> ().material.mainTexture = TextureShot;
        //获取Earth的渲染组件中的材质的主纹理,并将Texture2D赋值给这个主纹理
        //Model2.GetComponent<Renderer> ().material.mainTexture = TextureShot;
        //获取Earth的渲染组件中的材质的主纹理,并将Texture2D赋值给这个主纹理
    
        PlaneA.SetActive (false);
        PlaneB.SetActive (false);
        //取消面片的激活状态
    
    }
    

    }
    ///////////////////////////////////////////////////////////////
    // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,)' with 'UnityObjectToClipPos()'

    Shader "Texture/ScanTex" {
    //Shader的路径和名称
    Properties {
    //材质属性面板中所显示的Shader属性面板
    _MainTex ("Base (RGB)", 2D) = "white" {}
    //"_MainTex"在Shader中调用时所使用的名称
    //"Base (RGB)"在面板中显示的名称
    //"2D"2D纹理
    //"white"给这个属性的默认值

        //从C#中获取截图时 识别图四个点世界坐标
        _Uvpoint1("point1", Vector) = (0 , 0 , 0 , 0)
        //"_Uvpoint1"在Shader中调用时所使用的名称
        //"point1"在面板中所显示的名称
        //Vector 四个浮点数组成的类型 
        //"0 , 0 , 0 , 0"附的初始值
        _Uvpoint2("point2", Vector) = (0 , 0 , 0 , 0)
        _Uvpoint3("point3", Vector) = (0 , 0 , 0 , 0)
        _Uvpoint4("point4", Vector) = (0 , 0 , 0 , 0)
    
    }
    
    //“ SubShader”着色器方案 在Shader中至少有一个SubShader 显卡每次只选择一个SubShader 如果当前硬件不支持这个SubShader 就会选择一个针对较旧的硬件的SubShader
    SubShader {
        Tags { "Queue"="Transparent" "RenderType"="Transparent" }
        //加入透明渲染处理,没有这一段的话赋值透明贴图时就会出现问题。
        LOD 200
        //细致程度   Level of Details 也叫作 Level of Development
        //"200"是一个代号 限制Shader的级别到200为止
    
        Pass{
            Blend SrcAlpha OneMinusSrcAlpha
            //加入Alpha的混合渲染  不加的话Alpha值无用
            CGPROGRAM
            //CG开始的关键词
            #pragma vertex vert
            //编译指令 顶点程序
            #pragma fragment frag
            //编译指令 片段程序
            #include "UnityCG.cginc"
            //"UnityCG.cginc" 是使用unity中带的封装好的cg代码集合
            //有点类似于C#中命名空间的引用
    
            //C#中传递来的值的引用
            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _Uvpoint1;
            float4 _Uvpoint2;
            float4 _Uvpoint3;
            float4 _Uvpoint4;
            float4x4 _VP;
            //C#在截取图像时 世界坐标到摄像机坐标以及相机坐标到屏幕坐标的两个矩阵值相乘
    
            //结构体 
            struct v2f {
                float4  pos : SV_POSITION;
                float2  uv : TEXCOORD0;
                float4  fixedPos : TEXCOORD2;
            } ;
    
            //顶点程序和片段程序中用来计算UV的匹配和最护模型效果的渲染
            v2f vert (appdata_base v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
                
                float4 top = lerp(_Uvpoint1, _Uvpoint3, o.uv.x);
                float4 bottom = lerp(_Uvpoint2, _Uvpoint4, o.uv.x);
                float4 fixedPos = lerp(bottom, top, o.uv.y);
                o.fixedPos = ComputeScreenPos(mul(UNITY_MATRIX_VP, fixedPos));
                return o;
            }
            float4 frag (v2f i) : COLOR
            {
                
                float4 top = lerp(_Uvpoint1, _Uvpoint3, i.uv.x);
                float4 bottom = lerp(_Uvpoint2, _Uvpoint4, i.uv.x);
                float4 fixedPos = lerp(bottom, top, i.uv.y);
                fixedPos = ComputeScreenPos(mul(_VP, fixedPos));
                return tex2D(_MainTex, fixedPos.xy / fixedPos.w);
                
            }
            ENDCG
            //CG结束的关键词
        }
    }
    //FallBack "Diffuse"
    

    }

    相关文章

      网友评论

          本文标题:EaayAR2.1/Vuforia涂涂乐2,长方形

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