mirror of
				https://github.com/maxartz15/VolumetricLighting.git
				synced 2025-10-31 13:35:56 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			144 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using UnityEngine;
 | |
| using UnityEngine.Rendering;
 | |
| using System.Collections.Generic;
 | |
| 
 | |
| public partial class AreaLight : MonoBehaviour
 | |
| {
 | |
| 	[HideInInspector]
 | |
| 	public Mesh m_Cube;
 | |
| 	[HideInInspector]
 | |
| 	public Shader m_ProxyShader;
 | |
| 	Material m_ProxyMaterial;
 | |
| 	static Texture2D s_TransformInvTexture_Specular;
 | |
| 	static Texture2D s_TransformInvTexture_Diffuse;
 | |
| 	static Texture2D s_AmpDiffAmpSpecFresnel;
 | |
| 
 | |
| 	Dictionary<Camera, CommandBuffer> m_Cameras = new Dictionary<Camera, CommandBuffer>();
 | |
| 	static CameraEvent kCameraEvent = CameraEvent.AfterLighting;
 | |
| 
 | |
| 	bool InitDirect()
 | |
| 	{
 | |
| 		if (m_ProxyShader == null || m_Cube  == null)
 | |
| 			return false;
 | |
| 
 | |
| 		// Proxy
 | |
| 		m_ProxyMaterial = new Material(m_ProxyShader);
 | |
| 		m_ProxyMaterial.hideFlags = HideFlags.HideAndDontSave;
 | |
| 
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	void SetUpLUTs()
 | |
| 	{
 | |
| 		if (s_TransformInvTexture_Diffuse == null)
 | |
| 			s_TransformInvTexture_Diffuse = AreaLightLUT.LoadLUT(AreaLightLUT.LUTType.TransformInv_DisneyDiffuse);
 | |
| 		if (s_TransformInvTexture_Specular == null)
 | |
| 			s_TransformInvTexture_Specular = AreaLightLUT.LoadLUT(AreaLightLUT.LUTType.TransformInv_GGX);
 | |
| 		if (s_AmpDiffAmpSpecFresnel == null)
 | |
| 			s_AmpDiffAmpSpecFresnel = AreaLightLUT.LoadLUT(AreaLightLUT.LUTType.AmpDiffAmpSpecFresnel);
 | |
| 
 | |
| 		m_ProxyMaterial.SetTexture("_TransformInv_Diffuse", s_TransformInvTexture_Diffuse);
 | |
| 		m_ProxyMaterial.SetTexture("_TransformInv_Specular", s_TransformInvTexture_Specular);
 | |
| 		m_ProxyMaterial.SetTexture("_AmpDiffAmpSpecFresnel", s_AmpDiffAmpSpecFresnel);
 | |
| 	}
 | |
| 
 | |
| 	void Cleanup()
 | |
| 	{
 | |
| 		for(var e = m_Cameras.GetEnumerator(); e.MoveNext();)
 | |
| 		{
 | |
| 			var cam = e.Current;
 | |
| 			if (cam.Key != null && cam.Value != null)
 | |
| 			{
 | |
| 				cam.Key.RemoveCommandBuffer (kCameraEvent, cam.Value);
 | |
| 			}
 | |
| 		}
 | |
| 		m_Cameras.Clear();
 | |
| 	}
 | |
| 
 | |
| 	static readonly float[,] offsets = new float[4,2] {{1, 1}, {1, -1}, {-1, -1}, {-1, 1}};
 | |
| 
 | |
| 	CommandBuffer GetOrCreateCommandBuffer(Camera cam)
 | |
| 	{
 | |
| 		if(cam == null)
 | |
| 			return null;
 | |
| 
 | |
| 		CommandBuffer buf = null;
 | |
| 		if(!m_Cameras.ContainsKey(cam)) {
 | |
| 			buf = new CommandBuffer();
 | |
| 			buf.name = /*"Area light: " +*/ gameObject.name;
 | |
| 			m_Cameras[cam] = buf;
 | |
| 			cam.AddCommandBuffer(kCameraEvent, buf);
 | |
| 			cam.depthTextureMode |= DepthTextureMode.Depth;
 | |
| 		} else {
 | |
| 			buf = m_Cameras[cam];
 | |
| 			buf.Clear();
 | |
| 		}
 | |
| 
 | |
| 		return buf;
 | |
| 	}
 | |
| 
 | |
| 	public void SetUpCommandBuffer()
 | |
| 	{
 | |
| 		if (InsideShadowmapCameraRender())
 | |
| 			return;
 | |
| 
 | |
| 		Camera cam = Camera.current;
 | |
| 		CommandBuffer buf = GetOrCreateCommandBuffer(cam);
 | |
| 
 | |
| 		buf.SetGlobalVector("_LightPos", transform.position);
 | |
| 		buf.SetGlobalVector("_LightColor", GetColor());
 | |
| 		SetUpLUTs();
 | |
| 
 | |
| 		// Needed as we're using the vert_deferred vertex shader from UnityDeferredLibrary.cginc
 | |
| 		// TODO: Make the light render as quad if it intersects both near and far plane.
 | |
| 		// (Also missing: rendering as front faces when near doesn't intersect, stencil optimisations)
 | |
| 		buf.SetGlobalFloat("_LightAsQuad", 0);
 | |
| 		
 | |
| 		// A little bit of bias to prevent the light from lighting itself - the source quad
 | |
| 		float z = 0.01f;
 | |
| 		Transform t = transform;
 | |
| 
 | |
| 		Matrix4x4 lightVerts = new Matrix4x4();
 | |
| 		for (int i = 0; i < 4; i++)
 | |
| 			lightVerts.SetRow(i, t.TransformPoint(new Vector3(m_Size.x * offsets[i,0], m_Size.y * offsets[i,1], z) * 0.5f));
 | |
| 		buf.SetGlobalMatrix("_LightVerts", lightVerts);
 | |
| 
 | |
| 		if (m_Shadows)
 | |
| 			SetUpShadowmapForSampling(buf);
 | |
| 
 | |
| 		Matrix4x4 m = Matrix4x4.TRS(new Vector3(0, 0, 10.0f), Quaternion.identity, Vector3.one * 20);
 | |
| 		buf.DrawMesh(m_Cube, t.localToWorldMatrix * m, m_ProxyMaterial, 0, m_Shadows ? /*shadows*/ 0 : /*no shadows*/ 1);
 | |
| 	}
 | |
| 
 | |
| 	void SetKeyword(string keyword, bool on)
 | |
| 	{
 | |
| 		if (on)
 | |
| 			m_ProxyMaterial.EnableKeyword(keyword);
 | |
| 		else
 | |
| 			m_ProxyMaterial.DisableKeyword(keyword);
 | |
| 	}
 | |
| 
 | |
| 	void ReleaseTemporary(ref RenderTexture rt)
 | |
| 	{
 | |
| 		if (rt == null)
 | |
| 			return;
 | |
| 
 | |
| 		RenderTexture.ReleaseTemporary(rt);
 | |
| 		rt = null;
 | |
| 	}
 | |
| 
 | |
| 	Color GetColor()
 | |
| 	{
 | |
| 		if (QualitySettings.activeColorSpace == ColorSpace.Gamma)
 | |
| 			return m_Color * m_Intensity;
 | |
| 
 | |
| 		return new Color(
 | |
| 			Mathf.GammaToLinearSpace(m_Color.r * m_Intensity),
 | |
| 			Mathf.GammaToLinearSpace(m_Color.g * m_Intensity),
 | |
| 			Mathf.GammaToLinearSpace(m_Color.b * m_Intensity),
 | |
| 			1.0f
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| }
 |