Duckstation/data/resources/shaders/reshade/Shaders/crt/crt-royale/src/crt-royale-first-pass-linearize-crt-gamma-bob-fields.fxh
Hyllian bf1b023f12
Add a new port of crt-royale.fx (#3260)
- A new port of crt-royale. More faithful to original. It uses the same mask textures.
- The only thing not ported is the original geometry pass. It was replaced by geom curvature code.
- It's configured for 1080p displays. 4k displays need to adjust param mask_triad_size_desired from 3.0 to 4.0.

OBS: It's up to you decide if the two versions should be maintained.
2024-07-26 14:33:01 +10:00

110 lines
4.6 KiB
HLSL

///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
// crt-royale: A full-featured CRT shader, with cheese.
// Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.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
///////////////////////////// SETTINGS MANAGEMENT ////////////////////////////
// PASS SETTINGS:
// gamma-management.h needs to know what kind of pipeline we're using and
// what pass this is in that pipeline. This will become obsolete if/when we
// can #define things like this in the .cgp preset file.
#define FIRST_PASS
#define SIMULATE_CRT_ON_LCD
////////////////////////////////// INCLUDES //////////////////////////////////
#include "../include/user-settings.fxh"
#include "../include/bind-shader-params.fxh"
#include "../include/gamma-management.fxh"
#include "../include/scanline-functions.fxh"
///////////////////////////////// STRUCTURES /////////////////////////////////
struct out_vertex
{
float2 tex_uv : TEXCOORD1;
float2 uv_step : TEXCOORD2;
float interlaced : TEXCOORD3;
};
//////////////////////////////// VERTEX SHADER ///////////////////////////////
// Vertex shader generating a triangle covering the entire screen
void VS_Linearize(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out out_vertex OUT)
{
texcoord.x = (id == 2) ? 2.0 : 0.0;
texcoord.y = (id == 1) ? 2.0 : 0.0;
position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
OUT.tex_uv = texcoord;
// OUT.tex_uv = (floor(texcoord / NormalizedNativePixelSize)+float2(0.5,0.5)) * NormalizedNativePixelSize;
// Save the uv distance between texels:
OUT.uv_step = NormalizedNativePixelSize;
// Detect interlacing: 1.0 = true, 0.0 = false.
OUT.interlaced = is_interlaced(1.0/NormalizedNativePixelSize.y);
}
/////////////////////////////// FRAGMENT SHADER //////////////////////////////
sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=BORDER;AddressV=BORDER;AddressW=BORDER;MagFilter=POINT;MinFilter=POINT;};
#define input_texture sBackBuffer
float4 PS_Linearize(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in out_vertex VAR) : SV_Target
{
// Linearize the input based on CRT gamma and bob interlaced fields.
// Bobbing ensures we can immediately blur without getting artifacts.
// Note: TFF/BFF won't matter for sources that double-weave or similar.
// VAR.tex_uv = (floor(VAR.tex_uv / NormalizedNativePixelSize)+float2(0.5,0.5)) * NormalizedNativePixelSize;
if(interlace_detect)
{
// Sample the current line and an average of the previous/next line;
// tex2D_linearize will decode CRT gamma. Don't bother branching:
const float2 tex_uv = VAR.tex_uv;
const float2 v_step = float2(0.0, VAR.uv_step.y);
const float3 curr_line = tex2D_linearize_first(
input_texture, tex_uv).rgb;
const float3 last_line = tex2D_linearize_first(
input_texture, tex_uv - v_step).rgb;
const float3 next_line = tex2D_linearize_first(
input_texture, tex_uv + v_step).rgb;
const float3 interpolated_line = 0.5 * (last_line + next_line);
// If we're interlacing, determine which field curr_line is in:
const float modulus = VAR.interlaced + 1.0;
const float field_offset =
fmod(FrameCount + float(interlace_bff), modulus);
const float curr_line_texel = tex_uv.y / NormalizedNativePixelSize.y;
// Use under_half to fix a rounding bug around exact texel locations.
const float line_num_last = floor(curr_line_texel - under_half);
const float wrong_field = fmod(line_num_last + field_offset, modulus);
// Select the correct color, and output the result:
const float3 color = lerp(curr_line, interpolated_line, wrong_field);
return encode_output(float4(color, 1.0));
}
else
{
return encode_output(tex2D_linearize_first(input_texture, VAR.tex_uv));
}
}