// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.Rendering; namespace Microsoft.MixedReality.GraphicsTools.Samples.MaterialGallery { /// /// Builds a matrix of spheres demonstrating a spectrum of two material properties. /// [ExecuteInEditMode] public class MaterialMatrix : MonoBehaviour { [SerializeField] private Material material = null; [SerializeField] private bool useDefaultMaterial = false; [SerializeField] private UnityEngine.Mesh mesh = null; [SerializeField] [Range(2, 100)] private int dimension = 5; [SerializeField] [Range(0.0f, 10.0f)] private float positionOffset = 0.1f; [SerializeField] private Color materialColor = new Color(0.5f, 0.5f, 0.5f, 1.0f); [SerializeField] private string firstPropertyName = "_Metallic"; [SerializeField] private string secondPropertyName = "_Smoothness"; [SerializeField] private string secondPropertyFallbackName = "_Glossiness"; [SerializeField] private Vector3 localScale = Vector3.one * 0.1f; [SerializeField] private Vector3 localRotation = Vector3.zero; private RenderPipelineAsset lastRenderPipelineAsset = null; #if UNITY_EDITOR private void Awake() { BuildMatrix(); } private void Update() { // Poll for when the render pipeline changes. if (useDefaultMaterial) { if (lastRenderPipelineAsset != GraphicsSettings.renderPipelineAsset) { BuildMatrix(); } } } #endif [ContextMenu("Build Matrix")] private void BuildMatrix() { List children = transform.Cast().ToList(); for (int i = 0; i < children.Count; ++i) { Transform child = children[i]; if (Application.isPlaying) { Destroy(child.gameObject); } else { DestroyImmediate(child.gameObject); } } Material currentMaterial; if (useDefaultMaterial) { lastRenderPipelineAsset = GraphicsSettings.renderPipelineAsset; if (lastRenderPipelineAsset != null) { currentMaterial = lastRenderPipelineAsset.defaultMaterial; } else { GameObject primitive = GameObject.CreatePrimitive(PrimitiveType.Quad); currentMaterial = primitive.GetComponent().sharedMaterial; DestroyImmediate(primitive); } } else { if (material == null) { Debug.LogError("Failed to build material matrix due to missing material."); return; } currentMaterial = material; } currentMaterial.color = materialColor; float center = (dimension - 1) * positionOffset * -0.5f; Vector3 position = new Vector3(center, 0.0f, center); int firstPropertyId = Shader.PropertyToID(firstPropertyName); int secondPropertyId = currentMaterial.HasProperty(secondPropertyName) ? Shader.PropertyToID(secondPropertyName) : Shader.PropertyToID(secondPropertyFallbackName); float firstProperty = 0.0f; float secondProperty = 0.0f; for (int i = 0; i < dimension; ++i) { for (int j = 0; j < dimension; ++j) { GameObject element = GameObject.CreatePrimitive(PrimitiveType.Sphere); element.name = "Element" + (i * dimension + j); element.transform.parent = transform; element.transform.localPosition = position; element.transform.localRotation = Quaternion.Euler(localRotation); element.transform.localScale = localScale; position.x += positionOffset; Material newMaterial = new Material(currentMaterial); newMaterial.SetFloat(firstPropertyId, firstProperty); newMaterial.SetFloat(secondPropertyId, secondProperty); Renderer _renderer = element.GetComponent(); MeshFilter meshFilter = element.GetComponent(); if (Application.isPlaying) { _renderer.material = newMaterial; if (mesh != null) { meshFilter.mesh = mesh; Destroy(element.GetComponent()); element.AddComponent(); } } else { _renderer.sharedMaterial = newMaterial; if (mesh != null) { meshFilter.mesh = mesh; DestroyImmediate(element.GetComponent()); element.AddComponent(); } } firstProperty += 1.0f / (dimension - 1); } position.x = center; position.z += positionOffset; firstProperty = 0.0f; secondProperty += 1.0f / (dimension - 1); } } } }