Multi display. Extend the central screen virtually onto the lateral.

  • ExtasZ
  • Topic Author
More
3 weeks 5 days ago - 3 weeks 5 days ago #1 by ExtasZ Multi display. Extend the central screen virtually onto the lateral. was created by ExtasZ
/*                        --== Multi_2_Virtu V 1.2 ==--

   Helps align the image across monitors with different resolutions and PPI
   set bezel boundary and compensation
   Extends the central display virtually onto side monitors
   for a portrait-landscape-portrait
   in windowed mode: set the resolution to the sum of monitor widths on the X-axis with a slight reduction,
   and add 80-200 pixels to the height of the central monitor 
*/

//[Shader Options]

uniform float imageWidth
  < ui_type = "drag"; ui_label = "Image Width in Pixels";
    ui_min = 1; ui_max = 8000; ui_step = 1; > = 6000;

uniform float BezelBoundary 
  < ui_type = "drag"; ui_label = "Screen Bezel Boundary";
    ui_min = 0.0; ui_max = 1.0; ui_step = 0.0001; > = 0.1747;

uniform float BezelCompensationPixels
  < ui_type = "drag"; ui_label = "Bezel Compensation (Pixels)";
    ui_min = 0.0; ui_max = 100.0; ui_step = 1.0; > = 45;

uniform float LateralZoom
  < ui_type = "drag"; ui_label = "Zoom Level";
    ui_min = 0.5; ui_max = 2.0; ui_step = 0.0001; > = 0.7767;

uniform float CentralZoomY
  < ui_type = "drag"; ui_label = "Center Y Zoom Level";
    ui_min = 0.5; ui_max = 2.0; ui_step = 0.001; > = 1.211;

uniform float OffsetYCenter
  < ui_type = "drag"; ui_label = "Center Y Offset"; 
    ui_min = -1.0; ui_max = 1.0; ui_step = 0.001; > = 0.5; // offset and adding the recalibraion for the uv.y (no offset is 0.5)

uniform float2 ZoomYLat
  < ui_type = "drag"; ui_label = "Y Zoom for Lateral Zones (Outer | Inner)";
    ui_tooltip = "First value is for the outer edge, second for the inner edge of lateral zones.";
    ui_min = 0.5; ui_max = 3.0; ui_step = 0.001; > = float2(1.688, 1.663);

uniform float2 OffsetYLat
    < ui_type = "drag"; ui_label = "Y Offset for Lateral Zones (Outer | Inner)";
    ui_tooltip = "First value is for the outer edge, second for the inner edge of lateral zones.";
    ui_min = -1.0; ui_max = 1.0; ui_step = 0.001; > = float2(-0.261, -0.263);

//[Pixel Shader] 

#include "ReShade.fxh"

// Function to calculate the pixel source of the inner edge of the lateral zone
float CalculatePixelSourceAtBorder(float leftZoneEnd, float imageWidth, float lateralZoom)
{
    float uv_border = leftZoneEnd;
    float uv_source_x = (uv_border - 0.5) / lateralZoom + 0.5;
    float pixelX = uv_source_x * imageWidth;
    return pixelX;
}

// Function to calculate central zoom with bezel compensation
float CalculateCentralZoomWithBezel(float pixelSourceX, float imageWidth, float bezelCompensation, float centralStartUV)
{
    float nextPixelSourceX = pixelSourceX - bezelCompensation; // Compensation approx in pixels
    float uv_source_central = nextPixelSourceX / imageWidth;
    float centralZoom = (centralStartUV - 0.5) / (uv_source_central - 0.5);
    return centralZoom;
}

float4 PS_Multi_2_Virtu(float4 position : SV_Position, float2 uv : TEXCOORD0) : SV_Target
{
    // static const float only 1 time by frame precalculation
    // Define boundaries for each display zone
    static const float leftZoneEnd = BezelBoundary;
    static const float centerZoneEnd = 1.0 - BezelBoundary;
    // Automatic calculation of central zoom
    static const float pixelXAtBorder = CalculatePixelSourceAtBorder(leftZoneEnd, imageWidth, LateralZoom);
    static const float CentralZoom = CalculateCentralZoomWithBezel(pixelXAtBorder, imageWidth, BezelCompensationPixels, leftZoneEnd);

    float zoomFactor;       // global zoom

    if (uv.x < leftZoneEnd) // Left side
    {
        float t = uv.x / leftZoneEnd;
        zoomFactor = lerp(1.0, LateralZoom, t); // global zoom
        float zoomY = lerp(ZoomYLat.x, ZoomYLat.y, t); // Interpolate Y zoom
        float offsetY = lerp(OffsetYLat.x, OffsetYLat.y, t); // Interpolate Y offset
        uv.y = uv.y * zoomY + offsetY;
    }
    else if (uv.x < centerZoneEnd) // Center
    {
        zoomFactor = CentralZoom;  // global zoom
        uv.y = (-0.5 + uv.y) * CentralZoomY + OffsetYCenter ;    // Y zoom + Y Offset
    }
    else // Right side
    {
        float t = (uv.x - centerZoneEnd) / (1.0 - centerZoneEnd);
        zoomFactor = lerp(LateralZoom, 1.0, t); // global zoom 
        float zoomY = lerp(ZoomYLat.y, ZoomYLat.x, t); // Interpolate Y zoom
        float offsetY = lerp(OffsetYLat.y, OffsetYLat.x, t); // Interpolate Y offset
        uv.y = uv.y * zoomY + offsetY;
     }

    // Apply the global zoom factor to the UV coordinates
    float2 center = float2(0.5, 0.5);
    uv = lerp(center, uv, zoomFactor);
    float4 Color = tex2D(ReShade::BackBuffer, uv);
    return Color;
}

//[Technique]

technique Multi_to_Virtu <
    ui_tooltip = "Applies a customized backbuffer copy with individual zoom levels for central and lateral zones, including separate Y-axis zoom and vertical offsets for each zone."; >
{
    pass
    {
        BlendEnable = FALSE; // Disable blending to fully replace the image
        VertexShader = PostProcessVS;
        PixelShader  = PS_Multi_2_Virtu;
    }
}
Last edit: 3 weeks 5 days ago by ExtasZ.

Please Log in or Create an account to join the conversation.

  • ExtasZ
  • Topic Author
More
3 weeks 5 days ago - 3 weeks 5 days ago #2 by ExtasZ Replied by ExtasZ on topic Multi display. Extend the central screen virtually onto the lateral.
Of course, you need to play in windowed mode with a window size that covers the total width of your monitors, and you can position it wherever you want. Your setup should ideally be symmetrical, meaning you use two matching monitors for the side sections. For example, my setup is portrait (1080x1920) - landscape (3860x1600) - portrait (1080x1920). I play in windowed mode at a resolution of 5992x1720.Almost all games allow you to set custom resolutions in their configuration files.Another option is to use the Magnifier tool windows key + + but it doesn’t look as nice as playing in native windowed mode.
Last edit: 3 weeks 5 days ago by ExtasZ.

Please Log in or Create an account to join the conversation.

  • ExtasZ
  • Topic Author
More
3 weeks 2 days ago - 3 weeks 2 days ago #3 by ExtasZ Replied by ExtasZ on topic Multi display. Extend the central screen virtually onto the lateral.
For those who want to move a window outside the screen a little, like hiding the border and all, I made a PowerShell script for moving a window outside the monitor limits. Pixel
(0,0)
aligns with the coordinates of the OS.Save the script as
place.ps1
in a directory of your choice.
Script:
Add-Type -AssemblyName System.Windows.Forms

function Set-Window {
    param (
        [Parameter(Position = 0)]
        [string]$ProcessName,      # Process name
        [Parameter(Position = 1)]
        [int]$MonitorIndex,        # Monitor index
        [Parameter(Position = 2)]
        [int]$X,
        [Parameter(Position = 3)]
        [int]$Y
    )

    Add-Type @"
using System;
using System.Runtime.InteropServices;
public class Window {
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
    [DllImport("user32.dll")]
    public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
}
public struct RECT {
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}
"@

    # Retrieve the process by name
    $process = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue
    if (-not $process) {
        Write-Host "The process with the name '$ProcessName' is not running."
        return
    }

    $handle = $process.MainWindowHandle

    # Get the current window dimensions
    $rect = New-Object RECT
    [Window]::GetWindowRect($handle, [ref]$rect)

    # Preserve the current width and height while moving the window
    $currentWidth = $rect.Right - $rect.Left
    $currentHeight = $rect.Bottom - $rect.Top

    # Retrieve monitors
    $screens = [System.Windows.Forms.Screen]::AllScreens

    if ($MonitorIndex -ge $screens.Length -or $MonitorIndex -lt 0) {
        Write-Host "Invalid monitor index."
        return
    }

    # Get the position of the chosen monitor
    $monitor = $screens[$MonitorIndex]
    $monitorBounds = $monitor.Bounds

    # Move the window to the specified monitor
    [Window]::MoveWindow($handle, $monitorBounds.Left + $X, $monitorBounds.Top + $Y, $currentWidth, $currentHeight, $true)
}
Instructions:
  1. Find the process name of your application or game in the Task Manager (Ctrl + Alt + Delete). For example, for War Thunder, the process name is aces.exe 
  2. Launch PowerShell in administrator mode, navigate to the directory where you saved the script, and execute it:
  3. Use Set-Window command made by this script with the following arguments:
  • The name of your process.( without .exe)
  • The monitor ID (starting from 0 for the first monitor).
  • The X coordinate.
  • The Y coordinate.
cd c:\moving
. .\place.ps1
Set-Window aces 0 -3 -111

This will move the window to the specified position and can hide the borders (e.g., -3 -26 may remove the borders depending on your Windows theme).
of curse you dont see anymore border of windows so you will need to close your game like in full screen or in the task manager
you willl have the comman set-window aveable as long as you don't close your powersell session
Last edit: 3 weeks 2 days ago by ExtasZ. Reason: more clear

Please Log in or Create an account to join the conversation.

We use cookies
We use cookies on our website. Some of them are essential for the operation of the forum. You can decide for yourself whether you want to allow cookies or not. Please note that if you reject them, you may not be able to use all the functionalities of the site.