|
|
|
|
|
|
return 1.0f - Mathf.Clamp01(distanceToCamera * scale + bias); |
|
|
|
} |
|
|
|
|
|
|
|
public bool GetLightData(CommandBuffer cmd, ShadowSettings shadowSettings, Camera camera, GPULightType gpuLightType, VisibleLight light, HDAdditionalLightData additionalLightData, AdditionalShadowData additionalshadowData, int lightIndex) |
|
|
|
public bool GetLightData(CommandBuffer cmd, ShadowSettings shadowSettings, Camera camera, GPULightType gpuLightType, |
|
|
|
VisibleLight light, HDAdditionalLightData additionalLightData, AdditionalShadowData additionalshadowData, |
|
|
|
int lightIndex, ref Vector3 lightDimensions) |
|
|
|
{ |
|
|
|
var lightData = new LightData(); |
|
|
|
|
|
|
|
|
|
|
lightData.up = light.light.transform.up; |
|
|
|
lightData.right = light.light.transform.right; |
|
|
|
|
|
|
|
lightData.size = new Vector2(additionalLightData.shapeLength, additionalLightData.shapeWidth); |
|
|
|
lightDimensions.x = additionalLightData.shapeLength; |
|
|
|
lightDimensions.x = additionalLightData.shapeWidth; |
|
|
|
lightDimensions.z = light.range; |
|
|
|
lightData.size.x = light.range; |
|
|
|
|
|
|
|
// Rescale for cookies and windowing.
|
|
|
|
lightData.right *= 2.0f / additionalLightData.shapeLength; |
|
|
|
lightData.up *= 2.0f / additionalLightData.shapeWidth; |
|
|
|
|
|
|
// Get width and height for the current frustum
|
|
|
|
var spotAngle = light.spotAngle; |
|
|
|
|
|
|
|
float frustumHeight; |
|
|
|
float frustumWidth; |
|
|
|
float frustumLength, frustumWidth; |
|
|
|
|
|
|
|
frustumHeight = 2.0f * Mathf.Tan(spotAngle * 0.5f * Mathf.Deg2Rad); |
|
|
|
frustumWidth = frustumHeight * additionalLightData.aspectRatio; |
|
|
|
frustumWidth = 2.0f * Mathf.Tan(spotAngle * 0.5f * Mathf.Deg2Rad); |
|
|
|
frustumLength = frustumWidth * additionalLightData.aspectRatio; |
|
|
|
frustumWidth = 2.0f * Mathf.Tan(spotAngle * 0.5f * Mathf.Deg2Rad); |
|
|
|
frustumHeight = frustumWidth / additionalLightData.aspectRatio; |
|
|
|
frustumLength = 2.0f * Mathf.Tan(spotAngle * 0.5f * Mathf.Deg2Rad); |
|
|
|
frustumWidth = frustumLength / additionalLightData.aspectRatio; |
|
|
|
lightData.size = new Vector2(frustumWidth, frustumHeight); |
|
|
|
// Adjust based on the new parametrization.
|
|
|
|
lightDimensions.x = frustumLength; |
|
|
|
lightDimensions.y = frustumWidth; |
|
|
|
lightData.right *= 2.0f / frustumWidth; |
|
|
|
lightData.up *= 2.0f / frustumHeight; |
|
|
|
lightData.right *= 2.0f / frustumLength; |
|
|
|
lightData.up *= 2.0f / frustumWidth; |
|
|
|
} |
|
|
|
|
|
|
|
if (lightData.lightType == GPULightType.Spot) |
|
|
|
|
|
|
// These are the neutral values allowing GetAngleAnttenuation in shader code to return 1.0
|
|
|
|
lightData.angleScale = 0.0f; |
|
|
|
lightData.angleOffset = 1.0f; |
|
|
|
} |
|
|
|
|
|
|
|
if (lightData.lightType == GPULightType.Rectangle || lightData.lightType == GPULightType.Line) |
|
|
|
{ |
|
|
|
lightData.size = new Vector2(additionalLightData.shapeLength, additionalLightData.shapeWidth); |
|
|
|
} |
|
|
|
|
|
|
|
float distanceToCamera = (lightData.positionWS - camera.transform.position).magnitude; |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// TODO: we should be able to do this calculation only with LightData without VisibleLight light, but for now pass both
|
|
|
|
public void GetLightVolumeDataAndBound(LightCategory lightCategory, GPULightType gpuLightType, LightVolumeType lightVolumeType, VisibleLight light, LightData lightData, Matrix4x4 worldToView) |
|
|
|
public void GetLightVolumeDataAndBound(LightCategory lightCategory, GPULightType gpuLightType, LightVolumeType lightVolumeType, |
|
|
|
VisibleLight light, LightData lightData, Vector3 lightDimensions, Matrix4x4 worldToView) |
|
|
|
var range = light.range; |
|
|
|
var range = lightDimensions.z; |
|
|
|
var lightToWorld = light.localToWorld; |
|
|
|
Vector3 positionWS = lightData.positionWS; |
|
|
|
Vector3 positionVS = worldToView.MultiplyPoint(positionWS); |
|
|
|
|
|
|
|
|
|
|
if (gpuLightType == GPULightType.ProjectorPyramid) |
|
|
|
{ |
|
|
|
Vector3 lightPosToProjWindowCorner = (0.5f * lightData.size.x) * vx + (0.5f * lightData.size.y) * vy + 1.0f * vz; |
|
|
|
Vector3 lightPosToProjWindowCorner = (0.5f * lightDimensions.x) * vx + (0.5f * lightDimensions.y) * vy + 1.0f * vz; |
|
|
|
cs = Vector3.Dot(vz, Vector3.Normalize(lightPosToProjWindowCorner)); |
|
|
|
si = Mathf.Sqrt(1.0f - cs * cs); |
|
|
|
} |
|
|
|
|
|
|
} |
|
|
|
else if (gpuLightType == GPULightType.Line) |
|
|
|
{ |
|
|
|
Vector3 dimensions = new Vector3(lightData.size.x + 2 * range, 2 * range, 2 * range); // Omni-directional
|
|
|
|
Vector3 dimensions = new Vector3(lightDimensions.x + 2 * range, 2 * range, 2 * range); // Omni-directional
|
|
|
|
Vector3 extents = 0.5f * dimensions; |
|
|
|
|
|
|
|
bound.center = positionVS; |
|
|
|
|
|
|
lightVolumeData.lightAxisX = xAxisVS; |
|
|
|
lightVolumeData.lightAxisY = yAxisVS; |
|
|
|
lightVolumeData.lightAxisZ = zAxisVS; |
|
|
|
lightVolumeData.boxInnerDist = new Vector3(lightData.size.x, 0, 0); |
|
|
|
lightVolumeData.boxInnerDist = new Vector3(lightDimensions.x, 0, 0); |
|
|
|
Vector3 dimensions = new Vector3(lightData.size.x + 2 * range, lightData.size.y + 2 * range, range); // One-sided
|
|
|
|
Vector3 dimensions = new Vector3(lightDimensions.x + 2 * range, lightDimensions.y + 2 * range, range); // One-sided
|
|
|
|
Vector3 extents = 0.5f * dimensions; |
|
|
|
Vector3 centerVS = positionVS + extents.z * zAxisVS; |
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
else if (gpuLightType == GPULightType.ProjectorBox) |
|
|
|
{ |
|
|
|
Vector3 dimensions = new Vector3(lightData.size.x, lightData.size.y, range); // One-sided
|
|
|
|
Vector3 dimensions = new Vector3(lightDimensions.x, lightDimensions.y, range); // One-sided
|
|
|
|
Vector3 extents = 0.5f * dimensions; |
|
|
|
Vector3 centerVS = positionVS + extents.z * zAxisVS; |
|
|
|
|
|
|
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
Vector3 lightDimensions = new Vector3(); // X = length, Y = width, Z = range
|
|
|
|
|
|
|
|
if (GetLightData(cmd, shadowSettings, camera, gpuLightType, light, additionalLightData, additionalShadowData, lightIndex)) |
|
|
|
if (GetLightData(cmd, shadowSettings, camera, gpuLightType, light, additionalLightData, additionalShadowData, lightIndex, ref lightDimensions)) |
|
|
|
{ |
|
|
|
switch (lightCategory) |
|
|
|
{ |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Then culling side. Must be call in this order as we pass the created Light data to the function
|
|
|
|
GetLightVolumeDataAndBound(lightCategory, gpuLightType, lightVolumeType, light, m_lightList.lights[m_lightList.lights.Count - 1], worldToView); |
|
|
|
GetLightVolumeDataAndBound(lightCategory, gpuLightType, lightVolumeType, light, m_lightList.lights[m_lightList.lights.Count - 1], lightDimensions, worldToView); |
|
|
|
|
|
|
|
// We make the light position camera-relative as late as possible in order
|
|
|
|
// to allow the preceding code to work with the absolute world space coordinates.
|
|
|
|