Unity Docker基础镜像构建:Windows与镜面效果

Unity镜子效果的制作过程

Create Mirror —— 创建镜子

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

unity docker windows基础镜像 unity 镜面_世界坐标系

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

unity docker windows基础镜像 unity 镜面_Cross_02

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

unity docker windows基础镜像 unity 镜面_世界坐标_03

Create Camera —— 创建一个新相机

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

unity docker windows基础镜像 unity 镜面_世界坐标_04

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

unity docker windows基础镜像 unity 镜面_Cross_05

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

unity docker windows基础镜像 unity 镜面_世界坐标系_06

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

unity docker windows基础镜像 unity 镜面_世界坐标_07

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

unity docker windows基础镜像 unity 镜面_世界坐标_08

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

unity docker windows基础镜像 unity 镜面_世界坐标_09

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

unity docker windows基础镜像 unity 镜面_世界坐标_10

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

unity docker windows基础镜像 unity 镜面_Cross_11

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

登录后复制

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 —— 用来作为参照对象,然后点击运行后,即可看到镜子效果已经完成

unity docker windows基础镜像 unity 镜面_世界坐标_12

Indistinct —— 显示效果不清晰

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

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

unity docker windows基础镜像 unity 镜面_世界坐标_13

镜面显示效果

unity docker windows基础镜像 unity 镜面_Cross_14

END


免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删

QR Code
微信扫一扫,欢迎咨询~

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 155-2731-8020
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

手机不正确

公司不为空