zoukankan      html  css  js  c++  java
  • Unity 镜子效果的实现(转载)

    Unity镜子效果的制作过程

    Create Mirror —— 创建镜子

    1. 创建一个 Plane —— 作为镜子

    2. 创建一个材质球 Material —— 给到 Plane 上

    3. 修改新创建 Material 的 Shader 为 Unlit/Texture

    Create Camera —— 创建一个新相机

    1. 新建一个 Render Texture(这里重新命名为 Plane 便于区分和理解)

    2. 在层次列表Hierarchy 下创建一个新的 Camera

     

    3. 将新建的 Render Texture(Plane)给新 Camera 组件中的 Target Texture

    4. 给 Camera相机,添加脚本 MirrorPlane

    并将 Plane 拖到 Inspector 面板中对应的属性里

    5. 给新 Camera相机,添加脚本 Mirror 

     

    并将Main Camera与 Plane 拖至 Inspector 面板中

     注意: 一定要修改 Plane 材质的属性为:

     两个脚本,具体代码如下 : 

      1 using UnityEngine;
      2 
      3 /// <summary>
      4 /// Plane管理脚本 —— 挂载新建的Camera上
      5 /// </summary>
      6 [ExecuteInEditMode] //编辑模式中执行
      7 public class MirrorPlane : MonoBehaviour
      8 {
      9     public GameObject mirrorPlane; //镜子Plane
     10     public bool estimateViewFrustum = true;
     11     public bool setNearClipPlane = true;   //是否设置近剪切平面
     12     public float nearClipDistanceOffset = -0.01f; //近剪切平面的距离
     13     private Camera mirrorCamera;                    //镜像摄像机
     14     private Vector3 vn;                              //屏幕的法线
     15     private float l;                               //到屏幕左边缘的距离
     16     private float r;                               //到屏幕右边缘的距离
     17     private float b;                               //到屏幕下边缘的距离
     18     private float t;                               //到屏幕上边缘的距离
     19     private float d;                               //从镜像摄像机到屏幕的距离
     20     private float n;                               //镜像摄像机的近剪切面的距离
     21     private float f;                               //镜像摄像机的远剪切面的距离
     22     private Vector3 pa;                              //世界坐标系的左下角
     23     private Vector3 pb;                              //世界坐标系的右下角
     24     private Vector3 pc;                              //世界坐标系的左上角
     25     private Vector3 pe;                              //镜像观察角度的世界坐标位置
     26     private Vector3 va;                              //从镜像摄像机到左下角
     27     private Vector3 vb;                              //从镜像摄像机到右下角
     28     private Vector3 vc;                              //从镜像摄像机到左上角
     29     private Vector3 vr;                              //屏幕的右侧旋转轴
     30     private Vector3 vu;                              //屏幕的上侧旋转轴
     31     private Matrix4x4 p = new Matrix4x4();
     32     private Matrix4x4 rm = new Matrix4x4();
     33     private Matrix4x4 tm = new Matrix4x4();
     34     private Quaternion q = new Quaternion();
     35 
     36     private void Start()
     37     {
     38         mirrorCamera = GetComponent<Camera>();
     39     }
     40 
     41     private void Update()
     42     {
     43         if (null == mirrorPlane || null == mirrorCamera) return;
     44         pa = mirrorPlane.transform.TransformPoint(new Vector3(-5.0f, 0.0f, -5.0f)); //世界坐标系的左下角
     45         pb = mirrorPlane.transform.TransformPoint(new Vector3(5.0f, 0.0f, -5.0f)); //世界坐标系的右下角
     46         pc = mirrorPlane.transform.TransformPoint(new Vector3(-5.0f, 0.0f, 5.0f));  //世界坐标系的左上角
     47         pe = transform.position;                                                    //镜像观察角度的世界坐标位置
     48         n = mirrorCamera.nearClipPlane;                                            //镜像摄像机的近剪切面的距离
     49         f = mirrorCamera.farClipPlane;                                             //镜像摄像机的远剪切面的距离
     50         va = pa - pe;                                                               //从镜像摄像机到左下角
     51         vb = pb - pe;                                                               //从镜像摄像机到右下角
     52         vc = pc - pe;                                                               //从镜像摄像机到左上角
     53         vr = pb - pa;                                                               //屏幕的右侧旋转轴
     54         vu = pc - pa;                                                               //屏幕的上侧旋转轴
     55         if (Vector3.Dot(-Vector3.Cross(va, vc), vb) < 0.0f)                         //如果看向镜子的背面
     56         {
     57             vu = -vu;
     58             pa = pc;
     59             pb = pa + vr;
     60             pc = pa + vu;
     61             va = pa - pe;
     62             vb = pb - pe;
     63             vc = pc - pe;
     64         }
     65         vr.Normalize();
     66         vu.Normalize();
     67         vn = -Vector3.Cross(vr, vu); //两个向量的叉乘,最后在取负,因为Unity是使用左手坐标系
     68         vn.Normalize();
     69         d = -Vector3.Dot(va, vn);
     70         if (setNearClipPlane)
     71         {
     72             n = d + nearClipDistanceOffset;
     73             mirrorCamera.nearClipPlane = n;
     74         }
     75         l = Vector3.Dot(vr, va) * n / d;
     76         r = Vector3.Dot(vr, vb) * n / d;
     77         b = Vector3.Dot(vu, va) * n / d;
     78         t = Vector3.Dot(vu, vc) * n / d;
     79 
     80         //投影矩阵
     81         p[0, 0] = 2.0f * n / (r - l);
     82         p[0, 1] = 0.0f;
     83         p[0, 2] = (r + l) / (r - l);
     84         p[0, 3] = 0.0f;
     85 
     86         p[1, 0] = 0.0f;
     87         p[1, 1] = 2.0f * n / (t - b);
     88         p[1, 2] = (t + b) / (t - b);
     89         p[1, 3] = 0.0f;
     90 
     91         p[2, 0] = 0.0f;
     92         p[2, 1] = 0.0f;
     93         p[2, 2] = (f + n) / (n - f);
     94         p[2, 3] = 2.0f * f * n / (n - f);
     95 
     96         p[3, 0] = 0.0f;
     97         p[3, 1] = 0.0f;
     98         p[3, 2] = -1.0f;
     99         p[3, 3] = 0.0f;
    100 
    101         //旋转矩阵
    102         rm[0, 0] = vr.x;
    103         rm[0, 1] = vr.y;
    104         rm[0, 2] = vr.z;
    105         rm[0, 3] = 0.0f;
    106 
    107         rm[1, 0] = vu.x;
    108         rm[1, 1] = vu.y;
    109         rm[1, 2] = vu.z;
    110         rm[1, 3] = 0.0f;
    111 
    112         rm[2, 0] = vn.x;
    113         rm[2, 1] = vn.y;
    114         rm[2, 2] = vn.z;
    115         rm[2, 3] = 0.0f;
    116 
    117         rm[3, 0] = 0.0f;
    118         rm[3, 1] = 0.0f;
    119         rm[3, 2] = 0.0f;
    120         rm[3, 3] = 1.0f;
    121 
    122         tm[0, 0] = 1.0f;
    123         tm[0, 1] = 0.0f;
    124         tm[0, 2] = 0.0f;
    125         tm[0, 3] = -pe.x;
    126 
    127         tm[1, 0] = 0.0f;
    128         tm[1, 1] = 1.0f;
    129         tm[1, 2] = 0.0f;
    130         tm[1, 3] = -pe.y;
    131 
    132         tm[2, 0] = 0.0f;
    133         tm[2, 1] = 0.0f;
    134         tm[2, 2] = 1.0f;
    135         tm[2, 3] = -pe.z;
    136 
    137         tm[3, 0] = 0.0f;
    138         tm[3, 1] = 0.0f;
    139         tm[3, 2] = 0.0f;
    140         tm[3, 3] = 1.0f;
    141 
    142         mirrorCamera.projectionMatrix = p; //矩阵组
    143         mirrorCamera.worldToCameraMatrix = rm * tm;
    144         if (!estimateViewFrustum) return;
    145         q.SetLookRotation((0.5f * (pb + pc) - pe), vu); //旋转摄像机
    146         mirrorCamera.transform.rotation = q;            //聚焦到屏幕的中心点
    147 
    148         //估值 —— 三目简写
    149         mirrorCamera.fieldOfView = mirrorCamera.aspect >= 1.0 ? Mathf.Rad2Deg * 
    150             Mathf.Atan(((pb - pa).magnitude + (pc - pa).magnitude) / va.magnitude) : 
    151             Mathf.Rad2Deg / mirrorCamera.aspect * 
    152             Mathf.Atan(((pb - pa).magnitude + (pc - pa).magnitude) / va.magnitude);
    153         //在摄像机角度考虑,保证视锥足够宽
    154     }
    155 }

     

     1 using UnityEngine;
     2 
     3 /// <summary>
     4 /// 镜子管理脚本 —— 挂在新建的Camera上
     5 /// </summary>
     6 [ExecuteInEditMode]
     7 public class Mirror : MonoBehaviour
     8 {
     9     public GameObject mirrorPlane;  //镜子
    10     public Camera mainCamera;   //主摄像机
    11     private Camera mirrorCamera; //镜像摄像机
    12 
    13     private void Start()
    14     {
    15         mirrorCamera = GetComponent<Camera>();
    16     }
    17 
    18     private void Update()
    19     {
    20         if (null == mirrorPlane || null == mirrorCamera || null == mainCamera) return;
    21         //将主摄像机的世界坐标位置转换为镜子的局部坐标位置
    22         Vector3 postionInMirrorSpace = mirrorPlane.transform.
    23             InverseTransformPoint(mainCamera.transform.position);
    24         //一般y为镜面的法线方向
    25         postionInMirrorSpace.y = -postionInMirrorSpace.y;
    26         //转回到世界坐标系的位置
    27         mirrorCamera.transform.position = mirrorPlane.transform.TransformPoint(postionInMirrorSpace);
    28     }
    29 }

    Create Cube —— 创建一个立方体

    为了看镜子的效果,在场景中创建一个 Cube —— 用来作为参照对象,然后点击运行后,即可看到镜子效果已经完成

    Indistinct —— 显示效果不清晰

    如果发现,镜子的显示效果并不清晰,这是因为我们创建的 Render Texture 时使用的是默认的分辨率 256*256,修改成较高的分辨率即可,这里我修改为:1024*1024 (可视情况自己设定)

    注意:分辨率设置越高,是越耗性能的

    镜面显示效果

    END

    原文: https://www.cnblogs.com/chinarbolg/p/9601388.html

     

     

     

  • 相关阅读:
    Eclipse中显示行号
    PeerSim中一些自己的理解
    迄今为止看过的书籍
    Java程序跨平台运行
    Linux下在PeerSim中运行Chord源代码
    在Eclipse中运行PeerSim的例子
    Ubuntu下安装Java
    Eclipse中自动调整代码
    Eclipse中Outline里各种图标的含义
    Java是如何运行的
  • 原文地址:https://www.cnblogs.com/ChenZiRong1999/p/12894079.html
Copyright © 2011-2022 走看看