mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 10:40:01 +01:00
D3D: load gpu scaler code from the assets folder at runtime. also add
xbrz code in addition to xbr.
This commit is contained in:
1 parent
0b2511ea90
commit
45a0809768
23 files changed
+779
-388
No files matched your search
+2
-1
@@ -1851,7 +1851,8 @@ endif()
|
||||
set(NativeAssets
|
||||
android/assets/ui_atlas.zim
|
||||
assets/lang
|
||||
assets/shaders
|
||||
assets/shaders
|
||||
assets/scalers
|
||||
assets/Roboto-Condensed.ttf
|
||||
assets/7z.png
|
||||
assets/compat.ini
|
||||
|
||||
@@ -555,8 +555,9 @@ bool TextureScalerCommon::ScaleInto(u32 *outputBuf, u32 *src, u32 &dstFmt, int &
|
||||
|
||||
// scale
|
||||
switch (g_Config.iTexScalingType) {
|
||||
case XBR:
|
||||
case SABR:
|
||||
// no cpu implementation for sabr, fall back to xbrz
|
||||
// no cpu implementation, fall back to xbrz
|
||||
case XBRZ:
|
||||
ScaleXBRZ(factor, inputBuf, outputBuf, width, height);
|
||||
break;
|
||||
@@ -565,7 +566,7 @@ bool TextureScalerCommon::ScaleInto(u32 *outputBuf, u32 *src, u32 &dstFmt, int &
|
||||
break;
|
||||
case GAUSSIAN:
|
||||
case COSINE:
|
||||
// no cpu implementation for those, fall back to bicubic
|
||||
// no cpu implementation, fall back to bicubic
|
||||
case BICUBIC:
|
||||
ScaleBicubicMitchell(factor, inputBuf, outputBuf, width, height);
|
||||
break;
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
bool Scale(u32 *&data, u32 &dstfmt, int &width, int &height, int factor);
|
||||
bool ScaleInto(u32 *out, u32 *src, u32 &dstfmt, int &width, int &height, int factor);
|
||||
|
||||
enum { XBRZ = 0, HYBRID = 1, BICUBIC = 2, HYBRID_BICUBIC = 3, SABR = 4, GAUSSIAN = 5, COSINE = 6 };
|
||||
enum { XBRZ = 0, HYBRID = 1, BICUBIC = 2, HYBRID_BICUBIC = 3, XBR = 4, SABR = 5, GAUSSIAN = 6, COSINE = 7 };
|
||||
|
||||
protected:
|
||||
virtual void ConvertTo8888(u32 format, u32 *source, u32 *&dest, int width, int height) = 0;
|
||||
|
||||
@@ -19,6 +19,6 @@
|
||||
#include "GPU/D3D11/FragmentShaderGeneratorD3D11.h"
|
||||
#include "GPU/Directx9/PixelShaderGeneratorDX9.h"
|
||||
|
||||
void GenerateFragmentShaderD3D11(const FShaderID &id, char *buffer, ShaderLanguage lang) {
|
||||
DX9::GenerateFragmentShaderHLSL(id, buffer, lang);
|
||||
void GenerateFragmentShaderD3D11(const FShaderID &id, char *buffer, char* scalerCode, ShaderLanguage lang) {
|
||||
DX9::GenerateFragmentShaderHLSL(id, buffer, scalerCode, lang);
|
||||
}
|
||||
@@ -19,4 +19,4 @@
|
||||
|
||||
#include "GPU/Common/ShaderId.h"
|
||||
|
||||
void GenerateFragmentShaderD3D11(const FShaderID &id, char *buffer, ShaderLanguage lang);
|
||||
void GenerateFragmentShaderD3D11(const FShaderID &id, char *buffer, char *scalerCode, ShaderLanguage lang);
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "math/lin/matrix4x4.h"
|
||||
#include "math/math_util.h"
|
||||
#include "math/dataconv.h"
|
||||
#include "file/vfs.h"
|
||||
#include "util/text/utf8.h"
|
||||
#include "Common/Common.h"
|
||||
#include "Core/Config.h"
|
||||
@@ -89,8 +90,8 @@ std::string D3D11VertexShader::GetShaderString(DebugShaderStringType type) const
|
||||
}
|
||||
|
||||
ShaderManagerD3D11::ShaderManagerD3D11(ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel)
|
||||
: device_(device), context_(context), featureLevel_(featureLevel), lastVShader_(nullptr), lastFShader_(nullptr) {
|
||||
codeBuffer_ = new char[16384];
|
||||
: device_(device), context_(context), featureLevel_(featureLevel), lastVShader_(nullptr), lastFShader_(nullptr), scalerCode_(nullptr) {
|
||||
codeBuffer_ = new char[16384 * 2];
|
||||
memset(&ub_base, 0, sizeof(ub_base));
|
||||
memset(&ub_lights, 0, sizeof(ub_lights));
|
||||
|
||||
@@ -101,6 +102,7 @@ ShaderManagerD3D11::ShaderManagerD3D11(ID3D11Device *device, ID3D11DeviceContext
|
||||
ASSERT_SUCCESS(device_->CreateBuffer(&desc, nullptr, &push_base));
|
||||
desc.ByteWidth = sizeof(ub_lights);
|
||||
ASSERT_SUCCESS(device_->CreateBuffer(&desc, nullptr, &push_lights));
|
||||
needScalerCode = g_Config.bRealtimeTexScaling && g_Config.iTexScalingLevel != 1;
|
||||
}
|
||||
|
||||
ShaderManagerD3D11::~ShaderManagerD3D11() {
|
||||
@@ -128,6 +130,9 @@ void ShaderManagerD3D11::ClearShaders() {
|
||||
Clear();
|
||||
DirtyLastShader();
|
||||
gstate_c.Dirty(DIRTY_ALL_UNIFORMS);
|
||||
free(scalerCode_);
|
||||
scalerCode_ = nullptr;
|
||||
needScalerCode = g_Config.bRealtimeTexScaling && g_Config.iTexScalingLevel != 1;
|
||||
}
|
||||
|
||||
void ShaderManagerD3D11::DirtyLastShader() {
|
||||
@@ -208,7 +213,28 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **
|
||||
D3D11FragmentShader *fs;
|
||||
if (fsIter == fsCache_.end()) {
|
||||
// Fragment shader not in cache. Let's compile it.
|
||||
GenerateFragmentShaderD3D11(FSID, codeBuffer_, featureLevel_ <= D3D_FEATURE_LEVEL_9_3 ? HLSL_D3D11_LEVEL9 : HLSL_D3D11);
|
||||
if(needScalerCode && !scalerCode_) {
|
||||
static const char* filenames[] = {
|
||||
"scalers/xbrz.hlsl",
|
||||
"scalers/hybrid.hlsl",
|
||||
"scalers/bicubic.hlsl",
|
||||
"scalers/hybrid_bicubic.hlsl",
|
||||
"scalers/xbr.hlsl",
|
||||
"scalers/sabr.hlsl",
|
||||
"scalers/gaussian.hlsl",
|
||||
"scalers/cosine.hlsl",
|
||||
};
|
||||
if ((g_Config.iTexScalingType < 0) || (g_Config.iTexScalingType >= sizeof(filenames) / sizeof(*filenames))) {
|
||||
ERROR_LOG(G3D, "Unknown scaling type: %i", g_Config.iTexScalingType);
|
||||
} else {
|
||||
size_t sz;
|
||||
scalerCode_ = (char *)VFSReadFile(filenames[g_Config.iTexScalingType], &sz);
|
||||
if(!scalerCode_)
|
||||
ERROR_LOG(G3D, "Scaler not found: %s", filenames[g_Config.iTexScalingType]);
|
||||
}
|
||||
needScalerCode = false;
|
||||
}
|
||||
GenerateFragmentShaderD3D11(FSID, codeBuffer_, scalerCode_, featureLevel_ <= D3D_FEATURE_LEVEL_9_3 ? HLSL_D3D11_LEVEL9 : HLSL_D3D11);
|
||||
fs = new D3D11FragmentShader(device_, featureLevel_, FSID, codeBuffer_, useHWTransform);
|
||||
fsCache_[FSID] = fs;
|
||||
} else {
|
||||
|
||||
@@ -116,6 +116,8 @@ private:
|
||||
VSCache vsCache_;
|
||||
|
||||
char *codeBuffer_;
|
||||
char *scalerCode_;
|
||||
bool needScalerCode;
|
||||
|
||||
// Uniform block scratchpad. These (the relevant ones) are copied to the current pushbuffer at draw time.
|
||||
UB_VS_FS_Base ub_base;
|
||||
|
||||
@@ -32,349 +32,9 @@
|
||||
|
||||
namespace DX9 {
|
||||
|
||||
static const char* sampler_default =
|
||||
"float4 tex_sample(float2 coord) {\n"
|
||||
" return tex_sample_direct(coord);\n"
|
||||
"};\n";
|
||||
|
||||
static const char* sampler_gaussian =
|
||||
"#define sharpness 1.0\n"
|
||||
"#define pi 3.14159265358\n"
|
||||
"#define normalGauss(x) ((exp(-(x)*(x)*0.5))/sqrt(2.0*pi))\n"
|
||||
"#define normalGauss2(x) (normalGauss(x - 0.5) - 0.5)\n"
|
||||
"float normalGaussIntegral(float x)\n"
|
||||
"{\n"
|
||||
" float a1 = 0.4361836;\n"
|
||||
" float a2 = -0.1201676;\n"
|
||||
" float a3 = 0.9372980;\n"
|
||||
" float p = 0.3326700;\n"
|
||||
" float t = 1.0 / (1.0 + p*abs(x));\n"
|
||||
"\n"
|
||||
" return (0.5-normalGauss(x) * (t*(a1 + t*(a2 + a3*t))))*sign(x);\n"
|
||||
"}\n"
|
||||
"#define KERNEL(x,b) (normalGaussIntegral(sqrt(2*pi)*b*(x - 0.5)) - normalGaussIntegral(sqrt(2*pi)*b*(x + 0.5)))\n"
|
||||
"\n"
|
||||
"float4 tex_sample(float2 coord) {\n"
|
||||
" float2 offset = frac(coord * u_texSize.xy) - 0.5;\n"
|
||||
" float4 tempColor = 0.0;\n"
|
||||
" float4 c;\n"
|
||||
" float i,j;\n"
|
||||
" float2 pos;\n"
|
||||
" for (i = -2.0; i < 2.0; i++){\n"
|
||||
" pos.x = offset.x - i;\n"
|
||||
" for (j = -2.0; j< 2.0 ;j++){\n"
|
||||
" pos.y = offset.y - j;\n"
|
||||
" c=premultiply_alpha(tex_sample_direct(coord - pos * u_texSize.zw));\n"
|
||||
" tempColor+=c*KERNEL(pos.x,sharpness)*KERNEL(pos.y,sharpness);\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" return postdivide_alpha(tempColor);\n"
|
||||
"};\n";
|
||||
static const char* sampler_cosine =
|
||||
"#define sharpness 1.0\n"
|
||||
"#define pi 3.14159265358\n"
|
||||
"#define a(x) abs(x)\n"
|
||||
"#define d(x,b) (pi*b*min(a(x)+0.5,1.0/b))\n"
|
||||
"#define e(x,b) (pi*b*min(max(a(x)-0.5,-1.0/b),1.0/b))\n"
|
||||
"#define KERNEL(x,b) ((d(x,b)+sin(d(x,b))-e(x,b)-sin(e(x,b)))/(2.0*pi))\n"
|
||||
"\n"
|
||||
"float4 tex_sample(float2 coord) {\n"
|
||||
" float2 offset = frac(coord * u_texSize.xy) - 0.5;\n"
|
||||
" float4 tempColor = 0.0;\n"
|
||||
" float4 c;\n"
|
||||
" float i,j;\n"
|
||||
" float2 pos;\n"
|
||||
" for (i = -2.0; i < 2.0; i++){\n"
|
||||
" pos.x = offset.x - i;\n"
|
||||
" for (j = -2.0; j< 2.0 ;j++){\n"
|
||||
" pos.y = offset.y - j;\n"
|
||||
" c=premultiply_alpha(tex_sample_direct(coord - pos * u_texSize.zw));\n"
|
||||
" tempColor+=c*KERNEL(pos.x,sharpness)*KERNEL(pos.y,sharpness);\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" return postdivide_alpha(tempColor);\n"
|
||||
"};\n";
|
||||
static const char* sampler_xbrz =
|
||||
"float c_df(float3 c1, float3 c2) {\n"
|
||||
" float3 df = abs(c1 - c2);\n"
|
||||
" return df.r + df.g + df.b;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static const float coef = 2.0;\n"
|
||||
"\n"
|
||||
"static const float3 rgbw = float3(14.352, 28.176, 5.472);\n"
|
||||
"static const float4 eq_threshold = float4(15.0, 15.0, 15.0, 15.0);\n"
|
||||
"\n"
|
||||
"static const float4 delta = float4(1.0/4., 1.0/4., 1.0/4., 1.0/4.);\n"
|
||||
"static const float4 delta_l = float4(0.5/4., 1.0/4., 0.5/4., 1.0/4.);\n"
|
||||
"static const float4 delta_u = delta_l.yxwz;\n"
|
||||
"\n"
|
||||
"static const float4 Ao = float4( 1.0, -1.0, -1.0, 1.0 );\n"
|
||||
"static const float4 Bo = float4( 1.0, 1.0, -1.0,-1.0 );\n"
|
||||
"static const float4 Co = float4( 1.5, 0.5, -0.5, 0.5 );\n"
|
||||
"static const float4 Ax = float4( 1.0, -1.0, -1.0, 1.0 );\n"
|
||||
"static const float4 Bx = float4( 0.5, 2.0, -0.5,-2.0 );\n"
|
||||
"static const float4 Cx = float4( 1.0, 1.0, -0.5, 0.0 );\n"
|
||||
"static const float4 Ay = float4( 1.0, -1.0, -1.0, 1.0 );\n"
|
||||
"static const float4 By = float4( 2.0, 0.5, -2.0,-0.5 );\n"
|
||||
"static const float4 Cy = float4( 2.0, 0.0, -1.0, 0.5 );\n"
|
||||
"static const float4 Ci = float4(0.25, 0.25, 0.25, 0.25);\n"
|
||||
"\n"
|
||||
"// Difference between vector components.\n"
|
||||
"float4 df(float4 A, float4 B)\n"
|
||||
"{\n"
|
||||
" return float4(abs(A-B));\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"// Compare two vectors and return their components are different.\n"
|
||||
"float4 diff(float4 A, float4 B)\n"
|
||||
"{\n"
|
||||
" return step(0.001, df(A, B));\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"// Determine if two vector components are equal based on a threshold.\n"
|
||||
"float4 eq(float4 A, float4 B)\n"
|
||||
"{\n"
|
||||
" return step(df(A, B), 15.);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"// Determine if two vector components are NOT equal based on a threshold.\n"
|
||||
"float4 neq(float4 A, float4 B)\n"
|
||||
"{\n"
|
||||
" return step(15., df(A, B));\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"// Weighted distance.\n"
|
||||
"float4 wd(float4 a, float4 b, float4 c, float4 d, float4 e, float4 f, float4 g, float4 h)\n"
|
||||
"{\n"
|
||||
" return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h));\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float4 tex_sample(float2 coord)\n"
|
||||
"{\n"
|
||||
" float2 tc = coord * u_texSize.xy;\n"
|
||||
" float2 fp = frac(tc);\n"
|
||||
" tc = floor(tc) + 0.5;\n"
|
||||
"\n"
|
||||
" float4 xyp_01_02_03 = u_texSize.zzzw * (tc.xxxy + float4(-1., 0., 1., -2.));\n"
|
||||
" float4 xyp_06_07_08 = u_texSize.zzzw * (tc.xxxy + float4(-1., 0., 1., -1.));\n"
|
||||
" float4 xyp_11_12_13 = u_texSize.zzzw * (tc.xxxy + float4(-1., 0., 1., 0.));\n"
|
||||
" float4 xyp_16_17_18 = u_texSize.zzzw * (tc.xxxy + float4(-1., 0., 1., 1.));\n"
|
||||
" float4 xyp_21_22_23 = u_texSize.zzzw * (tc.xxxy + float4(-1., 0., 1., 2.));\n"
|
||||
" float4 xyp_05_10_15 = u_texSize.zwww * (tc.xyyy + float4(-2., -1., 0., 1.));\n"
|
||||
" float4 xyp_09_14_09 = u_texSize.zwww * (tc.xyyy + float4( 2., -1., 0., 1.));\n"
|
||||
"\n"
|
||||
" float4 edri;\n"
|
||||
" float4 edr;\n"
|
||||
" float4 edr_l;\n"
|
||||
" float4 edr_u;\n"
|
||||
" float4 px; // px = pixel, edr = edge detection rule\n"
|
||||
" float4 irlv0;\n"
|
||||
" float4 irlv1;\n"
|
||||
" float4 irlv2l;\n"
|
||||
" float4 irlv2u;\n"
|
||||
" float4 block_3d;\n"
|
||||
" float4 fx;\n"
|
||||
" float4 fx_l;\n"
|
||||
" float4 fx_u; // inequations of straight lines.\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" float4 A1 = premultiply_alpha(tex_sample_direct(xyp_01_02_03.xw));\n"
|
||||
" float4 B1 = premultiply_alpha(tex_sample_direct(xyp_01_02_03.yw));\n"
|
||||
" float4 C1 = premultiply_alpha(tex_sample_direct(xyp_01_02_03.zw));\n"
|
||||
" float4 A = premultiply_alpha(tex_sample_direct(xyp_06_07_08.xw));\n"
|
||||
" float4 B = premultiply_alpha(tex_sample_direct(xyp_06_07_08.yw));\n"
|
||||
" float4 C = premultiply_alpha(tex_sample_direct(xyp_06_07_08.zw));\n"
|
||||
" float4 D = premultiply_alpha(tex_sample_direct(xyp_11_12_13.xw));\n"
|
||||
" float4 E = premultiply_alpha(tex_sample_direct(xyp_11_12_13.yw));\n"
|
||||
" float4 F = premultiply_alpha(tex_sample_direct(xyp_11_12_13.zw));\n"
|
||||
" float4 G = premultiply_alpha(tex_sample_direct(xyp_16_17_18.xw));\n"
|
||||
" float4 H = premultiply_alpha(tex_sample_direct(xyp_16_17_18.yw));\n"
|
||||
" float4 I = premultiply_alpha(tex_sample_direct(xyp_16_17_18.zw));\n"
|
||||
" float4 G5 = premultiply_alpha(tex_sample_direct(xyp_21_22_23.xw));\n"
|
||||
" float4 H5 = premultiply_alpha(tex_sample_direct(xyp_21_22_23.yw));\n"
|
||||
" float4 I5 = premultiply_alpha(tex_sample_direct(xyp_21_22_23.zw));\n"
|
||||
" float4 A0 = premultiply_alpha(tex_sample_direct(xyp_05_10_15.xy));\n"
|
||||
" float4 D0 = premultiply_alpha(tex_sample_direct(xyp_05_10_15.xz));\n"
|
||||
" float4 G0 = premultiply_alpha(tex_sample_direct(xyp_05_10_15.xw));\n"
|
||||
" float4 C4 = premultiply_alpha(tex_sample_direct(xyp_09_14_09.xy));\n"
|
||||
" float4 F4 = premultiply_alpha(tex_sample_direct(xyp_09_14_09.xz));\n"
|
||||
" float4 I4 = premultiply_alpha(tex_sample_direct(xyp_09_14_09.xw));\n"
|
||||
"\n"
|
||||
" float4 b = float4(dot(B.rgb ,rgbw), dot(D.rgb ,rgbw), dot(H.rgb ,rgbw), dot(F.rgb ,rgbw));\n"
|
||||
" float4 c = float4(dot(C.rgb ,rgbw), dot(A.rgb ,rgbw), dot(G.rgb ,rgbw), dot(I.rgb ,rgbw));\n"
|
||||
" float4 d = b.yzwx;\n"
|
||||
" float4 e = dot(E.rgb,rgbw).xxxx;\n"
|
||||
" float4 f = b.wxyz;\n"
|
||||
" float4 g = c.zwxy;\n"
|
||||
" float4 h = b.zwxy;\n"
|
||||
" float4 i = c.wxyz;\n"
|
||||
" float4 i4 = float4(dot(I4.rgb,rgbw), dot(C1.rgb,rgbw), dot(A0.rgb,rgbw), dot(G5.rgb,rgbw));\n"
|
||||
" float4 i5 = float4(dot(I5.rgb,rgbw), dot(C4.rgb,rgbw), dot(A1.rgb,rgbw), dot(G0.rgb,rgbw));\n"
|
||||
" float4 h5 = float4(dot(H5.rgb,rgbw), dot(F4.rgb,rgbw), dot(B1.rgb,rgbw), dot(D0.rgb,rgbw));\n"
|
||||
" float4 f4 = h5.yzwx;\n"
|
||||
"\n"
|
||||
" // These inequations define the line below which interpolation occurs.\n"
|
||||
" fx = (Ao*fp.y+Bo*fp.x);\n"
|
||||
" fx_l = (Ax*fp.y+Bx*fp.x);\n"
|
||||
" fx_u = (Ay*fp.y+By*fp.x);\n"
|
||||
"\n"
|
||||
" irlv0 = diff(e,f) * diff(e,h);\n"
|
||||
"\n"
|
||||
// " irlv1 = irlv0;\n"
|
||||
// " irlv1 = (irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) );\n"
|
||||
// " float4 c1 = i4.yzwx;\n"
|
||||
// " float4 g0 = i5.wxyz;\n"
|
||||
// " irlv1 = (irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) * (diff(f,f4) * diff(f,i) + diff(h,h5) * diff(h,i) + diff(h,g) + diff(f,c) + eq(b,c1) * eq(d,g0)));\n"
|
||||
" irlv1 = (irlv0 * ( neq(f,b) * neq(f,c) + neq(h,d) * neq(h,g) + eq(e,i) * (neq(f,f4) * neq(f,i4) + neq(h,h5) * neq(h,i5)) + eq(e,g) + eq(e,c)) );\n"
|
||||
"\n"
|
||||
" irlv2l = diff(e,g) * diff(d,g);\n"
|
||||
" irlv2u = diff(e,c) * diff(b,c);\n"
|
||||
"\n"
|
||||
" float4 fx45i = clamp((fx + delta -Co - Ci)/(2.0*delta ), 0.0, 1.0);\n"
|
||||
" float4 fx45 = clamp((fx + delta -Co )/(2.0*delta ), 0.0, 1.0);\n"
|
||||
" float4 fx30 = clamp((fx_l + delta_l -Cx )/(2.0*delta_l), 0.0, 1.0);\n"
|
||||
" float4 fx60 = clamp((fx_u + delta_u -Cy )/(2.0*delta_u), 0.0, 1.0);\n"
|
||||
"\n"
|
||||
" float4 wd1 = wd( e, c, g, i, h5, f4, h, f);\n"
|
||||
" float4 wd2 = wd( h, d, i5, f, i4, b, e, i);\n"
|
||||
"\n"
|
||||
" edri = step(wd1, wd2) * irlv0;\n"
|
||||
" edr = step(wd1 + float4(0.1, 0.1, 0.1, 0.1), wd2) * step(float4(0.5, 0.5, 0.5, 0.5), irlv1);\n"
|
||||
" edr_l = step( 2.*df(f,g), df(h,c) ) * irlv2l * edr;\n"
|
||||
" edr_u = step( 2.*df(h,c), df(f,g) ) * irlv2u * edr;\n"
|
||||
"\n"
|
||||
" fx45 = edr * fx45;\n"
|
||||
" fx30 = edr_l * fx30;\n"
|
||||
" fx60 = edr_u * fx60;\n"
|
||||
" fx45i = edri * fx45i;\n"
|
||||
"\n"
|
||||
" px = step(df(e,f), df(e,h));\n"
|
||||
"\n"
|
||||
" float4 maximos = max(max(fx30, fx60), max(fx45, fx45i));\n"
|
||||
// " float4 maximos = max(max(fx30, fx60), fx45);"
|
||||
"\n"
|
||||
" float4 res1 = E;\n"
|
||||
" res1 = lerp(res1, lerp(H, F, px.x), maximos.x);\n"
|
||||
" res1 = lerp(res1, lerp(B, D, px.z), maximos.z);\n"
|
||||
"\n"
|
||||
" float4 res2 = E;\n"
|
||||
" res2 = lerp(res2, lerp(F, B, px.y), maximos.y);\n"
|
||||
" res2 = lerp(res2, lerp(D, H, px.w), maximos.w);\n"
|
||||
"\n"
|
||||
" float4 res = lerp(res1, res2, step(c_df(E.rgb, res1.rgb), c_df(E.rgb, res2.rgb)));\n"
|
||||
" return postdivide_alpha(res);\n"
|
||||
"}\n";
|
||||
static const char* sampler_sabr =
|
||||
"float c_df(float4 c1, float4 c2) {\n"
|
||||
" float3 df = abs(c1.rgb - c2.rgb);\n"
|
||||
" return df.r + df.g + df.b;\n"
|
||||
"}\n"
|
||||
"static const float4 Ai = float4( 1.0, -1.0, -1.0, 1.0);\n"
|
||||
"static const float4 B45 = float4( 1.0, 1.0, -1.0, -1.0);\n"
|
||||
"static const float4 C45 = float4( 1.5, 0.5, -0.5, 0.5);\n"
|
||||
"static const float4 M45 = float4(0.4, 0.4, 0.4, 0.4);\n"
|
||||
"static const float4 M30 = float4(0.2, 0.4, 0.2, 0.4);\n"
|
||||
"static const float3 lum = float3(0.21, 0.72, 0.07);\n"
|
||||
"\n"
|
||||
"float lum_to(float4 v) {\n"
|
||||
" return dot(lum, v.rgb);\n"
|
||||
"}\n"
|
||||
"float4 lum_to(float4 v0, float4 v1, float4 v2, float4 v3) {\n"
|
||||
" return float4(lum_to(v0), lum_to(v1), lum_to(v2), lum_to(v3));\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"float4 tex_sample(float2 coord)\n"
|
||||
"{\n"
|
||||
"/*\n"
|
||||
" Mask for algorithm\n"
|
||||
" +-----+-----+-----+\n"
|
||||
" | | 7 | |\n"
|
||||
" +-----+-----+-----+\n"
|
||||
" | 11 | 12 | 13 |\n"
|
||||
" +-----+-----+-----+\n"
|
||||
" | | 17 | |\n"
|
||||
" +-----+-----+-----+\n"
|
||||
"*/\n"
|
||||
"// Store mask values\n"
|
||||
" float4 P07 = premultiply_alpha(tex_sample_direct(coord + u_texSize.zw * float2( 0.0, -1.0)));\n"
|
||||
" float4 P11 = premultiply_alpha(tex_sample_direct(coord + u_texSize.zw * float2(-1.0, 0.0)));\n"
|
||||
" float4 P12 = premultiply_alpha(tex_sample_direct(coord + u_texSize.zw * float2( 0.0, 0.0)));\n"
|
||||
" float4 P13 = premultiply_alpha(tex_sample_direct(coord + u_texSize.zw * float2( 1.0, 0.0)));\n"
|
||||
" float4 P17 = premultiply_alpha(tex_sample_direct(coord + u_texSize.zw * float2( 0.0, 1.0)));\n"
|
||||
"\n"
|
||||
" // Store luminance values of each point\n"
|
||||
" float4 p7 = lum_to(P07, P11, P17, P13);\n"
|
||||
" float4 p12 = lum_to(P12);\n"
|
||||
" float4 p13 = p7.wxyz; // P13, P7, P11, P17\n"
|
||||
" float4 p17 = p7.zwxy; // P11, P17, P13, P7\n"
|
||||
"\n"
|
||||
" float2 fp = frac(coord * u_texSize.xy);\n"
|
||||
" float4 ma45 = smoothstep(C45 - M45, C45 + M45, Ai * fp.y + B45 * fp.x);\n"
|
||||
" float4 px = step(abs(p12 - p17), abs(p12 - p13));\n"
|
||||
"\n"
|
||||
" float4 res1 = P12;\n"
|
||||
" res1 = lerp(res1, lerp(P13, P17, px.x), ma45.x);\n"
|
||||
" res1 = lerp(res1, lerp(P07, P13, px.y), ma45.y);\n"
|
||||
" res1 = lerp(res1, lerp(P11, P07, px.z), ma45.z);\n"
|
||||
" res1 = lerp(res1, lerp(P17, P11, px.w), ma45.w);\n"
|
||||
"\n"
|
||||
" float4 res2 = P12;\n"
|
||||
" res2 = lerp(res2, lerp(P17, P11, px.w), ma45.w);\n"
|
||||
" res2 = lerp(res2, lerp(P11, P07, px.z), ma45.z);\n"
|
||||
" res2 = lerp(res2, lerp(P07, P13, px.y), ma45.y);\n"
|
||||
" res2 = lerp(res2, lerp(P13, P17, px.x), ma45.x);\n"
|
||||
"\n"
|
||||
" float4 res = lerp(res1, res2, step(c_df(P12, res1), c_df(P12, res2)));\n"
|
||||
" return postdivide_alpha(res);\n"
|
||||
"}\n";
|
||||
|
||||
static const char* sampler_hybrid = sampler_xbrz;
|
||||
static const char* sampler_hybrid_bicubic = sampler_xbrz;
|
||||
static const char* sampler_bicubic =
|
||||
"// generate the value of a Mitchell-Netravali scaling spline at distance d, with parameters A and B\n"
|
||||
"// B=1 C=0 : cubic B spline (very smooth)\n"
|
||||
"// B=C=1/3 : recommended for general upscaling\n"
|
||||
"// B=0 C=1/2 : Catmull-Rom spline (sharp, ringing)\n"
|
||||
"// see Mitchell & Netravali, \"Reconstruction Filters in Computer Graphics\"\n"
|
||||
"\n"
|
||||
"//#define BSPLINE\n"
|
||||
"#ifdef BSPLINE\n"
|
||||
" static const float B = 1.0f;\n"
|
||||
" static const float C = 0.0f;\n"
|
||||
"#else\n"
|
||||
" static const float B = 1.0f / 3.0f;\n"
|
||||
" static const float C = 1.0f / 3.0f;\n"
|
||||
"#endif\n"
|
||||
"float mitchell(float2 pos) {\n"
|
||||
" float x = sqrt(dot(pos, pos));\n"
|
||||
" return\n"
|
||||
" step(x, 2.0) * \n"
|
||||
" (step(1.0, x) * ((-B - 6 * C)*(x*x*x) + (6 * B + 30 * C)*(x*x) + (-12 * B - 48 * C)*x + (8 * B + 24 * C)) +\n"
|
||||
" step(x, 1.0) * ((12 - 9 * B - 6 * C)*(x*x*x) + (-18 + 12 * B + 6 * C)*(x*x) + (6 - 2 * B)))\n"
|
||||
" / 6.0f;\n"
|
||||
"}\n"
|
||||
"float4 tex_sample(float2 coord) {\n"
|
||||
" float2 offset = frac(coord * u_texSize.xy) - 0.5;\n"
|
||||
" float4 tempColor = 0.0;\n"
|
||||
" float4 c;\n"
|
||||
" float i,j;\n"
|
||||
" float2 pos;\n"
|
||||
" for (i = -2.0; i < 3.0; i++){\n"
|
||||
" pos.x = offset.x - i;\n"
|
||||
" for (j = -2.0; j < 3.0 ;j++){\n"
|
||||
" pos.y = offset.y - j;\n"
|
||||
" c=premultiply_alpha(tex_sample_direct(coord - pos * u_texSize.zw));\n"
|
||||
" tempColor+=c*mitchell(pos);\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" return postdivide_alpha(tempColor);\n"
|
||||
"};\n";
|
||||
|
||||
// Missing: Z depth range
|
||||
// Also, logic ops etc, of course, as they are not supported in DX9.
|
||||
bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguage lang) {
|
||||
bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, char* scalerCode, ShaderLanguage lang) {
|
||||
char *p = buffer;
|
||||
|
||||
bool lmode = id.Bit(FS_BIT_LMODE);
|
||||
@@ -396,7 +56,6 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
|
||||
GEComparison alphaTestFunc = (GEComparison)id.Bits(FS_BIT_ALPHA_TEST_FUNC, 3);
|
||||
GEComparison colorTestFunc = (GEComparison)id.Bits(FS_BIT_COLOR_TEST_FUNC, 2);
|
||||
bool needShaderTexClamp = id.Bit(FS_BIT_SHADER_TEX_CLAMP);
|
||||
bool needScaleFilter = g_Config.bRealtimeTexScaling && g_Config.iTexScalingLevel != 1 && !gstate_c.curTextureIsRT;
|
||||
|
||||
ReplaceBlendType replaceBlend = static_cast<ReplaceBlendType>(id.Bits(FS_BIT_REPLACE_BLEND, 3));
|
||||
ReplaceAlphaType stencilToAlpha = static_cast<ReplaceAlphaType>(id.Bits(FS_BIT_STENCIL_TO_ALPHA, 2));
|
||||
@@ -495,7 +154,7 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
|
||||
if (doTextureAlpha) {
|
||||
// TODO: check why the [0.0,1.0] clamp is necessary here
|
||||
WRITE(p, "float4 premultiply_alpha(float4 c) { float a = clamp(c.a, 0.0, 1.0); return float4(c.rgb * a, a); }");
|
||||
WRITE(p, "float4 postdivide_alpha(float4 c) { return c.a < 0.001f? 0.0f : float4(c.rgb / c.a, c.a); }\n");
|
||||
WRITE(p, "float4 postdivide_alpha(float4 c) { return c.a < 0.0001f? 0.0f : float4(c.rgb / c.a, c.a); }\n");
|
||||
} else {
|
||||
WRITE(p, "#define premultiply_alpha(c) (c)\n");
|
||||
WRITE(p, "#define postdivide_alpha(c) (c)\n");
|
||||
@@ -509,35 +168,10 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
|
||||
}
|
||||
WRITE(p, "};\n");
|
||||
|
||||
if (needScaleFilter) {
|
||||
switch (g_Config.iTexScalingType) {
|
||||
case TextureScalerCommon::XBRZ:
|
||||
WRITE(p, sampler_xbrz);
|
||||
break;
|
||||
case TextureScalerCommon::HYBRID:
|
||||
WRITE(p, sampler_hybrid);
|
||||
break;
|
||||
case TextureScalerCommon::BICUBIC:
|
||||
WRITE(p, sampler_bicubic);
|
||||
break;
|
||||
case TextureScalerCommon::HYBRID_BICUBIC:
|
||||
WRITE(p, sampler_hybrid_bicubic);
|
||||
break;
|
||||
case TextureScalerCommon::SABR:
|
||||
WRITE(p, sampler_sabr);
|
||||
break;
|
||||
case TextureScalerCommon::GAUSSIAN:
|
||||
WRITE(p, sampler_gaussian);
|
||||
break;
|
||||
case TextureScalerCommon::COSINE:
|
||||
WRITE(p, sampler_cosine);
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(G3D, "Unknown scaling type: %d", g_Config.iTexScalingType);
|
||||
break;
|
||||
}
|
||||
if (scalerCode && !gstate_c.curTextureIsRT) {
|
||||
WRITE(p, scalerCode);
|
||||
} else {
|
||||
WRITE(p, sampler_default);
|
||||
WRITE(p, "#define tex_sample(x) tex_sample_direct(x)\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
namespace DX9 {
|
||||
|
||||
bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguage lang = HLSL_DX9);
|
||||
bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, char *scalerCode = nullptr, ShaderLanguage lang = HLSL_DX9);
|
||||
|
||||
#define CONST_PS_TEXENV 0
|
||||
#define CONST_PS_ALPHACOLORREF 1
|
||||
|
||||
@@ -476,7 +476,7 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) {
|
||||
}
|
||||
|
||||
ShaderManagerDX9::ShaderManagerDX9(LPDIRECT3DDEVICE9 device) : device_(device), lastVShader_(nullptr), lastPShader_(nullptr) {
|
||||
codeBuffer_ = new char[16384];
|
||||
codeBuffer_ = new char[16384 * 2];
|
||||
}
|
||||
|
||||
ShaderManagerDX9::~ShaderManagerDX9() {
|
||||
|
||||
@@ -378,7 +378,7 @@ void GameSettingsScreen::CreateViews() {
|
||||
});
|
||||
texScalingChoice->SetDisabledPtr(&g_Config.bSoftwareRendering);
|
||||
|
||||
static const char *texScaleAlgos[] = { "xBRZ", "Hybrid", "Bicubic", "Hybrid + Bicubic", "SABR", "Gaussian", "Cosine"};
|
||||
static const char *texScaleAlgos[] = { "xBRZ", "Hybrid", "Bicubic", "Hybrid + Bicubic", "XBR", "SABR", "Gaussian", "Cosine"};
|
||||
PopupMultiChoice *texScalingType = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iTexScalingType, gr->T("Upscale Type"), texScaleAlgos, 0, ARRAY_SIZE(texScaleAlgos), gr->GetName(), screenManager()));
|
||||
texScalingType->SetDisabledPtr(&g_Config.bSoftwareRendering);
|
||||
|
||||
|
||||
@@ -787,6 +787,7 @@ namespace MainWindow {
|
||||
case ID_TEXTURESCALING_HYBRID: setTexScalingType(TextureScalerCommon::HYBRID); break;
|
||||
case ID_TEXTURESCALING_BICUBIC: setTexScalingType(TextureScalerCommon::BICUBIC); break;
|
||||
case ID_TEXTURESCALING_HYBRID_BICUBIC: setTexScalingType(TextureScalerCommon::HYBRID_BICUBIC); break;
|
||||
case ID_TEXTURESCALING_XBR: setTexScalingType(TextureScalerCommon::XBR); break;
|
||||
case ID_TEXTURESCALING_SABR: setTexScalingType(TextureScalerCommon::SABR); break;
|
||||
case ID_TEXTURESCALING_GAUSSIAN: setTexScalingType(TextureScalerCommon::GAUSSIAN); break;
|
||||
case ID_TEXTURESCALING_COSINE: setTexScalingType(TextureScalerCommon::COSINE); break;
|
||||
@@ -1214,6 +1215,7 @@ namespace MainWindow {
|
||||
ID_TEXTURESCALING_HYBRID,
|
||||
ID_TEXTURESCALING_BICUBIC,
|
||||
ID_TEXTURESCALING_HYBRID_BICUBIC,
|
||||
ID_TEXTURESCALING_XBR,
|
||||
ID_TEXTURESCALING_SABR,
|
||||
ID_TEXTURESCALING_GAUSSIAN,
|
||||
ID_TEXTURESCALING_COSINE,
|
||||
|
||||
@@ -613,6 +613,7 @@ BEGIN
|
||||
MENUITEM "Hybrid", ID_TEXTURESCALING_HYBRID
|
||||
MENUITEM "Bicubic", ID_TEXTURESCALING_BICUBIC
|
||||
MENUITEM "Hybrid + Bicubic", ID_TEXTURESCALING_HYBRID_BICUBIC
|
||||
MENUITEM "XBR", ID_TEXTURESCALING_XBR
|
||||
MENUITEM "SABR", ID_TEXTURESCALING_SABR
|
||||
MENUITEM "Gaussian", ID_TEXTURESCALING_GAUSSIAN
|
||||
MENUITEM "Cosine", ID_TEXTURESCALING_COSINE
|
||||
|
||||
+4
-3
@@ -342,9 +342,10 @@
|
||||
|
||||
#define ID_TEXTURESCALING_REALTIME 40177
|
||||
#define ID_TEXTURESCALING_REALTIME_HC 40178
|
||||
#define ID_TEXTURESCALING_SABR 40179
|
||||
#define ID_TEXTURESCALING_GAUSSIAN 40180
|
||||
#define ID_TEXTURESCALING_COSINE 40181
|
||||
#define ID_TEXTURESCALING_XBR 40179
|
||||
#define ID_TEXTURESCALING_SABR 40180
|
||||
#define ID_TEXTURESCALING_GAUSSIAN 40181
|
||||
#define ID_TEXTURESCALING_COSINE 40182
|
||||
|
||||
// Dummy option to let the buffered rendering hotkey cycle through all the options.
|
||||
#define ID_OPTIONS_BUFFEREDRENDERINGDUMMY 40500
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
// generate the value of a Mitchell-Netravali scaling spline at distance d, with parameters A and B
|
||||
// B=1 C=0 : cubic B spline (very smooth)
|
||||
// B=C=1/3 : recommended for general upscaling
|
||||
// B=0 C=1/2 : Catmull-Rom spline (sharp, ringing)
|
||||
// see Mitchell & Netravali, \Reconstruction Filters in Computer Graphics\
|
||||
|
||||
//#define BSPLINE
|
||||
#ifdef BSPLINE
|
||||
static const float B = 1.0f;
|
||||
static const float C = 0.0f;
|
||||
#else
|
||||
static const float B = 1.0f / 3.0f;
|
||||
static const float C = 1.0f / 3.0f;
|
||||
#endif
|
||||
|
||||
float mitchell_0_1(float x) {
|
||||
return ((12 - 9 * B - 6 * C)*(x*x*x) + (-18 + 12 * B + 6 * C)*(x*x) + (6 - 2 * B)) / 6.0f;
|
||||
}
|
||||
|
||||
float mitchell_1_2(float x) {
|
||||
return ((-B - 6 * C)*(x*x*x) + (6 * B + 30 * C)*(x*x) + (-12 * B - 48 * C)*x + (8 * B + 24 * C)) / 6.0f;
|
||||
}
|
||||
|
||||
float mitchell(float2 pos) {
|
||||
float x = sqrt(dot(pos, pos));
|
||||
// return lerp(mitchell_0_1(x), mitchell_1_2(x), step(1.0,x)) * step(x, 2.0);
|
||||
if (x < 1.0)
|
||||
return mitchell_0_1(x);
|
||||
if (x < 2.0)
|
||||
return mitchell_1_2(x);
|
||||
return 0.0;
|
||||
}
|
||||
float4 tex_sample(float2 coord) {
|
||||
float2 offset = frac(coord * u_texSize.xy) - 0.5;
|
||||
float4 tempColor = 0.0;
|
||||
float4 c;
|
||||
float i,j;
|
||||
float2 pos;
|
||||
for (i = -2.0; i < 3.0; i++){
|
||||
pos.x = offset.x - i;
|
||||
for (j = -2.0; j < 3.0 ;j++){
|
||||
pos.y = offset.y - j;
|
||||
c=premultiply_alpha(tex_sample_direct(coord - pos * u_texSize.zw));
|
||||
tempColor+=c*mitchell(pos);
|
||||
}
|
||||
}
|
||||
return postdivide_alpha(tempColor);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
#define sharpness 1.0
|
||||
#define pi 3.14159265358
|
||||
#define a(x) abs(x)
|
||||
#define d(x,b) (pi*b*min(a(x)+0.5,1.0/b))
|
||||
#define e(x,b) (pi*b*min(max(a(x)-0.5,-1.0/b),1.0/b))
|
||||
#define KERNEL(x,b) ((d(x,b)+sin(d(x,b))-e(x,b)-sin(e(x,b)))/(2.0*pi))
|
||||
|
||||
float4 tex_sample(float2 coord) {
|
||||
float2 offset = frac(coord * u_texSize.xy) - 0.5;
|
||||
float4 tempColor = 0.0;
|
||||
float4 c;
|
||||
float i,j;
|
||||
float2 pos;
|
||||
for (i = -2.0; i < 2.0; i++){
|
||||
pos.x = offset.x - i;
|
||||
for (j = -2.0; j< 2.0 ;j++){
|
||||
pos.y = offset.y - j;
|
||||
c=premultiply_alpha(tex_sample_direct(coord - pos * u_texSize.zw));
|
||||
tempColor+=c*KERNEL(pos.x,sharpness)*KERNEL(pos.y,sharpness);
|
||||
}
|
||||
}
|
||||
return postdivide_alpha(tempColor);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
#define sharpness 1.0
|
||||
#define pi 3.14159265358
|
||||
#define normalGauss(x) ((exp(-(x)*(x)*0.5))/sqrt(2.0*pi))
|
||||
#define normalGauss2(x) (normalGauss(x - 0.5) - 0.5)
|
||||
float normalGaussIntegral(float x)
|
||||
{
|
||||
float a1 = 0.4361836;
|
||||
float a2 = -0.1201676;
|
||||
float a3 = 0.9372980;
|
||||
float p = 0.3326700;
|
||||
float t = 1.0 / (1.0 + p*abs(x));
|
||||
|
||||
return (0.5-normalGauss(x) * (t*(a1 + t*(a2 + a3*t))))*sign(x);
|
||||
}
|
||||
#define KERNEL(x,b) (normalGaussIntegral(sqrt(2*pi)*b*(x - 0.5)) - normalGaussIntegral(sqrt(2*pi)*b*(x + 0.5)))
|
||||
|
||||
float4 tex_sample(float2 coord) {
|
||||
float2 offset = frac(coord * u_texSize.xy) - 0.5;
|
||||
float4 tempColor = 0.0;
|
||||
float4 c;
|
||||
float i,j;
|
||||
float2 pos;
|
||||
for (i = -2.0; i < 2.0; i++){
|
||||
pos.x = offset.x - i;
|
||||
for (j = -2.0; j< 2.0 ;j++){
|
||||
pos.y = offset.y - j;
|
||||
c=premultiply_alpha(tex_sample_direct(coord - pos * u_texSize.zw));
|
||||
tempColor+=c*KERNEL(pos.x,sharpness)*KERNEL(pos.y,sharpness);
|
||||
}
|
||||
}
|
||||
return postdivide_alpha(tempColor);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
float4 tex_sample(float2 coord) {
|
||||
return tex_sample_direct(coord);
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
float4 tex_sample(float2 coord) {
|
||||
return tex_sample_direct(coord);
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
|
||||
float c_df(float4 c1, float4 c2) {
|
||||
float3 df = abs(c1.rgb - c2.rgb);
|
||||
return df.r + df.g + df.b;
|
||||
}
|
||||
static const float4 Ai = float4( 1.0, -1.0, -1.0, 1.0);
|
||||
static const float4 B45 = float4( 1.0, 1.0, -1.0, -1.0);
|
||||
static const float4 C45 = float4( 1.5, 0.5, -0.5, 0.5);
|
||||
static const float4 M45 = float4(0.4, 0.4, 0.4, 0.4);
|
||||
static const float4 M30 = float4(0.2, 0.4, 0.2, 0.4);
|
||||
static const float3 lum = float3(0.21, 0.72, 0.07);
|
||||
|
||||
float lum_to(float4 v) {
|
||||
return dot(lum, v.rgb);
|
||||
}
|
||||
float4 lum_to(float4 v0, float4 v1, float4 v2, float4 v3) {
|
||||
return float4(lum_to(v0), lum_to(v1), lum_to(v2), lum_to(v3));
|
||||
}
|
||||
|
||||
|
||||
float4 tex_sample(float2 coord)
|
||||
{
|
||||
/*
|
||||
Mask for algorithm
|
||||
+-----+-----+-----+
|
||||
| | 7 | |
|
||||
+-----+-----+-----+
|
||||
| 11 | 12 | 13 |
|
||||
+-----+-----+-----+
|
||||
| | 17 | |
|
||||
+-----+-----+-----+
|
||||
*/
|
||||
// Store mask values
|
||||
float4 P07 = premultiply_alpha(tex_sample_direct(coord + u_texSize.zw * float2( 0.0, -1.0)));
|
||||
float4 P11 = premultiply_alpha(tex_sample_direct(coord + u_texSize.zw * float2(-1.0, 0.0)));
|
||||
float4 P12 = premultiply_alpha(tex_sample_direct(coord + u_texSize.zw * float2( 0.0, 0.0)));
|
||||
float4 P13 = premultiply_alpha(tex_sample_direct(coord + u_texSize.zw * float2( 1.0, 0.0)));
|
||||
float4 P17 = premultiply_alpha(tex_sample_direct(coord + u_texSize.zw * float2( 0.0, 1.0)));
|
||||
|
||||
// Store luminance values of each point
|
||||
float4 p7 = lum_to(P07, P11, P17, P13);
|
||||
float4 p12 = lum_to(P12);
|
||||
float4 p13 = p7.wxyz; // P13, P7, P11, P17
|
||||
float4 p17 = p7.zwxy; // P11, P17, P13, P7
|
||||
|
||||
float2 fp = frac(coord * u_texSize.xy);
|
||||
float4 ma45 = smoothstep(C45 - M45, C45 + M45, Ai * fp.y + B45 * fp.x);
|
||||
float4 px = step(abs(p12 - p17), abs(p12 - p13));
|
||||
|
||||
float4 res1 = P12;
|
||||
res1 = lerp(res1, lerp(P13, P17, px.x), ma45.x);
|
||||
res1 = lerp(res1, lerp(P07, P13, px.y), ma45.y);
|
||||
res1 = lerp(res1, lerp(P11, P07, px.z), ma45.z);
|
||||
res1 = lerp(res1, lerp(P17, P11, px.w), ma45.w);
|
||||
|
||||
float4 res2 = P12;
|
||||
res2 = lerp(res2, lerp(P17, P11, px.w), ma45.w);
|
||||
res2 = lerp(res2, lerp(P11, P07, px.z), ma45.z);
|
||||
res2 = lerp(res2, lerp(P07, P13, px.y), ma45.y);
|
||||
res2 = lerp(res2, lerp(P13, P17, px.x), ma45.x);
|
||||
|
||||
float4 res = lerp(res1, res2, step(c_df(P12, res1), c_df(P12, res2)));
|
||||
return postdivide_alpha(res);
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
Hyllian's xBR-lv2 Shader
|
||||
|
||||
Copyright (C) 2011-2015 Hyllian - sergiogdb@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Incorporates some of the ideas from SABR shader. Thanks to Joshua Street.
|
||||
*/
|
||||
|
||||
#define XBR_Y_WEIGHT 48.0 // 0.0 .. 100.0
|
||||
#define XBR_EQ_THRESHOLD 15.0 // 0.0 .. 50.0
|
||||
#define XBR_LV1_COEFFICIENT 0.5 // 0.0 .. 30.0
|
||||
#define XBR_LV2_COEFFICIENT 2.0 // 1.0 .. 3.0
|
||||
//#define SMALL_DETAILS
|
||||
|
||||
#define CORNER_TYPE 3 // 1 .. 4
|
||||
#define XBR_SCALE 4.0
|
||||
|
||||
static const float coef = 2.0;
|
||||
static const float3 rgbw = float3(14.352, 28.176, 5.472);
|
||||
static const float4 eq_threshold = float4(15.0, 15.0, 15.0, 15.0);
|
||||
|
||||
static const float4 delta = float4(1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE);
|
||||
static const float4 delta_l = float4(0.5/XBR_SCALE, 1.0/XBR_SCALE, 0.5/XBR_SCALE, 1.0/XBR_SCALE);
|
||||
static const float4 delta_u = delta_l.yxwz;
|
||||
|
||||
static const float4 Ao = float4( 1.0, -1.0, -1.0, 1.0 );
|
||||
static const float4 Bo = float4( 1.0, 1.0, -1.0,-1.0 );
|
||||
static const float4 Co = float4( 1.5, 0.5, -0.5, 0.5 );
|
||||
static const float4 Ax = float4( 1.0, -1.0, -1.0, 1.0 );
|
||||
static const float4 Bx = float4( 0.5, 2.0, -0.5,-2.0 );
|
||||
static const float4 Cx = float4( 1.0, 1.0, -0.5, 0.0 );
|
||||
static const float4 Ay = float4( 1.0, -1.0, -1.0, 1.0 );
|
||||
static const float4 By = float4( 2.0, 0.5, -2.0,-0.5 );
|
||||
static const float4 Cy = float4( 2.0, 0.0, -1.0, 0.5 );
|
||||
static const float4 Ci = float4(0.25, 0.25, 0.25, 0.25);
|
||||
|
||||
static const float3 Y = float3(0.2126, 0.7152, 0.0722);
|
||||
|
||||
// Difference between vector components.
|
||||
float4 df(float4 A, float4 B) { return abs(A-B); }
|
||||
|
||||
// Compare two vectors and return their components are different.
|
||||
float4 diff(float4 A, float4 B) { return step(0.001, df(A, B)); }
|
||||
|
||||
// Determine if two vector components are equal based on a threshold.
|
||||
float4 eq(float4 A, float4 B) { return (step(df(A, B), XBR_EQ_THRESHOLD)); }
|
||||
|
||||
// Determine if two vector components are NOT equal based on a threshold.
|
||||
float4 neq(float4 A, float4 B) { return (1.0 - eq(A, B)); }
|
||||
|
||||
// Weighted distance.
|
||||
float4 wd(float4 a, float4 b, float4 c, float4 d, float4 e, float4 f, float4 g, float4 h) {
|
||||
return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h));
|
||||
}
|
||||
|
||||
float4 weighted_distance(float4 a, float4 b, float4 c, float4 d, float4 e, float4 f, float4 g, float4 h, float4 i, float4 j, float4 k, float4 l) {
|
||||
return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + df(i,j) + df(k,l) + 2.0*df(g,h));
|
||||
}
|
||||
|
||||
float c_df(float3 c1, float3 c2) {
|
||||
float3 df = abs(c1 - c2);
|
||||
return df.r + df.g + df.b;
|
||||
}
|
||||
|
||||
float4 tex_sample(float2 coord) {
|
||||
float dx = u_texSize.z;
|
||||
float dy = u_texSize.w;
|
||||
|
||||
float4 t1 = coord.xxxy + float4( -dx, 0, dx,-2.0*dy); // A1 B1 C1
|
||||
float4 t2 = coord.xxxy + float4( -dx, 0, dx, -dy); // A B C
|
||||
float4 t3 = coord.xxxy + float4( -dx, 0, dx, 0); // D E F
|
||||
float4 t4 = coord.xxxy + float4( -dx, 0, dx, dy); // G H I
|
||||
float4 t5 = coord.xxxy + float4( -dx, 0, dx, 2.0*dy); // G5 H5 I5
|
||||
float4 t6 = coord.xyyy + float4(-2.0*dx,-dy, 0, dy); // A0 D0 G0
|
||||
float4 t7 = coord.xyyy + float4( 2.0*dx,-dy, 0, dy); // C4 F4 I4
|
||||
float4 edri, edr, edr_l, edr_u, px; // px = pixel, edr = edge detection rule
|
||||
float4 irlv0, irlv1, irlv2l, irlv2u, block_3d;
|
||||
float4 fx, fx_l, fx_u; // inequations of straight lines.
|
||||
|
||||
float2 fp = frac(coord*u_texSize.xy);
|
||||
|
||||
float4 A1 = premultiply_alpha(tex_sample_direct(t1.xw));
|
||||
float4 B1 = premultiply_alpha(tex_sample_direct(t1.yw));
|
||||
float4 C1 = premultiply_alpha(tex_sample_direct(t1.zw));
|
||||
float4 A = premultiply_alpha(tex_sample_direct(t2.xw));
|
||||
float4 B = premultiply_alpha(tex_sample_direct(t2.yw));
|
||||
float4 C = premultiply_alpha(tex_sample_direct(t2.zw));
|
||||
float4 D = premultiply_alpha(tex_sample_direct(t3.xw));
|
||||
float4 E = premultiply_alpha(tex_sample_direct(t3.yw));
|
||||
float4 F = premultiply_alpha(tex_sample_direct(t3.zw));
|
||||
float4 G = premultiply_alpha(tex_sample_direct(t4.xw));
|
||||
float4 H = premultiply_alpha(tex_sample_direct(t4.yw));
|
||||
float4 I = premultiply_alpha(tex_sample_direct(t4.zw));
|
||||
float4 G5 = premultiply_alpha(tex_sample_direct(t5.xw));
|
||||
float4 H5 = premultiply_alpha(tex_sample_direct(t5.yw));
|
||||
float4 I5 = premultiply_alpha(tex_sample_direct(t5.zw));
|
||||
float4 A0 = premultiply_alpha(tex_sample_direct(t6.xy));
|
||||
float4 D0 = premultiply_alpha(tex_sample_direct(t6.xz));
|
||||
float4 G0 = premultiply_alpha(tex_sample_direct(t6.xw));
|
||||
float4 C4 = premultiply_alpha(tex_sample_direct(t7.xy));
|
||||
float4 F4 = premultiply_alpha(tex_sample_direct(t7.xz));
|
||||
float4 I4 = premultiply_alpha(tex_sample_direct(t7.xw));
|
||||
|
||||
float4 b = float4(dot(B.rgb ,rgbw), dot(D.rgb ,rgbw), dot(H.rgb ,rgbw), dot(F.rgb ,rgbw));
|
||||
float4 c = float4(dot(C.rgb ,rgbw), dot(A.rgb ,rgbw), dot(G.rgb ,rgbw), dot(I.rgb ,rgbw));
|
||||
float4 d = b.yzwx;
|
||||
float4 e = dot(E.rgb,rgbw);
|
||||
float4 f = b.wxyz;
|
||||
float4 g = c.zwxy;
|
||||
float4 h = b.zwxy;
|
||||
float4 i = c.wxyz;
|
||||
|
||||
float4 i4, i5, h5, f4;
|
||||
|
||||
float y_weight = XBR_Y_WEIGHT;
|
||||
#ifdef SMALL_DETAILS
|
||||
i4 = mul(float4x3(I4.rgb, C1.rgb, A0.rgb, G5.rgb), y_weight * Y);
|
||||
i5 = mul(float4x3(I5.rgb, C4.rgb, A1.rgb, G0.rgb), y_weight * Y);
|
||||
h5 = mul(float4x3(H5.rgb, F4.rgb, B1.rgb, D0.rgb), y_weight * Y);
|
||||
#else
|
||||
i4 = float4(dot(I4.rgb,rgbw), dot(C1.rgb,rgbw), dot(A0.rgb,rgbw), dot(G5.rgb,rgbw));
|
||||
i5 = float4(dot(I5.rgb,rgbw), dot(C4.rgb,rgbw), dot(A1.rgb,rgbw), dot(G0.rgb,rgbw));
|
||||
h5 = float4(dot(H5.rgb,rgbw), dot(F4.rgb,rgbw), dot(B1.rgb,rgbw), dot(D0.rgb,rgbw));
|
||||
#endif
|
||||
f4 = h5.yzwx;
|
||||
|
||||
// These inequations define the line below which interpolation occurs.
|
||||
fx = (Ao*fp.y+Bo*fp.x);
|
||||
fx_l = (Ax*fp.y+Bx*fp.x);
|
||||
fx_u = (Ay*fp.y+By*fp.x);
|
||||
|
||||
irlv1 = irlv0 = diff(e,f) * diff(e,h);
|
||||
|
||||
#if CORNER_TYPE == 1
|
||||
#define SMOOTH_TIPS
|
||||
#elif CORNER_TYPE == 2
|
||||
irlv1 = (irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) );
|
||||
#elif CORNER_TYPE == 3
|
||||
irlv1 = (irlv0 * ( neq(f,b) * neq(f,c) + neq(h,d) * neq(h,g) + eq(e,i) * (neq(f,f4) * neq(f,i4) + neq(h,h5) * neq(h,i5)) + eq(e,g) + eq(e,c)) );
|
||||
#else // CORNER_TYPE == 4
|
||||
float4 c1 = i4.yzwx;
|
||||
float4 g0 = i5.wxyz;
|
||||
irlv1 = (irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) * (diff(f,f4) * diff(f,i) + diff(h,h5) * diff(h,i) + diff(h,g) + diff(f,c) + eq(b,c1) * eq(d,g0)));
|
||||
#endif
|
||||
|
||||
irlv2l = diff(e,g) * diff(d,g);
|
||||
irlv2u = diff(e,c) * diff(b,c);
|
||||
|
||||
float4 fx45i = clamp((fx + delta -Co - Ci)/(2.0*delta ), 0.0, 1.0);
|
||||
float4 fx45 = clamp((fx + delta -Co )/(2.0*delta ), 0.0, 1.0);
|
||||
float4 fx30 = clamp((fx_l + delta_l -Cx )/(2.0*delta_l), 0.0, 1.0);
|
||||
float4 fx60 = clamp((fx_u + delta_u -Cy )/(2.0*delta_u), 0.0, 1.0);
|
||||
|
||||
float4 wd1, wd2;
|
||||
#ifdef SMALL_DETAILS
|
||||
wd1 = weighted_distance( e, c, g, i, f4, h5, h, f, b, d, i4, i5);
|
||||
wd2 = weighted_distance( h, d, i5, f, b, i4, e, i, g, h5, c, f4);
|
||||
#else
|
||||
wd1 = wd( e, c, g, i, h5, f4, h, f);
|
||||
wd2 = wd( h, d, i5, f, i4, b, e, i);
|
||||
#endif
|
||||
|
||||
edri = step(wd1, wd2) * irlv0;
|
||||
edr = step(wd1 + float4(0.1, 0.1, 0.1, 0.1), wd2) * step(float4(0.5, 0.5, 0.5, 0.5), irlv1);
|
||||
edr_l = step( XBR_LV2_COEFFICIENT*df(f,g), df(h,c) ) * irlv2l * edr;
|
||||
edr_u = step( XBR_LV2_COEFFICIENT*df(h,c), df(f,g) ) * irlv2u * edr;
|
||||
|
||||
fx45 = edr * fx45;
|
||||
fx30 = edr_l * fx30;
|
||||
fx60 = edr_u * fx60;
|
||||
fx45i = edri * fx45i;
|
||||
|
||||
px = step(df(e,f), df(e,h));
|
||||
|
||||
#ifdef SMOOTH_TIPS
|
||||
float4 maximos = max(max(fx30, fx60), max(fx45, fx45i));
|
||||
#else
|
||||
float4 maximos = max(max(fx30, fx60), fx45);
|
||||
#endif
|
||||
|
||||
float4 res1 = E;
|
||||
res1 = lerp(res1, lerp(H, F, px.x), maximos.x);
|
||||
res1 = lerp(res1, lerp(B, D, px.z), maximos.z);
|
||||
|
||||
float4 res2 = E;
|
||||
res2 = lerp(res2, lerp(F, B, px.y), maximos.y);
|
||||
res2 = lerp(res2, lerp(D, H, px.w), maximos.w);
|
||||
|
||||
float4 res = lerp(res1, res2, step(c_df(E.rgb, res1.rgb), c_df(E.rgb, res2.rgb)));
|
||||
return postdivide_alpha(res);
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
|
||||
// 4xBRZ shader - Copyright (C) 2014-2016 DeSmuME team
|
||||
//
|
||||
// This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
/*
|
||||
Hyllian's xBR-vertex code and texel mapping
|
||||
|
||||
Copyright (C) 2011/2016 Hyllian - sergiogdb@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define BLEND_NONE 0
|
||||
#define BLEND_NORMAL 1
|
||||
#define BLEND_DOMINANT 2
|
||||
#define LUMINANCE_WEIGHT 1.0
|
||||
#define EQUAL_COLOR_TOLERANCE 30.0/255.0
|
||||
#define STEEP_DIRECTION_THRESHOLD 2.2
|
||||
#define DOMINANT_DIRECTION_THRESHOLD 3.6
|
||||
|
||||
float reduce(float4 color)
|
||||
{
|
||||
return dot(color.rgb, float3(65536.0, 256.0, 1.0));
|
||||
}
|
||||
|
||||
float DistYCbCr(float4 pixA, float4 pixB)
|
||||
{
|
||||
const float3 w = float3(0.2627, 0.6780, 0.0593);
|
||||
const float scaleB = 0.5 / (1.0 - w.b);
|
||||
const float scaleR = 0.5 / (1.0 - w.r);
|
||||
float3 diff = pixA.rgb - pixB.rgb;
|
||||
float Y = dot(diff, w);
|
||||
float Cb = scaleB * (diff.b - Y);
|
||||
float Cr = scaleR * (diff.r - Y);
|
||||
|
||||
return sqrt( ((LUMINANCE_WEIGHT * Y) * (LUMINANCE_WEIGHT * Y)) + (Cb * Cb) + (Cr * Cr) );
|
||||
}
|
||||
|
||||
bool IsPixEqual(const float4 pixA, const float4 pixB)
|
||||
{
|
||||
return (DistYCbCr(pixA, pixB) < EQUAL_COLOR_TOLERANCE);
|
||||
}
|
||||
|
||||
bool IsBlendingNeeded(const int4 blend)
|
||||
{
|
||||
return any(blend - BLEND_NONE);
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
// Input Pixel Mapping: --|21|22|23|--
|
||||
// 19|06|07|08|09
|
||||
// 18|05|00|01|10
|
||||
// 17|04|03|02|11
|
||||
// --|15|14|13|--
|
||||
//
|
||||
// Output Pixel Mapping: 20|21|22|23|24|25
|
||||
// 19|06|07|08|09|26
|
||||
// 18|05|00|01|10|27
|
||||
// 17|04|03|02|11|28
|
||||
// 16|15|14|13|12|29
|
||||
// 35|34|33|32|31|30
|
||||
|
||||
float4 tex_sample(float2 coord)
|
||||
{
|
||||
float dx = u_texSize.z;
|
||||
float dy = u_texSize.w;
|
||||
|
||||
// A1 B1 C1
|
||||
// A0 A B C C4
|
||||
// D0 D E F F4
|
||||
// G0 G H I I4
|
||||
// G5 H5 I5
|
||||
|
||||
float4 t1 = coord.xxxy + float4( -dx, 0.0, dx,-2.0*dy); // A1 B1 C1
|
||||
float4 t2 = coord.xxxy + float4( -dx, 0.0, dx, -dy); // A B C
|
||||
float4 t3 = coord.xxxy + float4( -dx, 0.0, dx, 0.0); // D E F
|
||||
float4 t4 = coord.xxxy + float4( -dx, 0.0, dx, dy); // G H I
|
||||
float4 t5 = coord.xxxy + float4( -dx, 0.0, dx, 2.0*dy); // G5 H5 I5
|
||||
float4 t6 = coord.xyyy + float4(-2.0*dx,-dy, 0.0, dy); // A0 D0 G0
|
||||
float4 t7 = coord.xyyy + float4( 2.0*dx,-dy, 0.0, dy); // C4 F4 I4
|
||||
|
||||
float2 f = frac(coord.xy * u_texSize.xy);
|
||||
|
||||
//---------------------------------------
|
||||
// Input Pixel Mapping: |21|22|23|
|
||||
// 19|06|07|08|09
|
||||
// 18|05|00|01|10
|
||||
// 17|04|03|02|11
|
||||
// |15|14|13|
|
||||
|
||||
float4 src[25];
|
||||
|
||||
src[21] = premultiply_alpha(tex_sample_direct(t1.xw));
|
||||
src[22] = premultiply_alpha(tex_sample_direct(t1.yw));
|
||||
src[23] = premultiply_alpha(tex_sample_direct(t1.zw));
|
||||
src[ 6] = premultiply_alpha(tex_sample_direct(t2.xw));
|
||||
src[ 7] = premultiply_alpha(tex_sample_direct(t2.yw));
|
||||
src[ 8] = premultiply_alpha(tex_sample_direct(t2.zw));
|
||||
src[ 5] = premultiply_alpha(tex_sample_direct(t3.xw));
|
||||
src[ 0] = premultiply_alpha(tex_sample_direct(t3.yw));
|
||||
src[ 1] = premultiply_alpha(tex_sample_direct(t3.zw));
|
||||
src[ 4] = premultiply_alpha(tex_sample_direct(t4.xw));
|
||||
src[ 3] = premultiply_alpha(tex_sample_direct(t4.yw));
|
||||
src[ 2] = premultiply_alpha(tex_sample_direct(t4.zw));
|
||||
src[15] = premultiply_alpha(tex_sample_direct(t5.xw));
|
||||
src[14] = premultiply_alpha(tex_sample_direct(t5.yw));
|
||||
src[13] = premultiply_alpha(tex_sample_direct(t5.zw));
|
||||
src[19] = premultiply_alpha(tex_sample_direct(t6.xy));
|
||||
src[18] = premultiply_alpha(tex_sample_direct(t6.xz));
|
||||
src[17] = premultiply_alpha(tex_sample_direct(t6.xw));
|
||||
src[ 9] = premultiply_alpha(tex_sample_direct(t7.xy));
|
||||
src[10] = premultiply_alpha(tex_sample_direct(t7.xz));
|
||||
src[11] = premultiply_alpha(tex_sample_direct(t7.xw));
|
||||
|
||||
float v[9];
|
||||
v[0] = reduce(src[0]);
|
||||
v[1] = reduce(src[1]);
|
||||
v[2] = reduce(src[2]);
|
||||
v[3] = reduce(src[3]);
|
||||
v[4] = reduce(src[4]);
|
||||
v[5] = reduce(src[5]);
|
||||
v[6] = reduce(src[6]);
|
||||
v[7] = reduce(src[7]);
|
||||
v[8] = reduce(src[8]);
|
||||
|
||||
int4 blendResult = BLEND_NONE;
|
||||
|
||||
// Preprocess corners
|
||||
// Pixel Tap Mapping: --|--|--|--|--
|
||||
// --|--|07|08|--
|
||||
// --|05|00|01|10
|
||||
// --|04|03|02|11
|
||||
// --|--|14|13|--
|
||||
// Corner (1, 1)
|
||||
if ( ((v[0] == v[1] && v[3] == v[2]) || (v[0] == v[3] && v[1] == v[2])) == false)
|
||||
{
|
||||
float dist_03_01 = DistYCbCr(src[ 4], src[ 0]) + DistYCbCr(src[ 0], src[ 8]) + DistYCbCr(src[14], src[ 2]) + DistYCbCr(src[ 2], src[10]) + (4.0 * DistYCbCr(src[ 3], src[ 1]));
|
||||
float dist_00_02 = DistYCbCr(src[ 5], src[ 3]) + DistYCbCr(src[ 3], src[13]) + DistYCbCr(src[ 7], src[ 1]) + DistYCbCr(src[ 1], src[11]) + (4.0 * DistYCbCr(src[ 0], src[ 2]));
|
||||
bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_03_01) < dist_00_02;
|
||||
blendResult[2] = ((dist_03_01 < dist_00_02) && (v[0] != v[1]) && (v[0] != v[3])) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
|
||||
}
|
||||
|
||||
// Pixel Tap Mapping: --|--|--|--|--
|
||||
// --|06|07|--|--
|
||||
// 18|05|00|01|--
|
||||
// 17|04|03|02|--
|
||||
// --|15|14|--|--
|
||||
// Corner (0, 1)
|
||||
if ( ((v[5] == v[0] && v[4] == v[3]) || (v[5] == v[4] && v[0] == v[3])) == false)
|
||||
{
|
||||
float dist_04_00 = DistYCbCr(src[17], src[ 5]) + DistYCbCr(src[ 5], src[ 7]) + DistYCbCr(src[15], src[ 3]) + DistYCbCr(src[ 3], src[ 1]) + (4.0 * DistYCbCr(src[ 4], src[ 0]));
|
||||
float dist_05_03 = DistYCbCr(src[18], src[ 4]) + DistYCbCr(src[ 4], src[14]) + DistYCbCr(src[ 6], src[ 0]) + DistYCbCr(src[ 0], src[ 2]) + (4.0 * DistYCbCr(src[ 5], src[ 3]));
|
||||
bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_05_03) < dist_04_00;
|
||||
blendResult[3] = ((dist_04_00 > dist_05_03) && (v[0] != v[5]) && (v[0] != v[3])) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
|
||||
}
|
||||
|
||||
// Pixel Tap Mapping: --|--|22|23|--
|
||||
// --|06|07|08|09
|
||||
// --|05|00|01|10
|
||||
// --|--|03|02|--
|
||||
// --|--|--|--|--
|
||||
// Corner (1, 0)
|
||||
if ( ((v[7] == v[8] && v[0] == v[1]) || (v[7] == v[0] && v[8] == v[1])) == false)
|
||||
{
|
||||
float dist_00_08 = DistYCbCr(src[ 5], src[ 7]) + DistYCbCr(src[ 7], src[23]) + DistYCbCr(src[ 3], src[ 1]) + DistYCbCr(src[ 1], src[ 9]) + (4.0 * DistYCbCr(src[ 0], src[ 8]));
|
||||
float dist_07_01 = DistYCbCr(src[ 6], src[ 0]) + DistYCbCr(src[ 0], src[ 2]) + DistYCbCr(src[22], src[ 8]) + DistYCbCr(src[ 8], src[10]) + (4.0 * DistYCbCr(src[ 7], src[ 1]));
|
||||
bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_07_01) < dist_00_08;
|
||||
blendResult[1] = ((dist_00_08 > dist_07_01) && (v[0] != v[7]) && (v[0] != v[1])) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
|
||||
}
|
||||
|
||||
// Pixel Tap Mapping: --|21|22|--|--
|
||||
// 19|06|07|08|--
|
||||
// 18|05|00|01|--
|
||||
// --|04|03|--|--
|
||||
// --|--|--|--|--
|
||||
// Corner (0, 0)
|
||||
if ( ((v[6] == v[7] && v[5] == v[0]) || (v[6] == v[5] && v[7] == v[0])) == false)
|
||||
{
|
||||
float dist_05_07 = DistYCbCr(src[18], src[ 6]) + DistYCbCr(src[ 6], src[22]) + DistYCbCr(src[ 4], src[ 0]) + DistYCbCr(src[ 0], src[ 8]) + (4.0 * DistYCbCr(src[ 5], src[ 7]));
|
||||
float dist_06_00 = DistYCbCr(src[19], src[ 5]) + DistYCbCr(src[ 5], src[ 3]) + DistYCbCr(src[21], src[ 7]) + DistYCbCr(src[ 7], src[ 1]) + (4.0 * DistYCbCr(src[ 6], src[ 0]));
|
||||
bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_05_07) < dist_06_00;
|
||||
blendResult[0] = ((dist_05_07 < dist_06_00) && (v[0] != v[5]) && (v[0] != v[7])) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
|
||||
}
|
||||
|
||||
float4 dst[16];
|
||||
dst[ 0] = src[0];
|
||||
dst[ 1] = src[0];
|
||||
dst[ 2] = src[0];
|
||||
dst[ 3] = src[0];
|
||||
dst[ 4] = src[0];
|
||||
dst[ 5] = src[0];
|
||||
dst[ 6] = src[0];
|
||||
dst[ 7] = src[0];
|
||||
dst[ 8] = src[0];
|
||||
dst[ 9] = src[0];
|
||||
dst[10] = src[0];
|
||||
dst[11] = src[0];
|
||||
dst[12] = src[0];
|
||||
dst[13] = src[0];
|
||||
dst[14] = src[0];
|
||||
dst[15] = src[0];
|
||||
|
||||
// Scale pixel
|
||||
if (IsBlendingNeeded(blendResult) == true)
|
||||
{
|
||||
float dist_01_04 = DistYCbCr(src[1], src[4]);
|
||||
float dist_03_08 = DistYCbCr(src[3], src[8]);
|
||||
bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_01_04 <= dist_03_08) && (v[0] != v[4]) && (v[5] != v[4]);
|
||||
bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_03_08 <= dist_01_04) && (v[0] != v[8]) && (v[7] != v[8]);
|
||||
bool needBlend = (blendResult[2] != BLEND_NONE);
|
||||
bool doLineBlend = ( blendResult[2] >= BLEND_DOMINANT ||
|
||||
((blendResult[1] != BLEND_NONE && !IsPixEqual(src[0], src[4])) ||
|
||||
(blendResult[3] != BLEND_NONE && !IsPixEqual(src[0], src[8])) ||
|
||||
(IsPixEqual(src[4], src[3]) && IsPixEqual(src[3], src[2]) && IsPixEqual(src[2], src[1]) && IsPixEqual(src[1], src[8]) && IsPixEqual(src[0], src[2]) == false) ) == false );
|
||||
|
||||
float4 blendPix = ( DistYCbCr(src[0], src[1]) <= DistYCbCr(src[0], src[3]) ) ? src[1] : src[3];
|
||||
dst[ 2] = lerp(dst[ 2], blendPix, (needBlend && doLineBlend) ? ((haveShallowLine) ? ((haveSteepLine) ? 1.0/3.0 : 0.25) : ((haveSteepLine) ? 0.25 : 0.00)) : 0.00);
|
||||
dst[ 9] = lerp(dst[ 9], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.25 : 0.00);
|
||||
dst[10] = lerp(dst[10], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.75 : 0.00);
|
||||
dst[11] = lerp(dst[11], blendPix, (needBlend) ? ((doLineBlend) ? ((haveSteepLine) ? 1.00 : ((haveShallowLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00);
|
||||
dst[12] = lerp(dst[12], blendPix, (needBlend) ? ((doLineBlend) ? 1.00 : 0.6848532563) : 0.00);
|
||||
dst[13] = lerp(dst[13], blendPix, (needBlend) ? ((doLineBlend) ? ((haveShallowLine) ? 1.00 : ((haveSteepLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00);
|
||||
dst[14] = lerp(dst[14], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.75 : 0.00);
|
||||
dst[15] = lerp(dst[15], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.25 : 0.00);
|
||||
|
||||
dist_01_04 = DistYCbCr(src[7], src[2]);
|
||||
dist_03_08 = DistYCbCr(src[1], src[6]);
|
||||
haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_01_04 <= dist_03_08) && (v[0] != v[2]) && (v[3] != v[2]);
|
||||
haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_03_08 <= dist_01_04) && (v[0] != v[6]) && (v[5] != v[6]);
|
||||
needBlend = (blendResult[1] != BLEND_NONE);
|
||||
doLineBlend = ( blendResult[1] >= BLEND_DOMINANT ||
|
||||
!((blendResult[0] != BLEND_NONE && !IsPixEqual(src[0], src[2])) ||
|
||||
(blendResult[2] != BLEND_NONE && !IsPixEqual(src[0], src[6])) ||
|
||||
(IsPixEqual(src[2], src[1]) && IsPixEqual(src[1], src[8]) && IsPixEqual(src[8], src[7]) && IsPixEqual(src[7], src[6]) && !IsPixEqual(src[0], src[8])) ) );
|
||||
|
||||
blendPix = ( DistYCbCr(src[0], src[7]) <= DistYCbCr(src[0], src[1]) ) ? src[7] : src[1];
|
||||
dst[ 1] = lerp(dst[ 1], blendPix, (needBlend && doLineBlend) ? ((haveShallowLine) ? ((haveSteepLine) ? 1.0/3.0 : 0.25) : ((haveSteepLine) ? 0.25 : 0.00)) : 0.00);
|
||||
dst[ 6] = lerp(dst[ 6], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.25 : 0.00);
|
||||
dst[ 7] = lerp(dst[ 7], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.75 : 0.00);
|
||||
dst[ 8] = lerp(dst[ 8], blendPix, (needBlend) ? ((doLineBlend) ? ((haveSteepLine) ? 1.00 : ((haveShallowLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00);
|
||||
dst[ 9] = lerp(dst[ 9], blendPix, (needBlend) ? ((doLineBlend) ? 1.00 : 0.6848532563) : 0.00);
|
||||
dst[10] = lerp(dst[10], blendPix, (needBlend) ? ((doLineBlend) ? ((haveShallowLine) ? 1.00 : ((haveSteepLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00);
|
||||
dst[11] = lerp(dst[11], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.75 : 0.00);
|
||||
dst[12] = lerp(dst[12], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.25 : 0.00);
|
||||
|
||||
dist_01_04 = DistYCbCr(src[5], src[8]);
|
||||
dist_03_08 = DistYCbCr(src[7], src[4]);
|
||||
haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_01_04 <= dist_03_08) && (v[0] != v[8]) && (v[1] != v[8]);
|
||||
haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_03_08 <= dist_01_04) && (v[0] != v[4]) && (v[3] != v[4]);
|
||||
needBlend = (blendResult[0] != BLEND_NONE);
|
||||
doLineBlend = ( blendResult[0] >= BLEND_DOMINANT ||
|
||||
!((blendResult[3] != BLEND_NONE && !IsPixEqual(src[0], src[8])) ||
|
||||
(blendResult[1] != BLEND_NONE && !IsPixEqual(src[0], src[4])) ||
|
||||
(IsPixEqual(src[8], src[7]) && IsPixEqual(src[7], src[6]) && IsPixEqual(src[6], src[5]) && IsPixEqual(src[5], src[4]) && !IsPixEqual(src[0], src[6])) ) );
|
||||
|
||||
blendPix = ( DistYCbCr(src[0], src[5]) <= DistYCbCr(src[0], src[7]) ) ? src[5] : src[7];
|
||||
dst[ 0] = lerp(dst[ 0], blendPix, (needBlend && doLineBlend) ? ((haveShallowLine) ? ((haveSteepLine) ? 1.0/3.0 : 0.25) : ((haveSteepLine) ? 0.25 : 0.00)) : 0.00);
|
||||
dst[15] = lerp(dst[15], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.25 : 0.00);
|
||||
dst[ 4] = lerp(dst[ 4], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.75 : 0.00);
|
||||
dst[ 5] = lerp(dst[ 5], blendPix, (needBlend) ? ((doLineBlend) ? ((haveSteepLine) ? 1.00 : ((haveShallowLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00);
|
||||
dst[ 6] = lerp(dst[ 6], blendPix, (needBlend) ? ((doLineBlend) ? 1.00 : 0.6848532563) : 0.00);
|
||||
dst[ 7] = lerp(dst[ 7], blendPix, (needBlend) ? ((doLineBlend) ? ((haveShallowLine) ? 1.00 : ((haveSteepLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00);
|
||||
dst[ 8] = lerp(dst[ 8], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.75 : 0.00);
|
||||
dst[ 9] = lerp(dst[ 9], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.25 : 0.00);
|
||||
|
||||
|
||||
dist_01_04 = DistYCbCr(src[3], src[6]);
|
||||
dist_03_08 = DistYCbCr(src[5], src[2]);
|
||||
haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_01_04 <= dist_03_08) && (v[0] != v[6]) && (v[7] != v[6]);
|
||||
haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_03_08 <= dist_01_04) && (v[0] != v[2]) && (v[1] != v[2]);
|
||||
needBlend = (blendResult[3] != BLEND_NONE);
|
||||
doLineBlend = ( blendResult[3] >= BLEND_DOMINANT ||
|
||||
!((blendResult[2] != BLEND_NONE && !IsPixEqual(src[0], src[6])) ||
|
||||
(blendResult[0] != BLEND_NONE && !IsPixEqual(src[0], src[2])) ||
|
||||
(IsPixEqual(src[6], src[5]) && IsPixEqual(src[5], src[4]) && IsPixEqual(src[4], src[3]) && IsPixEqual(src[3], src[2]) && !IsPixEqual(src[0], src[4])) ) );
|
||||
|
||||
blendPix = ( DistYCbCr(src[0], src[3]) <= DistYCbCr(src[0], src[5]) ) ? src[3] : src[5];
|
||||
dst[ 3] = lerp(dst[ 3], blendPix, (needBlend && doLineBlend) ? ((haveShallowLine) ? ((haveSteepLine) ? 1.0/3.0 : 0.25) : ((haveSteepLine) ? 0.25 : 0.00)) : 0.00);
|
||||
dst[12] = lerp(dst[12], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.25 : 0.00);
|
||||
dst[13] = lerp(dst[13], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.75 : 0.00);
|
||||
dst[14] = lerp(dst[14], blendPix, (needBlend) ? ((doLineBlend) ? ((haveSteepLine) ? 1.00 : ((haveShallowLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00);
|
||||
dst[15] = lerp(dst[15], blendPix, (needBlend) ? ((doLineBlend) ? 1.00 : 0.6848532563) : 0.00);
|
||||
dst[ 4] = lerp(dst[ 4], blendPix, (needBlend) ? ((doLineBlend) ? ((haveShallowLine) ? 1.00 : ((haveSteepLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00);
|
||||
dst[ 5] = lerp(dst[ 5], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.75 : 0.00);
|
||||
dst[ 6] = lerp(dst[ 6], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.25 : 0.00);
|
||||
}
|
||||
|
||||
// select output pixel
|
||||
float4 res = lerp(lerp(lerp(lerp(dst[ 6], dst[ 7], step(0.25, f.x)),
|
||||
lerp(dst[ 8], dst[ 9], step(0.75, f.x)),
|
||||
step(0.50, f.x)),
|
||||
lerp(lerp(dst[ 5], dst[ 0], step(0.25, f.x)),
|
||||
lerp(dst[ 1], dst[10], step(0.75, f.x)),
|
||||
step(0.50, f.x)),
|
||||
step(0.25, f.y)),
|
||||
lerp(lerp(lerp(dst[ 4], dst[ 3], step(0.25, f.x)),
|
||||
lerp(dst[ 2], dst[11], step(0.75, f.x)),
|
||||
step(0.50, f.x)),
|
||||
lerp(lerp(dst[15], dst[14], step(0.25, f.x)),
|
||||
lerp(dst[13], dst[12], step(0.75, f.x)),
|
||||
step(0.50, f.x)),
|
||||
step(0.75, f.y)),
|
||||
step(0.50, f.y));
|
||||
|
||||
return postdivide_alpha(res);
|
||||
};
|
||||
@@ -175,7 +175,7 @@ static RetroOption<int> ppsspp_button_preference("ppsspp_button_preference", "Co
|
||||
static RetroOption<bool> ppsspp_fast_memory("ppsspp_fast_memory", "Fast Memory (Speedhack)", true);
|
||||
static RetroOption<bool> ppsspp_block_transfer_gpu("ppsspp_block_transfer_gpu", "Block Transfer GPU", true);
|
||||
static RetroOption<int> ppsspp_texture_scaling_level("ppsspp_texture_scaling_level", "Texture Scaling Level", { { "1", 1 }, { "2", 2 }, { "3", 3 }, { "4", 4 }, { "5", 5 }, { "0", 0 } });
|
||||
static RetroOption<int> ppsspp_texture_scaling_type("ppsspp_texture_scaling_type", "Texture Scaling Type", { { "xbrz", TextureScalerCommon::XBRZ }, { "hybrid", TextureScalerCommon::HYBRID }, { "bicubic", TextureScalerCommon::BICUBIC }, { "hybrid_bicubic", TextureScalerCommon::HYBRID_BICUBIC }, { "SABR", TextureScalerCommon::SABR }, { "gaussian", TextureScalerCommon::GAUSSIAN }, { "cosine", TextureScalerCommon::COSINE } });
|
||||
static RetroOption<int> ppsspp_texture_scaling_type("ppsspp_texture_scaling_type", "Texture Scaling Type", { { "xbrz", TextureScalerCommon::XBRZ }, { "hybrid", TextureScalerCommon::HYBRID }, { "bicubic", TextureScalerCommon::BICUBIC }, { "hybrid_bicubic", TextureScalerCommon::HYBRID_BICUBIC }, { "XBR", TextureScalerCommon::XBR }, { "SABR", TextureScalerCommon::SABR }, { "gaussian", TextureScalerCommon::GAUSSIAN }, { "cosine", TextureScalerCommon::COSINE } });
|
||||
static RetroOption<bool> ppsspp_texture_scaling_realtime("ppsspp_texture_scaling_realtime", "Realtime Texture Scaling", false);
|
||||
static RetroOption<int> ppsspp_texture_anisotropic_filtering("ppsspp_texture_anisotropic_filtering", "Anisotropic Filtering", { "off", "1x", "2x", "4x", "8x", "16x" });
|
||||
static RetroOption<bool> ppsspp_texture_deposterize("ppsspp_texture_deposterize", "Texture Deposterize", false);
|
||||
|
||||
Reference in new issue
Block a user