浏览代码

Implement ITerrainLayerCustomUI interface on TerrainLitGUI class with fancy parameter remapping GUI.

/main
Yao Xiaoling 7 年前
当前提交
e70e11ce
共有 2 个文件被更改,包括 169 次插入7 次删除
  1. 162
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/TerrainLit/TerrainLitUI.cs
  2. 14
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/TerrainLit/TerrainLitSplatCommon.hlsl

162
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/TerrainLit/TerrainLitUI.cs


namespace UnityEditor.Experimental.Rendering.HDPipeline
{
public class TerrainLitGUI : LitGUI
public class TerrainLitGUI : LitGUI, ITerrainLayerCustomUI
{
private class StylesLayer
{

public readonly GUIContent heightTransition = new GUIContent("Height Transition", "Size in world units of the smooth transition between layers.");
public readonly GUIContent enableInstancedPerPixelNormal = new GUIContent("Enable Per-pixel Normal", "Enable per-pixel normal when the terrain uses instanced rendering.");
public readonly GUIContent diffuseTexture = new GUIContent("Diffuse", "Alpha: Density");
public readonly GUIContent tint = new GUIContent("Tint");
public readonly GUIContent enableDensity = new GUIContent("Enable Density");
public readonly GUIContent diffuseTextureWithoutDensity = new GUIContent("Diffuse");
public readonly GUIContent normalMapTexture = new GUIContent("Normal Map");
public readonly GUIContent normalScale = new GUIContent("Normal Scale");
public readonly GUIContent maskMapTexture = new GUIContent("Mask", "R: Metallic\nG: AO\nB: Height\nA: Smoothness");
public readonly GUIContent maskMapTextureWithoutHeight = new GUIContent("Mask Map", "R: Metallic\nG: AO\nA: Smoothness");
public readonly GUIContent channelRemapping = new GUIContent("Channel Remapping");
public readonly GUIContent defaultValues = new GUIContent("Channel Default Values");
public readonly GUIContent metallic = new GUIContent("R: Metallic");
public readonly GUIContent ao = new GUIContent("G: AO");
public readonly GUIContent height = new GUIContent("B: Height");
public readonly GUIContent heightParametrization = new GUIContent("Parametrization");
public readonly GUIContent heightAmplitude = new GUIContent("Amplitude (cm)");
public readonly GUIContent heightBase = new GUIContent("Base");
public readonly GUIContent heightMin = new GUIContent("Min (cm)");
public readonly GUIContent heightMax = new GUIContent("Max (cm)");
public readonly GUIContent heightCm = new GUIContent("B: Height (cm)");
public readonly GUIContent smoothness = new GUIContent("A: Smoothness");
}
static StylesLayer s_Styles = null;

// We should always do this call at the end
m_MaterialEditor.serializedObject.ApplyModifiedProperties();
}
private bool m_ShowChannelRemapping = false;
enum HeightParametrization
{
Amplitude,
MinMax
};
private HeightParametrization m_HeightParametrization = HeightParametrization.Amplitude;
bool ITerrainLayerCustomUI.OnTerrainLayerGUI(TerrainLayer terrainLayer, Terrain terrain, bool maskMapUsed)
{
if (!maskMapUsed)
return false;
var layerBlendMode = terrain.materialTemplate.GetFloat("_LayerBlendMode"); // Don't use the member field layerBlendMode as ShaderGUI.OnGUI might not be called if the material is folded.
bool densityUsed = layerBlendMode == 1;
bool heightUsed = layerBlendMode == 2;
terrainLayer.diffuseTexture = EditorGUILayout.ObjectField(densityUsed ? styles.diffuseTexture : styles.diffuseTextureWithoutDensity, terrainLayer.diffuseTexture, typeof(Texture2D), false) as Texture2D;
TerrainLayerUtility.ValidateDiffuseTextureUI(terrainLayer.diffuseTexture);
var diffuseRemapMin = terrainLayer.diffuseRemapMin;
var diffuseRemapMax = terrainLayer.diffuseRemapMax;
EditorGUI.BeginChangeCheck();
if (terrainLayer.diffuseTexture != null)
{
var rect = GUILayoutUtility.GetLastRect();
rect.y += 16;
++EditorGUI.indentLevel;
rect = EditorGUI.PrefixLabel(rect, styles.tint);
rect.width = 64;
rect.height = 16;
--EditorGUI.indentLevel;
var diffuseTint = new Color(diffuseRemapMax.x, diffuseRemapMax.y, diffuseRemapMax.z);
diffuseTint = EditorGUI.ColorField(rect, GUIContent.none, diffuseTint, true, false, false);
diffuseRemapMax.x = diffuseTint.r;
diffuseRemapMax.y = diffuseTint.g;
diffuseRemapMax.z = diffuseTint.b;
diffuseRemapMin.x = diffuseRemapMin.y = diffuseRemapMin.z = 0;
}
if (densityUsed)
{
bool enableDensity = EditorGUILayout.Toggle(styles.enableDensity, diffuseRemapMax.w == 1);
diffuseRemapMax.w = enableDensity ? 1 : 0;
diffuseRemapMin.w = terrainLayer.diffuseTexture == null && enableDensity ? 1 : 0;
}
if (EditorGUI.EndChangeCheck())
{
terrainLayer.diffuseRemapMin = diffuseRemapMin;
terrainLayer.diffuseRemapMax = diffuseRemapMax;
}
terrainLayer.normalMapTexture = EditorGUILayout.ObjectField(styles.normalMapTexture, terrainLayer.normalMapTexture, typeof(Texture2D), false) as Texture2D;
TerrainLayerUtility.ValidateNormalMapTextureUI(terrainLayer.normalMapTexture, TerrainLayerUtility.CheckNormalMapTextureType(terrainLayer.normalMapTexture));
if (terrainLayer.normalMapTexture != null)
{
++EditorGUI.indentLevel;
terrainLayer.normalScale = EditorGUILayout.FloatField(styles.normalScale, terrainLayer.normalScale);
--EditorGUI.indentLevel;
EditorGUILayout.Space();
}
terrainLayer.maskMapTexture = EditorGUILayout.ObjectField(heightUsed ? styles.maskMapTexture : styles.maskMapTextureWithoutHeight, terrainLayer.maskMapTexture, typeof(Texture2D), false) as Texture2D;
TerrainLayerUtility.ValidateMaskMapTextureUI(terrainLayer.maskMapTexture);
var maskMapRemapMin = terrainLayer.maskMapRemapMin;
var maskMapRemapMax = terrainLayer.maskMapRemapMax;
++EditorGUI.indentLevel;
EditorGUI.BeginChangeCheck();
m_ShowChannelRemapping = EditorGUILayout.Foldout(m_ShowChannelRemapping, terrainLayer.maskMapTexture != null ? s_Styles.channelRemapping : s_Styles.defaultValues);
if (m_ShowChannelRemapping)
{
if (terrainLayer.maskMapTexture != null)
{
float min, max;
min = maskMapRemapMin.x; max = maskMapRemapMax.x;
EditorGUILayout.MinMaxSlider(s_Styles.metallic, ref min, ref max, 0, 1);
maskMapRemapMin.x = min; maskMapRemapMax.x = max;
min = maskMapRemapMin.y; max = maskMapRemapMax.y;
EditorGUILayout.MinMaxSlider(s_Styles.ao, ref min, ref max, 0, 1);
maskMapRemapMin.y = min; maskMapRemapMax.y = max;
if (heightUsed)
{
EditorGUILayout.LabelField(styles.height);
++EditorGUI.indentLevel;
m_HeightParametrization = (HeightParametrization)EditorGUILayout.EnumPopup(styles.heightParametrization, m_HeightParametrization);
if (m_HeightParametrization == HeightParametrization.Amplitude)
{
// (height - heightBase) * amplitude
float amplitude = maskMapRemapMax.z - maskMapRemapMin.z;
float heightBase = -maskMapRemapMin.z / amplitude;
amplitude = EditorGUILayout.FloatField(styles.heightAmplitude, amplitude * 100) / 100;
heightBase = EditorGUILayout.FloatField(styles.heightBase, heightBase);
maskMapRemapMin.z = -heightBase * amplitude;
maskMapRemapMax.z = (1 - heightBase) * amplitude;
}
else
{
maskMapRemapMin.z = EditorGUILayout.FloatField(styles.heightMin, maskMapRemapMin.z * 100) / 100;
maskMapRemapMax.z = EditorGUILayout.FloatField(styles.heightMax, maskMapRemapMax.z * 100) / 100;
}
--EditorGUI.indentLevel;
}
min = maskMapRemapMin.w; max = maskMapRemapMax.w;
EditorGUILayout.MinMaxSlider(s_Styles.smoothness, ref min, ref max, 0, 1);
maskMapRemapMin.w = min; maskMapRemapMax.w = max;
}
else
{
maskMapRemapMin.x = maskMapRemapMax.x = EditorGUILayout.Slider(s_Styles.metallic, maskMapRemapMin.x, 0, 1);
maskMapRemapMin.y = maskMapRemapMax.y = EditorGUILayout.Slider(s_Styles.ao, maskMapRemapMin.y, 0, 1);
if (heightUsed)
maskMapRemapMin.z = maskMapRemapMax.z = EditorGUILayout.FloatField(s_Styles.heightCm, maskMapRemapMin.z * 100) / 100;
maskMapRemapMin.w = maskMapRemapMax.w = EditorGUILayout.Slider(s_Styles.smoothness, maskMapRemapMin.w, 0, 1);
}
}
if (EditorGUI.EndChangeCheck())
{
terrainLayer.maskMapRemapMin = maskMapRemapMin;
terrainLayer.maskMapRemapMax = maskMapRemapMax;
}
--EditorGUI.indentLevel;
EditorGUILayout.Space();
TerrainLayerUtility.TilingSettingsUI(terrainLayer);
return true;
}
}
} // namespace UnityEditor

14
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/TerrainLit/TerrainLitSplatCommon.hlsl


float _Metallic##n; \
float _Smoothness##n; \
float _NormalScale##n; \
float4 _MaskRemapOffset##n; \
float4 _MaskRemapScale##n
float4 _DiffuseRemapScale##n; \
float4 _MaskMapRemapOffset##n; \
float4 _MaskMapRemapScale##n
DECLARE_TERRAIN_LAYER(0);
DECLARE_TERRAIN_LAYER(1);

#endif
#ifdef _MASKMAP
#define SampleMasks(i, blendMask) RemapMasks(SAMPLE_TEXTURE2D_GRAD(_Mask##i, sampler_Splat0, splatuv, splatdxuv, splatdyuv), blendMask, _Metallic##i, _Smoothness##i, _MaskRemapOffset##i, _MaskRemapScale##i)
#define NullMask(i) float4(0, 0, _MaskRemapOffset##i.z, 0) // only height matters when weight is zero.
#define SampleMasks(i, blendMask) RemapMasks(SAMPLE_TEXTURE2D_GRAD(_Mask##i, sampler_Splat0, splatuv, splatdxuv, splatdyuv), blendMask, _Metallic##i, _Smoothness##i, _MaskMapRemapOffset##i, _MaskMapRemapScale##i)
#define NullMask(i) float4(0, 0, _MaskMapRemapOffset##i.z, 0) // only height matters when weight is zero.
#else
#define SampleMasks(i, blendMask) float4(_Metallic##i, 0, 0, albedo[i].a * _Smoothness##i)
#define NullMask(i) float4(0, 0, 0, 0)

float2 splatdxuv = dxuv * _Splat##i##_ST.x; \
float2 splatdyuv = dyuv * _Splat##i##_ST.y; \
albedo[i] = SAMPLE_TEXTURE2D_GRAD(_Splat##i, sampler_Splat0, splatuv, splatdxuv, splatdyuv); \
albedo[i].rgb *= _DiffuseRemapScale##i.xyz; \
normal[i] = SampleNormal(i); \
masks[i] = SampleMasks(i, mask); \
} \

#elif defined(_TERRAIN_BLEND_DENSITY) && defined(_MASKMAP)
// Denser layers are more visible.
float4 opacityAsDensity0 = saturate((float4(albedo[0].a, albedo[1].a, albedo[2].a, albedo[3].a) - (float4(1.0, 1.0, 1.0, 1.0) - blendMasks0)) * 20.0); // 20.0 is the number of steps in inputAlphaMask (Density mask. We decided 20 empirically)
float4 useOpacityAsDensityParam0 = { 1, 1, 1, 1 };
float4 useOpacityAsDensityParam0 = { _DiffuseRemapScale0.w, _DiffuseRemapScale1.w, _DiffuseRemapScale2.w, _DiffuseRemapScale3.w };
float4 useOpacityAsDensityParam1 = { 1, 1, 1, 1 };
float4 useOpacityAsDensityParam1 = { _DiffuseRemapScale4.w, _DiffuseRemapScale5.w, _DiffuseRemapScale6.w, _DiffuseRemapScale7.w };
blendMasks1 = lerp(blendMasks1, opacityAsDensity1, useOpacityAsDensityParam1);
#endif
#endif

正在加载...
取消
保存