FastUIDraw
fastuidraw_atlas_image_fetch.glsl.hpp
Go to the documentation of this file.
1 /*!
2  * \file fastuidraw_atlas_image_fetch.glsl.hpp
3  * \brief file fastuidraw_atlas_image_fetch.glsl.hpp
4  *
5  * Copyright 2018 by Intel.
6  *
7  * Contact: kevin.rogovin@gmail.com
8  *
9  * This Source Code Form is subject to the
10  * terms of the Mozilla Public License, v. 2.0.
11  * If a copy of the MPL was not distributed with
12  * this file, You can obtain one at
13  * http://mozilla.org/MPL/2.0/.
14  *
15  * \author Kevin Rogovin <kevin.rogovin@gmail.com>
16  *
17  */
18 
19 /*!\addtogroup GLSLVertFragCode
20  * @{
21  */
22 
23 #ifndef FASTUIDRAW_IMAGE_ATLAS_DISABLED
24 
25 #ifdef GLSL_DOXYGEN
26 /*!
27  * \def FASTUIDRAW_IMAGE_ATLAS_DISABLED
28  * If FASTUIDRAW_IMAGE_ATLAS_DISABLED is defined by the GLSL preamble
29  * generated by fastuidraw, then images backed by an atlas (i.e. \ref
30  * fastuidraw::Image::type() is \ref fastuidraw::Image::on_atlas) do
31  * not occur and are not supported.
32  */
33 #define FASTUIDRAW_IMAGE_ATLAS_DISABLED
34 
35 /*!
36  * \def FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_SIZE
37  * The size of the color tiles (as an uint), i.e. \ref fastuidraw::ImageAtlas::color_tile_size().
38  * Value is always a power of 2.
39  */
40 #define FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_SIZE
41 
42 /*!
43  * \def FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_RECIP_SIZE
44  * The reciprocal of size of the color tiles (as a float).
45  * Value is always a power of 2.
46  */
47 #define FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_RECIP_SIZE
48 
49 /*!
50  * \def FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_LOG2_SIZE
51  * The log2 of size of the color tiles (as an uint).
52  */
53 #define FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_LOG2_SIZE
54 
55 /*!
56  * \def FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_SIZE
57  * The size of the index tiles, i.e. \ref fastuidraw::ImageAtlas::index_tile_size().
58  * Value is always a power of 2.
59  */
60 #define FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_SIZE
61 
62 /*!
63  * \def FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_RECIP_SIZE
64  * The reciprocal of size of the index tiles (as a float)
65  */
66 #define FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_RECIP_SIZE
67 
68 /*!
69  * \def FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_LOG2_SIZE
70  * The log2 of size of the index tiles (as an uint).
71  */
72 #define FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_LOG2_SIZE
73 
74 #endif
75 
76 /*!
77  * \brief
78  * Structure that describes the relationship between
79  * the master index tile and the color tiles of an image.
80  * Only available if \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is
81  * not defined.
82  */
84 {
85  /*! Number of index tile levels */
86  uint num_levels;
87 
88  /*!
89  * The amount to delta on the master index tile
90  * to move one texel in the color tile.
91  */
93 
94  /*!
95  * The reciprocial of \ref
96  * image_texel_size_on_master_index_tile
97  */
99 };
100 
101 /*!
102  * \brief
103  * Structure that fully describes a \ref
104  * fastuidraw::Image or a sub-image of one.
105  * Only available if \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is
106  * not defined.
107  */
109 {
110  /*!
111  * GLSL style inheritance
112  */
114 
115  /*! the size of the image in texels */
117 
118  /*!
119  * the bottom-left corner of the master index tile
120  * of the sub-rectangle of the Image being examined
121  */
123 
124  /*! the layer of the master index tile */
126 };
127 
128 /*!
129  * \brief
130  * Structure to give information about what tile and where
131  * within a tile an image texel is located.
132  * Only available if \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is
133  * not defined.
134  */
136 {
137  /*!
138  * the most positive value allowed to go in texels
139  * before leaving the tile
140  */
142 
143  /*! the unnormalized texel coordinate within the color-atlas */
145 
146  /*! the layer within the color atlas */
147  uint layer;
148 };
149 
150 /*!
151  * \brief
152  * Structure that holds the 2x2 texel block.
153  * Only available if \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is
154  * not defined.
155  */
157 {
158  /*!
159  * The texel value in the (min-x, min-y) corner of the
160  * 2x2 texel block
161  */
163 
164  /*!
165  * The texel value in the (max-x, min-y) corner of the
166  * 2x2 texel block
167  */
169 
170  /*!
171  * The texel value in the (min-x, max-y) corner of the
172  * 2x2 texel block
173  */
175 
176  /*!
177  * The texel value in the (max-x, max-y) corner of the
178  * 2x2 texel block
179  */
181 
182  /*!
183  * The atlas coordinate for the (min-x, min-y) corner
184  */
186 };
187 
188 /*!
189  * Given the number of levels of an \ref fastuidraw::Image with
190  * \ref fastuidraw::Image::type() being \ref fastuidraw::Image::on_atlas,
191  * compute the \ref fastuidraw_image_info_type. Only available if
192  * \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is not defined.
193  * \param num_levels value of \ref fastuidraw::Image::number_index_lookups()
194  * \param d location to which to write the results
195  */
196 void
198 {
199  d.num_levels = num_levels;
200  if (num_levels >= 1u)
201  {
202  /* Each level increases the size by a factor of FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_SIZE,
203  * thus the ratio is R where R is given by
204  *
205  * R = C * pow(FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_SIZE, num_levels - 1)
206  *
207  * where
208  *
209  * C = FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_SIZE
210  *
211  * Now,
212  *
213  * R = C * pow(FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_SIZE, num_levels - 1)
214  * = C * pow(2, FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_LOG2_SIZE * (num_levels - 1))
215  *
216  * Using bitshift, we then have:
217  *
218  * R = C * (1u << (FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_LOG2_SIZE * (num_levels - 1)))
219  */
220  uint ww = uint(FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_LOG2_SIZE) * (num_levels - 1u);
221  float index_pows = float(1u << ww);
222 
223  d.recip_image_texel_size_on_master_index_tile = float(FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_SIZE) * index_pows;
224  d.image_texel_size_on_master_index_tile = 1.0 / d.recip_image_texel_size_on_master_index_tile;
225  }
226  else
227  {
228  d.image_texel_size_on_master_index_tile = 1.0;
229  d.recip_image_texel_size_on_master_index_tile = 1.0;
230  }
231 }
232 
233 /*!
234  * Given a master_tile_tex_coord value, compute the image coordinate
235  * relate to the actual fastuidraw::Image (not a sub-image as tracked
236  * by fastuidraw_image_extended_info_type additional fields). Only
237  * available if \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is not defined.
238  * \param master_tile_tex_coord interpolated value of \ref fastuidraw::Image::master_index_tile().xy
239  * \param image_info infomration of the image
240  */
241 vec2
243  in fastuidraw_image_info_type image_info)
244 {
245  /* The master index tile of an Image is ALWAYS starts at a multiple
246  * of FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_SIZE, so the value of
247  * mod(master_tile_tex_coord, FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_SIZE)
248  * gives the relative coordinate within the tile. To avoid the
249  * expensive divide, we use FASTUIDRAW_IMAGE_ATLAS_INDEX_RECIP_TILE_SIZE
250  * together with floor.
251  */
252  vec2 relative;
253 
254  relative = master_tile_tex_coord
255  - vec2(FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_SIZE) * floor(FASTUIDRAW_IMAGE_ATLAS_INDEX_RECIP_TILE_SIZE * master_tile_tex_coord);
256 
257  /* The image coordinate is then given by the relative value times
258  * the size ratio of the color-tile to master-tile
259  */
260  return relative * image_info.recip_image_texel_size_on_master_index_tile;
261 }
262 
263 /*!
264  * Gives the signed distance from an image coordinate value to
265  * the tile boundary. NOTE! the input value is the image coordinate
266  * within a fastuidraw::Image, not a sub-image.
267  * \param root_image_coordinate texel coordinate within a fastuidraw::Image;
268  * an image coordinate within a partial image
269  * is not useful.
270  * \param[out] tile_min_dist signed distance, in image texels, to min-side of tile
271  * \param[out] tile_max_dist signed distance, in image texels, to max-side of tile
272  */
273 void
274 fastuidraw_image_atlas_compute_tile_range(in float root_image_coordinate,
275  out float tile_min_dist,
276  out float tile_max_dist)
277 {
278  float tile_coord;
279 
280  tile_coord = root_image_coordinate
281  - float(FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_SIZE) * floor(root_image_coordinate * FASTUIDRAW_IMAGE_ATLAS_COLOR_RECIP_TILE_SIZE);
282 
283  tile_min_dist = -tile_coord;
284  tile_max_dist = float(FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_SIZE) - 1.0 - tile_coord;
285 }
286 
287 /*!
288  * Gives the signed distance from an image coordinate value to
289  * the tile boundary. NOTE! the input value is the image coordinate
290  * within a fastuidraw::Image, not a sub-image. Only available
291  * if \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is not defined.
292  * \param root_image_coord texel coordinate within a fastuidraw::Image;
293  * an image coordinate within a partial image
294  * is not useful.
295  * \param[out] tile_min_dist signed distance, in image texels, to min-side of tile
296  * \param[out] tile_max_dist signed distance, in image texels, to max-side of tile
297  */
298 void
300  out vec2 tile_min_dist,
301  out vec2 tile_max_dist)
302 {
303  fastuidraw_image_atlas_compute_tile_range(root_image_coord.x, tile_min_dist.x, tile_max_dist.x);
304  fastuidraw_image_atlas_compute_tile_range(root_image_coord.y, tile_min_dist.y, tile_max_dist.y);
305 }
306 
307 /*!
308  * Computes the sub-image-texel coordinate from a master-tile texel coordinate. Only
309  * available if \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is not defined.
310  * \param master_tile_tex_coord interpolated value of \ref fastuidraw::Image::master_index_tile().xy
311  * \param image_info information of the image
312  */
313 vec2
314 fastuidraw_compute_image_coordinate(in vec2 master_tile_tex_coord,
316 {
317  vec2 return_value;
318 
319  return_value = (master_tile_tex_coord - image_info.master_index_tile_bottom_left)
320  * image_info.base.recip_image_texel_size_on_master_index_tile;
321 
322  return return_value;
323 }
324 
325 /*!
326  * Computes the the master-tile texel coordinate from a sub-image-texel coordinate. Only
327  * available if \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is not defined.
328  * \param image_coordinate texel coordinate relative to the sub-image described by image_info
329  * \param image_info information of the image
330  */
331 vec2
334 {
335  vec2 return_value;
336 
337  return_value = image_coordinate * image_info.base.image_texel_size_on_master_index_tile
338  + image_info.master_index_tile_bottom_left;
339 
340  return return_value;
341 }
342 
343 /*!
344  * Clamps a image texel coordinate for nearest filtering. Only
345  * available if \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is not defined.
346  * \param image_coordinate texel coordinate relative to the sub-image described by image_info
347  * \param image_info information of the image
348  */
349 vec2
352 {
353  return clamp(image_coordinate, vec2(0.0), image_info.image_size);
354 }
355 
356 /*!
357  * Clamps a image texel coordinate for linear filtering. Only
358  * available if \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is not defined.
359  * \param image_coordinate texel coordinate relative to the sub-image described by image_info
360  * \param image_info information of the image
361  * \param pow2_lod pow2 of lod parameter
362  */
363 vec2
366  float pow2_lod)
367 {
368  return clamp(image_coordinate,
369  vec2(0.5 * pow2_lod),
370  image_info.image_size - vec2(0.5 * pow2_lod));
371 }
372 
373 /*!
374  * Clamps a image texel coordinate for cubic filtering. Only
375  * available if \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is not defined.
376  * \param image_coordinate texel coordinate relative to the sub-image described by image_info
377  * \param image_info information of the image
378  */
379 vec2
382 {
383  return clamp(image_coordinate,
384  vec2(2.0),
385  image_info.image_size - vec2(2.0));
386 }
387 
388 ///@cond
389 
390 /* Structure to make fastuidraw_compute_image_atlas_coord_helper()
391  * less ugly
392  */
393 struct fastuidraw_compute_image_atlas_coord_helper_type
394 {
395  vec2 master_tile_texel_coord;
396  uint index_layer;
397  uvec4 tile_id;
398 };
399 
400 void
401 fastuidraw_compute_image_atlas_coord_helper_init(in vec2 master_tile_texel_coord,
402  in uint index_layer,
403  out fastuidraw_compute_image_atlas_coord_helper_type v)
404 {
405  v.master_tile_texel_coord = master_tile_texel_coord;
406  v.index_layer = index_layer;
407  v.tile_id = texelFetch(fastuidraw_imageIndexAtlas,
408  ivec3(v.master_tile_texel_coord, v.index_layer),
409  0);
410  v.index_layer = v.tile_id.z + 256u * v.tile_id.w;
411 }
412 
413 void
414 fastuidraw_compute_image_atlas_coord_helper_iterate(inout fastuidraw_compute_image_atlas_coord_helper_type v)
415 {
416  vec2 index_tile_offset;
417  vec2 texel_coordinate;
418 
419  v.master_tile_texel_coord -= floor(v.master_tile_texel_coord);
420  index_tile_offset = v.master_tile_texel_coord * float(FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_SIZE);
421  texel_coordinate = index_tile_offset
422  + vec2(v.tile_id.xy) * float(FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_SIZE);
423 
424  v.tile_id = texelFetch(fastuidraw_imageIndexAtlas,
425  ivec3(texel_coordinate, v.index_layer),
426  0);
427  v.index_layer = v.tile_id.z + 256u * v.tile_id.w;
428  v.master_tile_texel_coord = texel_coordinate;
429 }
430 
431 void
432 fastuidraw_compute_image_atlas_coord_helper_fini(in fastuidraw_compute_image_atlas_coord_helper_type v,
434 {
435 
436  /* at this point index_layer gives the layer into colorAtlas
437  * and tile_id gives which tile in the color atlas
438  */
439  vec2 tile_offset;
440  uint subtile_image_size;
441 
442  subtile_image_size = uint(FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_SIZE);
443  tile_offset = (v.master_tile_texel_coord - floor(v.master_tile_texel_coord)) * float(subtile_image_size);
444 
445  return_value.unnormalized_texcoord_xy = tile_offset //offset into tile
446  + vec2(v.tile_id.xy) * float(FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_SIZE); //location of tile
447 
448  return_value.max_delta_within_tile =
449  vec2(float(FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_SIZE - 1u)) - tile_offset;
450 
451  return_value.layer = v.index_layer;
452 }
453 ///@endcond
454 
455 /*!
456  * Computes the image-atlas coordinate. Only available if \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED
457  * is not defined.
458  * \param master_tile_texel_coord unnormalized texel coordinate of within the master-index tile
459  * \param index_layer what layer from the index-atlas the master tile is located at
460  * \param num_levels number of index levels needed to reach the color-tile
461  * \param return_value location to which to write values
462  */
463 void
464 fastuidraw_compute_image_atlas_coord(in vec2 master_tile_texel_coord,
465  in uint index_layer,
466  in uint num_levels,
468 {
469  fastuidraw_compute_image_atlas_coord_helper_type v;
470 
471  fastuidraw_compute_image_atlas_coord_helper_init(master_tile_texel_coord, index_layer, v);
472  for(uint i = 1u; i < num_levels; ++i)
473  {
474  fastuidraw_compute_image_atlas_coord_helper_iterate(v);
475  }
476  fastuidraw_compute_image_atlas_coord_helper_fini(v, return_value);
477 }
478 
479 /*!
480  * Computes the image-atlas coordinate. Only available if \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED
481  * is not defined.
482  * \param image_texel_coordinate image texel coordinate relative to the sub-image described by image_info
483  * \param image_info information of the image
484  * \param return_value location to which to write values
485  */
486 void
487 fastuidraw_compute_image_atlas_coord(in vec2 image_texel_coordinate,
490 {
491  vec2 master_tile_texel_coord;
492 
493  master_tile_texel_coord = fastuidraw_compute_master_index_tile_coordinate(image_texel_coordinate, image_info);
494  fastuidraw_compute_image_atlas_coord(master_tile_texel_coord,
495  image_info.master_index_tile_layer,
496  image_info.base.num_levels,
497  return_value);
498 }
499 
500 ///@cond
501 void
502 fastuidraw_atlas_image_gather(in int lod_i,
503  in float lod_factor,
504  in float inverse_lod_factor,
505  in vec2 master_tile_texel_coord,
506  in uint index_layer,
507  in fastuidraw_image_info_type image_info,
509 {
510  /* Sighs, we need to do the bilinear filter ourselves because
511  * atleas one of the neighboring texels is in a different tile.
512  */
513  ivec3 t00, t10, t01, t11;
514  float next_pixel_delta, half_next_pixel_delta;
515  vec2 delta;
516 
517  next_pixel_delta = lod_factor * image_info.image_texel_size_on_master_index_tile;
518  half_next_pixel_delta = 0.5 * next_pixel_delta;
519 
520  /* we want the texel that is half a pixel to the left/down
521  * of the input location.
522  */
523  delta = -vec2(half_next_pixel_delta);
524  fastuidraw_compute_image_atlas_coord(master_tile_texel_coord + delta,
525  index_layer,
526  image_info.num_levels,
527  output_value.atlas_location_t00);
528 
529  t00 = ivec3(output_value.atlas_location_t00.unnormalized_texcoord_xy * inverse_lod_factor,
530  output_value.atlas_location_t00.layer);
531  if (output_value.atlas_location_t00.max_delta_within_tile.x >= lod_factor)
532  {
533  t10.yz = t00.yz;
534  t10.x = t00.x + 1;
535  }
536  else
537  {
539  vec2 delta_nxt;
540  vec2 master_tile_texel_coord_nxt;
541 
542  delta_nxt = vec2(half_next_pixel_delta, -half_next_pixel_delta);
543  master_tile_texel_coord_nxt = master_tile_texel_coord + delta_nxt;
544  fastuidraw_compute_image_atlas_coord(master_tile_texel_coord_nxt, index_layer,
545  image_info.num_levels, atlas_location_t10);
546  t10 = ivec3(atlas_location_t10.unnormalized_texcoord_xy * inverse_lod_factor,
547  atlas_location_t10.layer);
548  }
549 
550  if (output_value.atlas_location_t00.max_delta_within_tile.y >= lod_factor)
551  {
552  t01.xz = t00.xz;
553  t01.y = t00.y + 1;
554 
555  t11.xz = t10.xz;
556  t11.y = t10.y + 1;
557  }
558  else
559  {
561  vec2 delta_nxt;
562  vec2 master_tile_texel_coord_nxt;
563 
564  delta_nxt = vec2(-half_next_pixel_delta, half_next_pixel_delta);
565  master_tile_texel_coord_nxt = master_tile_texel_coord + delta_nxt;
566 
567  fastuidraw_compute_image_atlas_coord(master_tile_texel_coord_nxt,
568  index_layer, image_info.num_levels,
569  atlas_location_t01);
570  t01 = ivec3(atlas_location_t01.unnormalized_texcoord_xy * inverse_lod_factor,
571  atlas_location_t01.layer);
572 
573  if (output_value.atlas_location_t00.max_delta_within_tile.x >= lod_factor)
574  {
575  t11.x = t01.x + 1;
576  t11.yz = t01.yz;
577  }
578  else
579  {
581  vec2 delta_nxt;
582  vec2 master_tile_texel_coord_nxt;
583 
584  delta_nxt = vec2(half_next_pixel_delta);
585  master_tile_texel_coord_nxt = master_tile_texel_coord + delta_nxt;
586 
587  fastuidraw_compute_image_atlas_coord(master_tile_texel_coord_nxt,
588  index_layer, image_info.num_levels,
589  atlas_location_t11);
590  t11 = ivec3(atlas_location_t11.unnormalized_texcoord_xy * inverse_lod_factor,
591  atlas_location_t11.layer);
592  }
593  }
594 
595  output_value.c00 = texelFetch(fastuidraw_imageAtlasLinear, t00, lod_i);
596  output_value.c01 = texelFetch(fastuidraw_imageAtlasLinear, t01, lod_i);
597  output_value.c10 = texelFetch(fastuidraw_imageAtlasLinear, t10, lod_i);
598  output_value.c11 = texelFetch(fastuidraw_imageAtlasLinear, t11, lod_i);
599 }
600 ///@endcond
601 
602 /*!
603  * Perform nearest filtering sampling on a sub-image
604  * \param image_texel_coordinate image texel coordinate relative to the sub-image described by image_info
605  * \param image_info information of the image
606  * \param lod mipmap-lod (i.e. same value as one would feed textureLod)
607  */
608 vec4
609 fastuidraw_nearest_filter_atlas_image(in vec2 image_texel_coordinate,
611  in float lod)
612 {
614 
615  image_texel_coordinate = fastuidraw_image_coordinate_clamp_for_nearest_filtering(image_texel_coordinate, image_info);
616  fastuidraw_compute_image_atlas_coord(image_texel_coordinate, image_info, atlas_location);
617 
618  return textureLod(fastuidraw_imageAtlasNearest,
619  vec3(atlas_location.unnormalized_texcoord_xy * fastuidraw_imageAtlasLinear_size_reciprocal,
620  atlas_location.layer),
621  lod);
622 }
623 
624 /*!
625  * Perform linear filtering sampling on a sub-image. Only available if
626  * \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is not defined.
627  * \param master_tile_texel_coord unnormalized texel coordinate of within the master-index tile
628  * \param index_layer what layer from the index-atlas the master tile is located at
629  * \param image_info information of image
630  * \param lod_i which mipmap level to take (level = 0 is the base image)
631  * \param lod_factor the value of pow2(lod_i)
632  */
633 vec4
634 fastuidraw_linear_filter_atlas_image(in vec2 master_tile_texel_coord,
635  in uint index_layer,
636  in fastuidraw_image_info_type image_info,
637  in int lod_i,
638  in float lod_factor)
639 {
640  vec4 image_color;
641  vec2 image_coordinate, min_tile_dist, max_tile_dist;
642  float slack_requirement;
643 
644  /* In exact artithmatic the texel image coordinate
645  * needs to be half a texel away from the boundary
646  * in each dimension to let the sampler perform the
647  * bilinear filtering. Because of round-off error
648  * we will play it safe and require an entire texel.
649  */
650  slack_requirement = lod_factor;
651 
652  /* store the image coordinate relative to the root fastuidraw::Image */
653  image_coordinate =
654  fastuidraw_compute_root_image_coordinate(master_tile_texel_coord, image_info);
655 
656  /* compute the tile range so that we can decide whether or not
657  * to use the sampler for linear filtering.
658  */
659  fastuidraw_image_atlas_compute_tile_range(image_coordinate, min_tile_dist, max_tile_dist);
660 
661  if (max_tile_dist.x >= slack_requirement
662  && max_tile_dist.y >= slack_requirement
663  && min_tile_dist.x <= -slack_requirement
664  && min_tile_dist.y <= -slack_requirement)
665  {
667 
668  fastuidraw_compute_image_atlas_coord(master_tile_texel_coord,
669  index_layer, image_info.num_levels,
670  atlas_location);
671 
672  image_color = textureLod(fastuidraw_imageAtlasLinear,
673  vec3(atlas_location.unnormalized_texcoord_xy * fastuidraw_imageAtlasLinear_size_reciprocal,
674  atlas_location.layer),
675  float(lod_i));
676  }
677  else
678  {
680  float inverse_lod_factor = 1.0f / lod_factor;
681 
682  /* Sighs, we need to do the bilinear filter ourselves because
683  * atleas one of the neighboring texels is in a different tile.
684  */
685  fastuidraw_atlas_image_gather(lod_i, lod_factor, inverse_lod_factor,
686  master_tile_texel_coord,
687  index_layer, image_info,
688  gather);
689 
690  vec4 c0, c1;
691 
692  c0 = mix(gather.c00, gather.c01, fract(inverse_lod_factor * gather.atlas_location_t00.unnormalized_texcoord_xy.y));
693  c1 = mix(gather.c10, gather.c11, fract(inverse_lod_factor * gather.atlas_location_t00.unnormalized_texcoord_xy.y));
694 
695  image_color = mix(c0, c1, fract(inverse_lod_factor * gather.atlas_location_t00.unnormalized_texcoord_xy.x));
696  }
697  return image_color;
698 }
699 
700 /*!
701  * Perform linear filtering sampling on a sub-image. Only available if
702  * \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is not defined.
703  * \param image_coordinate texel coordinate relative to the sub-image specified
704  * by image_info
705  * \param image_info describes the fastuidraw::Image and the sub-image within it
706  * to sample
707  * \param lod_i which mipmap level to take (level = 0 is the base image)
708  */
709 vec4
712  in int lod_i)
713 {
714  vec2 master_tile_texel_coord;
715  float lod_factor;
716 
717  lod_factor = float(1 << lod_i);
718 
719  /* clamp the image_coordinate to within the sub-image. */
720  image_coordinate =
722  image_info, lod_factor);
723 
724  /* get the master index tile coordinate */
725  master_tile_texel_coord =
726  fastuidraw_compute_master_index_tile_coordinate(image_coordinate, image_info);
727 
728  return fastuidraw_linear_filter_atlas_image(master_tile_texel_coord,
729  image_info.master_index_tile_layer,
730  image_info.base,
731  lod_i, lod_factor);
732 }
733 
734 /*!
735  * Perform cubic filtering sampling on a sub-image. Only available if
736  * \ref FASTUIDRAW_IMAGE_ATLAS_DISABLED is not defined.
737  * \param image_coordinate texel coordinate relative to the sub-image specified
738  * by image_info
739  * \param image_info describes the fastuidraw::Image and the sub-image within it
740  * to sample
741  */
742 vec4
745 {
746  vec4 image_color;
747  vec2 master_tile_texel_coord;
748  vec2 fract_image_coordinate;
749  vec2 min_tile_dist, max_tile_dist, linear_weight;
750  vec4 x_weights, y_weights, weight_sums, recip_weight_sums;
751  vec4 t00, t10, t01, t11;
752  uint index_layer;
753 
754  index_layer = image_info.master_index_tile_layer;
755 
756  image_coordinate =
757  fastuidraw_image_coordinate_clamp_for_cubic_filtering(image_coordinate, image_info);
758 
759  master_tile_texel_coord =
760  fastuidraw_compute_master_index_tile_coordinate(image_coordinate, image_info);
761 
762  /* slide the input coordinate by 0.5 image texels to the left/bottom */
763  master_tile_texel_coord -= vec2(0.5 * image_info.base.image_texel_size_on_master_index_tile);
764 
765  /* now store the image coordinate relative to the root fastuidraw::Image */
766  image_coordinate = fastuidraw_compute_image_coordinate(master_tile_texel_coord, image_info);
767 
768  /* compute the tile range so that we can decide whether or not
769  * to use the sampler directly for linear filtering.
770  */
771  fastuidraw_image_atlas_compute_tile_range(image_coordinate, min_tile_dist, max_tile_dist);
772 
773  fract_image_coordinate = fract(image_coordinate);
774  image_coordinate -= fract_image_coordinate;
775 
776  x_weights = fastuidraw_cubic_weights(fract_image_coordinate.x);
777  y_weights = fastuidraw_cubic_weights(fract_image_coordinate.y);
778  weight_sums = vec4(x_weights.x + x_weights.y, x_weights.z + x_weights.w,
779  y_weights.x + y_weights.y, y_weights.z + y_weights.w);
780  recip_weight_sums = vec4(1.0) / weight_sums;
781 
782  linear_weight.x = weight_sums.y / (weight_sums.x + weight_sums.y);
783  linear_weight.y = weight_sums.w / (weight_sums.z + weight_sums.w);
784 
785  if (min_tile_dist.x <= -1.5
786  && min_tile_dist.y <= -1.5
787  && max_tile_dist.x >= 2.5
788  && max_tile_dist.y >= 2.5)
789  {
791  fastuidraw_compute_image_atlas_coord(master_tile_texel_coord, index_layer,
792  image_info.base.num_levels, atlas_location);
793 
794  /* Cubic filtering by realizing cubic-filtering as repeated
795  * bilinear filtering, see GPU Gems 2, Chapter 20.
796  * Code inspired by StackOverflow (http://stackoverflow.com/questions/13501081/efficient-bicubic-filtering-code-in-glsl)
797  * and from Shiny Pixels (http://vec3.ca/bicubic-filtering-in-fewer-taps/)
798  */
799  vec2 texel_coord;
800  vec4 corner_coords, texture_coords;
801 
802  texel_coord = atlas_location.unnormalized_texcoord_xy;
803  texel_coord -= fract_image_coordinate;
804 
805  corner_coords = texel_coord.xxyy;
806  corner_coords.xz -= vec2(0.5);
807  corner_coords.yw += vec2(1.5);
808 
809  texture_coords = corner_coords + vec4(x_weights.y, x_weights.w, y_weights.y, y_weights.w) * recip_weight_sums;
810  texture_coords *= fastuidraw_imageAtlasLinear_size_reciprocal.xyxy;
811 
812  t00 = textureLod(fastuidraw_imageAtlasLinear, vec3(texture_coords.xz, atlas_location.layer), 0.0);
813  t10 = textureLod(fastuidraw_imageAtlasLinear, vec3(texture_coords.yz, atlas_location.layer), 0.0);
814  t01 = textureLod(fastuidraw_imageAtlasLinear, vec3(texture_coords.xw, atlas_location.layer), 0.0);
815  t11 = textureLod(fastuidraw_imageAtlasLinear, vec3(texture_coords.yw, atlas_location.layer), 0.0);
816  }
817  else
818  {
819  vec2 master_texel_coord;
820  vec4 corner_coords, offset_coords, master_coords;
821 
822  master_texel_coord = master_tile_texel_coord;
823  master_texel_coord -= fract_image_coordinate * vec2(image_info.base.image_texel_size_on_master_index_tile);
824 
825  corner_coords = master_texel_coord.xxyy;
826  corner_coords.xz -= vec2(0.5 * image_info.base.image_texel_size_on_master_index_tile);
827  corner_coords.yw += vec2(1.5 * image_info.base.image_texel_size_on_master_index_tile);
828 
829  offset_coords = vec4(x_weights.y, x_weights.w, y_weights.y, y_weights.w) * recip_weight_sums;
830  offset_coords *= image_info.base.image_texel_size_on_master_index_tile;
831 
832  master_coords = corner_coords + offset_coords;
833  t00 = fastuidraw_linear_filter_atlas_image(master_coords.xz, index_layer, image_info.base, 0, 1.0);
834  t10 = fastuidraw_linear_filter_atlas_image(master_coords.yz, index_layer, image_info.base, 0, 1.0);
835  t01 = fastuidraw_linear_filter_atlas_image(master_coords.xw, index_layer, image_info.base, 0, 1.0);
836  t11 = fastuidraw_linear_filter_atlas_image(master_coords.yw, index_layer, image_info.base, 0, 1.0);
837  }
838 
839  image_color = mix(mix(t00, t10, linear_weight.x),
840  mix(t01, t11, linear_weight.x),
841  linear_weight.y);
842 
843  return image_color;
844 }
845 
846 #endif
847 /*! @} */
uniform sampler2DArray fastuidraw_imageAtlasLinear
vec4 fastuidraw_nearest_filter_atlas_image(in vec2 image_texel_coordinate, in fastuidraw_image_extended_info_type image_info, in float lod)
Structure that holds the 2x2 texel block. Only available if FASTUIDRAW_IMAGE_ATLAS_DISABLED is not de...
#define FASTUIDRAW_IMAGE_ATLAS_COLOR_TILE_SIZE
#define FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_LOG2_SIZE
void fastuidraw_compute_image_atlas_coord(in vec2 master_tile_texel_coord, in uint index_layer, in uint num_levels, out fastuidraw_compute_image_atlas_coord_type return_value)
vec2 fastuidraw_image_coordinate_clamp_for_nearest_filtering(in vec2 image_coordinate, in fastuidraw_image_extended_info_type image_info)
fastuidraw_compute_image_atlas_coord_type atlas_location_t00
vec2 fastuidraw_image_coordinate_clamp_for_linear_filtering(in vec2 image_coordinate, in fastuidraw_image_extended_info_type image_info, float pow2_lod)
vecN< uint32_t, 4 > uvec4
Definition: vecN.hpp:1290
vec4 fastuidraw_linear_filter_atlas_image(in vec2 master_tile_texel_coord, in uint index_layer, in fastuidraw_image_info_type image_info, in int lod_i, in float lod_factor)
vec2 fastuidraw_compute_root_image_coordinate(in vec2 master_tile_tex_coord, in fastuidraw_image_info_type image_info)
vecN< float, 2 > vec2
Definition: vecN.hpp:1231
void fastuidraw_compute_image_info(in uint num_levels, out fastuidraw_image_info_type d)
#define FASTUIDRAW_IMAGE_ATLAS_INDEX_TILE_SIZE
Structure that fully describes a fastuidraw::Image or a sub-image of one. Only available if FASTUIDRA...
void fastuidraw_image_atlas_compute_tile_range(in float root_image_coordinate, out float tile_min_dist, out float tile_max_dist)
Structure that describes the relationship between the master index tile and the color tiles of an ima...
vec2 fastuidraw_image_coordinate_clamp_for_cubic_filtering(in vec2 image_coordinate, in fastuidraw_image_extended_info_type image_info)
vecN< int32_t, 3 > ivec3
Definition: vecN.hpp:1269
Structure to give information about what tile and where within a tile an image texel is located...
uniform sampler2DArray fastuidraw_imageAtlasNearest
vecN< float, 4 > vec4
Definition: vecN.hpp:1239
reference x(void)
Definition: vecN.hpp:435
vec2 fastuidraw_compute_image_coordinate(in vec2 master_tile_tex_coord, in fastuidraw_image_extended_info_type image_info)
uniform usampler2DArray fastuidraw_imageIndexAtlas
vec2 fastuidraw_compute_master_index_tile_coordinate(in vec2 image_coordinate, in fastuidraw_image_extended_info_type image_info)
vecN< float, 3 > vec3
Definition: vecN.hpp:1235
vec4 fastuidraw_cubic_filter_atlas_image(in vec2 image_coordinate, in fastuidraw_image_extended_info_type image_info)