// Upgrade NOTE: replaced 'defined _ALPHATEST_ON' with 'defined (_ALPHATEST_ON)'
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Unity Shaders/Specular" {
Properties {
_Color ("Color Tint", Color) = (1, 1, 1, 1)
_MainTex ("Main Tex", 2D) = "white" {}
_Cutoff ("Cutoff", Range(0.0, 1.0)) = 0.5
_SpecColor ("SpecColor", Color) = (1, 1, 1, 1)
_Glossiness ("Glossiness", Range(0.0, 1.0)) = 0.5
_SpecGlossMap ("MetallicGlossMap", 2D) = "white" {}
_GlossMapScale ("GlossMapScale", Range(0.0, 1.0)) = 0.5
_BumpMap ("Normal Map", 2D) = "bump" {}
_EmissionColor("Color", Color) = (0,0,0)
_EmissionMap("Emission", 2D) = "white" {}
[HideInInspector] _Mode ("__mode", Float) = 0.0
[HideInInspector] _SrcBlend ("__src", Float) = 1.0
[HideInInspector] _DstBlend ("__dst", Float) = 0.0
[HideInInspector] _ZWrite ("__zw", Float) = 1.0
[Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0
}
CGINCLUDE
#define UNITY_SETUP_BRDF_INPUT SpecularSetup
ENDCG
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry"}
Pass {
Tags { "LightMode"="ForwardBase" }
Blend [_SrcBlend] [_DstBlend]
CGPROGRAM
#pragma multi_compile_fwdbase
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _NORMALMAP
#pragma shader_feature _SPECGLOSSMAP
#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#define SHOULD_SAMPLE_SH ( defined (LIGHTMAP_OFF) && defined(DYNAMICLIGHTMAP_OFF) )
#include "UnityCG.cginc"
#include "UnityStandardCore.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
#include "UnityPBSLighting.cginc"
#include "UnityStandardBRDF.cginc"
fixed _CutOff;
//fixed3 _Color;
//sampler2D _MainTex;
//float4 _MainTex_ST;
//sampler2D _BumpMap;
float4 _BumpMap_ST;
//sampler2D _MetallicGlossMap;
//float4 _GlossMapScale;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float4 texcoord0 : TEXCOORD0;
float4 texcoord1 : TEXCOORD2;
float4 texcoord2 : TEXCOORD2;
};
struct v2f {
float4 pos : SV_POSITION;
float4 uv0 : TEXCOORD0;
half4 tangent2WorldAndLightDir[3] : TEXCOORD1;
half3 eyeVec : TEXCOORD4;
half3 posWorld : TEXCOORD5;
// half3 TtoW0: TEXCOORD6;
// half3 TtoW1 : TEXCOORD7;
// half3 TtoW2 : TEXCOORD8;
half3 uv1 : TEXCOORD7;
half3 uv2 : TEXCOORD6;
#if defined(LIGHTMAP_ON) || defined(UNITY_SHOULD_SAMPLE_SH)
float4 ambientOrLightmapUV : TEXCOORD10;
#endif
SHADOW_COORDS(8)
};
v2f vert(a2v v) {
v2f o;
UNITY_INITIALIZE_OUTPUT(v2f, o);
o.pos = UnityObjectToClipPos(v.vertex);
o.uv0 = v.texcoord0;
o.uv1 = v.texcoord1;
o.uv2 = v.texcoord2;
o.uv0.xy = v.texcoord0.xy * _MainTex_ST.xy + _MainTex_ST.zw;
o.uv0.zw = v.texcoord0.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;
o.posWorld = mul(unity_ObjectToWorld, v.vertex).xyz;
o.eyeVec = normalize(_WorldSpaceCameraPos-o.posWorld.xyz );
fixed3 normalWorld = UnityObjectToWorldNormal(v.normal);
#ifdef LIGHTMAP_ON
o.ambientOrLightmapUV.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
o.ambientOrLightmapUV.zw = 0;
#elif UNITY_SHOULD_SAMPLE_SH
#ifdef VERTEXLIGHT_ON
o.ambientOrLightmapUV.rgb = Shade4PointLights (
unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
unity_4LightAtten0, o.posWorld, normalWorld);
#endif
o.ambientOrLightmapUV.rgb = ShadeSHPerVertex (normalWorld, o.ambientOrLightmapUV.rgb);
#endif
#ifdef DYNAMICLIGHTMAP_ON
o.ambientOrLightmapUV.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
#endif
#ifdef _NORMALMAP
float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);
float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w);
o.tangent2WorldAndLightDir[0].xyz = tangentToWorld[0];
o.tangent2WorldAndLightDir[1].xyz = tangentToWorld[1];
o.tangent2WorldAndLightDir[2].xyz = tangentToWorld[2];
#else
o.tangent2WorldAndLightDir[0].xyz = 0;
o.tangent2WorldAndLightDir[1].xyz = 0;
o.tangent2WorldAndLightDir[2].xyz = normalWorld;
#endif
// float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
// float3 worldBinormal = cross(normalWorld,worldTangent)*v.tangent.xyz;
// o.TtoW0 = float4(worldTangent.x, worldBinormal.x, normalWorld.x, o.posWorld.x);
// o.TtoW1 = float4(worldTangent.y, worldBinormal.y, normalWorld.y, o.posWorld.y);
// o.TtoW2 = float4(worldTangent.z, worldBinormal.z, normalWorld.z, o.posWorld.z);
//
// TRANSFER_SHADOW(o);
return o;
}
fixed4 frag(v2f i) : SV_Target {
// float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(i.posWorld));
// fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
//fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv0.zw));
//bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
fixed4 albedo = tex2D(_MainTex, i.uv0.xy) * _Color;
#if defined (_ALPHATEST_ON)
clip(albedo.a - _CutOff);
#endif
///////// Gloss:
half4 sg;
#ifdef _SPECGLOSSMAP
#if defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A)
sg.rgb = tex2D(_SpecGlossMap, i.uv0.xy).rgb;
sg.a = tex2D(_MainTex, i.uv0.xy).a;
#else
sg = tex2D(_SpecGlossMap, i.uv0.xy);
#endif
sg.a *= _GlossMapScale;
#else
sg.rgb = _SpecColor.rgb;
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
sg.a = tex2D(_MainTex, i.uv0.xy).a * _GlossMapScale;
#else
sg.a = _Glossiness;
#endif
#endif
half4 specGloss = sg;
half3 specColor = specGloss.rgb;
half smoothness = specGloss.a;
half oneMinusReflectivity;
half3 diffColor = EnergyConservationBetweenDiffuseAndSpecular (albedo, specColor, oneMinusReflectivity);
// half2 mg;
// mg= tex2D(_MetallicGlossMap, i.uv0.xy).ra;
//mg.g *= _GlossMapScale;
// half3 specColor = lerp(unity_ColorSpaceDielectricSpec.rgb, albedo, mg.x);
//half oneMinusReflectivity = OneMinusReflectivityFromMetallic(mg.x);
//half3 color = albedo*oneMinusReflectivity;
FragmentCommonData o;
UNITY_INITIALIZE_OUTPUT(FragmentCommonData, o);
o.diffColor = diffColor;
o.specColor = specColor;
o.oneMinusReflectivity = oneMinusReflectivity;
o.smoothness = smoothness;
o.posWorld = i.posWorld;
#ifdef _NORMALMAP
// fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv0.zw));
// o.normalWorld = normalize(half3(dot(i.tangent2WorldAndLightDir[0].xyz, bump), dot(i.tangent2WorldAndLightDir[1].xyz, bump), dot(i.tangent2WorldAndLightDir[2].xyz, bump)));
o.normalWorld = normalize(mul(UnpackScaleNormal(tex2D(_BumpMap, i.uv0.xy),1), ExtractTangentToWorldPerPixel(i.tangent2WorldAndLightDir)));
#else
o.normalWorld = normalize(i.tangent2WorldAndLightDir[2].xyz);
#endif
o.eyeVec = i.eyeVec;
////// Lighting:
float attenuation = LIGHT_ATTENUATION(i);
float3 attenColor = attenuation * _LightColor0.xyz;
float Pi = 3.141592654;
float InvPi = 0.31830988618;
/////// GI Data:
UnityLight l;
UNITY_INITIALIZE_OUTPUT(UnityLight, l);
l.color = _LightColor0.rgb;
l.dir = _WorldSpaceLightPos0.xyz;
l.ndotl = LambertTerm (o.normalWorld, lightDir);
UnityGIInput d;
UNITY_INITIALIZE_OUTPUT(UnityGIInput, d);
d.light = l;
d.worldPos = i.posWorld.xyz;
d.worldViewDir = o.eyeVec;
d.atten = attenuation;
#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
d.ambient = 0;
d.lightmapUV = i.ambientOrLightmapUV;
#else
d.ambient = i.ambientOrLightmapUV;
#endif
#if UNITY_SPECCUBE_BLENDING || UNITY_SPECCUBE_BOX_PROJECTION
d.boxMin[0] = unity_SpecCube0_BoxMin;
d.boxMin[1] = unity_SpecCube1_BoxMin;
#endif
#if UNITY_SPECCUBE_BOX_PROJECTION
d.boxMax[0] = unity_SpecCube0_BoxMax;
d.boxMax[1] = unity_SpecCube1_BoxMax;
d.probePosition[0] = unity_SpecCube0_ProbePosition;
d.probePosition[1] = unity_SpecCube1_ProbePosition;
#endif
d.probeHDR[0] = unity_SpecCube0_HDR;
d.probeHDR[1] = unity_SpecCube1_HDR;
Unity_GlossyEnvironmentData data;
UNITY_INITIALIZE_OUTPUT(Unity_GlossyEnvironmentData, data);
data.roughness = 1.0 - o.smoothness;
data.reflUVW = reflect( -d.worldViewDir, o.normalWorld );
UnityGI gi;
UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
gi = UnityGlobalIllumination(d, 1, o.normalWorld, data );
d.light.dir = gi.light.dir;
d.light.color = gi.light.color;
// half3 indirectspecular = gi.indirect.specular;
// half3 indirectdiffuse = gi.indirect.diffuse;
////// Specular:
half nl = saturate(dot(o.normalWorld, l.dir));
half3 halfDir = normalize(d.worldViewDir);//l.dir+
half nh = BlinnTerm(o.normalWorld, halfDir);
half nv = saturate(dot(o.normalWorld, d.worldViewDir));
half2 rlPow4AndFresnelTerm = Pow4 (half2(nh, 1-nv));
half rlPow4 = rlPow4AndFresnelTerm.x;
half fresnelTerm = rlPow4AndFresnelTerm.y;
half grazingTerm = saturate(data.roughness + (1-oneMinusReflectivity));
half LUT_RANGE = 16.0;
half specular = tex2D(unity_NHxRoughness, half2(rlPow4, 1-data.roughness)).UNITY_ATTEN_CHANNEL * LUT_RANGE;
// #if defined(_SPECULARHIGHLIGHTS_OFF)
// specular = 0.0;
// #endif
half3 finalspecular = specular * o.specColor ;
finalspecular*= gi.light.color ;
half3 c = gi.indirect.diffuse * o.diffColor *nl;
c += gi.indirect.specular * lerp (o.specColor, grazingTerm, fresnelTerm);
finalspecular += c;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
// fixed3 aadiffuse = _LightColor0.rgb * albedo * max(0, dot(bump, lightDir));
// UNITY_LIGHT_ATTENUATION(atten, i, worldPos);
//return fixed4( finalspecular + ambient, 1.0);//diffuse * atten
return fixed4(gi.indirect.specular,1);
}
ENDCG
}
Pass {
Tags { "LightMode"="ForwardAdd" }
Blend One One
CGPROGRAM
#pragma multi_compile_fwdadd
// Use the line below to add shadows for point and spot lights
// #pragma multi_compile_fwdadd_fullshadows
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "AutoLight.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _BumpMap;
float4 _BumpMap_ST;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
float4 TtoW0 : TEXCOORD1;
float4 TtoW1 : TEXCOORD2;
float4 TtoW2 : TEXCOORD3;
SHADOW_COORDS(4)
};
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag(v2f i) : SV_Target {
float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
fixed3 albedo = tex2D(_MainTex, i.uv.xy).rgb * _Color.rgb;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(bump, lightDir));
UNITY_LIGHT_ATTENUATION(atten, i, worldPos);
return fixed4(diffuse * atten, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
CustomEditor "MyShaderGUI"
}
using System;
using UnityEngine;
namespace UnityEditor
{
internal class MyShaderGUI : ShaderGUI
{
private enum WorkflowMode
{
Specular,
Metallic,
Dielectric
}
public enum BlendMode
{
Opaque,
Cutout,
Fade, // Old school alpha-blending mode, fresnel does not affect amount of transparency
Transparent // Physically plausible transparency mode, implemented as alpha pre-multiply
}
public enum SmoothnessMapChannel
{
SpecularMetallicAlpha,
AlbedoAlpha,
}
private static class Styles
{
public static GUIContent uvSetLabel = new GUIContent("UV Set");
public static GUIContent albedoText = new GUIContent("Albedo", "Albedo (RGB) and Transparency (A)");
public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
public static GUIContent specularMapText = new GUIContent("Specular", "Specular (RGB) and Smoothness (A)");
public static GUIContent metallicMapText = new GUIContent("Metallic", "Metallic (R) and Smoothness (A)");
public static GUIContent smoothnessText = new GUIContent("Smoothness", "Smoothness value");
public static GUIContent smoothnessScaleText = new GUIContent("Smoothness", "Smoothness scale factor");
public static GUIContent smoothnessMapChannelText = new GUIContent("Source", "Smoothness texture and channel");
//public static GUIContent highlightsText = new GUIContent("Specular Highlights", "Specular Highlights");
public static GUIContent reflectionsText = new GUIContent("Reflections", "Glossy Reflections");
public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map");
//public static GUIContent heightMapText = new GUIContent("Height Map", "Height Map (G)");
//public static GUIContent occlusionText = new GUIContent("Occlusion", "Occlusion (G)");
//public static GUIContent emissionText = new GUIContent("Color", "Emission (RGB)");
//public static GUIContent detailMaskText = new GUIContent("Detail Mask", "Mask for Secondary Maps (A)");
//public static GUIContent detailAlbedoText = new GUIContent("Detail Albedo x2", "Albedo (RGB) multiplied by 2");
//public static GUIContent detailNormalMapText = new GUIContent("Normal Map", "Normal Map");
public static string primaryMapsText = "Main Maps";
public static string secondaryMapsText = "Secondary Maps";
public static string forwardText = "Forward Rendering Options";
public static string renderingMode = "Rendering Mode";
public static string advancedText = "Advanced Options";
public static GUIContent emissiveWarning = new GUIContent("Emissive value is animated but the material has not been configured to support emissive. Please make sure the material itself has some amount of emissive.");
public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode));
}
MaterialProperty blendMode = null;
MaterialProperty albedoMap = null;
MaterialProperty albedoColor = null;
MaterialProperty alphaCutoff = null;
MaterialProperty specularMap = null;
MaterialProperty specularColor = null;
MaterialProperty metallicMap = null;
MaterialProperty metallic = null;
MaterialProperty smoothness = null;
MaterialProperty smoothnessScale = null;
MaterialProperty smoothnessMapChannel = null;
//MaterialProperty highlights = null;
MaterialProperty reflections = null;
MaterialProperty bumpScale = null;
MaterialProperty bumpMap = null;
// MaterialProperty occlusionStrength = null;
// MaterialProperty occlusionMap = null;
// MaterialProperty heigtMapScale = null;
// MaterialProperty heightMap = null;
//MaterialProperty emissionColorForRendering = null;
//MaterialProperty emissionMap = null;
// MaterialProperty detailMask = null;
// MaterialProperty detailAlbedoMap = null;
// MaterialProperty detailNormalMapScale = null;
// MaterialProperty detailNormalMap = null;
MaterialProperty uvSetSecondary = null;
MaterialEditor m_MaterialEditor;
WorkflowMode m_WorkflowMode = WorkflowMode.Specular;
private const float kMaxfp16 = 65536f; // Clamp to a value that fits into fp16.
ColorPickerHDRConfig m_ColorPickerHDRConfig = new ColorPickerHDRConfig(0f, kMaxfp16, 1 / kMaxfp16, 3f);
bool m_FirstTimeApply = true;
public void FindProperties(MaterialProperty[] props)
{
blendMode = FindProperty("_Mode", props);
albedoMap = FindProperty("_MainTex", props);
albedoColor = FindProperty("_Color", props);
alphaCutoff = FindProperty("_Cutoff", props);
specularMap = FindProperty("_SpecGlossMap", props, false);
specularColor = FindProperty("_SpecColor", props, false);
metallicMap = FindProperty("_MetallicGlossMap", props, false);
metallic = FindProperty("_Metallic", props, false);
if (specularMap != null && specularColor != null)
m_WorkflowMode = WorkflowMode.Specular;
else if (metallicMap != null && metallic != null)
m_WorkflowMode = WorkflowMode.Metallic;
else
m_WorkflowMode = WorkflowMode.Dielectric;
smoothness = FindProperty("_Glossiness", props);
smoothnessScale = FindProperty("_GlossMapScale", props, false);
smoothnessMapChannel = FindProperty("_SmoothnessTextureChannel", props, false);
//highlights = FindProperty("_SpecularHighlights", props, false);
reflections = FindProperty("_GlossyReflections", props, false);
//bumpScale = FindProperty("_BumpScale", props);
bumpMap = FindProperty("_BumpMap", props);
//heigtMapScale = FindProperty("_Parallax", props);
//heightMap = FindProperty("_ParallaxMap", props);
//occlusionStrength = FindProperty("_OcclusionStrength", props);
//occlusionMap = FindProperty("_OcclusionMap", props);
//emissionColorForRendering = FindProperty("_EmissionColor", props);
//emissionMap = FindProperty("_EmissionMap", props);
//detailMask = FindProperty("_DetailMask", props);
//detailAlbedoMap = FindProperty("_DetailAlbedoMap", props);
//detailNormalMapScale = FindProperty("_DetailNormalMapScale", props);
//detailNormalMap = FindProperty("_DetailNormalMap", props);
uvSetSecondary = FindProperty("_UVSec", props);
}
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
{
FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
m_MaterialEditor = materialEditor;
Material material = materialEditor.target as Material;
// Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing
// material to a standard shader.
// Do this before any GUI code has been issued to prevent layout issues in subsequent GUILayout statements (case 780071)
if (m_FirstTimeApply)
{
MaterialChanged(material, m_WorkflowMode);
m_FirstTimeApply = false;
}
ShaderPropertiesGUI(material);
}
public void ShaderPropertiesGUI(Material material)
{
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
// Detect any changes to the material
EditorGUI.BeginChangeCheck();
{
BlendModePopup();
// Primary properties
GUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel);
DoAlbedoArea(material);
DoSpecularMetallicArea();
m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null);
//m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null);
// m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null);
// m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask);
DoEmissionArea(material);
EditorGUI.BeginChangeCheck();
m_MaterialEditor.TextureScaleOffsetProperty(albedoMap);
if (EditorGUI.EndChangeCheck())
//emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake
EditorGUILayout.Space();
// Secondary properties
GUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel);
//m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap);
//m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale);
//m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap);
m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text);
// Third properties
GUILayout.Label(Styles.forwardText, EditorStyles.boldLabel);
//if (highlights != null)
// m_MaterialEditor.ShaderProperty(highlights, Styles.highlightsText);
if (reflections != null)
m_MaterialEditor.ShaderProperty(reflections, Styles.reflectionsText);
}
if (EditorGUI.EndChangeCheck())
{
foreach (var obj in blendMode.targets)
MaterialChanged((Material)obj, m_WorkflowMode);
}
EditorGUILayout.Space();
// NB renderqueue editor is not shown on purpose: we want to override it based on blend mode
GUILayout.Label(Styles.advancedText, EditorStyles.boldLabel);
m_MaterialEditor.EnableInstancingField();
m_MaterialEditor.DoubleSidedGIField();
}
internal void DetermineWorkflow(MaterialProperty[] props)
{
if (FindProperty("_SpecGlossMap", props, false) != null && FindProperty("_SpecColor", props, false) != null)
m_WorkflowMode = WorkflowMode.Specular;
else if (FindProperty("_MetallicGlossMap", props, false) != null && FindProperty("_Metallic", props, false) != null)
m_WorkflowMode = WorkflowMode.Metallic;
else
m_WorkflowMode = WorkflowMode.Dielectric;
}
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
{
// _Emission property is lost after assigning Standard shader to the material
// thus transfer it before assigning the new shader
if (material.HasProperty("_Emission"))
{
material.SetColor("_EmissionColor", material.GetColor("_Emission"));
}
base.AssignNewShaderToMaterial(material, oldShader, newShader);
if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/"))
{
SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));
return;
}
BlendMode blendMode = BlendMode.Opaque;
if (oldShader.name.Contains("/Transparent/Cutout/"))
{
blendMode = BlendMode.Cutout;
}
else if (oldShader.name.Contains("/Transparent/"))
{
// NOTE: legacy shaders did not provide physically based transparency
// therefore Fade mode
blendMode = BlendMode.Fade;
}
material.SetFloat("_Mode", (float)blendMode);
DetermineWorkflow(MaterialEditor.GetMaterialProperties(new Material[] { material }));
MaterialChanged(material, m_WorkflowMode);
}
void BlendModePopup()
{
EditorGUI.showMixedValue = blendMode.hasMixedValue;
var mode = (BlendMode)blendMode.floatValue;
EditorGUI.BeginChangeCheck();
mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode");
blendMode.floatValue = (float)mode;
}
EditorGUI.showMixedValue = false;
}
void DoAlbedoArea(Material material)
{
m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);
if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Cutout))
{
m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
}
}
void DoEmissionArea(Material material)
{
// Emission for GI?
if (m_MaterialEditor.EmissionEnabledProperty())
{
//bool hadEmissionTexture = emissionMap.textureValue != null;
// Texture and HDR color controls
// m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, m_ColorPickerHDRConfig, false);
// If texture was assigned and color was black set color to white
// float brightness = emissionColorForRendering.colorValue.maxColorComponent;
// if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f)
// emissionColorForRendering.colorValue = Color.white;
// change the GI flag and fix it up with emissive as black if necessary
//m_MaterialEditor.LightmapEmissionFlagsProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel, true);
}
}
void DoSpecularMetallicArea()
{
bool hasGlossMap = false;
if (m_WorkflowMode == WorkflowMode.Specular)
{
hasGlossMap = specularMap.textureValue != null;
m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap, specularColor, hasGlossMap ? null : specularColor);
}
else if (m_WorkflowMode == WorkflowMode.Metallic)
{
hasGlossMap = metallicMap.textureValue != null;
m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap, hasGlossMap ? null : metallic);
}
bool showSmoothnessScale = hasGlossMap;
if (smoothnessMapChannel != null)
{
int smoothnessChannel = (int)smoothnessMapChannel.floatValue;
if (smoothnessChannel == (int)SmoothnessMapChannel.AlbedoAlpha)
showSmoothnessScale = true;
}
int indentation = 2; // align with labels of texture properties
m_MaterialEditor.ShaderProperty(showSmoothnessScale ? smoothnessScale : smoothness, showSmoothnessScale ? Styles.smoothnessScaleText : Styles.smoothnessText, indentation);
++indentation;
if (smoothnessMapChannel != null)
m_MaterialEditor.ShaderProperty(smoothnessMapChannel, Styles.smoothnessMapChannelText, indentation);
}
public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode)
{
switch (blendMode)
{
case BlendMode.Opaque:
material.SetOverrideTag("RenderType", "");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = -1;
break;
case BlendMode.Cutout:
material.SetOverrideTag("RenderType", "TransparentCutout");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.EnableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;
break;
case BlendMode.Fade:
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.EnableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
break;
case BlendMode.Transparent:
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
break;
}
}
static SmoothnessMapChannel GetSmoothnessMapChannel(Material material)
{
int ch = (int)material.GetFloat("_SmoothnessTextureChannel");
if (ch == (int)SmoothnessMapChannel.AlbedoAlpha)
return SmoothnessMapChannel.AlbedoAlpha;
else
return SmoothnessMapChannel.SpecularMetallicAlpha;
}
static void SetMaterialKeywords(Material material, WorkflowMode workflowMode)
{
// Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
// (MaterialProperty value might come from renderer material property block)
SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap") || material.GetTexture("_DetailNormalMap"));
if (workflowMode == WorkflowMode.Specular)
SetKeyword(material, "_SPECGLOSSMAP", material.GetTexture("_SpecGlossMap"));
else if (workflowMode == WorkflowMode.Metallic)
SetKeyword(material, "_METALLICGLOSSMAP", material.GetTexture("_MetallicGlossMap"));
SetKeyword(material, "_PARALLAXMAP", material.GetTexture("_ParallaxMap"));
SetKeyword(material, "_DETAIL_MULX2", material.GetTexture("_DetailAlbedoMap") || material.GetTexture("_DetailNormalMap"));
// A material's GI flag internally keeps track of whether emission is enabled at all, it's enabled but has no effect
// or is enabled and may be modified at runtime. This state depends on the values of the current flag and emissive color.
// The fixup routine makes sure that the material is in the correct state if/when changes are made to the mode or color.
// MaterialEditor.FixupEmissiveFlag(material);
bool shouldEmissionBeEnabled = (material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0;
// SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled);
if (material.HasProperty("_SmoothnessTextureChannel"))
{
SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A", GetSmoothnessMapChannel(material) == SmoothnessMapChannel.AlbedoAlpha);
}
}
static void MaterialChanged(Material material, WorkflowMode workflowMode)
{
SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));
SetMaterialKeywords(material, workflowMode);
}
static void SetKeyword(Material m, string keyword, bool state)
{
if (state)
m.EnableKeyword(keyword);
else
m.DisableKeyword(keyword);
}
}
} // namespace UnityEditor