Unity在BuildIn渲染管线下实现PlanarReflection的初级方法

36 篇文章 2 订阅
35 篇文章 1 订阅

首先是要创建一个反向摄像机,同时让该反向摄像机渲染的图像发送给反射平面的Shader来与原来的颜色叠加,代码参考如下:

using UnityEngine;

public class PlanarReflection : MonoBehaviour
{
	Camera m_ReflectionCamera;
	Camera m_MainCamera;

	RenderTexture m_RenderTarget;

	[SerializeField]
	GameObject m_ReflectionPlane;
	[SerializeField]
	Material m_FloorMaterial;

	[SerializeField]
	[Range(0f, 1f)]
	float m_ReflectionFactor = 0.5f;

	void Start()
	{
		GameObject reflectionCameraGo = new GameObject("ReflectionCamera");
		m_ReflectionCamera = reflectionCameraGo.AddComponent<Camera>();
		m_ReflectionCamera.enabled = false;

		m_MainCamera = Camera.main;

		m_RenderTarget = new RenderTexture(Screen.width, Screen.height, 24);
	}

	void Update()
	{
		m_FloorMaterial.SetFloat("_ReflectionFactor", m_ReflectionFactor);
	}

	void OnPreRender()
	{
		RenderReflection();
	}

	void RenderReflection()
	{
		m_ReflectionCamera.CopyFrom(m_MainCamera);

		Vector3 cameraDirectionWorldSpace = m_MainCamera.transform.forward;
		Vector3 cameraUpWorldSpace = m_MainCamera.transform.up;
		Vector3 cameraPositionWorldSpace = m_MainCamera.transform.position;

		Vector3 cameraDirectionPlaneSpace = m_ReflectionPlane.transform.InverseTransformDirection(cameraDirectionWorldSpace);
		Vector3 cameraUpPlaneSpace = m_ReflectionPlane.transform.InverseTransformDirection(cameraUpWorldSpace);
		Vector3 cameraPositionPlaneSpace = m_ReflectionPlane.transform.InverseTransformPoint(cameraPositionWorldSpace);

		cameraDirectionPlaneSpace.y *= -1f;
		cameraUpPlaneSpace.y *= -1f;
		cameraPositionPlaneSpace.y *= -1f;

		cameraDirectionWorldSpace = m_ReflectionPlane.transform.TransformDirection(cameraDirectionPlaneSpace);
		cameraUpWorldSpace = m_ReflectionPlane.transform.TransformDirection(cameraUpPlaneSpace);
		cameraPositionWorldSpace = m_ReflectionPlane.transform.TransformPoint(cameraPositionPlaneSpace);

		m_ReflectionCamera.transform.position = cameraPositionWorldSpace;
		m_ReflectionCamera.transform.LookAt(cameraPositionWorldSpace + cameraDirectionWorldSpace, cameraUpWorldSpace);

		Vector4 viewPlane = CameraSpacePlane(m_ReflectionCamera.worldToCameraMatrix, m_ReflectionPlane.transform.position, m_ReflectionPlane.transform.up);
		m_ReflectionCamera.projectionMatrix = m_ReflectionCamera.CalculateObliqueMatrix(viewPlane);

		m_ReflectionCamera.targetTexture = m_RenderTarget;
		m_ReflectionCamera.Render();

		m_FloorMaterial.SetTexture("_ReflectionTex", m_RenderTarget);
	}

	Vector4 CameraSpacePlane(Matrix4x4 worldToCameraMatrix, Vector3 pos, Vector3 normal)
	{
		Vector3 viewPos = worldToCameraMatrix.MultiplyPoint3x4(pos);
		Vector3 viewNormal = worldToCameraMatrix.MultiplyVector(normal).normalized;
		float w = -Vector3.Dot(viewPos, viewNormal);
		return new Vector4(viewNormal.x, viewNormal.y, viewNormal.z, w);
	}
}

其次是用于叠加反射颜色的Shader,对应的材质是添加给反射平面的。代码如下:

Shader "Custom/FloorTotal"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
        _ReflectionFactor("ReflectionFactor",Range(0,1)) = 0.5
        [Hide]_ReflectionTex("ReflectionTex",2D) = "White"{}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue"="Geometry+1"}
        LOD 200

        Stencil{
                Ref 1
                Comp always
                Pass replace
        }

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;
        sampler2D _ReflectionTex;

        struct Input
        {
            float2 uv_MainTex;
            float4 screenPos;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;
        float _ReflectionFactor;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            // Albedo comes from a texture tinted by color
            float2 uv = IN.screenPos.xy / IN.screenPos.w;
            uv.x = 1 - uv.x;
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color * (1 - _ReflectionFactor) +  _ReflectionFactor * tex2D(_ReflectionTex,uv);
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值