Example #1
0
 internal ShadowContainer(RenderTexture texture,
                          ShadowSettingSnapshot snapshot,
                          int padding,
                          Vector2 pxMisalignmentAtMinLS)
 {
     Texture  = texture;
     Snapshot = snapshot;
     Padding  = padding;
     PxMisalignmentAtMinLS = pxMisalignmentAtMinLS;
     RefCount    = 1;
     requestHash = snapshot.GetHashCode();
 }
        // public int createdContainerCount;
        // public int releasedContainerCount;

        internal void Get(ShadowSettingSnapshot snapshot, ref ShadowContainer container)
        {
            if (float.IsNaN(snapshot.dimensions.x) || snapshot.dimensions.x < 1 ||
                float.IsNaN(snapshot.dimensions.y) || snapshot.dimensions.y < 1)
            {
                ReleaseContainer(container);
                return;
            }

#if LETAI_TRUESHADOW_DEBUG
            RenderTexture.ReleaseTemporary(debugTexture);
            if (snapshot.shadow.alwaysRender)
            {
                debugTexture = GenerateShadow(snapshot).Texture;
            }
#endif

            // Each request need a coresponding shadow texture
            // Texture may be shared by multiple elements
            // Texture are released when no longer used by any element
            // ShadowContainer keep track of texture and their usage


            int requestHash = snapshot.GetHashCode();

            // Case: requester can keep the same texture
            if (container?.requestHash == requestHash)
            {
                return;
            }

            ReleaseContainer(container);

            if (shadowCache.TryGetValue(requestHash, out var existingContainer))
            {
                // Case: requester got texture from someone else
                existingContainer.RefCount++;
                container = existingContainer;
            }
            else
            {
                // Case: requester got new unique texture
                container = shadowCache[requestHash] = GenerateShadow(snapshot);
                // Debug.Log($"Created new container for request\t{requestHash}\tTotal Created: {++createdContainerCount}\t Alive: {createdContainerCount - releasedContainerCount}");
            }
        }
        ShadowContainer GenerateShadow(ShadowSettingSnapshot snapshot)
        {
            // return GenColoredTexture(request.GetHashCode());

            cmd.Clear();
            cmd.BeginSample("TrueShadow:Capture");

            var bounds       = snapshot.shadow.SpriteMesh.bounds;
            var misalignment = CalcMisalignment(snapshot.canvas, snapshot.canvasRt, snapshot.shadow.RectTransform, bounds);

            var padding      = Mathf.CeilToInt(snapshot.size);
            var imprintViewW = Mathf.RoundToInt(snapshot.dimensions.x + misalignment.bothSS.x);
            var imprintViewH = Mathf.RoundToInt(snapshot.dimensions.y + misalignment.bothSS.y);
            var tw           = imprintViewW + padding * 2;
            var th           = imprintViewH + padding * 2;

            var shadowTex      = RenderTexture.GetTemporary(tw, th, 0, RenderTextureFormat.ARGB32);
            var imprintTexDesc = shadowTex.descriptor;

            imprintTexDesc.msaaSamples = snapshot.shouldAntialiasImprint ? Mathf.Max(1, QualitySettings.antiAliasing) : 1;
            var imprintTex = RenderTexture.GetTemporary(imprintTexDesc);

            RenderTexture imprintTexProcessed = null;

            bool needProcessImprint = snapshot.shadow.IgnoreCasterColor || snapshot.shadow.Inset;

            if (needProcessImprint)
            {
                imprintTexProcessed = RenderTexture.GetTemporary(imprintTexDesc);
            }

            var texture = snapshot.shadow.Content;

            if (texture)
            {
                materialProps.SetTexture(ShaderId.MAIN_TEX, texture);
            }
            else
            {
                materialProps.SetTexture(ShaderId.MAIN_TEX, Texture2D.whiteTexture);
            }

            cmd.SetRenderTarget(imprintTex);
            cmd.ClearRenderTarget(true, true, snapshot.shadow.ClearColor);

            cmd.SetViewport(new Rect(padding, padding, imprintViewW, imprintViewH));

            var imprintBoundMin = (Vector2)bounds.min - misalignment.minLS;
            var imprintBoundMax = (Vector2)bounds.max + misalignment.maxLS;

            cmd.SetViewProjectionMatrices(
                Matrix4x4.identity,
                Matrix4x4.Ortho(imprintBoundMin.x, imprintBoundMax.x,
                                imprintBoundMin.y, imprintBoundMax.y,
                                -1, 1)
                );

            snapshot.shadow.ModifyShadowCastingMesh(snapshot.shadow.SpriteMesh);
            snapshot.shadow.ModifyShadowCastingMaterialProperties(materialProps);
            cmd.DrawMesh(snapshot.shadow.SpriteMesh,
                         Matrix4x4.identity,
                         snapshot.shadow.GetShadowCastingMaterial(),
                         0, 0,
                         materialProps);

            if (needProcessImprint)
            {
                ImprintPostProcessMaterial.SetKeyword("BLEACH", snapshot.shadow.IgnoreCasterColor);
                ImprintPostProcessMaterial.SetKeyword("INSET", snapshot.shadow.Inset);

                cmd.Blit(imprintTex, imprintTexProcessed, ImprintPostProcessMaterial);
            }

            cmd.EndSample("TrueShadow:Capture");

            var needPostProcess = snapshot.shadow.Spread > 1e-3;

            cmd.BeginSample("TrueShadow:Cast");
            RenderTexture blurSrc = needProcessImprint ? imprintTexProcessed : imprintTex;
            RenderTexture blurDst;

            if (needPostProcess)
            {
                blurDst = RenderTexture.GetTemporary(shadowTex.descriptor);
            }
            else
            {
                blurDst = shadowTex;
            }

            if (snapshot.size < 1e-2)
            {
                cmd.Blit(blurSrc, blurDst);
            }
            else
            {
                blurConfig.Strength = snapshot.size;
                blurProcessor.Blur(cmd, blurSrc, UNIT_RECT, blurDst);
            }

            cmd.EndSample("TrueShadow:Cast");

            var relativeOffset = new Vector2(snapshot.canvasRelativeOffset.x / tw,
                                             snapshot.canvasRelativeOffset.y / th);
            var overflowAlpha = snapshot.shadow.Inset ? 1 : 0;

            if (needPostProcess)
            {
                cmd.BeginSample("TrueShadow:PostProcess");

                ShadowPostProcessMaterial.SetTexture(ShaderId.SHADOW_TEX, blurDst);
                ShadowPostProcessMaterial.SetVector(ShaderId.OFFSET, relativeOffset);
                ShadowPostProcessMaterial.SetFloat(ShaderId.OVERFLOW_ALPHA, overflowAlpha);
                ShadowPostProcessMaterial.SetFloat(ShaderId.ALPHA_MULTIPLIER,
                                                   1f / Mathf.Max(1e-6f, 1f - snapshot.shadow.Spread));

                cmd.SetViewport(UNIT_RECT);
                cmd.Blit(blurSrc, shadowTex, ShadowPostProcessMaterial);

                cmd.EndSample("TrueShadow:PostProcess");
            }
            else if (snapshot.shadow.Cutout)
            {
                cmd.BeginSample("TrueShadow:Cutout");

                CutoutMaterial.SetVector(ShaderId.OFFSET, relativeOffset);
                CutoutMaterial.SetFloat(ShaderId.OVERFLOW_ALPHA, overflowAlpha);

                cmd.SetViewport(UNIT_RECT);
                cmd.Blit(blurSrc, shadowTex, CutoutMaterial);

                cmd.EndSample("TrueShadow:Cutout");
            }

            Graphics.ExecuteCommandBuffer(cmd);

            RenderTexture.ReleaseTemporary(imprintTex);
            RenderTexture.ReleaseTemporary(blurSrc);
            if (needPostProcess)
            {
                RenderTexture.ReleaseTemporary(blurDst);
            }

            return(new ShadowContainer(shadowTex, snapshot, padding, misalignment.minLS));
        }