123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- using UnityEngine.Experimental.GlobalIllumination;
- using Unity.Collections;
- namespace UnityEngine.Rendering.Universal.Internal
- {
- /// <summary>
- /// Computes and submits lighting data to the GPU.
- /// </summary>
- public class ForwardLights
- {
- static class LightConstantBuffer
- {
- public static int _MainLightPosition; // DeferredLights.LightConstantBuffer also refers to the same ShaderPropertyID - TODO: move this definition to a common location shared by other UniversalRP classes
- public static int _MainLightColor; // DeferredLights.LightConstantBuffer also refers to the same ShaderPropertyID - TODO: move this definition to a common location shared by other UniversalRP classes
- public static int _MainLightOcclusionProbesChannel; // Deferred?
- public static int _AdditionalLightsCount;
- public static int _AdditionalLightsPosition;
- public static int _AdditionalLightsColor;
- public static int _AdditionalLightsAttenuation;
- public static int _AdditionalLightsSpotDir;
- public static int _AdditionalLightOcclusionProbeChannel;
- }
- int m_AdditionalLightsBufferId;
- int m_AdditionalLightsIndicesId;
- const string k_SetupLightConstants = "Setup Light Constants";
- private static readonly ProfilingSampler m_ProfilingSampler = new ProfilingSampler(k_SetupLightConstants);
- MixedLightingSetup m_MixedLightingSetup;
- Vector4[] m_AdditionalLightPositions;
- Vector4[] m_AdditionalLightColors;
- Vector4[] m_AdditionalLightAttenuations;
- Vector4[] m_AdditionalLightSpotDirections;
- Vector4[] m_AdditionalLightOcclusionProbeChannels;
- bool m_UseStructuredBuffer;
- public ForwardLights()
- {
- m_UseStructuredBuffer = RenderingUtils.useStructuredBuffer;
- LightConstantBuffer._MainLightPosition = Shader.PropertyToID("_MainLightPosition");
- LightConstantBuffer._MainLightColor = Shader.PropertyToID("_MainLightColor");
- LightConstantBuffer._MainLightOcclusionProbesChannel = Shader.PropertyToID("_MainLightOcclusionProbes");
- LightConstantBuffer._AdditionalLightsCount = Shader.PropertyToID("_AdditionalLightsCount");
- if (m_UseStructuredBuffer)
- {
- m_AdditionalLightsBufferId = Shader.PropertyToID("_AdditionalLightsBuffer");
- m_AdditionalLightsIndicesId = Shader.PropertyToID("_AdditionalLightsIndices");
- }
- else
- {
- LightConstantBuffer._AdditionalLightsPosition = Shader.PropertyToID("_AdditionalLightsPosition");
- LightConstantBuffer._AdditionalLightsColor = Shader.PropertyToID("_AdditionalLightsColor");
- LightConstantBuffer._AdditionalLightsAttenuation = Shader.PropertyToID("_AdditionalLightsAttenuation");
- LightConstantBuffer._AdditionalLightsSpotDir = Shader.PropertyToID("_AdditionalLightsSpotDir");
- LightConstantBuffer._AdditionalLightOcclusionProbeChannel = Shader.PropertyToID("_AdditionalLightsOcclusionProbes");
- int maxLights = UniversalRenderPipeline.maxVisibleAdditionalLights;
- m_AdditionalLightPositions = new Vector4[maxLights];
- m_AdditionalLightColors = new Vector4[maxLights];
- m_AdditionalLightAttenuations = new Vector4[maxLights];
- m_AdditionalLightSpotDirections = new Vector4[maxLights];
- m_AdditionalLightOcclusionProbeChannels = new Vector4[maxLights];
- }
- }
- public void Setup(ScriptableRenderContext context, ref RenderingData renderingData)
- {
- int additionalLightsCount = renderingData.lightData.additionalLightsCount;
- bool additionalLightsPerVertex = renderingData.lightData.shadeAdditionalLightsPerVertex;
- CommandBuffer cmd = CommandBufferPool.Get();
- using (new ProfilingScope(cmd, m_ProfilingSampler))
- {
- SetupShaderLightConstants(cmd, ref renderingData);
- CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.AdditionalLightsVertex,
- additionalLightsCount > 0 && additionalLightsPerVertex);
- CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.AdditionalLightsPixel,
- additionalLightsCount > 0 && !additionalLightsPerVertex);
- bool isShadowMask = renderingData.lightData.supportsMixedLighting && m_MixedLightingSetup == MixedLightingSetup.ShadowMask;
- bool isShadowMaskAlways = isShadowMask && QualitySettings.shadowmaskMode == ShadowmaskMode.Shadowmask;
- bool isSubtractive = renderingData.lightData.supportsMixedLighting && m_MixedLightingSetup == MixedLightingSetup.Subtractive;
- CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.LightmapShadowMixing, isSubtractive || isShadowMaskAlways);
- CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.ShadowsShadowMask, isShadowMask);
- CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MixedLightingSubtractive, isSubtractive); // Backward compatibility
- }
- context.ExecuteCommandBuffer(cmd);
- CommandBufferPool.Release(cmd);
- }
- void InitializeLightConstants(NativeArray<VisibleLight> lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightAttenuation, out Vector4 lightSpotDir, out Vector4 lightOcclusionProbeChannel)
- {
- UniversalRenderPipeline.InitializeLightConstants_Common(lights, lightIndex, out lightPos, out lightColor, out lightAttenuation, out lightSpotDir, out lightOcclusionProbeChannel);
- // When no lights are visible, main light will be set to -1.
- // In this case we initialize it to default values and return
- if (lightIndex < 0)
- return;
- VisibleLight lightData = lights[lightIndex];
- Light light = lightData.light;
- if (light == null)
- return;
- if (light.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed &&
- lightData.light.shadows != LightShadows.None &&
- m_MixedLightingSetup == MixedLightingSetup.None)
- {
- switch (light.bakingOutput.mixedLightingMode)
- {
- case MixedLightingMode.Subtractive:
- m_MixedLightingSetup = MixedLightingSetup.Subtractive;
- break;
- case MixedLightingMode.Shadowmask:
- m_MixedLightingSetup = MixedLightingSetup.ShadowMask;
- break;
- }
- }
- }
- void SetupShaderLightConstants(CommandBuffer cmd, ref RenderingData renderingData)
- {
- m_MixedLightingSetup = MixedLightingSetup.None;
- // Main light has an optimized shader path for main light. This will benefit games that only care about a single light.
- // Universal pipeline also supports only a single shadow light, if available it will be the main light.
- SetupMainLightConstants(cmd, ref renderingData.lightData);
- SetupAdditionalLightConstants(cmd, ref renderingData);
- }
- void SetupMainLightConstants(CommandBuffer cmd, ref LightData lightData)
- {
- Vector4 lightPos, lightColor, lightAttenuation, lightSpotDir, lightOcclusionChannel;
- InitializeLightConstants(lightData.visibleLights, lightData.mainLightIndex, out lightPos, out lightColor, out lightAttenuation, out lightSpotDir, out lightOcclusionChannel);
- cmd.SetGlobalVector(LightConstantBuffer._MainLightPosition, lightPos);
- cmd.SetGlobalVector(LightConstantBuffer._MainLightColor, lightColor);
- cmd.SetGlobalVector(LightConstantBuffer._MainLightOcclusionProbesChannel, lightOcclusionChannel);
- }
- void SetupAdditionalLightConstants(CommandBuffer cmd, ref RenderingData renderingData)
- {
- ref LightData lightData = ref renderingData.lightData;
- var cullResults = renderingData.cullResults;
- var lights = lightData.visibleLights;
- int maxAdditionalLightsCount = UniversalRenderPipeline.maxVisibleAdditionalLights;
- int additionalLightsCount = SetupPerObjectLightIndices(cullResults, ref lightData);
- if (additionalLightsCount > 0)
- {
- if (m_UseStructuredBuffer)
- {
- NativeArray<ShaderInput.LightData> additionalLightsData = new NativeArray<ShaderInput.LightData>(additionalLightsCount, Allocator.Temp);
- for (int i = 0, lightIter = 0; i < lights.Length && lightIter < maxAdditionalLightsCount; ++i)
- {
- VisibleLight light = lights[i];
- if (lightData.mainLightIndex != i)
- {
- ShaderInput.LightData data;
- InitializeLightConstants(lights, i,
- out data.position, out data.color, out data.attenuation,
- out data.spotDirection, out data.occlusionProbeChannels);
- additionalLightsData[lightIter] = data;
- lightIter++;
- }
- }
- var lightDataBuffer = ShaderData.instance.GetLightDataBuffer(additionalLightsCount);
- lightDataBuffer.SetData(additionalLightsData);
- int lightIndices = cullResults.lightAndReflectionProbeIndexCount;
- var lightIndicesBuffer = ShaderData.instance.GetLightIndicesBuffer(lightIndices);
- cmd.SetGlobalBuffer(m_AdditionalLightsBufferId, lightDataBuffer);
- cmd.SetGlobalBuffer(m_AdditionalLightsIndicesId, lightIndicesBuffer);
- additionalLightsData.Dispose();
- }
- else
- {
- for (int i = 0, lightIter = 0; i < lights.Length && lightIter < maxAdditionalLightsCount; ++i)
- {
- VisibleLight light = lights[i];
- if (lightData.mainLightIndex != i)
- {
- InitializeLightConstants(lights, i, out m_AdditionalLightPositions[lightIter],
- out m_AdditionalLightColors[lightIter],
- out m_AdditionalLightAttenuations[lightIter],
- out m_AdditionalLightSpotDirections[lightIter],
- out m_AdditionalLightOcclusionProbeChannels[lightIter]);
- lightIter++;
- }
- }
- cmd.SetGlobalVectorArray(LightConstantBuffer._AdditionalLightsPosition, m_AdditionalLightPositions);
- cmd.SetGlobalVectorArray(LightConstantBuffer._AdditionalLightsColor, m_AdditionalLightColors);
- cmd.SetGlobalVectorArray(LightConstantBuffer._AdditionalLightsAttenuation, m_AdditionalLightAttenuations);
- cmd.SetGlobalVectorArray(LightConstantBuffer._AdditionalLightsSpotDir, m_AdditionalLightSpotDirections);
- cmd.SetGlobalVectorArray(LightConstantBuffer._AdditionalLightOcclusionProbeChannel, m_AdditionalLightOcclusionProbeChannels);
- }
- cmd.SetGlobalVector(LightConstantBuffer._AdditionalLightsCount, new Vector4(lightData.maxPerObjectAdditionalLightsCount,
- 0.0f, 0.0f, 0.0f));
- }
- else
- {
- cmd.SetGlobalVector(LightConstantBuffer._AdditionalLightsCount, Vector4.zero);
- }
- }
- int SetupPerObjectLightIndices(CullingResults cullResults, ref LightData lightData)
- {
- if (lightData.additionalLightsCount == 0)
- return lightData.additionalLightsCount;
- var visibleLights = lightData.visibleLights;
- var perObjectLightIndexMap = cullResults.GetLightIndexMap(Allocator.Temp);
- int globalDirectionalLightsCount = 0;
- int additionalLightsCount = 0;
- // Disable all directional lights from the perobject light indices
- // Pipeline handles main light globally and there's no support for additional directional lights atm.
- for (int i = 0; i < visibleLights.Length; ++i)
- {
- if (additionalLightsCount >= UniversalRenderPipeline.maxVisibleAdditionalLights)
- break;
- VisibleLight light = visibleLights[i];
- if (i == lightData.mainLightIndex)
- {
- perObjectLightIndexMap[i] = -1;
- ++globalDirectionalLightsCount;
- }
- else
- {
- perObjectLightIndexMap[i] -= globalDirectionalLightsCount;
- ++additionalLightsCount;
- }
- }
- // Disable all remaining lights we cannot fit into the global light buffer.
- for (int i = globalDirectionalLightsCount + additionalLightsCount; i < perObjectLightIndexMap.Length; ++i)
- perObjectLightIndexMap[i] = -1;
- cullResults.SetLightIndexMap(perObjectLightIndexMap);
- if (m_UseStructuredBuffer && additionalLightsCount > 0)
- {
- int lightAndReflectionProbeIndices = cullResults.lightAndReflectionProbeIndexCount;
- Assertions.Assert.IsTrue(lightAndReflectionProbeIndices > 0, "Pipelines configures additional lights but per-object light and probe indices count is zero.");
- cullResults.FillLightAndReflectionProbeIndices(ShaderData.instance.GetLightIndicesBuffer(lightAndReflectionProbeIndices));
- }
- perObjectLightIndexMap.Dispose();
- return additionalLightsCount;
- }
- }
- }
|