mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-23 16:45:37 +00:00
bf1b023f12
- 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.
110 lines
4.6 KiB
HLSL
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));
|
|
}
|
|
}
|
|
|