using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; public class VolumetricFogLightsFeature : ScriptableRendererFeature { class LightsPass : ScriptableRenderPass { static readonly int _CountID = Shader.PropertyToID("_FogLightCount"); static readonly int _PosID = Shader.PropertyToID("_FogLightPos"); static readonly int _ColorID = Shader.PropertyToID("_FogLightColor"); static readonly int _RangeID = Shader.PropertyToID("_FogLightRange"); const int MAX = 16; Vector4[] pos = new Vector4[MAX]; Vector4[] color = new Vector4[MAX]; float[] range = new float[MAX]; public override void Execute(ScriptableRenderContext ctx, ref RenderingData data) { int count = 0; foreach (var vl in data.lightData.visibleLights) { if (count >= MAX) break; if (vl.lightType == LightType.Point || vl.lightType == LightType.Spot) { pos[count] = vl.light.transform.position; color[count] = vl.finalColor; range[count] = vl.range; count++; } } var cmd = CommandBufferPool.Get("FogLights"); cmd.SetGlobalInt(_CountID, count); cmd.SetGlobalVectorArray(_PosID, pos); cmd.SetGlobalVectorArray(_ColorID, color); cmd.SetGlobalFloatArray(_RangeID, range); ctx.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); Debug.Log($"[FogLights] Passed {count} lights to shader"); } } LightsPass pass; public override void Create() { pass = new LightsPass { renderPassEvent = RenderPassEvent.BeforeRendering }; } public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData data) { renderer.EnqueuePass(pass); } }