unity3d镜面效果_unity3d镜面反射 - CSDN
  • 本教程,无需自己找镜子Shader,只需2个脚本即可在Unity中创建一个简单的模拟镜面反射效果 本教程,无需自己找镜子Shader,只需2个脚本即可在Unity中创建一个简单的模拟镜面反射效果 1. 在场景中创建一个 Plane ——...

    Unity镜子效果制作教程


    本文提供全流程,中文翻译。

    Chinar 坚持将简单的生活方式,带给世人!

    (拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)



    Chinar —— 心分享、心创新!

    助力快速实现一个简单的镜面反射效果

    为新手节省宝贵的时间,避免采坑!


    Chinar 教程效果:
    这里写图片描述



    全文高清图片,点击即可放大观看 (很多人竟然不知道)


    1

    Create Mirror —— 创建镜子


    本教程,无需自己找镜子Shader,只需2个脚本即可在Unity中创建一个简单的模拟镜面反射效果

    1. 在场景中创建一个 Plane —— 用来作为镜子

    2. 同时创建一个材质球 /Material —— 给到 Plane

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

    举个栗子黑白88
    这里写图片描述


    2

    Create Camera —— 创建一个新相机


    1. 新建一个 Render Texture(我改名为 Plane 便于区分和理解)

    2. 右键 层次列表/Hierarchy —— 创建一个新的 Camera

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

    4. 给新建的 Camera相机,添加脚本 ChinarMirrorPlane

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

    5. 给新建的 Camera相机,添加脚本 ChinarMirror ,并将 Plane 拖至 Inspector 面板中

    注意: 一定要修改 Plane 材质的属性为:
    这里写图片描述
    具体流程其实很简单,如下
    举个栗子黑白88
    这里写图片描述
    两个脚本,都需要挂载到 Camera

    using UnityEngine;
    
    
    /// <summary>
    /// 镜子管理脚本 —— 挂在新建的Camera上
    /// </summary>
    [ExecuteInEditMode]
    public class ChinarMirror : MonoBehaviour
    {
        public  GameObject mirrorPlane;  //镜子
        public  Camera     mainCamera;   //主摄像机
        private Camera     mirrorCamera; //镜像摄像机
    
    
        private void Start()
        {
            mirrorCamera = GetComponent<Camera>();
        }
    
    
        private void Update()
        {
            if (null == mirrorPlane || null == mirrorCamera || null == mainCamera) return;
            Vector3 postionInMirrorSpace    = mirrorPlane.transform.InverseTransformPoint(mainCamera.transform.position); //将主摄像机的世界坐标位置转换为镜子的局部坐标位置
            postionInMirrorSpace.y          = -postionInMirrorSpace.y;                                                    //一般y为镜面的法线方向
            mirrorCamera.transform.position = mirrorPlane.transform.TransformPoint(postionInMirrorSpace);                 //转回到世界坐标系的位置
        }
    }
    using UnityEngine;
    
    /// <summary>
    /// Plane管理脚本 —— 挂载新建的Camera上
    /// </summary>
    [ExecuteInEditMode] //编辑模式中执行
    public class ChinarMirrorPlane : MonoBehaviour
    {
        public  GameObject mirrorPlane; //镜子Plane
        public  bool       estimateViewFrustum    = true;
        public  bool       setNearClipPlane       = true;   //是否设置近剪切平面
        public  float      nearClipDistanceOffset = -0.01f; //近剪切平面的距离
        private Camera     mirrorCamera;                    //镜像摄像机
        private Vector3    vn;                              //屏幕的法线
        private float      l;                               //到屏幕左边缘的距离
        private float      r;                               //到屏幕右边缘的距离
        private float      b;                               //到屏幕下边缘的距离
        private float      t;                               //到屏幕上边缘的距离
        private float      d;                               //从镜像摄像机到屏幕的距离
        private float      n;                               //镜像摄像机的近剪切面的距离
        private float      f;                               //镜像摄像机的远剪切面的距离
        private Vector3    pa;                              //世界坐标系的左下角
        private Vector3    pb;                              //世界坐标系的右下角
        private Vector3    pc;                              //世界坐标系的左上角
        private Vector3    pe;                              //镜像观察角度的世界坐标位置
        private Vector3    va;                              //从镜像摄像机到左下角
        private Vector3    vb;                              //从镜像摄像机到右下角
        private Vector3    vc;                              //从镜像摄像机到左上角
        private Vector3    vr;                              //屏幕的右侧旋转轴
        private Vector3    vu;                              //屏幕的上侧旋转轴
        private Matrix4x4  p  = new Matrix4x4();
        private Matrix4x4  rm = new Matrix4x4();
        private Matrix4x4  tm = new Matrix4x4();
        private Quaternion q  = new Quaternion();
    
    
        private void Start()
        {
            mirrorCamera = GetComponent<Camera>();
        }
    
    
        private void Update()
        {
            if (null == mirrorPlane || null == mirrorCamera) return;
            pa = mirrorPlane.transform.TransformPoint(new Vector3(-5.0f, 0.0f, -5.0f)); //世界坐标系的左下角
            pb = mirrorPlane.transform.TransformPoint(new Vector3(5.0f,  0.0f, -5.0f)); //世界坐标系的右下角
            pc = mirrorPlane.transform.TransformPoint(new Vector3(-5.0f, 0.0f, 5.0f));  //世界坐标系的左上角
            pe = transform.position;                                                    //镜像观察角度的世界坐标位置
            n  = mirrorCamera.nearClipPlane;                                            //镜像摄像机的近剪切面的距离
            f  = mirrorCamera.farClipPlane;                                             //镜像摄像机的远剪切面的距离
            va = pa - pe;                                                               //从镜像摄像机到左下角
            vb = pb - pe;                                                               //从镜像摄像机到右下角
            vc = pc - pe;                                                               //从镜像摄像机到左上角
            vr = pb - pa;                                                               //屏幕的右侧旋转轴
            vu = pc - pa;                                                               //屏幕的上侧旋转轴
            if (Vector3.Dot(-Vector3.Cross(va, vc), vb) < 0.0f)                         //如果看向镜子的背面
            {
                vu = -vu;
                pa = pc;
                pb = pa + vr;
                pc = pa + vu;
                va = pa - pe;
                vb = pb - pe;
                vc = pc - pe;
            }
            vr.Normalize();
            vu.Normalize();
            vn = -Vector3.Cross(vr, vu); //两个向量的叉乘,最后在取负,因为Unity是使用左手坐标系
            vn.Normalize();
            d = -Vector3.Dot(va, vn);
            if (setNearClipPlane)
            {
                n                          = d + nearClipDistanceOffset;
                mirrorCamera.nearClipPlane = n;
            }
            l = Vector3.Dot(vr, va) * n / d;
            r = Vector3.Dot(vr, vb) * n / d;
            b = Vector3.Dot(vu, va) * n / d;
            t = Vector3.Dot(vu, vc) * n / d;
    
    
            //投影矩阵
            p[0, 0] = 2.0f * n / (r - l);
            p[0, 1] = 0.0f;
            p[0, 2] = (r + l) / (r - l);
            p[0, 3] = 0.0f;
    
            p[1, 0] = 0.0f;
            p[1, 1] = 2.0f * n / (t - b);
            p[1, 2] = (t + b) / (t - b);
            p[1, 3] = 0.0f;
    
            p[2, 0] = 0.0f;
            p[2, 1] = 0.0f;
            p[2, 2] = (f + n) / (n - f);
            p[2, 3] = 2.0f * f * n / (n - f);
    
            p[3, 0] = 0.0f;
            p[3, 1] = 0.0f;
            p[3, 2] = -1.0f;
            p[3, 3] = 0.0f;
    
            //旋转矩阵
            rm[0, 0] = vr.x;
            rm[0, 1] = vr.y;
            rm[0, 2] = vr.z;
            rm[0, 3] = 0.0f;
    
            rm[1, 0] = vu.x;
            rm[1, 1] = vu.y;
            rm[1, 2] = vu.z;
            rm[1, 3] = 0.0f;
    
            rm[2, 0] = vn.x;
            rm[2, 1] = vn.y;
            rm[2, 2] = vn.z;
            rm[2, 3] = 0.0f;
    
            rm[3, 0] = 0.0f;
            rm[3, 1] = 0.0f;
            rm[3, 2] = 0.0f;
            rm[3, 3] = 1.0f;
    
            tm[0, 0] = 1.0f;
            tm[0, 1] = 0.0f;
            tm[0, 2] = 0.0f;
            tm[0, 3] = -pe.x;
    
            tm[1, 0] = 0.0f;
            tm[1, 1] = 1.0f;
            tm[1, 2] = 0.0f;
            tm[1, 3] = -pe.y;
    
            tm[2, 0] = 0.0f;
            tm[2, 1] = 0.0f;
            tm[2, 2] = 1.0f;
            tm[2, 3] = -pe.z;
    
            tm[3, 0] = 0.0f;
            tm[3, 1] = 0.0f;
            tm[3, 2] = 0.0f;
            tm[3, 3] = 1.0f;
    
    
            mirrorCamera.projectionMatrix    = p; //矩阵组
            mirrorCamera.worldToCameraMatrix = rm * tm;
            if (!estimateViewFrustum) return;
            q.SetLookRotation((0.5f * (pb + pc) - pe), vu); //旋转摄像机
            mirrorCamera.transform.rotation = q;            //聚焦到屏幕的中心点
    
            //估值 —— 三目简写
            mirrorCamera.fieldOfView = mirrorCamera.aspect >= 1.0 ? Mathf.Rad2Deg * Mathf.Atan(((pb - pa).magnitude + (pc - pa).magnitude) / va.magnitude) : Mathf.Rad2Deg / mirrorCamera.aspect * Mathf.Atan(((pb - pa).magnitude + (pc - pa).magnitude) / va.magnitude);
            //在摄像机角度考虑,保证视锥足够宽
        }
    }

    3

    Main Camera —— 主相机脚本(方便看到测试效果)


    为了方便看到运行后的镜面效果, Chinar 在这里提供了一个第三人称的脚本

    用于转镜头,看不同方位

    需要挂载到主相机上,并将层次列表中的 Plane 拖到 Pivot
    举个栗子黑白88

    using UnityEngine;
    
    /// <summary>
    /// 主相机脚本 —— 挂载到主相机上,并 层次列表中的 Plane 拖到 pivot 
    /// </summary>
    public class ChinarCamera : MonoBehaviour
    {
        public  Transform pivot;
        public  Vector3   pivotOffset = Vector3.zero;
        public  Transform target;
        public  float     distance       = 10.0f;
        public  float     minDistance    = 2f;
        public  float     maxDistance    = 15f;
        public  float     zoomSpeed      = 1f;
        public  float     xSpeed         = 250.0f;
        public  float     ySpeed         = 120.0f;
        public  bool      allowYTilt     = true;
        public  float     yMinLimit      = -90f;
        public  float     yMaxLimit      = 90f;
        private float     x              = 0.0f;
        private float     y              = 0.0f;
        private float     targetX        = 0f;
        private float     targetY        = 0f;
        private float     targetDistance = 0f;
        private float     xVelocity      = 1f;
        private float     yVelocity      = 1f;
        private float     zoomVelocity   = 1f;
    
    
        private void Start()
        {
            var angles     = transform.eulerAngles;
            targetX        = x = angles.x;
            targetY        = y = ClampAngle(angles.y, yMinLimit, yMaxLimit);
            targetDistance = distance;
        }
    
    
        private void LateUpdate()
        {
            if (!pivot) return;
            var scroll = Input.GetAxis("Mouse ScrollWheel");
    
            if (scroll > 0.0f) targetDistance -= zoomSpeed;
            else if (scroll < 0.0f)
                targetDistance += zoomSpeed;
            targetDistance     =  Mathf.Clamp(targetDistance, minDistance, maxDistance);
            if (Input.GetMouseButton(1) || (Input.GetMouseButton(0) && (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))))
            {
                targetX += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
                if (allowYTilt)
                {
                    targetY -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
                    targetY =  ClampAngle(targetY, yMinLimit, yMaxLimit);
                }
            }
            x                   = Mathf.SmoothDampAngle(x,              targetX, ref xVelocity, 0.3f);
            y                   = allowYTilt ? Mathf.SmoothDampAngle(y, targetY, ref yVelocity, 0.3f) : targetY;
            Quaternion rotation = Quaternion.Euler(y, x, 0);
            distance            = Mathf.SmoothDamp(distance, targetDistance, ref zoomVelocity, 0.5f);
            Vector3 position    = rotation * new Vector3(0.0f, 0.0f, -distance) + pivot.position + pivotOffset;
            transform.rotation  = rotation;
            transform.position  = position;
        }
    
    
        private static float ClampAngle(float angle, float min, float max)
        {
            if (angle < -360) angle += 360;
            if (angle > 360) angle  -= 360;
            return Mathf.Clamp(angle, min, max);
        }
    }

    4

    Create Cube —— 创建一个立方体


    为了看镜子的效果

    在场景中创建一个 Cube —— 用来作为参照对象

    然后点击运行后,即可看到镜子效果已经完成
    举个栗子黑白88
    这里写图片描述
    这里写图片描述


    5

    Indistinct —— 显示效果不清晰


    如果发现,镜子的显示效果并不清晰

    这是因为我们创建的 Render Texture 时使用的是默认的分辨率 256*256

    修改成较高的分辨率即可,这里我修改为:1024*1024 (可视情况自己设定)

    注意:分辨率设置越高,是越耗性能的
    举个栗子黑白88
    这里写图片描述
    这里写图片描述

    至此:镜子的制作教程结束


    6

    Project —— 项目文件


    项目文件为 unitypackage 文件包:

    下载导入 Unity 即可使用
    举个栗子黑白88
    点击下载 —— 项目资源


    支持

    May Be —— 搞开发,总有一天要做的事!


    拥有自己的服务器,无需再找攻略!

    Chinar 提供一站式教程,闭眼式创建!

    为新手节省宝贵时间,避免采坑!


    先点击领取 —— 阿里全产品优惠券 (享受最低优惠)


    1 —— 云服务器超全购买流程 (新手必备!)

    2 —— 阿里ECS云服务器自定义配置 - 购买教程(新手必备!)

    3—— Windows 服务器配置、运行、建站一条龙 !

    4 —— Linux 服务器配置、运行、建站一条龙 !





    技术交流群:806091680 ! Chinar 欢迎你的加入


    END

    本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

    对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

    对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

    展开全文
  • Unity3D——镜面反射原理及实现

    千次阅读 2016-12-23 17:03:22
    原文:http://gad.qq.com/user/myarticle?id=438905

    原文:http://gad.qq.com/user/myarticle?id=438905


    展开全文
  • Unity3D镜面反射

    千次阅读 2014-12-03 11:56:46
    点击这里下载 原文地址点击这里
    展开全文
  • 无需自己找镜子Shader,只需2个脚本即可在Unity中创建一个简单的模拟镜面反射效果。 使用教程链接:https://blog.csdn.net/ChinarCSDN/article/details/80862999
  • Unity实现水面渲染效果

    千次阅读 2019-03-29 16:16:34
    镜面反射 将摄像机的位置和视锥体关于镜面进行对称变换,渲染一张RenderTexture。在渲染水面时,计算水面某像素在屏幕中的位置,根据该位置对RenderTexture进行采样。 ...Unity3D教程:实现水...
    展开全文
  • unity镜面反射效果

    2020-07-28 23:33:36
    unity镜面反射效果
  • Unity:图片翻动浏览效果Demo

    千次阅读 2012-09-25 23:33:39
    本Demo涉及的Unity知识点有: 1.天空盒的添加;http://blog.csdn.net/tanmengwen/article/details/8013410 2.镜面反射效果的实现;http://blog.csdn.net/tanmengwen/article/details/8015138 3.给摄像机添加Image...
  • Unity实现镜子效果

    千次阅读 2019-04-12 14:42:19
    详细步骤参考http://www.sikiedu.com/course/306/task/16510/show Mirror Shader 导入资源:链接:https://pan.baidu.com/s/1tBmAycMEC7oxP2EV3o0LzQ 密码:23n2
  • Unity3D算反射向量

    千次阅读 2019-06-21 17:20:54
    如图根据入射向量In和法线N。算出反射向量Out Unity3D已提供API: public static Vector3 Reflect(Vector3 inDirection, Vector3 inNormal);
  • unity3d超漂亮的动态天空盒 风吹树动效果源码
  • Unity3D中使用uGUI实现3D旋转特效(简单,好用),只需要两个脚本文件
  • unity3d粒子 水的效果图。

    热门讨论 2020-07-30 23:33:23
    unity3d粒子 水的效果图。瀑布形式的。
  • unity ugui 3D翻书效果

    2020-07-30 23:30:17
    使用了一个插件,经过优化实现流畅的翻书效果,用的是原生的ugui,是3D翻书页的效果,有需要的拿去
  • Unity3D特效包 100种unity特效 种类丰富 效果绚丽 直接使用
  • unity3d实现物体透明渐变效果

    热门讨论 2020-07-30 23:33:23
    unity3d实现物体透明渐变效果,只需要将脚本放在物体上即可
  • 自制unity闪烁屏幕效果,整个工程
  • Unity环境镜面效果

    2020-07-30 23:32:00
    Unity环境镜面反射效果 利用Unity提供的设置、Shader、Cube、 简单的设置即可完成对环境的反射效果,无需写代码。 教程地址:https://blog.csdn.net/chinarcsdn/article/details/80210924
  • unity中使用c#实现跑马灯效果,可根据自身需求进行修改和优化
  • unity3d 灰尘云粒子特效

    热门讨论 2020-07-30 23:30:36
    unity3d 的灰尘云粒子特效,效果还不错
  • Unity3D-实现水墨渲染效果

    千次阅读 2016-12-23 17:01:14
    原文:http://gad.qq.com/user/myarticle?id=438905
1 2 3 4 5 ... 20
收藏数 250,069
精华内容 100,027
关键字:

unity3d镜面效果