public readonly GUIStyle [ ] layerLabelColors =
{
new GUIStyle ( EditorStyles . label ) ,
new GUIStyle ( EditorStyles . label ) ,
new GUIStyle ( EditorStyles . label ) ,
new GUIStyle ( EditorStyles . label )
new GUIStyle ( EditorStyles . foldout ) ,
new GUIStyle ( EditorStyles . foldout ) ,
new GUIStyle ( EditorStyles . foldout ) ,
new GUIStyle ( EditorStyles . foldout )
} ;
public readonly GUIContent materialLayerText = new GUIContent ( "Material" ) ;
public readonly GUIContent objectScaleAffectTileText = new GUIContent ( "Tiling 0123 follow object Scale" , "Tiling will be affected by the object scale." ) ;
public readonly GUIContent objectScaleAffectTileText2 = new GUIContent ( "Tiling 123 follow object Scale" , "Tiling will be affected by the object scale." ) ;
public readonly GUIContent layerTilingText = new GUIContent ( "Tiling" , "Tiling factor applied to UVSet" ) ;
public readonly GUIContent UVBaseText = new GUIContent ( "Base UV Mapping" , "Base UV Mapping mode of the layer." ) ;
public readonly GUIContent UVDetailText = new GUIContent ( "Detail UV Mapping" , "Detail UV Mapping mode of the layer." ) ;
public readonly GUIContent layeringOptionText = new GUIContent ( "Layering Options" ) ;
public readonly GUIContent heightFactorText = new GUIContent ( "Height Multiplier" , "Scale applied to the height of the layer." ) ;
public readonly GUIContent heightControlText = new GUIContent ( "Height control" ) ;
public readonly GUIContent heightCenterOffsetText = new GUIContent ( "Height Center Offset" , "Offset applied to the center of the height of the layer." ) ;
public readonly GUIContent blendUsingHeight = new GUIContent ( "Blend Using Height" , "Blend Layers using height." ) ;
public readonly GUIContent inheritBaseColorThresholdText = new GUIContent ( "Threshold" , "Inherit the base color from the base layer." ) ;
public readonly GUIContent minimumOpacityText = new GUIContent ( "Minimum Opacity" , "Minimum Opacity." ) ;
const int kMaxLayerCount = 4 ;
const int kSyncButtonWidth = 5 8 ;
public InfluenceLayeredLitGUI ( )
{
m_LayerCount = 4 ;
m_PropertySuffixes [ 0 ] = "0" ;
m_PropertySuffixes [ 1 ] = "1" ;
m_PropertySuffixes [ 2 ] = "2" ;
m_PropertySuffixes [ 3 ] = "3" ;
}
[SerializeField]
private bool [ ] showLayer = { false , false , false , false } ;
Material [ ] m_MaterialLayers = new Material [ kMaxLayerCount ] ;
// Layer options
MaterialProperty useHeightBasedBlend = null ;
const string kUseHeightBasedBlend = "_UseHeightBasedBlend" ;
// Properties for multiple layers inherit from referenced lit materials
MaterialProperty [ ] layerTexWorldScale = new MaterialProperty [ kMaxLayerCount ] ;
MaterialProperty [ ] layerUVBase = new MaterialProperty [ kMaxLayerCount ] ;
MaterialProperty [ ] layerUVMappingMask = new MaterialProperty [ kMaxLayerCount ] ;
MaterialProperty [ ] layerUVDetail = new MaterialProperty [ kMaxLayerCount ] ;
MaterialProperty [ ] layerUVDetailsMappingMask = new MaterialProperty [ kMaxLayerCount ] ;
// This one is specific to layer lit
MaterialProperty [ ] layerTiling = new MaterialProperty [ kMaxLayerCount ] ;
const string kLayerTiling = "_LayerTiling" ;
// Density/opacity mode
MaterialProperty useDensityMode = null ;
const string kUseDensityMode = "_UseDensityMode" ;
const string kMinimumOpacity = "_MinimumOpacity" ;
// HeightmapMode control
MaterialProperty [ ] heightFactor = new MaterialProperty [ kMaxLayerCount ] ;
const string kHeightFactor = "_HeightFactor" ;
MaterialProperty [ ] heightCenterOffset = new MaterialProperty [ kMaxLayerCount ] ;
const string kHeightCenterOffset = "_HeightCenterOffset" ;
MaterialProperty [ ] layerHeightAmplitude = new MaterialProperty [ kMaxLayerCount ] ;
const string kLayerHeightAmplitude = "_LayerHeightAmplitude" ;
MaterialProperty [ ] layerCenterOffset = new MaterialProperty [ kMaxLayerCount ] ;
const string kLayerCenterOffset = "_LayerCenterOffset" ;
MaterialProperty [ ] blendUsingHeight = new MaterialProperty [ kMaxLayerCount - 1 ] ; // Only in case of influence mode
const string kBlendUsingHeight = "_BlendUsingHeight" ;
protected override void FindMaterialProperties ( MaterialProperty [ ] props )
{
// Inherit from LitUI
horizonFade = FindProperty ( kHorizonFade , props ) ;
base . FindMaterialLayerProperties ( props ) ;
base . FindMaterialEmissiveProperties ( props ) ;
layerCount = FindProperty ( kLayerCount , props ) ;
layerMaskMap = FindProperty ( kLayerMaskMap , props ) ;
for ( int i = 0 ; i < kMaxLayerCount ; + + i )
{
layerTexWorldScale [ i ] = FindProperty ( string . Format ( "{0}{1}" , kTexWorldScale , i ) , props ) ;
layerUVBase [ i ] = FindProperty ( string . Format ( "{0}{1}" , kUVBase , i ) , props ) ;
layerUVMappingMask [ i ] = FindProperty ( string . Format ( "{0}{1}" , kUVMappingMask , i ) , props ) ;
layerUVDetail [ i ] = FindProperty ( string . Format ( "{0}{1}" , kUVDetail , i ) , props ) ;
layerUVDetailsMappingMask [ i ] = FindProperty ( string . Format ( "{0}{1}" , kUVDetailsMappingMask , i ) , props ) ;
layerTiling [ i ] = FindProperty ( string . Format ( "{0}{1}" , kLayerTiling , i ) , props ) ;
// HeightmapMode control
heightFactor [ i ] = FindProperty ( string . Format ( "{0}{1}" , kHeightFactor , i ) , props ) ;
heightCenterOffset [ i ] = FindProperty ( string . Format ( "{0}{1}" , kHeightCenterOffset , i ) , props ) ;
layerHeightAmplitude [ i ] = FindProperty ( string . Format ( "{0}{1}" , kLayerHeightAmplitude , i ) , props ) ;
layerCenterOffset [ i ] = FindProperty ( string . Format ( "{0}{1}" , kLayerCenterOffset , i ) , props ) ;
if ( i ! = 0 )
{
blendUsingHeight [ i - 1 ] = FindProperty ( string . Format ( "{0}{1}" , kBlendUsingHeight , i ) , props ) ;
inheritBaseColorThreshold [ i - 1 ] = FindProperty ( string . Format ( "{0}{1}" , kInheritBaseColorThreshold , i ) , props ) ;
}
}
// Reuse property from LitUI.cs
emissiveColor = FindProperty ( kEmissiveColor , props ) ;
emissiveColorMap = FindProperty ( kEmissiveColorMap , props ) ;
emissiveIntensity = FindProperty ( kEmissiveIntensity , props ) ;
}
int numLayer
// put the name in the exclusionList below
static void SynchronizeLayerProperties ( Material material , Material [ ] layers , int layerIndex )
{
string [ ] exclusionList = { kTexWorldScale , kUVBase , kUVMappingMask , kUVDetail , kUVDetailsMappingMask } ;
Material layerMaterial = layers [ layerIndex ] ;
if ( layerMaterial ! = null )
string propertyName = ShaderUtil . GetPropertyName ( layerShader , i ) ;
string layerPropertyName = propertyName + layerIndex ;
if ( ! exclusionList . Contains ( propertyName ) )
if ( material . HasProperty ( layerPropertyName ) )
if ( material . HasProperty ( layerPropertyName ) )
ShaderUtil . ShaderPropertyType type = ShaderUtil . GetPropertyType ( layerShader , i ) ;
switch ( type )
ShaderUtil . ShaderPropertyType type = ShaderUtil . GetPropertyType ( layerShader , i ) ;
switch ( type )
case ShaderUtil . ShaderPropertyType . Color :
case ShaderUtil . ShaderPropertyType . Color :
{
material . SetColor ( layerPropertyName , layerMaterial . GetColor ( propertyName ) ) ;
break ;
}
case ShaderUtil . ShaderPropertyType . Float :
case ShaderUtil . ShaderPropertyType . Range :
{
material . SetFloat ( layerPropertyName , layerMaterial . GetFloat ( propertyName ) ) ;
break ;
}
case ShaderUtil . ShaderPropertyType . Vector :
{
material . SetVector ( layerPropertyName , layerMaterial . GetVector ( propertyName ) ) ;
break ;
}
case ShaderUtil . ShaderPropertyType . TexEnv :
{
material . SetTexture ( layerPropertyName , layerMaterial . GetTexture ( propertyName ) ) ;
material . SetTextureOffset ( layerPropertyName , layerMaterial . GetTextureOffset ( propertyName ) ) ;
material . SetTextureScale ( layerPropertyName , layerMaterial . GetTextureScale ( propertyName ) ) ;
break ;
}
material . SetColor ( layerPropertyName , layerMaterial . GetColor ( propertyName ) ) ;
break ;
}
case ShaderUtil . ShaderPropertyType . Float :
case ShaderUtil . ShaderPropertyType . Range :
{
material . SetFloat ( layerPropertyName , layerMaterial . GetFloat ( propertyName ) ) ;
break ;
}
case ShaderUtil . ShaderPropertyType . Vector :
{
material . SetVector ( layerPropertyName , layerMaterial . GetVector ( propertyName ) ) ;
break ;
}
case ShaderUtil . ShaderPropertyType . TexEnv :
{
material . SetTexture ( layerPropertyName , layerMaterial . GetTexture ( propertyName ) ) ;
material . SetTextureOffset ( layerPropertyName , layerMaterial . GetTextureOffset ( propertyName ) ) ;
material . SetTextureScale ( layerPropertyName , layerMaterial . GetTextureScale ( propertyName ) ) ;
break ;
}
}
}
{
bool result = false ;
showLayer [ layerIndex ] = EditorGUILayout . Foldout ( showLayer [ layerIndex ] , styles . layerLabels [ layerIndex ] , styles . layerLabelColors [ layerIndex ] ) ;
if ( ! showLayer [ layerIndex ] )
return false ;
;
EditorGUILayout . LabelField ( styles . layerLabels [ layerIndex ] , styles . layerLabelColors [ layerIndex ] ) ;
EditorGUI . indentLevel + + ;
EditorGUI . BeginChangeCheck ( ) ;
m_MaterialLayers [ layerIndex ] = EditorGUILayout . ObjectField ( styles . materialLayerText , m_MaterialLayers [ layerIndex ] , typeof ( Material ) , true ) as Material ;
if ( EditorGUI . EndChangeCheck ( ) )
{
Undo . RecordObject ( materialImporter , "Change layer material" ) ;
SynchronizeLayerProperties ( material , m_MaterialLayers , layerIndex ) ;
result = true ;
}
EditorGUI . BeginChangeCheck ( ) ;
m_MaterialEditor . ShaderProperty ( layerUVBase [ layerIndex ] , styles . UVBaseText ) ;
if ( EditorGUI . EndChangeCheck ( ) )
{
SynchronizeLayerProperties ( material , m_MaterialLayers , layerIndex ) ;
result = true ;
}
if ( ( ( LayerUVBaseMapping ) layerUVBase [ layerIndex ] . floatValue = = LayerUVBaseMapping . Planar ) | |
( ( LayerUVBaseMapping ) layerUVBase [ layerIndex ] . floatValue = = LayerUVBaseMapping . Triplanar ) )
{
EditorGUI . indentLevel + + ;
m_MaterialEditor . ShaderProperty ( layerTexWorldScale [ layerIndex ] , styles . layerTexWorldScaleText ) ;
EditorGUI . indentLevel - - ;
if ( ( ( LayerUVBaseMapping ) layerUVBase [ layerIndex ] . floatValue = = LayerUVBaseMapping . Planar ) )
GUILayout . Label ( " " + styles . UVDetailText . text + ": Planar" ) ;
else
GUILayout . Label ( " " + styles . UVDetailText . text + ": Triplanar" ) ;
}
else
EditorGUILayout . LabelField ( styles . layeringOptionText , EditorStyles . boldLabel ) ;
m_MaterialEditor . ShaderProperty ( layerTiling [ layerIndex ] , styles . layerTilingText ) ;
EditorGUI . indentLevel - - ;
m_MaterialEditor . ShaderProperty ( layerUVDetail [ layerIndex ] , styles . UVDetailText ) ;
m_MaterialLayers [ layerIndex ] = EditorGUILayout . ObjectField ( styles . materialLayerText , m_MaterialLayers [ layerIndex ] , typeof ( Material ) , true ) as Material ;
Undo . RecordObject ( materialImporter , "Change layer material" ) ;
}
// We setup the masking map based on the enum for each layer.
// using mapping mask allow to reduce the number of generated combination for a very small increase in ALU
LayerUVBaseMapping layerUVBaseMapping = ( LayerUVBaseMapping ) layerUVBase [ layerIndex ] . floatValue ;
// influence
if ( layerIndex > 0 )
{
int paramIndex = layerIndex - 1 ;
float X , Y , Z , W ;
X = ( layerUVBaseMapping = = LayerUVBaseMapping . UV0 ) ? 1.0f : 0.0f ;
Y = ( layerUVBaseMapping = = LayerUVBaseMapping . UV1 ) ? 1.0f : 0.0f ;
Z = ( layerUVBaseMapping = = LayerUVBaseMapping . UV2 ) ? 1.0f : 0.0f ;
W = ( layerUVBaseMapping = = LayerUVBaseMapping . UV3 ) ? 1.0f : 0.0f ;
layerUVMappingMask [ layerIndex ] . colorValue = ( layerIndex = = 0 ) ? new Color ( 1.0f , 0.0f , 0.0f , 0.0f ) : new Color ( X , Y , Z , W ) ; // Special case for Main Layer and Blend Mask, only UV0. As Layer0 is share by both here, need to force X to 1.0 in all case
UVDetailMapping layerUVDetailMapping = ( UVDetailMapping ) layerUVDetail [ layerIndex ] . floatValue ;
X = ( layerUVDetailMapping = = UVDetailMapping . UV0 ) ? 1.0f : 0.0f ;
Y = ( layerUVDetailMapping = = UVDetailMapping . UV1 ) ? 1.0f : 0.0f ;
Z = ( layerUVDetailMapping = = UVDetailMapping . UV2 ) ? 1.0f : 0.0f ;
W = ( layerUVDetailMapping = = UVDetailMapping . UV3 ) ? 1.0f : 0.0f ;
layerUVDetailsMappingMask [ layerIndex ] . colorValue = new Color ( X , Y , Z , W ) ;
bool useDensityModeEnable = useDensityMode . floatValue ! = 0.0f ;
if ( useDensityModeEnable )
{
m_MaterialEditor . ShaderProperty ( opacityAsDensity [ layerIndex ] , styles . opacityAsDensityText ) ;
m_MaterialEditor . ShaderProperty ( minimumOpacity [ layerIndex ] , styles . minimumOpacityText ) ;
}
bool useDensityModeEnable = useDensityMode . floatValue ! = 0.0f ;
if ( useDensityModeEnable )
{
EditorGUILayout . LabelField ( styles . densityOpacityInfluenceText , EditorStyles . boldLabel ) ;
EditorGUI . indentLevel + + ;
m_MaterialEditor . ShaderProperty ( opacityAsDensity [ layerIndex ] , styles . opacityAsDensityText ) ;
m_MaterialEditor . ShaderProperty ( minimumOpacity [ layerIndex ] , styles . minimumOpacityText ) ;
EditorGUI . indentLevel - - ;
}
bool heightBasedBlendEnable = useHeightBasedBlend . floatValue > 0.0f ;
if ( heightBasedBlendEnable )
{
m_MaterialEditor . ShaderProperty ( blendUsingHeight [ paramIndex ] , styles . blendUsingHeight ) ;
}
// Display height control if they have a meaning
if ( ( tessellationMode ! = null & & ( ( TessellationMode ) tessellationMode . floatValue = = TessellationMode . Displacement | | ( TessellationMode ) tessellationMode . floatValue = = TessellationMode . DisplacementPhong ) )
| | ( enablePerPixelDisplacement . floatValue > 0.0f )
| | ( useHeightBasedBlend . floatValue > 0.0f )
)
{
EditorGUILayout . LabelField ( styles . heightControlText , EditorStyles . boldLabel ) ;
if ( mainLayerInfluenceEnable )
{
m_MaterialEditor . ShaderProperty ( inheritBaseColor [ paramIndex ] , styles . inheritBaseColorText ) ;
EditorGUI . indentLevel + + ;
m_MaterialEditor . ShaderProperty ( inheritBaseColorThreshold [ paramIndex ] , styles . inheritBaseColorThresholdText ) ;
EditorGUI . indentLevel - - ;
m_MaterialEditor . ShaderProperty ( inheritBaseNormal [ paramIndex ] , styles . inheritBaseNormalText ) ;
// Main height influence is only available if the shader use the heightmap for displacement (per vertex or per level)
// We always display it as it can be tricky to know when per pixel displacement is enabled or not
m_MaterialEditor . ShaderProperty ( inheritBaseHeight [ paramIndex ] , styles . inheritBaseHeightText ) ;
}
}
EditorGUI . indentLevel + + ;
m_MaterialEditor . ShaderProperty ( heightFactor [ layerIndex ] , styles . heightFactorText ) ;
layerHeightAmplitude [ layerIndex ] . floatValue = material . GetFloat ( kHeightAmplitude + layerIndex ) * heightFactor [ layerIndex ] . floatValue ;
m_MaterialEditor . ShaderProperty ( heightCenterOffset [ layerIndex ] , styles . heightCenterOffsetText ) ;
layerCenterOffset [ layerIndex ] . floatValue = material . GetFloat ( kHeightCenter + layerIndex ) + heightCenterOffset [ layerIndex ] . floatValue ;
EditorGUILayout . Space ( ) ;
// influence
if ( layerIndex > 0 )
{
int paramIndex = layerIndex - 1 ;
bool heightBasedBlendEnable = useHeightBasedBlend . floatValue > 0.0f ;
if ( heightBasedBlendEnable )
{
EditorGUI . indentLevel + + ;
m_MaterialEditor . ShaderProperty ( blendUsingHeight [ paramIndex ] , styles . blendUsingHeight ) ;
EditorGUI . indentLevel - - ;
}
if ( mainLayerInfluenceEnable )
{
EditorGUILayout . LabelField ( styles . mainLayerInfluenceText , EditorStyles . boldLabel ) ;
EditorGUI . indentLevel + + ;
m_MaterialEditor . ShaderProperty ( inheritBaseColor [ paramIndex ] , styles . inheritBaseColorText ) ;
EditorGUI . indentLevel + + ;
m_MaterialEditor . ShaderProperty ( inheritBaseColorThreshold [ paramIndex ] , styles . inheritBaseColorThresholdText ) ;
EditorGUI . indentLevel - - ;
m_MaterialEditor . ShaderProperty ( inheritBaseNormal [ paramIndex ] , styles . inheritBaseNormalText ) ;
// Main height influence is only available if the shader use the heightmap for displacement (per vertex or per level)
// We always display it as it can be tricky to know when per pixel displacement is enabled or not
m_MaterialEditor . ShaderProperty ( inheritBaseHeight [ paramIndex ] , styles . inheritBaseHeightText ) ;
EditorGUI . indentLevel - - ;
}
}
EditorGUI . indentLevel - - ;
DoLayerGUI ( material , false , layerIndex ) ;
if ( layerIndex = = 0 )
EditorGUILayout . Space ( ) ;
m_MaterialEditor . ShaderProperty ( objectScaleAffectTile , mainLayerModeInfluenceEnable ? styles . objectScaleAffectTileText2 : styles . objectScaleAffectTileText ) ;
//m_MaterialEditor.ShaderProperty(horizonFade, Styles.horizonFadeText);
EditorGUILayout . Space ( ) ;
for ( int i = 0 ; i < numLayer ; i + + )
static public void SetupLayersMappingKeywords ( Material material )
{
SetKeyword ( material , "LAYERED_LIT_USE_SIMPLE_BLEND" , true ) ;
// object scale affect tile
SetKeyword ( material , "_LAYER_TILING_COUPLED_WITH_UNIFORM_OBJECT_SCALE" , material . GetFloat ( kObjectScaleAffectTile ) > 0.0f ) ;