Пример #1
0
        /// <summary>
        /// Can be used to change the material of a prototype at runtime
        /// </summary>
        /// <param name="manager">GPUI Manager</param>
        /// <param name="prototype">GPUI Prototype</param>
        /// <param name="material">New material to set on the renderer</param>
        /// <param name="lodLevel">LOD level</param>
        /// <param name="rendererIndex">Renderer index on the LOD level</param>
        /// <param name="subMeshIndex">Submesh index of the renderer</param>
        public static void ChangeMaterial(GPUInstancerManager manager, GPUInstancerPrototype prototype, Material material, int lodLevel = 0, int rendererIndex = 0, int subMeshIndex = 0)
        {
            GPUInstancerRuntimeData runtimeData = manager.GetRuntimeData(prototype, true);

            if (runtimeData == null)
            {
                return;
            }
            GPUInstancerRenderer gpuiRenderer = runtimeData.instanceLODs[lodLevel].renderers[rendererIndex];

            // Generate proxy GO with a Mesh Renderer to get material property blocks
            GameObject   proxyGameObject = new GameObject("ProxyGO");
            MeshFilter   meshFilter      = proxyGameObject.AddComponent <MeshFilter>();
            MeshRenderer proxyRenderer   = proxyGameObject.AddComponent <MeshRenderer>();

            // Set mesh to proxy GO
            meshFilter.mesh = gpuiRenderer.mesh;
            // Set new material to runtime data
            gpuiRenderer.materials[subMeshIndex] = GPUInstancerConstants.gpuiSettings.shaderBindings.GetInstancedMaterial(material);
            // Set new material to proxy GO
            proxyRenderer.materials[subMeshIndex] = material;
            // Get material property blocks
            proxyRenderer.GetPropertyBlock(gpuiRenderer.mpb);
            if (gpuiRenderer.shadowMPB != null)
            {
                proxyRenderer.GetPropertyBlock(gpuiRenderer.shadowMPB);
            }

            // Destroy proxy GO
            GameObject.Destroy(proxyGameObject);

            // Setup new materials for instancing
            GPUInstancerUtility.SetAppendBuffers(runtimeData);
        }
Пример #2
0
        /// <summary>
        /// Can be used to change the mesh of a prototype at runtime
        /// </summary>
        /// <param name="manager">GPUI Manager</param>
        /// <param name="prototype">GPUI Prototype</param>
        /// <param name="mesh">New mesh to set on the renderer</param>
        /// <param name="lodLevel">LOD level</param>
        /// <param name="rendererIndex">Renderer index on the LOD level</param>
        /// <param name="subMeshIndex">Submesh index of the renderer</param>
        public static void ChangeMesh(GPUInstancerManager manager, GPUInstancerPrototype prototype, Mesh mesh, int lodLevel = 0, int rendererIndex = 0, int subMeshIndex = 0)
        {
            GPUInstancerRuntimeData runtimeData = manager.GetRuntimeData(prototype, true);

            if (runtimeData == null)
            {
                return;
            }
            GPUInstancerRenderer gpuiRenderer = runtimeData.instanceLODs[lodLevel].renderers[rendererIndex];

            if (gpuiRenderer.mesh.subMeshCount != mesh.subMeshCount)
            {
                Debug.LogError("ChangeMesh method can not be used with a mesh that has different amount of submeshes than the original mesh.");
                return;
            }

            if (gpuiRenderer.mesh.vertexCount != mesh.vertexCount)
            {
                int argsLastIndex = gpuiRenderer.argsBufferOffset;
                // Setup the indirect renderer buffer:
                for (int j = 0; j < gpuiRenderer.mesh.subMeshCount; j++)
                {
                    runtimeData.args[argsLastIndex++] = gpuiRenderer.mesh.GetIndexCount(j); // index count per instance
                    runtimeData.args[argsLastIndex++] = 0;                                  // (uint)runtimeData.bufferSize;
                    runtimeData.args[argsLastIndex++] = gpuiRenderer.mesh.GetIndexStart(j); // start index location
                    runtimeData.args[argsLastIndex++] = 0;                                  // base vertex location
                    runtimeData.args[argsLastIndex++] = 0;                                  // start instance location
                }
                runtimeData.argsBuffer.SetData(runtimeData.args);
            }

            gpuiRenderer.mesh = mesh;
        }
Пример #3
0
        public virtual void DrawRegisteredPrefabsBoxList()
        {
            if (Application.isPlaying && _manager.runtimeDataList != null && _manager.runtimeDataList.Count > 0)
            {
                int totalInsanceCount   = 0;
                int totalDrawCallCount  = 0;
                int totalShadowDrawCall = 0;
                foreach (GPUInstancerRuntimeData runtimeData in _manager.runtimeDataList)
                {
                    if (runtimeData == null)
                    {
                        continue;
                    }

                    int drawCallCount       = 0;
                    int shadowDrawCallCount = 0;
                    if (runtimeData.transformationMatrixVisibilityBuffer != null && runtimeData.instanceLODs != null && runtimeData.bufferSize > 0 && runtimeData.instanceCount > 0)
                    {
                        for (int i = 0; i < runtimeData.instanceLODs.Count; i++)
                        {
                            for (int j = 0; j < runtimeData.instanceLODs[i].renderers.Count; j++)
                            {
                                GPUInstancerRenderer gpuiRenderer = runtimeData.instanceLODs[i].renderers[j];
                                if (!GPUInstancerUtility.IsInLayer(prop_layerMask.intValue, gpuiRenderer.layer))
                                {
                                    continue;
                                }
                                drawCallCount += gpuiRenderer.materials.Count;
                                if (runtimeData.prototype.isShadowCasting && gpuiRenderer.castShadows)
                                {
                                    shadowDrawCallCount += gpuiRenderer.materials.Count * QualitySettings.shadowCascades;
                                }
                            }
                        }
                    }
                    GUILayout.Label(runtimeData.prototype.ToString() + " Instance Count: " + runtimeData.instanceCount +
                                    "\n" + runtimeData.prototype.ToString() + " Geometry Draw Call Count: " + drawCallCount +
                                    (shadowDrawCallCount > 0 ? "\n" + runtimeData.prototype.ToString() + " Shadow Draw Call Count: " + shadowDrawCallCount : ""), GPUInstancerEditorConstants.Styles.label);

                    totalInsanceCount   += runtimeData.instanceCount;
                    totalDrawCallCount  += drawCallCount;
                    totalShadowDrawCall += shadowDrawCallCount;
                }

                GUILayout.Label("\nTotal Instance Count: " + totalInsanceCount +
                                "\n\n" + "Total Geometry Draw Call Count: " + totalDrawCallCount +
                                "\n" + "Total Shadow Draw Call Count: " + totalShadowDrawCall + " (" + QualitySettings.shadowCascades + " Cascades)" +
                                "\n\n" + "Total Draw Call Count: " + (totalDrawCallCount + totalShadowDrawCall)
                                , GPUInstancerEditorConstants.Styles.boldLabel);
            }
            else
            {
                GPUInstancerEditorConstants.DrawCustomLabel("No registered prefabs.", GPUInstancerEditorConstants.Styles.label, false);
            }
        }
Пример #4
0
        /// <summary>
        /// Adds a renderer to an LOD. Renderers define the meshes and materials to render for a given instance prototype LOD.
        /// </summary>
        /// <param name="lod">The LOD to add this renderer to. LOD indices start from 0.</param>
        /// <param name="mesh">The mesh that this renderer will use.</param>
        /// <param name="materials">The list of materials that this renderer will use (must be GPU Instancer compatible materials)</param>
        /// <param name="transformOffset">The transformation matrix that represents a change in position, rotation and scale
        /// for this renderer as an offset from the instance prototype. This matrix will be applied to the prototype instance
        /// matrix for final rendering calculations in the shader. Use Matrix4x4.Identity if no offset is desired.</param>
        public virtual void AddRenderer(int lod, Mesh mesh, List <Material> materials, Matrix4x4 transformOffset, MaterialPropertyBlock mpb, bool castShadows,
                                        int layer = 0, MaterialPropertyBlock shadowMPB = null, Renderer rendererRef = null)
        {
            if (instanceLODs == null || instanceLODs.Count <= lod || instanceLODs[lod] == null)
            {
                Debug.LogError("Can't add renderer: Invalid LOD");
                return;
            }

            if (mesh == null)
            {
                Debug.LogError("Can't add renderer: mesh is null. Make sure that all the MeshFilters on the objects has a mesh assigned.");
                return;
            }

            if (materials == null || materials.Count == 0)
            {
                Debug.LogError("Can't add renderer: no materials. Make sure that all the MeshRenderers have their materials assigned.");
                return;
            }

            if (instanceLODs[lod].renderers == null)
            {
                instanceLODs[lod].renderers = new List <GPUInstancerRenderer>();
            }

            GPUInstancerRenderer renderer = new GPUInstancerRenderer
            {
                mesh            = mesh,
                materials       = materials,
                transformOffset = transformOffset,
                mpb             = mpb,
                shadowMPB       = shadowMPB,
                layer           = layer,
                castShadows     = castShadows,
                rendererRef     = rendererRef
            };

            instanceLODs[lod].renderers.Add(renderer);
            CalculateBounds();
        }