unity/Assets/Scripts/Randomizers/MaterialRandomizer.cs (123 lines of code) (raw):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// MaterialRandomizer assigns random tint, texture and normal map
// to a subset of materials. It also modifies the material's
// glossiness and metallic properties that control how shading
// appears in the Unity PBR model. The textures and normals are
// randomly picked from a small set of random images: checkers,
// patterns, noise, etc... Texture map tiling is also randomized.
//
// Configurable properties:
// string blacklist_prefix - comma separated list of material
// name prefixes to ignore,
// string whitelist_prefix - comma separated list of material
// name prefixes to randomize,
// float min_metallic - used to clamp the metallic randomization range,
// float max_metallic - used to clamp the metallic randomization range,
// float min_glossiness - used to clamp the glossiness randomization range,
// float max_glossiness - used to clamp the glossiness randomization range,
// bool randomize_textures - should textures and normal maps be
// randomly assigned.
public class MaterialRandomizer : RendererComponent {
[SerializeField]
[ConfigProperty]
public string blacklist_prefix_ = "cube";
[SerializeField]
[ConfigProperty]
public string whitelist_prefix_ = "";
[SerializeField]
[ConfigProperty]
public float min_metallic_ = 0.05f;
[SerializeField]
[ConfigProperty]
public float max_metallic_ = 0.25f;
[SerializeField]
[ConfigProperty]
public float min_glossiness_ = 0.0f;
[SerializeField]
[ConfigProperty]
public float max_glossiness_ = 1.0f;
[SerializeField]
[ConfigProperty]
public bool randomize_textures_ = false;
private List<Texture> textures_ = new List<Texture>();
private List<Texture> normals_ = new List<Texture>();
private string[] blacklist_prefixes_ = new string[0];
private string[] whitelist_prefixes_ = new string[0];
public override bool InitializeComponent(Orrb.RendererComponentConfig config) {
textures_.AddRange(Resources.LoadAll<Texture>("Textures"));
normals_.AddRange(Resources.LoadAll<Texture>("Normals"));
return base.InitializeComponent(config);
}
public override bool UpdateComponent(Orrb.RendererComponentConfig config) {
ConfigUtils.GetProperties(this, config);
blacklist_prefixes_ = blacklist_prefix_.Split(new char[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries);
whitelist_prefixes_ = whitelist_prefix_.Split(new char[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries);
return true;
}
public override bool RunComponent(RendererComponent.IOutputContext context) {
MeshRenderer[] renderers = GetComponentsInChildren<MeshRenderer>();
foreach (MeshRenderer mesh_renderer in renderers) {
foreach (Material material in mesh_renderer.materials) {
RandomizeMaterial(material);
}
}
return true;
}
private void RandomizeMaterial(Material material) {
foreach (string prefix in blacklist_prefixes_) {
if (material.name.StartsWith(prefix, System.StringComparison.Ordinal)) {
return;
}
}
if (whitelist_prefixes_.Length == 0) {
DoRandomizeMaterial(material);
} else {
foreach (string prefix in whitelist_prefixes_) {
if (material.name.StartsWith(prefix, System.StringComparison.Ordinal)) {
DoRandomizeMaterial(material);
return;
}
}
}
}
private void DoRandomizeMaterial(Material material) {
if (material.HasProperty("_Color")) {
// Do not randomize transparency, keep alpha as it was.
float alpha = material.color.a;
material.color = Random.ColorHSV(0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, alpha, alpha);
}
if (material.HasProperty("_Metallic")) {
material.SetFloat("_Metallic", Random.Range(min_metallic_, max_metallic_));
}
if (material.HasProperty("_Glossiness")) {
material.SetFloat("_Glossiness", Random.Range(min_glossiness_, max_glossiness_));
}
if (randomize_textures_) {
if (material.HasProperty("_MainTex")) {
material.SetTexture("_MainTex", GetRandomTexture());
material.SetTextureScale("_MainTex", new Vector2(Random.Range(0.4f, 4.0f), Random.Range(0.4f, 4.0f)));
material.SetTextureOffset("_MainTex", new Vector2(Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f)));
}
if (material.HasProperty("_BumpMap")) {
material.SetTexture("_BumpMap", GetRandomNormal());
material.SetTextureScale("_BumpMap", new Vector2(Random.Range(0.4f, 4.0f), Random.Range(0.4f, 4.0f)));
material.SetTextureOffset("_BumpMap", new Vector2(Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f)));
}
} else {
if (material.HasProperty("_MainTex")) {
material.SetTexture("_MainTex", null);
}
if (material.HasProperty("_BumpMap")) {
material.SetTexture("_BumpMap", null);
}
}
}
private Texture GetRandomTexture() {
if (textures_.Count > 0) {
return textures_[Random.Range(0, textures_.Count)];
} else {
return null;
}
}
private Texture GetRandomNormal() {
if (normals_.Count > 0) {
return normals_[Random.Range(0, normals_.Count)];
} else {
return null;
}
}
public override void DrawEditorGUI() {
GUILayout.BeginVertical();
RendererComponent.GUIField("blacklist_prefix", ref blacklist_prefix_);
RendererComponent.GUIField("whitelist_prefix", ref whitelist_prefix_);
RendererComponent.GUISlider("min_metallic", ref min_metallic_, 0.0f, max_metallic_);
RendererComponent.GUISlider("max_metallic", ref max_metallic_, min_metallic_, 1.0f);
RendererComponent.GUISlider("min_glossiness", ref min_glossiness_, 0.0f, max_glossiness_);
RendererComponent.GUISlider("max_glossiness", ref max_glossiness_, min_glossiness_, 1.0f);
RendererComponent.GUIToggle("randomize_textures", ref randomize_textures_);
GUILayout.EndVertical();
}
}