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
}
}
}