Data: Include crt-royale
From https://github.com/akgunter/crt-royale-reshade
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
#ifndef _BLOOM_H
|
||||
#define _BLOOM_H
|
||||
|
||||
///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
|
||||
|
||||
// crt-royale: A full-featured CRT shader, with cheese.
|
||||
// Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
|
||||
//
|
||||
// crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade.
|
||||
// Copyright (C) 2020 Alex Gunter <akg7634@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or 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 "../lib/user-settings.fxh"
|
||||
#include "../lib/derived-settings-and-constants.fxh"
|
||||
#include "../lib/bind-shader-params.fxh"
|
||||
#include "../lib/gamma-management.fxh"
|
||||
#include "../lib/downsampling-functions.fxh"
|
||||
#include "../lib/blur-functions.fxh"
|
||||
#include "../lib/bloom-functions.fxh"
|
||||
|
||||
#include "shared-objects.fxh"
|
||||
|
||||
|
||||
void approximateBloomVertPS(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
const float2 delta_uv = blur_radius * float2(0.0, rcp(TEX_BEAMCONVERGENCE_HEIGHT));
|
||||
|
||||
color = float4(opaque_linear_downsample(
|
||||
samplerBeamConvergence, texcoord,
|
||||
uint((bloomapprox_downsizing_factor - 1)/2),
|
||||
delta_uv
|
||||
), 1);
|
||||
}
|
||||
|
||||
void approximateBloomHorizPS(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
const float2 delta_uv = blur_radius * float2(rcp(TEX_BEAMCONVERGENCE_WIDTH), 0.0);
|
||||
|
||||
color = float4(opaque_linear_downsample(
|
||||
samplerBloomApproxVert, texcoord,
|
||||
uint((bloomapprox_downsizing_factor - 1)/2),
|
||||
delta_uv
|
||||
), 1);
|
||||
}
|
||||
|
||||
|
||||
void bloomHorizontalVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0,
|
||||
out float bloom_sigma_runtime : TEXCOORD1
|
||||
) {
|
||||
PostProcessVS(id, position, texcoord);
|
||||
|
||||
bloom_sigma_runtime = get_min_sigma_to_blur_triad(calc_triad_size().x, bloom_diff_thresh_);
|
||||
}
|
||||
|
||||
void bloomHorizontalPS(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
in float bloom_sigma_runtime : TEXCOORD1,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
const float2 bloom_dxdy = float2(rcp(TEX_BLOOMVERTICAL_WIDTH), 0);
|
||||
|
||||
// Blur the vertically blurred brightpass horizontally by 9/17/25/43x:
|
||||
const float bloom_sigma = get_final_bloom_sigma(bloom_sigma_runtime);
|
||||
const float3 blurred_brightpass = tex2DblurNfast(samplerBloomVertical,
|
||||
texcoord, bloom_dxdy, bloom_sigma, get_intermediate_gamma());
|
||||
|
||||
// Sample the masked scanlines. Alpha contains the auto-dim factor:
|
||||
const float3 intensity_dim = tex2D_linearize(samplerMaskedScanlines, texcoord, get_intermediate_gamma()).rgb;
|
||||
const float auto_dim_factor = levels_autodim_temp;
|
||||
const float undim_factor = 1.0/auto_dim_factor;
|
||||
|
||||
// Calculate the mask dimpass, add it to the blurred brightpass, and
|
||||
// undim (from scanline auto-dim) and amplify (from mask dim) the result:
|
||||
const float mask_amplify = get_mask_amplify();
|
||||
const float3 brightpass = tex2D_linearize(samplerBrightpass, texcoord, get_intermediate_gamma()).rgb;
|
||||
const float3 dimpass = intensity_dim - brightpass;
|
||||
const float3 phosphor_bloom = (dimpass + blurred_brightpass) *
|
||||
mask_amplify * undim_factor * levels_contrast;
|
||||
|
||||
// Sample the halation texture, and let some light bleed into refractive
|
||||
// diffusion. Conceptually this occurs before the phosphor bloom, but
|
||||
// adding it in earlier passes causes black crush in the diffusion colors.
|
||||
const float3 raw_diffusion_color = tex2D_linearize(samplerBlurHorizontal, texcoord, get_intermediate_gamma()).rgb;
|
||||
const float3 raw_halation_color = dot(raw_diffusion_color, float3(1, 1, 1)) / 3.0;
|
||||
const float3 diffusion_color = levels_contrast * lerp(raw_diffusion_color, raw_halation_color, halation_weight);
|
||||
const float3 final_bloom = lerp(phosphor_bloom, diffusion_color, diffusion_weight);
|
||||
|
||||
// Encode and output the bloomed image:
|
||||
color = encode_output(float4(final_bloom, 1.0), get_intermediate_gamma());
|
||||
}
|
||||
|
||||
|
||||
void bloomVerticalVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0,
|
||||
out float bloom_sigma_runtime : TEXCOORD1
|
||||
) {
|
||||
PostProcessVS(id, position, texcoord);
|
||||
|
||||
bloom_sigma_runtime = get_min_sigma_to_blur_triad(calc_triad_size().x, bloom_diff_thresh_);
|
||||
}
|
||||
|
||||
void bloomVerticalPS(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
in float bloom_sigma_runtime : TEXCOORD1,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
const float2 bloom_dxdy = float2(0, rcp(TEX_BLOOMVERTICAL_HEIGHT));
|
||||
|
||||
// Blur the brightpass horizontally with a 9/17/25/43x blur:
|
||||
const float bloom_sigma = get_final_bloom_sigma(bloom_sigma_runtime);
|
||||
const float3 color3 = tex2DblurNfast(samplerBrightpass, texcoord,
|
||||
bloom_dxdy, bloom_sigma, get_intermediate_gamma());
|
||||
|
||||
// Encode and output the blurred image:
|
||||
color = encode_output(float4(color3, 1.0), get_intermediate_gamma());
|
||||
}
|
||||
|
||||
#endif // _BLOOM_H
|
||||
@@ -0,0 +1,131 @@
|
||||
#ifndef _BLURRING_H
|
||||
#define _BLURRING_H
|
||||
|
||||
///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
|
||||
|
||||
// crt-royale: A full-featured CRT shader, with cheese.
|
||||
// Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
|
||||
//
|
||||
// crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade.
|
||||
// Copyright (C) 2020 Alex Gunter <akg7634@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or 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
|
||||
|
||||
|
||||
|
||||
///////////////////////////////// MIT LICENSE ////////////////////////////////
|
||||
|
||||
// Copyright (C) 2014 TroggleMonkey
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
#include "../lib/gamma-management.fxh"
|
||||
#include "../lib/blur-functions.fxh"
|
||||
|
||||
#include "shared-objects.fxh"
|
||||
|
||||
|
||||
void blurHorizontalVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0,
|
||||
out float2 blur_dxdy : TEXCOORD1
|
||||
) {
|
||||
PostProcessVS(id, position, texcoord);
|
||||
|
||||
// Get the uv sample distance between output pixels. Blurs are not generic
|
||||
// Gaussian resizers, and correct blurs require:
|
||||
// 1.) OutputSize == InputSize * 2^m, where m is an integer <= 0.
|
||||
// 2.) mipmap_inputN = "true" for this pass in the preset if m != 0
|
||||
// 3.) filter_linearN = "true" except for 1x scale nearest neighbor blurs
|
||||
// Gaussian resizers would upsize using the distance between input texels
|
||||
// (not output pixels), but we avoid this and consistently blur at the
|
||||
// destination size. Otherwise, combining statically calculated weights
|
||||
// with bilinear sample exploitation would result in terrible artifacts.
|
||||
static const float2 output_size = TEX_BLURHORIZONTAL_SIZE;
|
||||
static const float2 dxdy = 1.0 / output_size;
|
||||
// This blur is vertical-only, so zero out the horizontal offset:
|
||||
blur_dxdy = float2(dxdy.x, 0.0);
|
||||
}
|
||||
|
||||
void blurHorizontalPS(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
in float2 blur_dxdy : TEXCOORD1,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
static const float3 blur_color = tex2Dblur9fast(samplerBlurVertical, texcoord, blur_dxdy, get_intermediate_gamma());
|
||||
// Encode and output the blurred image:
|
||||
// color = encode_output(float4(blur_color, 1.0), 1.0);
|
||||
color = encode_output(float4(blur_color, 1.0), get_intermediate_gamma());
|
||||
}
|
||||
|
||||
|
||||
void blurVerticalVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0,
|
||||
out float2 blur_dxdy : TEXCOORD1
|
||||
) {
|
||||
PostProcessVS(id, position, texcoord);
|
||||
|
||||
// Get the uv sample distance between output pixels. Blurs are not generic
|
||||
// Gaussian resizers, and correct blurs require:
|
||||
// 1.) OutputSize == InputSize * 2^m, where m is an integer <= 0.
|
||||
// 2.) mipmap_inputN = "true" for this pass in the preset if m != 0
|
||||
// 3.) filter_linearN = "true" except for 1x scale nearest neighbor blurs
|
||||
// Gaussian resizers would upsize using the distance between input texels
|
||||
// (not output pixels), but we avoid this and consistently blur at the
|
||||
// destination size. Otherwise, combining statically calculated weights
|
||||
// with bilinear sample exploitation would result in terrible artifacts.
|
||||
static const float2 output_size = TEX_BLURVERTICAL_SIZE;
|
||||
static const float2 dxdy = 1.0 / output_size;
|
||||
// This blur is vertical-only, so zero out the horizontal offset:
|
||||
blur_dxdy = float2(0.0, dxdy.y);
|
||||
}
|
||||
|
||||
void blurVerticalPS(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
in float2 blur_dxdy : TEXCOORD1,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
static const float3 blur_color = tex2Dblur9fast(samplerBloomApproxHoriz, texcoord, blur_dxdy, get_intermediate_gamma());
|
||||
// Encode and output the blurred image:
|
||||
// color = encode_output(float4(blur_color, 1.0), 1.0);
|
||||
color = encode_output(float4(blur_color, 1.0), get_intermediate_gamma());
|
||||
}
|
||||
|
||||
#endif // _BLURRING_H
|
||||
@@ -0,0 +1,90 @@
|
||||
#ifndef _BRIGHTPASS_H
|
||||
#define _BRIGHTPASS_H
|
||||
|
||||
///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
|
||||
|
||||
// crt-royale: A full-featured CRT shader, with cheese.
|
||||
// Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
|
||||
//
|
||||
// crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade.
|
||||
// Copyright (C) 2020 Alex Gunter <akg7634@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or 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 "../lib/user-settings.fxh"
|
||||
#include "../lib/derived-settings-and-constants.fxh"
|
||||
#include "../lib/bind-shader-params.fxh"
|
||||
#include "../lib/gamma-management.fxh"
|
||||
#include "../lib/phosphor-mask-calculations.fxh"
|
||||
#include "../lib/scanline-functions.fxh"
|
||||
#include "../lib/bloom-functions.fxh"
|
||||
#include "../lib/blur-functions.fxh"
|
||||
|
||||
|
||||
void brightpassVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0,
|
||||
out float bloom_sigma_runtime : TEXCOORD1
|
||||
) {
|
||||
PostProcessVS(id, position, texcoord);
|
||||
|
||||
bloom_sigma_runtime = get_min_sigma_to_blur_triad(calc_triad_size().x, bloom_diff_thresh_);
|
||||
}
|
||||
|
||||
void brightpassPS(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
in float bloom_sigma_runtime : TEXCOORD1,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
// Sample the masked scanlines:
|
||||
const float3 intensity_dim = tex2D_linearize(samplerMaskedScanlines, texcoord, get_intermediate_gamma()).rgb;
|
||||
// Get the full intensity, including auto-undimming, and mask compensation:
|
||||
const float mask_amplify = get_mask_amplify();
|
||||
const float3 intensity = intensity_dim * rcp(levels_autodim_temp) * mask_amplify * levels_contrast;
|
||||
|
||||
// Sample BLOOM_APPROX to estimate what a straight blur of masked scanlines
|
||||
// would look like, so we can estimate how much energy we'll receive from
|
||||
// blooming neighbors:
|
||||
const float3 phosphor_blur_approx = levels_contrast * tex2D_linearize(samplerBloomApproxHoriz, texcoord, get_intermediate_gamma()).rgb;
|
||||
|
||||
// Compute the blur weight for the center texel and the maximum energy we
|
||||
// expect to receive from neighbors:
|
||||
const float bloom_sigma = get_final_bloom_sigma(bloom_sigma_runtime);
|
||||
const float center_weight = get_center_weight(bloom_sigma);
|
||||
const float3 max_area_contribution_approx =
|
||||
max(float3(0.0, 0.0, 0.0), phosphor_blur_approx - center_weight * intensity);
|
||||
// Assume neighbors will blur 100% of their intensity (blur_ratio = 1.0),
|
||||
// because it actually gets better results (on top of being very simple),
|
||||
// but adjust all intensities for the user's desired underestimate factor:
|
||||
const float3 area_contrib_underestimate = bloom_underestimate_levels * max_area_contribution_approx;
|
||||
const float3 intensity_underestimate = bloom_underestimate_levels * intensity;
|
||||
// Calculate the blur_ratio, the ratio of intensity we want to blur:
|
||||
const float3 blur_ratio_temp =
|
||||
((float3(1.0, 1.0, 1.0) - area_contrib_underestimate) /
|
||||
intensity_underestimate - float3(1.0, 1.0, 1.0)) / (center_weight - 1.0);
|
||||
const float3 blur_ratio = saturate(blur_ratio_temp);
|
||||
// Calculate the brightpass based on the auto-dimmed, unamplified, masked
|
||||
// scanlines, encode if necessary, and return!
|
||||
const float3 brightpass = intensity_dim *
|
||||
lerp(blur_ratio, float3(1.0, 1.0, 1.0), bloom_excess);
|
||||
|
||||
color = encode_output(float4(brightpass, 1.0), get_intermediate_gamma());
|
||||
}
|
||||
|
||||
#endif // _BRIGHTPASS_H
|
||||
@@ -0,0 +1,221 @@
|
||||
#ifndef _CONTENT_BOX_H
|
||||
#define _CONTENT_BOX_H
|
||||
|
||||
///////////////////////////////// MIT LICENSE ////////////////////////////////
|
||||
|
||||
// Copyright (C) 2020 Alex Gunter
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
#include "shared-objects.fxh"
|
||||
|
||||
|
||||
void contentCropVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0
|
||||
) {
|
||||
#if _DX9_ACTIVE
|
||||
texcoord.x = (id == 1 || id == 3) ? content_right : content_left;
|
||||
texcoord.y = (id > 1) ? content_lower : content_upper;
|
||||
|
||||
position.x = (id == 1 || id == 3) ? 1 : -1;
|
||||
position.y = (id > 1) ? -1 : 1;
|
||||
position.zw = 1;
|
||||
#else
|
||||
texcoord.x = (id & 1) ? content_right : content_left;
|
||||
texcoord.y = (id & 2) ? content_lower : content_upper;
|
||||
|
||||
position.x = (id & 1) ? 1 : -1;
|
||||
position.y = (id & 2) ? -1 : 1;
|
||||
position.zw = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if USE_VERTEX_UNCROPPING
|
||||
/*
|
||||
* Using the vertex shader for uncropping can save about 0.1ms in some apps.
|
||||
* However, some apps like SNES9X w/ DX9 don't trigger a refresh of the entire screen,
|
||||
* which in turn causes the ReShade UI to "stick around" after it's closed.
|
||||
*
|
||||
* The slower algorithm forces the entire screen to refresh, which forces the
|
||||
* area outside the content box to be black. I assume most users will prefer
|
||||
* the results of the slower algorithm and won't notice the 0.1ms. Users who
|
||||
* need that 0.1ms can use a preprocessor def to recover that time.
|
||||
*/
|
||||
void contentUncropVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0
|
||||
) {
|
||||
#if _DX9_ACTIVE
|
||||
texcoord.x = id == 1 || id == 3;
|
||||
texcoord.y = id < 2;
|
||||
|
||||
position.x = (id == 1 || id == 3) ? content_scale.x : -content_scale.x;
|
||||
position.y = (id > 1) ? content_scale.y : -content_scale.y;
|
||||
position.zw = 1;
|
||||
#else
|
||||
texcoord.x = id & 1;
|
||||
texcoord.y = !(id & 2);
|
||||
|
||||
position.x = (id & 1) ? content_scale.x : -content_scale.x;
|
||||
position.y = (id & 2) ? content_scale.y : -content_scale.y;
|
||||
position.zw = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uncropContentPixelShader(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
color = tex2D(samplerGeometry, texcoord);
|
||||
}
|
||||
#else
|
||||
void contentUncropVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0
|
||||
) {
|
||||
// TODO: There's probably a better way to code this.
|
||||
// I'll figure it out later.
|
||||
#if _DX9_ACTIVE
|
||||
texcoord.x = id == 1 || id == 3;
|
||||
texcoord.y = id < 2;
|
||||
|
||||
position.x = (id == 1 || id == 3) ? 1 : -1;
|
||||
position.y = (id > 1) ? 1 : -1;
|
||||
position.zw = 1;
|
||||
#else
|
||||
texcoord.x = id & 1;
|
||||
texcoord.y = !(id & 2);
|
||||
|
||||
position.x = (id & 1) ? 1 : -1;
|
||||
position.y = (id & 2) ? 1 : -1;
|
||||
position.zw = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uncropContentPixelShader(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
const bool is_in_boundary = float(
|
||||
texcoord.x >= content_left && texcoord.x <= content_right &&
|
||||
texcoord.y >= content_upper && texcoord.y <= content_lower
|
||||
);
|
||||
const float2 texcoord_uncropped = ((texcoord - content_offset) * buffer_size + 0) / content_size;
|
||||
|
||||
const float4 raw_color = tex2D(samplerGeometry, texcoord_uncropped);
|
||||
color = float4(is_in_boundary * raw_color.rgb, raw_color.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if CONTENT_BOX_VISIBLE
|
||||
#ifndef CONTENT_BOX_INSCRIBED
|
||||
#define CONTENT_BOX_INSCRIBED 1
|
||||
#endif
|
||||
|
||||
#ifndef CONTENT_BOX_THICKNESS
|
||||
#define CONTENT_BOX_THICKNESS 5
|
||||
#endif
|
||||
|
||||
#ifndef CONTENT_BOX_COLOR_R
|
||||
#define CONTENT_BOX_COLOR_R 1.0
|
||||
#endif
|
||||
|
||||
#ifndef CONTENT_BOX_COLOR_G
|
||||
#define CONTENT_BOX_COLOR_G 0.0
|
||||
#endif
|
||||
|
||||
#ifndef CONTENT_BOX_COLOR_B
|
||||
#define CONTENT_BOX_COLOR_B 0.0
|
||||
#endif
|
||||
|
||||
static const float vert_line_thickness = float(CONTENT_BOX_THICKNESS) / BUFFER_WIDTH;
|
||||
static const float horiz_line_thickness = float(CONTENT_BOX_THICKNESS) / BUFFER_HEIGHT;
|
||||
|
||||
#if CONTENT_BOX_INSCRIBED
|
||||
// Set the outer borders to the edge of the content
|
||||
static const float left_line_1 = content_left;
|
||||
static const float left_line_2 = left_line_1 + vert_line_thickness;
|
||||
static const float right_line_2 = content_right;
|
||||
static const float right_line_1 = right_line_2 - vert_line_thickness;
|
||||
|
||||
static const float upper_line_1 = content_upper;
|
||||
static const float upper_line_2 = upper_line_1 + horiz_line_thickness;
|
||||
static const float lower_line_2 = content_lower;
|
||||
static const float lower_line_1 = lower_line_2 - horiz_line_thickness;
|
||||
#else
|
||||
// Set the inner borders to the edge of the content
|
||||
static const float left_line_2 = content_left;
|
||||
static const float left_line_1 = left_line_2 - vert_line_thickness;
|
||||
static const float right_line_1 = content_right;
|
||||
static const float right_line_2 = right_line_1 + vert_line_thickness;
|
||||
|
||||
static const float upper_line_2 = content_upper;
|
||||
static const float upper_line_1 = upper_line_2 - horiz_line_thickness;
|
||||
static const float lower_line_1 = content_lower;
|
||||
static const float lower_line_2 = lower_line_1 + horiz_line_thickness;
|
||||
#endif
|
||||
|
||||
|
||||
static const float4 box_color = float4(
|
||||
CONTENT_BOX_COLOR_R,
|
||||
CONTENT_BOX_COLOR_G,
|
||||
CONTENT_BOX_COLOR_B,
|
||||
1.0
|
||||
);
|
||||
|
||||
void contentBoxPixelShader(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
|
||||
const bool is_inside_outerbound = (
|
||||
texcoord.x >= left_line_1 && texcoord.x <= right_line_2 &&
|
||||
texcoord.y >= upper_line_1 && texcoord.y <= lower_line_2
|
||||
);
|
||||
const bool is_outside_innerbound = (
|
||||
texcoord.x <= left_line_2 || texcoord.x >= right_line_1 ||
|
||||
texcoord.y <= upper_line_2 || texcoord.y >= lower_line_1
|
||||
);
|
||||
|
||||
if (is_inside_outerbound && is_outside_innerbound) {
|
||||
color = box_color;
|
||||
}
|
||||
else {
|
||||
color = tex2D(ReShade::BackBuffer, texcoord);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // CONTENT_BOX_VISIBLE
|
||||
#endif // _CONTENT_BOX_H
|
||||
@@ -0,0 +1,137 @@
|
||||
#ifndef _DEINTERLACE_H
|
||||
#define _DEINTERLACE_H
|
||||
|
||||
///////////////////////////////// MIT LICENSE ////////////////////////////////
|
||||
|
||||
// Copyright (C) 2020 Alex Gunter
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
#include "../lib/user-settings.fxh"
|
||||
#include "../lib/derived-settings-and-constants.fxh"
|
||||
#include "../lib/bind-shader-params.fxh"
|
||||
#include "../lib/gamma-management.fxh"
|
||||
#include "../lib/scanline-functions.fxh"
|
||||
|
||||
|
||||
|
||||
void freezeFrameVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0
|
||||
) {
|
||||
float use_deinterlacing_tex = enable_interlacing && (
|
||||
scanline_deinterlacing_mode == 2 || scanline_deinterlacing_mode == 3
|
||||
);
|
||||
|
||||
texcoord.x = (id == 2) ? use_deinterlacing_tex*2.0 : 0.0;
|
||||
texcoord.y = (id == 1) ? 2.0 : 0.0;
|
||||
position = float4(texcoord * float2(2, -2) + float2(-1, 1), 0, 1);
|
||||
}
|
||||
|
||||
void freezeFramePS(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
color = tex2D(samplerBeamConvergence, texcoord);
|
||||
}
|
||||
|
||||
|
||||
void deinterlaceVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0,
|
||||
out float2 v_step : TEXCOORD1
|
||||
) {
|
||||
freezeFrameVS(id, position, texcoord);
|
||||
|
||||
v_step = float2(0.0, scanline_thickness * rcp(TEX_FREEZEFRAME_HEIGHT));
|
||||
}
|
||||
|
||||
|
||||
void deinterlacePS(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
in float2 v_step : TEXCOORD1,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
// float2 scanline_offset_norm;
|
||||
// float triangle_wave_freq;
|
||||
// bool field_parity;
|
||||
// bool wrong_field;
|
||||
// calc_wrong_field(texcoord, scanline_offset_norm, triangle_wave_freq, field_parity, wrong_field);
|
||||
|
||||
float2 rotated_coord = lerp(texcoord.yx, texcoord, geom_rotation_mode == 0 || geom_rotation_mode == 2);
|
||||
float scale = lerp(CONTENT_WIDTH, CONTENT_HEIGHT, geom_rotation_mode == 0 || geom_rotation_mode == 2);
|
||||
|
||||
InterpolationFieldData interpolation_data = calc_interpolation_field_data(rotated_coord, scale);
|
||||
|
||||
// TODO: add scanline_parity to calc_wrong_field()
|
||||
|
||||
// Weaving
|
||||
// Sample texcoord from this frame and the previous frame
|
||||
// If we're in the correct field, use the current sample
|
||||
// If we're in the wrong field, average the current and prev samples
|
||||
// In this case, we're probably averaging a color with 0 and producing a brightness of 0.5.
|
||||
[branch]
|
||||
if (enable_interlacing && scanline_deinterlacing_mode == 2) {
|
||||
// const float cur_scanline_idx = get_curr_scanline_idx(texcoord.y, content_size.y);
|
||||
// const float wrong_field = curr_line_is_wrong_field(cur_scanline_idx);
|
||||
|
||||
const float4 cur_line_color = tex2D_nograd(samplerBeamConvergence, texcoord);
|
||||
const float4 cur_line_prev_color = tex2D_nograd(samplerFreezeFrame, texcoord);
|
||||
|
||||
const float4 avg_color = (cur_line_color + cur_line_prev_color) / 2.0;
|
||||
|
||||
// Multiply by 1.5, so each pair of scanlines has total brightness 2
|
||||
const float4 raw_out_color = lerp(1.5*cur_line_color, avg_color, interpolation_data.wrong_field);
|
||||
color = encode_output(raw_out_color, deinterlacing_blend_gamma);
|
||||
}
|
||||
// Blended Weaving
|
||||
// Sample texcoord from this frame
|
||||
// From the previous frame, sample the current scanline's sibling
|
||||
// Do this by shifting up or down by a line
|
||||
// If we're in the correct field, use the current sample
|
||||
// If we're in the wrong field, average the current and prev samples
|
||||
// In this case, we're averaging two fully illuminated colors
|
||||
else if (enable_interlacing && scanline_deinterlacing_mode == 3) {
|
||||
const float2 raw_offset = lerp(1, -1, interpolation_data.scanline_parity) * v_step;
|
||||
const float2 curr_offset = lerp(0, raw_offset, interpolation_data.wrong_field);
|
||||
const float2 prev_offset = lerp(raw_offset, 0, interpolation_data.wrong_field);
|
||||
|
||||
const float4 cur_line_color = tex2D_nograd(samplerBeamConvergence, texcoord + curr_offset);
|
||||
const float4 prev_line_color = tex2D_nograd(samplerFreezeFrame, texcoord + prev_offset);
|
||||
|
||||
const float4 avg_color = (cur_line_color + prev_line_color) / 2.0;
|
||||
const float4 raw_out_color = lerp(cur_line_color, avg_color, interpolation_data.wrong_field);
|
||||
color = encode_output(raw_out_color, deinterlacing_blend_gamma);
|
||||
}
|
||||
// No temporal blending
|
||||
else {
|
||||
color = tex2D_nograd(samplerBeamConvergence, texcoord);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _DEINTERLACE_H
|
||||
@@ -0,0 +1,347 @@
|
||||
#ifndef _ELECTRON_BEAMS_H
|
||||
#define _ELECTRON_BEAMS_H
|
||||
|
||||
///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
|
||||
|
||||
// crt-royale: A full-featured CRT shader, with cheese.
|
||||
// Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
|
||||
//
|
||||
// crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade.
|
||||
// Copyright (C) 2020 Alex Gunter <akg7634@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or 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 "../lib/bind-shader-params.fxh"
|
||||
#include "../lib/gamma-management.fxh"
|
||||
#include "../lib/scanline-functions.fxh"
|
||||
|
||||
#include "content-box.fxh"
|
||||
#include "shared-objects.fxh"
|
||||
|
||||
|
||||
void calculateBeamDistsVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0
|
||||
) {
|
||||
const float compute_mask_factor = frame_count % 60 == 0 || overlay_active > 0;
|
||||
|
||||
texcoord.x = (id == 2) ? compute_mask_factor*2.0 : 0.0;
|
||||
texcoord.y = (id == 1) ? 2.0 : 0.0;
|
||||
position = float4(texcoord * float2(2, -2) + float2(-1, 1), 0, 1);
|
||||
}
|
||||
|
||||
|
||||
void calculateBeamDistsPS(
|
||||
in float4 position : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
|
||||
out float4 beam_strength : SV_Target
|
||||
) {
|
||||
InterpolationFieldData interpolation_data = precalc_interpolation_field_data(texcoord);
|
||||
|
||||
// We have to subtract off the texcoord offset to make sure we're using domain [0, 1]
|
||||
const float color_corrected = texcoord.x - 1.0 / TEX_BEAMDIST_WIDTH;
|
||||
|
||||
// Digital shape
|
||||
// Beam will be perfectly rectangular
|
||||
[branch]
|
||||
if (beam_shape_mode == 0) {
|
||||
// Double the intensity when interlacing to maintain the same apparent brightness
|
||||
const float interlacing_brightness_factor = 1 + float(
|
||||
enable_interlacing &&
|
||||
(scanline_deinterlacing_mode != 2) &&
|
||||
(scanline_deinterlacing_mode != 3)
|
||||
);
|
||||
const float raw_beam_strength = (1 - interpolation_data.scanline_parity * enable_interlacing) * interlacing_brightness_factor * levels_autodim_temp;
|
||||
|
||||
beam_strength = float4(color_corrected * raw_beam_strength, 0, 0, 1);
|
||||
}
|
||||
// Linear shape
|
||||
// Beam intensity will drop off linarly with distance from center
|
||||
// Works better than gaussian with narrow scanlines (about 1-6 pixels wide)
|
||||
// Will only consider contribution from nearest scanline
|
||||
else if (beam_shape_mode == 1) {
|
||||
const float beam_dist_y = triangle_wave(texcoord.y, interpolation_data.triangle_wave_freq);
|
||||
|
||||
const bool scanline_is_wider_than_1 = scanline_thickness > 1;
|
||||
const bool deinterlacing_mode_requires_boost = (
|
||||
enable_interlacing &&
|
||||
(scanline_deinterlacing_mode != 2) &&
|
||||
(scanline_deinterlacing_mode != 3)
|
||||
);
|
||||
|
||||
const float interlacing_brightness_factor = (1 + scanline_is_wider_than_1) * (1 + deinterlacing_mode_requires_boost);
|
||||
// const float raw_beam_strength = (1 - beam_dist_y) * (1 - interpolation_data.scanline_parity * enable_interlacing) * interlacing_brightness_factor * levels_autodim_temp;
|
||||
// const float raw_beam_strength = (1 - beam_dist_y);
|
||||
const float raw_beam_strength = saturate(-beam_dist_y * rcp(linear_beam_thickness) + 1);
|
||||
const float adj_beam_strength = raw_beam_strength * (1 - interpolation_data.scanline_parity * enable_interlacing) * interlacing_brightness_factor * levels_autodim_temp;
|
||||
|
||||
beam_strength = float4(color_corrected * adj_beam_strength, 0, 0, 1);
|
||||
}
|
||||
// Gaussian Shape
|
||||
// Beam will be a distorted Gaussian, dependent on color brightness and hyperparameters
|
||||
// Will only consider contribution from nearest scanline
|
||||
else if (beam_shape_mode == 2) {
|
||||
// Calculate {sigma, shape}_range outside of scanline_contrib so it's only
|
||||
// done once per pixel (not 6 times) with runtime params. Don't reuse the
|
||||
// vertex shader calculations, so static versions can be constant-folded.
|
||||
const float sigma_range = max(gaussian_beam_max_sigma, gaussian_beam_min_sigma) - gaussian_beam_min_sigma;
|
||||
const float shape_range = max(gaussian_beam_max_shape, gaussian_beam_min_shape) - gaussian_beam_min_shape;
|
||||
|
||||
const float beam_dist_factor = 1 + float(enable_interlacing);
|
||||
const float freq_adj = interpolation_data.triangle_wave_freq * rcp(beam_dist_factor);
|
||||
// The conditional 0.25*f offset ensures the interlaced scanlines align with the non-interlaced ones as in the other beam shapes
|
||||
const float frame_offset = enable_interlacing * (!interpolation_data.field_parity * 0.5 + 0.25) * rcp(freq_adj);
|
||||
const float beam_dist_y = triangle_wave((texcoord.y - frame_offset), freq_adj) * rcp(linear_beam_thickness);
|
||||
|
||||
const float interlacing_brightness_factor = 1 + float(
|
||||
!enable_interlacing &&
|
||||
(scanline_thickness > 1)
|
||||
) + float(
|
||||
enable_interlacing &&
|
||||
(scanline_deinterlacing_mode != 2) &&
|
||||
(scanline_deinterlacing_mode != 3)
|
||||
);
|
||||
const float raw_beam_strength = get_gaussian_beam_strength(
|
||||
beam_dist_y, color_corrected,
|
||||
sigma_range, shape_range
|
||||
) * interlacing_brightness_factor * levels_autodim_temp;
|
||||
|
||||
beam_strength = float4(raw_beam_strength, 0, 0, 1);
|
||||
}
|
||||
// Gaussian Shape
|
||||
// Beam will be a distorted Gaussian, dependent on color brightness and hyperparameters
|
||||
// Will consider contributions from current scanline and two neighboring in-field scanlines
|
||||
else {
|
||||
// Calculate {sigma, shape}_range outside of scanline_contrib so it's only
|
||||
// done once per pixel (not 6 times) with runtime params. Don't reuse the
|
||||
// vertex shader calculations, so static versions can be constant-folded.
|
||||
const float sigma_range = max(gaussian_beam_max_sigma, gaussian_beam_min_sigma) - gaussian_beam_min_sigma;
|
||||
const float shape_range = max(gaussian_beam_max_shape, gaussian_beam_min_shape) - gaussian_beam_min_shape;
|
||||
|
||||
const float beam_dist_factor = (1 + float(enable_interlacing));
|
||||
const float freq_adj = interpolation_data.triangle_wave_freq * rcp(beam_dist_factor);
|
||||
// The conditional 0.25*f offset ensures the interlaced scanlines align with the non-interlaced ones as in the other beam shapes
|
||||
const float frame_offset = enable_interlacing * (!interpolation_data.field_parity * 0.5 + 0.25) * rcp(freq_adj);
|
||||
const float curr_beam_dist_y = triangle_wave(texcoord.y - frame_offset, freq_adj) * rcp(linear_beam_thickness);
|
||||
const float upper_beam_dist_y = (sawtooth_incr_wave(texcoord.y - frame_offset, freq_adj)*2 + 1) * rcp(linear_beam_thickness);
|
||||
const float lower_beam_dist_y = 4 * rcp(linear_beam_thickness) - upper_beam_dist_y;
|
||||
|
||||
const float upper_beam_strength = get_gaussian_beam_strength(
|
||||
upper_beam_dist_y, color_corrected,
|
||||
sigma_range, shape_range
|
||||
);
|
||||
const float curr_beam_strength = get_gaussian_beam_strength(
|
||||
curr_beam_dist_y, color_corrected,
|
||||
sigma_range, shape_range
|
||||
);
|
||||
const float lower_beam_strength = get_gaussian_beam_strength(
|
||||
lower_beam_dist_y, color_corrected,
|
||||
sigma_range, shape_range
|
||||
);
|
||||
|
||||
const float interlacing_brightness_factor = 1 + float(
|
||||
!enable_interlacing &&
|
||||
(scanline_thickness > 1)
|
||||
) + float(
|
||||
enable_interlacing &&
|
||||
(scanline_deinterlacing_mode != 2) &&
|
||||
(scanline_deinterlacing_mode != 3)
|
||||
);
|
||||
const float3 raw_beam_strength = float3(curr_beam_strength, upper_beam_strength, lower_beam_strength) * interlacing_brightness_factor * levels_autodim_temp;
|
||||
|
||||
beam_strength = float4(raw_beam_strength, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void simulateEletronBeamsVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0,
|
||||
out float4 runtime_bin_shapes : TEXCOORD1
|
||||
) {
|
||||
#if ENABLE_PREBLUR
|
||||
PostProcessVS(id, position, texcoord);
|
||||
#else
|
||||
// texcoord.x = (id == 0 || id == 2) ? content_left : content_right;
|
||||
// texcoord.y = (id < 2) ? content_lower : content_upper;
|
||||
// position.x = (id == 0 || id == 2) ? -1 : 1;
|
||||
// position.y = (id < 2) ? -1 : 1;
|
||||
// position.zw = 1;
|
||||
contentCropVS(id, position, texcoord);
|
||||
#endif
|
||||
|
||||
bool screen_is_landscape = geom_rotation_mode == 0 || geom_rotation_mode == 2;
|
||||
|
||||
// Mode 0: size of pixel in [0, 1] = pixel_dims / viewport_size
|
||||
// Mode 1: size of pixel in [0, 1] = viewport_size / grid_dims
|
||||
// float2 runtime_pixel_size = (pixel_grid_mode == 0) ? pixel_size * rcp(content_size) : rcp(pixel_grid_resolution);
|
||||
float2 runtime_pixel_size = rcp(content_size);
|
||||
float2 runtime_scanline_shape = lerp(
|
||||
float2(scanline_thickness, 1),
|
||||
float2(1, scanline_thickness),
|
||||
screen_is_landscape
|
||||
) * rcp(content_size);
|
||||
|
||||
runtime_bin_shapes = float4(runtime_pixel_size, runtime_scanline_shape);
|
||||
}
|
||||
|
||||
void simulateEletronBeamsPS(
|
||||
in float4 position : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
in float4 runtime_bin_shapes : TEXCOORD1,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
bool screen_is_landscape = geom_rotation_mode == 0 || geom_rotation_mode == 2;
|
||||
float2 rotated_coord = lerp(texcoord.yx, texcoord, screen_is_landscape);
|
||||
float scale = lerp(CONTENT_WIDTH, CONTENT_HEIGHT, screen_is_landscape);
|
||||
|
||||
// InterpolationFieldData interpolation_data = precalc_interpolation_field_data(rotated_coord);
|
||||
|
||||
// // We have to subtract off the texcoord offset to make sure we're using domain [0, 1]
|
||||
// const float color_corrected = rotated_coord.x - 1.0 / scale;
|
||||
|
||||
|
||||
InterpolationFieldData interpolation_data = calc_interpolation_field_data(rotated_coord, scale);
|
||||
const float ypos = (rotated_coord.y * interpolation_data.triangle_wave_freq + interpolation_data.field_parity) * 0.5;
|
||||
|
||||
float2 texcoord_scanlined = round_coord(texcoord, 0, runtime_bin_shapes.zw);
|
||||
|
||||
// Sample from the neighboring scanline when in the wrong field
|
||||
[branch]
|
||||
if (interpolation_data.wrong_field && screen_is_landscape) {
|
||||
const float coord_moved_up = texcoord_scanlined.y <= texcoord.y;
|
||||
const float direction = lerp(-1, 1, coord_moved_up);
|
||||
texcoord_scanlined.y += direction * scanline_thickness * rcp(content_size.y);
|
||||
}
|
||||
else if (interpolation_data.wrong_field) {
|
||||
const float coord_moved_up = texcoord_scanlined.x <= texcoord.x;
|
||||
const float direction = lerp(-1, 1, coord_moved_up);
|
||||
texcoord_scanlined.x += direction * scanline_thickness * rcp(content_size.x);
|
||||
}
|
||||
|
||||
// Now we apply pixellation and cropping
|
||||
// float2 texcoord_pixellated = round_coord(
|
||||
// texcoord_scanlined,
|
||||
// pixel_grid_offset * rcp(content_size),
|
||||
// runtime_bin_shapes.xy
|
||||
// );
|
||||
float2 texcoord_pixellated = texcoord_scanlined;
|
||||
|
||||
const float2 texcoord_uncropped = texcoord_pixellated;
|
||||
#if ENABLE_PREBLUR
|
||||
// If the pre-blur pass ran, then it's already handled cropping.
|
||||
// const float2 texcoord_uncropped = texcoord_pixellated;
|
||||
#define source_sampler samplerPreblurHoriz
|
||||
#else
|
||||
// const float2 texcoord_uncropped = texcoord_pixellated * content_scale + content_offset;
|
||||
#define source_sampler ReShade::BackBuffer
|
||||
#endif
|
||||
|
||||
[branch]
|
||||
if (beam_shape_mode < 3) {
|
||||
const float4 scanline_color = tex2Dlod_linearize(
|
||||
source_sampler,
|
||||
texcoord_uncropped,
|
||||
get_input_gamma()
|
||||
);
|
||||
|
||||
const float beam_strength_r = tex2D_nograd(samplerBeamDist, float2(scanline_color.r, ypos)).x;
|
||||
const float beam_strength_g = tex2D_nograd(samplerBeamDist, float2(scanline_color.g, ypos)).x;
|
||||
const float beam_strength_b = tex2D_nograd(samplerBeamDist, float2(scanline_color.b, ypos)).x;
|
||||
const float4 beam_strength = float4(beam_strength_r, beam_strength_g, beam_strength_b, 1);
|
||||
|
||||
color = beam_strength;
|
||||
}
|
||||
else {
|
||||
const float2 offset = float2(0, scanline_thickness) * (1 + enable_interlacing) * rcp(content_size);
|
||||
|
||||
const float4 curr_scanline_color = tex2Dlod_linearize(
|
||||
source_sampler,
|
||||
texcoord_uncropped,
|
||||
get_input_gamma()
|
||||
);
|
||||
const float4 upper_scanline_color = tex2Dlod_linearize(
|
||||
source_sampler,
|
||||
texcoord_uncropped - offset,
|
||||
get_input_gamma()
|
||||
);
|
||||
const float4 lower_scanline_color = tex2Dlod_linearize(
|
||||
source_sampler,
|
||||
texcoord_uncropped + offset,
|
||||
get_input_gamma()
|
||||
);
|
||||
|
||||
const float curr_beam_strength_r = tex2D_nograd(samplerBeamDist, float2(curr_scanline_color.r, ypos)).x;
|
||||
const float curr_beam_strength_g = tex2D_nograd(samplerBeamDist, float2(curr_scanline_color.g, ypos)).x;
|
||||
const float curr_beam_strength_b = tex2D_nograd(samplerBeamDist, float2(curr_scanline_color.b, ypos)).x;
|
||||
|
||||
const float upper_beam_strength_r = tex2D_nograd(samplerBeamDist, float2(upper_scanline_color.r, ypos)).y;
|
||||
const float upper_beam_strength_g = tex2D_nograd(samplerBeamDist, float2(upper_scanline_color.g, ypos)).y;
|
||||
const float upper_beam_strength_b = tex2D_nograd(samplerBeamDist, float2(upper_scanline_color.b, ypos)).y;
|
||||
|
||||
const float lower_beam_strength_r = tex2D_nograd(samplerBeamDist, float2(lower_scanline_color.r, ypos)).z;
|
||||
const float lower_beam_strength_g = tex2D_nograd(samplerBeamDist, float2(lower_scanline_color.g, ypos)).z;
|
||||
const float lower_beam_strength_b = tex2D_nograd(samplerBeamDist, float2(lower_scanline_color.b, ypos)).z;
|
||||
|
||||
color = float4(
|
||||
curr_beam_strength_r + upper_beam_strength_r + lower_beam_strength_r,
|
||||
curr_beam_strength_g + upper_beam_strength_g + lower_beam_strength_g,
|
||||
curr_beam_strength_b + upper_beam_strength_b + lower_beam_strength_b,
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void beamConvergenceVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0,
|
||||
out float run_convergence : TEXCOORD1
|
||||
) {
|
||||
PostProcessVS(id, position, texcoord);
|
||||
const uint3 x_flag = convergence_offset_x != 0;
|
||||
const uint3 y_flag = convergence_offset_y != 0;
|
||||
run_convergence = dot(x_flag, 1) + dot(y_flag, 1);
|
||||
}
|
||||
|
||||
void beamConvergencePS(
|
||||
in float4 position : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
in float run_convergence : TEXCOORD1,
|
||||
|
||||
out float4 color : SV_TARGET
|
||||
) {
|
||||
// [branch]
|
||||
if (!run_convergence) {
|
||||
color = tex2D(samplerElectronBeams, texcoord - float2(0, scanline_offset * rcp(content_size.y)));
|
||||
}
|
||||
else {
|
||||
const float3 offset_sample = sample_rgb_scanline(
|
||||
samplerElectronBeams, texcoord - float2(0, scanline_offset * rcp(content_size.y)),
|
||||
TEX_ELECTRONBEAMS_SIZE, rcp(TEX_ELECTRONBEAMS_SIZE)
|
||||
);
|
||||
|
||||
color = float4(offset_sample, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _ELECTRON_BEAMS_H
|
||||
@@ -0,0 +1,220 @@
|
||||
#ifndef _GEOMETRY_AA_LAST_PASS_H
|
||||
#define _GEOMETRY_AA_LAST_PASS_H
|
||||
|
||||
///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
|
||||
|
||||
// crt-royale: A full-featured CRT shader, with cheese.
|
||||
// Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
|
||||
//
|
||||
// crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade.
|
||||
// Copyright (C) 2020 Alex Gunter <akg7634@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or 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 "../lib/user-settings.fxh"
|
||||
#include "../lib/derived-settings-and-constants.fxh"
|
||||
#include "../lib/bind-shader-params.fxh"
|
||||
#include "../lib/gamma-management.fxh"
|
||||
#include "../lib/tex2Dantialias.fxh"
|
||||
#include "../lib/geometry-functions.fxh"
|
||||
|
||||
// Disabled in the ReShade port because I don't know a good way to make these
|
||||
// static AND global AND defined with sin(), cos(), or pow().
|
||||
|
||||
// #if !_RUNTIME_GEOMETRY_TILT
|
||||
// // Create a local-to-global rotation matrix for the CRT's coordinate frame
|
||||
// // and its global-to-local inverse. See the vertex shader for details.
|
||||
// // It's faster to compute these statically if possible.
|
||||
// static const float2 sin_tilt = sin(geom_tilt_angle_static);
|
||||
// static const float2 cos_tilt = cos(geom_tilt_angle_static);
|
||||
// static const float3x3 geom_local_to_global_static = float3x3(
|
||||
// cos_tilt.x, sin_tilt.y*sin_tilt.x, cos_tilt.y*sin_tilt.x,
|
||||
// 0.0, cos_tilt.y, -sin_tilt.y,
|
||||
// -sin_tilt.x, sin_tilt.y*cos_tilt.x, cos_tilt.y*cos_tilt.x);
|
||||
// static const float3x3 geom_global_to_local_static = float3x3(
|
||||
// cos_tilt.x, 0.0, -sin_tilt.x,
|
||||
// sin_tilt.y*sin_tilt.x, cos_tilt.y, sin_tilt.y*cos_tilt.x,
|
||||
// cos_tilt.y*sin_tilt.x, -sin_tilt.y, cos_tilt.y*cos_tilt.x);
|
||||
// #endif
|
||||
|
||||
float2x2 mul_scale(float2 scale, float2x2 mtrx)
|
||||
{
|
||||
float4 temp_matrix = float4(mtrx[0][0], mtrx[0][1], mtrx[1][0], mtrx[1][1]) * scale.xxyy;
|
||||
return float2x2(temp_matrix.x, temp_matrix.y, temp_matrix.z, temp_matrix.w);
|
||||
}
|
||||
|
||||
|
||||
void geometryVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0,
|
||||
out float2 output_size_inv : TEXCOORD1,
|
||||
out float4 geom_aspect_and_overscan : TEXCOORD2,
|
||||
out float3 eye_pos_local : TEXCOORD3,
|
||||
out float3 global_to_local_row0 : TEXCOORD4,
|
||||
out float3 global_to_local_row1 : TEXCOORD5,
|
||||
out float3 global_to_local_row2 : TEXCOORD6
|
||||
) {
|
||||
PostProcessVS(id, position, texcoord);
|
||||
|
||||
output_size_inv = 1.0 / content_size;
|
||||
|
||||
// Get aspect/overscan vectors from scalar parameters (likely uniforms):
|
||||
const float viewport_aspect_ratio = output_size_inv.y / output_size_inv.x;
|
||||
const float2 geom_aspect = get_aspect_vector(viewport_aspect_ratio);
|
||||
const float2 geom_overscan = get_geom_overscan_vector();
|
||||
geom_aspect_and_overscan = float4(geom_aspect, geom_overscan);
|
||||
|
||||
#if _RUNTIME_GEOMETRY_TILT
|
||||
// Create a local-to-global rotation matrix for the CRT's coordinate
|
||||
// frame and its global-to-local inverse. Rotate around the x axis
|
||||
// first (pitch) and then the y axis (yaw) with yucky Euler angles.
|
||||
// Positive angles go clockwise around the right-vec and up-vec.
|
||||
// Runtime shader parameters prevent us from computing these globally,
|
||||
// but we can still combine the pitch/yaw matrices by hand to cut a
|
||||
// few instructions. Note that cg matrices fill row1 first, then row2,
|
||||
// etc. (row-major order).
|
||||
const float2 geom_tilt_angle = get_geom_tilt_angle_vector();
|
||||
const float2 sin_tilt = sin(geom_tilt_angle);
|
||||
const float2 cos_tilt = cos(geom_tilt_angle);
|
||||
// Conceptual breakdown:
|
||||
static const float3x3 rot_x_matrix = float3x3(
|
||||
1.0, 0.0, 0.0,
|
||||
0.0, cos_tilt.y, -sin_tilt.y,
|
||||
0.0, sin_tilt.y, cos_tilt.y);
|
||||
static const float3x3 rot_y_matrix = float3x3(
|
||||
cos_tilt.x, 0.0, sin_tilt.x,
|
||||
0.0, 1.0, 0.0,
|
||||
-sin_tilt.x, 0.0, cos_tilt.x);
|
||||
static const float3x3 local_to_global =
|
||||
mul(rot_y_matrix, rot_x_matrix);
|
||||
/* static const float3x3 global_to_local =
|
||||
transpose(local_to_global);
|
||||
const float3x3 local_to_global = float3x3(
|
||||
cos_tilt.x, sin_tilt.y*sin_tilt.x, cos_tilt.y*sin_tilt.x,
|
||||
0.0, cos_tilt.y, sin_tilt.y,
|
||||
sin_tilt.x, sin_tilt.y*cos_tilt.x, cos_tilt.y*cos_tilt.x);
|
||||
*/ // This is a pure rotation, so transpose = inverse:
|
||||
const float3x3 global_to_local = transpose(local_to_global);
|
||||
// Decompose the matrix into 3 float3's for output:
|
||||
global_to_local_row0 = float3(global_to_local[0][0], global_to_local[0][1], global_to_local[0][2]);//._m00_m01_m02);
|
||||
global_to_local_row1 = float3(global_to_local[1][0], global_to_local[1][1], global_to_local[1][2]);//._m10_m11_m12);
|
||||
global_to_local_row2 = float3(global_to_local[2][0], global_to_local[2][1], global_to_local[2][2]);//._m20_m21_m22);
|
||||
#else
|
||||
static const float3x3 global_to_local = geom_global_to_local_static;
|
||||
static const float3x3 local_to_global = geom_local_to_global_static;
|
||||
#endif
|
||||
|
||||
// Get an optimal eye position based on geom_view_dist, viewport_aspect,
|
||||
// and CRT radius/rotation:
|
||||
#if _RUNTIME_GEOMETRY_MODE
|
||||
const float geom_mode = geom_mode_runtime;
|
||||
#else
|
||||
static const float geom_mode = geom_mode_static;
|
||||
#endif
|
||||
const float3 eye_pos_global = get_ideal_global_eye_pos(local_to_global, geom_aspect, geom_mode);
|
||||
eye_pos_local = mul(global_to_local, eye_pos_global);
|
||||
}
|
||||
|
||||
void geometryPS(
|
||||
in float4 position : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
in float2 output_size_inv : TEXCOORD1,
|
||||
in float4 geom_aspect_and_overscan : TEXCOORD2,
|
||||
in float3 eye_pos_local : TEXCOORD3,
|
||||
in float3 global_to_local_row0 : TEXCOORD4,
|
||||
in float3 global_to_local_row1 : TEXCOORD5,
|
||||
in float3 global_to_local_row2 : TEXCOORD6,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
// Localize some parameters:
|
||||
const float2 geom_aspect = geom_aspect_and_overscan.xy;
|
||||
const float2 geom_overscan = geom_aspect_and_overscan.zw;
|
||||
#if _RUNTIME_GEOMETRY_TILT
|
||||
const float3x3 global_to_local = float3x3(global_to_local_row0,
|
||||
global_to_local_row1, global_to_local_row2);
|
||||
#else
|
||||
static const float3x3 global_to_local = geom_global_to_local_static;
|
||||
#endif
|
||||
#if _RUNTIME_GEOMETRY_MODE
|
||||
const float geom_mode = geom_mode_runtime;
|
||||
#else
|
||||
static const float geom_mode = geom_mode_static;
|
||||
#endif
|
||||
|
||||
// Get flat and curved texture coords for the current fragment point sample
|
||||
// and a pixel_to_tangent_video_uv matrix for transforming pixel offsets:
|
||||
// video_uv = relative position in video frame, mapped to [0.0, 1.0] range
|
||||
// tex_uv = relative position in padded texture, mapped to [0.0, 1.0] range
|
||||
const float2 flat_video_uv = texcoord;
|
||||
float2x2 pixel_to_video_uv;
|
||||
float2 video_uv_no_geom_overscan;
|
||||
if(geom_mode > 0.5)
|
||||
{
|
||||
video_uv_no_geom_overscan =
|
||||
get_curved_video_uv_coords_and_tangent_matrix(flat_video_uv,
|
||||
eye_pos_local, output_size_inv, geom_aspect,
|
||||
geom_mode, global_to_local, pixel_to_video_uv);
|
||||
}
|
||||
else
|
||||
{
|
||||
video_uv_no_geom_overscan = flat_video_uv;
|
||||
pixel_to_video_uv = float2x2(
|
||||
output_size_inv.x, 0.0, 0.0, output_size_inv.y);
|
||||
}
|
||||
// Correct for overscan here (not in curvature code):
|
||||
const float2 video_uv =
|
||||
(video_uv_no_geom_overscan - float2(0.5, 0.5))/geom_overscan + float2(0.5, 0.5);
|
||||
const float2 tex_uv = video_uv;
|
||||
|
||||
// Get a matrix transforming pixel vectors to tex_uv vectors:
|
||||
const float2x2 pixel_to_tex_uv =
|
||||
mul_scale(1.0 / geom_overscan, pixel_to_video_uv);
|
||||
|
||||
// Sample! Skip antialiasing if antialias_level < 0.5 or both of these hold:
|
||||
// 1.) Geometry/curvature isn't used
|
||||
// 2.) Overscan == float2(1.0, 1.0)
|
||||
// Skipping AA is sharper, but it's only faster with dynamic branches.
|
||||
const float2 abs_aa_r_offset = abs(get_aa_subpixel_r_offset());
|
||||
// this next check seems to always return true, even when it shouldn't so disabling it for now
|
||||
const bool need_subpixel_aa = false;//abs_aa_r_offset.x + abs_aa_r_offset.y > 0.0;
|
||||
float3 raw_color;
|
||||
|
||||
if(antialias_level > 0.5 && (geom_mode > 0.5 || any(bool2((geom_overscan.x != 1.0), (geom_overscan.y != 1.0)))))
|
||||
{
|
||||
// Sample the input with antialiasing (due to sharp phosphors, etc.):
|
||||
raw_color = tex2Daa(samplerBloomHorizontal, tex_uv, pixel_to_tex_uv, float(frame_count), get_intermediate_gamma());
|
||||
}
|
||||
else if(antialias_level > 0.5 && need_subpixel_aa)
|
||||
{
|
||||
// Sample at each subpixel location:
|
||||
raw_color = tex2Daa_subpixel_weights_only(
|
||||
samplerBloomHorizontal, tex_uv, pixel_to_tex_uv, get_intermediate_gamma());
|
||||
}
|
||||
else
|
||||
{
|
||||
raw_color = tex2D_linearize(samplerBloomHorizontal, tex_uv, get_intermediate_gamma()).rgb;
|
||||
}
|
||||
|
||||
// Dim borders and output the final result:
|
||||
const float border_dim_factor = get_border_dim_factor(video_uv, geom_aspect);
|
||||
const float3 final_color = raw_color * border_dim_factor;
|
||||
|
||||
color = encode_output(float4(final_color, 1.0), get_output_gamma());
|
||||
}
|
||||
|
||||
#endif // _GEOMETRY_AA_LAST_PASS_H
|
||||
@@ -0,0 +1,74 @@
|
||||
#ifndef _INPUT_BLURRING_H
|
||||
#define _INPUT_BLURRING_H
|
||||
|
||||
///////////////////////////////// MIT LICENSE ////////////////////////////////
|
||||
|
||||
// Copyright (C) 2022 Alex Gunter
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
// Theoretically this could go in blurring.fxh
|
||||
// But that file has a bunch of GPL stuff in it.
|
||||
// Keeping it separate makes it easier to communicate that this portion is
|
||||
// available under the MIT license.
|
||||
|
||||
#include "../lib/downsampling-functions.fxh"
|
||||
|
||||
#include "content-box.fxh"
|
||||
#include "shared-objects.fxh"
|
||||
|
||||
|
||||
void preblurVertPS(
|
||||
in const float4 pos : SV_Position,
|
||||
in const float2 texcoord : TEXCOORD0,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
const float2 texcoord_uncropped = texcoord;
|
||||
|
||||
const float2 max_delta_uv = float2(0.0, rcp(content_size.y)) * preblur_effect_radius;
|
||||
const float2 delta_uv = max_delta_uv * rcp(max(preblur_sampling_radius.y, 1));
|
||||
|
||||
color = float4(opaque_linear_downsample(
|
||||
ReShade::BackBuffer,
|
||||
texcoord_uncropped,
|
||||
preblur_sampling_radius.y,
|
||||
delta_uv
|
||||
), 1);
|
||||
}
|
||||
|
||||
void preblurHorizPS(
|
||||
in const float4 pos : SV_Position,
|
||||
in const float2 texcoord : TEXCOORD0,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
const float2 max_delta_uv = float2(rcp(content_size.x), 0.0) * preblur_effect_radius;
|
||||
const float2 delta_uv = max_delta_uv * rcp(max(preblur_sampling_radius.x, 1));
|
||||
|
||||
color = float4(opaque_linear_downsample(
|
||||
samplerPreblurVert,
|
||||
texcoord,
|
||||
preblur_sampling_radius.x,
|
||||
delta_uv
|
||||
), 1);
|
||||
}
|
||||
|
||||
#endif // _INPUT_BLURRING_H
|
||||
@@ -0,0 +1,211 @@
|
||||
#ifndef _PHOSPHOR_MASK_H
|
||||
#define _PHOSPHOR_MASK_H
|
||||
|
||||
///////////////////////////////// MIT LICENSE ////////////////////////////////
|
||||
|
||||
// Copyright (C) 2022 Alex Gunter
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
#include "../lib/bind-shader-params.fxh"
|
||||
#include "../lib/phosphor-mask-calculations.fxh"
|
||||
|
||||
#include "shared-objects.fxh"
|
||||
|
||||
|
||||
// Split into 64 segments that overlap a little bit
|
||||
static const float num_segments = 64;
|
||||
static const float segment_offset = 0.015625; // 1/64
|
||||
static const float segment_width = 0.0234375; // 1/128
|
||||
|
||||
void generatePhosphorMaskVS(
|
||||
in uint id : SV_VertexID,
|
||||
|
||||
out float4 position : SV_Position,
|
||||
out float2 texcoord : TEXCOORD0,
|
||||
out float2 viewport_frequency_factor: TEXCOORD1,
|
||||
out float2 mask_pq_x : TEXCOORD2,
|
||||
out float2 mask_pq_y : TEXCOORD3
|
||||
) {
|
||||
const float screen_segment_idx = frame_count % num_segments;
|
||||
const float left_coord = lerp(segment_offset * screen_segment_idx, 0, overlay_active > 0);
|
||||
const float right_coord = lerp(left_coord + segment_width, 1, overlay_active > 0);
|
||||
const float pos_center = 2 * (left_coord + 0.5 * segment_width - 0.5);
|
||||
const float pos_left = lerp(pos_center - segment_width, -1, overlay_active > 0);
|
||||
const float pos_right = lerp(pos_center + segment_width, 1, overlay_active > 0);
|
||||
|
||||
#if _DX9_ACTIVE
|
||||
texcoord.x = (id == 1 || id == 3) ? right_coord : left_coord;
|
||||
texcoord.y = (id > 1) ? 1 : 0;
|
||||
|
||||
position.x = (id == 1 || id == 3) ? pos_right : pos_left;
|
||||
position.y = (id > 1) ? -1 : 1;
|
||||
position.zw = 1;
|
||||
#else
|
||||
texcoord.x = (id & 1) ? right_coord : left_coord;
|
||||
texcoord.y = (id & 2) ? 1 : 0;
|
||||
|
||||
position.x = (id & 1) ? pos_right : pos_left;
|
||||
position.y = (id & 2) ? -1 : 1;
|
||||
position.zw = 1;
|
||||
#endif
|
||||
|
||||
viewport_frequency_factor = calc_phosphor_viewport_frequency_factor();
|
||||
|
||||
// We don't alter these based on screen rotation because they're independent of screen dimensions.
|
||||
float edge_norm_tx;
|
||||
float edge_norm_ty;
|
||||
[flatten]
|
||||
switch (mask_type) {
|
||||
case 0:
|
||||
edge_norm_tx = grille_edge_norm_t;
|
||||
break;
|
||||
case 1:
|
||||
edge_norm_tx = slot_edge_norm_tx;
|
||||
edge_norm_ty = slot_edge_norm_ty;
|
||||
break;
|
||||
case 2:
|
||||
edge_norm_tx = shadow_edge_norm_tx;
|
||||
edge_norm_ty = shadow_edge_norm_ty;
|
||||
break;
|
||||
case 3:
|
||||
edge_norm_tx = smallgrille_edge_norm_t;
|
||||
break;
|
||||
case 4:
|
||||
edge_norm_tx = smallslot_edge_norm_tx;
|
||||
edge_norm_ty = smallslot_edge_norm_ty;
|
||||
break;
|
||||
default:
|
||||
edge_norm_tx = smallshadow_edge_norm_tx;
|
||||
edge_norm_ty = smallshadow_edge_norm_ty;
|
||||
break;
|
||||
}
|
||||
|
||||
const float2 thickness_scaled = linearize_phosphor_thickness_param(phosphor_thickness);
|
||||
const float mask_p_x = exp(-calculate_phosphor_p_value(edge_norm_tx, thickness_scaled.x, phosphor_sharpness.x));
|
||||
const float mask_p_y = exp(-calculate_phosphor_p_value(edge_norm_ty, thickness_scaled.y, phosphor_sharpness.y));
|
||||
mask_pq_x = float2(mask_p_x, phosphor_sharpness.x);
|
||||
mask_pq_y = float2(mask_p_y, phosphor_sharpness.y);
|
||||
}
|
||||
|
||||
void generatePhosphorMaskPS(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
in float2 viewport_frequency_factor: TEXCOORD1,
|
||||
in float2 mask_pq_x : TEXCOORD2,
|
||||
in float2 mask_pq_y : TEXCOORD3,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
[branch]
|
||||
if (geom_rotation_mode == 1 || geom_rotation_mode == 3) {
|
||||
texcoord = texcoord.yx;
|
||||
viewport_frequency_factor = viewport_frequency_factor.yx;
|
||||
}
|
||||
|
||||
float3 phosphor_color;
|
||||
[branch]
|
||||
if (mask_type == 0) {
|
||||
phosphor_color = get_phosphor_intensity_grille(
|
||||
texcoord,
|
||||
viewport_frequency_factor,
|
||||
mask_pq_x
|
||||
);
|
||||
}
|
||||
else if (mask_type == 1) {
|
||||
phosphor_color = get_phosphor_intensity_slot(
|
||||
texcoord,
|
||||
viewport_frequency_factor,
|
||||
mask_pq_x,
|
||||
mask_pq_y
|
||||
);
|
||||
}
|
||||
else if (mask_type == 2) {
|
||||
phosphor_color = get_phosphor_intensity_shadow(
|
||||
texcoord,
|
||||
viewport_frequency_factor,
|
||||
float2(mask_pq_x.y, mask_pq_y.y)
|
||||
);
|
||||
}
|
||||
else if (mask_type == 3) {
|
||||
phosphor_color = get_phosphor_intensity_grille_small(
|
||||
texcoord,
|
||||
viewport_frequency_factor,
|
||||
mask_pq_x
|
||||
);
|
||||
}
|
||||
else if (mask_type == 4) {
|
||||
phosphor_color = get_phosphor_intensity_slot_small(
|
||||
texcoord,
|
||||
viewport_frequency_factor,
|
||||
mask_pq_x,
|
||||
mask_pq_y
|
||||
);
|
||||
}
|
||||
else {
|
||||
phosphor_color = get_phosphor_intensity_shadow_small(
|
||||
texcoord,
|
||||
viewport_frequency_factor,
|
||||
mask_pq_x,
|
||||
mask_pq_y
|
||||
);
|
||||
}
|
||||
|
||||
color = float4(phosphor_color, 1.0);
|
||||
}
|
||||
|
||||
|
||||
void applyComputedPhosphorMaskPS(
|
||||
in float4 pos : SV_Position,
|
||||
in float2 texcoord : TEXCOORD0,
|
||||
|
||||
out float4 color : SV_Target
|
||||
) {
|
||||
bool use_deinterlacing_tex = enable_interlacing && (
|
||||
scanline_deinterlacing_mode == 2 || scanline_deinterlacing_mode == 3
|
||||
);
|
||||
|
||||
float3 scanline_color_dim;
|
||||
[branch]
|
||||
if (use_deinterlacing_tex) scanline_color_dim = tex2D(samplerDeinterlace, texcoord).rgb;
|
||||
else scanline_color_dim = tex2D(samplerBeamConvergence, texcoord).rgb;
|
||||
|
||||
const float3 phosphor_color = tex2D(samplerPhosphorMask, texcoord).rgb;
|
||||
|
||||
// Sample the halation texture (auto-dim to match the scanlines), and
|
||||
// account for both horizontal and vertical convergence offsets, given
|
||||
// in units of texels horizontally and same-field scanlines vertically:
|
||||
const float3 halation_color = tex2D_linearize(samplerBlurHorizontal, texcoord, get_intermediate_gamma()).rgb;
|
||||
|
||||
// Apply halation: Halation models electrons flying around under the glass
|
||||
// and hitting the wrong phosphors (of any color). It desaturates, so
|
||||
// average the halation electrons to a scalar. Reduce the local scanline
|
||||
// intensity accordingly to conserve energy.
|
||||
const float halation_intensity_dim_scalar = dot(halation_color, float3(1, 1, 1)) / 3.0;
|
||||
const float3 halation_intensity_dim = halation_intensity_dim_scalar;
|
||||
const float3 electron_intensity_dim = lerp(scanline_color_dim, halation_intensity_dim, halation_weight);
|
||||
|
||||
// Apply the phosphor mask:
|
||||
const float3 phosphor_emission_dim = electron_intensity_dim * phosphor_color;
|
||||
|
||||
color = float4(phosphor_emission_dim, 1.0);
|
||||
}
|
||||
|
||||
#endif // _PHOSPHOR_MASK_H
|
||||
@@ -0,0 +1,370 @@
|
||||
#ifndef _SHARED_OBJECTS_H
|
||||
#define _SHARED_OBJECTS_H
|
||||
|
||||
///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
|
||||
|
||||
// crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade.
|
||||
// Copyright (C) 2020 Alex Gunter <akg7634@gmail.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 2 of the License, or 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 "../lib/helper-functions-and-macros.fxh"
|
||||
#include "../lib/derived-settings-and-constants.fxh"
|
||||
#include "../lib/bind-shader-params.fxh"
|
||||
|
||||
|
||||
// Yes, the WIDTH/HEIGHT/SIZE defines are kinda weird.
|
||||
// Yes, we have to have them or something similar. This is for D3D11 which
|
||||
// returns (0, 0) when you call tex2Dsize() on the pass's render target.
|
||||
|
||||
|
||||
// Pass 0 Buffer (cropPass)
|
||||
// Cannot be conditioned on __RENDERER__ b/c there are no
|
||||
// available buffers of the same size
|
||||
// Last usage is in interlacingPass
|
||||
// electronBeamPass -> beamConvergencePass
|
||||
// deinterlacePass -> phosphorMaskPass
|
||||
// brightpassPass -> bloomHorizontalPass
|
||||
// #define TEX_CROP_WIDTH content_size.x
|
||||
// #define TEX_CROP_HEIGHT content_size.y
|
||||
// #define TEX_CROP_SIZE int2(TEX_CROP_WIDTH, TEX_CROP_HEIGHT)
|
||||
// texture2D texCrop {
|
||||
// Width = TEX_CROP_WIDTH;
|
||||
// Height = TEX_CROP_HEIGHT;
|
||||
|
||||
// Format = RGBA16;
|
||||
// };
|
||||
// sampler2D samplerCrop { Texture = texCrop; };
|
||||
|
||||
|
||||
// Pass 1 Buffer (interlacingPass)
|
||||
// Cannot be conditioned on __RENDERER__ b/c there are no
|
||||
// available buffers of the same size
|
||||
// Last usage is in electronBeamPass
|
||||
// beamConvergencPass -> freezeFramePass
|
||||
// phosphorMaskPass -> bloomHorizontalPass
|
||||
// #define TEX_INTERLACED_WIDTH content_size.x
|
||||
// #define TEX_INTERLACED_HEIGHT content_size.y
|
||||
// #define TEX_INTERLACED_SIZE int2(TEX_INTERLACED_WIDTH, TEX_INTERLACED_HEIGHT)
|
||||
// texture2D texInterlaced {
|
||||
// Width = TEX_INTERLACED_WIDTH;
|
||||
// Height = TEX_INTERLACED_HEIGHT;
|
||||
|
||||
// Format = RGBA16;
|
||||
// };
|
||||
// sampler2D samplerInterlaced { Texture = texInterlaced; };
|
||||
|
||||
// Pass 2 Buffer (electronBeamPass)
|
||||
// Last usage is in beamConvergencePass
|
||||
|
||||
|
||||
#define TEX_PREBLUR_VERT_WIDTH content_size.x
|
||||
#define TEX_PREBLUR_VERT_HEIGHT content_size.y
|
||||
static const uint2 TEX_PREBLUR_SIZE = uint2(TEX_PREBLUR_VERT_WIDTH, TEX_PREBLUR_VERT_HEIGHT);
|
||||
texture2D texPreblurVert < pooled = true; > {
|
||||
Width = TEX_PREBLUR_VERT_WIDTH;
|
||||
Height = TEX_PREBLUR_VERT_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerPreblurVert { Texture = texPreblurVert; };
|
||||
|
||||
#define TEX_PREBLUR_HORIZ_WIDTH content_size.x
|
||||
#define TEX_PREBLUR_HORIZ_HEIGHT content_size.y
|
||||
static const uint2 TEX_PREBLUR_SIZE = uint2(TEX_PREBLUR_HORIZ_WIDTH, TEX_PREBLUR_HORIZ_HEIGHT);
|
||||
texture2D texPreblurHoriz < pooled = true; > {
|
||||
Width = TEX_PREBLUR_HORIZ_WIDTH;
|
||||
Height = TEX_PREBLUR_HORIZ_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerPreblurHoriz { Texture = texPreblurHoriz; };
|
||||
|
||||
|
||||
#define TEX_BEAMDIST_WIDTH num_beamdist_color_samples
|
||||
#define TEX_BEAMDIST_HEIGHT num_beamdist_dist_samples
|
||||
#define TEX_BEAMDIST_SIZE int2(TEX_BEAMDIST_WIDTH, TEX_BEAMDIST_HEIGHT)
|
||||
texture2D texBeamDist < pooled = false; > {
|
||||
Width = TEX_BEAMDIST_WIDTH;
|
||||
Height = TEX_BEAMDIST_HEIGHT;
|
||||
|
||||
|
||||
Format = RGB10A2;
|
||||
};
|
||||
sampler2D samplerBeamDist {
|
||||
Texture = texBeamDist;
|
||||
AddressV = WRAP;
|
||||
};
|
||||
|
||||
|
||||
// Pass 2 Buffer (electronBeamPass)
|
||||
// Last usage is in beamConvergencePass
|
||||
#define TEX_ELECTRONBEAMS_WIDTH content_size.x
|
||||
#define TEX_ELECTRONBEAMS_HEIGHT content_size.y
|
||||
#define TEX_ELECTRONBEAMS_SIZE int2(TEX_ELECTRONBEAMS_WIDTH, TEX_ELECTRONBEAMS_HEIGHT)
|
||||
texture2D texElectronBeams < pooled = true; > {
|
||||
Width = TEX_ELECTRONBEAMS_WIDTH;
|
||||
Height = TEX_ELECTRONBEAMS_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerElectronBeams {
|
||||
Texture = texElectronBeams;
|
||||
|
||||
AddressU = BORDER;
|
||||
AddressV = BORDER;
|
||||
};
|
||||
// #define texElectronBeams texCrop
|
||||
// #define samplerElectronBeams samplerCrop
|
||||
|
||||
|
||||
// Pass 3 Buffer (beamConvergencPass)
|
||||
// Last usage is freezeFramePass
|
||||
#define TEX_BEAMCONVERGENCE_WIDTH content_size.x
|
||||
#define TEX_BEAMCONVERGENCE_HEIGHT content_size.y
|
||||
#define TEX_BEAMCONVERGENCE_SIZE int2(TEX_BEAMCONVERGENCE_WIDTH, TEX_BEAMCONVERGENCE_HEIGHT)
|
||||
texture2D texBeamConvergence < pooled = true; > {
|
||||
Width = TEX_BEAMCONVERGENCE_WIDTH;
|
||||
Height = TEX_BEAMCONVERGENCE_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerBeamConvergence { Texture = texBeamConvergence; };
|
||||
// #define texBeamConvergence texInterlaced
|
||||
// #define samplerBeamConvergence samplerInterlaced
|
||||
|
||||
|
||||
/*
|
||||
// Pass 4 Buffer (bloomApproxPass)
|
||||
// Cannot be conditioned on __RENDERER__ b/c there are no
|
||||
// available buffers of the same size
|
||||
// Last usage is in brightpassPass
|
||||
#define TEX_BLOOMAPPROX_WIDTH 320
|
||||
#define TEX_BLOOMAPPROX_HEIGHT 240
|
||||
#define TEX_BLOOMAPPROX_SIZE int2(TEX_BLOOMAPPROX_WIDTH, TEX_BLOOMAPPROX_HEIGHT)
|
||||
texture2D texBloomApprox {
|
||||
Width = TEX_BLOOMAPPROX_WIDTH;
|
||||
Height = TEX_BLOOMAPPROX_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerBloomApprox { Texture = texBloomApprox; };
|
||||
*/
|
||||
|
||||
// Pass 4a Buffer (bloomApproxVerticalPass)
|
||||
// Cannot be conditioned on __RENDERER__ b/c there are no
|
||||
// available buffers of the same size
|
||||
// Last usage is in brightpassPass
|
||||
#define TEX_BLOOMAPPROXVERT_WIDTH content_size.x
|
||||
// #define TEX_BLOOMAPPROXVERT_HEIGHT 240
|
||||
#define TEX_BLOOMAPPROXVERT_HEIGHT int(content_size.y / bloomapprox_downsizing_factor)
|
||||
#define TEX_BLOOMAPPROXVERT_SIZE int2(TEX_BLOOMAPPROXVERT_WIDTH, TEX_BLOOMAPPROXVERT_HEIGHT)
|
||||
texture2D texBloomApproxVert < pooled = true; > {
|
||||
Width = TEX_BLOOMAPPROXVERT_WIDTH;
|
||||
Height = TEX_BLOOMAPPROXVERT_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerBloomApproxVert { Texture = texBloomApproxVert; };
|
||||
|
||||
// Pass 4b Buffer (bloomApproxHorizontalPass)
|
||||
// Cannot be conditioned on __RENDERER__ b/c there are no
|
||||
// available buffers of the same size
|
||||
// Last usage is in brightpassPass
|
||||
// #define TEX_BLOOMAPPROXHORIZ_WIDTH 320
|
||||
// #define TEX_BLOOMAPPROXHORIZ_HEIGHT 240
|
||||
#define TEX_BLOOMAPPROXHORIZ_WIDTH int(content_size.x / bloomapprox_downsizing_factor)
|
||||
#define TEX_BLOOMAPPROXHORIZ_HEIGHT TEX_BLOOMAPPROXVERT_HEIGHT
|
||||
#define TEX_BLOOMAPPROXHORIZ_SIZE int2(TEX_BLOOMAPPROXHORIZ_WIDTH, TEX_BLOOMAPPROXHORIZ_HEIGHT)
|
||||
texture2D texBloomApproxHoriz < pooled = true; > {
|
||||
Width = TEX_BLOOMAPPROXHORIZ_WIDTH;
|
||||
Height = TEX_BLOOMAPPROXHORIZ_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerBloomApproxHoriz { Texture = texBloomApproxHoriz; };
|
||||
|
||||
// Pass 5 Buffer (blurVerticalPass)
|
||||
// Cannot be conditioned on __RENDERER__ b/c there are no
|
||||
// available buffers of the same size
|
||||
// Last usage is blurHorizontalPass
|
||||
#define TEX_BLURVERTICAL_WIDTH TEX_BLOOMAPPROXHORIZ_WIDTH
|
||||
#define TEX_BLURVERTICAL_HEIGHT TEX_BLOOMAPPROXHORIZ_HEIGHT
|
||||
#define TEX_BLURVERTICAL_SIZE int2(TEX_BLURVERTICAL_WIDTH, TEX_BLURVERTICAL_HEIGHT)
|
||||
texture2D texBlurVertical < pooled = true; > {
|
||||
Width = TEX_BLURVERTICAL_WIDTH;
|
||||
Height = TEX_BLURVERTICAL_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerBlurVertical { Texture = texBlurVertical; };
|
||||
|
||||
|
||||
// Pass 6 Buffer (blurHorizontalPass)
|
||||
// Cannot be conditioned on __RENDERER__ b/c there are no
|
||||
// available buffers of the same size
|
||||
// Last usage is bloomHorizontalPass
|
||||
#define TEX_BLURHORIZONTAL_WIDTH TEX_BLOOMAPPROXHORIZ_WIDTH
|
||||
#define TEX_BLURHORIZONTAL_HEIGHT TEX_BLOOMAPPROXHORIZ_HEIGHT
|
||||
#define TEX_BLURHORIZONTAL_SIZE int2(TEX_BLURHORIZONTAL_WIDTH, TEX_BLURHORIZONTAL_HEIGHT)
|
||||
texture2D texBlurHorizontal < pooled = true; > {
|
||||
Width = TEX_BLURHORIZONTAL_WIDTH;
|
||||
Height = TEX_BLURHORIZONTAL_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerBlurHorizontal { Texture = texBlurHorizontal; };
|
||||
|
||||
|
||||
// Pass 7 (deinterlacePass)
|
||||
// Last usage is phosphorMaskPass
|
||||
#define TEX_DEINTERLACE_WIDTH content_size.x
|
||||
#define TEX_DEINTERLACE_HEIGHT content_size.y
|
||||
#define TEX_DEINTERLACE_SIZE int2(TEX_DEINTERLACE_WIDTH, TEX_DEINTERLACE_HEIGHT)
|
||||
#if _DX9_ACTIVE == 0
|
||||
texture2D texDeinterlace < pooled = true; > {
|
||||
Width = TEX_DEINTERLACE_WIDTH;
|
||||
Height = TEX_DEINTERLACE_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerDeinterlace { Texture = texDeinterlace; };
|
||||
#else
|
||||
#define texDeinterlace texElectronBeams
|
||||
#define samplerDeinterlace samplerElectronBeams
|
||||
#endif
|
||||
|
||||
// Pass 8 (freezeFramePass)
|
||||
// Do not condition this on __RENDERER__. It will not work if another
|
||||
// pass corrupts it.
|
||||
#define TEX_FREEZEFRAME_WIDTH content_size.x
|
||||
#define TEX_FREEZEFRAME_HEIGHT content_size.y
|
||||
#define TEX_FREEZEFRAME_SIZE int2(TEX_FREEZEFRAME_WIDTH, TEX_FREEZEFRAME_HEIGHT
|
||||
texture2D texFreezeFrame < pooled = false; > {
|
||||
Width = TEX_FREEZEFRAME_WIDTH;
|
||||
Height = TEX_FREEZEFRAME_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerFreezeFrame { Texture = texFreezeFrame; };
|
||||
|
||||
|
||||
// Pass 10 Mask Texture (phosphorMaskResizeHorizontalPass)
|
||||
// Cannot be conditioned on __RENDERER__ b/c there are no
|
||||
// available buffers of the same size
|
||||
#define TEX_PHOSPHORMASK_WIDTH content_size.x
|
||||
#define TEX_PHOSPHORMASK_HEIGHT content_size.y
|
||||
#define TEX_PHOSPHORMASKL_SIZE int2(TEX_PHOSPHORMASK_WIDTH, TEX_PHOSPHORMASK_HEIGHT)
|
||||
texture2D texPhosphorMask < pooled = false; > {
|
||||
Width = TEX_PHOSPHORMASK_WIDTH;
|
||||
Height = TEX_PHOSPHORMASK_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerPhosphorMask { Texture = texPhosphorMask; };
|
||||
|
||||
|
||||
// Pass 11 Buffer (phosphorMaskPass)
|
||||
// Last usage is bloomHorizontalPass
|
||||
#define TEX_MASKEDSCANLINES_WIDTH content_size.x
|
||||
#define TEX_MASKEDSCANLINES_HEIGHT content_size.y
|
||||
#define TEX_MASKEDSCANLINES_SIZE int2(TEX_MASKEDSCANLINES_WIDTH, TEX_MASKEDSCANLINES_HEIGHT)
|
||||
|
||||
#if _DX9_ACTIVE == 0
|
||||
texture2D texMaskedScanlines < pooled = true; > {
|
||||
Width = TEX_MASKEDSCANLINES_WIDTH;
|
||||
Height = TEX_MASKEDSCANLINES_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerMaskedScanlines { Texture = texMaskedScanlines; };
|
||||
#else
|
||||
#define texMaskedScanlines texBeamConvergence
|
||||
#define samplerMaskedScanlines samplerBeamConvergence
|
||||
#endif
|
||||
|
||||
|
||||
// Pass 12 Buffer (brightpassPass)
|
||||
// Last usage is bloomHorizontalPass
|
||||
#define TEX_BRIGHTPASS_WIDTH content_size.x
|
||||
#define TEX_BRIGHTPASS_HEIGHT content_size.y
|
||||
#define TEX_BRIGHTPASS_SIZE int2(TEX_BRIGHTPASS_WIDTH, TEX_BRIGHTPASS_HEIGHT)
|
||||
|
||||
#if _DX9_ACTIVE == 0
|
||||
texture2D texBrightpass < pooled = true; > {
|
||||
Width = TEX_BRIGHTPASS_WIDTH;
|
||||
Height = TEX_BRIGHTPASS_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerBrightpass { Texture = texBrightpass; };
|
||||
#else
|
||||
#define texBrightpass texElectronBeams
|
||||
#define samplerBrightpass samplerElectronBeams
|
||||
#endif
|
||||
|
||||
|
||||
// Pass 13 Buffer (bloomVerticalPass)
|
||||
// Cannot be conditioned on __RENDERER__ b/c there are no
|
||||
// available buffers of the same size
|
||||
// Last usage is bloomHorizontalPass
|
||||
#define TEX_BLOOMVERTICAL_WIDTH content_size.x
|
||||
#define TEX_BLOOMVERTICAL_HEIGHT content_size.y
|
||||
#define TEX_BLOOMVERTICAL_SIZE int2(TEX_BLOOMVERTICAL_WIDTH, TEX_BLOOMVERTICAL_HEIGHT)
|
||||
texture2D texBloomVertical < pooled = true; > {
|
||||
Width = TEX_BLOOMVERTICAL_WIDTH;
|
||||
Height = TEX_BLOOMVERTICAL_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerBloomVertical { Texture = texBloomVertical; };
|
||||
|
||||
|
||||
// Pass 14 Buffer (bloomHorizontalPass)
|
||||
// Cannot be conditioned on __RENDERER__ b/c there are no
|
||||
// available buffers of the same size
|
||||
// Last usage is geometryPass
|
||||
#define TEX_BLOOMHORIZONTAL_WIDTH content_size.x
|
||||
#define TEX_BLOOMHORIZONTAL_HEIGHT content_size.y
|
||||
#define TEX_BLOOMHORIZONTAL_SIZE int2(TEX_BLOOMHORIZONTAL_WIDTH, TEX_BLOOMHORIZONTAL_HEIGHT)
|
||||
texture2D texBloomHorizontal < pooled = true; > {
|
||||
Width = TEX_BLOOMHORIZONTAL_WIDTH;
|
||||
Height = TEX_BLOOMHORIZONTAL_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerBloomHorizontal { Texture = texBloomHorizontal; };
|
||||
|
||||
|
||||
// Pass 15 Buffer (geometryPass)
|
||||
// Last usage is uncropPass
|
||||
#define TEX_GEOMETRY_WIDTH content_size.x
|
||||
#define TEX_GEOMETRY_HEIGHT content_size.y
|
||||
#define TEX_GEOMETRY_SIZE int2(TEX_GEOMETRY_WIDTH, TEX_GEOMETRY_HEIGHT)
|
||||
|
||||
#if _DX9_ACTIVE == 0
|
||||
texture2D texGeometry < pooled = true; > {
|
||||
Width = TEX_GEOMETRY_WIDTH;
|
||||
Height = TEX_GEOMETRY_HEIGHT;
|
||||
|
||||
Format = RGBA16;
|
||||
};
|
||||
sampler2D samplerGeometry { Texture = texGeometry; };
|
||||
#else
|
||||
#define texGeometry texElectronBeams
|
||||
#define samplerGeometry samplerElectronBeams
|
||||
#endif
|
||||
|
||||
#endif // _SHARED_OBJECTS_H
|
||||
Reference in New Issue
Block a user