美文网首页AR/VR/MR
AR开发实战Vuforia项目之太阳系八大行星(实现涂涂乐功能)

AR开发实战Vuforia项目之太阳系八大行星(实现涂涂乐功能)

作者: TonyWan_AR | 来源:发表于2017-12-12 21:16 被阅读774次

    一、框架视图

    二、主要代码

    Shader "Color/Special" (传说会写shader是大神)

    Shader "Color/Special" {
    //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 = mul(UNITY_MATRIX_MVP,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"
    }
    

    AudioPlay

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class AudioPlay : MonoBehaviour {
    
        //定义一条射线的类型;
        private Ray ray;
    
        //定义一个射线碰撞信息的存贮;
        private RaycastHit hit;//类型: 射线检测碰撞(信息存贮)
    
        //播放地球的声音
        //private AudioSource mAudioSource;
        //public AudioSource earthAudioSource;
        //public AudioSource sunAudioSource;
    
        //将所有便签放进去
        public AudioSource[] mAudioSource;
        //贮存名称;
        //string strName;
    
        //贮存便签
        int intTag;
    
        //贮存太阳系的,太阳系消失,所有配音不播放;
       // public GameObject SolarSystem;
        void Start () {
            
        }
        
    
        void Update () {
            //执行射线的方法;
            CameraSendRay();
            //判断太阳系隐藏,所有声音都停止;
            //if (SolarSystem.activeInHierarchy==false)
            //{
            //    sunAudioSource.Stop();
            //    earthAudioSource.Stop();
            //}
        }
        //----------------------------------------------------------------
        /// <summary>
        ///执行播放声音的方法; 
        /// </summary>
        //void CameraSendRay() //第一种方法
        //{
        //    if (Input.GetMouseButtonDown(0)) //点击屏幕
        //    {
        //        ray = Camera.main.ScreenPointToRay(Input.mousePosition); //射线的位置就是鼠标点击的位置
        //        if (Physics.Raycast(ray, out hit))  //获取射线碰撞信息
        //        {
        //            strName = hit.transform.name;
        //            Debug.Log(strName);
        //            switch (strName) //分别播放不同声音的信息
        //            {
        //                case "Earth_A":
        //                    if (sunAudioSource.isPlaying)
        //                    {
        //                        sunAudioSource.Stop();
        //                    }
        //                    earthAudioSource.Play();
        //                    break;
        //                case "Sun_Modle":
        //                    if (earthAudioSource.isPlaying)
        //                    {
        //                        earthAudioSource.Stop();
        //                    }
        //                    sunAudioSource.Play();
        //                    break;
        //                default:
        //                    break;
        //            }
        //        }
        //    }
        //}
        //----------------------------------------------------------------
    
        /// <summary>
        ///执行播放声音的方法; 
        /// </summary>
        void CameraSendRay() //第二种方法
        {
            if (Input.GetMouseButtonDown(0)) //点击屏幕
            {
                ray = Camera.main.ScreenPointToRay(Input.mousePosition); //射线的位置就是鼠标点击的位置
                if (Physics.Raycast(ray, out hit))  //获取射线碰撞信息
                {
                   intTag =int.Parse(hit.transform.tag);
                    //Debug.Log(intTag);
                    //mAudioSource[intTag].Play();
                    for (int i = 0; i < mAudioSource.Length; i++)
                    {
                        if (mAudioSource[i].isPlaying && i != intTag)
                        {
                            mAudioSource[i].Stop();
                        }
                        else
                        {
                            mAudioSource[intTag].Play();
                        }
                    }
                }
            }
        }
    
    
        /// <summary>
        /// 停止所有播放音乐的方法 第一种方法
        /// </summary>
        //public void StopAudioPlay() {
        //    sunAudioSource.Stop();
        //    earthAudioSource.Stop();
        //}
    
        /// <summary>
        /// 停止所有播放音乐的方法 第二种方法
        /// </summary>
        public void StopAudioPlay()
        {
            for (int i = 0; i < mAudioSource.Length; i++)
            {
                    mAudioSource[i].Stop();
            }
        }
    
    
    
    }
    
    

    EarthInSunA

    using UnityEngine;
    using System.Collections;
    
    public class EarthInSunA : MonoBehaviour
    {
    
        public GameObject Earth;
        //保存地球
        public GameObject SolarSystem;
        //保存太阳系
    
        //地球显示的标志位
        private bool isShow = false; 
    
        // Use this for initialization
        void Start()
        {
            //赋值给声效
            //mAudioSource = gameObject.transform.GetComponent<AudioSource>();
        }
    
        // Update is called once per frame
        void Update()
        {
         
        }
    
        void OnMouseDown()
        {
            if (isShow)
            {
                //Earth.GetComponent<Renderer>().enabled = true;
                Earth.SetActive(true);
                //激活地球渲染组件
                Earth.GetComponent<ScreenShot>().EarthFrame.SetActive(true);
                //通过截图脚本中地球仪配件的变量 来激活地球仪配件的显示
                //Earth.GetComponent<EarthTouchA>().SetState = 0;
                Earth.GetComponent<EarthTouchA>().SetState = 0;
                //将点击交互的状态设置为0
                GameObject.Find("Sun").SendMessage("StopAudioPlay");
               // Debug.Log("有没有发送方法------------------");
                SolarSystem.SetActive(false);
                //取消太阳系的显示
            }
            isShow = !isShow;
        }
    
        
    }
    
    
    

    EarthTouchA

    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI; //引用命名空间
    
    public class EarthTouchA : MonoBehaviour
    {
    
        public GameObject EarthFrame;
        //储存地球仪配件
    
        public GameObject SolarSystem;
        //储存太阳系模块
    
        public int SetState = 0;
        //申请Int型变量来储存点击的次数
    
        //public Image UIArea;
        //扫描框隐藏
    
        void Start()
        {
    
        }
    
    
        void Update()
        {
           // if (SetState==1||SetState==2)
            if (SetState == 1 || SetState == 2)
            {
                //当第一次点击状态或第二次点击状态时
                transform.Rotate(0, 25 * Time.deltaTime, 0, Space.Self);
                //让地球沿着自身Y轴转动
            }
        }
    
        //点击函数
        void OnMouseDown()
        {
            //if(SetState==0)
            if (SetState == 0)
            {
               // SetState = 1;
                //设置为状态1
                // gameObject.SetActive(true);
               // UIArea.enabled = false;
    
            }
            else if (SetState == 1)
                //else if(SetState==1)
            {
                //SetState = 2;
                //状态设置为2
               // gameObject.SetActive(true);
                EarthFrame.SetActive(false);
                //取消地球仪配件
    
            }
            else if (SetState == 2)
                //else if(SetState==2)
            {
               // SetState = 3;
                //状态设置为3
                //gameObject.GetComponent<Renderer>().enabled = false;
                gameObject.SetActive(false);
                //取消地球的显示,此处仅仅是渲染方式上不渲染,而不取消模型的激活状态
                SolarSystem.SetActive(true);
                //显示太阳系
            }
            //else if (SetState == 13)
            //{
            //    // SetState = 0;
            //    SetState = -1;
            //    //状态设置为0
            //    // gameObject.GetComponent<Renderer>().enabled = true;
            //    gameObject.SetActive(true);
            //    //显示地球
            //    EarthFrame.SetActive(true);
            //    //显示地球仪配件
            //    SolarSystem.SetActive(false);
            //    //取消太阳系的显示
            //}
            SetState++;
        }
    
        /// <summary>
        /// 通过发送方法调用次函数,不过已经禁用了,没成功
        /// </summary>
        public void ResetAgain() {
            SetState = 0;
            //状态设置为0
            // gameObject.GetComponent<Renderer>().enabled = true;
            gameObject.SetActive(true);
            //显示地球
            EarthFrame.SetActive(true);
            //显示地球仪配件
            SolarSystem.SetActive(false);
    
        }
    
    
    }
    
    
    

    PageNotFound //脱卡

    using UnityEngine;
    using Vuforia;
    public class PageNotFound : MonoBehaviour, ITrackableEventHandler
    {
        //引用
        private TrackableBehaviour mTrackableBehaviour;
        public Transform Target;//识别物
        Vector3 imgPos = new Vector3(0, 0, 0);//识别图上的位置
        Vector3 camPos = new Vector3(0, -3f, 100f);//脱卡后在屏幕中的位置
                                                    //这俩值,具体多少得自己调,模型尺寸、重心不同
    
        bool isFirstTime = true; //第一查找
    
        public GameObject sun;
        //控制太阳大小
        void Start()
        {
            mTrackableBehaviour = GetComponent<TrackableBehaviour>();
            if (mTrackableBehaviour)
            {
                //重置
                mTrackableBehaviour.RegisterTrackableEventHandler(this);
            }
            // Target.GetComponent<MeshRenderer>().enabled = false;//起始时不显示
            Target.gameObject.SetActive(false);
    
        }
    
    
        //接口实现 公开的
        public void OnTrackableStateChanged(
                TrackableBehaviour.Status previousStatus,
                TrackableBehaviour.Status newStatus)
        {
            if (newStatus == TrackableBehaviour.Status.DETECTED ||
                    newStatus == TrackableBehaviour.Status.TRACKED ||
                    newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
            {
                //视野内发现识别图时
                //Target.GetComponent<MeshRenderer>().enabled = true;
                Target.gameObject.SetActive(true);
                Target.parent = this.transform;
                Target.localPosition = imgPos;
                Target.localRotation = Quaternion.identity;
                //Target.localRotation = Quaternion.Euler(90, 0, 0);
                isFirstTime = false;
            }
            else
            {
                //视野内没有识别图时,这里我是把位置和旋转都归零了,如果不做处理,可以
                if (!isFirstTime)
                {
                    // Target.parent = Camera.main.transform;
                    Target.parent = GameObject.FindGameObjectWithTag("MainCamera").transform;
                    Target.localPosition = camPos;
                    //Target.localRotation = Quaternion.identity;
                    Target.localRotation = Quaternion.Euler(-30, 0, 0);
                    //Debug.Log("3333333333333");
    
                    //控制太阳大小
                    sun.GetComponent<ParticleScaler>().particleScale = 1f;
                }
            }
        }
    }
    
    

    Sun_Rotate

    using UnityEngine;
    using System.Collections;
    
    public class Sun_Rotate : MonoBehaviour {
    
        public float speed=8.0f;
    
        // Use this for initialization
        void Start () {
        
        }
        
        // Update is called once per frame
        void Update () {
            transform.Rotate(0,speed*Time.deltaTime,0,Space.Self );
        }
    }
    
    

    Area

    //命名空间
    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    //加入UI命名空间
    
    public class Area : MonoBehaviour
    {
        //"Area"类名 ,需要和外部脚本名称保持一致
        public GameObject SuccessPlane_Image;
        //储存识别成功图片
        public GameObject Scan_Image;
        //将用于隐藏扫描框
        public GameObject Earth;
        //储存地球模型
        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;
        //记录面片的宽高
    
    
        //脚本刚开始运行的时候调用一次
        void Start()
        {
    
            CanS = GameObject.Find("Canvas").gameObject.GetComponent<CanvasScaler>();
            //获取控制屏幕自适度的组件
    
            X_Sc = Screen.width / CanS.referenceResolution.x;
            //获取实际的缩放比例
    
            //计算了扫描框四个点的坐标位置,“*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 * 50 * 0.1f, gameObject.GetComponent<MeshFilter>().mesh.bounds.size.z * 50 * 0.0646f) * 0.5f;
            //获取面片的宽高的一半
            //"gameObject.GetComponent<MeshFilter>().mesh.bounds.size.x"获取面片X方向的宽度
            //"*5"是因为开始获取到的长宽是模型本身的长宽,而场景中我们有缩放因素,父级物体放大了50倍,自身缩小到了0.1,因此获取实际宽高需要再乘以5
        }
    
        //每一帧都调用
        void Update()
        {      
            //获取面片四个点的世界坐标
            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秒
            SuccessPlane_Image.SetActive(true);
            //激活提示识别成功的图片
            gameObject.GetComponent<Renderer>().material = Tran_Mate;
            //给面片材质赋值为透明材质,出去截图时的影响
            Scan_Image.SetActive(false);
            //识别成功后隐藏扫描框;
        }
    
        //截图的延迟函数
        IEnumerator ScreenShot()
        {
            yield return new WaitForSeconds(2.0f);
            //延迟2秒
            if (HasRe == true)
            {
                //当处于识别状态的时候才执行截图函数
                gameObject.GetComponent<Renderer>().material = Tran_Mate;
                //给面片材质赋值为透明材质,出去截图时的影响
                Earth.GetComponent<ScreenShot>().ScreenShot_Button();
                //调用地球模型上截图脚本的截图函数
            }
        }
    }
    
    

    ResetExitUI

    using UnityEngine;
    using System.Collections;
    
    public class ResetExitUI : MonoBehaviour {
    
        // Use this for initialization
        void Start () {
        
        }
        
        // Update is called once per frame
        void Update () {
        
        }
    
        /// <summary>
        /// 退出游戏的方法
        /// </summary>
        public void QuitUI(){
            //点击退出按钮 退出页面
            Application.Quit ();
            //退出app
        }
    
        /// <summary>
        /// 重置游戏方法
        /// </summary>
        public void ResetUI() {
            GameObject.Find("Earth_A").SendMessage("OnMouseDown");
        }
    }
    
    

    ScreenShot

    using UnityEngine;
    using System.Collections;
    
    public class ScreenShot : MonoBehaviour
    {
        public GameObject Earth;
        //申请公有变量储存要赋予贴图的模型
        public GameObject EarthFrame;
        //储存地球仪配件模型
        public GameObject EarthA;
        //储存太阳系中的地球
        //地球公开的引用
        public GameObject PlaneA;
        public GameObject PlaneB;
        //储存面片B
    
        private int ScreenWidth;
        //申请私有int型变量 记录屏幕的宽
        private int ScreenHeight;
        //申请私有int型变量 记录屏幕的高
        private Texture2D TextureShot;
        //申请Texture2D型变量 用来储存屏幕截图
    
        private Vector2 PlaneWH;
        //记录面片的宽高
    
        //记录面片的世界坐标
        private Vector3 TopLeft_Pl_W;
        //记录面片左上角的世界坐标
        private Vector3 BottomLeft_Pl_W;
        //记录面片左下角的世界坐标
        private Vector3 TopRight_Pl_W;
        //记录面片右上角的世界坐标
        private Vector3 BottomRight_Pl_W;
        //记录面片右下角的世界坐标
    
        // Use this for initialization
        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是一种分级纹理  在屏幕中显示大小不同时候给予不同级别的纹理 这里不使用
    
        }
    
        // Update is called once per frame
        void Update()
        {
    
        }
    
        public void ScreenShot_Button()
        {
    
            PlaneWH = new Vector2(PlaneB.GetComponent<MeshFilter>().mesh.bounds.size.x, PlaneB.GetComponent<MeshFilter>().mesh.bounds.size.z) * 5 * 0.5f;
            //获取面片的宽高的一半
            //"gameObject.GetComponent<MeshFilter>().mesh.bounds.size.x"获取面片X方向的宽度
            //"*5"是因为开始获取到的长宽是模型本身的长宽,而场景中我们有缩放因素,父级物体放大了50倍,自身缩小到了0.1,因此获取实际宽高需要再乘以5
    
            //获取面片四个点的世界坐标
            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
            Earth.GetComponent<Renderer>().material.SetVector("_Uvpoint1", new Vector4(TopLeft_Pl_W.x, TopLeft_Pl_W.y, TopLeft_Pl_W.z, 1f));
            //将左上角的世界坐标传递给Shader ,其中1f是否了凑齐四位浮点数 ,用来进行后续的矩阵变换操作
            Earth.GetComponent<Renderer>().material.SetVector("_Uvpoint2", new Vector4(BottomLeft_Pl_W.x, BottomLeft_Pl_W.y, BottomLeft_Pl_W.z, 1f));
            Earth.GetComponent<Renderer>().material.SetVector("_Uvpoint3", new Vector4(TopRight_Pl_W.x, TopRight_Pl_W.y, TopRight_Pl_W.z, 1f));
            Earth.GetComponent<Renderer>().material.SetVector("_Uvpoint4", new Vector4(BottomRight_Pl_W.x, BottomRight_Pl_W.y, BottomRight_Pl_W.z, 1f));
    
            //将截图时识别图四个角的世界坐标信息传递给Shader
            EarthFrame.GetComponent<Renderer>().material.SetVector("_Uvpoint1", new Vector4(TopLeft_Pl_W.x, TopLeft_Pl_W.y, TopLeft_Pl_W.z, 1f));
            //将左上角的世界坐标传递给Shader ,其中1f是否了凑齐四位浮点数 ,用来进行后续的矩阵变换操作
            EarthFrame.GetComponent<Renderer>().material.SetVector("_Uvpoint2", new Vector4(BottomLeft_Pl_W.x, BottomLeft_Pl_W.y, BottomLeft_Pl_W.z, 1f));
            EarthFrame.GetComponent<Renderer>().material.SetVector("_Uvpoint3", new Vector4(TopRight_Pl_W.x, TopRight_Pl_W.y, TopRight_Pl_W.z, 1f));
            EarthFrame.GetComponent<Renderer>().material.SetVector("_Uvpoint4", new Vector4(BottomRight_Pl_W.x, BottomRight_Pl_W.y, BottomRight_Pl_W.z, 1f));
    
            //将截图时识别图四个角的世界坐标信息传递给Shader
            EarthA.GetComponent<Renderer>().material.SetVector("_Uvpoint1",new Vector4(TopLeft_Pl_W.x,TopLeft_Pl_W.y,TopLeft_Pl_W.z,1f));
            //将左上角的世界坐标传递给Shader ,其中1f是否了凑齐四位浮点数 ,用来进行后续的矩阵变换操作
            EarthA.GetComponent<Renderer>().material.SetVector("_Uvpoint2",new Vector4(BottomLeft_Pl_W.x,BottomLeft_Pl_W.y,BottomLeft_Pl_W.z,1f));
            EarthA.GetComponent<Renderer>().material.SetVector("_Uvpoint3",new Vector4(TopRight_Pl_W.x,TopRight_Pl_W.y,TopRight_Pl_W.z,1f));
            EarthA.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;
            //储存两个矩阵的乘积
            Earth.GetComponent<Renderer>().material.SetMatrix("_VP", VP);
            //将截图时的矩阵转换信息传递给Shader
            EarthFrame.GetComponent<Renderer>().material.SetMatrix("_VP", VP);
            //将截图时的矩阵转换信息传递给Shader
            EarthA.GetComponent<Renderer>().material.SetMatrix("_VP",VP);
            //将截图时的矩阵转换信息传递给Shader
    
           // Debug.Log("----------错误前");
            TextureShot.ReadPixels(new Rect(0, 0, ScreenWidth, ScreenHeight), 0, 0);
          //  Debug.Log("错误后--------------");
            //获取屏幕的像素信息 
            //第一个"0,0"获取屏幕像素的起始点
            //“ScreenWidth,ScreenHeight”获取屏幕像素的范围
            //第二个“0,0” 填充texture2D时填充的坐标
    
            TextureShot.Apply();
            //确认之前对Texture2D进行的修改
    
            Earth.GetComponent<Renderer>().material.mainTexture = TextureShot;
            //获取Earth的渲染组件中的材质的主纹理,并将Texture2D赋值给这个主纹理
            EarthFrame.GetComponent<Renderer>().material.mainTexture = TextureShot;
            //获取Earth的渲染组件中的材质的主纹理,并将Texture2D赋值给这个主纹理
            EarthA.GetComponent<Renderer> ().material.mainTexture = TextureShot;
            //获取Earth的渲染组件中的材质的主纹理,并将Texture2D赋值给这个主纹理
    
            //状态隐藏
            PlaneA.SetActive(false);
            PlaneB.SetActive(false);
            //取消面片的激活状态
        }
    
    
    }
    
    
    

    SecUI

    using UnityEngine;
    using System.Collections;
    
    public class SecUI : MonoBehaviour {
    
        private float CancelTime=0;
        //申请浮点类型的变量来记录 识别成功提示所存在的时间
    
        // Use this for initialization
        void Start () {
        
        }
        
        // Update is called once per frame
        void Update () {
            CancelTime += Time.deltaTime;
            //记录识别成功提示所存在的时间
            //每一帧运行都加经过一帧所使用的键
    
            if(CancelTime>1.3f){  
            //当识别成功的提示存在时间大于1.3秒时
                CancelTime=0;
                //记录存在时间归零
                gameObject.SetActive(false);
                //取消识别成功提示面板
            }
        }
    }
    
    

    Duijiao

    using UnityEngine;
    using System.Collections;
    using Vuforia;
    
    /// <summary>
    /// 相机对焦
    /// </summary>
    public class Duijiao : MonoBehaviour
    {
    
    
        // Use this for initialization
        //void Start()
        //{
        //   //通过Find寻找Ar摄像机
        //    GameObject ARCamera = GameObject.Find("ARCamera");
    
        //    //实例化摄像机时候自动对焦
        //    Vuforia.CameraDevice.Instance.SetFocusMode(Vuforia.CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
        //}
    
        //// Update is called once per frame
        //void Update()
        //{
        //    //运行过程中实行对焦功能
        //    Vuforia.CameraDevice.Instance.SetFocusMode(Vuforia.CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
        //}
    
    
    
        //-----------------------------------------------------
        //第二种对焦方法
        void Start()
        {
            //一开始自动对焦
            //Vuforia.CameraDevice.Instance.SetFocusMode(Vuforia.CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
            VuforiaARController.Instance.RegisterVuforiaStartedCallback(OnVuforiaStarted);
            VuforiaARController.Instance.RegisterOnPauseCallback(OnPaused);
        }
    
    
        private void OnVuforiaStarted()
        {
            CameraDevice.Instance.SetFocusMode(
            CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
        }
    
        private void OnPaused(bool paused)
        {
            if (!paused)
            { // resumed
                // Set again autofocus mode when app is resumed
                CameraDevice.Instance.SetFocusMode(
                CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
            }
        }
    
    }
    
    
    
    

    三、效果展示

    相关文章

      网友评论

      本文标题:AR开发实战Vuforia项目之太阳系八大行星(实现涂涂乐功能)

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