Added ChannelMixer

This commit is contained in:
Misaki
2024-12-26 19:48:31 +09:00
parent 2a455513bc
commit b00b63cfb4
30 changed files with 284 additions and 61 deletions

View File

@@ -0,0 +1,85 @@
Shader "Hidden/GenerateMask"
{
Properties
{
_TexR ("Red Channel Texture", 2D) = "white"
_TexG ("Green Channel Texture", 2D) = "white"
_TexB ("Blue Channel Texture", 2D) = "white"
_TexA ("Alpha Channel Texture", 2D) = "white"
}
SubShader
{
Cull Off
ZWrite Off
ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature_local _HAS_TEX_R
#pragma shader_feature_local _HAS_TEX_G
#pragma shader_feature_local _HAS_TEX_B
#pragma shader_feature_local _HAS_TEX_A
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _TexR;
sampler2D _TexG;
sampler2D _TexB;
sampler2D _TexA;
float4 _Fallback;
float4 frag (v2f i) : SV_Target
{
#ifdef _HAS_TEX_R
float r = tex2D(_TexR, i.uv).r;
#else
float r = _Fallback.r;
#endif
#ifdef _HAS_TEX_G
float g = tex2D(_TexG, i.uv).r;
#else
float g = _Fallback.g;
#endif
#ifdef _HAS_TEX_B
float b = tex2D(_TexB, i.uv).r;
#else
float b = _Fallback.b;
#endif
#ifdef _HAS_TEX_A
float a = tex2D(_TexA, i.uv).r;
#else
float a = _Fallback.a;
#endif
return float4(r, g, b, a);
}
ENDCG
}
}
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 132046c0498c1ab49aa91453b6ae2766
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -21,20 +21,20 @@ namespace Misaki.ArtToolEditor
}
}
private class Constants
private class ShaderConstants
{
internal const string Generate_Mask_Shader_Path = "Hidden/GenerateMask";
internal const string Texture_R_Property = "_TexR";
internal const string Texture_G_Property = "_TexG";
internal const string Texture_B_Property = "_TexB";
internal const string Texture_A_Property = "_TexA";
internal const string Fallback_Property = "_Fallback";
internal const string Has_Texture_R_Keyword = "_HAS_TEX_R";
internal const string Has_Texture_G_Keyword = "_HAS_TEX_G";
internal const string Has_Texture_B_Keyword = "_HAS_TEX_B";
internal const string Has_Texture_A_Keyword = "_HAS_TEX_A";
internal const string Png_Extension = ".png";
}
public string metallicTextureRegex = ".*_metallic";
@@ -49,7 +49,7 @@ namespace Misaki.ArtToolEditor
public string textureGroupingRegex = "^([^_]+)_";
public string namingRegex;
public TextureNamingSourceType namingSource;
public TextureChannel namingSource;
public string replaceBy = "Mask";
public void OnPreProcess(AssetsProcessContext context)
@@ -100,10 +100,13 @@ namespace Misaki.ArtToolEditor
GetTextureSizeAndName(metallicTexture, aoTexture, detailMaskTexture, out var textureSize, out var textureName);
SetupAndBlitTexture(metallicTexture, aoTexture, detailMaskTexture, smoothnessTexture, textureSize, out var tempRT, out var material);
ExportTextureToPNG(group, textureName, tempRT);
var texturePath = Path.Combine(group.Value.outputDirectory, textureName + Constants.Extensions.PNG);
TextureHelpers.ExportRenderTextureToPNG(tempRT, texturePath);
AssetDatabase.ImportAsset(texturePath);
UnityEngine.Object.DestroyImmediate(material);
tempRT.Release();
RenderTexture.ReleaseTemporary(tempRT);
}
}
catch (Exception e)
@@ -138,19 +141,19 @@ namespace Misaki.ArtToolEditor
textureName = string.Empty;
switch (namingSource)
{
case TextureNamingSourceType.R:
case TextureChannel.R:
textureSize = new Vector2Int(metallicTexture.width, metallicTexture.height);
textureName = Regex.Replace(metallicTexture.name, namingRegex, replaceBy, RegexOptions.IgnoreCase | RegexOptions.Compiled);
break;
case TextureNamingSourceType.G:
case TextureChannel.G:
textureSize = new Vector2Int(aoTexture.width, aoTexture.height);
textureName = Regex.Replace(aoTexture.name, namingRegex, replaceBy, RegexOptions.IgnoreCase | RegexOptions.Compiled);
break;
case TextureNamingSourceType.B:
case TextureChannel.B:
textureSize = new Vector2Int(detailMaskTexture.width, detailMaskTexture.height);
textureName = Regex.Replace(detailMaskTexture.name, namingRegex, replaceBy, RegexOptions.IgnoreCase | RegexOptions.Compiled);
break;
case TextureNamingSourceType.A:
case TextureChannel.A:
textureSize = new Vector2Int(detailMaskTexture.width, detailMaskTexture.height);
textureName = Regex.Replace(detailMaskTexture.name, namingRegex, replaceBy, RegexOptions.IgnoreCase | RegexOptions.Compiled);
break;
@@ -162,29 +165,29 @@ namespace Misaki.ArtToolEditor
tempRT = RenderTexture.GetTemporary(textureSize.x, textureSize.y, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
tempRT.Create();
material = new Material(Shader.Find(Constants.Generate_Mask_Shader_Path));
material = new Material(Shader.Find(ShaderConstants.Generate_Mask_Shader_Path));
if (textureR != null)
{
material.SetTexture(Constants.Texture_R_Property, textureR);
material.EnableKeyword(Constants.Has_Texture_R_Keyword);
material.SetTexture(ShaderConstants.Texture_R_Property, textureR);
material.EnableKeyword(ShaderConstants.Has_Texture_R_Keyword);
}
if (textureG != null)
{
material.SetTexture(Constants.Texture_G_Property, textureG);
material.EnableKeyword(Constants.Has_Texture_G_Keyword);
material.SetTexture(ShaderConstants.Texture_G_Property, textureG);
material.EnableKeyword(ShaderConstants.Has_Texture_G_Keyword);
}
if (textureB != null)
{
material.SetTexture(Constants.Texture_B_Property, textureB);
material.EnableKeyword(Constants.Has_Texture_B_Keyword);
material.SetTexture(ShaderConstants.Texture_B_Property, textureB);
material.EnableKeyword(ShaderConstants.Has_Texture_B_Keyword);
}
if (textureA != null)
{
material.SetTexture(Constants.Texture_A_Property, textureA);
material.EnableKeyword(Constants.Has_Texture_A_Keyword);
material.SetTexture(ShaderConstants.Texture_A_Property, textureA);
material.EnableKeyword(ShaderConstants.Has_Texture_A_Keyword);
}
var fallback = new Vector4(
@@ -198,20 +201,6 @@ namespace Misaki.ArtToolEditor
Graphics.Blit(null, tempRT, material);
}
private static void ExportTextureToPNG(KeyValuePair<string, PackingConfig> group, string textureName, RenderTexture tempRT)
{
var exportTexture = new Texture2D(tempRT.width, tempRT.height, TextureFormat.RGBA32, false);
exportTexture.ReadPixels(new Rect(0, 0, tempRT.width, tempRT.height), 0, 0);
exportTexture.Apply();
var bytes = exportTexture.EncodeToPNG();
var path = Path.Combine(group.Value.outputDirectory, textureName + Constants.Png_Extension);
File.WriteAllBytes(path, bytes);
UnityEngine.Object.DestroyImmediate(exportTexture);
AssetDatabase.ImportAsset(path);
}
private float GetFallbackValue(TextureFallbackType type)
{
return type switch

View File

@@ -6,7 +6,7 @@ namespace Misaki.ArtToolEditor
{
internal class GenerateMaskVisualProvider : OptionsVisualProvider
{
internal override VisualElement ContentAfterList()
public override VisualElement ContentAfterList()
{
var root = new VisualElement();
@@ -35,7 +35,7 @@ namespace Misaki.ArtToolEditor
root.Add(CreateTextInputWithEnumField("Naming Regex",
nameof(GenerateMaskProcessor.namingRegex),
nameof(GenerateMaskProcessor.namingSource),
TextureNamingSourceType.R));
TextureChannel.R));
root.Add(CreateTextInputField("Replace By",
nameof(GenerateMaskProcessor.replaceBy)));
@@ -43,14 +43,14 @@ namespace Misaki.ArtToolEditor
return root;
}
private VisualElement CreateTextInputField(string label, string binding)
private static VisualElement CreateTextInputField(string label, string binding)
{
var textField = new TextField(label);
textField.SetBinding(nameof(TextField.value), new DataBinding() { dataSourcePath = PropertyPath.FromName(binding) });
return textField;
}
private VisualElement CreateTextInputWithEnumField(string label, string textInputBinding, string enumBinding, Enum defaultEnumValue)
private static VisualElement CreateTextInputWithEnumField(string label, string textInputBinding, string enumBinding, Enum defaultEnumValue)
{
var root = new VisualElement()
{