From bdb8077f6ac61a54cd33bec953a14271c52e578e Mon Sep 17 00:00:00 2001 From: hunterk Date: Fri, 20 Dec 2019 11:47:12 -0600 Subject: [PATCH] add subpixel masks and customize metacrt --- crt/shaders/metacrt/bufC.slang | 49 ++++--- include/subpixel_masks.h | 247 +++++++++++++++++++++++++++++++++ 2 files changed, 280 insertions(+), 16 deletions(-) create mode 100644 include/subpixel_masks.h diff --git a/crt/shaders/metacrt/bufC.slang b/crt/shaders/metacrt/bufC.slang index b605517..ddc8ea0 100644 --- a/crt/shaders/metacrt/bufC.slang +++ b/crt/shaders/metacrt/bufC.slang @@ -6,11 +6,17 @@ layout(push_constant) uniform Push vec4 OriginalSize; vec4 OutputSize; uint FrameCount; - float cam_spot, noise_intensity; + float cam_spot, noise_intensity, cam_loc_y, cam_loc_x, cam_zoom, cam_angle_y, cam_angle_x, cam_fov; } params; -#pragma parameter cam_spot "Camera Location" 2.0 0.0 9.0 1.0 -#pragma parameter noise_intensity "Noise Intensity" 0.1 0.0 0.5 0.01 +#pragma parameter cam_spot "Cam Loc (0 = Custom, -1 = cycle)" 0.0 -1.0 9.0 1.0 +#pragma parameter noise_intensity "Noise Intensity" 0.03 0.0 0.5 0.01 +#pragma parameter cam_angle_y "Tilt Cam Y" 0.24 -0.5 0.5 0.01 +#pragma parameter cam_angle_x "Turn Cam X" 0.0 -0.5 0.5 0.01 +#pragma parameter cam_zoom "Custom Cam Zoom" -0.915 -2.0 2.0 0.05 +#pragma parameter cam_loc_y "Rotate World Y Axis" 0.25 0.0001 1.0 0.01 +#pragma parameter cam_loc_x "Rotate World X Axis" 0.0 -0.5 0.5 0.01 +#pragma parameter cam_fov "Custom Cam FOV" 10.0 0.0 100.0 1.0 #define vFragCoord vTexCoord.xy * params.OutputSize.xy #define iResolution params.OutputSize.xy @@ -688,10 +694,10 @@ Interference GetInterference( vec2 vUV ) vec3 SampleScreen( vec3 vUVW ) { - vec3 vAmbientEmissive = vec3(0.1); + vec3 vAmbientEmissive = vec3(0.01); vec3 vBlackEmissive = vec3(0.02); float fBrightness = 1.75; - vec2 vResolution = vec2(480.0f, 576.0f); + vec2 vResolution = 2.4999 * params.SourceSize.xy; vec2 vPixelCoord = vUVW.xy * vResolution; vec3 vPixelMatrix = GetPixelMatrix( vPixelCoord ); @@ -918,7 +924,7 @@ SceneResult Scene_GetDistance( vec3 vPos ) resultSet.fDist = length(vPos - vec3(0.35,0.075,-0.1)) - 0.075; resultSet.iObjectId = MAT_CHROME; Scene_Union( result, resultSet ); - + return result; } @@ -955,7 +961,7 @@ vec4 Env_GetSkyColor( const vec3 vViewPos, const vec3 vViewDir ) vec4 vResult = vec4( 0.0, 0.0, 0.0, kFarDist ); //#if 1 - vec3 vEnvMap = textureLod( iChannel1, vViewDir.xy, 0.0 ).rgb; + vec3 vEnvMap = textureLod( iChannel1, (vViewDir.xy - vec2(0.0, 1.0)) / 2., 0.0 ).rgb; vResult.rgb = vEnvMap; //#endif @@ -1036,17 +1042,17 @@ CameraState GetCameraPosition( int index ) //index=2; - if ( index == 0 ) + if ( index == 1 ) { cam.vPos = vec3(-0.1,0.2,-0.08); cam.vTarget = vec3(0,0.25,0.1); cam.fFov = 10.0; } - if ( index == 1 ) + if ( index == 0 ) { - cam.vPos = vec3(0.0,0.25,-0.915); - cam.vTarget = vec3(0.0,0.24,0.25); - cam.fFov = 10.0; + cam.vPos = vec3(params.cam_loc_x,params.cam_loc_y,params.cam_zoom); + cam.vTarget = vec3(params.cam_angle_x,params.cam_angle_y,0.0); + cam.fFov = params.cam_fov; } if ( index == 2 ) { @@ -1115,11 +1121,19 @@ void main() CameraState camA; CameraState camB; - float fSeqTime = 1.0;//iTime; + if(params.cam_spot > -0.5){ + camA = GetCameraPosition(int(params.cam_spot)); + cam.vPos = camA.vPos; + cam.vTarget = camA.vTarget; + cam.fFov = camA.fFov; + cam.fPlaneInFocus = camA.fPlaneInFocus; + } + else{ + float fSeqTime = iTime; float fSequenceSegLength = 5.0; float fSeqIndex = floor(fSeqTime / fSequenceSegLength); float fSeqPos = fract(fSeqTime / fSequenceSegLength); - int iIndex = int(params.cam_spot); + int iIndex = int(fSeqIndex); int iIndexNext = int(fSeqIndex) + 1; camA = GetCameraPosition(iIndex); camB = GetCameraPosition(iIndexNext); @@ -1129,8 +1143,10 @@ void main() cam.vTarget = mix(camA.vTarget, camB.vTarget, t ); cam.fFov = mix(camA.fFov, camB.fFov, t ); cam.fPlaneInFocus = mix(camA.fPlaneInFocus, camB.fPlaneInFocus, t ); + } } - + +#if 0 if ( iMouse.z > 0.0 ) { float fDist = 0.01 + 3.0 * (iMouse.y / iResolution.y); @@ -1146,7 +1162,8 @@ void main() vec3 vFocus = vec3(0,0.25,-0.012); cam.fPlaneInFocus = length( vFocus - cam.vPos ); } - +#endif + #ifdef ENABLE_TAA_JITTER cam.vJitter = hash21( fract( iTime ) ) - 0.5f; #else diff --git a/include/subpixel_masks.h b/include/subpixel_masks.h new file mode 100644 index 0000000..04b6235 --- /dev/null +++ b/include/subpixel_masks.h @@ -0,0 +1,247 @@ +vec3 mask_weights(vec2 coord, float mask_intensity, int phosphor_layout){ + vec3 weights = vec3(0.,0.,0.); + float intens = 1.; + float inv = 1.-mask_intensity; + vec3 green = vec3(inv, intens, inv); + vec3 magenta = vec3(intens,inv,intens); + vec3 black = vec3(inv,inv,inv); + vec3 red = vec3(intens,inv,inv); + vec3 yellow = vec3(intens,inv,intens); + vec3 cyan = vec3(inv,intens,intens); + vec3 blue = vec3(inv,inv,intens); + int w, z = 0; + + vec3 aperture_weights = mix(magenta, green, floor(mod(coord.x, 2.0))); + + if(phosphor_layout == 1){ + // classic aperture for RGB panels; good for 1080p, too small for 4K+ + // aka aperture_1_2_bgr + weights = aperture_weights; + } + + else if(phosphor_layout == 2){ + // 2x2 shadow mask for RGB panels; good for 1080p, too small for 4K+ + // aka delta_1_2x1_bgr + vec3 inverse_aperture = mix(green, magenta, floor(mod(coord.x, 2.0))); + weights = mix(aperture_weights, inverse_aperture, floor(mod(coord.y, 2.0))); + } + + else if(phosphor_layout == 3){ + // slot mask for RGB panels; looks okay at 1080p, looks better at 4K + vec3 slotmask[3][4] = { + {magenta, green, black, black}, + {magenta, green, magenta, green}, + {black, black, magenta, green} + }; + + // find the vertical index + w = int(floor(mod(coord.y, 3.0))); + + // find the horizontal index + z = int(floor(mod(coord.x, 4.0))); + + // use the indexes to find which color to apply to the current pixel + weights = slotmask[w][z]; + } + + if(phosphor_layout == 4){ + // classic aperture for RBG panels; good for 1080p, too small for 4K+ + weights = mix(yellow, blue, floor(mod(coord.x, 2.0))); + } + + else if(phosphor_layout == 5){ + // 2x2 shadow mask for RBG panels; good for 1080p, too small for 4K+ + vec3 inverse_aperture = mix(blue, yellow, floor(mod(coord.x, 2.0))); + weights = mix(mix(yellow, blue, floor(mod(coord.x, 2.0))), inverse_aperture, floor(mod(coord.y, 2.0))); + } + + else if(phosphor_layout == 6){ + // aperture_1_4_rgb; good for simulating lower + vec3 ap4[4] = vec3[](red, green, blue, black); + + z = int(floor(mod(coord.x, 4.0))); + + weights = ap4[z]; + } + + else if(phosphor_layout == 7){ + // aperture_2_5_bgr + vec3 ap3[5] = vec3[](red, magenta, blue, green, green); + + z = int(floor(mod(coord.x, 5.0))); + + weights = ap3[z]; + } + + else if(phosphor_layout == 8){ + // aperture_3_6_rgb + + vec3 big_ap[7] = vec3[](red, red, yellow, green, cyan, blue, blue); + + w = int(floor(mod(coord.x, 7.))); + + weights = big_ap[w]; + } + + else if(phosphor_layout == 9){ + // reduced TVL aperture for RGB panels + // aperture_2_4_rgb + + vec3 big_ap_rgb[4] = vec3[](red, yellow, cyan, blue); + + w = int(floor(mod(coord.x, 4.))); + + weights = big_ap_rgb[w]; + } + + else if(phosphor_layout == 10){ + // reduced TVL aperture for RBG panels + + vec3 big_ap_rbg[4] = vec3[](red, magenta, cyan, green); + + w = int(floor(mod(coord.x, 4.))); + + weights = big_ap_rbg[w]; + } + + else if(phosphor_layout == 11){ + // delta_1_4x1_rgb; dunno why this is called 4x1 when it's obviously 4x2 /shrug + vec3 delta1[2][4] = { + {red, green, blue, black}, + {blue, black, red, green} + }; + + w = int(floor(mod(coord.y, 2.0))); + z = int(floor(mod(coord.x, 4.0))); + + weights = delta1[w][z]; + } + + else if(phosphor_layout == 12){ + // delta_2_4x1_rgb + vec3 delta[2][4] = { + {red, yellow, cyan, blue}, + {cyan, blue, red, yellow} + }; + + w = int(floor(mod(coord.y, 2.0))); + z = int(floor(mod(coord.x, 4.0))); + + weights = delta[w][z]; + } + + else if(phosphor_layout == 13){ + // delta_2_4x2_rgb + vec3 delta[4][4] = { + {red, yellow, cyan, blue}, + {red, yellow, cyan, blue}, + {cyan, blue, red, yellow}, + {cyan, blue, red, yellow} + }; + + w = int(floor(mod(coord.y, 4.0))); + z = int(floor(mod(coord.x, 4.0))); + + weights = delta[w][z]; + } + + else if(phosphor_layout == 14){ + // slot mask for RGB panels; too low-pitch for 1080p, looks okay at 4K, but wants 8K+ + vec3 slotmask[3][6] = { + {magenta, green, black, black, black, black}, + {magenta, green, black, magenta, green, black}, + {black, black, black, magenta, green, black} + }; + + // find the vertical index + w = int(floor(mod(coord.y, 3.0))); + + // find the horizontal index + z = int(floor(mod(coord.x, 6.0))); + + // use the indexes to find which color to apply to the current pixel + weights = slotmask[w][z]; + } + + else if(phosphor_layout == 15){ + // slot_2_4x4_rgb + vec3 slot2[4][8] = { + {red, yellow, cyan, blue, red, yellow, cyan, blue }, + {red, yellow, cyan, blue, black, black, black, black}, + {red, yellow, cyan, blue, red, yellow, cyan, blue }, + {black, black, black, black, red, yellow, cyan, blue } + }; + + w = int(floor(mod(coord.y, 4.0))); + z = int(floor(mod(coord.x, 8.0))); + + weights = slot2[w][z]; + } + + else if(phosphor_layout == 16){ + // slot mask for RBG panels; too low-pitch for 1080p, looks okay at 4K, but wants 8K+ + vec3 slotmask[3][4] = { + {yellow, blue, black, black}, + {yellow, blue, yellow, blue}, + {black, black, yellow, blue} + }; + + // find the vertical index + w = int(floor(mod(coord.y, 3.0))); + + // find the horizontal index + z = int(floor(mod(coord.x, 4.0))); + + // use the indexes to find which color to apply to the current pixel + weights = slotmask[w][z]; + } + + else if(phosphor_layout == 17){ + // slot_2_5x4_bgr + vec3 slot2[4][10] = { + {red, magenta, blue, green, green, red, magenta, blue, green, green}, + {black, blue, blue, green, green, red, red, black, black, black}, + {red, magenta, blue, green, green, red, magenta, blue, green, green}, + {red, red, black, black, black, black, blue, blue, green, green} + }; + + w = int(floor(mod(coord.y, 4.0))); + z = int(floor(mod(coord.x, 10.0))); + + weights = slot2[w][z]; + } + + else if(phosphor_layout == 18){ + // same as above but for RBG panels + vec3 slot2[4][10] = { + {red, yellow, green, blue, blue, red, yellow, green, blue, blue }, + {black, green, green, blue, blue, red, red, black, black, black}, + {red, yellow, green, blue, blue, red, yellow, green, blue, blue }, + {red, red, black, black, black, black, green, green, blue, blue } + }; + + w = int(floor(mod(coord.y, 4.0))); + z = int(floor(mod(coord.x, 10.0))); + + weights = slot2[w][z]; + } + + else if(phosphor_layout == 19){ + // slot_3_7x6_rgb + vec3 slot[6][14] = { + {red, red, yellow, green, cyan, blue, blue, red, red, yellow, green, cyan, blue, blue}, + {red, red, yellow, green, cyan, blue, blue, red, red, yellow, green, cyan, blue, blue}, + {red, red, yellow, green, cyan, blue, blue, black, black, black, black, black, black, black}, + {red, red, yellow, green, cyan, blue, blue, red, red, yellow, green, cyan, blue, blue}, + {red, red, yellow, green, cyan, blue, blue, red, red, yellow, green, cyan, blue, blue}, + {black, black, black, black, black, black, black, black, red, red, yellow, green, cyan, blue} + }; + + w = int(floor(mod(coord.y, 6.0))); + z = int(floor(mod(coord.x, 14.0))); + + weights = slot[w][z]; + } + + return weights; +} \ No newline at end of file