private IEnumerator DoRendering(bool forceRenderFullMap = false)
        {
            yield return(new WaitForFixedUpdate());

            if (Rendering)
            {
                Log.Error("Progress Renderer is still rendering an image while a new rendering was requested. This can lead to missing or wrong data. (This can also happen in rare situations when you trigger manual rendering the exact same time as an automatic rendering happens. If you did that, just check your export folder if both renderings were done corrently and ignore this error.)");
            }
            Rendering = true;

            // Temporary switch to this map for rendering
            bool switchedMap   = false;
            Map  rememberedMap = Find.CurrentMap;

            if (map != rememberedMap)
            {
                switchedMap             = true;
                Current.Game.CurrentMap = map;
            }

            // Close world view if needed
            bool rememberedWorldRendered = WorldRendererUtility.WorldRenderedNow;

            if (rememberedWorldRendered)
            {
                CameraJumper.TryHideWorld();
            }

            // Calculate rendered area
            float startX = 0;
            float startZ = 0;
            float endX   = map.Size.x;
            float endZ   = map.Size.z;

            if (!forceRenderFullMap)
            {
                List <Designation> cornerMarkers = map.designationManager.allDesignations.FindAll(des => des.def == DesignationDefOf.CornerMarker);
                if (cornerMarkers.Count > 1)
                {
                    startX = endX;
                    startZ = endZ;
                    endX   = 0;
                    endZ   = 0;
                    foreach (Designation des in cornerMarkers)
                    {
                        IntVec3 cell = des.target.Cell;
                        if (cell.x < startX)
                        {
                            startX = cell.x;
                        }
                        if (cell.z < startZ)
                        {
                            startZ = cell.z;
                        }
                        if (cell.x > endX)
                        {
                            endX = cell.x;
                        }
                        if (cell.z > endZ)
                        {
                            endZ = cell.z;
                        }
                    }
                    endX += 1;
                    endZ += 1;
                }
            }

            // Only use smoothing when rendering was not triggered manually
            if (!manuallyTriggered)
            {
                // Test if target render area changed to reset smoothing
                if (rsTargetStartX != startX || rsTargetStartZ != startZ || rsTargetEndX != endX || rsTargetEndZ != endZ)
                {
                    // Check if area was manually reset or uninitialized (-1) to not smooth
                    if (rsTargetStartX == -1f && rsTargetStartZ == -1f && rsTargetEndX == -1f && rsTargetEndZ == -1f)
                    {
                        rsCurrentPosition = 1f;
                    }
                    else
                    {
                        rsCurrentPosition = 1f / (PRModSettings.smoothRenderAreaSteps + 1);
                    }
                    rsOldStartX    = rsTargetStartX;
                    rsOldStartZ    = rsTargetStartZ;
                    rsOldEndX      = rsTargetEndX;
                    rsOldEndZ      = rsTargetEndZ;
                    rsTargetStartX = startX;
                    rsTargetStartZ = startZ;
                    rsTargetEndX   = endX;
                    rsTargetEndZ   = endZ;
                }
                // Apply smoothing to render area
                if (rsCurrentPosition < 1f)
                {
                    startX             = rsOldStartX + (rsTargetStartX - rsOldStartX) * rsCurrentPosition;
                    startZ             = rsOldStartZ + (rsTargetStartZ - rsOldStartZ) * rsCurrentPosition;
                    endX               = rsOldEndX + (rsTargetEndX - rsOldEndX) * rsCurrentPosition;
                    endZ               = rsOldEndZ + (rsTargetEndZ - rsOldEndZ) * rsCurrentPosition;
                    rsCurrentPosition += 1f / (PRModSettings.smoothRenderAreaSteps + 1);
                }
            }

            float distX = endX - startX;
            float distZ = endZ - startZ;

            // Calculate basic values that are used for rendering
            int imageWidth;
            int imageHeight;

            if (PRModSettings.scaleOutputImage)
            {
                imageHeight = PRModSettings.outputImageFixedHeight;
                imageWidth  = (int)((float)imageHeight / distZ * distX);
            }
            else
            {
                imageWidth  = (int)(distX * PRModSettings.pixelPerCell);
                imageHeight = (int)(distZ * PRModSettings.pixelPerCell);
            }

            int renderCountX = (int)Math.Ceiling((float)imageWidth / RenderTextureSize);
            int renderCountZ = (int)Math.Ceiling((float)imageHeight / RenderTextureSize);
            int renderWidth  = (int)Math.Ceiling((float)imageWidth / renderCountX);
            int renderHeight = (int)Math.Ceiling((float)imageHeight / renderCountZ);

            float cameraPosX       = (float)distX / 2 / renderCountX;
            float cameraPosZ       = (float)distZ / 2 / renderCountZ;
            float orthographicSize = Math.Min(cameraPosX, cameraPosZ);

            orthographicSize = cameraPosZ;
            Vector3 cameraBasePos = new Vector3(cameraPosX, 15f + (orthographicSize - 11f) / 49f * 50f, cameraPosZ);

            RenderTexture renderTexture = RenderTexture.GetTemporary(renderWidth, renderHeight, 24);

            imageTexture = new Texture2D(imageWidth, imageHeight, TextureFormat.RGB24, false);

            Camera       camera    = Find.Camera;
            CameraDriver camDriver = camera.GetComponent <CameraDriver>();

            camDriver.enabled = false;

            // Store current camera data
            Vector3 rememberedRootPos      = map.rememberedCameraPos.rootPos;
            float   rememberedRootSize     = map.rememberedCameraPos.rootSize;
            float   rememberedFarClipPlane = camera.farClipPlane;

            // Overwrite current view rect in the camera driver
            CellRect camViewRect       = camDriver.CurrentViewRect;
            int      camRectMinX       = Math.Min((int)startX, camViewRect.minX);
            int      camRectMinZ       = Math.Min((int)startZ, camViewRect.minZ);
            int      camRectMaxX       = Math.Max((int)Math.Ceiling(endX), camViewRect.maxX);
            int      camRectMaxZ       = Math.Max((int)Math.Ceiling(endZ), camViewRect.maxZ);
            Traverse camDriverTraverse = Traverse.Create(camDriver);

            camDriverTraverse.Field("lastViewRect").SetValue(CellRect.FromLimits(camRectMinX, camRectMinZ, camRectMaxX, camRectMaxZ));
            camDriverTraverse.Field("lastViewRectGetFrame").SetValue(Time.frameCount);
            yield return(new WaitForEndOfFrame());

            // Set camera values needed for rendering
            camera.orthographicSize = orthographicSize;
            camera.farClipPlane     = cameraBasePos.y + 6.5f;

            // Create a temporary camera for rendering

            /*Camera tmpCam = Camera.Instantiate(camera);
             * tmpCam.orthographicSize = orthographicSize;
             * tmpCam.farClipPlane = cameraPos.y + 6.5f;*/

            // Set render textures
            //tmpCam.targetTexture = renderTexture;
            camera.targetTexture = renderTexture;
            RenderTexture.active = renderTexture;

            // Render the image texture
            try
            {
                if (PRModSettings.renderWeather)
                {
                    map.weatherManager.DrawAllWeather();
                }
                for (int i = 0; i < renderCountZ; i++)
                {
                    for (int j = 0; j < renderCountX; j++)
                    {
                        camera.transform.position = new Vector3(startX + cameraBasePos.x * (2 * j + 1), cameraBasePos.y, startZ + cameraBasePos.z * (2 * i + 1));
                        camera.Render();
                        imageTexture.ReadPixels(new Rect(0, 0, renderWidth, renderHeight), renderWidth * j, renderHeight * i, false);
                    }
                }
            } catch (Exception e)
            {
                Log.Error(e.Message, true);
            }

            // Restore camera and viewport
            RenderTexture.active = null;
            //tmpCam.targetTexture = null;
            camera.targetTexture = null;
            camera.farClipPlane  = rememberedFarClipPlane;
            camDriver.SetRootPosAndSize(rememberedRootPos, rememberedRootSize);
            camDriver.enabled = true;

            RenderTexture.ReleaseTemporary(renderTexture);

            // Switch back to world view if needed
            if (rememberedWorldRendered)
            {
                CameraJumper.TryShowWorld();
            }

            // Switch back to remembered map if needed
            if (switchedMap)
            {
                Current.Game.CurrentMap = rememberedMap;
            }

            // Sinal finished rendering
            Rendering = false;
            yield return(null);

            // Start encoding
            DoEncoding();

            yield break;
        }