浏览代码

HDRenderPipeline: Specular color mat id is no more store as material id

- Instead of wasting one value in materialId (only 4 availabe, we reuse
the matid standard and the value in the specular), it allow to have 2
matId free.
- Optimize the code with shader features for materialID
/RenderPassXR_Sandbox
Sebastien Lagarde 7 年前
当前提交
e9e6cf59
共有 10 个文件被更改,包括 145 次插入79 次删除
  1. 2
      Assets/ScriptableRenderPipeline/Core/Shadow/ShadowBase.cs.hlsl
  2. 2
      Assets/ScriptableRenderPipeline/Fptl/LightDefinitions.cs.hlsl
  3. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/FeatureFlags.hlsl
  4. 16
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/LitUI.cs
  5. 22
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs
  6. 21
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs.hlsl
  7. 132
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  8. 7
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.shader
  9. 19
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl
  10. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitProperties.hlsl

2
Assets/ScriptableRenderPipeline/Core/Shadow/ShadowBase.cs.hlsl


//
// This file was automatically generated from Assets/ScriptableRenderPipeline/Core/Shadow/ShadowBase.cs. Please don't edit by hand.
// This file was automatically generated from Assets/ScriptableRenderPipeline/core/Shadow/ShadowBase.cs. Please don't edit by hand.
//
#ifndef SHADOWBASE_CS_HLSL

2
Assets/ScriptableRenderPipeline/Fptl/LightDefinitions.cs.hlsl


//
// This file was automatically generated from Assets/ScriptableRenderPipeline/Fptl/LightDefinitions.cs. Please don't edit by hand.
// This file was automatically generated from Assets/ScriptableRenderPipeline/fptl/LightDefinitions.cs. Please don't edit by hand.
//
#ifndef LIGHTDEFINITIONS_CS_HLSL

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/FeatureFlags.hlsl


static const uint FeatureVariantFlags[NUM_FEATURE_VARIANTS] =
{
/* 0 */ 0 | MATERIALFEATUREFLAGS_MASK,
/* 0 */ 0 | MATERIALFEATUREFLAGS_MASK, // TODO: ask Runes if this is really needed ? In case of material only, it mean debug and we don't care about performance
/* 1 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 2 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 3 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_STANDARD,

16
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/LitUI.cs


m_MaterialEditor.TexturePropertySingleLine(Styles.thicknessMapText, thicknessMap);
}
protected void ShaderStandardInputGUI()
protected void ShaderAnisoInputGUI()
{
if ((NormalMapSpace)normalMapSpace.floatValue == NormalMapSpace.TangentSpace)
{

m_MaterialEditor.TexturePropertySingleLine(Styles.baseColorText, baseColorMap, baseColor);
if ((Lit.MaterialId)materialID.floatValue == Lit.MaterialId.LitStandard)
if ((Lit.MaterialId)materialID.floatValue == Lit.MaterialId.LitStandard || (Lit.MaterialId)materialID.floatValue == Lit.MaterialId.LitAniso)
{
m_MaterialEditor.ShaderProperty(metallic, Styles.metallicText);
}

ShaderSSSInputGUI(material);
break;
case Lit.MaterialId.LitStandard:
ShaderStandardInputGUI();
// Nothing
break;
case Lit.MaterialId.LitAniso:
ShaderAnisoInputGUI();
break;
case Lit.MaterialId.LitSpecular:
m_MaterialEditor.TexturePropertySingleLine(Styles.specularColorText, specularColorMap, specularColor);

material.DisableKeyword("_REQUIRE_UV2");
material.DisableKeyword("_REQUIRE_UV3");
}
Lit.MaterialId materialId = (Lit.MaterialId)material.GetFloat(kMaterialID);
SetKeyword(material, "_MATID_SSS", materialId == Lit.MaterialId.LitSSS);
//SetKeyword(material, "_MATID_STANDARD", materialId == Lit.MaterialId.LitStandard); // See comment in Lit.shader, it is the default, we don't define it
SetKeyword(material, "_MATID_ANISO", materialId == Lit.MaterialId.LitAniso);
SetKeyword(material, "_MATID_SPECULAR", materialId == Lit.MaterialId.LitSpecular);
}
}
} // namespace UnityEditor

22
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs


{
LitSSS = 0,
LitStandard = 1,
LitSpecular = 2,
LitUnused = 3,
LitAniso = 4 // Should be the last as it is not setup by the users but generated based on anisotropy property
LitUnused0 = 2,
LitUnused1 = 3,
LitAniso = 4, // Should be the last as it is not setup by the users but generated based on anisotropy property
LitSpecular = 5, // Should be the last as it is not setup by the users but generated based on anisotropy property and specular
};
[GenerateHLSL]

LitStandard = 1 << 13,
LitSpecular = 1 << 14,
LitAniso = 1 << 15
LitAniso = 1 << 14,
LitSpecular = 1 << 15
}
[GenerateHLSL]
public enum SpecularValue
{
Water = 0, // 0.02 Water or ice
Regular = 1, // 0.04 regular dieletric
Gemstone = 2, // 0.20
SpecularColor = 3 // Special case: use specular color
}
//-----------------------------------------------------------------------------

[SurfaceDataAttributes("Metallic")]
public float metallic;
[SurfaceDataAttributes("Specular")]
public float specular; // 0.02, 0.04, 0.16, 0.2
public SpecularValue specular;
// SSS
[SurfaceDataAttributes("Subsurface Radius")]

21
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs.hlsl


//
#define MATERIALID_LIT_SSS (0)
#define MATERIALID_LIT_STANDARD (1)
#define MATERIALID_LIT_SPECULAR (2)
#define MATERIALID_LIT_UNUSED (3)
#define MATERIALID_LIT_UNUSED0 (2)
#define MATERIALID_LIT_UNUSED1 (3)
#define MATERIALID_LIT_SPECULAR (5)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Lit+MaterialFeatureFlags: static fields

#define MATERIALFEATUREFLAGS_LIT_SPECULAR (16384)
#define MATERIALFEATUREFLAGS_LIT_ANISO (32768)
#define MATERIALFEATUREFLAGS_LIT_ANISO (16384)
#define MATERIALFEATUREFLAGS_LIT_SPECULAR (32768)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Lit+SpecularValue: static fields
//
#define SPECULARVALUE_WATER (0)
#define SPECULARVALUE_REGULAR (1)
#define SPECULARVALUE_GEMSTONE (2)
#define SPECULARVALUE_SPECULAR_COLOR (3)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Lit+SurfaceData: static fields

float3 tangentWS;
float anisotropy;
float metallic;
float specular;
int specular;
float subsurfaceRadius;
float thickness;
int subsurfaceProfile;

result = surfacedata.metallic.xxx;
break;
case DEBUGVIEW_LIT_SURFACEDATA_SPECULAR:
result = surfacedata.specular.xxx;
result = GetIndexColor(surfacedata.specular);
break;
case DEBUGVIEW_LIT_SURFACEDATA_SUBSURFACE_RADIUS:
result = surfacedata.subsurfaceRadius.xxx;

132
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


#endif
}
void FillMaterialIdStandardData(float3 baseColor, float specular, float metallic, float roughness, float3 normalWS, float3 tangentWS, float anisotropy, inout BSDFData bsdfData)
static const float3 arraySpecularValue = float3(SPECULARVALUE_WATER, SPECULARVALUE_REGULAR, SPECULARVALUE_GEMSTONE);
void FillMaterialIdStandardData(float3 baseColor, int specular, float metallic, inout BSDFData bsdfData)
bsdfData.fresnel0 = lerp(float3(specular.xxx), baseColor, metallic);
// TODO: encode specular
float val = arraySpecularValue[specular];
bsdfData.fresnel0 = lerp(val.xxx, baseColor, metallic);
}
void FillMaterialIdAnisoData(float roughness, float3 normalWS, float3 tangentWS, float anisotropy, inout BSDFData bsdfData)
{
bsdfData.tangentWS = tangentWS;
bsdfData.bitangentWS = cross(normalWS, tangentWS);
ConvertAnisotropyToRoughness(roughness, anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);

bsdfData.roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
bsdfData.materialId = surfaceData.materialId;
// IMPORTANT: In case of foward or gbuffer pass we know what we are, we don't need to check specular or aniso to know the materialId, this is because we have static compile shader feature for it
FillMaterialIdStandardData(surfaceData.baseColor, surfaceData.specular, surfaceData.metallic, bsdfData.roughness, surfaceData.normalWS, surfaceData.tangentWS, surfaceData.anisotropy, bsdfData);
bsdfData.materialId = surfaceData.anisotropy > 0.0 ? MATERIALID_LIT_ANISO : bsdfData.materialId;
}
else if (bsdfData.materialId == MATERIALID_LIT_SSS)
{
FillMaterialIdSSSData(surfaceData.baseColor, surfaceData.subsurfaceProfile, surfaceData.subsurfaceRadius, surfaceData.thickness, bsdfData);
FillMaterialIdStandardData(surfaceData.baseColor, surfaceData.specular, surfaceData.metallic, bsdfData);
}
else if (bsdfData.materialId == MATERIALID_LIT_SPECULAR)
{

else if (bsdfData.materialId == MATERIALID_LIT_ANISO)
{
FillMaterialIdStandardData(surfaceData.baseColor, surfaceData.specular, surfaceData.metallic, bsdfData);
FillMaterialIdAnisoData(bsdfData.roughness, surfaceData.normalWS, surfaceData.tangentWS, surfaceData.anisotropy, bsdfData);
}
else if (bsdfData.materialId == MATERIALID_LIT_SSS)
{
FillMaterialIdSSSData(surfaceData.baseColor, surfaceData.subsurfaceProfile, surfaceData.subsurfaceRadius, surfaceData.thickness, bsdfData);
}
ApplyDebugToBSDFData(bsdfData);

//-----------------------------------------------------------------------------
// conversion function for deferred
//-----------------------------------------------------------------------------
// Tetra encoding 10:10 + 2 seems equivalent to oct 11:11, as oct is cheaper use that. Let here for future testing in reflective scene for comparison
//#define USE_NORMAL_TETRAHEDRON_ENCODING
// Encode SurfaceData (BSDF parameters) into GBuffer
// Must be in sync with RT declared in HDRenderPipeline.cs ::Rebuild

// RT1 - 10:10:10:2
// We store perceptualRoughness instead of roughness because it save a sqrt ALU when decoding
// (as we want both perceptualRoughness and roughness for the lighting due to Disney Diffuse model)
#ifdef USE_NORMAL_TETRAHEDRON_ENCODING
// Encode normal on 20bit + 2bit (faceIndex) with tetrahedal compression
uint faceIndex;
float2 tetraNormalWS = PackNormalTetraEncode(surfaceData.normalWS, faceIndex);
// Store faceIndex on two bits with perceptualRoughness
outGBuffer1 = float4(tetraNormalWS * 0.5 + 0.5, PackFloatInt10bit(PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness), faceIndex, 4.0), PackMaterialId(surfaceData.materialId));
#else
// Encode normal on 20bit with oct compression + 2bit of sign
float2 octNormalWS = PackNormalOctEncode(surfaceData.normalWS);
// To have more precision encode the sign of xy in a separate uint

#endif
// Encode specular on two bit for the enum
outGBuffer2 = float4(0.0, 0.0, 0.0, PackFloatInt8bit(surfaceData.metallic, surfaceData.specular, 4.0));
}
else if (surfaceData.materialId == MATERIALID_LIT_SPECULAR)
{
outGBuffer1.a = PackMaterialId(MATERIALID_LIT_STANDARD); // We save 1bit in gbuffer1 to store it in gbuffer2 instead
// Encode specular on two bit for the enum, must match encoding of MATERIALID_LIT_STANDARD
// TODO: encoding here could be optimize as we know what is the value of surfaceData.specular
outGBuffer2 = float4(surfaceData.specularColor, PackFloatInt8bit(0.0, surfaceData.specular, 4.0));
}
else if (surfaceData.materialId == MATERIALID_LIT_ANISO)
{
outGBuffer1.a = PackMaterialId(MATERIALID_LIT_STANDARD); // We save 1bit in gbuffer1 and use aniso value instead to detect we are aniso
// TODO: store metal and specular together, specular should be an enum (fixed value)
outGBuffer2 = float4(octTangentWS * 0.5 + 0.5, surfaceData.anisotropy, surfaceData.metallic);
outGBuffer2 = float4(octTangentWS * 0.5 + 0.5, surfaceData.anisotropy, PackFloatInt8bit(surfaceData.metallic, surfaceData.specular, 4.0));
}
else if (surfaceData.materialId == MATERIALID_LIT_SPECULAR)
{
outGBuffer2 = float4(surfaceData.specularColor, 0.0);
}
// Lighting

float3 baseColor = inGBuffer0.rgb;
bsdfData.specularOcclusion = inGBuffer0.a;
#ifdef USE_NORMAL_TETRAHEDRON_ENCODING
int faceIndex;
UnpackFloatInt10bit(inGBuffer1.b, 4.0, bsdfData.perceptualRoughness, faceIndex);
bsdfData.normalWS = UnpackNormalTetraEncode(inGBuffer1.xy * 2.0 - 1.0, faceIndex);
#else
#endif
int supportsStandard = (featureFlags & (MATERIALFEATUREFLAGS_LIT_STANDARD | MATERIALFEATUREFLAGS_LIT_ANISO)) != 0;
int supportsStandard = (featureFlags & (MATERIALFEATUREFLAGS_LIT_STANDARD | MATERIALFEATUREFLAGS_LIT_ANISO | MATERIALFEATUREFLAGS_LIT_SPECULAR)) != 0;
int supportsSpecular = (featureFlags & (MATERIALFEATUREFLAGS_LIT_SPECULAR)) != 0;
if(supportsStandard + supportsSSS + supportsSpecular > 1)
if (supportsStandard + supportsSSS > 1)
{
bsdfData.materialId = UnpackMaterialId(inGBuffer1.a); // only fetch materialid if it is not statically known from feature flags
}

if(supportsStandard) bsdfData.materialId = MATERIALID_LIT_STANDARD;
else if(supportsSSS) bsdfData.materialId = MATERIALID_LIT_SSS;
else bsdfData.materialId = MATERIALID_LIT_SPECULAR;
if (supportsStandard)
bsdfData.materialId = MATERIALID_LIT_STANDARD;
else // if (supportsSSS)
bsdfData.materialId = MATERIALID_LIT_SSS;
float metallic = inGBuffer2.a;
float specular = 0.04; // TODO extract spec
float metallic;
int specular;
UnpackFloatInt8bit(inGBuffer2.a, 4.0, metallic, specular);
float3 tangentWS = UnpackNormalOctEncode(float2(inGBuffer2.rg * 2.0 - 1.0));
FillMaterialIdStandardData(baseColor, specular, metallic, bsdfData.roughness, bsdfData.normalWS, tangentWS, anisotropy, bsdfData);
if ((featureFlags & MATERIALFEATUREFLAGS_LIT_ANISO) && (featureFlags & MATERIALFEATUREFLAGS_LIT_STANDARD) == 0 || anisotropy > 0)
if (((featureFlags & MATERIALFEATUREFLAGS_LIT_SPECULAR) && (featureFlags & MATERIALFEATUREFLAGS_LIT_STANDARD) == 0)
|| specular == SPECULARVALUE_SPECULAR_COLOR)
{
bsdfData.materialId = MATERIALID_LIT_SPECULAR;
bsdfData.diffuseColor = baseColor;
bsdfData.fresnel0 = inGBuffer2.rgb;
}
else if ( ((featureFlags & MATERIALFEATUREFLAGS_LIT_ANISO) && (featureFlags & MATERIALFEATUREFLAGS_LIT_STANDARD) == 0)
|| anisotropy > 0)
float3 tangentWS = UnpackNormalOctEncode(float2(inGBuffer2.rg * 2.0 - 1.0));
FillMaterialIdAnisoData(bsdfData.roughness, bsdfData.normalWS, tangentWS, anisotropy, bsdfData);
}
else
{
FillMaterialIdStandardData(baseColor, specular, metallic, bsdfData);
else if (supportsSSS && bsdfData.materialId == MATERIALID_LIT_SSS)
else // if (supportsSSS && bsdfData.materialId == MATERIALID_LIT_SSS)
{
float subsurfaceRadius = inGBuffer2.x;
float thickness = inGBuffer2.y;

}
else if (supportsSpecular && bsdfData.materialId == MATERIALID_LIT_SPECULAR)
{
bsdfData.diffuseColor = baseColor;
bsdfData.fresnel0 = inGBuffer2.rgb;
}
bakeDiffuseLighting = inGBuffer3.rgb;

#endif
int materialId = UnpackMaterialId(inGBuffer1.a);
float anisotropy = inGBuffer2.b;
featureFlags |= (anisotropy > 0) ? MATERIALFEATUREFLAGS_LIT_ANISO : MATERIALFEATUREFLAGS_LIT_STANDARD;
float metallic;
int specular;
UnpackFloatInt8bit(inGBuffer2.a, 4.0, metallic, specular);
float anisotropy = inGBuffer2.b;
if (specular == SPECULARVALUE_SPECULAR_COLOR)
{
featureFlags |= MATERIALFEATUREFLAGS_LIT_SPECULAR;
}
else if (anisotropy > 0.0)
{
featureFlags |= MATERIALFEATUREFLAGS_LIT_ANISO;
}
else
{
featureFlags |= MATERIALFEATUREFLAGS_LIT_STANDARD;
}
else if (materialId == MATERIALID_LIT_SPECULAR)
{
featureFlags |= MATERIALFEATUREFLAGS_LIT_SPECULAR;
}
return featureFlags;
}

7
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.shader


[HideInInspector] _UVMappingMask("_UVMappingMask", Color) = (1, 0, 0, 0)
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace("NormalMap space", Float) = 0
[Enum(Subsurface Scattering, 0, Standard, 1, Specular Color, 2)] _MaterialID("MaterialId", Int) = 1 // MaterialId.RegularLighting
// Note: 2 and 3 are currently unused
[Enum(Subsurface Scattering, 0, Standard, 1, Anisotropy, 4, Specular Color, 5)] _MaterialID("MaterialId", Int) = 1 // MaterialId.RegularLighting
[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
_PPDMinSamples("Min sample for POM", Range(1.0, 64.0)) = 5

#pragma shader_feature _THICKNESSMAP
#pragma shader_feature _SPECULARCOLORMAP
#pragma shader_feature _VERTEX_WIND
// MaterialId are used as shader feature to allow compiler to optimize properly
// Note _MATID_STANDARD is not define as there is always the default case "_". We assign default as _MATID_STANDARD, so we never test _MATID_STANDARD
#pragma shader_feature _ _MATID_SSS _MATID_ANISO _MATID_SPECULAR
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED

19
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl


// This part of the code is not used in case of layered shader but we keep the same macro system for simplicity
#if !defined(LAYERED_LIT_SHADER)
// TODO: In order to let the compiler optimize in case of forward rendering this need to be a variant (shader feature) and not a parameter!
surfaceData.materialId = _MaterialID;
// Having individual shader features for each materialID like this allow the compiler to optimize
#ifdef _MATID_SSS
surfaceData.materialId = MATERIALID_LIT_SSS;
#elif defined(_MATID_ANISO)
surfaceData.materialId = MATERIALID_LIT_ANISO;
#elif defined(_MATID_SPECULAR)
surfaceData.materialId = MATERIALID_LIT_SPECULAR;
#else // Default
surfaceData.materialId = MATERIALID_LIT_STANDARD;
#endif
#ifdef _TANGENTMAP
#ifdef _NORMALMAP_TANGENT_SPACE_IDX // Normal and tangent use same space

#endif
surfaceData.anisotropy *= ADD_IDX(_Anisotropy);
surfaceData.specular = 0.04;
#ifdef _MATID_SPECULAR
// To save 1bit space in GBuffer we don't store specular as materialID but in the enum of the specular value
surfaceData.specular = SPECULARVALUE_SPECULAR_COLOR;
#else
surfaceData.specular = SPECULARVALUE_REGULAR;
#endif
surfaceData.subsurfaceProfile = _SubsurfaceProfile;
surfaceData.subsurfaceRadius = _SubsurfaceRadius;

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitProperties.hlsl


float _Anisotropy;
int _MaterialID;
int _SubsurfaceProfile;
float _SubsurfaceRadius;
float _Thickness;

正在加载...
取消
保存