mirror of
https://github.com/maxartz15/VolumetricLighting.git
synced 2025-06-14 15:46:14 +02:00
Added the project.
This commit is contained in:
59
Assets/VolumetricFog/Scripts/FogEllipsoid.cs
Normal file
59
Assets/VolumetricFog/Scripts/FogEllipsoid.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using UnityEngine;
|
||||
|
||||
[ExecuteInEditMode]
|
||||
public class FogEllipsoid : MonoBehaviour
|
||||
{
|
||||
public enum Blend
|
||||
{
|
||||
Additive,
|
||||
Multiplicative
|
||||
}
|
||||
|
||||
public Blend m_Blend = Blend.Additive;
|
||||
public float m_Density = 1.0f;
|
||||
[MinValue(0)]
|
||||
public float m_Radius = 1.0f;
|
||||
[MinValue(0)]
|
||||
public float m_Stretch = 2.0f;
|
||||
[Range(0, 1)]
|
||||
public float m_Feather = 0.7f;
|
||||
[Range(0, 1)]
|
||||
public float m_NoiseAmount = 0.0f;
|
||||
public float m_NoiseSpeed = 1.0f;
|
||||
[MinValue(0)]
|
||||
public float m_NoiseScale = 1.0f;
|
||||
|
||||
bool m_AddedToLightManager = false;
|
||||
|
||||
void AddToLightManager()
|
||||
{
|
||||
if (!m_AddedToLightManager)
|
||||
m_AddedToLightManager = LightManagerFogEllipsoids.Add(this);
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
AddToLightManager();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// LightManager might not have been available during this light's OnEnable(), so keep trying.
|
||||
AddToLightManager();
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
LightManagerFogEllipsoids.Remove(this);
|
||||
m_AddedToLightManager = false;
|
||||
}
|
||||
|
||||
void OnDrawGizmosSelected()
|
||||
{
|
||||
Matrix4x4 m = Matrix4x4.identity;
|
||||
Transform t = transform;
|
||||
m.SetTRS(t.position, t.rotation, new Vector3(1.0f, m_Stretch, 1.0f));
|
||||
Gizmos.matrix = m;
|
||||
Gizmos.DrawWireSphere(Vector3.zero, m_Radius);
|
||||
}
|
||||
}
|
12
Assets/VolumetricFog/Scripts/FogEllipsoid.cs.meta
Normal file
12
Assets/VolumetricFog/Scripts/FogEllipsoid.cs.meta
Normal file
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 789ae5fef74e6754ab3c20bdeca67ad9
|
||||
timeCreated: 1447327681
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
157
Assets/VolumetricFog/Scripts/FogLight.DirectionalShadow.cs
Normal file
157
Assets/VolumetricFog/Scripts/FogLight.DirectionalShadow.cs
Normal file
@ -0,0 +1,157 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
public partial class FogLight : LightOverride
|
||||
{
|
||||
CommandBuffer m_BufGrabShadowmap;
|
||||
CommandBuffer m_BufGrabShadowParams;
|
||||
RenderTexture m_Shadowmap;
|
||||
|
||||
ComputeBuffer m_ShadowParamsCB;
|
||||
//[HideInInspector]
|
||||
public Shader m_BlurShadowmapShader;
|
||||
Material m_BlurShadowmapMaterial;
|
||||
|
||||
public Shader m_CopyShadowParamsShader;
|
||||
Material m_CopyShadowParamsMaterial;
|
||||
|
||||
bool directionalShadow {get{ return m_Shadows && type == Type.Directional; }}
|
||||
|
||||
void InitDirectionalShadowmap()
|
||||
{
|
||||
if (m_BufGrabShadowmap != null || !directionalShadow)
|
||||
return;
|
||||
|
||||
Light light = GetComponent<Light>();
|
||||
|
||||
m_BufGrabShadowmap = new CommandBuffer();
|
||||
m_BufGrabShadowmap.name = "Grab shadowmap for Volumetric Fog";
|
||||
light.AddCommandBuffer(LightEvent.AfterShadowMap, m_BufGrabShadowmap);
|
||||
|
||||
m_BufGrabShadowParams = new CommandBuffer();
|
||||
m_BufGrabShadowParams.name = "Grab shadow params for Volumetric Fog";
|
||||
light.AddCommandBuffer(LightEvent.BeforeScreenspaceMask, m_BufGrabShadowParams);
|
||||
|
||||
m_BlurShadowmapMaterial = new Material(m_BlurShadowmapShader);
|
||||
m_BlurShadowmapMaterial.hideFlags = HideFlags.HideAndDontSave;
|
||||
|
||||
m_CopyShadowParamsMaterial = new Material(m_CopyShadowParamsShader);
|
||||
m_CopyShadowParamsMaterial.hideFlags = HideFlags.HideAndDontSave;
|
||||
}
|
||||
|
||||
int[] temp;
|
||||
|
||||
public void UpdateDirectionalShadowmap()
|
||||
{
|
||||
InitDirectionalShadowmap();
|
||||
|
||||
if (m_BufGrabShadowmap != null)
|
||||
m_BufGrabShadowmap.Clear();
|
||||
if (m_BufGrabShadowParams != null)
|
||||
m_BufGrabShadowParams.Clear();
|
||||
|
||||
if (!directionalShadow)
|
||||
return;
|
||||
|
||||
// Copy directional shadowmap params - they're only set for regular shaders, but we need them in compute
|
||||
if (m_ShadowParamsCB == null)
|
||||
m_ShadowParamsCB = new ComputeBuffer(1, 336);
|
||||
Graphics.SetRandomWriteTarget(2, m_ShadowParamsCB);
|
||||
m_BufGrabShadowParams.DrawProcedural(Matrix4x4.identity, m_CopyShadowParamsMaterial, 0, MeshTopology.Points, 1);
|
||||
|
||||
// TODO: get the real size of the shadowmap
|
||||
int startRes = 4096;
|
||||
// To make things easier, blurred shadowmap is at most half the size of the regular.
|
||||
int targetRes = Mathf.Min((int)m_ShadowmapRes, startRes/2);
|
||||
int downsampleSteps = (int)Mathf.Log(startRes / targetRes, 2);
|
||||
|
||||
RenderTargetIdentifier shadowmap = BuiltinRenderTextureType.CurrentActive;
|
||||
m_BufGrabShadowmap.SetShadowSamplingMode(shadowmap, ShadowSamplingMode.RawDepth);
|
||||
|
||||
// RFloat for ESM, RGHalf for VSM
|
||||
RenderTextureFormat format = RenderTextureFormat.RGHalf;
|
||||
|
||||
ReleaseTemporary(ref m_Shadowmap);
|
||||
m_Shadowmap = RenderTexture.GetTemporary(targetRes, targetRes, 0, format, RenderTextureReadWrite.Linear);
|
||||
m_Shadowmap.filterMode = FilterMode.Bilinear;
|
||||
m_Shadowmap.wrapMode = TextureWrapMode.Clamp;
|
||||
|
||||
if (temp == null || temp.Length != downsampleSteps - 1)
|
||||
temp = new int[downsampleSteps - 1];
|
||||
|
||||
for (int i = 0, currentRes = startRes/2; i < downsampleSteps; i++)
|
||||
{
|
||||
m_BufGrabShadowmap.SetGlobalVector("_TexelSize", new Vector4(0.5f/currentRes, 0.5f/currentRes, 0, 0));
|
||||
|
||||
RenderTargetIdentifier targetRT;
|
||||
|
||||
if (i < downsampleSteps - 1)
|
||||
{
|
||||
temp[i] = Shader.PropertyToID("ShadowmapDownscaleTemp" + i);
|
||||
m_BufGrabShadowmap.GetTemporaryRT(temp[i], currentRes, currentRes, 0, FilterMode.Bilinear, format, RenderTextureReadWrite.Linear);
|
||||
targetRT = new RenderTargetIdentifier(temp[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Last step: write into the shadowmap texture
|
||||
targetRT = new RenderTargetIdentifier(m_Shadowmap);
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
// This step should convert to ESM/VSM
|
||||
// m_BufGrabShadowmap.Blit(shadowmap, targetRT);
|
||||
m_BufGrabShadowmap.SetGlobalTexture("_DirShadowmap", shadowmap);
|
||||
m_BufGrabShadowmap.Blit(null, targetRT, m_BlurShadowmapMaterial, /*sample & convert to VSM*/ 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_BufGrabShadowmap.Blit(temp[i - 1], targetRT, m_BlurShadowmapMaterial, /*regular sample*/ 5);
|
||||
}
|
||||
|
||||
currentRes /= 2;
|
||||
}
|
||||
|
||||
//var directionalShadowmapBlurred = Shader.PropertyToID("_DirectionalShadowmapBlurred");
|
||||
//m_BufGrabShadowmap.GetTemporaryRT(directionalShadowmapBlurred, 1024, 1024, 0, FilterMode.Bilinear, RenderTextureFormat.RFloat, RenderTextureReadWrite.Linear);
|
||||
//m_BufGrabShadowmap.Blit(shadowmap, m_Shadowmap);
|
||||
//m_BufGrabShadowmap.SetGlobalTexture(directionalShadowmapBlurred, directionalShadowmapBlurred);
|
||||
}
|
||||
|
||||
void CleanupDirectionalShadowmap()
|
||||
{
|
||||
if (m_BufGrabShadowmap != null)
|
||||
m_BufGrabShadowmap.Clear();
|
||||
|
||||
if (m_BufGrabShadowParams != null)
|
||||
m_BufGrabShadowParams.Clear();
|
||||
|
||||
if(m_ShadowParamsCB != null)
|
||||
m_ShadowParamsCB.Release();
|
||||
m_ShadowParamsCB = null;
|
||||
}
|
||||
|
||||
public bool SetUpDirectionalShadowmapForSampling(bool shadows, ComputeShader cs, int kernel)
|
||||
{
|
||||
if (!shadows || m_ShadowParamsCB == null || m_Shadowmap == null)
|
||||
{
|
||||
cs.SetFloat("_DirLightShadows", 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
cs.SetFloat("_DirLightShadows", 1);
|
||||
cs.SetBuffer(kernel, "_ShadowParams", m_ShadowParamsCB);
|
||||
cs.SetTexture(kernel, "_DirectionalShadowmap", m_Shadowmap);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReleaseTemporary(ref RenderTexture rt)
|
||||
{
|
||||
if (rt == null)
|
||||
return;
|
||||
|
||||
RenderTexture.ReleaseTemporary(rt);
|
||||
rt = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f567a9d3b2b31ac4d818cea1e427a215
|
||||
timeCreated: 1460031458
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
60
Assets/VolumetricFog/Scripts/FogLight.cs
Normal file
60
Assets/VolumetricFog/Scripts/FogLight.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using UnityEngine;
|
||||
|
||||
[ExecuteInEditMode]
|
||||
public partial class FogLight : LightOverride
|
||||
{
|
||||
public bool m_ForceOnForFog = false;
|
||||
[Tooltip("Only one shadowed fog AreaLight at a time.")]
|
||||
[Header("Shadows")]
|
||||
public bool m_Shadows = false;
|
||||
|
||||
public enum TextureSize
|
||||
{
|
||||
x256 = 256,
|
||||
x512 = 512,
|
||||
x1024 = 1024,
|
||||
}
|
||||
|
||||
[Tooltip("Always at most half the res of the AreaLight's shadowmap.")]
|
||||
public TextureSize m_ShadowmapRes = TextureSize.x256;
|
||||
[Range(0, 3)]
|
||||
public int m_BlurIterations = 0;
|
||||
[MinValue(0)]
|
||||
public float m_BlurSize = 1.0f;
|
||||
[MinValue(0)]
|
||||
[Tooltip("Affects shadow softness.")]
|
||||
public float m_ESMExponent = 40.0f;
|
||||
|
||||
public bool m_Bounded = true;
|
||||
|
||||
public override bool GetForceOn()
|
||||
{
|
||||
return m_ForceOnForFog;
|
||||
}
|
||||
|
||||
bool m_AddedToLightManager = false;
|
||||
|
||||
void AddToLightManager()
|
||||
{
|
||||
if (!m_AddedToLightManager)
|
||||
m_AddedToLightManager = LightManagerFogLights.Add(this);
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
AddToLightManager();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// LightManager might not have been available during this light's OnEnable(), so keep trying.
|
||||
AddToLightManager();
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
LightManagerFogLights.Remove(this);
|
||||
m_AddedToLightManager = false;
|
||||
CleanupDirectionalShadowmap();
|
||||
}
|
||||
}
|
16
Assets/VolumetricFog/Scripts/FogLight.cs.meta
Normal file
16
Assets/VolumetricFog/Scripts/FogLight.cs.meta
Normal file
@ -0,0 +1,16 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 097385f2a510795498370c4d62e61572
|
||||
timeCreated: 1463313191
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_BlurShadowmapShader: {fileID: 4800000, guid: 701192b62a7678549918bc87434699fe,
|
||||
type: 3}
|
||||
- m_CopyShadowParamsShader: {fileID: 4800000, guid: 33fc45db43408764c8dd7647b877e561,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
719
Assets/VolumetricFog/Scripts/VolumetricFog.cs
Normal file
719
Assets/VolumetricFog/Scripts/VolumetricFog.cs
Normal file
@ -0,0 +1,719 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent (typeof(Camera))]
|
||||
public class VolumetricFog : MonoBehaviour
|
||||
{
|
||||
Material m_DebugMaterial;
|
||||
[HideInInspector]
|
||||
public Shader m_DebugShader;
|
||||
[HideInInspector]
|
||||
public Shader m_ShadowmapShader;
|
||||
[HideInInspector]
|
||||
public ComputeShader m_InjectLightingAndDensity;
|
||||
[HideInInspector]
|
||||
public ComputeShader m_Scatter;
|
||||
Material m_ApplyToOpaqueMaterial;
|
||||
[HideInInspector]
|
||||
public Shader m_ApplyToOpaqueShader;
|
||||
Material m_BlurShadowmapMaterial;
|
||||
[HideInInspector]
|
||||
public Shader m_BlurShadowmapShader;
|
||||
[HideInInspector]
|
||||
public Texture2D m_Noise;
|
||||
[HideInInspector]
|
||||
public bool m_Debug = false;
|
||||
[HideInInspector]
|
||||
[Range(0.0f, 1.0f)]
|
||||
public float m_Z = 1.0f;
|
||||
|
||||
[Header("Size")]
|
||||
[MinValue(0.1f)]
|
||||
public float m_NearClip = 0.1f;
|
||||
[MinValue(0.1f)]
|
||||
public float m_FarClipMax = 100.0f;
|
||||
|
||||
[Header("Fog Density")]
|
||||
[FormerlySerializedAs("m_Density")]
|
||||
public float m_GlobalDensityMult = 1.0f;
|
||||
Vector3i m_InjectNumThreads = new Vector3i(16, 2, 16);
|
||||
Vector3i m_ScatterNumThreads = new Vector3i(32, 2, 1);
|
||||
RenderTexture m_VolumeInject;
|
||||
RenderTexture m_VolumeScatter;
|
||||
Vector3i m_VolumeResolution = new Vector3i(160, 90, 128);
|
||||
Camera m_Camera;
|
||||
Camera m_ShadowmapCamera;
|
||||
RenderTexture m_Shadowmap;
|
||||
RenderTexture m_ShadowmapBlurred;
|
||||
int m_ShadowmapRes = 1024;
|
||||
|
||||
// Density
|
||||
public float m_ConstantFog = 0;
|
||||
public float m_HeightFogAmount = 0;
|
||||
public float m_HeightFogExponent = 0;
|
||||
public float m_HeightFogOffset = 0;
|
||||
|
||||
[Tooltip("Noise multiplies with constant fog and height fog, but not with fog ellipsoids.")]
|
||||
[Range(0.0f, 1.0f)]
|
||||
public float m_NoiseFogAmount = 0;
|
||||
public float m_NoiseFogScale = 1;
|
||||
public Wind m_Wind;
|
||||
|
||||
[Range(0.0f, 0.999f)]
|
||||
public float m_Anisotropy = 0.0f;
|
||||
|
||||
[Header("Lights")]
|
||||
[FormerlySerializedAs("m_Intensity")]
|
||||
public float m_GlobalIntensityMult = 1.0f;
|
||||
[MinValue(0)]
|
||||
public float m_AmbientLightIntensity = 0.0f;
|
||||
public Color m_AmbientLightColor = Color.white;
|
||||
|
||||
[HideInInspector]
|
||||
public bool m_BlurShadowmap = false;
|
||||
[HideInInspector]
|
||||
[Range(0, 2)]
|
||||
public int m_ShadowmapDownsample = 1;
|
||||
[HideInInspector]
|
||||
[Range(0.0f, 10.0f)]
|
||||
public float m_BlurSize = 3.0f;
|
||||
[HideInInspector]
|
||||
[Range(1, 4)]
|
||||
public int m_BlurIterations = 2;
|
||||
|
||||
struct Vector3i
|
||||
{
|
||||
public int x, y, z;
|
||||
public Vector3i(int x, int y, int z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
}
|
||||
|
||||
struct PointLightParams
|
||||
{
|
||||
public Vector3 pos;
|
||||
public float range;
|
||||
public Vector3 color;
|
||||
float padding;
|
||||
}
|
||||
|
||||
PointLightParams[] m_PointLightParams;
|
||||
ComputeBuffer m_PointLightParamsCB;
|
||||
|
||||
struct TubeLightParams
|
||||
{
|
||||
public Vector3 start;
|
||||
public float range;
|
||||
public Vector3 end;
|
||||
public float radius;
|
||||
public Vector3 color;
|
||||
float padding;
|
||||
}
|
||||
|
||||
TubeLightParams[] m_TubeLightParams;
|
||||
ComputeBuffer m_TubeLightParamsCB;
|
||||
|
||||
struct TubeLightShadowPlaneParams
|
||||
{
|
||||
public Vector4 plane0;
|
||||
public Vector4 plane1;
|
||||
public float feather0;
|
||||
public float feather1;
|
||||
float padding0;
|
||||
float padding1;
|
||||
}
|
||||
|
||||
TubeLightShadowPlaneParams[] m_TubeLightShadowPlaneParams;
|
||||
ComputeBuffer m_TubeLightShadowPlaneParamsCB;
|
||||
|
||||
struct AreaLightParams
|
||||
{
|
||||
public Matrix4x4 mat;
|
||||
public Vector4 pos;
|
||||
public Vector3 color;
|
||||
public float bounded;
|
||||
}
|
||||
|
||||
AreaLightParams[] m_AreaLightParams;
|
||||
ComputeBuffer m_AreaLightParamsCB;
|
||||
|
||||
struct FogEllipsoidParams
|
||||
{
|
||||
public Vector3 pos;
|
||||
public float radius;
|
||||
public Vector3 axis;
|
||||
public float stretch;
|
||||
public float density;
|
||||
public float noiseAmount;
|
||||
public float noiseSpeed;
|
||||
public float noiseScale;
|
||||
public float feather;
|
||||
public float blend;
|
||||
public float padding1;
|
||||
public float padding2;
|
||||
}
|
||||
|
||||
FogEllipsoidParams[] m_FogEllipsoidParams;
|
||||
ComputeBuffer m_FogEllipsoidParamsCB;
|
||||
|
||||
Camera cam{ get { if (m_Camera == null) m_Camera = GetComponent<Camera>(); return m_Camera; }}
|
||||
|
||||
float nearClip { get { return Mathf.Max(0, m_NearClip); } }
|
||||
float farClip { get { return Mathf.Min(cam.farClipPlane, m_FarClipMax); } }
|
||||
|
||||
void ReleaseComputeBuffer(ref ComputeBuffer buffer)
|
||||
{
|
||||
if(buffer != null)
|
||||
buffer.Release();
|
||||
buffer = null;
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
DestroyImmediate(m_VolumeInject);
|
||||
DestroyImmediate(m_VolumeScatter);
|
||||
ReleaseComputeBuffer(ref m_PointLightParamsCB);
|
||||
ReleaseComputeBuffer(ref m_TubeLightParamsCB);
|
||||
ReleaseComputeBuffer(ref m_TubeLightShadowPlaneParamsCB);
|
||||
ReleaseComputeBuffer(ref m_AreaLightParamsCB);
|
||||
ReleaseComputeBuffer(ref m_FogEllipsoidParamsCB);
|
||||
m_VolumeInject = null;
|
||||
m_VolumeScatter = null;
|
||||
}
|
||||
|
||||
void SanitizeInput()
|
||||
{
|
||||
m_GlobalDensityMult = Mathf.Max(m_GlobalDensityMult, 0);
|
||||
m_ConstantFog = Mathf.Max(m_ConstantFog, 0);
|
||||
m_HeightFogAmount = Mathf.Max(m_HeightFogAmount, 0);
|
||||
}
|
||||
|
||||
void SetUpPointLightBuffers(int kernel)
|
||||
{
|
||||
int count = m_PointLightParamsCB == null ? 0 : m_PointLightParamsCB.count;
|
||||
m_InjectLightingAndDensity.SetFloat("_PointLightsCount", count);
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
if (m_PointLightParams == null || m_PointLightParams.Length != count)
|
||||
m_PointLightParams = new PointLightParams[count];
|
||||
|
||||
HashSet<FogLight> fogLights = LightManagerFogLights.Get();
|
||||
|
||||
int j = 0;
|
||||
for (var x = fogLights.GetEnumerator(); x.MoveNext();)
|
||||
{
|
||||
var fl = x.Current;
|
||||
if (fl == null || fl.type != FogLight.Type.Point || !fl.isOn)
|
||||
continue;
|
||||
|
||||
Light light = fl.light;
|
||||
m_PointLightParams[j].pos = light.transform.position;
|
||||
float range = light.range * fl.m_RangeMult;
|
||||
m_PointLightParams[j].range = 1.0f / (range * range);
|
||||
m_PointLightParams[j].color = new Vector3(light.color.r, light.color.g, light.color.b) * light.intensity * fl.m_IntensityMult;
|
||||
j++;
|
||||
}
|
||||
|
||||
// TODO: try a constant buffer with setfloats instead for perf
|
||||
m_PointLightParamsCB.SetData(m_PointLightParams);
|
||||
m_InjectLightingAndDensity.SetBuffer(kernel, "_PointLights", m_PointLightParamsCB);
|
||||
}
|
||||
|
||||
TubeLightShadowPlane.Params[] sppArr;
|
||||
|
||||
void SetUpTubeLightBuffers(int kernel)
|
||||
{
|
||||
int count = m_TubeLightParamsCB == null ? 0 : m_TubeLightParamsCB.count;
|
||||
m_InjectLightingAndDensity.SetFloat("_TubeLightsCount", count);
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
if (m_TubeLightParams == null || m_TubeLightParams.Length != count)
|
||||
m_TubeLightParams = new TubeLightParams[count];
|
||||
|
||||
if (m_TubeLightShadowPlaneParams == null || m_TubeLightShadowPlaneParams.Length != count)
|
||||
m_TubeLightShadowPlaneParams = new TubeLightShadowPlaneParams[count];
|
||||
|
||||
HashSet<FogLight> fogLights = LightManagerFogLights.Get();
|
||||
|
||||
int j = 0;
|
||||
for (var x = fogLights.GetEnumerator(); x.MoveNext();)
|
||||
{
|
||||
var fl = x.Current;
|
||||
if (fl == null || fl.type != FogLight.Type.Tube || !fl.isOn)
|
||||
continue;
|
||||
|
||||
TubeLight light = fl.tubeLight;
|
||||
Transform t = light.transform;
|
||||
Vector3 pos = t.position;
|
||||
Vector3 halfLength = 0.5f * t.up * light.m_Length;
|
||||
|
||||
// Tube lights
|
||||
m_TubeLightParams[j].start = pos + halfLength;
|
||||
m_TubeLightParams[j].end = pos - halfLength;
|
||||
float range = light.m_Range * fl.m_RangeMult;
|
||||
m_TubeLightParams[j].range = 1.0f / (range * range);
|
||||
m_TubeLightParams[j].color = new Vector3(light.m_Color.r, light.m_Color.g, light.m_Color.b) * light.m_Intensity * fl.m_IntensityMult;
|
||||
m_TubeLightParams[j].radius = light.m_Radius;
|
||||
|
||||
// Tube light shadow planes
|
||||
var p = light.GetShadowPlaneParams(ref sppArr);
|
||||
m_TubeLightShadowPlaneParams[j].plane0 = p[0].plane;
|
||||
m_TubeLightShadowPlaneParams[j].plane1 = p[1].plane;
|
||||
m_TubeLightShadowPlaneParams[j].feather0 = p[0].feather;
|
||||
m_TubeLightShadowPlaneParams[j].feather1 = p[1].feather;
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
m_TubeLightParamsCB.SetData(m_TubeLightParams);
|
||||
m_InjectLightingAndDensity.SetBuffer(kernel, "_TubeLights", m_TubeLightParamsCB);
|
||||
m_TubeLightShadowPlaneParamsCB.SetData(m_TubeLightShadowPlaneParams);
|
||||
m_InjectLightingAndDensity.SetBuffer(kernel, "_TubeLightShadowPlanes", m_TubeLightShadowPlaneParamsCB);
|
||||
}
|
||||
|
||||
void SetUpAreaLightBuffers(int kernel)
|
||||
{
|
||||
int count = m_AreaLightParamsCB == null ? 0 : m_AreaLightParamsCB.count;
|
||||
m_InjectLightingAndDensity.SetFloat("_AreaLightsCount", count);
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
if (m_AreaLightParams == null || m_AreaLightParams.Length != count)
|
||||
m_AreaLightParams = new AreaLightParams[count];
|
||||
|
||||
HashSet<FogLight> fogLights = LightManagerFogLights.Get();
|
||||
|
||||
int shadowedAreaLightIndex = fogLights.Count;
|
||||
int j = 0;
|
||||
for (var x = fogLights.GetEnumerator(); x.MoveNext();)
|
||||
{
|
||||
var fl = x.Current;
|
||||
if (fl == null || fl.type != FogLight.Type.Area || !fl.isOn)
|
||||
continue;
|
||||
|
||||
AreaLight light = fl.areaLight;
|
||||
|
||||
m_AreaLightParams[j].mat = light.GetProjectionMatrix(true);
|
||||
m_AreaLightParams[j].pos = light.GetPosition();
|
||||
m_AreaLightParams[j].color = new Vector3(light.m_Color.r, light.m_Color.g, light.m_Color.b) * light.m_Intensity * fl.m_IntensityMult;
|
||||
m_AreaLightParams[j].bounded = fl.m_Bounded ? 1 : 0;
|
||||
|
||||
if (fl.m_Shadows)
|
||||
{
|
||||
RenderTexture shadowmap = light.GetBlurredShadowmap();
|
||||
if (shadowmap != null)
|
||||
{
|
||||
m_InjectLightingAndDensity.SetTexture(kernel, "_AreaLightShadowmap", shadowmap);
|
||||
m_InjectLightingAndDensity.SetFloat("_ESMExponentAreaLight", fl.m_ESMExponent);
|
||||
shadowedAreaLightIndex = j;
|
||||
}
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
m_AreaLightParamsCB.SetData(m_AreaLightParams);
|
||||
m_InjectLightingAndDensity.SetBuffer(kernel, "_AreaLights", m_AreaLightParamsCB);
|
||||
m_InjectLightingAndDensity.SetFloat("_ShadowedAreaLightIndex", shadowedAreaLightIndex);
|
||||
}
|
||||
|
||||
void SetUpFogEllipsoidBuffers(int kernel)
|
||||
{
|
||||
int count = 0;
|
||||
HashSet<FogEllipsoid> fogEllipsoids = LightManagerFogEllipsoids.Get();
|
||||
for (var x = fogEllipsoids.GetEnumerator(); x.MoveNext();) {
|
||||
var fe = x.Current;
|
||||
if (fe != null && fe.enabled && fe.gameObject.activeSelf)
|
||||
count++;
|
||||
}
|
||||
|
||||
m_InjectLightingAndDensity.SetFloat("_FogEllipsoidsCount", count);
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
if (m_FogEllipsoidParams == null || m_FogEllipsoidParams.Length != count)
|
||||
m_FogEllipsoidParams = new FogEllipsoidParams[count];
|
||||
|
||||
int j = 0;
|
||||
for (var x = fogEllipsoids.GetEnumerator(); x.MoveNext();)
|
||||
{
|
||||
var fe = x.Current;
|
||||
if (fe == null || !fe.enabled || !fe.gameObject.activeSelf)
|
||||
continue;
|
||||
|
||||
Transform t = fe.transform;
|
||||
|
||||
m_FogEllipsoidParams[j].pos = t.position;
|
||||
m_FogEllipsoidParams[j].radius = fe.m_Radius * fe.m_Radius;
|
||||
m_FogEllipsoidParams[j].axis = -t.up;
|
||||
m_FogEllipsoidParams[j].stretch = 1.0f/fe.m_Stretch - 1.0f;
|
||||
m_FogEllipsoidParams[j].density = fe.m_Density;
|
||||
m_FogEllipsoidParams[j].noiseAmount = fe.m_NoiseAmount;
|
||||
m_FogEllipsoidParams[j].noiseSpeed = fe.m_NoiseSpeed;
|
||||
m_FogEllipsoidParams[j].noiseScale = fe.m_NoiseScale;
|
||||
m_FogEllipsoidParams[j].feather = 1.0f - fe.m_Feather;
|
||||
m_FogEllipsoidParams[j].blend = fe.m_Blend == FogEllipsoid.Blend.Additive ? 0 : 1;
|
||||
j++;
|
||||
}
|
||||
|
||||
m_FogEllipsoidParamsCB.SetData(m_FogEllipsoidParams);
|
||||
m_InjectLightingAndDensity.SetBuffer(kernel, "_FogEllipsoids", m_FogEllipsoidParamsCB);
|
||||
}
|
||||
|
||||
FogLight GetDirectionalLight()
|
||||
{
|
||||
HashSet<FogLight> fogLights = LightManagerFogLights.Get();
|
||||
FogLight fogLight = null;
|
||||
|
||||
for (var x = fogLights.GetEnumerator(); x.MoveNext();)
|
||||
{
|
||||
var fl = x.Current;
|
||||
if (fl == null || fl.type != FogLight.Type.Directional || !fl.isOn)
|
||||
continue;
|
||||
|
||||
fogLight = fl;
|
||||
break;
|
||||
}
|
||||
|
||||
return fogLight;
|
||||
}
|
||||
|
||||
FogLight m_DirectionalLight;
|
||||
|
||||
void OnPreRender()
|
||||
{
|
||||
m_DirectionalLight = GetDirectionalLight();
|
||||
|
||||
if (m_DirectionalLight != null)
|
||||
m_DirectionalLight.UpdateDirectionalShadowmap();
|
||||
}
|
||||
|
||||
float[] m_dirLightColor;
|
||||
float[] m_dirLightDir;
|
||||
|
||||
void SetUpDirectionalLight(int kernel)
|
||||
{
|
||||
if (m_dirLightColor == null || m_dirLightColor.Length != 3)
|
||||
m_dirLightColor = new float[3];
|
||||
if (m_dirLightDir == null || m_dirLightDir.Length != 3)
|
||||
m_dirLightDir = new float[3];
|
||||
|
||||
if (m_DirectionalLight == null)
|
||||
{
|
||||
m_dirLightColor[0] = 0;
|
||||
m_dirLightColor[1] = 0;
|
||||
m_dirLightColor[2] = 0;
|
||||
m_InjectLightingAndDensity.SetFloats("_DirLightColor", m_dirLightColor);
|
||||
return;
|
||||
}
|
||||
|
||||
m_DirectionalLight.SetUpDirectionalShadowmapForSampling(m_DirectionalLight.m_Shadows, m_InjectLightingAndDensity, kernel);
|
||||
// TODO: if above fails, disable shadows
|
||||
|
||||
Light light = m_DirectionalLight.light;
|
||||
Vector4 color = light.color;
|
||||
color *= light.intensity * m_DirectionalLight.m_IntensityMult;
|
||||
m_dirLightColor[0] = color.x;
|
||||
m_dirLightColor[1] = color.y;
|
||||
m_dirLightColor[2] = color.z;
|
||||
m_InjectLightingAndDensity.SetFloats("_DirLightColor", m_dirLightColor);
|
||||
Vector3 dir = light.GetComponent<Transform>().forward;
|
||||
m_dirLightDir[0] = dir.x;
|
||||
m_dirLightDir[1] = dir.y;
|
||||
m_dirLightDir[2] = dir.z;
|
||||
m_InjectLightingAndDensity.SetFloats("_DirLightDir", m_dirLightDir);
|
||||
|
||||
}
|
||||
|
||||
float[] m_fogParams;
|
||||
float[] m_windDir;
|
||||
float[] m_ambientLight;
|
||||
|
||||
void SetUpForScatter(int kernel)
|
||||
{
|
||||
SanitizeInput();
|
||||
InitResources();
|
||||
SetFrustumRays();
|
||||
|
||||
// Compensate for more light and density being injected in per world space meter when near and far are closer.
|
||||
// TODO: Not quite correct yet.
|
||||
float depthCompensation = (farClip - nearClip) * 0.01f;
|
||||
m_InjectLightingAndDensity.SetFloat("_Density", m_GlobalDensityMult * 0.001f * depthCompensation);
|
||||
m_InjectLightingAndDensity.SetFloat("_Intensity", m_GlobalIntensityMult);
|
||||
m_InjectLightingAndDensity.SetFloat("_Anisotropy", m_Anisotropy);
|
||||
m_InjectLightingAndDensity.SetTexture(kernel, "_VolumeInject", m_VolumeInject);
|
||||
m_InjectLightingAndDensity.SetTexture(kernel, "_Shadowmap", m_BlurShadowmap ? m_ShadowmapBlurred : (m_Shadowmap != null ? m_Shadowmap : (Texture)Texture2D.whiteTexture));
|
||||
m_InjectLightingAndDensity.SetTexture(kernel, "_Noise", m_Noise);
|
||||
|
||||
if (m_fogParams == null || m_fogParams.Length != 4)
|
||||
m_fogParams = new float[4];
|
||||
if (m_windDir == null || m_windDir.Length != 3)
|
||||
m_windDir = new float[3];
|
||||
if (m_ambientLight == null || m_ambientLight.Length != 3)
|
||||
m_ambientLight = new float[3];
|
||||
m_fogParams[0] = m_ConstantFog;
|
||||
m_fogParams[1] = m_HeightFogExponent;
|
||||
m_fogParams[2] = m_HeightFogOffset;
|
||||
m_fogParams[3] = m_HeightFogAmount;
|
||||
|
||||
m_InjectLightingAndDensity.SetFloats("_FogParams", m_fogParams);
|
||||
m_InjectLightingAndDensity.SetFloat("_NoiseFogAmount", m_NoiseFogAmount);
|
||||
m_InjectLightingAndDensity.SetFloat("_NoiseFogScale", m_NoiseFogScale);
|
||||
m_InjectLightingAndDensity.SetFloat("_WindSpeed", m_Wind == null ? 0 : m_Wind.m_Speed);
|
||||
Vector3 windDir = m_Wind == null ? Vector3.forward : m_Wind.transform.forward;
|
||||
m_windDir[0] = windDir.x;
|
||||
m_windDir[1] = windDir.y;
|
||||
m_windDir[2] = windDir.z;
|
||||
m_InjectLightingAndDensity.SetFloats("_WindDir", m_windDir);
|
||||
m_InjectLightingAndDensity.SetFloat("_Time", Time.time);
|
||||
m_InjectLightingAndDensity.SetFloat("_NearOverFarClip", nearClip/farClip);
|
||||
Color ambient = m_AmbientLightColor * m_AmbientLightIntensity * 0.1f;
|
||||
m_ambientLight[0] = ambient.r;
|
||||
m_ambientLight[1] = ambient.g;
|
||||
m_ambientLight[2] = ambient.b;
|
||||
m_InjectLightingAndDensity.SetFloats("_AmbientLight", m_ambientLight);
|
||||
|
||||
SetUpPointLightBuffers(kernel);
|
||||
SetUpTubeLightBuffers(kernel);
|
||||
SetUpAreaLightBuffers(kernel);
|
||||
SetUpFogEllipsoidBuffers(kernel);
|
||||
SetUpDirectionalLight(kernel);
|
||||
}
|
||||
|
||||
void Scatter()
|
||||
{
|
||||
// Inject lighting and density
|
||||
int kernel = 0;
|
||||
|
||||
SetUpForScatter(kernel);
|
||||
|
||||
m_InjectLightingAndDensity.Dispatch(kernel, m_VolumeResolution.x/m_InjectNumThreads.x, m_VolumeResolution.y/m_InjectNumThreads.y, m_VolumeResolution.z/m_InjectNumThreads.z);
|
||||
|
||||
// Solve scattering
|
||||
m_Scatter.SetTexture(0, "_VolumeInject", m_VolumeInject);
|
||||
m_Scatter.SetTexture(0, "_VolumeScatter", m_VolumeScatter);
|
||||
m_Scatter.Dispatch(0, m_VolumeResolution.x/m_ScatterNumThreads.x, m_VolumeResolution.y/m_ScatterNumThreads.y, 1);
|
||||
|
||||
ReleaseTempResources();
|
||||
}
|
||||
|
||||
void DebugDisplay(RenderTexture src, RenderTexture dest)
|
||||
{
|
||||
InitMaterial(ref m_DebugMaterial, m_DebugShader);
|
||||
|
||||
m_DebugMaterial.SetTexture("_VolumeInject", m_VolumeInject);
|
||||
m_DebugMaterial.SetTexture("_VolumeScatter", m_VolumeScatter);
|
||||
m_DebugMaterial.SetTexture("_Shadowmap", m_Shadowmap);
|
||||
m_DebugMaterial.SetTexture("_ShadowmapBlurred", m_ShadowmapBlurred);
|
||||
m_DebugMaterial.SetFloat("_Z", m_Z);
|
||||
|
||||
m_DebugMaterial.SetTexture("_MainTex", src);
|
||||
|
||||
Graphics.Blit(src, dest, m_DebugMaterial);
|
||||
}
|
||||
|
||||
void SetUpGlobalFogSamplingUniforms(int width, int height)
|
||||
{
|
||||
Shader.SetGlobalTexture("_VolumeScatter", m_VolumeScatter);
|
||||
Shader.SetGlobalVector("_Screen_TexelSize", new Vector4(1.0f / width, 1.0f / height, width, height));
|
||||
Shader.SetGlobalVector("_VolumeScatter_TexelSize", new Vector4(1.0f / m_VolumeResolution.x, 1.0f / m_VolumeResolution.y, 1.0f / m_VolumeResolution.z, 0));
|
||||
Shader.SetGlobalFloat("_CameraFarOverMaxFar", cam.farClipPlane / farClip);
|
||||
Shader.SetGlobalFloat("_NearOverFarClip", nearClip / farClip);
|
||||
}
|
||||
|
||||
[ImageEffectOpaque]
|
||||
void OnRenderImage(RenderTexture src, RenderTexture dest)
|
||||
{
|
||||
if(m_Debug)
|
||||
{
|
||||
DebugDisplay(src, dest);
|
||||
return;
|
||||
}
|
||||
|
||||
Scatter();
|
||||
|
||||
InitMaterial(ref m_ApplyToOpaqueMaterial, m_ApplyToOpaqueShader);
|
||||
|
||||
// TODO: This shouldn't be needed. Is it because the shader doesn't have the Property block?
|
||||
m_ApplyToOpaqueMaterial.SetTexture("_MainTex", src);
|
||||
|
||||
SetUpGlobalFogSamplingUniforms(src.width, src.height);
|
||||
|
||||
Graphics.Blit(src, dest, m_ApplyToOpaqueMaterial);
|
||||
|
||||
VolumetricFogInForward(true);
|
||||
}
|
||||
|
||||
void OnPostRender()
|
||||
{
|
||||
VolumetricFogInForward(false);
|
||||
}
|
||||
|
||||
void VolumetricFogInForward(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
Shader.EnableKeyword("VOLUMETRIC_FOG");
|
||||
else
|
||||
Shader.DisableKeyword("VOLUMETRIC_FOG");
|
||||
}
|
||||
|
||||
Vector3 ViewportToLocalPoint(Camera c, Transform t, Vector3 p)
|
||||
{
|
||||
// TODO: viewporttoworldpoint inverts the clip-to-world matrix every time without caching it.
|
||||
return t.InverseTransformPoint(c.ViewportToWorldPoint(p));
|
||||
}
|
||||
|
||||
static readonly Vector2[] frustumUVs =
|
||||
new Vector2[] {new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1)};
|
||||
static float[] frustumRays = new float[16];
|
||||
|
||||
void SetFrustumRays()
|
||||
{
|
||||
float far = farClip;
|
||||
Vector3 cameraPos = cam.transform.position;
|
||||
Vector2[] uvs = frustumUVs;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Vector3 ray = cam.ViewportToWorldPoint(new Vector3(uvs[i].x, uvs[i].y, far)) - cameraPos;
|
||||
frustumRays[i*4+0] = ray.x;
|
||||
frustumRays[i*4+1] = ray.y;
|
||||
frustumRays[i*4+2] = ray.z;
|
||||
frustumRays[i*4+3] = 0;
|
||||
}
|
||||
|
||||
m_InjectLightingAndDensity.SetVector("_CameraPos", cameraPos);
|
||||
m_InjectLightingAndDensity.SetFloats("_FrustumRays", frustumRays);
|
||||
}
|
||||
|
||||
void InitVolume(ref RenderTexture volume)
|
||||
{
|
||||
if(volume)
|
||||
return;
|
||||
|
||||
volume = new RenderTexture (m_VolumeResolution.x, m_VolumeResolution.y, 0, RenderTextureFormat.ARGBHalf);
|
||||
volume.volumeDepth = m_VolumeResolution.z;
|
||||
volume.dimension = UnityEngine.Rendering.TextureDimension.Tex3D;
|
||||
volume.enableRandomWrite = true;
|
||||
volume.Create();
|
||||
}
|
||||
|
||||
void CreateBuffer(ref ComputeBuffer buffer, int count, int stride)
|
||||
{
|
||||
if (buffer != null && buffer.count == count)
|
||||
return;
|
||||
|
||||
if(buffer != null)
|
||||
{
|
||||
buffer.Release();
|
||||
buffer = null;
|
||||
}
|
||||
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
buffer = new ComputeBuffer(count, stride);
|
||||
}
|
||||
|
||||
void InitResources ()
|
||||
{
|
||||
// Shadowmap
|
||||
m_Shadowmap = RenderTexture.GetTemporary(m_ShadowmapRes, m_ShadowmapRes, 24, RenderTextureFormat.RFloat);
|
||||
m_Shadowmap.filterMode = FilterMode.Bilinear;
|
||||
m_Shadowmap.wrapMode = TextureWrapMode.Clamp;
|
||||
|
||||
// Volume
|
||||
InitVolume(ref m_VolumeInject);
|
||||
InitVolume(ref m_VolumeScatter);
|
||||
|
||||
|
||||
// Compute buffers
|
||||
int pointLightCount = 0, tubeLightCount = 0, areaLightCount = 0;
|
||||
HashSet<FogLight> fogLights = LightManagerFogLights.Get();
|
||||
for (var x = fogLights.GetEnumerator(); x.MoveNext();)
|
||||
{
|
||||
var fl = x.Current;
|
||||
if (fl == null)
|
||||
continue;
|
||||
|
||||
bool isOn = fl.isOn;
|
||||
|
||||
switch(fl.type)
|
||||
{
|
||||
case FogLight.Type.Point: if (isOn) pointLightCount++; break;
|
||||
case FogLight.Type.Tube: if (isOn) tubeLightCount++; break;
|
||||
case FogLight.Type.Area: if (isOn) areaLightCount++; break;
|
||||
}
|
||||
}
|
||||
|
||||
// PointLightParams {float3 float float3 float} -> 32 bytes
|
||||
CreateBuffer(ref m_PointLightParamsCB, pointLightCount, 32);
|
||||
|
||||
// TubeLightParams {float3 float float3 float float3 float} -> 48 bytes
|
||||
CreateBuffer(ref m_TubeLightParamsCB, tubeLightCount, 48);
|
||||
|
||||
// TubeLightShadowPlaneParams {float4 float4 float float float float} -> 48 bytes
|
||||
CreateBuffer(ref m_TubeLightShadowPlaneParamsCB, tubeLightCount, 48);
|
||||
|
||||
// TubeLightParams {float4x4 float4 float3 float} -> 96 bytes
|
||||
CreateBuffer(ref m_AreaLightParamsCB, areaLightCount, 96);
|
||||
|
||||
// FogEllipsoidParams {float3 float float3 9xfloat} -> 64 bytes
|
||||
HashSet<FogEllipsoid> fogEllipsoids = LightManagerFogEllipsoids.Get();
|
||||
CreateBuffer(ref m_FogEllipsoidParamsCB, fogEllipsoids == null ? 0 : fogEllipsoids.Count, 64);
|
||||
}
|
||||
|
||||
void ReleaseTemporary(ref RenderTexture rt)
|
||||
{
|
||||
if (rt == null)
|
||||
return;
|
||||
|
||||
RenderTexture.ReleaseTemporary(rt);
|
||||
rt = null;
|
||||
}
|
||||
|
||||
void ReleaseTempResources()
|
||||
{
|
||||
ReleaseTemporary(ref m_Shadowmap);
|
||||
ReleaseTemporary(ref m_ShadowmapBlurred);
|
||||
}
|
||||
|
||||
void InitMaterial(ref Material material, Shader shader)
|
||||
{
|
||||
if (material)
|
||||
return;
|
||||
|
||||
if (!shader)
|
||||
{
|
||||
Debug.LogError("Missing shader");
|
||||
return;
|
||||
}
|
||||
|
||||
material = new Material(shader);
|
||||
material.hideFlags = HideFlags.HideAndDontSave;
|
||||
}
|
||||
|
||||
void OnDrawGizmosSelected()
|
||||
{
|
||||
Gizmos.color = Color.yellow;
|
||||
Gizmos.matrix = transform.localToWorldMatrix;
|
||||
Gizmos.DrawFrustum(Vector3.zero, cam.fieldOfView, farClip, nearClip, cam.aspect);
|
||||
}
|
||||
}
|
23
Assets/VolumetricFog/Scripts/VolumetricFog.cs.meta
Normal file
23
Assets/VolumetricFog/Scripts/VolumetricFog.cs.meta
Normal file
@ -0,0 +1,23 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f35c02a2c6230584391703bf32006791
|
||||
timeCreated: 1432253353
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_DebugShader: {fileID: 4800000, guid: 91e29ad407521e447a7254f5c1ea9b54, type: 3}
|
||||
- m_ShadowmapShader: {fileID: 4800000, guid: 2c4cd42b134f7864fa579350e9cf6896, type: 3}
|
||||
- m_InjectLightingAndDensity: {fileID: 7200000, guid: 55812fd61bd54104aa23612fc28bfeb8,
|
||||
type: 3}
|
||||
- m_Scatter: {fileID: 7200000, guid: 2a7c01c2354d03a4e9c31096bf130b6a, type: 3}
|
||||
- m_ApplyToOpaqueShader: {fileID: 4800000, guid: 6f73df8e11615074dbf62a3a384af521,
|
||||
type: 3}
|
||||
- m_BlurShadowmapShader: {fileID: 4800000, guid: 701192b62a7678549918bc87434699fe,
|
||||
type: 3}
|
||||
- m_Noise: {fileID: 2800000, guid: 35eb47181d630134c97488476efbda59, type: 3}
|
||||
- m_Sun: {instanceID: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user