浏览代码

Merge brnganch 'LightweightPipeline' into LW-ScreenSpaceShadows

Fetching 5x5 tent PCF
/main
John 7 年前
当前提交
3c40b17c
共有 20 个文件被更改,包括 2820 次插入3025 次删除
  1. 245
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowSampling.hlsl
  2. 110
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Data/LightweightPipelineAsset.cs
  3. 13
      ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightConstantBuffer.cs
  4. 119
      ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs
  5. 24
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl
  6. 1
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandard.shader
  7. 3
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightUnlit.shader
  8. 1
      Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Assets/CommonAssets/Cornell Box.fbx.meta
  9. 4
      Tests/GraphicsTests/RenderPipeline/LightweightPipeline/LightweightPipelineAsset.asset
  10. 3
      Tests/GraphicsTests/RenderPipeline/LightweightPipeline/LightweightPipelineAsset.asset.meta
  11. 65
      Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/LightingData.asset
  12. 2
      Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/LightingData.asset.meta
  13. 999
      Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/Lightmap-0_comp_dir.png
  14. 1001
      Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/Lightmap-0_comp_light.exr
  15. 999
      Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/Lightmap-1_comp_dir.png
  16. 1001
      Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/Lightmap-1_comp_light.exr
  17. 1
      Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/Models/Environment/Floor.fbx.meta
  18. 1001
      Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/ReflectionProbe-0.exr
  19. 244
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowSamplingTent.hlsl
  20. 9
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowSamplingTent.hlsl.meta

245
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowSampling.hlsl


// Various shadow sampling logic.
// Again two versions, one for dynamic resource indexing, one for static resource access.
// ------------------------------------------------------------------
// PCF Filtering helpers
// ------------------------------------------------------------------
// Assuming a isoceles right angled triangle of height "triangleHeight" (as drawn below).
// This function return the area of the triangle above the first texel.
//
// |\ <-- 45 degree slop isosceles right angled triangle
// | \
// ---- <-- length of this side is "triangleHeight"
// _ _ _ _ <-- texels
real SampleShadow_GetTriangleTexelArea(real triangleHeight)
{
return triangleHeight - 0.5;
}
// Assuming a isoceles triangle of 1.5 texels height and 3 texels wide lying on 4 texels.
// This function return the area of the triangle above each of those texels.
// | <-- offset from -0.5 to 0.5, 0 meaning triangle is exactly in the center
// / \ <-- 45 degree slop isosceles triangle (ie tent projected in 2D)
// / \
// _ _ _ _ <-- texels
// X Y Z W <-- result indices (in computedArea.xyzw and computedAreaUncut.xyzw)
void SampleShadow_GetTexelAreas_Tent_3x3(real offset, out real4 computedArea, out real4 computedAreaUncut)
{
// Compute the exterior areas
real offset01SquaredHalved = (offset + 0.5) * (offset + 0.5) * 0.5;
computedAreaUncut.x = computedArea.x = offset01SquaredHalved - offset;
computedAreaUncut.w = computedArea.w = offset01SquaredHalved;
// Compute the middle areas
// For Y : We find the area in Y of as if the left section of the isoceles triangle would
// intersect the axis between Y and Z (ie where offset = 0).
computedAreaUncut.y = SampleShadow_GetTriangleTexelArea(1.5 - offset);
// This area is superior to the one we are looking for if (offset < 0) thus we need to
// subtract the area of the triangle defined by (0,1.5-offset), (0,1.5+offset), (-offset,1.5).
real clampedOffsetLeft = min(offset,0);
real areaOfSmallLeftTriangle = clampedOffsetLeft * clampedOffsetLeft;
computedArea.y = computedAreaUncut.y - areaOfSmallLeftTriangle;
// We do the same for the Z but with the right part of the isoceles triangle
computedAreaUncut.z = SampleShadow_GetTriangleTexelArea(1.5 + offset);
real clampedOffsetRight = max(offset,0);
real areaOfSmallRightTriangle = clampedOffsetRight * clampedOffsetRight;
computedArea.z = computedAreaUncut.z - areaOfSmallRightTriangle;
}
// Assuming a isoceles triangle of 1.5 texels height and 3 texels wide lying on 4 texels.
// This function return the weight of each texels area relative to the full triangle area.
void SampleShadow_GetTexelWeights_Tent_3x3(real offset, out real4 computedWeight)
{
real4 dummy;
SampleShadow_GetTexelAreas_Tent_3x3(offset, computedWeight, dummy);
computedWeight *= 0.44444;//0.44 == 1/(the triangle area)
}
// Assuming a isoceles triangle of 2.5 texel height and 5 texels wide lying on 6 texels.
// This function return the weight of each texels area relative to the full triangle area.
// / \
// _ _ _ _ _ _ <-- texels
// 0 1 2 3 4 5 <-- computed area indices (in texelsWeights[])
void SampleShadow_GetTexelWeights_Tent_5x5(real offset, out real3 texelsWeightsA, out real3 texelsWeightsB)
{
// See _UnityInternalGetAreaPerTexel_3TexelTriangleFilter for details.
real4 computedArea_From3texelTriangle;
real4 computedAreaUncut_From3texelTriangle;
SampleShadow_GetTexelAreas_Tent_3x3(offset, computedArea_From3texelTriangle, computedAreaUncut_From3texelTriangle);
// Triangle slope is 45 degree thus we can almost reuse the result of the 3 texel wide computation.
// the 5 texel wide triangle can be seen as the 3 texel wide one but shifted up by one unit/texel.
// 0.16 is 1/(the triangle area)
texelsWeightsA.x = 0.16 * (computedArea_From3texelTriangle.x);
texelsWeightsA.y = 0.16 * (computedAreaUncut_From3texelTriangle.y);
texelsWeightsA.z = 0.16 * (computedArea_From3texelTriangle.y + 1);
texelsWeightsB.x = 0.16 * (computedArea_From3texelTriangle.z + 1);
texelsWeightsB.y = 0.16 * (computedAreaUncut_From3texelTriangle.z);
texelsWeightsB.z = 0.16 * (computedArea_From3texelTriangle.w);
}
// Assuming a isoceles triangle of 3.5 texel height and 7 texels wide lying on 8 texels.
// This function return the weight of each texels area relative to the full triangle area.
// / \
// _ _ _ _ _ _ _ _ <-- texels
// 0 1 2 3 4 5 6 7 <-- computed area indices (in texelsWeights[])
void SampleShadow_GetTexelWeights_Tent_7x7(real offset, out real4 texelsWeightsA, out real4 texelsWeightsB)
{
// See _UnityInternalGetAreaPerTexel_3TexelTriangleFilter for details.
real4 computedArea_From3texelTriangle;
real4 computedAreaUncut_From3texelTriangle;
SampleShadow_GetTexelAreas_Tent_3x3(offset, computedArea_From3texelTriangle, computedAreaUncut_From3texelTriangle);
// Triangle slope is 45 degree thus we can almost reuse the result of the 3 texel wide computation.
// the 7 texel wide triangle can be seen as the 3 texel wide one but shifted up by two unit/texel.
// 0.081632 is 1/(the triangle area)
texelsWeightsA.x = 0.081632 * (computedArea_From3texelTriangle.x);
texelsWeightsA.y = 0.081632 * (computedAreaUncut_From3texelTriangle.y);
texelsWeightsA.z = 0.081632 * (computedAreaUncut_From3texelTriangle.y + 1);
texelsWeightsA.w = 0.081632 * (computedArea_From3texelTriangle.y + 2);
texelsWeightsB.x = 0.081632 * (computedArea_From3texelTriangle.z + 2);
texelsWeightsB.y = 0.081632 * (computedAreaUncut_From3texelTriangle.z + 1);
texelsWeightsB.z = 0.081632 * (computedAreaUncut_From3texelTriangle.z);
texelsWeightsB.w = 0.081632 * (computedArea_From3texelTriangle.w);
}
// 3x3 Tent filter (45 degree sloped triangles in U and V)
void SampleShadow_ComputeSamples_Tent_3x3(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[4], out real2 fetchesUV[4])
{
// tent base is 3x3 base thus covering from 9 to 12 texels, thus we need 4 bilinear PCF fetches
real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
// find the weight of each texel based
real4 texelsWeightsU, texelsWeightsV;
SampleShadow_GetTexelWeights_Tent_3x3(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU);
SampleShadow_GetTexelWeights_Tent_3x3(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV);
// each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels
real2 fetchesWeightsU = texelsWeightsU.xz + texelsWeightsU.yw;
real2 fetchesWeightsV = texelsWeightsV.xz + texelsWeightsV.yw;
// move the PCF bilinear fetches to respect texels weights
real2 fetchesOffsetsU = texelsWeightsU.yw / fetchesWeightsU.xy + real2(-1.5,0.5);
real2 fetchesOffsetsV = texelsWeightsV.yw / fetchesWeightsV.xy + real2(-1.5,0.5);
fetchesOffsetsU *= shadowMapTexture_TexelSize.xx;
fetchesOffsetsV *= shadowMapTexture_TexelSize.yy;
real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;
fetchesWeights[2] = fetchesWeightsU.x * fetchesWeightsV.y;
fetchesWeights[3] = fetchesWeightsU.y * fetchesWeightsV.y;
}
// 5x5 Tent filter (45 degree sloped triangles in U and V)
void SampleShadow_ComputeSamples_Tent_5x5(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[9], out real2 fetchesUV[9])
{
// tent base is 5x5 base thus covering from 25 to 36 texels, thus we need 9 bilinear PCF fetches
real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
// find the weight of each texel based on the area of a 45 degree slop tent above each of them.
real3 texelsWeightsU_A, texelsWeightsU_B;
real3 texelsWeightsV_A, texelsWeightsV_B;
SampleShadow_GetTexelWeights_Tent_5x5(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU_A, texelsWeightsU_B);
SampleShadow_GetTexelWeights_Tent_5x5(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV_A, texelsWeightsV_B);
// each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels
real3 fetchesWeightsU = real3(texelsWeightsU_A.xz, texelsWeightsU_B.y) + real3(texelsWeightsU_A.y, texelsWeightsU_B.xz);
real3 fetchesWeightsV = real3(texelsWeightsV_A.xz, texelsWeightsV_B.y) + real3(texelsWeightsV_A.y, texelsWeightsV_B.xz);
// move the PCF bilinear fetches to respect texels weights
real3 fetchesOffsetsU = real3(texelsWeightsU_A.y, texelsWeightsU_B.xz) / fetchesWeightsU.xyz + real3(-2.5,-0.5,1.5);
real3 fetchesOffsetsV = real3(texelsWeightsV_A.y, texelsWeightsV_B.xz) / fetchesWeightsV.xyz + real3(-2.5,-0.5,1.5);
fetchesOffsetsU *= shadowMapTexture_TexelSize.xxx;
fetchesOffsetsV *= shadowMapTexture_TexelSize.yyy;
real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.x);
fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[4] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesUV[5] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.y);
fetchesUV[6] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.z);
fetchesUV[7] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.z);
fetchesUV[8] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.z);
fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;
fetchesWeights[2] = fetchesWeightsU.z * fetchesWeightsV.x;
fetchesWeights[3] = fetchesWeightsU.x * fetchesWeightsV.y;
fetchesWeights[4] = fetchesWeightsU.y * fetchesWeightsV.y;
fetchesWeights[5] = fetchesWeightsU.z * fetchesWeightsV.y;
fetchesWeights[6] = fetchesWeightsU.x * fetchesWeightsV.z;
fetchesWeights[7] = fetchesWeightsU.y * fetchesWeightsV.z;
fetchesWeights[8] = fetchesWeightsU.z * fetchesWeightsV.z;
}
// 7x7 Tent filter (45 degree sloped triangles in U and V)
void SampleShadow_ComputeSamples_Tent_7x7(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[16], out real2 fetchesUV[16])
{
// tent base is 7x7 base thus covering from 49 to 64 texels, thus we need 16 bilinear PCF fetches
real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
// find the weight of each texel based on the area of a 45 degree slop tent above each of them.
real4 texelsWeightsU_A, texelsWeightsU_B;
real4 texelsWeightsV_A, texelsWeightsV_B;
SampleShadow_GetTexelWeights_Tent_7x7(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU_A, texelsWeightsU_B);
SampleShadow_GetTexelWeights_Tent_7x7(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV_A, texelsWeightsV_B);
// each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels
real4 fetchesWeightsU = real4(texelsWeightsU_A.xz, texelsWeightsU_B.xz) + real4(texelsWeightsU_A.yw, texelsWeightsU_B.yw);
real4 fetchesWeightsV = real4(texelsWeightsV_A.xz, texelsWeightsV_B.xz) + real4(texelsWeightsV_A.yw, texelsWeightsV_B.yw);
// move the PCF bilinear fetches to respect texels weights
real4 fetchesOffsetsU = real4(texelsWeightsU_A.yw, texelsWeightsU_B.yw) / fetchesWeightsU.xyzw + real4(-3.5,-1.5,0.5,2.5);
real4 fetchesOffsetsV = real4(texelsWeightsV_A.yw, texelsWeightsV_B.yw) / fetchesWeightsV.xyzw + real4(-3.5,-1.5,0.5,2.5);
fetchesOffsetsU *= shadowMapTexture_TexelSize.xxxx;
fetchesOffsetsV *= shadowMapTexture_TexelSize.yyyy;
real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.x);
fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.x);
fetchesUV[4] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[5] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesUV[6] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.y);
fetchesUV[7] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.y);
fetchesUV[8] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.z);
fetchesUV[9] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.z);
fetchesUV[10] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.z);
fetchesUV[11] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.z);
fetchesUV[12] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.w);
fetchesUV[13] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.w);
fetchesUV[14] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.w);
fetchesUV[15] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.w);
fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;
fetchesWeights[2] = fetchesWeightsU.z * fetchesWeightsV.x;
fetchesWeights[3] = fetchesWeightsU.w * fetchesWeightsV.x;
fetchesWeights[4] = fetchesWeightsU.x * fetchesWeightsV.y;
fetchesWeights[5] = fetchesWeightsU.y * fetchesWeightsV.y;
fetchesWeights[6] = fetchesWeightsU.z * fetchesWeightsV.y;
fetchesWeights[7] = fetchesWeightsU.w * fetchesWeightsV.y;
fetchesWeights[8] = fetchesWeightsU.x * fetchesWeightsV.z;
fetchesWeights[9] = fetchesWeightsU.y * fetchesWeightsV.z;
fetchesWeights[10] = fetchesWeightsU.z * fetchesWeightsV.z;
fetchesWeights[11] = fetchesWeightsU.w * fetchesWeightsV.z;
fetchesWeights[12] = fetchesWeightsU.x * fetchesWeightsV.w;
fetchesWeights[13] = fetchesWeightsU.y * fetchesWeightsV.w;
fetchesWeights[14] = fetchesWeightsU.z * fetchesWeightsV.w;
fetchesWeights[15] = fetchesWeightsU.w * fetchesWeightsV.w;
}
#include "CoreRP/ShaderLibrary/Shadow/ShadowSamplingTent.hlsl"
// ------------------------------------------------------------------
// PCF Filtering methods

110
ScriptableRenderPipeline/LightweightPipeline/LWRP/Data/LightweightPipelineAsset.cs


_8x = 8
}
public enum DefaultMaterialType
{
Standard = 0,
Particle,
Terrain,
UnityBuiltinDefault
}
private Shader m_DefaultShader;
[SerializeField] private float kAssetVersion = 1.0f;
[SerializeField] private int kAssetVersion = 2;
[SerializeField] private int m_MaxPixelLights = 4;
[SerializeField] private bool m_SupportsVertexLight = false;
[SerializeField] private bool m_RequireDepthTexture = false;

[SerializeField] private Vector3 m_Cascade4Split = new Vector3(0.067f, 0.2f, 0.467f);
// Resources
[SerializeField] private Shader m_DefaultShader;
[SerializeField] private LightweightPipelineResource m_ResourceAsset;
private LightweightPipelineResource m_ResourceAsset;
[MenuItem("Assets/Create/Render Pipeline/Lightweight/Pipeline Asset", priority = CoreUtils.assetCreateMenuPriority1)]
static void CreateLightweightPipeline()

public override void Action(int instanceId, string pathName, string resourceFile)
{
var instance = CreateInstance<LightweightPipelineAsset>();
string[] guids = AssetDatabase.FindAssets("LightweightPipelineResource t:scriptableobject", m_SearchPaths);
LightweightPipelineResource resourceAsset = null;
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
resourceAsset = AssetDatabase.LoadAssetAtPath<LightweightPipelineResource>(path);
if (resourceAsset != null)
break;
}
// There's currently an issue that prevents FindAssets from find resources withing the package folder.
if (resourceAsset == null)
{
string path = m_SearchPaths[PACKAGE_MANAGER_PATH_INDEX] + "/LWRP/Data/LightweightPipelineResource.asset";
resourceAsset = AssetDatabase.LoadAssetAtPath<LightweightPipelineResource>(path);
}
instance.m_ResourceAsset = resourceAsset;
instance.m_DefaultShader = Shader.Find(LightweightShaderUtils.GetShaderPath(ShaderPathID.STANDARD_PBS));
instance.m_BlitShader = Shader.Find(LightweightShaderUtils.GetShaderPath(ShaderPathID.HIDDEN_BLIT));
instance.m_CopyDepthShader = Shader.Find(LightweightShaderUtils.GetShaderPath(ShaderPathID.HIDDEN_DEPTH_COPY));

private void LoadResourceFile()
{
string[] guids = AssetDatabase.FindAssets("LightweightPipelineResource t:scriptableobject", m_SearchPaths);
LightweightPipelineResource resourceAsset = null;
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
m_ResourceAsset = AssetDatabase.LoadAssetAtPath<LightweightPipelineResource>(path);
if (m_ResourceAsset != null)
break;
}
// There's currently an issue that prevents FindAssets from find resources withing the package folder.
if (m_ResourceAsset == null)
{
string path = m_SearchPaths[PACKAGE_MANAGER_PATH_INDEX] + "/LWRP/Data/LightweightPipelineResource.asset";
m_ResourceAsset = AssetDatabase.LoadAssetAtPath<LightweightPipelineResource>(path);
}
}
#endif
protected override IRenderPipeline InternalCreatePipeline()

DestroyCreatedInstances();
}
private Material GetMaterial(DefaultMaterialType materialType)
{
#if UNITY_EDITOR
if (m_ResourceAsset == null)
LoadResourceFile();
switch (materialType)
{
case DefaultMaterialType.Standard:
return m_ResourceAsset.DefaultMaterial;
case DefaultMaterialType.Particle:
return m_ResourceAsset.DefaultParticleMaterial;
case DefaultMaterialType.Terrain:
return m_ResourceAsset.DefaultTerrainMaterial;
// Unity Builtin Default
default:
return null;
}
#else
return null;
#endif
}
public bool AreShadowsEnabled()
{
return ShadowSetting != ShadowType.NO_SHADOW;

public override Material GetDefaultMaterial()
{
#if UNITY_EDITOR
if (m_ResourceAsset != null)
return m_ResourceAsset.DefaultMaterial;
#endif
return null;
return GetMaterial(DefaultMaterialType.Standard);
#if UNITY_EDITOR
if (m_ResourceAsset != null)
return m_ResourceAsset.DefaultParticleMaterial;
#endif
return null;
return GetMaterial(DefaultMaterialType.Particle);
return null;
return GetMaterial(DefaultMaterialType.UnityBuiltinDefault);
#if UNITY_EDITOR
if (m_ResourceAsset != null)
return m_ResourceAsset.DefaultTerrainMaterial;
#endif
return null;
return GetMaterial(DefaultMaterialType.Terrain);
return null;
return GetMaterial(DefaultMaterialType.UnityBuiltinDefault);
return null;
return GetMaterial(DefaultMaterialType.UnityBuiltinDefault);
return null;
return GetMaterial(DefaultMaterialType.UnityBuiltinDefault);
return null;
return GetMaterial(DefaultMaterialType.UnityBuiltinDefault);
if (m_DefaultShader == null)
m_DefaultShader = Shader.Find(LightweightShaderUtils.GetShaderPath(ShaderPathID.STANDARD_PBS));
return m_DefaultShader;
}

13
ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightConstantBuffer.cs


public static int _AdditionalLightSpotDir;
public static int _AdditionalLightSpotAttenuation;
}
public static class ShadowConstantBuffer
{
public static int _WorldToShadow;
public static int _ShadowData;
public static int _DirShadowSplitSpheres;
public static int _DirShadowSplitSphereRadii;
public static int _ShadowOffset0;
public static int _ShadowOffset1;
public static int _ShadowOffset2;
public static int _ShadowOffset3;
public static int _ShadowmapSize;
}
}

119
ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs


private bool m_IsOffscreenCamera;
private Vector4 kDefaultLightPosition = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
private Vector4 kDefaultLightColor = Color.black;
private Vector4 kDefaultLightAttenuation = new Vector4(0.0f, 1.0f, 0.0f, 1.0f);
private Vector4 kDefaultLightSpotDirection = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
private Vector4 kDefaultLightSpotAttenuation = new Vector4(0.0f, 1.0f, 0.0f, 0.0f);
private Vector4[] m_LightPositions = new Vector4[kMaxVisibleLights];
private Vector4[] m_LightColors = new Vector4[kMaxVisibleLights];
private Vector4[] m_LightDistanceAttenuations = new Vector4[kMaxVisibleLights];

PerCameraBuffer._AdditionalLightDistanceAttenuation = Shader.PropertyToID("_AdditionalLightDistanceAttenuation");
PerCameraBuffer._AdditionalLightSpotDir = Shader.PropertyToID("_AdditionalLightSpotDir");
PerCameraBuffer._AdditionalLightSpotAttenuation = Shader.PropertyToID("_AdditionalLightSpotAttenuation");
ShadowConstantBuffer._WorldToShadow = Shader.PropertyToID("_WorldToShadow");
ShadowConstantBuffer._ShadowData = Shader.PropertyToID("_ShadowData");
ShadowConstantBuffer._DirShadowSplitSpheres = Shader.PropertyToID("_DirShadowSplitSpheres");
ShadowConstantBuffer._DirShadowSplitSphereRadii = Shader.PropertyToID("_DirShadowSplitSphereRadii");
ShadowConstantBuffer._ShadowOffset0 = Shader.PropertyToID("_ShadowOffset0");
ShadowConstantBuffer._ShadowOffset1 = Shader.PropertyToID("_ShadowOffset1");
ShadowConstantBuffer._ShadowOffset2 = Shader.PropertyToID("_ShadowOffset2");
ShadowConstantBuffer._ShadowOffset3 = Shader.PropertyToID("_ShadowOffset3");
ShadowConstantBuffer._ShadowmapSize = Shader.PropertyToID("_ShadowmapSize");
m_ShadowMapRTID = Shader.PropertyToID("_ShadowMap");
m_ScreenSpaceShadowMapRTID = Shader.PropertyToID("_ScreenSpaceShadowMap");

// If we have a main light we don't shade it in the per-object light loop. We also remove it from the per-object cull list
int mainLightPresent = (lightData.mainLightIndex >= 0) ? 1 : 0;
int additionalPixelLightsCount = visibleLightsCount - mainLightPresent;
int vertexLightCount = (m_Asset.SupportsVertexLight) ? Math.Min(visibleLights.Count, kMaxPerObjectLights) - additionalPixelLightsCount : 0;
int vertexLightCount = (m_Asset.SupportsVertexLight) ? Math.Min(visibleLights.Count, kMaxPerObjectLights) - additionalPixelLightsCount - mainLightPresent : 0;
vertexLightCount = Math.Min(vertexLightCount, kMaxVertexLights);
lightData.pixelAdditionalLightsCount = additionalPixelLightsCount;

private void InitializeLightConstants(List<VisibleLight> lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightDistanceAttenuation, out Vector4 lightSpotDir,
out Vector4 lightSpotAttenuation)
{
float directContributionNotBaked = 1.0f;
lightPos = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
lightColor = Color.black;
lightDistanceAttenuation = new Vector4(0.0f, 1.0f, 0.0f, directContributionNotBaked);
lightSpotDir = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
lightSpotAttenuation = new Vector4(0.0f, 1.0f, 0.0f, 0.0f);
lightPos = kDefaultLightPosition;
lightColor = kDefaultLightColor;
lightDistanceAttenuation = kDefaultLightSpotAttenuation;
lightSpotDir = kDefaultLightSpotDirection;
lightSpotAttenuation = kDefaultLightAttenuation;
// When no lights are visible, main light will be set to -1.
// In this case we initialize it to default values and return

float oneOverFadeRangeSqr = 1.0f / fadeRangeSqr;
float lightRangeSqrOverFadeRangeSqr = -lightRangeSqr / fadeRangeSqr;
float quadAtten = 25.0f / lightRangeSqr;
lightDistanceAttenuation = new Vector4(quadAtten, oneOverFadeRangeSqr, lightRangeSqrOverFadeRangeSqr, directContributionNotBaked);
lightDistanceAttenuation = new Vector4(quadAtten, oneOverFadeRangeSqr, lightRangeSqrOverFadeRangeSqr, 1.0f);
}
if (lightData.lightType == LightType.Spot)

if (lightData.shadowMapSampleType != LightShadows.None)
SetupShadowReceiverConstants(cmd, lights[lightData.mainLightIndex]);
if (lightData.totalAdditionalLightsCount > 0)
SetupAdditionalListConstants(cmd, lights, ref lightData);
SetupAdditionalListConstants(cmd, lights, ref lightData);
}
private void SetupMainLightConstants(CommandBuffer cmd, List<VisibleLight> lights, int lightIndex)

{
int additionalLightIndex = 0;
// We need to update per-object light list with the proper map to our global additional light buffer
// First we initialize all lights in the map to -1 to tell the system to discard main light index and
// remaining lights in the scene that don't fit the max additional light buffer (kMaxVisibileAdditionalLights)
int[] perObjectLightIndexMap = m_CullResults.GetLightIndexMap();
for (int i = 0; i < lights.Count; ++i)
perObjectLightIndexMap[i] = -1;
for (int i = 0; i < lights.Count && additionalLightIndex < kMaxVisibleLights; ++i)
if (lightData.totalAdditionalLightsCount > 0)
if (i != lightData.mainLightIndex)
// We need to update per-object light list with the proper map to our global additional light buffer
// First we initialize all lights in the map to -1 to tell the system to discard main light index and
// remaining lights in the scene that don't fit the max additional light buffer (kMaxVisibileAdditionalLights)
int[] perObjectLightIndexMap = m_CullResults.GetLightIndexMap();
for (int i = 0; i < lights.Count; ++i)
perObjectLightIndexMap[i] = -1;
for (int i = 0; i < lights.Count && additionalLightIndex < kMaxVisibleLights; ++i)
// The engine performs per-object light culling and initialize 8 light indices into two vec4 constants unity_4LightIndices0 and unity_4LightIndices1.
// In the shader we iterate over each visible light using the indices provided in these constants to index our global light buffer
// ex: first light position would be m_LightPosisitions[unity_4LightIndices[0]];
if (i != lightData.mainLightIndex)
{
// The engine performs per-object light culling and initialize 8 light indices into two vec4 constants unity_4LightIndices0 and unity_4LightIndices1.
// In the shader we iterate over each visible light using the indices provided in these constants to index our global light buffer
// ex: first light position would be m_LightPosisitions[unity_4LightIndices[0]];
// However since we sorted the lights we need to tell the engine how to map the original/unsorted indices to our global buffer
// We do it by settings the perObjectLightIndexMap to the appropriate additionalLightIndex.
perObjectLightIndexMap[GetLightUnsortedIndex(i)] = additionalLightIndex;
InitializeLightConstants(lights, i, out m_LightPositions[additionalLightIndex],
out m_LightColors[additionalLightIndex],
out m_LightDistanceAttenuations[additionalLightIndex],
out m_LightSpotDirections[additionalLightIndex],
out m_LightSpotAttenuations[additionalLightIndex]);
additionalLightIndex++;
// However since we sorted the lights we need to tell the engine how to map the original/unsorted indices to our global buffer
// We do it by settings the perObjectLightIndexMap to the appropriate additionalLightIndex.
perObjectLightIndexMap[GetLightUnsortedIndex(i)] = additionalLightIndex;
InitializeLightConstants(lights, i, out m_LightPositions[additionalLightIndex],
out m_LightColors[additionalLightIndex],
out m_LightDistanceAttenuations[additionalLightIndex],
out m_LightSpotDirections[additionalLightIndex],
out m_LightSpotAttenuations[additionalLightIndex]);
additionalLightIndex++;
}
m_CullResults.SetLightIndexMap(perObjectLightIndexMap);
cmd.SetGlobalVector(PerCameraBuffer._AdditionalLightCount, new Vector4(lightData.pixelAdditionalLightsCount,
lightData.totalAdditionalLightsCount, 0.0f, 0.0f));
m_CullResults.SetLightIndexMap(perObjectLightIndexMap);
else
{
cmd.SetGlobalVector(PerCameraBuffer._AdditionalLightCount, Vector4.zero);
// Clear to default all light cosntant data
for (int i = 0; i < kMaxVisibleLights; ++i)
InitializeLightConstants(lights, -1, out m_LightPositions[additionalLightIndex],
out m_LightColors[additionalLightIndex],
out m_LightDistanceAttenuations[additionalLightIndex],
out m_LightSpotDirections[additionalLightIndex],
out m_LightSpotAttenuations[additionalLightIndex]);
}
cmd.SetGlobalVector(PerCameraBuffer._AdditionalLightCount, new Vector4(lightData.pixelAdditionalLightsCount,
lightData.totalAdditionalLightsCount, 0.0f, 0.0f));
cmd.SetGlobalVectorArray(PerCameraBuffer._AdditionalLightPosition, m_LightPositions);
cmd.SetGlobalVectorArray(PerCameraBuffer._AdditionalLightColor, m_LightColors);
cmd.SetGlobalVectorArray(PerCameraBuffer._AdditionalLightDistanceAttenuation, m_LightDistanceAttenuations);

private void SetupShadowReceiverConstants(CommandBuffer cmd, VisibleLight shadowLight)
{
Light light = shadowLight.light;
float shadowResolution = m_ShadowSlices[0].shadowResolution;
int cascadeCount = m_ShadowCasterCascadesCount;
for (int i = 0; i < kMaxCascades; ++i)

noOpShadowMatrix.m33 = (SystemInfo.usesReversedZBuffer) ? 1.0f : 0.0f;
m_ShadowMatrices[kMaxCascades] = noOpShadowMatrix;
float invShadowResolution = 0.5f / shadowResolution;
cmd.SetGlobalMatrixArray("_WorldToShadow", m_ShadowMatrices);
cmd.SetGlobalVector("_ShadowData", new Vector4(light.shadowStrength, 0.0f, 0.0f, 0.0f));
cmd.SetGlobalVectorArray("_DirShadowSplitSpheres", m_DirectionalShadowSplitDistances);
cmd.SetGlobalVector("_DirShadowSplitSphereRadii", m_DirectionalShadowSplitRadii);
cmd.SetGlobalVector("_ShadowOffset0", new Vector4(-invShadowResolution, -invShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector("_ShadowOffset1", new Vector4(invShadowResolution, -invShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector("_ShadowOffset2", new Vector4(-invShadowResolution, invShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector("_ShadowOffset3", new Vector4(invShadowResolution, invShadowResolution, 0.0f, 0.0f));
float invShadowResolution = 1.0f / m_Asset.ShadowAtlasResolution;
float invHalfShadowResolution = 0.5f * invShadowResolution;
cmd.SetGlobalMatrixArray(ShadowConstantBuffer._WorldToShadow, m_ShadowMatrices);
cmd.SetGlobalVector(ShadowConstantBuffer._ShadowData, new Vector4(light.shadowStrength, 0.0f, 0.0f, 0.0f));
cmd.SetGlobalVectorArray(ShadowConstantBuffer._DirShadowSplitSpheres, m_DirectionalShadowSplitDistances);
cmd.SetGlobalVector(ShadowConstantBuffer._DirShadowSplitSphereRadii, m_DirectionalShadowSplitRadii);
cmd.SetGlobalVector(ShadowConstantBuffer._ShadowOffset0, new Vector4(-invHalfShadowResolution, -invHalfShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector(ShadowConstantBuffer._ShadowOffset1, new Vector4( invHalfShadowResolution, -invHalfShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector(ShadowConstantBuffer._ShadowOffset2, new Vector4(-invHalfShadowResolution, invHalfShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector(ShadowConstantBuffer._ShadowOffset3, new Vector4( invHalfShadowResolution, invHalfShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector(ShadowConstantBuffer._ShadowmapSize, new Vector4(invShadowResolution, invShadowResolution, m_Asset.ShadowAtlasResolution, m_Asset.ShadowAtlasResolution));
}
private void SetShaderKeywords(CommandBuffer cmd, ref LightData lightData, List<VisibleLight> visibleLights)

24
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl


#define LIGHTWEIGHT_SHADOWS_INCLUDED
#include "CoreRP/ShaderLibrary/Common.hlsl"
#include "CoreRP/ShaderLibrary/Shadow/ShadowSamplingTent.hlsl"
#define MAX_SHADOW_CASCADES 4

half4 _ShadowOffset2;
half4 _ShadowOffset3;
half4 _ShadowData; // (x: shadowStrength)
half4 _ShadowmapSize; // (xy: width and height, zw: 1/width and 1/height)
CBUFFER_END
inline half SampleShadowmap(float4 shadowCoord)

#endif
half attenuation;
#ifdef SHADER_API_MOBILE
// 4-tap hardware comparison
half4 attenuation4;
attenuation4.x = SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, shadowCoord.xyz + _ShadowOffset0.xyz);

half attenuation = dot(attenuation4, 0.25);
attenuation = dot(attenuation4, 0.25);
#else
real fetchesWeights[9];
real2 fetchesUV[9];
SampleShadow_ComputeSamples_Tent_5x5(_ShadowmapSize, shadowCoord.xy, fetchesWeights, fetchesUV);
attenuation = fetchesWeights[0] * SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, real3(fetchesUV[0].xy, shadowCoord.z));
attenuation += fetchesWeights[1] * SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, real3(fetchesUV[1].xy, shadowCoord.z));
attenuation += fetchesWeights[2] * SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, real3(fetchesUV[2].xy, shadowCoord.z));
attenuation += fetchesWeights[3] * SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, real3(fetchesUV[3].xy, shadowCoord.z));
attenuation += fetchesWeights[4] * SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, real3(fetchesUV[4].xy, shadowCoord.z));
attenuation += fetchesWeights[5] * SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, real3(fetchesUV[5].xy, shadowCoord.z));
attenuation += fetchesWeights[6] * SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, real3(fetchesUV[6].xy, shadowCoord.z));
attenuation += fetchesWeights[7] * SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, real3(fetchesUV[7].xy, shadowCoord.z));
attenuation += fetchesWeights[8] * SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, real3(fetchesUV[8].xy, shadowCoord.z));
#endif
half attenuation = SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, shadowCoord.xyz);
attenuation = SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, shadowCoord.xyz);
#endif
// Apply shadow strength

1
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandard.shader


#pragma vertex LightweightVertexMeta
#pragma fragment LightweightFragmentMeta
#pragma shader_feature _SPECULAR_SETUP
#pragma shader_feature _EMISSION
#pragma shader_feature _METALLICSPECGLOSSMAP
#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A

3
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightUnlit.shader


}
SubShader
{
Tags { "RenderType" = "Opaque" "IgnoreProjectors" = "True" "RenderPipeline" = "LightweightPipe" }
Tags { "RenderType" = "Opaque" "IgnoreProjectors" = "True" "RenderPipeline" = "LightweightPipeline" }
LOD 100
Blend [_SrcBlend][_DstBlend]

ENDHLSL
}
}
FallBack "Hidden/InternalErrorShader"
CustomEditor "LightweightUnlitGUI"
}

1
Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Assets/CommonAssets/Cornell Box.fbx.meta


2186277476908879412: ImportLogs
2186277476908879414: ImportLogs
2186277476908879416: ImportLogs
2186277476908879418: ImportLogs
externalObjects:
- first:
type: UnityEngine:Material

4
Tests/GraphicsTests/RenderPipeline/LightweightPipeline/LightweightPipelineAsset.asset


m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3}
m_Name: LightweightPipelineAsset
m_EditorClassIdentifier:
kAssetVersion: 1
kAssetVersion: 2
m_MaxPixelLights: 4
m_SupportsVertexLight: 0
m_RequireDepthTexture: 0

m_ShadowCascades: 2
m_Cascade2Split: 0.25
m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467}
m_DefaultShader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_ResourceAsset: {fileID: 11400000, guid: c8afc0a27fb8c0b4da18151c689a1082, type: 2}

3
Tests/GraphicsTests/RenderPipeline/LightweightPipeline/LightweightPipelineAsset.asset.meta


fileFormatVersion: 2
guid: e6987eea1dd29074597d54ed91a54a26
timeCreated: 1489068733
licenseType: Pro
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:

65
Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/LightingData.asset
文件差异内容过多而无法显示
查看文件

2
Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/LightingData.asset.meta


fileFormatVersion: 2
guid: c1e3921e553ae4bdea5bd3521abb96e2
timeCreated: 1509632247
licenseType: Pro
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 25800000

999
Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/Lightmap-0_comp_dir.png
文件差异内容过多而无法显示
查看文件

1001
Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/Lightmap-0_comp_light.exr
文件差异内容过多而无法显示
查看文件

999
Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/Lightmap-1_comp_dir.png
文件差异内容过多而无法显示
查看文件

1001
Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/Lightmap-1_comp_light.exr
文件差异内容过多而无法显示
查看文件

1
Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/Models/Environment/Floor.fbx.meta


2186277476908879412: ImportLogs
2186277476908879414: ImportLogs
2186277476908879416: ImportLogs
2186277476908879418: ImportLogs
externalObjects:
- first:
type: UnityEngine:Material

1001
Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/040_UpgradeScene/ReflectionProbe-0.exr
文件差异内容过多而无法显示
查看文件

244
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowSamplingTent.hlsl


// ------------------------------------------------------------------
// PCF Filtering Tent Functions
// ------------------------------------------------------------------
// Assuming a isoceles right angled triangle of height "triangleHeight" (as drawn below).
// This function return the area of the triangle above the first texel.
//
// |\ <-- 45 degree slop isosceles right angled triangle
// | \
// ---- <-- length of this side is "triangleHeight"
// _ _ _ _ <-- texels
real SampleShadow_GetTriangleTexelArea(real triangleHeight)
{
return triangleHeight - 0.5;
}
// Assuming a isoceles triangle of 1.5 texels height and 3 texels wide lying on 4 texels.
// This function return the area of the triangle above each of those texels.
// | <-- offset from -0.5 to 0.5, 0 meaning triangle is exactly in the center
// / \ <-- 45 degree slop isosceles triangle (ie tent projected in 2D)
// / \
// _ _ _ _ <-- texels
// X Y Z W <-- result indices (in computedArea.xyzw and computedAreaUncut.xyzw)
void SampleShadow_GetTexelAreas_Tent_3x3(real offset, out real4 computedArea, out real4 computedAreaUncut)
{
// Compute the exterior areas
real offset01SquaredHalved = (offset + 0.5) * (offset + 0.5) * 0.5;
computedAreaUncut.x = computedArea.x = offset01SquaredHalved - offset;
computedAreaUncut.w = computedArea.w = offset01SquaredHalved;
// Compute the middle areas
// For Y : We find the area in Y of as if the left section of the isoceles triangle would
// intersect the axis between Y and Z (ie where offset = 0).
computedAreaUncut.y = SampleShadow_GetTriangleTexelArea(1.5 - offset);
// This area is superior to the one we are looking for if (offset < 0) thus we need to
// subtract the area of the triangle defined by (0,1.5-offset), (0,1.5+offset), (-offset,1.5).
real clampedOffsetLeft = min(offset,0);
real areaOfSmallLeftTriangle = clampedOffsetLeft * clampedOffsetLeft;
computedArea.y = computedAreaUncut.y - areaOfSmallLeftTriangle;
// We do the same for the Z but with the right part of the isoceles triangle
computedAreaUncut.z = SampleShadow_GetTriangleTexelArea(1.5 + offset);
real clampedOffsetRight = max(offset,0);
real areaOfSmallRightTriangle = clampedOffsetRight * clampedOffsetRight;
computedArea.z = computedAreaUncut.z - areaOfSmallRightTriangle;
}
// Assuming a isoceles triangle of 1.5 texels height and 3 texels wide lying on 4 texels.
// This function return the weight of each texels area relative to the full triangle area.
void SampleShadow_GetTexelWeights_Tent_3x3(real offset, out real4 computedWeight)
{
real4 dummy;
SampleShadow_GetTexelAreas_Tent_3x3(offset, computedWeight, dummy);
computedWeight *= 0.44444;//0.44 == 1/(the triangle area)
}
// Assuming a isoceles triangle of 2.5 texel height and 5 texels wide lying on 6 texels.
// This function return the weight of each texels area relative to the full triangle area.
// / \
// _ _ _ _ _ _ <-- texels
// 0 1 2 3 4 5 <-- computed area indices (in texelsWeights[])
void SampleShadow_GetTexelWeights_Tent_5x5(real offset, out real3 texelsWeightsA, out real3 texelsWeightsB)
{
// See _UnityInternalGetAreaPerTexel_3TexelTriangleFilter for details.
real4 computedArea_From3texelTriangle;
real4 computedAreaUncut_From3texelTriangle;
SampleShadow_GetTexelAreas_Tent_3x3(offset, computedArea_From3texelTriangle, computedAreaUncut_From3texelTriangle);
// Triangle slope is 45 degree thus we can almost reuse the result of the 3 texel wide computation.
// the 5 texel wide triangle can be seen as the 3 texel wide one but shifted up by one unit/texel.
// 0.16 is 1/(the triangle area)
texelsWeightsA.x = 0.16 * (computedArea_From3texelTriangle.x);
texelsWeightsA.y = 0.16 * (computedAreaUncut_From3texelTriangle.y);
texelsWeightsA.z = 0.16 * (computedArea_From3texelTriangle.y + 1);
texelsWeightsB.x = 0.16 * (computedArea_From3texelTriangle.z + 1);
texelsWeightsB.y = 0.16 * (computedAreaUncut_From3texelTriangle.z);
texelsWeightsB.z = 0.16 * (computedArea_From3texelTriangle.w);
}
// Assuming a isoceles triangle of 3.5 texel height and 7 texels wide lying on 8 texels.
// This function return the weight of each texels area relative to the full triangle area.
// / \
// _ _ _ _ _ _ _ _ <-- texels
// 0 1 2 3 4 5 6 7 <-- computed area indices (in texelsWeights[])
void SampleShadow_GetTexelWeights_Tent_7x7(real offset, out real4 texelsWeightsA, out real4 texelsWeightsB)
{
// See _UnityInternalGetAreaPerTexel_3TexelTriangleFilter for details.
real4 computedArea_From3texelTriangle;
real4 computedAreaUncut_From3texelTriangle;
SampleShadow_GetTexelAreas_Tent_3x3(offset, computedArea_From3texelTriangle, computedAreaUncut_From3texelTriangle);
// Triangle slope is 45 degree thus we can almost reuse the result of the 3 texel wide computation.
// the 7 texel wide triangle can be seen as the 3 texel wide one but shifted up by two unit/texel.
// 0.081632 is 1/(the triangle area)
texelsWeightsA.x = 0.081632 * (computedArea_From3texelTriangle.x);
texelsWeightsA.y = 0.081632 * (computedAreaUncut_From3texelTriangle.y);
texelsWeightsA.z = 0.081632 * (computedAreaUncut_From3texelTriangle.y + 1);
texelsWeightsA.w = 0.081632 * (computedArea_From3texelTriangle.y + 2);
texelsWeightsB.x = 0.081632 * (computedArea_From3texelTriangle.z + 2);
texelsWeightsB.y = 0.081632 * (computedAreaUncut_From3texelTriangle.z + 1);
texelsWeightsB.z = 0.081632 * (computedAreaUncut_From3texelTriangle.z);
texelsWeightsB.w = 0.081632 * (computedArea_From3texelTriangle.w);
}
// 3x3 Tent filter (45 degree sloped triangles in U and V)
void SampleShadow_ComputeSamples_Tent_3x3(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[4], out real2 fetchesUV[4])
{
// tent base is 3x3 base thus covering from 9 to 12 texels, thus we need 4 bilinear PCF fetches
real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
// find the weight of each texel based
real4 texelsWeightsU, texelsWeightsV;
SampleShadow_GetTexelWeights_Tent_3x3(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU);
SampleShadow_GetTexelWeights_Tent_3x3(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV);
// each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels
real2 fetchesWeightsU = texelsWeightsU.xz + texelsWeightsU.yw;
real2 fetchesWeightsV = texelsWeightsV.xz + texelsWeightsV.yw;
// move the PCF bilinear fetches to respect texels weights
real2 fetchesOffsetsU = texelsWeightsU.yw / fetchesWeightsU.xy + real2(-1.5,0.5);
real2 fetchesOffsetsV = texelsWeightsV.yw / fetchesWeightsV.xy + real2(-1.5,0.5);
fetchesOffsetsU *= shadowMapTexture_TexelSize.xx;
fetchesOffsetsV *= shadowMapTexture_TexelSize.yy;
real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;
fetchesWeights[2] = fetchesWeightsU.x * fetchesWeightsV.y;
fetchesWeights[3] = fetchesWeightsU.y * fetchesWeightsV.y;
}
// 5x5 Tent filter (45 degree sloped triangles in U and V)
void SampleShadow_ComputeSamples_Tent_5x5(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[9], out real2 fetchesUV[9])
{
// tent base is 5x5 base thus covering from 25 to 36 texels, thus we need 9 bilinear PCF fetches
real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
// find the weight of each texel based on the area of a 45 degree slop tent above each of them.
real3 texelsWeightsU_A, texelsWeightsU_B;
real3 texelsWeightsV_A, texelsWeightsV_B;
SampleShadow_GetTexelWeights_Tent_5x5(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU_A, texelsWeightsU_B);
SampleShadow_GetTexelWeights_Tent_5x5(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV_A, texelsWeightsV_B);
// each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels
real3 fetchesWeightsU = real3(texelsWeightsU_A.xz, texelsWeightsU_B.y) + real3(texelsWeightsU_A.y, texelsWeightsU_B.xz);
real3 fetchesWeightsV = real3(texelsWeightsV_A.xz, texelsWeightsV_B.y) + real3(texelsWeightsV_A.y, texelsWeightsV_B.xz);
// move the PCF bilinear fetches to respect texels weights
real3 fetchesOffsetsU = real3(texelsWeightsU_A.y, texelsWeightsU_B.xz) / fetchesWeightsU.xyz + real3(-2.5,-0.5,1.5);
real3 fetchesOffsetsV = real3(texelsWeightsV_A.y, texelsWeightsV_B.xz) / fetchesWeightsV.xyz + real3(-2.5,-0.5,1.5);
fetchesOffsetsU *= shadowMapTexture_TexelSize.xxx;
fetchesOffsetsV *= shadowMapTexture_TexelSize.yyy;
real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.x);
fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[4] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesUV[5] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.y);
fetchesUV[6] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.z);
fetchesUV[7] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.z);
fetchesUV[8] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.z);
fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;
fetchesWeights[2] = fetchesWeightsU.z * fetchesWeightsV.x;
fetchesWeights[3] = fetchesWeightsU.x * fetchesWeightsV.y;
fetchesWeights[4] = fetchesWeightsU.y * fetchesWeightsV.y;
fetchesWeights[5] = fetchesWeightsU.z * fetchesWeightsV.y;
fetchesWeights[6] = fetchesWeightsU.x * fetchesWeightsV.z;
fetchesWeights[7] = fetchesWeightsU.y * fetchesWeightsV.z;
fetchesWeights[8] = fetchesWeightsU.z * fetchesWeightsV.z;
}
// 7x7 Tent filter (45 degree sloped triangles in U and V)
void SampleShadow_ComputeSamples_Tent_7x7(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[16], out real2 fetchesUV[16])
{
// tent base is 7x7 base thus covering from 49 to 64 texels, thus we need 16 bilinear PCF fetches
real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
// find the weight of each texel based on the area of a 45 degree slop tent above each of them.
real4 texelsWeightsU_A, texelsWeightsU_B;
real4 texelsWeightsV_A, texelsWeightsV_B;
SampleShadow_GetTexelWeights_Tent_7x7(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU_A, texelsWeightsU_B);
SampleShadow_GetTexelWeights_Tent_7x7(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV_A, texelsWeightsV_B);
// each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels
real4 fetchesWeightsU = real4(texelsWeightsU_A.xz, texelsWeightsU_B.xz) + real4(texelsWeightsU_A.yw, texelsWeightsU_B.yw);
real4 fetchesWeightsV = real4(texelsWeightsV_A.xz, texelsWeightsV_B.xz) + real4(texelsWeightsV_A.yw, texelsWeightsV_B.yw);
// move the PCF bilinear fetches to respect texels weights
real4 fetchesOffsetsU = real4(texelsWeightsU_A.yw, texelsWeightsU_B.yw) / fetchesWeightsU.xyzw + real4(-3.5,-1.5,0.5,2.5);
real4 fetchesOffsetsV = real4(texelsWeightsV_A.yw, texelsWeightsV_B.yw) / fetchesWeightsV.xyzw + real4(-3.5,-1.5,0.5,2.5);
fetchesOffsetsU *= shadowMapTexture_TexelSize.xxxx;
fetchesOffsetsV *= shadowMapTexture_TexelSize.yyyy;
real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.x);
fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.x);
fetchesUV[4] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[5] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesUV[6] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.y);
fetchesUV[7] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.y);
fetchesUV[8] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.z);
fetchesUV[9] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.z);
fetchesUV[10] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.z);
fetchesUV[11] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.z);
fetchesUV[12] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.w);
fetchesUV[13] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.w);
fetchesUV[14] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.w);
fetchesUV[15] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.w);
fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;
fetchesWeights[2] = fetchesWeightsU.z * fetchesWeightsV.x;
fetchesWeights[3] = fetchesWeightsU.w * fetchesWeightsV.x;
fetchesWeights[4] = fetchesWeightsU.x * fetchesWeightsV.y;
fetchesWeights[5] = fetchesWeightsU.y * fetchesWeightsV.y;
fetchesWeights[6] = fetchesWeightsU.z * fetchesWeightsV.y;
fetchesWeights[7] = fetchesWeightsU.w * fetchesWeightsV.y;
fetchesWeights[8] = fetchesWeightsU.x * fetchesWeightsV.z;
fetchesWeights[9] = fetchesWeightsU.y * fetchesWeightsV.z;
fetchesWeights[10] = fetchesWeightsU.z * fetchesWeightsV.z;
fetchesWeights[11] = fetchesWeightsU.w * fetchesWeightsV.z;
fetchesWeights[12] = fetchesWeightsU.x * fetchesWeightsV.w;
fetchesWeights[13] = fetchesWeightsU.y * fetchesWeightsV.w;
fetchesWeights[14] = fetchesWeightsU.z * fetchesWeightsV.w;
fetchesWeights[15] = fetchesWeightsU.w * fetchesWeightsV.w;
}

9
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowSamplingTent.hlsl.meta


fileFormatVersion: 2
guid: 6ff912bb23fcd5b468dd2e5c37addac3
timeCreated: 1491321444
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存