Shader Controller classes
Hi. I will do a series of posts explaining some of the new features.
In order to get 3rd party shaders integrated better with I added a system to create shader controller classes. These are found by reflection and can be included in 3rd party assets but I will also create and include several.
These classes can expose settings to the Vegetation System UI that will serialize and save with the Vegetation Package.

Here is an example for the shader UI for the grass from Nature Manufacture.
The shader class will also get a callback for setting wind and when a material needs updating.
This way you can add custom logic to the material update.
The speedtree support is added this way. It contains a bit more custom logic. I will share it here.

The default behavior if the speedtree controller is to replace the speedtree shader with a custom version that supports instanced indirect rendering. This is done run-time and will not change the original prefab.
In addition to this it exposes different tint setting for bark and foliage.
#if VEGETATION_STUDIO_PRO
using AwesomeTechnologies.VegetationSystem;
using UnityEngine;
namespace AwesomeTechnologies.Shaders
{
public class SpeedtreeShaderController : IShaderController
{
public bool MatchShader(string shaderName)
{
return (shaderName == "Nature/SpeedTree");
}
public bool MatchBillboardShader(Material[] materials)
{
return false;
}
public ShaderControllerSettings Settings { get; set; }
public void CreateDefaultSettings(Material[] materials)
{
Settings = new ShaderControllerSettings
{
Heading = "SpeedTree settings",
Description = "",
LODFadePercentage = true,
LODFadeCrossfade = true,
SampleWind = true,
DynamicHUE = true,
BillboardHDWind = false
};
Settings.AddBooleanProperty("ReplaceShader", "Replace shader", "This will replace the speedtree shader with a Vegetation Studio version that supports instancd indirect", true);
Settings.AddLabelProperty("Foliage settings");
Settings.AddColorProperty("FoliageHue", "Foliage HUE variation", "",
ShaderControllerSettings.GetColorFromMaterials(materials, "_HueVariation"));
Settings.AddColorProperty("FoliageTintColor", "Foliage tint color", "",
ShaderControllerSettings.GetColorFromMaterials(materials, "_Color"));
Settings.AddLabelProperty("Bark settings");
Settings.AddColorProperty("BarkHue", "Bark HUE variation", "",
ShaderControllerSettings.GetColorFromMaterials(materials, "_HueVariation"));
Settings.AddColorProperty("BarkTintColor", "Bark tint color", "",
ShaderControllerSettings.GetColorFromMaterials(materials, "_Color"));
}
public void UpdateMaterial(Material material, EnvironmentSettings environmentSettings)
{
if (Settings == null) return;
Color foliageHueVariation = Settings.GetColorPropertyValue("FoliageHue");
Color barkHueVariation = Settings.GetColorPropertyValue("BarkHue");
Color foliageTintColor = Settings.GetColorPropertyValue("FoliageTintColor");
Color barkTintColor = Settings.GetColorPropertyValue("BarkTintColor");
bool replaceShader = Settings.GetBooleanPropertyValue("ReplaceShader");
material.SetFloat("_Cutoff", material.GetFloat("_Cutoff"));
if (HasKeyword(material,"GEOM_TYPE_BRANCH"))
{
material.SetColor("_HueVariation", barkHueVariation);
material.SetColor("_Color", barkTintColor);
}
else
{
material.SetColor("_HueVariation", foliageHueVariation);
material.SetColor("_Color", foliageTintColor);
}
if (replaceShader)
{
if (material.shader.name != "AwesomeTechnologies/VS_SpeedTree")
{
material.shader = Shader.Find("AwesomeTechnologies/VS_SpeedTree");
}
}
else
{
if (material.shader.name != "Nature/SpeedTree")
{
material.shader = Shader.Find("Nature/SpeedTree");
}
}
}
bool HasKeyword(Material material, string keyword)
{
for (int i = 0; i <= material.shaderKeywords.Length - 1; i++)
{
if (material.shaderKeywords[i].Contains(keyword))
{
return true;
}
}
return false;
}
public void UpdateWind(Material material, WindSettings windSettings)
{
}
}
}
#endif
The class needs to implement the functions on the IShaderController interface to be detected by Vegetation Studio Pro.
The match shader function is used to detect what shaders the controller supports. this could be multiple shaders.
Match billboard shader is used to detect custom billboard shaders in prefabs with LODGroups and exclude those from rendering. The billboard system in vegetation studio will take over this.
public bool MatchShader(string shaderName)
{
return (shaderName == "Nature/SpeedTree");
}
public bool MatchBillboardShader(Material[] materials)
{
return false;
}
CreateDefaultSettings is called the first time the controller is initialized. It allows you to set capabilities of the shader like instanced indirect support. With this set to true this will be the default render setting for the shader. Also fading, billboard wind etc.
it then allows you to add properties for the UI and saving. Floats, labels, colors, booleans etc.
These are saved in the vegetation package and you can read them back to use in the UpdateMaterial call.
public void CreateDefaultSettings(Material[] materials)
{
Settings = new ShaderControllerSettings
{
Heading = "SpeedTree settings",
Description = "",
LODFadePercentage = true,
LODFadeCrossfade = true,
SampleWind = true,
DynamicHUE = true,
BillboardHDWind = false
};
Settings.AddBooleanProperty("ReplaceShader", "Replace shader", "This will replace the speedtree shader with a Vegetation Studio version that supports instancd indirect", true);
Settings.AddLabelProperty("Foliage settings");
Settings.AddColorProperty("FoliageHue", "Foliage HUE variation", "",
When a material needs to refresh the UpdateMaterial function is called. Here you can read back properties and set material properties as needed. It also gets access to EnvironmentSettings that holds info like snow cover, wetness etc from a global setting for all vegetation. Shaders that support this can then update.
public void UpdateMaterial(Material material, EnvironmentSettings environmentSettings)
{
if (Settings == null) return;
Color foliageHueVariation = Settings.GetColorPropertyValue("FoliageHue");
Color barkHueVariation = Settings.GetColorPropertyValue("BarkHue");
Color foliageTintColor = Settings.GetColorPropertyValue("FoliageTintColor");
Color barkTintColor = Settings.GetColorPropertyValue("BarkTintColor");
bool replaceShader = Settings.GetBooleanPropertyValue("ReplaceShader");
material.SetFloat("_Cutoff", material.GetFloat("_Cutoff"));
Lennart