mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-05-09 03:41:10 +08:00
268 lines
7.5 KiB
HLSL
268 lines
7.5 KiB
HLSL
/*
|
|
* Hq2x scaler pixel shader version by Mitja Gros (Mitja.Gros@gmail.com)
|
|
*
|
|
* Port of OpenGL-HQ Copyright (C) 2004-2005 Jörg Walter <jwalt@garni.ch>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "scaling.inc"
|
|
|
|
string name : NAME = "hq2x";
|
|
float scaling : SCALING = 1.00;
|
|
float staticTreshold : HQ2XSTATICTRESHOLD = 10.0 / 255.0;
|
|
float dynamicTreshold : HQ2XDYNAMICTRESHOLD = 33.0 / 100.0;
|
|
|
|
// combineTechnique: Final combine steps. Outputs to destination frame buffer
|
|
string combineTechique : COMBINETECHNIQUE = "Combine_hq2x";
|
|
|
|
// sourcetexture -> workingtexture
|
|
string preprocessTechique : PREPROCESSTECHNIQUE = "Preprocess0_hq2x";
|
|
// workingtexture -> workingtexture1
|
|
string preprocessTechique1 : PREPROCESSTECHNIQUE1 = "Preprocess1_hq2x";
|
|
|
|
texture Hq2xLookupTexture : HQ2XLOOKUPTEXTURE;
|
|
|
|
sampler Hq2xLookupSampler = sampler_state {
|
|
Texture = (Hq2xLookupTexture);
|
|
MinFilter = POINT;
|
|
MagFilter = POINT;
|
|
MipFilter = NONE;
|
|
AddressU = Clamp;
|
|
AddressV = Clamp;
|
|
AddressW = Clamp;
|
|
SRGBTEXTURE = FALSE;
|
|
};
|
|
|
|
struct VS_OUTPUT_PRODUCT0
|
|
{
|
|
float4 Position : POSITION;
|
|
float2 pixel0 : TEXCOORD0;
|
|
float2 pixel1 : TEXCOORD1;
|
|
float2 pixel2 : TEXCOORD2;
|
|
float2 pixel3 : TEXCOORD3;
|
|
};
|
|
|
|
struct VS_OUTPUT_PRODUCT1
|
|
{
|
|
float4 Position : POSITION;
|
|
float2 pixel0 : TEXCOORD0;
|
|
float2 pixel1 : TEXCOORD1;
|
|
float2 pixel2 : TEXCOORD2;
|
|
float2 pixel3 : TEXCOORD3;
|
|
};
|
|
|
|
struct VS_OUTPUT_PRODUCT2
|
|
{
|
|
float4 Position : POSITION;
|
|
float2 pixel0 : TEXCOORD0;
|
|
};
|
|
|
|
// vertex shaders
|
|
VS_OUTPUT_PRODUCT0 VS_Product0(
|
|
float3 Position : POSITION,
|
|
float2 TexCoord : TEXCOORD0)
|
|
{
|
|
VS_OUTPUT_PRODUCT0 Out = (VS_OUTPUT_PRODUCT0)0;
|
|
|
|
const float4 coordmask = { 1, 0, 1, 0 };
|
|
|
|
Out.Position = mul(half4(Position, 1), WorldViewProjection); // Matrix multipliy
|
|
Out.pixel0 = TexCoord;
|
|
Out.pixel1 = TexelSize * coordmask + Out.pixel0;
|
|
Out.pixel2 = TexelSize * coordmask.gbra + Out.pixel0;
|
|
Out.pixel3 = TexelSize + Out.pixel0;
|
|
|
|
return Out;
|
|
}
|
|
|
|
VS_OUTPUT_PRODUCT1 VS_Product1(
|
|
float3 Position : POSITION,
|
|
float2 TexCoord : TEXCOORD0)
|
|
{
|
|
VS_OUTPUT_PRODUCT1 Out = (VS_OUTPUT_PRODUCT1)0;
|
|
|
|
const float4 coordmask = { 0, -1, 0, 0.0625 };
|
|
|
|
Out.Position = mul(half4(Position, 1), WorldViewProjection); // Matrix multipliy
|
|
Out.pixel3 = TexCoord;
|
|
Out.pixel0 = Out.pixel3 - TexelSize;
|
|
Out.pixel1 = TexelSize.x * coordmask + Out.pixel3;
|
|
Out.pixel2 = TexelSize.x * coordmask.gbra + Out.pixel3;
|
|
|
|
return Out;
|
|
}
|
|
|
|
VS_OUTPUT_PRODUCT2 VS_Product2(
|
|
float3 Position : POSITION,
|
|
float2 TexCoord : TEXCOORD0)
|
|
{
|
|
VS_OUTPUT_PRODUCT2 Out = (VS_OUTPUT_PRODUCT2)0;
|
|
|
|
Out.Position = mul(half4(Position, 1), WorldViewProjection); // Matrix multipliy
|
|
|
|
Out.pixel0 = TexCoord;
|
|
|
|
return Out;
|
|
}
|
|
|
|
// pixel shaders
|
|
half PS_Product0_Diff(half4 pixel1, half4 pixel2)
|
|
{
|
|
const half4 weight = { 1.884313725490196078431372549, 3.768627450980392156862745098, 2.822790287990196078431372548, 0 };
|
|
const half4 mask = { 0.4710784313725490196078431372, 0, -0.4710784313725490196078431372, 0 };
|
|
|
|
half4 diff = 0, rmean = 0;
|
|
|
|
diff.rgb = pixel1 - pixel2;
|
|
rmean.a = pixel1.r + pixel2.r;
|
|
rmean.rgb = rmean.a * mask + weight;
|
|
diff.rgb = diff * diff;
|
|
return clamp(dot(rmean, diff), 0 , 1);
|
|
}
|
|
|
|
half4 PS_Product0 ( in VS_OUTPUT_PRODUCT0 input ) : COLOR
|
|
{
|
|
half4 pixel0 = tex2D(SourceSampler, input.pixel0);
|
|
half4 pixel1 = tex2D(SourceSampler, input.pixel1);
|
|
half4 pixel2 = tex2D(SourceSampler, input.pixel2);
|
|
half4 pixel3 = tex2D(SourceSampler, input.pixel3);
|
|
|
|
half4 result = 0;
|
|
|
|
result.b = PS_Product0_Diff(pixel0, pixel3);
|
|
result.r = PS_Product0_Diff(pixel0, pixel1);
|
|
result.g = PS_Product0_Diff(pixel0, pixel2);
|
|
result.a = PS_Product0_Diff(pixel1, pixel2);
|
|
|
|
return result;
|
|
}
|
|
|
|
half4 PS_Product1 ( in VS_OUTPUT_PRODUCT1 input ) : COLOR
|
|
{
|
|
const half4 constant = { 65536, 0.1666666666666666, 1, 0 };
|
|
const half4 factors = { 0.0627450980392157, 0.125490196078431, 0.250980392156863, 0.501960784313725 };
|
|
const half4 oneSixteenth = { 0, -1, 0, 0.0625 };
|
|
|
|
half4 pixel0 = tex2D(WorkingSampler, input.pixel0);
|
|
half4 pixel1 = tex2D(WorkingSampler, input.pixel1);
|
|
half4 pixel2 = tex2D(WorkingSampler, input.pixel2);
|
|
half4 pixel3 = tex2D(WorkingSampler, input.pixel3);
|
|
|
|
half4 minimum = 0, currentTrigger = 0, result = 0;
|
|
|
|
pixel1.r = pixel0.b;
|
|
pixel2.g = pixel0.a;
|
|
|
|
minimum = pixel1 + pixel2 + pixel3;
|
|
currentTrigger.a = dot(minimum, constant.g);
|
|
currentTrigger.a = clamp(currentTrigger.a * dynamicTreshold, 0, 1);
|
|
currentTrigger.a = max(currentTrigger.a, staticTreshold);
|
|
|
|
currentTrigger.a = currentTrigger.a * constant.r;
|
|
pixel1 = clamp(pixel1 * constant.r - currentTrigger.a, 0, 1);
|
|
pixel2 = clamp(pixel2 * constant.r - currentTrigger.a, 0, 1);
|
|
pixel3 = clamp(pixel3 * constant.r - currentTrigger.a, 0, 1);
|
|
|
|
result.a = dot(pixel3, factors);
|
|
pixel2 = pixel2 * oneSixteenth.a + pixel1;
|
|
result.rgb = dot(pixel2, factors);
|
|
|
|
return result;
|
|
}
|
|
|
|
half4 PS_Product2 ( in VS_OUTPUT_PRODUCT2 input ) : COLOR
|
|
{
|
|
const half4 cap = { 1.142857142857142857127368540393064222371, -0.07142857142857143002735720305196309709572, 0.83825, 0.080875 };
|
|
const half4 constant = { 0.0625, 0.5, 0.99609375, 0.001953125 };
|
|
|
|
half2 coord1 = 0.0f;
|
|
half2 coord2 = 0.0f;
|
|
half2 coord3 = 0.0f;
|
|
half3 centerOffset = 0.0f;
|
|
|
|
half4 diff = tex2D(WorkingSampler1, input.pixel0);
|
|
|
|
centerOffset.xy = input.pixel0.xy * SourceDims.xy;
|
|
centerOffset.xy = frac(centerOffset.xy);
|
|
|
|
coord3.xy = centerOffset.xy - constant.g;
|
|
coord3 = (coord3 < 0) ? -TexelSize : TexelSize;
|
|
|
|
coord3.xy = input.pixel0 + coord3;
|
|
coord1.x = coord3.x;
|
|
coord1.y = input.pixel0.y;
|
|
coord2.x = input.pixel0.x;
|
|
coord2.y = coord3.y;
|
|
|
|
centerOffset.xy = clamp(centerOffset.xy * cap.r + cap.g, 0, 1);
|
|
centerOffset.xy = centerOffset.xy * cap.b + cap.a;
|
|
|
|
centerOffset.x = centerOffset.x * constant.x + diff.a;
|
|
centerOffset.z = diff.z * constant.b + constant.a;
|
|
|
|
half4 pixel0 = tex2D(SourceSampler, input.pixel0);
|
|
half4 pixel1 = tex2D(SourceSampler, coord1);
|
|
half4 pixel2 = tex2D(SourceSampler, coord2);
|
|
half4 pixel3 = tex2D(SourceSampler, coord3);
|
|
half4 factors = tex3D(Hq2xLookupSampler, centerOffset);
|
|
|
|
pixel0 = pixel0 * factors.b;
|
|
pixel0 = pixel1 * factors.g + pixel0;
|
|
pixel0 = pixel2 * factors.r + pixel0;
|
|
half4 result = pixel3 * factors.a + pixel0;
|
|
|
|
return result;
|
|
}
|
|
|
|
technique Preprocess0_hq2x
|
|
{
|
|
pass P0
|
|
{
|
|
// shaders
|
|
VertexShader = compile vs_2_0 VS_Product0();
|
|
PixelShader = compile ps_2_0 PS_Product0();
|
|
AlphaBlendEnable = FALSE;
|
|
ColorWriteEnable = RED|GREEN|BLUE|ALPHA;
|
|
SRGBWRITEENABLE = FALSE;
|
|
}
|
|
}
|
|
|
|
technique Preprocess1_hq2x
|
|
{
|
|
pass P0
|
|
{
|
|
// shaders
|
|
VertexShader = compile vs_2_0 VS_Product1();
|
|
PixelShader = compile ps_2_0 PS_Product1();
|
|
AlphaBlendEnable = FALSE;
|
|
ColorWriteEnable = RED|GREEN|BLUE|ALPHA;
|
|
SRGBWRITEENABLE = FALSE;
|
|
}
|
|
}
|
|
|
|
technique Combine_hq2x
|
|
{
|
|
pass P0
|
|
{
|
|
// shaders
|
|
VertexShader = compile vs_2_0 VS_Product2();
|
|
PixelShader = compile ps_2_0 PS_Product2();
|
|
AlphaBlendEnable = FALSE;
|
|
ColorWriteEnable = RED|GREEN|BLUE|ALPHA;
|
|
SRGBWRITEENABLE = FALSE;
|
|
}
|
|
}
|