浏览代码

Add SpotLightShape, and clean up bounding volume computation in the TilePass.cs

/RenderPassXR_Sandbox
Evgenii Golubev 8 年前
当前提交
5b236c70
共有 2 个文件被更改,包括 71 次插入91 次删除
  1. 5
      Assets/ScriptableRenderPipeline/HDRenderPipeline/AdditionalData/HDAdditionalLightData.cs
  2. 157
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs

5
Assets/ScriptableRenderPipeline/HDRenderPipeline/AdditionalData/HDAdditionalLightData.cs


namespace UnityEngine.Experimental.Rendering
{
public enum LightArchetype { Punctual, Area, Projector };
public enum LightArchetype { Punctual, Area };
public enum SpotLightShape { Cone, Pyramid, Box };
//@TODO: We should continuously move these values
// into the engine when we can see them being generally useful

public bool affectSpecular = true;
public LightArchetype archetype = LightArchetype.Punctual;
public SpotLightShape spotLightShape = SpotLightShape.Cone;
[Range(0.0f, 20.0f)]
public float lightLength = 0.0f; // Area & projector lights

157
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs


lightData.up = light.light.transform.up;
lightData.right = light.light.transform.right;
if (additionalLightData.archetype != LightArchetype.Punctual)
{
lightData.size = new Vector2(additionalLightData.lightLength, additionalLightData.lightWidth);
}
lightData.size = new Vector2(additionalLightData.lightLength, additionalLightData.lightWidth);
if (lightData.lightType == GPULightType.ProjectorBox || lightData.lightType == GPULightType.ProjectorPyramid)
{

case LightType.Point:
lightData.cookieIndex = m_CubeCookieTexArray.FetchSlice(light.light.cookie);
break;
}
if (additionalLightData.archetype == LightArchetype.Projector)
{
lightData.cookieIndex = m_CookieTexArray.FetchSlice(light.light.cookie);
else if (additionalLightData.archetype == LightArchetype.Projector)
else if (light.lightType == LightType.Spot && additionalLightData.spotLightShape != SpotLightShape.Cone)
{
// Projectors lights must always have a cookie texture.
lightData.cookieIndex = m_CookieTexArray.FetchSlice(Texture2D.whiteTexture);

// Then Culling side
var range = light.range;
var lightToWorld = light.localToWorld;
Vector3 lightPos = lightData.positionWS;
Vector3 positionWS = lightData.positionWS;
Vector3 positionVS = worldToView.MultiplyPoint(positionWS);
Matrix4x4 lightToView = worldToView * lightToWorld;
Vector3 xAxisVS = lightToView.GetColumn(0);

// apply nonuniform scale to OBB of spot light
var squeeze = true;//sa < 0.7f * 90.0f; // arb heuristic
var fS = squeeze ? ta : si;
bound.center = worldToView.MultiplyPoint(lightPos + ((0.5f * range) * lightDir)); // use mid point of the spot as the center of the bounding volume for building screen-space AABB for tiled lighting.
bound.center = worldToView.MultiplyPoint(positionWS + ((0.5f * range) * lightDir)); // use mid point of the spot as the center of the bounding volume for building screen-space AABB for tiled lighting.
// scale axis to match box or base of pyramid
bound.boxAxisX = (fS * range) * vx;

lightVolumeData.lightAxisX = vx;
lightVolumeData.lightAxisY = vy;
lightVolumeData.lightAxisZ = vz;
lightVolumeData.lightPos = worldToView.MultiplyPoint(lightPos);
lightVolumeData.lightPos = positionVS;
lightVolumeData.radiusSq = range * range;
lightVolumeData.cotan = cota;
lightVolumeData.featureFlags = (uint)LightFeatureFlags.Punctual;

bool isNegDeterminant = Vector3.Dot(worldToView.GetColumn(0), Vector3.Cross(worldToView.GetColumn(1), worldToView.GetColumn(2))) < 0.0f; // 3x3 Determinant.
bound.center = worldToView.MultiplyPoint(lightPos);
bound.center = positionVS;
bound.boxAxisX.Set(range, 0, 0);
bound.boxAxisY.Set(0, range, 0);
bound.boxAxisZ.Set(0, 0, isNegDeterminant ? (-range) : range); // transform to camera space (becomes a left hand coordinate frame in Unity since Determinant(worldToView)<0)

lightVolumeData.radiusSq = range * range;
lightVolumeData.featureFlags = (uint)LightFeatureFlags.Punctual;
}
else if (gpuLightType == GPULightType.Rectangle)
else if (gpuLightType == GPULightType.Line)
Vector3 centerVS = worldToView.MultiplyPoint(lightData.positionWS);
float radius = 1.0f / Mathf.Sqrt(lightData.invSqrAttenuationRadius);
Vector3 dimensions = new Vector3(lightData.size.x + 2 * range, 2 * range, 2 * range); // Omni-directional
Vector3 extents = 0.5f * dimensions;
Vector3 dimensions = new Vector3(lightData.size.x * 0.5f + radius, lightData.size.y * 0.5f + radius, radius);
dimensions.z *= 0.5f;
centerVS += zAxisVS * radius * 0.5f;
bound.center = centerVS;
bound.boxAxisX = dimensions.x * xAxisVS;
bound.boxAxisY = dimensions.y * yAxisVS;
bound.boxAxisZ = dimensions.z * zAxisVS;
bound.center = positionVS;
bound.boxAxisX = extents.x * xAxisVS;
bound.boxAxisY = extents.y * yAxisVS;
bound.boxAxisZ = extents.z * zAxisVS;
bound.radius = dimensions.magnitude;
bound.radius = extents.magnitude;
lightVolumeData.lightPos = centerVS;
lightVolumeData.lightPos = positionVS;
lightVolumeData.boxInnerDist = dimensions;
lightVolumeData.boxInvRange.Set(1e5f, 1e5f, 1e5f);
lightVolumeData.boxInnerDist = new Vector3(lightData.size.x, 0, 0);
lightVolumeData.boxInvRange.Set(1.0f / range, 1.0f / range, 1.0f / range);
else if (gpuLightType == GPULightType.Line)
else if (gpuLightType == GPULightType.Rectangle)
Vector3 centerVS = worldToView.MultiplyPoint(lightData.positionWS);
float radius = 1.0f / Mathf.Sqrt(lightData.invSqrAttenuationRadius);
Vector3 dimensions = new Vector3(lightData.size.x * 0.5f + radius, radius, radius);
Vector3 dimensions = new Vector3(lightData.size.x + 2 * range, lightData.size.y + 2 * range, range); // One-sided
Vector3 extents = 0.5f * dimensions;
Vector3 centerVS = positionVS + extents.z * zAxisVS;
bound.boxAxisX = dimensions.x * xAxisVS;
bound.boxAxisY = dimensions.y * yAxisVS;
bound.boxAxisZ = dimensions.z * zAxisVS;
bound.boxAxisX = extents.x * xAxisVS;
bound.boxAxisY = extents.y * yAxisVS;
bound.boxAxisZ = extents.z * zAxisVS;
bound.radius = dimensions.magnitude;
bound.radius = extents.magnitude;
lightVolumeData.lightPos = centerVS;
lightVolumeData.lightAxisX = xAxisVS;
lightVolumeData.lightAxisY = yAxisVS;
lightVolumeData.lightAxisZ = zAxisVS;
lightVolumeData.boxInnerDist = new Vector3(lightData.size.x * 0.5f, 0.01f, 0.01f);
lightVolumeData.boxInvRange.Set(1.0f / radius, 1.0f / radius, 1.0f / radius);
lightVolumeData.lightPos = centerVS;
lightVolumeData.lightAxisX = xAxisVS;
lightVolumeData.lightAxisY = yAxisVS;
lightVolumeData.lightAxisZ = zAxisVS;
lightVolumeData.boxInnerDist = extents;
lightVolumeData.boxInvRange.Set(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity);
Vector3 posVS = worldToView.MultiplyPoint(lightData.positionWS);
// Projector lights point forwards (along Z). The projection window is aligned with the XY plane.
Vector3 boxDims = new Vector3(lightData.size.x, lightData.size.y, 100000);
Vector3 halfDims = 0.5f * boxDims;
Vector3 dimensions = new Vector3(lightData.size.x, lightData.size.y, range); // One-sided
Vector3 extents = 0.5f * dimensions;
Vector3 centerVS = positionVS + extents.z * zAxisVS;
bound.center = posVS;
bound.boxAxisX = halfDims.x * xAxisVS;
bound.boxAxisY = halfDims.y * yAxisVS;
bound.boxAxisZ = halfDims.z * zAxisVS;
bound.radius = halfDims.magnitude;
bound.center = centerVS;
bound.boxAxisX = extents.x * xAxisVS;
bound.boxAxisY = extents.y * yAxisVS;
bound.boxAxisZ = extents.z * zAxisVS;
bound.radius = extents.magnitude;
lightVolumeData.lightPos = posVS;
lightVolumeData.lightPos = centerVS;
lightVolumeData.boxInnerDist = halfDims;
lightVolumeData.boxInvRange.Set(1.0f / halfDims.x, 1.0f / halfDims.y, 1.0f / halfDims.z);
lightVolumeData.boxInnerDist = extents;
lightVolumeData.boxInvRange.Set(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity);
lightVolumeData.featureFlags = (uint)LightFeatureFlags.Punctual;
}
else

case LightType.Spot:
if (punctualLightcount >= k_MaxPunctualLightsOnScreen)
continue;
gpuLightType = GPULightType.Spot;
lightVolumeType = LightVolumeType.Cone;
switch (additionalData.spotLightShape)
{
case SpotLightShape.Cone:
gpuLightType = GPULightType.Spot;
lightVolumeType = LightVolumeType.Cone;
break;
case SpotLightShape.Pyramid:
gpuLightType = GPULightType.ProjectorPyramid;
lightVolumeType = LightVolumeType.Cone;
break;
case SpotLightShape.Box:
gpuLightType = GPULightType.ProjectorBox;
lightVolumeType = LightVolumeType.Box;
break;
default:
Debug.Assert(false, "Encountered an unknown SpotLightShape.");
break;
}
break;
case LightType.Directional:

break;
default:
Debug.Assert(false, "TODO: encountered an unknown LightType.");
Debug.Assert(false, "Encountered an unknown LightType.");
else
else // LightArchetype.Area
switch (additionalData.archetype)
{
case LightArchetype.Area:
if (areaLightCount >= k_MaxAreaLightsOnScreen) { continue; }
lightCategory = LightCategory.Area;
gpuLightType = (additionalData.lightWidth > 0) ? GPULightType.Rectangle : GPULightType.Line;
lightVolumeType = LightVolumeType.Box;
break;
case LightArchetype.Projector:
if (punctualLightcount >= k_MaxPunctualLightsOnScreen) { continue; }
lightCategory = LightCategory.Punctual;
switch (light.lightType)
{
case LightType.Directional:
gpuLightType = GPULightType.ProjectorBox;
lightVolumeType = LightVolumeType.Box;
break;
case LightType.Spot:
gpuLightType = GPULightType.ProjectorPyramid;
lightVolumeType = LightVolumeType.Cone;
break;
default:
Debug.Assert(false, "Projectors can only be Spot or Directional lights.");
break;
}
break;
default:
Debug.Assert(false, "TODO: encountered an unknown LightArchetype.");
break;
}
if (areaLightCount >= k_MaxAreaLightsOnScreen) { continue; }
lightCategory = LightCategory.Area;
gpuLightType = (additionalData.lightWidth > 0) ? GPULightType.Rectangle : GPULightType.Line;
lightVolumeType = LightVolumeType.Box;
}
uint shadow = m_ShadowIndices.ContainsKey(lightIndex) ? 1u : 0;

正在加载...
取消
保存