123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- /* clang-format off */
- #[modes]
- mode_load = #define MODE_LOAD
- mode_load_shrink = #define MODE_LOAD_SHRINK
- mode_process = #define MODE_PROCESS
- mode_store = #define MODE_STORE
- mode_store_shrink = #define MODE_STORE_SHRINK
- #[specializations]
- #[vertex]
- layout(location = 0) in vec2 vertex_attrib;
- /* clang-format on */
- uniform ivec2 size;
- uniform int stride;
- uniform int shift;
- uniform ivec2 base_size;
- void main() {
- gl_Position = vec4(vertex_attrib, 1.0, 1.0);
- }
- /* clang-format off */
- #[fragment]
- #define SDF_MAX_LENGTH 16384.0
- #if defined(MODE_LOAD) || defined(MODE_LOAD_SHRINK)
- uniform lowp sampler2D src_pixels;//texunit:0
- #else
- uniform highp isampler2D src_process;//texunit:0
- #endif
- uniform ivec2 size;
- uniform int stride;
- uniform int shift;
- uniform ivec2 base_size;
- #if defined(MODE_LOAD) || defined(MODE_LOAD_SHRINK) || defined(MODE_PROCESS)
- layout(location = 0) out ivec4 distance_field;
- #else
- layout(location = 0) out vec4 distance_field;
- #endif
- vec4 float_to_vec4(float p_float) {
- highp vec4 comp = fract(p_float * vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0));
- comp -= comp.xxyz * vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);
- return comp;
- }
- void main() {
- ivec2 pos = ivec2(gl_FragCoord.xy);
- #ifdef MODE_LOAD
- bool solid = texelFetch(src_pixels, pos, 0).r > 0.5;
- distance_field = solid ? ivec4(ivec2(-32767), 0, 0) : ivec4(ivec2(32767), 0, 0);
- #endif
- #ifdef MODE_LOAD_SHRINK
- int s = 1 << shift;
- ivec2 base = pos << shift;
- ivec2 center = base + ivec2(shift);
- ivec2 rel = ivec2(32767);
- float d = 1e20;
- int found = 0;
- int solid_found = 0;
- for (int i = 0; i < s; i++) {
- for (int j = 0; j < s; j++) {
- ivec2 src_pos = base + ivec2(i, j);
- if (any(greaterThanEqual(src_pos, base_size))) {
- continue;
- }
- bool solid = texelFetch(src_pixels, src_pos, 0).r > 0.5;
- if (solid) {
- float dist = length(vec2(src_pos - center));
- if (dist < d) {
- d = dist;
- rel = src_pos;
- }
- solid_found++;
- }
- found++;
- }
- }
- if (solid_found == found) {
- //mark solid only if all are solid
- rel = ivec2(-32767);
- }
- distance_field = ivec4(rel, 0, 0);
- #endif
- #ifdef MODE_PROCESS
- ivec2 base = pos << shift;
- ivec2 center = base + ivec2(shift);
- ivec2 rel = texelFetch(src_process, pos, 0).xy;
- bool solid = rel.x < 0;
- if (solid) {
- rel = -rel - ivec2(1);
- }
- if (center != rel) {
- //only process if it does not point to itself
- const int ofs_table_size = 8;
- const ivec2 ofs_table[ofs_table_size] = ivec2[](
- ivec2(-1, -1),
- ivec2(0, -1),
- ivec2(+1, -1),
- ivec2(-1, 0),
- ivec2(+1, 0),
- ivec2(-1, +1),
- ivec2(0, +1),
- ivec2(+1, +1));
- float dist = length(vec2(rel - center));
- for (int i = 0; i < ofs_table_size; i++) {
- ivec2 src_pos = pos + ofs_table[i] * stride;
- if (any(lessThan(src_pos, ivec2(0))) || any(greaterThanEqual(src_pos, size))) {
- continue;
- }
- ivec2 src_rel = texelFetch(src_process, src_pos, 0).xy;
- bool src_solid = src_rel.x < 0;
- if (src_solid) {
- src_rel = -src_rel - ivec2(1);
- }
- if (src_solid != solid) {
- src_rel = ivec2(src_pos << shift); //point to itself if of different type
- }
- float src_dist = length(vec2(src_rel - center));
- if (src_dist < dist) {
- dist = src_dist;
- rel = src_rel;
- }
- }
- }
- if (solid) {
- rel = -rel - ivec2(1);
- }
- distance_field = ivec4(rel, 0, 0);
- #endif
- #ifdef MODE_STORE
- ivec2 rel = texelFetch(src_process, pos, 0).xy;
- bool solid = rel.x < 0;
- if (solid) {
- rel = -rel - ivec2(1);
- }
- float d = length(vec2(rel - pos));
- if (solid) {
- d = -d;
- }
- d /= SDF_MAX_LENGTH;
- d = clamp(d, -1.0, 1.0);
- distance_field = float_to_vec4(d*0.5+0.5);
- #endif
- #ifdef MODE_STORE_SHRINK
- ivec2 base = pos << shift;
- ivec2 center = base + ivec2(shift);
- ivec2 rel = texelFetch(src_process, pos, 0).xy;
- bool solid = rel.x < 0;
- if (solid) {
- rel = -rel - ivec2(1);
- }
- float d = length(vec2(rel - center));
- if (solid) {
- d = -d;
- }
- d /= SDF_MAX_LENGTH;
- d = clamp(d, -1.0, 1.0);
- distance_field = float_to_vec4(d*0.5+0.5);
- #endif
- }
|