/// <summary> /// 通过顶点列表获取AABB包围盒 /// </summary> /// <param name="vertexList"></param> /// <returns></returns> public static AABBBounds GetAABBBoundsByVertexList(List <Vector3> vertexList) { AABBBounds aabbBounds = new AABBBounds(); for (int i = 0; i < vertexList.Count; ++i) { aabbBounds.UpdatePoint(vertexList[i]); } return(aabbBounds); }
public static AABBBounds GetAABBBoundsOnTargetSpace(Transform targetSpaceTransform, List <Vector3> worldVertexList) { AABBBounds aabbBounds = new AABBBounds(); foreach (Vector3 vertex in worldVertexList) { Vector3 pointOnTargetSpace = targetSpaceTransform.worldToLocalMatrix.MultiplyPoint(vertex); aabbBounds.UpdatePoint(pointOnTargetSpace); } return(aabbBounds); }
/// <summary> /// 设置LightCamera 适应视角 /// </summary> /// <param name="lightTransform"></param> /// <param name="lightCamera"></param> /// <param name="mainCamera"></param> /// <param name="sceneConnerList"></param> private void SetLightCameraFitView(Transform lightTransform, Camera lightCamera, Camera mainCamera, List <Vector3> sceneConnerList) { List <Vector3> mainCameraFrustumConners = GetCameraPerspectiveFrustumConners(mainCamera); AABBBounds frustumBoundsInLightSpace = new AABBBounds(); mainCameraFrustumConners.ForEach(connerVertex => { Vector3 worldFrustumConner = mainCamera.transform.localToWorldMatrix.MultiplyPoint(connerVertex); Vector3 pointInLightSpace = lightTransform.worldToLocalMatrix.MultiplyPoint(worldFrustumConner); frustumBoundsInLightSpace.UpdatePoint(pointInLightSpace); }); AABBBounds sceneBounds = GetSceneAABBBoundsInTargetSpace(sceneConnerList, lightTransform); //计算Frustum 时,需要注意,如果Camera.farpanel 特别大,计算出的AABB太大, 所以可以采取AABBFrustum 跟 SceneAABB 相交作为最终的投影包围体 //或者设置farpanel neaarpanel到合理的大小 //lightCamera.transform.localPosition = new Vector3(frustumBoundsInLightSpace.Center.x, frustumBoundsInLightSpace.Center.y, frustumBoundsInLightSpace.Min.z - 0.05f); //lightCamera.orthographicSize = Mathf.Max(frustumBoundsInLightSpace.Extends.x, frustumBoundsInLightSpace.Extends.y); //lightCamera.nearClipPlane = 0.05f; //lightCamera.farClipPlane = 0.05f + (frustumBoundsInLightSpace.Size.z); Vector3 shadowCameraMin = new Vector3( Mathf.Max(sceneBounds.Min.x, frustumBoundsInLightSpace.Min.x), Mathf.Max(sceneBounds.Min.y, frustumBoundsInLightSpace.Min.y), Mathf.Max(sceneBounds.Min.z, frustumBoundsInLightSpace.Min.z)); Vector3 shadowCameraMax = new Vector3( Mathf.Min(sceneBounds.Max.x, frustumBoundsInLightSpace.Max.x), Mathf.Min(sceneBounds.Max.y, frustumBoundsInLightSpace.Max.y), Mathf.Min(sceneBounds.Max.z, frustumBoundsInLightSpace.Max.z)); Vector3 center = (shadowCameraMax + shadowCameraMin) / 2; Vector3 extends = (shadowCameraMax - shadowCameraMin) / 2; lightCamera.transform.localPosition = new Vector3(center.x, center.y, shadowCameraMin.z - 0.05f); lightCamera.orthographicSize = Mathf.Max(extends.x, extends.y); lightCamera.nearClipPlane = 0.05f; lightCamera.farClipPlane = 0.05f + (extends.z * 2); Matrix4x4 lightCameraProjectionUVMatrix = new Matrix4x4(); Vector3 transpose = new Vector3(0.5f, 0.5f, 0); Vector3 scale = new Vector3(0.5f, 0.5f, 1); lightCameraProjectionUVMatrix.SetTRS(transpose, Quaternion.identity, scale); lightCameraProjectionUVMatrix = lightCameraProjectionUVMatrix * GL.GetGPUProjectionMatrix(lightCamera.projectionMatrix, false) * lightCamera.worldToCameraMatrix; Shader.SetGlobalMatrix("_LightSpaceProjectionUVMatrix", lightCameraProjectionUVMatrix); }
private AABBBounds GetSceneAABBBoundsInTargetSpace(List <Vector3> worldConnerList, Transform targetSpace) { AABBBounds boundsInLightSpace = new AABBBounds(); worldConnerList.ForEach(worldConnerVertex => { Vector3 connerPosInLightSpace = targetSpace.worldToLocalMatrix.MultiplyPoint(worldConnerVertex); boundsInLightSpace.UpdatePoint(connerPosInLightSpace); }); return(boundsInLightSpace); }
public static AABBBounds GetAABBBoundsOnWorldSpace(List <Vector3> vertexList, Transform relativeToSpace) { AABBBounds aabbBounds = new AABBBounds(); foreach (Vector3 vertex in vertexList) { Vector3 worldPos = relativeToSpace.localToWorldMatrix.MultiplyPoint(vertex); aabbBounds.UpdatePoint(worldPos); } return(aabbBounds); }