首页 > 其他分享 >Unity URP 平面反射

Unity URP 平面反射

时间:2023-03-01 23:55:21浏览次数:50  
标签:反射 Vector3 2F private Unity plane URP cameraReflection reflectionMat

https://www.bilibili.com/video/BV1TA4y1D7s4/?spm_id_from=333.999.0.0&vd_source=5672eeb8a9721da01495e313f0dff6c2
https://zhuanlan.zhihu.com/p/493766119

PlannarReflectionTest.cs 挂载在平面对象上

// https://www.bilibili.com/video/BV1TA4y1D7s4/?spm_id_from=333.999.0.0&vd_source=5672eeb8a9721da01495e313f0dff6c2
// https://zhuanlan.zhihu.com/p/493766119
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class PlannarReflectionTest : MonoBehaviour {

    public LayerMask reflectMask = -1;

    [SerializeField] private MeshRenderer m_targetPlaneRenderer;
    [SerializeField] private int m_targetTextureWidth = 1024;
    [SerializeField] private string m_reflectTexName = "_MirrorReflectTex";
    [SerializeField] private float m_scale = 1.0f;
    [HideInInspector] private float m_clipPlaneOffset = 0.01f;

    private Camera m_cameraMain;
    private Transform m_cameraMainTransform;
    private Camera m_cameraReflection;
    private Transform m_cameraReflectionTransform;
    private RenderTexture m_targetTexture;
    private int m_reflectTexInt;
    private Vector3 m_planeNormal;
    private Vector3 m_planePosition;
    private Transform m_normalTransform;
    private Vector4 m_reflectionPlane;


    private void Awake() {
        m_cameraMain = Camera.main;
        m_cameraMainTransform = m_cameraMain.transform;

        var go = new GameObject("ReflectionCamera");
        m_cameraReflection = go.AddComponent<Camera>();
        m_cameraReflection.aspect = m_cameraMain.aspect;
        m_cameraReflection.fieldOfView = m_cameraMain.fieldOfView;
        m_cameraReflection.enabled = false;
        m_cameraReflection.depth = -10;
        //go.hideFlags = HideFlags.HideAndDontSave;

        var cameraData = go.AddComponent<UniversalAdditionalCameraData>();
        cameraData.requiresColorOption = CameraOverrideOption.Off;
        cameraData.requiresDepthOption = CameraOverrideOption.Off;
        cameraData.SetRenderer(0);

        m_cameraReflectionTransform = m_cameraReflection.transform;

        int newWidth = (int)(m_targetTextureWidth * m_scale);
        int newHeight = (int)(newWidth * ((float)Screen.height / Screen.width));
        m_targetTexture = new RenderTexture(newWidth, newHeight, 24);
        //m_targetTexture.antiAliasing = 4;
        m_targetTexture.format = RenderTextureFormat.ARGB32;
        m_cameraReflection.targetTexture = m_targetTexture;
        m_cameraReflection.cullingMask = reflectMask.value;

        m_normalTransform = new GameObject("Normal").transform;
        var planeTransform = m_targetPlaneRenderer.transform;
        m_normalTransform.SetPositionAndRotation(planeTransform.position, planeTransform.rotation);
        m_normalTransform.SetParent(planeTransform);
        m_planePosition = m_normalTransform.position;
        m_planeNormal = m_normalTransform.up;
        m_cameraReflection.transform.SetParent(m_normalTransform);

        m_reflectTexInt = Shader.PropertyToID(m_reflectTexName);
        Shader.SetGlobalTexture(m_reflectTexName, m_targetTexture);

    }

    private void OnEnable() {
        RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering;
    }

    private void OnDisable() {
        RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
    }

    private static void CalculateReflectionMatrix(ref Matrix4x4 reflectionMat, ref Vector4 plane) {
        reflectionMat.m00 = (1F - 2F * plane[0] * plane[0]);
        reflectionMat.m01 = (-2F * plane[0] * plane[1]);
        reflectionMat.m02 = (-2F * plane[0] * plane[2]);
        reflectionMat.m03 = (-2F * plane[3] * plane[0]);

        reflectionMat.m10 = (-2F * plane[1] * plane[0]);
        reflectionMat.m11 = (1F - 2F * plane[1] * plane[1]);
        reflectionMat.m12 = (-2F * plane[1] * plane[2]);
        reflectionMat.m13 = (-2F * plane[3] * plane[1]);

        reflectionMat.m20 = (-2F * plane[2] * plane[0]);
        reflectionMat.m21 = (-2F * plane[2] * plane[1]);
        reflectionMat.m22 = (1F - 2F * plane[2] * plane[2]);
        reflectionMat.m23 = (-2F * plane[3] * plane[2]);

        reflectionMat.m30 = 0F;
        reflectionMat.m31 = 0F;
        reflectionMat.m32 = 0F;
        reflectionMat.m33 = 1F;
    }

    private void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) {
        if (camera.cameraType == CameraType.Reflection || camera.cameraType == CameraType.Preview) return;

        // 判断相机是不是在法线下方,如果在下方就不做渲染了
        Vector3 localPos = m_normalTransform.worldToLocalMatrix.MultiplyPoint3x4(m_cameraMainTransform.position);
        if (localPos.y < 0) return;

        // 调整位置
        // 首先计算反射矩阵
        // 法线
        Vector3 normal = m_normalTransform.up;
        // 平面上一个点的位置
        Vector3 pos = m_normalTransform.position;

        // 获取反射面
        float d = -Vector3.Dot(normal, pos) - m_clipPlaneOffset;
        m_reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d);
        var reflection = Matrix4x4.identity;
        reflection *= Matrix4x4.Scale(new Vector3(1, -1, 1));
        // 计算反射矩阵
        CalculateReflectionMatrix(ref reflection, ref m_reflectionPlane);

        // 直接计算世界到相机矩阵
        Matrix4x4 worldToCameraMatrix = m_cameraMain.worldToCameraMatrix * reflection;
        m_cameraReflection.worldToCameraMatrix = worldToCameraMatrix;

        // m_cameraReflectionTransform.eulerAngles = m_cameraMainTransform.eulerAngles;
        // Vector3 localEuler = m_cameraReflectionTransform.localEulerAngles;
        // localEuler.x *= -1;
        // localEuler.z *= -1;
        // localEuler.y *= -1;
        // m_cameraReflectionTransform.localEulerAngles = localEuler;
        // m_cameraReflectionTransform.localPosition = localPos;

        // 计算相机空间下的斜切平面
        Vector3 offsetPos = pos + normal * m_clipPlaneOffset;
        Vector3 cpos = worldToCameraMatrix.MultiplyPoint3x4(offsetPos);
        Vector3 cnormal = worldToCameraMatrix.MultiplyVector(normal).normalized;
        // 通过斜切面算投影矩阵
        Vector4 clipPlane = new Vector4(cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos, cnormal));
        m_cameraReflection.projectionMatrix = m_cameraMain.CalculateObliqueMatrix(clipPlane);
        //m_cameraReflection.projectionMatrix = CalculateObliqueMatrix(m_cameraMain, clipPlane);

        GL.invertCulling = true;
        UniversalRenderPipeline.RenderSingleCamera(context, m_cameraReflection);
        GL.invertCulling = false;
        Shader.SetGlobalTexture(m_reflectTexName, m_targetTexture);
    }

    // private Matrix4x4 CalculateObliqueMatrix(Camera cam, Vector4 clipPlane) {
    //     Matrix4x4 projectionMatrix= cam.projectionMatrix;
    //     Vector4 qClip = new Vector4(Mathf.Sign(clipPlane.x), Mathf.Sign(clipPlane.y), 1f, 1f);
    //     Vector4 qView = projectionMatrix.inverse.MultiplyPoint(qClip);
    //
    //     Vector4 scaledPlane = clipPlane * 2.0f / Vector4.Dot(clipPlane, qView);
    //    
    //     Vector4 m3 = scaledPlane - projectionMatrix.GetRow(3);
    //
    //     Matrix4x4 newM = projectionMatrix;
    //     newM.SetRow(2, m3);
    //     
    //     return newM;
    // }
}

平面对象使用的材质的ShaderGraph(Unity 2019.4.28f1c1):
image

标签:反射,Vector3,2F,private,Unity,plane,URP,cameraReflection,reflectionMat
From: https://www.cnblogs.com/kingBook/p/17170406.html

相关文章

  • C#基于HSL批量读取三菱PLC地址 反射/数据写入Model实体类
    usingHslCommunication;usingHslCommunication.Profinet.Melsec;usingNewtonsoft.Json;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usin......
  • 2023-03-01 react-native 实现 复制功能 @react-native-community/clipboard 报错:Type
    我的react-native(下称rn)版本为0.68,要实现这个功能主要用到rn的clipboard,在21年的时候他就已经提示clipboard会在未来的版本中上去掉,官方的建议是不要再从react-native引入,......
  • Java反射入门
    1.概述反射就是在运行状态,对于任意一个类,都可以直达这个类的属性和方法;对于任何一个对象,都可以调用它的任意一个方法和属性。而对于官方的解释是,反射允许对封装类的字段、......
  • java反射机制
    JAVA反射机制-----copy自p牛的java安全漫谈反射是⼤多数语⾔⾥都必不可少的组成部分,对象可以通过反射获取他的类,类可以通过反射拿到所有⽅法(包括私有),拿到的⽅法可以调⽤,......
  • Windows平台Unity Camera场景实现轻量级RTSP服务和RTMP推送
    技术背景随着VR技术在医疗、军事、农业、学校、景区、消防、公共安全、研学机构、展厅展馆,商场等场所普及,开发者对Unity平台下的直播体验提出了更高的要求。技术实现Unity平......
  • unity study 2
    使用unitystore寻找素材,编辑素材,并且用c#为我的人物添加了简单的移动动作,为场景和人物添加刚体,使其具有重力。usingSystem.Collections;usingSystem.Collections.Generi......
  • python getattr 反射的使用
    前言反射的本质是通过字符串去调用某对对象的方法/属性,或者调用模块中的函数等。python中提供了四个重要的方法getattr获取对象属性/对象方法hasattr判断对象是否有对......
  • unity 阿拉伯数字转中文汉字
    直接调用即可代码如下: usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;usingSystem.Text;usingUnityEngine;publicclassToolS......
  • Unity URP Shader 基础光照
    函数GetMainLight()返回一个数据结构LightstructLight{half3direction;//颜色&强度half3color;//方向halfdistanceAttenuation;//距......
  • Proxifier配合burp抓包但是burp收不到响应包解决思路
    题记        最近公司的项目比较特殊,不是传统的在web端的测试。而是客户给了一个exe,安装在电脑之后需要登录在工作台点击相关系统测试,点击相关系统后会在exe内部......