浏览代码

Menu Items : Create Custom Material / Custom Processor (#21)

* Custom Material Shader Generator

* Custom Processor Template

* Updated Documentation

* Fixed Custom Processor Class Name Generation
/main
GitHub 3 年前
当前提交
9e60ef5f
共有 7 个文件被更改,包括 300 次插入4 次删除
  1. 9
      Documentation~/ImageSequencer.md
  2. 8
      Editor/ImageSequencer/EditorTemplates.meta
  3. 106
      Editor/ImageSequencer/EditorTemplates/ImageSequencerCustomShaderTemplateFactory.cs
  4. 11
      Editor/ImageSequencer/EditorTemplates/ImageSequencerCustomShaderTemplateFactory.cs.meta
  5. 11
      Editor/ImageSequencer/EditorTemplates/ImageSequencerCustomProcessorTemplateFactory.cs.meta
  6. 159
      Editor/ImageSequencer/EditorTemplates/ImageSequencerCustomProcessorTemplateFactory.cs

9
Documentation~/ImageSequencer.md


#### Writing a shader for Custom Materials
In order to create shaders for Custom material processor you need to create a simple unlit shader from the Project Create Menu : **Shaders > Unlit Shader**. You can alter the default code to match the following code:
In order to create shaders for Custom material processor you need to create a simple unlit shader from the Project Create Menu : **Visual Effects > Custom Material (Shader)**. You can alter the default code to match the following code:
```c
Shader "ImageSequencer/SimpleCustomMaterial"

#### Creating a new Custom Processor
To create a new custom processor so you need the following:
You can create both assets by clicking the Create Asset Menu, under **Visual Effects > Custom Processor (C#, Shader)**
This will create the following assets:
Here is a sample C# code that you can use as a starting base.

8
Editor/ImageSequencer/EditorTemplates.meta


fileFormatVersion: 2
guid: 9d239ec7163605d4db190de7c23cb789
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

106
Editor/ImageSequencer/EditorTemplates/ImageSequencerCustomShaderTemplateFactory.cs


using System.IO;
using System.Linq;
using System.Text;
using UnityEditor.ProjectWindowCallback;
using UnityEngine;
namespace UnityEditor.Experimental.VFX.Toolbox.ImageSequencer
{
internal class ImageSequencerCustomShaderTemplateFactory
{
[MenuItem("Assets/Create/Visual Effects/Custom Material (Shader)", priority = 323)]
static void CreateStaticEditorShaderTemplate()
{
var icon = EditorGUIUtility.FindTexture("Shader Icon");
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateImageSequencerCustomShader>(), "New Custom Shader.shader", icon, null);
}
public static Shader CreateShaderAtPath(string path)
{
string name = path.Split('/').Last().Replace(".shader", "");
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Shader \"ImageSequencer/{0}\"", name);
sb.Append(@"
{
Properties
{
}
SubShader
{
Tags { ""RenderType"" = ""Opaque"" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include ""UnityCG.cginc""
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
// ImageSequencer CustomMaterial uniforms
// ======================================
//
// sampler2D _InputFrame; // Input Frame (from previous sequence)
//
// float4 _FrameData; // Frame Data
// // x, y : width (x) and height (y) in pixels
// // z, w : sequence index (z) and length (w)
//
// float4 _FlipbookData; // Flipbook Data
// // x, y : number of columns (x) and rows (y)
//
sampler2D _InputFrame;
float4 _FrameData;
float4 _FlipbookData;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
// Process the Color
fixed4 col = tex2D(_InputFrame, i.uv);
return col;
}
ENDCG
}
}
}");
File.WriteAllText(path, sb.ToString());
AssetDatabase.ImportAsset(path);
return AssetDatabase.LoadAssetAtPath<Shader>(path);
}
}
internal class DoCreateImageSequencerCustomShader : EndNameEditAction
{
public override void Action(int instanceId, string pathName, string resourceFile)
{
Shader asset = ImageSequencerCustomShaderTemplateFactory.CreateShaderAtPath(pathName);
ProjectWindowUtil.ShowCreatedAsset(asset);
}
}
}

11
Editor/ImageSequencer/EditorTemplates/ImageSequencerCustomShaderTemplateFactory.cs.meta


fileFormatVersion: 2
guid: 7e4a42824d0f61745a7c3e3299a23fbf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Editor/ImageSequencer/EditorTemplates/ImageSequencerCustomProcessorTemplateFactory.cs.meta


fileFormatVersion: 2
guid: ca6ac7e00ea22164aab9ec303d5b9afb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

159
Editor/ImageSequencer/EditorTemplates/ImageSequencerCustomProcessorTemplateFactory.cs


using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor.ProjectWindowCallback;
using UnityEngine;
namespace UnityEditor.Experimental.VFX.Toolbox.ImageSequencer
{
internal class ImageSequencerCustomProcessorTemplateFactory
{
[MenuItem("Assets/Create/Visual Effects/Custom Processor (C#, Shader)", priority = 322)]
static void CreateStaticEditorShaderTemplate()
{
var icon = EditorGUIUtility.FindTexture("Shader Icon");
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateImageSequencerCustomProcessor>(), "New Custom Processor.cs", icon, null);
}
public static MonoScript CreateAssetsAtPath(string path)
{
string name = path.Split('/').Last().Replace(".cs", "");
string shaderPath = path.Replace(".cs", ".shader");
StringBuilder sb_shader = new StringBuilder();
sb_shader.AppendFormat("Shader \"Hidden/VFXToolbox/ImageSequencer/{0}\"", name);
sb_shader.Append(@"
{
Properties
{
_MainTex(""Texture"", 2D) = ""white"" {}
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
# include ""UnityCG.cginc""
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return tex2D(_MainTex, i.uv);
}
ENDCG
}
}
}");
File.WriteAllText(shaderPath, sb_shader.ToString());
AssetDatabase.ImportAsset(shaderPath);
StringBuilder sb_monoScript = new StringBuilder();
string friendlyName = ObjectNames.NicifyVariableName(name);
string className = Regex.Replace(name, @"[^0-9a-zA-Z_]+", "");
Debug.Log(className);
sb_monoScript.Append(@"using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Experimental.VFX.Toolbox.ImageSequencer;
using UnityEngine;
");
sb_monoScript.AppendFormat("[Processor(\"Category\",\"{0}\")]\n", friendlyName);
sb_monoScript.AppendFormat("public class {0} : ProcessorBase\n", className);
sb_monoScript.Append(@"{
/// <summary>
/// The Shader Path (in the project) of the Shader File
/// </summary>
");
sb_monoScript.AppendFormat(" public override string shaderPath => \"{0}\";", shaderPath);
sb_monoScript.Append(@"
/// <summary>
/// The Processor Name (as it will appear in the list)
/// </summary>
");
sb_monoScript.AppendFormat(" public override string processorName => \"{0}\";", friendlyName);
sb_monoScript.Append(@"
/// <summary>
/// Default() configures a default instance of the processor
/// of the processor (e.g: when it will be added from the menu)
/// </summary>
public override void Default()
{
}
/// <summary>
/// OnInspectorGUI() displays the properties in the left pane editor.
/// use the serializedObject to fetch serializedProperties
/// </summary>
public override bool OnInspectorGUI(bool changed, SerializedObject serializedObject)
{
return changed;
}
/// <summary>
/// Process(int frame) method is called when the frame needs to be processed.
/// ProcessFrame(int, texture) needs to be called in order to run the shader on the full frame.
/// You can still perform Graphics.Blit() if you need to perform multiple blits.
/// </summary>
public override bool Process(int frame)
{
Texture inputFrame = RequestInputTexture(frame);
ProcessFrame(frame, inputFrame);
return true;
}
}");
File.WriteAllText(path, sb_monoScript.ToString());
AssetDatabase.ImportAsset(path);
return AssetDatabase.LoadAssetAtPath<MonoScript>(path);
}
}
internal class DoCreateImageSequencerCustomProcessor : EndNameEditAction
{
public override void Action(int instanceId, string pathName, string resourceFile)
{
MonoScript asset = ImageSequencerCustomProcessorTemplateFactory.CreateAssetsAtPath(pathName);
ProjectWindowUtil.ShowCreatedAsset(asset);
}
}
}
正在加载...
取消
保存