Multi display. Extend the central screen virtually onto the lateral.
- ExtasZ
- Topic Author
Less
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
Less
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
Less
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. Pixelaligns with the coordinates of the OS.Save the script asin a directory of your choice.
Script:
Instructions:
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
(0,0)
place.ps1
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)
}
- 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
- Launch PowerShell in administrator mode, navigate to the directory where you saved the script, and execute it:
- 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.