Пример #1
0
        public static void CopyTexture(CommandBuffer cmd, Texture source, Texture destination, int mipStart, int mipStop = -1)
        {
            if (mipStop == -1)
            {
                mipStop = mipStart + 1;
            }
            using (new ProfilingScope(cmd, new ProfilingSampler("Copy Texture " + source.name + " to " + destination.name)))
            {
                int originalSliceCount = (source.dimension == TextureDimension.Cube) ? 6 : TextureUtils.GetSliceCount(source);

                bool canCopy = source.graphicsFormat == destination.graphicsFormat && source.width == destination.width && source.height == destination.height;

                if (canCopy)
                {
                    for (int mipLevel = mipStart; mipLevel < mipStop; mipLevel++)
                    {
                        int sliceCount = source.dimension == TextureDimension.Tex3D ? Mathf.Max(originalSliceCount >> mipLevel, 1) : originalSliceCount;
                        for (int slice = 0; slice < sliceCount; slice++)
                        {
                            // CopyTexture with mip API is really weird, it needs to take the slice << mipLevel otherwise it doesn't work
                            int copySlice = source.dimension == TextureDimension.Tex3D ? slice << mipLevel : slice;
                            cmd.CopyTexture(source, copySlice, mipLevel, destination, copySlice, mipLevel);
                        }
                    }
                }
                else
                {
                    // no mips mip target in Blit call
                    for (int slice = 0; slice < originalSliceCount; slice++)
                    {
                        cmd.Blit(source, destination, slice, 0);
                    }
                }
            }
        }
Пример #2
0
        public static void ComputeHistogram(CommandBuffer cmd, Texture input, HistogramData data)
        {
            using (new ProfilingScope(cmd, new ProfilingSampler("Generate Histogram")))
            {
                MixtureUtils.SetupComputeTextureDimension(cmd, histogramCompute, input.dimension);

                // Clear buffers
                cmd.SetComputeBufferParam(histogramCompute, clearKernel, "_ImageLuminance", luminanceBuffer);
                cmd.SetComputeBufferParam(histogramCompute, clearKernel, "_Histogram", data.histogram);
                int dispatchCount = input.width * input.height * TextureUtils.GetSliceCount(input) / 64;
                // Limit computing to 8K textures
                int yCount = Mathf.Clamp(dispatchCount / dispatchGroupSizeX / 64, 1, dispatchGroupSizeX);
                int xCount = Mathf.Clamp(dispatchCount / yCount / 8, 1, dispatchGroupSizeX);
                cmd.SetComputeIntParam(histogramCompute, "_DispatchSizeX", dispatchGroupSizeX);
                cmd.DispatchCompute(histogramCompute, clearKernel, xCount, yCount, 1);

                // Find luminance min / max in the texture
                // TODO: handle texture 3D and Cube
                cmd.SetComputeTextureParam(histogramCompute, computeLuminanceBufferKernel, "_Input", input);
                cmd.SetComputeBufferParam(histogramCompute, computeLuminanceBufferKernel, "_ImageLuminance", luminanceBuffer);
                cmd.SetComputeVectorParam(histogramCompute, "_InputTextureSize", new Vector4(input.width, input.height, TextureUtils.GetSliceCount(input), 0));
                cmd.SetComputeVectorParam(histogramCompute, "_RcpTextureSize", new Vector4(1.0f / input.width, 1.0f / input.height, 1.0f / TextureUtils.GetSliceCount(input), 0));
                MixtureUtils.SetTextureWithDimension(cmd, histogramCompute, computeLuminanceBufferKernel, "_Input", input);
                cmd.DispatchCompute(histogramCompute, computeLuminanceBufferKernel, Mathf.Max(1, input.width / 8), Mathf.Max(1, input.height / 8), TextureUtils.GetSliceCount(input));

                ReduceLuminanceBuffer(cmd, dispatchCount);

                // Generate histogram data in compute buffer
                cmd.SetComputeBufferParam(histogramCompute, generateHistogramKernel, "_ImageLuminance", luminanceBuffer);
                cmd.SetComputeBufferParam(histogramCompute, generateHistogramKernel, "_Histogram", data.histogram);
                cmd.SetComputeTextureParam(histogramCompute, generateHistogramKernel, "_Input", input);
                cmd.SetComputeIntParam(histogramCompute, "_HistogramBucketCount", data.bucketCount);
                cmd.SetComputeVectorParam(histogramCompute, "_RcpTextureSize", new Vector4(1.0f / input.width, 1.0f / input.height, 1.0f / TextureUtils.GetSliceCount(input), 0));
                MixtureUtils.SetTextureWithDimension(cmd, histogramCompute, generateHistogramKernel, "_Input", input);
                cmd.DispatchCompute(histogramCompute, generateHistogramKernel, Mathf.Max(1, input.width / 8), Mathf.Max(1, input.height / 8), TextureUtils.GetSliceCount(input));

                cmd.SetComputeBufferParam(histogramCompute, computeHistogramDataKernel, "_HistogramData", data.histogramData);
                cmd.SetComputeBufferParam(histogramCompute, computeHistogramDataKernel, "_Histogram", data.histogram);
                cmd.DispatchCompute(histogramCompute, computeHistogramDataKernel, Mathf.Max(1, data.bucketCount / 64), 1, 1);

                // Request histogram data back for inspector
                cmd.RequestAsyncReadback(luminanceBuffer, 8, 0, (c) => {
                    var d = c.GetData <float>();
                    if (d.Length > 0)
                    {
                        data.minLuminance = d[0];
                        data.maxLuminance = d[1];
                    }
                });
            }
        }
Пример #3
0
        public static Texture DuplicateTexture(Texture source, bool copyContent = true)
        {
            TextureCreationFlags flags = source.mipmapCount > 1 ? TextureCreationFlags.MipChain : TextureCreationFlags.None;

            switch (source)
            {
            case Texture2D t2D:
                var new2D = new Texture2D(t2D.width, t2D.height, t2D.graphicsFormat, t2D.mipmapCount, flags);
                CopyCommonTextureSettings(source, new2D);

                if (copyContent)
                {
                    for (int mipLevel = 0; mipLevel < t2D.mipmapCount; mipLevel++)
                    {
                        new2D.SetPixelData(t2D.GetPixelData <byte>(mipLevel), mipLevel);
                    }
                }

                return(new2D);

            case Texture3D t3D:
                var new3D = new Texture3D(t3D.width, t3D.height, t3D.depth, t3D.graphicsFormat, flags, t3D.mipmapCount);
                CopyCommonTextureSettings(source, new3D);

                if (copyContent)
                {
                    for (int mipLevel = 0; mipLevel < t3D.mipmapCount; mipLevel++)
                    {
                        new3D.SetPixelData(t3D.GetPixelData <byte>(mipLevel), mipLevel);
                    }
                }

                return(new3D);

            case Cubemap cube:
                var newCube = new Cubemap(cube.width, cube.graphicsFormat, flags, cube.mipmapCount);
                CopyCommonTextureSettings(source, newCube);

                if (copyContent)
                {
                    for (int slice = 0; slice < 6; slice++)
                    {
                        for (int mipLevel = 0; mipLevel < cube.mipmapCount; mipLevel++)
                        {
                            newCube.SetPixelData(cube.GetPixelData <byte>(mipLevel, (CubemapFace)slice), mipLevel, (CubemapFace)slice);
                        }
                    }
                }

                return(newCube);

            case CustomRenderTexture rt:
                var newRT = new CustomRenderTexture(rt.width, rt.height, rt.graphicsFormat);
                newRT.dimension   = rt.dimension;
                newRT.depth       = rt.depth;
                newRT.volumeDepth = rt.volumeDepth;
                CopyCommonTextureSettings(source, newRT);
                newRT.enableRandomWrite = rt.enableRandomWrite;

                if (copyContent)
                {
                    for (int slice = 0; slice < TextureUtils.GetSliceCount(rt); slice++)
                    {
                        for (int mipLevel = 0; mipLevel < rt.mipmapCount; mipLevel++)
                        {
                            Graphics.CopyTexture(rt, slice, mipLevel, newRT, slice, mipLevel);
                        }
                    }
                }

                return(newRT);

            default:
                throw new System.Exception("Can't duplicate texture of type " + source.GetType());
            }

            void CopyCommonTextureSettings(Texture source, Texture destination)
            {
                destination.name       = source.name;
                destination.wrapMode   = source.wrapMode;
                destination.filterMode = source.filterMode;
                destination.wrapModeU  = source.wrapModeU;
                destination.wrapModeV  = source.wrapModeV;
                destination.wrapModeW  = source.wrapModeW;
                destination.anisoLevel = source.anisoLevel;
            }
        }
Пример #4
0
        void CreateTexturePreviewImGUI(VisualElement previewContainer, MixtureNode node)
        {
            if (node.showPreviewExposure)
            {
                var previewExposure = new Slider(0, 10)
                {
                    label = "Preview EV100",
                    value = node.previewEV100,
                };
                previewExposure.RegisterValueChangedCallback(e => {
                    node.previewEV100 = e.newValue;
                });
                previewContainer.Add(previewExposure);
            }

            var previewImageSlice = new IMGUIContainer(() => {
                if (node.previewTexture == null)
                {
                    return;
                }

                if (node.previewTexture.dimension == TextureDimension.Tex3D)
                {
                    EditorGUI.BeginChangeCheck();
                    EditorGUIUtility.labelWidth = 70;
                    node.previewSlice           = EditorGUILayout.Slider("3D Slice", node.previewSlice, 0, TextureUtils.GetSliceCount(node.previewTexture) - 1);
                    EditorGUIUtility.labelWidth = 0;
                    if (EditorGUI.EndChangeCheck())
                    {
                        MarkDirtyRepaint();
                    }
                }

                DrawPreviewCommonSettings(node.previewTexture);

                Rect previewRect = GetPreviewRect(node.previewTexture);
                DrawImGUIPreview(node, previewRect, node.previewSlice);

                DrawTextureInfoHover(previewRect, node.previewTexture);
            });

            previewContainer.Add(previewImageSlice);
        }
Пример #5
0
        public static void ComputeLuminanceMinMax(CommandBuffer cmd, ComputeBuffer targetBuffer, Texture input)
        {
            MixtureUtils.SetupComputeTextureDimension(cmd, histogramCompute, input.dimension);

            // Clear buffers
            cmd.SetComputeBufferParam(histogramCompute, clearLuminanceKernel, "_ImageLuminance", luminanceBuffer);
            int dispatchCount = input.width * input.height * TextureUtils.GetSliceCount(input) / 64;
            // Limit computing to 8K textures
            int yCount = Mathf.Clamp(dispatchCount / dispatchGroupSizeX / 64, 1, dispatchGroupSizeX);
            int xCount = Mathf.Clamp(dispatchCount / yCount / 8, 1, dispatchGroupSizeX);

            cmd.SetComputeIntParam(histogramCompute, "_DispatchSizeX", dispatchGroupSizeX);
            cmd.DispatchCompute(histogramCompute, clearLuminanceKernel, xCount, yCount, TextureUtils.GetSliceCount(input));

            // Find luminance min / max in the texture
            cmd.SetComputeTextureParam(histogramCompute, computeLuminanceBufferKernel, "_Input", input);
            cmd.SetComputeBufferParam(histogramCompute, computeLuminanceBufferKernel, "_ImageLuminance", luminanceBuffer);
            cmd.SetComputeVectorParam(histogramCompute, "_InputTextureSize", new Vector4(input.width, input.height, TextureUtils.GetSliceCount(input), 0));
            MixtureUtils.SetTextureWithDimension(cmd, histogramCompute, computeLuminanceBufferKernel, "_Input", input);
            cmd.SetComputeVectorParam(histogramCompute, "_RcpTextureSize", new Vector4(1.0f / input.width, 1.0f / input.height, 1.0f / TextureUtils.GetSliceCount(input), 0));
            cmd.DispatchCompute(histogramCompute, computeLuminanceBufferKernel, Mathf.Max(1, input.width / 8), Mathf.Max(1, input.height / 8), TextureUtils.GetSliceCount(input));

            ReduceLuminanceBuffer(cmd, dispatchCount);

            cmd.SetComputeBufferParam(histogramCompute, copyMinMaxToBuffer, "_ImageLuminance", luminanceBuffer);
            cmd.SetComputeBufferParam(histogramCompute, copyMinMaxToBuffer, "_Target", targetBuffer);
            cmd.DispatchCompute(histogramCompute, copyMinMaxToBuffer, 1, 1, 1);
        }
Пример #6
0
        protected override bool ProcessNode(CommandBuffer cmd)
        {
            if (!base.ProcessNode(cmd) || input == null)
            {
                return(false);
            }

            cmd.SetComputeBufferCounterValue(vertices, 0);

            // TODO: non pot texture3Ds
            cmd.SetComputeVectorParam(computeShader, "_VolumeSize", new Vector4(input.width, input.height, TextureUtils.GetSliceCount(input)));
            cmd.SetComputeFloatParam(computeShader, "_VoxelResolution", 1);
            cmd.SetComputeFloatParam(computeShader, "_Threshold", threshold);

            cmd.SetComputeTextureParam(computeShader, marchingCubes, "_VolumeTexture", input);
            cmd.SetComputeBufferParam(computeShader, marchingCubes, "_Vertices", vertices);
            cmd.SetComputeBufferParam(computeShader, marchingCubes, "_Normals", normals);
            cmd.SetComputeBufferParam(computeShader, marchingCubes, "_Triangles", triangles);
            DispatchCompute(cmd, marchingCubes, input.width, input.height, TextureUtils.GetSliceCount(input));

            MixtureGraphProcessor.AddGPUAndCPUBarrier(cmd);

            ComputeBuffer.CopyCount(vertices, counterReadback, 0);
            int[] count = new int[1];
            counterReadback.GetData(count);
            int vertexCount = count[0] * 3;

            // Readback all buffers
            Vector3[] vBuffer = new Vector3[vertexCount];
            vertices.GetData(vBuffer, 0, 0, vertexCount);
            int[] iBuffer = new int[vertexCount];
            triangles.GetData(iBuffer, 0, 0, vertexCount);

            var mesh = new Mesh {
                indexFormat = IndexFormat.UInt32
            };

            mesh.vertices    = vBuffer;
            mesh.indexFormat = IndexFormat.UInt32;
            // mesh.triangles = iBuffer;
            mesh.SetIndices(iBuffer, MeshTopology.Triangles, 0);
            mesh.RecalculateBounds();
            mesh.RecalculateNormals();
            mesh.UploadMeshData(false);

            output = new MixtureMesh {
                mesh = mesh
            };

            return(true);
        }
Пример #7
0
        protected override bool ProcessNode(CommandBuffer cmd)
        {
            if (!base.ProcessNode(cmd) || textureAsset == null)
            {
                return(false);
            }

#if UNITY_EDITOR
            var importer = UnityEditor.AssetImporter.GetAtPath(UnityEditor.AssetDatabase.GetAssetPath(textureAsset));
            if (importer is UnityEditor.TextureImporter textureImporter)
            {
                normalMap = textureImporter.textureType == UnityEditor.TextureImporterType.NormalMap;
            }
#endif

            int  targetWidth     = textureAsset.width;
            int  targetHeight    = textureAsset.height;
            int  targetDepth     = TextureUtils.GetSliceCount(textureAsset);
            bool needsTempTarget = false;
            if (!IsPowerOf2(textureAsset) && POTMode != PowerOf2Mode.None)
            {
                int maxSize = Mathf.Max(Mathf.Max(targetWidth, targetHeight), targetDepth);
                int potSize = 0;

                switch (POTMode)
                {
                case PowerOf2Mode.ScaleToNextPowerOf2:
                    potSize = Mathf.NextPowerOfTwo(maxSize);
                    break;

                default:
                    potSize = Mathf.ClosestPowerOfTwo(maxSize);
                    break;
                }
                targetWidth     = targetHeight = targetDepth = potSize;
                needsTempTarget = true;
            }
            if (normalMap)
            {
                needsTempTarget = true;
            }

            if (needsTempTarget && postProcessedTexture == null)
            {
                postProcessedTexture = new RenderTexture(1, 1, 0, GraphicsFormat.R16G16B16A16_SFloat, mipCount: textureAsset.mipmapCount)
                {
                    dimension = textureAsset.dimension, enableRandomWrite = true, volumeDepth = 1
                }
            }
            ;
            else if (!needsTempTarget)
            {
                postProcessedTexture?.Release();
                postProcessedTexture = null;
            }

            if (postProcessedTexture != null && (postProcessedTexture.width != targetWidth ||
                                                 postProcessedTexture.height != targetHeight ||
                                                 postProcessedTexture.volumeDepth != targetDepth))
            {
                postProcessedTexture.Release();
                postProcessedTexture.width       = targetWidth;
                postProcessedTexture.height      = targetHeight;
                postProcessedTexture.volumeDepth = targetDepth;
                postProcessedTexture.Create();
            }
            // TODO: same alloc as normal map + scale and crop options

            // Compressed normal maps need to be converted from AG to RG format
            if (normalMap)
            {
                // Transform normal map texture into POT
                var blitMaterial = GetTempMaterial("Hidden/Mixture/TextureNode");
                MixtureUtils.SetTextureWithDimension(blitMaterial, "_Source", textureAsset);
                blitMaterial.SetInt("_POTMode", (int)POTMode);
                MixtureUtils.Blit(cmd, blitMaterial, textureAsset, postProcessedTexture, 0);

                outputTexture = postProcessedTexture;
            }
            else if (needsTempTarget)
            {
                // Transform standard texture into POT
                var blitMaterial = GetTempMaterial("Hidden/Mixture/TextureNode");
                MixtureUtils.SetTextureWithDimension(blitMaterial, "_Source", textureAsset);
                blitMaterial.SetInt("_POTMode", (int)POTMode);
                MixtureUtils.Blit(cmd, blitMaterial, textureAsset, postProcessedTexture, 1);

                outputTexture = postProcessedTexture;
            }
            else
            {
                outputTexture = textureAsset;
            }

            if (outputTexture != null)
            {
                settings.sizeMode = OutputSizeMode.Absolute;
                settings.width    = outputTexture.width;
                settings.height   = outputTexture.height;
                settings.depth    = TextureUtils.GetSliceCount(outputTexture);
            }

            return(true);
        }
Пример #8
0
        void UpdateIsDirtyAndPreview()
        {
            if (updateNeededInfoBox == null)
            {
                return;
            }

            isDirty = variant.IsDirty();
            updateNeededInfoBox.style.display = isDirty ? DisplayStyle.Flex : DisplayStyle.None;

            if (isDirty)
            {
                // Copy the result into the inspector preview RT
                var output = graph.outputNode.outputTextureSettings.FirstOrDefault(n => n.name == defaultTextureEditor.target.name);
                if (output == null)
                {
                    output = graph.outputNode.outputTextureSettings.First();
                }

                // Refresh the preview in the inspector:
                var s = graph.outputNode.rtSettings;
                if (variantPreview.graphicsFormat != s.graphicsFormat ||
                    variantPreview.height != s.height ||
                    variantPreview.width != s.width ||
                    variantPreview.volumeDepth != s.sliceCount ||
                    variantPreview.filterMode != s.filterMode ||
                    variantPreview.wrapMode != s.wrapMode ||
                    variantPreview.dimension != (TextureDimension)s.dimension ||
                    variantPreview.useMipMap != output.hasMipMaps)
                {
                    variantPreview.Release();
                    variantPreview.graphicsFormat = s.graphicsFormat;
                    variantPreview.width          = s.width;
                    variantPreview.height         = s.height;
                    variantPreview.volumeDepth    = s.sliceCount;
                    variantPreview.filterMode     = s.filterMode;
                    variantPreview.wrapMode       = s.wrapMode;
                    variantPreview.dimension      = (TextureDimension)s.dimension;
                    variantPreview.name           = target.name + "*";
                    variantPreview.useMipMap      = output.hasMipMaps;
                    variantPreview.Create();
                }

                // Update the texture in the inspector
                variant.ProcessGraphWithOverrides();

                TextureUtils.CopyTexture(output.finalCopyRT, variantPreview);

                // If the parentGraph is opened in the editor, we don't want to mess with previews
                // so we update the parentGraph with the original params again.
                if (IsMixtureEditorOpened(graph))
                {
                    MixtureGraphProcessor.RunOnce(graph);
                }

                if (variantPreviewEditor == null || variantPreviewEditor.target != variantPreview)
                {
                    Editor.CreateCachedEditor(variantPreview, renderTextureEditorType, ref variantPreviewEditor);
                }
            }
        }
Пример #9
0
        protected override bool ProcessNode()
        {
            if (graph.outputTexture == null)
            {
                Debug.LogError("Output Node can't write to target texture, Graph references a null output texture");
                return(false);
            }

            // Update the renderTexture reference for realtime graph
            if (graph.isRealtime)
            {
                if (tempRenderTexture != graph.outputTexture)
                {
                    onTempRenderTextureUpdated?.Invoke();
                }
                tempRenderTexture = graph.outputTexture as CustomRenderTexture;
            }

            var inputPort = GetPort(nameof(input), nameof(input));

            if (inputPort.GetEdges().Count == 0)
            {
                if (uniqueMessages.Add("OutputNotConnected"))
                {
                    AddMessage("Output node input is not connected", NodeMessageType.Warning);
                }
                input = TextureUtils.GetBlackTexture(rtSettings);
                // TODO: set a black texture of texture dimension as default value
                return(false);
            }
            else
            {
                uniqueMessages.Clear();
                ClearMessages();
            }

            // Update the renderTexture size and format:
            if (UpdateTempRenderTexture(ref tempRenderTexture))
            {
                onTempRenderTextureUpdated?.Invoke();
            }

            if (input.dimension != graph.outputTexture.dimension)
            {
                Debug.LogError("Error: Expected texture type input for the OutputNode is " + graph.outputTexture.dimension + " but " + input?.dimension + " was provided");
                return(false);
            }

            MixtureUtils.SetupDimensionKeyword(finalCopyMaterial, input.dimension);

            // Manually reset all texture inputs
            ResetMaterialPropertyToDefault(finalCopyMaterial, "_Source_2D");
            ResetMaterialPropertyToDefault(finalCopyMaterial, "_Source_3D");
            ResetMaterialPropertyToDefault(finalCopyMaterial, "_Source_Cube");

            if (input.dimension == TextureDimension.Tex2D)
            {
                finalCopyMaterial.SetTexture("_Source_2D", input);
            }
            else if (input.dimension == TextureDimension.Tex3D)
            {
                finalCopyMaterial.SetTexture("_Source_3D", input);
            }
            else
            {
                finalCopyMaterial.SetTexture("_Source_Cube", input);
            }

            tempRenderTexture.material = finalCopyMaterial;

            return(true);
        }
Пример #10
0
        protected override bool ProcessNode(CommandBuffer cmd)
        {
            if (!base.ProcessNode(cmd) || input == null)
            {
                return(false);
            }

            HistogramUtility.ComputeLuminanceMinMax(cmd, minMaxBuffer, input);
            TextureUtils.UpdateTextureFromCurve(interpolationCurve, ref curveTexture);

            var mat = tempRenderTexture.material = GetTempMaterial("Hidden/Mixture/Levels");

            mat.SetFloat("_Mode", (int)mode);
            mat.SetFloat("_ManualMin", min);
            mat.SetFloat("_ManualMax", max);
            mat.SetVector("_RcpTextureSize", new Vector4(1.0f / input.width, 1.0f / input.height, 1.0f / TextureUtils.GetSliceCount(input), 0));
            MixtureUtils.SetupDimensionKeyword(mat, tempRenderTexture.dimension);
            MixtureUtils.SetTextureWithDimension(mat, "_Input", input);
            mat.SetBuffer("_Luminance", minMaxBuffer);
            mat.SetTexture("_InterpolationCurve", curveTexture);

            tempRenderTexture.Update();
            CustomTextureManager.UpdateCustomRenderTexture(cmd, tempRenderTexture);

            output = tempRenderTexture;

            return(true);
        }
Пример #11
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();

            if (!rt.enableRandomWrite)
            {
                rt.Release();
                rt.enableRandomWrite = true;
                rt.Create();
            }

            MixtureUtils.SetupComputeTextureDimension(cmd, computeShader, input.dimension);

            MixtureUtils.SetTextureWithDimension(cmd, computeShader, fillUvKernel, "_Input", input);
            MixtureUtils.SetTextureWithDimension(cmd, computeShader, fillUvKernel, "_Output", output);
            MixtureUtils.SetTextureWithDimension(cmd, 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);
                MixtureUtils.SetTextureWithDimension(cmd, computeShader, jumpFloodingKernel, "_Input", output);
                MixtureUtils.SetTextureWithDimension(cmd, computeShader, jumpFloodingKernel, "_Output", rt);
                cmd.SetComputeIntParam(computeShader, "_DistanceMode", (int)distanceMode);
                DispatchCompute(cmd, jumpFloodingKernel, output.width, output.height, output.volumeDepth);
                TextureUtils.CopyTexture(cmd, rt, output);
            }

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

            return(true);
        }
Пример #12
0
        protected override bool ProcessNode(CommandBuffer cmd)
        {
            settings.doubleBuffered = true;
            if (!base.ProcessNode(cmd) || input == null)
            {
                return(false);
            }

            TextureUtils.CopyTexture(cmd, input, output, false);

            var mipmapGenMat = GetTempMaterial("Hidden/Mixture/GenerateMipMaps");

            if (mode == Mode.Custom)
            {
                mipmapGenMat = material;
            }
            else
            {
                output.material = null;
            }

            if (mode == Mode.Auto)
            {
                cmd.GenerateMips(output);
            }
            else
            {
                var props = new MaterialPropertyBlock();
                MixtureUtils.SetupDimensionKeyword(mipmapGenMat, settings.GetResolvedTextureDimension(graph));
                mipmapGenMat.SetFloat("_Mode", (int)mode);
                MixtureUtils.SetTextureWithDimension(props, "_PreviousMip", input);
                // Manually generate mips:
                for (int i = 0; i < output.mipmapCount - 1; i++)
                {
                    props.SetFloat("_SourceMip", i);
                    float width  = Mathf.Max(1, input.width >> i);
                    float height = Mathf.Max(1, input.width >> i);
                    float depth  = Mathf.Max(1, TextureUtils.GetSliceCount(input) >> i);
                    props.SetVector("_RcpTextureSize", new Vector4(1.0f / width, 1.0f / height, 1.0f / depth, 0.0f));
                    output.material = mipmapGenMat;

                    if (mode == Mode.Gaussian)
                    {
                        // 2 passes of gaussian blur for 2D and Cubemaps
                        props.SetVector("_GaussianBlurDirection", Vector3.right);
                        CustomTextureManager.UpdateCustomRenderTexture(cmd, output, 1, i + 1, props);
                        TextureUtils.CopyTexture(cmd, output.GetDoubleBufferRenderTexture(), output, i + 1);

                        props.SetFloat("_SourceMip", i + 1);
                        MixtureUtils.SetTextureWithDimension(props, "_PreviousMip", output);
                        props.SetVector("_GaussianBlurDirection", Vector3.up);
                        CustomTextureManager.UpdateCustomRenderTexture(cmd, output, 1, i + 1, props);

                        // And a third pass if we're in 3D
                        if (input.dimension == TextureDimension.Tex3D)
                        {
                            props.SetVector("_GaussianBlurDirection", Vector3.forward);
                            TextureUtils.CopyTexture(cmd, output.GetDoubleBufferRenderTexture(), output, i + 1);
                            CustomTextureManager.UpdateCustomRenderTexture(cmd, output, 1, i + 1, props);
                        }
                    }
                    else
                    {
                        CustomTextureManager.UpdateCustomRenderTexture(cmd, output, 1, i + 1, props);
                    }

                    TextureUtils.CopyTexture(cmd, output.GetDoubleBufferRenderTexture(), output, i + 1);
                    MixtureUtils.SetTextureWithDimension(props, "_PreviousMip", output);
                }
            }
            output.material = null;

            return(true);
        }