URP 镜面

资源绑定 下载
在这里插入图片描述

namespace UnityEngine.Rendering.Universal
{       
    [ExecuteInEditMode]
    public class PlanarURP : MonoBehaviour
    {
        public bool VR = false;
        public int ReflectionTexResolution = 512;
        public float Offset = 0.0f;
        [Range(0, 1)]
        public float ReflectionAlpha = 0.5f;
        public bool BlurredReflection;
        public LayerMask LayersToReflect = -1;

        private Camera reflectionCamera;
        private RenderTexture reflectionTexture = null, reflectionTextureRight = null;
        private static bool isRendering = false;
        private Material material;
        private static readonly int reflectionTexString = Shader.PropertyToID("_ReflectionTex");
        private static readonly int reflectionTexRString = Shader.PropertyToID("_ReflectionTexRight");
        private static readonly int reflectionAlphaString = Shader.PropertyToID("_RefAlpha");
        private static readonly string blurString = "BLUR";
        private static readonly string vrString = "VRon";
        private Matrix4x4 reflectionMatrix;
        private Vector4 reflectionPlane;
        private Vector3 posistion;
        private Vector3 normal;
        private Matrix4x4 projection;
        private Vector4 oblique;
        private Matrix4x4 worldToCameraMatrix;
        private Vector3 clipNormal;
        private Vector4 clipPlane;
        private Vector3 oldPosition;
        Vector3 eulerAngles;


        void OnEnable()
        {
            RenderPipelineManager.beginCameraRendering += this.RenderObject;

            Start();
        }
        

        private void OnDisable()
        {
            RenderPipelineManager.beginCameraRendering -= this.RenderObject;
            if (reflectionTexture)
            {
                RemoveObject(reflectionTexture);
                reflectionTexture = null;
            }
            if (reflectionTextureRight)
            {
                RemoveObject(reflectionTextureRight);
                reflectionTextureRight = null;
            }
            if (reflectionCamera)
            {
                RemoveObject(reflectionCamera.gameObject);
                reflectionCamera = null;
            }
        }

        public void Start()
        {
            material = GetComponent<Renderer>().sharedMaterials[0];
            QualitySettings.pixelLightCount = 0;

            var go = new GameObject(GetInstanceID().ToString(), typeof(Camera), typeof(Skybox));
            reflectionCamera = go.GetComponent<Camera>();
            var lwrpCamData = go.AddComponent(typeof(UniversalAdditionalCameraData)) as UniversalAdditionalCameraData;
            lwrpCamData.renderShadows = false;
            lwrpCamData.requiresColorOption = CameraOverrideOption.Off;
            lwrpCamData.requiresDepthOption = CameraOverrideOption.Off;
            reflectionCamera.enabled = false;
            reflectionCamera.transform.position = transform.position;
            reflectionCamera.transform.rotation = transform.rotation;
            reflectionCamera.cullingMask = ~(1 << 4) & LayersToReflect.value;
            reflectionCamera.cameraType = CameraType.Reflection;

            go.hideFlags = HideFlags.HideAndDontSave;

            if (reflectionTexture)
            {
                RemoveObject(reflectionTexture);
            }

            reflectionTexture = new RenderTexture(ReflectionTexResolution, ReflectionTexResolution, 16)
            {
                isPowerOfTwo = true,
                hideFlags = HideFlags.DontSave
            };

            if (reflectionTextureRight)
            {
                RemoveObject(reflectionTextureRight);
            }

            reflectionTextureRight = new RenderTexture(ReflectionTexResolution, ReflectionTexResolution, 16)
            {
                isPowerOfTwo = true,
                hideFlags = HideFlags.DontSave
            };
        }

        void RenderObject(ScriptableRenderContext context, Camera cam)
        {
            if (isRendering)
            {
                return;
            }

            isRendering = true;
            posistion = transform.position;
            normal = transform.up;

            reflectionCamera.clearFlags = cam.clearFlags;
            reflectionCamera.backgroundColor = cam.backgroundColor;
            reflectionCamera.farClipPlane = cam.farClipPlane;
            reflectionCamera.nearClipPlane = cam.nearClipPlane;
            reflectionCamera.orthographic = cam.orthographic;
            reflectionCamera.fieldOfView = cam.fieldOfView;
            reflectionCamera.aspect = cam.aspect;
            reflectionCamera.orthographicSize = cam.orthographicSize;

            if (cam.clearFlags == CameraClearFlags.Skybox)
            {
                var sky = cam.GetComponent(typeof(Skybox)) as Skybox;
                var mysky = reflectionCamera.GetComponent(typeof(Skybox)) as Skybox;
                if (!sky || !sky.material)
                {
                    mysky.enabled = false;
                }
                else
                {
                    mysky.enabled = true;
                    mysky.material = sky.material;
                }
            }

            reflectionPlane = new Vector4(normal.x, normal.y, normal.z, -Vector3.Dot(normal, posistion) - Offset);

            reflectionMatrix.m00 = (1F - 2F * reflectionPlane[0] * reflectionPlane[0]);
            reflectionMatrix.m01 = (-2F * reflectionPlane[0] * reflectionPlane[1]);
            reflectionMatrix.m02 = (-2F * reflectionPlane[0] * reflectionPlane[2]);
            reflectionMatrix.m03 = (-2F * reflectionPlane[3] * reflectionPlane[0]);
            reflectionMatrix.m10 = (-2F * reflectionPlane[1] * reflectionPlane[0]);
            reflectionMatrix.m11 = (1F - 2F * reflectionPlane[1] * reflectionPlane[1]);
            reflectionMatrix.m12 = (-2F * reflectionPlane[1] * reflectionPlane[2]);
            reflectionMatrix.m13 = (-2F * reflectionPlane[3] * reflectionPlane[1]);
            reflectionMatrix.m20 = (-2F * reflectionPlane[2] * reflectionPlane[0]);
            reflectionMatrix.m21 = (-2F * reflectionPlane[2] * reflectionPlane[1]);
            reflectionMatrix.m22 = (1F - 2F * reflectionPlane[2] * reflectionPlane[2]);
            reflectionMatrix.m23 = (-2F * reflectionPlane[3] * reflectionPlane[2]);
            reflectionMatrix.m30 = 0F;
            reflectionMatrix.m31 = 0F;
            reflectionMatrix.m32 = 0F;
            reflectionMatrix.m33 = 1F;

            oldPosition = cam.transform.position;
            reflectionCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflectionMatrix;

            worldToCameraMatrix = reflectionCamera.worldToCameraMatrix;
            clipNormal = worldToCameraMatrix.MultiplyVector(normal).normalized;
            clipPlane = new Vector4(clipNormal.x, clipNormal.y, clipNormal.z, -Vector3.Dot(worldToCameraMatrix.MultiplyPoint(posistion + normal * Offset), clipNormal));

            if (!VR)
            {
                RenderObjectCamera(cam.projectionMatrix, false);
                material.DisableKeyword(vrString);
                GL.invertCulling = true;
                reflectionCamera.transform.position = reflectionMatrix.MultiplyPoint(oldPosition);
                eulerAngles = cam.transform.eulerAngles;
                reflectionCamera.transform.eulerAngles = new Vector3(0, eulerAngles.y, eulerAngles.z);
                UniversalRenderPipeline.RenderSingleCamera(context, reflectionCamera);
                reflectionCamera.transform.position = oldPosition;
                GL.invertCulling = false;
                material.SetTexture(reflectionTexString, reflectionTexture);
            }
            else
            {
                RenderObjectCamera(cam.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left), false);
                material.EnableKeyword(vrString);
                GL.invertCulling = true;
                reflectionCamera.transform.position = reflectionMatrix.MultiplyPoint(oldPosition);
                eulerAngles = cam.transform.eulerAngles;
                reflectionCamera.transform.eulerAngles = new Vector3(0, eulerAngles.y, eulerAngles.z);
                UniversalRenderPipeline.RenderSingleCamera(context, reflectionCamera);
                reflectionCamera.transform.position = oldPosition;
                GL.invertCulling = false;
                material.SetTexture(reflectionTexString, reflectionTexture);
                RenderObjectCamera(cam.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right), true);
                GL.invertCulling = true;
                reflectionCamera.transform.position = reflectionMatrix.MultiplyPoint(oldPosition);
                eulerAngles = cam.transform.eulerAngles;
                reflectionCamera.transform.eulerAngles = new Vector3(0, eulerAngles.y, eulerAngles.z);
                UniversalRenderPipeline.RenderSingleCamera(context, reflectionCamera);
                reflectionCamera.transform.position = oldPosition;
                GL.invertCulling = false;
                material.SetTexture(reflectionTexRString, reflectionTextureRight);
            }

            material.SetFloat(reflectionAlphaString, ReflectionAlpha);

            if (BlurredReflection)
            {
                material.EnableKeyword(blurString);
            }
            else
            {
                material.DisableKeyword(blurString);
            }

            isRendering = false;
        }

        void RemoveObject(Object obj)
        {
            if (Application.isEditor)
            {
                DestroyImmediate(obj);
            }
            else
            {
                Destroy(obj);
            }
        }

        private void RenderObjectCamera(Matrix4x4 projection, bool right)
        {
            oblique = clipPlane * (2.0F / (Vector4.Dot(clipPlane, projection.inverse * new Vector4(sgn(clipPlane.x), sgn(clipPlane.y), 1.0f, 1.0f))));
            projection[2] = oblique.x - projection[3];
            projection[6] = oblique.y - projection[7];
            projection[10] = oblique.z - projection[11];
            projection[14] = oblique.w - projection[15];
            reflectionCamera.projectionMatrix = projection;
            reflectionCamera.targetTexture = right ? reflectionTextureRight : reflectionTexture;
        }

        private static float sgn(float a)
        {
            return a > 0.0f ? 1.0f : a < 0.0f ? -1.0f : 0.0f;
        }
    }
}

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'

Shader "SupGames/PlanarReflectionURP/Diffuse"
{
	Properties{
		_Color("Color", Color) = (1,1,1,1)
		_MainTex("Main Texture", 2D) = "white" {}
		_MaskTex("Mask Texture", 2D) = "white" {}
		_BlurAmount("Blur Amount", Range(0,7)) = 1
		[Toggle(RECEIVE_SHADOWS)]
		_ReceiveShadows("Recieve Shadows", Float) = 0
	}
	SubShader{
		Tags {"RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "IgnoreProjector" = "True"}
		LOD 100

		Pass {
			Tags { "LightMode" = "UniversalForward" }

            Blend SrcAlpha OneMinusSrcAlpha

			HLSLPROGRAM
			#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
				
			#pragma vertex vert
			#pragma fragment frag
			#pragma shader_feature_local BLUR
			#pragma shader_feature_local VRon
			#pragma shader_feature RECEIVE_SHADOWS
			#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
			#pragma multi_compile _ LIGHTMAP_ON
			#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
			#pragma multi_compile_instancing
			#pragma multi_compile_fog

            TEXTURE2D(_MainTex);
			SAMPLER(sampler_MainTex);
			TEXTURE2D(_ReflectionTex);
			SAMPLER(sampler_ReflectionTex);
#ifdef VRon
			TEXTURE2D(_ReflectionTexRight);
			SAMPLER(sampler_ReflectionTexRight);
#endif
			TEXTURE2D(_MaskTex);
			SAMPLER(sampler_MaskTex);

			half _BlurAmount;
			half _RefAlpha;
			half4 _MainTex_ST;
			half4 _Color;
			half4 _ReflectionTex_TexelSize;

			struct Attributes
			{
				half4 pos : POSITION;
				half4 uv : TEXCOORD0;
				half4 normal : NORMAL;
				UNITY_VERTEX_INPUT_INSTANCE_ID
			};

			struct Varyings
			{
				half4 pos : SV_POSITION;
				half4 uv : TEXCOORD0;
				half4 normal : TEXCOORD1;
#ifdef LIGHTMAP_ON
				half3 lightmapUV : TEXCOORD2;
#else
				half4 vertexSH : TEXCOORD2;
#endif
#if defined(BLUR)
				half4 offset : TEXCOORD3;
#endif
#if defined(_MAIN_LIGHT_SHADOWS)
				half4 shadowCoord : TEXCOORD4;
#endif
#if defined(_ADDITIONAL_LIGHTS) || defined(_ADDITIONAL_LIGHTS_VERTEX)
				half3 lightData : TEXCOORD5;
#endif
				UNITY_VERTEX_INPUT_INSTANCE_ID
				UNITY_VERTEX_OUTPUT_STEREO
			};

			Varyings vert(Attributes i)
			{
				Varyings o = (Varyings)0;
				UNITY_SETUP_INSTANCE_ID(i);
				UNITY_TRANSFER_INSTANCE_ID(i, o);
				UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
				o.uv.xy = TRANSFORM_TEX(i.uv, _MainTex);
				o.normal.xyz = normalize(mul(i.normal, unity_WorldToObject).xyz);
				half4 ws = mul(unity_ObjectToWorld, i.pos);
				o.pos = mul(unity_MatrixVP, ws);
				half4 scrPos = ComputeScreenPos(o.pos);
				o.uv.zw = scrPos.xy;
				o.normal.w = scrPos.w;
#if defined(BLUR)
				half2 offset = _ReflectionTex_TexelSize.xy * _BlurAmount;
				o.offset = half4(-offset, offset);
#endif
#if defined(_MAIN_LIGHT_SHADOWS)
				o.shadowCoord = TransformWorldToShadowCoord(ws.xyz);
#endif
#ifdef LIGHTMAP_ON
				o.lightmapUV.xy = i.uv.zw * unity_LightmapST.xy + unity_LightmapST.zw;
				o.lightmapUV.z = ComputeFogFactor(o.pos.z);
#else
				o.vertexSH.xyz = SampleSHVertex(i.normal.xyz);
				o.vertexSH.w = ComputeFogFactor(o.pos.z);
#endif
#ifdef _ADDITIONAL_LIGHTS_VERTEX
				o.lightData = half3(0.0h, 0.0h, 0.0h);
				uint lightsCount = GetAdditionalLightsCount();
				for (uint lightIndex = 0u; lightIndex < lightsCount; ++lightIndex)
				{
					Light light = GetAdditionalLight(lightIndex, ws.xyz);
					o.lightData += light.color * light.distanceAttenuation * saturate(dot(o.normal.xyz, light.direction));
				}
#endif
#ifdef _ADDITIONAL_LIGHTS
				o.lightData = ws.xyz;
#endif
				return o;
			}

			half4 frag(Varyings i) : SV_Target
			{
				UNITY_SETUP_INSTANCE_ID(i);
				UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
				half3 diffuseReflection = _MainLightColor.rgb * dot(i.normal.xyz, _MainLightPosition.xyz);

				half3 bakedGI = SAMPLE_GI(i.lightmapUV.xy, i.vertexSH.xyz, i.normal.xyz);
#if defined(_MAIN_LIGHT_SHADOWS) && defined(RECEIVE_SHADOWS)
				half3 realtimeShadow = lerp(bakedGI, max(bakedGI - diffuseReflection * (1.0h - MainLightRealtimeShadow(i.shadowCoord)), _SubtractiveShadowColor.xyz), _MainLightShadowData.x);
				bakedGI = min(bakedGI, realtimeShadow);
#endif
				half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv.xy);
				half4 mask = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex, i.uv.xy);
				i.uv.zw /= i.normal.w;
				half4 reflection = SAMPLE_TEXTURE2D(_ReflectionTex, sampler_ReflectionTex, i.uv.zw);
#if defined(BLUR)
				i.offset /= i.normal.w;
				i.offset = half4(i.uv.zz + i.offset.xz, i.uv.ww + i.offset.yw);
				reflection += SAMPLE_TEXTURE2D(_ReflectionTex, sampler_ReflectionTex, i.offset.xz);
				reflection += SAMPLE_TEXTURE2D(_ReflectionTex, sampler_ReflectionTex, i.offset.xw);
				reflection += SAMPLE_TEXTURE2D(_ReflectionTex, sampler_ReflectionTex, i.offset.yz);
				reflection += SAMPLE_TEXTURE2D(_ReflectionTex, sampler_ReflectionTex, i.offset.yw);
				reflection *= 0.2h;
#endif
#ifdef VRon
				half4 reflectionr = SAMPLE_TEXTURE2D(_ReflectionTexRight, sampler_ReflectionTexRight, i.uv.zw);
#ifdef BLUR
				reflectionr += SAMPLE_TEXTURE2D(_ReflectionTexRight, sampler_ReflectionTexRight, i.offset.xz);
				reflectionr += SAMPLE_TEXTURE2D(_ReflectionTexRight, sampler_ReflectionTexRight, i.offset.xw);
				reflectionr += SAMPLE_TEXTURE2D(_ReflectionTexRight, sampler_ReflectionTexRight, i.offset.yz);
				reflectionr += SAMPLE_TEXTURE2D(_ReflectionTexRight, sampler_ReflectionTexRight, i.offset.yw);
				reflectionr *= 0.2h;
#endif
				reflection = lerp(reflection, reflectionr, unity_StereoEyeIndex);
#endif
#ifdef _ADDITIONAL_LIGHTS
				uint pixelLightCount = GetAdditionalLightsCount();
				for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
				{
					Light light = GetAdditionalLight(lightIndex, i.lightData.xyz);
					diffuseReflection += light.color * light.distanceAttenuation * light.shadowAttenuation * saturate(dot(i.normal.xyz, light.direction));
				}
#endif
#ifdef _ADDITIONAL_LIGHTS_VERTEX
				diffuseReflection += i.lightData;
#endif
				color.rgb *= (diffuseReflection + bakedGI);
#ifdef LIGHTMAP_ON
				color.rgb = MixFog(color.rgb, i.lightmapUV.z);
#else
				color.rgb = MixFog(color.rgb, i.vertexSH.w);
#endif
				return (lerp(color, reflection, _RefAlpha * mask.r) + lerp(reflection, color, 1 - _RefAlpha * mask.r))*_Color * 0.5h;
			}
			ENDHLSL
		}
	}
}

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部