Skip to content

Instantly share code, notes, and snippets.

@isuzu-shiranui
Created March 27, 2023 16:27
Show Gist options
  • Save isuzu-shiranui/5b8d2a5505eed80d954b95d1cd5da285 to your computer and use it in GitHub Desktop.
Save isuzu-shiranui/5b8d2a5505eed80d954b95d1cd5da285 to your computer and use it in GitHub Desktop.
シェーダーのPropertiesから定義部分を生成させるやつ
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
public class ShaderPropertiesGenerator : EditorWindow
{
private Shader targetShader;
private void OnGUI()
{
EditorGUILayout.BeginVertical();
this.targetShader = (Shader)EditorGUILayout.ObjectField("Target Shader", this.targetShader, typeof(Shader), false);
if (GUILayout.Button("Generate HLSL")) this.ExtractShaderProperties();
EditorGUILayout.EndVertical();
}
[MenuItem("Window/Shader Properties Generator")]
public static void ShowWindow()
{
GetWindow<ShaderPropertiesGenerator>("Shader Properties Generator");
}
private void ExtractShaderProperties()
{
if (this.targetShader == null)
{
Debug.LogError("Please select a shader.");
return;
}
var shaderProperties = new List<ShaderProperty>();
var propertyCount = ShaderUtil.GetPropertyCount(this.targetShader);
for (var i = 0; i < propertyCount; i++)
{
var propertyName = ShaderUtil.GetPropertyName(this.targetShader, i);
if (!propertyName.StartsWith("_")) continue;
var propertyType = ShaderUtil.GetPropertyType(this.targetShader, i);
var propertyDimension = GetPropertyDimension(propertyType);
var propertyAttributes = this.targetShader.GetPropertyAttributes(i);
if (ShaderUtil.IsShaderPropertyHidden(this.targetShader, i)) continue;
var texturePropertyName = GetTexturePropertyName(propertyAttributes);
shaderProperties.Add(new ShaderProperty(propertyType, propertyName, propertyDimension, texturePropertyName));
}
this.GenerateHLSLFile(shaderProperties);
}
private void GenerateHLSLFile(List<ShaderProperty> shaderProperties)
{
var shaderPath = AssetDatabase.GetAssetPath(this.targetShader);
var directoryPath = Path.GetDirectoryName(shaderPath);
var fileName = $"{Path.GetFileNameWithoutExtension(shaderPath)}Properties.hlsl";
var filePath = Path.Combine(directoryPath, fileName);
var maxPropertyNameLength = shaderProperties.Max(x => x.Name.Length);
var sb = new StringBuilder();
sb.AppendLine("//");
sb.AppendLine("// This file is generated by ShaderPropertiesGenerator. Do not edit manually.");
sb.AppendLine("//");
sb.AppendLine();
sb.AppendLine("#include \"Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl\"");
sb.AppendLine("#include \"Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl\"");
sb.AppendLine();
// CBUFFER_START and CBUFFER_END
sb.AppendLine("CBUFFER_START(UnityPerMaterial)");
foreach (var property in shaderProperties)
{
if (property.Type is not (ShaderUtil.ShaderPropertyType.Color or ShaderUtil.ShaderPropertyType.Range or ShaderUtil.ShaderPropertyType.Float or ShaderUtil.ShaderPropertyType.Vector)) continue;
sb.AppendLine($"float{(property.Dimension == 1 ? " " : property.Dimension.ToString())} {property.Name};");
}
sb.AppendLine();
foreach (var property in shaderProperties)
{
if (property.Type != ShaderUtil.ShaderPropertyType.TexEnv) continue;
if (!string.IsNullOrEmpty(property.TexturePropertyName)) continue;
sb.AppendLine($"float4 {property.Name}_ST;");
sb.AppendLine($"float4 {property.Name}_TexelSize;");
sb.AppendLine($"float4 {property.Name}_MipInfo;");
sb.AppendLine();
}
sb.AppendLine();
sb.AppendLine("CBUFFER_END");
sb.AppendLine();
sb.AppendLine();
// UNITY_DOTS_INSTANCING_START and UNITY_DOTS_INSTANCING_END
sb.AppendLine("#ifdef UNITY_DOTS_INSTANCING_ENABLED");
sb.AppendLine("UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)");
foreach (var property in shaderProperties)
{
if (property.Type is ShaderUtil.ShaderPropertyType.Color or ShaderUtil.ShaderPropertyType.Range or ShaderUtil.ShaderPropertyType.Float or ShaderUtil.ShaderPropertyType.Vector)
sb.AppendLine($" UNITY_DOTS_INSTANCED_PROP(float{(property.Dimension == 1 ? " " : property.Dimension.ToString())}, {property.Name})");
}
sb.AppendLine("UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)");
sb.AppendLine();
foreach (var property in shaderProperties)
{
if (property.Type is not (ShaderUtil.ShaderPropertyType.Color or ShaderUtil.ShaderPropertyType.Range or ShaderUtil.ShaderPropertyType.Float)) continue;
var padding = new string(' ', maxPropertyNameLength - property.Name.Length);
sb.AppendLine($"#define {property.Name} {padding}UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float{(property.Dimension == 1 ? " " : property.Dimension.ToString())}, {property.Name})");
}
sb.AppendLine("#endif");
sb.AppendLine();
// TEXTURE2D and SAMPLER
foreach (var property in shaderProperties)
{
if (property.Type != ShaderUtil.ShaderPropertyType.TexEnv) continue;
if (property.TexturePropertyName == null)
{
var padding = new string(' ', maxPropertyNameLength - property.Name.Length);
sb.AppendLine($"TEXTURE2D({property.Name}); {padding}SAMPLER(sampler{property.Name});");
}
else
{
sb.AppendLine($"TEXTURE2D({property.Name});");
}
}
sb.AppendLine("SAMPLER(sampler_linear_clamp);");
File.WriteAllText(filePath, sb.ToString());
AssetDatabase.Refresh();
Debug.Log($"Generated HLSL file: {filePath}");
}
private static int GetPropertyDimension(ShaderUtil.ShaderPropertyType type)
{
return type switch
{
ShaderUtil.ShaderPropertyType.Color => 4,
ShaderUtil.ShaderPropertyType.Vector => 4,
ShaderUtil.ShaderPropertyType.TexEnv => 2,
_ => 1
};
}
private static string GetTexturePropertyName(string[] attributes)
{
foreach (var attribute in attributes)
{
if (!attribute.StartsWith("TextureSampler(")) continue;
var startIndex = "TextureSampler(".Length;
var endIndex = attribute.LastIndexOf(")");
if (endIndex <= startIndex) break;
return attribute.Substring(startIndex, endIndex - startIndex);
}
return null;
}
private record ShaderProperty(ShaderUtil.ShaderPropertyType Type, string Name, int Dimension, string TexturePropertyName = null)
{
public ShaderUtil.ShaderPropertyType Type { get; } = Type;
public string Name { get; } = Name;
public int Dimension { get; } = Dimension;
public string TexturePropertyName { get; } = TexturePropertyName;
}
}
@isuzu-shiranui
Copy link
Author

プロパティのアトリビュートに[TextureSampler(_MainTex)]とかって書くと、Samplerは生成しなくなる。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment