RenderTexture RenderShadow(ShadowRenderingRequest request)
        {
            // return GenColoredTexture(request.GetHashCode());

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

            var padding      = Mathf.CeilToInt(request.shadowSize);
            var imprintViewW = Mathf.CeilToInt(request.dimensions.x);
            var imprintViewH = Mathf.CeilToInt(request.dimensions.y);
            var tw           = imprintViewW + padding * 2;
            var th           = imprintViewH + padding * 2;
            var shadowTex    = RenderTexture.GetTemporary(tw, th, 0, RenderTextureFormat.Default);

            cmd.GetTemporaryRT(IMPRINT_TEX_ID, tw, th, 0, FilterMode.Bilinear, RenderTextureFormat.Default);

            bool needPostProcess = request.shadow.IgnoreCasterColor || request.shadow.Inset;

            if (needPostProcess)
            {
                cmd.GetTemporaryRT(IMPRINT_AFTER_POSTPROCESS_TEX_ID, tw, th, 0, FilterMode.Bilinear,
                                   RenderTextureFormat.Default);
            }

            var texture = request.shadow.Content;

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

            cmd.SetRenderTarget(IMPRINT_TEX_ID);
            cmd.ClearRenderTarget(true, true, request.shadow.ClearColor);

            cmd.SetViewport(new Rect(padding, padding, imprintViewW, imprintViewH));
            var bounds = request.rect;

            cmd.SetViewProjectionMatrices(
                Matrix4x4.identity,
                Matrix4x4.Ortho(bounds.min.x, bounds.max.x + bounds.width * (imprintViewW / request.dimensions.x - 1),
                                bounds.min.y, bounds.max.y + bounds.height * (imprintViewH / request.dimensions.y - 1),
                                -1, 1)
                );

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

            if (needPostProcess)
            {
                ImprintPostProcessMaterial.SetKeyword("BLEACH", request.shadow.IgnoreCasterColor);
                ImprintPostProcessMaterial.SetKeyword("INSET", request.shadow.Inset);

                cmd.Blit(IMPRINT_TEX_ID, IMPRINT_AFTER_POSTPROCESS_TEX_ID, ImprintPostProcessMaterial);
            }

            cmd.EndSample("TrueShadow:Capture");


            cmd.BeginSample("TrueShadow:Cast");
            int source = needPostProcess ? IMPRINT_AFTER_POSTPROCESS_TEX_ID : IMPRINT_TEX_ID;

            if (request.shadowSize < 1e-2)
            {
                cmd.Blit(source, shadowTex);
            }
            else
            {
                blurConfig.Strength = request.shadowSize;
                blurProcessor.Blur(cmd, source, UNIT_RECT, shadowTex);
            }

            cmd.EndSample("TrueShadow:Cast");

            if (request.shadow.Cutout)
            {
                cmd.BeginSample("TrueShadow:Cutout");
                CutoutMaterial.SetVector(ShaderId.OFFSET, new Vector2(request.shadowOffset.x / tw,
                                                                      request.shadowOffset.y / th));
                CutoutMaterial.SetFloat(ShaderId.OVERFLOW_ALPHA, request.shadow.Inset ? 1 : 0);
                cmd.SetViewport(UNIT_RECT);
                cmd.Blit(source, shadowTex, CutoutMaterial);
                cmd.EndSample("TrueShadow:Cutout");
            }

            cmd.ReleaseTemporaryRT(source);

            Graphics.ExecuteCommandBuffer(cmd);

            return(shadowTex);
        }
Ejemplo n.º 2
0
        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));
        }