|
|
|
|
|
|
using UnityEngine.Rendering; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System; |
|
|
|
using UnityEngine.Assertions; |
|
|
|
|
|
|
|
namespace UnityEngine.Experimental.Rendering.HDPipeline |
|
|
|
{ |
|
|
|
|
|
|
public const int k_MaxEnvLightsOnScreen = 64; |
|
|
|
public const int k_MaxShadowOnScreen = 16; |
|
|
|
public const int k_MaxCascadeCount = 4; //Should be not less than m_Settings.directionalLightCascadeCount;
|
|
|
|
static readonly Vector3 k_BoxCullingExtentThreshold = Vector3.one * 0.01f; |
|
|
|
|
|
|
|
// Static keyword is required here else we get a "DestroyBuffer can only be call in main thread"
|
|
|
|
static ComputeBuffer s_DirectionalLightDatas = null; |
|
|
|
|
|
|
|
|
|
|
public void GetEnvLightVolumeDataAndBound(VisibleReflectionProbe probe, LightVolumeType lightVolumeType, Matrix4x4 worldToView) |
|
|
|
{ |
|
|
|
var add = probe.probe.GetComponent<HDAdditionalReflectionData>(); |
|
|
|
Assert.IsNotNull(add); |
|
|
|
|
|
|
|
var bnds = probe.bounds; |
|
|
|
var boxOffset = probe.center; // reflection volume offset relative to cube map capture point
|
|
|
|
var blendDistance = probe.blendDistance; |
|
|
|
|
|
|
|
var centerOffset = probe.center; // reflection volume offset relative to cube map capture point
|
|
|
|
var mat = probe.localToWorld; |
|
|
|
|
|
|
|
Vector3 vx = mat.GetColumn(0); |
|
|
|
|
|
|
vz.Normalize(); |
|
|
|
|
|
|
|
// C is reflection volume center in world space (NOT same as cube map capture point)
|
|
|
|
var e = bnds.extents; // 0.5f * Vector3.Max(-boxSizes[p], boxSizes[p]);
|
|
|
|
var C = vx * boxOffset.x + vy * boxOffset.y + vz * boxOffset.z + vw; |
|
|
|
|
|
|
|
var combinedExtent = e + new Vector3(blendDistance, blendDistance, blendDistance); |
|
|
|
var influenceExtents = probe.bounds.extents; // 0.5f * Vector3.Max(-boxSizes[p], boxSizes[p]);
|
|
|
|
var centerWS = vx * centerOffset.x + vy * centerOffset.y + vz * centerOffset.z + vw; |
|
|
|
|
|
|
|
// transform to camera space (becomes a left hand coordinate frame in Unity since Determinant(worldToView)<0)
|
|
|
|
vx = worldToView.MultiplyVector(vx); |
|
|
|
|
|
|
var Cw = worldToView.MultiplyPoint(C); |
|
|
|
|
|
|
|
bound.center = Cw; |
|
|
|
bound.boxAxisX = combinedExtent.x * vx; |
|
|
|
bound.boxAxisY = combinedExtent.y * vy; |
|
|
|
bound.boxAxisZ = combinedExtent.z * vz; |
|
|
|
bound.scaleXY.Set(1.0f, 1.0f); |
|
|
|
bound.radius = combinedExtent.magnitude; |
|
|
|
|
|
|
|
var centerVS = worldToView.MultiplyPoint(centerWS); |
|
|
|
lightVolumeData.lightPos = Cw; |
|
|
|
lightVolumeData.lightAxisX = vx; |
|
|
|
lightVolumeData.lightAxisY = vy; |
|
|
|
lightVolumeData.lightAxisZ = vz; |
|
|
|
var delta = combinedExtent - e; |
|
|
|
lightVolumeData.boxInnerDist = e; |
|
|
|
lightVolumeData.boxInvRange.Set(1.0f / delta.x, 1.0f / delta.y, 1.0f / delta.z); |
|
|
|
switch (lightVolumeType) |
|
|
|
{ |
|
|
|
case LightVolumeType.Sphere: |
|
|
|
{ |
|
|
|
lightVolumeData.lightPos = centerVS; |
|
|
|
lightVolumeData.radiusSq = add.influenceSphereRadius * add.influenceSphereRadius; |
|
|
|
lightVolumeData.lightAxisX = vx; |
|
|
|
lightVolumeData.lightAxisY = vy; |
|
|
|
lightVolumeData.lightAxisZ = vz; |
|
|
|
|
|
|
|
bound.center = centerVS; |
|
|
|
bound.boxAxisX = vx * add.influenceSphereRadius; |
|
|
|
bound.boxAxisY = vy * add.influenceSphereRadius; |
|
|
|
bound.boxAxisZ = vz * add.influenceSphereRadius; |
|
|
|
bound.scaleXY.Set(1.0f, 1.0f); |
|
|
|
bound.radius = add.influenceSphereRadius; |
|
|
|
break; |
|
|
|
} |
|
|
|
case LightVolumeType.Box: |
|
|
|
{ |
|
|
|
bound.center = centerVS; |
|
|
|
bound.boxAxisX = influenceExtents.x * vx; |
|
|
|
bound.boxAxisY = influenceExtents.y * vy; |
|
|
|
bound.boxAxisZ = influenceExtents.z * vz; |
|
|
|
bound.scaleXY.Set(1.0f, 1.0f); |
|
|
|
bound.radius = influenceExtents.magnitude; |
|
|
|
|
|
|
|
// The culling system culls pixels that are further
|
|
|
|
// than a threshold to the box influence extents.
|
|
|
|
// So we use an arbitrary threshold here (k_BoxCullingExtentOffset)
|
|
|
|
lightVolumeData.lightPos = centerVS; |
|
|
|
lightVolumeData.lightAxisX = vx; |
|
|
|
lightVolumeData.lightAxisY = vy; |
|
|
|
lightVolumeData.lightAxisZ = vz; |
|
|
|
lightVolumeData.boxInnerDist = influenceExtents - k_BoxCullingExtentThreshold; |
|
|
|
lightVolumeData.boxInvRange.Set(1.0f / k_BoxCullingExtentThreshold.x, 1.0f / k_BoxCullingExtentThreshold.y, 1.0f / k_BoxCullingExtentThreshold.z); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
m_lightList.bounds.Add(bound); |
|
|
|
m_lightList.lightVolumes.Add(lightVolumeData); |
|
|
|
|
|
|
for (int probeIndex = 0, numProbes = cullResults.visibleReflectionProbes.Count; (probeIndex < numProbes) && (sortCount < probeCount); probeIndex++) |
|
|
|
{ |
|
|
|
VisibleReflectionProbe probe = cullResults.visibleReflectionProbes[probeIndex]; |
|
|
|
HDAdditionalReflectionData additional = probe.probe.GetComponent<HDAdditionalReflectionData>(); |
|
|
|
|
|
|
|
// probe.texture can be null when we are adding a reflection probe in the editor
|
|
|
|
if (probe.texture == null || envLightCount >= k_MaxEnvLightsOnScreen) |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// TODO: Support LightVolumeType.Sphere, currently in UI there is no way to specify a sphere influence volume
|
|
|
|
LightVolumeType lightVolumeType = probe.boxProjection != 0 ? LightVolumeType.Box : LightVolumeType.Box; |
|
|
|
LightVolumeType lightVolumeType = LightVolumeType.Box; |
|
|
|
if (additional != null && additional.influenceShape == ReflectionInfluenceShape.Sphere) |
|
|
|
lightVolumeType = LightVolumeType.Sphere; |
|
|
|
++envLightCount; |
|
|
|
|
|
|
|
float boxVolume = 8 * probe.bounds.extents.x * probe.bounds.extents.y * probe.bounds.extents.z; |
|
|
|