From 3cd334b61e01fbb55edabe470bbae7dba0591eee Mon Sep 17 00:00:00 2001 From: jp9000 Date: Wed, 20 Mar 2013 17:10:05 -0700 Subject: [PATCH] Added bicubic and lanczos downscale shaders, optimized existing bilinear downscale shaders --- OBS.rc | 14 +-- Source/OBS.h | 1 + Source/OBSCapture.cpp | 22 ++-- Source/OBSVideoCapture.cpp | 11 +- Source/Settings.h | 1 + Source/SettingsVideo.cpp | 57 +++++++++- resource.h | 2 + rundir/locale/en.txt | 5 + rundir/shaders/DownscaleBicubicYUV.pShader | 91 ++++++++++++++++ ....pShader => DownscaleBilinear1YUV.pShader} | 14 +-- ....pShader => DownscaleBilinear9YUV.pShader} | 40 +++---- .../shaders/DownscaleLanczos6tapYUV.pShader | 102 ++++++++++++++++++ rundir/shaders/DownscaleYUV2.25.pShader | 102 ------------------ rundir/shaders/DownscaleYUV3.pShader | 61 ----------- 14 files changed, 306 insertions(+), 217 deletions(-) create mode 100644 rundir/shaders/DownscaleBicubicYUV.pShader rename rundir/shaders/{DownscaleYUV2.pShader => DownscaleBilinear1YUV.pShader} (73%) rename rundir/shaders/{DownscaleYUV1.5.pShader => DownscaleBilinear9YUV.pShader} (58%) create mode 100644 rundir/shaders/DownscaleLanczos6tapYUV.pShader delete mode 100644 rundir/shaders/DownscaleYUV2.25.pShader delete mode 100644 rundir/shaders/DownscaleYUV3.pShader diff --git a/OBS.rc b/OBS.rc index f31f5a5d..f7e4243d 100644 --- a/OBS.rc +++ b/OBS.rc @@ -139,12 +139,14 @@ BEGIN CONTROL "Settings.Video.Monitor",IDC_USEMONITOR,"Button",BS_AUTORADIOBUTTON,22,31,116,10 COMBOBOX IDC_MONITOR,144,30,36,126,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP RTEXT "Settings.Video.Downscale",IDC_STATIC,4,61,138,8 - COMBOBOX IDC_DOWNSCALE,144,59,151,126,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - RTEXT "Settings.Video.FPS",IDC_STATIC,4,80,138,8 - EDITTEXT IDC_FPS_EDIT,144,77,40,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_FPS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,185,77,10,14 - LTEXT "Settings.Info",IDC_INFO,7,117,418,37,NOT WS_VISIBLE - CONTROL "Settings.Video.DisableAero",IDC_DISABLEAERO,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,4,96,149,10,WS_EX_RIGHT + COMBOBOX IDC_DOWNSCALE,144,59,144,126,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + RTEXT "Settings.Video.Filter",IDC_STATIC,4,78,138,8 + COMBOBOX IDC_FILTER,144,76,234,126,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + RTEXT "Settings.Video.FPS",IDC_STATIC,4,96,138,8 + EDITTEXT IDC_FPS_EDIT,144,93,40,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_FPS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,185,93,10,14 + LTEXT "Settings.Info",IDC_INFO,7,133,418,37,NOT WS_VISIBLE + CONTROL "Settings.Video.DisableAero",IDC_DISABLEAERO,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,4,112,149,10,WS_EX_RIGHT END IDD_SETTINGS_GENERAL DIALOGEX 0, 0, 427, 336 diff --git a/Source/OBS.h b/Source/OBS.h index 89b8e1c6..71c28de6 100644 --- a/Source/OBS.h +++ b/Source/OBS.h @@ -536,6 +536,7 @@ private: UINT scaleCX, scaleCY; UINT outputCX, outputCY; float downscale; + int downscaleType; UINT frameTime, fps; bool bUsing444; diff --git a/Source/OBSCapture.cpp b/Source/OBSCapture.cpp index f3efcc00..efa1e23e 100644 --- a/Source/OBSCapture.cpp +++ b/Source/OBSCapture.cpp @@ -139,6 +139,7 @@ void OBS::Start() int defCX = screenRect.right - screenRect.left; int defCY = screenRect.bottom - screenRect.top; + downscaleType = AppConfig->GetInt(TEXT("Video"), TEXT("Filter"), 0); downscale = AppConfig->GetFloat(TEXT("Video"), TEXT("Downscale"), 1.0f); baseCX = AppConfig->GetInt(TEXT("Video"), TEXT("BaseWidth"), defCX); baseCY = AppConfig->GetInt(TEXT("Video"), TEXT("BaseHeight"), defCY); @@ -179,17 +180,20 @@ void OBS::Start() //------------------------------------------------------------------ - CTSTR lpShader = NULL; + CTSTR lpShader; if(CloseFloat(downscale, 1.0)) lpShader = TEXT("shaders/DrawYUVTexture.pShader"); - else if(CloseFloat(downscale, 1.5)) - lpShader = TEXT("shaders/DownscaleYUV1.5.pShader"); - else if(CloseFloat(downscale, 2.0)) - lpShader = TEXT("shaders/DownscaleYUV2.pShader"); - else if(CloseFloat(downscale, 2.25)) - lpShader = TEXT("shaders/DownscaleYUV2.25.pShader"); - else if(CloseFloat(downscale, 3.0)) - lpShader = TEXT("shaders/DownscaleYUV3.pShader"); + else if(downscale < 2.01) + { + switch(downscaleType) + { + case 0: lpShader = TEXT("shaders/DownscaleBilinear1YUV.pShader"); break; + case 1: lpShader = TEXT("shaders/DownscaleBicubicYUV.pShader"); break; + case 2: lpShader = TEXT("shaders/DownscaleLanczos6tapYUV.pShader"); break; + } + } + else if(downscale < 3.01) + lpShader = TEXT("shaders/DownscaleBilinear9YUV.pShader"); else CrashError(TEXT("Invalid downscale value (must be either 1.0, 1.5, 2.0, 2.25, or 3.0)")); diff --git a/Source/OBSVideoCapture.cpp b/Source/OBSVideoCapture.cpp index 8635133d..ae552618 100644 --- a/Source/OBSVideoCapture.cpp +++ b/Source/OBSVideoCapture.cpp @@ -602,7 +602,7 @@ void OBS::MainCaptureLoop() if(renderFrameCtrlSize.x != oldRenderFrameCtrlWidth || renderFrameCtrlSize.y != oldRenderFrameCtrlHeight) { // User is drag resizing the window. We don't recreate the swap chains so our coordinates are wrong - SetViewport(0.0f, 0.0f, oldRenderFrameCtrlWidth, oldRenderFrameCtrlHeight); + SetViewport(0.0f, 0.0f, (float)oldRenderFrameCtrlWidth, (float)oldRenderFrameCtrlHeight); } else SetViewport(0.0f, 0.0f, renderFrameCtrlSize.x, renderFrameCtrlSize.y); @@ -653,7 +653,10 @@ void OBS::MainCaptureLoop() Texture *yuvRenderTexture = yuvRenderTextures[curRenderTarget]; SetRenderTarget(yuvRenderTexture); - yuvScalePixelShader->SetVector2(hScaleVal, 1.0f/baseSize); + if(downscale < 2.01) + yuvScalePixelShader->SetVector2(hScaleVal, 1.0f/baseSize); + else if(downscale < 3.01) + yuvScalePixelShader->SetVector2(hScaleVal, 1.0f/(outputSize*3.0f)); Ortho(0.0f, outputSize.x, outputSize.y, 0.0f, -100.0f, 100.0f); SetViewport(0.0f, 0.0f, outputSize.x, outputSize.y); @@ -664,11 +667,11 @@ void OBS::MainCaptureLoop() if(bTransitioning) { BlendFunction(GS_BLEND_ONE, GS_BLEND_ZERO); - DrawSpriteEx(transitionTexture, 0xFFFFFFFF, 0.0f, 0.0f, scaleSize.x, scaleSize.y, 0.0f, 0.0f, scaleSize.x, scaleSize.y); + DrawSpriteEx(transitionTexture, 0xFFFFFFFF, 0.0f, 0.0f, scaleSize.x, scaleSize.y, 0.0f, 0.0f, 1.0f, 1.0f); BlendFunction(GS_BLEND_FACTOR, GS_BLEND_INVFACTOR, transitionAlpha); } - DrawSpriteEx(mainRenderTextures[curRenderTarget], 0xFFFFFFFF, 0.0f, 0.0f, outputSize.x, outputSize.y, 0.0f, 0.0f, outputSize.x, outputSize.y); + DrawSpriteEx(mainRenderTextures[curRenderTarget], 0xFFFFFFFF, 0.0f, 0.0f, outputSize.x, outputSize.y, 0.0f, 0.0f, 1.0f, 1.0f); //------------------------------------ diff --git a/Source/Settings.h b/Source/Settings.h index 9654b216..5e0c308c 100644 --- a/Source/Settings.h +++ b/Source/Settings.h @@ -140,6 +140,7 @@ public: private: void RefreshDownscales(HWND hwnd, int cx, int cy); + void RefreshFilters(HWND hwndParent, bool bGetConfig); public: // Interface diff --git a/Source/SettingsVideo.cpp b/Source/SettingsVideo.cpp index a2eb4f7f..ba915f3d 100644 --- a/Source/SettingsVideo.cpp +++ b/Source/SettingsVideo.cpp @@ -52,8 +52,8 @@ LRESULT WINAPI ResolutionEditSubclassProc(HWND hwnd, UINT message, WPARAM wParam return CallWindowProc((WNDPROC)editProc, hwnd, message, wParam, lParam); } -const int multiplierCount = 5; -const float downscaleMultipliers[multiplierCount] = {1.0f, 1.5f, 2.0f, 2.25f, 3.0f}; +const int multiplierCount = 9; +const float downscaleMultipliers[multiplierCount] = {1.0f, 1.25f, 1.5f, 1.75f, 2.0f, 2.25f, 2.5f, 2.75f, 3.0f}; //============================================================================ // SettingsVideo class @@ -132,6 +132,41 @@ void SettingsVideo::RefreshDownscales(HWND hwnd, int cx, int cy) SendMessage(hwnd, CB_SETCURSEL, lastID, 0); } +void SettingsVideo::RefreshFilters(HWND hwndParent, bool bGetConfig) +{ + HWND hwndFilter = GetDlgItem(hwndParent, IDC_FILTER); + HWND hwndDownscale = GetDlgItem(hwndParent, IDC_DOWNSCALE); + + int curFilter; + if(bGetConfig) + curFilter = AppConfig->GetInt(TEXT("Video"), TEXT("Filter"), 0); + else + curFilter = (int)SendMessage(GetDlgItem(hwnd, IDC_FILTER), CB_GETCURSEL, 0, 0); + + float downscale = 1.0f; + + int curSel = (int)SendMessage(GetDlgItem(hwnd, IDC_DOWNSCALE), CB_GETCURSEL, 0, 0); + if(curSel != CB_ERR) + downscale = downscaleMultipliers[curSel]; + + SendMessage(hwndFilter, CB_RESETCONTENT, 0, 0); + if(downscale < 2.01) + { + SendMessage(hwndFilter, CB_ADDSTRING, 0, (LPARAM)Str("Settings.Video.Filter.Bilinear")); + SendMessage(hwndFilter, CB_ADDSTRING, 0, (LPARAM)Str("Settings.Video.Filter.Bicubic")); + SendMessage(hwndFilter, CB_ADDSTRING, 0, (LPARAM)Str("Settings.Video.Filter.Lanczos")); + + SendMessage(hwndFilter, CB_SETCURSEL, curFilter, 0); + } + else + { + SendMessage(hwndFilter, CB_ADDSTRING, 0, (LPARAM)Str("Settings.Video.Filter.Bilinear")); + SendMessage(hwndFilter, CB_SETCURSEL, 0, 0); + } + + EnableWindow(hwndFilter, (downscale > 1.01)); +} + void SettingsVideo::ApplySettings() { int curSel = (int)SendMessage(GetDlgItem(hwnd, IDC_MONITOR), CB_GETCURSEL, 0, 0); @@ -157,6 +192,10 @@ void SettingsVideo::ApplySettings() if(curSel != CB_ERR) AppConfig->SetFloat(TEXT("Video"), TEXT("Downscale"), downscaleMultipliers[curSel]); + curSel = (int)SendMessage(GetDlgItem(hwnd, IDC_FILTER), CB_GETCURSEL, 0, 0); + if(curSel == CB_ERR) curSel = 0; + AppConfig->SetInt(TEXT("Video"), TEXT("Filter"), curSel); + int gammaVal = (int)SendMessage(GetDlgItem(hwnd, IDC_GAMMA), TBM_GETPOS, 0, 0); AppConfig->SetInt(TEXT("Video"), TEXT("Gamma"), gammaVal); @@ -297,6 +336,10 @@ INT_PTR SettingsVideo::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam) //-------------------------------------------- + RefreshFilters(hwnd, true); + + //-------------------------------------------- + ShowWindow(GetDlgItem(hwnd, IDC_INFO), SW_HIDE); SetChangedSettings(false); @@ -396,10 +439,18 @@ INT_PTR SettingsVideo::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam) bDataChanged = true; break; - case IDC_DOWNSCALE: + case IDC_FILTER: if(HIWORD(wParam) == CBN_SELCHANGE) bDataChanged = true; break; + + case IDC_DOWNSCALE: + if(HIWORD(wParam) == CBN_SELCHANGE) + { + bDataChanged = true; + RefreshFilters(hwnd, false); + } + break; } if(bDataChanged) diff --git a/resource.h b/resource.h index 2de5d5d1..2f0e1f86 100644 --- a/resource.h +++ b/resource.h @@ -48,6 +48,8 @@ #define IDC_BINDIP 1014 #define IDC_MAXBITRATE 1015 #define IDC_COLORPICKER 1015 +#define IDC_DOWNSCALE2 1015 +#define IDC_FILTER 1015 #define IDC_BUFFERSIZE 1016 #define IDC_AUDIOCODEC 1017 #define IDC_USECOLORKEY 1017 diff --git a/rundir/locale/en.txt b/rundir/locale/en.txt index dd26db2b..7b6f2301 100644 --- a/rundir/locale/en.txt +++ b/rundir/locale/en.txt @@ -196,10 +196,15 @@ Settings.Video.DisableAero "Disable Aero at startup:" Settings.Video.DisableAeroTooltip "Disabling Aero is recommended if using software monitor capture" Settings.Video.Downscale "Resolution Downscale:" Settings.Video.DownscaleTooltip "Downscale can improve video quality at the cost of resolution." +Settings.Video.Filter "Filter:" Settings.Video.FPS "FPS:" Settings.Video.Monitor "Monitor:" Settings.Video.Resolution "Base Resolution:" +Settings.Video.Filter.Bilinear "Bilinear (fastest)" +Settings.Video.Filter.Bicubic "Bicubic sharper (good detail, 16 samples)" +Settings.Video.Filter.Lanczos "Lanczos (best detail, 36 samples)" + Sources.BitmapSource "Image" Sources.GameCaptureSource "Game Capture" Sources.GlobalSource "Global Source" diff --git a/rundir/shaders/DownscaleBicubicYUV.pShader b/rundir/shaders/DownscaleBicubicYUV.pShader new file mode 100644 index 00000000..95d6aa94 --- /dev/null +++ b/rundir/shaders/DownscaleBicubicYUV.pShader @@ -0,0 +1,91 @@ +uniform Texture2D diffuseTexture; +uniform float2 baseDimensionI; + +SamplerState textureSampler +{ + AddressU = Clamp; + AddressV = Clamp; + Filter = Linear; +}; + +struct VertData +{ + float4 pos : SV_Position; + float2 texCoord : TexCoord0; +}; + +float weight(float x) +{ + float ax = abs(x); + // Sharper version. + // May look better in some cases. + const float B = 0.0; + const float C = 0.75; + + if (ax < 1.0) + return (pow(x, 2.0) * ((12.0 - 9.0 * B - 6.0 * C) * ax + (-18.0 + 12.0 * B + 6.0 * C)) + (6.0 - 2.0 * B)) / 6.0; + else if ((ax >= 1.0) && (ax < 2.0)) + return (pow(x, 2.0) * ((-B - 6.0 * C) * ax + (6.0 * B + 30.0 * C)) + (-12.0 * B - 48.0 * C) * ax + (8.0 * B + 24.0 * C)) / 6.0; + else + return 0.0; +} + +float4 weight4(float x) +{ + return float4( + weight(x - 2.0), + weight(x - 1.0), + weight(x), + weight(x + 1.0)); +} + +float3 pixel(float xpos, float ypos) +{ + return diffuseTexture.Sample(textureSampler, float2(xpos, ypos)).rgb; +} + +float3 get_line(float ypos, float4 xpos, float4 linetaps) +{ + return + pixel(xpos.r, ypos) * linetaps.r + + pixel(xpos.g, ypos) * linetaps.g + + pixel(xpos.b, ypos) * linetaps.b + + pixel(xpos.a, ypos) * linetaps.a; +} + +float4 main(VertData input) : SV_Target +{ + float2 stepxy = baseDimensionI; + float2 pos = input.texCoord + stepxy * 0.5; + float2 f = frac(pos / stepxy); + + float4 linetaps = weight4(1.0 - f.x); + float4 columntaps = weight4(1.0 - f.y); + + //make sure all taps added together is exactly 1.0, otherwise some (very small) distortion can occur + linetaps /= linetaps.r + linetaps.g + linetaps.b + linetaps.a; + columntaps /= columntaps.r + columntaps.g + columntaps.b + columntaps.a; + + float2 xystart = (-1.5 - f) * stepxy + pos; + float4 xpos = float4(xystart.x, xystart.x + stepxy.x, xystart.x + stepxy.x * 2.0, xystart.x + stepxy.x * 3.0); + + float4 rgba; + rgba.rgb = + get_line(xystart.y , xpos, linetaps) * columntaps.r + + get_line(xystart.y + stepxy.y , xpos, linetaps) * columntaps.g + + get_line(xystart.y + stepxy.y * 2.0, xpos, linetaps) * columntaps.b + + get_line(xystart.y + stepxy.y * 3.0, xpos, linetaps) * columntaps.a; + + rgba.a = 1.0; + + //------------------------------------------------------------- + + const float4x4 yuvMat = {0.257, -0.148, 0.439, 0.0, + 0.504, -0.291, -0.368, 0.0, + 0.098, 0.439, -0.071, 0.0, + 0.0625, 0.50, 0.50, 1.0}; + + //a nice quick colorspace conversion + float4 yuvx = mul(float4(rgba.rgb, 1.0), yuvMat); + return float4(saturate(yuvx.zxy), rgba.a); +} diff --git a/rundir/shaders/DownscaleYUV2.pShader b/rundir/shaders/DownscaleBilinear1YUV.pShader similarity index 73% rename from rundir/shaders/DownscaleYUV2.pShader rename to rundir/shaders/DownscaleBilinear1YUV.pShader index c028c6ed..89542296 100644 --- a/rundir/shaders/DownscaleYUV2.pShader +++ b/rundir/shaders/DownscaleBilinear1YUV.pShader @@ -1,5 +1,5 @@ /******************************************************************************** - Copyright (C) 2012 Hugh Bailey + Copyright (C) 2013 Hugh Bailey This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -35,15 +35,11 @@ struct VertData float4 main(VertData input) : SV_Target { - float2 texAdjust = (input.texCoord-0.5)*2.0; - float2 floorVal = floor(texAdjust+0.001); - float4 rgba; - rgba = diffuseTexture.Sample(textureSampler, (floorVal+float2(0.5f, 0.5f)) * baseDimensionI); - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(1.5f, 0.5f)) * baseDimensionI); - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(0.5f, 1.5f)) * baseDimensionI); - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(1.5f, 1.5f)) * baseDimensionI); - rgba *= 0.25; + rgba.rgb = diffuseTexture.Sample(textureSampler, input.texCoord); + rgba.a = 1.0; + + //------------------------------------------------------------- const float4x4 yuvMat = {0.257, -0.148, 0.439, 0.0, 0.504, -0.291, -0.368, 0.0, diff --git a/rundir/shaders/DownscaleYUV1.5.pShader b/rundir/shaders/DownscaleBilinear9YUV.pShader similarity index 58% rename from rundir/shaders/DownscaleYUV1.5.pShader rename to rundir/shaders/DownscaleBilinear9YUV.pShader index 75011ebb..ab86a462 100644 --- a/rundir/shaders/DownscaleYUV1.5.pShader +++ b/rundir/shaders/DownscaleBilinear9YUV.pShader @@ -1,5 +1,5 @@ /******************************************************************************** - Copyright (C) 2012 Hugh Bailey + Copyright (C) 2013 Hugh Bailey This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,8 +17,6 @@ ********************************************************************************/ -//1.5 downscale requires kind of a lot of sampling, more sampling than there are pixels on the base texture - uniform Texture2D diffuseTexture; uniform float2 baseDimensionI; @@ -37,28 +35,24 @@ struct VertData float4 main(VertData input) : SV_Target { - float2 texAdjust = (input.texCoord-0.5)*1.5; - float2 floorVal = floor(texAdjust+0.001); - float2 offset = (texAdjust-floorVal); - - float2x2 pixelMat = {1.0, 1.0, 1.0, 1.0}; - - if(offset.x > 0.4) - pixelMat._11_21 = 0.5; - else - pixelMat._12_22 = 0.5; - - if(offset.y > 0.4) - pixelMat._11_12 *= 0.5; - else - pixelMat._21_22 *= 0.5; + float2 texCoord = input.texCoord; + float2 adjust = baseDimensionI; float4 rgba; - rgba = diffuseTexture.Sample(textureSampler, (floorVal+float2(0.5, 0.5)) * baseDimensionI) * pixelMat._11; - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(1.5, 0.5)) * baseDimensionI) * pixelMat._12; - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(0.5, 1.5)) * baseDimensionI) * pixelMat._21; - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(1.5, 1.5)) * baseDimensionI) * pixelMat._22; - rgba /= 2.25; + rgba.rgb = diffuseTexture.Sample(textureSampler, texCoord).rgb; + rgba.rgb += diffuseTexture.Sample(textureSampler, texCoord + float2(-adjust.x, -adjust.y)).rgb; + rgba.rgb += diffuseTexture.Sample(textureSampler, texCoord + float2(-adjust.x, 0.0)).rgb; + rgba.rgb += diffuseTexture.Sample(textureSampler, texCoord + float2(-adjust.x, adjust.y)).rgb; + rgba.rgb += diffuseTexture.Sample(textureSampler, texCoord + float2( 0.0, -adjust.y)).rgb; + rgba.rgb += diffuseTexture.Sample(textureSampler, texCoord + float2( 0.0, adjust.y)).rgb; + rgba.rgb += diffuseTexture.Sample(textureSampler, texCoord + float2( adjust.x, -adjust.y)).rgb; + rgba.rgb += diffuseTexture.Sample(textureSampler, texCoord + float2( adjust.x, 0.0)).rgb; + rgba.rgb += diffuseTexture.Sample(textureSampler, texCoord + float2( adjust.x, adjust.y)).rgb; + rgba.rgb /= 9.0; + + rgba.a = 1.0; + + //------------------------------------------------------------- const float4x4 yuvMat = {0.257, -0.148, 0.439, 0.0, 0.504, -0.291, -0.368, 0.0, diff --git a/rundir/shaders/DownscaleLanczos6tapYUV.pShader b/rundir/shaders/DownscaleLanczos6tapYUV.pShader new file mode 100644 index 00000000..f4b72661 --- /dev/null +++ b/rundir/shaders/DownscaleLanczos6tapYUV.pShader @@ -0,0 +1,102 @@ +uniform Texture2D diffuseTexture; +uniform float2 baseDimensionI; + +SamplerState textureSampler +{ + AddressU = Clamp; + AddressV = Clamp; + Filter = Linear; +}; + +struct VertData +{ + float4 pos : SV_Position; + float2 texCoord : TexCoord0; +}; + +float sinc(float x) +{ + const float PIval = 3.1415926535897932384626433832795; + return sin(x * PIval) / (x * PIval); +} + +float weight(float x, float radius) +{ + float ax = abs(x); + if (x == 0.0) + return 1.0; + else if (ax < radius) + return sinc(x) * sinc(x / radius); + else + return 0.0; +} + +float3 weight3(float x) +{ + return float3( + weight(x * 2.0 + 0.0 * 2.0 - 3.0, 3.0), + weight(x * 2.0 + 1.0 * 2.0 - 3.0, 3.0), + weight(x * 2.0 + 2.0 * 2.0 - 3.0, 3.0)); +} + +float3 pixel(float xpos, float ypos) +{ + return diffuseTexture.Sample(textureSampler, float2(xpos, ypos)).rgb; +} + +float3 get_line(float ypos, float3 xpos1, float3 xpos2, float3 linetaps1, float3 linetaps2) +{ + return + pixel(xpos1.r, ypos) * linetaps1.r + + pixel(xpos1.g, ypos) * linetaps2.r + + pixel(xpos1.b, ypos) * linetaps1.g + + pixel(xpos2.r, ypos) * linetaps2.g + + pixel(xpos2.g, ypos) * linetaps1.b + + pixel(xpos2.b, ypos) * linetaps2.b; +} + +float4 main(VertData input) : SV_Target +{ + float2 stepxy = baseDimensionI; + float2 pos = input.texCoord + stepxy * 0.5; + float2 f = frac(pos / stepxy); + + float3 linetaps1 = weight3((1.0 - f.x) / 2.0); + float3 linetaps2 = weight3((1.0 - f.x) / 2.0 + 0.5); + float3 columntaps1 = weight3((1.0 - f.y) / 2.0); + float3 columntaps2 = weight3((1.0 - f.y) / 2.0 + 0.5); + + //make sure all taps added together is exactly 1.0, otherwise some (very small) distortion can occur + float suml = linetaps1.r + linetaps1.g + linetaps1.b + linetaps2.r + linetaps2.g + linetaps2.b; + float sumc = columntaps1.r + columntaps1.g + columntaps1.b + columntaps2.r + columntaps2.g + columntaps2.b; + linetaps1 /= suml; + linetaps2 /= suml; + columntaps1 /= sumc; + columntaps2 /= sumc; + + float2 xystart = (-2.5 - f) * stepxy + pos; + float3 xpos1 = float3(xystart.x, xystart.x + stepxy.x, xystart.x + stepxy.x * 2.0); + float3 xpos2 = float3(xystart.x + stepxy.x * 3.0, xystart.x + stepxy.x * 4.0, xystart.x + stepxy.x * 5.0); + + float4 rgba; + rgba.rgb = + get_line(xystart.y , xpos1, xpos2, linetaps1, linetaps2) * columntaps1.r + + get_line(xystart.y + stepxy.y , xpos1, xpos2, linetaps1, linetaps2) * columntaps2.r + + get_line(xystart.y + stepxy.y * 2.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps1.g + + get_line(xystart.y + stepxy.y * 3.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps2.g + + get_line(xystart.y + stepxy.y * 4.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps1.b + + get_line(xystart.y + stepxy.y * 5.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps2.b; + + rgba.a = 1.0; + + //------------------------------------------------------------- + + const float4x4 yuvMat = {0.257, -0.148, 0.439, 0.0, + 0.504, -0.291, -0.368, 0.0, + 0.098, 0.439, -0.071, 0.0, + 0.0625, 0.50, 0.50, 1.0}; + + //a nice quick colorspace conversion + float4 yuvx = mul(float4(rgba.rgb, 1.0), yuvMat); + return float4(saturate(yuvx.zxy), rgba.a); +} diff --git a/rundir/shaders/DownscaleYUV2.25.pShader b/rundir/shaders/DownscaleYUV2.25.pShader deleted file mode 100644 index aecfe447..00000000 --- a/rundir/shaders/DownscaleYUV2.25.pShader +++ /dev/null @@ -1,102 +0,0 @@ -/******************************************************************************** - Copyright (C) 2012 Hugh Bailey - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -********************************************************************************/ - - -//2.25 is also pretty bad - -uniform Texture2D diffuseTexture; -uniform float2 baseDimensionI; - -SamplerState textureSampler -{ - AddressU = Clamp; - AddressV = Clamp; - Filter = Linear; -}; - -struct VertData -{ - float4 pos : SV_Position; - float2 texCoord : TexCoord0; -}; - -float4 main(VertData input) : SV_Target -{ - float2 texAdjust = (input.texCoord-0.5)*2.25; - float2 floorVal = floor(texAdjust+0.001); - float2 offset = (texAdjust-floorVal); - - float3x3 pixelMat = - { - 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0 - }; - - if(offset.x < 0.25) - pixelMat._13_23_33 = 0.25; - else if(offset.x < 0.5) //0.25 - { - pixelMat._11_21_31 = 0.75; - pixelMat._13_23_33 = 0.5; - } - else if(offset.x < 0.75) //0.5 - { - pixelMat._11_21_31 = 0.5; - pixelMat._13_23_33 = 0.75; - } - else if(offset.x < 1.0) //0.75 - pixelMat._11_21_31 = 0.25; - - - if(offset.y < 0.25) - pixelMat._31_32_33 *= 0.25; - else if(offset.y < 0.5) //0.25 - { - pixelMat._11_12_13 *= 0.75; - pixelMat._31_32_33 *= 0.5; - } - else if(offset.y < 0.75) //0.5 - { - pixelMat._11_12_13 *= 0.5; - pixelMat._31_32_33 *= 0.75; - } - else if(offset.y < 1.0) //0.75 - pixelMat._11_12_13 *= 0.25; - - float4 rgba; - rgba = diffuseTexture.Sample(textureSampler, (floorVal+float2(0.5, 0.5)) * baseDimensionI) * pixelMat._11; - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(1.5, 0.5)) * baseDimensionI) * pixelMat._12; - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(2.5, 0.5)) * baseDimensionI) * pixelMat._13; - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(0.5, 1.5)) * baseDimensionI) * pixelMat._21; - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(1.5, 1.5)) * baseDimensionI) * pixelMat._22; - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(2.5, 1.5)) * baseDimensionI) * pixelMat._23; - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(0.5, 2.5)) * baseDimensionI) * pixelMat._31; - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(1.5, 2.5)) * baseDimensionI) * pixelMat._32; - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(2.5, 2.5)) * baseDimensionI) * pixelMat._33; - rgba /= 5.0625; - - const float4x4 yuvMat = {0.257, -0.148, 0.439, 0.0, - 0.504, -0.291, -0.368, 0.0, - 0.098, 0.439, -0.071, 0.0, - 0.0625, 0.50, 0.50, 1.0}; - - //a nice quick colorspace conversion - float4 yuvx = mul(float4(rgba.rgb, 1.0), yuvMat); - return float4(saturate(yuvx.zxy), rgba.a); -} diff --git a/rundir/shaders/DownscaleYUV3.pShader b/rundir/shaders/DownscaleYUV3.pShader deleted file mode 100644 index f6c6a907..00000000 --- a/rundir/shaders/DownscaleYUV3.pShader +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************** - Copyright (C) 2012 Hugh Bailey - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. -********************************************************************************/ - - -uniform Texture2D diffuseTexture; -uniform float2 baseDimensionI; - -SamplerState textureSampler -{ - AddressU = Clamp; - AddressV = Clamp; - Filter = Linear; -}; - -struct VertData -{ - float4 pos : SV_Position; - float2 texCoord : TexCoord0; -}; - -float4 main(VertData input) : SV_Target -{ - float2 texAdjust = (input.texCoord-0.5)*3.0; - float2 floorVal = floor(texAdjust+0.001); - - float4 rgba; - rgba = diffuseTexture.Sample(textureSampler, (floorVal+float2(0.5f, 0.5f)) * baseDimensionI); - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(1.5f, 0.5f)) * baseDimensionI); - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(2.5f, 0.5f)) * baseDimensionI); - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(0.5f, 1.5f)) * baseDimensionI); - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(1.5f, 1.5f)) * baseDimensionI); - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(2.5f, 1.5f)) * baseDimensionI); - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(0.5f, 2.5f)) * baseDimensionI); - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(1.5f, 2.5f)) * baseDimensionI); - rgba += diffuseTexture.Sample(textureSampler, (floorVal+float2(2.5f, 2.5f)) * baseDimensionI); - rgba /= 9.0; - - const float4x4 yuvMat = {0.257, -0.148, 0.439, 0.0, - 0.504, -0.291, -0.368, 0.0, - 0.098, 0.439, -0.071, 0.0, - 0.0625, 0.50, 0.50, 1.0}; - - //a nice quick colorspace conversion - float4 yuvx = mul(float4(rgba.rgb, 1.0), yuvMat); - return float4(saturate(yuvx.zxy), rgba.a); -}