// Check all light maps referenced within the current batch of converted Renderers.
        // Any references to light maps that have already been inserted into a LightMaps array
        // will be implemented by reusing the existing LightMaps object. Any leftover previously
        // unseen (or changed = content hash changed) light maps are combined into a new LightMaps array.
        public void ProcessLightMapsForConversion()
        {
            var lightmaps     = LightmapSettings.lightmaps;
            var uniqueIndices = m_UsedLightmapIndices
                                .Distinct()
                                .OrderBy(x => x)
                                .Where(x => x >= 0 && x != 65534 && x < lightmaps.Length)
                                .ToArray();

            var colors          = new List <Texture2D>();
            var directions      = new List <Texture2D>();
            var shadowMasks     = new List <Texture2D>();
            var lightMapIndices = new List <int>();

            // Each light map reference is converted into a LightMapKey which identifies the light map
            // using the content hashes regardless of the index number. Previously encountered light maps
            // should be found from the cache even if their index number has changed. New or changed
            // light maps are placed into a new array.
            for (var i = 0; i < uniqueIndices.Length; i++)
            {
                var index        = uniqueIndices[i];
                var lightmapData = lightmaps[index];
                var key          = new LightMapKey(lightmapData);

                if (m_LightMapArrayCache.TryGetValue(key, out var lightMapRef))
                {
                    m_LightMapReferences[index] = lightMapRef;
                    ++m_NumLightMapCacheHits;
                }
                else
                {
                    colors.Add(lightmapData.lightmapColor);
                    directions.Add(lightmapData.lightmapDir);
                    shadowMasks.Add(lightmapData.shadowMask);
                    lightMapIndices.Add(index);
                    ++m_NumLightMapCacheMisses;
                }
            }

            if (lightMapIndices.Count > 0)
            {
#if DEBUG_LOG_LIGHT_MAP_CONVERSION
                Debug.Log($"Creating new DOTS light map array from {lightMapIndices.Count} light maps.");
#endif

                var lightMapArray = LightMaps.ConstructLightMaps(colors, directions, shadowMasks);

                for (int i = 0; i < lightMapIndices.Count; ++i)
                {
                    var lightMapRef = new LightMapReference
                    {
                        LightMaps     = lightMapArray,
                        LightMapIndex = i,
                    };

                    m_LightMapReferences[lightMapIndices[i]] = lightMapRef;
                    m_LightMapArrayCache[new LightMapKey(colors[i], directions[i], shadowMasks[i])] = lightMapRef;
                }
            }
        }
Example #2
0
        protected override void OnUpdate()
        {
            var globalToLocalLightmapMap = new Dictionary <int, int>();

#if UNITY_2020_2_OR_NEWER
            var usedIndicies = new List <int>();
            Entities.WithNone <TextMesh>().ForEach((MeshRenderer meshRenderer, MeshFilter meshFilter) =>
            {
                usedIndicies.Add(meshRenderer.lightmapIndex);
            });

            var setting       = LightmapSettings.lightmaps;
            var uniqueIndices = usedIndicies.Distinct().OrderBy(x => x).Where(x => x >= 0 && x != 65534 && x < setting.Length).ToArray();

            var colors      = new List <Texture2D>();
            var directions  = new List <Texture2D>();
            var shadowMasks = new List <Texture2D>();

            for (var i = 0; i < uniqueIndices.Length; i++)
            {
                var index = uniqueIndices[i];
                colors.Add(setting[index].lightmapColor);
                directions.Add(setting[index].lightmapDir);
                shadowMasks.Add(setting[index].shadowMask);
                globalToLocalLightmapMap.Add(index, i);
            }

            var lightMaps = LightMaps.ConstructLightMaps(colors, directions, shadowMasks);
#else
            var lightMaps = new LightMaps();
#endif
            var sourceMaterials  = new List <Material>(10);
            var createdMaterials = new Dictionary <MaterialLookupKey, Material>();

            Entities.WithNone <TextMesh>().ForEach((MeshRenderer meshRenderer, MeshFilter meshFilter) =>
            {
                var mesh = meshFilter.sharedMesh;
                meshRenderer.GetSharedMaterials(sourceMaterials);

                if (!globalToLocalLightmapMap.TryGetValue(meshRenderer.lightmapIndex, out var lightmapIndex))
                {
                    lightmapIndex = meshRenderer.lightmapIndex;
                }

                if (mesh != null)
                {
                    Convert(DstEntityManager, this, AttachToPrimaryEntityForSingleMaterial, meshRenderer, mesh, sourceMaterials,
                            createdMaterials, lightMaps, lightmapIndex, meshRenderer.transform, mesh.bounds.ToAABB());
                }
            });
        }
        private static Material CreateLightMappedMaterial(Material material, LightMaps lightMaps)
        {
            var lightMappedMaterial = new Material(material);

            lightMappedMaterial.name = $"{lightMappedMaterial.name}_Lightmapped_";
            lightMappedMaterial.EnableKeyword("LIGHTMAP_ON");

            lightMappedMaterial.SetTexture("unity_Lightmaps", lightMaps.colors);
            lightMappedMaterial.SetTexture("unity_LightmapsInd", lightMaps.directions);
            lightMappedMaterial.SetTexture("unity_ShadowMasks", lightMaps.shadowMasks);

            if (lightMaps.hasDirections)
            {
                lightMappedMaterial.name = lightMappedMaterial.name + "_DIRLIGHTMAP";
                lightMappedMaterial.EnableKeyword("DIRLIGHTMAP_COMBINED");
            }

            if (lightMaps.hasShadowMask)
            {
                lightMappedMaterial.name = lightMappedMaterial.name + "_SHADOW_MASK";
            }

            return(lightMappedMaterial);
        }
Example #4
0
        public static void Convert(
            EntityManager dstEntityManager,
            GameObjectConversionSystem conversionSystem,
            bool attachToPrimaryEntityForSingleMaterial,
            Renderer meshRenderer,
            Mesh mesh,
            List <Material> materials,
            Dictionary <MaterialLookupKey, Material> createdMaterials,
            LightMaps lightMaps,
            int lightmapIndex,
            Transform root,
            AABB localBounds)
        {
            var materialCount = materials.Count;

            // Don't add RenderMesh (and other required components) unless both mesh and material are assigned.
            if (mesh == null || materialCount == 0)
            {
                Debug.LogWarning(
                    "MeshRenderer is not converted because either the assigned mesh is null or no materials are assigned.",
                    meshRenderer);
                return;
            }

            //@TODO: Transform system should handle RenderMeshFlippedWindingTag automatically. This should not be the responsibility of the conversion system.
            float4x4 localToWorld = root.localToWorldMatrix;
            var      flipWinding  = math.determinant(localToWorld) < 0.0;

            if (materialCount == 1 && attachToPrimaryEntityForSingleMaterial)
            {
                var meshEntity = conversionSystem.GetPrimaryEntity(meshRenderer);

                AddComponentsToEntity(
                    meshEntity,
                    dstEntityManager,
                    conversionSystem,
                    meshRenderer,
                    mesh,
                    materials,
                    createdMaterials,
                    flipWinding,
                    0,
                    lightMaps,
                    lightmapIndex,
                    localBounds);
            }
            else
            {
                var rootEntity = conversionSystem.GetPrimaryEntity(root);

                for (var m = 0; m != materialCount; m++)
                {
                    var meshEntity = conversionSystem.CreateAdditionalEntity(meshRenderer);

                    dstEntityManager.AddComponentData(meshEntity, new LocalToWorld {
                        Value = localToWorld
                    });
                    if (!dstEntityManager.HasComponent <Static>(meshEntity))
                    {
                        dstEntityManager.AddComponentData(meshEntity, new Parent {
                            Value = rootEntity
                        });
                        dstEntityManager.AddComponentData(meshEntity,
                                                          new LocalToParent {
                            Value = float4x4.identity
                        });
                    }

                    AddComponentsToEntity(
                        meshEntity,
                        dstEntityManager,
                        conversionSystem,
                        meshRenderer,
                        mesh,
                        materials,
                        createdMaterials,
                        flipWinding,
                        m,
                        lightMaps,
                        lightmapIndex,
                        localBounds);
                }
            }
        }
Example #5
0
        private static void AddComponentsToEntity(
            Entity entity,
            EntityManager dstEntityManager,
            GameObjectConversionSystem conversionSystem,
            Renderer meshRenderer,
            Mesh mesh,
            List <Material> materials,
            Dictionary <MaterialLookupKey, Material> createdMaterials,
            bool flipWinding,
            int id,
            LightMaps lightMaps,
            int lightmapIndex,
            AABB localBounds)
        {
            var needMotionVectorPass = (meshRenderer.motionVectorGenerationMode == MotionVectorGenerationMode.Object) ||
                                       (meshRenderer.motionVectorGenerationMode == MotionVectorGenerationMode.ForceNoMotion);

            var renderMesh = new RenderMesh
            {
                mesh                 = mesh,
                castShadows          = meshRenderer.shadowCastingMode,
                receiveShadows       = meshRenderer.receiveShadows,
                layer                = meshRenderer.gameObject.layer,
                subMesh              = id,
                needMotionVectorPass = needMotionVectorPass
            };

            var staticLightingMode = StaticLightingMode.None;

            if (meshRenderer.lightmapIndex >= 65534 || meshRenderer.lightmapIndex < 0)
            {
                staticLightingMode = StaticLightingMode.LightProbes;
            }
            else if (meshRenderer.lightmapIndex >= 0)
            {
                staticLightingMode = StaticLightingMode.Lightmapped;
            }

            dstEntityManager.AddComponentData(entity, new PerInstanceCullingTag());
            dstEntityManager.AddComponentData(entity, new RenderBounds {
                Value = localBounds
            });

            var material = materials[id];

            if (staticLightingMode == StaticLightingMode.Lightmapped && lightMaps.isValid)
            {
                conversionSystem.DeclareAssetDependency(meshRenderer.gameObject, material);

                var localFlags = LightMappingFlags.Lightmapped;
                if (lightMaps.hasDirections)
                {
                    localFlags |= LightMappingFlags.Directional;
                }
                if (lightMaps.hasShadowMask)
                {
                    localFlags |= LightMappingFlags.ShadowMask;
                }

                var key = new MaterialLookupKey
                {
                    BaseMaterial = materials[id],
                    lightmaps    = lightMaps,
                    Flags        = localFlags
                };

                var lookUp = createdMaterials ?? new Dictionary <MaterialLookupKey, Material>();
                if (lookUp.TryGetValue(key, out Material result))
                {
                    material = result;
                }
                else
                {
                    material      = new Material(materials[id]);
                    material.name = $"{material.name}_Lightmapped_";
                    material.EnableKeyword("LIGHTMAP_ON");

                    material.SetTexture("unity_Lightmaps", lightMaps.colors);
                    material.SetTexture("unity_LightmapsInd", lightMaps.directions);
                    material.SetTexture("unity_ShadowMasks", lightMaps.shadowMasks);

                    if (lightMaps.hasDirections)
                    {
                        material.name = material.name + "_DIRLIGHTMAP";
                        material.EnableKeyword("DIRLIGHTMAP_COMBINED");
                    }

                    if (lightMaps.hasShadowMask)
                    {
                        material.name = material.name + "_SHADOW_MASK";
                    }

                    lookUp[key] = material;
                }
                dstEntityManager.AddComponentData(entity, new BuiltinMaterialPropertyUnity_LightmapST()
                {
                    Value = meshRenderer.lightmapScaleOffset
                });
                dstEntityManager.AddComponentData(entity, new BuiltinMaterialPropertyUnity_LightmapIndex()
                {
                    Value = lightmapIndex
                });
                dstEntityManager.AddSharedComponentData(entity, lightMaps);
            }
            else if (staticLightingMode == StaticLightingMode.LightProbes)
            {
                if (meshRenderer.lightProbeUsage == LightProbeUsage.CustomProvided)
                {
                    dstEntityManager.AddComponent <CustomProbeTag>(entity);
                }
                else if (meshRenderer.lightProbeUsage == LightProbeUsage.BlendProbes &&
                         LightmapSettings.lightProbes != null &&
                         LightmapSettings.lightProbes.count > 0)
                {
                    dstEntityManager.AddComponent <BlendProbeTag>(entity);
                }
                else
                {
                    dstEntityManager.AddComponent <AmbientProbeTag>(entity);
                }
            }
            renderMesh.material = material;

            dstEntityManager.AddSharedComponentData(entity, renderMesh);

            if (flipWinding)
            {
                dstEntityManager.AddComponent(entity, ComponentType.ReadWrite <RenderMeshFlippedWindingTag>());
            }

            conversionSystem.ConfigureEditorRenderData(entity, meshRenderer.gameObject, true);

#if ENABLE_HYBRID_RENDERER_V2
            dstEntityManager.AddComponent(entity, ComponentType.ReadOnly <WorldToLocal_Tag>());

#if HDRP_9_0_0_OR_NEWER
            // HDRP previous frame matrices (for motion vectors)
            if (needMotionVectorPass)
            {
                dstEntityManager.AddComponent(entity, ComponentType.ReadWrite <BuiltinMaterialPropertyUnity_MatrixPreviousM>());
                dstEntityManager.AddComponent(entity, ComponentType.ReadWrite <BuiltinMaterialPropertyUnity_MatrixPreviousMI_Tag>());
            }
            dstEntityManager.AddComponentData(entity, CreateMotionVectorsParams(ref renderMesh, ref meshRenderer));
#endif

            dstEntityManager.AddComponentData(entity, new BuiltinMaterialPropertyUnity_RenderingLayer
            {
                Value = new uint4(meshRenderer.renderingLayerMask, 0, 0, 0)
            });

            dstEntityManager.AddComponentData(entity, new BuiltinMaterialPropertyUnity_WorldTransformParams
            {
                Value = flipWinding ? new float4(0, 0, 0, -1) : new float4(0, 0, 0, 1)
            });

#if URP_9_0_0_OR_NEWER
            // Default initialized light data for URP
            dstEntityManager.AddComponentData(entity, new BuiltinMaterialPropertyUnity_LightData
            {
                Value = new float4(0, 0, 1, 0)
            });
#endif
#endif
        }