SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
Shaders/CRT.fsh
1 #define COLOR_LOW 0.45
2 #define COLOR_HIGH 1.0
3 #define VERTICAL_BORDER_DEPTH 0.6
4 #define SCANLINE_DEPTH 0.55
5 #define CURVENESS 0.3
6
7 STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 output_resolution)
8 {
9 /* Curve and pixel ratio */
10 float y_curve = cos(position.x - 0.5) * CURVENESS + (1.0 - CURVENESS);
11 float y_multiplier = 8.0 / 7.0 / y_curve;
12 position.y *= y_multiplier;
13 position.y -= (y_multiplier - 1.0) / 2.0;
14 if (position.y < 0.0) return vec4(0,0,0,0);
15 if (position.y > 1.0) return vec4(0,0,0,0);
16
17 float x_curve = cos(position.y - 0.5) * CURVENESS + (1.0 - CURVENESS);
18 float x_multiplier = 1.0/x_curve;
19 position.x *= x_multiplier;
20 position.x -= (x_multiplier - 1.0) / 2.0;
21 if (position.x < 0.0) return vec4(0,0,0,0);
22 if (position.x > 1.0) return vec4(0,0,0,0);
23
24 /* Setting up common vars */
25 vec2 pos = fract(position * input_resolution);
26 vec2 sub_pos = pos * 6.0;
27
28 vec4 center = texture_relative(image, position, vec2(0, 0));
29 vec4 left = texture_relative(image, position, vec2(-1, 0));
30 vec4 right = texture_relative(image, position, vec2(1, 0));
31
32 /* Vertical blurring */
33 if (sub_pos.y < 1.0) {
34 center = mix(center, texture_relative(image, position, vec2( 0, -1)), 0.5 - sub_pos.y / 2.0);
35 left = mix(left, texture_relative(image, position, vec2(-1, -1)), 0.5 - sub_pos.y / 2.0);
36 right = mix(right, texture_relative(image, position, vec2( 1, -1)), 0.5 - sub_pos.y / 2.0);
37 }
38 else if (sub_pos.y > 5.0) {
39 center = mix(center, texture_relative(image, position, vec2( 0, 1)), (sub_pos.y - 5.0) / 2.0);
40 left = mix(left, texture_relative(image, position, vec2(-1, 1)), (sub_pos.y - 5.0) / 2.0);
41 right = mix(right, texture_relative(image, position, vec2( 1, 1)), (sub_pos.y - 5.0) / 2.0);
42 }
43
44 /* Scanlines */
45 float scanline_multiplier;
46 if (pos.y < 0.5) {
47 scanline_multiplier = (pos.y * 2.0) * SCANLINE_DEPTH + (1.0 - SCANLINE_DEPTH);
48 }
49 else {
50 scanline_multiplier = ((1.0 - pos.y) * 2.0) * SCANLINE_DEPTH + (1.0 - SCANLINE_DEPTH);
51 }
52
53 center *= scanline_multiplier;
54 left *= scanline_multiplier;
55 right *= scanline_multiplier;
56
57 /* Vertical seperator for shadow masks */
58 bool odd = bool(int((position * input_resolution).x) & 1);
59 if (odd) {
60 pos.y += 0.5;
61 pos.y = fract(pos.y);
62 }
63
64 if (pos.y < 1.0 / 3.0) {
65 float gradient_position = pos.y * 3.0;
66 center *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
67 left *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
68 right *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
69 }
70 else if (pos.y > 2.0 / 3.0) {
71 float gradient_position = (1.0 - pos.y) * 3.0;
72 center *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
73 left *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
74 right *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
75 }
76
77 /* Blur the edges of the separators of adjacent columns */
78 if (sub_pos.x < 1.0 || sub_pos.x > 5.0) {
79 pos.y += 0.5;
80 pos.y = fract(pos.y);
81
82 if (pos.y < 1.0 / 3.0) {
83 float gradient_position = pos.y * 3.0;
84 if (pos.x < 0.5) {
85 gradient_position = 1.0 - (1.0 - gradient_position) * (1.0 - (pos.x) * 6.0);
86 }
87 else {
88 gradient_position = 1.0 - (1.0 - gradient_position) * (1.0 - (1.0 - pos.x) * 6.0);
89 }
90 center *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
91 left *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
92 right *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
93 }
94 else if (pos.y > 2.0 / 3.0) {
95 float gradient_position = (1.0 - pos.y) * 3.0;
96 if (pos.x < 0.5) {
97 gradient_position = 1.0 - (1.0 - gradient_position) * (1.0 - (pos.x) * 6.0);
98 }
99 else {
100 gradient_position = 1.0 - (1.0 - gradient_position) * (1.0 - (1.0 - pos.x) * 6.0);
101 }
102 center *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
103 left *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
104 right *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
105 }
106 }
107
108
109 /* Subpixel blurring, like LCD filter*/
110
111 vec4 midleft = mix(left, center, 0.5);
112 vec4 midright = mix(right, center, 0.5);
113
114 vec4 ret;
115 if (sub_pos.x < 1.0) {
116 ret = mix(vec4(COLOR_HIGH * center.r, COLOR_LOW * center.g, COLOR_HIGH * left.b, 1),
117 vec4(COLOR_HIGH * center.r, COLOR_LOW * center.g, COLOR_LOW * left.b, 1),
118 sub_pos.x);
119 }
120 else if (sub_pos.x < 2.0) {
121 ret = mix(vec4(COLOR_HIGH * center.r, COLOR_LOW * center.g, COLOR_LOW * left.b, 1),
122 vec4(COLOR_HIGH * center.r, COLOR_HIGH * center.g, COLOR_LOW * midleft.b, 1),
123 sub_pos.x - 1.0);
124 }
125 else if (sub_pos.x < 3.0) {
126 ret = mix(vec4(COLOR_HIGH * center.r , COLOR_HIGH * center.g, COLOR_LOW * midleft.b, 1),
127 vec4(COLOR_LOW * midright.r, COLOR_HIGH * center.g, COLOR_LOW * center.b, 1),
128 sub_pos.x - 2.0);
129 }
130 else if (sub_pos.x < 4.0) {
131 ret = mix(vec4(COLOR_LOW * midright.r, COLOR_HIGH * center.g , COLOR_LOW * center.b, 1),
132 vec4(COLOR_LOW * right.r , COLOR_HIGH * center.g, COLOR_HIGH * center.b, 1),
133 sub_pos.x - 3.0);
134 }
135 else if (sub_pos.x < 5.0) {
136 ret = mix(vec4(COLOR_LOW * right.r, COLOR_HIGH * center.g , COLOR_HIGH * center.b, 1),
137 vec4(COLOR_LOW * right.r, COLOR_LOW * midright.g, COLOR_HIGH * center.b, 1),
138 sub_pos.x - 4.0);
139 }
140 else {
141 ret = mix(vec4(COLOR_LOW * right.r, COLOR_LOW * midright.g, COLOR_HIGH * center.b, 1),
142 vec4(COLOR_HIGH * right.r, COLOR_LOW * right.g , COLOR_HIGH * center.b, 1),
143 sub_pos.x - 5.0);
144 }
145
146 /* Anti alias the curve */
147 vec2 pixel_position = position * output_resolution;
148 if (pixel_position.x < 1.0) {
149 ret *= pixel_position.x;
150 }
151 else if (pixel_position.x > output_resolution.x - 1.0) {
152 ret *= output_resolution.x - pixel_position.x;
153 }
154 if (pixel_position.y < 1.0) {
155 ret *= pixel_position.y;
156 }
157 else if (pixel_position.y > output_resolution.y - 1.0) {
158 ret *= output_resolution.y - pixel_position.y;
159 }
160
161 return ret;
162 }
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.