Minor - Add Assets And Support Dual Screen

This commit is contained in:
2026-02-03 16:15:50 +01:00
parent 76132c2cbe
commit 7a3d9e54c4
1039 changed files with 149985 additions and 21327 deletions

View File

@@ -0,0 +1,18 @@
{
"name": "OmniShade.Editor",
"rootNamespace": "",
"references": [
"GUID:e9de827a4aa124dc5932ae83b40f91fc"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: a5e550829f8084fb6a2ed5cb130e43e0
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 215111
packageName: OmniShade - Mobile Optimized Shader
packageVersion: 1.9.5
assetPath: Assets/OmniShade/Scripts/Editor/OmniShade.Editor.asmdef
uploadId: 825160

View File

@@ -0,0 +1,712 @@
#define LITE
//------------------------------------
// OmniShade
// Copyright© 2025 OmniShade
//------------------------------------
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using System.Collections.Generic;
using System.Linq;
/**
* This class manages the GUI for the shader, automatically enabling/disabling keywords when values change.
**/
public class OmniShadeGUI : ShaderGUI {
// Shader keywords which are automatically enabled/disabled based on usage
readonly List<(string keyword, string name, PropertyType type, Vector4 defaultValue)> props = new List<(string keyword, string name, PropertyType type, Vector4 defaultValue)>() {
("TOP_TEX", "_TopTex", PropertyType.Texture, Vector4.one), // Triplanar
("TRIPLANAR_SHARPNESS", "_TriplanarSharpness", PropertyType.Float, Vector4.one), // Triplanar
("BASE_CONTRAST", "_Contrast", PropertyType.Float, Vector4.one),
("BASE_SATURATION", "_Saturation", PropertyType.Float, Vector4.one),
("SPECULAR_MAP", "_SpecularTex", PropertyType.Texture, Vector4.one),
("RIM_DIRECTION", "_RimDirection", PropertyType.Vector, Vector4.zero),
("REFLECTION_TEX", "_ReflectionTex", PropertyType.Texture, Vector4.one),
("NORMAL_MAP", "_NormalTex", PropertyType.Texture, Vector4.one),
("NORMAL_MAP2", "_NormalTex2", PropertyType.Texture, Vector4.one),
("NORMAL_MAP_TOP", "_NormalTopTex", PropertyType.Texture, Vector4.one), // Triplanar
("LIGHT_MAP", "_LightmapTex", PropertyType.Texture, Vector4.one),
("EMISSIVE_MAP", "_EmissiveTex", PropertyType.Texture, Vector4.one),
("MATCAP", "_MatCapTex", PropertyType.Texture, Vector4.one),
("MATCAP_CONTRAST", "_MatCapContrast", PropertyType.Float, Vector4.one),
("VERTEX_COLORS_CONTRAST", "_VertexColorsContrast", PropertyType.Float, Vector4.one),
("DETAIL", "_DetailTex", PropertyType.Texture, Vector4.one),
("DETAIL_CONTRAST", "_DetailContrast", PropertyType.Float, Vector4.one),
("LAYER1", "_Layer1Tex", PropertyType.Texture, Vector4.one),
("LAYER2", "_Layer2Tex", PropertyType.Texture, Vector4.one),
("LAYER3", "_Layer3Tex", PropertyType.Texture, Vector4.one),
("TRANSPARENCY_MASK", "_TransparencyMaskTex", PropertyType.Texture, Vector4.one),
("TRANSPARENCY_MASK_CONTRAST", "_TransparencyMaskContrast", PropertyType.Float, Vector4.one),
("HEIGHT_COLORS_TEX", "_HeightColorsTex", PropertyType.Texture, Vector4.one),
("AMBIENT", "_AmbientBrightness", PropertyType.Float, Vector4.zero),
("SHADOW_OVERLAY", "_ShadowOverlayTex", PropertyType.Texture, Vector4.one),
("ANIME_SOFT", "_AnimeSoftness", PropertyType.Float, Vector4.zero),
("ZOFFSET", "_ZOffset", PropertyType.Float, Vector4.zero),
};
// Parameters that are ON by default
readonly List<(string keyword, string name)> defaultOnParams = new List<(string keyword, string name)>() {
("DIFFUSE", "_Diffuse" ),
("MATCAP_PERSPECTIVE", "_MatCapPerspective" ),
("AMBIENT", "_Ambient" ),
("FOG", "_Fog" ),
("SHADOWS_ENABLED", "_ShadowsEnabled" ),
};
enum PropertyType {
Float, Vector, Texture
};
struct PropertyHeader {
public string headerName;
public bool isOpen;
public PropertyHeader(string _header, bool _isOpen) {
this.headerName = _header;
this.isOpen = _isOpen;
}
};
const string HEADER_GROUP = "HeaderGroup";
enum ExpandType {
All,
Active,
Collapse,
Keep,
};
ExpandType forceExpand = ExpandType.Active;
int prevPreset = -1;
List<Material> prevSelectedMats = new List<Material>();
readonly Dictionary<string, PropertyHeader> propertyHeaders = new Dictionary<string, PropertyHeader>();
static readonly Dictionary<string, GUIContent> toolTipsCache = new Dictionary<string, GUIContent>();
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) {
this.RenderGUI(materialEditor, properties);
// Loop selected materials
var mats = this.GetSelectedMaterials(materialEditor);
foreach (var material in mats) {
this.AutoEnableShaderKeywords(material);
this.UpdatePresetValues(material);
// Reset previous preset if multi-selection
if (mats.Count > 1)
this.prevPreset = -1;
}
// Reset preset if selection changed
if (mats.Count == 1 && this.prevSelectedMats.Count == 1 &&
mats[0] != null && this.prevSelectedMats[0] != null && mats[0].name != this.prevSelectedMats[0].name)
this.prevPreset = -1;
this.prevSelectedMats = mats;
}
List<Material> GetSelectedMaterials(MaterialEditor materialEditor) {
var mat = materialEditor.target as Material;
var mats = new List<Material>();
if (mat != null)
mats.Add(mat);
foreach (var selected in Selection.objects) {
if (selected.GetType() == typeof(Material)) {
var selectedMat = selected as Material;
if (selectedMat != mat && selectedMat != null &&
selectedMat.shader.name.Contains(OmniShade.NAME))
mats.Add(selectedMat);
}
}
return mats;
}
void AutoEnableShaderKeywords(Material mat) {
foreach (var prop in this.props) {
if (!mat.HasProperty(prop.name))
continue;
// Check if property value is being used (not set to default)
bool isInUse = false;
switch (prop.type) {
case PropertyType.Float:
isInUse = mat.GetFloat(prop.name) != prop.defaultValue.x;
break;
case PropertyType.Vector:
isInUse = mat.GetVector(prop.name) != prop.defaultValue;
break;
case PropertyType.Texture:
isInUse = mat.GetTexture(prop.name) != null;
break;
default:
break;
}
// Enable or disable shader keyword
if (isInUse) {
if (!mat.IsKeywordEnabled(prop.keyword))
mat.EnableKeyword(prop.keyword);
}
else if (mat.IsKeywordEnabled(prop.keyword))
mat.DisableKeyword(prop.keyword);
}
// Set keywords for parameters that are ON by default
foreach (var defaultOnParam in this.defaultOnParams) {
if (mat.HasProperty(defaultOnParam.name) && mat.GetFloat(defaultOnParam.name) == 1)
mat.EnableKeyword(defaultOnParam.keyword);
}
this.AutoConfigureProperties(mat);
}
void AutoConfigureProperties(Material mat) {
// MatCap Static Rotation default angle points to camera
if (mat.IsKeywordEnabled("MATCAP_STATIC") && mat.HasProperty("_MatCapRot") &&
mat.GetVector("_MatCapRot") == Vector4.zero) {
var cam = GameObject.FindFirstObjectByType<Camera>();
if (cam != null) {
var matCapRot = -cam.transform.rotation.eulerAngles * Mathf.PI / 180;
mat.SetVector("_MatCapRot", matCapRot);
}
}
// Camera fade
float fadeStart = mat.HasProperty("_CameraFadeStart") ? mat.GetFloat("_CameraFadeStart") : 0;
float fadeEnd = mat.HasProperty("_CameraFadeEnd") ? mat.GetFloat("_CameraFadeEnd") : 0;
bool cameraFadeEnabled = fadeStart < fadeEnd;
EnableDisableKeyword(mat, cameraFadeEnabled, "CAMERA_FADE");
// Enable/disable outline pass
bool outlineEnabled = mat.GetFloat("_Outline") == 1;
string outlinePassName = mat.shader.name.Contains("URP") ? "SRPDefaultUnlit" : "Always";
if (outlineEnabled != mat.GetShaderPassEnabled(outlinePassName))
mat.SetShaderPassEnabled(outlinePassName, outlineEnabled);
EnableDisableKeyword(mat, !outlineEnabled, "OUTLINE_PASS_DISABLED");
if (mat.GetInt("_OutlineComp") == 6) { // Interior outline: Show
// Auto-set OutlineGroup to non-zero value if hiding interior outlines
if (mat.GetInt("_OutlineGroup") == 0)
mat.SetInt("_OutlineGroup", 1);
mat.SetInt("_OutlinePass", 2); // Stencil pass: Replace
}
else
mat.SetInt("_OutlinePass", 0); // Stencil pass: Keep
// Enable GPU instancing automatically for certain keywords
var instancingParams = new List<string>() {
"_Plant",
};
if (!mat.enableInstancing) {
foreach (var instancingParma in instancingParams) {
if ((mat.HasProperty(instancingParma) && mat.GetFloat(instancingParma) == 1))
mat.enableInstancing = true;
}
}
// Global illumination floag
if (mat.GetVector("_Emissive") != Vector4.zero) {
if (mat.globalIlluminationFlags != MaterialGlobalIlluminationFlags.BakedEmissive)
mat.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
}
else {
if (mat.globalIlluminationFlags != MaterialGlobalIlluminationFlags.EmissiveIsBlack)
mat.globalIlluminationFlags = MaterialGlobalIlluminationFlags.EmissiveIsBlack;
}
}
void EnableDisableKeyword(Material mat, bool value, string keyword) {
if (value) {
if (!mat.IsKeywordEnabled(keyword))
mat.EnableKeyword(keyword);
}
else {
if (mat.IsKeywordEnabled(keyword))
mat.DisableKeyword(keyword);
}
}
void UpdatePresetValues(Material mat) {
int preset = (int)mat.GetFloat("_Preset");
// Do nothing if preset was not changed
if (this.prevPreset == -1 || this.prevPreset == preset) {
this.prevPreset = preset;
return;
}
mat.SetFloat("_Cull", 2); // Back
mat.SetFloat("_ZTest", 4); // LessEqual
mat.SetFloat("_BlendOp", 0); // Add
switch (preset) {
case 0: // OPAQUE
mat.SetFloat("_ZWrite", 1);
mat.SetFloat("_SourceBlend", 1); // One
mat.SetFloat("_DestBlend", 0); // Zero
if (mat.renderQueue >= 2450)
mat.renderQueue = 2000;
mat.SetFloat("_Cutout", 0); // Cutout
mat.DisableKeyword("CUTOUT");
break;
case 1: // TRANSPARENT
mat.SetFloat("_ZWrite", 0);
mat.SetFloat("_SourceBlend", 5); // SrcAlpha
mat.SetFloat("_DestBlend", 10); // OneMinusSrcAlpha
if (mat.renderQueue < 3000)
mat.renderQueue = 3000;
mat.SetFloat("_Cutout", 0); // Cutout
mat.DisableKeyword("CUTOUT");
break;
case 2: // TRANSPARENT ADDITIVE
mat.SetFloat("_ZWrite", 0);
mat.SetFloat("_SourceBlend", 1); // One
mat.SetFloat("_DestBlend", 1); // One
if (mat.renderQueue < 3000)
mat.renderQueue = 3000;
mat.SetFloat("_Cutout", 0); // Cutout
mat.DisableKeyword("CUTOUT");
break;
case 3: // TRANSPARENT ADDITIVE ALPHA
mat.SetFloat("_ZWrite", 0);
mat.SetFloat("_SourceBlend", 5); // SrcAlpha
mat.SetFloat("_DestBlend", 1); // One
if (mat.renderQueue < 3000)
mat.renderQueue = 3000;
mat.SetFloat("_Cutout", 0); // Cutout
mat.DisableKeyword("CUTOUT");
break;
case 4: // OPAQUE CUTOUT
mat.SetFloat("_Cull", 0); // Disabled
mat.SetFloat("_ZWrite", 1);
mat.SetFloat("_SourceBlend", 1); // One
mat.SetFloat("_DestBlend", 0); // Zero
mat.SetFloat("_Cutout", 1); // Cutout
mat.EnableKeyword("CUTOUT");
if (mat.renderQueue < 2450 || mat.renderQueue >= 3000)
mat.renderQueue = 2450;
break;
default:
Debug.LogError(OmniShade.NAME + ": Unrecognized Preset (" + preset + ")");
break;
}
this.prevPreset = preset;
}
void RenderGUI(MaterialEditor materialEditor, MaterialProperty[] properties) {
materialEditor.SetDefaultGUIWidths();
// Documentation button
var content = new GUIContent(EditorGUIUtility.IconContent("_Help")) {
text = OmniShade.NAME + " Docs",
tooltip = OmniShade.DOCS_URL
};
if (GUILayout.Button(content))
Help.BrowseURL(OmniShade.DOCS_URL);
// Expand/Close all buttons
GUILayout.BeginHorizontal();
var expandAll = new GUIContent(EditorGUIUtility.IconContent("Toolbar Plus")) { text = "Expand All" };
if (GUILayout.Button(expandAll))
this.forceExpand = ExpandType.All;
if (GUILayout.Button("Expand Active"))
this.forceExpand = ExpandType.Active;
var collapse = new GUIContent(EditorGUIUtility.IconContent("Toolbar Minus")) { text = "Collapse" };
if (GUILayout.Button(collapse))
this.forceExpand = ExpandType.Collapse;
GUILayout.EndHorizontal();
string currentHeaderName = this.RenderShaderProperties(materialEditor, properties);
// Append Unity rendering options to Rendering group
if (currentHeaderName == "Rendering") {
materialEditor.EnableInstancingField();
materialEditor.DoubleSidedGIField();
}
EditorGUILayout.EndFoldoutHeaderGroup();
// Upgrade button
#if LITE
GUILayout.Space(10);
if (GUILayout.Button("Upgrade to " + OmniShade.NAME + " Pro"))
Help.BrowseURL(OmniShade.PRO_URL);
#endif
}
string RenderShaderProperties(MaterialEditor materialEditor, MaterialProperty[] properties) {
this.RefreshPropertyHeaders(materialEditor);
bool isFoldoutOpen = true;
string currentHeaderName = string.Empty;
int uvTileCount = 0;
foreach (var prop in properties) {
if (((uint)prop.propertyFlags & (uint)ShaderPropertyFlags.HideInInspector) == 1)
continue;
// If start of header, begin a new foldout group
if (this.propertyHeaders.ContainsKey(prop.name)) {
// Close previous foldout group
if (!string.IsNullOrEmpty(currentHeaderName)) {
// Append Unity rendering options to end of groups
if (isFoldoutOpen) {
if (currentHeaderName == "Culling And Blending")
materialEditor.RenderQueueField();
else if (currentHeaderName == "Rendering") {
materialEditor.EnableInstancingField();
materialEditor.DoubleSidedGIField();
}
}
EditorGUILayout.EndFoldoutHeaderGroup();
}
// Begin foldout header
var header = this.propertyHeaders[prop.name];
currentHeaderName = header.headerName;
isFoldoutOpen = header.isOpen = this.BeginFoldoutHeader(header.isOpen, header.headerName);
this.propertyHeaders[prop.name] = header;
}
// Render shader property
if (isFoldoutOpen) {
if (prop.name.StartsWith("_UVTileV")) {
this.RenderUVTileDiscardProperty(materialEditor, prop, uvTileCount);
uvTileCount++;
}
else
this.RenderShaderProperty(materialEditor, prop);
}
}
return currentHeaderName;
}
void RenderUVTileDiscardProperty(MaterialEditor materialEditor, MaterialProperty prop, int uvTileCount) {
if (uvTileCount % 4 == 0) {
EditorGUILayout.BeginHorizontal();
GUILayout.Label(prop.displayName);
}
float val = GUILayout.Toggle(prop.floatValue > 0, string.Empty) ? 1.0f : 0.0f;
if (val != prop.floatValue) {
var mats = this.GetSelectedMaterials(materialEditor);
foreach (var mat in mats)
mat.SetFloat(prop.name, val);
}
if ((uvTileCount + 1) % 4 == 0)
EditorGUILayout.EndHorizontal();
}
void RenderShaderProperty(MaterialEditor materialEditor, MaterialProperty prop) {
string label = prop.displayName;
var content = this.GetTooltip(label);
materialEditor.ShaderProperty(prop, content);
}
void RefreshPropertyHeaders(MaterialEditor materialEditor) {
var mat = materialEditor.target as Material;
var shader = mat.shader;
int numProps = shader.GetPropertyCount();
var headerActiveDic = GetActivePropertyHeaders(mat);
// Update property headers and check for new headers
var newProps = new List<string>();
for (int i = 0; i < numProps; i++) {
var propAttrs = shader.GetPropertyAttributes(i);
for (int j = 0; j < propAttrs.Length; j++) {
// Skip if not a header attribute
string propAttr = propAttrs[j];
if (!this.IsHeaderGroup(propAttr))
continue;
string propName = shader.GetPropertyName(i);
string headerName = this.GetHeaderGroupName(propAttr);
newProps.Add(propName);
// Update cache if something changed
if (!this.propertyHeaders.ContainsKey(propName) ||
this.propertyHeaders[propName].headerName != headerName || this.forceExpand != ExpandType.Keep) {
bool isOpen = this.forceExpand == ExpandType.All;
if (!this.propertyHeaders.ContainsKey(propName)) { // New entry
if (this.forceExpand == ExpandType.Keep || this.forceExpand == ExpandType.Active)
isOpen = !headerActiveDic.ContainsKey(headerName) || headerActiveDic[headerName];
var header = new PropertyHeader(headerName, isOpen);
this.propertyHeaders.Add(propName, header);
}
else { // Update existing entry
if (this.forceExpand == ExpandType.Keep)
isOpen = this.propertyHeaders[propName].isOpen;
else if (this.forceExpand == ExpandType.Active)
isOpen = !headerActiveDic.ContainsKey(headerName) || headerActiveDic[headerName];
var header = new PropertyHeader(headerName, isOpen);
this.propertyHeaders[propName] = header;
}
}
}
}
this.forceExpand = ExpandType.Keep;
// Remove any headers that were deleted
var propNames = new List<string>();
foreach (var propName in this.propertyHeaders.Keys)
propNames.Add(propName);
var deletedProps = propNames.Except(newProps);
foreach (var deletedProp in deletedProps)
this.propertyHeaders.Remove(deletedProp);
}
Dictionary<string, bool> GetActivePropertyHeaders(Material mat) {
var defaultOnHeaders = new string[] {
"Culling And Blending"
};
var shader = mat.shader;
int numProps = shader.GetPropertyCount();
var headerActiveDic = new Dictionary<string, bool>();
if (this.forceExpand == ExpandType.Active) {
string currentHeaderName = string.Empty;
for (int i = 0; i < numProps; i++) {
// Check if header group
var propAttrs = shader.GetPropertyAttributes(i);
string headerName = this.GetHeaderGroupName(propAttrs);
if (!string.IsNullOrEmpty(headerName))
currentHeaderName = headerName;
// Skip if no headers found yet
if (string.IsNullOrEmpty(currentHeaderName))
continue;
// Check active headers
bool isInUse = defaultOnHeaders.Contains(currentHeaderName) || this.IsPropertyActive(mat, i);
if (headerActiveDic.ContainsKey(currentHeaderName))
headerActiveDic[currentHeaderName] |= isInUse;
else
headerActiveDic.Add(currentHeaderName, isInUse);
}
}
return headerActiveDic;
}
bool IsPropertyActive(Material mat, int propertyIndex) {
var shader = mat.shader;
string propName = shader.GetPropertyName(propertyIndex);
string propDesc = shader.GetPropertyDescription(propertyIndex);
var propType = shader.GetPropertyType(propertyIndex);
if (!mat.HasProperty(propName))
return false;
if ((propType == ShaderPropertyType.Float && propDesc.StartsWith("Enable") && mat.GetFloat(propName) == 1) ||
(propType == ShaderPropertyType.Texture && mat.GetTexture(propName) != null) ||
(propName == "_Emissive" && (Vector3)mat.GetVector("_Emissive") != Vector3.zero) ||
(propName == "_AmbientBrightness" && mat.GetFloat("_AmbientBrightness") != 0) ||
(propName.StartsWith("_Opt") && mat.GetFloat(propName) != 0) ||
(propName == "_CameraFadeStart" && mat.IsKeywordEnabled("CAMERA_FADE")))
return true;
return false;
}
bool IsHeaderGroup(string propAttr) {
return propAttr.StartsWith(HEADER_GROUP);
}
string GetHeaderGroupName(string[] propAttrs) {
for (int j = 0; j < propAttrs.Length; j++) {
string propAttr = propAttrs[j];
if (this.IsHeaderGroup(propAttr)) {
return GetHeaderGroupName(propAttr);
}
}
return null;
}
string GetHeaderGroupName(string header) {
int headerGroupLen = HEADER_GROUP.Length + 1;
return header.Substring(headerGroupLen, header.LastIndexOf(")") - headerGroupLen);
}
bool BeginFoldoutHeader(bool isOpen, string label) {
var content = this.GetTooltip(label);
var defaultColor = GUI.backgroundColor;
GUI.backgroundColor = new Color(1.35f, 1.35f, 1.35f);
isOpen = EditorGUILayout.BeginFoldoutHeaderGroup(isOpen, content);
GUI.backgroundColor = defaultColor;
return isOpen;
}
GUIContent GetTooltip(string label) {
// Check cache first
if (OmniShadeGUI.toolTipsCache.ContainsKey(label))
return OmniShadeGUI.toolTipsCache[label];
string tooltip;
switch (label) {
case "Ignore Main Texture Alpha": tooltip = "Ignore the alpha channel on the texture, forcing it to be opaque."; break;
case "Use UV For Sides": tooltip = "Use UV coordinates instead of triplanar for the side texturing."; break;
case "Triplanar Blend Sharpness": tooltip = "The blend sharpness between the sides and top texture."; break;
case "Diffuse Softness": tooltip = "Wraps the diffuse lighting around to make it softer."; break;
case "Per-Pixel Point Lights": tooltip = "Compute point lights in fragment shader instead of vertex shader for higher quality. Slower, but useful on low-poly objects."; break;
case "Enable Baked and Dynamic Lights": tooltip = "Toggle when using both a baked realtime light sources."; break;
case "Specular Hair": tooltip = "Computes specular along tangents for hair or brushed metal highlights. In this mode, the Specular Map is used as a roughness map for the highlights as well."; break;
case "Rim Direction": tooltip = "Rim light direction in world space."; break;
case "Reflection": tooltip = "Uses Environment Skybox Material from Lighting Settings unless Reflection Cubemap specified."; break;
case "Enable Reflection": tooltip = "Uses Environment Skybox Material from Lighting Settings unless Reflection Cubemap specified."; break;
case "Mask With Rim": tooltip = "Mask the reflection with the rim's fresnel effect to simulate reflections only at glancing angles."; break;
case "Perspective Correction": tooltip = "Improves accuracy for dynamic cameras. For stationary cameras, disable to improve performance."; break;
case "Use Static Rotation": tooltip = "Lock the MatCap rotation to a static angle."; break;
case "Apply To Lighting": tooltip = "Apply the Detail Map as a mask to the lighting instead, useful for effects like glitter."; break;
case "Mask With Vertex Color (A)": tooltip = "Mask with the vertex color's alpha channel."; break;
case "Mask With Vertex Color (R)": tooltip = "Mask with the vertex color's red channel."; break;
case "Mask With Vertex Color (G)": tooltip = "Mask with the vertex color's green channel."; break;
case "Mask With Vertex Color (B)": tooltip = "Mask with the vertex color's blue channel."; break;
case "Transparency Mask": tooltip = "Use a texture (either red or alpha channel) to control the transparency of the object."; break;
case "Height Based Colors": tooltip = "Apply a color to the object based on its local or world-space height."; break;
case "Enable Height Based Colors": tooltip = "Apply a color to the object based on its local or world-space height."; break;
case "Coordinate Space": tooltip = "World space is the final position after transforms, Local space is as it was modeled."; break;
case "Shadow Overlay": tooltip = "Overlay a texture using world space coordinates, useful for simulating clouds over multiple ojects."; break;
case "Animation Type": tooltip = "Scroll to continuously slide the texture, Sway to ping-pong."; break;
case "Plant Sway": tooltip = "Animates the object gently back and forth to simulate wind movement."; break;
case "Enable Plant Sway": tooltip = "Animates the object gently back and forth to simulate wind movement."; break;
case "Phase Variation": tooltip = "A greater value means less synchronicity in the animation of objects."; break;
case "Base Height": tooltip = "The height in local space from which the sway occurs when Plant Type set to Plant."; break;
case "Plant Type": tooltip = "Plant will sway as if the object were anchored at the base height. Leaf has no anchor. Vertex Color Alpha sways more with higher alpha values."; break;
case "Outline": tooltip = "Adds an outline silhouette around the object."; break;
case "Enable Outline": tooltip = "Adds an outline silhouette around the object."; break;
case "Outline Width": tooltip = "Width of the outline. Recommend not setting this too large."; break;
case "Outline Width Camera-Independent": tooltip = "Width does not vary based on camera depth."; break;
case "Interior Outlines": tooltip = "Show or hide interior outlines."; break;
case "Outline Group": tooltip = "Group object outlines, used with Interior Outlines."; break;
case "Anime": tooltip = "Anime-style ramp-lighting."; break;
case "Enable Anime": tooltip = "Anime-style ramp-lighting."; break;
case "Color 1": tooltip = "First ramp (shadow) color."; break;
case "Luminance Threshold 1": tooltip = "Luminance threshold between first and second ramp."; break;
case "Color 2": tooltip = "Second ramp (midtone) color."; break;
case "Luminance Threshold 2": tooltip = "Luminance threshold between second and third ramp."; break;
case "Color 3": tooltip = "Third ramp (highlights) color."; break;
case "Softness": tooltip = "Softness between color transitions."; break;
case "Ambient Brightness": tooltip = "Intensity of the Environment Lighting from the Lighting Settings."; break;
case "Culling And Blend Preset": tooltip = "Set cull and blend settings from presets."; break;
case "Culling": tooltip = "Side of the geometry that is rendered."; break;
case "Z Write": tooltip = "If enabled, this object occludes those behind it."; break;
case "Z Test": tooltip = "Set to Always if this object should always render, even if behind others."; break;
case "Depth Offset": tooltip = "Adjust the distance from the camera to tune visibility."; break;
case "Cutout Transparency": tooltip = "Discards pixels with alpha less than 0.5. Performance may be slow on mobile."; break;
case "Enable Flat Shading": tooltip = "Use a flat-shading style for a blocky low-poly look."; break;
case "Enable UV Tile Discard": tooltip = "Discard vertices based on UV values, used for toggling portions of a model on/off."; break;
default: tooltip = ""; break;
}
// Create tool tip and cache
var content = new GUIContent() {
text = label,
tooltip = tooltip
};
OmniShadeGUI.toolTipsCache.Add(label, content);
return content;
}
public override void AssignNewShaderToMaterial(Material mat, Shader oldShader, Shader newShader) {
// Convert texture mapping
var textureMapping = new Dictionary<string, string>() {
{ "_BaseMap", "_MainTex" },
{ "_MainTex", "_MainTex" },
{ "_MetallicGlossMap", "_SpecularTex" },
{ "_BumpMap", "_NormalTex" },
{ "_OcclusionMap", "_LightmapTex" },
{ "_DetailAlbedoMap", "_DetailTex" },
{ "_EmissionMap", "_EmissiveTex" },
};
var tilingOffsetMapping = new Dictionary<string, Vector4>();
// Fetch textures from mapping
var texToReplace = new Dictionary<string, Texture>();
foreach (var texMap in textureMapping) {
if (mat.HasProperty(texMap.Key) && mat.GetTexture(texMap.Key) != null) {
if (!texToReplace.ContainsKey(texMap.Value)) {
texToReplace.Add(texMap.Value, mat.GetTexture(texMap.Key));
// Store tiling offset
Vector4 tilingOffset;
Vector2 tiling, offset;
tiling = mat.GetTextureScale(texMap.Key);
offset = mat.GetTextureOffset(texMap.Key);
tilingOffset.x = tiling.x;
tilingOffset.y = tiling.y;
tilingOffset.z = offset.x;
tilingOffset.w = offset.y;
tilingOffsetMapping.Add(texMap.Value, tilingOffset);
}
mat.SetTexture(texMap.Key, null);
}
}
// Get base color
Vector4 baseColor = Vector4.one;
if (mat.HasProperty("_BaseColor"))
baseColor = mat.GetVector("_BaseColor");
// Get emission color
Vector4 emissive = Vector4.zero;
if (mat.HasProperty("_Emissive"))
emissive = mat.GetVector("_Emissive");
if (mat.HasProperty("_EmissionColor") && mat.globalIlluminationFlags != MaterialGlobalIlluminationFlags.EmissiveIsBlack)
emissive = mat.GetVector("_EmissionColor");
// Replace shader
base.AssignNewShaderToMaterial(mat, oldShader, newShader);
// Re-enable outline pass
string outlinePassName = mat.shader.name.Contains("URP") ? "SRPDefaultUnlit" : "Always";
mat.SetShaderPassEnabled(outlinePassName, true);
// Replace textures
Vector2 baseTiling = Vector2.one, baseOffset = Vector2.zero;
foreach (var texToRep in texToReplace) {
var texName = texToRep.Key;
if (mat.HasProperty(texName)) {
mat.SetTexture(texName, texToRep.Value);
if (tilingOffsetMapping.ContainsKey(texName)) {
// Restore tiling offset
Vector4 tilingOffset = tilingOffsetMapping[texName];
Vector2 tiling = (Vector2)tilingOffset;
Vector2 offset;
offset.x = tilingOffset.z;
offset.y = tilingOffset.w;
mat.SetTextureScale(texName, tiling);
mat.SetTextureOffset(texName, offset);
// Store base tiling offset
if (texName == "_MainTex") {
baseTiling = tiling;
baseOffset = offset;
}
}
}
}
// If prev shader is Lit, apply base tiling offset to all tex
if (oldShader.name.Contains("Lit") || oldShader.name == "Standard") {
foreach (var texMap in textureMapping) {
var texName = texMap.Value;
if (mat.HasProperty(texName)) {
mat.SetTextureScale(texName, baseTiling);
mat.SetTextureOffset(texName, baseOffset);
}
}
}
// Replace Base Color
if (oldShader.name.Contains("Lit"))
mat.SetColor("_Color", baseColor);
// Replace emission color
if (mat.HasProperty("_Emissive"))
mat.SetVector("_Emissive", emissive);
this.forceExpand = ExpandType.Active;
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: e755d3d0b395d4ae4a336fe4ab484d2f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 215111
packageName: OmniShade - Mobile Optimized Shader
packageVersion: 1.9.5
assetPath: Assets/OmniShade/Scripts/Editor/OmniShadeGUI.cs
uploadId: 825160