├── ProjectSettings ├── ProjectVersion.txt ├── ClusterInputManager.asset ├── PresetManager.asset ├── EditorBuildSettings.asset ├── NetworkManager.asset ├── TimeManager.asset ├── AudioManager.asset ├── EditorSettings.asset ├── TagManager.asset ├── DynamicsManager.asset ├── UnityConnectSettings.asset ├── NavMeshAreas.asset ├── Physics2DSettings.asset ├── GraphicsSettings.asset ├── QualitySettings.asset └── InputManager.asset ├── .gitignore ├── Assets ├── LightManager │ ├── Scripts │ │ ├── LightManagerFogLights.cs │ │ ├── LightManagerFogEllipsoids.cs │ │ ├── LightManager.cs.meta │ │ ├── LightManagerFogLights.cs.meta │ │ ├── LightManagerFogEllipsoids.cs.meta │ │ └── LightManager.cs │ ├── LightManagerFogEllipsoids.prefab.meta │ ├── LightManagerFogLights.prefab.meta │ ├── Scripts.meta │ ├── LightManagerFogLights.prefab │ └── LightManagerFogEllipsoids.prefab ├── VolumetricFog │ ├── Shaders │ │ ├── noise.png │ │ ├── Debug.shader.meta │ │ ├── Shadowmap.shader.meta │ │ ├── ApplyToOpaque.shader.meta │ │ ├── BlurShadowmap.shader.meta │ │ ├── CopyShadowParams.shader.meta │ │ ├── VolumetricFog.cginc.meta │ │ ├── Scatter.compute.meta │ │ ├── InjectLightingAndDensity.compute.meta │ │ ├── Shadowmap.shader │ │ ├── VolumetricFog.cginc │ │ ├── ApplyToOpaque.shader │ │ ├── CopyShadowParams.shader │ │ ├── Debug.shader │ │ ├── noise.png.meta │ │ ├── Scatter.compute │ │ ├── BlurShadowmap.shader │ │ └── InjectLightingAndDensity.compute │ ├── FogEllipsoid.prefab.meta │ ├── Editor.meta │ ├── Scripts.meta │ ├── Shaders.meta │ ├── Editor │ │ ├── FogLightEditor.cs.meta │ │ ├── VolumetricFogEditor.cs.meta │ │ ├── VolumetricFogEditor.cs │ │ └── FogLightEditor.cs │ ├── Scripts │ │ ├── FogEllipsoid.cs.meta │ │ ├── FogLight.DirectionalShadow.cs.meta │ │ ├── FogLight.cs.meta │ │ ├── VolumetricFog.cs.meta │ │ ├── FogEllipsoid.cs │ │ ├── FogLight.cs │ │ └── FogLight.DirectionalShadow.cs │ └── FogEllipsoid.prefab ├── Scenes │ ├── Area light.unity.meta │ ├── Materials │ │ ├── blck.mat.meta │ │ ├── StandardAlphaBlended-VolumetricFog.mat.meta │ │ ├── StandardAlphaBlended-VolumetricFog.shader.meta │ │ ├── StandardAlphaBlended-VolumetricFog.mat │ │ ├── StandardAlphaBlended-VolumetricFog.shader │ │ └── blck.mat │ ├── Transparency and point lights.unity.meta │ ├── Materials.meta │ ├── Tube lights and local fog density.unity.meta │ └── Tube lights with shadow planes and global fog density.unity.meta ├── Wind │ ├── Wind.prefab.meta │ ├── Scripts.meta │ ├── Scripts │ │ ├── Wind.cs.meta │ │ └── Wind.cs │ └── Wind.prefab ├── AreaLight │ ├── AreaLight.prefab.meta │ ├── Shaders │ │ ├── AreaLightSource.mat.meta │ │ ├── AreaLight.cginc.meta │ │ ├── AreaLight.shader.meta │ │ ├── AreaLightShadows.cginc.meta │ │ ├── AreaLight.shader │ │ ├── AreaLightShadows.cginc │ │ ├── AreaLightSource.mat │ │ └── AreaLight.cginc │ ├── Scripts.meta │ ├── Shaders.meta │ ├── Scripts │ │ ├── AreaLight.Direct.cs.meta │ │ ├── AreaLight.Shadow.cs.meta │ │ ├── AreaLightLUT.GGX.cs.meta │ │ ├── AreaLightLUT.Load.cs.meta │ │ ├── AreaLightLUT.DisneyDiffuse.cs.meta │ │ ├── AreaLight.cs.meta │ │ ├── AreaLightLUT.Load.cs │ │ ├── AreaLight.Direct.cs │ │ ├── AreaLight.cs │ │ └── AreaLight.Shadow.cs │ └── AreaLight.prefab ├── TubeLight │ ├── TubeLight.prefab.meta │ ├── Shaders │ │ ├── TubeLightSource.mat.meta │ │ ├── TubeLight.cginc.meta │ │ ├── TubeLight.shader.meta │ │ ├── TubeLightAttenuation.cginc.meta │ │ ├── TubeLightShadowPlanes.cginc.meta │ │ ├── TubeLightShadowPlanes.cginc │ │ ├── TubeLightAttenuation.cginc │ │ ├── TubeLight.shader │ │ ├── TubeLightSource.mat │ │ └── TubeLight.cginc │ ├── Editor.meta │ ├── Scripts.meta │ ├── Shaders.meta │ ├── Editor │ │ ├── TubeLightEditor.cs.meta │ │ └── TubeLightEditor.cs │ ├── Scripts │ │ ├── TubeLightShadowPlane.cs.meta │ │ ├── TubeLight.cs.meta │ │ ├── TubeLightShadowPlane.cs │ │ └── TubeLight.cs │ └── TubeLight.prefab ├── Wind.meta ├── AreaLight.meta ├── MinValueAttribute │ ├── MinValueAttribute.cs │ ├── Editor.meta │ ├── MinValueAttribute.cs.meta │ └── Editor │ │ ├── MinValueDrawer.cs.meta │ │ └── MinValueDrawer.cs ├── Scenes.meta ├── TubeLight.meta ├── LightManager.meta ├── LightOverride.meta ├── VolumetricFog.meta ├── MinValueAttribute.meta └── LightOverride │ ├── LightOverride.cs.meta │ └── LightOverride.cs ├── LICENSE ├── Packages └── manifest.json └── README.md /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2018.3.0b5 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /Library 2 | /Temp 3 | /obj 4 | *.sln 5 | *.csproj 6 | .vscode/settings.json 7 | -------------------------------------------------------------------------------- /Assets/LightManager/Scripts/LightManagerFogLights.cs: -------------------------------------------------------------------------------- 1 | public class LightManagerFogLights : LightManager 2 | { 3 | 4 | } 5 | -------------------------------------------------------------------------------- /Assets/LightManager/Scripts/LightManagerFogEllipsoids.cs: -------------------------------------------------------------------------------- 1 | public class LightManagerFogEllipsoids : LightManager 2 | { 3 | 4 | } 5 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/VolumetricLighting/HEAD/Assets/VolumetricFog/Shaders/noise.png -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /ProjectSettings/PresetManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1386491679 &1 4 | PresetManager: 5 | m_ObjectHideFlags: 0 6 | m_DefaultList: [] 7 | -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: [] 8 | -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!149 &1 4 | NetworkManager: 5 | m_ObjectHideFlags: 0 6 | m_DebugLevel: 0 7 | m_Sendrate: 15 8 | m_AssetToPrefab: {} 9 | -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: 0.02 7 | Maximum Allowed Timestep: 0.33333334 8 | m_TimeScale: 1 9 | -------------------------------------------------------------------------------- /Assets/Scenes/Area light.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e4b4074801779784da23d0db51071030 3 | timeCreated: 1477663661 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Wind/Wind.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9efedcad2c8232b4fa0b974c01cae2c4 3 | timeCreated: 1447455658 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Scenes/Materials/blck.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 407b0765066496e4da88d97aa9205037 3 | timeCreated: 1432511050 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/AreaLight/AreaLight.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c946fa75949b4b0469e29c6e49bd3577 3 | timeCreated: 1450870880 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/TubeLight/TubeLight.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fdeb35bdab08b7442a67e36ffe2ff830 3 | timeCreated: 1444651113 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Wind.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3db076e37535ca74bba5011a34e1e7c0 3 | folderAsset: yes 4 | timeCreated: 1476957694 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/AreaLight.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 692b74bd11c622b4ab56587cf3ebc53a 3 | folderAsset: yes 4 | timeCreated: 1476957694 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/MinValueAttribute/MinValueAttribute.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class MinValueAttribute : PropertyAttribute 4 | { 5 | public float min; 6 | 7 | public MinValueAttribute (float min) 8 | { 9 | this.min = min; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Assets/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 08cc8bb0acab7fa4f89387fd57ea92f5 3 | folderAsset: yes 4 | timeCreated: 1477661017 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/TubeLight.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7af1fbf5b0c3fc34e929a665f1822f98 3 | folderAsset: yes 4 | timeCreated: 1476957694 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/FogEllipsoid.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: df830a50a2bb02541a47504c9da3b3cf 3 | timeCreated: 1447329149 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/AreaLight/Shaders/AreaLightSource.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1eb056d70e23cc34a9e926d8c8c887a5 3 | timeCreated: 1450296949 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/LightManager.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 37a7d2078af3b7645802711b72cbcfb1 3 | folderAsset: yes 4 | timeCreated: 1477430433 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/LightOverride.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d10a5eee313f53847b6aed96428c054d 3 | folderAsset: yes 4 | timeCreated: 1477430433 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Scenes/Transparency and point lights.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 915ed33d3a042174eb51699251f87c5b 3 | timeCreated: 1478261417 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/TubeLight/Shaders/TubeLightSource.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 86b3c638dc56298409890ac32f9e6baf 3 | timeCreated: 1446644410 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/VolumetricFog.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 40bc07addad39024a9ef54e341a25a68 3 | folderAsset: yes 4 | timeCreated: 1476957694 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Wind/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f3261b0719ca8b249992f74f94d3ffa0 3 | folderAsset: yes 4 | timeCreated: 1477748653 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/AreaLight/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 26b199722eb73ad45b1ee21d58a9242f 3 | folderAsset: yes 4 | timeCreated: 1477748665 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/AreaLight/Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d622c47de56b9e84e971b5a72b861f95 3 | folderAsset: yes 4 | timeCreated: 1477749207 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/LightManager/LightManagerFogEllipsoids.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 88ddc3de348eb9044aa7d0614809939e 3 | timeCreated: 1454679592 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/LightManager/LightManagerFogLights.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a81286e4a5a12aa41825352231edaae9 3 | timeCreated: 1454679202 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/MinValueAttribute.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9ad541daae932084a874bba45d821e60 3 | folderAsset: yes 4 | timeCreated: 1476957694 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Scenes/Materials.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 44021e8904d04fa4bab45700dd060f65 3 | folderAsset: yes 4 | timeCreated: 1477748594 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Scenes/Tube lights and local fog density.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 54a18da41a501694a8e1980a2a897da7 3 | timeCreated: 1477692305 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/TubeLight/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 95f79d7423b1c4239ba221be74ca9134 3 | folderAsset: yes 4 | timeCreated: 1446582841 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/TubeLight/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fa6f2ae72d2fc9643afe34db34a35a28 3 | folderAsset: yes 4 | timeCreated: 1477748611 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/TubeLight/Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b041de53e70b28e4fb9256c930c13615 3 | folderAsset: yes 4 | timeCreated: 1477749221 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/LightManager/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: de005349eca348945bb8d27456a32d16 3 | folderAsset: yes 4 | timeCreated: 1477748682 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/MinValueAttribute/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 32a49e8d55dc4c848ae0d5a0aca3b357 3 | folderAsset: yes 4 | timeCreated: 1447329667 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9d612dacdb3ca214c9322d7f9c288f22 3 | folderAsset: yes 4 | timeCreated: 1457126022 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dcf5e0fc0fb8d64458536282eee32001 3 | folderAsset: yes 4 | timeCreated: 1477748633 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f9f2001f237efb348b16ef606855bab7 3 | folderAsset: yes 4 | timeCreated: 1477749236 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Scenes/Materials/StandardAlphaBlended-VolumetricFog.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b92b0577b1e30bf4ab3b04c3e6a74994 3 | timeCreated: 1478261393 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/AreaLight/Shaders/AreaLight.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fd7e771f2b4bdf14da1d4e099b8bd629 3 | timeCreated: 1453121090 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/AreaLight/Shaders/AreaLight.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2b28be3523d190a41910088d1ee68ef7 3 | timeCreated: 1453120999 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Scenes/Tube lights with shadow planes and global fog density.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 272d3d2fab1f6784dae6c85bdf479508 3 | timeCreated: 1477693506 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/TubeLight/Shaders/TubeLight.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bea54fea6aabea841b90651d989d88f5 3 | timeCreated: 1452380090 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/TubeLight/Shaders/TubeLight.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2e6fd90941a3e3c458d01f851dca21ed 3 | timeCreated: 1442344786 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/Debug.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 91e29ad407521e447a7254f5c1ea9b54 3 | timeCreated: 1431963567 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/AreaLight/Shaders/AreaLightShadows.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eeb2994f509cea043bc495c62bc72a29 3 | timeCreated: 1456842264 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/Shadowmap.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c4cd42b134f7864fa579350e9cf6896 3 | timeCreated: 1432028591 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/TubeLight/Shaders/TubeLightAttenuation.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3d6df6428d576d147994b0b7ac0d5ea5 3 | timeCreated: 1456703457 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/TubeLight/Shaders/TubeLightShadowPlanes.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f4ec63bd62722b840b982641528198db 3 | timeCreated: 1457385992 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/ApplyToOpaque.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6f73df8e11615074dbf62a3a384af521 3 | timeCreated: 1432216767 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/BlurShadowmap.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 701192b62a7678549918bc87434699fe 3 | timeCreated: 1432227463 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/CopyShadowParams.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 33fc45db43408764c8dd7647b877e561 3 | timeCreated: 1463056552 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/VolumetricFog.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5353ac921ca28c4448781247e4f9ec3b 3 | timeCreated: 1452690568 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/Scatter.compute.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2a7c01c2354d03a4e9c31096bf130b6a 3 | timeCreated: 1432198206 4 | licenseType: Pro 5 | ComputeShaderImporter: 6 | currentBuildTarget: 5 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Scenes/Materials/StandardAlphaBlended-VolumetricFog.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9dca33cc83d85fd409e8d3dfc9db5676 3 | timeCreated: 1478225190 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/InjectLightingAndDensity.compute.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 55812fd61bd54104aa23612fc28bfeb8 3 | timeCreated: 1431967312 4 | licenseType: Pro 5 | ComputeShaderImporter: 6 | currentBuildTarget: 5 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Wind/Scripts/Wind.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 705fc1fdc327ad04787d9b3b7a2aefe6 3 | timeCreated: 1447455268 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/LightOverride/LightOverride.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 74f38ff2229b3664e979e3a59d7ace3f 3 | timeCreated: 1452857267 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/AreaLight/Scripts/AreaLight.Direct.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f166f8247b9668b45bd44bb7d17f3e1d 3 | timeCreated: 1453074905 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/AreaLight/Scripts/AreaLight.Shadow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 263b59280b7c4e04aa70d3c9cb1a5586 3 | timeCreated: 1455014110 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/AreaLight/Scripts/AreaLightLUT.GGX.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2b0041ac2ad0ef8459f7565f64f4d731 3 | timeCreated: 1453066169 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/AreaLight/Scripts/AreaLightLUT.Load.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0c08d6c4951e30c42a4bd6209323dfb8 3 | timeCreated: 1453070529 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/LightManager/Scripts/LightManager.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 172fcfd4ae7b9874ea684dc927b34a73 3 | timeCreated: 1454671716 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/MinValueAttribute/MinValueAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b2932d2cdf3aaea4abe51315dc89f761 3 | timeCreated: 1447329589 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/TubeLight/Editor/TubeLightEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 00a6ee99a4a9a44879507a5c4077d7a0 3 | timeCreated: 1446582855 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Editor/FogLightEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 93f87826f4342d7448c226b220a4342e 3 | timeCreated: 1457126034 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Scripts/FogEllipsoid.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 789ae5fef74e6754ab3c20bdeca67ad9 3 | timeCreated: 1447327681 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/MinValueAttribute/Editor/MinValueDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: af909d555c4764145b02bd06b0c9646d 3 | timeCreated: 1447329696 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/TubeLight/Scripts/TubeLightShadowPlane.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 66d8e50a047abb54aa901236f0ed84d2 3 | timeCreated: 1446129202 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Editor/VolumetricFogEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9dc42dc79f60fe8449ca035a77f732ae 3 | timeCreated: 1507493299 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/AreaLight/Scripts/AreaLightLUT.DisneyDiffuse.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9cbf86f9b2114924a91acc43796a307b 3 | timeCreated: 1454419446 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/LightManager/Scripts/LightManagerFogLights.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 01ae89c4c08f92f4fb90537335efa1ac 3 | timeCreated: 1454678969 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/LightManager/Scripts/LightManagerFogEllipsoids.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ed243fe90a2e7384f9f6f59acf71e19b 3 | timeCreated: 1454679513 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Scripts/FogLight.DirectionalShadow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f567a9d3b2b31ac4d818cea1e427a215 3 | timeCreated: 1460031458 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | m_Volume: 1 7 | Rolloff Scale: 1 8 | Doppler Factor: 1 9 | Default Speaker Mode: 2 10 | m_SampleRate: 0 11 | m_DSPBufferSize: 0 12 | m_VirtualVoiceCount: 512 13 | m_RealVoiceCount: 32 14 | m_SpatializerPlugin: 15 | m_DisableAudio: 0 16 | m_VirtualizeEffects: 1 17 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Editor/VolumetricFogEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | 3 | [CustomEditor(typeof(VolumetricFog))] 4 | [CanEditMultipleObjects] 5 | public class VolumetricFogEditor : Editor 6 | { 7 | override public void OnInspectorGUI() 8 | { 9 | if (!VolumetricFog.CheckSupport()) 10 | { 11 | EditorGUILayout.HelpBox(VolumetricFog.GetUnsupportedErrorMessage(), MessageType.Error); 12 | return; 13 | } 14 | 15 | DrawDefaultInspector(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Scripts/FogLight.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 097385f2a510795498370c4d62e61572 3 | timeCreated: 1463313191 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: 8 | - m_BlurShadowmapShader: {fileID: 4800000, guid: 701192b62a7678549918bc87434699fe, 9 | type: 3} 10 | - m_CopyShadowParamsShader: {fileID: 4800000, guid: 33fc45db43408764c8dd7647b877e561, 11 | type: 3} 12 | executionOrder: 0 13 | icon: {instanceID: 0} 14 | userData: 15 | assetBundleName: 16 | assetBundleVariant: 17 | -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 3 7 | m_ExternalVersionControlSupport: Visible Meta Files 8 | m_SerializationMode: 2 9 | m_WebSecurityEmulationEnabled: 0 10 | m_WebSecurityEmulationHostUrl: http://www.mydomain.com/mygame.unity3d 11 | m_DefaultBehaviorMode: 0 12 | m_SpritePackerMode: 2 13 | m_SpritePackerPaddingPower: 1 14 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd 15 | m_ProjectGenerationRootNamespace: 16 | -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | serializedVersion: 2 6 | tags: [] 7 | layers: 8 | - Default 9 | - TransparentFX 10 | - Ignore Raycast 11 | - 12 | - Water 13 | - UI 14 | - 15 | - 16 | - 17 | - 18 | - 19 | - 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | - 33 | - 34 | - 35 | - 36 | - 37 | - 38 | - 39 | - 40 | m_SortingLayers: 41 | - name: Default 42 | uniqueID: 0 43 | locked: 0 44 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/Shadowmap.shader: -------------------------------------------------------------------------------- 1 | Shader "Hidden/Shadowmap" { 2 | SubShader { 3 | Tags { "RenderType"="Opaque" } 4 | Pass 5 | { 6 | Fog { Mode Off } 7 | Cull Back 8 | CGPROGRAM 9 | #pragma vertex vert 10 | #pragma fragment frag 11 | #include "UnityCG.cginc" 12 | 13 | struct v2f 14 | { 15 | float4 pos : SV_POSITION; 16 | }; 17 | 18 | v2f vert (appdata_base v) 19 | { 20 | v2f o; 21 | o.pos = UnityObjectToClipPos (v.vertex); 22 | return o; 23 | } 24 | 25 | float4 frag(v2f i) : COLOR 26 | { 27 | return 0; 28 | } 29 | ENDCG 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Assets/AreaLight/Scripts/AreaLight.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 792909cacf2415c48a1d7eebef426b5d 3 | timeCreated: 1453121021 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: 8 | - m_Cube: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 9 | - m_ProxyShader: {fileID: 4800000, guid: 2b28be3523d190a41910088d1ee68ef7, type: 3} 10 | - m_Quad: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} 11 | - m_ShadowmapShader: {fileID: 4800000, guid: 2c4cd42b134f7864fa579350e9cf6896, type: 3} 12 | executionOrder: 0 13 | icon: {instanceID: 0} 14 | userData: 15 | assetBundleName: 16 | assetBundleVariant: 17 | -------------------------------------------------------------------------------- /Assets/TubeLight/Scripts/TubeLight.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5a3b99ed98424ea4587ec18d930a1d77 3 | timeCreated: 1444638222 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: 8 | - m_Sphere: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} 9 | - m_Capsule: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0} 10 | - m_ProxyShader: {fileID: 4800000, guid: 2e6fd90941a3e3c458d01f851dca21ed, type: 3} 11 | - m_SourceShader: {fileID: 10755, guid: 0000000000000000f000000000000000, type: 0} 12 | executionOrder: 0 13 | icon: {instanceID: 0} 14 | userData: 15 | assetBundleName: 16 | assetBundleVariant: 17 | -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Gravity: {x: 0, y: -9.81, z: 0} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_BounceThreshold: 2 10 | m_SleepThreshold: 0.005 11 | m_DefaultContactOffset: 0.01 12 | m_SolverIterationCount: 6 13 | m_SolverVelocityIterations: 1 14 | m_QueriesHitTriggers: 1 15 | m_EnableAdaptiveForce: 0 16 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 17 | -------------------------------------------------------------------------------- /Assets/MinValueAttribute/Editor/MinValueDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | [CustomPropertyDrawer (typeof (MinValueAttribute))] 5 | public class MinValueDrawer : PropertyDrawer { 6 | 7 | public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) 8 | { 9 | if (property.propertyType != SerializedPropertyType.Float && property.propertyType != SerializedPropertyType.Integer) 10 | { 11 | EditorGUI.LabelField (position, label.text, "Use MinValue with float or int."); 12 | return; 13 | } 14 | 15 | EditorGUI.PropertyField(position, property, label); 16 | 17 | if (GUI.changed) 18 | { 19 | MinValueAttribute minValue = attribute as MinValueAttribute; 20 | property.floatValue = Mathf.Max(property.floatValue, minValue.min); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Assets/TubeLight/Scripts/TubeLightShadowPlane.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class TubeLightShadowPlane : MonoBehaviour 4 | { 5 | [MinValue(0)] 6 | public float m_Feather = 1.0f; 7 | 8 | public float feather {get{ return m_Feather * 0.1f;}} 9 | 10 | public Vector4 GetShadowPlaneVector() 11 | { 12 | Transform t = transform; 13 | Vector3 v = t.forward; 14 | float d = Vector3.Dot(t.position, v); 15 | return new Vector4(v.x, v.y, v.z, d); 16 | } 17 | 18 | void OnDrawGizmosSelected() 19 | { 20 | Matrix4x4 m = Matrix4x4.zero; 21 | Transform t = transform; 22 | m.SetTRS(t.position, t.rotation, new Vector3(1, 1, 0)); 23 | Gizmos.matrix = m; 24 | Gizmos.DrawWireSphere(Vector3.zero, 1); 25 | } 26 | 27 | public struct Params 28 | { 29 | public Vector4 plane; 30 | public float feather; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | m_Enabled: 0 7 | m_TestMode: 0 8 | m_TestEventUrl: 9 | m_TestConfigUrl: 10 | CrashReportingSettings: 11 | m_EventUrl: https://perf-events.cloud.unity3d.com/api/events/crashes 12 | m_Enabled: 0 13 | m_CaptureEditorExceptions: 1 14 | UnityPurchasingSettings: 15 | m_Enabled: 0 16 | m_TestMode: 0 17 | UnityAnalyticsSettings: 18 | m_Enabled: 0 19 | m_InitializeOnStartup: 1 20 | m_TestMode: 0 21 | m_TestEventUrl: 22 | m_TestConfigUrl: 23 | UnityAdsSettings: 24 | m_Enabled: 0 25 | m_InitializeOnStartup: 1 26 | m_TestMode: 0 27 | m_EnabledPlatforms: 4294967295 28 | m_IosGameId: 29 | m_AndroidGameId: 30 | -------------------------------------------------------------------------------- /Assets/Wind/Scripts/Wind.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class Wind : MonoBehaviour { 4 | 5 | [MinValue(0)] 6 | public float m_Speed = 1.0f; 7 | 8 | void OnDrawGizmosSelected() 9 | { 10 | Vector3[] arrow = 11 | { 12 | new Vector3(0,0,1.5f), 13 | new Vector3( 1.0f,0.0f, 0.5f), new Vector3( 0.5f,0.0f,0.5f), new Vector3( 0.5f,0.0f,-1.0f), 14 | new Vector3(-0.5f,0.0f,-1.0f), new Vector3(-0.5f,0.0f,0.5f), new Vector3(-1.0f,0.0f, 0.5f), 15 | new Vector3(0,0,1.5f) 16 | }; 17 | 18 | Gizmos.matrix = transform.localToWorldMatrix; 19 | int count = arrow.Length; 20 | 21 | for(int i = 0; i < count; i++) 22 | Gizmos.DrawLine(arrow[i], arrow[(i + 1) % count]); 23 | 24 | Gizmos.matrix = Gizmos.matrix * Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, 0, 90), Vector3.one); 25 | 26 | for(int i = 0; i < count; i++) 27 | Gizmos.DrawLine(arrow[i], arrow[(i + 1) % count]); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/VolumetricFog.cginc: -------------------------------------------------------------------------------- 1 | sampler3D _VolumeScatter; 2 | float4 _VolumeScatter_TexelSize; 3 | float4 _Screen_TexelSize; 4 | float _CameraFarOverMaxFar; 5 | float _NearOverFarClip; 6 | 7 | int ihash(int n) 8 | { 9 | n = (n<<13)^n; 10 | return (n*(n*n*15731+789221)+1376312589) & 2147483647; 11 | } 12 | 13 | float frand(int n) 14 | { 15 | return ihash(n) / 2147483647.0; 16 | } 17 | 18 | float2 cellNoise(int2 p) 19 | { 20 | int i = p.y*256 + p.x; 21 | return float2(frand(i), frand(i + 57)) - 0.5;//*2.0-1.0; 22 | } 23 | 24 | half4 Fog(half linear01Depth, half2 screenuv) 25 | { 26 | half z = linear01Depth * _CameraFarOverMaxFar; 27 | z = (z - _NearOverFarClip) / (1 - _NearOverFarClip); 28 | if (z < 0.0) 29 | return half4(0, 0, 0, 1); 30 | 31 | half3 uvw = half3(screenuv.x, screenuv.y, z); 32 | uvw.xy += cellNoise(uvw.xy * _Screen_TexelSize.zw) * _VolumeScatter_TexelSize.xy * 0.8; 33 | return tex3D(_VolumeScatter, uvw); 34 | } 35 | -------------------------------------------------------------------------------- /Assets/Scenes/Materials/StandardAlphaBlended-VolumetricFog.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: StandardAlphaBlended-VolumetricFog 10 | m_Shader: {fileID: 4800000, guid: 9dca33cc83d85fd409e8d3dfc9db5676, type: 3} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 5 13 | m_CustomRenderQueue: -1 14 | stringTagMap: {} 15 | m_SavedProperties: 16 | serializedVersion: 2 17 | m_TexEnvs: 18 | - first: 19 | name: _MainTex 20 | second: 21 | m_Texture: {fileID: 0} 22 | m_Scale: {x: 1, y: 1} 23 | m_Offset: {x: 0, y: 0} 24 | m_Floats: 25 | - first: 26 | name: _Glossiness 27 | second: 0.667 28 | - first: 29 | name: _Metallic 30 | second: 0 31 | m_Colors: 32 | - first: 33 | name: _Color 34 | second: {r: 1, g: 1, b: 1, a: 0} 35 | -------------------------------------------------------------------------------- /Assets/TubeLight/Shaders/TubeLightShadowPlanes.cginc: -------------------------------------------------------------------------------- 1 | half ShadowPlane(half3 worldPos, half4 plane, half feather) 2 | { 3 | half x = plane.w - dot(worldPos, plane.xyz); 4 | // Compiler bug workaround 5 | x += 0.0001; 6 | return smoothstep(-feather, feather, x); 7 | } 8 | 9 | float4 _ShadowPlane0; 10 | float _ShadowPlaneFeather0; 11 | float4 _ShadowPlane1; 12 | float _ShadowPlaneFeather1; 13 | 14 | half ShadowPlanes(half3 worldPos) 15 | { 16 | half att = 1; 17 | att *= ShadowPlane(worldPos, _ShadowPlane0, _ShadowPlaneFeather0); 18 | att *= ShadowPlane(worldPos, _ShadowPlane1, _ShadowPlaneFeather1); 19 | return att; 20 | } 21 | 22 | struct TubeLightShadowPlane 23 | { 24 | float4 plane0; 25 | float4 plane1; 26 | float feather0; 27 | float feather1; 28 | float padding0; 29 | float padding1; 30 | }; 31 | 32 | half ShadowPlanes(half3 worldPos, TubeLightShadowPlane params) 33 | { 34 | half att = 1; 35 | att *= ShadowPlane(worldPos, params.plane0, params.feather0); 36 | att *= ShadowPlane(worldPos, params.plane1, params.feather1); 37 | return att; 38 | } -------------------------------------------------------------------------------- /Assets/VolumetricFog/Scripts/VolumetricFog.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f35c02a2c6230584391703bf32006791 3 | timeCreated: 1432253353 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: 8 | - m_DebugShader: {fileID: 4800000, guid: 91e29ad407521e447a7254f5c1ea9b54, type: 3} 9 | - m_ShadowmapShader: {fileID: 4800000, guid: 2c4cd42b134f7864fa579350e9cf6896, type: 3} 10 | - m_InjectLightingAndDensity: {fileID: 7200000, guid: 55812fd61bd54104aa23612fc28bfeb8, 11 | type: 3} 12 | - m_Scatter: {fileID: 7200000, guid: 2a7c01c2354d03a4e9c31096bf130b6a, type: 3} 13 | - m_ApplyToOpaqueShader: {fileID: 4800000, guid: 6f73df8e11615074dbf62a3a384af521, 14 | type: 3} 15 | - m_BlurShadowmapShader: {fileID: 4800000, guid: 701192b62a7678549918bc87434699fe, 16 | type: 3} 17 | - m_Noise: {fileID: 2800000, guid: 35eb47181d630134c97488476efbda59, type: 3} 18 | - m_Sun: {instanceID: 0} 19 | executionOrder: 0 20 | icon: {instanceID: 0} 21 | userData: 22 | assetBundleName: 23 | assetBundleVariant: 24 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/ApplyToOpaque.shader: -------------------------------------------------------------------------------- 1 | Shader "Hidden/ApplyToOpaque" { 2 | SubShader { 3 | Pass { 4 | ZTest Always Cull Off ZWrite Off 5 | Blend Off 6 | 7 | CGPROGRAM 8 | #pragma target 3.0 9 | #include "UnityCG.cginc" 10 | #include "VolumetricFog.cginc" 11 | #pragma vertex vert 12 | #pragma fragment frag 13 | 14 | sampler2D _CameraDepthTexture; 15 | sampler2D _MainTex; 16 | 17 | struct v2f 18 | { 19 | float4 pos : SV_POSITION; 20 | float2 uv : TEXCOORD0; 21 | }; 22 | 23 | v2f vert (appdata_img v) 24 | { 25 | v2f o; 26 | o.pos = v.vertex; 27 | o.pos.xy = o.pos.xy * 2 - 1; 28 | o.uv = v.texcoord.xy; 29 | 30 | #if UNITY_UV_STARTS_AT_TOP 31 | if (_ProjectionParams.x < 0) 32 | o.uv.y = 1-o.uv.y; 33 | #endif 34 | 35 | return o; 36 | } 37 | 38 | half4 frag (v2f i) : SV_Target 39 | { 40 | half linear01Depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv)); 41 | half4 fog = Fog(linear01Depth, i.uv); 42 | return tex2D(_MainTex, i.uv) * fog.a + fog; 43 | } 44 | 45 | ENDCG 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Assets/LightManager/Scripts/LightManager.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | 4 | public class LightManager : MonoBehaviour 5 | { 6 | static LightManager s_Instance; 7 | HashSet m_Container = new HashSet(); 8 | 9 | static LightManager Instance 10 | { 11 | get 12 | { 13 | if (s_Instance != null) 14 | return s_Instance; 15 | 16 | s_Instance = (LightManager) FindObjectOfType(typeof(LightManager)); 17 | return s_Instance; 18 | } 19 | } 20 | 21 | public static HashSet Get() 22 | { 23 | LightManager instance = Instance; 24 | return instance == null ? new HashSet() : instance.m_Container; 25 | } 26 | 27 | public static bool Add(T t) 28 | { 29 | LightManager instance = Instance; 30 | if (instance == null) 31 | return false; 32 | 33 | instance.m_Container.Add(t); 34 | return true; 35 | } 36 | 37 | public static void Remove(T t) 38 | { 39 | LightManager instance = Instance; 40 | if (instance == null) 41 | return; 42 | 43 | instance.m_Container.Remove(t); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/CopyShadowParams.shader: -------------------------------------------------------------------------------- 1 | Shader "Hidden/CopyShadowParams" 2 | { 3 | SubShader 4 | { 5 | Pass 6 | { 7 | CGPROGRAM 8 | #pragma target 5.0 9 | #pragma only_renderers d3d11 10 | #pragma vertex vert 11 | #pragma fragment frag 12 | #include "UnityCG.cginc" 13 | 14 | struct ShadowParams 15 | { 16 | float4x4 worldToShadow[4]; 17 | float4 shadowSplitSpheres[4]; 18 | float4 shadowSplitSqRadii; 19 | }; 20 | 21 | // Hmm, we can't be sure u2 doesn't conflict with other effects. 22 | RWStructuredBuffer _ShadowParams : register(u2); 23 | 24 | float4 vert () : SV_POSITION 25 | { 26 | for (int i = 0; i < 4; i++) 27 | { 28 | _ShadowParams[0].worldToShadow[i] = unity_WorldToShadow[i]; 29 | _ShadowParams[0].shadowSplitSpheres[i] = unity_ShadowSplitSpheres[i]; 30 | } 31 | _ShadowParams[0].shadowSplitSqRadii = unity_ShadowSplitSqRadii; 32 | 33 | return float4(0, 0, 0, 1); 34 | } 35 | 36 | fixed4 frag () : SV_Target 37 | { 38 | return 0; 39 | } 40 | ENDCG 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Unity Technologies 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshAreas: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | areas: 8 | - name: Walkable 9 | cost: 1 10 | - name: Not Walkable 11 | cost: 1 12 | - name: Jump 13 | cost: 2 14 | - name: 15 | cost: 1 16 | - name: 17 | cost: 1 18 | - name: 19 | cost: 1 20 | - name: 21 | cost: 1 22 | - name: 23 | cost: 1 24 | - name: 25 | cost: 1 26 | - name: 27 | cost: 1 28 | - name: 29 | cost: 1 30 | - name: 31 | cost: 1 32 | - name: 33 | cost: 1 34 | - name: 35 | cost: 1 36 | - name: 37 | cost: 1 38 | - name: 39 | cost: 1 40 | - name: 41 | cost: 1 42 | - name: 43 | cost: 1 44 | - name: 45 | cost: 1 46 | - name: 47 | cost: 1 48 | - name: 49 | cost: 1 50 | - name: 51 | cost: 1 52 | - name: 53 | cost: 1 54 | - name: 55 | cost: 1 56 | - name: 57 | cost: 1 58 | - name: 59 | cost: 1 60 | - name: 61 | cost: 1 62 | - name: 63 | cost: 1 64 | - name: 65 | cost: 1 66 | - name: 67 | cost: 1 68 | - name: 69 | cost: 1 70 | - name: 71 | cost: 1 72 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/Debug.shader: -------------------------------------------------------------------------------- 1 | Shader "Hidden/Debug" { 2 | SubShader { 3 | Pass { 4 | ZTest Always Cull Off ZWrite Off 5 | Blend Off 6 | 7 | CGPROGRAM 8 | #pragma target 3.0 9 | #include "UnityCG.cginc" 10 | #pragma vertex vert 11 | #pragma fragment frag 12 | 13 | sampler2D _CameraDepthTexture; 14 | sampler3D _VolumeInject; 15 | sampler3D _VolumeScatter; 16 | sampler2D _Shadowmap; 17 | sampler2D _ShadowmapBlurred; 18 | sampler2D _MainTex; 19 | sampler2D _BoxLightShadowmap; 20 | float _Z; 21 | 22 | struct v2f 23 | { 24 | float4 pos : SV_POSITION; 25 | float2 uv : TEXCOORD0; 26 | }; 27 | 28 | v2f vert (appdata_img v) 29 | { 30 | v2f o; 31 | o.pos = v.vertex; 32 | o.pos.xy = o.pos.xy * 2 - 1; 33 | o.uv = v.texcoord.xy; 34 | 35 | #if UNITY_UV_STARTS_AT_TOP 36 | if (_ProjectionParams.x < 0) 37 | o.uv.y = 1-o.uv.y; 38 | #endif 39 | 40 | return o; 41 | } 42 | 43 | half4 frag (v2f i) : SV_Target 44 | { 45 | half depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv)); 46 | 47 | // return i.uv.xyyy; 48 | return tex2D(_BoxLightShadowmap, i.uv); 49 | //return log(tex2D(_ShadowmapBlurred, i.uv))/80.0; 50 | return tex3D(_VolumeInject, half3(i.uv.x, i.uv.y, _Z)).a;// * tex2D(_MainTex, float2(i.uv.x, i.uv.y)); 51 | } 52 | 53 | ENDCG 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Gravity: {x: 0, y: -9.81} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_VelocityIterations: 8 10 | m_PositionIterations: 3 11 | m_VelocityThreshold: 1 12 | m_MaxLinearCorrection: 0.2 13 | m_MaxAngularCorrection: 8 14 | m_MaxTranslationSpeed: 100 15 | m_MaxRotationSpeed: 360 16 | m_MinPenetrationForPenalty: 0.01 17 | m_BaumgarteScale: 0.2 18 | m_BaumgarteTimeOfImpactScale: 0.75 19 | m_TimeToSleep: 0.5 20 | m_LinearSleepTolerance: 0.01 21 | m_AngularSleepTolerance: 2 22 | m_QueriesHitTriggers: 1 23 | m_QueriesStartInColliders: 1 24 | m_ChangeStopsCallbacks: 0 25 | m_AlwaysShowColliders: 0 26 | m_ShowColliderSleep: 1 27 | m_ShowColliderContacts: 0 28 | m_ContactArrowScale: 0.2 29 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} 30 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} 31 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} 32 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 33 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/noise.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 35eb47181d630134c97488476efbda59 3 | timeCreated: 1432252542 4 | licenseType: Pro 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 2 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | linearTexture: 0 12 | correctGamma: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: .25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 0 25 | cubemapConvolution: 0 26 | cubemapConvolutionSteps: 8 27 | cubemapConvolutionExponent: 1.5 28 | seamlessCubemap: 0 29 | textureFormat: -3 30 | maxTextureSize: 2048 31 | textureSettings: 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapMode: 0 36 | nPOTScale: 1 37 | lightmap: 0 38 | rGBM: 0 39 | compressionQuality: 50 40 | spriteMode: 0 41 | spriteExtrude: 1 42 | spriteMeshType: 1 43 | alignment: 0 44 | spritePivot: {x: .5, y: .5} 45 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 46 | spritePixelsToUnits: 100 47 | alphaIsTransparency: 0 48 | textureType: 5 49 | buildTargetSettings: [] 50 | spriteSheet: 51 | sprites: [] 52 | spritePackingTag: 53 | userData: 54 | assetBundleName: 55 | assetBundleVariant: 56 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Scripts/FogEllipsoid.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | [ExecuteInEditMode] 4 | public class FogEllipsoid : MonoBehaviour 5 | { 6 | public enum Blend 7 | { 8 | Additive, 9 | Multiplicative 10 | } 11 | 12 | public Blend m_Blend = Blend.Additive; 13 | public float m_Density = 1.0f; 14 | [MinValue(0)] 15 | public float m_Radius = 1.0f; 16 | [MinValue(0)] 17 | public float m_Stretch = 2.0f; 18 | [Range(0, 1)] 19 | public float m_Feather = 0.7f; 20 | [Range(0, 1)] 21 | public float m_NoiseAmount = 0.0f; 22 | public float m_NoiseSpeed = 1.0f; 23 | [MinValue(0)] 24 | public float m_NoiseScale = 1.0f; 25 | 26 | bool m_AddedToLightManager = false; 27 | 28 | void AddToLightManager() 29 | { 30 | if (!m_AddedToLightManager) 31 | m_AddedToLightManager = LightManagerFogEllipsoids.Add(this); 32 | } 33 | 34 | void OnEnable() 35 | { 36 | AddToLightManager(); 37 | } 38 | 39 | void Update() 40 | { 41 | // LightManager might not have been available during this light's OnEnable(), so keep trying. 42 | AddToLightManager(); 43 | } 44 | 45 | void OnDisable() 46 | { 47 | LightManagerFogEllipsoids.Remove(this); 48 | m_AddedToLightManager = false; 49 | } 50 | 51 | void OnDrawGizmosSelected() 52 | { 53 | Matrix4x4 m = Matrix4x4.identity; 54 | Transform t = transform; 55 | m.SetTRS(t.position, t.rotation, new Vector3(1.0f, m_Stretch, 1.0f)); 56 | Gizmos.matrix = m; 57 | Gizmos.DrawWireSphere(Vector3.zero, m_Radius); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Scripts/FogLight.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | [ExecuteInEditMode] 4 | public partial class FogLight : LightOverride 5 | { 6 | public bool m_ForceOnForFog = false; 7 | [Tooltip("Only one shadowed fog AreaLight at a time.")] 8 | [Header("Shadows")] 9 | public bool m_Shadows = false; 10 | 11 | public enum TextureSize 12 | { 13 | x256 = 256, 14 | x512 = 512, 15 | x1024 = 1024, 16 | } 17 | 18 | [Tooltip("Always at most half the res of the AreaLight's shadowmap.")] 19 | public TextureSize m_ShadowmapRes = TextureSize.x256; 20 | [Range(0, 3)] 21 | public int m_BlurIterations = 0; 22 | [MinValue(0)] 23 | public float m_BlurSize = 1.0f; 24 | [MinValue(0)] 25 | [Tooltip("Affects shadow softness.")] 26 | public float m_ESMExponent = 40.0f; 27 | 28 | public bool m_Bounded = true; 29 | 30 | public override bool GetForceOn() 31 | { 32 | return m_ForceOnForFog; 33 | } 34 | 35 | bool m_AddedToLightManager = false; 36 | 37 | void AddToLightManager() 38 | { 39 | if (!m_AddedToLightManager) 40 | m_AddedToLightManager = LightManagerFogLights.Add(this); 41 | } 42 | 43 | void OnEnable() 44 | { 45 | AddToLightManager(); 46 | } 47 | 48 | void Update() 49 | { 50 | // LightManager might not have been available during this light's OnEnable(), so keep trying. 51 | AddToLightManager(); 52 | } 53 | 54 | void OnDisable() 55 | { 56 | LightManagerFogLights.Remove(this); 57 | m_AddedToLightManager = false; 58 | CleanupDirectionalShadowmap(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Assets/Wind/Wind.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &189734 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_PrefabParentObject: {fileID: 0} 7 | m_PrefabInternal: {fileID: 100100000} 8 | serializedVersion: 4 9 | m_Component: 10 | - 4: {fileID: 456534} 11 | - 114: {fileID: 11403654} 12 | m_Layer: 0 13 | m_Name: Wind 14 | m_TagString: Untagged 15 | m_Icon: {fileID: 0} 16 | m_NavMeshLayer: 0 17 | m_StaticEditorFlags: 0 18 | m_IsActive: 1 19 | --- !u!4 &456534 20 | Transform: 21 | m_ObjectHideFlags: 1 22 | m_PrefabParentObject: {fileID: 0} 23 | m_PrefabInternal: {fileID: 100100000} 24 | m_GameObject: {fileID: 189734} 25 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 26 | m_LocalPosition: {x: 0, y: 0, z: 0} 27 | m_LocalScale: {x: 1, y: 1, z: 1} 28 | m_Children: [] 29 | m_Father: {fileID: 0} 30 | m_RootOrder: 0 31 | --- !u!114 &11403654 32 | MonoBehaviour: 33 | m_ObjectHideFlags: 1 34 | m_PrefabParentObject: {fileID: 0} 35 | m_PrefabInternal: {fileID: 100100000} 36 | m_GameObject: {fileID: 189734} 37 | m_Enabled: 1 38 | m_EditorHideFlags: 0 39 | m_Script: {fileID: 11500000, guid: 705fc1fdc327ad04787d9b3b7a2aefe6, type: 3} 40 | m_Name: 41 | m_EditorClassIdentifier: 42 | --- !u!1001 &100100000 43 | Prefab: 44 | m_ObjectHideFlags: 1 45 | serializedVersion: 2 46 | m_Modification: 47 | m_TransformParent: {fileID: 0} 48 | m_Modifications: [] 49 | m_RemovedComponents: [] 50 | m_ParentPrefab: {fileID: 0} 51 | m_RootGameObject: {fileID: 189734} 52 | m_IsPrefabParent: 1 53 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/FogEllipsoid.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &141782 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_PrefabParentObject: {fileID: 0} 7 | m_PrefabInternal: {fileID: 100100000} 8 | serializedVersion: 4 9 | m_Component: 10 | - 4: {fileID: 463416} 11 | - 114: {fileID: 11477592} 12 | m_Layer: 0 13 | m_Name: FogEllipsoid 14 | m_TagString: Untagged 15 | m_Icon: {fileID: 0} 16 | m_NavMeshLayer: 0 17 | m_StaticEditorFlags: 0 18 | m_IsActive: 1 19 | --- !u!4 &463416 20 | Transform: 21 | m_ObjectHideFlags: 1 22 | m_PrefabParentObject: {fileID: 0} 23 | m_PrefabInternal: {fileID: 100100000} 24 | m_GameObject: {fileID: 141782} 25 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 26 | m_LocalPosition: {x: 0, y: 0, z: 0} 27 | m_LocalScale: {x: 1, y: 1, z: 1} 28 | m_Children: [] 29 | m_Father: {fileID: 0} 30 | m_RootOrder: 0 31 | --- !u!114 &11477592 32 | MonoBehaviour: 33 | m_ObjectHideFlags: 1 34 | m_PrefabParentObject: {fileID: 0} 35 | m_PrefabInternal: {fileID: 100100000} 36 | m_GameObject: {fileID: 141782} 37 | m_Enabled: 1 38 | m_EditorHideFlags: 0 39 | m_Script: {fileID: 11500000, guid: 789ae5fef74e6754ab3c20bdeca67ad9, type: 3} 40 | m_Name: 41 | m_EditorClassIdentifier: 42 | m_Radius: 1 43 | m_Stretch: 2 44 | --- !u!1001 &100100000 45 | Prefab: 46 | m_ObjectHideFlags: 1 47 | serializedVersion: 2 48 | m_Modification: 49 | m_TransformParent: {fileID: 0} 50 | m_Modifications: [] 51 | m_RemovedComponents: [] 52 | m_ParentPrefab: {fileID: 0} 53 | m_RootGameObject: {fileID: 141782} 54 | m_IsPrefabParent: 1 55 | -------------------------------------------------------------------------------- /Assets/LightManager/LightManagerFogLights.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1001 &100100000 4 | Prefab: 5 | m_ObjectHideFlags: 1 6 | serializedVersion: 2 7 | m_Modification: 8 | m_TransformParent: {fileID: 0} 9 | m_Modifications: [] 10 | m_RemovedComponents: [] 11 | m_ParentPrefab: {fileID: 0} 12 | m_RootGameObject: {fileID: 1000011378053400} 13 | m_IsPrefabParent: 1 14 | --- !u!1 &1000011378053400 15 | GameObject: 16 | m_ObjectHideFlags: 0 17 | m_PrefabParentObject: {fileID: 0} 18 | m_PrefabInternal: {fileID: 100100000} 19 | serializedVersion: 4 20 | m_Component: 21 | - 4: {fileID: 4000012687929690} 22 | - 114: {fileID: 114000010476117714} 23 | m_Layer: 0 24 | m_Name: LightManagerFogLights 25 | m_TagString: Untagged 26 | m_Icon: {fileID: 0} 27 | m_NavMeshLayer: 0 28 | m_StaticEditorFlags: 0 29 | m_IsActive: 1 30 | --- !u!4 &4000012687929690 31 | Transform: 32 | m_ObjectHideFlags: 1 33 | m_PrefabParentObject: {fileID: 0} 34 | m_PrefabInternal: {fileID: 100100000} 35 | m_GameObject: {fileID: 1000011378053400} 36 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 37 | m_LocalPosition: {x: -8.9284725, y: 3.427047, z: -0.21317804} 38 | m_LocalScale: {x: 1, y: 1, z: 1} 39 | m_Children: [] 40 | m_Father: {fileID: 0} 41 | m_RootOrder: 0 42 | --- !u!114 &114000010476117714 43 | MonoBehaviour: 44 | m_ObjectHideFlags: 1 45 | m_PrefabParentObject: {fileID: 0} 46 | m_PrefabInternal: {fileID: 100100000} 47 | m_GameObject: {fileID: 1000011378053400} 48 | m_Enabled: 1 49 | m_EditorHideFlags: 0 50 | m_Script: {fileID: 11500000, guid: 01ae89c4c08f92f4fb90537335efa1ac, type: 3} 51 | m_Name: 52 | m_EditorClassIdentifier: 53 | -------------------------------------------------------------------------------- /Assets/LightManager/LightManagerFogEllipsoids.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1001 &100100000 4 | Prefab: 5 | m_ObjectHideFlags: 1 6 | serializedVersion: 2 7 | m_Modification: 8 | m_TransformParent: {fileID: 0} 9 | m_Modifications: [] 10 | m_RemovedComponents: [] 11 | m_ParentPrefab: {fileID: 0} 12 | m_RootGameObject: {fileID: 1000010085349158} 13 | m_IsPrefabParent: 1 14 | --- !u!1 &1000010085349158 15 | GameObject: 16 | m_ObjectHideFlags: 0 17 | m_PrefabParentObject: {fileID: 0} 18 | m_PrefabInternal: {fileID: 100100000} 19 | serializedVersion: 4 20 | m_Component: 21 | - 4: {fileID: 4000010739719174} 22 | - 114: {fileID: 114000014191307454} 23 | m_Layer: 0 24 | m_Name: LightManagerFogEllipsoids 25 | m_TagString: Untagged 26 | m_Icon: {fileID: 0} 27 | m_NavMeshLayer: 0 28 | m_StaticEditorFlags: 0 29 | m_IsActive: 1 30 | --- !u!4 &4000010739719174 31 | Transform: 32 | m_ObjectHideFlags: 1 33 | m_PrefabParentObject: {fileID: 0} 34 | m_PrefabInternal: {fileID: 100100000} 35 | m_GameObject: {fileID: 1000010085349158} 36 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 37 | m_LocalPosition: {x: -8.9284725, y: 3.427047, z: -0.21317804} 38 | m_LocalScale: {x: 1, y: 1, z: 1} 39 | m_Children: [] 40 | m_Father: {fileID: 0} 41 | m_RootOrder: 0 42 | --- !u!114 &114000014191307454 43 | MonoBehaviour: 44 | m_ObjectHideFlags: 1 45 | m_PrefabParentObject: {fileID: 0} 46 | m_PrefabInternal: {fileID: 100100000} 47 | m_GameObject: {fileID: 1000010085349158} 48 | m_Enabled: 1 49 | m_EditorHideFlags: 0 50 | m_Script: {fileID: 11500000, guid: ed243fe90a2e7384f9f6f59acf71e19b, type: 3} 51 | m_Name: 52 | m_EditorClassIdentifier: 53 | -------------------------------------------------------------------------------- /Assets/TubeLight/Shaders/TubeLightAttenuation.cginc: -------------------------------------------------------------------------------- 1 | #ifndef TUBE_LIGHT_ATTENUATION_LEGACY 2 | #define TUBE_LIGHT_ATTENUATION_LEGACY 0 3 | #endif 4 | 5 | #if TUBE_LIGHT_ATTENUATION_LEGACY 6 | 7 | float Attenuation(float distNorm) 8 | { 9 | return 1.0 / (1.0 + 25.0 * distNorm); 10 | } 11 | 12 | float AttenuationToZero(float distNorm) 13 | { 14 | float att = Attenuation(distNorm); 15 | 16 | // Replicating unity light attenuation - pulled to 0 at range 17 | // if (distNorm > 0.8 * 0.8) 18 | // att *= 1 - (distNorm - 0.8 * 0.8) / (1 - 0.8 * 0.8); 19 | // Same, simplified 20 | float oneDistNorm = 1.0 - distNorm; 21 | att *= lerp(1.0, oneDistNorm * 2.78, step(0.64, distNorm)); 22 | 23 | att *= step(0.0, oneDistNorm); 24 | 25 | return att; 26 | } 27 | 28 | #else 29 | 30 | float Attenuation(float distSqr) 31 | { 32 | float d = sqrt(distSqr); 33 | float kDefaultPointLightRadius = 0.25; 34 | return 1.0 / pow(1.0 + d/kDefaultPointLightRadius, 2); 35 | } 36 | 37 | float AttenuationToZero(float distSqr) 38 | { 39 | // attenuation = 1 / (1 + distance_to_light / light_radius)^2 40 | // = 1 / (1 + 2*(d/r) + (d/r)^2) 41 | // For more details see: https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/ 42 | float d = sqrt(distSqr); 43 | float kDefaultPointLightRadius = 0.25; 44 | float atten = 1.0 / pow(1.0 + d/kDefaultPointLightRadius, 2); 45 | float kCutoff = 1.0 / pow(1.0 + 1.0/kDefaultPointLightRadius, 2); // cutoff equal to attenuation at distance 1.0 46 | 47 | // Force attenuation to fall towards zero at distance 1.0 48 | atten = (atten - kCutoff) / (1.f - kCutoff); 49 | if (d >= 1.f) 50 | atten = 0.f; 51 | 52 | return atten; 53 | } 54 | 55 | #endif -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/Scatter.compute: -------------------------------------------------------------------------------- 1 | // Based on 'Volumetric fog: Unified, compute shader based solution to atmospheric scattering, ACM Siggraph 2014' 2 | // https://bartwronski.com/publications/ 3 | 4 | #pragma kernel CSMain 5 | #define VOLUME_DEPTH 128.0 6 | 7 | Texture3D _VolumeInject; 8 | RWTexture3D _VolumeScatter; 9 | 10 | float4 ScatterStep(float3 accumulatedLight, float accumulatedTransmittance, float3 sliceLight, float sliceDensity) 11 | { 12 | sliceDensity = max(sliceDensity, 0.000001); 13 | float sliceTransmittance = exp(-sliceDensity / VOLUME_DEPTH); 14 | 15 | // Seb Hillaire's improved transmission by calculating an integral over slice depth instead of 16 | // constant per slice value. Light still constant per slice, but that's acceptable. See slide 28 of 17 | // Physically-based & Unified Volumetric Rendering in Frostbite 18 | // http://www.frostbite.com/2015/08/physically-based-unified-volumetric-rendering-in-frostbite/ 19 | float3 sliceLightIntegral = sliceLight * (1.0 - sliceTransmittance) / sliceDensity; 20 | 21 | accumulatedLight += sliceLightIntegral * accumulatedTransmittance; 22 | accumulatedTransmittance *= sliceTransmittance; 23 | 24 | return float4(accumulatedLight, accumulatedTransmittance); 25 | } 26 | 27 | [numthreads(32, 2, 1)] 28 | void CSMain (uint3 id : SV_DispatchThreadID) 29 | { 30 | // Store transmission in .a, as opposed to density in _VolumeInject 31 | float4 accum = float4(0, 0, 0, 1); 32 | uint3 pos = uint3(id.xy, 0); 33 | uint steps = VOLUME_DEPTH; 34 | 35 | for(uint z = 0; z < steps; z++) 36 | { 37 | pos.z = z; 38 | float4 slice = _VolumeInject[pos]; 39 | accum = ScatterStep(accum.rgb, accum.a, slice.rgb, slice.a); 40 | _VolumeScatter[pos] = accum; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Packages/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.unity.ads": "2.0.8", 4 | "com.unity.analytics": "3.0.9", 5 | "com.unity.collab-proxy": "1.2.9", 6 | "com.unity.package-manager-ui": "2.0.1", 7 | "com.unity.purchasing": "2.0.3", 8 | "com.unity.textmeshpro": "1.3.0", 9 | "com.unity.modules.ai": "1.0.0", 10 | "com.unity.modules.animation": "1.0.0", 11 | "com.unity.modules.assetbundle": "1.0.0", 12 | "com.unity.modules.audio": "1.0.0", 13 | "com.unity.modules.cloth": "1.0.0", 14 | "com.unity.modules.director": "1.0.0", 15 | "com.unity.modules.imageconversion": "1.0.0", 16 | "com.unity.modules.imgui": "1.0.0", 17 | "com.unity.modules.jsonserialize": "1.0.0", 18 | "com.unity.modules.particlesystem": "1.0.0", 19 | "com.unity.modules.physics": "1.0.0", 20 | "com.unity.modules.physics2d": "1.0.0", 21 | "com.unity.modules.screencapture": "1.0.0", 22 | "com.unity.modules.terrain": "1.0.0", 23 | "com.unity.modules.terrainphysics": "1.0.0", 24 | "com.unity.modules.tilemap": "1.0.0", 25 | "com.unity.modules.ui": "1.0.0", 26 | "com.unity.modules.uielements": "1.0.0", 27 | "com.unity.modules.umbra": "1.0.0", 28 | "com.unity.modules.unityanalytics": "1.0.0", 29 | "com.unity.modules.unitywebrequest": "1.0.0", 30 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0", 31 | "com.unity.modules.unitywebrequestaudio": "1.0.0", 32 | "com.unity.modules.unitywebrequesttexture": "1.0.0", 33 | "com.unity.modules.unitywebrequestwww": "1.0.0", 34 | "com.unity.modules.vehicles": "1.0.0", 35 | "com.unity.modules.video": "1.0.0", 36 | "com.unity.modules.vr": "1.0.0", 37 | "com.unity.modules.wind": "1.0.0", 38 | "com.unity.modules.xr": "1.0.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Assets/TubeLight/Editor/TubeLightEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using UnityEditor.AnimatedValues; 4 | 5 | [CustomEditor(typeof(TubeLight))] 6 | [CanEditMultipleObjects] 7 | public class TubeLightEditor : Editor { 8 | 9 | AnimFloat m_ShowInfo; 10 | 11 | void OnEnable() 12 | { 13 | m_ShowInfo = new AnimFloat(0); 14 | m_ShowInfo.valueChanged.AddListener(Repaint); 15 | m_ShowInfo.speed = 0.5f; 16 | } 17 | 18 | override public void OnInspectorGUI() 19 | { 20 | DrawDefaultInspector(); 21 | 22 | if (targets.Length > 1) 23 | return; 24 | 25 | EditorGUILayout.Space(); 26 | 27 | if(GUILayout.Button("Add a shadow plane")) 28 | m_ShowInfo.value = AddShadowPlane() ? 0 : 100; 29 | 30 | foreach (TubeLightShadowPlane shadowPlane in ((TubeLight)target).m_ShadowPlanes) 31 | if (shadowPlane != null) 32 | EditorGUILayout.ObjectField("Shadow Plane", shadowPlane, typeof(TubeLightShadowPlane), !EditorUtility.IsPersistent(target)); 33 | 34 | m_ShowInfo.target = 0; 35 | if (EditorGUILayout.BeginFadeGroup(Mathf.Min(1.0f, m_ShowInfo.value))) 36 | EditorGUILayout.HelpBox("Limit of " + TubeLight.maxPlanes + " planes reached. Delete an existing one.", MessageType.Info); 37 | EditorGUILayout.EndFadeGroup(); 38 | } 39 | 40 | bool AddShadowPlane() 41 | { 42 | TubeLight tubeLight = (TubeLight)target; 43 | 44 | int i = 0; 45 | for (; i < TubeLight.maxPlanes; i++) 46 | { 47 | if (tubeLight.m_ShadowPlanes[i] != null) 48 | continue; 49 | 50 | GameObject go = new GameObject("Shadow Plane"); 51 | TubeLightShadowPlane shadowPlane = go.AddComponent(); 52 | 53 | go.transform.position = tubeLight.transform.position + go.transform.forward; 54 | go.transform.parent = tubeLight.transform; 55 | tubeLight.m_ShadowPlanes[i] = shadowPlane; 56 | EditorUtility.SetDirty (tubeLight); 57 | break; 58 | } 59 | 60 | return i < TubeLight.maxPlanes; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Assets/LightOverride/LightOverride.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public abstract class LightOverride : MonoBehaviour 4 | { 5 | 6 | [Header("Overrides")] 7 | public float m_IntensityMult = 1.0f; 8 | [MinValue(0.0f)] 9 | public float m_RangeMult = 1.0f; 10 | 11 | public enum Type{None, Point, Tube, Area, Directional} 12 | 13 | Type m_Type = Type.None; 14 | bool m_Initialized = false; 15 | Light m_Light; 16 | TubeLight m_TubeLight; 17 | AreaLight m_AreaLight; 18 | 19 | public bool isOn 20 | { 21 | get 22 | { 23 | if (!isActiveAndEnabled) 24 | return false; 25 | 26 | Init(); 27 | 28 | switch(m_Type) 29 | { 30 | case Type.Point: return m_Light.enabled || GetForceOn(); 31 | case Type.Tube: return m_TubeLight.enabled || GetForceOn(); 32 | case Type.Area: return m_AreaLight.enabled || GetForceOn(); 33 | case Type.Directional: return m_Light.enabled || GetForceOn(); 34 | } 35 | 36 | return false; 37 | } 38 | 39 | private set{} 40 | } 41 | 42 | new public Light light {get{Init(); return m_Light;} private set{}} 43 | public TubeLight tubeLight {get{Init(); return m_TubeLight;} private set{}} 44 | public AreaLight areaLight {get{Init(); return m_AreaLight;} private set{}} 45 | 46 | public Type type {get{Init(); return m_Type;} private set{}} 47 | 48 | // To get the "enabled" state checkbox 49 | void Update() 50 | { 51 | 52 | } 53 | 54 | public abstract bool GetForceOn(); 55 | 56 | void Init() 57 | { 58 | if (m_Initialized) 59 | return; 60 | 61 | if ((m_Light = GetComponent()) != null) 62 | { 63 | switch(m_Light.type) 64 | { 65 | case LightType.Point: m_Type = Type.Point; break; 66 | case LightType.Directional: m_Type = Type.Directional; break; 67 | default: m_Type = Type.None; break; 68 | } 69 | } 70 | else if ((m_TubeLight = GetComponent()) != null) 71 | { 72 | m_Type = Type.Tube; 73 | } 74 | else if ((m_AreaLight = GetComponent()) != null) 75 | { 76 | m_Type = Type.Area; 77 | } 78 | 79 | m_Initialized = true; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Assets/AreaLight/Scripts/AreaLightLUT.Load.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public partial class AreaLightLUT 4 | { 5 | const int kLUTResolution = 64; 6 | const int kLUTMatrixDim = 3; 7 | 8 | public enum LUTType 9 | { 10 | TransformInv_DisneyDiffuse, 11 | TransformInv_GGX, 12 | AmpDiffAmpSpecFresnel 13 | } 14 | 15 | public static Texture2D LoadLUT(LUTType type) 16 | { 17 | switch(type) 18 | { 19 | case LUTType.TransformInv_DisneyDiffuse: return LoadLUT(s_LUTTransformInv_DisneyDiffuse); 20 | case LUTType.TransformInv_GGX: return LoadLUT(s_LUTTransformInv_GGX); 21 | case LUTType.AmpDiffAmpSpecFresnel: return LoadLUT(s_LUTAmplitude_DisneyDiffuse, s_LUTAmplitude_GGX, s_LUTFresnel_GGX); 22 | } 23 | 24 | return null; 25 | } 26 | 27 | static Texture2D CreateLUT(TextureFormat format, Color[] pixels) 28 | { 29 | Texture2D tex = new Texture2D(kLUTResolution, kLUTResolution, format, false /*mipmap*/, true /*linear*/); 30 | tex.hideFlags = HideFlags.HideAndDontSave; 31 | tex.wrapMode = TextureWrapMode.Clamp; 32 | tex.SetPixels(pixels); 33 | tex.Apply(); 34 | return tex; 35 | } 36 | 37 | static Texture2D LoadLUT(double[,] LUTTransformInv) 38 | { 39 | const int count = kLUTResolution * kLUTResolution; 40 | Color[] pixels = new Color[count]; 41 | 42 | // transformInv 43 | for (int i = 0; i < count; i++) 44 | { 45 | // Only columns 0, 2, 4 and 6 contain interesting values (at least in the case of GGX). 46 | pixels[i] = new Color( (float)LUTTransformInv[i, 0], 47 | (float)LUTTransformInv[i, 2], 48 | (float)LUTTransformInv[i, 4], 49 | (float)LUTTransformInv[i, 6]); 50 | } 51 | 52 | return CreateLUT(TextureFormat.RGBAHalf, pixels); 53 | } 54 | 55 | static Texture2D LoadLUT(float[] LUTScalar0, float[] LUTScalar1, float[] LUTScalar2) 56 | { 57 | const int count = kLUTResolution * kLUTResolution; 58 | Color[] pixels = new Color[count]; 59 | 60 | // amplitude 61 | for (int i = 0; i < count; i++) 62 | { 63 | pixels[i] = new Color(LUTScalar0[i], LUTScalar1[i], LUTScalar2[i], 0); 64 | } 65 | 66 | return CreateLUT(TextureFormat.RGBAHalf, pixels); 67 | } 68 | } -------------------------------------------------------------------------------- /Assets/VolumetricFog/Editor/FogLightEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | [CustomEditor(typeof(FogLight))] 5 | [CanEditMultipleObjects] 6 | public class FogLightEditor : Editor 7 | { 8 | SerializedProperty m_IntensityMult; 9 | SerializedProperty m_RangeMult; 10 | SerializedProperty m_ForceOnForFog; 11 | SerializedProperty m_Shadows; 12 | SerializedProperty m_ShadowmapRes; 13 | SerializedProperty m_BlurIterations; 14 | SerializedProperty m_BlurSize; 15 | SerializedProperty m_Bounded; 16 | 17 | void OnEnable() 18 | { 19 | m_IntensityMult = serializedObject.FindProperty ("m_IntensityMult"); 20 | m_RangeMult = serializedObject.FindProperty ("m_RangeMult"); 21 | m_ForceOnForFog = serializedObject.FindProperty ("m_ForceOnForFog"); 22 | m_Shadows = serializedObject.FindProperty ("m_Shadows"); 23 | m_ShadowmapRes = serializedObject.FindProperty ("m_ShadowmapRes"); 24 | m_BlurIterations = serializedObject.FindProperty ("m_BlurIterations"); 25 | m_BlurSize = serializedObject.FindProperty ("m_BlurSize"); 26 | m_Bounded = serializedObject.FindProperty("m_Bounded"); 27 | } 28 | 29 | override public void OnInspectorGUI() 30 | { 31 | serializedObject.Update(); 32 | 33 | EditorGUILayout.PropertyField(m_IntensityMult); 34 | EditorGUILayout.PropertyField(m_RangeMult); 35 | EditorGUILayout.PropertyField(m_ForceOnForFog); 36 | 37 | // Section below just for light types with shadow 38 | bool supportsShadows = false; 39 | bool isAreaLight = false; 40 | foreach (FogLight fogLight in targets) 41 | { 42 | if (fogLight.type == FogLight.Type.Area) 43 | { 44 | supportsShadows = true; 45 | isAreaLight = true; 46 | break; 47 | } 48 | else if (fogLight.type == FogLight.Type.Directional) 49 | { 50 | supportsShadows = true; 51 | break; 52 | } 53 | } 54 | 55 | if (supportsShadows) 56 | { 57 | EditorGUILayout.Space(); 58 | 59 | EditorGUILayout.PropertyField(m_Shadows); 60 | EditorGUILayout.PropertyField(m_ShadowmapRes); 61 | EditorGUILayout.PropertyField(m_BlurIterations); 62 | EditorGUILayout.PropertyField(m_BlurSize); 63 | } 64 | 65 | if (isAreaLight) 66 | { 67 | EditorGUILayout.Space(); 68 | EditorGUILayout.PropertyField(m_Bounded); 69 | } 70 | 71 | serializedObject.ApplyModifiedProperties(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Assets/TubeLight/Shaders/TubeLight.shader: -------------------------------------------------------------------------------- 1 | Shader "Hidden/TubeLight" { 2 | SubShader { 3 | Tags { "Queue"="Geometry-1" } 4 | 5 | CGINCLUDE 6 | #include "UnityCG.cginc" 7 | #include "UnityPBSLighting.cginc" 8 | #include "UnityDeferredLibrary.cginc" 9 | 10 | #define SHADOW_PLANES 1 11 | #include "TubeLight.cginc" 12 | 13 | sampler2D _CameraGBufferTexture0; 14 | sampler2D _CameraGBufferTexture1; 15 | sampler2D _CameraGBufferTexture2; 16 | 17 | float _LightRadius; 18 | float _LightLength; 19 | float4 _LightAxis; 20 | 21 | 22 | void DeferredCalculateLightParams ( 23 | unity_v2f_deferred i, 24 | out float3 outWorldPos, 25 | out float2 outUV) 26 | { 27 | i.ray = i.ray * (_ProjectionParams.z / i.ray.z); 28 | float2 uv = i.uv.xy / i.uv.w; 29 | 30 | // read depth and reconstruct world position 31 | float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv); 32 | depth = Linear01Depth (depth); 33 | float4 vpos = float4(i.ray * depth,1); 34 | float3 wpos = mul (unity_CameraToWorld, vpos).xyz; 35 | 36 | outWorldPos = wpos; 37 | outUV = uv; 38 | } 39 | 40 | half4 CalculateLightDeferred (unity_v2f_deferred i) 41 | { 42 | float3 worldPos; 43 | float2 uv; 44 | DeferredCalculateLightParams (i, worldPos, uv); 45 | 46 | half4 gbuffer0 = tex2D (_CameraGBufferTexture0, uv); 47 | half4 gbuffer1 = tex2D (_CameraGBufferTexture1, uv); 48 | half4 gbuffer2 = tex2D (_CameraGBufferTexture2, uv); 49 | 50 | half3 baseColor = gbuffer0.rgb; 51 | half3 specColor = gbuffer1.rgb; 52 | half oneMinusRoughness = gbuffer1.a; 53 | half3 normalWorld = gbuffer2.rgb * 2 - 1; 54 | normalWorld = normalize(normalWorld); 55 | 56 | return CalculateLight (worldPos, uv, baseColor, specColor, oneMinusRoughness, normalWorld, 57 | _LightPos.xyz, _LightPos.xyz + _LightAxis.xyz * _LightLength, _LightColor.xyz, _LightRadius, _LightPos.w); 58 | } 59 | ENDCG 60 | 61 | Pass { 62 | Fog { Mode Off } 63 | ZWrite Off 64 | Blend One One 65 | Cull Front 66 | ZTest Always 67 | 68 | 69 | CGPROGRAM 70 | #pragma target 3.0 71 | #pragma vertex vert_deferred 72 | #pragma fragment frag 73 | #pragma exclude_renderers nomrt 74 | 75 | fixed4 frag (unity_v2f_deferred i) : SV_Target 76 | { 77 | half4 light = CalculateLightDeferred(i); 78 | // TODO: squash those NaNs at their source 79 | return isnan(light) ? 0 : light; 80 | } 81 | 82 | ENDCG 83 | } 84 | 85 | } 86 | Fallback Off 87 | } 88 | -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!30 &1 4 | GraphicsSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 10 7 | m_Deferred: 8 | m_Mode: 1 9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} 10 | m_DeferredReflections: 11 | m_Mode: 1 12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} 13 | m_ScreenSpaceShadows: 14 | m_Mode: 1 15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} 16 | m_LegacyDeferred: 17 | m_Mode: 1 18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} 19 | m_DepthNormals: 20 | m_Mode: 1 21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} 22 | m_MotionVectors: 23 | m_Mode: 1 24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} 25 | m_LightHalo: 26 | m_Mode: 1 27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} 28 | m_LensFlare: 29 | m_Mode: 1 30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} 31 | m_AlwaysIncludedShaders: 32 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} 33 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} 34 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} 35 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} 36 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} 37 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 38 | - {fileID: 10782, guid: 0000000000000000f000000000000000, type: 0} 39 | - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} 40 | m_PreloadedShaders: [] 41 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, 42 | type: 0} 43 | m_TransparencySortMode: 0 44 | m_TransparencySortAxis: {x: 0, y: 0, z: 1} 45 | m_DefaultRenderingPath: 3 46 | m_DefaultMobileRenderingPath: 1 47 | m_TierSettings: [] 48 | m_LightmapStripping: 0 49 | m_FogStripping: 0 50 | m_LightmapKeepPlain: 1 51 | m_LightmapKeepDirCombined: 1 52 | m_LightmapKeepDirSeparate: 1 53 | m_LightmapKeepDynamicPlain: 1 54 | m_LightmapKeepDynamicDirCombined: 1 55 | m_LightmapKeepDynamicDirSeparate: 1 56 | m_FogKeepLinear: 1 57 | m_FogKeepExp: 1 58 | m_FogKeepExp2: 1 59 | m_AlbedoSwatchInfos: [] 60 | -------------------------------------------------------------------------------- /Assets/AreaLight/Shaders/AreaLight.shader: -------------------------------------------------------------------------------- 1 | Shader "Hidden/AreaLight" { 2 | SubShader { 3 | Tags { "Queue"="Geometry-1" } 4 | 5 | CGINCLUDE 6 | #include "UnityCG.cginc" 7 | #include "UnityPBSLighting.cginc" 8 | #include "UnityDeferredLibrary.cginc" 9 | 10 | #define AREA_LIGHT_ENABLE_DIFFUSE 1 11 | 12 | #if AREA_LIGHT_SHADOWS 13 | #include "AreaLightShadows.cginc" 14 | #endif 15 | #include "AreaLight.cginc" 16 | 17 | sampler2D _CameraGBufferTexture0; 18 | sampler2D _CameraGBufferTexture1; 19 | sampler2D _CameraGBufferTexture2; 20 | 21 | void DeferredCalculateLightParams ( 22 | unity_v2f_deferred i, 23 | out float3 outWorldPos, 24 | out float2 outUV) 25 | { 26 | i.ray = i.ray * (_ProjectionParams.z / i.ray.z); 27 | float2 uv = i.uv.xy / i.uv.w; 28 | 29 | // read depth and reconstruct world position 30 | float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv); 31 | depth = Linear01Depth (depth); 32 | float4 vpos = float4(i.ray * depth,1); 33 | float3 wpos = mul (unity_CameraToWorld, vpos).xyz; 34 | 35 | outWorldPos = wpos; 36 | outUV = uv; 37 | } 38 | 39 | half4 CalculateLightDeferred (unity_v2f_deferred i) 40 | { 41 | float3 worldPos; 42 | float2 uv; 43 | DeferredCalculateLightParams (i, worldPos, uv); 44 | 45 | half4 gbuffer0 = tex2D (_CameraGBufferTexture0, uv); 46 | half4 gbuffer1 = tex2D (_CameraGBufferTexture1, uv); 47 | half4 gbuffer2 = tex2D (_CameraGBufferTexture2, uv); 48 | 49 | half3 baseColor = gbuffer0.rgb; 50 | half3 specColor = gbuffer1.rgb; 51 | half oneMinusRoughness = gbuffer1.a; 52 | half3 normalWorld = gbuffer2.rgb * 2 - 1; 53 | normalWorld = normalize(normalWorld); 54 | 55 | return CalculateLight (worldPos, baseColor, specColor, oneMinusRoughness, normalWorld, 56 | _LightPos.xyz, _LightColor.xyz).rgbb; 57 | } 58 | ENDCG 59 | 60 | // shadows 61 | Pass 62 | { 63 | Fog { Mode Off } 64 | ZWrite Off 65 | Blend One One 66 | Cull Front 67 | ZTest Always 68 | 69 | CGPROGRAM 70 | #pragma target 3.0 71 | #pragma vertex vert_deferred 72 | #pragma fragment frag 73 | #pragma exclude_renderers nomrt 74 | // only one option, so it will always be set and before any includes 75 | #pragma multi_compile AREA_LIGHT_SHADOWS 76 | 77 | fixed4 frag (unity_v2f_deferred i) : SV_Target 78 | { 79 | return CalculateLightDeferred(i); 80 | } 81 | 82 | ENDCG 83 | } 84 | 85 | // no shadows 86 | Pass 87 | { 88 | Fog { Mode Off } 89 | ZWrite Off 90 | Blend One One 91 | Cull Front 92 | ZTest Always 93 | 94 | CGPROGRAM 95 | #pragma target 3.0 96 | #pragma vertex vert_deferred 97 | #pragma fragment frag 98 | #pragma exclude_renderers nomrt 99 | 100 | fixed4 frag (unity_v2f_deferred i) : SV_Target 101 | { 102 | return CalculateLightDeferred(i); 103 | } 104 | 105 | ENDCG 106 | } 107 | 108 | } 109 | Fallback Off 110 | } 111 | -------------------------------------------------------------------------------- /Assets/AreaLight/Shaders/AreaLightShadows.cginc: -------------------------------------------------------------------------------- 1 | cbuffer POISSON_DISKS { 2 | static half2 poisson[40] = { 3 | half2(0.02971195f, 0.8905211f), 4 | half2(0.2495298f, 0.732075f), 5 | half2(-0.3469206f, 0.6437836f), 6 | half2(-0.01878909f, 0.4827394f), 7 | half2(-0.2725213f, 0.896188f), 8 | half2(-0.6814336f, 0.6480481f), 9 | half2(0.4152045f, 0.2794172f), 10 | half2(0.1310554f, 0.2675925f), 11 | half2(0.5344744f, 0.5624411f), 12 | half2(0.8385689f, 0.5137348f), 13 | half2(0.6045052f, 0.08393857f), 14 | half2(0.4643163f, 0.8684642f), 15 | half2(0.335507f, -0.110113f), 16 | half2(0.03007669f, -0.0007075319f), 17 | half2(0.8077537f, 0.2551664f), 18 | half2(-0.1521498f, 0.2429521f), 19 | half2(-0.2997617f, 0.0234927f), 20 | half2(0.2587779f, -0.4226915f), 21 | half2(-0.01448214f, -0.2720358f), 22 | half2(-0.3937779f, -0.228529f), 23 | half2(-0.7833176f, 0.1737299f), 24 | half2(-0.4447537f, 0.2582748f), 25 | half2(-0.9030743f, 0.406874f), 26 | half2(-0.729588f, -0.2115215f), 27 | half2(-0.5383645f, -0.6681151f), 28 | half2(-0.07709587f, -0.5395499f), 29 | half2(-0.3402214f, -0.4782109f), 30 | half2(-0.5580465f, 0.01399586f), 31 | half2(-0.105644f, -0.9191031f), 32 | half2(-0.8343651f, -0.4750755f), 33 | half2(-0.9959937f, -0.0540134f), 34 | half2(0.1747736f, -0.936202f), 35 | half2(-0.3642297f, -0.926432f), 36 | half2(0.1719682f, -0.6798802f), 37 | half2(0.4424475f, -0.7744268f), 38 | half2(0.6849481f, -0.3031401f), 39 | half2(0.5453879f, -0.5152272f), 40 | half2(0.9634013f, -0.2050581f), 41 | half2(0.9907925f, 0.08320642f), 42 | half2(0.8386722f, -0.5428791f) 43 | }; 44 | }; 45 | 46 | Texture2D _Shadowmap; 47 | SamplerComparisonState sampler_Shadowmap; 48 | 49 | // To get a sampler, which doesn't do comparison 50 | Texture2D _ShadowmapDummy; 51 | SamplerState sampler_ShadowmapDummy; 52 | 53 | half _ShadowReceiverWidth; 54 | half _ShadowReceiverDistanceScale; 55 | half2 _ShadowLightWidth; 56 | half _ShadowBias; 57 | float4x4 _ShadowProjectionMatrix; 58 | 59 | half EdgeSmooth(half2 xy) 60 | { 61 | // Magic tweaks to the shape 62 | float corner = 0.4; 63 | float outset = 1.0; 64 | float smooth = 0.5; 65 | 66 | float d = length(max(abs(xy) - 1 + corner*outset, 0.0)) - corner; 67 | return saturate(1 - smoothstep(-smooth, 0, d)); 68 | } 69 | 70 | half ReverseZ(half z) 71 | { 72 | #if UNITY_REVERSED_Z 73 | return 1.0 - z; 74 | #endif 75 | return z; 76 | } 77 | 78 | half Shadow(half3 position) 79 | { 80 | half4 pClip = mul(_ShadowProjectionMatrix, half4(position, 1)); 81 | half3 p = pClip.xyz/pClip.w; 82 | if (any(step(1.0, abs(p.xy)))) 83 | return 0; 84 | 85 | // The texture contains just 0. But we need to sample it somewhere for Unity to initialize the corresponding sampler. 86 | float dist = _ShadowmapDummy.Sample(sampler_ShadowmapDummy, 0).a; 87 | 88 | half edgeSmooth = EdgeSmooth(p.xy); 89 | p = p * 0.5 + 0.5; 90 | 91 | for(int j = 0; j < 10; ++j) 92 | { 93 | half2 offset = poisson[j + 24] * _ShadowReceiverWidth; 94 | float depth = ReverseZ(_Shadowmap.SampleLevel(sampler_ShadowmapDummy, p.xy + offset, 0).r); 95 | 96 | dist += max(0.0, p.z - depth); 97 | } 98 | 99 | dist *= _ShadowReceiverDistanceScale; 100 | 101 | p.z -= _ShadowBias/pClip.w; 102 | p.z = ReverseZ(p.z); 103 | half shadow = 0; 104 | for(int i = 0; i < 32; ++i) 105 | { 106 | half lightWidth = lerp(_ShadowLightWidth.x, _ShadowLightWidth.y, min(1.0, dist)); 107 | const half2 offset = poisson[i] * lightWidth; 108 | shadow += _Shadowmap.SampleCmpLevelZero(sampler_Shadowmap, p.xy + offset, p.z); 109 | } 110 | 111 | return shadow * edgeSmooth / 32.0; 112 | } 113 | -------------------------------------------------------------------------------- /Assets/Scenes/Materials/StandardAlphaBlended-VolumetricFog.shader: -------------------------------------------------------------------------------- 1 | Shader "Custom/StandardAlphaBlended-VolumetricFog" 2 | { 3 | Properties 4 | { 5 | _Color ("Color", Color) = (1,1,1,1) 6 | _MainTex ("Albedo (RGB)", 2D) = "white" {} 7 | _Glossiness ("Smoothness", Range(0,1)) = 0.5 8 | _Metallic ("Metallic", Range(0,1)) = 0.0 9 | } 10 | SubShader 11 | { 12 | Tags {"Queue" = "Transparent" "RenderType"="Transparent" } 13 | LOD 200 14 | 15 | CGPROGRAM 16 | 17 | #pragma surface surf Standard fullforwardshadows alpha finalcolor:ApplyFog 18 | #pragma target 3.0 19 | #pragma multi_compile _ VOLUMETRIC_FOG 20 | 21 | #if VOLUMETRIC_FOG 22 | #include "../../VolumetricFog/Shaders/VolumetricFog.cginc" 23 | #endif 24 | 25 | sampler2D _MainTex; 26 | sampler2D _CameraDepthTexture; 27 | 28 | struct Input { 29 | float2 uv_MainTex; 30 | float4 screenPos; 31 | }; 32 | 33 | void ApplyFog(Input IN, SurfaceOutputStandard o, inout fixed4 color) 34 | { 35 | #if VOLUMETRIC_FOG 36 | half3 uvscreen = IN.screenPos.xyz/IN.screenPos.w; 37 | half linear01Depth = Linear01Depth(uvscreen.z); 38 | fixed4 fog = Fog(linear01Depth, uvscreen.xy); 39 | 40 | // Always apply fog attenuation - also in the forward add pass. 41 | color.rgb *= fog.a; 42 | 43 | // Alpha premultiply mode (used with alpha and Standard lighting function, or explicitly alpha:premul) 44 | // uses source blend factor of One instead of SrcAlpha. `color` is compensated for it, so we need to compensate 45 | // the amount of inscattering too. A note on why this works: below. 46 | #if _ALPHAPREMULTIPLY_ON 47 | fog.rgb *= o.Alpha; 48 | #endif 49 | 50 | // Add inscattering only once, so in forward base, but not forward add. 51 | #ifndef UNITY_PASS_FORWARDADD 52 | color.rgb += fog.rgb; 53 | #endif 54 | 55 | // So why does multiplying the inscattered light by alpha work? 56 | // In other words: how did fog ever work, if opaque objects add all of the inscattered light 57 | // between them and the camera, and then the transparencies add even more? 58 | // 59 | // This is our scene initially: 60 | // scene |---is0---------------------------------------> camera 61 | // 62 | // And that's with the transparent object added in between the opaque stuff and the camera: 63 | // scene |---is1---> transparent |---is2---------------> camera 64 | // 65 | // When rendering, we start with the opaque part of the scene and add all the light inscattered between that and the camera: is0. 66 | // Then we add the transparent object. It does two things (let's consider the alpha premultiply version): 67 | // - Dims whatever was behind it (including is0) by OneMinusSrcAlpha 68 | // - Adds light inscattered in front of it (is2), multiplied by Alpha 69 | // 70 | // So all in all we end up with this much inscattered light: 71 | // is0 * OneMinusSrcAlpha + is2 * Alpha 72 | // 73 | // Judging by the diagram, though, the correct amount should be: 74 | // is1 * OneMinusSrcAlpha + is2 75 | // 76 | // Turns out the two expressions are equal - who would've thunk? 77 | // is1 = is0 - is2 78 | // (is0 - is2) * OneMinusSrcAlpha + is2 79 | // is0 * OneMinusSrcAlpha - is2 * (1 - Alpha) + is2 80 | // is0 * OneMinusSrcAlpha - is2 + is2 * Alpha + is2 81 | // is0 * OneMinusSrcAlpha + is2 * Alpha 82 | 83 | // I leave figuring out if the fog attenuation is correct as an exercise to the reader ;) 84 | #endif 85 | } 86 | 87 | half _Glossiness; 88 | half _Metallic; 89 | fixed4 _Color; 90 | 91 | void surf (Input IN, inout SurfaceOutputStandard o) 92 | { 93 | fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; 94 | o.Albedo = c.rgb; 95 | o.Metallic = _Metallic; 96 | o.Smoothness = _Glossiness; 97 | o.Alpha = c.a; 98 | } 99 | ENDCG 100 | } 101 | FallBack "Standard" 102 | } -------------------------------------------------------------------------------- /Assets/AreaLight/Scripts/AreaLight.Direct.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Rendering; 3 | using System.Collections.Generic; 4 | 5 | public partial class AreaLight : MonoBehaviour 6 | { 7 | [HideInInspector] 8 | public Mesh m_Cube; 9 | [HideInInspector] 10 | public Shader m_ProxyShader; 11 | Material m_ProxyMaterial; 12 | static Texture2D s_TransformInvTexture_Specular; 13 | static Texture2D s_TransformInvTexture_Diffuse; 14 | static Texture2D s_AmpDiffAmpSpecFresnel; 15 | 16 | Dictionary m_Cameras = new Dictionary(); 17 | static CameraEvent kCameraEvent = CameraEvent.AfterLighting; 18 | 19 | bool InitDirect() 20 | { 21 | if (m_ProxyShader == null || m_Cube == null) 22 | return false; 23 | 24 | // Proxy 25 | m_ProxyMaterial = new Material(m_ProxyShader); 26 | m_ProxyMaterial.hideFlags = HideFlags.HideAndDontSave; 27 | 28 | return true; 29 | } 30 | 31 | void SetUpLUTs() 32 | { 33 | if (s_TransformInvTexture_Diffuse == null) 34 | s_TransformInvTexture_Diffuse = AreaLightLUT.LoadLUT(AreaLightLUT.LUTType.TransformInv_DisneyDiffuse); 35 | if (s_TransformInvTexture_Specular == null) 36 | s_TransformInvTexture_Specular = AreaLightLUT.LoadLUT(AreaLightLUT.LUTType.TransformInv_GGX); 37 | if (s_AmpDiffAmpSpecFresnel == null) 38 | s_AmpDiffAmpSpecFresnel = AreaLightLUT.LoadLUT(AreaLightLUT.LUTType.AmpDiffAmpSpecFresnel); 39 | 40 | m_ProxyMaterial.SetTexture("_TransformInv_Diffuse", s_TransformInvTexture_Diffuse); 41 | m_ProxyMaterial.SetTexture("_TransformInv_Specular", s_TransformInvTexture_Specular); 42 | m_ProxyMaterial.SetTexture("_AmpDiffAmpSpecFresnel", s_AmpDiffAmpSpecFresnel); 43 | } 44 | 45 | void Cleanup() 46 | { 47 | for(var e = m_Cameras.GetEnumerator(); e.MoveNext();) 48 | { 49 | var cam = e.Current; 50 | if (cam.Key != null && cam.Value != null) 51 | { 52 | cam.Key.RemoveCommandBuffer (kCameraEvent, cam.Value); 53 | } 54 | } 55 | m_Cameras.Clear(); 56 | } 57 | 58 | static readonly float[,] offsets = new float[4,2] {{1, 1}, {1, -1}, {-1, -1}, {-1, 1}}; 59 | 60 | CommandBuffer GetOrCreateCommandBuffer(Camera cam) 61 | { 62 | if(cam == null) 63 | return null; 64 | 65 | CommandBuffer buf = null; 66 | if(!m_Cameras.ContainsKey(cam)) { 67 | buf = new CommandBuffer(); 68 | buf.name = /*"Area light: " +*/ gameObject.name; 69 | m_Cameras[cam] = buf; 70 | cam.AddCommandBuffer(kCameraEvent, buf); 71 | cam.depthTextureMode |= DepthTextureMode.Depth; 72 | } else { 73 | buf = m_Cameras[cam]; 74 | buf.Clear(); 75 | } 76 | 77 | return buf; 78 | } 79 | 80 | public void SetUpCommandBuffer() 81 | { 82 | if (InsideShadowmapCameraRender()) 83 | return; 84 | 85 | Camera cam = Camera.current; 86 | CommandBuffer buf = GetOrCreateCommandBuffer(cam); 87 | 88 | buf.SetGlobalVector("_LightPos", transform.position); 89 | buf.SetGlobalVector("_LightColor", GetColor()); 90 | SetUpLUTs(); 91 | 92 | // Needed as we're using the vert_deferred vertex shader from UnityDeferredLibrary.cginc 93 | // TODO: Make the light render as quad if it intersects both near and far plane. 94 | // (Also missing: rendering as front faces when near doesn't intersect, stencil optimisations) 95 | buf.SetGlobalFloat("_LightAsQuad", 0); 96 | 97 | // A little bit of bias to prevent the light from lighting itself - the source quad 98 | float z = 0.01f; 99 | Transform t = transform; 100 | 101 | Matrix4x4 lightVerts = new Matrix4x4(); 102 | for (int i = 0; i < 4; i++) 103 | lightVerts.SetRow(i, t.TransformPoint(new Vector3(m_Size.x * offsets[i,0], m_Size.y * offsets[i,1], z) * 0.5f)); 104 | buf.SetGlobalMatrix("_LightVerts", lightVerts); 105 | 106 | if (m_Shadows) 107 | SetUpShadowmapForSampling(buf); 108 | 109 | Matrix4x4 m = Matrix4x4.TRS(new Vector3(0, 0, 10.0f), Quaternion.identity, Vector3.one * 20); 110 | buf.DrawMesh(m_Cube, t.localToWorldMatrix * m, m_ProxyMaterial, 0, m_Shadows ? /*shadows*/ 0 : /*no shadows*/ 1); 111 | } 112 | 113 | void SetKeyword(string keyword, bool on) 114 | { 115 | if (on) 116 | m_ProxyMaterial.EnableKeyword(keyword); 117 | else 118 | m_ProxyMaterial.DisableKeyword(keyword); 119 | } 120 | 121 | void ReleaseTemporary(ref RenderTexture rt) 122 | { 123 | if (rt == null) 124 | return; 125 | 126 | RenderTexture.ReleaseTemporary(rt); 127 | rt = null; 128 | } 129 | 130 | Color GetColor() 131 | { 132 | if (QualitySettings.activeColorSpace == ColorSpace.Gamma) 133 | return m_Color * m_Intensity; 134 | 135 | return new Color( 136 | Mathf.GammaToLinearSpace(m_Color.r * m_Intensity), 137 | Mathf.GammaToLinearSpace(m_Color.g * m_Intensity), 138 | Mathf.GammaToLinearSpace(m_Color.b * m_Intensity), 139 | 1.0f 140 | ); 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /Assets/AreaLight/Shaders/AreaLightSource.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: AreaLightSource 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _EMISSION 12 | m_LightmapFlags: 1 13 | m_CustomRenderQueue: -1 14 | stringTagMap: {} 15 | m_SavedProperties: 16 | serializedVersion: 2 17 | m_TexEnvs: 18 | - first: 19 | name: _BumpMap 20 | second: 21 | m_Texture: {fileID: 0} 22 | m_Scale: {x: 1, y: 1} 23 | m_Offset: {x: 0, y: 0} 24 | - first: 25 | name: _DetailAlbedoMap 26 | second: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - first: 31 | name: _DetailMask 32 | second: 33 | m_Texture: {fileID: 0} 34 | m_Scale: {x: 1, y: 1} 35 | m_Offset: {x: 0, y: 0} 36 | - first: 37 | name: _DetailNormalMap 38 | second: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - first: 43 | name: _EmissionMap 44 | second: 45 | m_Texture: {fileID: 0} 46 | m_Scale: {x: 1, y: 1} 47 | m_Offset: {x: 0, y: 0} 48 | - first: 49 | name: _MainTex 50 | second: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - first: 55 | name: _MetallicGlossMap 56 | second: 57 | m_Texture: {fileID: 0} 58 | m_Scale: {x: 1, y: 1} 59 | m_Offset: {x: 0, y: 0} 60 | - first: 61 | name: _OcclusionMap 62 | second: 63 | m_Texture: {fileID: 0} 64 | m_Scale: {x: 1, y: 1} 65 | m_Offset: {x: 0, y: 0} 66 | - first: 67 | name: _ParallaxMap 68 | second: 69 | m_Texture: {fileID: 0} 70 | m_Scale: {x: 1, y: 1} 71 | m_Offset: {x: 0, y: 0} 72 | - first: 73 | name: _SpecGlossMap 74 | second: 75 | m_Texture: {fileID: 0} 76 | m_Scale: {x: 1, y: 1} 77 | m_Offset: {x: 0, y: 0} 78 | m_Floats: 79 | - first: 80 | name: _BumpScale 81 | second: 1 82 | - first: 83 | name: _CullMode 84 | second: 2 85 | - first: 86 | name: _Cutoff 87 | second: 0.5 88 | - first: 89 | name: _DetailMode 90 | second: 0 91 | - first: 92 | name: _DetailNormalMapScale 93 | second: 1 94 | - first: 95 | name: _DstBlend 96 | second: 0 97 | - first: 98 | name: _GlossMapScale 99 | second: 1 100 | - first: 101 | name: _Glossiness 102 | second: 0 103 | - first: 104 | name: _GlossyReflections 105 | second: 1 106 | - first: 107 | name: _MetaDiffuseScale 108 | second: 1 109 | - first: 110 | name: _MetaEmissionScale 111 | second: 1 112 | - first: 113 | name: _MetaMetallicSoup 114 | second: 1 115 | - first: 116 | name: _MetaSpecularScale 117 | second: 1 118 | - first: 119 | name: _MetaUseCustom 120 | second: 0 121 | - first: 122 | name: _Metallic 123 | second: 0 124 | - first: 125 | name: _Mode 126 | second: 0 127 | - first: 128 | name: _OcclusionStrength 129 | second: 1 130 | - first: 131 | name: _Parallax 132 | second: 0.02 133 | - first: 134 | name: _SmoothnessTextureChannel 135 | second: 0 136 | - first: 137 | name: _SpecularHighlights 138 | second: 1 139 | - first: 140 | name: _SrcBlend 141 | second: 1 142 | - first: 143 | name: _Translucency 144 | second: 0 145 | - first: 146 | name: _UVDetailMask 147 | second: 0 148 | - first: 149 | name: _UVSec 150 | second: 0 151 | - first: 152 | name: _VertexOcclusionPower 153 | second: 1 154 | - first: 155 | name: _ZWrite 156 | second: 1 157 | m_Colors: 158 | - first: 159 | name: _Color 160 | second: {r: 0, g: 0, b: 0, a: 1} 161 | - first: 162 | name: _EmissionColor 163 | second: {r: 1, g: 1, b: 1, a: 1} 164 | - first: 165 | name: _MetaDiffuseAdd 166 | second: {r: 0, g: 0, b: 0, a: 1} 167 | - first: 168 | name: _MetaDiffuseTint 169 | second: {r: 1, g: 1, b: 1, a: 1} 170 | - first: 171 | name: _MetaEmissionAdd 172 | second: {r: 0, g: 0, b: 0, a: 1} 173 | - first: 174 | name: _MetaEmissionTint 175 | second: {r: 1, g: 1, b: 1, a: 1} 176 | - first: 177 | name: _MetaSpecularAdd 178 | second: {r: 0, g: 0, b: 0, a: 1} 179 | - first: 180 | name: _MetaSpecularTint 181 | second: {r: 1, g: 1, b: 1, a: 1} 182 | - first: 183 | name: _SpecColor 184 | second: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} 185 | -------------------------------------------------------------------------------- /Assets/Scenes/Materials/blck.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: blck 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _EMISSION 12 | m_LightmapFlags: 1 13 | m_CustomRenderQueue: -1 14 | stringTagMap: {} 15 | m_SavedProperties: 16 | serializedVersion: 2 17 | m_TexEnvs: 18 | - first: 19 | name: _BumpMap 20 | second: 21 | m_Texture: {fileID: 0} 22 | m_Scale: {x: 1, y: 1} 23 | m_Offset: {x: 0, y: 0} 24 | - first: 25 | name: _DetailAlbedoMap 26 | second: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - first: 31 | name: _DetailMask 32 | second: 33 | m_Texture: {fileID: 0} 34 | m_Scale: {x: 1, y: 1} 35 | m_Offset: {x: 0, y: 0} 36 | - first: 37 | name: _DetailNormalMap 38 | second: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - first: 43 | name: _EmissionMap 44 | second: 45 | m_Texture: {fileID: 0} 46 | m_Scale: {x: 1, y: 1} 47 | m_Offset: {x: 0, y: 0} 48 | - first: 49 | name: _MainTex 50 | second: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - first: 55 | name: _MetallicGlossMap 56 | second: 57 | m_Texture: {fileID: 0} 58 | m_Scale: {x: 1, y: 1} 59 | m_Offset: {x: 0, y: 0} 60 | - first: 61 | name: _OcclusionMap 62 | second: 63 | m_Texture: {fileID: 0} 64 | m_Scale: {x: 1, y: 1} 65 | m_Offset: {x: 0, y: 0} 66 | - first: 67 | name: _ParallaxMap 68 | second: 69 | m_Texture: {fileID: 0} 70 | m_Scale: {x: 1, y: 1} 71 | m_Offset: {x: 0, y: 0} 72 | - first: 73 | name: _SpecGlossMap 74 | second: 75 | m_Texture: {fileID: 0} 76 | m_Scale: {x: 1, y: 1} 77 | m_Offset: {x: 0, y: 0} 78 | m_Floats: 79 | - first: 80 | name: _BumpScale 81 | second: 1 82 | - first: 83 | name: _CullMode 84 | second: 2 85 | - first: 86 | name: _Cutoff 87 | second: 0.5 88 | - first: 89 | name: _DetailMode 90 | second: 0 91 | - first: 92 | name: _DetailNormalMapScale 93 | second: 1 94 | - first: 95 | name: _DstBlend 96 | second: 0 97 | - first: 98 | name: _GlossMapScale 99 | second: 1 100 | - first: 101 | name: _Glossiness 102 | second: 0.633 103 | - first: 104 | name: _GlossyReflections 105 | second: 1 106 | - first: 107 | name: _LightProbeScale 108 | second: 1 109 | - first: 110 | name: _MetaDiffuseScale 111 | second: 1 112 | - first: 113 | name: _MetaEmissionScale 114 | second: 1 115 | - first: 116 | name: _MetaMetallicSoup 117 | second: 1 118 | - first: 119 | name: _MetaSpecularScale 120 | second: 1 121 | - first: 122 | name: _MetaUseCustom 123 | second: 0 124 | - first: 125 | name: _Metallic 126 | second: 0 127 | - first: 128 | name: _Mode 129 | second: 0 130 | - first: 131 | name: _OcclusionStrength 132 | second: 1 133 | - first: 134 | name: _Parallax 135 | second: 0.02 136 | - first: 137 | name: _ReflectionProbeBoost 138 | second: 1 139 | - first: 140 | name: _SmoothnessTextureChannel 141 | second: 0 142 | - first: 143 | name: _SpecularHighlights 144 | second: 1 145 | - first: 146 | name: _SrcBlend 147 | second: 1 148 | - first: 149 | name: _Translucency 150 | second: 0 151 | - first: 152 | name: _UVDetailMask 153 | second: 0 154 | - first: 155 | name: _UVSec 156 | second: 0 157 | - first: 158 | name: _VertexOcclusionPower 159 | second: 1 160 | - first: 161 | name: _ZWrite 162 | second: 1 163 | m_Colors: 164 | - first: 165 | name: _Color 166 | second: {r: 0.16176468, g: 0.16176468, b: 0.16176468, a: 1} 167 | - first: 168 | name: _EmissionColor 169 | second: {r: 0, g: 0, b: 0, a: 1} 170 | - first: 171 | name: _MetaDiffuseAdd 172 | second: {r: 0, g: 0, b: 0, a: 1} 173 | - first: 174 | name: _MetaDiffuseTint 175 | second: {r: 1, g: 1, b: 1, a: 1} 176 | - first: 177 | name: _MetaEmissionAdd 178 | second: {r: 0, g: 0, b: 0, a: 1} 179 | - first: 180 | name: _MetaEmissionTint 181 | second: {r: 1, g: 1, b: 1, a: 1} 182 | - first: 183 | name: _MetaSpecularAdd 184 | second: {r: 0, g: 0, b: 0, a: 1} 185 | - first: 186 | name: _MetaSpecularTint 187 | second: {r: 1, g: 1, b: 1, a: 1} 188 | - first: 189 | name: _SpecColor 190 | second: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} 191 | -------------------------------------------------------------------------------- /Assets/TubeLight/Shaders/TubeLightSource.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: TubeLightSource 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _EMISSION 12 | m_LightmapFlags: 0 13 | m_CustomRenderQueue: -1 14 | stringTagMap: {} 15 | m_SavedProperties: 16 | serializedVersion: 2 17 | m_TexEnvs: 18 | - first: 19 | name: _BumpMap 20 | second: 21 | m_Texture: {fileID: 0} 22 | m_Scale: {x: 1, y: 1} 23 | m_Offset: {x: 0, y: 0} 24 | - first: 25 | name: _DetailAlbedoMap 26 | second: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - first: 31 | name: _DetailMask 32 | second: 33 | m_Texture: {fileID: 0} 34 | m_Scale: {x: 1, y: 1} 35 | m_Offset: {x: 0, y: 0} 36 | - first: 37 | name: _DetailNormalMap 38 | second: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - first: 43 | name: _EmissionMap 44 | second: 45 | m_Texture: {fileID: 0} 46 | m_Scale: {x: 1, y: 1} 47 | m_Offset: {x: 0, y: 0} 48 | - first: 49 | name: _MainTex 50 | second: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - first: 55 | name: _MetallicGlossMap 56 | second: 57 | m_Texture: {fileID: 0} 58 | m_Scale: {x: 1, y: 1} 59 | m_Offset: {x: 0, y: 0} 60 | - first: 61 | name: _OcclusionMap 62 | second: 63 | m_Texture: {fileID: 0} 64 | m_Scale: {x: 1, y: 1} 65 | m_Offset: {x: 0, y: 0} 66 | - first: 67 | name: _ParallaxMap 68 | second: 69 | m_Texture: {fileID: 0} 70 | m_Scale: {x: 1, y: 1} 71 | m_Offset: {x: 0, y: 0} 72 | - first: 73 | name: _SpecGlossMap 74 | second: 75 | m_Texture: {fileID: 0} 76 | m_Scale: {x: 1, y: 1} 77 | m_Offset: {x: 0, y: 0} 78 | m_Floats: 79 | - first: 80 | name: _BumpScale 81 | second: 1 82 | - first: 83 | name: _CullMode 84 | second: 2 85 | - first: 86 | name: _Cutoff 87 | second: 0.5 88 | - first: 89 | name: _DetailMode 90 | second: 0 91 | - first: 92 | name: _DetailNormalMapScale 93 | second: 1 94 | - first: 95 | name: _DstBlend 96 | second: 0 97 | - first: 98 | name: _GlossMapScale 99 | second: 1 100 | - first: 101 | name: _Glossiness 102 | second: 0.234 103 | - first: 104 | name: _GlossyReflections 105 | second: 1 106 | - first: 107 | name: _LightProbeScale 108 | second: 1 109 | - first: 110 | name: _MetaDiffuseScale 111 | second: 1 112 | - first: 113 | name: _MetaEmissionScale 114 | second: 1 115 | - first: 116 | name: _MetaMetallicSoup 117 | second: 1 118 | - first: 119 | name: _MetaSpecularScale 120 | second: 1 121 | - first: 122 | name: _MetaUseCustom 123 | second: 0 124 | - first: 125 | name: _Metallic 126 | second: 0 127 | - first: 128 | name: _Mode 129 | second: 0 130 | - first: 131 | name: _OcclusionStrength 132 | second: 1 133 | - first: 134 | name: _Parallax 135 | second: 0.02 136 | - first: 137 | name: _ReflectionProbeBoost 138 | second: 1 139 | - first: 140 | name: _SmoothnessTextureChannel 141 | second: 0 142 | - first: 143 | name: _SpecularHighlights 144 | second: 1 145 | - first: 146 | name: _SrcBlend 147 | second: 1 148 | - first: 149 | name: _Translucency 150 | second: 0 151 | - first: 152 | name: _UVDetailMask 153 | second: 0 154 | - first: 155 | name: _UVSec 156 | second: 0 157 | - first: 158 | name: _VertexOcclusionPower 159 | second: 1 160 | - first: 161 | name: _ZWrite 162 | second: 1 163 | m_Colors: 164 | - first: 165 | name: _Color 166 | second: {r: 0.47794116, g: 1, b: 0.85685486, a: 1} 167 | - first: 168 | name: _EmissionColor 169 | second: {r: 1, g: 1, b: 1, a: 1} 170 | - first: 171 | name: _MetaDiffuseAdd 172 | second: {r: 0, g: 0, b: 0, a: 1} 173 | - first: 174 | name: _MetaDiffuseTint 175 | second: {r: 1, g: 1, b: 1, a: 1} 176 | - first: 177 | name: _MetaEmissionAdd 178 | second: {r: 0, g: 0, b: 0, a: 1} 179 | - first: 180 | name: _MetaEmissionTint 181 | second: {r: 1, g: 1, b: 1, a: 1} 182 | - first: 183 | name: _MetaSpecularAdd 184 | second: {r: 0, g: 0, b: 0, a: 1} 185 | - first: 186 | name: _MetaSpecularTint 187 | second: {r: 1, g: 1, b: 1, a: 1} 188 | - first: 189 | name: _SpecColor 190 | second: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} 191 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 5 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: Fastest 11 | pixelLightCount: 0 12 | shadows: 0 13 | shadowResolution: 0 14 | shadowProjection: 1 15 | shadowCascades: 1 16 | shadowDistance: 15 17 | shadowNearPlaneOffset: 2 18 | shadowCascade2Split: 0.33333334 19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 20 | blendWeights: 1 21 | textureQuality: 1 22 | anisotropicTextures: 0 23 | antiAliasing: 0 24 | softParticles: 0 25 | softVegetation: 0 26 | realtimeReflectionProbes: 0 27 | billboardsFaceCameraPosition: 0 28 | vSyncCount: 0 29 | lodBias: 0.3 30 | maximumLODLevel: 0 31 | particleRaycastBudget: 4 32 | asyncUploadTimeSlice: 2 33 | asyncUploadBufferSize: 4 34 | excludedTargetPlatforms: [] 35 | - serializedVersion: 2 36 | name: Fast 37 | pixelLightCount: 0 38 | shadows: 0 39 | shadowResolution: 0 40 | shadowProjection: 1 41 | shadowCascades: 1 42 | shadowDistance: 20 43 | shadowNearPlaneOffset: 2 44 | shadowCascade2Split: 0.33333334 45 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 46 | blendWeights: 2 47 | textureQuality: 0 48 | anisotropicTextures: 0 49 | antiAliasing: 0 50 | softParticles: 0 51 | softVegetation: 0 52 | realtimeReflectionProbes: 0 53 | billboardsFaceCameraPosition: 0 54 | vSyncCount: 0 55 | lodBias: 0.4 56 | maximumLODLevel: 0 57 | particleRaycastBudget: 16 58 | asyncUploadTimeSlice: 2 59 | asyncUploadBufferSize: 4 60 | excludedTargetPlatforms: [] 61 | - serializedVersion: 2 62 | name: Simple 63 | pixelLightCount: 1 64 | shadows: 1 65 | shadowResolution: 0 66 | shadowProjection: 1 67 | shadowCascades: 1 68 | shadowDistance: 20 69 | shadowNearPlaneOffset: 2 70 | shadowCascade2Split: 0.33333334 71 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 72 | blendWeights: 2 73 | textureQuality: 0 74 | anisotropicTextures: 1 75 | antiAliasing: 0 76 | softParticles: 0 77 | softVegetation: 0 78 | realtimeReflectionProbes: 0 79 | billboardsFaceCameraPosition: 0 80 | vSyncCount: 1 81 | lodBias: 0.7 82 | maximumLODLevel: 0 83 | particleRaycastBudget: 64 84 | asyncUploadTimeSlice: 2 85 | asyncUploadBufferSize: 4 86 | excludedTargetPlatforms: [] 87 | - serializedVersion: 2 88 | name: Good 89 | pixelLightCount: 2 90 | shadows: 2 91 | shadowResolution: 1 92 | shadowProjection: 1 93 | shadowCascades: 2 94 | shadowDistance: 40 95 | shadowNearPlaneOffset: 2 96 | shadowCascade2Split: 0.33333334 97 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 98 | blendWeights: 2 99 | textureQuality: 0 100 | anisotropicTextures: 1 101 | antiAliasing: 0 102 | softParticles: 0 103 | softVegetation: 1 104 | realtimeReflectionProbes: 1 105 | billboardsFaceCameraPosition: 1 106 | vSyncCount: 1 107 | lodBias: 1 108 | maximumLODLevel: 0 109 | particleRaycastBudget: 256 110 | asyncUploadTimeSlice: 2 111 | asyncUploadBufferSize: 4 112 | excludedTargetPlatforms: [] 113 | - serializedVersion: 2 114 | name: Beautiful 115 | pixelLightCount: 3 116 | shadows: 2 117 | shadowResolution: 2 118 | shadowProjection: 1 119 | shadowCascades: 2 120 | shadowDistance: 70 121 | shadowNearPlaneOffset: 2 122 | shadowCascade2Split: 0.33333334 123 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 124 | blendWeights: 4 125 | textureQuality: 0 126 | anisotropicTextures: 2 127 | antiAliasing: 2 128 | softParticles: 1 129 | softVegetation: 1 130 | realtimeReflectionProbes: 1 131 | billboardsFaceCameraPosition: 1 132 | vSyncCount: 1 133 | lodBias: 1.5 134 | maximumLODLevel: 0 135 | particleRaycastBudget: 1024 136 | asyncUploadTimeSlice: 2 137 | asyncUploadBufferSize: 4 138 | excludedTargetPlatforms: [] 139 | - serializedVersion: 2 140 | name: Fantastic 141 | pixelLightCount: 4 142 | shadows: 2 143 | shadowResolution: 2 144 | shadowProjection: 1 145 | shadowCascades: 4 146 | shadowDistance: 150 147 | shadowNearPlaneOffset: 2 148 | shadowCascade2Split: 0.33333334 149 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 150 | blendWeights: 4 151 | textureQuality: 0 152 | anisotropicTextures: 2 153 | antiAliasing: 2 154 | softParticles: 1 155 | softVegetation: 1 156 | realtimeReflectionProbes: 1 157 | billboardsFaceCameraPosition: 1 158 | vSyncCount: 1 159 | lodBias: 2 160 | maximumLODLevel: 0 161 | particleRaycastBudget: 4096 162 | asyncUploadTimeSlice: 2 163 | asyncUploadBufferSize: 4 164 | excludedTargetPlatforms: [] 165 | m_PerPlatformDefaultQuality: 166 | Android: 2 167 | Nintendo 3DS: 5 168 | PS3: 5 169 | PS4: 5 170 | PSM: 5 171 | PSP2: 2 172 | Samsung TV: 2 173 | Standalone: 5 174 | Tizen: 2 175 | Web: 5 176 | WebGL: 3 177 | WiiU: 5 178 | Windows Store Apps: 5 179 | XBOX360: 5 180 | XboxOne: 5 181 | iPhone: 2 182 | tvOS: 5 183 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Scripts/FogLight.DirectionalShadow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Rendering; 3 | 4 | public partial class FogLight : LightOverride 5 | { 6 | CommandBuffer m_BufGrabShadowmap; 7 | CommandBuffer m_BufGrabShadowParams; 8 | RenderTexture m_Shadowmap; 9 | 10 | ComputeBuffer m_ShadowParamsCB; 11 | //[HideInInspector] 12 | public Shader m_BlurShadowmapShader; 13 | Material m_BlurShadowmapMaterial; 14 | 15 | public Shader m_CopyShadowParamsShader; 16 | Material m_CopyShadowParamsMaterial; 17 | 18 | bool directionalShadow {get{ return m_Shadows && type == Type.Directional; }} 19 | 20 | void InitDirectionalShadowmap() 21 | { 22 | if (m_BufGrabShadowmap != null || !directionalShadow) 23 | return; 24 | 25 | Light light = GetComponent(); 26 | 27 | m_BufGrabShadowmap = new CommandBuffer(); 28 | m_BufGrabShadowmap.name = "Grab shadowmap for Volumetric Fog"; 29 | light.AddCommandBuffer(LightEvent.AfterShadowMap, m_BufGrabShadowmap); 30 | 31 | m_BufGrabShadowParams = new CommandBuffer(); 32 | m_BufGrabShadowParams.name = "Grab shadow params for Volumetric Fog"; 33 | light.AddCommandBuffer(LightEvent.BeforeScreenspaceMask, m_BufGrabShadowParams); 34 | 35 | m_BlurShadowmapMaterial = new Material(m_BlurShadowmapShader); 36 | m_BlurShadowmapMaterial.hideFlags = HideFlags.HideAndDontSave; 37 | 38 | m_CopyShadowParamsMaterial = new Material(m_CopyShadowParamsShader); 39 | m_CopyShadowParamsMaterial.hideFlags = HideFlags.HideAndDontSave; 40 | } 41 | 42 | int[] temp; 43 | 44 | public void UpdateDirectionalShadowmap() 45 | { 46 | InitDirectionalShadowmap(); 47 | 48 | if (m_BufGrabShadowmap != null) 49 | m_BufGrabShadowmap.Clear(); 50 | if (m_BufGrabShadowParams != null) 51 | m_BufGrabShadowParams.Clear(); 52 | 53 | if (!directionalShadow) 54 | return; 55 | 56 | // Copy directional shadowmap params - they're only set for regular shaders, but we need them in compute 57 | if (m_ShadowParamsCB == null) 58 | m_ShadowParamsCB = new ComputeBuffer(1, 336); 59 | Graphics.SetRandomWriteTarget(2, m_ShadowParamsCB); 60 | m_BufGrabShadowParams.DrawProcedural(Matrix4x4.identity, m_CopyShadowParamsMaterial, 0, MeshTopology.Points, 1); 61 | 62 | // TODO: get the real size of the shadowmap 63 | int startRes = 4096; 64 | // To make things easier, blurred shadowmap is at most half the size of the regular. 65 | int targetRes = Mathf.Min((int)m_ShadowmapRes, startRes/2); 66 | int downsampleSteps = (int)Mathf.Log(startRes / targetRes, 2); 67 | 68 | RenderTargetIdentifier shadowmap = BuiltinRenderTextureType.CurrentActive; 69 | m_BufGrabShadowmap.SetShadowSamplingMode(shadowmap, ShadowSamplingMode.RawDepth); 70 | 71 | // RFloat for ESM, RGHalf for VSM 72 | RenderTextureFormat format = RenderTextureFormat.RGHalf; 73 | 74 | ReleaseTemporary(ref m_Shadowmap); 75 | m_Shadowmap = RenderTexture.GetTemporary(targetRes, targetRes, 0, format, RenderTextureReadWrite.Linear); 76 | m_Shadowmap.filterMode = FilterMode.Bilinear; 77 | m_Shadowmap.wrapMode = TextureWrapMode.Clamp; 78 | 79 | if (temp == null || temp.Length != downsampleSteps - 1) 80 | temp = new int[downsampleSteps - 1]; 81 | 82 | for (int i = 0, currentRes = startRes/2; i < downsampleSteps; i++) 83 | { 84 | m_BufGrabShadowmap.SetGlobalVector("_TexelSize", new Vector4(0.5f/currentRes, 0.5f/currentRes, 0, 0)); 85 | 86 | RenderTargetIdentifier targetRT; 87 | 88 | if (i < downsampleSteps - 1) 89 | { 90 | temp[i] = Shader.PropertyToID("ShadowmapDownscaleTemp" + i); 91 | m_BufGrabShadowmap.GetTemporaryRT(temp[i], currentRes, currentRes, 0, FilterMode.Bilinear, format, RenderTextureReadWrite.Linear); 92 | targetRT = new RenderTargetIdentifier(temp[i]); 93 | } 94 | else 95 | { 96 | // Last step: write into the shadowmap texture 97 | targetRT = new RenderTargetIdentifier(m_Shadowmap); 98 | } 99 | 100 | if (i == 0) 101 | { 102 | // This step should convert to ESM/VSM 103 | // m_BufGrabShadowmap.Blit(shadowmap, targetRT); 104 | m_BufGrabShadowmap.SetGlobalTexture("_DirShadowmap", shadowmap); 105 | m_BufGrabShadowmap.Blit(null, targetRT, m_BlurShadowmapMaterial, /*sample & convert to VSM*/ 4); 106 | } 107 | else 108 | { 109 | m_BufGrabShadowmap.Blit(temp[i - 1], targetRT, m_BlurShadowmapMaterial, /*regular sample*/ 5); 110 | } 111 | 112 | currentRes /= 2; 113 | } 114 | 115 | //var directionalShadowmapBlurred = Shader.PropertyToID("_DirectionalShadowmapBlurred"); 116 | //m_BufGrabShadowmap.GetTemporaryRT(directionalShadowmapBlurred, 1024, 1024, 0, FilterMode.Bilinear, RenderTextureFormat.RFloat, RenderTextureReadWrite.Linear); 117 | //m_BufGrabShadowmap.Blit(shadowmap, m_Shadowmap); 118 | //m_BufGrabShadowmap.SetGlobalTexture(directionalShadowmapBlurred, directionalShadowmapBlurred); 119 | } 120 | 121 | void CleanupDirectionalShadowmap() 122 | { 123 | if (m_BufGrabShadowmap != null) 124 | m_BufGrabShadowmap.Clear(); 125 | 126 | if (m_BufGrabShadowParams != null) 127 | m_BufGrabShadowParams.Clear(); 128 | 129 | if(m_ShadowParamsCB != null) 130 | m_ShadowParamsCB.Release(); 131 | m_ShadowParamsCB = null; 132 | } 133 | 134 | public bool SetUpDirectionalShadowmapForSampling(bool shadows, ComputeShader cs, int kernel) 135 | { 136 | if (!shadows || m_ShadowParamsCB == null || m_Shadowmap == null) 137 | { 138 | cs.SetFloat("_DirLightShadows", 0); 139 | return false; 140 | } 141 | 142 | cs.SetFloat("_DirLightShadows", 1); 143 | cs.SetBuffer(kernel, "_ShadowParams", m_ShadowParamsCB); 144 | cs.SetTexture(kernel, "_DirectionalShadowmap", m_Shadowmap); 145 | 146 | return true; 147 | } 148 | 149 | void ReleaseTemporary(ref RenderTexture rt) 150 | { 151 | if (rt == null) 152 | return; 153 | 154 | RenderTexture.ReleaseTemporary(rt); 155 | rt = null; 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /Assets/TubeLight/TubeLight.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &154090 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_PrefabParentObject: {fileID: 0} 7 | m_PrefabInternal: {fileID: 100100000} 8 | serializedVersion: 4 9 | m_Component: 10 | - 4: {fileID: 466162} 11 | - 114: {fileID: 11466842} 12 | - 33: {fileID: 3327276} 13 | - 23: {fileID: 2315154} 14 | - 114: {fileID: 114000012794840980} 15 | m_Layer: 0 16 | m_Name: TubeLight 17 | m_TagString: Untagged 18 | m_Icon: {fileID: 0} 19 | m_NavMeshLayer: 0 20 | m_StaticEditorFlags: 0 21 | m_IsActive: 1 22 | --- !u!4 &466162 23 | Transform: 24 | m_ObjectHideFlags: 1 25 | m_PrefabParentObject: {fileID: 0} 26 | m_PrefabInternal: {fileID: 100100000} 27 | m_GameObject: {fileID: 154090} 28 | m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071067} 29 | m_LocalPosition: {x: 0, y: 0, z: 0} 30 | m_LocalScale: {x: 1, y: 1, z: 1} 31 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 32 | m_Children: [] 33 | m_Father: {fileID: 0} 34 | m_RootOrder: 0 35 | --- !u!23 &2315154 36 | MeshRenderer: 37 | m_ObjectHideFlags: 1 38 | m_PrefabParentObject: {fileID: 0} 39 | m_PrefabInternal: {fileID: 100100000} 40 | m_GameObject: {fileID: 154090} 41 | m_Enabled: 1 42 | m_CastShadows: 0 43 | m_ReceiveShadows: 0 44 | m_MotionVectors: 1 45 | m_LightProbeUsage: 0 46 | m_ReflectionProbeUsage: 0 47 | m_Materials: 48 | - {fileID: 2100000, guid: 86b3c638dc56298409890ac32f9e6baf, type: 2} 49 | m_SubsetIndices: 50 | m_StaticBatchRoot: {fileID: 0} 51 | m_ProbeAnchor: {fileID: 0} 52 | m_LightProbeVolumeOverride: {fileID: 0} 53 | m_ScaleInLightmap: 1 54 | m_PreserveUVs: 0 55 | m_IgnoreNormalsForChartDetection: 0 56 | m_ImportantGI: 0 57 | m_SelectedWireframeHidden: 0 58 | m_MinimumChartSize: 4 59 | m_AutoUVMaxDistance: 0.5 60 | m_AutoUVMaxAngle: 89 61 | m_LightmapParameters: {fileID: 0} 62 | m_SortingLayerID: 0 63 | m_SortingOrder: 0 64 | --- !u!33 &3327276 65 | MeshFilter: 66 | m_ObjectHideFlags: 1 67 | m_PrefabParentObject: {fileID: 0} 68 | m_PrefabInternal: {fileID: 100100000} 69 | m_GameObject: {fileID: 154090} 70 | m_Mesh: {fileID: 0} 71 | --- !u!114 &11466842 72 | MonoBehaviour: 73 | m_ObjectHideFlags: 1 74 | m_PrefabParentObject: {fileID: 0} 75 | m_PrefabInternal: {fileID: 100100000} 76 | m_GameObject: {fileID: 154090} 77 | m_Enabled: 1 78 | m_EditorHideFlags: 0 79 | m_Script: {fileID: 11500000, guid: 5a3b99ed98424ea4587ec18d930a1d77, type: 3} 80 | m_Name: 81 | m_EditorClassIdentifier: 82 | m_Intensity: 0.8 83 | m_Color: {r: 1, g: 1, b: 1, a: 1} 84 | m_Range: 10 85 | m_Radius: 0.3 86 | m_Length: 0 87 | m_Sphere: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} 88 | m_Capsule: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0} 89 | m_ProxyShader: {fileID: 4800000, guid: 2e6fd90941a3e3c458d01f851dca21ed, type: 3} 90 | m_RenderSource: 1 91 | m_ShadowPlanes: 92 | - {fileID: 0} 93 | - {fileID: 0} 94 | --- !u!1001 &100100000 95 | Prefab: 96 | m_ObjectHideFlags: 1 97 | serializedVersion: 2 98 | m_Modification: 99 | m_TransformParent: {fileID: 0} 100 | m_Modifications: 101 | - target: {fileID: 0} 102 | propertyPath: m_RenderSource 103 | value: 1 104 | objectReference: {fileID: 0} 105 | - target: {fileID: 0} 106 | propertyPath: m_Radius 107 | value: .340000004 108 | objectReference: {fileID: 0} 109 | - target: {fileID: 0} 110 | propertyPath: m_Length 111 | value: .649999976 112 | objectReference: {fileID: 0} 113 | - target: {fileID: 0} 114 | propertyPath: m_LocalRotation.x 115 | value: -.707106829 116 | objectReference: {fileID: 0} 117 | - target: {fileID: 0} 118 | propertyPath: m_LocalRotation.w 119 | value: .707106709 120 | objectReference: {fileID: 0} 121 | - target: {fileID: 0} 122 | propertyPath: m_LocalPosition.x 123 | value: 0 124 | objectReference: {fileID: 0} 125 | - target: {fileID: 0} 126 | propertyPath: m_LocalPosition.y 127 | value: 0 128 | objectReference: {fileID: 0} 129 | - target: {fileID: 0} 130 | propertyPath: m_LocalPosition.z 131 | value: 0 132 | objectReference: {fileID: 0} 133 | - target: {fileID: 0} 134 | propertyPath: m_CastShadows 135 | value: 0 136 | objectReference: {fileID: 0} 137 | - target: {fileID: 0} 138 | propertyPath: m_ReceiveShadows 139 | value: 0 140 | objectReference: {fileID: 0} 141 | - target: {fileID: 0} 142 | propertyPath: m_UseLightProbes 143 | value: 0 144 | objectReference: {fileID: 0} 145 | - target: {fileID: 0} 146 | propertyPath: m_ReflectionProbeUsage 147 | value: 0 148 | objectReference: {fileID: 0} 149 | - target: {fileID: 0} 150 | propertyPath: m_Materials.Array.data[0] 151 | value: 152 | objectReference: {fileID: 2100000, guid: 86b3c638dc56298409890ac32f9e6baf, type: 2} 153 | m_RemovedComponents: [] 154 | m_ParentPrefab: {fileID: 0} 155 | m_RootGameObject: {fileID: 154090} 156 | m_IsPrefabParent: 1 157 | --- !u!114 &114000012794840980 158 | MonoBehaviour: 159 | m_ObjectHideFlags: 1 160 | m_PrefabParentObject: {fileID: 0} 161 | m_PrefabInternal: {fileID: 100100000} 162 | m_GameObject: {fileID: 154090} 163 | m_Enabled: 1 164 | m_EditorHideFlags: 0 165 | m_Script: {fileID: 11500000, guid: 097385f2a510795498370c4d62e61572, type: 3} 166 | m_Name: 167 | m_EditorClassIdentifier: 168 | m_IntensityMult: 1 169 | m_RangeMult: 1 170 | m_BlurShadowmapShader: {fileID: 4800000, guid: 701192b62a7678549918bc87434699fe, 171 | type: 3} 172 | m_CopyShadowParamsShader: {fileID: 4800000, guid: 33fc45db43408764c8dd7647b877e561, 173 | type: 3} 174 | m_ForceOnForFog: 0 175 | m_Shadows: 0 176 | m_ShadowmapRes: 256 177 | m_BlurIterations: 0 178 | m_BlurSize: 1 179 | m_ESMExponent: 40 180 | m_Bounded: 1 181 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/BlurShadowmap.shader: -------------------------------------------------------------------------------- 1 | 2 | Shader "Hidden/BlurShadowmap" { 3 | Properties 4 | { 5 | _MainTex ("Base (RGB)", 2D) = "white" {} 6 | _Bloom ("Bloom (RGB)", 2D) = "black" {} 7 | } 8 | 9 | CGINCLUDE 10 | #include "UnityCG.cginc" 11 | 12 | half4 _TexelSize; 13 | 14 | struct v2f_tap 15 | { 16 | float4 pos : SV_POSITION; 17 | half2 uv20 : TEXCOORD0; 18 | half2 uv21 : TEXCOORD1; 19 | half2 uv22 : TEXCOORD2; 20 | half2 uv23 : TEXCOORD3; 21 | }; 22 | 23 | v2f_tap vert4Tap ( appdata_img v ) 24 | { 25 | v2f_tap o; 26 | o.pos = v.vertex; 27 | 28 | o.uv20 = v.texcoord + _TexelSize.xy; 29 | o.uv21 = v.texcoord + _TexelSize.xy * half2(-0.5, -0.5); 30 | o.uv22 = v.texcoord + _TexelSize.xy * half2( 0.5, -0.5); 31 | o.uv23 = v.texcoord + _TexelSize.xy * half2(-0.5, 0.5); 32 | 33 | return o; 34 | } 35 | 36 | // TODO: consolidate with the above, but make sure both area and dir shadows work 37 | v2f_tap vert4TapDir ( appdata_img v ) 38 | { 39 | v2f_tap o; 40 | o.pos = UnityObjectToClipPos(v.vertex); 41 | 42 | o.uv20 = v.texcoord + _TexelSize.xy; 43 | o.uv21 = v.texcoord + _TexelSize.xy * half2(-0.5, -0.5); 44 | o.uv22 = v.texcoord + _TexelSize.xy * half2( 0.5, -0.5); 45 | o.uv23 = v.texcoord + _TexelSize.xy * half2(-0.5, 0.5); 46 | 47 | return o; 48 | } 49 | 50 | float4 _ZParams; 51 | float _ESMExponent; 52 | Texture2D _Shadowmap; 53 | SamplerComparisonState sampler_Shadowmap; 54 | 55 | // To get a sampler, which doesn't do comparison 56 | Texture2D _ShadowmapDummy; 57 | SamplerState sampler_ShadowmapDummy; 58 | 59 | #define VSM 1 60 | 61 | float4 fragDownsampleFromShadowmapFormat ( v2f_tap i ) : SV_Target 62 | { 63 | float4 z; 64 | z.r = _Shadowmap.Sample(sampler_ShadowmapDummy, i.uv20).r; 65 | z.g = _Shadowmap.Sample(sampler_ShadowmapDummy, i.uv21).r; 66 | z.b = _Shadowmap.Sample(sampler_ShadowmapDummy, i.uv22).r; 67 | z.a = _Shadowmap.Sample(sampler_ShadowmapDummy, i.uv23).r; 68 | 69 | // The texture contains just 0. But we need to sample it somewhere for Unity to initialize the corresponding sampler. 70 | z.r += _ShadowmapDummy.Sample(sampler_ShadowmapDummy, 0).a; 71 | 72 | #if UNITY_REVERSED_Z 73 | z = 1.0 - z; 74 | #endif 75 | 76 | // Transform to linear z, 0 at near, 1 at far 77 | z = z * 2 - 1; 78 | z = _ZParams.x * (z + 1.0) / (z + _ZParams.y); 79 | 80 | #if VSM 81 | // TODO: this is wrong. We can't average/blur z values before converting to VSM. 82 | // This doesn't affect m, but affects m * m, so I should swap those two lines. 83 | float m = dot(z, 0.25); 84 | return float4(m, m * m, 0, 0); 85 | #else 86 | z = exp(_ESMExponent * z); 87 | return dot(z, 0.25); 88 | #endif 89 | } 90 | 91 | sampler2D _DirShadowmap; 92 | 93 | float4 fragDownsampleFromShadowmapFormatDir ( v2f_tap i ) : SV_Target 94 | { 95 | float4 z; 96 | z.r = tex2D (_DirShadowmap, i.uv20).r; 97 | z.g = tex2D (_DirShadowmap, i.uv21).r; 98 | z.b = tex2D (_DirShadowmap, i.uv22).r; 99 | z.a = tex2D (_DirShadowmap, i.uv23).r; 100 | 101 | return z.r; 102 | 103 | // Transform to linear z, 0 at near, 1 at far 104 | // z = z * 2 - 1; 105 | // z = _ZParams.x * (z + 1.0) / (z + _ZParams.y); 106 | 107 | #if 1 108 | // float m = dot(z, 0.25); 109 | // return float4(m, m * m, 0, 0); 110 | float4 z2 = z * z; 111 | return float4(dot(z, 0.25), dot(z2, 0.25), 0, 0); 112 | #else 113 | //z = exp(_ESMExponent * z); 114 | z = exp(40.0 * z); 115 | return dot(z, 0.25); 116 | #endif 117 | } 118 | 119 | sampler2D _MainTex; 120 | 121 | float4 fragDownsample ( v2f_tap i ) : SV_Target 122 | { 123 | float4 color = tex2D (_MainTex, i.uv20); 124 | color += tex2D (_MainTex, i.uv21); 125 | color += tex2D (_MainTex, i.uv22); 126 | color += tex2D (_MainTex, i.uv23); 127 | return color * 0.25; 128 | } 129 | 130 | struct v2f 131 | { 132 | float4 pos : SV_POSITION; 133 | half4 uv : TEXCOORD0; 134 | half2 offs : TEXCOORD1; 135 | }; 136 | 137 | float _BlurSize; 138 | 139 | v2f vertBlurHorizontal (appdata_img v) 140 | { 141 | v2f o; 142 | o.pos = v.vertex; 143 | 144 | o.uv = half4(v.texcoord.xy,1,1); 145 | o.offs = _TexelSize.xy * half2(1.0, 0.0) * _BlurSize; 146 | 147 | return o; 148 | } 149 | 150 | v2f vertBlurVertical (appdata_img v) 151 | { 152 | v2f o; 153 | o.pos = v.vertex; 154 | 155 | o.uv = half4(v.texcoord.xy, 1, 1); 156 | o.offs = _TexelSize.xy * half2(0.0, 1.0) * _BlurSize; 157 | 158 | return o; 159 | } 160 | 161 | float4 fragBlur8 (v2f i) : SV_Target 162 | { 163 | half2 coords = i.uv.xy - i.offs * 5.0; 164 | 165 | float4 color = 0; 166 | for(int k = 0; k < 11; k++) 167 | { 168 | color += tex2D(_MainTex, coords); 169 | coords += i.offs; 170 | } 171 | return color/11.0; 172 | } 173 | 174 | ENDCG 175 | 176 | SubShader { 177 | ZTest Off Cull Off ZWrite Off Blend Off 178 | 179 | // 0 180 | Pass 181 | { 182 | CGPROGRAM 183 | #pragma vertex vert4Tap 184 | #pragma fragment fragDownsampleFromShadowmapFormat 185 | ENDCG 186 | } 187 | 188 | // 1 189 | Pass 190 | { 191 | CGPROGRAM 192 | #pragma vertex vert4Tap 193 | #pragma fragment fragDownsample 194 | ENDCG 195 | } 196 | 197 | // 2 198 | Pass { 199 | ZTest Always 200 | Cull Off 201 | 202 | CGPROGRAM 203 | 204 | #pragma vertex vertBlurVertical 205 | #pragma fragment fragBlur8 206 | 207 | ENDCG 208 | } 209 | 210 | // 3 211 | Pass { 212 | ZTest Always 213 | Cull Off 214 | 215 | CGPROGRAM 216 | 217 | #pragma vertex vertBlurHorizontal 218 | #pragma fragment fragBlur8 219 | 220 | ENDCG 221 | } 222 | 223 | // 4 224 | Pass 225 | { 226 | CGPROGRAM 227 | #pragma vertex vert4TapDir 228 | #pragma fragment fragDownsampleFromShadowmapFormatDir 229 | ENDCG 230 | } 231 | 232 | // 5 233 | Pass 234 | { 235 | CGPROGRAM 236 | #pragma vertex vert4TapDir 237 | #pragma fragment fragDownsample 238 | ENDCG 239 | } 240 | 241 | } 242 | 243 | FallBack Off 244 | } 245 | -------------------------------------------------------------------------------- /Assets/AreaLight/AreaLight.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1001 &100100000 4 | Prefab: 5 | m_ObjectHideFlags: 1 6 | serializedVersion: 2 7 | m_Modification: 8 | m_TransformParent: {fileID: 0} 9 | m_Modifications: 10 | - target: {fileID: 0} 11 | propertyPath: m_ProxyShader 12 | value: 13 | objectReference: {fileID: 4800000, guid: 2b28be3523d190a41910088d1ee68ef7, type: 3} 14 | - target: {fileID: 0} 15 | propertyPath: m_Cube 16 | value: 17 | objectReference: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 18 | - target: {fileID: 0} 19 | propertyPath: m_LocalPosition.x 20 | value: 0 21 | objectReference: {fileID: 0} 22 | - target: {fileID: 0} 23 | propertyPath: m_LocalPosition.y 24 | value: 0 25 | objectReference: {fileID: 0} 26 | - target: {fileID: 0} 27 | propertyPath: m_LocalPosition.z 28 | value: 0 29 | objectReference: {fileID: 0} 30 | - target: {fileID: 0} 31 | propertyPath: m_LocalRotation.y 32 | value: 0 33 | objectReference: {fileID: 0} 34 | - target: {fileID: 0} 35 | propertyPath: m_LocalRotation.w 36 | value: 1 37 | objectReference: {fileID: 0} 38 | - target: {fileID: 0} 39 | propertyPath: m_Intensity 40 | value: 0.8 41 | objectReference: {fileID: 0} 42 | - target: {fileID: 0} 43 | propertyPath: m_BlurShadowmapShader 44 | value: 45 | objectReference: {fileID: 4800000, guid: 701192b62a7678549918bc87434699fe, type: 3} 46 | - target: {fileID: 0} 47 | propertyPath: m_ShadowmapRes 48 | value: 2048 49 | objectReference: {fileID: 0} 50 | - target: {fileID: 0} 51 | propertyPath: m_Shadows 52 | value: 0 53 | objectReference: {fileID: 0} 54 | m_RemovedComponents: [] 55 | m_ParentPrefab: {fileID: 0} 56 | m_RootGameObject: {fileID: 1000010046428508} 57 | m_IsPrefabParent: 1 58 | --- !u!1 &1000010046428508 59 | GameObject: 60 | m_ObjectHideFlags: 0 61 | m_PrefabParentObject: {fileID: 0} 62 | m_PrefabInternal: {fileID: 100100000} 63 | serializedVersion: 4 64 | m_Component: 65 | - 4: {fileID: 4000014113918066} 66 | - 114: {fileID: 114000011647635530} 67 | - 33: {fileID: 33000012356353452} 68 | - 23: {fileID: 23000012433474804} 69 | - 114: {fileID: 114000013519192348} 70 | m_Layer: 0 71 | m_Name: AreaLight 72 | m_TagString: Untagged 73 | m_Icon: {fileID: 0} 74 | m_NavMeshLayer: 0 75 | m_StaticEditorFlags: 0 76 | m_IsActive: 1 77 | --- !u!4 &4000014113918066 78 | Transform: 79 | m_ObjectHideFlags: 1 80 | m_PrefabParentObject: {fileID: 0} 81 | m_PrefabInternal: {fileID: 100100000} 82 | m_GameObject: {fileID: 1000010046428508} 83 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 84 | m_LocalPosition: {x: 0, y: 0, z: 0} 85 | m_LocalScale: {x: 1, y: 1, z: 1} 86 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 87 | m_Children: [] 88 | m_Father: {fileID: 0} 89 | m_RootOrder: 0 90 | --- !u!23 &23000012433474804 91 | MeshRenderer: 92 | m_ObjectHideFlags: 1 93 | m_PrefabParentObject: {fileID: 0} 94 | m_PrefabInternal: {fileID: 100100000} 95 | m_GameObject: {fileID: 1000010046428508} 96 | m_Enabled: 1 97 | m_CastShadows: 1 98 | m_ReceiveShadows: 1 99 | m_MotionVectors: 1 100 | m_LightProbeUsage: 0 101 | m_ReflectionProbeUsage: 1 102 | m_Materials: 103 | - {fileID: 2100000, guid: 1eb056d70e23cc34a9e926d8c8c887a5, type: 2} 104 | m_SubsetIndices: 105 | m_StaticBatchRoot: {fileID: 0} 106 | m_ProbeAnchor: {fileID: 0} 107 | m_LightProbeVolumeOverride: {fileID: 0} 108 | m_ScaleInLightmap: 1 109 | m_PreserveUVs: 1 110 | m_IgnoreNormalsForChartDetection: 0 111 | m_ImportantGI: 0 112 | m_SelectedWireframeHidden: 0 113 | m_MinimumChartSize: 4 114 | m_AutoUVMaxDistance: 0.5 115 | m_AutoUVMaxAngle: 89 116 | m_LightmapParameters: {fileID: 0} 117 | m_SortingLayerID: 0 118 | m_SortingOrder: 0 119 | --- !u!33 &33000012356353452 120 | MeshFilter: 121 | m_ObjectHideFlags: 1 122 | m_PrefabParentObject: {fileID: 0} 123 | m_PrefabInternal: {fileID: 100100000} 124 | m_GameObject: {fileID: 1000010046428508} 125 | m_Mesh: {fileID: 0} 126 | --- !u!114 &114000011647635530 127 | MonoBehaviour: 128 | m_ObjectHideFlags: 1 129 | m_PrefabParentObject: {fileID: 0} 130 | m_PrefabInternal: {fileID: 100100000} 131 | m_GameObject: {fileID: 1000010046428508} 132 | m_Enabled: 1 133 | m_EditorHideFlags: 0 134 | m_Script: {fileID: 11500000, guid: 792909cacf2415c48a1d7eebef426b5d, type: 3} 135 | m_Name: 136 | m_EditorClassIdentifier: 137 | m_Cube: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 138 | m_ProxyShader: {fileID: 4800000, guid: 2b28be3523d190a41910088d1ee68ef7, type: 3} 139 | m_ShadowmapShader: {fileID: 4800000, guid: 2c4cd42b134f7864fa579350e9cf6896, type: 3} 140 | m_BlurShadowmapShader: {fileID: 4800000, guid: 701192b62a7678549918bc87434699fe, 141 | type: 3} 142 | m_RenderSource: 1 143 | m_Size: {x: 2, y: 2, z: 6} 144 | m_Angle: 100 145 | m_Intensity: 0.8 146 | m_Color: {r: 1, g: 1, b: 1, a: 1} 147 | m_Shadows: 0 148 | m_ShadowCullingMask: 149 | serializedVersion: 2 150 | m_Bits: 4294967295 151 | m_ShadowmapRes: 2048 152 | m_ReceiverSearchDistance: 24 153 | m_ReceiverDistanceScale: 5 154 | m_LightNearSize: 4 155 | m_LightFarSize: 22 156 | m_ShadowBias: 0.02 157 | m_Quad: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} 158 | --- !u!114 &114000013519192348 159 | MonoBehaviour: 160 | m_ObjectHideFlags: 1 161 | m_PrefabParentObject: {fileID: 0} 162 | m_PrefabInternal: {fileID: 100100000} 163 | m_GameObject: {fileID: 1000010046428508} 164 | m_Enabled: 1 165 | m_EditorHideFlags: 0 166 | m_Script: {fileID: 11500000, guid: 097385f2a510795498370c4d62e61572, type: 3} 167 | m_Name: 168 | m_EditorClassIdentifier: 169 | m_IntensityMult: 1 170 | m_RangeMult: 1 171 | m_BlurShadowmapShader: {fileID: 0} 172 | m_CopyShadowParamsShader: {fileID: 0} 173 | m_ForceOnForFog: 0 174 | m_Shadows: 0 175 | m_ShadowmapRes: 512 176 | m_BlurIterations: 0 177 | m_BlurSize: 1 178 | m_ESMExponent: 40 179 | m_Bounded: 1 180 | -------------------------------------------------------------------------------- /Assets/AreaLight/Shaders/AreaLight.cginc: -------------------------------------------------------------------------------- 1 | // Based on 'Real-Time Polygonal-Light Shading with Linearly Transformed Cosines' 2 | // https://labs.unity.com/article/real-time-polygonal-light-shading-linearly-transformed-cosines 3 | 4 | #if AREA_LIGHT_ENABLE_DIFFUSE 5 | sampler2D _TransformInv_Diffuse; 6 | #endif 7 | sampler2D _TransformInv_Specular; 8 | sampler2D _AmpDiffAmpSpecFresnel; 9 | float4x4 _LightVerts; 10 | 11 | half IntegrateEdge(half3 v1, half3 v2) 12 | { 13 | half d = dot(v1,v2); 14 | half theta = acos(max(-0.9999, dot(v1,v2))); 15 | half theta_sintheta = theta / sin(theta); 16 | return theta_sintheta * (v1.x*v2.y - v1.y*v2.x); 17 | } 18 | 19 | // Baum's equation 20 | // Expects non-normalized vertex positions 21 | half PolygonRadiance(half4x3 L) 22 | { 23 | // detect clipping config 24 | uint config = 0; 25 | if (L[0].z > 0) config += 1; 26 | if (L[1].z > 0) config += 2; 27 | if (L[2].z > 0) config += 4; 28 | if (L[3].z > 0) config += 8; 29 | 30 | 31 | // The fifth vertex for cases when clipping cuts off one corner. 32 | // Due to a compiler bug, copying L into a vector array with 5 rows 33 | // messes something up, so we need to stick with the matrix + the L4 vertex. 34 | half3 L4 = L[3]; 35 | 36 | // This switch is surprisingly fast. Tried replacing it with a lookup array of vertices. 37 | // Even though that replaced the switch with just some indexing and no branches, it became 38 | // way, way slower - mem fetch stalls? 39 | 40 | // clip 41 | uint n = 0; 42 | switch(config) 43 | { 44 | case 0: // clip all 45 | break; 46 | 47 | case 1: // V1 clip V2 V3 V4 48 | n = 3; 49 | L[1] = -L[1].z * L[0] + L[0].z * L[1]; 50 | L[2] = -L[3].z * L[0] + L[0].z * L[3]; 51 | break; 52 | 53 | case 2: // V2 clip V1 V3 V4 54 | n = 3; 55 | L[0] = -L[0].z * L[1] + L[1].z * L[0]; 56 | L[2] = -L[2].z * L[1] + L[1].z * L[2]; 57 | break; 58 | 59 | case 3: // V1 V2 clip V3 V4 60 | n = 4; 61 | L[2] = -L[2].z * L[1] + L[1].z * L[2]; 62 | L[3] = -L[3].z * L[0] + L[0].z * L[3]; 63 | break; 64 | 65 | case 4: // V3 clip V1 V2 V4 66 | n = 3; 67 | L[0] = -L[3].z * L[2] + L[2].z * L[3]; 68 | L[1] = -L[1].z * L[2] + L[2].z * L[1]; 69 | break; 70 | 71 | case 5: // V1 V3 clip V2 V4: impossible 72 | break; 73 | 74 | case 6: // V2 V3 clip V1 V4 75 | n = 4; 76 | L[0] = -L[0].z * L[1] + L[1].z * L[0]; 77 | L[3] = -L[3].z * L[2] + L[2].z * L[3]; 78 | break; 79 | 80 | case 7: // V1 V2 V3 clip V4 81 | n = 5; 82 | L4 = -L[3].z * L[0] + L[0].z * L[3]; 83 | L[3] = -L[3].z * L[2] + L[2].z * L[3]; 84 | break; 85 | 86 | case 8: // V4 clip V1 V2 V3 87 | n = 3; 88 | L[0] = -L[0].z * L[3] + L[3].z * L[0]; 89 | L[1] = -L[2].z * L[3] + L[3].z * L[2]; 90 | L[2] = L[3]; 91 | break; 92 | 93 | case 9: // V1 V4 clip V2 V3 94 | n = 4; 95 | L[1] = -L[1].z * L[0] + L[0].z * L[1]; 96 | L[2] = -L[2].z * L[3] + L[3].z * L[2]; 97 | break; 98 | 99 | case 10: // V2 V4 clip V1 V3: impossible 100 | break; 101 | 102 | case 11: // V1 V2 V4 clip V3 103 | n = 5; 104 | L[3] = -L[2].z * L[3] + L[3].z * L[2]; 105 | L[2] = -L[2].z * L[1] + L[1].z * L[2]; 106 | break; 107 | 108 | case 12: // V3 V4 clip V1 V2 109 | n = 4; 110 | L[1] = -L[1].z * L[2] + L[2].z * L[1]; 111 | L[0] = -L[0].z * L[3] + L[3].z * L[0]; 112 | break; 113 | 114 | case 13: // V1 V3 V4 clip V2 115 | n = 5; 116 | L[3] = L[2]; 117 | L[2] = -L[1].z * L[2] + L[2].z * L[1]; 118 | L[1] = -L[1].z * L[0] + L[0].z * L[1]; 119 | break; 120 | 121 | case 14: // V2 V3 V4 clip V1 122 | n = 5; 123 | L4 = -L[0].z * L[3] + L[3].z * L[0]; 124 | L[0] = -L[0].z * L[1] + L[1].z * L[0]; 125 | break; 126 | 127 | case 15: // V1 V2 V3 V4 128 | n = 4; 129 | break; 130 | } 131 | 132 | if (n == 0) 133 | return 0; 134 | 135 | // normalize 136 | L[0] = normalize(L[0]); 137 | L[1] = normalize(L[1]); 138 | L[2] = normalize(L[2]); 139 | if(n == 3) 140 | L[3] = L[0]; 141 | else 142 | { 143 | L[3] = normalize(L[3]); 144 | if (n == 4) 145 | L4 = L[0]; 146 | else 147 | L4 = normalize(L4); 148 | } 149 | 150 | // integrate 151 | half sum = 0; 152 | sum += IntegrateEdge(L[0], L[1]); 153 | sum += IntegrateEdge(L[1], L[2]); 154 | sum += IntegrateEdge(L[2], L[3]); 155 | if(n >= 4) 156 | sum += IntegrateEdge(L[3], L4); 157 | if(n == 5) 158 | sum += IntegrateEdge(L4, L[0]); 159 | 160 | sum *= 0.15915; // 1/2pi 161 | 162 | return max(0, sum); 163 | } 164 | 165 | half TransformedPolygonRadiance(half4x3 L, half2 uv, sampler2D transformInv, half amplitude) 166 | { 167 | // Get the inverse LTC matrix M 168 | half3x3 Minv = 0; 169 | Minv._m22 = 1; 170 | Minv._m00_m02_m11_m20 = tex2D(transformInv, uv); 171 | 172 | // Transform light vertices into diffuse configuration 173 | half4x3 LTransformed = mul(L, Minv); 174 | 175 | // Polygon radiance in transformed configuration - specular 176 | return PolygonRadiance(LTransformed) * amplitude; 177 | } 178 | 179 | half3 CalculateLight (half3 position, half3 diffColor, half3 specColor, half oneMinusRoughness, half3 N, 180 | half3 lightPos, half3 lightColor) 181 | { 182 | #if AREA_LIGHT_SHADOWS 183 | half shadow = Shadow(position); 184 | if (shadow == 0.0) 185 | return 0; 186 | #endif 187 | // TODO: larger and smaller values cause artifacts - why? 188 | oneMinusRoughness = clamp(oneMinusRoughness, 0.01, 0.93); 189 | half roughness = 1 - oneMinusRoughness; 190 | half3 V = normalize(_WorldSpaceCameraPos - position); 191 | 192 | // Construct orthonormal basis around N, aligned with V 193 | half3x3 basis; 194 | basis[0] = normalize(V - N * dot(V, N)); 195 | basis[1] = normalize(cross(N, basis[0])); 196 | basis[2] = N; 197 | 198 | // Transform light vertices into that space 199 | half4x3 L; 200 | L = _LightVerts - half4x3(position, position, position, position); 201 | L = mul(L, transpose(basis)); 202 | 203 | // UVs for sampling the LUTs 204 | half theta = acos(dot(V, N)); 205 | half2 uv = half2(roughness, theta/1.57); 206 | 207 | half3 AmpDiffAmpSpecFresnel = tex2D(_AmpDiffAmpSpecFresnel, uv).rgb; 208 | 209 | half3 result = 0; 210 | #if AREA_LIGHT_ENABLE_DIFFUSE 211 | half diffuseTerm = TransformedPolygonRadiance(L, uv, _TransformInv_Diffuse, AmpDiffAmpSpecFresnel.x); 212 | result = diffuseTerm * diffColor; 213 | #endif 214 | 215 | half specularTerm = TransformedPolygonRadiance(L, uv, _TransformInv_Specular, AmpDiffAmpSpecFresnel.y); 216 | half fresnelTerm = specColor + (1.0 - specColor) * AmpDiffAmpSpecFresnel.z; 217 | result += specularTerm * fresnelTerm * UNITY_PI; 218 | 219 | #if AREA_LIGHT_SHADOWS 220 | result *= shadow; 221 | #endif 222 | 223 | return result * lightColor; 224 | } -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!13 &1 4 | InputManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Axes: 8 | - serializedVersion: 3 9 | m_Name: Horizontal 10 | descriptiveName: 11 | descriptiveNegativeName: 12 | negativeButton: left 13 | positiveButton: right 14 | altNegativeButton: a 15 | altPositiveButton: d 16 | gravity: 3 17 | dead: 0.001 18 | sensitivity: 3 19 | snap: 1 20 | invert: 0 21 | type: 0 22 | axis: 0 23 | joyNum: 0 24 | - serializedVersion: 3 25 | m_Name: Vertical 26 | descriptiveName: 27 | descriptiveNegativeName: 28 | negativeButton: down 29 | positiveButton: up 30 | altNegativeButton: s 31 | altPositiveButton: w 32 | gravity: 3 33 | dead: 0.001 34 | sensitivity: 3 35 | snap: 1 36 | invert: 0 37 | type: 0 38 | axis: 0 39 | joyNum: 0 40 | - serializedVersion: 3 41 | m_Name: Fire1 42 | descriptiveName: 43 | descriptiveNegativeName: 44 | negativeButton: 45 | positiveButton: left ctrl 46 | altNegativeButton: 47 | altPositiveButton: mouse 0 48 | gravity: 1000 49 | dead: 0.001 50 | sensitivity: 1000 51 | snap: 0 52 | invert: 0 53 | type: 0 54 | axis: 0 55 | joyNum: 0 56 | - serializedVersion: 3 57 | m_Name: Fire2 58 | descriptiveName: 59 | descriptiveNegativeName: 60 | negativeButton: 61 | positiveButton: left alt 62 | altNegativeButton: 63 | altPositiveButton: mouse 1 64 | gravity: 1000 65 | dead: 0.001 66 | sensitivity: 1000 67 | snap: 0 68 | invert: 0 69 | type: 0 70 | axis: 0 71 | joyNum: 0 72 | - serializedVersion: 3 73 | m_Name: Fire3 74 | descriptiveName: 75 | descriptiveNegativeName: 76 | negativeButton: 77 | positiveButton: left shift 78 | altNegativeButton: 79 | altPositiveButton: mouse 2 80 | gravity: 1000 81 | dead: 0.001 82 | sensitivity: 1000 83 | snap: 0 84 | invert: 0 85 | type: 0 86 | axis: 0 87 | joyNum: 0 88 | - serializedVersion: 3 89 | m_Name: Jump 90 | descriptiveName: 91 | descriptiveNegativeName: 92 | negativeButton: 93 | positiveButton: space 94 | altNegativeButton: 95 | altPositiveButton: 96 | gravity: 1000 97 | dead: 0.001 98 | sensitivity: 1000 99 | snap: 0 100 | invert: 0 101 | type: 0 102 | axis: 0 103 | joyNum: 0 104 | - serializedVersion: 3 105 | m_Name: Mouse X 106 | descriptiveName: 107 | descriptiveNegativeName: 108 | negativeButton: 109 | positiveButton: 110 | altNegativeButton: 111 | altPositiveButton: 112 | gravity: 0 113 | dead: 0 114 | sensitivity: 0.1 115 | snap: 0 116 | invert: 0 117 | type: 1 118 | axis: 0 119 | joyNum: 0 120 | - serializedVersion: 3 121 | m_Name: Mouse Y 122 | descriptiveName: 123 | descriptiveNegativeName: 124 | negativeButton: 125 | positiveButton: 126 | altNegativeButton: 127 | altPositiveButton: 128 | gravity: 0 129 | dead: 0 130 | sensitivity: 0.1 131 | snap: 0 132 | invert: 0 133 | type: 1 134 | axis: 1 135 | joyNum: 0 136 | - serializedVersion: 3 137 | m_Name: Mouse ScrollWheel 138 | descriptiveName: 139 | descriptiveNegativeName: 140 | negativeButton: 141 | positiveButton: 142 | altNegativeButton: 143 | altPositiveButton: 144 | gravity: 0 145 | dead: 0 146 | sensitivity: 0.1 147 | snap: 0 148 | invert: 0 149 | type: 1 150 | axis: 2 151 | joyNum: 0 152 | - serializedVersion: 3 153 | m_Name: Horizontal 154 | descriptiveName: 155 | descriptiveNegativeName: 156 | negativeButton: 157 | positiveButton: 158 | altNegativeButton: 159 | altPositiveButton: 160 | gravity: 0 161 | dead: 0.19 162 | sensitivity: 1 163 | snap: 0 164 | invert: 0 165 | type: 2 166 | axis: 0 167 | joyNum: 0 168 | - serializedVersion: 3 169 | m_Name: Vertical 170 | descriptiveName: 171 | descriptiveNegativeName: 172 | negativeButton: 173 | positiveButton: 174 | altNegativeButton: 175 | altPositiveButton: 176 | gravity: 0 177 | dead: 0.19 178 | sensitivity: 1 179 | snap: 0 180 | invert: 1 181 | type: 2 182 | axis: 1 183 | joyNum: 0 184 | - serializedVersion: 3 185 | m_Name: Fire1 186 | descriptiveName: 187 | descriptiveNegativeName: 188 | negativeButton: 189 | positiveButton: joystick button 0 190 | altNegativeButton: 191 | altPositiveButton: 192 | gravity: 1000 193 | dead: 0.001 194 | sensitivity: 1000 195 | snap: 0 196 | invert: 0 197 | type: 0 198 | axis: 0 199 | joyNum: 0 200 | - serializedVersion: 3 201 | m_Name: Fire2 202 | descriptiveName: 203 | descriptiveNegativeName: 204 | negativeButton: 205 | positiveButton: joystick button 1 206 | altNegativeButton: 207 | altPositiveButton: 208 | gravity: 1000 209 | dead: 0.001 210 | sensitivity: 1000 211 | snap: 0 212 | invert: 0 213 | type: 0 214 | axis: 0 215 | joyNum: 0 216 | - serializedVersion: 3 217 | m_Name: Fire3 218 | descriptiveName: 219 | descriptiveNegativeName: 220 | negativeButton: 221 | positiveButton: joystick button 2 222 | altNegativeButton: 223 | altPositiveButton: 224 | gravity: 1000 225 | dead: 0.001 226 | sensitivity: 1000 227 | snap: 0 228 | invert: 0 229 | type: 0 230 | axis: 0 231 | joyNum: 0 232 | - serializedVersion: 3 233 | m_Name: Jump 234 | descriptiveName: 235 | descriptiveNegativeName: 236 | negativeButton: 237 | positiveButton: joystick button 3 238 | altNegativeButton: 239 | altPositiveButton: 240 | gravity: 1000 241 | dead: 0.001 242 | sensitivity: 1000 243 | snap: 0 244 | invert: 0 245 | type: 0 246 | axis: 0 247 | joyNum: 0 248 | - serializedVersion: 3 249 | m_Name: Submit 250 | descriptiveName: 251 | descriptiveNegativeName: 252 | negativeButton: 253 | positiveButton: return 254 | altNegativeButton: 255 | altPositiveButton: joystick button 0 256 | gravity: 1000 257 | dead: 0.001 258 | sensitivity: 1000 259 | snap: 0 260 | invert: 0 261 | type: 0 262 | axis: 0 263 | joyNum: 0 264 | - serializedVersion: 3 265 | m_Name: Submit 266 | descriptiveName: 267 | descriptiveNegativeName: 268 | negativeButton: 269 | positiveButton: enter 270 | altNegativeButton: 271 | altPositiveButton: space 272 | gravity: 1000 273 | dead: 0.001 274 | sensitivity: 1000 275 | snap: 0 276 | invert: 0 277 | type: 0 278 | axis: 0 279 | joyNum: 0 280 | - serializedVersion: 3 281 | m_Name: Cancel 282 | descriptiveName: 283 | descriptiveNegativeName: 284 | negativeButton: 285 | positiveButton: escape 286 | altNegativeButton: 287 | altPositiveButton: joystick button 1 288 | gravity: 1000 289 | dead: 0.001 290 | sensitivity: 1000 291 | snap: 0 292 | invert: 0 293 | type: 0 294 | axis: 0 295 | joyNum: 0 296 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Volumetric fog, area lights and tube lights 2 | =========================================== 3 | 4 | This repository contains some of the lighting effects implemented for the [Unity Adam demo](https://unity3d.com/pages/adam): volumetric fog, area lights and tube lights. 5 | 6 | ##### Adam 7 | ![fog in the Adam demo](http://i.imgur.com/XYExw51.gif) 8 | 9 | ##### Test scenes 10 | ![area light](http://i.imgur.com/HxwAefB.png) 11 | Area light with shadows. 12 | 13 | ![tube light](http://i.imgur.com/MxS8Jus.png) 14 | Two tube lights with some locally controlled fog density. 15 | 16 | ![tube light](http://i.imgur.com/ZSXoCYX.png) 17 | Tube light with a shadow plane and global fog noise + wind. 18 | 19 | ![transparency](http://i.imgur.com/Yr8Zj2S.png) 20 | Transparent spheres and a point light. 21 | 22 | System requirements 23 | ------------------- 24 | - Compute shaders. Tested on dx11, dx12 and osx with metal. Might work on other platforms with compute shaders too. 25 | - Tested in Unity 5.6 to Unity 2018.3.0b5. Please let me know in case of trouble in a newer version. 26 | 27 | Usage notes 28 | ----------- 29 | ##### Volumetric fog 30 | - The final outcome of light scattering in the fog depends on three factors: fog density, fog anisotropy and light sources. 31 | - To affect the fog, an area light, tube light or point light needs to have the FogLight component and the scene needs an instance of LightManagerFogLights. 32 | - Global fog density controls on the VolumetricFog component allow defining constant fog density, exponential height-based and animated noise. 33 | - Density can also be controlled locally with the FogEllipsoid shapes. 34 | - Anisotropy is a global property on the VolumetricFog component. It allows the light to scatter forward more than in other directions, which is characteristic for Mie scattering occuring with larger particles like water droplets of fog. 35 | 36 | ##### Area lights 37 | - Area lights give great direct light results, but their shadows and scattering in the fog are very rough approximations in this project. 38 | - Direct light soft shadows are implemented using PCSS - the technique was good enough for our specific cameras, but in general isn't great and the settings are difficult to tweak. Real time shadows from area lights is still an open research topic. 39 | - Regular area light should contribute to the scene in its entire front hemisphere. This is difficult to handle for a shadowmap (paraboloidal projection and multiple shadowmaps are not very practical), so with shadows enabled, area light's influence gets limited to a frustum with a controllable angle. 40 | - The scattering contribution in the fog is limited to the same frustum and not physically correct either. 41 | - Volumetric shadows in the fog use Variance Shadow Maps. VSM allows for pre-blurring the shadowmap for very soft shadows with wide penumbra for the cost of just one shadow sample at the stage of injecting the light into the froxel volume. 42 | - Softness of the volumetric shadows, apart from looking more natural, has an important role: it avoids aliasing by changing sharp shadow edges into smoother gradients, this way pushing the gradient above the Nyquist freqency of the froxel resolution. In other words: if shadows are aliasing, try blurring them more in the *FogLight* settings. 43 | - The original paper uses Exponential Shadow Maps. ESMs cause light leaking right behind the shadow caster; on top of that, their penumbra is very wide right behind the shadow caster, but gets narrow further away. Those two properties made them very hard to tweak for our shots not to be washed out, avoid aliasing, etc. VSMs don't leak light this way and have a more constant penumbra, so were a better fit for us. (VSMs experience a different kind of light leaking in a specific configuration of shadow casters and receivers, but we didn't have that problem in our scene). 44 | 45 | ##### Tube lights 46 | - Tube lights use a very cheap and practical solution to approximate area lights, but the resulting quality is much lower. 47 | - Still a very useful fill light, source of extra specular highlights or simply when there's a need for an elongated, omnidirectional light. 48 | - Tube lights don't have proper shadows, but each one can have two *ShadowPlanes*. Shadow planes cut off the light's influence and have a controllable feather. 49 | 50 | Known issues and missing functionality 51 | -------------------------------------- 52 | - Directional light support disabled for now, but should be added soon. 53 | - The froxel resolution is currently hardcoded and larger view distances will cause undersampling issues along the view axis. Should be fixed soon. In the meantime use the *Far Clip Max* setting to limit how far the volumetrics are calculated. 54 | - The lights only work in deferred rendering and won't affect any objects rendered in forward. 55 | - No scaling via the transform component - currently the size and shape of the lights can only be changed via the properties of the light component. Changing the scale in the transform component doesn't work. 56 | - Currently the lights always render as back faces of the proxy mesh, without using the stencil buffer. A proper deferred light needs to be rendered as front faces, back faces or a quad (depending on the intersections with the near and far plane) and cull pixels using stencil. Not implemented for Adam, since wouldn't have changed anything with our specific cameras and light setup, but necessary for the lights to be universal. 57 | - The material emission of the light source mesh (the quad and the capsule) is only a rough approximation - needs to be calculated properly. 58 | - Banding - there's quite a bit of banding, particularly visible in those dark scenes above; needs to be solved somehow. Note that banding isn't the same as aliasing. The latter creates differently looking bands and happens due to the froxel resolution being too low (below the Nyquist frequency) for the sharpness of features in the fog (shadow edges, quick changing gradients). To fix aliasing, increase froxel resolution (controls coming, or decrease *Far Clip Max*), or make the features in the fog smoother (e.g. by blurring the shadows more). 59 | - Area light's have Unity's standard shader BRDF *baked* into its lookup tables. To make them work with a different shader, its BRDF would have to baked into new lookup tables. There's currently no tool to do that, but we should make one. In the meantime take a look at the original paper in the references. 60 | 61 | 62 | Contact 63 | ------- 64 | Please use GitHub's issue tracker to file any bugs. 65 | 66 | If you have any questions, it's best to reach Robert via twitter: [@robertcupisz](https://twitter.com/robertcupisz) 67 | 68 | References 69 | ---------- 70 | - Volumetric fog based on [Volumetric fog: Unified, compute shader based solution to atmospheric scattering, ACM Siggraph 2014](https://bartwronski.com/publications/), Bart Wronski (Ubisoft) 71 | - Area lights based on [Real-Time Polygonal-Light Shading with Linearly Transformed Cosines](https://labs.unity.com/article/real-time-polygonal-light-shading-linearly-transformed-cosines), Eric Heitz (Unity Technologies), Jonathan Dupuy (Unity Technologies), Stephen Hill (Ubisoft) and David Neubelt (Ready At Dawn Studios) 72 | - Tube lights based on [Real Shading in Unreal Engine 4](http://blog.selfshadow.com/publications/s2013-shading-course/#course_content), Brian Karis (Epic Games) 73 | 74 | Some more Adam demo shots 75 | 76 | ![fog in the Adam demo](http://i.imgur.com/3ZZk7cL.png) 77 | ![fog in the Adam demo](http://i.imgur.com/QfIeIYR.png) 78 | 79 | -------------------------------------------------------------------------------- /Assets/TubeLight/Shaders/TubeLight.cginc: -------------------------------------------------------------------------------- 1 | // Based on 'Real Shading in Unreal Engine 4' 2 | // http://blog.selfshadow.com/publications/s2013-shading-course/#course_content 3 | 4 | #include "TubeLightAttenuation.cginc" 5 | 6 | #ifndef SHADOW_PLANES 7 | #define SHADOW_PLANES 1 8 | #endif 9 | 10 | #if SHADOW_PLANES 11 | #include "TubeLightShadowPlanes.cginc" 12 | #endif 13 | 14 | #define SHARP_EDGE_FIX 1 15 | 16 | void SphereLightToPointLight(float3 pos, float3 lightPos, float3 eyeVec, half3 normal, float sphereRad, half rangeSqInv, inout UnityLight light, out half lightDist) 17 | { 18 | half3 viewDir = -eyeVec; 19 | half3 r = reflect (viewDir, normal); 20 | 21 | float3 L = lightPos - pos; 22 | float3 centerToRay = dot (L, r) * r - L; 23 | float3 closestPoint = L + centerToRay * saturate(sphereRad / length(centerToRay)); 24 | 25 | lightDist = length(closestPoint); 26 | light.dir = closestPoint / lightDist; 27 | 28 | half distLSq = dot(L, L); 29 | light.ndotl = saturate(dot(normal, L/sqrt(distLSq))); 30 | 31 | float distNorm = distLSq * rangeSqInv; 32 | float atten = AttenuationToZero(distNorm); 33 | light.color *= atten; 34 | } 35 | 36 | void TubeLightToPointLight(float3 pos, float3 tubeStart, float3 tubeEnd, float3 normal, float tubeRad, float rangeSqInv, float3 representativeDir, float3 lightColor, out float3 outLightColor, out float3 outLightDir, out float outNdotL, out half outLightDist) 37 | { 38 | half3 N = normal; 39 | float3 L0 = tubeStart - pos; 40 | float3 L1 = tubeEnd - pos; 41 | float L0dotL0 = dot(L0, L0); 42 | float distL0 = sqrt(L0dotL0); 43 | float distL1 = length(L1); 44 | 45 | float NdotL0 = dot(L0, N) / (2.0 * distL0); 46 | float NdotL1 = dot(L1, N) / (2.0 * distL1); 47 | outNdotL = saturate(NdotL0 + NdotL1); 48 | 49 | float3 Ldir = L1 - L0; 50 | float RepdotL0 = dot(representativeDir, L0); 51 | float RepdotLdir = dot(representativeDir, Ldir); 52 | float L0dotLdir = dot(L0, Ldir); 53 | float LdirdotLdir = dot(Ldir, Ldir); 54 | float distLdir = sqrt(LdirdotLdir); 55 | 56 | #if SHARP_EDGE_FIX 57 | // There's a very visible discontinuity if we just take the closest distance to ray, 58 | // as the original paper suggests. This is an attempt to fix it, but it gets slightly more expensive and 59 | // has its own artifact, although this time at least C0 smooth. 60 | 61 | // Smallest angle to ray 62 | float t = (L0dotLdir * RepdotL0 - L0dotL0 * RepdotLdir) / (L0dotLdir * RepdotLdir - LdirdotLdir * RepdotL0); 63 | t = saturate(t); 64 | 65 | // As representativeDir becomes parallel (well, in some plane) to Ldir and then points away, t flips from 0 to 1 (or vv) and a discontinuity shows up. 66 | // Counteract by detecting that relative angle/position and flip t. The discontinuity in t moves to the back side. 67 | float3 L0xLdir = cross(L0, Ldir); 68 | float3 LdirxR = cross(Ldir, representativeDir); 69 | float RepAtLdir = dot(L0xLdir, LdirxR); 70 | 71 | // RepAtLdir is negative if R points away from Ldir. 72 | // TODO: check if lerp below is indeed cheaper. 73 | // if (RepAtLdir < 0) 74 | // t = 1 - t; 75 | t = lerp(1 - t, t, step(0, RepAtLdir)); 76 | 77 | #else 78 | // Original by Karis 79 | // Closest distance to ray 80 | float t = (RepdotL0 * RepdotLdir - L0dotLdir) / (distLdir * distLdir - RepdotLdir * RepdotLdir); 81 | t = saturate(t); 82 | 83 | #endif 84 | 85 | float3 closestPoint = L0 + Ldir * t; 86 | float3 centerToRay = dot(closestPoint, representativeDir) * representativeDir - closestPoint; 87 | 88 | closestPoint = closestPoint + centerToRay * saturate(tubeRad / length(centerToRay)); 89 | 90 | outLightDist = length(closestPoint); 91 | outLightDir = closestPoint / outLightDist; 92 | 93 | float distNorm = 0.5f * (distL0 * distL1 + dot(L0, L1)) * rangeSqInv; 94 | outLightColor = lightColor * AttenuationToZero(distNorm); 95 | } 96 | 97 | void TubeLightToPointLight(float3 pos, float3 tubeStart, float3 tubeEnd, float3 eyeVec, float3 normal, float tubeRad, float rangeSqInv, float3 lightColor, out float3 outLightColor, out float3 outLightDir, out float outNdotL, out half outLightDist) 98 | { 99 | half3 viewDir = -eyeVec; 100 | half3 representativeDir = reflect (viewDir, normal); 101 | 102 | TubeLightToPointLight(pos, tubeStart, tubeEnd, normal, tubeRad, rangeSqInv, representativeDir, lightColor, outLightColor, outLightDir, outNdotL, outLightDist); 103 | } 104 | 105 | inline half GGXTerm_Area (half NdotH, half roughness, half lightDist, half lightRadius) 106 | { 107 | half a = roughness * roughness; 108 | half a2 = a * a; 109 | half d = NdotH * NdotH * (a2 - 1.f) + 1.f; 110 | d = max(d, 0.000001); 111 | 112 | half aP = saturate( lightRadius / (lightDist*2.0) + a); 113 | half aP2 = aP * aP; 114 | 115 | return a2 * a2 / (UNITY_PI * d * d * aP2); 116 | } 117 | 118 | half4 BRDF1_Unity_PBS_Area (half3 diffColor, half3 specColor, half oneMinusReflectivity, half oneMinusRoughness, 119 | half3 normal, half3 viewDir, 120 | UnityLight light, UnityIndirect gi, half lightDist, half lightRadius) 121 | { 122 | half roughness = 1-oneMinusRoughness; 123 | half3 halfDir = Unity_SafeNormalize (light.dir + viewDir); 124 | 125 | half nl = light.ndotl; 126 | half nh = BlinnTerm (normal, halfDir); 127 | half nv = DotClamped (normal, viewDir); 128 | half lv = DotClamped (light.dir, viewDir); 129 | half lh = DotClamped (light.dir, halfDir); 130 | 131 | half V = SmithGGXVisibilityTerm (nl, nv, roughness); 132 | half D = GGXTerm_Area (nh, roughness, lightDist, lightRadius); 133 | 134 | half nlPow5 = Pow5 (1-nl); 135 | half nvPow5 = Pow5 (1-nv); 136 | half Fd90 = 0.5 + 2 * lh * lh * roughness; 137 | half disneyDiffuse = (1 + (Fd90-1) * nlPow5) * (1 + (Fd90-1) * nvPow5); 138 | 139 | // HACK: theoretically we should divide by Pi diffuseTerm and not multiply specularTerm! 140 | // BUT 1) that will make shader look significantly darker than Legacy ones 141 | // and 2) on engine side "Non-important" lights have to be divided by Pi to in cases when they are injected into ambient SH 142 | // NOTE: multiplication by Pi is part of single constant together with 1/4 now 143 | 144 | half specularTerm = (V * D) * (UNITY_PI/4); // Torrance-Sparrow model, Fresnel is applied later (for optimization reasons) 145 | if (IsGammaSpace()) 146 | specularTerm = sqrt(max(1e-4h, specularTerm)); 147 | specularTerm = max(0, specularTerm * nl); 148 | half diffuseTerm = disneyDiffuse * nl; 149 | 150 | half grazingTerm = saturate(oneMinusRoughness + (1-oneMinusReflectivity)); 151 | half3 color = diffColor * (gi.diffuse + light.color * diffuseTerm) 152 | + specularTerm * light.color * FresnelTerm (specColor, lh) 153 | + gi.specular * FresnelLerp (specColor, grazingTerm, nv); 154 | 155 | return half4(color, 1); 156 | } 157 | 158 | half4 CalculateLight (float3 worldPos, float2 uv, half3 baseColor, half3 specColor, half oneMinusRoughness, half3 normalWorld, 159 | half3 lightStart, half3 lightEnd, half3 lightColor, half lightRadius, half lightRangeSqInv) 160 | { 161 | UnityLight light = (UnityLight)0; 162 | 163 | float3 eyeVec = normalize(worldPos - _WorldSpaceCameraPos); 164 | half lightDist = 0; 165 | 166 | #if 0 167 | // Can't use a keyword, because no keywords in material property blocks. 168 | // TODO: is it worth the dynamic branch? 169 | if (sphereLight) 170 | SphereLightToPointLight (worldPos, lightStart, eyeVec, normalWorld, lightRadius, lightRangeSqInv, light, lightDist); 171 | else 172 | #else 173 | TubeLightToPointLight (worldPos, lightStart, lightEnd, eyeVec, normalWorld, lightRadius, lightRangeSqInv, lightColor, light.color, light.dir, light.ndotl, lightDist); 174 | #endif 175 | 176 | #if SHADOW_PLANES 177 | light.color *= ShadowPlanes(worldPos); 178 | #endif 179 | 180 | half oneMinusReflectivity = 1 - SpecularStrength(specColor.rgb); 181 | 182 | UnityIndirect ind; 183 | UNITY_INITIALIZE_OUTPUT(UnityIndirect, ind); 184 | ind.diffuse = 0; 185 | ind.specular = 0; 186 | 187 | half4 res = BRDF1_Unity_PBS_Area (baseColor, specColor, oneMinusReflectivity, oneMinusRoughness, normalWorld, -eyeVec, light, ind, lightDist, lightRadius); 188 | return res; 189 | } 190 | -------------------------------------------------------------------------------- /Assets/AreaLight/Scripts/AreaLight.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | [ExecuteInEditMode] 4 | public partial class AreaLight : MonoBehaviour 5 | { 6 | public bool m_RenderSource = true; 7 | public Vector3 m_Size = new Vector3(1, 1, 2); 8 | [Range(0, 179)] 9 | public float m_Angle = 0.0f; 10 | [MinValue(0)] 11 | public float m_Intensity = 0.8f; 12 | public Color m_Color = Color.white; 13 | 14 | [Header("Shadows")] 15 | public bool m_Shadows = false; 16 | public LayerMask m_ShadowCullingMask = ~0; 17 | public TextureSize m_ShadowmapRes = TextureSize.x2048; 18 | [MinValue(0)] 19 | public float m_ReceiverSearchDistance = 24.0f; 20 | [MinValue(0)] 21 | public float m_ReceiverDistanceScale = 5.0f; 22 | [MinValue(0)] 23 | public float m_LightNearSize = 4.0f; 24 | [MinValue(0)] 25 | public float m_LightFarSize = 22.0f; 26 | [Range(0, 0.1f)] 27 | public float m_ShadowBias = 0.001f; 28 | 29 | MeshRenderer m_SourceRenderer; 30 | Mesh m_SourceMesh; 31 | [HideInInspector] 32 | public Mesh m_Quad; 33 | Vector2 m_CurrentQuadSize = Vector2.zero; 34 | Vector3 m_CurrentSize = Vector3.zero; 35 | float m_CurrentAngle = -1.0f; 36 | 37 | bool m_Initialized = false; 38 | MaterialPropertyBlock m_props; 39 | 40 | void Awake() 41 | { 42 | if(!Init()) 43 | return; 44 | UpdateSourceMesh(); 45 | } 46 | 47 | bool Init() 48 | { 49 | if (m_Initialized) 50 | return true; 51 | 52 | if (m_Quad == null || !InitDirect()) 53 | return false; 54 | 55 | m_SourceRenderer = GetComponent(); 56 | m_SourceRenderer.enabled = true; 57 | m_SourceMesh = Instantiate(m_Quad); 58 | m_SourceMesh.hideFlags = HideFlags.HideAndDontSave; 59 | MeshFilter mfs = gameObject.GetComponent(); 60 | mfs.sharedMesh = m_SourceMesh; 61 | 62 | Transform t = transform; 63 | if (t.localScale != Vector3.one) 64 | { 65 | #if UNITY_EDITOR 66 | Debug.LogError("AreaLights don't like to be scaled. Setting local scale to 1.", this); 67 | #endif 68 | t.localScale = Vector3.one; 69 | } 70 | 71 | SetUpLUTs(); 72 | 73 | m_Initialized = true; 74 | return true; 75 | } 76 | 77 | void OnEnable() 78 | { 79 | m_props = new MaterialPropertyBlock(); 80 | 81 | if(!Init()) 82 | return; 83 | UpdateSourceMesh(); 84 | } 85 | 86 | void OnDisable() 87 | { 88 | if(!Application.isPlaying) 89 | Cleanup(); 90 | else 91 | for(var e = m_Cameras.GetEnumerator(); e.MoveNext();) 92 | if(e.Current.Value != null) 93 | e.Current.Value.Clear(); 94 | } 95 | 96 | void OnDestroy() 97 | { 98 | if (m_ProxyMaterial != null) 99 | DestroyImmediate(m_ProxyMaterial); 100 | if (m_SourceMesh != null) 101 | DestroyImmediate(m_SourceMesh); 102 | Cleanup(); 103 | } 104 | 105 | static Vector3[] vertices = new Vector3[4]; 106 | 107 | void UpdateSourceMesh() 108 | { 109 | m_Size.x = Mathf.Max(m_Size.x, 0); 110 | m_Size.y = Mathf.Max(m_Size.y, 0); 111 | m_Size.z = Mathf.Max(m_Size.z, 0); 112 | 113 | Vector2 quadSize = m_RenderSource && enabled ? new Vector2(m_Size.x, m_Size.y) : Vector2.one * 0.0001f; 114 | if (quadSize != m_CurrentQuadSize) 115 | { 116 | 117 | float x = quadSize.x * 0.5f; 118 | float y = quadSize.y * 0.5f; 119 | // To prevent the source quad from getting into the shadowmap, offset it back a bit. 120 | float z = -0.001f; 121 | vertices[0].Set(-x, y, z); 122 | vertices[1].Set( x, -y, z); 123 | vertices[2].Set( x, y, z); 124 | vertices[3].Set(-x, -y, z); 125 | 126 | m_SourceMesh.vertices = vertices; 127 | 128 | m_CurrentQuadSize = quadSize; 129 | } 130 | 131 | if (m_Size != m_CurrentSize || m_Angle != m_CurrentAngle) 132 | { 133 | // Set the bounds of the mesh to large, so that they drive rendering of the entire light 134 | // TODO: Make the bounds tight around the shape of the light. Right now they're just tight around 135 | // the shadow frustum, which is fine if the shadows are enable (ok, maybe far plane should be more clever), 136 | // but doesn't make sense if shadows are disabled. 137 | m_SourceMesh.bounds = GetFrustumBounds(); 138 | } 139 | } 140 | 141 | void Update() 142 | { 143 | if (!gameObject.activeInHierarchy || !enabled) 144 | { 145 | Cleanup(); 146 | return; 147 | } 148 | 149 | if(!Init()) 150 | return; 151 | 152 | UpdateSourceMesh(); 153 | 154 | if(Application.isPlaying) 155 | for(var e = m_Cameras.GetEnumerator(); e.MoveNext();) 156 | if(e.Current.Value != null) 157 | e.Current.Value.Clear(); 158 | } 159 | 160 | void OnWillRenderObject() 161 | { 162 | if(!Init()) 163 | return; 164 | 165 | // TODO: This is just a very rough guess. Need to properly calculate the surface emission 166 | // intensity based on light's intensity. 167 | Color color = new Color( 168 | Mathf.GammaToLinearSpace(m_Color.r), 169 | Mathf.GammaToLinearSpace(m_Color.g), 170 | Mathf.GammaToLinearSpace(m_Color.b), 171 | 1.0f); 172 | m_props.SetVector("_EmissionColor", color * m_Intensity); 173 | m_SourceRenderer.SetPropertyBlock(m_props); 174 | 175 | SetUpCommandBuffer(); 176 | } 177 | 178 | float GetNearToCenter() 179 | { 180 | if (m_Angle == 0.0f) 181 | return 0; 182 | 183 | return m_Size.y * 0.5f / Mathf.Tan(m_Angle * 0.5f * Mathf.Deg2Rad); 184 | } 185 | 186 | Matrix4x4 GetOffsetMatrix(float zOffset) 187 | { 188 | Matrix4x4 m = Matrix4x4.identity; 189 | m.SetColumn(3, new Vector4(0, 0, zOffset, 1)); 190 | return m; 191 | } 192 | 193 | public Matrix4x4 GetProjectionMatrix(bool linearZ = false) 194 | { 195 | Matrix4x4 m; 196 | 197 | if (m_Angle == 0.0f) 198 | { 199 | m = Matrix4x4.Ortho(-0.5f * m_Size.x, 0.5f * m_Size.x, -0.5f * m_Size.y, 0.5f * m_Size.y, 0, -m_Size.z); 200 | } 201 | else 202 | { 203 | float near = GetNearToCenter(); 204 | if (linearZ) 205 | { 206 | m = PerspectiveLinearZ(m_Angle, m_Size.x/m_Size.y, near, near + m_Size.z); 207 | } 208 | else 209 | { 210 | m = Matrix4x4.Perspective(m_Angle, m_Size.x/m_Size.y, near, near + m_Size.z); 211 | m = m * Matrix4x4.Scale(new Vector3(1, 1, -1)); 212 | } 213 | m = m * GetOffsetMatrix(near); 214 | } 215 | 216 | return m * transform.worldToLocalMatrix; 217 | } 218 | 219 | public Vector4 MultiplyPoint(Matrix4x4 m, Vector3 v) 220 | { 221 | Vector4 res; 222 | res.x = m.m00 * v.x + m.m01 * v.y + m.m02 * v.z + m.m03; 223 | res.y = m.m10 * v.x + m.m11 * v.y + m.m12 * v.z + m.m13; 224 | res.z = m.m20 * v.x + m.m21 * v.y + m.m22 * v.z + m.m23; 225 | res.w = m.m30 * v.x + m.m31 * v.y + m.m32 * v.z + m.m33; 226 | return res; 227 | } 228 | 229 | Matrix4x4 PerspectiveLinearZ(float fov, float aspect, float near, float far) 230 | { 231 | // A vector transformed with this matrix should get perspective division on x and y only: 232 | // Vector4 vClip = MultiplyPoint(PerspectiveLinearZ(...), vEye); 233 | // Vector3 vNDC = Vector3(vClip.x / vClip.w, vClip.y / vClip.w, vClip.z); 234 | // vNDC is [-1, 1]^3 and z is linear, i.e. z = 0 is half way between near and far in world space. 235 | 236 | float rad = Mathf.Deg2Rad * fov * 0.5f; 237 | float cotan = Mathf.Cos(rad) / Mathf.Sin(rad); 238 | float deltainv = 1.0f / (far - near); 239 | Matrix4x4 m; 240 | 241 | m.m00 = cotan / aspect; m.m01 = 0.0f; m.m02 = 0.0f; m.m03 = 0.0f; 242 | m.m10 = 0.0f; m.m11 = cotan; m.m12 = 0.0f; m.m13 = 0.0f; 243 | m.m20 = 0.0f; m.m21 = 0.0f; m.m22 = 2.0f * deltainv; m.m23 = - (far + near) * deltainv; 244 | m.m30 = 0.0f; m.m31 = 0.0f; m.m32 = 1.0f; m.m33 = 0.0f; 245 | 246 | return m; 247 | } 248 | 249 | public Vector4 GetPosition() 250 | { 251 | Transform t = transform; 252 | 253 | if (m_Angle == 0.0f) 254 | { 255 | Vector3 dir = -t.forward; 256 | return new Vector4(dir.x, dir.y, dir.z, 0); 257 | } 258 | 259 | Vector3 pos = t.position - GetNearToCenter() * t.forward; 260 | return new Vector4(pos.x, pos.y, pos.z, 1); 261 | } 262 | 263 | Bounds GetFrustumBounds() 264 | { 265 | if (m_Angle == 0.0f) 266 | return new Bounds(Vector3.zero, m_Size); 267 | 268 | float tanhalffov = Mathf.Tan(m_Angle * 0.5f * Mathf.Deg2Rad); 269 | float near = m_Size.y * 0.5f / tanhalffov; 270 | float z = m_Size.z; 271 | float y = (near + m_Size.z) * tanhalffov * 2.0f; 272 | float x = m_Size.x * y / m_Size.y; 273 | return new Bounds(Vector3.forward * m_Size.z * 0.5f, new Vector3(x, y, z)); 274 | } 275 | 276 | void OnDrawGizmosSelected() 277 | { 278 | Gizmos.color = Color.white; 279 | 280 | if (m_Angle == 0.0f) 281 | { 282 | Gizmos.matrix = transform.localToWorldMatrix; 283 | Gizmos.DrawWireCube(new Vector3(0, 0, 0.5f * m_Size.z), m_Size); 284 | return; 285 | } 286 | 287 | float near = GetNearToCenter(); 288 | Gizmos.matrix = transform.localToWorldMatrix * GetOffsetMatrix(-near); 289 | 290 | Gizmos.DrawFrustum(Vector3.zero, m_Angle, near + m_Size.z, near, m_Size.x/m_Size.y); 291 | 292 | Gizmos.matrix = transform.localToWorldMatrix; 293 | Gizmos.color = Color.yellow; 294 | Bounds bounds = GetFrustumBounds(); 295 | Gizmos.DrawWireCube(bounds.center, bounds.size); 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /Assets/TubeLight/Scripts/TubeLight.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Rendering; 3 | using System.Collections.Generic; 4 | 5 | [ExecuteInEditMode] 6 | public class TubeLight : MonoBehaviour 7 | { 8 | public float m_Intensity = 0.8f; 9 | public Color m_Color = Color.white; 10 | public float m_Range = 10.0f; 11 | public float m_Radius = 0.3f; 12 | public float m_Length = 0.0f; 13 | 14 | [HideInInspector] 15 | public Mesh m_Sphere; 16 | [HideInInspector] 17 | public Mesh m_Capsule; 18 | [HideInInspector] 19 | public Shader m_ProxyShader; 20 | Material m_ProxyMaterial; 21 | 22 | public bool m_RenderSource = false; 23 | Renderer m_SourceRenderer; 24 | Transform m_SourceTransform; 25 | Mesh m_SourceMesh; 26 | float m_LastLength = -1; 27 | 28 | public const int maxPlanes = 2; 29 | [HideInInspector] 30 | public TubeLightShadowPlane[] m_ShadowPlanes = new TubeLightShadowPlane[maxPlanes]; 31 | 32 | bool m_Initialized = false; 33 | MaterialPropertyBlock m_props; 34 | 35 | const float kMinRadius = 0.001f; 36 | bool renderSource {get{return m_RenderSource && m_Radius >= kMinRadius;}} 37 | 38 | Dictionary m_Cameras = new Dictionary(); 39 | static CameraEvent kCameraEvent = CameraEvent.AfterLighting; 40 | 41 | void Start() 42 | { 43 | if(!Init()) 44 | return; 45 | UpdateMeshesAndBounds(); 46 | } 47 | 48 | bool Init() 49 | { 50 | if (m_Initialized) 51 | return true; 52 | 53 | // Sometimes on editor startup (especially after project upgrade?), Init() gets called 54 | // while m_ProxyShader, m_Sphere or m_Capsule is still null/hasn't loaded. 55 | if (m_ProxyShader == null || m_Sphere == null || m_Capsule == null) 56 | return false; 57 | 58 | // Proxy 59 | m_ProxyMaterial = new Material(m_ProxyShader); 60 | m_ProxyMaterial.hideFlags = HideFlags.HideAndDontSave; 61 | 62 | // Source 63 | m_SourceMesh = Instantiate(m_Capsule); 64 | m_SourceMesh.hideFlags = HideFlags.HideAndDontSave; 65 | 66 | // Can't create the MeshFilter here, since for some reason the DontSave flag has 67 | // no effect on it. Has to be added to the prefab instead. 68 | //m_SourceMeshFilter = gameObject.AddComponent(); 69 | MeshFilter mfs = gameObject.GetComponent(); 70 | // Hmm, causes trouble 71 | // mfs.hideFlags = HideFlags.HideInInspector; 72 | mfs.sharedMesh = m_SourceMesh; 73 | 74 | // A similar problem here. 75 | // m_SourceRenderer = gameObject.AddComponent(); 76 | m_SourceRenderer = gameObject.GetComponent(); 77 | m_SourceRenderer.enabled = true; 78 | 79 | // We want it to be pickable in the scene view, so no HideAndDontSave 80 | // Hmm, causes trouble 81 | // m_SourceRenderer.hideFlags = HideFlags.DontSave | HideFlags.HideInInspector; 82 | 83 | m_SourceTransform = transform; 84 | 85 | m_Initialized = true; 86 | return true; 87 | } 88 | 89 | void OnEnable() 90 | { 91 | if(m_props == null) 92 | m_props = new MaterialPropertyBlock(); 93 | 94 | if(!Init()) 95 | return; 96 | UpdateMeshesAndBounds(); 97 | } 98 | 99 | void OnDisable() 100 | { 101 | if(!Application.isPlaying) 102 | Cleanup(); 103 | else 104 | for(var e = m_Cameras.GetEnumerator(); e.MoveNext();) 105 | if(e.Current.Value != null) 106 | e.Current.Value.Clear(); 107 | } 108 | 109 | void OnDestroy() 110 | { 111 | if (m_ProxyMaterial != null) 112 | DestroyImmediate(m_ProxyMaterial); 113 | if (m_SourceMesh != null) 114 | DestroyImmediate(m_SourceMesh); 115 | Cleanup(); 116 | } 117 | 118 | void Cleanup() 119 | { 120 | for(var e = m_Cameras.GetEnumerator(); e.MoveNext();) 121 | { 122 | var cam = e.Current; 123 | if(cam.Key != null && cam.Value != null) 124 | cam.Key.RemoveCommandBuffer (kCameraEvent, cam.Value); 125 | } 126 | m_Cameras.Clear(); 127 | } 128 | 129 | void UpdateMeshesAndBounds() 130 | { 131 | // Sanitize 132 | m_Range = Mathf.Max(m_Range, 0); 133 | m_Radius = Mathf.Max(m_Radius, 0); 134 | m_Length = Mathf.Max(m_Length, 0); 135 | m_Intensity = Mathf.Max(m_Intensity, 0); 136 | 137 | Vector3 sourceSize = renderSource ? Vector3.one * m_Radius * 2.0f : Vector3.one; 138 | if (m_SourceTransform.localScale != sourceSize || m_Length != m_LastLength) 139 | { 140 | m_LastLength = m_Length; 141 | 142 | Vector3[] vertices = m_Capsule.vertices; 143 | for (int i = 0; i < vertices.Length; i++) 144 | { 145 | if (renderSource) 146 | vertices[i].y += Mathf.Sign(vertices[i].y) * (- 0.5f + 0.25f * m_Length / m_Radius); 147 | else 148 | vertices[i] = Vector3.one * 0.0001f; 149 | } 150 | 151 | m_SourceMesh.vertices = vertices; 152 | } 153 | 154 | m_SourceTransform.localScale = sourceSize; 155 | 156 | float range = m_Range + m_Radius; 157 | 158 | // TODO: lazy for now, should draw a tight capsule 159 | range += 0.5f * m_Length; 160 | range *= 1.02f; 161 | 162 | range /= m_Radius; 163 | 164 | m_SourceMesh.bounds = new Bounds(Vector3.zero, Vector3.one * range); 165 | } 166 | 167 | void Update() 168 | { 169 | if(!Init()) 170 | return; 171 | 172 | UpdateMeshesAndBounds(); 173 | 174 | if(Application.isPlaying) 175 | for(var e = m_Cameras.GetEnumerator(); e.MoveNext();) 176 | if(e.Current.Value != null) 177 | e.Current.Value.Clear(); 178 | } 179 | 180 | Color GetColor() 181 | { 182 | if (QualitySettings.activeColorSpace == ColorSpace.Gamma) 183 | return m_Color * m_Intensity; 184 | 185 | return new Color( 186 | Mathf.GammaToLinearSpace(m_Color.r * m_Intensity), 187 | Mathf.GammaToLinearSpace(m_Color.g * m_Intensity), 188 | Mathf.GammaToLinearSpace(m_Color.b * m_Intensity), 189 | 1.0f 190 | ); 191 | } 192 | 193 | void OnWillRenderObject() 194 | { 195 | if(InsideShadowmapCameraRender()) 196 | return; 197 | 198 | if(!Init()) 199 | return; 200 | 201 | // TODO: This is just a very rough guess. Need to properly calculate the surface emission 202 | // intensity based on light's intensity. 203 | m_props.SetVector("_EmissionColor", m_Color * Mathf.Sqrt(m_Intensity) * 2.0f); 204 | m_SourceRenderer.SetPropertyBlock(m_props); 205 | 206 | SetUpCommandBuffer(); 207 | } 208 | 209 | void SetUpCommandBuffer() 210 | { 211 | Camera cam = Camera.current; 212 | CommandBuffer buf = null; 213 | if (!m_Cameras.ContainsKey(cam)) 214 | { 215 | buf = new CommandBuffer(); 216 | buf.name = gameObject.name; 217 | m_Cameras[cam] = buf; 218 | cam.AddCommandBuffer(kCameraEvent, buf); 219 | cam.depthTextureMode |= DepthTextureMode.Depth; 220 | } 221 | else 222 | { 223 | buf = m_Cameras[cam]; 224 | buf.Clear(); 225 | } 226 | 227 | Transform t = transform; 228 | Vector3 lightAxis = t.up; 229 | Vector3 lightPos = t.position - 0.5f * lightAxis * m_Length; 230 | buf.SetGlobalVector("_LightPos", new Vector4(lightPos.x, lightPos.y, lightPos.z, 1.0f/(m_Range*m_Range))); 231 | buf.SetGlobalVector("_LightAxis", new Vector4(lightAxis.x, lightAxis.y, lightAxis.z, 0.0f)); 232 | buf.SetGlobalFloat("_LightAsQuad", 0); 233 | buf.SetGlobalFloat("_LightRadius", m_Radius); 234 | buf.SetGlobalFloat("_LightLength", m_Length); 235 | buf.SetGlobalVector("_LightColor", GetColor()); 236 | 237 | SetShadowPlaneVectors(buf); 238 | 239 | float range = m_Range + m_Radius; 240 | // TODO: lazy for now, should draw a tight capsule 241 | range += 0.5f * m_Length; 242 | range *= 1.02f; 243 | range /= m_Radius; 244 | 245 | Matrix4x4 m = Matrix4x4.Scale(Vector3.one * range); 246 | buf.DrawMesh(m_Sphere, t.localToWorldMatrix * m, m_ProxyMaterial, 0, 0); 247 | } 248 | 249 | public TubeLightShadowPlane.Params[] GetShadowPlaneParams(ref TubeLightShadowPlane.Params[] p) 250 | { 251 | if (p == null || p.Length != maxPlanes) 252 | p = new TubeLightShadowPlane.Params[maxPlanes]; 253 | for(int i = 0; i < maxPlanes; i++) 254 | { 255 | TubeLightShadowPlane sp = m_ShadowPlanes[i]; 256 | p[i].plane = sp == null ? new Vector4(0, 0, 0, 1) : sp.GetShadowPlaneVector(); 257 | p[i].feather = sp == null ? 1 : sp.feather; 258 | } 259 | return p; 260 | } 261 | 262 | TubeLightShadowPlane.Params[] sppArr = new TubeLightShadowPlane.Params[maxPlanes]; 263 | 264 | void SetShadowPlaneVectors(CommandBuffer buf) 265 | { 266 | var p = GetShadowPlaneParams(ref sppArr); 267 | 268 | for (int i = 0, n = p.Length; i < n; ++i) 269 | { 270 | var spp = p[i]; 271 | if(i == 0) { 272 | buf.SetGlobalVector("_ShadowPlane0", spp.plane); 273 | buf.SetGlobalFloat("_ShadowPlaneFeather0", spp.feather); 274 | } else if(i == 1) { 275 | buf.SetGlobalVector("_ShadowPlane1", spp.plane); 276 | buf.SetGlobalFloat("_ShadowPlaneFeather1", spp.feather); 277 | } else { 278 | buf.SetGlobalVector("_ShadowPlane" + i, spp.plane); 279 | buf.SetGlobalFloat("_ShadowPlaneFeather" + i, spp.feather); 280 | } 281 | } 282 | } 283 | 284 | void OnDrawGizmosSelected() 285 | { 286 | if (m_SourceTransform == null) 287 | return; 288 | 289 | Gizmos.color = Color.white; 290 | // Skip the scale 291 | Matrix4x4 m = new Matrix4x4(); 292 | m.SetTRS(m_SourceTransform.position, m_SourceTransform.rotation, Vector3.one); 293 | Gizmos.matrix = m; 294 | 295 | Gizmos.DrawWireSphere(Vector3.zero, m_Radius + m_Range + 0.5f * m_Length); 296 | 297 | Vector3 start = 0.5f * Vector3.up * m_Length; 298 | Gizmos.DrawWireSphere(start, m_Radius); 299 | 300 | if (m_Length == 0.0f) 301 | return; 302 | 303 | Vector3 end = - 0.5f * Vector3.up * m_Length; 304 | Gizmos.DrawWireSphere(end, m_Radius); 305 | 306 | Vector3 r = Vector3.forward * m_Radius; 307 | Gizmos.DrawLine(start + r, end + r); 308 | Gizmos.DrawLine(start - r, end - r); 309 | 310 | r = Vector3.right * m_Radius; 311 | Gizmos.DrawLine(start + r, end + r); 312 | Gizmos.DrawLine(start - r, end - r); 313 | 314 | } 315 | 316 | void OnDrawGizmos() 317 | { 318 | // TODO: Looks like this changed the name. Find a more robust way to use the icon. 319 | // Gizmos.DrawIcon(transform.position, "PointLight Gizmo_MIP0.png", true); 320 | } 321 | 322 | bool InsideShadowmapCameraRender() 323 | { 324 | RenderTexture target = Camera.current.targetTexture; 325 | return target != null && target.format == RenderTextureFormat.Shadowmap; 326 | } 327 | } 328 | -------------------------------------------------------------------------------- /Assets/AreaLight/Scripts/AreaLight.Shadow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Rendering; 3 | 4 | public partial class AreaLight : MonoBehaviour 5 | { 6 | Camera m_ShadowmapCamera; 7 | Transform m_ShadowmapCameraTransform; 8 | 9 | [HideInInspector] 10 | public Shader m_ShadowmapShader; 11 | [HideInInspector] 12 | public Shader m_BlurShadowmapShader; 13 | Material m_BlurShadowmapMaterial; 14 | RenderTexture m_Shadowmap = null; 15 | RenderTexture m_BlurredShadowmap = null; 16 | Texture2D m_ShadowmapDummy = null; 17 | 18 | int m_ShadowmapRenderTime = -1; 19 | int m_BlurredShadowmapRenderTime = -1; 20 | FogLight m_FogLight = null; 21 | 22 | public enum TextureSize 23 | { 24 | x512 = 512, 25 | x1024 = 1024, 26 | x2048 = 2048, 27 | x4096 = 4096, 28 | } 29 | 30 | void UpdateShadowmap(int res) 31 | { 32 | if (m_Shadowmap != null && m_ShadowmapRenderTime == Time.renderedFrameCount) 33 | return; 34 | 35 | // Create the camera 36 | if (m_ShadowmapCamera == null) 37 | { 38 | if (m_ShadowmapShader == null) 39 | { 40 | Debug.LogError("AreaLight's shadowmap shader not assigned.", this); 41 | return; 42 | } 43 | 44 | GameObject go = new GameObject("Shadowmap Camera"); 45 | go.AddComponent(typeof(Camera)); 46 | m_ShadowmapCamera = go.GetComponent(); 47 | go.hideFlags = HideFlags.HideAndDontSave; 48 | m_ShadowmapCamera.enabled = false; 49 | m_ShadowmapCamera.clearFlags = CameraClearFlags.SolidColor; 50 | m_ShadowmapCamera.renderingPath = RenderingPath.Forward; 51 | // exp(EXPONENT) for ESM, white for VSM 52 | // m_ShadowmapCamera.backgroundColor = new Color(Mathf.Exp(EXPONENT), 0, 0, 0); 53 | m_ShadowmapCamera.backgroundColor = Color.white; 54 | m_ShadowmapCameraTransform = go.transform; 55 | m_ShadowmapCameraTransform.parent = transform; 56 | m_ShadowmapCameraTransform.localRotation = Quaternion.identity; 57 | } 58 | 59 | if (m_Angle == 0.0f) 60 | { 61 | m_ShadowmapCamera.orthographic = true; 62 | m_ShadowmapCameraTransform.localPosition = Vector3.zero; 63 | m_ShadowmapCamera.nearClipPlane = 0; 64 | m_ShadowmapCamera.farClipPlane = m_Size.z; 65 | m_ShadowmapCamera.orthographicSize = 0.5f * m_Size.y; 66 | m_ShadowmapCamera.aspect = m_Size.x / m_Size.y; 67 | } 68 | else 69 | { 70 | m_ShadowmapCamera.orthographic = false; 71 | float near = GetNearToCenter(); 72 | m_ShadowmapCameraTransform.localPosition = -near * Vector3.forward; 73 | m_ShadowmapCamera.nearClipPlane = near; 74 | m_ShadowmapCamera.farClipPlane = near + m_Size.z; 75 | m_ShadowmapCamera.fieldOfView = m_Angle; 76 | m_ShadowmapCamera.aspect = m_Size.x / m_Size.y; 77 | } 78 | 79 | ReleaseTemporary(ref m_Shadowmap); 80 | m_Shadowmap = RenderTexture.GetTemporary(res, res, 24, RenderTextureFormat.Shadowmap); 81 | m_Shadowmap.name = "AreaLight Shadowmap"; 82 | m_Shadowmap.filterMode = FilterMode.Bilinear; 83 | m_Shadowmap.wrapMode = TextureWrapMode.Clamp; 84 | 85 | m_ShadowmapCamera.targetTexture = m_Shadowmap; 86 | 87 | // Clear. RenderWithShader() should clear too, but it doesn't. 88 | // TODO: Check if it's a bug. 89 | m_ShadowmapCamera.cullingMask = 0; 90 | m_ShadowmapCamera.Render(); 91 | m_ShadowmapCamera.cullingMask = m_ShadowCullingMask; 92 | 93 | // We might be rendering inside PlaneReflections, which invert culling. Disable temporarily. 94 | var oldCulling = GL.invertCulling; 95 | GL.invertCulling = false; 96 | 97 | m_ShadowmapCamera.RenderWithShader(m_ShadowmapShader, "RenderType"); 98 | 99 | // Back to whatever was the culling mode. 100 | GL.invertCulling = oldCulling; 101 | 102 | m_ShadowmapRenderTime = Time.renderedFrameCount; 103 | } 104 | 105 | public RenderTexture GetBlurredShadowmap() 106 | { 107 | UpdateBlurredShadowmap(); 108 | return m_BlurredShadowmap; 109 | } 110 | 111 | RenderTexture[] temp; 112 | 113 | void UpdateBlurredShadowmap() 114 | { 115 | if (m_BlurredShadowmap != null && m_BlurredShadowmapRenderTime == Time.renderedFrameCount) 116 | return; 117 | 118 | InitFogLight(); 119 | 120 | int startRes = (int)m_ShadowmapRes; 121 | int targetRes = (int)m_FogLight.m_ShadowmapRes; 122 | 123 | // To make things easier, blurred shadowmap is at most half the size of the regular. 124 | if (isActiveAndEnabled && m_Shadows) 125 | { 126 | targetRes = Mathf.Min(targetRes, startRes/2); 127 | } 128 | else 129 | { 130 | // If the area light or the shadows on it are disabled, we can 131 | // just get the most convenient resolution for us. 132 | startRes = 2 * startRes; 133 | } 134 | 135 | UpdateShadowmap(startRes); 136 | 137 | RenderTexture originalRT = RenderTexture.active; 138 | 139 | // Downsample 140 | ReleaseTemporary(ref m_BlurredShadowmap); 141 | InitMaterial(ref m_BlurShadowmapMaterial, m_BlurShadowmapShader); 142 | int downsampleSteps = (int)Mathf.Log(startRes / targetRes, 2); 143 | if (temp == null || temp.Length != downsampleSteps) 144 | temp = new RenderTexture[downsampleSteps]; 145 | // RFloat for ESM, RGHalf for VSM 146 | RenderTextureFormat format = RenderTextureFormat.RGHalf; 147 | 148 | for(int i = 0, currentRes = startRes/2; i < downsampleSteps; i++) 149 | { 150 | temp[i] = RenderTexture.GetTemporary(currentRes, currentRes, 0, format, RenderTextureReadWrite.Linear); 151 | temp[i].name = "AreaLight Shadow Downsample"; 152 | temp[i].filterMode = FilterMode.Bilinear; 153 | temp[i].wrapMode = TextureWrapMode.Clamp; 154 | m_BlurShadowmapMaterial.SetVector("_TexelSize", new Vector4(0.5f/currentRes, 0.5f/currentRes, 0, 0)); 155 | 156 | if (i == 0) 157 | { 158 | m_BlurShadowmapMaterial.SetTexture("_Shadowmap", m_Shadowmap); 159 | InitShadowmapDummy(); 160 | m_BlurShadowmapMaterial.SetTexture("_ShadowmapDummy", m_ShadowmapDummy); 161 | m_BlurShadowmapMaterial.SetVector("_ZParams", GetZParams()); 162 | m_BlurShadowmapMaterial.SetFloat("_ESMExponent", m_FogLight.m_ESMExponent); 163 | Blur(m_Shadowmap, temp[i], /*sample & convert shadowmap*/ 0); 164 | } 165 | else 166 | { 167 | m_BlurShadowmapMaterial.SetTexture("_MainTex", temp[i - 1]); 168 | Blur(temp[i - 1], temp[i], /*regular sample*/ 1); 169 | } 170 | 171 | currentRes /= 2; 172 | } 173 | 174 | for (int i = 0; i < downsampleSteps - 1; i++) 175 | RenderTexture.ReleaseTemporary(temp[i]); 176 | 177 | m_BlurredShadowmap = temp[downsampleSteps - 1]; 178 | 179 | // Blur 180 | if (m_FogLight.m_BlurIterations > 0) 181 | { 182 | RenderTexture tempBlur = RenderTexture.GetTemporary (targetRes, targetRes, 0, format, RenderTextureReadWrite.Linear); 183 | tempBlur.name = "AreaLight Shadow Blur"; 184 | tempBlur.filterMode = FilterMode.Bilinear; 185 | tempBlur.wrapMode = TextureWrapMode.Clamp; 186 | 187 | m_BlurShadowmapMaterial.SetVector("_MainTex_TexelSize", new Vector4(1.0f/targetRes, 1.0f/targetRes, 0, 0)); 188 | 189 | float blurSize = m_FogLight.m_BlurSize; 190 | for(int i = 0; i < m_FogLight.m_BlurIterations; i++) 191 | { 192 | m_BlurShadowmapMaterial.SetFloat ("_BlurSize", blurSize); 193 | Blur(m_BlurredShadowmap, tempBlur, /*vertical blur*/2); 194 | Blur(tempBlur, m_BlurredShadowmap, /*horizontal blur*/3); 195 | blurSize *= 1.2f; 196 | } 197 | 198 | RenderTexture.ReleaseTemporary(tempBlur); 199 | } 200 | 201 | RenderTexture.active = originalRT; 202 | 203 | m_BlurredShadowmapRenderTime = Time.renderedFrameCount; 204 | } 205 | 206 | // Normally would've used Graphics.Blit(), but it breaks picking in the scene view. 207 | // TODO: bug report 208 | void Blur(RenderTexture src, RenderTexture dst, int pass) 209 | { 210 | RenderTexture.active = dst; 211 | m_BlurShadowmapMaterial.SetTexture("_MainTex", src); 212 | m_BlurShadowmapMaterial.SetPass(pass); 213 | RenderQuad(); 214 | } 215 | 216 | void RenderQuad() 217 | { 218 | GL.Begin(GL.QUADS); 219 | GL.TexCoord2( 0, 0); 220 | GL.Vertex3 (-1, 1, 0); 221 | GL.TexCoord2( 0, 1); 222 | GL.Vertex3 (-1,-1, 0); 223 | GL.TexCoord2( 1, 1); 224 | GL.Vertex3 ( 1,-1, 0); 225 | GL.TexCoord2( 1, 0); 226 | GL.Vertex3 ( 1, 1, 0); 227 | GL.End(); 228 | } 229 | 230 | void SetUpShadowmapForSampling(CommandBuffer buf) 231 | { 232 | UpdateShadowmap((int)m_ShadowmapRes); 233 | 234 | buf.SetGlobalTexture("_Shadowmap", m_Shadowmap); 235 | InitShadowmapDummy(); 236 | m_ProxyMaterial.SetTexture("_ShadowmapDummy", m_ShadowmapDummy); 237 | buf.SetGlobalMatrix("_ShadowProjectionMatrix", GetProjectionMatrix()); 238 | 239 | float texelsInMap = (int)m_ShadowmapRes; 240 | float relativeTexelSize = texelsInMap / 2048.0f; 241 | 242 | buf.SetGlobalFloat("_ShadowReceiverWidth", relativeTexelSize * m_ReceiverSearchDistance / texelsInMap); 243 | 244 | buf.SetGlobalFloat("_ShadowReceiverDistanceScale", m_ReceiverDistanceScale * 0.5f / 10.0f); // 10 samples in shader 245 | 246 | Vector2 shadowLightWidth = new Vector2(m_LightNearSize, m_LightFarSize) * relativeTexelSize / texelsInMap; 247 | buf.SetGlobalVector("_ShadowLightWidth", shadowLightWidth); 248 | 249 | buf.SetGlobalFloat("_ShadowBias", m_ShadowBias); 250 | } 251 | 252 | void InitMaterial(ref Material material, Shader shader) 253 | { 254 | if (material) 255 | return; 256 | 257 | if (!shader) 258 | { 259 | Debug.LogError("Missing shader"); 260 | return; 261 | } 262 | 263 | material = new Material(shader); 264 | material.hideFlags = HideFlags.HideAndDontSave; 265 | } 266 | 267 | void InitShadowmapDummy() 268 | { 269 | if(m_ShadowmapDummy != null) 270 | return; 271 | m_ShadowmapDummy = new Texture2D(1, 1, TextureFormat.Alpha8, false, true); 272 | m_ShadowmapDummy.filterMode = FilterMode.Point; 273 | m_ShadowmapDummy.SetPixel(0, 0, new Color(0f, 0f, 0f, 0f)); 274 | m_ShadowmapDummy.Apply(false, true); 275 | } 276 | 277 | void InitFogLight() 278 | { 279 | if (m_FogLight != null) 280 | return; 281 | 282 | // It should always be here, because it triggered this code path in the first place. 283 | m_FogLight = GetComponent(); 284 | } 285 | 286 | bool InsideShadowmapCameraRender() 287 | { 288 | RenderTexture target = Camera.current.targetTexture; 289 | return target != null && target.format == RenderTextureFormat.Shadowmap; 290 | } 291 | 292 | Vector4 GetZParams() 293 | { 294 | float n = GetNearToCenter(); 295 | float f = n + m_Size.z; 296 | // linear z, 0 near, 1 far 297 | // linearz = A * (z + 1.0) / (z + B); 298 | // A = n/(n - f) 299 | // B = (n + f)/(n - f) 300 | 301 | return new Vector4(n/(n - f), (n + f)/(n - f), 0, 0); 302 | } 303 | } 304 | -------------------------------------------------------------------------------- /Assets/VolumetricFog/Shaders/InjectLightingAndDensity.compute: -------------------------------------------------------------------------------- 1 | #pragma kernel CSMain TUBE_LIGHTS TUBE_LIGHT_SHADOW_PLANES FOG_ELLIPSOIDS ANISOTROPY AREA_LIGHTS POINT_LIGHTS 2 | 3 | // Directional light support not quite ready yet 4 | // #pragma kernel CSMain TUBE_LIGHTS TUBE_LIGHT_SHADOW_PLANES FOG_ELLIPSOIDS ANISOTROPY AREA_LIGHTS POINT_LIGHTS DIR_LIGHT 5 | 6 | #define TUBE_LIGHT_ATTENUATION_LEGACY 1 7 | #include "..\..\TubeLight\Shaders\TubeLightAttenuation.cginc" 8 | 9 | #ifdef TUBE_LIGHT_SHADOW_PLANES 10 | #include "..\..\TubeLight\Shaders\TubeLightShadowPlanes.cginc" 11 | #endif 12 | 13 | RWTexture3D _VolumeInject; 14 | float4 _FrustumRays[4]; 15 | float4 _CameraPos; 16 | float4 _FrustumRaysLight[4]; 17 | float4 _CameraPosLight; 18 | float _Density; 19 | float _Intensity; 20 | float _Anisotropy; 21 | Texture2D _Noise; 22 | SamplerState sampler_Noise; 23 | float4 _FogParams; 24 | float _NoiseFogAmount; 25 | float _NoiseFogScale; 26 | float _WindSpeed; 27 | float3 _WindDir; 28 | float _Time; 29 | Texture2D _LightTextureB0; 30 | SamplerState sampler_LightTextureB0; 31 | float _NearOverFarClip; 32 | float3 _AmbientLight; 33 | #ifdef FOG_BOMB 34 | float _FogBombRadius; 35 | float3 _FogBombPos; 36 | #endif 37 | 38 | #ifdef DIR_LIGHT 39 | float3 _DirLightColor; 40 | float3 _DirLightDir; 41 | #ifdef DIR_LIGHT_SHADOWS 42 | float _DirLightShadows; 43 | float _ESMExponentDirLight; 44 | struct ShadowParams 45 | { 46 | float4x4 worldToShadow[4]; 47 | float4 shadowSplitSpheres[4]; 48 | float4 shadowSplitSqRadii; 49 | }; 50 | RWStructuredBuffer _ShadowParams; 51 | Texture2D _DirectionalShadowmap; 52 | SamplerState sampler_DirectionalShadowmap; 53 | #endif 54 | #endif 55 | 56 | #ifdef POINT_LIGHTS 57 | struct PointLight 58 | { 59 | float3 pos; 60 | float range; 61 | float3 color; 62 | float padding; 63 | }; 64 | StructuredBuffer _PointLights; 65 | float _PointLightsCount; 66 | #endif 67 | 68 | #ifdef TUBE_LIGHTS 69 | struct TubeLight 70 | { 71 | float3 start; 72 | float range; 73 | float3 end; 74 | float radius; 75 | float3 color; 76 | float padding; 77 | }; 78 | StructuredBuffer _TubeLights; 79 | float _TubeLightsCount; 80 | 81 | #ifdef TUBE_LIGHT_SHADOW_PLANES 82 | // Same count as _TubeLightsCount 83 | StructuredBuffer _TubeLightShadowPlanes; 84 | #endif 85 | 86 | #endif // TUBE_LIGHTS 87 | 88 | #ifdef AREA_LIGHTS 89 | struct AreaLight 90 | { 91 | float4x4 mat; 92 | float4 pos; // only needed for anisotropy. w: 0 ortho, 1 proj 93 | float3 color; 94 | float bounded; 95 | }; 96 | StructuredBuffer _AreaLights; 97 | float _AreaLightsCount; 98 | Texture2D _AreaLightShadowmap; 99 | SamplerState sampler_AreaLightShadowmap; 100 | float _ShadowedAreaLightIndex; 101 | float4 _AreaLightShadowmapZParams; 102 | float _ESMExponentAreaLight; 103 | #endif 104 | 105 | #ifdef FOG_ELLIPSOIDS 106 | struct FogEllipsoid 107 | { 108 | float3 pos; 109 | float radius; 110 | float3 axis; 111 | float stretch; 112 | float density; 113 | float noiseAmount; 114 | float noiseSpeed; 115 | float noiseScale; 116 | float feather; 117 | float blend; 118 | float padding1; 119 | float padding2; 120 | }; 121 | StructuredBuffer _FogEllipsoids; 122 | float _FogEllipsoidsCount; 123 | #endif 124 | 125 | float hash( float n ) { return frac(sin(n)*753.5453123); } 126 | float noisep(float3 x) 127 | { 128 | float3 p = floor(x); 129 | float3 f = frac(x); 130 | f = f*f*(3.0-2.0*f); 131 | 132 | float n = p.x + p.y*157.0 + 113.0*p.z; 133 | return lerp(lerp(lerp( hash(n+ 0.0), hash(n+ 1.0),f.x), 134 | lerp( hash(n+157.0), hash(n+158.0),f.x),f.y), 135 | lerp(lerp( hash(n+113.0), hash(n+114.0),f.x), 136 | lerp( hash(n+270.0), hash(n+271.0),f.x),f.y),f.z); 137 | } 138 | 139 | float noise(float3 x) 140 | { 141 | float3 p = floor(x); 142 | float3 f = frac(x); 143 | f = f * f * (3.0 - 2.0 * f); 144 | float2 uv = (p.xy + float2(37.0,17.0) * p.z) + f.xy; 145 | float2 rg = _Noise.SampleLevel(sampler_Noise, (uv + 0.5) / 256.0, 0).yx; 146 | return -1.0 + 2.0 * lerp(rg.x, rg.y, f.z); 147 | } 148 | 149 | float ScrollNoise(float3 pos, float speed, float scale, float3 dir, float amount, float bias = 0.0, float mult = 1.0) 150 | { 151 | float time = _Time * speed; 152 | float noiseScale = scale; 153 | float3 noiseScroll = dir * time; 154 | float3 q = pos - noiseScroll; 155 | q *= scale; 156 | float f = 0; 157 | f = 0.5 * noisep(q); 158 | // scroll the next octave in the opposite direction to get some morphing instead of just scrolling 159 | q += noiseScroll * scale; 160 | q = q * 2.01; 161 | f += 0.25 * noisep(q); 162 | 163 | f += bias; 164 | f *= mult; 165 | 166 | f = max(f, 0.0); 167 | return lerp(1.0, f, amount); 168 | } 169 | 170 | #ifdef FOG_ELLIPSOIDS 171 | void FogEllipsoids(float3 pos, inout float density) 172 | { 173 | for (int i = 0; i < _FogEllipsoidsCount; i++) 174 | { 175 | float3 dir = _FogEllipsoids[i].pos - pos; 176 | float3 axis = _FogEllipsoids[i].axis; 177 | float3 dirAlongAxis = dot(dir, axis) * axis; 178 | 179 | float scrollNoise = ScrollNoise(dir, _FogEllipsoids[i].noiseSpeed, _FogEllipsoids[i].noiseScale, axis, _FogEllipsoids[i].noiseAmount); 180 | 181 | dir = dir + dirAlongAxis * _FogEllipsoids[i].stretch; 182 | float distsq = dot(dir, dir); 183 | float radius = _FogEllipsoids[i].radius; 184 | float feather = _FogEllipsoids[i].feather; 185 | // float feather = 0.3; 186 | feather = (1.0 - smoothstep (radius * feather, radius, distsq)); 187 | 188 | float contribution = scrollNoise * feather * _FogEllipsoids[i].density; 189 | density = lerp(density + contribution, density * contribution, _FogEllipsoids[i].blend); 190 | } 191 | } 192 | #endif 193 | 194 | #ifdef FOG_BOMB 195 | float Pulse(float c, float w, float x) 196 | { 197 | return smoothstep(c - w, c, x) - smoothstep(c, c + w, x); 198 | } 199 | #endif 200 | 201 | float Density(float3 pos) 202 | { 203 | float fog = _FogParams.x; 204 | 205 | fog += max(exp(_FogParams.y*(-pos.y + _FogParams.z)) * _FogParams.w, 0.0); 206 | 207 | float3 warp = pos; 208 | 209 | #ifdef FOG_BOMB 210 | if (_FogBombRadius > 0) 211 | { 212 | float3 posToBomb = _FogBombPos - pos; 213 | float distToBomb = length(posToBomb); 214 | fog *= smoothstep (_FogBombRadius * 0.9, _FogBombRadius * 1.1, distToBomb); 215 | fog *= 1.0 + 0.5 * Pulse(_FogBombRadius * 1.35, 0.7, distToBomb); 216 | warp += (1 - smoothstep(_FogBombRadius, _FogBombRadius * 1.4, distToBomb)) * posToBomb * 0.3; 217 | } 218 | #endif 219 | 220 | fog *= ScrollNoise(warp, _WindSpeed, _NoiseFogScale, _WindDir, _NoiseFogAmount, -0.3, 8.0); 221 | 222 | #ifdef FOG_ELLIPSOIDS 223 | FogEllipsoids(pos, fog); 224 | #endif 225 | 226 | return max(fog * _Density, 0.0); 227 | } 228 | 229 | float3 FrustumRay(float2 uv, float4 frustumRays[4]) 230 | { 231 | float3 ray0 = lerp(frustumRays[0].xyz, frustumRays[1].xyz, uv.x); 232 | float3 ray1 = lerp(frustumRays[3].xyz, frustumRays[2].xyz, uv.x); 233 | return lerp(ray0, ray1, uv.y); 234 | } 235 | 236 | #ifdef ANISOTROPY 237 | float anisotropy(float costheta) 238 | { 239 | float g = _Anisotropy; 240 | float gsq = g*g; 241 | float denom = 1 + gsq - 2.0 * g * costheta; 242 | denom = denom * denom * denom; 243 | denom = sqrt(max(0, denom)); 244 | return (1 - gsq) / denom; 245 | } 246 | #endif 247 | 248 | #if AREA_LIGHTS || DIR_LIGHT_SHADOWS 249 | #define VSM 1 250 | #if VSM 251 | float ChebyshevUpperBound(float2 moments, float mean) 252 | { 253 | // Compute variance 254 | float variance = moments.y - (moments.x * moments.x); 255 | float _VSMBias = 0.001f; 256 | variance = max(variance, _VSMBias * mean * mean); 257 | 258 | // Compute probabilistic upper bound 259 | float d = mean - moments.x; 260 | float pMax = variance / (variance + (d * d)); 261 | 262 | // One-tailed Chebyshev 263 | return (mean <= moments.x ? 1.0f : pMax); 264 | } 265 | #endif 266 | #endif 267 | 268 | #if DIR_LIGHT 269 | #if DIR_LIGHT_SHADOWS 270 | float4 getCascadeWeights_splitSpheres(float3 pos) 271 | { 272 | float3 fromCenter0 = pos - _ShadowParams[0].shadowSplitSpheres[0].xyz; 273 | float3 fromCenter1 = pos - _ShadowParams[0].shadowSplitSpheres[1].xyz; 274 | float3 fromCenter2 = pos - _ShadowParams[0].shadowSplitSpheres[2].xyz; 275 | float3 fromCenter3 = pos - _ShadowParams[0].shadowSplitSpheres[3].xyz; 276 | float4 distances2 = float4(dot(fromCenter0,fromCenter0), dot(fromCenter1,fromCenter1), dot(fromCenter2,fromCenter2), dot(fromCenter3,fromCenter3)); 277 | float4 weights = float4(distances2 >= _ShadowParams[0].shadowSplitSqRadii); 278 | return weights; 279 | } 280 | 281 | float4 getShadowCoord(float3 pos, float4 cascadeWeights) 282 | { 283 | return mul(_ShadowParams[0].worldToShadow[(int)dot(cascadeWeights, float4(1,1,1,1))], float4(pos, 1)); 284 | } 285 | #endif 286 | 287 | float3 DirectionalLight(float3 pos) 288 | { 289 | if (!any(_DirLightColor)) 290 | return 0; 291 | 292 | float att = 1; 293 | 294 | #if DIR_LIGHT_SHADOWS 295 | if (_DirLightShadows > 0.0) 296 | { 297 | float4 cascadeWeights = getCascadeWeights_splitSpheres(pos); 298 | //bool inside = dot(cascadeWeights, float4(1,1,1,1)) < 4; 299 | float3 samplePos = getShadowCoord(pos, cascadeWeights).xyz; 300 | //occlusion += inside ? UNITY_SAMPLE_SHADOW(u_CascadedShadowMap, samplePos) : 1.f; 301 | #if 1 302 | att *= _DirectionalShadowmap.SampleLevel(sampler_DirectionalShadowmap, samplePos.xy, 0).r > samplePos.z; 303 | #else 304 | float2 shadowmap = _DirectionalShadowmap.SampleLevel(sampler_DirectionalShadowmap, samplePos, 0).xy; 305 | att *= ChebyshevUpperBound(shadowmap.xy, samplePos.z); 306 | 307 | // float depth = exp(-40.0 * samplePos.z); 308 | // att = saturate(shadowmap.r * depth); 309 | #endif 310 | } 311 | #endif 312 | 313 | #if ANISOTROPY 314 | float3 posToCamera = normalize(_CameraPos.xyz - pos); 315 | float costheta = dot(posToCamera, _DirLightDir); 316 | att *= anisotropy(costheta); 317 | #endif 318 | 319 | return _DirLightColor * att; 320 | } 321 | #endif 322 | 323 | #ifdef POINT_LIGHTS 324 | float3 PointLights(float3 pos) 325 | { 326 | float3 color = 0; 327 | for (int i = 0; i < _PointLightsCount; i++) 328 | { 329 | float3 posToLight = _PointLights[i].pos - pos; 330 | float distNorm = dot(posToLight, posToLight) * _PointLights[i].range; 331 | float att = Attenuation(distNorm); 332 | 333 | #if ANISOTROPY 334 | float3 cameraToPos = normalize(pos - _CameraPos.xyz); 335 | float costheta = dot(cameraToPos, normalize(posToLight)); 336 | att *= anisotropy(costheta); 337 | #endif 338 | 339 | color += _PointLights[i].color * att; 340 | } 341 | return color; 342 | } 343 | #endif 344 | 345 | #ifdef TUBE_LIGHTS 346 | float almostIdentity(float x, float m, float n) 347 | { 348 | if (x > m) 349 | return x; 350 | 351 | float a = 2.0f*n - m; 352 | float b = 2.0f*m - 3.0f*n; 353 | float t = x/m; 354 | 355 | return (a*t + b)*t*t + n; 356 | } 357 | 358 | float3 TubeLights(float3 pos) 359 | { 360 | float3 color = 0; 361 | for (int i = 0; i < _TubeLightsCount; i++) 362 | { 363 | float3 L0 = _TubeLights[i].start - pos; 364 | float3 L1 = _TubeLights[i].end - pos; 365 | float distNorm = 0.5f * (length(L0) * length(L1) + dot(L0, L1)) * _TubeLights[i].range; 366 | float att = Attenuation(distNorm); 367 | 368 | #if ANISOTROPY 369 | // Just like when calculating specular for area lights: 370 | // assume forward scattering lobe -> the point on the light that's the closest to 371 | // the view direction is representative 372 | float3 posToCamera = normalize(pos - _CameraPos.xyz); 373 | float3 r = -posToCamera; 374 | float3 Ld = L1 - L0; 375 | float L0oL0 = dot(L0, L0); 376 | float RoL0 = dot(r, L0); 377 | float RoLd = dot(r, Ld); 378 | float L0oLd = dot(L0, Ld); 379 | float LdoLd = dot(Ld, Ld); 380 | float distLd = sqrt(LdoLd); 381 | 382 | #if 1 383 | // Smallest angle to ray 384 | float t = (L0oLd * RoL0 - L0oL0 * RoLd) / (L0oLd * RoLd - LdoLd * RoL0); 385 | t = saturate(t); 386 | 387 | // As r becomes parallel to Ld and then points away, t flips from 0 to 1 (or vv) and a discontinuity shows up. 388 | // Counteract by detecting that relative angle/position and flip t. The discontinuity in t moves to the back side. 389 | float3 L0xLd = cross(L0, Ld); 390 | float3 LdxR = cross(Ld, r); 391 | float RAtLd = dot(L0xLd, LdxR); 392 | 393 | // RAtLd is negative if R points away from Ld. 394 | // TODO: check if lerp below is indeed cheaper. 395 | // if (RAtLd < 0) 396 | // t = 1 - t; 397 | t = lerp(1 - t, t, step(0, RAtLd)); 398 | 399 | #else 400 | // Original by Karis 401 | // Closest distance to ray 402 | float t = (RoL0 * RoLd - L0oLd) / (distLd * distLd - RoLd * RoLd); 403 | t = saturate(t); 404 | 405 | #endif 406 | float3 closestPoint = L0 + Ld * t; 407 | float3 centerToRay = dot(closestPoint, r) * r - closestPoint; 408 | // closestPoint = closestPoint + centerToRay * saturate(_TubeLights[i].radius / length(centerToRay)); 409 | float centerToRayNorm = length(centerToRay) / _TubeLights[i].radius; 410 | // The last param should in theory be 1 411 | centerToRayNorm = almostIdentity(centerToRayNorm, 2, 1.2); 412 | closestPoint = closestPoint + centerToRay / centerToRayNorm; 413 | 414 | // Attenuation from the closest point looks really good if there's anisotropy, but breaks 415 | // for (close to) isotropic medium. Probably because there's no forward lobe anymore, so 416 | // the closest point to the view direction is not representative? But artifacts look like 417 | // smth else is going on too. 418 | // att = Attenuation(dot(closestPoint, closestPoint) * _TubeLights[i].range); 419 | 420 | float costheta = dot(posToCamera, normalize(closestPoint)); 421 | att *= anisotropy(costheta); 422 | #endif 423 | 424 | #ifdef TUBE_LIGHT_SHADOW_PLANES 425 | att *= ShadowPlanes(pos, _TubeLightShadowPlanes[i]); 426 | #endif 427 | 428 | // GDC hack 429 | att = isnan(att) || isinf(att) ? 0 : att; 430 | 431 | color += _TubeLights[i].color * att; 432 | } 433 | return color; 434 | } 435 | #endif 436 | 437 | #ifdef AREA_LIGHTS 438 | float3 AreaLights(float3 pos) 439 | { 440 | float3 color = 0; 441 | uint count = _AreaLightsCount; 442 | uint shadowedAreaLightIndex = _ShadowedAreaLightIndex; 443 | for (uint i = 0; i < count; i++) 444 | { 445 | float4 pClip = mul(_AreaLights[i].mat, float4(pos, 1)); 446 | float3 p = float3(pClip.x / pClip.w, pClip.y / pClip.w, pClip.z); 447 | float z = p.z * 0.5 + 0.5; 448 | 449 | float att = 1; 450 | 451 | if (_AreaLights[i].bounded) 452 | { 453 | att *= saturate(AttenuationToZero(z * z)); 454 | 455 | // Magic tweaks to the shape 456 | float corner = 0.4; 457 | float outset = 0.8; 458 | float smooth = 0.7; 459 | 460 | float d = length(max(abs(p.xy) - 1 + corner*outset, 0.0)) - corner; 461 | att *= saturate(1 - smoothstep(-smooth, 0, d)); 462 | att *= smoothstep(-0.01, 0.01, z); 463 | } 464 | 465 | #if ANISOTROPY 466 | float3 cameraToPos = normalize(pos - _CameraPos.xyz); 467 | float4 lightPos = _AreaLights[i].pos; 468 | float3 posToLight = lerp(lightPos.xyz, lightPos.xyz - pos, lightPos.w); 469 | float costheta = dot(cameraToPos, normalize(posToLight)); 470 | att *= anisotropy(costheta); 471 | #endif 472 | 473 | if (i == shadowedAreaLightIndex && all(abs(p) < 1)) 474 | { 475 | #if VSM 476 | float2 shadowmap = _AreaLightShadowmap.SampleLevel(sampler_AreaLightShadowmap, p.xy * 0.5 + 0.5, 0).xy; 477 | att *= ChebyshevUpperBound(shadowmap.xy, z); 478 | #else 479 | float shadowmap = _AreaLightShadowmap.SampleLevel(sampler_AreaLightShadowmap, p.xy * 0.5 + 0.5, 0); 480 | float depth = exp(-_ESMExponentAreaLight * z); 481 | att *= saturate(shadowmap * depth); 482 | #endif 483 | } 484 | 485 | color += _AreaLights[i].color * att; 486 | } 487 | return color; 488 | } 489 | #endif 490 | 491 | 492 | [numthreads(16,2,16)] 493 | void CSMain (uint3 id : SV_DispatchThreadID) 494 | { 495 | float3 color = _AmbientLight; 496 | float2 uv = float2(id.x/159.0, id.y/89.0); 497 | float z = id.z/127.0; 498 | z = _NearOverFarClip + z * (1 - _NearOverFarClip); 499 | float3 pos = FrustumRay(uv, _FrustumRays) * z + _CameraPos.xyz; 500 | 501 | 502 | // Directional light 503 | #ifdef DIR_LIGHT 504 | color += DirectionalLight(pos); 505 | #endif 506 | 507 | 508 | // Point lights 509 | #ifdef POINT_LIGHTS 510 | color += PointLights(pos); 511 | #endif 512 | 513 | 514 | // Tube lights 515 | #ifdef TUBE_LIGHTS 516 | color += TubeLights(pos); 517 | #endif 518 | 519 | 520 | // Area lights 521 | #ifdef AREA_LIGHTS 522 | color += AreaLights(pos); 523 | #endif 524 | 525 | 526 | // Density 527 | float density = Density(pos); 528 | 529 | 530 | // Output 531 | float4 output; 532 | output.rgb = _Intensity * density * color; 533 | output.a = density; 534 | _VolumeInject[id] = output; 535 | } 536 | 537 | --------------------------------------------------------------------------------