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); }
public static void RunOnce(MixtureGraph graph) { using (var processor = new MixtureGraphProcessor(graph)) { processor.Run(); } }
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); } } } } }
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); }
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); }
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); }
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(); }
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); } }
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); } }
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(); }
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; } } }
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); }
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); }
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); } } }
public ProcessingScope(MixtureGraphProcessor processor) { this.processor = processor; processor.isProcessing++; }
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); } }