312 lines
15 KiB
C#
312 lines
15 KiB
C#
using System;
|
|
using UnityEngine.Rendering.HighDefinition.Attributes;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// structure definition
|
|
//-----------------------------------------------------------------------------
|
|
namespace UnityEngine.Rendering.HighDefinition
|
|
{
|
|
class AxF : RenderPipelineMaterial
|
|
{
|
|
// Misc flags:
|
|
//
|
|
// Warning: first bits are those from the importer, make sure they match.
|
|
//
|
|
// Others are for further material customization.
|
|
// Note that contrary to the usual HDRP shaders' MaterialFeatureFlags,
|
|
// these are NOT necessarily known at static time since we haven't created
|
|
// shader features for each of them to then set eg surfaceData.materialFeatures.
|
|
// For this reason, these flags are set in the same shader property than used
|
|
// by the importer, _Flags.
|
|
// Some may become static shader_features later and thus become just UI state.
|
|
[GenerateHLSL(PackingRules.Exact)]
|
|
public enum FeatureFlags
|
|
{
|
|
AxfAnisotropy = 1 << 0,
|
|
AxfClearCoat = 1 << 1,
|
|
AxfClearCoatRefraction = 1 << 2,
|
|
AxfUseHeightMap = 1 << 3,
|
|
AxfBRDFColorDiagonalClamp = 1 << 4,
|
|
//Some TODO:
|
|
AxfHonorMinRoughness = 1 << 8,
|
|
AxfHonorMinRoughnessCoat = 1 << 9, // the X-Rite viewer never shows a specular highlight on coat for dirac lights
|
|
AxfDebugTest = 1 << 23,
|
|
//Experimental:
|
|
//
|
|
// Warning: don't go over 23, or need to use float and bitcast on the UI side, and in the shader,
|
|
// use float property/uniform and bitcast in hlsl code asuint()
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// SurfaceData
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Main structure that store the user data (i.e user input of master node in material graph)
|
|
[GenerateHLSL(PackingRules.Exact, false, false, true, 1200)]
|
|
public struct SurfaceData
|
|
{
|
|
[MaterialSharedPropertyMapping(MaterialSharedProperty.Smoothness)]
|
|
[SurfaceDataAttributes("Smoothness", precision = FieldPrecision.Real)]
|
|
public float perceptualSmoothness; // approximated for raytracing stage
|
|
|
|
[MaterialSharedPropertyMapping(MaterialSharedProperty.AmbientOcclusion)]
|
|
[SurfaceDataAttributes("Ambient Occlusion")]
|
|
public float ambientOcclusion;
|
|
|
|
[SurfaceDataAttributes("Specular Occlusion")]
|
|
public float specularOcclusion;
|
|
|
|
[MaterialSharedPropertyMapping(MaterialSharedProperty.Normal)]
|
|
[SurfaceDataAttributes(new string[] { "Normal", "Normal View Space" }, true, checkIsNormalized = true)]
|
|
public Vector3 normalWS;
|
|
|
|
[SurfaceDataAttributes("Tangent", true)]
|
|
public Vector3 tangentWS;
|
|
|
|
// SVBRDF Variables
|
|
[MaterialSharedPropertyMapping(MaterialSharedProperty.Albedo)]
|
|
[SurfaceDataAttributes("Diffuse Color", false, true)]
|
|
public Vector3 diffuseColor;
|
|
|
|
[MaterialSharedPropertyMapping(MaterialSharedProperty.Specular)]
|
|
[SurfaceDataAttributes("Specular Color", false, true)]
|
|
public Vector3 specularColor;
|
|
|
|
[SurfaceDataAttributes("Fresnel F0")]
|
|
public Vector3 fresnelF0;
|
|
|
|
[SurfaceDataAttributes("Specular Lobe")]
|
|
public Vector3 specularLobe; // .xy for SVBRDF, .xyz for CARPAINT2, for _CarPaint2_CTSpreads per lobe roughnesses
|
|
|
|
[SurfaceDataAttributes("Height")]
|
|
public float height_mm;
|
|
|
|
[SurfaceDataAttributes("Anisotropic Angle")]
|
|
public float anisotropyAngle;
|
|
|
|
// Car Paint Variables
|
|
[SurfaceDataAttributes("Flakes UV (or PlanarZY)")]
|
|
public Vector2 flakesUVZY;
|
|
[SurfaceDataAttributes("Flakes PlanarXZ")]
|
|
public Vector2 flakesUVXZ;
|
|
[SurfaceDataAttributes("Flakes PlanarXY")]
|
|
public Vector2 flakesUVXY;
|
|
|
|
[SurfaceDataAttributes("Flakes Mip (and for PlanarZY)")]
|
|
public float flakesMipLevelZY;
|
|
[SurfaceDataAttributes("Flakes Mip for PlanarXZ")]
|
|
public float flakesMipLevelXZ;
|
|
[SurfaceDataAttributes("Flakes Mip for PlanarXY")]
|
|
public float flakesMipLevelXY;
|
|
[SurfaceDataAttributes("Flakes Triplanar Weights")]
|
|
public Vector3 flakesTriplanarWeights;
|
|
|
|
// if non null, we will prefer gradients (to be used statically only!)
|
|
[SurfaceDataAttributes("Flakes ddx (and for PlanarZY)")]
|
|
public Vector2 flakesDdxZY;
|
|
[SurfaceDataAttributes("Flakes ddy (and for PlanarZY)")]
|
|
public Vector2 flakesDdyZY;
|
|
[SurfaceDataAttributes("Flakes ddx for PlanarXZ")]
|
|
public Vector2 flakesDdxXZ;
|
|
[SurfaceDataAttributes("Flakes ddy for PlanarXZ")]
|
|
public Vector2 flakesDdyXZ;
|
|
[SurfaceDataAttributes("Flakes ddx for PlanarXY")]
|
|
public Vector2 flakesDdxXY;
|
|
[SurfaceDataAttributes("Flakes ddy for PlanarXY")]
|
|
public Vector2 flakesDdyXY;
|
|
// BTF Variables
|
|
|
|
// Clearcoat
|
|
[SurfaceDataAttributes("Clearcoat Color")]
|
|
public Vector3 clearcoatColor;
|
|
|
|
[SurfaceDataAttributes("Clearcoat Normal", true)]
|
|
public Vector3 clearcoatNormalWS;
|
|
|
|
[SurfaceDataAttributes("Clearcoat IOR")]
|
|
public float clearcoatIOR;
|
|
|
|
[SurfaceDataAttributes(new string[] { "Geometric Normal", "Geometric Normal View Space" }, true, checkIsNormalized = true)]
|
|
public Vector3 geomNormalWS;
|
|
|
|
// Needed for raytracing.
|
|
// TODO: should just modify FitToStandardLit in ShaderPassRaytracingGBuffer.hlsl and callee
|
|
// to have "V" (from -incidentDir)
|
|
[SurfaceDataAttributes("View Direction", true)]
|
|
public Vector3 viewWS;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// BSDFData
|
|
//-----------------------------------------------------------------------------
|
|
|
|
[GenerateHLSL(PackingRules.Exact, false, false, true, 1250)]
|
|
public struct BSDFData
|
|
{
|
|
public float ambientOcclusion;
|
|
public float specularOcclusion;
|
|
|
|
[SurfaceDataAttributes(new string[] { "Normal WS", "Normal View Space" }, true, checkIsNormalized = true)]
|
|
public Vector3 normalWS;
|
|
[SurfaceDataAttributes("", true)]
|
|
public Vector3 tangentWS;
|
|
[SurfaceDataAttributes("", true)]
|
|
public Vector3 biTangentWS;
|
|
|
|
// SVBRDF Variables
|
|
public Vector3 diffuseColor;
|
|
public Vector3 specularColor;
|
|
public Vector3 fresnelF0;
|
|
public float perceptualRoughness; // approximated for SSAO
|
|
public Vector3 roughness; // .xy for SVBRDF, .xyz for CARPAINT2, for _CarPaint2_CTSpreads per lobe roughnesses
|
|
public float height_mm;
|
|
|
|
// Car Paint Variables
|
|
public Vector2 flakesUVZY;
|
|
public Vector2 flakesUVXZ;
|
|
public Vector2 flakesUVXY;
|
|
public float flakesMipLevelZY;
|
|
public float flakesMipLevelXZ;
|
|
public float flakesMipLevelXY;
|
|
public Vector3 flakesTriplanarWeights;
|
|
public Vector2 flakesDdxZY; // if non null, we will prefer gradients (to be used statically only!)
|
|
public Vector2 flakesDdyZY;
|
|
public Vector2 flakesDdxXZ;
|
|
public Vector2 flakesDdyXZ;
|
|
public Vector2 flakesDdxXY;
|
|
public Vector2 flakesDdyXY;
|
|
|
|
// BTF Variables
|
|
|
|
// Clearcoat
|
|
public Vector3 clearcoatColor;
|
|
[SurfaceDataAttributes("", true)]
|
|
public Vector3 clearcoatNormalWS;
|
|
public float clearcoatIOR;
|
|
|
|
[SurfaceDataAttributes(new string[] { "Geometric Normal", "Geometric Normal View Space" }, true, checkIsNormalized = true)]
|
|
public Vector3 geomNormalWS;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Init precomputed texture
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// For area lighting - We pack all texture inside a texture array to reduce the number of resource required
|
|
Texture2DArray m_LtcData; // 0: m_LtcGGXMatrix - RGBA;
|
|
|
|
Material m_preIntegratedFGDMaterial_Ward = null;
|
|
Material m_preIntegratedFGDMaterial_CookTorrance = null;
|
|
RenderTexture m_preIntegratedFGD_Ward = null;
|
|
RenderTexture m_preIntegratedFGD_CookTorrance = null;
|
|
|
|
private bool m_precomputedFGDTablesAreInit = false;
|
|
|
|
public static readonly int _PreIntegratedFGD_Ward = Shader.PropertyToID("_PreIntegratedFGD_Ward");
|
|
public static readonly int _PreIntegratedFGD_CookTorrance = Shader.PropertyToID("_PreIntegratedFGD_CookTorrance");
|
|
public static readonly int _AxFLtcData = Shader.PropertyToID("_AxFLtcData");
|
|
|
|
public AxF() {}
|
|
|
|
public override void Build(HDRenderPipelineAsset hdAsset, RenderPipelineResources defaultResources)
|
|
{
|
|
// Create Materials
|
|
m_preIntegratedFGDMaterial_Ward = CoreUtils.CreateEngineMaterial(defaultResources.shaders.preIntegratedFGD_WardPS);
|
|
if (m_preIntegratedFGDMaterial_Ward == null)
|
|
throw new Exception("Failed to create material for Ward BRDF pre-integration!");
|
|
|
|
m_preIntegratedFGDMaterial_CookTorrance = CoreUtils.CreateEngineMaterial(defaultResources.shaders.preIntegratedFGD_CookTorrancePS);
|
|
if (m_preIntegratedFGDMaterial_CookTorrance == null)
|
|
throw new Exception("Failed to create material for Cook-Torrance BRDF pre-integration!");
|
|
|
|
// Create render textures where we will render the FGD tables
|
|
m_preIntegratedFGD_Ward = new RenderTexture(128, 128, 0, RenderTextureFormat.ARGB2101010, RenderTextureReadWrite.Linear);
|
|
m_preIntegratedFGD_Ward.hideFlags = HideFlags.HideAndDontSave;
|
|
m_preIntegratedFGD_Ward.filterMode = FilterMode.Bilinear;
|
|
m_preIntegratedFGD_Ward.wrapMode = TextureWrapMode.Clamp;
|
|
m_preIntegratedFGD_Ward.hideFlags = HideFlags.DontSave;
|
|
m_preIntegratedFGD_Ward.name = CoreUtils.GetRenderTargetAutoName(128, 128, 1, RenderTextureFormat.ARGB2101010, "PreIntegratedFGD_Ward");
|
|
m_preIntegratedFGD_Ward.Create();
|
|
|
|
m_preIntegratedFGD_CookTorrance = new RenderTexture(128, 128, 0, RenderTextureFormat.ARGB2101010, RenderTextureReadWrite.Linear);
|
|
m_preIntegratedFGD_CookTorrance.hideFlags = HideFlags.HideAndDontSave;
|
|
m_preIntegratedFGD_CookTorrance.filterMode = FilterMode.Bilinear;
|
|
m_preIntegratedFGD_CookTorrance.wrapMode = TextureWrapMode.Clamp;
|
|
m_preIntegratedFGD_CookTorrance.hideFlags = HideFlags.DontSave;
|
|
m_preIntegratedFGD_CookTorrance.name = CoreUtils.GetRenderTargetAutoName(128, 128, 1, RenderTextureFormat.ARGB2101010, "PreIntegratedFGD_CookTorrance");
|
|
m_preIntegratedFGD_CookTorrance.Create();
|
|
|
|
// LTC data
|
|
|
|
m_LtcData = new Texture2DArray(LTCAreaLight.k_LtcLUTResolution, LTCAreaLight.k_LtcLUTResolution, 3, TextureFormat.RGBAHalf, false /*mipmap*/, true /* linear */)
|
|
{
|
|
hideFlags = HideFlags.HideAndDontSave,
|
|
wrapMode = TextureWrapMode.Clamp,
|
|
filterMode = FilterMode.Bilinear,
|
|
name = CoreUtils.GetTextureAutoName(LTCAreaLight.k_LtcLUTResolution, LTCAreaLight.k_LtcLUTResolution, TextureFormat.RGBAHalf, depth: 2, dim: TextureDimension.Tex2DArray, name: "LTC_LUT")
|
|
};
|
|
|
|
// Caution: This need to match order define in AxFLTCAreaLight
|
|
LTCAreaLight.LoadLUT(m_LtcData, 0, TextureFormat.RGBAHalf, LTCAreaLight.s_LtcMatrixData_GGX);
|
|
// Warning: check /Material/AxF/AxFLTCAreaLight/LtcData.GGX2.cs: 5 columns are needed, the entries are NOT normalized!
|
|
// For now, we patch for this in LoadLUT, which should affect the loading of s_LtcGGXMatrixData for the rest of the materials
|
|
// (Lit, etc.)
|
|
|
|
m_LtcData.Apply();
|
|
|
|
// TODO BugFix:
|
|
// We still bind the original data for now, see AxFLTCAreaLight.hlsl: when using a local table, results differ,
|
|
// even if we patch the non-normalization error in the 8th column when calling the LTCInvMatrix loading routine (LoadLUT).
|
|
LTCAreaLight.instance.Build();
|
|
}
|
|
|
|
public override void Cleanup()
|
|
{
|
|
CoreUtils.Destroy(m_preIntegratedFGD_CookTorrance);
|
|
CoreUtils.Destroy(m_preIntegratedFGD_Ward);
|
|
CoreUtils.Destroy(m_preIntegratedFGDMaterial_CookTorrance);
|
|
CoreUtils.Destroy(m_preIntegratedFGDMaterial_Ward);
|
|
m_preIntegratedFGD_CookTorrance = null;
|
|
m_preIntegratedFGD_Ward = null;
|
|
m_preIntegratedFGDMaterial_Ward = null;
|
|
m_preIntegratedFGDMaterial_CookTorrance = null;
|
|
m_precomputedFGDTablesAreInit = false;
|
|
|
|
// LTC data
|
|
CoreUtils.Destroy(m_LtcData);
|
|
LTCAreaLight.instance.Cleanup();
|
|
}
|
|
|
|
public override void RenderInit(CommandBuffer cmd)
|
|
{
|
|
if (m_precomputedFGDTablesAreInit || m_preIntegratedFGDMaterial_Ward == null || m_preIntegratedFGDMaterial_CookTorrance == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.PreIntegradeWardCookTorrance)))
|
|
{
|
|
CoreUtils.DrawFullScreen(cmd, m_preIntegratedFGDMaterial_Ward, new RenderTargetIdentifier(m_preIntegratedFGD_Ward));
|
|
CoreUtils.DrawFullScreen(cmd, m_preIntegratedFGDMaterial_CookTorrance, new RenderTargetIdentifier(m_preIntegratedFGD_CookTorrance));
|
|
}
|
|
|
|
m_precomputedFGDTablesAreInit = true;
|
|
}
|
|
|
|
public override void Bind(CommandBuffer cmd)
|
|
{
|
|
if (m_preIntegratedFGD_Ward == null || m_preIntegratedFGD_CookTorrance == null)
|
|
{
|
|
throw new Exception("Ward & Cook-Torrance BRDF pre-integration table not available!");
|
|
}
|
|
|
|
cmd.SetGlobalTexture(_PreIntegratedFGD_Ward, m_preIntegratedFGD_Ward);
|
|
cmd.SetGlobalTexture(_PreIntegratedFGD_CookTorrance, m_preIntegratedFGD_CookTorrance);
|
|
|
|
// LTC Data
|
|
cmd.SetGlobalTexture(_AxFLtcData, m_LtcData);
|
|
LTCAreaLight.instance.Bind(cmd);
|
|
}
|
|
}
|
|
}
|