duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

CRT-NewPixie.fx (12105B)


      1 #include "ReShade.fxh"
      2 
      3 // newpixie CRT
      4 // by Mattias Gustavsson
      5 // adapted for slang by hunterk
      6 
      7 /*
      8 ------------------------------------------------------------------------------
      9 This software is available under 2 licenses - you may choose the one you like.
     10 ------------------------------------------------------------------------------
     11 ALTERNATIVE A - MIT License
     12 Copyright (c) 2016 Mattias Gustavsson
     13 Permission is hereby granted, free of charge, to any person obtaining a copy of 
     14 this software and associated documentation files (the "Software"), to deal in 
     15 the Software without restriction, including without limitation the rights to 
     16 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
     17 of the Software, and to permit persons to whom the Software is furnished to do 
     18 so, subject to the following conditions:
     19 The above copyright notice and this permission notice shall be included in all 
     20 copies or substantial portions of the Software.
     21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
     22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
     23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
     24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
     25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
     26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
     27 SOFTWARE.
     28 ------------------------------------------------------------------------------
     29 ALTERNATIVE B - Public Domain (www.unlicense.org)
     30 This is free and unencumbered software released into the public domain.
     31 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 
     32 software, either in source code form or as a compiled binary, for any purpose, 
     33 commercial or non-commercial, and by any means.
     34 In jurisdictions that recognize copyright laws, the author or authors of this 
     35 software dedicate any and all copyright interest in the software to the public 
     36 domain. We make this dedication for the benefit of the public at large and to 
     37 the detriment of our heirs and successors. We intend this dedication to be an 
     38 overt act of relinquishment in perpetuity of all present and future rights to 
     39 this software under copyright law.
     40 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
     41 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
     42 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
     43 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
     44 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
     45 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     46 ------------------------------------------------------------------------------
     47 */
     48 
     49 uniform float acc_modulate <
     50 	ui_type = "drag";
     51 	ui_min = 0.0;
     52 	ui_max = 1.0;
     53 	ui_step = 0.01;
     54 	ui_label = "Accumulate Modulation [CRT-NewPixie]";
     55 > = 0.65;
     56 
     57 
     58 texture2D tAccTex { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
     59 sampler sAccTex { Texture=tAccTex; };
     60 
     61 //PASS 1
     62 float3 PrevColor(float4 pos : SV_Position, float2 uv : TEXCOORD0) : SV_Target
     63 {
     64 	return tex2D(ReShade::BackBuffer, uv).rgb;
     65 }
     66 
     67 float4 PS_NewPixie_Accum(float4 pos : SV_Position, float2 uv : TEXCOORD0) : SV_Target
     68 {
     69    float4 a = tex2D(sAccTex, uv.xy) * float4(acc_modulate,acc_modulate,acc_modulate,acc_modulate);
     70    float4 b = tex2D(ReShade::BackBuffer, uv.xy);
     71    return max( a, b * 0.96 );
     72 }
     73 
     74 //PASS 2 AND 3
     75 texture GaussianBlurTex { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
     76 sampler GaussianBlurSampler { Texture = GaussianBlurTex;};
     77 
     78 uniform float blur_x <
     79 	ui_type = "drag";
     80 	ui_min = 0.0;
     81 	ui_max = 5.0;
     82 	ui_step = 0.25;
     83 	ui_label = "Horizontal Blur [CRT-NewPixie]"; 
     84 > = 1.0;
     85 
     86 uniform float blur_y <
     87 	ui_type = "drag";
     88 	ui_min = 0.0;
     89 	ui_max = 5.0;
     90 	ui_step = 0.25;
     91 	ui_label = "Vertical Blur [CRT-NewPixie]";
     92 > = 1.0;
     93 
     94 float4 PS_NewPixie_Blur(float4 pos : SV_Position, float2 uv_tx : TEXCOORD0) : SV_Target
     95 {
     96    float2 blur = float2(blur_x, blur_y) * ReShade::PixelSize.xy;
     97    float2 uv = uv_tx.xy;
     98    float4 sum = tex2D( ReShade::BackBuffer, uv ) * 0.2270270270;
     99    sum += tex2D(ReShade::BackBuffer, float2( uv.x - 4.0 * blur.x, uv.y - 4.0 * blur.y ) ) * 0.0162162162;
    100    sum += tex2D(ReShade::BackBuffer, float2( uv.x - 3.0 * blur.x, uv.y - 3.0 * blur.y ) ) * 0.0540540541;
    101    sum += tex2D(ReShade::BackBuffer, float2( uv.x - 2.0 * blur.x, uv.y - 2.0 * blur.y ) ) * 0.1216216216;
    102    sum += tex2D(ReShade::BackBuffer, float2( uv.x - 1.0 * blur.x, uv.y - 1.0 * blur.y ) ) * 0.1945945946;
    103    sum += tex2D(ReShade::BackBuffer, float2( uv.x + 1.0 * blur.x, uv.y + 1.0 * blur.y ) ) * 0.1945945946;
    104    sum += tex2D(ReShade::BackBuffer, float2( uv.x + 2.0 * blur.x, uv.y + 2.0 * blur.y ) ) * 0.1216216216;
    105    sum += tex2D(ReShade::BackBuffer, float2( uv.x + 3.0 * blur.x, uv.y + 3.0 * blur.y ) ) * 0.0540540541;
    106    sum += tex2D(ReShade::BackBuffer, float2( uv.x + 4.0 * blur.x, uv.y + 4.0 * blur.y ) ) * 0.0162162162;
    107    return sum;
    108 }
    109 
    110 //PASS 4
    111 uniform int FCount < source = "framecount"; >;
    112 uniform float2 BufferViewportRatio < source = "buffer_to_viewport_ratio"; >;
    113 
    114 texture tFrame < source = "crt-newpixie/crtframe.png"; >
    115 {
    116 	Width = 1024;
    117 	Height = 1024;
    118 	MipLevels = 1;
    119 };
    120 
    121 sampler sFrame { Texture = tFrame; AddressU = BORDER; AddressV = BORDER; MinFilter = LINEAR; MagFilter = LINEAR;};
    122 
    123 uniform bool use_frame <
    124 	ui_type = "boolean";
    125 	ui_label = "Use Frame Image [CRT-NewPixie]";
    126 > = false;
    127 
    128 uniform float curvature <
    129 	ui_type = "drag";
    130 	ui_min = 0.0001;
    131 	ui_max = 4.0;
    132 	ui_step = 0.25;
    133 	ui_label = "Curvature [CRT-NewPixie]";
    134 > = 2.0;
    135 
    136 uniform bool wiggle_toggle <
    137 	ui_type = "boolean";
    138 	ui_label = "Interference [CRT-NewPixie]";
    139 > = false;
    140 
    141 uniform bool scanroll <
    142 	ui_type = "boolean";
    143 	ui_label = "Rolling Scanlines [CRT-NewPixie]";
    144 > = true;
    145 
    146 float3 tsample( sampler samp, float2 tc, float offs, float2 resolution )
    147 {
    148 	tc = tc * float2(1.025, 0.92) + float2(-0.0125, 0.04);
    149 	float3 s = pow( abs( tex2D( samp, float2( tc.x, 1.0-tc.y ) ).rgb), float3( 2.2,2.2,2.2 ) );
    150 	return s*float3(1.25,1.25,1.25);
    151 }
    152 		
    153 float3 filmic( float3 LinearColor )
    154 {
    155 	float3 x = max( float3(0.0,0.0,0.0), LinearColor-float3(0.004,0.004,0.004));
    156     return (x*(6.2*x+0.5))/(x*(6.2*x+1.7)+0.06);
    157 }
    158 		
    159 float2 curve( float2 uv )
    160 {
    161     uv = (uv - 0.5);// * 2.0;
    162     uv *= float2(0.925, 1.095);  
    163     uv *= curvature;
    164     uv.x *= 1.0 + pow((abs(uv.y) / 4.0), 2.0);
    165     uv.y *= 1.0 + pow((abs(uv.x) / 3.0), 2.0);
    166     uv /= curvature;
    167     uv  += 0.5;
    168     uv =  uv *0.92 + 0.04;
    169     return uv;
    170 }
    171 		
    172 float rand(float2 co){ return frac(sin(dot(co.xy ,float2(12.9898,78.233))) * 43758.5453); }
    173     
    174 #define resolution ReShade::ScreenSize.xy
    175 #define mod(x,y) (x-y*floor(x/y))
    176 
    177 float4 PS_NewPixie_Final(float4 pos: SV_Position, float2 uv_tx : TEXCOORD0) : SV_Target
    178 {
    179    // stop time variable so the screen doesn't wiggle
    180    float time = mod(FCount, 849.0) * 36.0;
    181     float2 uv = uv_tx.xy;
    182 	uv.y = 1.0 - uv_tx.y;
    183     /* Curve */
    184     float2 curved_uv = lerp( curve( uv ), uv, 0.4 );
    185     float scale = -0.101;
    186     float2 scuv = curved_uv*(1.0-scale)+scale/2.0+float2(0.003, -0.001);
    187 	
    188     uv = scuv;
    189 		
    190     /* Main color, Bleed */
    191     float3 col;
    192 	
    193     float x = wiggle_toggle* sin(0.1*time+curved_uv.y*13.0)*sin(0.23*time+curved_uv.y*19.0)*sin(0.3+0.11*time+curved_uv.y*23.0)*0.0012;
    194     float o =sin(uv_tx.y*1.5)/resolution.x;
    195     x+=o*0.25;
    196    // make time do something again
    197     time = float(mod(FCount, 640) * 1); 
    198     col.r = tsample(ReShade::BackBuffer,float2(x+scuv.x+0.0009,scuv.y+0.0009),resolution.y/800.0, resolution ).x+0.02;
    199     col.g = tsample(ReShade::BackBuffer,float2(x+scuv.x+0.0000,scuv.y-0.0011),resolution.y/800.0, resolution ).y+0.02;
    200     col.b = tsample(ReShade::BackBuffer,float2(x+scuv.x-0.0015,scuv.y+0.0000),resolution.y/800.0, resolution ).z+0.02;
    201     float i = clamp(col.r*0.299 + col.g*0.587 + col.b*0.114, 0.0, 1.0 );
    202     i = pow( 1.0 - pow(i,2.0), 1.0 );
    203     i = (1.0-i) * 0.85 + 0.15; 
    204     
    205     /* Ghosting */
    206     float ghs = 0.15;
    207     float3 r = tsample(GaussianBlurSampler, float2(x-0.014*1.0, -0.027)*0.85+0.007*float2( 0.35*sin(1.0/7.0 + 15.0*curved_uv.y + 0.9*time), 
    208         0.35*sin( 2.0/7.0 + 10.0*curved_uv.y + 1.37*time) )+float2(scuv.x+0.001,scuv.y+0.001),
    209         5.5+1.3*sin( 3.0/9.0 + 31.0*curved_uv.x + 1.70*time),resolution).xyz*float3(0.5,0.25,0.25);
    210     float3 g = tsample(GaussianBlurSampler, float2(x-0.019*1.0, -0.020)*0.85+0.007*float2( 0.35*cos(1.0/9.0 + 15.0*curved_uv.y + 0.5*time), 
    211         0.35*sin( 2.0/9.0 + 10.0*curved_uv.y + 1.50*time) )+float2(scuv.x+0.000,scuv.y-0.002),
    212         5.4+1.3*sin( 3.0/3.0 + 71.0*curved_uv.x + 1.90*time),resolution).xyz*float3(0.25,0.5,0.25);
    213     float3 b = tsample(GaussianBlurSampler, float2(x-0.017*1.0, -0.003)*0.85+0.007*float2( 0.35*sin(2.0/3.0 + 15.0*curved_uv.y + 0.7*time), 
    214         0.35*cos( 2.0/3.0 + 10.0*curved_uv.y + 1.63*time) )+float2(scuv.x-0.002,scuv.y+0.000),
    215         5.3+1.3*sin( 3.0/7.0 + 91.0*curved_uv.x + 1.65*time),resolution).xyz*float3(0.25,0.25,0.5);
    216 		
    217     col += float3(ghs*(1.0-0.299),ghs*(1.0-0.299),ghs*(1.0-0.299))*pow(clamp(float3(3.0,3.0,3.0)*r,float3(0.0,0.0,0.0),float3(1.0,1.0,1.0)),float3(2.0,2.0,2.0))*float3(i,i,i);
    218     col += float3(ghs*(1.0-0.587),ghs*(1.0-0.587),ghs*(1.0-0.587))*pow(clamp(float3(3.0,3.0,3.0)*g,float3(0.0,0.0,0.0),float3(1.0,1.0,1.0)),float3(2.0,2.0,2.0))*float3(i,i,i);
    219     col += float3(ghs*(1.0-0.114),ghs*(1.0-0.114),ghs*(1.0-0.114))*pow(clamp(float3(3.0,3.0,3.0)*b,float3(0.0,0.0,0.0),float3(1.0,1.0,1.0)),float3(2.0,2.0,2.0))*float3(i,i,i);
    220 		
    221     /* Level adjustment (curves) */
    222     col *= float3(0.95,1.05,0.95);
    223     col = clamp(col*1.3 + 0.75*col*col + 1.25*col*col*col*col*col,float3(0.0,0.0,0.0),float3(10.0,10.0,10.0));
    224 		
    225     /* Vignette */
    226     float vig = (0.1 + 1.0*16.0*curved_uv.x*curved_uv.y*(1.0-curved_uv.x)*(1.0-curved_uv.y));
    227     vig = 1.3*pow(vig,0.5);
    228     col *= vig;
    229     
    230     time *= scanroll;
    231 		
    232     /* Scanlines */
    233     float scans = clamp( 0.35+0.18*sin(6.0*time-curved_uv.y*resolution.y*1.5), 0.0, 1.0);
    234     float s = pow(scans,0.9);
    235     col = col * float3(s,s,s);
    236 		
    237     /* Vertical lines (shadow mask) */
    238     col*=1.0-0.23*(clamp((mod(uv_tx.xy.x, 3.0))/2.0,0.0,1.0));
    239 		
    240     /* Tone map */
    241     col = filmic( col );
    242 		
    243     /* Noise */
    244     /*float2 seed = floor(curved_uv*resolution.xy*float2(0.5))/resolution.xy;*/
    245     float2 seed = curved_uv*resolution.xy;;
    246     /* seed = curved_uv; */
    247     col -= 0.015*pow(float3(rand( seed +time ), rand( seed +time*2.0 ), rand( seed +time * 3.0 ) ), float3(1.5,1.5,1.5) );
    248 		
    249     /* Flicker */
    250     col *= (1.0-0.004*(sin(50.0*time+curved_uv.y*2.0)*0.5+0.5));
    251 		
    252     /* Clamp */
    253 //    if(max(abs(uv.x-0.5),abs(uv.y-0.5))>0.5)
    254 //        col = float3(0.0,0.0,0.0);
    255 		
    256 //    if (curved_uv.x < 0.0 || curved_uv.x > 1.0)
    257 //        col *= 0.0;
    258 //    if (curved_uv.y < 0.0 || curved_uv.y > 1.0)
    259 //        col *= 0.0;
    260 
    261     uv = curved_uv;
    262 	
    263     /* Frame */
    264     float2 fscale = float2( 0.026, -0.018);//float2( -0.018, -0.013 );
    265     uv = float2(uv.x, 1.-uv.y);
    266 //    float4 f= tex2D(sFrame,uv_tx.xy);//*((1.0)+2.0*fscale)-fscale-float2(-0.0, 0.005));
    267     float4 f= tex2D(sFrame,(uv_tx-float2(0.5,0.5)) * BufferViewportRatio + float2(0.5,0.5));//*((1.0)+2.0*fscale)-fscale-float2(-0.0, 0.005));
    268     f.xyz = lerp( f.xyz, float3(0.5,0.5,0.5), 0.5 );
    269     float fvig = clamp( -0.00+512.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y), 0.2, 0.8 );
    270     col = lerp( col, lerp( max( col, 0.0), pow( abs( f.xyz ), float3( 1.4,1.4,1.4 ) ) * fvig, f.w * f.w), float3( use_frame,use_frame,use_frame ) );
    271 	
    272     return float4( col, 1.0 );
    273 }
    274 
    275 technique CRTNewPixie
    276 {
    277 	pass PS_CRTNewPixie_Accum
    278 	{
    279 		VertexShader=PostProcessVS;
    280 		PixelShader=PS_NewPixie_Accum;
    281 	}
    282 	
    283 	pass PS_CRTNewPixie_SaveBuffer {
    284 		VertexShader=PostProcessVS;
    285 		PixelShader=PrevColor;
    286 		RenderTarget = tAccTex;
    287 	}
    288 	
    289 	pass PS_CRTNewPixie_Blur
    290 	{
    291 		VertexShader = PostProcessVS;
    292 		PixelShader = PS_NewPixie_Blur;
    293 		RenderTarget = GaussianBlurTex;
    294 	}
    295 	
    296 	pass PS_CRTNewPixie_Final
    297 	{
    298 		VertexShader = PostProcessVS;
    299 		PixelShader = PS_NewPixie_Final;
    300 	}
    301 }