美文网首页
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,长方形

    //截图赋值,移走图片,涂色还在,长方形识别图,UV是正方形//模型使用shander-ScanTexusing ...

  • EaayAR2.1/vuforia6.5涂涂乐2,正方形

    //截图赋值,移走图片,涂色还在,正方形识别图,同时UV也是正方形//模型使用shander-ScanTexusi...

  • Ar 涂涂乐的实现

    Ar 涂涂乐的实现 使用 Vuforia 实现 Ar 涂涂乐 项目名: LessonA30Unity567f1Un...

  • EaayAR2.1涂涂乐1

    //模型身上挂此脚本,实时渲染,//模型身上使用shader--ScanTex2using UnityEngine...

  • 晚间涂涂乐

    流莺悄飞近船侧 伴桨声低语浅说 柳梢沾绿了烟波 绕堤三分春色 旧书翻入寻常调 隔岸依稀吴越歌 反复着几回啼笑 往来...

  • AR简单创建

    1:先登录vuforia官网,没有账号的要先注册 2:登录网站后,下载vuforia for Unity的SDK,...

  • 感恩遇见微商

    我是个微商,一个有诚信的善良的人。我主要从事涂涂乐代理,涂涂乐是一款高科技早教产品,是国家是十二五科技支撑项目,2...

  • 2019-10-20

    5级涂涂乐让我去若无群

  • 天弘教育

    今天是泥膜哼嗯涂涂乐舅舅套路

  • vuforia android 教程(1) 利用vuforia

    系列教程:vuforia android 教程(2)https://www.jianshu.com/p/2d709...

网友评论

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

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