private void SetLocalMapCoordinates() { int resolution = Mathf.NextPowerOfTwo((thisCamera.pixelWidth + thisCamera.pixelHeight) >> 1); float maxHeight = 0.0f; float maxWaterLevel = 0.0f; var waters = WaterGlobals.Instance.Waters; int numWaterInstances = waters.Count; for (int waterIndex = 0; waterIndex < numWaterInstances; ++waterIndex) { var water = waters[waterIndex]; maxHeight += water.MaxVerticalDisplacement; float posY = water.transform.position.y; if (maxWaterLevel < posY) { maxWaterLevel = posY; } } // place camera Vector3 thisCameraPosition = thisCamera.transform.position; Vector3 screenSpaceDown = WaterUtilities.ViewportWaterPerpendicular(thisCamera); Vector3 worldSpaceDown = thisCamera.transform.localToWorldMatrix * WaterUtilities.RaycastPlane(thisCamera, maxWaterLevel, screenSpaceDown); Vector3 worldSpaceCenter = thisCamera.transform.localToWorldMatrix * WaterUtilities.RaycastPlane(thisCamera, maxWaterLevel, new Vector3(0.5f, 0.5f, 0.5f)); Vector3 effectCameraPosition; if (worldSpaceDown.sqrMagnitude > worldSpaceCenter.sqrMagnitude) { effectCameraPosition = new Vector3(thisCameraPosition.x + worldSpaceDown.x * 3.0f, 0.0f, thisCameraPosition.z + worldSpaceDown.z * 3.0f); } else { effectCameraPosition = new Vector3(thisCameraPosition.x + worldSpaceCenter.x * 3.0f, 0.0f, thisCameraPosition.z + worldSpaceCenter.z * 3.0f); } Vector3 diff = effectCameraPosition - thisCameraPosition; if (diff.magnitude > thisCamera.farClipPlane * 0.5f) { effectCameraPosition = thisCameraPosition + diff.normalized * thisCamera.farClipPlane * 0.5f; effectCameraPosition.y = 0.0f; } Vector3 thisCameraForward = thisCamera.transform.forward; float forwardFactor = Mathf.Min(1.0f, thisCameraForward.y + 1.0f); float size1 = thisCameraPosition.y * (1.0f + 7.0f * Mathf.Sqrt(forwardFactor)); float size2 = maxHeight * 2.5f; //float size3 = Vector3.Distance(effectCameraPosition, thisCameraPosition); //float size = size1 > size2 ? (size1 > size3 ? size1 : size3) : (size2 > size3 ? size2 : size3); float size = size1 > size2 ? size1 : size2; effectCameraPosition = new Vector3(thisCameraPosition.x + thisCameraForward.x * size * 0.4f, 0.0f, thisCameraPosition.z + thisCameraForward.z * size * 0.4f); localMapsRectPrevious = localMapsRect; float halfPixelSize = size / resolution; localMapsRect = new Rect((effectCameraPosition.x - size) + halfPixelSize, (effectCameraPosition.z - size) + halfPixelSize, 2.0f * size, 2.0f * size); Shader.SetGlobalVector("_LocalMapsCoordsPrevious", new Vector4(-localMapsRectPrevious.xMin, -localMapsRectPrevious.yMin, 1.0f / localMapsRectPrevious.width, localMapsRectPrevious.width)); Shader.SetGlobalVector("_LocalMapsCoords", new Vector4(-localMapsRect.xMin, -localMapsRect.yMin, 1.0f / localMapsRect.width, localMapsRect.width)); }
protected override Matrix4x4 GetMatrix(Camera camera) { Vector3 down = WaterUtilities.ViewportWaterPerpendicular(camera); Vector3 right = WaterUtilities.ViewportWaterRight(camera); float waterPositionY = water.transform.position.y; Vector3 ld = WaterUtilities.RaycastPlane(camera, waterPositionY, (down - right)); Vector3 rd = WaterUtilities.RaycastPlane(camera, waterPositionY, (down + right)); float farClipPlane = camera.farClipPlane; float fieldOfViewTan = Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad); Vector3 position = camera.transform.position; Vector3 scale = camera.orthographic ? new Vector3(farClipPlane, farClipPlane, farClipPlane) : new Vector3(farClipPlane * fieldOfViewTan * camera.aspect + water.MaxHorizontalDisplacement * 2, farClipPlane, farClipPlane); float width = rd.x - ld.x; if (width < 0.0f) { width = -width; } float offset = (ld.z < rd.z ? ld.z : rd.z) - (width + water.MaxHorizontalDisplacement * 2.0f) * scale.z / scale.x; if (camera.orthographic) { offset -= camera.orthographicSize * 3.2f; } Vector3 backward; float dp = camera.transform.forward.y; // Vector3.Dot(Vector3.down, camera.transform.forward) if (dp < -0.98f || dp > 0.98f) { backward = -camera.transform.up; float len = Mathf.Sqrt(backward.x * backward.x + backward.z * backward.z); backward.x /= len; backward.z /= len; if (!camera.orthographic) { offset = -position.y * 4.0f * fieldOfViewTan; } } else { backward = camera.transform.forward; float len = Mathf.Sqrt(backward.x * backward.x + backward.z * backward.z); backward.x /= len; backward.z /= len; } if (!camera.orthographic) { scale.z -= offset; } return(Matrix4x4.TRS( new Vector3(position.x + backward.x * offset, waterPositionY, position.z + backward.z * offset), Quaternion.AngleAxis(Mathf.Atan2(backward.x, backward.z) * Mathf.Rad2Deg, Vector3.up), scale )); }