diff --git a/Assets/Prisma.unity b/Assets/Prisma.unity index 9ee2910..0cc06f3 100644 --- a/Assets/Prisma.unity +++ b/Assets/Prisma.unity @@ -2451,6 +2451,7 @@ Transform: - {fileID: 895455914} - {fileID: 999185933} - {fileID: 1450734907} + - {fileID: 1107727447} m_Father: {fileID: 0} m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -3288,15 +3289,15 @@ Light: m_GameObject: {fileID: 390130554} m_Enabled: 1 serializedVersion: 8 - m_Type: 1 + m_Type: 0 m_Color: {r: 1, g: 1, b: 1, a: 1} - m_Intensity: 0.2 - m_Range: 10 - m_SpotAngle: 30 + m_Intensity: 0.6 + m_Range: 25 + m_SpotAngle: 50 m_CookieSize: 10 m_Shadows: m_Type: 2 - m_Resolution: -1 + m_Resolution: 1 m_CustomResolution: -1 m_Strength: 1 m_Bias: 0.05 @@ -3323,7 +3324,7 @@ Transform: m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 390130554} m_LocalRotation: {x: 0.008726536, y: 0, z: 0, w: 0.9999619} - m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalPosition: {x: 0, y: 3, z: -10} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 659405360} @@ -3761,13 +3762,13 @@ Light: serializedVersion: 8 m_Type: 0 m_Color: {r: 1, g: 1, b: 1, a: 1} - m_Intensity: 1.4 + m_Intensity: 1.64 m_Range: 14 m_SpotAngle: 40 m_CookieSize: 10 m_Shadows: m_Type: 2 - m_Resolution: -1 + m_Resolution: 0 m_CustomResolution: -1 m_Strength: 1 m_Bias: 0.01 @@ -11415,6 +11416,51 @@ MonoBehaviour: m_CallState: 2 m_TypeName: Klak.Wiring.NodeBase+VoidEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null +--- !u!1 &1107727445 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1107727447} + - component: {fileID: 1107727446} + m_Layer: 0 + m_Name: Shadow Slicer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1107727446 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1107727445} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41fef7dd5c8b7a54fa30a95193c69a80, type: 3} + m_Name: + m_EditorClassIdentifier: + _baseCamera: {fileID: 199947338} + _targetTexture: {fileID: 8400000, guid: 847b7e8511b6e454c86a6b84397f298c, type: 2} + _albedo: {r: 0.84313726, g: 0.84313726, b: 0.84313726, a: 0} + _quadMesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} + _slicerShader: {fileID: 4800000, guid: db41ffe7fccd2c843b554ecae7e1f07b, type: 3} +--- !u!4 &1107727447 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1107727445} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1.9345, z: 3.3215} + m_LocalScale: {x: 9.1, y: 3.869, z: 1} + m_Children: [] + m_Father: {fileID: 310351456} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1116142349 GameObject: m_ObjectHideFlags: 0 @@ -13788,13 +13834,13 @@ Light: serializedVersion: 8 m_Type: 0 m_Color: {r: 1, g: 1, b: 1, a: 1} - m_Intensity: 1.4 + m_Intensity: 1.64 m_Range: 14 m_SpotAngle: 40 m_CookieSize: 10 m_Shadows: m_Type: 2 - m_Resolution: -1 + m_Resolution: 0 m_CustomResolution: -1 m_Strength: 1 m_Bias: 0.01 @@ -14697,7 +14743,7 @@ Light: m_CookieSize: 10 m_Shadows: m_Type: 2 - m_Resolution: -1 + m_Resolution: 2 m_CustomResolution: -1 m_Strength: 1 m_Bias: 0.01 @@ -14810,7 +14856,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!20 &1450734906 Camera: m_ObjectHideFlags: 0 diff --git a/Assets/Prisma/Scripts/ShadowSlicer.cs b/Assets/Prisma/Scripts/ShadowSlicer.cs new file mode 100644 index 0000000..2d8be8d --- /dev/null +++ b/Assets/Prisma/Scripts/ShadowSlicer.cs @@ -0,0 +1,118 @@ +using UnityEngine; +using UnityEngine.Rendering; + +namespace Prisma +{ + // + // Shadow Slicer + // + // In the previous versions of the Pepper's ghost rig, I used a secondary + // camera to render shadows on the background wall. This is very costly + // because it needs generating whole shadow maps twice (Unity never shares + // shadow maps between cameras). + // + // This "Shadow Slicer" is designed to eliminate the cost of the secondary + // camera. It renders the shadows on the wall with reusing the shadow maps + // generated by the main camera. + // + // How it works: The shadow slicer renders the shadows by hijacking the + // forward-opaque pass of the main camera -- the other parts of this + // project only use the deferred shading pass, so we can safely mess it up! + // + // 1. (Before Forward Opaque) Make a backup of the color buffer. + // 2. (Forward Base) Clear the color buffer with a full-screen quad. + // 3. (Forward Add) Draw a full-screen quad with shadow maps. + // 4. (After Forward Opaque) Retrieve the results and restore the backup. + // + // One of the biggest disadvantages of this approach is that we can't use + // directional lights with it (in Unity 5.x, shadow maps with directional + // lights are flatten into screen-space shadow masks while rendering, so + // we can't "slice" these shadows in the later passes). + // + public class ShadowSlicer : MonoBehaviour + { + #region Exposed attributes + + [SerializeField] Camera _baseCamera; + [SerializeField] RenderTexture _targetTexture; + [SerializeField, ColorUsage(false)] Color _albedo = Color.white; + + #endregion + + #region Built-in resources + + [SerializeField, HideInInspector] Mesh _quadMesh; + [SerializeField, HideInInspector] Shader _slicerShader; + + #endregion + + #region Private objects + + Material _slicerMaterial; + RenderTexture _backupBuffer; + CommandBuffer _backupCommand; + CommandBuffer _restoreCommand; + + #endregion + + #region MonoBehaviour functions + + void OnEnable() + { + var width = _baseCamera.pixelWidth; + var height = _baseCamera.pixelHeight; + + _backupBuffer = RenderTexture.GetTemporary(width, height, 0); + + if (_backupCommand == null) + { + _backupCommand = new CommandBuffer(); + _backupCommand.name = "Shadow Slicer (Backup)"; + _backupCommand.Blit(BuiltinRenderTextureType.CurrentActive, _backupBuffer); + } + + if (_restoreCommand == null) + { + _restoreCommand = new CommandBuffer(); + _restoreCommand.name = "Shadow Slicer (Restore)"; + _restoreCommand.Blit(BuiltinRenderTextureType.CurrentActive, _targetTexture); + _restoreCommand.Blit(_backupBuffer, BuiltinRenderTextureType.CameraTarget); + } + + _baseCamera.AddCommandBuffer(CameraEvent.BeforeForwardOpaque, _backupCommand); + _baseCamera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, _restoreCommand); + } + + void OnDisable() + { + if (_baseCamera != null) + { + _baseCamera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, _backupCommand); + _baseCamera.RemoveCommandBuffer(CameraEvent.AfterForwardOpaque, _restoreCommand); + } + } + + void OnDestroy() + { + if (_slicerMaterial != null) Destroy(_slicerMaterial); + if (_backupBuffer != null) RenderTexture.ReleaseTemporary(_backupBuffer); + if (_backupCommand != null) _backupCommand.Dispose(); + if (_restoreCommand != null) _restoreCommand.Dispose(); + } + + void Update() + { + if (_slicerMaterial == null) + _slicerMaterial = new Material(_slicerShader); + + _slicerMaterial.SetColor("_Color", _albedo); + + Graphics.DrawMesh( + _quadMesh, transform.localToWorldMatrix, _slicerMaterial, + gameObject.layer, _baseCamera + ); + } + + #endregion + } +} diff --git a/Assets/Prisma/Scripts/ShadowSlicer.cs.meta b/Assets/Prisma/Scripts/ShadowSlicer.cs.meta new file mode 100644 index 0000000..3ab0ec5 --- /dev/null +++ b/Assets/Prisma/Scripts/ShadowSlicer.cs.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 41fef7dd5c8b7a54fa30a95193c69a80 +timeCreated: 1497456880 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: + - _targetCamera: {instanceID: 0} + - _targetTexture: {instanceID: 0} + - _quadMesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} + - _slicerShader: {fileID: 4800000, guid: db41ffe7fccd2c843b554ecae7e1f07b, type: 3} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prisma/Shaders/ShadowSlicer.shader b/Assets/Prisma/Shaders/ShadowSlicer.shader new file mode 100644 index 0000000..6d097ac --- /dev/null +++ b/Assets/Prisma/Shaders/ShadowSlicer.shader @@ -0,0 +1,83 @@ +// Shadow Slicer shader: See ShadowSlicer.cs for details. + +Shader "Hidden/Prisma/ShadowSlicer" +{ + Properties + { + _Color("", Color) = (1, 1, 1, 1) + } + SubShader + { + ZTest always ZWrite off + + // Forward base: draws black full-screen quad. + Pass + { + Tags { "LightMode" = "ForwardBase" } + + CGPROGRAM + + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + + float4 vert(float4 vertex : POSITION) : SV_POSITION + { + return float4(vertex.xy * float2(2, -2), 0, 1); + } + + fixed4 frag() : SV_Target + { + return 0; + } + + ENDCG + } + + // Forward add: + // renders a slice of a shadow volume with a full-screen quad. + Pass + { + Tags { "LightMode" = "ForwardAdd" } + + Blend One One + + CGPROGRAM + + #pragma vertex vert + #pragma fragment frag + + #pragma multi_compile_fwdadd_fullshadows + #pragma skip_variants DIRECTIONAL SHADOWS_SCREEN POINT_COOKIE DIRECTIONAL_COOKIE + + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "AutoLight.cginc" + + fixed4 _Color; + + struct v2f + { + float4 vertex : SV_POSITION; + float3 worldPos : TEXCOORD0; + }; + + v2f vert(float4 vertex : POSITION) + { + v2f o; + o.vertex = float4(vertex.xy * float2(2, -2), 0, 1); + o.worldPos = mul(unity_ObjectToWorld, vertex).xyz; + return o; + } + + half4 frag(v2f IN) : SV_Target + { + UNITY_LIGHT_ATTENUATION(atten, IN, IN.worldPos) + return half4(_Color.rgb * _LightColor0.rgb * atten, 1); + } + + ENDCG + } + } +} diff --git a/Assets/Prisma/Shaders/ShadowSlicer.shader.meta b/Assets/Prisma/Shaders/ShadowSlicer.shader.meta new file mode 100644 index 0000000..461b9b3 --- /dev/null +++ b/Assets/Prisma/Shaders/ShadowSlicer.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: db41ffe7fccd2c843b554ecae7e1f07b +timeCreated: 1497445773 +licenseType: Pro +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset index 74d7b53..d74737e 100644 --- a/ProjectSettings/GraphicsSettings.asset +++ b/ProjectSettings/GraphicsSettings.asset @@ -35,6 +35,7 @@ GraphicsSettings: - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} m_PreloadedShaders: [] m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index 2e457fd..0ff49fe 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -498,7 +498,8 @@ PlayerSettings: webGLUseEmbeddedResources: 0 webGLUseWasm: 0 webGLCompressionFormat: 1 - scriptingDefineSymbols: {} + scriptingDefineSymbols: + 1: platformArchitecture: {} scriptingBackend: {} incrementalIl2cppBuild: {}