diff --git a/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/CoreBuildData.cs b/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/CoreBuildData.cs index 05de0b1a735..2a848721577 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/CoreBuildData.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/CoreBuildData.cs @@ -35,20 +35,31 @@ public class CoreBuildData : IDisposable public List renderPipelineAssets { get; private set; } = new(); /// - /// Whether the build is a development build or not. + /// Whether the current build's managed code variant has UNITY_ENABLE_CHECKS defined + /// (Debug or Checked variant). /// - public bool developmentBuild { get; private set; } = false; + /// + /// Use this to gate inclusion of diagnostic shaders, resources, and other build-time decisions + /// that mirror C# code paths compiled under #if UNITY_ENABLE_CHECKS. + /// + public bool useDiagnosticChecks { get; private set; } = false; + + /// + /// Obsolete. Always returns false. + /// + [Obsolete("developmentBuild is no longer populated and always returns false. Use useDiagnosticChecks for stripping decisions that mirror UNITY_ENABLE_CHECKS-gated C# code.")] + public bool developmentBuild => false; internal Dictionary computeShaderCache { get; private set; } = new(); internal bool pipelineSupportGPUResidentDrawer { get; private set; } = false; internal bool playerNeedGPUResidentDrawer { get; private set; } = false; - private CoreBuildData(BuildTarget buildTarget, bool development) + private CoreBuildData(BuildTarget buildTarget) { m_Instance = this; - developmentBuild = development; + useDiagnosticChecks = PlayerSettings.GetManagedCodeVariant(GetNamedBuildTarget(buildTarget)) <= ManagedCodeVariant.Checked; if (!buildTarget.TryGetRenderPipelineAssets(renderPipelineAssets)) return; @@ -63,7 +74,19 @@ private CoreBuildData(BuildTarget buildTarget, bool development) } private static CoreBuildData CreateInstance() - => new(EditorUserBuildSettings.activeBuildTarget, EditorUserBuildSettings.development); + => new(EditorUserBuildSettings.activeBuildTarget); + + // NamedBuildTarget for buildTarget under the active subtarget (Player vs Server for Standalone). + private static NamedBuildTarget GetNamedBuildTarget(BuildTarget buildTarget) + { + var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(buildTarget); + if (buildTargetGroup == BuildTargetGroup.Standalone && + EditorUserBuildSettings.standaloneBuildSubtarget == StandaloneBuildSubtarget.Server) + { + return NamedBuildTarget.Server; + } + return NamedBuildTarget.FromBuildTargetGroup(buildTargetGroup); + } private void CheckGPUResidentDrawerUsage() { diff --git a/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/SettingsStrippers/RenderingDebuggerRuntimeResourcesStripper.cs b/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/SettingsStrippers/RenderingDebuggerRuntimeResourcesStripper.cs index 15fc576e592..ae16b4fa84c 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/SettingsStrippers/RenderingDebuggerRuntimeResourcesStripper.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/SettingsStrippers/RenderingDebuggerRuntimeResourcesStripper.cs @@ -6,6 +6,6 @@ class RenderingDebuggerRuntimeResourcesStripper : IRenderPipelineGraphicsSetting { public bool active => true; - public bool CanRemoveSettings(RenderingDebuggerRuntimeResources settings) => !CoreBuildData.instance.developmentBuild; + public bool CanRemoveSettings(RenderingDebuggerRuntimeResources settings) => !CoreBuildData.instance.useDiagnosticChecks; } } diff --git a/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.Deprecated.cs b/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.Deprecated.cs index 46caf670494..c22d1f19b36 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.Deprecated.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.Deprecated.cs @@ -1,4 +1,4 @@ -#if ENABLE_UIELEMENTS_MODULE && (UNITY_EDITOR || DEVELOPMENT_BUILD) +#if ENABLE_UIELEMENTS_MODULE && UNITY_ENABLE_CHECKS #define ENABLE_RENDERING_DEBUGGER_UI #endif diff --git a/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.SearchFilter.cs b/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.SearchFilter.cs index 84b48fb80e7..c1ffb573242 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.SearchFilter.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.SearchFilter.cs @@ -1,4 +1,4 @@ -#if ENABLE_UIELEMENTS_MODULE && (UNITY_EDITOR || DEVELOPMENT_BUILD) +#if ENABLE_UIELEMENTS_MODULE && UNITY_ENABLE_CHECKS #define ENABLE_RENDERING_DEBUGGER_UI #endif diff --git a/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.cs b/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.cs index 506245e32a4..6c8084ebbb9 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.cs @@ -1,4 +1,4 @@ -#if ENABLE_UIELEMENTS_MODULE && (UNITY_EDITOR || DEVELOPMENT_BUILD) +#if ENABLE_UIELEMENTS_MODULE && UNITY_ENABLE_CHECKS #define ENABLE_RENDERING_DEBUGGER_UI #endif diff --git a/Packages/com.unity.render-pipelines.core/Editor/InternalBridge/AssemblyInfo.cs b/Packages/com.unity.render-pipelines.core/Editor/InternalBridge/AssemblyInfo.cs index 8ea160f1dec..0a04494f984 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/InternalBridge/AssemblyInfo.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/InternalBridge/AssemblyInfo.cs @@ -2,3 +2,4 @@ [assembly: InternalsVisibleTo("Unity.RenderPipelines.Core.Editor")] [assembly: InternalsVisibleTo("Unity.RenderPipelines.HighDefinition.Editor")] +[assembly: InternalsVisibleTo("Unity.RenderPipelines.Universal.Editor")] diff --git a/Packages/com.unity.render-pipelines.core/Editor/InternalBridge/ObjectSelector.cs b/Packages/com.unity.render-pipelines.core/Editor/InternalBridge/ObjectSelector.cs index 8c398439214..ea3b96a5f2b 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/InternalBridge/ObjectSelector.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/InternalBridge/ObjectSelector.cs @@ -10,5 +10,12 @@ public static void Show(UnityEngine.Object obj, Type requiredType, UnityEngine.O { UnityEditor.ObjectSelector.get.Show(obj, requiredType, objectBeingEdited, allowSceneObjects, allowedEntityIds, onObjectSelectorClosed, onObjectSelectedUpdated, showNoneItem); } + + public static void SetVisualSelection(EntityId entityId) + { + UnityEditor.ObjectSelector.get.SetVisualSelection(entityId); + } + + public static bool isVisible => UnityEditor.ObjectSelector.isVisible; } } diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs index 1ce93cfc1bd..48e0430d820 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.cs @@ -1717,8 +1717,11 @@ Vector3Int GetCellPositionFromVoxel(Vector3Int voxelToLookup, int cellSizeInBric continue; // 3. - // Overwrite lighting data with trilinear sampled data from the brick with highest subdiv level - float brickSize = ProbeReferenceVolume.instance.BrickSize(largestBrick.subdivisionLevel - 1); + // Overwrite lighting data with trilinear sampled data from the brick with highest subdiv level. + // Use minBrickSize from m_ProfileInfo (live bake settings), not ProbeReferenceVolume.instance, + // because that runtime state is restored to the previous bake's snapshot at the end of + // ApplySubdivisionResults and would be stale here. UUM-141983. + float brickSize = ProbeVolumeUtil.BrickSize(minBrickSize, largestBrick.subdivisionLevel - 1); float3 uvw = math.clamp((pos - (Vector3)largestBrick.position * minBrickSize) / brickSize, 0, 3); var probe = Vector3Int.FloorToInt(uvw); diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeLightingTab.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeLightingTab.cs index c98fda030da..dc9e2554d97 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeLightingTab.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeVolumeLightingTab.cs @@ -1,4 +1,4 @@ -#if ENABLE_UIELEMENTS_MODULE && (UNITY_EDITOR || DEVELOPMENT_BUILD) +#if ENABLE_UIELEMENTS_MODULE && UNITY_ENABLE_CHECKS #define ENABLE_RENDERING_DEBUGGER_UI #endif diff --git a/Packages/com.unity.render-pipelines.core/Editor/PathTracing/BakeInputSerialization.cs b/Packages/com.unity.render-pipelines.core/Editor/PathTracing/BakeInputSerialization.cs index 70c2c43dc6b..bee116e2a20 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/PathTracing/BakeInputSerialization.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/PathTracing/BakeInputSerialization.cs @@ -5,7 +5,6 @@ using Unity.Mathematics; using UnityEngine; using Unity.Collections.LowLevel.Unsafe; -using UnityEditor.LightBaking; using MixedLightingMode = UnityEngine.MixedLightingMode; // The types defined in this file should match the types defined in BakeInput.h. @@ -253,15 +252,16 @@ internal struct LightingSettings : IBakeInputVisitable public bool aoEnabled; public float aoDistance; public bool useHardwareRayTracing; + public bool enableHeightfieldRayTracing; - public LightSamplingMode directLightSamplingMode; + public UnityEngine.PathTracing.Core.LightSamplingMode directLightSamplingMode; public uint directRISCandidateCount; - public LightSamplingMode indirectLightSamplingMode; + public UnityEngine.PathTracing.Core.LightSamplingMode indirectLightSamplingMode; public UInt32 indirectRISCandidateCount; public LightAccelerationStructure lightAccelerationStructure; public uint lightGridMaxCells; - public EmissiveSamplingMode directEmissiveSamplingMode; - public EmissiveSamplingMode indirectEmissiveSamplingMode; + public UnityEngine.PathTracing.Core.EmissiveSamplingMode directEmissiveSamplingMode; + public UnityEngine.PathTracing.Core.EmissiveSamplingMode indirectEmissiveSamplingMode; public void Transfer(IBakeInputVisitor visitor) { @@ -274,6 +274,7 @@ public void Transfer(IBakeInputVisitor visitor) visitor.TransferBoolean(ref aoEnabled); visitor.TransferBlittable(ref aoDistance); visitor.TransferBoolean(ref useHardwareRayTracing); + visitor.TransferBoolean(ref enableHeightfieldRayTracing); visitor.TransferBlittable(ref directLightSamplingMode); visitor.TransferBlittable(ref directRISCandidateCount); @@ -572,6 +573,7 @@ internal struct LightData : IBakeInputVisitable public AngularFalloffType angularFalloff; public bool castsShadows; public UInt32 shadowMaskChannel; + public float indirectMultiplier; public void Transfer(IBakeInputVisitor visitor) { @@ -592,6 +594,7 @@ public void Transfer(IBakeInputVisitor visitor) visitor.TransferBlittable(ref angularFalloff); visitor.TransferBoolean(ref castsShadows); visitor.TransferBlittable(ref shadowMaskChannel); + visitor.TransferBlittable(ref indirectMultiplier); } } @@ -951,7 +954,7 @@ internal static class BakeInputSerialization { // Should match BakeInputSerialization::kCurrentFileVersion in BakeInputSerialization.h. // If these are out of sync, the implementation in this file probably needs to be updated. - const UInt64 CurrentFileVersion = 202603061; + const UInt64 CurrentFileVersion = 202605011; public static bool Deserialize(string path, out BakeInput bakeInput) { diff --git a/Packages/com.unity.render-pipelines.core/Editor/PathTracing/BakeInputToWorldConversion.cs b/Packages/com.unity.render-pipelines.core/Editor/PathTracing/BakeInputToWorldConversion.cs index 89ac8f38bcd..9a09210dd7e 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/PathTracing/BakeInputToWorldConversion.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/PathTracing/BakeInputToWorldConversion.cs @@ -242,10 +242,7 @@ internal static void InjectAnalyticalLights( { ref readonly LightData lightData = ref bakeInput.lightData[i]; - // TODO(pema.malling): The following transform is only correct for linear color space :( https://jira.unity3d.com/browse/LIGHT-1763 - float maxColor = Mathf.Max(lightData.color.x, Mathf.Max(lightData.color.y, lightData.color.z)); - float maxIndirectColor = Mathf.Max(lightData.indirectColor.x, Mathf.Max(lightData.indirectColor.y, lightData.indirectColor.z)); - float bounceIntensity = maxColor <= 0 ? 0 : maxIndirectColor / maxColor; + float bounceIntensity = lightData.indirectMultiplier; World.LightDescriptor lightDescriptor; lightDescriptor.Type = LightBakerLightTypeToUnityLightType(lightData.type); @@ -504,6 +501,43 @@ internal static Mesh TerrainDataToMesh(in TerrainData terrainData, in HeightmapD return outMesh; } + internal static Mesh CreateTerrainQuadMesh() + { + // Match TerrainToMesh's extent convention: UV = vertex.xz / (resolution - 1). + // The quad spans [0, 1] in both vertex space and UV so the lightmap atlas + // region is fully covered (matches Progressive GPU). + var mesh = new Mesh(); + mesh.vertices = new Vector3[] { new(0, 0, 0), new(1, 0, 0), new(1, 0, 1), new(0, 0, 1) }; + mesh.uv = new Vector2[] { new(0, 0), new(1, 0), new(1, 1), new(0, 1) }; + mesh.uv2 = new Vector2[] { new(0, 0), new(1, 0), new(1, 1), new(0, 1) }; + mesh.normals = new Vector3[] { Vector3.up, Vector3.up, Vector3.up, Vector3.up }; + mesh.triangles = new int[] { 0, 2, 1, 0, 3, 2 }; + return mesh; + } + + // Compute world-space bounds for a procedural terrain. The quad mesh used by procedural terrain + // is in normalized UV space and has Y=0, so CalculateMeshBounds on it gives wrong results. + // The terrain occupies (resolution-1) * heightmapScale.x in X, (resolution-1) * heightmapScale.z in Z, + // and Y in [0, heightmapScale.y] (conservative — uses the maximum possible height). + private static Bounds CalculateProceduralTerrainBounds(in HeightmapData heightMap, in LightBakerBridge.TerrainData terrainData, Matrix4x4 localToWorldMatrix4x4, out Vector3 meshMinVertex, out Vector3 meshMaxVertex) + { + float extentX = (heightMap.resolution - 1) * terrainData.heightmapScale.x; + float extentZ = (heightMap.resolution - 1) * terrainData.heightmapScale.z; + float maxY = terrainData.heightmapScale.y; + Vector3[] corners = new Vector3[] + { + new(0, 0, 0), + new(extentX, 0, 0), + new(0, 0, extentZ), + new(extentX, 0, extentZ), + new(0, maxY, 0), + new(extentX, maxY, 0), + new(0, maxY, extentZ), + new(extentX, maxY, extentZ), + }; + return CalculateMeshBounds(corners, localToWorldMatrix4x4, out meshMinVertex, out meshMaxVertex); + } + private static Bounds CalculateMeshBounds(Vector3[] vertices, Matrix4x4 localToWorldMatrix4x4, out Vector3 meshMinVertex, out Vector3 meshMaxVertex) { meshMinVertex = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); @@ -531,6 +565,8 @@ internal static void ConvertInstancesAndMeshes( List allocatedObjects, uint renderingObjectLayer) { + bool useProceduralTerrain = bakeInput.lightingSettings.enableHeightfieldRayTracing; + // Extract meshes meshes = new Mesh[bakeInput.meshData.Length + bakeInput.terrainData.Length]; int meshIndex = 0; @@ -542,15 +578,67 @@ internal static void ConvertInstancesAndMeshes( } // Extract terrains - int terrainMeshOffset = meshIndex; // remember where the terrains start + int terrainMeshOffset = meshIndex; for (int i = 0; i < bakeInput.terrainData.Length; i++) { - var heightMap = bakeInput.heightMapData[bakeInput.terrainData[i].heightMapIndex]; - var holeMap = bakeInput.terrainData[i].terrainHoleIndex >= 0 ? bakeInput.terrainHoleData[bakeInput.terrainData[i].terrainHoleIndex] : new TerrainHoleData(); - meshes[meshIndex] = TerrainDataToMesh(in bakeInput.terrainData[i], in heightMap, in holeMap); + if (useProceduralTerrain) + { + meshes[meshIndex] = CreateTerrainQuadMesh(); + } + else + { + var heightMap = bakeInput.heightMapData[bakeInput.terrainData[i].heightMapIndex]; + var holeMap = bakeInput.terrainData[i].terrainHoleIndex >= 0 ? bakeInput.terrainHoleData[bakeInput.terrainData[i].terrainHoleIndex] : new TerrainHoleData(); + meshes[meshIndex] = TerrainDataToMesh(in bakeInput.terrainData[i], in heightMap, in holeMap); + } meshIndex++; } + // Add procedural terrain instances to the acceleration structure + if (useProceduralTerrain && bakeInput.terrainData.Length > 0) + { + + for (int i = 0; i < bakeInput.terrainData.Length; i++) + { + ref readonly LightBakerBridge.TerrainData terrain = ref bakeInput.terrainData[i]; + var heightMap = bakeInput.heightMapData[terrain.heightMapIndex]; + var holeMap = terrain.terrainHoleIndex >= 0 ? bakeInput.terrainHoleData[terrain.terrainHoleIndex] : new TerrainHoleData(); + + if (terrain.terrainHoleIndex >= 0) + Debug.Assert(holeMap.resolution == heightMap.resolution - 1, $"Hole resolution {holeMap.resolution} should be heightmap resolution {heightMap.resolution} - 1."); + + // Find the instance data for this terrain to get the transform and material + for (int inst = 0; inst < bakeInput.instanceData.Length; inst++) + { + if (bakeInput.instanceData[inst].terrainIndex != i) + continue; + + ref readonly InstanceData instanceData = ref bakeInput.instanceData[inst]; + float4x4 localToWorldFloat4x4 = instanceData.transform; + Matrix4x4 localToWorldMatrix4x4 = new Matrix4x4(localToWorldFloat4x4.c0, localToWorldFloat4x4.c1, localToWorldFloat4x4.c2, localToWorldFloat4x4.c3); + + var materials = perInstanceSubMeshMaterials[inst]; + MaterialHandle terrainMaterial = materials.Length > 0 ? materials[0] : MaterialHandle.Invalid; + + uint mask = World.GetInstanceMask( + instanceData.castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off, + true, RenderedGameObjectsFilter.OnlyStatic); + + world.AddTerrainInstance( + heightMap.data, + heightMap.resolution, + terrain.heightmapScale, + holeMap.data, + holeMap.resolution, + terrainMaterial, + mask, + renderingObjectLayer, + localToWorldMatrix4x4); + break; + } + } + } + // Compute the tight UV scale and offset for each mesh. Vector2[] uvBoundsSizes = new Vector2[meshes.Length]; Vector2[] uvBoundsOffsets = new Vector2[meshes.Length]; @@ -573,8 +661,9 @@ internal static void ConvertInstancesAndMeshes( List fatInstanceList = new(); for (int i = 0; i < bakeInput.instanceData.Length; i++) { - // Get materials ref readonly InstanceData instanceData = ref bakeInput.instanceData[i]; + + // Get materials var materials = perInstanceSubMeshMaterials[i]; var visibility = perInstanceSubMeshVisibility[i]; @@ -589,8 +678,21 @@ internal static void ConvertInstancesAndMeshes( Vector2 uvBoundsSize = uvBoundsSizes[globalMeshIndex]; Vector2 uvBoundsOffset = uvBoundsOffsets[globalMeshIndex]; - // Calculate bounds - Bounds meshBounds = CalculateMeshBounds(mesh.vertices, localToWorldMatrix4x4, out Vector3 meshMinVertex, out Vector3 meshMaxVertex); + // Calculate bounds. For procedural terrain the quad mesh is in normalized UV space, + // so we must derive bounds from the heightmap extent and scale instead. + bool isProceduralTerrain = useProceduralTerrain && instanceData.terrainIndex >= 0; + Bounds meshBounds; + Vector3 meshMinVertex, meshMaxVertex; + if (isProceduralTerrain) + { + ref readonly LightBakerBridge.TerrainData terrain = ref bakeInput.terrainData[instanceData.terrainIndex]; + var heightMap = bakeInput.heightMapData[terrain.heightMapIndex]; + meshBounds = CalculateProceduralTerrainBounds(in heightMap, in terrain, localToWorldMatrix4x4, out meshMinVertex, out meshMaxVertex); + } + else + { + meshBounds = CalculateMeshBounds(mesh.vertices, localToWorldMatrix4x4, out meshMinVertex, out meshMaxVertex); + } // Keep track of scene bounds as we go sceneMinVertex = Vector3.Min(sceneMinVertex, meshMinVertex); @@ -605,8 +707,18 @@ internal static void ConvertInstancesAndMeshes( // add instance var boundingSphere = new BoundingSphere(); - boundingSphere.position = localToWorldMatrix4x4.MultiplyPoint(mesh.bounds.center); - boundingSphere.radius = (localToWorldMatrix4x4.MultiplyPoint(mesh.bounds.extents) - boundingSphere.position).magnitude; + if (isProceduralTerrain) + { + // For procedural terrain the mesh is a normalized-UV quad, so use the world-space + // bounds we just computed instead of mesh.bounds. + boundingSphere.position = meshBounds.center; + boundingSphere.radius = meshBounds.extents.magnitude; + } + else + { + boundingSphere.position = localToWorldMatrix4x4.MultiplyPoint(mesh.bounds.center); + boundingSphere.radius = (localToWorldMatrix4x4.MultiplyPoint(mesh.bounds.extents) - boundingSphere.position).magnitude; + } var lodIdentifier = new LodIdentifier(instanceData.lodGroup, instanceData.lodMask, instanceData.contributingLodLevel); var fatInstance = new FatInstance { @@ -623,7 +735,9 @@ internal static void ConvertInstancesAndMeshes( ReceiveShadows = instanceData.receiveShadows, Filter = filter, RenderingObjectLayer = renderingObjectLayer, - EnableEmissiveSampling = true + EnableEmissiveSampling = true, + IsProceduralTerrain = isProceduralTerrain, + TerrainIndex = instanceData.terrainIndex }; fatInstanceList.Add(fatInstance); } diff --git a/Packages/com.unity.render-pipelines.core/Editor/PathTracing/LightBakerStrangler.cs b/Packages/com.unity.render-pipelines.core/Editor/PathTracing/LightBakerStrangler.cs index e5c30c2d677..9b55f3c33de 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/PathTracing/LightBakerStrangler.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/PathTracing/LightBakerStrangler.cs @@ -59,6 +59,12 @@ internal static void AddContributingInstancesToWorld(World world, in FatInstance continue; } + // Procedural terrain is not added to the acceleration structure as a mesh. + // The procedural instance handles ray intersection, and GBuffer generation + // uses the heightmap directly (g_InstanceGeometryIndex == -1). + if (fatInstance.IsProceduralTerrain) + continue; + var instanceHandle = world.AddInstance( fatInstance.Mesh, fatInstance.Materials, @@ -277,7 +283,9 @@ internal static LightmapDesc[] PopulateLightmapDescsFromAtlassing(in PVRAtlassin fatInstance.LocalToWorldMatrix, fatInstance.ReceiveShadows, fatInstance.LodIdentifier, - bakeInputInstanceIndex); + bakeInputInstanceIndex, + fatInstance.IsProceduralTerrain, + fatInstance.TerrainIndex); ++instanceCounter; } @@ -405,13 +413,13 @@ private static ulong CalculateProbeWorkSteps(ulong count, ProbeRequestOutputType { ulong workSteps = 0; if (outputTypeMask.HasFlag(ProbeRequestOutputType.RadianceIndirect)) - workSteps += ProbeIntegrator.CalculateWorkSteps(count, effectiveIndirectSampleCount, bounceCount); + workSteps += ProbeIntegrator.CalculateWorkStepsIndirectRadiance(count, effectiveIndirectSampleCount, bounceCount); if (outputTypeMask.HasFlag(ProbeRequestOutputType.RadianceDirect)) - workSteps += ProbeIntegrator.CalculateWorkSteps(count, directSampleCount, 0); + workSteps += ProbeIntegrator.CalculateWorkStepsDirectRadiance(count, directSampleCount); if (outputTypeMask.HasFlag(ProbeRequestOutputType.Validity)) - workSteps += ProbeIntegrator.CalculateWorkSteps(count, effectiveIndirectSampleCount, 0); + workSteps += ProbeIntegrator.CalculateWorkStepsOcclusion(count, effectiveIndirectSampleCount); if (outputTypeMask.HasFlag(ProbeRequestOutputType.LightProbeOcclusion) && usesProbeOcclusion) - workSteps += ProbeIntegrator.CalculateWorkSteps(count, effectiveIndirectSampleCount, 0); + workSteps += ProbeIntegrator.CalculateWorkStepsValidity(count, effectiveIndirectSampleCount); return workSteps; } @@ -476,7 +484,7 @@ internal static LightmapBakeSettings GetLightmapBakeSettings(in LightingSettings // environment, we base the sample count on the number of emissive and environment lights. uint emissiveAndEnvLightCount = (uint)world.EnvLightCount + (uint)world.MeshLightCount; uint brdfSampleCount = emissiveAndEnvLightCount * lightingSettings.lightmapSampleCounts.directSampleCount; - if (lightingSettings.directEmissiveSamplingMode == EmissiveSamplingMode.LightSampling) + if (lightingSettings.directEmissiveSamplingMode == UnityEngine.PathTracing.Core.EmissiveSamplingMode.LightSampling) brdfSampleCount = 0; // Lightmap settings @@ -1018,7 +1026,9 @@ internal static Result ExecuteLightmapRequests( return Result.AddResourcesToCacheFailure; InstanceHandle[] currentLodInstances = PrepareLodInstances(cmd, lightmappingContext.World, bakeInstance, lodInstances, lodgroupToContributorInstances, false); - var instanceGeometryIndex = lightmappingContext.World.PathTracingWorld.GetAccelerationStructure().GeometryPool.GetInstanceGeometryIndex(bakeInstance.Mesh); + var instanceGeometryIndex = bakeInstance.IsProceduralTerrain + ? -1 + : lightmappingContext.World.PathTracingWorld.GetAccelerationStructure().GeometryPool.GetInstanceGeometryIndex(bakeInstance.Mesh); uint instanceWidth = (uint)bakeInstance.TexelSize.x; uint instanceHeight = (uint)bakeInstance.TexelSize.y; @@ -1068,6 +1078,7 @@ internal static Result ExecuteLightmapRequests( // geometry pool bindings Util.BindAccelerationStructure(cmd, normalShader, world.PathTracingWorld.GetAccelerationStructure()); Util.BindMaterialsAndTextures(cmd, normalShader, world.PathTracingWorld); + world.PathTracingWorld.GetAccelerationStructure().BindTerrainResources(cmd, normalShader); var requiredSizeInBytes = normalShader.GetTraceScratchBufferRequiredSizeInBytes((uint)chunkSize, 1, 1); if (requiredSizeInBytes > 0) @@ -1080,6 +1091,7 @@ internal static Result ExecuteLightmapRequests( normalShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorld, bakeInstance.LocalToWorldMatrix); normalShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorldNormals, bakeInstance.LocalToWorldMatrixNormals); normalShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.InstanceGeometryIndex, instanceGeometryIndex); + normalShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.TerrainIndex, bakeInstance.TerrainIndex); normalShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.InstanceWidth, (int)instanceWidth); normalShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.GBuffer, lightmappingContext.GBuffer); diff --git a/Packages/com.unity.render-pipelines.core/Editor/PostProcessing/LensFlareDataSRPEditor.cs b/Packages/com.unity.render-pipelines.core/Editor/PostProcessing/LensFlareDataSRPEditor.cs index 59883894eb0..53bcdfdd11b 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/PostProcessing/LensFlareDataSRPEditor.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/PostProcessing/LensFlareDataSRPEditor.cs @@ -1275,7 +1275,7 @@ void DrawLensFlareDataSRPFieldWithCycleDetection(Rect rect, SerializedProperty l // Recursive function to check if targetAsset is found in asset's dependency chain bool CheckCycle(LensFlareDataSRP asset, LensFlareDataSRP targetAsset) { - if (asset == null || visited.Contains(asset)) + if (asset == null || asset.elements == null || visited.Contains(asset)) return false; visited.Add(asset); diff --git a/Packages/com.unity.render-pipelines.core/Editor/SampleDependencyImportSystem/SampleDependencyImporter.cs b/Packages/com.unity.render-pipelines.core/Editor/SampleDependencyImportSystem/SampleDependencyImporter.cs index 6ae1a448d9c..06c60ab8e89 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/SampleDependencyImportSystem/SampleDependencyImporter.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/SampleDependencyImportSystem/SampleDependencyImporter.cs @@ -1,6 +1,8 @@ +using System; using System.Collections.Generic; using System.IO; using UnityEditor; +using UnityEditor.PackageManager; using UnityEditor.PackageManager.UI; using UnityEngine; using UnityEngine.UIElements; @@ -60,12 +62,10 @@ VisualElement IPackageManagerExtension.CreateExtensionUI() injectingElement = new VisualElement(); injectingElement.style.display = DisplayStyle.None; - // This callback is called once the element is added to the UI, at this point we should have access to rest of the elements. injectingElement.RegisterCallback((callback) => { - //Force clear the cached elements to fetch those from the newly openned window + // Clear cached elements when panel is attached _panelRoot = null; samplesButton = null; - RefreshSampleButtons(); }); @@ -73,108 +73,284 @@ VisualElement IPackageManagerExtension.CreateExtensionUI() } Button samplesButton; + Button m_InjectedDetailsButton; + bool m_IsOnAllSamplesTab; + const string samplesButtonName = "samplesButton"; - const string sampleContainerClassName = "sampleContainer"; - const string importButtonClassName = "actionButton"; + const string samplesListContainerClassName = "sampleContainer"; + const string importButtonClassName = "actionButtonsContainer"; const string injectedButtonClassName = "importWithDependenciesButton"; internal void RefreshSampleButtons() { - if (injectingElement == null || m_PackageInfo == null || m_SampleList == null || panelRoot == null) - return; - - // Call refresh of samples and button injection when switching to the "Samples" tab. - if (samplesButton == null) + if (m_IsOnAllSamplesTab) + { + RefreshSampleButtonInDetailsView(); + } + else + { + RefreshSampleButtonInListView(); + } + } + + internal void RefreshSampleButtonInListView() + { + if (injectingElement == null || m_PackageInfo == null || m_SampleList == null || panelRoot == null) + return; + + // Hook up to the "Samples" tab button click event + if (samplesButton == null) + { + samplesButton = panelRoot.Q