예제 #1
0
            public override void Action(int instanceId, string pathName, string resourceFile)
            {
                var mixture = CreateMixtureGraphAsset();

                mixture.name      = Path.GetFileNameWithoutExtension(pathName);
                mixture.hideFlags = HideFlags.HideInHierarchy;

                AssetDatabase.CreateAsset(mixture, pathName);

                // Generate the output texture:
                mixture.outputTextures.Clear();
                if (mixture.type == MixtureGraphType.Realtime)
                {
                    mixture.UpdateRealtimeAssetsOnDisk();
                }
                else
                {
                    MixtureGraphProcessor.RunOnce(mixture);
                    mixture.SaveAllTextures(false);
                }

                ProjectWindowUtil.ShowCreatedAsset(mixture.mainOutputTexture);
                Selection.activeObject       = mixture.mainOutputTexture;
                EditorApplication.delayCall += () => EditorGUIUtility.PingObject(mixture.mainOutputTexture);
            }
예제 #2
0
 public static void RunOnce(MixtureGraph graph)
 {
     using (var processor = new MixtureGraphProcessor(graph))
     {
         processor.Run();
     }
 }
예제 #3
0
        static void BeforeCustomRenderTextureUpdate(CommandBuffer cmd, CustomRenderTexture crt)
        {
            MixtureGraph graph = MixtureDatabase.GetGraphFromTexture(crt);;

            // If the graph is valid and realtime
            if (graph != null && graph.type == MixtureGraphType.Realtime)
            {
                MixtureGraphProcessor.processorInstances.TryGetValue(graph, out var processorSet);
                if (processorSet == null)
                {
                    var processor = new MixtureGraphProcessor(graph);
                    // Relay the event to the processor
                    processor.BeforeCustomRenderTextureUpdate(cmd, crt);
                }
                else
                {
                    foreach (var processor in processorSet)
                    {
                        // Relay the event to the processor
                        if (processor.isProcessing == 0)
                        {
                            processor.BeforeCustomRenderTextureUpdate(cmd, crt);
                        }
                    }
                }
            }
        }
예제 #4
0
        protected override bool ProcessNode(CommandBuffer cmd)
        {
            if (input == null)
            {
                return(false);
            }

            if (input.dimension != TextureDimension.Tex2D)
            {
                return(false);
            }

            Color32[] colors = null;
            cache            = new Texture2D(input.width, input.height, settings.GetGraphicsFormat(graph), TextureCreationFlags.None);
            cache.filterMode = FilterMode.Point;
            if (input is RenderTexture rt)
            {
                cmd.RequestAsyncReadback(rt, (r) => {
                    colors = r.GetData <Color32>().ToArray();
                });
                cmd.WaitAllAsyncReadbackRequests();
                MixtureGraphProcessor.AddGPUAndCPUBarrier(cmd);
            }
            else
            {
                colors = (input as Texture2D).GetPixels32();
            }

            var r = new System.Random(42);

            points = new MixtureAttributeList();

            for (int i = 0; i < colors.Length; i++)
            {
                float f = (float)r.NextDouble();
                var   p = colors[i];

                float a = (float)p.a / 255.0f;
                if (f * a > density)
                {
                    colors[i] = Color.white;
                    Vector3 position = new Vector3((float)(i % input.width), 0, (Mathf.Floor(i / (float)input.width)));
                    Vector2 uv       = new Vector2(position.x / (float)input.width, position.z / (float)input.height);
                    points.Add(new MixtureAttribute {
                        { "uv", uv },
                        { "position", position },
                        { "density", p.a }
                    });
                }
                else
                {
                    colors[i] = Color.black;
                }
            }

            cache.SetPixels32(colors);
            cache.Apply();

            return(true);
        }
예제 #5
0
        protected override bool ProcessNode(CommandBuffer cmd)
        {
            if (!base.ProcessNode(cmd) || input == null)
            {
                return(false);
            }

#if UNITY_2021_2_OR_NEWER
            cmd.SetBufferCounterValue(vertices, 0);
#else
            cmd.SetComputeBufferCounterValue(vertices, 0);
#endif

            // 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);
        }
예제 #6
0
        protected override bool ProcessNode(CommandBuffer cmd)
        {
            if (input == null || inputPoints == null)
            {
                return(false);
            }

            if (input.dimension != TextureDimension.Tex2D)
            {
                return(false);
            }

            Color32[] colors = null;
            cache            = new Texture2D(rtSettings.GetWidth(graph), rtSettings.GetHeight(graph), rtSettings.GetGraphicsFormat(graph), TextureCreationFlags.None);
            cache.filterMode = FilterMode.Point;

            if (input is RenderTexture rt)
            {
                cmd.RequestAsyncReadback(rt, (r) => {
                    colors = r.GetData <Color32>().ToArray();
                });
                cmd.WaitAllAsyncReadbackRequests();
                MixtureGraphProcessor.AddGPUAndCPUBarrier(cmd);
            }
            else
            {
                colors = (input as Texture2D).GetPixels32();
            }

            var r = new System.Random(42);

            outputPoints = new MixtureAttributeList();

            Color32[] previewColor = new Color32[cache.width * cache.height];
            foreach (var attr in inputPoints)
            {
                // Sample the input texture with points:
                if (attr.TryGetValue("uv", out var ouv) && ouv is Vector2 uv)
                {
                    int     index = (int)(uv.x * input.width + uv.y * input.height * input.width);
                    Vector4 color = new Vector4(colors[index].r / 255f, colors[index].g / 255f, colors[index].b / 255f, colors[index].a / 255f);

                    AddAttribute(attr, uv, color, ref previewColor);
                }
                outputPoints.Add(attr);
            }

            cache.SetPixels32(previewColor);
            cache.Apply();

            return(true);
        }
예제 #7
0
        void Initialize()
        {
            RegisterCallback <KeyDownEvent>(KeyCallback);

            processor                     = new MixtureGraphProcessor(graph);
            computeOrderUpdated          += processor.UpdateComputeOrder;
            graph.onOutputTextureUpdated += () => processor.Run();
            graph.onGraphChanges         += _ => {
                this.schedule.Execute(() => ProcessGraph()).ExecuteLater(10);
                MarkDirtyRepaint();
            };

            // Run the processor when we open the graph
            ProcessGraph();
        }
예제 #8
0
        void UpdateExposedParameters()
        {
            parameters.Clear();

            bool header           = true;
            bool showUpdateButton = false;

            foreach (var param in graph.exposedParameters)
            {
                if (param.settings.isHidden)
                {
                    continue;
                }

                if (header)
                {
                    var headerLabel = new Label("Exposed Parameters");
                    headerLabel.AddToClassList("Header");
                    parameters.Add(headerLabel);
                    header           = false;
                    showUpdateButton = true;
                }
                VisualElement prop = new VisualElement();
                prop.AddToClassList("Indent");
                prop.style.display = DisplayStyle.Flex;
                Type paramType = Type.GetType(param.type);
                var  field     = FieldFactory.CreateField(paramType, param.serializedValue.value, (newValue) => {
                    Undo.RegisterCompleteObjectUndo(graph, "Changed Parameter " + param.name + " to " + newValue);
                    param.serializedValue.value = newValue;
                }, param.name);
                prop.Add(field);
                parameters.Add(prop);
            }

            if (showUpdateButton)
            {
                var updateButton = new Button(() => {
                    MixtureGraphProcessor.RunOnce(graph);
                    graph.SaveAllTextures(false);
                })
                {
                    text = "Update"
                };
                updateButton.AddToClassList("Indent");
                parameters.Add(updateButton);
            }
        }
예제 #9
0
        void UpdateAllVariantTextures()
        {
            variant.UpdateAllVariantTextures();

            // Update all child variants:
            foreach (var child in variant.GetChildVariants())
            {
                if (child.IsDirty())
                {
                    child.UpdateAllVariantTextures();
                }
            }

            // 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);
            }
        }
예제 #10
0
        void Initialize()
        {
            RegisterCallback <KeyDownEvent>(KeyCallback);

            processor            = MixtureGraphProcessor.GetOrCreate(graph);
            computeOrderUpdated += () => {
                processor.UpdateComputeOrder();
                UpdateNodeColors();
            };
            graph.onOutputTextureUpdated += () => ProcessGraph();

            graph.onGraphChanges -= ProcessGraphWhenChanged;
            graph.onGraphChanges += ProcessGraphWhenChanged;

            // Run the processor when we open the graph
            ProcessGraph();


            SetupRepaintChecker();
        }
예제 #11
0
        void Initialize()
        {
            RegisterCallback <KeyDownEvent>(KeyCallback);

            processor            = MixtureGraphProcessor.GetOrCreate(graph);
            computeOrderUpdated += () => {
                processor.UpdateComputeOrder();
                UpdateNodeColors();
            };
            graph.onOutputTextureUpdated += () => ProcessGraph();

            bool delayQueued = false;

            graph.onGraphChanges += ProcessGraphWhenChanged;

            // Run the processor when we open the graph
            ProcessGraph();

            void ProcessGraphWhenChanged(GraphChanges changes)
            {
                if (delayQueued)
                {
                    return;
                }

                if (changes.addedEdge != null || changes.removedEdge != null ||
                    changes.addedNode != null || changes.removedNode != null || changes.nodeChanged != null)
                {
                    EditorApplication.update += DelayedProcess;
                    void DelayedProcess()
                    {
                        ProcessGraph(changes.nodeChanged ?? changes.addedNode);
                        MarkDirtyRepaint();
                        delayQueued = false;
                        EditorApplication.update -= DelayedProcess;
                    }

                    delayQueued = true;
                }
            }
        }
예제 #12
0
        Texture2D ExecuteAndReadback(MixtureGraph graph)
        {
            // Process the graph andreadback the result
            var processor = new MixtureGraphProcessor(graph);

            processor.Run();

            graph.outputNode.outputTextureSettings.First().enableCompression = false;
            var       settings    = graph.outputNode.rtSettings;
            Texture2D destination = new Texture2D(
                settings.GetWidth(graph),
                settings.GetHeight(graph),
                settings.GetGraphicsFormat(graph),
                TextureCreationFlags.None
                );

            graph.ReadbackMainTexture(destination);

            // Output the image to a file

            return(destination);
        }
예제 #13
0
        protected override bool ProcessNode(CommandBuffer cmd)
        {
            if (loopStart == null)
            {
                Debug.Log("For End node is not connected to a start");
                return(false);
            }

            if (mode == AggregationMode.FeedbackToStartNode)
            {
                FeedbackInputToStartNode(cmd);
            }

            // So right now we need to flush the command buffer because we are changing
            // the inputs to some potential CRT nodes in the loop, which result in a change
            // of material value and because this change is not registered within the command
            // buffer, it would cause issues to just change values without flushing the cmd.
            // We need to consider either material property blocks or a material pool in the loop
            // for these nodes.
            MixtureGraphProcessor.AddGPUAndCPUBarrier(cmd);

            return(true);
        }
예제 #14
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 graphicsFormat = graph.outputNode.settings.GetGraphicsFormat(graph);
                var width          = graph.outputNode.settings.GetResolvedWidth(graph);
                var height         = graph.outputNode.settings.GetResolvedHeight(graph);
                var depth          = graph.outputNode.settings.GetResolvedDepth(graph);
                var filterMode     = graph.outputNode.settings.GetResolvedFilterMode(graph);
                var wrapMode       = graph.outputNode.settings.GetResolvedWrapMode(graph);
                var dimension      = graph.outputNode.settings.GetResolvedTextureDimension(graph);

                if (variantPreview.graphicsFormat != graphicsFormat ||
                    variantPreview.height != height ||
                    variantPreview.width != width ||
                    variantPreview.volumeDepth != depth ||
                    variantPreview.filterMode != filterMode ||
                    variantPreview.wrapMode != wrapMode ||
                    variantPreview.dimension != dimension ||
                    variantPreview.useMipMap != output.hasMipMaps)
                {
                    variantPreview.Release();
                    variantPreview.graphicsFormat = graphicsFormat;
                    variantPreview.width          = width;
                    variantPreview.height         = height;
                    variantPreview.volumeDepth    = depth;
                    variantPreview.filterMode     = filterMode;
                    variantPreview.wrapMode       = wrapMode;
                    variantPreview.dimension      = 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);
                }
            }
        }
예제 #15
0
 public ProcessingScope(MixtureGraphProcessor processor)
 {
     this.processor = processor;
     processor.isProcessing++;
 }
예제 #16
0
        protected void UpdateExposedParameters()
        {
            if (root == null)
            {
                return;
            }

            if (parameters == null || !root.Contains(parameters))
            {
                parameters = new VisualElement()
                {
                    name = "ExposedParameters"
                };
                root.Add(parameters);
            }

            parameters.Clear();

            bool header           = true;
            bool showUpdateButton = false;

            foreach (var param in graph.exposedParameters)
            {
                if (param.settings.isHidden)
                {
                    continue;
                }

                if (header)
                {
                    var headerLabel = new Label("Exposed Parameters");
                    headerLabel.AddToClassList("Header");
                    parameters.Add(headerLabel);
                    header           = false;
                    showUpdateButton = true;
                }
                VisualElement prop = new VisualElement();
                prop.AddToClassList("Indent");
                prop.style.display = DisplayStyle.Flex;
                var p = exposedParameterFactory.GetParameterValueField(param, (newValue) => {
                    param.value = newValue;
                    graph.NotifyExposedParameterValueChanged(param);
                });
                prop.Add(p);
                parameters.Add(prop);
            }

            if (showUpdateButton)
            {
                var updateButton = new Button(() => {
                    MixtureGraphProcessor.RunOnce(graph);
                    graph.SaveAllTextures(false);
                    graph.UpdateLinkedVariants();
                })
                {
                    text = "Update Texture(s)"
                };
                updateButton.AddToClassList("Indent");
                updateButton.AddToClassList("UpdateTextureButton");
                parameters.Add(updateButton);
            }
        }