浏览代码

Update Stacklit normal map - Add support for triplanar normal map + obj space / tangent space

/main
sebastienlagarde 7 年前
当前提交
dd45564c
共有 5 个文件被更改,包括 125 次插入76 次删除
  1. 24
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/StackLit/BaseMaterialUI.cs
  2. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/StackLit/StackLitUI.cs
  3. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLit.shader
  4. 171
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLitData.hlsl
  5. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLitProperties.hlsl

24
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/StackLit/BaseMaterialUI.cs


Local
}
public enum NormalSpace
{
Tangent,
Object
}
public enum UVMapping
{
UV0,

public ComboProperty m_LocalOrWorldProperty;
public ComboProperty m_NormalSpaceProperty;
public Property m_ChannelProperty;
public Property m_RemapProperty;

public string m_ConstantPropertyName;
public bool m_IsNormalMap;
public TextureProperty(BaseMaterialGUI parent, string propertyName, string constantPropertyName, string guiText, bool useConstantAsTint, bool isMandatory = true, bool isNormalMap = false)
: this(parent, propertyName, constantPropertyName, guiText, string.Empty, useConstantAsTint, isMandatory, isNormalMap)
{

: base(parent, propertyName, guiText, toolTip, isMandatory)
{
m_IsNormalMap = isNormalMap;
m_ConstantPropertyName = constantPropertyName;
m_Show = new Property(parent, propertyName + "Show", "", isMandatory);

m_UvSetProperty = new ComboProperty(parent, propertyName + "UV", "UV Mapping", Enum.GetNames(typeof(UVMapping)), false);
m_LocalOrWorldProperty = new ComboProperty(parent, propertyName + "UVLocal", "Local or world", Enum.GetNames(typeof(PlanarSpace)), false);
m_NormalSpaceProperty = new ComboProperty(parent, propertyName + "ObjSpace", "Normal space", Enum.GetNames(typeof(NormalSpace)), false);
m_ChannelProperty = new ComboProperty(parent, propertyName + "Channel", "Channel", Enum.GetNames(typeof(Channel)), false);
m_RemapProperty = new Property(parent, constantPropertyName + "Remap", "Remapping", "Defines the range to remap/scale the values in texture", false);

m_TextureProperty.OnFindProperty(props);
m_UvSetProperty.OnFindProperty(props);
m_LocalOrWorldProperty.OnFindProperty(props);
m_NormalSpaceProperty.OnFindProperty(props);
m_ChannelProperty.OnFindProperty(props);
m_RemapProperty.OnFindProperty(props);
m_InvertRemapProperty.OnFindProperty(props);

m_LocalOrWorldProperty.OnGUI();
}
if (m_IsNormalMap)
{
m_NormalSpaceProperty.OnGUI();
}
if (m_RemapProperty.IsValid)
{
// Display the remap of texture values.

return string.Format(
"[HideInInspector] {0}MapShow(\"{1} Show\", Float) = 0\n" +
"{0}(\"{1}\", Range(0.0, 1.0)) = 0\n" +
"{2}(\"{1} Map\", 2D) = \"white\" {{ }}\n" +
"{2}(\"{1} Map\", 2D) = " + (m_IsNormalMap ? "\"bump\"" : "\"white\"") + " {{ }}\n" +
(m_IsNormalMap ? "{0}ObjSpace(\"{1} Object Space\", Float) = 0\n" : "") +
"{2}UV(\"{1} Map UV\", Float) = 0.0\n" +
"{2}UVLocal(\"{1} Map UV Local\", Float) = 0.0\n" +
"{2}Channel(\"{1} Map Channel\", Float) = 0.0\n" +

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Material/StackLit/StackLitUI.cs


new TextureProperty(this, k_MetallicMap, k_Metallic, "Metallic", "Metallic", false, false),
new TextureProperty(this, k_Smoothness1Map, k_Smoothness1, "Smoothness", "Smoothness", false, false),
// TODO: Special case for normal maps.
new TextureProperty(this, k_NormalMap, k_NormalScale, "Normal TODO", "Normal Map", false, false, true),
new TextureProperty(this, k_NormalMap, k_NormalScale, "Normal", "Normal Map", false, false, true),
//new TextureProperty(this, k_BaseColorMap, k_BaseColor, "Dielectric IoR", "Index of Refraction for Dielectric", false),
}),

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLit.shader


[HideInInspector] _NormalMapShow("NormalMap Show", Float) = 0.0
_NormalMap("NormalMap", 2D) = "bump" {} // Tangent space normal map
_NormalMapUV("NormalMapUV", Float) = 0.0
_NormalMapUVLocal("NormalMapUV Local", Float) = 0.0
_NormalMapObjSpace("NormalMapUV Local", Float) = 0.0
_NormalScale("Normal Scale", Range(0.0, 2.0)) = 1
[HideInInspector] _EmissiveColorMapShow("Emissive Color Map Show", Float) = 0.0

171
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLitData.hlsl


//#endif
#endif
float3 GetNormalTS(FragInputs input, float2 texCoord, float3 detailNormalTS, float detailMask)
{
// TODO: different spaces (eg #ifdef _NORMALMAP_TANGENT_SPACE #elif object space, SURFACE_GRADIENT, etc.)
// and use detail map
float3 normalTS;
// Note we don't use the _NORMALMAP_IDX mechanism of the Lit shader, since we don't have "layers", we can
// directly use the shader_feature keyword:
#ifdef _NORMALMAP
normalTS = float3(0.0, 0.0, 1.0); //normalTS = SAMPLE_UVMAPPING_NORMALMAP(_NormalMap, SAMPLER_NORMALMAP_ID, texCoord, _NormalScale);
#else
normalTS = float3(0.0, 0.0, 1.0);
#endif
return normalTS;
}
//-----------------------------------------------------------------------------
// Texture Mapping
//-----------------------------------------------------------------------------

float3 triplanarWeights[2];
#endif
#ifdef SURFACE_GRADIENT
// float3 vertexTangentWS[4];
// float3 vertexBitangentWS[4];
#endif
float3 vertexNormalWS;
float3 vertexTangentWS[4];
float3 vertexBitangentWS[4];
float4 SampleTexture2DPlanar(TEXTURE2D_ARGS(textureName, samplerName), float textureNameUV, float textureNameUVLocal, float4 textureNameST, TextureUVMapping uvMapping)
{
return SAMPLE_TEXTURE2D(textureName, samplerName, (uvMapping.texcoords[textureNameUV][textureNameUVLocal] * textureNameST.xy + textureNameST.zw));
}
// If we use triplanar on any of the properties, then we enable the triplanar path
#ifdef _USE_TRIPLANAR
float4 SampleTexture2DTriplanar(TEXTURE2D_ARGS(textureName, samplerName), float textureNameUV, float textureNameUVLocal, float4 textureNameST, TextureUVMapping uvMapping)
{
if (textureNameUV == TEXCOORD_INDEX_TRIPLANAR)
{
float4 val = float4(0.0, 0.0, 0.0, 0.0);
if (uvMapping.triplanarWeights[textureNameUVLocal].x > 0.0)
val += uvMapping.triplanarWeights[textureNameUVLocal].x * SAMPLE_TEXTURE2D(textureName, samplerName, (uvMapping.texcoords[TEXCOORD_INDEX_PLANAR_YZ][textureNameUVLocal] * textureNameST.xy + textureNameST.zw));
if (uvMapping.triplanarWeights[textureNameUVLocal].y > 0.0)
val += uvMapping.triplanarWeights[textureNameUVLocal].y * SAMPLE_TEXTURE2D(textureName, samplerName, (uvMapping.texcoords[TEXCOORD_INDEX_PLANAR_ZX][textureNameUVLocal] * textureNameST.xy + textureNameST.zw));
if (uvMapping.triplanarWeights[textureNameUVLocal].z > 0.0)
val += uvMapping.triplanarWeights[textureNameUVLocal].z * SAMPLE_TEXTURE2D(textureName, samplerName, (uvMapping.texcoords[TEXCOORD_INDEX_PLANAR_XY][textureNameUVLocal] * textureNameST.xy + textureNameST.zw));
return val;
}
else
{
return SampleTexture2DPlanar(TEXTURE2D_PARAM(textureName, samplerName), textureNameUV, textureNameUVLocal, textureNameST, uvMapping);
}
}
#define SAMPLE_TEXTURE2D_SCALE_BIAS(name) SampleTexture2DTriplanar(name, sampler##name, name##UV, name##UVLocal, name##_ST, uvMapping)
#else
#define SAMPLE_TEXTURE2D_SCALE_BIAS(name) SampleTexture2DPlanar(name, sampler##name, name##UV, name##UVLocal, name##_ST, uvMapping)
#endif // _USE_TRIPLANAR
void InitializeMappingData(FragInputs input, out TextureUVMapping uvMapping)
{
float3 position = GetAbsolutePositionWS(input.positionWS);

#endif
// Normal mapping with surface gradient
#ifdef SURFACE_GRADIENT
uvMapping.vertexNormalWS = vertexNormalWS;
uvMapping.vertexTangentWS[0] = input.worldToTangent[0];
uvMapping.vertexBitangentWS[0] = input.worldToTangent[1];

SurfaceGradientGenBasisTB(vertexNormalWS, sigmaX, sigmaY, flipSign, input.texCoord1, uvMapping.vertexTangentWS[1], uvMapping.vertexBitangentWS[1]);
SurfaceGradientGenBasisTB(vertexNormalWS, sigmaX, sigmaY, flipSign, input.texCoord2, uvMapping.vertexTangentWS[2], uvMapping.vertexBitangentWS[2]);
SurfaceGradientGenBasisTB(vertexNormalWS, sigmaX, sigmaY, flipSign, input.texCoord3, uvMapping.vertexTangentWS[3], uvMapping.vertexBitangentWS[3]);
#endif // SURFACE_GRADIENT
}
float4 SampleTexture2DScaleBias(TEXTURE2D_ARGS(textureName, samplerName), float textureNameUV, float textureNameUVLocal, float4 textureNameST, TextureUVMapping uvMapping)
{
return SAMPLE_TEXTURE2D(textureName, samplerName, (uvMapping.texcoords[textureNameUV][textureNameUVLocal] * textureNameST.xy + textureNameST.zw));
}
// If we use triplanar on any of the properties, then we enable the triplanar path
float4 SampleTexture2DTriplanarScaleBias(TEXTURE2D_ARGS(textureName, samplerName), float textureNameUV, float textureNameUVLocal, float4 textureNameST, TextureUVMapping uvMapping)
{
#ifdef _USE_TRIPLANAR
if (textureNameUV == TEXCOORD_INDEX_TRIPLANAR)
{
float4 val = float4(0.0, 0.0, 0.0, 0.0);
if (uvMapping.triplanarWeights[textureNameUVLocal].x > 0.0)
val += uvMapping.triplanarWeights[textureNameUVLocal].x * SampleTexture2DScaleBias(TEXTURE2D_PARAM(textureName, samplerName), TEXCOORD_INDEX_PLANAR_YZ, textureNameUVLocal, textureNameST, uvMapping);
if (uvMapping.triplanarWeights[textureNameUVLocal].y > 0.0)
val += uvMapping.triplanarWeights[textureNameUVLocal].y * SampleTexture2DScaleBias(TEXTURE2D_PARAM(textureName, samplerName), TEXCOORD_INDEX_PLANAR_ZX, textureNameUVLocal, textureNameST, uvMapping);
if (uvMapping.triplanarWeights[textureNameUVLocal].z > 0.0)
val += uvMapping.triplanarWeights[textureNameUVLocal].z * SampleTexture2DScaleBias(TEXTURE2D_PARAM(textureName, samplerName), TEXCOORD_INDEX_PLANAR_XY, textureNameUVLocal, textureNameST, uvMapping);
return val;
}
else
{
#endif // _USE_TRIPLANAR
return SampleTexture2DScaleBias(TEXTURE2D_PARAM(textureName, samplerName), textureNameUV, textureNameUVLocal, textureNameST, uvMapping);
#ifdef _USE_TRIPLANAR
}
#endif
}
float3 SampleTexture2DTriplanarNormalScaleBias(TEXTURE2D_ARGS(textureName, samplerName), float textureNameUV, float textureNameUVLocal, float4 textureNameST, float textureNameObjSpace, TextureUVMapping uvMapping, float2 scale)
{
if (textureNameObjSpace)
{
// TODO: obj triplanar (need to do * 2 - 1 before blending)
// We forbid scale in case of object space as it make no sense
// Decompress normal ourselve
float3 normalOS = SampleTexture2DTriplanarScaleBias(TEXTURE2D_PARAM(textureName, samplerName), textureNameUV, textureNameUVLocal, textureNameST, uvMapping) * 2.0 - 1.0;
// no need to renormalize normalOS for SurfaceGradientFromPerturbedNormal
return SurfaceGradientFromPerturbedNormal(uvMapping.vertexNormalWS, TransformObjectToWorldDir(normalOS));
}
else
{
#ifdef _USE_TRIPLANAR
if (textureNameUV == TEXCOORD_INDEX_TRIPLANAR)
{
float2 derivXplane;
float2 derivYPlane;
float2 derivZPlane;
derivXplane = derivYPlane = derivZPlane = float2(0.0, 0.0);
if (uvMapping.triplanarWeights[textureNameUVLocal].x > 0.0)
derivXplane = uvMapping.triplanarWeights[textureNameUVLocal].x * UnpackDerivativeNormalRGorAG(SampleTexture2DScaleBias(TEXTURE2D_PARAM(textureName, samplerName), TEXCOORD_INDEX_PLANAR_YZ, textureNameUVLocal, textureNameST, uvMapping), scale);
if (uvMapping.triplanarWeights[textureNameUVLocal].y > 0.0)
derivYPlane = uvMapping.triplanarWeights[textureNameUVLocal].y * UnpackDerivativeNormalRGorAG(SampleTexture2DScaleBias(TEXTURE2D_PARAM(textureName, samplerName), TEXCOORD_INDEX_PLANAR_ZX, textureNameUVLocal, textureNameST, uvMapping), scale);
if (uvMapping.triplanarWeights[textureNameUVLocal].z > 0.0)
derivZPlane = uvMapping.triplanarWeights[textureNameUVLocal].z * UnpackDerivativeNormalRGorAG(SampleTexture2DScaleBias(TEXTURE2D_PARAM(textureName, samplerName), TEXCOORD_INDEX_PLANAR_XY, textureNameUVLocal, textureNameST, uvMapping), scale);
// Assume derivXplane, derivYPlane and derivZPlane sampled using (z,y), (z,x) and (x,y) respectively.
float3 volumeGrad = float3(derivZPlane.x + derivYPlane.y, derivZPlane.y + derivXplane.y, derivXplane.x + derivYPlane.x);
return SurfaceGradientFromVolumeGradient(uvMapping.vertexNormalWS, volumeGrad);
}
#endif
float2 deriv = UnpackDerivativeNormalRGorAG(SampleTexture2DScaleBias(TEXTURE2D_PARAM(textureName, samplerName), textureNameUV, textureNameUVLocal, textureNameST, uvMapping));
if (textureNameUV <= TEXCOORD_INDEX_UV3)
{
return SurfaceGradientFromTBN(deriv, uvMapping.vertexTangentWS[textureNameUV], uvMapping.vertexBitangentWS[textureNameUV]);
}
else
{
float3 volumeGrad;
if (textureNameUV == TEXCOORD_INDEX_PLANAR_YZ)
volumeGrad = float3(0.0, deriv.y, deriv.x);
else if (textureNameUV == TEXCOORD_INDEX_PLANAR_ZX)
volumeGrad = float3(deriv.y, 0.0, deriv.x);
else if (textureNameUV == TEXCOORD_INDEX_PLANAR_XY)
volumeGrad = float3(deriv.x, deriv.y, 0.0);
return SurfaceGradientFromVolumeGradient(uvMapping.vertexNormalWS, volumeGrad);
}
}
#define SAMPLE_TEXTURE2D_SCALE_BIAS(name) SampleTexture2DTriplanarScaleBias(name, sampler##name, name##UV, name##UVLocal, name##_ST, uvMapping)
#define SAMPLE_TEXTURE2D_NORMAL_SCALE_BIAS(name, scale) SampleTexture2DTriplanarNormalScaleBias(name, sampler##name, name##UV, name##UVLocal, name##_ST, name##ObjSpace, uvMapping, scale)
//-----------------------------------------------------------------------------
// GetSurfaceAndBuiltinData
//-----------------------------------------------------------------------------

// Surface Data:
// -------------------------------------------------------------
// 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;
// TODO: Those are only needed once we handle specular occlusion and optionnally bent normal maps.
// Also, for the builtinData part, use bentnormal to sample diffuse GI
//float3 bentNormalTS;
//float3 bentNormalWS;
float alpha = SAMPLE_TEXTURE2D_SCALE_BIAS(_BaseColorMap).a * _BaseColor.a;
#ifdef _ALPHATEST_ON
//NEWLITTODO: Once we include those passes in the main StackLit.shader, add handling of CUTOFF_TRANSPARENT_DEPTH_PREPASS and _POSTPASS

// TODO detail map:
float3 detailNormalTS = float3(0.0, 0.0, 0.0);
float detailMask = 0.0;
//surfaceData.normalWS = float3(0.0, 0.0, 0.0);
normalTS = float3(0, 0, 1); // GetNormalTS(input, texcoords[_NormalMapUV], detailNormalTS, detailMask);
float3 gradient = SAMPLE_TEXTURE2D_NORMAL_SCALE_BIAS(_NormalMap, float2(_NormalScale.xx));
//TODO: bentNormalTS
surfaceData.perceptualSmoothnessA = dot(SAMPLE_TEXTURE2D_SCALE_BIAS(_SmoothnessAMap), _SmoothnessAMapChannelMask);

// Surface Data Part 2 (outsite GetSurfaceData( ) in Lit shader):
// -------------------------------------------------------------
GetNormalWS(input, V, normalTS, surfaceData.normalWS); // MaterialUtilities.hlsl
// Convert back to world space normal
surfaceData.normalWS = SurfaceGradientResolveNormal(input.worldToTangent[2], gradient);
// TODO: decal etc.

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLitProperties.hlsl


float _NormalScale;
float _NormalMapUV;
float _NormalMapUVLocal;
float _NormalMapObjSpace;
float4 _NormalMap_ST;
float4 _NormalMap_TexelSize;
float4 _NormalMap_MipInfo;

正在加载...
取消
保存