mirror of
https://github.com/Blinue/Magpie.git
synced 2026-06-24 02:04:10 +00:00
为 Adaptive Sharpen Effect 添加 Strength 属性
This commit is contained in:
parent
8159e2c5f5
commit
52eca2e45b
19 changed files with 313 additions and 144 deletions
|
|
@ -3,7 +3,9 @@
|
|||
#include "GUIDs.h"
|
||||
#include "Shaders.h"
|
||||
#include "SimpleDrawTransform.h"
|
||||
#include "AdaptiveSharpenPass2Transform.h"
|
||||
#include "EffectBase.h"
|
||||
#include <d2d1effecthelpers.h>
|
||||
|
||||
|
||||
// Adaptive sharpen Ëã·¨
|
||||
|
|
@ -16,17 +18,15 @@ public:
|
|||
HRESULT hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_pass1Transform,
|
||||
ADAPTIVE_SHARPEN_PASS1_SHADER,
|
||||
MAGPIE_ADAPTIVE_SHARPEN_PASS1_SHADER,
|
||||
GUID_MAGPIE_ADAPTIVE_SHARPEN_PASS1_SHADER
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
hr = SimpleDrawTransform::Create(
|
||||
hr = AdaptiveSharpenPass2Transform::Create(
|
||||
pEffectContext,
|
||||
&_pass2Transform,
|
||||
ADAPTIVE_SHARPEN_PASS2_SHADER,
|
||||
GUID_MAGPIE_ADAPTIVE_SHARPEN_PASS2_SHADER
|
||||
&_pass2Transform
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
|
|
@ -57,20 +57,51 @@ public:
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SetStrength(FLOAT value) {
|
||||
if (value < 0 || value > 1) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
// 将 0~1 映射到 0.3~2
|
||||
_pass2Transform->SetCurveHeight(value * 1.7f + 0.3f);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
FLOAT GetStrength() const {
|
||||
// 将 0.3~2 映射到 0~1
|
||||
return (_pass2Transform->GetCurveHeight() - 0.3f) / 1.7f;
|
||||
}
|
||||
|
||||
enum PROPS {
|
||||
// FLOAT 类型。指示锐化强度,取值范围为 0~1,默认值为 0
|
||||
PROP_STRENGTH = 0
|
||||
};
|
||||
|
||||
static HRESULT Register(_In_ ID2D1Factory1* pFactory) {
|
||||
const D2D1_PROPERTY_BINDING bindings[] =
|
||||
{
|
||||
D2D1_VALUE_TYPE_BINDING(L"Strength", &SetStrength, &GetStrength),
|
||||
};
|
||||
|
||||
HRESULT hr = pFactory->RegisterEffectFromString(CLSID_MAGPIE_ADAPTIVE_SHARPEN_EFFECT, XML(
|
||||
<?xml version='1.0'?>
|
||||
<Effect>
|
||||
<!--System Properties-->
|
||||
<Property name='DisplayName' type='string' value='Ripple' />
|
||||
<Property name='Author' type='string' value='Microsoft Corporation' />
|
||||
<Property name='Category' type='string' value='Stylize' />
|
||||
<Property name='Description' type='string' value='Adds a ripple effect that can be animated' />
|
||||
<Property name='DisplayName' type='string' value='Adaptive Sharpen' />
|
||||
<Property name='Author' type='string' value='Xu Liu' />
|
||||
<Property name='Category' type='string' value='Sharpen' />
|
||||
<Property name='Description' type='string' value='Adaptive Sharpen' />
|
||||
<Inputs>
|
||||
<Input name='Source' />
|
||||
</Inputs>
|
||||
<Property name='Strength' type='float'>
|
||||
<Property name='DisplayName' type='string' value='Strength' />
|
||||
<Property name='Default' type='float' value='0' />
|
||||
<Property name='Min' type='float' value='0' />
|
||||
<Property name='Max' type='float' value='1' />
|
||||
</Property>
|
||||
</Effect>
|
||||
), nullptr, 0, CreateEffect);
|
||||
), bindings, ARRAYSIZE(bindings), CreateEffect);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
|
@ -90,5 +121,5 @@ private:
|
|||
AdaptiveSharpenEffect() {}
|
||||
|
||||
ComPtr<SimpleDrawTransform> _pass1Transform = nullptr;
|
||||
ComPtr<SimpleDrawTransform> _pass2Transform = nullptr;
|
||||
ComPtr<AdaptiveSharpenPass2Transform> _pass2Transform = nullptr;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,12 +31,45 @@ D2D_PS_ENTRY(main) {
|
|||
// [ c20, c6, c7, c8, c17 ]
|
||||
// [ c15, c12, c14 ]
|
||||
// [ c13 ]
|
||||
float3 c[25] = {
|
||||
SampleInputCur(0), SampleInputOffCheckLeftTop(0, -1, -1), SampleInputOffCheckTop(0, 0, -1), SampleInputOffCheckRightTop(0, 1, -1), SampleInputOffCheckLeft(0, -1, 0),
|
||||
SampleInputOffCheckRight(0, 1, 0), SampleInputOffCheckLeftBottom(0, -1, 1), SampleInputOffCheckBottom(0, 0, 1), SampleInputOffCheckRightBottom(0, 1, 1), SampleInputOffCheckTop(0, 0, -2),
|
||||
SampleInputOffCheckLeft(0, -2, 0), SampleInputOffCheckRight(0, 2, 0), SampleInputOffCheckBottom(0, 0, 2), SampleInputOffCheckBottom(0, 0, 3), SampleInputOffCheckRightBottom(0, 1, 2),
|
||||
SampleInputOffCheckLeftBottom(0, -1, 2), SampleInputOffCheckRight(0, 3, 0), SampleInputOffCheckRightBottom(0, 2, 1), SampleInputOffCheckRightTop(0, 2,-1), SampleInputOffCheckLeft(0, -3, 0),
|
||||
SampleInputOffCheckLeftBottom(0, -2, 1), SampleInputOffCheckLeftTop(0, -2, -1), SampleInputOffCheckTop(0, 0, -3), SampleInputOffCheckRightTop(0, 1, -2), SampleInputOffCheckLeftTop(0, -1, -2)
|
||||
float left1X = GetCheckedLeft(0, 1);
|
||||
float left2X = GetCheckedLeft(0, 2);
|
||||
float left3X = GetCheckedLeft(0, 3);
|
||||
float right1X = GetCheckedRight(0, 1);
|
||||
float right2X = GetCheckedRight(0, 2);
|
||||
float right3X = GetCheckedRight(0, 3);
|
||||
float top1Y = GetCheckedTop(0, 1);
|
||||
float top2Y = GetCheckedTop(0, 2);
|
||||
float top3Y = GetCheckedTop(0, 3);
|
||||
float bottom1Y = GetCheckedBottom(0, 1);
|
||||
float bottom2Y = GetCheckedBottom(0, 2);
|
||||
float bottom3Y = GetCheckedBottom(0, 3);
|
||||
|
||||
float3 c[25] = {
|
||||
SampleInputCur(0), // c0
|
||||
SampleInputNoCheck(0, float2(left1X, top1Y)), // c1
|
||||
SampleInputNoCheck(0, float2(coord.x, top1Y)), // c2
|
||||
SampleInputNoCheck(0, float2(right1X, top1Y)), // c3
|
||||
SampleInputNoCheck(0, float2(left1X, coord.y)), // c4
|
||||
SampleInputNoCheck(0, float2(right1X, coord.y)), // c5
|
||||
SampleInputNoCheck(0, float2(left1X, bottom1Y)), // c6
|
||||
SampleInputNoCheck(0, float2(coord.x, bottom1Y)), // c7
|
||||
SampleInputNoCheck(0, float2(right1X, bottom1Y)), // c8
|
||||
SampleInputNoCheck(0, float2(coord.x, top2Y)), // c9
|
||||
SampleInputNoCheck(0, float2(left2X, coord.y)), // c10
|
||||
SampleInputNoCheck(0, float2(right2X, coord.y)), // c11
|
||||
SampleInputNoCheck(0, float2(coord.x, bottom2Y)), // c12
|
||||
SampleInputNoCheck(0, float2(coord.x, bottom3Y)), // c13
|
||||
SampleInputNoCheck(0, float2(right1X, bottom2Y)), // c14
|
||||
SampleInputNoCheck(0, float2(left1X, bottom2Y)), // c15
|
||||
SampleInputNoCheck(0, float2(right3X, coord.y)), // c16
|
||||
SampleInputNoCheck(0, float2(right2X, bottom1Y)), // c17
|
||||
SampleInputNoCheck(0, float2(right2X, top1Y)), // c18
|
||||
SampleInputNoCheck(0, float2(left3X, coord.y)), // c19
|
||||
SampleInputNoCheck(0, float2(left2X, bottom1Y)), // c20
|
||||
SampleInputNoCheck(0, float2(left2X, top1Y)), // c21
|
||||
SampleInputNoCheck(0, float2(coord.x, top3Y)), // c22
|
||||
SampleInputNoCheck(0, float2(right1X, top2Y)), // c23
|
||||
SampleInputNoCheck(0, float2(left1X, top2Y)) // c24
|
||||
};
|
||||
|
||||
// Blur, gauss 3x3
|
||||
|
|
@ -57,5 +90,5 @@ D2D_PS_ENTRY(main) {
|
|||
+ b_diff(4) + b_diff(5) + b_diff(6) + b_diff(7) + b_diff(8)
|
||||
+ 0.25 * (b_diff(9) + b_diff(10) + b_diff(11) + b_diff(12)));
|
||||
|
||||
return float4(D2DSampleInput(0, coord.xy).rgb, Compress(edge * c_comp));
|
||||
return float4(c[0].rgb, Compress(edge * c_comp));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,25 @@
|
|||
|
||||
|
||||
// 自适应锐化算法 Pass2
|
||||
// 移植自 https://github.com/libretro/common-shaders/blob/master/sharpen/shaders/adaptive-sharpen-pass2.cg
|
||||
//
|
||||
// Adaptive sharpen
|
||||
// Tuned for use post resize, EXPECTS FULL RANGE GAMMA LIGHT
|
||||
|
||||
cbuffer constants : register(b0) {
|
||||
int2 srcSize : packoffset(c0.x);
|
||||
//float curve_height : packoffset(c0.z); // 锐化强度,必须为正值。一般在 0.3~2.0 之间
|
||||
float curveHeight : packoffset(c0.z); // 锐化强度,必须为正值。一般在 0.3~2.0 之间
|
||||
};
|
||||
#define curve_height 1
|
||||
|
||||
|
||||
#define D2D_INPUT_COUNT 1
|
||||
#define D2D_INPUT0_COMPLEX
|
||||
#define MAGPIE_USE_SAMPLE_INPUT
|
||||
#include "AdaptiveSharpen.hlsli"
|
||||
|
||||
// Adaptive sharpen
|
||||
// Tuned for use post resize, EXPECTS FULL RANGE GAMMA LIGHT
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Defined values under this row are "optimal" DO NOT CHANGE IF YOU DO NOT KNOW WHAT YOU ARE DOING!
|
||||
|
||||
#define curveslope (curve_height*0.7) // Sharpening curve slope, high edge values
|
||||
#define curveslope (curveHeight*0.7) // Sharpening curve slope, high edge values
|
||||
|
||||
#define D_overshoot 0.009 // Max dark overshoot before max compression, >0!
|
||||
#define D_compr_low 0.250 // Max compression ratio, dark overshoot (1/0.250=4x)
|
||||
|
|
@ -40,8 +41,6 @@ cbuffer constants : register(b0) {
|
|||
// Soft limit
|
||||
#define soft_lim(v,s) (((exp(2*min(abs(v),s*16)/s)-1)/(exp(2*min(abs(v),s*16)/s)+1))*s)
|
||||
|
||||
#define sat(input) (float4(saturate((input).xyz),(input).w))
|
||||
|
||||
// Colour to luma, fast approx gamma
|
||||
#define CtL(RGB) (sqrt(dot(float3(0.256,0.651,0.093),saturate((RGB).rgb*abs(RGB).rgb))))
|
||||
|
||||
|
|
@ -49,30 +48,20 @@ cbuffer constants : register(b0) {
|
|||
#define mdiff(a,b,c,d,e,f,g) (abs(luma[g]-luma[a])+abs(luma[g]-luma[b])+abs(luma[g]-luma[c])+abs(luma[g]-luma[d])+0.5*(abs(luma[g]-luma[e])+abs(luma[g]-luma[f])))
|
||||
|
||||
|
||||
float4 sample0(float2 pos) {
|
||||
float4 coord = D2DGetInputCoordinate(0);
|
||||
|
||||
pos.x = max(0, pos.x);
|
||||
pos.x = min((srcSize.x - 1) * coord.z, pos.x);
|
||||
pos.y = max(0, pos.y);
|
||||
pos.y = min((srcSize.y - 1) * coord.w, pos.y);
|
||||
|
||||
return D2DSampleInput(0, pos);
|
||||
}
|
||||
|
||||
float4 get(float x, float y) {
|
||||
float4 coord = D2DGetInputCoordinate(0);
|
||||
float4 s = sample0(coord.xy + float2(x, y) * coord.zw);
|
||||
float4 s = SampleInputRGBANoCheck(0, float2(x, y));
|
||||
return float4(s.xyz, Uncompress(s.w));
|
||||
}
|
||||
|
||||
D2D_PS_ENTRY(main) {
|
||||
float4 coord = D2DGetInputCoordinate(0);
|
||||
|
||||
float4 orig0 = get(0,0);
|
||||
D2D_PS_ENTRY(main) {
|
||||
InitMagpieSampleInput();
|
||||
|
||||
float4 orig0 = get(coord.x, coord.y);
|
||||
float c_edge = orig0.w;
|
||||
|
||||
// Displays a green screen if the edge data is not inside a valid range in the .w channel
|
||||
// Displays the origin image if the edge data is not inside a valid range in the .w channel
|
||||
if (c_edge > 32 || c_edge < -0.5) { return float4(orig0.xyz, 1); }
|
||||
|
||||
// Get points, saturate colour data in c[0]
|
||||
|
|
@ -83,11 +72,46 @@ D2D_PS_ENTRY(main) {
|
|||
// [ c20, c6, c7, c8, c17 ]
|
||||
// [ c15, c12, c14 ]
|
||||
// [ c13 ]
|
||||
float4 c[25] = { orig0, get(-1,-1), get(0,-1), get(1,-1), get(-1, 0),
|
||||
get(1, 0), get(-1, 1), get(0, 1), get(1, 1), get(0,-2),
|
||||
get(-2, 0), get(2, 0), get(0, 2), get(0, 3), get(1, 2),
|
||||
get(-1, 2), get(3, 0), get(2, 1), get(2,-1), get(-3, 0),
|
||||
get(-2, 1), get(-2,-1), get(0,-3), get(1,-2), get(-1,-2) };
|
||||
float left1X = GetCheckedLeft(0, 1);
|
||||
float left2X = GetCheckedLeft(0, 2);
|
||||
float left3X = GetCheckedLeft(0, 3);
|
||||
float right1X = GetCheckedRight(0, 1);
|
||||
float right2X = GetCheckedRight(0, 2);
|
||||
float right3X = GetCheckedRight(0, 3);
|
||||
float top1Y = GetCheckedTop(0, 1);
|
||||
float top2Y = GetCheckedTop(0, 2);
|
||||
float top3Y = GetCheckedTop(0, 3);
|
||||
float bottom1Y = GetCheckedBottom(0, 1);
|
||||
float bottom2Y = GetCheckedBottom(0, 2);
|
||||
float bottom3Y = GetCheckedBottom(0, 3);
|
||||
|
||||
float4 c[25] = {
|
||||
orig0, // c0
|
||||
get(left1X, top1Y), // c1
|
||||
get(coord.x, top1Y), // c2
|
||||
get(right1X, top1Y), // c3
|
||||
get(left1X, coord.y), // c4
|
||||
get(right1X, coord.y), // c5
|
||||
get(left1X, bottom1Y), // c6
|
||||
get(coord.x, bottom1Y), // c7
|
||||
get(right1X, bottom1Y), // c8
|
||||
get(coord.x, top2Y), // c9
|
||||
get(left2X, coord.y), // c10
|
||||
get(right2X, coord.y), // c11
|
||||
get(coord.x, bottom2Y), // c12
|
||||
get(coord.x, bottom3Y), // c13
|
||||
get(right1X, bottom2Y), // c14
|
||||
get(left1X, bottom2Y), // c15
|
||||
get(right3X, coord.y), // c16
|
||||
get(right2X, bottom1Y), // c17
|
||||
get(right2X, top1Y), // c18
|
||||
get(left3X, coord.y), // c19
|
||||
get(left2X, bottom1Y), // c20
|
||||
get(left2X, top1Y), // c21
|
||||
get(coord.x, top3Y), // c22
|
||||
get(right1X, top2Y), // c23
|
||||
get(left1X, top2Y) // c24
|
||||
};
|
||||
|
||||
// Allow for higher overshoot if the current edge pixel is surrounded by similar edge pixels
|
||||
float maxedge = (max4(max4(c[1].w, c[2].w, c[3].w, c[4].w), max4(c[5].w, c[6].w, c[7].w, c[8].w),
|
||||
|
|
@ -163,7 +187,7 @@ D2D_PS_ENTRY(main) {
|
|||
neg_laplace = pow((neg_laplace / weightsum), (1.0 / 2.4)) - 0.064;
|
||||
|
||||
// Compute sharpening magnitude function
|
||||
float sharpen_val = (lowthsum / 12) * (curve_height / (curveslope * pow(abs(c_edge), 3.5) + 0.5));
|
||||
float sharpen_val = (lowthsum / 12) * (curveHeight / (curveslope * pow(abs(c_edge), 3.5) + 0.5));
|
||||
|
||||
// Calculate sharpening diff and scale
|
||||
float sharpdiff = (c0_Y - neg_laplace) * (sharpen_val * 0.8 + 0.01);
|
||||
|
|
@ -197,5 +221,5 @@ D2D_PS_ENTRY(main) {
|
|||
// Normal path
|
||||
if (sharpdiff > 0) { return float4(minim_satloss, 1); }
|
||||
|
||||
else { return float4((c[0].rgb + sharpdiff), 1); }
|
||||
else { return float4((orig0.rgb + sharpdiff), 1); }
|
||||
}
|
||||
|
|
|
|||
55
Magpie/AdaptiveSharpenPass2Transform.h
Normal file
55
Magpie/AdaptiveSharpenPass2Transform.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
#include "GUIDs.h"
|
||||
#include "SimpleDrawTransform.h"
|
||||
|
||||
// Adaptive Sharpen Pass 2 需要 curveHeight 参数
|
||||
// curveHeight 越大,锐化程度越大
|
||||
// curveHeight 的取值在 0.3~2 之间,默认值为 0.3
|
||||
class AdaptiveSharpenPass2Transform : public SimpleDrawTransform {
|
||||
private:
|
||||
AdaptiveSharpenPass2Transform(): SimpleDrawTransform(GUID_MAGPIE_ADAPTIVE_SHARPEN_PASS2_SHADER) {}
|
||||
public:
|
||||
static HRESULT Create(_In_ ID2D1EffectContext* d2dEC, _Outptr_ AdaptiveSharpenPass2Transform** ppOutput) {
|
||||
*ppOutput = nullptr;
|
||||
|
||||
HRESULT hr = DrawTransformBase::LoadShader(
|
||||
d2dEC,
|
||||
MAGPIE_ADAPTIVE_SHARPEN_PASS2_SHADER,
|
||||
GUID_MAGPIE_ADAPTIVE_SHARPEN_PASS2_SHADER
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
*ppOutput = new AdaptiveSharpenPass2Transform();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void SetCurveHeight(float value) {
|
||||
assert(value >= 0.3 && value <= 2);
|
||||
_curveHeight = value;
|
||||
}
|
||||
|
||||
float GetCurveHeight() {
|
||||
return _curveHeight;
|
||||
}
|
||||
protected:
|
||||
void SetShaderContantBuffer(const SIZE& srcSize) override {
|
||||
struct {
|
||||
INT32 srcWidth;
|
||||
INT32 srcHeight;
|
||||
FLOAT curveHeight;
|
||||
} shaderConstants {
|
||||
srcSize.cx,
|
||||
srcSize.cy,
|
||||
_curveHeight
|
||||
};
|
||||
|
||||
_drawInfo->SetPixelShaderConstantBuffer((BYTE*)&shaderConstants, sizeof(shaderConstants));
|
||||
}
|
||||
|
||||
private:
|
||||
float _curveHeight = 0.3f;
|
||||
};
|
||||
|
|
@ -13,7 +13,7 @@ public:
|
|||
|
||||
HRESULT hr = DrawTransformBase::LoadShader(
|
||||
d2dEC,
|
||||
ANIME4K_UPSCALE_CONV_REDUCE_SHADER,
|
||||
MAGPIE_ANIME4K_UPSCALE_CONV_REDUCE_SHADER,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_CONV_REDUCE_SHADER
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ public:
|
|||
HRESULT hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_conv4x3x3x1Transform,
|
||||
ANIME4K_UPSCALE_CONV_4x3x3x1_SHADER,
|
||||
MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x1_SHADER,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x1_SHADER);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
|
|
@ -43,7 +43,7 @@ public:
|
|||
hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_conv4x3x3x8Transform1,
|
||||
ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER1,
|
||||
MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER1,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER_1);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
|
|
@ -51,7 +51,7 @@ public:
|
|||
hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_conv4x3x3x8Transform2,
|
||||
ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER2,
|
||||
MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER2,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER_2
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
|
|
@ -60,7 +60,7 @@ public:
|
|||
hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_conv4x3x3x8Transform3,
|
||||
ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER3,
|
||||
MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER3,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER_3
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
|
|
@ -69,7 +69,7 @@ public:
|
|||
hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_conv4x3x3x8Transform4,
|
||||
ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER4,
|
||||
MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER4,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER_4
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
|
|
@ -78,7 +78,7 @@ public:
|
|||
hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_conv4x3x3x8Transform5,
|
||||
ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER5,
|
||||
MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER5,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER_5
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
|
|
@ -91,7 +91,7 @@ public:
|
|||
hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_deblurKernelXTransform,
|
||||
ANIME4K_DEBLUR_KERNEL_X_SHADER,
|
||||
MAGPIE_ANIME4K_DEBLUR_KERNEL_X_SHADER,
|
||||
GUID_MAGPIE_ANIME4K_DEBLUR_KERNEL_X_SHADER
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
|
|
@ -100,7 +100,7 @@ public:
|
|||
hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_deblurKernelYTransform,
|
||||
ANIME4K_DEBLUR_KERNEL_Y_SHADER,
|
||||
MAGPIE_ANIME4K_DEBLUR_KERNEL_Y_SHADER,
|
||||
GUID_MAGPIE_ANIME4K_DEBLUR_KERNEL_Y_SHADER
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public:
|
|||
|
||||
HRESULT hr = DrawTransformBase::LoadShader(
|
||||
d2dEC,
|
||||
ANIME4K_UPSCALE_DEBLUR_OUTPUT_SHADER,
|
||||
MAGPIE_ANIME4K_UPSCALE_DEBLUR_OUTPUT_SHADER,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_DEBLUR_OUTPUT_SHADER
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ public:
|
|||
HRESULT hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_conv4x3x3x1Transform,
|
||||
ANIME4K_UPSCALE_CONV_4x3x3x1_SHADER,
|
||||
MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x1_SHADER,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x1_SHADER);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
|
|
@ -43,7 +43,7 @@ public:
|
|||
hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_conv4x3x3x8Transform1,
|
||||
ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER1,
|
||||
MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER1,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER_1);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
|
|
@ -51,7 +51,7 @@ public:
|
|||
hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_conv4x3x3x8Transform2,
|
||||
ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER2,
|
||||
MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER2,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER_2
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
|
|
@ -60,7 +60,7 @@ public:
|
|||
hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_conv4x3x3x8Transform3,
|
||||
ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER3,
|
||||
MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER3,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER_3
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
|
|
@ -69,7 +69,7 @@ public:
|
|||
hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_conv4x3x3x8Transform4,
|
||||
ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER4,
|
||||
MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER4,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER_4
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
|
|
@ -78,7 +78,7 @@ public:
|
|||
hr = SimpleDrawTransform::Create(
|
||||
pEffectContext,
|
||||
&_conv4x3x3x8Transform5,
|
||||
ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER5,
|
||||
MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER5,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER_5
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public:
|
|||
|
||||
HRESULT hr = DrawTransformBase::LoadShader(
|
||||
d2dEC,
|
||||
ANIME4K_UPSCALE_OUTPUT_SHADER,
|
||||
MAGPIE_ANIME4K_UPSCALE_OUTPUT_SHADER,
|
||||
GUID_MAGPIE_ANIME4K_UPSCALE_OUTPUT_SHADER
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ private:
|
|||
const auto& subType = effect.value("type", "");
|
||||
|
||||
if (subType == "adaptive") {
|
||||
_AddAdaptiveSharpenEffect();
|
||||
_AddAdaptiveSharpenEffect(effect);
|
||||
_AddBuiltInSharpenEffect();
|
||||
}
|
||||
} else {
|
||||
|
|
@ -89,13 +89,31 @@ private:
|
|||
|
||||
}
|
||||
|
||||
void _AddAdaptiveSharpenEffect() {
|
||||
void _AddAdaptiveSharpenEffect(const nlohmann::json& props) {
|
||||
ComPtr<ID2D1Effect> adaptiveSharpenEffect = nullptr;
|
||||
Debug::ThrowIfFailed(
|
||||
_d2dDC->CreateEffect(CLSID_MAGPIE_ADAPTIVE_SHARPEN_EFFECT, &adaptiveSharpenEffect),
|
||||
L"创建 Adaptive sharpen effect 失败"
|
||||
);
|
||||
|
||||
// strength 属性
|
||||
const auto& it = props.find("strength");
|
||||
if (it != props.end()) {
|
||||
const auto& value = *it;
|
||||
Debug::ThrowIfFalse(value.is_number(), L"非法的 strength 属性值");
|
||||
|
||||
float strength = value.get<float>();
|
||||
Debug::ThrowIfFalse(
|
||||
strength >= 0 && strength <= 1,
|
||||
L"非法的 strength 属性值"
|
||||
);
|
||||
|
||||
Debug::ThrowIfFailed(
|
||||
adaptiveSharpenEffect->SetValue(AdaptiveSharpenEffect::PROP_STRENGTH, strength),
|
||||
L"设置 strength 属性失败"
|
||||
);
|
||||
}
|
||||
|
||||
// 替换 output effect
|
||||
adaptiveSharpenEffect->SetInputEffect(0, _outputEffect.Get());
|
||||
_outputEffect = adaptiveSharpenEffect;
|
||||
|
|
@ -166,6 +184,10 @@ private:
|
|||
);
|
||||
|
||||
D2D1_VECTOR_2F scale{ scaleValues[0], scaleValues[1]};
|
||||
Debug::ThrowIfFalse(
|
||||
scale.x >= 0 && scale.y >= 0,
|
||||
L"scale 属性的值非法"
|
||||
);
|
||||
|
||||
if (scale.x == 0 || scale.y == 0) {
|
||||
// 输出图像充满屏幕
|
||||
|
|
@ -175,7 +197,7 @@ private:
|
|||
|
||||
Debug::ThrowIfFailed(
|
||||
jinc2Effect->SetValue(ScaleEffect::PROP_SCALE, scale),
|
||||
L"»ñÈ¡ scale ʧ°Ü"
|
||||
L"设置 scale 属性失败"
|
||||
);
|
||||
|
||||
// 存在 scale 则输出图像尺寸改变
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
// Jinc2 ²åÖµËã·¨
|
||||
class Jinc2Transform : public SimpleScaleTransform {
|
||||
private:
|
||||
Jinc2Transform() : SimpleScaleTransform(GUID_MAGPIE_JINC2_SCALE_SHADER) {}
|
||||
public:
|
||||
static HRESULT Create(_In_ ID2D1EffectContext* d2dEC, _Outptr_ Jinc2Transform** ppOutput) {
|
||||
|
|
@ -12,7 +13,7 @@ public:
|
|||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
HRESULT hr = DrawTransformBase::LoadShader(d2dEC, JINC2_SCALE_SHADER, GUID_MAGPIE_JINC2_SCALE_SHADER);
|
||||
HRESULT hr = DrawTransformBase::LoadShader(d2dEC, MAGPIE_JINC2_SCALE_SHADER, GUID_MAGPIE_JINC2_SCALE_SHADER);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,6 +187,7 @@
|
|||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AdaptiveSharpenEffect.h" />
|
||||
<ClInclude Include="AdaptiveSharpenPass2Transform.h" />
|
||||
<ClInclude Include="Anime4KUpscaleDeblurEffect.h" />
|
||||
<ClInclude Include="Anime4KUpscaleDeblurOutputTransform.h" />
|
||||
<ClInclude Include="Anime4KUpscaleOutputTransform.h" />
|
||||
|
|
|
|||
|
|
@ -143,6 +143,9 @@
|
|||
<ClInclude Include="ScaleEffect.h">
|
||||
<Filter>头文件\Effect</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="AdaptiveSharpenPass2Transform.h">
|
||||
<Filter>头文件\Effect</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
|
|
|
|||
|
|
@ -48,7 +48,8 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
|
|||
},
|
||||
{
|
||||
"effect": "sharpen",
|
||||
"type": "adaptive"
|
||||
"type": "adaptive",
|
||||
"strength": 0.6
|
||||
}
|
||||
])"));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ public:
|
|||
_In_ ID2D1EffectContext* pEffectContext,
|
||||
_In_ ID2D1TransformGraph* pTransformGraph
|
||||
) {
|
||||
HRESULT hr = SimpleScaleTransform::Create(pEffectContext, &_jinc2SharpTransform, MITCHELL_NETRAVALI_SCALE_SHADER, GUID_MAGPIE_MITCHELL_NETRAVALI_SCALE_SHADER);
|
||||
HRESULT hr = SimpleScaleTransform::Create(pEffectContext, &_jinc2SharpTransform, MAGPIE_MITCHELL_NETRAVALI_SCALE_SHADER, GUID_MAGPIE_MITCHELL_NETRAVALI_SCALE_SHADER);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,31 +4,31 @@
|
|||
* 锐化相关
|
||||
*/
|
||||
// Adaptive sharpen
|
||||
constexpr auto ADAPTIVE_SHARPEN_PASS1_SHADER = L"shaders/AdaptiveSharpenPass1Shader.cso";
|
||||
constexpr auto ADAPTIVE_SHARPEN_PASS2_SHADER = L"shaders/AdaptiveSharpenPass2Shader.cso";
|
||||
constexpr auto MAGPIE_ADAPTIVE_SHARPEN_PASS1_SHADER = L"shaders/AdaptiveSharpenPass1Shader.cso";
|
||||
constexpr auto MAGPIE_ADAPTIVE_SHARPEN_PASS2_SHADER = L"shaders/AdaptiveSharpenPass2Shader.cso";
|
||||
|
||||
|
||||
/*
|
||||
* Anime4K 相关
|
||||
*/
|
||||
constexpr auto ANIME4K_UPSCALE_CONV_4x3x3x1_SHADER = L"shaders/Anime4KUpscaleConv4x3x3x1Shader.cso";
|
||||
constexpr auto ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER1 = L"shaders/Anime4KUpscaleConv4x3x3x8Shader1.cso";
|
||||
constexpr auto ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER2 = L"shaders/Anime4KUpscaleConv4x3x3x8Shader2.cso";
|
||||
constexpr auto ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER3 = L"shaders/Anime4KUpscaleConv4x3x3x8Shader3.cso";
|
||||
constexpr auto ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER4 = L"shaders/Anime4KUpscaleConv4x3x3x8Shader4.cso";
|
||||
constexpr auto ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER5 = L"shaders/Anime4KUpscaleConv4x3x3x8Shader5.cso";
|
||||
constexpr auto ANIME4K_UPSCALE_CONV_REDUCE_SHADER = L"shaders/Anime4KUpscaleConvReduceShader.cso";
|
||||
constexpr auto ANIME4K_UPSCALE_OUTPUT_SHADER = L"shaders/Anime4KUpscaleOutputShader.cso";
|
||||
constexpr auto ANIME4K_DEBLUR_KERNEL_X_SHADER = L"shaders/Anime4KDeblurKernelXShader.cso";
|
||||
constexpr auto ANIME4K_DEBLUR_KERNEL_Y_SHADER = L"shaders/Anime4KDeblurKernelYShader.cso";
|
||||
constexpr auto ANIME4K_UPSCALE_DEBLUR_OUTPUT_SHADER = L"shaders/Anime4KUpscaleDeblurOutputShader.cso";
|
||||
constexpr auto MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x1_SHADER = L"shaders/Anime4KUpscaleConv4x3x3x1Shader.cso";
|
||||
constexpr auto MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER1 = L"shaders/Anime4KUpscaleConv4x3x3x8Shader1.cso";
|
||||
constexpr auto MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER2 = L"shaders/Anime4KUpscaleConv4x3x3x8Shader2.cso";
|
||||
constexpr auto MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER3 = L"shaders/Anime4KUpscaleConv4x3x3x8Shader3.cso";
|
||||
constexpr auto MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER4 = L"shaders/Anime4KUpscaleConv4x3x3x8Shader4.cso";
|
||||
constexpr auto MAGPIE_ANIME4K_UPSCALE_CONV_4x3x3x8_SHADER5 = L"shaders/Anime4KUpscaleConv4x3x3x8Shader5.cso";
|
||||
constexpr auto MAGPIE_ANIME4K_UPSCALE_CONV_REDUCE_SHADER = L"shaders/Anime4KUpscaleConvReduceShader.cso";
|
||||
constexpr auto MAGPIE_ANIME4K_UPSCALE_OUTPUT_SHADER = L"shaders/Anime4KUpscaleOutputShader.cso";
|
||||
constexpr auto MAGPIE_ANIME4K_DEBLUR_KERNEL_X_SHADER = L"shaders/Anime4KDeblurKernelXShader.cso";
|
||||
constexpr auto MAGPIE_ANIME4K_DEBLUR_KERNEL_Y_SHADER = L"shaders/Anime4KDeblurKernelYShader.cso";
|
||||
constexpr auto MAGPIE_ANIME4K_UPSCALE_DEBLUR_OUTPUT_SHADER = L"shaders/Anime4KUpscaleDeblurOutputShader.cso";
|
||||
|
||||
/*
|
||||
* 缩放相关
|
||||
*/
|
||||
// Lanczos6
|
||||
constexpr auto LANCZOS6_SCALE_SHADER = L"shaders/Lanczos6ScaleShader.cso";
|
||||
constexpr auto MAGPIE_LANCZOS6_SCALE_SHADER = L"shaders/Lanczos6ScaleShader.cso";
|
||||
// Jinc2
|
||||
constexpr auto JINC2_SCALE_SHADER = L"shaders/Jinc2ScaleShader.cso";
|
||||
constexpr auto MAGPIE_JINC2_SCALE_SHADER = L"shaders/Jinc2ScaleShader.cso";
|
||||
// Mitchell-Netravali
|
||||
constexpr auto MITCHELL_NETRAVALI_SCALE_SHADER = L"shaders/MitchellNetravaliScaleShader.cso";
|
||||
constexpr auto MAGPIE_MITCHELL_NETRAVALI_SCALE_SHADER = L"shaders/MitchellNetravaliScaleShader.cso";
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
// * 只是简单地对输入应用了一个像素着色器
|
||||
// * 无状态
|
||||
class SimpleDrawTransform : public DrawTransformBase {
|
||||
private:
|
||||
protected:
|
||||
SimpleDrawTransform(const GUID &shaderID): _shaderID(shaderID) {}
|
||||
|
||||
public:
|
||||
|
|
@ -50,11 +50,10 @@ public:
|
|||
return hr;
|
||||
}
|
||||
|
||||
_shaderConstants = {
|
||||
pInputRects[0].right - pInputRects[0].left,
|
||||
pInputRects[0].bottom - pInputRects[0].top,
|
||||
};
|
||||
_drawInfo->SetPixelShaderConstantBuffer((BYTE*)&_shaderConstants, sizeof(_shaderConstants));
|
||||
SetShaderContantBuffer(SIZE {
|
||||
pInputRects->right - pInputRects->left,
|
||||
pInputRects->bottom - pInputRects->top
|
||||
});
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
@ -64,16 +63,22 @@ public:
|
|||
return pDrawInfo->SetPixelShader(_shaderID);
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
// 继承的类可以覆盖此方法向着色器传递参数
|
||||
virtual void SetShaderContantBuffer(const SIZE& srcSize) {
|
||||
struct {
|
||||
INT32 srcWidth;
|
||||
INT32 srcHeight;
|
||||
} shaderConstants{
|
||||
srcSize.cx,
|
||||
srcSize.cy
|
||||
};
|
||||
|
||||
_drawInfo->SetPixelShaderConstantBuffer((BYTE*)&shaderConstants, sizeof(shaderConstants));
|
||||
}
|
||||
|
||||
ComPtr<ID2D1DrawInfo> _drawInfo = nullptr;
|
||||
|
||||
// 输出图像的尺寸
|
||||
D2D1_SIZE_U _destSize{};
|
||||
|
||||
struct {
|
||||
INT32 width;
|
||||
INT32 height;
|
||||
} _shaderConstants{};
|
||||
|
||||
private:
|
||||
const GUID& _shaderID;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
#include "GUIDs.h"
|
||||
#include "DrawTransformBase.h"
|
||||
#include "SimpleDrawTransform.h"
|
||||
#include "Utils.h"
|
||||
|
||||
|
||||
// 通用的 scale transform
|
||||
// Ö»Ö§³Ö scale ÊôÐÔ
|
||||
class SimpleScaleTransform : public DrawTransformBase {
|
||||
// 只支持 scale 属性,默认值为 1.0
|
||||
class SimpleScaleTransform : public SimpleDrawTransform {
|
||||
protected:
|
||||
SimpleScaleTransform(const GUID& shaderID) : _shaderID(shaderID) {}
|
||||
SimpleScaleTransform(const GUID& shaderID) : SimpleDrawTransform(shaderID) {}
|
||||
|
||||
public:
|
||||
static HRESULT Create(
|
||||
|
|
@ -40,10 +40,6 @@ public:
|
|||
return _scale;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(UINT32) GetInputCount() const override {
|
||||
return 1;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP MapInputRectsToOutputRect(
|
||||
_In_reads_(inputRectCount) const D2D1_RECT_L* pInputRects,
|
||||
_In_reads_(inputRectCount) const D2D1_RECT_L* pInputOpaqueSubRects,
|
||||
|
|
@ -71,27 +67,11 @@ public:
|
|||
};
|
||||
*pOutputOpaqueSubRect = { 0,0,0,0 };
|
||||
|
||||
SetShaderContantBuffer(srcSize, destSize);
|
||||
_SetShaderContantBuffer(srcSize, destSize);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual void SetShaderContantBuffer(const SIZE& srcSize, const SIZE& destSize) {
|
||||
struct {
|
||||
INT32 srcWidth;
|
||||
INT32 srcHeight;
|
||||
INT32 destWidth;
|
||||
INT32 destHeight;
|
||||
} shaderConstants {
|
||||
_inputRect.right - _inputRect.left,
|
||||
_inputRect.bottom - _inputRect.top,
|
||||
destSize.cx,
|
||||
destSize.cy
|
||||
};
|
||||
|
||||
_drawInfo->SetPixelShaderConstantBuffer((BYTE*)&shaderConstants, sizeof(shaderConstants));
|
||||
}
|
||||
|
||||
IFACEMETHODIMP MapOutputRectToInputRects(
|
||||
_In_ const D2D1_RECT_L* pOutputRect,
|
||||
_Out_writes_(inputRectCount) D2D1_RECT_L* pInputRects,
|
||||
|
|
@ -105,26 +85,25 @@ public:
|
|||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP MapInvalidRect(
|
||||
UINT32 inputIndex,
|
||||
D2D1_RECT_L invalidInputRect,
|
||||
_Out_ D2D1_RECT_L* pInvalidOutputRect
|
||||
) const override {
|
||||
return DrawTransformBase::MapInvalidRect(inputIndex, invalidInputRect, pInvalidOutputRect);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP SetDrawInfo(ID2D1DrawInfo* pDrawInfo) override {
|
||||
_drawInfo = pDrawInfo;
|
||||
return pDrawInfo->SetPixelShader(_shaderID);
|
||||
}
|
||||
|
||||
protected:
|
||||
ComPtr<ID2D1DrawInfo> _drawInfo = nullptr;
|
||||
// 继承的类可以覆盖此方法向着色器传递参数
|
||||
virtual void _SetShaderContantBuffer(const SIZE& srcSize, const SIZE& destSize) {
|
||||
struct {
|
||||
INT32 srcWidth;
|
||||
INT32 srcHeight;
|
||||
INT32 destWidth;
|
||||
INT32 destHeight;
|
||||
} shaderConstants{
|
||||
srcSize.cx,
|
||||
srcSize.cy,
|
||||
destSize.cx,
|
||||
destSize.cy
|
||||
};
|
||||
|
||||
_drawInfo->SetPixelShaderConstantBuffer((BYTE*)&shaderConstants, sizeof(shaderConstants));
|
||||
}
|
||||
|
||||
private:
|
||||
const GUID& _shaderID;
|
||||
|
||||
// 保存输入图像的尺寸
|
||||
D2D1_RECT_L _inputRect{};
|
||||
|
||||
|
|
|
|||
|
|
@ -16,13 +16,17 @@
|
|||
|
||||
/*
|
||||
* 包含边界检查的 SampleInput
|
||||
* 欲使用下面的宏需要在包含此文件前定义 MAGPIE_USE_SAMPLE_INPUT,然后在 main 函数的开头调用 InitMagpieSampleInput
|
||||
*/
|
||||
|
||||
static float4 coord = 0;
|
||||
|
||||
#define SampleInputNoCheck(index, pos) (D2DSampleInput(index, pos).rgb)
|
||||
#define SampleInputRGBANoCheck(index, pos) (D2DSampleInput(index, pos))
|
||||
#define SampleInputOffNoCheck(index, pos) (D2DSampleInputAtOffset(index, pos).rgb)
|
||||
#define SampleInputRGBAOffNoCheck(index, pos) (D2DSampleInputAtOffset(index, pos))
|
||||
#define SampleInputCur(index) (D2DSampleInput(index, coord.xy).rgb)
|
||||
#define SampleInputRGBACur(index) (D2DSampleInput(index, coord.xy))
|
||||
|
||||
static float2 _maxCoord = 0;
|
||||
|
||||
|
|
@ -32,6 +36,7 @@ static float2 _maxCoord = 0;
|
|||
#define _checkTop(y) (max(0, y))
|
||||
#define _checkBottom(y) (min(_maxCoord.g, y))
|
||||
|
||||
// 检查边界的 D2DSampleInput
|
||||
#define SampleInputCheckLeft(index, x, y) (SampleInputNoCheck(index, float2(_checkLeft(x), y)))
|
||||
#define SampleInputCheckRight(index, x, y) (SampleInputNoCheck(index, float2(_checkRight(x), y)))
|
||||
#define SampleInputCheckTop(index, x, y) (SampleInputNoCheck(index, float2(x, _checkTop(y))))
|
||||
|
|
@ -41,6 +46,7 @@ static float2 _maxCoord = 0;
|
|||
#define SampleInputCheckRightTop(index, x, y) (SampleInputNoCheck(index, float2(_checkRight(x), _checkTop(y))))
|
||||
#define SampleInputCheckRightBottom(index, x, y) (SampleInputNoCheck(index, float2(_checkRight(x), _checkBottom(y))))
|
||||
|
||||
// 检查边界的 D2DSampleInputAtOffset
|
||||
// 使用 rg 而不是 xy
|
||||
#define SampleInputOffCheckLeft(index, x, y) SampleInputCheckLeft(index, x * coord.z + coord.r, y * coord.w + coord.g)
|
||||
#define SampleInputOffCheckRight(index, x, y) SampleInputCheckRight(index, x * coord.z + coord.r, y * coord.w + coord.g)
|
||||
|
|
@ -51,6 +57,13 @@ static float2 _maxCoord = 0;
|
|||
#define SampleInputOffCheckRightTop(index, x, y) SampleInputCheckRightTop(index, x * coord.z + coord.r, y * coord.w + coord.g)
|
||||
#define SampleInputOffCheckRightBottom(index, x, y) SampleInputCheckRightBottom(index, x * coord.z + coord.r, y * coord.w + coord.g)
|
||||
|
||||
// 限制坐标在边界内
|
||||
// n 为 offset
|
||||
#define GetCheckedLeft(index, n) _checkLeft(coord.x - n * coord.z)
|
||||
#define GetCheckedRight(index, n) _checkRight(coord.x + n * coord.w)
|
||||
#define GetCheckedTop(index, n) _checkTop(coord.y - n * coord.z)
|
||||
#define GetCheckedBottom(index, n) _checkBottom(coord.y + n * coord.w)
|
||||
|
||||
|
||||
// 需要 main 函数的开头调用
|
||||
void InitMagpieSampleInput() {
|
||||
|
|
@ -65,6 +78,7 @@ void InitMagpieSampleInput() {
|
|||
|
||||
/*
|
||||
* RGB 和 YUV 互转
|
||||
* 需在包含此文件前定义 MAGPIE_USE_YUV
|
||||
*/
|
||||
|
||||
const static float3x3 _rgb2yuv = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue