diff --git a/Assets/Custom RP.asset b/Assets/Custom RP.asset
index c17738c5f932e9d41a5139d5352732dd03267219..8eec27c34c76d3e8f8c6418d5bf88222da0cfb59 100644
--- a/Assets/Custom RP.asset
+++ b/Assets/Custom RP.asset
@@ -15,6 +15,7 @@ MonoBehaviour:
useDynamicBatching: 0
useGPUInstancing: 1
useSRPBatcher: 1
+ useLightsPerObject: 1
shadows:
maxDistance: 30
distanceFade: 0.1
diff --git a/Assets/Custom RP/Runtime/CustomRenderPipelineAsset.cs b/Assets/Custom RP/Runtime/CustomRenderPipelineAsset.cs
index b43722a2345bac7262cc384e46cf222065ffbbd0..cb20536d9824b9e7dff228cbed7e4898cb6b86ec 100644
--- a/Assets/Custom RP/Runtime/CustomRenderPipelineAsset.cs
+++ b/Assets/Custom RP/Runtime/CustomRenderPipelineAsset.cs
@@ -10,6 +10,7 @@ public class CustomRenderPipelineAsset : RenderPipelineAsset
[SerializeField]
bool useDynamicBatching = true, useGPUInstancing = true, useSRPBatcher = true;
// 是否使用逐对象光源
+ [SerializeField]
bool useLightsPerObject = true;
[SerializeField]
diff --git a/Assets/Custom RP/Runtime/Shadows.cs b/Assets/Custom RP/Runtime/Shadows.cs
index ec2be2c1cf34514a3a66a1035dfe38f90de4c181..576e7ca4b78fa402e44a321dfc99d3346b2eb379 100644
--- a/Assets/Custom RP/Runtime/Shadows.cs
+++ b/Assets/Custom RP/Runtime/Shadows.cs
@@ -117,8 +117,21 @@ public class Shadows
this.cullingResults = cullingResults;
this.shadowSettings = shadowSettings;
shadowedDirectionalLightCount = 0;
- useShadowMask = false;
shadowedOtherLightCount = 0;
+ useShadowMask = false;
+ }
+
+ ///
+ /// 释放申请的RT内存
+ ///
+ public void Cleanup()
+ {
+ buffer.ReleaseTemporaryRT(dirShadowAtlasId);
+ if (shadowedOtherLightCount > 0)
+ {
+ buffer.ReleaseTemporaryRT(otherShadowAtlasId);
+ }
+ ExecuteBuffer();
}
///
@@ -201,7 +214,7 @@ public class Shadows
normalBias = light.shadowNormalBias,
isPoint = isPoint
};
- Vector4 data = new Vector4(light.shadowStrength, shadowedOtherLightCount++, isPoint ? 1f : 0f, maskChannel);
+ Vector4 data = new Vector4(light.shadowStrength, shadowedOtherLightCount, isPoint ? 1f : 0f, maskChannel);
shadowedOtherLightCount = newLightCount;
return data;
}
@@ -307,7 +320,7 @@ public class Shadows
int split = tiles <= 1 ? 1 : tiles <= 4 ? 2 : 4;
int tileSize = atlasSize / split;
// 遍历所有光源渲染阴影贴图
- for (int i = 0; i < shadowedOtherLightCount; i++)
+ for (int i = 0; i < shadowedOtherLightCount;)
{
if (shadowedOtherLights[i].isPoint)
{
@@ -427,18 +440,22 @@ public class Shadows
{
ShadowedOtherLight light = shadowedOtherLights[index];
var newShadowSettings = new ShadowDrawingSettings(cullingResults, light.visibleLightIndex);
- for (int i = 0; i < 6; i++)
+ // 计算法线偏差
+ float texelSize = 2f / tileSize;
+ float filterSize = texelSize * ((float)shadowSettings.other.filter + 1f);
+ float bias = light.normalBias * filterSize * 1.4142136f;
+ float tileScale = 1f / split;
+ float fovBias = Mathf.Atan(1f + bias + filterSize) * Mathf.Rad2Deg * 2f - 90f;
+ for (int i = 0; i < 6; i++)
{
- cullingResults.ComputePointShadowMatricesAndCullingPrimitives(light.visibleLightIndex, (CubemapFace)i, 0f, out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix, out ShadowSplitData splitData);
- newShadowSettings.splitData = splitData;
+ cullingResults.ComputePointShadowMatricesAndCullingPrimitives(light.visibleLightIndex, (CubemapFace)i, fovBias, out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix, out ShadowSplitData splitData);
+ viewMatrix.m11 = -viewMatrix.m11;
+ viewMatrix.m12 = -viewMatrix.m12;
+ viewMatrix.m13 = -viewMatrix.m13;
+ newShadowSettings.splitData = splitData;
int tileIndex = index + i;
- // 计算法线偏差
- float texelSize = 2f / (tileSize * projectionMatrix.m00);
- float filterSize = texelSize * ((float)shadowSettings.other.filter + 1f);
- float bias = light.normalBias * filterSize * 1.4142136f;
Vector2 offset = SetTileViewport(tileIndex, split, tileSize);
- float tileScale = 1f / split;
SetOtherTileData(tileIndex, offset, tileScale, bias);
otherShadowMatrices[tileIndex] = ConvertToAtlasMatrix(projectionMatrix * viewMatrix, offset, tileScale);
buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
@@ -530,17 +547,4 @@ public class Shadows
m.m23 = 0.5f * (m.m23 + m.m33);
return m;
}
-
- ///
- /// 释放申请的RT内存
- ///
- public void Cleanup()
- {
- buffer.ReleaseTemporaryRT(dirShadowAtlasId);
- if (shadowedOtherLightCount > 0)
- {
- buffer.ReleaseTemporaryRT(otherShadowAtlasId);
- }
- ExecuteBuffer();
- }
}
diff --git a/Assets/Custom RP/ShaderLibrary/Light.hlsl b/Assets/Custom RP/ShaderLibrary/Light.hlsl
index 0e60f4613c996603391ec12cb6753ac23bd7b9fd..93c7c4342e7f91268e6b8f1a198563e0f4f680cc 100644
--- a/Assets/Custom RP/ShaderLibrary/Light.hlsl
+++ b/Assets/Custom RP/ShaderLibrary/Light.hlsl
@@ -60,7 +60,9 @@ OtherShadowData GetOtherShadowData(int lightIndex)
data.strength = _OtherLightShadowData[lightIndex].x;
data.tileIndex = _OtherLightShadowData[lightIndex].y;
data.shadowMaskChannel = _OtherLightShadowData[lightIndex].w;
+ data.isPoint = _OtherLightShadowData[lightIndex].z == 1.0;
data.lightPositionWS = 0.0;
+ data.lightDirectionWS = 0.0;
data.spotDirectionWS = 0.0;
return data;
}
@@ -97,6 +99,7 @@ Light GetOtherLight(int index, Surface surfaceWS, ShadowData shadowData)
OtherShadowData otherShadowData = GetOtherShadowData(index);
otherShadowData.lightPositionWS = position;
+ otherShadowData.lightDirectionWS = light.direction;
otherShadowData.spotDirectionWS = spotDirection;
// 光照强度随范围和距离衰减
light.attenuation = GetOtherShadowAttenuation(otherShadowData, shadowData, surfaceWS) * spotAttenuation * rangeAttenuation / distanceSqr;
diff --git a/Assets/Custom RP/ShaderLibrary/Shadows.hlsl b/Assets/Custom RP/ShaderLibrary/Shadows.hlsl
index 1f9b7ebb0349264c7cf42fb8b5bb4c843256cedb..b2317ec572a9da4ea6ac85cd14ba27a216ec65f4 100644
--- a/Assets/Custom RP/ShaderLibrary/Shadows.hlsl
+++ b/Assets/Custom RP/ShaderLibrary/Shadows.hlsl
@@ -79,6 +79,7 @@ float GetBakedShadow(ShadowMask mask, int channel)
return shadow;
}
+// 获取烘焙阴影的衰减值
float GetBakedShadow(ShadowMask mask, int channel, float strength)
{
if (mask.always || mask.distance)
@@ -265,6 +266,7 @@ struct OtherShadowData
{
float strength;
int tileIndex;
+ bool isPoint;
int shadowMaskChannel;
float3 lightPositionWS;
float3 lightDirectionWS;
@@ -302,7 +304,8 @@ float FilterOtherShadow(float3 positionSTS, float3 bonuds)
#endif
}
-static const float3 pointShadowPlanes[6] = {
+static const float3 pointShadowPlanes[6] =
+{
float3(-1.0, 0.0, 0.0),
float3(1.0, 0.0, 0.0),
float3(0.0, -1.0, 0.0),
@@ -315,9 +318,16 @@ static const float3 pointShadowPlanes[6] = {
float GetOtherShadow(OtherShadowData other, ShadowData global, Surface surfaceWS)
{
float tileIndex = other.tileIndex;
+ float3 lightPlane = other.spotDirectionWS;
+ if (other.isPoint)
+ {
+ float faceOffset = CubeMapFaceID(-other.lightDirectionWS);
+ tileIndex += faceOffset;
+ lightPlane = pointShadowPlanes[faceOffset];
+ }
float4 tileData = _OtherShadowTiles[tileIndex];
float3 surfaceToLight = other.lightPositionWS - surfaceWS.position;
- float distanceToLightPlane = dot(surfaceToLight, other.spotDirectionWS);
+ float distanceToLightPlane = dot(surfaceToLight, lightPlane);
float3 normalBias = surfaceWS.interpolatedNormal * (distanceToLightPlane * tileData.w);
float4 positionSTS = mul(_OtherShadowMatrices[tileIndex], float4(surfaceWS.position + normalBias, 1.0));
return FilterOtherShadow(positionSTS.xyz / positionSTS.w, tileData.xyz);