{"id":345044,"date":"2023-02-06T21:02:04","date_gmt":"2023-02-06T21:02:04","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=345044"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=345044","title":{"rendered":"<span>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0432\u043e Flutter. \u0427\u0430\u0441\u0442\u044c 2<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><em>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041d\u0430 \u0441\u0432\u044f\u0437\u0438<\/em> <em>\u042e\u0440\u0438\u0439 \u041f\u0435\u0442\u0440\u043e\u0432, Flutter Team Lead \u0432 <\/em><a href=\"https:\/\/friflex.com\/?utm_source=habr_article&amp;utm_medium=link_main_rus_30012023&amp;utm_campaign=Ispolzovanie_shejderov_vo_Flutter_CHast_1\"><em>Friflex<\/em><\/a><em>. \u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043b\u0438\u0441\u044c \u0441 \u0440\u0430\u0431\u043e\u0442\u043e\u0439 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0432\u043e Flutter, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438, \u043a\u0430\u043a \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 GLSL.<\/em> <em>\u0412<\/em> <em>\u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u043a\u0430\u043a \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0448\u0435\u0439\u0434\u0435\u0440\u044b \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u043c\u0438 \u0438\u0437 Flutter.<\/em><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/598\/db4\/6fa\/598db46fad7ab2466060c71dae95e1dd.gif\" width=\"2262\" height=\"1268\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/598\/db4\/6fa\/598db46fad7ab2466060c71dae95e1dd.gif\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435:<\/strong><\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/company\/friflex\/blog\/713298\/\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0432\u043e Flutter. \u0427\u0430\u0441\u0442\u044c 1<\/a><\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0432\u043e Flutter. \u0427\u0430\u0441\u0442\u044c 2<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438, \u0432\u044b \u0435\u0449\u0435 \u043d\u0435 \u0447\u0438\u0442\u0430\u043b\u0438 \u043f\u0435\u0440\u0432\u0443\u044e <a href=\"https:\/\/habr.com\/ru\/company\/friflex\/blog\/713298\/\">\u0447\u0430\u0441\u0442\u044c<\/a>, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043d\u0435\u0439, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438. <\/p>\n<p>\u0428\u0435\u0439\u0434\u0435\u0440\u044b \u2014 \u044d\u0442\u043e \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 GLSL. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u0433\u0434\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0434\u0435\u043b\u044f\u0442\u0441\u044f \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u043c\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u0430\u043c\u0438. \u041e\u0434\u0438\u043d \u0438\u0437 \u043d\u0438\u0445  \u2014<a href=\"https:\/\/glslsandbox.com\/\"><u>https:\/\/glslsandbox.com\/<\/u><\/a>. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u044f\u043c\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u043a\u043e\u0434 \u0448\u0435\u0439\u0434\u0435\u0440\u0430. \u042d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u0430. \u0412 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430 \u044d\u0442\u043e\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u0435 \u0435\u0441\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u043c\u043e\u0434\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430. \u041d\u043e \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 <a href=\"https:\/\/glslsandbox.com\/e#94097.0\">https:\/\/glslsandbox.com\/e#94097.0<\/a> \u2014  \u043f\u043e\u043b\u0435\u0442 \u0432 \u043e\u0431\u043b\u0430\u043a\u0430\u0445.<\/p>\n<details class=\"spoiler\">\n<summary>\u0428\u0435\u0439\u0434\u0435\u0440 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 \u0441\u0430\u0439\u0442\u0435  https:\/\/glslsandbox.com\/<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d08\/357\/598\/d08357598585f9d7fa08927033067ebe.png\" width=\"2467\" height=\"1192\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d08\/357\/598\/d08357598585f9d7fa08927033067ebe.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043d\u043e\u043f\u043a\u0438 Show\/Hide Code \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\/\u0441\u043a\u0440\u044b\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d.<\/p>\n<\/div>\n<\/details>\n<p>\u0415\u0441\u043b\u0438 \u0442\u0430\u043a\u0443\u044e \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 Flutter, \u0442\u043e \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430. \u0410 \u0432\u043e\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u043d\u0430 GLSL \u043d\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0442\u0440\u0443\u0434\u0430. \u0415\u0441\u043b\u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u043d\u0430 GLSL.<\/p>\n<h2>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0448\u0435\u0439\u0434\u0435\u0440\u0430<\/h2>\n<p>\u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \u0438 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043d\u0430\u0448 \u0440\u0430\u043d\u0435\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b shader.glsl.<\/p>\n<details class=\"spoiler\">\n<summary>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0448\u0435\u0439\u0434\u0435\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">#extension GL_OES_standard_derivatives : enable  precision highp float;  uniform float time; uniform vec2 mouse; uniform vec2 resolution;  #define iTime time #define iMouse mouse #define iResolution resolution  \/\/ referred https:\/\/www.shadertoy.com\/view\/4sXGRM  vec3 skytop = vec3(0.05, 0.2, 0.5);  vec3 light = normalize(vec3(0.1, 0.25, 0.9));  vec2 cloudrange = vec2(0.0, 10000.0);  mat3 m = mat3(0.00, 1.60, 1.20, -1.60, 0.72, -0.96, -1.20, -0.96, 1.28);  \/\/ hash function               float hash(float n) {     return fract(cos(n) * 114514.1919); }  \/\/ 3d noise function float noise(in vec3 x) {     vec3 p = floor(x);     vec3 f = smoothstep(0.0, 1.0, fract(x));              float n = p.x + p.y * 10.0 + p.z * 100.0;          return mix(         mix(mix(hash(n + 0.0), hash(n + 1.0), f.x),             mix(hash(n + 10.0), hash(n + 11.0), f.x), f.y),         mix(mix(hash(n + 100.0), hash(n + 101.0), f.x),             mix(hash(n + 110.0), hash(n + 111.0), f.x), f.y), f.z); }  \/\/ Fractional Brownian motion float fbm(vec3 p) {     float f = 0.5000 * noise(p);     p = m * p;     f += 0.2500 * noise(p);     p = m * p;     f += 0.1666 * noise(p);     p = m * p;     f += 0.0834 * noise(p);     return f; }  vec3 camera(float time) {     return vec3(5000.0 * sin(1.0 * time), 5000. + 1500. * sin(0.5 * time), 6000.0 * time); }  void mainImage(out vec4 fragColor, in vec2 fragCoord) {     vec2 uv = 2. * fragCoord.xy \/ iResolution.xy - 1.0;     uv.x *= iResolution.x \/ iResolution.y;      float time = (iTime + 13.5 + 44.) * 1.0;     vec3 campos = camera(time);     vec3 camtar = camera(time + 0.4);      vec3 front = normalize(camtar - campos);     vec3 right = normalize(cross(front, vec3(0.0, 1.0, 0.0)));     vec3 up = normalize(cross(right, front));     vec3 fragAt = normalize(uv.x * right + uv.y * up + front);          \/\/ clouds     vec4 sum = vec4(0, 0, 0, 0);     for (float depth = 0.0; depth &lt; 100000.0; depth += 200.0)     {         vec3 ray = campos + fragAt * depth;         if (cloudrange.x &lt; ray.y &amp;&amp; ray.y &lt; cloudrange.y)         {             float alpha = smoothstep(0.5, 1.0, fbm(ray * 0.00025));             vec3 localcolor = mix(vec3(1.1, 1.05, 1.0), vec3(0.3, 0.3, 0.2), alpha);             alpha = (1.0 - sum.a) * alpha;             sum += vec4(localcolor * alpha, alpha);         }     }          float alpha = smoothstep(0.7, 1.0, sum.a);     sum.rgb \/= sum.a + 0.0001;      float sundot = clamp(dot(fragAt, light), 0.0, 1.0);     vec3 col = 0.8 * (skytop);     col += 0.47 * vec3(1.6, 1.4, 1.0) * pow(sundot, 350.0);     col += 0.4 * vec3(0.8, 0.9, 1.0) * pow(sundot, 2.0);          sum.rgb -= 0.6 * vec3(0.8, 0.75, 0.7) * pow(sundot, 13.0) * alpha;          sum.rgb += 0.2 * vec3(1.3, 1.2, 1.0) * pow(sundot, 5.0) * (1.0 - alpha);      col = mix(col, sum.rgb, sum.a);      fragColor = vec4(col, 1.0); }  void main( void ) { mainImage(gl_FragColor,gl_FragCoord.xy); }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0430\u0434\u0430\u043f\u0442\u0430\u0446\u0438\u044e \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 Flutter. \u041f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u0430, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043e\u0448\u0438\u0431\u043a\u0443 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430. <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/69d\/e6b\/e34\/69de6be3489d4f3e33414d13065d88d8.png\" alt=\" \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 GLSL \u0432 SPIRV \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430.\" title=\" \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 GLSL \u0432 SPIRV \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430.\" width=\"1704\" height=\"127\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/69d\/e6b\/e34\/69de6be3489d4f3e33414d13065d88d8.png\"\/><figcaption> \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 GLSL \u0432 SPIRV \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430.<\/figcaption><\/figure>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0439 \u0441 \u043a\u043e\u0434\u043e\u043c.<\/p>\n<ul>\n<li>\n<p>\u0412 \u0441\u0442\u0440\u043e\u043a\u0435 62 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 \u0432 \u0448\u0435\u0439\u0434\u0435\u0440:<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0437\u043c\u0435\u043d\u044f\u0435\u043c:<\/p>\n<pre><code class=\"cpp\">void mainImage(out vec4 fragColor, in vec2 fragCoord)<\/code><\/pre>\n<p>\u043d\u0430:<\/p>\n<pre><code class=\"cpp\">void main()<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u044b \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e mainImage() \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u0438\u0437 \u043d\u0435\u0435 \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 \u0432 \u0448\u0435\u0439\u0434\u0435\u0440.<\/p>\n<ul>\n<li>\n<p>\u0412 \u0441\u0442\u0440\u043e\u043a\u0435 64, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 <strong>fragCoord,<\/strong> \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c<strong> gl_FragCoord.<\/strong><\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u0435\u043d\u044f\u0435\u043c:<\/p>\n<pre><code class=\"cpp\"> vec2 uv = 2. * fragCoord.xy \/ iResolution.xy - 1.0;<\/code><\/pre>\n<p>\u043d\u0430:<\/p>\n<pre><code class=\"cpp\">vec2 uv = 2. * gl_FragCoord.xy \/ iResolution.xy - 1.0;<\/code><\/pre>\n<ul>\n<li>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0443\u0436\u0435 \u043e\u0431\u044a\u044f\u0432\u0438\u043b\u0438 \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 \u0432 \u0448\u0435\u0439\u0434\u0435\u0440, \u0442\u043e \u0432\u0435\u0441\u044c \u043a\u043e\u0434, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0438 107, \u043d\u0443\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cpp\">void main( void ) { mainImage(gl_FragColor,gl_FragCoord.xy); }<\/code><\/pre>\n<ul>\n<li>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u044b\u0445\u043e\u0434\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442, \u043a\u0430\u043a \u0432\u0435\u043a\u0442\u043e\u0440 \u0438\u0437 \u0447\u0435\u0442\u044b\u0440\u0435\u0445 \u0447\u0438\u0441\u0435\u043b + \u0430\u043b\u044c\u0444\u0430 \u043a\u0430\u043d\u0430\u043b. \u042d\u0442\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043a\u0430\u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \u0432\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a Flutter.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cpp\">out vec4 fragColor;<\/code><\/pre>\n<ul>\n<li>\n<p>\u0423\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c \u0433\u043b\u0443\u0431\u0438\u043d\u0443 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u043e\u0431\u043b\u0430\u043a\u043e\u0432 \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 78.<\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u0435\u043d\u044f\u0435\u043c:<\/p>\n<pre><code class=\"cpp\"> for (float depth = 0.0; depth &lt; 100000.0; depth += 200.0)<\/code><\/pre>\n<p>\u043d\u0430:<\/p>\n<pre><code class=\"cpp\"> for (float depth = 0.0; depth &lt; 10000.0; depth += 200.0)<\/code><\/pre>\n<ul>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0448\u0442\u0440\u0438\u0445 \u2014  \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <strong>mouse<\/strong>. \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0448\u0435\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u0443 \u043d\u0430\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434.<\/p>\n<details class=\"spoiler\">\n<summary>\u0410\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0448\u0435\u0439\u0434\u0435\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">#extension GL_OES_standard_derivatives : enable  precision highp float;  uniform float time; uniform vec2 resolution; out vec4 fragColor;  #define iTime time #define iMouse mouse #define iResolution resolution  \/\/ referred https:\/\/www.shadertoy.com\/view\/4sXGRM  vec3 skytop = vec3(0.05, 0.2, 0.5);  vec3 light = normalize(vec3(0.1, 0.25, 0.9));  vec2 cloudrange = vec2(0.0, 10000.0);  mat3 m = mat3(0.00, 1.60, 1.20, -1.60, 0.72, -0.96, -1.20, -0.96, 1.28);  \/\/ hash function float hash(float n) {     return fract(cos(n) * 114514.1919); }  \/\/ 3d noise function float noise(in vec3 x) {     vec3 p = floor(x);     vec3 f = smoothstep(0.0, 1.0, fract(x));      float n = p.x + p.y * 10.0 + p.z * 100.0;      return mix(         mix(mix(hash(n + 0.0), hash(n + 1.0), f.x),             mix(hash(n + 10.0), hash(n + 11.0), f.x), f.y),         mix(mix(hash(n + 100.0), hash(n + 101.0), f.x),             mix(hash(n + 110.0), hash(n + 111.0), f.x), f.y), f.z); }  \/\/ Fractional Brownian motion float fbm(vec3 p) {     float f = 0.5000 * noise(p);     p = m * p;     f += 0.2500 * noise(p);     p = m * p;     f += 0.1666 * noise(p);     p = m * p;     f += 0.0834 * noise(p);     return f; }  vec3 camera(float time) {     return vec3(5000.0 * sin(1.0 * time), 5000. + 1500. * sin(0.5 * time), 6000.0 * time); }  void main() {     vec2 uv = 2. * gl_FragCoord.xy \/ iResolution.xy - 1.0;     uv.x *= iResolution.x \/ iResolution.y;      float time = (iTime + 13.5 + 44.) * 1.0;     vec3 campos = camera(time);     vec3 camtar = camera(time + 0.4);      vec3 front = normalize(camtar - campos);     vec3 right = normalize(cross(front, vec3(0.0, 1.0, 0.0)));     vec3 up = normalize(cross(right, front));     vec3 fragAt = normalize(uv.x * right + uv.y * up + front);      \/\/ clouds     vec4 sum = vec4(0, 0, 0, 0);      for (float depth = 0.0; depth &lt; 10000.0; depth += 200.0)     {         vec3 ray = campos + fragAt * depth;         if (cloudrange.x &lt; ray.y &amp;&amp; ray.y &lt; cloudrange.y)         {             float alpha = smoothstep(0.5, 1.0, fbm(ray * 0.00025));             vec3 localcolor = mix(vec3(1.1, 1.05, 1.0), vec3(0.3, 0.3, 0.2), alpha);             alpha = (1.0 - sum.a) * alpha;             sum += vec4(localcolor * alpha, alpha);         }     }      float alpha = smoothstep(0.7, 1.0, sum.a);     sum.rgb \/= sum.a + 0.0001;      float sundot = clamp(dot(fragAt, light), 0.0, 1.0);     vec3 col = 0.8 * (skytop);     col += 0.47 * vec3(1.6, 1.4, 1.0) * pow(sundot, 350.0);     col += 0.4 * vec3(0.8, 0.9, 1.0) * pow(sundot, 2.0);      sum.rgb -= 0.6 * vec3(0.8, 0.75, 0.7) * pow(sundot, 13.0) * alpha;      sum.rgb += 0.2 * vec3(1.3, 1.2, 1.0) * pow(sundot, 5.0) * (1.0 - alpha);      col = mix(col, sum.rgb, sum.a);      fragColor = vec4(col, 1.0); } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u043b\u044e\u0431\u0443\u0435\u043c\u0441\u044f \u043f\u043e\u043b\u0435\u0442\u043e\u043c \u0432 \u043e\u0431\u043b\u0430\u043a\u0430\u0445 \u043d\u0430 \u0432\u0430\u0448\u0435\u043c \u0441\u043c\u0430\u0440\u0442\u0444\u043e\u043d\u0435. \u0410 \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0448\u0435\u0439\u0434\u0435\u0440\u0430\u043c\u0438 \u0438\u0437 Flutter?<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0448\u0435\u0439\u0434\u0435\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/63dfc6a7a9cdfde042310d45\" data-style=\"\" id=\"63dfc6a7a9cdfde042310d45\" width=\"\"><\/div>\n<\/p>\n<\/div>\n<\/details>\n<h3>\u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u043c \u0438\u0437 Flutter<\/h3>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u043c, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<ul>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043a\u043b\u0430\u0441\u0441 <strong>_MyAppState<\/strong> \u0434\u0432\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0438\u0445 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u0448\u0435\u0439\u0434\u0435\u0440.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"dart\">  var _move = 0.0;   var _stop = 0.0;<\/code><\/pre>\n<ul>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0434\u0432\u0435 \u043a\u043d\u043e\u043f\u043a\u0438. \u041e\u0434\u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0435\u0442\u0430, \u0430 \u0434\u0440\u0443\u0433\u0430\u044f \u2014  \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0448\u0435\u0439\u0434\u0435\u0440\u0430. \u041d\u043e, \u043f\u043e \u0441\u0443\u0442\u0438, \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043c\u0435\u043d\u044f\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 <strong>_move<\/strong> \u0438 <strong>_stop<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0434\u0432\u0435 \u043a\u043d\u043e\u043f\u043a\u0438 \u0432 \u043c\u0435\u0442\u043e\u0434 build<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"dart\">         return Stack(                 children: [                   CustomPaint(painter: AnimRect(shader)),                   Align(                     alignment: Alignment.bottomLeft,                     child: FloatingActionButton(                       onPressed: () {                         if (_move == 1) {                           _move = 0.0;                         } else {                           _move = 1;                         }                         setState(() {});                       },                     ),                   ),                   Align(                     alignment: Alignment.bottomRight,                     child: FloatingActionButton(                       onPressed: () {                         if (_stop == 1) {                           _stop = 0.0;                         } else {                           _stop = 1;                         }                         setState(() {});                       },                     ),                   ),                 ],               );<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<ul>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0432 \u0448\u0435\u0439\u0434\u0435\u0440 \u044d\u0442\u0438 \u0434\u0432\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430.<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u0435\u0440\u0435\u0434\u0430\u0435\u043c _move  \u0438 _stop  \u0432 \u0448\u0435\u0439\u0434\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"dart\">... body: FutureBuilder&lt;FragmentProgram>(           future: _initShader(),           builder: (context, snapshot) {             if (snapshot.hasData) {               final shader = snapshot.data!.fragmentShader()                 ..setFloat(0, updateTime)                 ..setFloat(1, 300)                 ..setFloat(2, 300)                 ..setFloat(3, _move)                 ..setFloat(4, _stop);               return Stack(                 children: [ ...<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u0444\u0430\u0439\u043b main \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<details class=\"spoiler\">\n<summary>main.dart<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"dart\">import 'dart:ui';  import 'package:flutter\/material.dart';  void main() {   runApp(const MyApp()); }  class MyApp extends StatefulWidget {   const MyApp({Key? key}) : super(key: key);    @override   State&lt;MyApp> createState() => _MyAppState(); }  class _MyAppState extends State&lt;MyApp> with TickerProviderStateMixin {   var updateTime = 0.0;   var _move = 0.0;   var _stop = 0.0;    @override   void initState() {     super.initState();     createTicker((elapsed) {       updateTime = elapsed.inMilliseconds \/ 1000;       setState(() {});     }).start();   }    @override   Widget build(BuildContext context) {     return MaterialApp(       home: Scaffold(         backgroundColor: Colors.black,         body: FutureBuilder&lt;FragmentProgram>(           future: _initShader(),           builder: (context, snapshot) {             if (snapshot.hasData) {               final shader = snapshot.data!.fragmentShader()                 ..setFloat(0, updateTime)                 ..setFloat(1, 300)                 ..setFloat(2, 300)                 ..setFloat(3, _move)                 ..setFloat(4, _stop);               return Stack(                 children: [                   CustomPaint(painter: _MySweepPainter(shader)),                   Align(                     alignment: Alignment.bottomLeft,                     child: FloatingActionButton(                       onPressed: () {                         if (_move == 1) {                           _move = 0.0;                         } else {                           _move = 1;                         }                         setState(() {});                       },                     ),                   ),                   Align(                     alignment: Alignment.bottomRight,                     child: FloatingActionButton(                       onPressed: () {                         if (_stop == 1) {                           _stop = 0.0;                         } else {                           _stop = 1;                         }                         setState(() {});                       },                     ),                   ),                 ],               );             } else {               return const Center(                 child: CircularProgressIndicator(),               );             }           },         ),       ),     );   }    Future&lt;FragmentProgram> _initShader() {     return FragmentProgram.fromAsset(\"shader.glsl\");   } }  class _MySweepPainter extends CustomPainter {   _MySweepPainter(this.shader);    final Shader shader;    @override   void paint(Canvas canvas, Size size) {     const Rect rect = Rect.largest;     final Paint paint = Paint()..shader = shader;     canvas.drawRect(rect, paint);   }    @override   bool shouldRepaint(CustomPainter oldDelegate) => true; } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0448\u0435\u0439\u0434\u0435\u0440\u0430 <strong>shader.glsl.<\/strong> <\/p>\n<ul>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0434\u0432\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 <strong>iMovie<\/strong> \u0438 <strong>iStop<\/strong><\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cpp\">uniform float time; uniform vec2 resolution; uniform float iMove; uniform float iStop; out vec4 fragColor;<\/code><\/pre>\n<ul>\n<li>\n<p>\u041d\u0430\u0445\u043e\u0434\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <strong>vec3 camera(float time). <\/strong>\u0414\u0430\u043d\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u0435\u043a\u0442\u043e\u0440 \u0438\u0437 \u0442\u0440\u0435\u0445 \u0447\u0438\u0441\u0435\u043b, \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u0445 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <strong>time. <\/strong>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0443\u0441\u043b\u043e\u0432\u0438\u0435, \u0435\u0441\u043b\u0438 <strong>iMove <\/strong>\u0440\u0430\u0432\u043d\u0430 1, \u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u043c \u0447\u0438\u0441\u043b\u043e\u043c \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u043a\u0430\u043a \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443 \u0435\u0434\u0438\u043d\u0438\u0446\u0443. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043a\u0430\u043c\u0435\u0440\u044b. \u0418 \u043d\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043c\u044b \u043b\u0435\u0442\u0438\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u044f\u043c\u043e.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"dart\">vec3 camera(float time) {     if(iMove == 1){          return vec3(1, 5000. + 1500. * sin(0.5 * time), 6000.0 * time);     }     return vec3(5000.0 * sin(1.0 * time), 5000. + 1500. * sin(0.5 * time), 6000.0 * time); }<\/code><\/pre>\n<ul>\n<li>\n<p>\u0418 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <strong>iStop<\/strong> \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e. \u041d\u0430\u0439\u0434\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <strong>main()<\/strong>, \u0432 \u043d\u0435\u0439 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0435:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cpp\">...     vec3 campos = camera(time);         if(iStop == 1){         campos = camera(1);         } else {         campos = camera(time);         }      vec3 camtar = camera(time + 0.4); ...<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c, \u0435\u0441\u043b\u0438 <strong>iStop<\/strong> \u0440\u0430\u0432\u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0435, \u0442\u043e \u043c\u044b \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <strong>time <\/strong>\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e camera<strong> <\/strong>\u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443. <\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043d\u0430\u0448 \u0448\u0435\u0439\u0434\u0435\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0442\u0430\u043a\u0438\u043c:<\/p>\n<details class=\"spoiler\">\n<summary>shader.glsl<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"dart\">#extension GL_OES_standard_derivatives : enable  precision highp float;  uniform float time; uniform vec2 resolution; uniform float iMove; uniform float iStop; out vec4 fragColor;  #define iTime time #define iMouse mouse #define iResolution resolution  \/\/ referred https:\/\/www.shadertoy.com\/view\/4sXGRM  vec3 skytop = vec3(0.05, 0.2, 0.5);  vec3 light = normalize(vec3(0.1, 0.25, 0.9));  vec2 cloudrange = vec2(0.0, 10000.0);  mat3 m = mat3(0.00, 1.60, 1.20, -1.60, 0.72, -0.96, -1.20, -0.96, 1.28);  \/\/ hash function float hash(float n) {     return fract(cos(n) * 114514.1919); }  \/\/ 3d noise function float noise(in vec3 x) {     vec3 p = floor(x);     vec3 f = smoothstep(0.0, 1.0, fract(x));      float n = p.x + p.y * 10.0 + p.z * 100.0;      return mix(         mix(mix(hash(n + 0.0), hash(n + 1.0), f.x),             mix(hash(n + 10.0), hash(n + 11.0), f.x), f.y),         mix(mix(hash(n + 100.0), hash(n + 101.0), f.x),             mix(hash(n + 110.0), hash(n + 111.0), f.x), f.y), f.z); }  \/\/ Fractional Brownian motion float fbm(vec3 p) {     float f = 0.5000 * noise(p);     p = m * p;     f += 0.2500 * noise(p);     p = m * p;     f += 0.1666 * noise(p);     p = m * p;     f += 0.0834 * noise(p);     return f; }  vec3 camera(float time) {     if(iMove == 1){          return vec3(1, 5000. + 1500. * sin(0.5 * time), 6000.0 * time);     }     return vec3(5000.0 * sin(1.0 * time), 5000. + 1500. * sin(0.5 * time), 6000.0 * time); } void main() {     vec2 uv = 2. * gl_FragCoord.xy \/ iResolution.xy - 1.0;     uv.x *= iResolution.x \/ iResolution.y;      float time = (iTime + 13.5 + 44.) * 1.0;     vec3 campos = camera(time);        if(iStop == 1){         campos = camera(1);     } else {        campos = camera(time);     }      vec3 camtar = camera(time + 0.4);      vec3 front = normalize(camtar - campos);     vec3 right = normalize(cross(front, vec3(0.0, 1.0, 0.0)));     vec3 up = normalize(cross(right, front));     vec3 fragAt = normalize(uv.x * right + uv.y * up + front);      \/\/ clouds     vec4 sum = vec4(0, 0, 0, 0);      for (float depth = 0.0; depth &lt; 10000.0; depth += 200.0)     {         vec3 ray = campos + fragAt * depth;         if (cloudrange.x &lt; ray.y &amp;&amp; ray.y &lt; cloudrange.y)         {             float alpha = smoothstep(0.5, 1.0, fbm(ray * 0.00025));             vec3 localcolor = mix(vec3(1.1, 1.05, 1.0), vec3(0.3, 0.3, 0.2), alpha);             alpha = (1.0 - sum.a) * alpha;             sum += vec4(localcolor * alpha, alpha);         }     }      float alpha = smoothstep(0.7, 1.0, sum.a);     sum.rgb \/= sum.a + 0.0001;      float sundot = clamp(dot(fragAt, light), 0.0, 1.0);     vec3 col = 0.8 * (skytop);     col += 0.47 * vec3(1.6, 1.4, 1.0) * pow(sundot, 350.0);     col += 0.4 * vec3(0.8, 0.9, 1.0) * pow(sundot, 2.0);      sum.rgb -= 0.6 * vec3(0.8, 0.75, 0.7) * pow(sundot, 13.0) * alpha;      sum.rgb += 0.2 * vec3(1.3, 1.2, 1.0) * pow(sundot, 5.0) * (1.0 - alpha);      col = mix(col, sum.rgb, sum.a);      fragColor = vec4(col, 1.0); } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u043c \u0438\u0437 Flutter. <\/p>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/github.com\/petrovyuri\/shaders_tutorial\/tree\/9d3a410e5e86e6b6bf1b9349fb3173261a33cf08\">\u0437\u0434\u0435\u0441\u044c<\/a>.  <\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/summary>\n<div class=\"spoiler__content\">\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/63dfe6f3396453e03445812b\" data-style=\"\" id=\"63dfe6f3396453e03445812b\" width=\"\"><\/div>\n<\/p>\n<\/div>\n<\/details>\n<h2>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c ShaderMask<\/h2>\n<p>\u041c\u043d\u0435 \u0431\u044b \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u043b\u043e\u0436\u0438\u0442\u044c \u0448\u0435\u0439\u0434\u0435\u0440 \u043d\u0430 \u0432\u0438\u0434\u0436\u0435\u0442 Text. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <strong>build<\/strong> \u0432\u0438\u0434\u0436\u0435\u0442\u0430 <strong>MyApp, <\/strong>\u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0441 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u043c ShaderMask.<\/p>\n<details class=\"spoiler\">\n<summary>\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 build()<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"dart\">   @override   Widget build(BuildContext context) {     return MaterialApp(       home: Scaffold(         backgroundColor: Colors.black,         body: FutureBuilder&lt;FragmentProgram>(           future: _initShader(),           builder: (context, snapshot) {             if (snapshot.hasData) {               return ShaderMask(                 shaderCallback: (bounds) {                   return snapshot.data!.fragmentShader()                     ..setFloat(0, updateTime)                     ..setFloat(1, bounds.height)                     ..setFloat(2, bounds.width);                 },                 child: const Center(                     child: Text(                   \"TEST\",                   style: TextStyle(                     fontSize: 150,                     fontWeight: FontWeight.w900,                     color: Colors.white,                   ),                 )),               );             } else {               return const Center(                 child: CircularProgressIndicator(),               );             }           },         ),       ),     );   }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043a\u043e\u0434 \u043f\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e:<\/p>\n<ul>\n<li>\n<p>\u043d\u0430 \u0447\u0435\u0442\u0432\u0435\u0440\u0442\u0443\u044e \u0438 \u043f\u044f\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0438 \u0434\u043b\u044f \u043a\u0440\u0430\u0441\u043e\u0442\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c <strong>MaterialApp<\/strong> \u0438 <strong>Scaffold.<\/strong><\/p>\n<\/li>\n<li>\n<p>\u043d\u0430 \u043e\u0434\u0438\u043d\u043d\u0430\u0434\u0446\u0430\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0432\u0438\u0434\u0436\u0435\u0442 ShaderMask. \u0423 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 <strong>shaderCallback, <\/strong>\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <strong>bounds <\/strong>(\u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 ShaderMask). \u0410 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0438\u0434\u0436\u0435\u0442 Text. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u044b \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c \u0448\u0435\u0439\u0434\u0435\u0440 \u043d\u0430 \u0442\u0435\u043a\u0441\u0442. <\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u043b\u044e\u0431\u0443\u0435\u043c\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u043e\u0439 ShaderMask. <\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0438\u0434\u0436\u0435\u0442\u0430 ShaderMask <\/summary>\n<div class=\"spoiler__content\">\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/63dfca43d791666fa20f8b0a\" data-style=\"\" id=\"63dfca43d791666fa20f8b0a\" width=\"\"><\/div>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0425\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u00a0\u0448\u0435\u0439\u0434\u0435\u0440\u0430\u043c\u0438? \u0416\u0434\u0443 \u0432\u0430\u0448\u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0432\u00a0\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445!  <\/p>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0443\u0440\u043e\u043a\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u043e <a href=\"https:\/\/github.com\/petrovyuri\/shaders_tutorial\/tree\/9db35213e5083e82761c0a528c4183517293e5a8\">\u0441\u0441\u044b\u043b\u043a\u0435<\/a>.  <\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p> <!----> <!----><\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/friflex\/blog\/714956\/\"> https:\/\/habr.com\/ru\/company\/friflex\/blog\/714956\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><em>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041d\u0430 \u0441\u0432\u044f\u0437\u0438<\/em> <em>\u042e\u0440\u0438\u0439 \u041f\u0435\u0442\u0440\u043e\u0432, Flutter Team Lead \u0432 <\/em><a href=\"https:\/\/friflex.com\/?utm_source=habr_article&amp;utm_medium=link_main_rus_30012023&amp;utm_campaign=Ispolzovanie_shejderov_vo_Flutter_CHast_1\"><em>Friflex<\/em><\/a><em>. \u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043b\u0438\u0441\u044c \u0441 \u0440\u0430\u0431\u043e\u0442\u043e\u0439 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0432\u043e Flutter, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438, \u043a\u0430\u043a \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 GLSL.<\/em> <em>\u0412<\/em> <em>\u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u043a\u0430\u043a \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0448\u0435\u0439\u0434\u0435\u0440\u044b \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u043c\u0438 \u0438\u0437 Flutter.<\/em><\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435:<\/strong><\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/company\/friflex\/blog\/713298\/\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0432\u043e Flutter. \u0427\u0430\u0441\u0442\u044c 1<\/a><\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0432\u043e Flutter. \u0427\u0430\u0441\u0442\u044c 2<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438, \u0432\u044b \u0435\u0449\u0435 \u043d\u0435 \u0447\u0438\u0442\u0430\u043b\u0438 \u043f\u0435\u0440\u0432\u0443\u044e <a href=\"https:\/\/habr.com\/ru\/company\/friflex\/blog\/713298\/\">\u0447\u0430\u0441\u0442\u044c<\/a>, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043d\u0435\u0439, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438. <\/p>\n<p>\u0428\u0435\u0439\u0434\u0435\u0440\u044b \u2014 \u044d\u0442\u043e \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 GLSL. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u0433\u0434\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0434\u0435\u043b\u044f\u0442\u0441\u044f \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u043c\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u0430\u043c\u0438. \u041e\u0434\u0438\u043d \u0438\u0437 \u043d\u0438\u0445  \u2014<a href=\"https:\/\/glslsandbox.com\/\"><u>https:\/\/glslsandbox.com\/<\/u><\/a>. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u044f\u043c\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u043a\u043e\u0434 \u0448\u0435\u0439\u0434\u0435\u0440\u0430. \u042d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u0430. \u0412 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430 \u044d\u0442\u043e\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u0435 \u0435\u0441\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u043c\u043e\u0434\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430. \u041d\u043e \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 <a href=\"https:\/\/glslsandbox.com\/e#94097.0\">https:\/\/glslsandbox.com\/e#94097.0<\/a> \u2014  \u043f\u043e\u043b\u0435\u0442 \u0432 \u043e\u0431\u043b\u0430\u043a\u0430\u0445.<\/p>\n<details class=\"spoiler\">\n<summary>\u0428\u0435\u0439\u0434\u0435\u0440 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 \u0441\u0430\u0439\u0442\u0435  https:\/\/glslsandbox.com\/<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043d\u043e\u043f\u043a\u0438 Show\/Hide Code \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\/\u0441\u043a\u0440\u044b\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d.<\/p>\n<\/div>\n<\/details>\n<p>\u0415\u0441\u043b\u0438 \u0442\u0430\u043a\u0443\u044e \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 Flutter, \u0442\u043e \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430. \u0410 \u0432\u043e\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u043d\u0430 GLSL \u043d\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0442\u0440\u0443\u0434\u0430. \u0415\u0441\u043b\u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u043d\u0430 GLSL.<\/p>\n<h2>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0448\u0435\u0439\u0434\u0435\u0440\u0430<\/h2>\n<p>\u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \u0438 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043d\u0430\u0448 \u0440\u0430\u043d\u0435\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b shader.glsl.<\/p>\n<details class=\"spoiler\">\n<summary>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0448\u0435\u0439\u0434\u0435\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">#extension GL_OES_standard_derivatives : enable  precision highp float;  uniform float time; uniform vec2 mouse; uniform vec2 resolution;  #define iTime time #define iMouse mouse #define iResolution resolution  \/\/ referred https:\/\/www.shadertoy.com\/view\/4sXGRM  vec3 skytop = vec3(0.05, 0.2, 0.5);  vec3 light = normalize(vec3(0.1, 0.25, 0.9));  vec2 cloudrange = vec2(0.0, 10000.0);  mat3 m = mat3(0.00, 1.60, 1.20, -1.60, 0.72, -0.96, -1.20, -0.96, 1.28);  \/\/ hash function               float hash(float n) {     return fract(cos(n) * 114514.1919); }  \/\/ 3d noise function float noise(in vec3 x) {     vec3 p = floor(x);     vec3 f = smoothstep(0.0, 1.0, fract(x));              float n = p.x + p.y * 10.0 + p.z * 100.0;          return mix(         mix(mix(hash(n + 0.0), hash(n + 1.0), f.x),             mix(hash(n + 10.0), hash(n + 11.0), f.x), f.y),         mix(mix(hash(n + 100.0), hash(n + 101.0), f.x),             mix(hash(n + 110.0), hash(n + 111.0), f.x), f.y), f.z); }  \/\/ Fractional Brownian motion float fbm(vec3 p) {     float f = 0.5000 * noise(p);     p = m * p;     f += 0.2500 * noise(p);     p = m * p;     f += 0.1666 * noise(p);     p = m * p;     f += 0.0834 * noise(p);     return f; }  vec3 camera(float time) {     return vec3(5000.0 * sin(1.0 * time), 5000. + 1500. * sin(0.5 * time), 6000.0 * time); }  void mainImage(out vec4 fragColor, in vec2 fragCoord) {     vec2 uv = 2. * fragCoord.xy \/ iResolution.xy - 1.0;     uv.x *= iResolution.x \/ iResolution.y;      float time = (iTime + 13.5 + 44.) * 1.0;     vec3 campos = camera(time);     vec3 camtar = camera(time + 0.4);      vec3 front = normalize(camtar - campos);     vec3 right = normalize(cross(front, vec3(0.0, 1.0, 0.0)));     vec3 up = normalize(cross(right, front));     vec3 fragAt = normalize(uv.x * right + uv.y * up + front);          \/\/ clouds     vec4 sum = vec4(0, 0, 0, 0);     for (float depth = 0.0; depth &lt; 100000.0; depth += 200.0)     {         vec3 ray = campos + fragAt * depth;         if (cloudrange.x &lt; ray.y &amp;&amp; ray.y &lt; cloudrange.y)         {             float alpha = smoothstep(0.5, 1.0, fbm(ray * 0.00025));             vec3 localcolor = mix(vec3(1.1, 1.05, 1.0), vec3(0.3, 0.3, 0.2), alpha);             alpha = (1.0 - sum.a) * alpha;             sum += vec4(localcolor * alpha, alpha);         }     }          float alpha = smoothstep(0.7, 1.0, sum.a);     sum.rgb \/= sum.a + 0.0001;      float sundot = clamp(dot(fragAt, light), 0.0, 1.0);     vec3 col = 0.8 * (skytop);     col += 0.47 * vec3(1.6, 1.4, 1.0) * pow(sundot, 350.0);     col += 0.4 * vec3(0.8, 0.9, 1.0) * pow(sundot, 2.0);          sum.rgb -= 0.6 * vec3(0.8, 0.75, 0.7) * pow(sundot, 13.0) * alpha;          sum.rgb += 0.2 * vec3(1.3, 1.2, 1.0) * pow(sundot, 5.0) * (1.0 - alpha);      col = mix(col, sum.rgb, sum.a);      fragColor = vec4(col, 1.0); }  void main( void ) { mainImage(gl_FragColor,gl_FragCoord.xy); }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0430\u0434\u0430\u043f\u0442\u0430\u0446\u0438\u044e \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 Flutter. \u041f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u0430, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043e\u0448\u0438\u0431\u043a\u0443 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430. <\/p>\n<figure class=\"full-width\"><figcaption> \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 GLSL \u0432 SPIRV \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430.<\/figcaption><\/figure>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0439 \u0441 \u043a\u043e\u0434\u043e\u043c.<\/p>\n<ul>\n<li>\n<p>\u0412 \u0441\u0442\u0440\u043e\u043a\u0435 62 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 \u0432 \u0448\u0435\u0439\u0434\u0435\u0440:<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0437\u043c\u0435\u043d\u044f\u0435\u043c:<\/p>\n<pre><code class=\"cpp\">void mainImage(out vec4 fragColor, in vec2 fragCoord)<\/code><\/pre>\n<p>\u043d\u0430:<\/p>\n<pre><code class=\"cpp\">void main()<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u044b \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e mainImage() \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u0438\u0437 \u043d\u0435\u0435 \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 \u0432 \u0448\u0435\u0439\u0434\u0435\u0440.<\/p>\n<ul>\n<li>\n<p>\u0412 \u0441\u0442\u0440\u043e\u043a\u0435 64, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 <strong>fragCoord,<\/strong> \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c<strong> gl_FragCoord.<\/strong><\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u0435\u043d\u044f\u0435\u043c:<\/p>\n<pre><code class=\"cpp\"> vec2 uv = 2. * fragCoord.xy \/ iResolution.xy - 1.0;<\/code><\/pre>\n<p>\u043d\u0430:<\/p>\n<pre><code class=\"cpp\">vec2 uv = 2. * gl_FragCoord.xy \/ iResolution.xy - 1.0;<\/code><\/pre>\n<ul>\n<li>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0443\u0436\u0435 \u043e\u0431\u044a\u044f\u0432\u0438\u043b\u0438 \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430 \u0432 \u0448\u0435\u0439\u0434\u0435\u0440, \u0442\u043e \u0432\u0435\u0441\u044c \u043a\u043e\u0434, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0438 107, \u043d\u0443\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cpp\">void main( void ) { mainImage(gl_FragColor,gl_FragCoord.xy); }<\/code><\/pre>\n<ul>\n<li>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u044b\u0445\u043e\u0434\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442, \u043a\u0430\u043a \u0432\u0435\u043a\u0442\u043e\u0440 \u0438\u0437 \u0447\u0435\u0442\u044b\u0440\u0435\u0445 \u0447\u0438\u0441\u0435\u043b + \u0430\u043b\u044c\u0444\u0430 \u043a\u0430\u043d\u0430\u043b. \u042d\u0442\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043a\u0430\u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \u0432\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a Flutter.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cpp\">out vec4 fragColor;<\/code><\/pre>\n<ul>\n<li>\n<p>\u0423\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c \u0433\u043b\u0443\u0431\u0438\u043d\u0443 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u043e\u0431\u043b\u0430\u043a\u043e\u0432 \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 78.<\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u0435\u043d\u044f\u0435\u043c:<\/p>\n<pre><code class=\"cpp\"> for (float depth = 0.0; depth &lt; 100000.0; depth += 200.0)<\/code><\/pre>\n<p>\u043d\u0430:<\/p>\n<pre><code class=\"cpp\"> for (float depth = 0.0; depth &lt; 10000.0; depth += 200.0)<\/code><\/pre>\n<ul>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0448\u0442\u0440\u0438\u0445 \u2014  \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <strong>mouse<\/strong>. \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0448\u0435\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u0443 \u043d\u0430\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434.<\/p>\n<details class=\"spoiler\">\n<summary>\u0410\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0448\u0435\u0439\u0434\u0435\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">#extension GL_OES_standard_derivatives : enable  precision highp float;  uniform float time; uniform vec2 resolution; out vec4 fragColor;  #define iTime time #define iMouse mouse #define iResolution resolution  \/\/ referred https:\/\/www.shadertoy.com\/view\/4sXGRM  vec3 skytop = vec3(0.05, 0.2, 0.5);  vec3 light = normalize(vec3(0.1, 0.25, 0.9));  vec2 cloudrange = vec2(0.0, 10000.0);  mat3 m = mat3(0.00, 1.60, 1.20, -1.60, 0.72, -0.96, -1.20, -0.96, 1.28);  \/\/ hash function float hash(float n) {     return fract(cos(n) * 114514.1919); }  \/\/ 3d noise function float noise(in vec3 x) {     vec3 p = floor(x);     vec3 f = smoothstep(0.0, 1.0, fract(x));      float n = p.x + p.y * 10.0 + p.z * 100.0;      return mix(         mix(mix(hash(n + 0.0), hash(n + 1.0), f.x),             mix(hash(n + 10.0), hash(n + 11.0), f.x), f.y),         mix(mix(hash(n + 100.0), hash(n + 101.0), f.x),             mix(hash(n + 110.0), hash(n + 111.0), f.x), f.y), f.z); }  \/\/ Fractional Brownian motion float fbm(vec3 p) {     float f = 0.5000 * noise(p);     p = m * p;     f += 0.2500 * noise(p);     p = m * p;     f += 0.1666 * noise(p);     p = m * p;     f += 0.0834 * noise(p);     return f; }  vec3 camera(float time) {     return vec3(5000.0 * sin(1.0 * time), 5000. + 1500. * sin(0.5 * time), 6000.0 * time); }  void main() {     vec2 uv = 2. * gl_FragCoord.xy \/ iResolution.xy - 1.0;     uv.x *= iResolution.x \/ iResolution.y;      float time = (iTime + 13.5 + 44.) * 1.0;     vec3 campos = camera(time);     vec3 camtar = camera(time + 0.4);      vec3 front = normalize(camtar - campos);     vec3 right = normalize(cross(front, vec3(0.0, 1.0, 0.0)));     vec3 up = normalize(cross(right, front));     vec3 fragAt = normalize(uv.x * right + uv.y * up + front);      \/\/ clouds     vec4 sum = vec4(0, 0, 0, 0);      for (float depth = 0.0; depth &lt; 10000.0; depth += 200.0)     {         vec3 ray = campos + fragAt * depth;         if (cloudrange.x &lt; ray.y &amp;&amp; ray.y &lt; cloudrange.y)         {             float alpha = smoothstep(0.5, 1.0, fbm(ray * 0.00025));             vec3 localcolor = mix(vec3(1.1, 1.05, 1.0), vec3(0.3, 0.3, 0.2), alpha);             alpha = (1.0 - sum.a) * alpha;             sum += vec4(localcolor * alpha, alpha);         }     }      float alpha = smoothstep(0.7, 1.0, sum.a);     sum.rgb \/= sum.a + 0.0001;      float sundot = clamp(dot(fragAt, light), 0.0, 1.0);     vec3 col = 0.8 * (skytop);     col += 0.47 * vec3(1.6, 1.4, 1.0) * pow(sundot, 350.0);     col += 0.4 * vec3(0.8, 0.9, 1.0) * pow(sundot, 2.0);      sum.rgb -= 0.6 * vec3(0.8, 0.75, 0.7) * pow(sundot, 13.0) * alpha;      sum.rgb += 0.2 * vec3(1.3, 1.2, 1.0) * pow(sundot, 5.0) * (1.0 - alpha);      col = mix(col, sum.rgb, sum.a);      fragColor = vec4(col, 1.0); } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u043b\u044e\u0431\u0443\u0435\u043c\u0441\u044f \u043f\u043e\u043b\u0435\u0442\u043e\u043c \u0432 \u043e\u0431\u043b\u0430\u043a\u0430\u0445 \u043d\u0430 \u0432\u0430\u0448\u0435\u043c \u0441\u043c\u0430\u0440\u0442\u0444\u043e\u043d\u0435. \u0410 \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0448\u0435\u0439\u0434\u0435\u0440\u0430\u043c\u0438 \u0438\u0437 Flutter?<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0448\u0435\u0439\u0434\u0435\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/63dfc6a7a9cdfde042310d45\" data-style=\"\" id=\"63dfc6a7a9cdfde042310d45\" width=\"\"><\/div>\n<\/p>\n<\/div>\n<\/details>\n<h3>\u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u043c \u0438\u0437 Flutter<\/h3>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u043c, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<ul>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043a\u043b\u0430\u0441\u0441 <strong>_MyAppState<\/strong> \u0434\u0432\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0438\u0445 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u0448\u0435\u0439\u0434\u0435\u0440.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"dart\">  var _move = 0.0;   var _stop = 0.0;<\/code><\/pre>\n<ul>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0434\u0432\u0435 \u043a\u043d\u043e\u043f\u043a\u0438. \u041e\u0434\u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0435\u0442\u0430, \u0430 \u0434\u0440\u0443\u0433\u0430\u044f \u2014  \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0448\u0435\u0439\u0434\u0435\u0440\u0430. \u041d\u043e, \u043f\u043e \u0441\u0443\u0442\u0438, \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043c\u0435\u043d\u044f\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 <strong>_move<\/strong> \u0438 <strong>_stop<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0434\u0432\u0435 \u043a\u043d\u043e\u043f\u043a\u0438 \u0432 \u043c\u0435\u0442\u043e\u0434 build<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"dart\">         return Stack(                 children: [                   CustomPaint(painter: AnimRect(shader)),                   Align(                     alignment: Alignment.bottomLeft,                     child: FloatingActionButton(                       onPressed: () {                         if (_move == 1) {                           _move = 0.0;                         } else {                           _move = 1;                         }                         setState(() {});                       },                     ),                   ),                   Align(                     alignment: Alignment.bottomRight,                     child: FloatingActionButton(                       onPressed: () {                         if (_stop == 1) {<\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-345044","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/345044","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=345044"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/345044\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=345044"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=345044"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=345044"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}