Exemple #1
0
        // todo for tomorrow
        // stop allocating meshes, pool materials
        // handle not drawing screen aligned clipping bounds
        // handle multiple clip shapes in a path
        // maybe handle textures
        // handle lots of clip shapes
        // handle masking channels
        // profile

        public void ConstructClipData()
        {
            maskPackerR.Clear();
            maskPackerG.Clear();
            maskPackerB.Clear();
            maskPackerA.Clear();
            // todo -- profile sorting by size
            // might not need the -1 if screen level one is never sent
            // also don't need to render clipper for a view since it is automatically rectangular
            // basically any pure screen aligned rectangle doesn't need to be rendered out
            for (int i = 0; i < clippers.size; i++)
            {
                ClipData clipData = clippers.array[i];

                if (clipData.clipPath == null)
                {
                    float xy = VertigoUtil.PackSizeVector(new Vector2(clipData.aabb.x, clipData.aabb.y));
                    float zw = VertigoUtil.PackSizeVector(new Vector2(clipData.aabb.z, clipData.aabb.w));
                    clipData.packedBoundsAndChannel.x = xy;
                    clipData.packedBoundsAndChannel.y = zw;
                    continue;
                }

                clipData.zIndex = i + 1; // will have to change depending on how we decide to handle different channels

                int width  = (int)(clipData.aabb.z - clipData.aabb.x);
                int height = (int)(clipData.aabb.w - clipData.aabb.y);
                SimpleRectPacker.PackedRect region;

                clipData.textureChannel = -1;
                if (maskPackerR.TryPackRect(width, height, out region))
                {
                    clipData.textureChannel = 0;
                }
                // todo -- other channels don't work right now, need to figure out if we use additional draw calls or super double dip region packing
//                else if (maskPackerG.TryPackRect(width, height, out region)) {
//                    clipData.textureChannel = 1;
//                }
//                else if (maskPackerB.TryPackRect(width, height, out region)) {
//                    clipData.textureChannel = 2;
//                }
//                else if (maskPackerA.TryPackRect(width, height, out region)) {
//                    clipData.textureChannel = 3;
//                }
                else
                {
                    Debug.Log($"Can't fit {width}, {height} into clip texture");
                }

                // note this is in 2 point form, not height & width
                if (clipData.textureChannel != -1)
                {
                    clipData.clipTexture   = clipTexture;
                    clipData.textureRegion = region;
                    clipData.clipUVs       = new Vector4(
                        region.xMin / (float)clipTexture.width,
                        region.yMin / (float)clipTexture.height,
                        region.xMax / (float)clipTexture.width,
                        region.yMax / (float)clipTexture.height
                        );
                    float xy = VertigoUtil.PackSizeVector(new Vector2(clipData.aabb.x, clipData.aabb.y));
                    float zw = VertigoUtil.PackSizeVector(new Vector2(clipData.aabb.z, clipData.aabb.w));
                    clipData.packedBoundsAndChannel.x = xy;
                    clipData.packedBoundsAndChannel.y = zw;
                    clipData.packedBoundsAndChannel.z = clipData.textureChannel;
                }
            }
        }
Exemple #2
0
        // depth buffer means our regions are locked per channel
        // 2 options: 1. each channel is its own set of draw calls, this is easy but maybe not as fast. do this as a first pass
        //            2. try to re-use regions for different channels, almost certainly leads to less throughput but faster since we don't need extra draw calls
        // probably means we have sub-sorting regions, ie large packers would have sub-packers
        // would definitely want to sort by size in that case and first try to pack larger regions into themselves
        // would likely update rect packer to be channel aware, when trying to place next item instead of moving over try colliding a different channel instead

        public void Clip(Camera camera, CommandBuffer commandBuffer)
        {
            // breaks on refresh if we don't do this :(
            this.clearMaterial.SetColor(s_Color, Color.white);
            this.clearCountMaterial.SetColor(s_Color, new Color(0, 0, 0, 0));
            requireRegionCounting = false;

            for (int i = 0; i < batchesToRender.size; i++)
            {
                batchesToRender[i].pooledMesh.Release();
                StructList <Matrix4x4> .Release(ref batchesToRender.array[i].transforms);

                StructList <Vector4> .Release(ref batchesToRender.array[i].objectData);

                StructList <Vector4> .Release(ref batchesToRender.array[i].colorData);
            }

            batchesToRender.Clear();
            Gather();

            Vector3 cameraOrigin = camera.transform.position;

            cameraOrigin.x -= 0.5f * Screen.width;
            cameraOrigin.y += (0.5f * Screen.height);
            cameraOrigin.z += 2;

            Matrix4x4 origin = Matrix4x4.TRS(cameraOrigin, Quaternion.identity, Vector3.one);

            LightList <ClipData> texturedClippers = LightList <ClipData> .Get();

            regionMesh?.Release();

            regionMesh = GetRegionMesh(out requireRegionCounting);

            clipTexture = RenderTexture.GetTemporary(Screen.width, Screen.height, 24, RenderTextureFormat.Default); // todo -- use lower resolution

#if DEBUG
            commandBuffer.BeginSample("UIFora Clip Draw");
#endif
            commandBuffer.SetRenderTarget(clipTexture);

            // probably don't need this actually, can bake it into clear. keep for debugging
            commandBuffer.ClearRenderTarget(true, true, Color.black);

            commandBuffer.DrawMesh(regionMesh.mesh, origin, clearMaterial, 0, 0);

            // todo -- handle multiple shapes from one path

            ClipBatch batch = new ClipBatch();
            batch.transforms = StructList <Matrix4x4> .Get();

            batch.colorData = StructList <Vector4> .Get();

            batch.objectData = StructList <Vector4> .Get();

            for (int i = 0; i < clippers.size; i++)
            {
                ClipData clipData = clippers[i];
                Path2D   clipPath = clipData.clipPath;

                if (clipPath == null)
                {
                    // todo if transform is not identity we need to generate a rotated or skewed rect for the clip shape
                    continue;
                }

                clipPath.UpdateGeometry(); // should early out if no update required

                if (AnyShapeUsesTextures(clipPath))
                {
                    // todo -- handle textures
                    // todo -- handle text
                    continue;
                }

                batch = DrawShapesInPath(batch, clipPath, clipData, clipData);

                for (int j = 0; j < clipData.dependents.size; j++)
                {
                    batch = DrawShapesInPath(batch, clipPath, clipData, clipData.dependents[j]);
                }
            }

            FinalizeBatch(batch, false);

            for (int i = 0; i < batchesToRender.size; i++)
            {
                ref ClipBatch clipBatch = ref batchesToRender.array[i];

                ClipPropertyBlock propertyBlock = clipMaterialPool.GetPropertyBlock(clipBatch.transforms.size);

                propertyBlock.SetData(clipBatch);

                commandBuffer.DrawMesh(clipBatch.pooledMesh.mesh, origin, clipDrawMaterial, 0, 0, propertyBlock.matBlock);
            }
Exemple #3
0
 internal void AddClipper(ClipData clipData)
 {
     clippers.Add(clipData);
 }