Added bicubic and lanczos downscale shaders, optimized existing bilinear downscale shaders
This commit is contained in:
parent
10b43836bf
commit
3cd334b61e
14
OBS.rc
14
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
|
||||
|
@ -536,6 +536,7 @@ private:
|
||||
UINT scaleCX, scaleCY;
|
||||
UINT outputCX, outputCY;
|
||||
float downscale;
|
||||
int downscaleType;
|
||||
UINT frameTime, fps;
|
||||
bool bUsing444;
|
||||
|
||||
|
@ -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)"));
|
||||
|
||||
|
@ -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);
|
||||
|
||||
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);
|
||||
|
||||
//------------------------------------
|
||||
|
||||
|
@ -140,6 +140,7 @@ public:
|
||||
|
||||
private:
|
||||
void RefreshDownscales(HWND hwnd, int cx, int cy);
|
||||
void RefreshFilters(HWND hwndParent, bool bGetConfig);
|
||||
|
||||
public:
|
||||
// Interface
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
91
rundir/shaders/DownscaleBicubicYUV.pShader
Normal file
91
rundir/shaders/DownscaleBicubicYUV.pShader
Normal file
@ -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);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
Copyright (C) 2012 Hugh Bailey <obs.jim@gmail.com>
|
||||
Copyright (C) 2013 Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
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,
|
@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
Copyright (C) 2012 Hugh Bailey <obs.jim@gmail.com>
|
||||
Copyright (C) 2013 Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
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,
|
102
rundir/shaders/DownscaleLanczos6tapYUV.pShader
Normal file
102
rundir/shaders/DownscaleLanczos6tapYUV.pShader
Normal file
@ -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);
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
/********************************************************************************
|
||||
Copyright (C) 2012 Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
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);
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/********************************************************************************
|
||||
Copyright (C) 2012 Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user