summaryrefslogtreecommitdiffstats
path: root/Scripts/LinearPipeline.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Scripts/LinearPipeline.cs')
-rw-r--r--Scripts/LinearPipeline.cs154
1 files changed, 154 insertions, 0 deletions
diff --git a/Scripts/LinearPipeline.cs b/Scripts/LinearPipeline.cs
new file mode 100644
index 0000000..33b1fef
--- /dev/null
+++ b/Scripts/LinearPipeline.cs
@@ -0,0 +1,154 @@
+/*
+ Udon# Linear Pipeline Controller
+
+ This script manages a linear chain of image effects. It takes a source texture
+ and processes it through a sequence of materials, storing the result of each
+ step in a corresponding RenderTexture.
+
+ Setup:
+ 1. Create an empty GameObject in your scene.
+ 2. Add an UdonBehaviour component to it.
+ 3. Create this Udon# script in your project and assign it to the UdonBehaviour.
+ 4. Create all the Materials and RenderTextures you need for your pipeline.
+ 5. In the Inspector, assign the Source Input, Materials, and Output RenderTextures.
+ - The size of the Effect Materials and Pipeline Outputs arrays MUST be the same.
+ - The order of materials and textures in the arrays determines the pipeline order.
+ 6. Choose your desired execution mode (Run On Start, Run Continuously).
+*/
+
+using UdonSharp;
+using UnityEngine;
+using VRC.SDKBase;
+
+[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
+public class LinearPipeline : UdonSharpBehaviour
+{
+ [Header("Pipeline Assets")]
+ [Tooltip("The initial texture to start the pipeline with.")]
+ public Texture sourceInput;
+
+ [Tooltip("The materials to apply in sequence. The order matters.")]
+ public Material[] effectMaterials;
+
+ [Tooltip("The RenderTextures to store the output of each step. MUST be the same size as the materials array.")]
+ public RenderTexture[] pipelineOutputs;
+
+ [Header("Execution Mode")]
+ [Tooltip("If true, the pipeline will run once when the world loads.")]
+ public bool runOnStart = true;
+
+ [Tooltip("If true, the pipeline will run every frame. Use with caution, can be performance-intensive.")]
+ public bool runContinuously = false;
+
+ void Start()
+ {
+ _ConfigurePipeline();
+
+ if (runOnStart)
+ {
+ _RunPipeline();
+ }
+ }
+
+ void Update()
+ {
+ if (runContinuously)
+ {
+ _RunPipeline();
+ }
+ }
+
+ /// <summary>
+ /// Configure materials for the pipeline.
+ /// </summary>
+ void _ConfigurePipeline()
+ {
+ if (effectMaterials == null || effectMaterials.Length == 0)
+ {
+ Debug.LogError("[LinearUdonPipeline] No Effect Materials have been assigned!", this);
+ return;
+ }
+
+ if (pipelineOutputs == null || pipelineOutputs.Length == 0)
+ {
+ Debug.LogError("[LinearUdonPipeline] No Pipeline Outputs have been assigned!", this);
+ return;
+ }
+
+ if (effectMaterials.Length != pipelineOutputs.Length)
+ {
+ Debug.LogError("[LinearUdonPipeline] The number of materials does not match the number of output textures!", this);
+ return;
+ }
+
+ // Configure materials - set _MainTex to appropriate source
+ for (int i = 0; i < effectMaterials.Length; i++)
+ {
+ if (effectMaterials[i] != null)
+ {
+ if (i == 0)
+ {
+ // First material uses the source input
+ effectMaterials[i].SetTexture("_MainTex", sourceInput);
+ }
+ else
+ {
+ // Subsequent materials use the previous output as input
+ effectMaterials[i].SetTexture("_MainTex", pipelineOutputs[i - 1]);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// This public method can be called by other Udon scripts or UI events to run the pipeline.
+ /// </summary>
+ public void _RunPipeline()
+ {
+ // --- Pre-flight Checks ---
+ if (sourceInput == null)
+ {
+ Debug.LogError("[LinearUdonPipeline] Source Input is not assigned!", this);
+ return;
+ }
+
+ if (effectMaterials == null || effectMaterials.Length == 0)
+ {
+ Debug.LogError("[LinearUdonPipeline] No Effect Materials have been assigned!", this);
+ return;
+ }
+
+ if (pipelineOutputs == null || pipelineOutputs.Length == 0)
+ {
+ Debug.LogError("[LinearUdonPipeline] No Pipeline Outputs have been assigned!", this);
+ return;
+ }
+
+ if (effectMaterials.Length != pipelineOutputs.Length)
+ {
+ Debug.LogError("[LinearUdonPipeline] The number of materials does not match the number of output textures!", this);
+ return;
+ }
+
+ // --- Run Pipeline ---
+
+ // 1. First Blit: From the main source to the first texture in our chain.
+ VRCGraphics.Blit(sourceInput, pipelineOutputs[0], effectMaterials[0], -1);
+
+ // 2. Loop through the rest of the chain.
+ for (int i = 1; i < effectMaterials.Length; i++)
+ {
+ // The source for this step is the output from the previous step.
+ Texture sourceForThisStep = pipelineOutputs[i - 1];
+
+ // The destination is the current output texture.
+ RenderTexture destForThisStep = pipelineOutputs[i];
+
+ // The material for this step.
+ Material materialForThisStep = effectMaterials[i];
+
+ VRCGraphics.Blit(sourceForThisStep, destForThisStep, materialForThisStep, -1);
+ }
+ }
+}
+