浏览代码

Merge pull request #79 from Unity-Technologies/LayeredLit

Layeredlit
/main
GitHub 8 年前
当前提交
610b8d11
共有 9 个文件被更改,包括 128 次插入71 次删除
  1. 30
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs
  2. 4
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader
  3. 68
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitData.hlsl
  4. 3
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitProperties.hlsl
  5. 31
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitSurfaceData.hlsl
  6. 15
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl
  7. 2
      Assets/TestScenes/HDTest/LayeredLitTest.unity
  8. 35
      Assets/TestScenes/HDTest/LayeredLitTest/Material/Layered_HeightBased.mat
  9. 11
      Assets/TestScenes/HDTest/LayeredLitTest/Material/Lit_White.mat

30
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs


{
public readonly GUIContent[] layerLabels =
{
new GUIContent("Layer 0"),
new GUIContent("Base Layer"),
};
public readonly GUIStyle[] layerLabelColors =
{
new GUIStyle(EditorStyles.label),
new GUIStyle(EditorStyles.label),
new GUIStyle(EditorStyles.label),
new GUIStyle(EditorStyles.label)
};
public readonly GUIContent materialLayerText = new GUIContent("Material");

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 useHeightBasedBlendText = new GUIContent("Use Height Based Blend", "Layer will be blended with the underlying layer based on the height.");
public readonly GUIContent heightOffsetText = new GUIContent("HeightOffset", "Height offset from the previous layer.");
public readonly GUIContent heightOffsetText = new GUIContent("Height Offset", "Height offset from the previous layer.");
public readonly GUIContent inheritBaseLayerText = new GUIContent("Inherit Base Layer Normal", "Inherit the normal from the base layer.");
public StylesLayer()
{
layerLabelColors[1].normal.textColor = Color.red;
layerLabelColors[2].normal.textColor = Color.green;
layerLabelColors[3].normal.textColor = Color.blue;
}
}
static StylesLayer s_Styles = null;

MaterialProperty useHeightBasedBlend = null;
const string kHeightOffset = "_HeightOffset";
MaterialProperty[] heightOffset = new MaterialProperty[kMaxLayerCount-1];
const string kInheritBaseLayer = "_InheritBaseLayer";
MaterialProperty[] inheritBaseLayer = new MaterialProperty[kMaxLayerCount - 1];
const string kHeightFactor = "_HeightFactor";
MaterialProperty[] heightFactor = new MaterialProperty[kMaxLayerCount-1];
const string kBlendSize = "_BlendSize";

if(i != 0)
{
inheritBaseLayer[i - 1] = FindProperty(string.Format("{0}{1}", kInheritBaseLayer, i), props);
heightOffset[i-1] = FindProperty(string.Format("{0}{1}", kHeightOffset, i), props);
heightFactor[i-1] = FindProperty(string.Format("{0}{1}", kHeightFactor, i), props);
blendSize[i-1] = FindProperty(string.Format("{0}{1}", kBlendSize, i), props);

Material material = m_MaterialEditor.target as Material;
EditorGUILayout.LabelField(styles.layerLabels[layerIndex]);
EditorGUILayout.LabelField(styles.layerLabels[layerIndex], styles.layerLabelColors[layerIndex]);
EditorGUI.indentLevel++;

{
int heightParamIndex = layerIndex - 1;
m_MaterialEditor.ShaderProperty(inheritBaseLayer[heightParamIndex], styles.inheritBaseLayerText);
m_MaterialEditor.ShaderProperty(heightOffset[heightParamIndex], styles.heightOffsetText);
m_MaterialEditor.ShaderProperty(heightFactor[heightParamIndex], styles.heightFactorText);
m_MaterialEditor.ShaderProperty(blendSize[heightParamIndex], styles.blendSizeText);

EditorGUI.indentLevel--;
if(layerIndex == 0)
EditorGUILayout.Space();
return result;
}

4
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader


_BlendSize2("_BlendSize2", Range(0, 0.05)) = 0.0
_BlendSize3("_BlendSize3", Range(0, 0.05)) = 0.0
_InheritBaseLayer1("_InheritBaseLayer1", Range(0, 1.0)) = 0.0
_InheritBaseLayer2("_InheritBaseLayer2", Range(0, 1.0)) = 0.0
_InheritBaseLayer3("_InheritBaseLayer3", Range(0, 1.0)) = 0.0
_VertexColorHeightFactor("_VertexColorHeightFactor", Float) = 1.0
_DistortionVectorMap("DistortionVectorMap", 2D) = "black" {}

68
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitData.hlsl


ApplyDepthOffsetAttribute(depthOffset, input);
#endif
float alpha = GetSurfaceData(input, layerTexCoord, surfaceData);
// We perform the conversion to world of the normalTS outside of the GetSurfaceData
// so it allow us to correctly deal with detail normal map and optimize the code for the layered shaders
float3 normalTS;
float alpha = GetSurfaceData(input, layerTexCoord, surfaceData, normalTS);
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
// Caution: surfaceData must be fully initialize before calling GetBuiltinData
GetBuiltinData(input, surfaceData, alpha, depthOffset, builtinData);
}

outWeights[0] = left;
}
float3 BlendLayeredColor(float3 rgb0, float3 rgb1, float3 rgb2, float3 rgb3, float weight[4])
float3 BlendLayeredFloat3(float3 x0, float3 x1, float3 x2, float3 x3, float weight[4])
result = rgb0 * weight[0] + rgb1 * weight[1];
result = x0 * weight[0] + x1 * weight[1];
result += (rgb2 * weight[2]);
result += (x2 * weight[2]);
result += rgb3 * weight[3];
result += x3 * weight[3];
float3 BlendLayeredNormal(float3 normal0, float3 normal1, float3 normal2, float3 normal3, float weight[4])
{
float3 result = float3(0.0, 0.0, 0.0);
result = normal0 * weight[0] + normal1 * weight[1];
#if _LAYER_COUNT >= 3
result += normal2 * weight[2];
#endif
#if _LAYER_COUNT >= 4
result += normal3 * weight[3];
#endif
return normalize(result);
}
float BlendLayeredScalar(float x0, float x1, float x2, float x3, float weight[4])
{
float result = 0.0;

}
#define SURFACEDATA_BLEND_COLOR(surfaceData, name, mask) BlendLayeredColor(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define SURFACEDATA_BLEND_NORMAL(surfaceData, name, mask) BlendLayeredNormal(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define SURFACEDATA_BLEND_COLOR(surfaceData, name, mask) BlendLayeredFloat3(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define SURFACEDATA_BLEND_SCALAR(surfaceData, name, mask) BlendLayeredScalar(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define PROP_BLEND_SCALAR(name, mask) BlendLayeredScalar(name##0, name##1, name##2, name##3, mask);

SurfaceData surfaceData1;
SurfaceData surfaceData2;
SurfaceData surfaceData3;
float alpha0 = GetSurfaceData0(input, layerTexCoord, surfaceData0);
float alpha1 = GetSurfaceData1(input, layerTexCoord, surfaceData1);
float alpha2 = GetSurfaceData2(input, layerTexCoord, surfaceData2);
float alpha3 = GetSurfaceData3(input, layerTexCoord, surfaceData3);
float3 normalTS0;
float3 normalTS1;
float3 normalTS2;
float3 normalTS3;
float alpha0 = GetSurfaceData0(input, layerTexCoord, surfaceData0, normalTS0);
float alpha1 = GetSurfaceData1(input, layerTexCoord, surfaceData1, normalTS1);
float alpha2 = GetSurfaceData2(input, layerTexCoord, surfaceData2, normalTS2);
float alpha3 = GetSurfaceData3(input, layerTexCoord, surfaceData3, normalTS3);
// Mask Values : Layer 1, 2, 3 are r, g, b
float3 maskValues = SAMPLE_TEXTURE2D(_LayerMaskMap, sampler_LayerMaskMap, input.texCoord0).rgb;

surfaceData.baseColor = SURFACEDATA_BLEND_COLOR(surfaceData, baseColor, weights);
surfaceData.specularOcclusion = SURFACEDATA_BLEND_SCALAR(surfaceData, specularOcclusion, weights);
// Note: for normal map (in tangent space) it is possible to have better performance
// by blending in tangent space then transform to world and apply flip.
// Sadly this require a specific path (without taking into account that there is detail normal map)
// mean it add an extra cost of maintenance. We chose to not do this optimization in favor
// of simpler code and in the future will rely on shader graph to create optimize code.
surfaceData.normalWS = SURFACEDATA_BLEND_NORMAL(surfaceData, normalWS, weights);
float3 normalTS;
#if defined(_HEIGHT_BASED_BLEND)
float _InheritBaseLayer0 = 1.0f; // Default value for lerp when all weights but base layer are zero.
// Compute the combined inheritance factor of layers 1,2 and 3
float inheritFactor = PROP_BLEND_SCALAR(_InheritBaseLayer, weights);
float3 vertexNormalTS = float3(0.0, 0.0, 1.0);
// The idea here is to lerp toward vertex normal. This way when we don't want to inherit, we will combine layer 1/2/3 normal with a vertex normal which is neutral.
float3 baseLayerNormalTS = normalize(lerp(vertexNormalTS, normalTS0, inheritFactor));
// Blend layer 1/2/3 normals before combining to the base layer. Again we need to have a neutral value for base layer (vertex normal) in case all weights are zero.
float3 layersNormalTS = BlendLayeredFloat3(vertexNormalTS, normalTS1, normalTS2, normalTS3, weights);
normalTS = BlendNormalRNM(baseLayerNormalTS, layersNormalTS);
#else
normalTS = BlendLayeredFloat3(normalTS0, normalTS1, normalTS2, normalTS3, weights);
#endif
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
// Init other unused parameter
surfaceData.materialId = 0;

3
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitProperties.hlsl


float _BlendSize2;
float _BlendSize3;
float _VertexColorHeightFactor;
float _InheritBaseLayer1;
float _InheritBaseLayer2;
float _InheritBaseLayer3;
float3 _EmissiveColor;
TEXTURE2D(_EmissiveColorMap);

31
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitSurfaceData.hlsl


}
// Return opacity
float ADD_IDX(GetSurfaceData)(FragInputs input, LayerTexCoord layerTexCoord, out SurfaceData surfaceData)
float ADD_IDX(GetSurfaceData)(FragInputs input, LayerTexCoord layerTexCoord, out SurfaceData surfaceData, out float3 normalTS)
{
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
float alpha = ADD_IDX(_BaseColor).a;

//surfaceData.specularOcclusion *= surfaceData.specularOcclusion;
surfaceData.specularOcclusion = 1.0;
#endif
surfaceData.normalWS = float3(0.0, 0.0, 0.0); // Need to init this so that the compiler leaves us alone.
float3 vertexNormalWS = normalize(input.tangentToWorld[2].xyz);
float3 normalTS = SAMPLE_LAYER_NORMALMAP(ADD_IDX(_NormalMap), ADD_ZERO_IDX(sampler_NormalMap), ADD_IDX(layerTexCoord.base), ADD_ZERO_IDX(_NormalScale));
#ifdef _DETAIL_MAP
normalTS = lerp(normalTS, BlendNormal(normalTS, detailNormalTS), detailMask);
#endif
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
normalTS = SAMPLE_LAYER_NORMALMAP(ADD_IDX(_NormalMap), ADD_ZERO_IDX(sampler_NormalMap), ADD_IDX(layerTexCoord.base), ADD_ZERO_IDX(_NormalScale));
surfaceData.normalWS = TransformObjectToWorldDir(normalOS);
normalTS = TransformObjectToTangent(normalOS, input.tangentToWorld);
#endif
float3 detailNormalWS = TransformTangentToWorld(detailNormalTS, input.tangentToWorld);
surfaceData.normalWS = lerp(surfaceData.normalWS, BlendNormal(surfaceData.normalWS, detailNormalWS), detailMask);
normalTS = lerp(normalTS, BlendNormalRNM(normalTS, detailNormalTS), detailMask);
#endif
surfaceData.normalWS = vertexNormalWS;
normalTS = float3(0.0, 0.0, 1.0);
float3 oppositeNormalWS = -surfaceData.normalWS;
float3 oppositeNormalTS = -normalTS;
float3 oppositeNormalWS = reflect(surfaceData.normalWS, vertexNormalWS);
float3 oppositeNormalTS = reflect(normalTS, float3(0.0, 0.0, 1.0)); // Reflect around vertex normal (in tangent space this is z)
surfaceData.normalWS = input.isFrontFace ?
(GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS) :
(-GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS);
normalTS = input.isFrontFace ?
(GetOdddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS) :
(-GetOdddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS);
#endif
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A

15
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl


return normalize(mul(float3x3(tangentToWorld[0].xyz, tangentToWorld[1].xyz, tangentToWorld[2].xyz), dirWS));
}
float3 TransformTangentToObject(float3 dirTS, float3 worldToTangent[3])
{
// TODO check: do we need to normalize ?
// worldToTangent is orthonormal so inverse <==> transpose
float3x3 mWorldToTangent = float3x3(worldToTangent[0].xyz, worldToTangent[1].xyz, worldToTangent[2].xyz);
float3 normalWS = mul(dirTS, mWorldToTangent);
return normalize(mul((float3x3)unity_WorldToObject, normalWS));
}
// Assume TBN is orthonormal.
float3 TransformObjectToTangent(float3 dirOS, float3 worldToTangent[3])
{
// TODO check: do we need to normalize ?
return normalize(mul(float3x3(worldToTangent[0].xyz, worldToTangent[1].xyz, worldToTangent[2].xyz), mul((float3x3)unity_ObjectToWorld, dirOS)));
}
#endif // UNITY_SHADER_VARIABLES_INCLUDED

2
Assets/TestScenes/HDTest/LayeredLitTest.unity


m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 112888599}
m_LocalRotation: {x: 0.4442191, y: -0, z: -0, w: 0.8959182}
m_LocalPosition: {x: -41.74, y: -1.55, z: 8.82}
m_LocalPosition: {x: -41.31, y: -1.55, z: 13.03}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 1732353142}

35
Assets/TestScenes/HDTest/LayeredLitTest/Material/Layered_HeightBased.mat


- _HeightScale1: 0.1
- _HeightScale2: 0.05
- _HeightScale3: 0.06
- _InheritBaseLayer1: 1
- _InheritBaseLayer2: 1
- _InheritBaseLayer3: 1
- _LayerCount: 4
- _LayerMaskVertexColor: 0
- _Metallic: 0

- _SpecularHighlights: 1
- _SrcBlend: 1
- _SurfaceType: 0
- _TexWorldScale0: 1
- _TexWorldScale1: 1
- _TexWorldScale2: 1
- _TexWorldScale3: 1
- _UVBase0: 0
- _UVBase1: 0
- _UVBase2: 0
- _UVBase3: 0
- _TexWorldScale0: 0.1
- _TexWorldScale1: 0.1
- _TexWorldScale2: 0.1
- _TexWorldScale3: 0.1
- _UVBase0: 4
- _UVBase1: 4
- _UVBase2: 4
- _UVBase3: 4
- _UVMappingPlanar0: 0
- _UVMappingPlanar1: 0
- _UVMappingPlanar2: 0
- _UVMappingPlanar3: 0
- _UVMappingPlanar0: 1
- _UVMappingPlanar1: 1
- _UVMappingPlanar2: 1
- _UVMappingPlanar3: 1
- _UVSec: 0
- _UseHeightBasedBlend: 1
- _UseHeightBasedBlend1: 1

- _UVDetailsMappingMask1: {r: 1, g: 0, b: 0, a: 0}
- _UVDetailsMappingMask2: {r: 1, g: 0, b: 0, a: 0}
- _UVDetailsMappingMask3: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask0: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask1: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask2: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask3: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask0: {r: 0, g: 0, b: 0, a: 0}
- _UVMappingMask1: {r: 0, g: 0, b: 0, a: 0}
- _UVMappingMask2: {r: 0, g: 0, b: 0, a: 0}
- _UVMappingMask3: {r: 0, g: 0, b: 0, a: 0}

11
Assets/TestScenes/HDTest/LayeredLitTest/Material/Lit_White.mat


m_LightmapFlags: 1
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
disabledShaderPasses:
- DistortionVectors
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:

m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DistortionVectorMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}

- _BumpScale: 1
- _CullMode: 2
- _Cutoff: 0.5
- _DepthOffsetEnable: 0
- _DetailAOScale: 1
- _DetailAlbedoScale: 1
- _DetailHeightScale: 1

- _DetailSmoothnessScale: 1
- _DistortionDepthTest: 0
- _DistortionEnable: 0
- _DistortionOnly: 0
- _DoubleSidedMode: 0
- _DstBlend: 0

- _TexWorldScale: 1
- _UVBase: 0
- _UVDetail: 0
- _UVMappingPlanar: 0
- _ZTestMode: 8
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}

正在加载...
取消
保存