Beispiel #1
0
        protected override bool ProcessNode(CommandBuffer cmd)
        {
            // Force the double buffering for multi-pass flooding
            rtSettings.doubleBuffered = true;

            if (!base.ProcessNode(cmd) || input == null)
            {
                return(false);
            }

            UpdateTempRenderTexture(ref output);

            cmd.SetComputeFloatParam(computeShader, "_Threshold", threshold);
            cmd.SetComputeVectorParam(computeShader, "_Size", new Vector4(output.width, 1.0f / output.width));
            cmd.SetComputeFloatParam(computeShader, "_Distance", distance / 100.0f);
            cmd.SetComputeIntParam(computeShader, "_ThresholdMode", (int)thresholdMode);
            cmd.SetComputeIntParam(computeShader, "_DistanceMode", (int)distanceMode);
            cmd.SetComputeIntParam(computeShader, "_Mode", (int)mode);

            output.doubleBuffered = true;
            output.EnsureDoubleBufferConsistency();
            var rt = output.GetDoubleBufferRenderTexture();

            rt.Release();
            rt.enableRandomWrite = true;
            rt.Create();

            MixtureUtils.SetupComputeDimensionKeyword(computeShader, input.dimension);

            cmd.SetComputeTextureParam(computeShader, fillUvKernel, "_Input", input);
            cmd.SetComputeTextureParam(computeShader, fillUvKernel, "_Output", output);
            cmd.SetComputeTextureParam(computeShader, fillUvKernel, "_FinalOutput", rt);
            cmd.SetComputeIntParam(computeShader, "_DistanceMode", (int)distanceMode);
            cmd.SetComputeFloatParam(computeShader, "_InputScaleFactor", (float)input.width / (float)output.width);
            DispatchCompute(cmd, fillUvKernel, output.width, output.height, output.volumeDepth);

            int maxLevels = (int)Mathf.Log(input.width, 2);

            for (int i = 0; i <= maxLevels; i++)
            {
                float offset = 1 << (maxLevels - i);
                cmd.SetComputeFloatParam(computeShader, "_InputScaleFactor", 1);
                cmd.SetComputeFloatParam(computeShader, "_Offset", offset);
                cmd.SetComputeTextureParam(computeShader, jumpFloodingKernel, "_Input", output);
                cmd.SetComputeTextureParam(computeShader, jumpFloodingKernel, "_Output", rt);
                cmd.SetComputeIntParam(computeShader, "_DistanceMode", (int)distanceMode);
                DispatchCompute(cmd, jumpFloodingKernel, output.width, output.height, output.volumeDepth);
                cmd.CopyTexture(rt, output);
            }

            cmd.SetComputeFloatParam(computeShader, "_InputScaleFactor", (float)input.width / (float)output.width);
            cmd.SetComputeTextureParam(computeShader, finalPassKernel, "_Input", input);
            cmd.SetComputeTextureParam(computeShader, finalPassKernel, "_Output", rt);
            cmd.SetComputeIntParam(computeShader, "_DistanceMode", (int)distanceMode);
            cmd.SetComputeTextureParam(computeShader, finalPassKernel, "_FinalOutput", output);
            DispatchCompute(cmd, finalPassKernel, output.width, output.height, output.volumeDepth);

            return(true);
        }
Beispiel #2
0
    public static void UpdateCustomRenderTexture(CommandBuffer cmd, CustomRenderTexture crt, int updateCount, int mipLevel = 0, MaterialPropertyBlock block = null)
    {
        // Prepare "self" texture for reading in the shader for double buffered custom textures
        RenderTexture textureSelf2D   = null;
        RenderTexture textureSelf3D   = null;
        RenderTexture textureSelfCube = null;

        if (crt.doubleBuffered)
        {
            if (crt.dimension == TextureDimension.Tex2D)
            {
                textureSelf2D = crt;
            }
            if (crt.dimension == TextureDimension.Cube)
            {
                textureSelfCube = crt;
            }
            if (crt.dimension == TextureDimension.Tex3D)
            {
                textureSelf3D = crt;
            }
        }

        if (crt.doubleBuffered)
        {
            // Update the internal double buffered render texture (resize / alloc / ect.)
            crt.EnsureDoubleBufferConsistency();
        }

        if (block == null)
        {
            block = new MaterialPropertyBlock();
        }

        // If the user didn't called the update on CRT, we still process it because it's realtime
        for (int i = 0; i < updateCount; i++)
        {
            // TODO: cache everything
            List <CustomRenderTextureUpdateZone> updateZones = new List <CustomRenderTextureUpdateZone>();
            crt.GetUpdateZones(updateZones);

            if (updateZones.Count == 0)
            {
                updateZones.Add(new CustomRenderTextureUpdateZone {
                    needSwap = false, updateZoneCenter = new Vector3(0.5f, 0.5f, 0.5f), updateZoneSize = Vector3.one, rotation = 0, passIndex = 0
                });
            }

            foreach (var zone in updateZones)
            {
                var zoneCenters          = updateZones.Select(z => new Vector4(z.updateZoneCenter.x, z.updateZoneCenter.y, z.updateZoneCenter.z, 0)).ToList();
                var zoneSizesAndRotation = updateZones.Select(z => new Vector4(z.updateZoneSize.x, z.updateZoneSize.y, z.updateZoneSize.z, z.rotation)).ToList();
                var zonePrimitiveIDs     = Enumerable.Range(0, updateZones.Count).Select(j => (float)j).ToList();// updateZones.Select(z => 0.0f).ToList();
                int sliceCount           = GetSliceCount(crt, mipLevel);

                // Copy all the slices in case the texture is double buffered
                if (zone.needSwap)
                {
                    var doubleBuffer = crt.GetDoubleBufferRenderTexture();
                    if (doubleBuffer != null)
                    {
                        // For now, it's just a copy, once we actually do the swap of pointer, be careful to reset the Active Render Texture
                        for (int sliceIndex = 0; sliceIndex < sliceCount; sliceIndex++)
                        {
                            cmd.CopyTexture(doubleBuffer, sliceIndex, crt, sliceIndex);
                        }
                    }
                }

                for (int slice = 0; slice < sliceCount; slice++)
                {
                    RenderTexture renderTexture = crt.doubleBuffered ? crt.GetDoubleBufferRenderTexture() : crt;
                    cmd.SetRenderTarget(renderTexture, mipLevel, (crt.dimension == TextureDimension.Cube) ? (CubemapFace)slice : CubemapFace.Unknown, (crt.dimension == TextureDimension.Tex3D) ? slice : 0);
                    cmd.SetViewport(new Rect(0, 0, Mathf.Max(1, crt.width >> mipLevel), Mathf.Max(1, crt.height >> mipLevel)));
                    block.SetVector(kCustomRenderTextureInfo, GetTextureInfos(crt, slice, mipLevel));
                    block.SetVector(kCustomRenderTextureParameters, GetTextureParameters(crt, slice, mipLevel));
                    block.SetFloat(kMipLevel, mipLevel);
                    if (textureSelf2D != null)
                    {
                        block.SetTexture(kSelf2D, textureSelf2D);
                    }
                    if (textureSelf3D != null)
                    {
                        block.SetTexture(kSelf3D, textureSelf3D);
                    }
                    if (textureSelfCube != null)
                    {
                        block.SetTexture(kSelfCube, textureSelfCube);
                    }

                    int passIndex = zone.passIndex == -1 ? 0 : zone.passIndex;

                    block.SetVectorArray(kUpdateDataCenters, zoneCenters);
                    block.SetVectorArray(kUpdateDataSizesAndRotation, zoneSizesAndRotation);
                    block.SetFloatArray(kUpdateDataPrimitiveIDs, zonePrimitiveIDs);

                    cmd.DrawProcedural(Matrix4x4.identity, crt.material, passIndex, MeshTopology.Triangles, 6 * updateZones.Count, 1, block);
                }
            }
        }
    }
    // Update one custom render texture.
    public static void UpdateCustomRenderTexture(CommandBuffer cmd, CustomRenderTexture crt)
    {
        bool firstPass = crt.updateCount == 0;

        // Handle initialization here too:
        if (crt.initializationMode == CustomRenderTextureUpdateMode.Realtime || needsInitialization.Contains(crt) || (firstPass && crt.initializationMode == CustomRenderTextureUpdateMode.OnLoad))
        {
            switch (crt.initializationSource)
            {
            case CustomRenderTextureInitializationSource.Material:
                // TODO
                break;

            case CustomRenderTextureInitializationSource.TextureAndColor:
                // TODO
                break;
            }
            needsInitialization.Remove(crt);
        }

        needsUpdate.TryGetValue(crt, out int updateCount);

        if (crt.material != null && (crt.updateMode == CustomRenderTextureUpdateMode.Realtime || updateCount > 0 || (firstPass && crt.updateMode == CustomRenderTextureUpdateMode.OnLoad)))
        {
            onBeforeCustomTextureUpdated?.Invoke(cmd, crt);

#if CUSTOM_TEXTURE_PROFILING
            customRenderTextureSamplers.TryGetValue(crt, out var sampler);
            if (sampler == null)
            {
                sampler = customRenderTextureSamplers[crt] = CustomSampler.Create($"{crt.name} - {crt.GetInstanceID()}", true);
                sampler.GetRecorder().enabled = true;
            }
            cmd.BeginSample(sampler);
#endif

            using (new ProfilingScope(cmd, new ProfilingSampler($"Update {crt.name}")))
            {
                // Prepare "self" texture for reading in the shader for double buffered custom textures
                RenderTexture textureSelf2D   = null;
                RenderTexture textureSelf3D   = null;
                RenderTexture textureSelfCube = null;
                if (crt.doubleBuffered)
                {
                    if (crt.dimension == TextureDimension.Tex2D)
                    {
                        textureSelf2D = crt;
                    }
                    if (crt.dimension == TextureDimension.Cube)
                    {
                        textureSelfCube = crt;
                    }
                    if (crt.dimension == TextureDimension.Tex3D)
                    {
                        textureSelf3D = crt;
                    }
                }

                if (crt.doubleBuffered)
                {
                    // Update the internal double buffered render texture (resize / alloc / ect.)
                    crt.EnsureDoubleBufferConsistency();
                }

                MaterialPropertyBlock block = new MaterialPropertyBlock();

                // If the user didn't called the update on CRT, we still process it because it's realtime
                updateCount = Mathf.Max(updateCount, 1);
                for (int i = 0; i < updateCount; i++)
                {
                    // TODO: cache everything
                    List <CustomRenderTextureUpdateZone> updateZones = new List <CustomRenderTextureUpdateZone>();
                    crt.GetUpdateZones(updateZones);

                    if (updateZones.Count == 0)
                    {
                        updateZones.Add(new CustomRenderTextureUpdateZone {
                            needSwap = false, updateZoneCenter = new Vector3(0.5f, 0.5f, 0.5f), updateZoneSize = Vector3.one, rotation = 0, passIndex = 0
                        });
                    }

                    foreach (var zone in updateZones)
                    // int sliceCount = GetSliceCount(crt);
                    // for (int slice = 0; slice < sliceCount; slice++)
                    {
                        var zoneCenters          = updateZones.Select(z => new Vector4(z.updateZoneCenter.x, z.updateZoneCenter.y, z.updateZoneCenter.z, 0)).ToList();
                        var zoneSizesAndRotation = updateZones.Select(z => new Vector4(z.updateZoneSize.x, z.updateZoneSize.y, z.updateZoneSize.z, z.rotation)).ToList();
                        var zonePrimitiveIDs     = Enumerable.Range(0, updateZones.Count).Select(j => (float)j).ToList();// updateZones.Select(z => 0.0f).ToList();
                        int sliceCount           = GetSliceCount(crt);

                        // Copy all the slices in case the texture is double buffered
                        if (zone.needSwap)
                        {
                            var doubleBuffer = crt.GetDoubleBufferRenderTexture();
                            if (doubleBuffer != null)
                            {
                                // For now, it's just a copy, once we actually do the swap of pointer, be careful to reset the Active Render Texture
                                for (int slice = 0; slice < sliceCount; slice++)
                                {
                                    cmd.CopyTexture(doubleBuffer, slice, crt, slice);
                                }
                            }
                        }

                        // foreach (var zone in updateZones)
                        for (int slice = 0; slice < sliceCount; slice++)
                        {
                            RenderTexture renderTexture = crt.doubleBuffered ? crt.GetDoubleBufferRenderTexture() : crt;
                            cmd.SetRenderTarget(renderTexture, 0, (crt.dimension == TextureDimension.Cube) ? (CubemapFace)slice : 0, (crt.dimension == TextureDimension.Tex3D) ? slice : 0);
                            cmd.SetViewport(new Rect(0, 0, crt.width, crt.height));
                            block.SetVector(kCustomRenderTextureInfo, GetTextureInfos(crt, slice));
                            block.SetVector(kCustomRenderTextureParameters, GetTextureParameters(crt, slice));
                            if (textureSelf2D != null)
                            {
                                block.SetTexture(kSelf2D, textureSelf2D);
                            }
                            if (textureSelf3D != null)
                            {
                                block.SetTexture(kSelf3D, textureSelf3D);
                            }
                            if (textureSelfCube != null)
                            {
                                block.SetTexture(kSelfCube, textureSelfCube);
                            }

                            int passIndex = zone.passIndex == -1 ? 0 : zone.passIndex;

                            block.SetVectorArray(kUpdateDataCenters, zoneCenters);
                            block.SetVectorArray(kUpdateDataSizesAndRotation, zoneSizesAndRotation);
                            block.SetFloatArray(kUpdateDataPrimitiveIDs, zonePrimitiveIDs);

                            cmd.DrawProcedural(Matrix4x4.identity, crt.material, passIndex, MeshTopology.Triangles, 6 * updateZones.Count, 1, block);
                        }
                    }
                }

                needsUpdate.Remove(crt);
            }

#if CUSTOM_TEXTURE_PROFILING
            cmd.EndSample(sampler);
#endif
            crt.IncrementUpdateCount();
        }
    }