6
6
7
7
#include shared ,prim_shared,brush
8
8
9
- varying vec3 vSrcUv;
10
- varying vec3 vBackdropUv;
11
- flat varying int vOp;
9
+ varying vec4 vSourceAndBackdropUv;
10
+ flat varying ivec4 vSourceUvBounds;
11
+ flat varying ivec4 vBackdropUvBounds;
12
+ flat varying ivec3 vOpAndLayers;
12
13
13
14
#ifdef WR_VERTEX_SHADER
14
15
@@ -17,6 +18,10 @@ vec2 snap_device_pos(VertexInfo vi, float device_pixel_scale) {
17
18
return vi.world_pos.xy * device_pixel_scale / max (0.0 , vi.world_pos.w) + vi.snap_offset;
18
19
}
19
20
21
+ ivec4 rect_to_ivec(RectWithSize rect) {
22
+ return ivec4 (rect.p0, rect.p0 + rect.size - 1.0 );
23
+ }
24
+
20
25
void brush_vs(
21
26
VertexInfo vi,
22
27
int prim_address,
@@ -29,20 +34,25 @@ void brush_vs(
29
34
vec4 unused
30
35
) {
31
36
vec2 snapped_device_pos = snap_device_pos(vi, pic_task.device_pixel_scale);
32
- vec2 texture_size = vec2 (textureSize(sPrevPassColor, 0 ));
33
- vOp = user_data.x;
34
37
35
38
PictureTask src_task = fetch_picture_task(user_data.z);
39
+ PictureTask backdrop_task = fetch_picture_task(user_data.y);
40
+
36
41
vec2 src_uv = snapped_device_pos +
37
42
src_task.common_data.task_rect.p0 -
38
43
src_task.content_origin;
39
- vSrcUv = vec3 (src_uv / texture_size, src_task.common_data.texture_layer_index);
40
-
41
- RenderTaskCommonData backdrop_task = fetch_render_task_common_data(user_data.y);
42
44
vec2 backdrop_uv = snapped_device_pos +
43
- backdrop_task.task_rect.p0 -
44
- src_task.content_origin;
45
- vBackdropUv = vec3 (backdrop_uv / texture_size, backdrop_task.texture_layer_index);
45
+ backdrop_task.common_data.task_rect.p0 -
46
+ backdrop_task.content_origin;
47
+
48
+ vSourceAndBackdropUv = vec4 (src_uv, backdrop_uv);
49
+ vSourceUvBounds = rect_to_ivec(src_task.common_data.task_rect);
50
+ vBackdropUvBounds = rect_to_ivec(backdrop_task.common_data.task_rect);
51
+ vOpAndLayers = ivec3 (
52
+ user_data.x,
53
+ int (src_task.common_data.texture_layer_index),
54
+ int (backdrop_task.common_data.texture_layer_index)
55
+ );
46
56
}
47
57
#endif
48
58
@@ -205,81 +215,88 @@ const int MixBlendMode_Color = 14;
205
215
const int MixBlendMode_Luminosity = 15 ;
206
216
207
217
Fragment brush_fs() {
208
- vec4 Cb = textureLod(sPrevPassColor, vBackdropUv, 0.0 );
209
- vec4 Cs = textureLod(sPrevPassColor, vSrcUv, 0.0 );
210
-
211
- // The mix-blend-mode functions assume no premultiplied alpha
212
- if (Cb.a != 0.0 ) {
213
- Cb.rgb /= Cb.a;
214
- }
215
-
216
- if (Cs.a != 0.0 ) {
217
- Cs.rgb /= Cs.a;
218
- }
219
-
220
218
// Return yellow if none of the branches match (shouldn't happen).
221
219
vec4 result = vec4 (1.0 , 1.0 , 0.0 , 1.0 );
222
220
223
- switch (vOp) {
224
- case MixBlendMode_Multiply:
225
- result.rgb = Multiply(Cb.rgb, Cs.rgb);
226
- break ;
227
- case MixBlendMode_Screen:
228
- result.rgb = Screen(Cb.rgb, Cs.rgb);
229
- break ;
230
- case MixBlendMode_Overlay:
231
- // Overlay is inverse of Hardlight
232
- result.rgb = HardLight(Cs.rgb, Cb.rgb);
233
- break ;
234
- case MixBlendMode_Darken:
235
- result.rgb = min (Cs.rgb, Cb.rgb);
236
- break ;
237
- case MixBlendMode_Lighten:
238
- result.rgb = max (Cs.rgb, Cb.rgb);
239
- break ;
240
- case MixBlendMode_ColorDodge:
241
- result.r = ColorDodge(Cb.r, Cs.r);
242
- result.g = ColorDodge(Cb.g, Cs.g);
243
- result.b = ColorDodge(Cb.b, Cs.b);
244
- break ;
245
- case MixBlendMode_ColorBurn:
246
- result.r = ColorBurn(Cb.r, Cs.r);
247
- result.g = ColorBurn(Cb.g, Cs.g);
248
- result.b = ColorBurn(Cb.b, Cs.b);
249
- break ;
250
- case MixBlendMode_HardLight:
251
- result.rgb = HardLight(Cb.rgb, Cs.rgb);
252
- break ;
253
- case MixBlendMode_SoftLight:
254
- result.r = SoftLight(Cb.r, Cs.r);
255
- result.g = SoftLight(Cb.g, Cs.g);
256
- result.b = SoftLight(Cb.b, Cs.b);
257
- break ;
258
- case MixBlendMode_Difference:
259
- result.rgb = Difference(Cb.rgb, Cs.rgb);
260
- break ;
261
- case MixBlendMode_Exclusion:
262
- result.rgb = Exclusion(Cb.rgb, Cs.rgb);
263
- break ;
264
- case MixBlendMode_Hue:
265
- result.rgb = Hue(Cb.rgb, Cs.rgb);
266
- break ;
267
- case MixBlendMode_Saturation:
268
- result.rgb = Saturation(Cb.rgb, Cs.rgb);
269
- break ;
270
- case MixBlendMode_Color:
271
- result.rgb = Color(Cb.rgb, Cs.rgb);
272
- break ;
273
- case MixBlendMode_Luminosity:
274
- result.rgb = Luminosity(Cb.rgb, Cs.rgb);
275
- break ;
276
- default : break ;
277
- }
221
+ ivec2 source_uv = ivec2 (floor (vSourceAndBackdropUv.xy));
222
+ vec4 Cs = source_uv == clamp (source_uv, vSourceUvBounds.xy, vSourceUvBounds.zw) ?
223
+ texelFetch(sPrevPassColor, ivec3 (source_uv, vOpAndLayers.y), 0 ) :
224
+ vec4 (0.0 );
225
+ ivec2 backdrop_uv = ivec2 (floor (vSourceAndBackdropUv.zw));
226
+ vec4 Cb = backdrop_uv == clamp (backdrop_uv, vBackdropUvBounds.xy, vBackdropUvBounds.zw) ?
227
+ texelFetch(sPrevPassColor, ivec3 (backdrop_uv, vOpAndLayers.z), 0 ) :
228
+ vec4 (0.0 );
229
+
230
+ if (Cs.a == 0.0 ) {
231
+ result = Cb;
232
+ } else if (Cb.a == 0.0 ) {
233
+ result = Cs;
234
+ } else {
235
+ vec3 original_backdrop = Cb.rgb;
236
+ // The mix-blend-mode functions assume no premultiplied alpha
237
+ Cs.rgb /= Cs.a;
238
+ Cb.rgb /= Cb.a;
278
239
279
- result.rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
280
- result.a = Cs.a;
240
+ switch (vOpAndLayers.x) {
241
+ case MixBlendMode_Multiply:
242
+ result.rgb = Multiply(Cb.rgb, Cs.rgb);
243
+ break ;
244
+ case MixBlendMode_Screen:
245
+ result.rgb = Screen(Cb.rgb, Cs.rgb);
246
+ break ;
247
+ case MixBlendMode_Overlay:
248
+ // Overlay is inverse of Hardlight
249
+ result.rgb = HardLight(Cs.rgb, Cb.rgb);
250
+ break ;
251
+ case MixBlendMode_Darken:
252
+ result.rgb = min (Cs.rgb, Cb.rgb);
253
+ break ;
254
+ case MixBlendMode_Lighten:
255
+ result.rgb = max (Cs.rgb, Cb.rgb);
256
+ break ;
257
+ case MixBlendMode_ColorDodge:
258
+ result.r = ColorDodge(Cb.r, Cs.r);
259
+ result.g = ColorDodge(Cb.g, Cs.g);
260
+ result.b = ColorDodge(Cb.b, Cs.b);
261
+ break ;
262
+ case MixBlendMode_ColorBurn:
263
+ result.r = ColorBurn(Cb.r, Cs.r);
264
+ result.g = ColorBurn(Cb.g, Cs.g);
265
+ result.b = ColorBurn(Cb.b, Cs.b);
266
+ break ;
267
+ case MixBlendMode_HardLight:
268
+ result.rgb = HardLight(Cb.rgb, Cs.rgb);
269
+ break ;
270
+ case MixBlendMode_SoftLight:
271
+ result.r = SoftLight(Cb.r, Cs.r);
272
+ result.g = SoftLight(Cb.g, Cs.g);
273
+ result.b = SoftLight(Cb.b, Cs.b);
274
+ break ;
275
+ case MixBlendMode_Difference:
276
+ result.rgb = Difference(Cb.rgb, Cs.rgb);
277
+ break ;
278
+ case MixBlendMode_Exclusion:
279
+ result.rgb = Exclusion(Cb.rgb, Cs.rgb);
280
+ break ;
281
+ case MixBlendMode_Hue:
282
+ result.rgb = Hue(Cb.rgb, Cs.rgb);
283
+ break ;
284
+ case MixBlendMode_Saturation:
285
+ result.rgb = Saturation(Cb.rgb, Cs.rgb);
286
+ break ;
287
+ case MixBlendMode_Color:
288
+ result.rgb = Color(Cb.rgb, Cs.rgb);
289
+ break ;
290
+ case MixBlendMode_Luminosity:
291
+ result.rgb = Luminosity(Cb.rgb, Cs.rgb);
292
+ break ;
293
+ default : break ;
294
+ }
281
295
282
- result.rgb *= result.a;
296
+ vec3 rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
297
+ // simulate alpha-blending with the backdrop
298
+ result = mix (vec4 (original_backdrop, Cb.a), vec4 (rgb, 1.0 ), Cs.a);
299
+ }
283
300
284
301
return Fragment(result);
285
302
}
0 commit comments