Tip
For the Chinese version (中文版), please check this.
A shader mod in HS2 could be understood as a mod letting the materials of objects provided by other mods show a different effect such like changing tint color, texture, bump, transparency, glossiness, metallic, emission, or even some geometrical performance. This kind of shader mods are always in format of .zipmod file installed in HS2 (as well as in AI-Shoujo) and can be displayed and loaded on MaterialEditor tab.
Commonly, a custom shader used in a custom mod is only applied to this mod, only shown on MaterialEditor tab when this mod's objects are selected, and could not be applied in other mods. For getting a shader be used among various mods and be displayed corresponding properties (understood as the options) on MaterialEditor tab, shader mod is needed, and so is modding it.
This tutorial is to give a brief introduction to the modders who are experienced in modding for at least HS2 studio items, letting them know the rough knowledge on building a shader mod based on the shader they already have in Unity.
Important
In this tutorial, I will not go through with how to build a common mod, such as studio item, from scratch. If you're a newbie in modding studio items, especially by using hooh's Modding Tool, it suggests to check my other tutorial (available in both English and Chinese languages) on: https://www.blatke.cc/index.html#tutorials.
I would like to give special appreciation to Hanmen, who directly and generously helped me with modding a shader to let MaterialEditor in HS2 and AIS successfully load it.
I also thank kky-is, Pizdatyi, Getdowncrazy, enimaroah and ElusiveCake, who spent time in kindly replying to my questions about shader modding, and thus have brought me with enlightenment.
In short, the process of modding a shader includes:
- Build a .zipmod file with packing the object using the material shadered by your designated shader into a .unity3d assetbundle in it.
- If you want to let your future shader mod load default textures when loading the shader on MaterialEditor tab, creating a new assetbundle with putting textures into it and packing it into the .zipmod file are neccessary.
- Add MaterialEditor-recognized tags with referring to the path(s) of the assetbundle(s) into the manifest.xml script in the .zipmod file.
The first step is to get an assetbundle, in format of .unity3d, in which there has to be gameobjects, textures, materials, compiled shaders and other stuff packed in it:
In Unity Editor 2018.4.11f, I created a shader file, namely tutorial.shader and with the title "Custom/tutorial", and a material, namely mat.mat, in Project window. So we are going to build a shader mod based on this tutorial.shader.
Drag and drop tutorial.shader into mat.mat, so the latter is now adopt tutorial.shader as its shader, and can be checked in Inspector window when selecting mat.mat.
Besides the properties given by default, I added a custom property in type of color, _CustomProperty (with the display name of Custom Property). In this shader, _CustomProperty will blend color with _Color, such like Red(1,0,0) * Blue(0,0,1) = Black(0,0,0). This shader file can be found on the Examples folder.
I assigned Albedo (_MainTex) to a custom texture namely mask.png, and created a cube in the scene, then drag and drop the material to it.
Now, build these stuff into an assetbundle. If you're using Joan6694's method, I have no more things in this section to give you, and please move to the next section.
If you are using hooh's Modding Tool, you can do what you always do for modding a studio item:
- Create the prefab of the Cube in the created folder namely prefabs.
- Create a mod.xml (mod.sxml) outside the prefabs folder but without giving any tags between <list type="studioitem"></list>. Check the mod.xml as a template on: https://github.com/Blatke/How-to-Build-A-Shader-Mod-for-HS2/blob/main/Examples/mod.xml
- Press the Build button on the window of hooh tools to build the mod. It builds everything in the prefabs folder as well as eveything referred by these prefabs into an assetbundle namely data_prefab_000.unity3d, and packs it with a generated manifest.xml file (and other lists) into a .zipmod file. Suppose that our built mod is named Tutorial_Shader.zipmod.
- Use some uncompression software to open this .zipmod file, and uncompress the data_prefab_000.unity3d the assetbundle file to your desktop or somewhere else.
Now you get the assetbundle. But don't remove the .zipmod file, we still need it.
If you want your shader mod to use its default textures when loading it into a material on MaterialEditor, you have to transfer the textures packed in the assetbundle to another assetbundle, and separately referred to them in manifest.xml. Otherwise, the textures will never be loaded along with the shader. As addressed by Hanmen, if a texture is used in the bundle material, it gets unavailable for MaterialEditor. Perhaps it's an issue in MaterialEditor, but at present we have to adopt to it.
If your shader mod has no built-in textures to load, please jump to the next section. But if yours does, please follow these steps:
- Create a new folder named abdata, then inside it create another new folder, name it chara. Then drop the assetbundle file you got, in this case data_prefab_000.unity3d into the folder abdata/chara.
- Use SB3UtilityGUI to open it, and double click it to view its content. Why we created these folders above is to meet the requirements by SB3UtilityGUI.
- Use an almost empty assetbundle as the target file to which the textures are about to be transferred from the assetbundle you got. Put it also in abdata/chara. This "empty" assetbundle can be found as a template on: https://github.com/Blatke/How-to-Build-A-Shader-Mod-for-HS2/blob/main/Examples/tex.unity3d
- Drag and drop the "empty" assetbundle, for instance tex.unity3d, into SB3UtilityGUI. Then double click it to view its content structure.
- Drag the texture, mask.png, in the data_prefab_000.unity3d and drop it into tex.unity3d to complete the transfer. Then save tex.unity3d.
- Compress tex.unity3d into the .zipmod file, put it beside the original assetbundle, data_prefab_000.unity3d.
Now we refer to data_prefab_000.unity3d as the shader assetbundle, and tex.unity3d as the texture assetbundle.
MaterialEditor reads the relevant tags in a mod's manifest.xml when loading the mod. Those tags can let MaterialEditor load the designated shader, display on its tab the properties used in the shader, and load the default textures packed in assetbundle to the material. Anyway, we have to add this sort of tags into manifest.xml. The whole template for tags can be found on: https://github.com/IllusionMods/KK_Plugins/blob/master/Guides/Material%20Editor%20Guide/shader_manifest_template.xml
For the shader properties used in this case, we can add the following tags before </manifest>:
<AI_MaterialEditor>
<Shader Name="Custom/tutorial" AssetBundle="tutorial_shader/tutorial_shader/data_prefab_000.unity3d" Asset="Cube" >
<Property Name="Color" Type="Color" DefaultValue="1,1,1,1" />
<Property Name="MainTex" Type="Texture" DefaultValue="mask" DefaultValueAssetBundle="tutorial_shader/tutorial_shader/tex.unity3d"/>
<Property Name="Glossiness" Type="Float" Range="0,1" DefaultValue="0.5" />
<Property Name="Metallic" Type="Float" Range="0,1" DefaultValue="0.5" />
<Property Name="CustomProperty" Type="Color" DefaultValue="1,1,1,1" />
</Shader>
</AI_MaterialEditor>
where in <Shader>, Name is the shader name that is the heading in tutorial.shader; AssetBundle is the path of data_prefab_000.unity3d, which is the shader assetbundle; and Asset is the Cube object using the material mat.mat shadered by this shader;
and in <Property>, Name is the property name in tutorial.shader but without the prefix "_" as a private statement in the shader file; Type is the type of the property; DefaultValue is the parameter or asset name given to the property when loading the shader, such like "mask" referring to mask.png in the texture assetbundle; and DefaultValueAssetBundle is assetbundle's path applied to a texture-typed property, such like tutorial_shader/tutorial_shader/tex.unity3d containing mask.png in it.
Note
All the paths referred by MaterialEditor tags have to begin after abdata/. For instance, the shader assetbundle in Tutorial_Shader.zipmod has the actual path, abdata/tutorial_shader/tutorial_shader/data_prefab_000.unity3d, which you can see when you open the .zipmod file in uncompression software:
The path you have to fill in the attribute, such like in AssetBundle or DefaultValueAssetBundle, has to be tutorial_shader/tutorial_shader/data_prefab_000.unity3d, and without the abdata/.
Also, the slash symbol "/" used in the path should not be written as a backslash "\".
The relation between the properties in the .shader file and the tags in the manifest.xml are drawn like this:
Please note that the tags <AI_MaterialEditor></AI_MaterialEditor> means what tags between them are only applied to AI-Shoujo. For making it apply to HS2, we need to add <HS2_MaterialEditor></HS2_MaterialEditor>, and duplicate the same tags from above into them. So the whole manifest.xml could seem to be:
<manifest schema-ver="1">
<guid>Tutorial Shader</guid>
<name>Tutorial Shader</name>
<version>0.0.1</version>
<author>Anonymous</author>
<description></description>
<AI_MaterialEditor>
<Shader Name="Custom/tutorial" AssetBundle="tutorial_shader/tutorial_shader/data_prefab_000.unity3d" Asset="Cube" >
<Property Name="Color" Type="Color" DefaultValue="1,1,1,1" />
<Property Name="MainTex" Type="Texture" DefaultValue="mask" DefaultValueAssetBundle="tutorial_shader/tutorial_shader/tex.unity3d"/>
<Property Name="Glossiness" Type="Float" Range="0,1" DefaultValue="0.5" />
<Property Name="Metallic" Type="Float" Range="0,1" DefaultValue="0.5" />
<Property Name="CustomProperty" Type="Color" DefaultValue="1,1,1,1" />
</Shader>
</AI_MaterialEditor>
<HS2_MaterialEditor>
<Shader Name="Custom/tutorial" AssetBundle="tutorial_shader/tutorial_shader/data_prefab_000.unity3d" Asset="Cube" >
<Property Name="Color" Type="Color" DefaultValue="1,1,1,1" />
<Property Name="MainTex" Type="Texture" DefaultValue="mask" DefaultValueAssetBundle="tutorial_shader/tutorial_shader/tex.unity3d"/>
<Property Name="Glossiness" Type="Float" Range="0,1" DefaultValue="0.5" />
<Property Name="Metallic" Type="Float" Range="0,1" DefaultValue="0.5" />
<Property Name="CustomProperty" Type="Color" DefaultValue="1,1,1,1" />
</Shader>
</HS2_MaterialEditor>
</manifest>
Finally, save the manifest.xml into the .zipmod file to complete the whole process.
The manifest.xml and Tutorial_Shader.zipmod could be found in the Examples folder.
After installing this mod in the game, and loading the shader into an item such like a capsule in Studio, the tab of MaterialEditor and the texture are shown as below:
When you have tens of properties in a shader file, it's gonna be a nightmare for making each of them a tag to add in manifest.xml. If you use Visual Code or some other coding software that supports RegEx (Regular Expression), you can do the following steps to batch convert the properties in a shader file into MaterialEditor-related tags:
- Copy the properties to a new file.
- Press hotkey Ctrl + F to call the tab for finding and replacing. Enable the RegEx function.
- For converting float properties, copy and paste the following RegEx and tag respectively into the finding box and replacing box:
Copy to Finding Box:
_([^ ]+)[ ]*\([^,]+,[ ]*Range\(([\-0-9,. ]+)\)[^0-9]+([0-9.\-]+)
Copy to Replacing Box:
<Property Name="$1" Type="Float" Range="$2" DefaultValue="$3" />
Then replace all.
- For converting color properties, copy and paste the following RegEx and tag respectively into the finding box and replacing box:
Copy to Finding Box:
_([^ ]+)[ ]*\([^,]+,[ ]*Color\)[^\(]+\(([0-9., ]+)\)
Copy to Replacing Box:
<Property Name="$1" Type="Color" DefaultValue="$2" />
Then replace all.
- For converting texture properties, copy and paste the following RegEx and tag respectively into the finding box and replacing box:
Copy to Finding Box:
_([^ ]+)[ ]*\([^,]+,[ ]*2D\)[^\n]+
Copy to Replacing Box:
<Property Name="$1" Type="Texture" DefaultValue="" DefaultValueAssetBundle=""/>
Then replace all.