{"id":481753,"date":"2026-05-31T09:53:59","date_gmt":"2026-05-31T09:53:59","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=481753"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=481753","title":{"rendered":"\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u0432 \u0432\u0438\u0434\u0435\u043e\u0438\u0433\u0440\u0430\u0445"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0420\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u2014 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0441\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0431\u043b\u043e\u043a \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Video_post-processing#Uses_in_3D_rendering\" rel=\"noopener noreferrer nofollow\">\u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432 \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 \u0432\u0438\u0434\u0435\u043e\u0438\u0433\u0440\u0430\u0445<\/a>, \u0431\u0435\u0437 \u043d\u0435\u0433\u043e \u043d\u0435 \u043e\u0431\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Graphical_user_interface\" rel=\"noopener noreferrer nofollow\">GUI<\/a>. \u041e\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u044d\u0444\u0444\u0435\u043a\u0442\u0430\u0445 <a href=\"https:\/\/dev.epicgames.com\/documentation\/en-us\/unreal-engine\/depth-of-field-in-unreal-engine\" rel=\"noopener noreferrer nofollow\">Depth of Field<\/a>, <a href=\"https:\/\/en.wikipedia.org\/wiki\/Bloom_(shader_effect)\" rel=\"noopener noreferrer nofollow\">Bloom<\/a>\u00a0\u0438\u043b\u0438 <a href=\"https:\/\/blog.frost.kiwi\/GLSL-noise-and-radial-gradient\/#microsoft-windows-acrylic\" rel=\"noopener noreferrer nofollow\">\u043f\u0430\u043d\u0435\u043b\u044f\u0445 \u0441 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u043c \u043c\u0430\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0435\u043a\u043b\u0430<\/a> \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/074\/b03\/f2b\/074b03f2bf23e911891c2ea42ed26168.png\" alt=\"Texture coordinates, also called UV Coordinates or UVs for short\" title=\"\u042d\u0444\u0444\u0435\u043a\u0442 Bloom \u2014 \u043e\u0434\u0438\u043d \u0438\u0437 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f\" width=\"1026\" height=\"365\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/074\/b03\/f2b\/074b03f2bf23e911891c2ea42ed26168.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/074\/b03\/f2b\/074b03f2bf23e911891c2ea42ed26168.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u042d\u0444\u0444\u0435\u043a\u0442 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Bloom_(shader_effect)\" rel=\"noopener noreferrer nofollow\">Bloom<\/a> \u2014 \u043e\u0434\u0438\u043d \u0438\u0437 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u043b\u0435\u0433\u043a\u043e, \u0435\u0433\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u0441\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a \u0442\u043e\u043c\u0443 \u0438\u043b\u0438 \u0438\u043d\u043e\u043c\u0443 \u0441\u043f\u043e\u0441\u043e\u0431\u0443 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u044f \u0446\u0432\u0435\u0442\u043e\u0432 \u0432 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u043c \u0440\u0430\u0434\u0438\u0443\u0441\u0435. \u041e\u0434\u043d\u0430\u043a\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0435\u0433\u043e <a href=\"https:\/\/en.wikipedia.org\/wiki\/Real-time_computing\" rel=\"noopener noreferrer nofollow\">\u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/a>, \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u0438\u0441\u044c \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u043b\u0435\u0442 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0439 \u0438 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 computer science \u0438 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0435. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u044d\u0442\u0430\u043f\u043d\u043e \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u0438\u0445; \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u043f\u0443\u0442\u0435\u0448\u0435\u0441\u0442\u0432\u0438\u0435\u043c \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 \u0441\u0444\u0435\u0440\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u043a\u0438.<\/p>\n<p>\u0412 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u0442\u0435\u0445\u043d\u0438\u043a\u0438 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e <a href=\"https:\/\/en.wikipedia.org\/wiki\/Graphics_processing_unit\" rel=\"noopener noreferrer nofollow\">GPU<\/a>\u00a0\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WebGL_API\" rel=\"noopener noreferrer nofollow\">WebGL<\/a>\u00a0\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430.<\/p>\n<h4>\u041d\u0430\u0447\u0430\u043b\u043e: \u043f\u043e\u043a\u0430 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f<\/h4>\n<p>\u0412 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0438\u0434\u0435\u043e\u0438\u0433\u0440 3D-\u0441\u0446\u0435\u043d\u0430 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Rendering_(computer_graphics)\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u0441\u044f<\/a>) \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u2014 \u0431\u0443\u0444\u0435\u0440 \u043a\u0430\u0434\u0440\u043e\u0432. \u0412 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u044d\u0442\u043e\u0442 \u0431\u0443\u0444\u0435\u0440 \u043a\u0430\u0434\u0440\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432. \u0422\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u0430 <em>\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430<\/em>\u00a0\u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 <em>\u043f\u043e\u0441\u043b\u0435<\/em>\u00a0\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 3D-\u0441\u0446\u0435\u043d\u044b, \u043e\u043d\u0430 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <em>\u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439<\/em>. \u0418 \u043e\u043d\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0443.<\/p>\n<blockquote>\n<p><strong><em>\u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u0435\u0445\u043d\u0438\u043a<\/em><\/strong><em> \u0431\u0443\u0444\u0435\u0440\u044b \u043a\u0430\u0434\u0440\u043e\u0432 <\/em><a href=\"https:\/\/learnopengl.com\/Advanced-Lighting\/Deferred-Shading\" rel=\"noopener noreferrer nofollow\"><em>\u043c\u043e\u0433\u0443\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u0435\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435<\/em><\/a><em>, \u0430 \u044d\u0444\u0444\u0435\u043a\u0442\u044b \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430\u043f\u043e\u0434\u043e\u0431\u0438\u0435 <\/em><a href=\"https:\/\/en.wikipedia.org\/wiki\/Color_correction\" rel=\"noopener noreferrer nofollow\"><em>\u0446\u0432\u0435\u0442\u043e\u0432\u043e\u0439 \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u0438<\/em><\/a><em>\u00a0\u0438\u043b\u0438 <\/em><a href=\"https:\/\/en.wikipedia.org\/wiki\/Tone_mapping\" rel=\"noopener noreferrer nofollow\"><em>\u0442\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u0438<\/em><\/a><em>\u00a0\u0434\u0430\u0436\u0435 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0445 \u0431\u0443\u0444\u0435\u0440\u043e\u0432 \u043a\u0430\u0434\u0440\u043e\u0432: \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 <\/em><a href=\"https:\/\/takahirox.github.io\/three.js\/examples\/webgl_tonemapping.html\" rel=\"noopener noreferrer nofollow\"><em>\u043c\u043e\u0436\u043d\u043e<\/em><\/a><em> \u0440\u0430\u0437\u043d\u044b\u043c\u0438\u00a0<\/em><a href=\"https:\/\/gdcvault.com\/play\/1020631\/The-Revolution-in-Mobile-Game\" rel=\"noopener noreferrer nofollow\"><em>\u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438<\/em><\/a><em> (\u0441\u043c. \u0432\u0438\u0434\u0435\u043e \u0441 35:20)<\/em><\/p>\n<\/blockquote>\n<p>\u041d\u0430\u043c \u0432\u0430\u0436\u0435\u043d \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442: \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0431\u0443\u0444\u0435\u0440 \u043a\u0430\u0434\u0440\u043e\u0432 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 3D-\u0441\u0446\u0435\u043d\u044b. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u0446\u0435\u043d\u0443 \u0438\u0437 \u043c\u043e\u0434\u0430 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <a href=\"https:\/\/store.steampowered.com\/app\/244630\/NEOTOKYO\/\" rel=\"noopener noreferrer nofollow\">NEOTOKYO\u00b0<\/a>. \u041f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0432 <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Reference\/Elements\/canvas\" rel=\"noopener noreferrer nofollow\">canvas<\/a>, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WebGL_API\" rel=\"noopener noreferrer nofollow\">WebGL 1.0<\/a>, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0441 <strong>\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c <\/strong>\u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0432\u0430\u0448\u0435\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430. \u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0435\u0441\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438, \u0430 \u043d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u043a\u043e\u0434\u0430.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/44b\/52a\/8f8\/44b52a8f87bfb888a7fdc937076e144a.png\" alt=\"\u0421\u0446\u0435\u043d\u0430\" title=\"\u0421\u0446\u0435\u043d\u0430\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/44b\/52a\/8f8\/44b52a8f87bfb888a7fdc937076e144a.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/44b\/52a\/8f8\/44b52a8f87bfb888a7fdc937076e144a.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0446\u0435\u043d\u0430<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/646\/cb8\/658\/646cb8658fcb7c485b3cc42f35b5831b.png\" alt=\"\u0421\u0432\u0435\u0442\" title=\"\u0421\u0432\u0435\u0442\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/646\/cb8\/658\/646cb8658fcb7c485b3cc42f35b5831b.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/646\/cb8\/658\/646cb8658fcb7c485b3cc42f35b5831b.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0432\u0435\u0442<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f74\/3fd\/062\/f743fd062e45c87521498246096ec54f.png\" alt=\"Bloom\" title=\"Bloom\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/f74\/3fd\/062\/f743fd062e45c87521498246096ec54f.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f74\/3fd\/062\/f743fd062e45c87521498246096ec54f.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>Bloom<\/figcaption><\/div>\n<\/figure>\n<details class=\"spoiler\">\n<summary>\u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">\/* \u042d\u0442\u043e \"\u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440\" \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f - \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u0430\u044f \u043d\u0430 GPU.   \u0412 *\u044d\u0442\u043e\u0439* \u0441\u0442\u0430\u0442\u044c\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u0440\u0430\u0437\u0443   \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430 canvas *\/\/* \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 WebGL 1 \u0438 \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 \u043c\u043e\u0436\u0435\u0442   \u043d\u0438 \u043d\u0430 \u0447\u0442\u043e \u043d\u0435 \u0432\u043b\u0438\u044f\u0442\u044c.   \u041d\u0430 \u0431\u0443\u0434\u0443\u0449\u0435\u0435: \u0432 \u0441\u0438\u043b\u044c\u043d\u044b\u0445 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f\u0445 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043d\u0435\u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0432\u043b\u0438\u044f\u043d\u0438\u0439   \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0446\u0432\u0435\u0442\u043e\u0432, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0437\u0430\u0434\u0430\u0451\u043c \u0437\u0434\u0435\u0441\u044c \"highp\", \u0442\u043e \u0435\u0441\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c. *\/precision highp float;\/* UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0438\u0437 \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \"simpleQuad.vs\".   \u041e\u043d\u0438 \u0441\u043e\u043e\u0431\u0449\u0430\u044e\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u043f\u0438\u043a\u0441\u0435\u043b\u044e \u0432\u044b\u0432\u043e\u0434\u0430, \u043e\u0442\u043a\u0443\u0434\u0430 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u0443. *\/varying vec2 uv;\/* \u0412\u0432\u043e\u0434 lightBrightness. \u042f\u0440\u043a\u043e\u0441\u0442\u044c \u0441\u0432\u0435\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u043e\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u0435   \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f, \u0430 \u043d\u0435 \u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0438, \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u043c \u043d\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c \u044d\u0442\u0430\u043f\u0435, \u0438\u0437-\u0437\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439   \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u0446\u0432\u0435\u0442\u0430. *\/uniform float lightBrightness;\/* \u0422\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0439 \u0432\u0432\u043e\u0434 *\/uniform sampler2D texture;\/* \u0424\u0443\u043d\u043a\u0446\u0438\u044f \"main\", \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u0430\u044f \u0432 GPU *\/void main() {\/* gl_FragColor - \u044d\u0442\u043e \u0432\u044b\u0432\u043e\u0434 \u043d\u0430\u0448\u0435\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430. texture2D - \u044d\u0442\u043e \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b,   \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u043e\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b 'uv'. Then multiplied by   our lightBrightness value (a multiplier with eg. 1.0 at 100%, 0.5 at 50%)   In \"scene\" mode, this value is locked to 1.0 so it has no effect *\/gl_FragColor = texture2D(texture, uv) * lightBrightness;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>WebGL Javascript<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">import * as util from '..\/utility.js'export async function setupSimple() {\/* \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f *\/const WebGLBox = document.getElementById('WebGLBox-Simple');const canvas = WebGLBox.querySelector('canvas');\/* \u0420\u0430\u0437\u043c\u0435\u0440 \u043a\u0440\u0443\u0433\u0430 *\/const radius = 0.12;\/* \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 WebGL 1.0 *\/const gl = canvas.getContext('webgl', {preserveDrawingBuffer: false,antialias: false,alpha: false,});\/* \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b *\/const ctx = {\/* \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043b\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 *\/mode: \"scene\",flags: { isRendering: false, buffersInitialized: false, initComplete: false, benchMode: false },\/* \u0422\u0435\u043a\u0441\u0442\u0443\u0440\u044b *\/tex: { sdr: null, selfIllum: null, frame: null, frameFinal: null },\/* \u0411\u0443\u0444\u0435\u0440\u044b \u043a\u0430\u0434\u0440\u043e\u0432 *\/fb: { scene: null, final: null },\/* \u0428\u0435\u0439\u0434\u0435\u0440\u044b \u0438 \u043c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 *\/shd: {scene: { handle: null, uniforms: { offset: null, radius: null } },blur: { handle: null, uniforms: { frameSizeRCP: null, samplePosMult: null, lightBrightness: null } },bloom: { handle: null, uniforms: { offset: null, radius: null, texture: null, textureAdd: null } }}};\/* \u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b UI *\/const ui = {display: {spinner: canvas.parentElement.querySelector('svg', canvas.parentElement),contextLoss: canvas.parentElement.querySelector('div', canvas.parentElement),fps: WebGLBox.querySelector('#fps'),ms: WebGLBox.querySelector('#ms'),width: WebGLBox.querySelector('#width'),height: WebGLBox.querySelector('#height'),},rendering: {animate: WebGLBox.querySelector('#animateCheck'),modes: WebGLBox.querySelectorAll('input[type=\"radio\"]'),lightBrightness: WebGLBox.querySelector('#lightBrightness'),lightBrightnessReset: WebGLBox.querySelector('#lightBrightnessReset'),}};\/* \u0428\u0435\u0439\u0434\u0435\u0440\u044b *\/const circleAnimation = await util.fetchShader(\"shader\/circleAnimation.vs\");const simpleTexture = await util.fetchShader(\"shader\/simpleTexture.fs\");const bloomVert = await util.fetchShader(\"shader\/bloom.vs\");const bloomFrag = await util.fetchShader(\"shader\/bloom.fs\");const simpleQuad = await util.fetchShader(\"shader\/simpleQuad.vs\");const noBlurYetFrag = await util.fetchShader(\"shader\/noBlurYet.fs\");\/* \u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0431\u0435\u0437 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 *\/ui.rendering.lightBrightness.addEventListener('input', () =&gt; { if (!ui.rendering.animate.checked) redraw() });\/* \u0421\u043e\u0431\u044b\u0442\u0438\u044f *\/ui.rendering.animate.addEventListener(\"change\", () =&gt; {if (ui.rendering.animate.checked)startRendering();else {ui.display.fps.value = \"-\";ui.display.ms.value = \"-\";ctx.flags.isRendering = false;redraw()}});canvas.addEventListener(\"webglcontextlost\", () =&gt; {ui.display.contextLoss.style.display = \"block\";});\/* \u0420\u0435\u0436\u0438\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 *\/ui.rendering.modes.forEach(radio =&gt; {\/* \u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u0434\u0430\u0451\u043c \u0441\u0446\u0435\u043d\u0443, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u044c \u0431\u0430\u0433 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432 Firefox \u0434\u043b\u044f Android *\/if (radio.value === \"scene\")radio.checked = true;radio.addEventListener('change', (event) =&gt; {ctx.mode = event.target.value;ui.rendering.lightBrightness.disabled = ctx.mode === \"scene\";ui.rendering.lightBrightnessReset.disabled = ctx.mode === \"scene\";if (!ui.rendering.animate.checked) redraw();});});\/* Draw Texture Shader *\/ctx.shd.scene = util.compileAndLinkShader(gl, circleAnimation, simpleTexture, [\"offset\", \"radius\"]);\/* \u0420\u0438\u0441\u0443\u0435\u043c \u0448\u0435\u0439\u0434\u0435\u0440 bloom *\/ctx.shd.bloom = util.compileAndLinkShader(gl, bloomVert, bloomFrag, [\"texture\", \"textureAdd\", \"offset\", \"radius\"]);\/* \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0440\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 *\/function reCompileBlurShader() {ctx.shd.blur = util.compileAndLinkShader(gl, simpleQuad, noBlurYetFrag, [\"lightBrightness\"]);}\/* \u0428\u0435\u0439\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f *\/reCompileBlurShader()\/* \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0432 GPU *\/util.bindUnitQuad(gl);async function setupTextureBuffers() {ui.display.spinner.style.display = \"block\";ctx.flags.buffersInitialized = true;ctx.flags.initComplete = false;gl.deleteFramebuffer(ctx.fb.scene);gl.deleteFramebuffer(ctx.fb.final);[ctx.fb.scene, ctx.tex.frame] = util.setupFramebuffer(gl, canvas.width, canvas.height);[ctx.fb.final, ctx.tex.frameFinal] = util.setupFramebuffer(gl, canvas.width, canvas.height);let [base, selfIllum] = await Promise.all([fetch(\"\/dual-kawase\/img\/SDR_No_Sprite.png\"),fetch(\"\/dual-kawase\/img\/Selfillumination.png\")]);let [baseBlob, selfIllumBlob] = await Promise.all([base.blob(), selfIllum.blob()]);let [baseBitmap, selfIllumBitmap] = await Promise.all([createImageBitmap(baseBlob, { colorSpaceConversion: 'none', resizeWidth: canvas.width * 1.12, resizeHeight: canvas.height * 1.12, resizeQuality: \"high\" }),createImageBitmap(selfIllumBlob, { colorSpaceConversion: 'none', resizeWidth: canvas.width * 1.12, resizeHeight: canvas.height * 1.12, resizeQuality: \"high\" })]);ctx.tex.sdr = util.setupTexture(gl, null, null, ctx.tex.sdr, gl.LINEAR, baseBitmap);ctx.tex.selfIllum = util.setupTexture(gl, null, null, ctx.tex.selfIllum, gl.LINEAR, selfIllumBitmap);baseBitmap.close();selfIllumBitmap.close();ctx.flags.initComplete = true;ui.display.spinner.style.display = \"none\";}let prevNow = performance.now();let lastStatsUpdate = prevNow;let fpsEMA = 60;let msEMA = 16;async function redraw() {if (!ctx.flags.buffersInitialized)await setupTextureBuffers();if (!ctx.flags.initComplete)return;\/* \u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 UI *\/ui.display.width.value = canvas.width;ui.display.height.value = canvas.height;\/* \u041a\u0440\u0443\u0433\u043e\u0432\u043e\u0435 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 *\/let radiusSwitch = ui.rendering.animate.checked ? radius : 0.0;let speed = (performance.now() \/ 10000) % Math.PI * 2;const offset = [radiusSwitch * Math.cos(speed), radiusSwitch * Math.sin(speed)];gl.useProgram(ctx.shd.scene.handle);const texture = ctx.mode == \"scene\" ? ctx.tex.sdr : ctx.tex.selfIllum;gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, texture);gl.uniform2fv(ctx.shd.scene.uniforms.offset, offset);gl.uniform1f(ctx.shd.scene.uniforms.radius, radiusSwitch);\/* \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0431\u0443\u0444\u0435\u0440\u0430 \u043a\u0430\u0434\u0440\u043e\u0432 \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 *\/gl.bindFramebuffer(gl.FRAMEBUFFER, ctx.fb.scene);gl.viewport(0, 0, canvas.width, canvas.height);\/* \u0412\u044b\u0437\u043e\u0432 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 *\/gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);\/* \u0420\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u043f\u0440\u0438 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0438 *\/gl.useProgram(ctx.shd.blur.handle);const finalFB = ctx.mode == \"bloom\" ? ctx.fb.final : null;gl.bindFramebuffer(gl.FRAMEBUFFER, finalFB);gl.viewport(0, 0, canvas.width, canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.lightBrightness, ctx.mode == \"scene\" ? 1.0 : ui.rendering.lightBrightness.value);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.frame);gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);if (ctx.mode == \"bloom\") {\/* \u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u0438\u043d\u0433 bloom \u043d\u0430 \u044d\u043a\u0440\u0430\u043d *\/gl.bindFramebuffer(gl.FRAMEBUFFER, null);gl.useProgram(ctx.shd.bloom.handle);gl.uniform2fv(ctx.shd.bloom.uniforms.offset, offset);gl.uniform1f(ctx.shd.bloom.uniforms.radius, radiusSwitch);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.sdr);gl.uniform1i(ctx.shd.bloom.uniforms.texture, 0);gl.activeTexture(gl.TEXTURE1);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.frameFinal);gl.uniform1i(ctx.shd.bloom.uniforms.textureAdd, 1);gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);}\/* \u041f\u0440\u043e\u0441\u0438\u043c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e CPU-GPU \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0443 GPU \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u0438\u043d\u0433\u0435.   \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u044d\u0442\u043e \u0441 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u0441\u0431\u0440\u043e\u0441\u0443, \u043d\u043e, \u043f\u043e\u0445\u043e\u0436\u0435,    \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043d\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445 \u0441 \u043d\u0438\u0437\u043a\u0438\u043c FPS *\/gl.finish();const now = performance.now();let dt = now - prevNow;if (dt &gt; 0) {const instFPS = 1000 \/ dt;const ALPHA = 0.05;fpsEMA = ALPHA * instFPS + (1 - ALPHA) * fpsEMA;msEMA = ALPHA * dt + (1 - ALPHA) * msEMA;}prevNow = now;if (ui.rendering.animate.checked &amp;&amp; now - lastStatsUpdate &gt;= 1000) {ui.display.fps.value = fpsEMA.toFixed(0);ui.display.ms.value = msEMA.toFixed(2);lastStatsUpdate = now;}}let animationFrameId;\/* \u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c *\/function nativeResize() {const [width, height] = util.getNativeSize(canvas);if (width &amp;&amp; canvas.width !== width || height &amp;&amp; canvas.height !== height) {canvas.width = width;canvas.height = height;if (!ctx.flags.benchMode) {stopRendering();startRendering();}if (!ui.rendering.animate.checked)redraw();}}\/* \u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432 *\/nativeResize();let resizePending = false;window.addEventListener('resize', () =&gt; {if (!resizePending) {resizePending = true;requestAnimationFrame(() =&gt; {resizePending = false;nativeResize();});}});function renderLoop() {if (ctx.flags.isRendering &amp;&amp; ui.rendering.animate.checked) {redraw();animationFrameId = requestAnimationFrame(renderLoop);}}function startRendering() {\/* \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433, \u043a\u043e\u0433\u0434\u0430 canvas \u0432\u0438\u0434\u0438\u043c *\/ctx.flags.isRendering = true;renderLoop();}function stopRendering() {\/* \u041f\u0440\u0435\u043a\u0440\u0430\u0449\u0430\u0435\u043c \u0432\u044b\u0437\u043e\u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0438 *\/ctx.flags.isRendering = false;cancelAnimationFrame(animationFrameId);\/* \u0417\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441 CPU \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u043c\u044b \u0432\u043c\u0435\u0448\u0430\u0435\u043c\u0441\u044f \u0432 \u043d\u0435\u0433\u043e *\/gl.finish();\/* \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0431\u0443\u0444\u0435\u0440\u044b, \u0447\u0442\u043e\u0431\u044b \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c *\/gl.deleteTexture(ctx.tex.sdr); ctx.tex.sdr = null;gl.deleteTexture(ctx.tex.selfIllum); ctx.tex.selfIllum = null;gl.deleteTexture(ctx.tex.frame); ctx.tex.frame = null;gl.deleteTexture(ctx.tex.frameFinal); ctx.tex.frameFinal = null;gl.deleteFramebuffer(ctx.fb.scene); ctx.fb.scene = null;gl.deleteFramebuffer(ctx.fb.final); ctx.fb.final = null;ctx.flags.buffersInitialized = false;ctx.flags.initComplete = false;ui.display.fps.value = \"-\";ui.display.ms.value = \"-\";}function handleIntersection(entries) {entries.forEach(entry =&gt; {if (entry.isIntersecting) {if (!ctx.flags.isRendering &amp;&amp; !ctx.flags.benchMode) startRendering();} else {stopRendering();}});}\/* \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 canvas \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 *\/let observer = new IntersectionObserver(handleIntersection);observer.observe(canvas);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u043a\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442. \u0412 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u043d\u0430\u0434 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u0435\u0441\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0430 <code>Animate<\/code>\u00a0, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c \u0441\u0446\u0435\u043d\u0443 \u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432. \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0434\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0438\u0433\u0440\u043e\u043a\u0430. \u0420\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0442\u0440\u0451\u043c \u0440\u0435\u0436\u0438\u043c\u0430\u043c:<\/p>\n<blockquote>\n<p><em>\u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0432\u0435\u0434\u0443\u0442 \u0441\u0435\u0431\u044f \u043f\u043e-\u0440\u0430\u0437\u043d\u043e\u043c\u0443. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0447\u0435\u043d\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u043d\u043e \u043b\u043e\u043c\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0438. \u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u0440\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u044f\u0445 \u0441 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u043a\u043e\u043d\u0442\u0440\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u044c\u044e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0434\u0430\u043b\u0451\u043a\u0438\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u043e\u0441\u0432\u0435\u0449\u0435\u043d\u0438\u044f<\/em><\/p>\n<\/blockquote>\n<ul>\n<li>\n<p>\u0412 \u0440\u0435\u0436\u0438\u043c\u0435 <code>\u0421\u0446\u0435\u043d\u0430<\/code>\u00a0\u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u043e \u0432\u0441\u0435\u043c\u0443 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044e<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0440\u0435\u0436\u0438\u043c\u0435 <code>\u0421\u0432\u0435\u0442<\/code>\u00a0\u043c\u044b \u0432\u0438\u0434\u0438\u043c \u0438 \u0440\u0430\u0437\u043c\u044b\u0432\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e <a href=\"https:\/\/docs.blender.org\/manual\/en\/latest\/render\/shader_nodes\/shader\/principled.html#emission\" rel=\"noopener noreferrer nofollow\">\u0438\u0437\u043b\u0443\u0447\u0430\u044e\u0449\u0438\u0435<\/a>\u00a0\u0447\u0430\u0441\u0442\u0438 \u0441\u0446\u0435\u043d\u044b, \u0438\u043d\u043e\u0433\u0434\u0430 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0435 <a href=\"https:\/\/developer.valvesoftware.com\/wiki\/Glowing_textures_(Source)#%24selfillum\" rel=\"noopener noreferrer nofollow\">Self-Illumination<\/a><\/p>\n<ul>\n<li>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0432 \u044d\u0442\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0437\u0443\u043d\u043e\u043a <code>lightBrightness<\/code>, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u044d\u043d\u0435\u0440\u0433\u0438\u044e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u043e\u0441\u0432\u0435\u0449\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u0412 \u0440\u0435\u0436\u0438\u043c\u0435 <code>Bloom<\/code>\u00a0\u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u0443\u044e \u0441\u0446\u0435\u043d\u0443 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u0432\u0435\u0440\u0445 \u0440\u0430\u0437\u043c\u044b\u0442\u044b\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u043e\u0441\u0432\u0435\u0449\u0435\u043d\u0438\u044f \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0440\u0435\u0436\u0438\u043c\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0430\u0442\u043c\u043e\u0441\u0444\u0435\u0440\u043d\u043e\u0439 \u0441\u0446\u0435\u043d\u044b. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u044d\u0444\u0444\u0435\u043a\u0442 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Bloom_(shader_effect)\" rel=\"noopener noreferrer nofollow\">Bloom<\/a> \u2014 \u0432\u0430\u0436\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0432 3D-\u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/p>\n<\/li>\n<\/ul>\n<blockquote>\n<p><em>\u0421\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e\u0438\u0433\u0440\u044b \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442 <\/em><a href=\"https:\/\/chrismillervfx.wordpress.com\/2013\/04\/15\/understanding-render-passes\/\" rel=\"noopener noreferrer nofollow\"><em>\u043f\u0440\u043e\u0445\u043e\u0434<\/em><\/a><em> \u0440\u0430\u0437\u043c\u044b\u0442\u043e\u0433\u043e \u043e\u0441\u0432\u0435\u0449\u0435\u043d\u0438\u044f, \u043a\u0430\u043a \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u0438 \u043d\u0435 \u0437\u0430\u0434\u0430\u044e\u0442 <\/em><a href=\"https:\/\/en.wikipedia.org\/wiki\/Thresholding_(image_processing)\" rel=\"noopener noreferrer nofollow\"><em>\u043f\u043e\u0440\u043e\u0433\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435<\/em><\/a><em>\u00a0\u0434\u043b\u044f \u0441\u0446\u0435\u043d\u044b \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435\u043c; \u043e\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442 bloom \u0438\u043d\u0430\u0447\u0435. \u041c\u044b \u0432\u0435\u0440\u043d\u0451\u043c\u0441\u044f \u043a \u044d\u0442\u043e\u043c\u0443 \u0447\u0443\u0442\u044c \u043d\u0438\u0436\u0435.<\/em><\/p>\n<\/blockquote>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043d\u0430 canvas \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u0430\u0434\u0440\u043e\u0432 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0443\/\u0432\u0440\u0435\u043c\u044f, \u0437\u0430\u0442\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c\u043e\u0435 \u043d\u0430 \u043a\u0430\u0434\u0440. \u041e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u044b\u0439 \u0430\u0441\u043f\u0435\u043a\u0442 \u044d\u0442\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u2014 <strong><em>\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/em><\/strong>.<\/p>\n<blockquote>\n<p><em>\u0412 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u0447\u0430\u0441\u0442\u043e\u0442\u0430 \u043a\u0430\u0434\u0440\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 \u0447\u0430\u0441\u0442\u043e\u0442\u043e\u0439 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u044d\u0442\u043e \u0431\u0443\u0434\u0443\u0442 60 fps \/ 16,6 \u043c\u0441. \u041d\u0438\u0436\u0435 \u043c\u044b \u0437\u0430\u0439\u043c\u0451\u043c\u0441\u044f \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u043c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438\u043d\u0433\u043e\u043c<\/em><\/p>\n<\/blockquote>\n<h3>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437\u00a0<\/h3>\n<blockquote>\n<p><em>\u0414\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0437\u043d\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 GPU \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0440\u0435\u0448\u0438\u0442\u0435 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0433\u043b\u0443\u0431\u0436\u0435, \u043e\u043d\u043e \u0432\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f<\/em><\/p>\n<\/blockquote>\n<p>\u041c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0432 \u0432\u0438\u0434\u0435 <a href=\"https:\/\/learnopengl.com\/Getting-started\/Hello-Triangle\" rel=\"noopener noreferrer nofollow\">\u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430<\/a>, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u043d\u0430 <a href=\"https:\/\/en.wikipedia.org\/wiki\/OpenGL_Shading_Language\" rel=\"noopener noreferrer nofollow\">GLSL<\/a>. \u0415\u0441\u043b\u0438 \u0432\u043a\u0440\u0430\u0442\u0446\u0435, \u0442\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u2014 \u044d\u0442\u043e \u043a\u043e\u0434, \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u043d\u0430 GPU \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430. \u0412\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0432 \u0448\u0435\u0439\u0434\u0435\u0440\u0430\u0445 \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f <a href=\"https:\/\/learnopengl.com\/Getting-started\/Textures\" rel=\"noopener noreferrer nofollow\">\u0442\u0435\u043a\u0441\u0442\u0443\u0440\u0430\u043c\u0438<\/a>. \u0423 \u044d\u0442\u0438\u0445 \u0442\u0435\u043a\u0441\u0442\u0443\u0440 \u0435\u0441\u0442\u044c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u0447\u0430\u0441\u0442\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0435 <a href=\"https:\/\/en.wikipedia.org\/wiki\/UV_mapping\" rel=\"noopener noreferrer nofollow\">UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438<\/a>, \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u0438 \u0447\u0438\u0441\u043b\u0430 \u043d\u0430\u043c \u0438 \u0432\u0430\u0436\u043d\u044b.<\/p>\n<blockquote>\n<p><em>\u0421\u0442\u0440\u043e\u0433\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0435 \u0448\u0435\u0439\u0434\u0435\u0440\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0434\u043b\u044f <\/em><a href=\"https:\/\/www.khronos.org\/opengl\/wiki\/Fragment\" rel=\"noopener noreferrer nofollow\"><em>\u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043e\u0432<\/em><\/a><em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 \u043f\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0443 \u0441 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u043c; \u0442\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c <\/em><a href=\"https:\/\/registry.khronos.org\/OpenGL\/extensions\/EXT\/EXT_shader_framebuffer_fetch.txt\" rel=\"noopener noreferrer nofollow\"><em>\u0434\u0440\u0443\u0433\u0438\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b<\/em><\/a><em>\u00a0\u0447\u0442\u0435\u043d\u0438\u044f \u0431\u0443\u0444\u0435\u0440\u043e\u0432 \u043a\u0430\u0434\u0440\u043e\u0432, \u043d\u043e \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0441\u0451 \u044d\u0442\u043e \u043d\u0435 \u0432\u0430\u0436\u043d\u043e.<\/em><\/p>\n<\/blockquote>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/403\/a10\/43b\/403a1043b33d71b26e7480cbabf2081c.png\" alt=\"Texture coordinates, also called UV Coordinates or UVs for short\" title=\"\u0422\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0435 UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438 \u0438\u043b\u0438 UV. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u0436\u0430\u0442\u044b\u043c.\" width=\"350\" height=\"331\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/403\/a10\/43b\/403a1043b33d71b26e7480cbabf2081c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/403\/a10\/43b\/403a1043b33d71b26e7480cbabf2081c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0422\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0435 UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438 \u0438\u043b\u0438 UV. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u0436\u0430\u0442\u044b\u043c.<\/figcaption><\/div>\n<\/figure>\n<p>UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u043f\u043e\u0437\u0438\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0432 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438, \u043b\u0435\u0432\u044b\u0439 \u043d\u0438\u0436\u043d\u0438\u0439 \u0443\u0433\u043e\u043b \u0438\u043c\u0435\u0435\u0442 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b <code>0,0<\/code>, \u0430 \u043f\u0440\u0430\u0432\u044b\u0439 \u0432\u0435\u0440\u0445\u043d\u0438\u0439 \u2014 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b <code>1,1<\/code>. \u041d\u0438 UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u043d\u0438 \u0441\u0430\u043c\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u044b \u043d\u0435 \u0438\u043c\u0435\u044e\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u043a\u0440\u0430\u043d\u0430 \u0438\u043b\u0438 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u0441\u0442\u043e\u0440\u043e\u043d. \u0415\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u043c, \u043c\u044b \u0441\u0430\u043c\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u0438\u0445 \u0432 UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u0445.<\/p>\n<blockquote>\n<p><em>\u041c\u044b \u043d\u0435 \u0437\u043d\u0430\u0435\u043c, \u0432 \u043a\u0430\u043a\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0438\u043a\u0441\u0435\u043b\u0438 \u0432\u044b\u0432\u043e\u0434\u0430, <\/em><a href=\"https:\/\/michaldrobot.com\/2014\/04\/01\/gcn-execution-patterns-in-full-screen-passes\/\" rel=\"noopener noreferrer nofollow\"><em>\u043d\u043e \u0435\u0441\u0442\u044c \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u044d\u0442\u043e \u0443\u0437\u043d\u0430\u0442\u044c<\/em><\/a><em>, \u0438 \u0445\u043e\u0442\u044f <\/em><a href=\"https:\/\/docs.gl\/sl4\/gl_FragCoord\" rel=\"noopener noreferrer nofollow\"><em>\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0430\u0442\u044c \u043d\u0430\u043c \u043e\u0431 \u044d\u0442\u043e\u043c<\/em><\/a><em>, \u0448\u0435\u0439\u0434\u0435\u0440 \u0434\u0430\u0436\u0435 \u043d\u0435 \u0437\u043d\u0430\u0435\u0442, \u043a\u0430\u043a\u043e\u0439 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u0432\u044b\u0432\u043e\u0434\u0430 \u043e\u043d \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442<\/em><\/p>\n<\/blockquote>\n<p>\u0411\u0443\u0444\u0435\u0440 \u043a\u0430\u0434\u0440\u043e\u0432 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0432\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 <code>uniform sampler2D texture<\/code>\u00a0\u0432 \u0432\u0438\u0434\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b. \u041f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u043c\u044b \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u043d\u043e\u044d\u043a\u0440\u0430\u043d\u043d\u044b\u0439 \u0447\u0435\u0442\u044b\u0440\u0451\u0445\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a (Full Screen Quad) \u2014 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a, \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0432\u0435\u0441\u044c canvas, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 <code>0,0<\/code>\u00a0\u0432 \u043b\u0435\u0432\u043e\u043c \u043d\u0438\u0436\u043d\u0435\u043c \u0443\u0433\u043b\u0443 \u0438 <code>1,1<\/code>\u00a0\u0432 \u043f\u0440\u0430\u0432\u043e\u043c \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0433\u043b\u0443 UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b <code>varying vec2 uv<\/code>\u00a0\u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0438\u0437 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b.<\/p>\n<p>\u0421\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0441\u0442\u043e\u0440\u043e\u043d \u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b \u0442\u0430\u043a\u0438\u0435 \u0436\u0435, \u043a\u0430\u043a \u0438 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0441\u0442\u043e\u0440\u043e\u043d \u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0433\u043e canvas, \u0442\u043e \u0435\u0441\u0442\u044c \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u0440\u0430\u0432\u043d\u043e 1:1. \u041e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0437\u0430 \u044d\u0442\u043e <a href=\"https:\/\/github.com\/FrostKiwi\/treasurechest\/blob\/main\/posts\/dual-kawase\/js\/blur\/simple.js\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u0430\u043f\u044b \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430<\/a>\u00a0\u0438 <a href=\"https:\/\/github.com\/FrostKiwi\/treasurechest\/blob\/main\/posts\/dual-kawase\/shader\/simpleQuad.vs\" rel=\"noopener noreferrer nofollow\">\u0432\u0435\u0440\u0448\u0438\u043d\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440<\/a>\u00a0\u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043d\u0430\u0448\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043d\u0435 \u0432\u0430\u0436\u043d\u044b.<\/p>\n<p>\u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0446\u0432\u0435\u0442\u0443 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>texture2D(texture, uv)<\/code> \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f. \u0412 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0447\u0442\u0435\u043d\u0438\u0435 \u0438\u0437 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0445 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439, \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0442\u044c \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u2014 \u0434\u0435\u0441\u044f\u0442\u0438\u0447\u043d\u0443\u044e \u0434\u0440\u043e\u0431\u044c, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043e\u0434\u043d\u043e\u043c\u0443 \u0448\u0430\u0433\u0443 \u043f\u0438\u043a\u0441\u0435\u043b\u044f, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c\u0443\u044e \u043f\u043e \u0444\u043e\u0440\u043c\u0443\u043b\u0435 <code>1 \/ canvasResolution<\/code><\/p>\n<blockquote>\n<p><em>\u041a\u043e\u0434 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c, \u043a\u0430\u043a \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f.<\/em><\/p>\n<\/blockquote>\n<p>\u041f\u043e\u043d\u0430\u0447\u0430\u043b\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0433\u0440\u0430\u0444\u0438\u043a\u0438 <a href=\"https:\/\/www.youtube.com\/watch?v=xJQ0qXh1-m0\" rel=\"noopener noreferrer nofollow\">\u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e<\/a> \u0438\u0437-\u0437\u0430 \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u0440\u0430\u0432\u0438\u043b \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439, \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0435\u043c,\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Graphics_library\" rel=\"noopener noreferrer nofollow\">\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 API<\/a>\u00a0\u0438 <a href=\"https:\/\/fgiesen.wordpress.com\/2011\/07\/09\/a-trip-through-the-graphics-pipeline-2011-index\/\" rel=\"noopener noreferrer nofollow\">\u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u043e\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430<\/a>. \u041d\u043e \u0432 \u0442\u043e \u0436\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u043d\u043e \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u0432\u0435\u0440\u043e\u044f\u0442\u043d\u044b\u0439 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0434\u0440\u0443\u0433\u0438\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0451\u043c \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f, \u043a\u0430\u043a \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u044d\u0442\u043e\u0442 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b.<\/p>\n<h4>Box Blur\u00a0<\/h4>\n<p>\u0421 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430, \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0445 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u2014 \u044d\u0442\u043e <a href=\"https:\/\/en.wikipedia.org\/wiki\/For_loop\" rel=\"noopener noreferrer nofollow\">\u0446\u0438\u043a\u043b for<\/a>. \u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0432\u044b\u0440\u0430\u0436\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435: <em>\u00ab\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 Y \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0432\u0432\u0435\u0440\u0445 \u0438 \u0432\u043d\u0438\u0445, \u043d\u0430 X \u0432\u043b\u0435\u0432\u043e \u0438 \u0432\u043f\u0440\u0430\u0432\u043e, \u0430 \u043f\u043e\u0442\u043e\u043c \u0443\u0441\u0440\u0435\u0434\u043d\u044f\u0435\u043c \u0446\u0432\u0435\u0442\u0430\u00bb<\/em>. \u0427\u0435\u043c \u0441\u0438\u043b\u044c\u043d\u0435\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435, \u0442\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c <code>kernelSize<\/code>, \u0442\u043e \u0435\u0441\u0442\u044c \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u043d\u0430\u0448\u0435\u0433\u043e \u0446\u0438\u043a\u043b\u0430 for.<\/p>\n<pre><code class=\"cpp\">\/* \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0437 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b Y \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0432\u044b\u0448\u0435 \u0438 \u043d\u0438\u0436\u0435 *\/for (int y = -kernel_size; y &lt;= kernel_size; ++y) {\/* \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0437 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b X \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0441\u043b\u0435\u0432\u0430 \u0438 \u0441\u043f\u0440\u0430\u0432\u0430 *\/for (int x = -kernel_size; x &lt;= kernel_size; ++x) {\/* \u0421\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0435\u0435, \u043a\u0430\u043a\u043e\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c *\/vec2 offset = vec2(x, y) * samplePosMult * frameSizeRCP;\/* \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438 \u0441\u0443\u043c\u043c\u0438\u0440\u0443\u0435\u043c \u0432\u043a\u043b\u0430\u0434 \u0446\u0432\u0435\u0442\u0430 \u044d\u0442\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f *\/sum += texture2D(texture, uv + offset);}}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0427\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0446\u0438\u043a\u043b for, \u0442\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u043d\u0438\u0439 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b \u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c <strong>\u043d\u0430 \u043e\u0434\u0438\u043d \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c<\/strong>. \u041a\u0430\u0436\u0434\u043e\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b \u0447\u0430\u0441\u0442\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u00abtexture tap\u00bb, \u0438 \u043d\u0438\u0436\u0435 \u0442\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0442\u0430\u043a\u0438\u0445 \u00abtap\u00bb.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/14a\/da5\/17f\/14ada517f226a0676ed6baa7fe48485b.png\" alt=\"\u0421\u0446\u0435\u043d\u0430\" title=\"\u0421\u0446\u0435\u043d\u0430\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/14a\/da5\/17f\/14ada517f226a0676ed6baa7fe48485b.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/14a\/da5\/17f\/14ada517f226a0676ed6baa7fe48485b.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0446\u0435\u043d\u0430<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/686\/97d\/43b\/68697d43b518b2bd8fcb91d8e09df80f.png\" alt=\"\u0421\u0432\u0435\u0442\" title=\"\u0421\u0432\u0435\u0442\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/686\/97d\/43b\/68697d43b518b2bd8fcb91d8e09df80f.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/686\/97d\/43b\/68697d43b518b2bd8fcb91d8e09df80f.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0432\u0435\u0442<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cae\/68e\/fdd\/cae68efdd566c53459b45865bea37323.png\" alt=\"Bloom\" title=\"Bloom\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/cae\/68e\/fdd\/cae68efdd566c53459b45865bea37323.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cae\/68e\/fdd\/cae68efdd566c53459b45865bea37323.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>Bloom<\/figcaption><\/div>\n<\/figure>\n<details class=\"spoiler\">\n<summary>\u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">\/* \u0412\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u0441 \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0435\u0439 \u0437\u0430\u043f\u044f\u0442\u043e\u0439 \u043d\u0430 highp, \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f.   \u041f\u0440\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0440\u0430\u0437\u043c\u0435\u0440\u0430\u0445 \u044f\u0434\u0440\u0430 \u043d\u0430 \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u0432\u043b\u0438\u044f\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0446\u0432\u0435\u0442\u043e\u0432, \u0430 \u043f\u043e\u0442\u043e\u043c\u0443 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f   \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043e\u0442\u0441\u0435\u0447\u0435\u043d\u0438\u044f.   \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 \u0448\u0435\u0439\u0434\u0435\u0440\u0430\u0445 WebGL 1, \u0430 \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 \u043c\u043e\u0436\u0435\u0442 \u043d\u0438 \u043d\u0430 \u0447\u0442\u043e \u043d\u0435 \u0432\u043b\u0438\u044f\u0442\u044c *\/precision highp float;\/* UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0438\u0437 \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430 *\/varying vec2 uv;\/* \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044e. \u0414\u043b\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u043f\u0438\u043a\u0441\u0435\u043b\u044e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u044c   `UV Coordinate \/ frameSize`. \u041d\u0430 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0438 \u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0447\u0443\u0442\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435,   \u0447\u0435\u043c \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435. \u0422\u0430\u043a \u043a\u0430\u043a \u0448\u0435\u0439\u0434\u0435\u0440 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u043f\u0438\u043a\u0441\u0435\u043b\u044c\u043d\u043e, \u043c\u044b \u0438\u0437\u0431\u0435\u0436\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u0435\u043b\u0435\u043d\u0438\u044f   \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f, \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443 1 \/ frameSize \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0435\u0451   \u0432 \u0448\u0435\u0439\u0434\u0435\u0440. \u041e\u0447\u0435\u043d\u044c \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0430\u044f \u043c\u0438\u043a\u0440\u043e\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0438 *\/uniform vec2 frameSizeRCP;uniform float samplePosMult; \/* \u0423\u043c\u043d\u043e\u0436\u0430\u0435\u043c, \u0447\u0442\u043e\u0431\u044b \u0441\u0438\u043b\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u043b\u0430 \u0440\u0430\u0437\u043c\u0435\u0440 \u044f\u0434\u0440\u0430 *\/uniform float bloomStrength; \/* \u0441\u0438\u043b\u0430 bloom *\/uniform sampler2D texture;\/* `KERNEL_SIZE` \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 *\/const int kernel_size = KERNEL_SIZE;void main() {\/* \u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430 \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f *\/vec4 sum = vec4(0.0);\/* \u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0441\u044d\u043c\u043f\u043b\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0430 *\/const int size = 2 * kernel_size + 1;\/* \u041e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u044d\u043c\u043f\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0441\u0447\u0438\u0442\u0430\u0435\u043c *\/const float totalSamples = float(size * size);\/* \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0437 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b Y \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0441\u0432\u0435\u0440\u0445\u0443 \u0438 \u0441\u043d\u0438\u0437\u0443 *\/for (int y = -kernel_size; y &lt;= kernel_size; ++y) {\/* \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0437 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b X \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0441\u043b\u0435\u0432\u0430 \u0438 \u0441\u043f\u0440\u0430\u0432\u0430 *\/for (int x = -kernel_size; x &lt;= kernel_size; ++x) {\/* \u0421\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0435\u0435, \u043a\u0430\u043a\u043e\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c *\/vec2 offset = vec2(x, y) * samplePosMult * frameSizeRCP;\/* \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438 \u043f\u0440\u0438\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u043a\u043b\u0430\u0434 \u044d\u0442\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f *\/sum += texture2D(texture, uv + offset);}}\/* \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0441\u0443\u043c\u043c\u0443, \u043f\u043e\u0434\u0435\u043b\u0451\u043d\u043d\u0443\u044e \u043d\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u044d\u043c\u043f\u043b\u043e\u0432 (\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f) *\/gl_FragColor = (sum \/ totalSamples) * bloomStrength;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>WebGL Javascript<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">import * as util from '..\/utility.js'export async function setupBoxBlur() {\/* \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f *\/const WebGLBox = document.getElementById('WebGLBox-BoxBlur');const WebGLBoxDetail = document.getElementById('WebGLBox-BoxBlurDetail');const canvas = WebGLBox.querySelector('canvas');\/* \u0420\u0430\u0437\u043c\u0435\u0440 \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043e\u043a\u0440\u0443\u0436\u043d\u043e\u0441\u0442\u0438 *\/const radius = 0.12;\/* \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 WebGL 1.0 *\/const gl = canvas.getContext('webgl', {preserveDrawingBuffer: false,antialias: false,alpha: false,});\/* \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b *\/const ctx = {\/* \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043b\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 *\/mode: \"scene\",flags: { isRendering: false, buffersInitialized: false, initComplete: false, benchMode: false },\/* \u0422\u0435\u043a\u0441\u0442\u0443\u0440\u044b *\/tex: { sdr: null, selfIllum: null, frame: null, frameFinal: null },\/* \u0411\u0443\u0444\u0435\u0440\u044b \u043a\u0430\u0434\u0440\u043e\u0432 *\/fb: { scene: null, final: null },\/* \u0428\u0435\u0439\u0434\u0435\u0440\u044b \u0438 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 *\/shd: {scene: { handle: null, uniforms: { offset: null, radius: null } },blur: { handle: null, uniforms: { frameSizeRCP: null, samplePosMult: null, bloomStrength: null } },bloom: { handle: null, uniforms: { offset: null, radius: null, texture: null, textureAdd: null } }}};\/* \u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b UI *\/const ui = {display: {spinner: canvas.parentElement.querySelector('svg', canvas.parentElement),contextLoss: canvas.parentElement.querySelector('div', canvas.parentElement),fps: WebGLBox.querySelector('#fps'),ms: WebGLBox.querySelector('#ms'),width: WebGLBox.querySelector('#width'),height: WebGLBox.querySelector('#height'),tapsCount: WebGLBox.querySelector('#taps'),},blur: {kernelSize: WebGLBox.querySelector('#sizeRange'),samplePos: WebGLBox.querySelector('#samplePosRange'),samplePosReset: WebGLBox.querySelector('#samplePosRangeReset'),},rendering: {animate: WebGLBox.querySelector('#animateCheck'),modes: WebGLBox.querySelectorAll('input[type=\"radio\"]'),lightBrightness: WebGLBox.querySelector('#lightBrightness'),lightBrightnessReset: WebGLBox.querySelector('#lightBrightnessReset'),},benchmark: {button: WebGLBox.querySelector('#benchmark'),label: WebGLBox.querySelector('#benchmarkLabel'),iterOut: WebGLBox.querySelector('#iterOut'),renderer: WebGLBoxDetail.querySelector('#renderer'),iterTime: WebGLBoxDetail.querySelector('#iterTime'),tapsCount: WebGLBoxDetail.querySelector('#tapsCountBench'),iterations: WebGLBox.querySelector('#iterations')}};\/* \u0428\u0435\u0439\u0434\u0435\u0440\u044b *\/const circleAnimation = await util.fetchShader(\"shader\/circleAnimation.vs\");const simpleTexture = await util.fetchShader(\"shader\/simpleTexture.fs\");const bloomVert = await util.fetchShader(\"shader\/bloom.vs\");const bloomFrag = await util.fetchShader(\"shader\/bloom.fs\");const simpleQuad = await util.fetchShader(\"shader\/simpleQuad.vs\");const boxBlurFrag = await util.fetchShader(\"shader\/boxBlur.fs\");\/* \u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0431\u0435\u0437 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 *\/ui.blur.kernelSize.addEventListener('input', () =&gt; { if (!ui.rendering.animate.checked) redraw() });ui.blur.samplePos.addEventListener('input', () =&gt; { if (!ui.rendering.animate.checked) redraw() });ui.rendering.lightBrightness.addEventListener('input', () =&gt; { if (!ui.rendering.animate.checked) redraw() });\/* \u0421\u043e\u0431\u044b\u0442\u0438\u044f *\/ui.rendering.animate.addEventListener(\"change\", () =&gt; {if (ui.rendering.animate.checked)startRendering();else {ui.display.fps.value = \"-\";ui.display.ms.value = \"-\";ctx.flags.isRendering = false;redraw()}});canvas.addEventListener(\"webglcontextlost\", () =&gt; {ui.display.contextLoss.style.display = \"block\";});ui.blur.kernelSize.addEventListener('input', () =&gt; {reCompileBlurShader(ui.blur.kernelSize.value);ui.blur.samplePos.disabled = ui.blur.kernelSize.value == 0;ui.blur.samplePosReset.disabled = ui.blur.kernelSize.value == 0;});\/* \u0420\u0435\u0436\u0438\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 *\/ui.rendering.modes.forEach(radio =&gt; {\/* \u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 scene, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u044c \u0431\u0430\u0433 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432 Firefox Android *\/if (radio.value === \"scene\")radio.checked = true;radio.addEventListener('change', (event) =&gt; {ctx.mode = event.target.value;ui.rendering.lightBrightness.disabled = ctx.mode === \"scene\";ui.rendering.lightBrightnessReset.disabled = ctx.mode === \"scene\";if (!ui.rendering.animate.checked) redraw();});});ui.benchmark.button.addEventListener(\"click\", () =&gt; {ctx.flags.benchMode = true;stopRendering();ui.display.spinner.style.display = \"block\";ui.benchmark.button.disabled = true;\/* \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432\u043e\u0440\u043a\u0435\u0440\u0430 (\u043c\u043e\u0434\u0443\u043b\u044c ES) *\/const worker = new Worker(\".\/js\/benchmark\/boxBlurBenchmark.js\", { type: \"module\" });\/* \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u044b \u0432\u043e\u0440\u043a\u0435\u0440\u0443 *\/worker.postMessage({iterations: ui.benchmark.iterOut.value,blurShaderSrc: boxBlurFrag,kernelSize: ui.blur.kernelSize.value,samplePos: ui.blur.samplePos.value});\/* \u0411\u0435\u043d\u0447\u043c\u0430\u0440\u043a *\/worker.addEventListener(\"message\", (event) =&gt; {if (event.data.type !== \"done\") return;ui.benchmark.label.textContent = event.data.benchText;ui.benchmark.tapsCount.textContent = event.data.tapsCount;ui.benchmark.iterTime.textContent = event.data.iterationText;ui.benchmark.renderer.textContent = event.data.renderer;worker.terminate();ui.benchmark.button.disabled = false;ctx.flags.benchMode = false;if (ui.rendering.animate.checked)startRendering();elseredraw();});});ui.benchmark.iterations.addEventListener(\"change\", (event) =&gt; {ui.benchmark.iterOut.value = event.target.value;ui.benchmark.label.textContent = \"Benchmark\";});\/* \u0428\u0435\u0439\u0434\u0435\u0440 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u0442\u0435\u043a\u0441\u0442\u0443\u0440 *\/ctx.shd.scene = util.compileAndLinkShader(gl, circleAnimation, simpleTexture, [\"offset\", \"radius\"]);\/* \u0428\u0435\u0439\u0434\u0435\u0440 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 bloom *\/ctx.shd.bloom = util.compileAndLinkShader(gl, bloomVert, bloomFrag, [\"texture\", \"textureAdd\", \"offset\", \"radius\"]);\/* \u0412\u0441\u043f\u043e\u043c\u043e\u043d\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 *\/function reCompileBlurShader(blurSize) {ctx.shd.blur = util.compileAndLinkShader(gl, simpleQuad, boxBlurFrag, [\"frameSizeRCP\", \"samplePosMult\", \"bloomStrength\"], \"#define KERNEL_SIZE \" + blurSize + '\\n');}\/* \u0428\u0435\u0439\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f *\/reCompileBlurShader(ui.blur.kernelSize.value)\/* \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0432 GPU *\/util.bindUnitQuad(gl);async function setupTextureBuffers() {ui.display.spinner.style.display = \"block\";ctx.flags.buffersInitialized = true;ctx.flags.initComplete = false;gl.deleteFramebuffer(ctx.fb.scene);gl.deleteFramebuffer(ctx.fb.final);[ctx.fb.scene, ctx.tex.frame] = util.setupFramebuffer(gl, canvas.width, canvas.height);[ctx.fb.final, ctx.tex.frameFinal] = util.setupFramebuffer(gl, canvas.width, canvas.height);let [base, selfIllum] = await Promise.all([fetch(\"\/dual-kawase\/img\/SDR_No_Sprite.png\"),fetch(\"\/dual-kawase\/img\/Selfillumination.png\")]);let [baseBlob, selfIllumBlob] = await Promise.all([base.blob(), selfIllum.blob()]);let [baseBitmap, selfIllumBitmap] = await Promise.all([createImageBitmap(baseBlob, { colorSpaceConversion: 'none', resizeWidth: canvas.width * 1.12, resizeHeight: canvas.height * 1.12, resizeQuality: \"high\" }),createImageBitmap(selfIllumBlob, { colorSpaceConversion: 'none', resizeWidth: canvas.width * 1.12, resizeHeight: canvas.height * 1.12, resizeQuality: \"high\" })]);ctx.tex.sdr = util.setupTexture(gl, null, null, ctx.tex.sdr, gl.LINEAR, baseBitmap);ctx.tex.selfIllum = util.setupTexture(gl, null, null, ctx.tex.selfIllum, gl.LINEAR, selfIllumBitmap);baseBitmap.close();selfIllumBitmap.close();ctx.flags.initComplete = true;ui.display.spinner.style.display = \"none\";}let prevNow = performance.now();let lastStatsUpdate = prevNow;let fpsEMA = 60;let msEMA = 16;async function redraw() {if (!ctx.flags.buffersInitialized)await setupTextureBuffers();if (!ctx.flags.initComplete)return;\/* UI \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 *\/const KernelSizeSide = ui.blur.kernelSize.value * 2 + 1;const tapsNewText = (canvas.width * canvas.height * KernelSizeSide * KernelSizeSide \/ 1000000).toFixed(1) + \" Million\";ui.display.tapsCount.value = tapsNewText;ui.display.width.value = canvas.width;ui.display.height.value = canvas.height;\/* \u041a\u0440\u0443\u0433\u043e\u0432\u043e\u0435 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 *\/let radiusSwitch = ui.rendering.animate.checked ? radius : 0.0;let speed = (performance.now() \/ 10000) % Math.PI * 2;const offset = [radiusSwitch * Math.cos(speed), radiusSwitch * Math.sin(speed)];gl.useProgram(ctx.shd.scene.handle);const texture = ctx.mode == \"scene\" ? ctx.tex.sdr : ctx.tex.selfIllum;gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, texture);gl.uniform2fv(ctx.shd.scene.uniforms.offset, offset);gl.uniform1f(ctx.shd.scene.uniforms.radius, radiusSwitch);\/* \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0431\u0443\u0444\u0435\u0440\u0430 \u043a\u0430\u0434\u0440\u043e\u0432 \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 *\/gl.bindFramebuffer(gl.FRAMEBUFFER, ctx.fb.scene);gl.viewport(0, 0, canvas.width, canvas.height);\/* \u0412\u044b\u0437\u043e\u0432 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 *\/gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);\/* Box blur \u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c *\/gl.useProgram(ctx.shd.blur.handle);const finalFB = ctx.mode == \"bloom\" ? ctx.fb.final : null;gl.bindFramebuffer(gl.FRAMEBUFFER, finalFB);gl.viewport(0, 0, canvas.width, canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.bloomStrength, ctx.mode == \"scene\" ? 1.0 : ui.rendering.lightBrightness.value);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.frame);gl.uniform2f(ctx.shd.blur.uniforms.frameSizeRCP, 1.0 \/ canvas.width, 1.0 \/ canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.samplePosMult, ui.blur.samplePos.value);gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);if (ctx.mode == \"bloom\") {\/* \u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u0438\u043d\u0433 bloom \u043d\u0430 \u044d\u043a\u0440\u0430\u043d *\/gl.bindFramebuffer(gl.FRAMEBUFFER, null);gl.useProgram(ctx.shd.bloom.handle);gl.uniform2fv(ctx.shd.bloom.uniforms.offset, offset);gl.uniform1f(ctx.shd.bloom.uniforms.radius, radiusSwitch);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.sdr);gl.uniform1i(ctx.shd.bloom.uniforms.texture, 0);gl.activeTexture(gl.TEXTURE1);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.frameFinal);gl.uniform1i(ctx.shd.bloom.uniforms.textureAdd, 1);gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);}\/* \u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e CPU \u0438 GPU, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0443 GPU \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u0438\u043d\u0433\u0430.   \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u044d\u0442\u043e, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u0441\u0431\u0440\u043e\u0441\u0443,   \u043d\u043e \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445 \u043f\u0440\u0438 \u043d\u0438\u0437\u043a\u0438\u0445 FPS *\/gl.finish();const now = performance.now();let dt = now - prevNow;if (dt &gt; 0) {const instFPS = 1000 \/ dt;const ALPHA = 0.05;fpsEMA = ALPHA * instFPS + (1 - ALPHA) * fpsEMA;msEMA = ALPHA * dt + (1 - ALPHA) * msEMA;}prevNow = now;if (ui.rendering.animate.checked &amp;&amp; now - lastStatsUpdate &gt;= 1000) {ui.display.fps.value = fpsEMA.toFixed(0);ui.display.ms.value = msEMA.toFixed(2);lastStatsUpdate = now;}}let animationFrameId;\/* \u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u043f\u0440\u0438 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0438 *\/function nativeResize() {const [width, height] = util.getNativeSize(canvas);if (width &amp;&amp; canvas.width !== width || height &amp;&amp; canvas.height !== height) {canvas.width = width;canvas.height = height;if (!ctx.flags.benchMode) {stopRendering();startRendering();}if (!ui.rendering.animate.checked)redraw();}}\/* \u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u0430 *\/nativeResize();let resizePending = false;window.addEventListener('resize', () =&gt; {if (!resizePending) {resizePending = true;requestAnimationFrame(() =&gt; {resizePending = false;nativeResize();});}});function renderLoop() {if (ctx.flags.isRendering &amp;&amp; ui.rendering.animate.checked) {redraw();animationFrameId = requestAnimationFrame(renderLoop);}}function startRendering() {\/* \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433, \u043a\u043e\u0433\u0434\u0430 \u0432\u0438\u0434\u0435\u043d canvas *\/ctx.flags.isRendering = true;renderLoop();}function stopRendering() {\/* \u041f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0432\u044b\u0437\u043e\u0432 \u0435\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0438 *\/ctx.flags.isRendering = false;cancelAnimationFrame(animationFrameId);\/* \u0417\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441 CPU, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0432\u043c\u0435\u0448\u0430\u0435\u043c\u0441\u044f \u0432 \u043d\u0435\u0433\u043e *\/gl.finish();\/* \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0431\u0443\u0444\u0435\u0440\u044b, \u0447\u0442\u043e\u0431\u044b \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c *\/gl.deleteTexture(ctx.tex.sdr); ctx.tex.sdr = null;gl.deleteTexture(ctx.tex.selfIllum); ctx.tex.selfIllum = null;gl.deleteTexture(ctx.tex.frame); ctx.tex.frame = null;gl.deleteTexture(ctx.tex.frameFinal); ctx.tex.frameFinal = null;gl.deleteFramebuffer(ctx.fb.scene); ctx.fb.scene = null;gl.deleteFramebuffer(ctx.fb.final); ctx.fb.final = null;ctx.flags.buffersInitialized = false;ctx.flags.initComplete = false;ui.display.fps.value = \"-\";ui.display.ms.value = \"-\";}function handleIntersection(entries) {entries.forEach(entry =&gt; {if (entry.isIntersecting) {if (!ctx.flags.isRendering &amp;&amp; !ctx.flags.benchMode) startRendering();} else {stopRendering();}});}\/* \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433, \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u0433\u0434\u0430 canvas \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 *\/let observer = new IntersectionObserver(handleIntersection);observer.observe(canvas);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u043e. \u0427\u0435\u043c \u0441\u0438\u043b\u044c\u043d\u0435\u0435 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435, \u0442\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u00ab\u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u044b\u043c\u0438\u00bb \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u042d\u0442\u043e \u0432\u044b\u0437\u0432\u0430\u043d\u043e \u0442\u0435\u043c, \u0447\u0442\u043e \u043c\u044b \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438 \u0443\u0441\u0440\u0435\u0434\u043d\u044f\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u0443 \u043f\u043e \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0443. \u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u043e\u0441\u0432\u0435\u0449\u0435\u043d\u0438\u044f \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u0432 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u044b, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 bloom \u0441 \u0441\u0438\u043b\u044c\u043d\u043e\u0439 <code>lightBrightness<\/code>\u00a0\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u043c <code>kernelSize<\/code>.<\/p>\n<p>\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0442\u043e\u0436\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043b\u043e\u0445\u0430. \u041f\u0440\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 <code>kernelSize<\/code> \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e <code>Texture Taps<\/code>\u00a0\u0432\u0437\u043b\u0435\u0442\u0430\u0435\u0442 \u0434\u043e \u043d\u0435\u0431\u0435\u0441, \u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u0430\u0434\u0430\u0435\u0442. \u041c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442 \u0441\u0438\u043b\u044c\u043d\u043e \u0442\u043e\u0440\u043c\u043e\u0437\u0438\u0442\u044c. \u0414\u0430\u0436\u0435 \u0441\u0430\u043c\u044b\u0435 \u0431\u044b\u0441\u0442\u0440\u044b\u0435 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043a\u0430\u0440\u0442\u044b PC \u043f\u0440\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0438 <code>kernelSize<\/code>\u00a0\u0438 \u0437\u0443\u043c\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u043d\u0430 PC \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442 \u043d\u0435 \u043f\u043e\u0441\u043f\u0435\u0432\u0430\u0442\u044c \u0437\u0430 \u0447\u0430\u0441\u0442\u043e\u0442\u043e\u0439 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u044d\u043a\u0440\u0430\u043d\u0430.<\/p>\n<blockquote>\n<p><em>\u041f\u0440\u043e\u0432\u0430\u043b \u043f\u043e \u0432\u0441\u0435\u043c \u0444\u0440\u043e\u043d\u0442\u0430\u043c. \u0418 \u043d\u0435\u043a\u0440\u0430\u0441\u0438\u0432\u043e, \u0438 \u0442\u043e\u0440\u043c\u043e\u0437\u0438\u0442.<\/em><\/p>\n<\/blockquote>\n<p>\u0415\u0449\u0451 \u0435\u0441\u0442\u044c \u044d\u0442\u043e\u0442 <code>samplePosMultiplier<\/code>. \u041f\u043e\u0445\u043e\u0436\u0435, \u043e\u043d <em>\u0442\u043e\u0436\u0435<\/em> \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u0438\u043b\u0443 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f, <em>\u043d\u0435 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u044f<\/em> \u043f\u0440\u0438 \u044d\u0442\u043e\u043c textureTaps \u0438 \u043d\u0435 \u0441\u043d\u0438\u0436\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c (\u0438\u043b\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u043d\u0438\u0436\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445). \u041d\u043e \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u043d\u0435\u0442 <em>\u0441\u043b\u0438\u0448\u043a\u043e\u043c<\/em> \u0431\u043e\u043b\u044c\u0448\u0438\u043c, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0432 \u0432\u0438\u0434\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0445\u0441\u044f \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u043e \u0441\u0445\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c (\u0432 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u043e\u043d \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u0435\u043d):<\/p>\n<ul>\n<li>\n<p>\u0411\u0435\u043b\u044b\u0439 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u0432\u0430\u0434\u0440\u0430\u0442 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c<\/p>\n<\/li>\n<li>\n<p>\u0421\u0435\u0440\u044b\u0435 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u044b \u2014 \u044d\u0442\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c <code>kernelSize<\/code> \u0438 \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f <code>samplePosMult<\/code><\/p>\n<\/li>\n<li>\n<p>\u0447\u0451\u0440\u043d\u044b\u0435 \u0442\u043e\u0447\u043a\u0438 \u2014 \u044d\u0442\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b <strong><em>\u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c<\/em><\/strong>, \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u00ab\u0441\u044d\u043c\u043f\u043b\u043e\u0432\u00bb<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0c1\/a76\/faa\/0c1a76faa15681e330a0902ba504bba1.png\" alt=\"kernelSize 3x3, samplePosMult 100%\" title=\"kernelSize 3x3, samplePosMult 100%\" width=\"684\" height=\"513\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/0c1\/a76\/faa\/0c1a76faa15681e330a0902ba504bba1.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0c1\/a76\/faa\/0c1a76faa15681e330a0902ba504bba1.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>kernelSize 3&#215;3, samplePosMult 100%<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/11a\/99c\/766\/11a99c76623cd2e7ab8f83097e652151.png\" alt=\"kernelSize 17x17, samplePosMult 170%\" title=\"kernelSize 17x17, samplePosMult 170%\" width=\"684\" height=\"513\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/11a\/99c\/766\/11a99c76623cd2e7ab8f83097e652151.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/11a\/99c\/766\/11a99c76623cd2e7ab8f83097e652151.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>kernelSize 17&#215;17, samplePosMult 170%<\/figcaption><\/div>\n<\/figure>\n<p>\u041c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u2014 \u00ab\u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u044b\u0439 2D-\u0441\u0438\u0433\u043d\u0430\u043b\u00bb. \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u0443 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0439 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0435, \u043c\u044b <em>\u0441\u044d\u043c\u043f\u043b\u0438\u0440\u0443\u0435\u043c \u00ab\u0441\u0438\u0433\u043d\u0430\u043b \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u00bb \u0432 \u044d\u0442\u043e\u0439 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0435<\/em>. \u041a\u0430\u043a \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u043e\u0441\u044c \u0432\u044b\u0448\u0435, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0438 \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u044b \u0442\u0430\u043a\u0438\u043c\u0438 \u043f\u043e\u043d\u044f\u0442\u0438\u044f\u043c\u0438, \u043a\u0430\u043a \u00ab\u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439\u00bb.\u00a0<strong><em>\u0413\u0434\u0435 <\/em><\/strong>\u043c\u044b \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u0441\u044d\u043c\u043f\u043b\u044b, \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043e\u0442 \u043d\u0430\u0441.<\/p>\n<p>\u041e\u0434\u0438\u043d \u0438\u0437 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u043f\u0440\u0438\u0451\u043c\u043e\u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u2014 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432\u044b\u0431\u043e\u0440\u043e\u043a \u043e\u0442 \u0446\u0435\u043d\u0442\u0440\u0430, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043e\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u044f \u043e\u0431\u0440\u0430\u0437\u0446\u0430\u043c\u0438 \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u044f \u0431\u043e\u043b\u044c\u0448\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0430 \u043e\u0442 \u0442\u043e\u0433\u043e \u0436\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u044b\u0431\u043e\u0440\u043e\u043a.<\/p>\n<p>\u042d\u0442\u043e \u0434\u043e\u0441\u0442\u0438\u0433\u0430\u0435\u0442\u0441\u044f \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 <code>samplePosMult<\/code>, \u0438 \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432\u0430\u043c \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0431\u043e\u0440\u0449\u0438\u0442\u044c, \u043f\u043e\u044f\u0432\u044f\u0442\u0441\u044f \u043d\u0435\u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e \u0442\u043e\u043c, \u043e\u0442\u043a\u0443\u0434\u0430 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u0435 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0438 \u0447\u0442\u043e \u0432\u043e\u043e\u0431\u0449\u0435 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u0447\u0442\u0435\u043d\u0438\u0435\u043c \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u043c\u0438.\u00a0\u0418 \u043a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f! \u041d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430\u2026<\/p>\n<h4>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u044f\u0434\u0440\u043e?\u00a0<\/h4>\n<p>\u0422\u043e, \u0447\u0442\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0446\u0438\u043a\u043b\u0430 for, \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <a href=\"https:\/\/www.youtube.com\/watch?v=KuXjwB4LzSA0\" rel=\"noopener noreferrer nofollow\">\u0441\u0432\u0451\u0440\u0442\u043a\u043e\u0439<\/a>. \u0415\u0441\u043b\u0438 \u0441\u0438\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c, \u0442\u043e \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u044d\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u043a\u0432\u0430\u0434\u0440\u0430\u0442 \u0438\u0437 \u0447\u0438\u0441\u0435\u043b, \u0441\u043e\u0437\u0434\u0430\u044e\u0449\u0438\u0445 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0441\u0431\u043e\u0440\u0430 \u0438 \u0432\u0437\u0432\u0435\u0448\u0438\u0432\u0430\u043d\u0438\u044f \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439, \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u044d\u0442\u0438\u043c \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043e\u043c. \u042d\u0442\u043e\u0442 \u043a\u0432\u0430\u0434\u0440\u0430\u0442 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u044f\u0434\u0440\u043e\u043c, \u0438 \u0438\u043c\u0435\u043d\u043d\u043e \u0435\u0433\u043e \u043c\u044b \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0432\u044b\u0448\u0435.<\/p>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0432\u0435\u0441\u0430 \u044f\u0434\u0440\u0430 \u0434\u043e\u043b\u0436\u043d\u044b \u0432 \u0441\u0443\u043c\u043c\u0435 \u0434\u0430\u0432\u0430\u0442\u044c 1. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043d\u0435 \u0442\u0430\u043a, \u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0438\u043b\u0438 \u043e\u0441\u0432\u0435\u0442\u043b\u0438\u0442\u044c, \u0438\u043b\u0438 \u0437\u0430\u0442\u0435\u043c\u043d\u0438\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u044d\u0442\u0430\u043f \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441 box blur \u044d\u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0441\u0443\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430 \u043f\u0438\u043a\u0441\u0435\u043b\u044f \u043d\u0430 <code>totalSamples<\/code>, \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0430 \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0437\u044f\u0442\u044b\u0445 \u0441\u044d\u043c\u043f\u043b\u043e\u0432. \u041f\u0440\u043e\u0441\u0442\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0441\u0440\u0435\u0434\u043d\u0435\u0433\u043e.<\/p>\n<p>\u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c, \u043a\u0430\u043a \u0432\u0435\u0441\u0430 \u044f\u0434\u0440\u0430 \u2014 \u0447\u0438\u0441\u043b\u043e, \u0443\u043c\u043d\u043e\u0436\u0430\u0435\u043c\u043e\u0435 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0441\u044d\u043c\u043f\u043b \u0432 \u044d\u0442\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438. \u0422\u0430\u043a \u043a\u0430\u043a \u0432 box blur \u0432\u0441\u0435 \u0441\u044d\u043c\u043f\u043b\u044b \u0438\u043c\u0435\u044e\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u0432\u0435\u0441\u0430, \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u043e\u0437\u0438\u0446\u0438\u0438, \u0432\u0441\u0435 \u0432\u0435\u0441\u0430 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b. \u042d\u0442\u043e \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043d\u0438\u0436\u0435. \u0427\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0440\u0430\u0437\u043c\u0435\u0440 \u044f\u0434\u0440\u0430, \u0442\u0435\u043c \u043c\u0435\u043d\u044c\u0448\u0435 \u0432\u0435\u0441\u0430.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fbe\/6dc\/273\/fbe6dc2736f091160492c06a4f68a421.png\" alt=\"kernelSize 3x3, samplePosMult 100%\" title=\"kernelSize 3x3, samplePosMult 100%\" width=\"684\" height=\"513\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/fbe\/6dc\/273\/fbe6dc2736f091160492c06a4f68a421.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fbe\/6dc\/273\/fbe6dc2736f091160492c06a4f68a421.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>kernelSize 3&#215;3, samplePosMult 100%<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/571\/a51\/754\/571a51754befd2173fec732d19f3e818.png\" alt=\"kernelSize 7x7, samplePosMult 200%\" title=\"kernelSize 7x7, samplePosMult 200%\" width=\"684\" height=\"513\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/571\/a51\/754\/571a51754befd2173fec732d19f3e818.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/571\/a51\/754\/571a51754befd2173fec732d19f3e818.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>kernelSize 7&#215;7, samplePosMult 200%<\/figcaption><\/div>\n<\/figure>\n<p>\u042f\u0434\u0440\u0430, \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0435 \u043a \u043a\u0440\u0430\u044f\u043c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0438\u0437 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u00ab\u0441\u043d\u0430\u0440\u0443\u0436\u0438\u00bb \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441 UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438 \u043c\u0435\u043d\u044c\u0448\u0435 <code>0,0<\/code>\u00a0\u0438\u043b\u0438 \u0431\u043e\u043b\u044c\u0448\u0435 <code>1,1<\/code>. \u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, GPU \u0441\u0430\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u044d\u0442\u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439 \u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0440\u0435\u0448\u0430\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442 \u0441 \u044d\u0442\u0438\u043c\u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u043c\u0438 \u0441\u044d\u043c\u043f\u043b\u0430\u043c\u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0432\u044b\u0431\u043e\u0440\u0430 <a href=\"https:\/\/learnopengl.com\/Getting-started\/Textures#:~:text=Texture%20Wrapping\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u0436\u0438\u043c\u0430 \u043e\u0431\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b (Texture Wrapping)<\/a>.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2be\/55c\/6fa\/2be55c6faa09dbf13df4a16f6e0dec7b.png\" alt=\"Texture Wrapping Modes and results on blurring\" title=\"\u0420\u0435\u0436\u0438\u043c\u044b Texture Wrapping \u0438 \u0438\u0445 \u0432\u043b\u0438\u044f\u043d\u0438\u0435 \u043d\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 (\u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0441\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u0447\u0451\u0440\u043d\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430) \u041d\u0430\u0432\u0435\u0440\u0445\u0443: \u0431\u0443\u0444\u0435\u0440 \u043a\u0430\u0434\u0440\u043e\u0432.\u00a0\u0412\u043d\u0438\u0437\u0443: \u043d\u043e\u0440\u043c\u0430\u043b\u0438 \u0431\u0443\u0444\u0435\u0440\u0430 \u043a\u0430\u0434\u0440\u043e\u0432 \u0441 \u043f\u0440\u0438\u043c\u0435\u043d\u0451\u043d\u043d\u044b\u043c \u0441\u0438\u043b\u044c\u043d\u044b\u043c \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435\u043c\" width=\"1395\" height=\"1111\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/2be\/55c\/6fa\/2be55c6faa09dbf13df4a16f6e0dec7b.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2be\/55c\/6fa\/2be55c6faa09dbf13df4a16f6e0dec7b.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0435\u0436\u0438\u043c\u044b Texture Wrapping \u0438 \u0438\u0445 \u0432\u043b\u0438\u044f\u043d\u0438\u0435 \u043d\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 (\u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0441\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u0447\u0451\u0440\u043d\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430) <strong>\u041d\u0430\u0432\u0435\u0440\u0445\u0443<\/strong>: \u0431\u0443\u0444\u0435\u0440 \u043a\u0430\u0434\u0440\u043e\u0432.\u00a0<strong>\u0412\u043d\u0438\u0437\u0443<\/strong>: \u043d\u043e\u0440\u043c\u0430\u043b\u0438 \u0431\u0443\u0444\u0435\u0440\u0430 \u043a\u0430\u0434\u0440\u043e\u0432 \u0441 \u043f\u0440\u0438\u043c\u0435\u043d\u0451\u043d\u043d\u044b\u043c \u0441\u0438\u043b\u044c\u043d\u044b\u043c \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435\u043c<\/figcaption><\/div>\n<\/figure>\n<p>\u0421\u0440\u0435\u0434\u0438 \u043f\u0440\u043e\u0447\u0435\u0433\u043e, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0434\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0441\u043f\u043b\u043e\u0448\u043d\u043e\u0439 \u0446\u0432\u0435\u0442, \u0438\u043b\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c\u0441\u044f (clamp) \u0446\u0432\u0435\u0442\u043e\u043c \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0433\u043e \u043a\u0440\u0430\u044f. \u0415\u0441\u043b\u0438 \u043c\u044b \u0432\u044b\u0431\u0435\u0440\u0435\u043c \u0441\u043f\u043b\u043e\u0448\u043d\u043e\u0439 \u0446\u0432\u0435\u0442, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043f\u0440\u043e\u0441\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u0446\u0432\u0435\u0442\u0430 \u043f\u043e \u043a\u0440\u0430\u044f\u043c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0447\u0442\u0438 \u0434\u043b\u044f \u0432\u0441\u0435\u0439 \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0446\u0432\u0435\u0442\u0430 \u043a\u0440\u0430\u0451\u0432, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d\u043e \u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044e \u043f\u043e \u043a\u0440\u0430\u044f\u043c.\u00a0<a href=\"https:\/\/github.com\/FrostKiwi\/treasurechest\/blob\/main\/posts\/dual-kawase\/js\/utility.js#L49\" rel=\"noopener noreferrer nofollow\">\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0442\u0430\u043a \u0436\u0435<\/a>.<\/p>\n<blockquote>\n<p><em>\u041c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0447\u0451\u0440\u043d\u043e\u0435 \u00ab\u043f\u044f\u0442\u043d\u043e\u00bb \u043f\u043e \u043d\u0438\u0437\u0443, \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u044e\u0449\u0435\u0435\u0441\u044f \u043f\u0440\u0438 \u0432\u044b\u0441\u043e\u043a\u0438\u0445 \u0443\u0440\u043e\u0432\u043d\u044f\u0445 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f. \u041a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u0437\u0434\u0435\u0441\u044c \u043e\u043d\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043b\u0438\u043d\u0438\u0438 \u043f\u043b\u0438\u0442\u043e\u043a \u043f\u043e\u043b\u0430 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 \u0441 \u043d\u0438\u0436\u043d\u0438\u043c \u043a\u0440\u0430\u0435\u043c, \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u044f \u0447\u0451\u0440\u043d\u044b\u0439 \u0446\u0432\u0435\u0442 \u0432 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0441\u0442\u044c.<\/em><\/p>\n<\/blockquote>\n<p>\u0421\u0432\u0451\u0440\u0442\u043a\u0430 \u2014 \u044d\u0442\u043e \u043d\u0430 \u0443\u0434\u0438\u0432\u043b\u0435\u043d\u0438\u0435 \u0433\u043b\u0443\u0431\u043e\u043a\u043e\u0435 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u043e\u043d\u044f\u0442\u0438\u0435. \u041d\u0430 \u043a\u0430\u043d\u0430\u043b\u0435 <a href=\"https:\/\/www.youtube.com\/@3blue1brown\" rel=\"noopener noreferrer nofollow\">3blue1brown<\/a>\u00a0\u0435\u0441\u0442\u044c \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e\u0435 \u0432\u0438\u0434\u0435\u043e \u043e \u043d\u0451\u043c, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043e\u043d\u043e \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u0438 \u0442\u0435\u043c\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439. \u0422\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043c\u044b \u043d\u0435 \u043e\u0442\u0445\u043e\u0434\u0438\u043c \u043e\u0442 \u0441\u0432\u0451\u0440\u0442\u043e\u043a. \u041c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430\u0448 \u043a\u043e\u0434 \u0438 \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u0438\u0445 \u0432 \u0432\u0438\u0434\u0435 \u0432\u0435\u0441\u043e\u0432 \u0438 \u044f\u0434\u0435\u0440. \u041f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 box blur \u0438 \u0446\u0438\u043a\u043b\u043e\u043c for \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e!<\/p>\n<p><a href=\"https:\/\/embedd.srv.habr.com\/iframe\/68c128d9e474fcb2a36f6cbd\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed_link embed_layout-right\"><\/p>\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;undefined&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>\ud83c\udcad<\/span><\/div>\n<div class=\"embed__caption-description\">undefined&#8230;<\/div>\n<p><span class=\"embed__caption-host\">embedd.srv.habr.com<\/span><\/div>\n<p><\/a><\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043f\u043e\u043d\u044f\u0442\u0438\u044f \u0441\u0432\u0451\u0440\u0442\u043a\u0438, \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0438 \u0442\u0438\u043f\u0430 \u044f\u0434\u0435\u0440 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0432\u0441\u0451 \u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043e\u0442\u0445\u043e\u0434\u0438\u043c \u043e\u0442 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0438 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u0448\u0438\u0440\u043e\u043a\u0438\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u0433\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439. \u041d\u043e \u043f\u043e\u043a\u0430 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u043b\u0430\u0441\u0441\u0438\u043a\u0438:<\/p>\n<h4>\u0413\u0430\u0443\u0441\u0441\u043e\u0432\u043e \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435\u00a0<\/h4>\n<p>\u0421\u0430\u043c\u044b\u0439 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0438\u0437 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u2014 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u043e \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435. \u0412 \u043d\u0451\u043c \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0432\u0435\u0441\u043e\u0432 \u0441\u044d\u043c\u043f\u043b\u043e\u0432 \u0432\u043d\u0443\u0442\u0440\u0438 \u044f\u0434\u0440\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/en.wikipedia.org\/wiki\/Normal_distribution\" rel=\"noopener noreferrer nofollow\">\u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/a>, \u0430 \u043d\u043e\u0432\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <code>sigma \u03c3<\/code>\u00a0\u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u0435\u043c, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043b\u043e\u0441\u043a\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043a\u0440\u0438\u0432\u0430\u044f. \u0417\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0432\u0435\u0441\u043e\u0432 \u044f\u0434\u0435\u0440 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043d\u0438\u0447\u0435\u043c \u043d\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 box blur.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5fd\/a2e\/38e\/5fda2e38eda8f8476a1e6c50241317fb.png\" alt=\"\u0424\u043e\u0440\u043c\u0443\u043b\u0430 \u0432\u0435\u0441\u043e\u0432 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0434\u043b\u044f \u0442\u043e\u0447\u043a\u0438 (x,y)\u00a0(\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a)\" title=\"\u0424\u043e\u0440\u043c\u0443\u043b\u0430 \u0432\u0435\u0441\u043e\u0432 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0434\u043b\u044f \u0442\u043e\u0447\u043a\u0438 (x,y)\u00a0(\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a)\" width=\"400\" height=\"136\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/5fd\/a2e\/38e\/5fda2e38eda8f8476a1e6c50241317fb.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5fd\/a2e\/38e\/5fda2e38eda8f8476a1e6c50241317fb.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0424\u043e\u0440\u043c\u0443\u043b\u0430 \u0432\u0435\u0441\u043e\u0432 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0434\u043b\u044f \u0442\u043e\u0447\u043a\u0438 <code>(x,y)<\/code>\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Gaussian_blur#Mathematics\" rel=\"noopener noreferrer nofollow\">(\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a)<\/a><\/figcaption><\/div>\n<\/figure>\n<p>\u0414\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432\u0435\u0441\u043e\u0432 \u0442\u043e\u0447\u043a\u0438 <code>(x,y)<\/code>  \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d\u043d\u0430\u044f \u0432\u044b\u0448\u0435 \u0444\u043e\u0440\u043c\u0443\u043b\u0430. \u0413\u0430\u0443\u0441\u0441\u043e\u0432\u0430 \u0444\u043e\u0440\u043c\u0443\u043b\u0430 \u0438\u043c\u0435\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u043d\u043e\u0436\u0438\u0442\u0435\u043b\u044c \u0432\u0437\u0432\u0435\u0448\u0438\u0432\u0430\u043d\u0438\u044f <code>1\/(2\u03c0\u03c3\u00b2)<\/code>. \u041e\u0434\u043d\u0430\u043a\u043e \u0432 \u043a\u043e\u0434\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u043d\u0435\u0442. \u0424\u043e\u0440\u043c\u0443\u043b\u0430 \u0432\u044b\u0440\u0430\u0436\u0430\u0435\u0442 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u0443 \u043a\u0440\u0438\u0432\u0443\u044e \u043a\u0430\u043a <em>\u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0443\u044e<\/em>\u00a0\u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u0432\u0438\u0436\u0435\u0442\u0441\u044f \u0432 <em>\u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0441\u0442\u044c<\/em>. \u041d\u043e \u043d\u0430\u0448 \u043a\u043e\u0434 \u0438 \u0435\u0433\u043e \u0446\u0438\u043a\u043b for <strong><em>\u0434\u0438\u0441\u043a\u0440\u0435\u0442\u043d\u044b <\/em><\/strong>\u0438 <strong><em>\u043a\u043e\u043d\u0435\u0447\u043d\u044b<\/em><\/strong>.<\/p>\n<pre><code class=\"cpp\">float gaussianWeight(float x, float y, float sigma){\/* e ^ ( - (x\u00b2 + y\u00b2) \/ 2 \u03c3\u00b2 ) *\/return exp(-(x * x + y * y) \/ (2.0 * sigma * sigma));}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<blockquote>\n<p><em>\u0414\u043b\u044f \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0441\u0442\u0438 \u044f\u0434\u0440\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u043e\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u0435. \u0412 \u043e\u0431\u044b\u0447\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044c. \u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0435 \u0448\u0435\u0439\u0434\u0435\u0440\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f, \u043d\u043e \u0432\u0435\u0441\u0430 \u044f\u0434\u0435\u0440 \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044d\u0442\u043e \u043d\u0435\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e.<\/em><\/p>\n<\/blockquote>\n<p>\u041a\u0430\u043a \u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 box blur, \u0432 \u043a\u043e\u043d\u0446\u0435 \u0432\u0435\u0441\u0430 \u0441\u0443\u043c\u043c\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438 \u0434\u0435\u043b\u044f\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u043e \u0447\u043b\u0435\u043d\u0430 <code>1\/\u221a(2\u03c0\u03c3\u00b2)<\/code>\u00a0, \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u044e\u0449\u0435\u0433\u043e \u0432\u0435\u0441\u0430.\u00a0<code>sigma<\/code>\u00a0\u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0440\u0435\u0437\u043a\u043e\u0441\u0442\u044c\u044e \u043a\u0440\u0438\u0432\u043e\u0439, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442, \u0438 \u0441\u0438\u043b\u043e\u0439 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f, \u043d\u043e \u0440\u0430\u0437\u0432\u0435 \u044d\u0442\u0438\u043c \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043d\u0435 <code>kernelSize<\/code>? \u041f\u043e\u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u044d\u0442\u0438\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u0432 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u043e\u043d\u0438 \u0441\u0435\u0431\u044f \u0432\u0435\u0434\u0443\u0442.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/49f\/39e\/de0\/49f39ede026c61684cc70bcb7d759fd5.png\" alt=\"\u0421\u0446\u0435\u043d\u0430\" title=\"\u0421\u0446\u0435\u043d\u0430\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/49f\/39e\/de0\/49f39ede026c61684cc70bcb7d759fd5.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/49f\/39e\/de0\/49f39ede026c61684cc70bcb7d759fd5.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0446\u0435\u043d\u0430<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cbc\/c5d\/aa0\/cbcc5daa0f8b48b688de45763dba0e3d.png\" alt=\"\u0421\u0432\u0435\u0442\" title=\"\u0421\u0432\u0435\u0442\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/cbc\/c5d\/aa0\/cbcc5daa0f8b48b688de45763dba0e3d.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cbc\/c5d\/aa0\/cbcc5daa0f8b48b688de45763dba0e3d.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0432\u0435\u0442<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a5a\/84c\/dd8\/a5a84cdd8f918fe132175267e1b9a706.png\" alt=\"Bloom\" title=\"Bloom\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/a5a\/84c\/dd8\/a5a84cdd8f918fe132175267e1b9a706.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a5a\/84c\/dd8\/a5a84cdd8f918fe132175267e1b9a706.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>Bloom<\/figcaption><\/div>\n<\/figure>\n<details class=\"spoiler\">\n<summary>\u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">\/* \u0412\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u0441 \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0435\u0439 \u0437\u0430\u043f\u044f\u0442\u043e\u0439 \u043d\u0430 highp, \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f.   \u041f\u0440\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0440\u0430\u0437\u043c\u0435\u0440\u0430\u0445 \u044f\u0434\u0440\u0430 \u043d\u0430 \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u0432\u043b\u0438\u044f\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0446\u0432\u0435\u0442\u043e\u0432, \u0430 \u043f\u043e\u0442\u043e\u043c\u0443 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f   \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043e\u0442\u0441\u0435\u0447\u0435\u043d\u0438\u044f.   \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 \u0448\u0435\u0439\u0434\u0435\u0440\u0430\u0445 WebGL 1, \u0430 \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 \u043c\u043e\u0436\u0435\u0442 \u043d\u0438 \u043d\u0430 \u0447\u0442\u043e \u043d\u0435 \u0432\u043b\u0438\u044f\u0442\u044c *\/precision highp float;\/* UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0438\u0437 \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430 *\/varying vec2 uv;uniform vec2 frameSizeRCP; \/* \u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430, \u043e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044e *\/uniform float samplePosMult; \/* \u0423\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u0441\u0438\u043b\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0431\u044b\u043b\u0430 \u0431\u043e\u043b\u044c\u0448\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u044f\u0434\u0440\u0430 *\/uniform float sigma;uniform float bloomStrength; \/* \u0421\u0438\u043b\u0430 bloom *\/uniform sampler2D texture;\/* `KERNEL_SIZE` \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 *\/const int kernel_size = KERNEL_SIZE;float gaussianWeight(float x, float y, float sigma){\/* e ^ ( - (x\u00b2 + y\u00b2) \/ 2 \u03c3\u00b2 ) *\/return exp(-(x * x + y * y) \/ (2.0 * sigma * sigma));}void main() {\/* \u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f *\/vec4 sum = vec4(0.0);\/* \u0421\u0443\u043c\u043c\u0430 \u0432\u0441\u0435\u0445 \u0432\u0435\u0441\u043e\u0432 *\/float weightSum = 0.0;\/* \u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0441\u044d\u043c\u043f\u043b\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0430 *\/const int size = 2 * kernel_size + 1;\/* \u041e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u044d\u043c\u043f\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c *\/const float totalSamples = float(size * size);\/* \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0437 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b Y \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0441\u0432\u0435\u0440\u0445\u0443 \u0438 \u0441\u043d\u0438\u0437\u0443 *\/for (int y = -kernel_size; y &lt;= kernel_size; ++y) {\/* \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0437 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b X \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0441\u043b\u0435\u0432\u0430 \u0438 \u0441\u043f\u0440\u0430\u0432\u0430 *\/for (int x = -kernel_size; x &lt;= kernel_size; ++x) {\/* \u0412\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0439 \u0432\u0435\u0441 *\/float w = gaussianWeight(float(x), float(y), sigma);\/* \u0421\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0435\u0435, \u043a\u0430\u043a\u043e\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c *\/vec2 offset  = vec2(x, y) * samplePosMult * frameSizeRCP;\/* \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438 \u043f\u0440\u0438\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0437\u0432\u0435\u0448\u0435\u043d\u043d\u044b\u0439 \u0432\u043a\u043b\u0430\u0434 \u044d\u0442\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f *\/sum += texture2D(texture, uv + offset) * w;weightSum += w;}}\/* \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0441\u0443\u043c\u043c\u0443, \u043f\u043e\u0434\u0435\u043b\u0451\u043d\u043d\u0443\u044e \u043d\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u044d\u043c\u043f\u043b\u043e\u0432 (\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f) *\/gl_FragColor = (sum \/ weightSum) * bloomStrength;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>WebGL Javascript<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">import * as util from '..\/utility.js'export async function setupGaussianBlur() {\/* \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f *\/const WebGLBox = document.getElementById('WebGLBox-GaussianBlur');const WebGLBoxDetail = document.getElementById('WebGLBox-GaussianBlurDetail');const canvas = WebGLBox.querySelector('canvas');\/* \u0420\u0430\u0437\u043c\u0435\u0440 \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a\u0440\u0443\u0433\u0430 *\/const radius = 0.12;\/* \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 WebGL 1.0 *\/const gl = canvas.getContext('webgl', {preserveDrawingBuffer: false,antialias: false,alpha: false,});\/* \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b *\/const ctx = {\/* \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 *\/mode: \"scene\",flags: { isRendering: false, buffersInitialized: false, initComplete: false, benchMode: false },\/* \u0422\u0435\u043a\u0441\u0442\u0443\u0440\u044b *\/tex: { sdr: null, selfIllum: null, frame: null, frameFinal: null },\/* \u0411\u0443\u0444\u0435\u0440\u044b \u043a\u0430\u0434\u0440\u043e\u0432 *\/fb: { scene: null, final: null },\/* \u0428\u0435\u0439\u0434\u0435\u0440\u044b \u0438 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 *\/shd: {scene: { handle: null, uniforms: { offset: null, radius: null } },blur: { handle: null, uniforms: { frameSizeRCP: null, samplePosMult: null, sigma: null, bloomStrength: null } },bloom: { handle: null, uniforms: { offset: null, radius: null, texture: null, textureAdd: null } }}};\/* \u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b UI *\/const ui = {display: {spinner: canvas.parentElement.querySelector('svg', canvas.parentElement),contextLoss: canvas.parentElement.querySelector('div', canvas.parentElement),fps: WebGLBox.querySelector('#fps'),ms: WebGLBox.querySelector('#ms'),width: WebGLBox.querySelector('#width'),height: WebGLBox.querySelector('#height'),tapsCount: WebGLBox.querySelector('#taps'),},blur: {kernelSize: WebGLBox.querySelector('#sizeRange'),sigma: WebGLBox.querySelector('#sigmaRange'),samplePos: WebGLBox.querySelector('#samplePosRange'),samplePosReset: WebGLBox.querySelector('#samplePosRangeReset'),},rendering: {animate: WebGLBox.querySelector('#animateCheck'),modes: WebGLBox.querySelectorAll('input[type=\"radio\"]'),lightBrightness: WebGLBox.querySelector('#lightBrightness'),lightBrightnessReset: WebGLBox.querySelector('#lightBrightnessReset'),},benchmark: {button: WebGLBox.querySelector('#benchmark'),label: WebGLBox.querySelector('#benchmarkLabel'),iterOut: WebGLBox.querySelector('#iterOut'),renderer: WebGLBoxDetail.querySelector('#renderer'),iterTime: WebGLBoxDetail.querySelector('#iterTime'),tapsCount: WebGLBoxDetail.querySelector('#tapsCountBench'),iterations: WebGLBox.querySelector('#iterations')}};\/* \u0428\u0435\u0439\u0434\u0435\u0440\u044b *\/const circleAnimation = await util.fetchShader(\"shader\/circleAnimation.vs\");const simpleTexture = await util.fetchShader(\"shader\/simpleTexture.fs\");const bloomVert = await util.fetchShader(\"shader\/bloom.vs\");const bloomFrag = await util.fetchShader(\"shader\/bloom.fs\");const simpleQuad = await util.fetchShader(\"shader\/simpleQuad.vs\");const gaussianBlurFrag = await util.fetchShader(\"shader\/gaussianBlur.fs\");\/* \u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0431\u0435\u0437 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 *\/ui.blur.kernelSize.addEventListener('input', () =&gt; { if (!ui.rendering.animate.checked) redraw() });ui.blur.sigma.addEventListener('input', () =&gt; { if (!ui.rendering.animate.checked) redraw() });ui.blur.samplePos.addEventListener('input', () =&gt; { if (!ui.rendering.animate.checked) redraw() });ui.rendering.lightBrightness.addEventListener('input', () =&gt; { if (!ui.rendering.animate.checked) redraw() });\/* \u0421\u043e\u0431\u044b\u0442\u0438\u044f *\/ui.rendering.animate.addEventListener(\"change\", () =&gt; {if (ui.rendering.animate.checked)startRendering();else {ui.display.fps.value = \"-\";ui.display.ms.value = \"-\";ctx.flags.isRendering = false;redraw()}});canvas.addEventListener(\"webglcontextlost\", () =&gt; {ui.display.contextLoss.style.display = \"block\";});ui.blur.kernelSize.addEventListener('input', () =&gt; {reCompileBlurShader(ui.blur.kernelSize.value);ui.blur.samplePos.disabled = ui.blur.kernelSize.value == 0;ui.blur.samplePosReset.disabled = ui.blur.kernelSize.value == 0;});\/* \u0420\u0435\u0436\u0438\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 *\/ui.rendering.modes.forEach(radio =&gt; {\/* \u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 scene, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u044c \u0431\u0430\u0433 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432 Firefox Android *\/if (radio.value === \"scene\")radio.checked = true;radio.addEventListener('change', (event) =&gt; {ctx.mode = event.target.value;ui.rendering.lightBrightness.disabled = ctx.mode === \"scene\";ui.rendering.lightBrightnessReset.disabled = ctx.mode === \"scene\";if (!ui.rendering.animate.checked) redraw();});});ui.benchmark.button.addEventListener(\"click\", () =&gt; {ctx.flags.benchMode = true;stopRendering();ui.display.spinner.style.display = \"block\";ui.benchmark.button.disabled = true;\/* \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432\u043e\u0440\u043a\u0435\u0440\u0430 (\u043c\u043e\u0434\u0443\u043b\u044c ES) *\/const worker = new Worker(\".\/js\/benchmark\/gaussianBlurBenchmark.js\", { type: \"module\" });\/* \u041f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u044b \u0432\u043e\u0440\u043a\u0435\u0440\u0443 *\/worker.postMessage({iterations: ui.benchmark.iterOut.value,blurShaderSrc: gaussianBlurFrag,kernelSize: ui.blur.kernelSize.value,samplePos: ui.blur.samplePos.value,sigma: ui.blur.sigma.value});\/* \u0411\u0435\u043d\u0447\u043c\u0430\u0440\u043a *\/worker.addEventListener(\"message\", (event) =&gt; {if (event.data.type !== \"done\") return;ui.benchmark.label.textContent = event.data.benchText;ui.benchmark.tapsCount.textContent = event.data.tapsCount;ui.benchmark.iterTime.textContent = event.data.iterationText;ui.benchmark.renderer.textContent = event.data.renderer;worker.terminate();ui.benchmark.button.disabled = false;ctx.flags.benchMode = false;if (ui.rendering.animate.checked)startRendering();elseredraw();});});ui.benchmark.iterations.addEventListener(\"change\", (event) =&gt; {ui.benchmark.iterOut.value = event.target.value;ui.benchmark.label.textContent = \"Benchmark\";});\/* \u0428\u0435\u0439\u0434\u0435\u0440 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u0442\u0435\u043a\u0441\u0442\u0443\u0440 *\/ctx.shd.scene = util.compileAndLinkShader(gl, circleAnimation, simpleTexture, [\"offset\", \"radius\"]);\/* \u0428\u0435\u0439\u0434\u0435\u0440 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 bloom *\/ctx.shd.bloom = util.compileAndLinkShader(gl, bloomVert, bloomFrag, [\"texture\", \"textureAdd\", \"offset\", \"radius\"]);\/* \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 *\/function reCompileBlurShader(blurSize) {ctx.shd.blur = util.compileAndLinkShader(gl, simpleQuad, gaussianBlurFrag, [\"frameSizeRCP\", \"samplePosMult\", \"bloomStrength\", \"sigma\"], \"#define KERNEL_SIZE \" + blurSize + '\\n');}\/* \u0428\u0435\u0439\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f *\/reCompileBlurShader(ui.blur.kernelSize.value)\/* \u041f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0432 GPU *\/util.bindUnitQuad(gl);async function setupTextureBuffers() {ui.display.spinner.style.display = \"block\";ctx.flags.buffersInitialized = true;ctx.flags.initComplete = false;gl.deleteFramebuffer(ctx.fb.scene);gl.deleteFramebuffer(ctx.fb.final);[ctx.fb.scene, ctx.tex.frame] = util.setupFramebuffer(gl, canvas.width, canvas.height);[ctx.fb.final, ctx.tex.frameFinal] = util.setupFramebuffer(gl, canvas.width, canvas.height);let [base, selfIllum] = await Promise.all([fetch(\"\/dual-kawase\/img\/SDR_No_Sprite.png\"),fetch(\"\/dual-kawase\/img\/Selfillumination.png\")]);let [baseBlob, selfIllumBlob] = await Promise.all([base.blob(), selfIllum.blob()]);let [baseBitmap, selfIllumBitmap] = await Promise.all([createImageBitmap(baseBlob, { colorSpaceConversion: 'none', resizeWidth: canvas.width * 1.12, resizeHeight: canvas.height * 1.12, resizeQuality: \"high\" }),createImageBitmap(selfIllumBlob, { colorSpaceConversion: 'none', resizeWidth: canvas.width * 1.12, resizeHeight: canvas.height * 1.12, resizeQuality: \"high\" })]);ctx.tex.sdr = util.setupTexture(gl, null, null, ctx.tex.sdr, gl.LINEAR, baseBitmap);ctx.tex.selfIllum = util.setupTexture(gl, null, null, ctx.tex.selfIllum, gl.LINEAR, selfIllumBitmap);baseBitmap.close();selfIllumBitmap.close();ctx.flags.initComplete = true;ui.display.spinner.style.display = \"none\";}let prevNow = performance.now();let lastStatsUpdate = prevNow;let fpsEMA = 60;let msEMA = 16;async function redraw() {if (!ctx.flags.buffersInitialized)await setupTextureBuffers();if (!ctx.flags.initComplete)return;\/* UI \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 *\/const KernelSizeSide = ui.blur.kernelSize.value * 2 + 1;const tapsNewText = (canvas.width * canvas.height * KernelSizeSide * KernelSizeSide \/ 1000000).toFixed(1) + \" Million\";ui.display.tapsCount.value = tapsNewText;ui.display.width.value = canvas.width;ui.display.height.value = canvas.height;\/* \u041a\u0440\u0443\u0433\u043e\u0432\u043e\u0435 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 *\/let radiusSwitch = ui.rendering.animate.checked ? radius : 0.0;let speed = (performance.now() \/ 10000) % Math.PI * 2;const offset = [radiusSwitch * Math.cos(speed), radiusSwitch * Math.sin(speed)];gl.useProgram(ctx.shd.scene.handle);const texture = ctx.mode == \"scene\" ? ctx.tex.sdr : ctx.tex.selfIllum;gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, texture);gl.uniform2fv(ctx.shd.scene.uniforms.offset, offset);gl.uniform1f(ctx.shd.scene.uniforms.radius, radiusSwitch);\/* \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0431\u0443\u0444\u0435\u0440\u0430 \u043a\u0430\u0434\u0440\u043e\u0432 \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 *\/gl.bindFramebuffer(gl.FRAMEBUFFER, ctx.fb.scene);gl.viewport(0, 0, canvas.width, canvas.height);\/* \u0412\u044b\u0437\u043e\u0432 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 *\/gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);\/* \u0413\u0430\u0443\u0441\u0441\u043e\u0432\u043e \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u043f\u0440\u0438 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0438 *\/gl.useProgram(ctx.shd.blur.handle);const finalFB = ctx.mode == \"bloom\" ? ctx.fb.final : null;gl.bindFramebuffer(gl.FRAMEBUFFER, finalFB);gl.viewport(0, 0, canvas.width, canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.bloomStrength, ctx.mode == \"scene\" ? 1.0 : ui.rendering.lightBrightness.value);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.frame);gl.uniform2f(ctx.shd.blur.uniforms.frameSizeRCP, 1.0 \/ canvas.width, 1.0 \/ canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.samplePosMult, ui.blur.samplePos.value);gl.uniform1f(ctx.shd.blur.uniforms.sigma, Math.max(ui.blur.kernelSize.value \/ ui.blur.sigma.value, 0.001));gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);if (ctx.mode == \"bloom\") {\/* Now do the bloom composition to the screen *\/gl.bindFramebuffer(gl.FRAMEBUFFER, null);gl.useProgram(ctx.shd.bloom.handle);gl.uniform2fv(ctx.shd.bloom.uniforms.offset, offset);gl.uniform1f(ctx.shd.bloom.uniforms.radius, radiusSwitch);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.sdr);gl.uniform1i(ctx.shd.bloom.uniforms.texture, 0);gl.activeTexture(gl.TEXTURE1);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.frameFinal);gl.uniform1i(ctx.shd.bloom.uniforms.textureAdd, 1);gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);}\/* \u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e CPU \u0438 GPU, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0443 GPU \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u0438\u043d\u0433\u0430.   \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u044d\u0442\u043e, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u0441\u0431\u0440\u043e\u0441\u0443,   \u043d\u043e \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445 \u043f\u0440\u0438 \u043d\u0438\u0437\u043a\u0438\u0445 FPS *\/gl.finish();const now = performance.now();let dt = now - prevNow;if (dt &gt; 0) {const instFPS = 1000 \/ dt;const ALPHA = 0.05;fpsEMA = ALPHA * instFPS + (1 - ALPHA) * fpsEMA;msEMA = ALPHA * dt + (1 - ALPHA) * msEMA;}prevNow = now;if (ui.rendering.animate.checked &amp;&amp; now - lastStatsUpdate &gt;= 1000) {ui.display.fps.value = fpsEMA.toFixed(0);ui.display.ms.value = msEMA.toFixed(2);lastStatsUpdate = now;}}let animationFrameId;\/* \u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c *\/function nativeResize() {const [width, height] = util.getNativeSize(canvas);if (width &amp;&amp; canvas.width !== width || height &amp;&amp; canvas.height !== height) {canvas.width = width;canvas.height = height;if (!ctx.flags.benchMode) {stopRendering();startRendering();}if (!ui.rendering.animate.checked)redraw();}}\/* \u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u0430 *\/nativeResize();let resizePending = false;window.addEventListener('resize', () =&gt; {if (!resizePending) {resizePending = true;requestAnimationFrame(() =&gt; {resizePending = false;nativeResize();});}});function renderLoop() {if (ctx.flags.isRendering &amp;&amp; ui.rendering.animate.checked) {redraw();animationFrameId = requestAnimationFrame(renderLoop);}}function startRendering() {\/* \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433, \u043a\u043e\u0433\u0434\u0430 canvas \u0432\u0438\u0434\u0438\u043c *\/ctx.flags.isRendering = true;renderLoop();}function stopRendering() {\/* \u041e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0432\u044b\u0437\u043e\u0432 \u0435\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0438 *\/ctx.flags.isRendering = false;cancelAnimationFrame(animationFrameId);\/* \u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0441 CPU, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0432\u043c\u0435\u0448\u0430\u0435\u043c\u0441\u044f \u0432 \u043d\u0435\u0433\u043e *\/gl.finish();\/* \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0431\u0443\u0444\u0435\u0440\u044b, \u0447\u0442\u043e\u0431\u044b \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c *\/gl.deleteTexture(ctx.tex.sdr); ctx.tex.sdr = null;gl.deleteTexture(ctx.tex.selfIllum); ctx.tex.selfIllum = null;gl.deleteTexture(ctx.tex.frame); ctx.tex.frame = null;gl.deleteTexture(ctx.tex.frameFinal); ctx.tex.frameFinal = null;gl.deleteFramebuffer(ctx.fb.scene); ctx.fb.scene = null;gl.deleteFramebuffer(ctx.fb.final); ctx.fb.final = null;ctx.flags.buffersInitialized = false;ctx.flags.initComplete = false;ui.display.fps.value = \"-\";ui.display.ms.value = \"-\";}function handleIntersection(entries) {entries.forEach(entry =&gt; {if (entry.isIntersecting) {if (!ctx.flags.isRendering &amp;&amp; !ctx.flags.benchMode) startRendering();} else {stopRendering();}});}\/* \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 canvas \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 *\/let observer = new IntersectionObserver(handleIntersection);observer.observe(canvas);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0420\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043f\u043b\u0430\u0432\u043d\u0435\u0435, \u0447\u0435\u043c box blur, \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043a\u0430\u0436\u0443\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u00ab\u043e\u043a\u0440\u0443\u0433\u043b\u044b\u043c\u0438\u00bb \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u043b\u0430\u0432\u043d\u043e\u043c\u0443 \u043e\u0442\u0432\u0435\u0442\u043d\u043e\u043c\u0443 \u0441\u0438\u0433\u043d\u0430\u043b\u0443 \u043a\u0440\u0438\u0432\u043e\u0439. \u041e\u0434\u043d\u0430\u043a\u043e \u0435\u0441\u043b\u0438 <code>sigma<\/code>\u00a0\u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u0430\u043b\u043e\u0439, \u0442\u043e \u0441\u043d\u043e\u0432\u0430 \u043f\u043e\u044f\u0432\u044f\u0442\u0441\u044f \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b, \u043f\u043e\u0445\u043e\u0436\u0438\u0435 \u043d\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b box blur.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f, \u043a\u0430\u043a\u043e\u0439 \u0441\u043c\u044b\u0441\u043b \u0443 \u044d\u0442\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438 \u043a\u0430\u043a \u043e\u043d\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0442. \u041d\u0430 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043d\u0438\u0436\u0435 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u044f\u0434\u0440\u043e \u0441 \u0432\u0435\u0441\u0430\u043c\u0438, \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u043d\u044b\u043c\u0438 \u0432 \u0432\u0438\u0434\u0435 \u0432\u044b\u0441\u043e\u0442\u044b. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0434\u0432\u0430 \u0440\u0435\u0436\u0438\u043c\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 <code>sigma<\/code>\u00a0\u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 <code>kernelSize<\/code>\u00a0\u0438 \u0434\u0432\u0430 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f <code>sigma<\/code>.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/48d\/f05\/83a\/48df0583aca56462b809c59c7828c725.png\" alt=\"\u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u0430\u044f sigma. kernelSize 7\u00d77, sigma \u00b13.00\u03c3, 1.00px\" title=\"\u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u0430\u044f sigma. kernelSize 7\u00d77, sigma \u00b13.00\u03c3, 1.00px\" width=\"684\" height=\"508\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/48d\/f05\/83a\/48df0583aca56462b809c59c7828c725.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/48d\/f05\/83a\/48df0583aca56462b809c59c7828c725.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u0430\u044f sigma. kernelSize 7\u00d77, sigma \u00b13.00\u03c3, 1.00px<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0c6\/adf\/422\/0c6adf422fb9b9b675aa46c0ac28630e.png\" alt=\"\u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u0430\u044f sigma. kernelSize 11\u00d711 sigma \u00b11.80\u03c3, 2.78px\" title=\"\u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u0430\u044f sigma. kernelSize 11\u00d711 sigma \u00b11.80\u03c3, 2.78px\" width=\"682\" height=\"511\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/0c6\/adf\/422\/0c6adf422fb9b9b675aa46c0ac28630e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0c6\/adf\/422\/0c6adf422fb9b9b675aa46c0ac28630e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u0430\u044f sigma. kernelSize 11\u00d711 sigma \u00b11.80\u03c3, 2.78px<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/85a\/ab1\/311\/85aab1311717c86e62a1ecf1d140fa50.png\" alt=\"\u041e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f sigma. kernelSize 7\u00d77 sigma \u00b12.10\u03c3, 1.43px\" title=\"\u041e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f sigma. kernelSize 7\u00d77 sigma \u00b12.10\u03c3, 1.43px\" width=\"683\" height=\"522\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/85a\/ab1\/311\/85aab1311717c86e62a1ecf1d140fa50.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/85a\/ab1\/311\/85aab1311717c86e62a1ecf1d140fa50.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f sigma. kernelSize 7\u00d77 sigma \u00b12.10\u03c3, 1.43px<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/847\/ecc\/2d3\/847ecc2d3a1b087dd773e5a715ffa8b1.png\" alt=\"\u041e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f sigma. kernelSize 25\u00d725 sigma \u00b13.00\u03c3, 4.00px\" title=\"\u041e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f sigma. kernelSize 25\u00d725 sigma \u00b13.00\u03c3, 4.00px\" width=\"685\" height=\"517\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/847\/ecc\/2d3\/847ecc2d3a1b087dd773e5a715ffa8b1.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/847\/ecc\/2d3\/847ecc2d3a1b087dd773e5a715ffa8b1.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f sigma. kernelSize 25\u00d725 sigma \u00b13.00\u03c3, 4.00px<\/figcaption><\/div>\n<\/figure>\n<p><code>sigma<\/code>\u00a0\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0442\u043e, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043b\u043e\u0441\u043a\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043a\u0440\u0438\u0432\u0430\u044f, \u0434\u0432\u0438\u0436\u0443\u0449\u0430\u044f\u0441\u044f \u0432 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0441\u0442\u044c. \u041d\u043e \u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 <code>kernelSize<\/code> \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d. \u0422\u0430\u043c, \u0433\u0434\u0435 \u044f\u0434\u0440\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u043f\u0438\u043a\u0441\u0435\u043b\u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0432\u043d\u043e\u0441\u044f\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0432\u043a\u043b\u0430\u0434\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0437-\u0437\u0430 \u043e\u0442\u0441\u0435\u0447\u043a\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b, \u043f\u043e\u0445\u043e\u0436\u0438\u0435 \u043d\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b box blur. \u0412 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u043e \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0434\u0432\u0443\u043c\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438\u2026<\/p>\n<blockquote>\n<p><em>\u041c\u0430\u043b\u0430\u044f \u0441\u0438\u0433\u043c\u0430, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442, \u0438 \u043f\u043b\u043e\u0441\u043a\u0430\u044f \u043a\u0440\u0438\u0432\u0430\u044f \u043d\u0430\u0440\u044f\u0434\u0443 \u0441 \u043c\u0430\u043b\u044b\u043c \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u044f\u0434\u0440\u0430 \u2014 \u044d\u0442\u043e, \u043f\u043e \u0441\u0443\u0442\u0438, <\/em><strong><em>\u0438 \u0435\u0441\u0442\u044c<\/em><\/strong><em> box blur.<\/em><\/p>\n<\/blockquote>\n<p>\u0421\u043f\u043e\u0441\u043e\u0431 1:\u00a0<a href=\"https:\/\/www.youtube.com\/watch?v=ueNY30Cs8Lk\" rel=\"noopener noreferrer nofollow\">\u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u0430\u044f \u0441\u0438\u0433\u043c\u0430<\/a>.\u00a0<code>sigma<\/code>\u00a0\u2014 \u044d\u0442\u043e \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u0445, \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0435\u0435 \u043e\u0442 <code>kernelSize<\/code>, \u0430 <code>kernelSize<\/code>\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u00ab\u043e\u043a\u043d\u0430 \u043a\u0440\u0438\u0432\u043e\u0439\u00bb<\/p>\n<p>\u0421\u043f\u043e\u0441\u043e\u0431 2:\u00a0<code>sigma<\/code>\u00a0\u0432\u044b\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f <strong><em>\u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e<\/em><\/strong> \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e <code>kernelSize<\/code>. \u0418\u0437 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0441\u043e\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u044d\u0442\u043e\u0442 \u0441\u043f\u043e\u0441\u043e\u0431.<\/p>\n<p>\u041a\u0430\u043a \u0431\u044b \u0442\u043e \u043d\u0438 \u0431\u044b\u043b\u043e, \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u0430\u044f \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u0430 \u043a\u0440\u0438\u0432\u0430\u044f <strong>\u0434\u043e\u043b\u0436\u043d\u0430<\/strong> \u0438\u043c\u0435\u0442\u044c <em>\u0433\u0434\u0435-\u0442\u043e<\/em> \u043e\u0442\u0441\u0435\u0447\u043a\u0443.\u00a0\u0415\u0441\u043b\u0438 <code>sigma<\/code>\u00a0\u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u0430\u043b\u0430, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b. \u0415\u0441\u043b\u0438 <code>sigma<\/code>\u00a0\u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0432\u0435\u043b\u0438\u043a\u0430, \u0442\u043e \u043c\u044b \u0432\u043f\u0443\u0441\u0442\u0443\u044e \u043f\u043e\u0442\u0440\u0430\u0442\u0438\u043c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0442\u0430 \u0436\u0435 \u0432\u043e\u0441\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c\u0430\u044f \u0441\u0438\u043b\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u044f\u0434\u0435\u0440 \u0431\u043e\u043b\u044c\u0448\u0435\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442, \u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0446\u0438\u043a\u043b\u043e\u0432 for \u0441 \u0431\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u043e\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e. \u041b\u044e\u0431\u043e\u043c\u0443 \u041f\u041e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0434\u0442\u0438 \u043d\u0430 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441\u044b, \u0436\u0435\u0440\u0442\u0432\u0443\u044f \u0445\u0443\u0434\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0439.<\/p>\n<blockquote>\n<p><em>\u041e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u044f\u0434\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u043e\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0432\u0435\u0441\u0430 \u043f\u043e\u0447\u0442\u0438 \u0440\u0430\u0432\u043d\u044b \u043d\u0443\u043b\u044e. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0435\u0441\u043b\u0438 \u043c\u044b \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u043c <\/em><code><em>kernelSize<\/em><\/code><em>\u00a0\u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e\u0439 \u0441\u0438\u0433\u043c\u044b \u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0443, \u0442\u043e <\/em><strong><em>\u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e<\/em><\/strong><em> \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0447\u0442\u0438 \u043d\u0435\u0437\u0430\u043c\u0435\u0442\u043d\u043e.<\/em><\/p>\n<\/blockquote>\n<p>\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044f\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/en.wikipedia.org\/wiki\/Pascal%27s_triangle\" rel=\"noopener noreferrer nofollow\">\u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u041f\u0430\u0441\u043a\u0430\u043b\u044f<\/a>, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432 \u0438 \u0432\u0435\u0441\u043e\u0432 \u044f\u0434\u0440\u0430. \u042d\u0442\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <a href=\"https:\/\/bartwronski.com\/2021\/10\/31\/practical-gaussian-filter-binomial-filter-and-small-sigma-gaussians\/\" rel=\"noopener noreferrer nofollow\">\u0431\u0438\u043d\u043e\u043c\u0438\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u043c\u0438<\/a>; \u043c\u044b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u043c\u0441\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c\u0438 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u044f\u0434\u0435\u0440, \u043d\u043e \u0443\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u043c \u0434\u0438\u043b\u0435\u043c\u043c\u0443 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0441\u0442\u0438 \u0438 \u043e\u0442\u0441\u0435\u0447\u043a\u0438, \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u044f \u0432\u0435\u0441\u0430 \u0432 \u043d\u043e\u043b\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u043a\u043d\u0430 \u0441\u044d\u043c\u043f\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0411\u0438\u043d\u043e\u043c\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u044f\u0434\u0440\u0430 \u043f\u043e\u0445\u043e\u0436\u0438 \u043d\u0430 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u044b \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0439 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0438. \u041d\u0435 \u0431\u0443\u0434\u0443 \u0443\u0433\u043b\u0443\u0431\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443, \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u043c\u0435\u0439\u0442\u0435 \u0432 \u0432\u0438\u0434\u0443, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u044f\u0434\u0440\u0430 \u043f\u043e \u0440\u0430\u0437\u043d\u044b\u043c \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c, \u0441\u0442\u0440\u0435\u043c\u044f\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0438 \u043e\u0442\u0432\u0435\u0442\u043d\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430. \u041a\u0441\u0442\u0430\u0442\u0438, \u0430 \u0447\u0442\u043e \u0436\u0435 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u00ab\u043f\u043e\u0445\u043e\u0436\u0438 \u043d\u0430 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u044b\u00bb? \u0418 \u043f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u0432\u0430\u0436\u043d\u043e?<\/p>\n<h3>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0433\u0430\u0443\u0441\u0441\u0438\u0430\u043d\u043e\u043f\u043e\u0434\u043e\u0431\u0438\u0435?\u00a0<\/h3>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0430 \u0434\u0432\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438.\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Bokeh\" rel=\"noopener noreferrer nofollow\">\u0411\u043e\u043a\u0435-\u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f<\/a> \u0438 \u0433\u0430\u0443\u0441\u0441\u0438\u0430\u043d\u043e\u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f. \u0413\u0430\u0443\u0441\u0441\u0438\u0430\u043d\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u0430 \u0438\u0437-\u0437\u0430 \u0435\u0451 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438, \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0441\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c \u0446\u0432\u0435\u0442\u0430. \u0413\u0430\u0443\u0441\u0441\u043e\u0432\u044b \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u0438\u043d\u0433\u0440\u0435\u0434\u0438\u0435\u043d\u0442 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u0442\u0435\u043a\u043b\u044f\u043d\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u0438\u043b\u0438 Bloom.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/09f\/ba0\/fbf\/09fba0fbf951f2eaafcfda62ce920254.png\" alt=\"Bokeh blur, gaussian blur comparison\" title=\"\" width=\"1368\" height=\"555\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/09f\/ba0\/fbf\/09fba0fbf951f2eaafcfda62ce920254.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/09f\/ba0\/fbf\/09fba0fbf951f2eaafcfda62ce920254.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>Bokeh blur, gaussian blur comparison<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u0440\u0438 \u0438\u043c\u0438\u0442\u0430\u0446\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0438\u0432\u043e\u0432 \u0438\/\u0438\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 <a href=\"https:\/\/dev.epicgames.com\/documentation\/en-us\/unreal-engine\/depth-of-field-in-unreal-engine\" rel=\"noopener noreferrer nofollow\">Depth of Field<\/a> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/dev.epicgames.com\/documentation\/en-us\/unreal-engine\/cinematic-depth-of-field-method?application_version=4.27\" rel=\"noopener noreferrer nofollow\">\u0431\u043e\u043a\u0435-\u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435<\/a>, \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0435 Lens Blur \u0438\u043b\u0438 Cinematic Blur. \u0422\u0430\u043a\u043e\u0439 \u0442\u0438\u043f \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0438 \u0435\u0441\u0442\u044c \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u044d\u0444\u0444\u0435\u043a\u0442. \u0421\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439 \u0441\u0438\u043b\u044c\u043d\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u044b, \u043d\u043e \u0434\u043b\u044f \u043d\u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0440\u0430\u0437\u043d\u044b\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0444\u0435\u0440\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043e\u0447\u0435\u043d\u044c \u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438, \u0438 \u0432\u0441\u0435 \u043e\u043d\u0438 \u0438\u043c\u0435\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441\u044b \u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0432\u0438\u0434. \u0412 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0434\u043b\u044f \u0441\u044d\u043c\u043f\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f <a href=\"https:\/\/mynameismjp.wordpress.com\/2011\/02\/28\/bokeh\/\" rel=\"noopener noreferrer nofollow\">\u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u041f\u0443\u0430\u0441\u0441\u043e\u043d\u0430<\/a>, \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u2014 \u043d\u0435\u043e\u0440\u0434\u0438\u043d\u0430\u0440\u043d\u044b\u0435 \u0442\u0440\u044e\u043a\u0438: Computerphile \u0437\u0430\u043f\u0438\u0441\u0430\u043b \u0432\u0438\u0434\u0435\u043e \u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0431\u043e\u043a\u0435-\u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0445 \u0447\u0438\u0441\u0435\u043b \u2014 \u043f\u043e\u0442\u0440\u044f\u0441\u0430\u044e\u0449\u0435\u043c \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u0438 \u0441 \u0442\u0435\u043e\u0440\u0438\u0435\u0439 \u0447\u0438\u0441\u0435\u043b.<\/p>\n<p><a href=\"https:\/\/embedd.srv.habr.com\/iframe\/68c128d999edac48ac1e89b6\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed_link embed_layout-right\"><\/p>\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;undefined&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>\ud83c\udcad<\/span><\/div>\n<div class=\"embed__caption-description\">undefined&#8230;<\/div>\n<p><span class=\"embed__caption-host\">embedd.srv.habr.com<\/span><\/div>\n<p><\/a><\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u043a\u0430\u0441\u0430\u0442\u044c\u0441\u044f \u044d\u0442\u0438\u0445 \u0441\u0442\u0438\u043b\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u0438\u043a. \u041c\u044b \u0441\u0442\u0440\u0435\u043c\u0438\u043c\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0441\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0431\u043b\u043e\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u2014 \u0433\u0430\u0443\u0441\u0441\u0438\u0430\u043d\u043e\u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0441 \u0445\u043e\u0440\u043e\u0448\u0435\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<h4>\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/h4>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043c\u043e\u0442\u0438\u0432\u0430\u0442\u043e\u0440\u043e\u043c \u043a \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0441\u0442\u0430\u043b\u043e \u0441\u0442\u0440\u0435\u043c\u043b\u0435\u043d\u0438\u0435 \u043a \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u0412\u0441\u0451 \u0434\u043e\u043b\u0436\u043d\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0437\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434. \u041e\u0434\u043d\u0430\u043a\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u0430\u0442\u0440\u0430\u0442\u044b \u043d\u0430 \u0435\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u0438\u043d\u043e\u0433\u0434\u0430 \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f. \u041d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f!<\/p>\n<p>\u0411\u044b\u043b\u043e \u0431\u044b \u0441\u0442\u0440\u0430\u043d\u043d\u043e, \u0435\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u043d\u0435 \u043c\u043e\u0433\u043b\u0438 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0437\u0430\u043c\u0435\u0440\u044f\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e WebGL Box \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438\u043d\u0433\u0430, \u0440\u0430\u0437\u043c\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u0448\u0443\u043c \u0441 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c <code>1600x1200<\/code>, \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u0441 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0439 (\u044d\u0442\u0443 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043c\u044b \u043f\u043e\u043a\u0430 \u043d\u0435 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b\u0438).<\/p>\n<blockquote>\n<p><em>\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u2014 \u044d\u0442\u043e \u0447\u0430\u0441\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f, \u0447\u0435\u043c \u0441\u0430\u043c\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435.<\/em><\/p>\n<\/blockquote>\n<p>\u041b\u0443\u0447\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438\u043d\u0433, \u0438\u0437\u043c\u0435\u0440\u044f\u044f \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432. \u042d\u0442\u043e <a href=\"https:\/\/registry.khronos.org\/webgl\/extensions\/EXT_disjoint_timer_query_webgl2\/\" rel=\"noopener noreferrer nofollow\">\u043c\u043e\u0436\u043d\u043e<\/a>\u00a0\u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u0445, \u043d\u043e \u043d\u0435 \u043d\u0430 \u0432\u0441\u0435\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445. \u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0441 \u00ab\u043f\u0440\u043e\u0441\u0442\u0430\u0438\u0432\u0430\u043d\u0438\u0435\u043c \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430\u00bb \u2014 \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043a\u043e\u043c\u0430\u043d\u0434.<\/p>\n<blockquote>\n<p><em>\u041d\u0430 \u0432\u0441\u0435\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 \u043f\u0440\u043e\u0441\u0442\u0430\u0438\u0432\u0430\u043d\u0438\u0435 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 <\/em><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WebGLRenderingContext\/readPixels\" rel=\"noopener noreferrer nofollow\"><code><em>gl.readPixels()<\/em><\/code><\/a><em>. \u041b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u043e, \u0447\u0442\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0430 <\/em><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WebGLRenderingContext\/finish\" rel=\"noopener noreferrer nofollow\"><code><em>gl.finish()<\/em><\/code><\/a><em>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430\u043c, \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445 Apple.<\/em><\/p>\n<\/blockquote>\n<p>\u0412 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u043d\u0438\u0436\u0435 \u0435\u0441\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0430 \u0434\u043b\u044f \u0440\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438\u043d\u0433\u0430. \u041e\u043d\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u0441 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Web_Workers_API\/Using_web_workers\" rel=\"noopener noreferrer nofollow\">\u0432\u043e\u0440\u043a\u0435\u0440\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430<\/a>. \u0415\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b <strong><em>\u043e\u0447\u0435\u043d\u044c <\/em><\/strong>\u0441\u0435\u0440\u0434\u044f\u0442\u0441\u044f, \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c GPU \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0434\u043e\u043b\u0433\u043e, \u043d\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u044f \u043d\u0438\u0447\u0435\u0433\u043e \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443, \u0442\u043e \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0442 \u0434\u043e\u0441\u0442\u0443\u043f GPU \u043a\u043e \u0432\u0441\u0435\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0434\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432\u043a\u043b\u0430\u0434\u043a\u0438. \u0415\u0441\u043b\u0438 \u0436\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443, \u0442\u043e \u0437\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u044b; \u043a \u0442\u043e\u043c\u0443 \u0432\u043d\u0443\u0442\u0440\u0438 WebGL \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c GPU \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0435\u043c\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u043a\u043e\u043c\u0430\u043d\u0434\u044b.<\/p>\n<blockquote>\n<p>\u26a0\ufe0f \u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432\u0430\u0436\u043d\u043e \u0434\u043b\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445:\u00a0\u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0439\u0442\u0435 <code>kernelSize<\/code>\u00a0\u0438 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438 <strong>\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e<\/strong>. \u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430\u0445 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 <code>kernelSize<\/code>\u00a0\u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u043f\u043b\u043e\u0445\u0438\u043c, \u0442\u0430\u043a \u0447\u0442\u043e \u0441 \u043d\u0438\u043c\u0438 \u0431\u0443\u0434\u044c\u0442\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u044b.<\/p>\n<p>\u0412\u0440\u0435\u043c\u044f \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 <strong>2<\/strong>\u00a0\u0441\u0435\u043a\u0443\u043d\u0434; \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f GPU \u043a \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435, \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442 \u0432\u0441\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0434\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430. \u0412 Safari iOS \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 App Switcher, \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.<\/p>\n<\/blockquote>\n<blockquote>\n<p><em>iOS \u0438 iPad OS <\/em><strong><em>\u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e<\/em><\/strong><em> \u0441\u0442\u0440\u043e\u0433\u0438, \u043e\u043d\u0438 \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0442 \u0434\u043e\u0441\u0442\u0443\u043f GPU \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0432\u043a\u043b\u0430\u0434\u043a\u0438. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a App Switcher (\u0434\u0432\u043e\u0439\u043d\u043e\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 Home), \u0441\u0432\u0430\u0439\u043f\u043d\u0443\u0442\u044c Safari \u0432\u0432\u0435\u0440\u0445, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0435\u0433\u043e, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0437\u0430\u043d\u043e\u0432\u043e.<\/em><\/p>\n<\/blockquote>\n<h3>\u0427\u0442\u043e \u043c\u044b \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u043c?\u00a0<\/h3>\n<p>\u0412 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u0432\u044b\u0448\u0435 Box Blur\u00a0\u0438 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u043e\u043c \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0438 \u043c\u044b \u0437\u0430\u043c\u0435\u0440\u044f\u0435\u043c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0441 <code>kernelSize<\/code> \u043e\u0447\u0435\u043d\u044c \u043d\u0435\u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e. \u0415\u0441\u043b\u0438 \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u044d\u0442\u043e \u0432 \u00ab\u041e\u00bb \u0431\u043e\u043b\u044c\u0448\u043e\u043c, \u0442\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c, \u043a\u0430\u043a <code>O(pixelCount * kernelSize\u00b2)<\/code>. \u0422\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e texture tap \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e <code>kernelSize<\/code> \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u0447\u043d\u043e. \u041d\u0443\u0436\u043d\u043e \u0441 \u044d\u0442\u0438\u043c \u0447\u0442\u043e-\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<blockquote>\n<p><em>GPU \u043d\u043e\u0443\u0442\u0431\u0443\u043a\u043e\u0432 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e \u0432\u044b\u0445\u043e\u0434\u044f\u0442 \u0438\u0437 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043d\u0438\u0437\u043a\u043e\u0433\u043e \u044d\u043d\u0435\u0440\u0433\u043e\u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043f\u0440\u0438 \u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0431\u0443\u0434\u0443\u0442 \u043b\u0443\u0447\u0448\u0435.<\/em><\/p>\n<\/blockquote>\n<p>\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u043e \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 <a href=\"https:\/\/github.com\/FrostKiwi\/treasurechest\/blob\/main\/posts\/dual-kawase\/shader\/gaussianBlur.fs#L18\" rel=\"noopener noreferrer nofollow\">\u0432 \u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442 \u044f\u0434\u0440\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441 \u043d\u0443\u043b\u044f<\/a>, \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c box blur \u0438 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u043f\u0440\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0439 \u043e\u0447\u0435\u043d\u044c \u0431\u043b\u0438\u0437\u043a\u0430 \u0434\u0440\u0443\u0433 \u043a \u0434\u0440\u0443\u0433\u0443. \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0435\u0441\u043b\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0442\u044c \u044d\u0442\u0438 \u044f\u0434\u0440\u0430 \u0437\u0430\u0440\u0430\u043d\u0435\u0435, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<blockquote>\n<p><em>\u041d\u043e \u0440\u0430\u0437\u0432\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u043d\u0435 \u0441\u043b\u043e\u0436\u043d\u0435\u0435?<\/em><\/p>\n<\/blockquote>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0447\u0438\u043f\u043e\u0432, \u0432\u044b\u043f\u0443\u0441\u043a\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u043b\u0435\u0442 \u043d\u0430\u0437\u0430\u0434, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043a\u0430\u0440\u0442\u044b \u0438\u043c\u0435\u044e\u0442 \u043e\u0447\u0435\u043d\u044c \u0431\u044b\u0441\u0442\u0440\u0443\u044e \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u043a\u0443, \u043d\u043e \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u0430\u043c\u044f\u0442\u0438. \u041f\u0440\u0438 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430\u0445 \u0441\u0430\u043c\u044b\u043c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u043c \u0430\u0441\u043f\u0435\u043a\u0442\u043e\u043c \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u0430\u043c\u044f\u0442\u0438; \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e texture tap. \u0427\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e tap, \u0442\u0435\u043c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c.<\/p>\n<blockquote>\n<p><em>\u041d\u0430\u0448\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442 <\/em><strong><em>\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440<\/em><\/strong><em>, \u0430 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u044d\u0442\u043e \u0433\u0440\u0435\u0445. \u041f\u043e\u0434 \u044d\u0442\u0438\u043c \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0448\u0435\u0439\u0434\u0435\u0440\u0430, \u0438\u0437-\u0437\u0430 \u0447\u0435\u0433\u043e \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432.<\/em><\/p>\n<\/blockquote>\n<p>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c (\u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043d\u0430 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430\u0445), \u0447\u0442\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 <code>samplePosMultiplier<\/code> \u043e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 (\u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0439 \u043c\u0435\u0440\u0435), \u0445\u043e\u0442\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 texture tap \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0442\u0435\u043c \u0436\u0435.<\/p>\n<p>\u042d\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u044b\u0435 \u043a\u044d\u0448\u0438 \u0442\u0435\u043a\u0441\u0442\u0443\u0440 \u0443\u0441\u043a\u043e\u0440\u044f\u044e\u0442 \u0447\u0442\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0433\u0434\u0430 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0442 \u043a \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0431\u043b\u0438\u0437\u043a\u0438\u043c \u0443\u0447\u0430\u0441\u0442\u043a\u0430\u043c. \u0415\u0441\u043b\u0438 \u0436\u0435 \u0432\u0441\u0435 \u0432\u044b\u0431\u043e\u0440\u043a\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0434\u0430\u043b\u0435\u043a\u043e \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430, \u043a\u044d\u0448 \u0443\u0436\u0435 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u044d\u0442\u043e \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435. \u041f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043d\u0430\u043f\u043e\u0434\u043e\u0431\u0438\u0435 <a href=\"https:\/\/developer.nvidia.com\/blog\/identifying-shader-limiters-with-the-shader-profiler-in-nvidia-nsight-graphics\/\" rel=\"noopener noreferrer nofollow\">Nvidia NSight<\/a>\u00a0\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b \u0438\u0437\u043c\u0435\u0440\u044f\u0442\u044c \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u044d\u0448\u0430 GPU, \u043e\u0434\u043d\u0430\u043a\u043e \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b \u043d\u0430 \u044d\u0442\u043e \u043d\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b.<\/p>\n<p>\u042d\u0442\u043e \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u043a \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u044b \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0445 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432:\u00a0<strong>Texture Taps<\/strong>\u00a0\u0438 <strong>\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u044d\u0448\u0430<\/strong>. \u0415\u0441\u0442\u044c \u0438 \u0435\u0449\u0451 \u043e\u0434\u0438\u043d, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0441\u043a\u043e\u0440\u043e \u043a\u043e\u0441\u043d\u0451\u043c\u0441\u044f. \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u2014 \u044d\u0442\u043e <strong><em>\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e<\/em><\/strong>. \u041f\u0440\u0438\u0448\u043b\u0430 \u043f\u043e\u0440\u0430 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c\u0441\u044f!<\/p>\n<h4>\u0420\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0435 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u043e \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435<\/h4>\n<p>\u041c\u044b \u0432\u0441\u0451 \u0435\u0449\u0451 \u043d\u0435 \u0434\u043e \u043a\u043e\u043d\u0446\u0430 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 <em>\u043a\u043b\u0430\u0441\u0441\u0438\u043a\u0443<\/em> \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f. \u041e\u0441\u0442\u0430\u043b\u0430\u0441\u044c \u0435\u0449\u0451 \u043e\u0434\u043d\u0430 \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u2014 \u00ab\u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0441\u0442\u044c \u0441\u0432\u0451\u0440\u0442\u043e\u043a\u00bb. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0432\u0451\u0440\u0442\u043a\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430\u0448 <a href=\"https:\/\/blog.frost.kiwi\/dual-kawase\/#box-blur\" rel=\"noopener noreferrer nofollow\">Box Blur<\/a>, \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u043e \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u0438 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u0430\u044f \u0432\u044b\u0448\u0435 <a href=\"https:\/\/bartwronski.com\/2021\/10\/31\/practical-gaussian-filter-binomial-filter-and-small-sigma-gaussians\/\" rel=\"noopener noreferrer nofollow\">\u0431\u0438\u043d\u043e\u043c\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f<\/a>, \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0437\u0430 \u0434\u0432\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0445\u043e\u0434\u0430 \u0434\u0432\u0443\u043c\u044f <strong><em>\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c\u0438<\/em><\/strong>\u00a01D-\u044f\u0434\u0440\u0430\u043c\u0438.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/830\/e33\/028\/830e330288336524eab232b59a46669c.jpg\" alt=\"\u0420\u0430\u0437\u0431\u0438\u0442\u0430\u044f \u043d\u0430 \u0447\u0430\u0441\u0442\u0438 \u0444\u043e\u0440\u043c\u0443\u043b\u0430 \u0432\u0435\u0441\u043e\u0432 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f\" title=\"\u0420\u0430\u0437\u0431\u0438\u0442\u0430\u044f \u043d\u0430 \u0447\u0430\u0441\u0442\u0438 \u0444\u043e\u0440\u043c\u0443\u043b\u0430 \u0432\u0435\u0441\u043e\u0432 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f\" width=\"348\" height=\"227\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/830\/e33\/028\/830e330288336524eab232b59a46669c.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/830\/e33\/028\/830e330288336524eab232b59a46669c.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0430\u0437\u0431\u0438\u0442\u0430\u044f \u043d\u0430 \u0447\u0430\u0441\u0442\u0438 \u0444\u043e\u0440\u043c\u0443\u043b\u0430 \u0432\u0435\u0441\u043e\u0432 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0435 \u0432\u0441\u0435 \u0441\u0432\u0451\u0440\u0442\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0442\u044c. \u0412 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u043a\u0438: \u0435\u0441\u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u0432\u0435\u0441\u0430 \u044f\u0434\u0440\u0430 \u0432 \u0432\u0438\u0434\u0435 \u0444\u043e\u0440\u043c\u0443\u043b\u044b \u0441 \u043e\u0441\u044f\u043c\u0438 <code>X, Y<\/code>, \u0438 \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c <code>X<\/code>\u00a0\u0438 <code>Y<\/code>\u00a0\u0432 \u0434\u0432\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0443\u043b\u044b, \u0442\u043e \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0441\u0442\u044c 2D-\u044f\u0434\u0440\u0430 \u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u0432\u0451\u0440\u0442\u043a\u0443 \u0432 \u0434\u0432\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0430, \u0441\u0438\u043b\u044c\u043d\u043e \u044d\u043a\u043e\u043d\u043e\u043c\u044f \u043d\u0430 texture tap.<\/p>\n<blockquote>\n<p><em>\u0412 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043a\u0440\u0443\u043f\u043d\u043e\u0431\u044e\u0434\u0436\u0435\u0442\u043d\u044b\u0445 \u0432\u0438\u0434\u0435\u043e\u0438\u0433\u0440\u0430\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u044b \u0441 \u044f\u0434\u0440\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 <\/em><strong><em>\u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e<\/em><\/strong><em> \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c, \u043d\u043e \u0440\u0430\u0434\u0438 \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043e\u043d\u0438 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0438\u0441\u044c \u0432 \u0434\u0432\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0430 \u043f\u043b\u044e\u0441 + 1D-\u044f\u0434\u0440\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043b\u0438 \u043d\u0435 \u0442\u0430\u043a\u0438\u043c\u0438 \u0443\u0436 \u043f\u043b\u043e\u0445\u0438\u043c\u0438.<\/em><\/p>\n<\/blockquote>\n<p>Computerphile \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448\u043e \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u043b \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044e \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0441\u0442\u0438 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 2D-\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u0442\u0430\u043a \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0431\u043e\u043b\u0435\u0435 \u0444\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435, \u0442\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0432\u0438\u0434\u0435\u043e.<\/p>\n<p><a href=\"https:\/\/embedd.srv.habr.com\/iframe\/68c128d9b28d31b26cce0694\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed_link embed_layout-right\"><\/p>\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;undefined&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>\ud83c\udcad<\/span><\/div>\n<div class=\"embed__caption-description\">undefined&#8230;<\/div>\n<p><span class=\"embed__caption-host\">embedd.srv.habr.com<\/span><\/div>\n<p><\/a><\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u043d\u0430\u0448\u0435 \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u043e \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435, \u043d\u043e \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. \u041c\u044b \u0432\u0438\u0434\u0438\u043c \u043f\u0440\u043e\u0445\u043e\u0434 1 \u0438 \u043f\u0440\u043e\u0445\u043e\u0434 2, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442. \u0422\u043e \u0436\u0435 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e, \u0447\u0442\u043e \u0438 \u0432 \u043d\u0430\u0448\u0435\u043c \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u043e\u043c \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0438, \u0442\u0435 \u0436\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u043d\u043e \u0432\u0441\u0451 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0445 texture tap \u043d\u0435 \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u0435\u0442 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u0447\u043d\u043e.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441 kernelSize 19&#215;19<\/strong><\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e3c\/504\/ed8\/e3c504ed8eb0de5fc5a37ab2debd8fb3.png\" alt=\"\u0421\u0446\u0435\u043d\u0430: \u043f\u0440\u043e\u0445\u043e\u0434 1\" title=\"\u0421\u0446\u0435\u043d\u0430: \u043f\u0440\u043e\u0445\u043e\u0434 1\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/e3c\/504\/ed8\/e3c504ed8eb0de5fc5a37ab2debd8fb3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e3c\/504\/ed8\/e3c504ed8eb0de5fc5a37ab2debd8fb3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0446\u0435\u043d\u0430: \u043f\u0440\u043e\u0445\u043e\u0434 1<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fd0\/91e\/6b5\/fd091e6b56b9538f45e3f0e16cbfd5f8.png\" alt=\"\u0421\u0446\u0435\u043d\u0430: \u043f\u0440\u043e\u0445\u043e\u0434 2\" title=\"\u0421\u0446\u0435\u043d\u0430: \u043f\u0440\u043e\u0445\u043e\u0434 2\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/fd0\/91e\/6b5\/fd091e6b56b9538f45e3f0e16cbfd5f8.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fd0\/91e\/6b5\/fd091e6b56b9538f45e3f0e16cbfd5f8.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0446\u0435\u043d\u0430: \u043f\u0440\u043e\u0445\u043e\u0434 2<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/17a\/168\/567\/17a168567549ce9a6e5511d512cb7eb7.png\" alt=\"\u0421\u0446\u0435\u043d\u0430: \u043e\u0431\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0430\" title=\"\u0421\u0446\u0435\u043d\u0430: \u043e\u0431\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0430\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/17a\/168\/567\/17a168567549ce9a6e5511d512cb7eb7.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/17a\/168\/567\/17a168567549ce9a6e5511d512cb7eb7.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0446\u0435\u043d\u0430: \u043e\u0431\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0430<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/73c\/647\/f62\/73c647f62faba99dd1e08b423b97aead.png\" alt=\"\u0421\u0432\u0435\u0442: \u043f\u0440\u043e\u0445\u043e\u0434 1\" title=\"\u0421\u0432\u0435\u0442: \u043f\u0440\u043e\u0445\u043e\u0434 1\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/73c\/647\/f62\/73c647f62faba99dd1e08b423b97aead.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/73c\/647\/f62\/73c647f62faba99dd1e08b423b97aead.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0432\u0435\u0442: \u043f\u0440\u043e\u0445\u043e\u0434 1<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/643\/a08\/c18\/643a08c184ec849fe9321b60165e9e5e.png\" alt=\"\u0421\u0432\u0435\u0442: \u043f\u0440\u043e\u0445\u043e\u0434 2\" title=\"\u0421\u0432\u0435\u0442: \u043f\u0440\u043e\u0445\u043e\u0434 2\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/643\/a08\/c18\/643a08c184ec849fe9321b60165e9e5e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/643\/a08\/c18\/643a08c184ec849fe9321b60165e9e5e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0432\u0435\u0442: \u043f\u0440\u043e\u0445\u043e\u0434 2<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fa9\/99f\/7d5\/fa999f7d503710cfbd307455a69dd9ea.png\" alt=\"\u0421\u0432\u0435\u0442: \u043e\u0431\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0430\" title=\"\u0421\u0432\u0435\u0442: \u043e\u0431\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0430\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/fa9\/99f\/7d5\/fa999f7d503710cfbd307455a69dd9ea.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fa9\/99f\/7d5\/fa999f7d503710cfbd307455a69dd9ea.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0432\u0435\u0442: \u043e\u0431\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0430<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d85\/843\/431\/d85843431ea1317d364e6f8ff704c8d1.png\" alt=\"Bloom: \u043f\u0440\u043e\u0445\u043e\u0434 1\" title=\"Bloom: \u043f\u0440\u043e\u0445\u043e\u0434 1\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d85\/843\/431\/d85843431ea1317d364e6f8ff704c8d1.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d85\/843\/431\/d85843431ea1317d364e6f8ff704c8d1.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>Bloom: \u043f\u0440\u043e\u0445\u043e\u0434 1<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/30f\/7dc\/432\/30f7dc432842657f557c39c9f580200e.png\" alt=\"Bloom: \u043f\u0440\u043e\u0445\u043e\u0434 2\" title=\"Bloom: \u043f\u0440\u043e\u0445\u043e\u0434 2\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/30f\/7dc\/432\/30f7dc432842657f557c39c9f580200e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/30f\/7dc\/432\/30f7dc432842657f557c39c9f580200e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>Bloom: \u043f\u0440\u043e\u0445\u043e\u0434 2<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4a1\/aa6\/59f\/4a1aa659ffc1e41956653dcd42192fab.png\" alt=\"Bloom: \u043e\u0431\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0430\" title=\"Bloom: \u043e\u0431\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0430\" width=\"680\" height=\"510\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/4a1\/aa6\/59f\/4a1aa659ffc1e41956653dcd42192fab.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4a1\/aa6\/59f\/4a1aa659ffc1e41956653dcd42192fab.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>Bloom: \u043e\u0431\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0430<\/figcaption><\/div>\n<\/figure>\n<details class=\"spoiler\">\n<summary>\u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">\/* \u0412\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u0441 \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0435\u0439 \u0437\u0430\u043f\u044f\u0442\u043e\u0439 \u043d\u0430 highp, \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f.   \u041f\u0440\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0440\u0430\u0437\u043c\u0435\u0440\u0430\u0445 \u044f\u0434\u0440\u0430 \u043d\u0430 \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u0432\u043b\u0438\u044f\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0446\u0432\u0435\u0442\u043e\u0432, \u0430 \u043f\u043e\u0442\u043e\u043c\u0443 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f   \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043e\u0442\u0441\u0435\u0447\u0435\u043d\u0438\u044f.   \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 \u0448\u0435\u0439\u0434\u0435\u0440\u0430\u0445 WebGL 1, \u0430 \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 \u043c\u043e\u0436\u0435\u0442 \u043d\u0438 \u043d\u0430 \u0447\u0442\u043e \u043d\u0435 \u0432\u043b\u0438\u044f\u0442\u044c *\/precision highp float;\/* UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0438\u0437 \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430 *\/varying vec2 uv;uniform vec2 frameSizeRCP; \/* \u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430, \u043e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044e *\/uniform float samplePosMult; \/* \u0423\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u0441\u0438\u043b\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0431\u044b\u043b\u0430 \u0431\u043e\u043b\u044c\u0448\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u044f\u0434\u0440\u0430 *\/uniform float sigma;uniform vec2 direction; \/* \u0412\u0435\u043a\u0442\u043e\u0440 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f: (1,0) \u0434\u043b\u044f \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e, (0,1) \u0434\u043b\u044f \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e *\/uniform float bloomStrength; \/* \u0441\u0438\u043b\u0430 bloom *\/uniform sampler2D texture;\/* `KERNEL_SIZE` \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 *\/const int kernel_size = KERNEL_SIZE;float gaussianWeight(float x, float sigma){\/* e ^ ( - x\u00b2 \/ 2 \u03c3\u00b2 ) *\/return exp(-(x * x) \/ (2.0 * sigma * sigma));}void main() {\/* \u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f *\/vec4 sum = vec4(0.0);\/* \u0421\u0443\u043c\u043c\u0430 \u0432\u0441\u0435\u0445 \u0432\u0435\u0441\u043e\u0432 *\/float weightSum = 0.0;\/* \u0412\u0435\u043b\u0438\u0447\u0438\u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0441\u044d\u043c\u043f\u043b\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0430 *\/const int size = 2 * kernel_size + 1;\/* \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0441\u044d\u043c\u043f\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0434\u043e\u043b\u044c \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f (\u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e) *\/for (int i = -kernel_size; i &lt;= kernel_size; ++i) {\/* \u0412\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0439 \u044d\u0442\u043e\u043c\u0443 1D-\u0441\u044d\u043c\u043f\u043b\u0443 \u0432\u0435\u0441 *\/float w = gaussianWeight(float(i), sigma);\/* \u0421\u043c\u0435\u0449\u0430\u0435\u043c\u0441\u044f \u043e\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f \u0432\u0434\u043e\u043b\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f *\/vec2 offset = vec2(i) * direction * samplePosMult * frameSizeRCP;\/* \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438 \u043f\u0440\u0438\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0437\u0432\u0435\u0448\u0435\u043d\u043d\u044b\u0439 \u0432\u043a\u043b\u0430\u0434 \u044d\u0442\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f *\/sum += texture2D(texture, uv + offset) * w;weightSum += w;}\/* \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0441\u0443\u043c\u043c\u0443, \u043f\u043e\u0434\u0435\u043b\u0451\u043d\u043d\u0443\u044e \u043d\u0430 \u0441\u0443\u043c\u043c\u0430\u0440\u043d\u044b\u0439 \u0432\u0435\u0441 (\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f) *\/gl_FragColor = (sum \/ weightSum) * bloomStrength;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>WebGL Javascript<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">import * as util from '..\/utility.js'export async function setupGaussianSeparableBlur() {\/* \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f *\/const WebGLBox = document.getElementById('WebGLBox-GaussianSeparableBlur');const canvas = WebGLBox.querySelector('canvas');\/* \u0420\u0430\u0437\u043c\u0435\u0440 \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a\u0440\u0443\u0433\u0430 *\/const radius = 0.12;\/* \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 WebGL 1.0 *\/const gl = canvas.getContext('webgl', {preserveDrawingBuffer: false,antialias: false,alpha: false,});\/* \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b *\/const ctx = {\/* \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 *\/mode: \"scene\",passMode: \"pass1\",flags: { isRendering: false, buffersInitialized: false, initComplete: false, benchMode: false },\/* \u0422\u0435\u043a\u0441\u0442\u0443\u0440\u044b *\/tex: { sdr: null, selfIllum: null, frame: null, frameIntermediate: null, frameFinal: null },\/* \u0411\u0443\u0444\u0435\u0440\u044b \u043a\u0430\u0434\u0440\u043e\u0432 *\/fb: { scene: null, intermediate: null, final: null },\/* \u0428\u0435\u0439\u0434\u0435\u0440\u044b \u0438 \u043c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 *\/shd: {scene: { handle: null, uniforms: { offset: null, radius: null } },blur: { handle: null, uniforms: { frameSizeRCP: null, samplePosMult: null, sigma: null, bloomStrength: null, direction: null } },bloom: { handle: null, uniforms: { offset: null, radius: null, texture: null, textureAdd: null } }}};\/* \u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b UI *\/const ui = {display: {spinner: canvas.parentElement.querySelector('svg', canvas.parentElement),contextLoss: canvas.parentElement.querySelector('div', canvas.parentElement),fps: WebGLBox.querySelector('#fps'),ms: WebGLBox.querySelector('#ms'),width: WebGLBox.querySelector('#width'),height: WebGLBox.querySelector('#height'),tapsCount: WebGLBox.querySelector('#taps'),},blur: {kernelSize: WebGLBox.querySelector('#sizeRange'),sigma: WebGLBox.querySelector('#sigmaRange'),samplePos: WebGLBox.querySelector('#samplePosRange'),samplePosReset: WebGLBox.querySelector('#samplePosRangeReset'),},rendering: {animate: WebGLBox.querySelector('#animateCheck'),modes: WebGLBox.querySelectorAll('input[name=\"modeGaussSep\"]'),passModes: WebGLBox.querySelectorAll('input[name=\"passMode\"]'),lightBrightness: WebGLBox.querySelector('#lightBrightness'),lightBrightnessReset: WebGLBox.querySelector('#lightBrightnessReset'),},benchmark: {button: WebGLBox.querySelector('#benchmark'),label: WebGLBox.querySelector('#benchmarkLabel'),iterOut: WebGLBox.querySelector('#iterOut'),renderer: document.getElementById('WebGLBox-GaussianSeparableBlurDetail').querySelector('#renderer'),passMode: document.getElementById('WebGLBox-GaussianSeparableBlurDetail').querySelector('#passMode'),iterTime: document.getElementById('WebGLBox-GaussianSeparableBlurDetail').querySelector('#iterTime'),tapsCount: document.getElementById('WebGLBox-GaussianSeparableBlurDetail').querySelector('#tapsCountBench'),iterations: WebGLBox.querySelector('#iterations')}};\/* \u0428\u0435\u0439\u0434\u0435\u0440\u044b *\/const circleAnimation = await util.fetchShader(\"shader\/circleAnimation.vs\");const simpleTexture = await util.fetchShader(\"shader\/simpleTexture.fs\");const bloomVert = await util.fetchShader(\"shader\/bloom.vs\");const bloomFrag = await util.fetchShader(\"shader\/bloom.fs\");const simpleQuad = await util.fetchShader(\"shader\/simpleQuad.vs\");const gaussianBlurFrag = await util.fetchShader(\"shader\/gaussianBlurSeparable.fs\");\/* \u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0431\u0435\u0437 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439 *\/ui.blur.kernelSize.addEventListener('input', () =&gt; { if (!ui.rendering.animate.checked) redraw() });ui.blur.sigma.addEventListener('input', () =&gt; { if (!ui.rendering.animate.checked) redraw() });ui.blur.samplePos.addEventListener('input', () =&gt; { if (!ui.rendering.animate.checked) redraw() });ui.rendering.lightBrightness.addEventListener('input', () =&gt; { if (!ui.rendering.animate.checked) redraw() });\/* \u0421\u043e\u0431\u044b\u0442\u0438\u044f *\/ui.rendering.animate.addEventListener(\"change\", () =&gt; {if (ui.rendering.animate.checked)startRendering();else {ui.display.fps.value = \"-\";ui.display.ms.value = \"-\";ctx.flags.isRendering = false;redraw()}});canvas.addEventListener(\"webglcontextlost\", () =&gt; {ui.display.contextLoss.style.display = \"block\";});ui.blur.kernelSize.addEventListener('input', () =&gt; {reCompileBlurShader(ui.blur.kernelSize.value);ui.blur.samplePos.disabled = ui.blur.kernelSize.value == 0;ui.blur.samplePosReset.disabled = ui.blur.kernelSize.value == 0;});\/* \u0420\u0435\u0436\u0438\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 *\/ui.rendering.modes.forEach(radio =&gt; {\/* \u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 scene, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u044c \u0431\u0430\u0433 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432 Firefox Android *\/if (radio.value === \"scene\")radio.checked = true;radio.addEventListener('change', (event) =&gt; {ctx.mode = event.target.value;ui.rendering.lightBrightness.disabled = ctx.mode === \"scene\";ui.rendering.lightBrightnessReset.disabled = ctx.mode === \"scene\";if (!ui.rendering.animate.checked) redraw();});});\/* \u0420\u0435\u0436\u0438\u043c \u043f\u0440\u043e\u0445\u043e\u0434\u0430 *\/ui.rendering.passModes.forEach(radio =&gt; {\/* \u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 pass1, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u044c \u0431\u0430\u0433 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432 Firefox Android *\/if (radio.value === \"pass1\")radio.checked = true;radio.addEventListener('change', (event) =&gt; {ctx.passMode = event.target.value;if (!ui.rendering.animate.checked) redraw();});});ui.benchmark.button.addEventListener(\"click\", () =&gt; {ctx.flags.benchMode = true;stopRendering();ui.display.spinner.style.display = \"block\";ui.benchmark.button.disabled = true;\/* \u0417\u0430\u043f\u0443\u0441\u043a \u0432\u043e\u0440\u043a\u0435\u0440\u0430 (ES-module) *\/const worker = new Worker(\".\/js\/benchmark\/gaussianSeparableBlurBenchmark.js\", { type: \"module\" });\/* \u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0432\u0441\u0435\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043d\u0443\u0436\u043d\u044b\u0445 \u0432\u043e\u0440\u043a\u0435\u0440\u0443 *\/worker.postMessage({iterations: ui.benchmark.iterOut.value,blurShaderSrc: gaussianBlurFrag,kernelSize: ui.blur.kernelSize.value,samplePos: ui.blur.samplePos.value,sigma: ui.blur.sigma.value,passMode: ctx.passMode});\/* \u0411\u0435\u043d\u0447\u043c\u0430\u0440\u043a *\/worker.addEventListener(\"message\", (event) =&gt; {if (event.data.type !== \"done\") return;ui.benchmark.label.textContent = event.data.benchText;ui.benchmark.tapsCount.textContent = event.data.tapsCount;ui.benchmark.iterTime.textContent = event.data.iterationText;ui.benchmark.renderer.textContent = event.data.renderer;ui.benchmark.passMode.textContent = event.data.passMode;worker.terminate();ui.benchmark.button.disabled = false;ctx.flags.benchMode = false;if (ui.rendering.animate.checked)startRendering();elseredraw();});});ui.benchmark.iterations.addEventListener(\"change\", (event) =&gt; {ui.benchmark.iterOut.value = event.target.value;ui.benchmark.label.textContent = \"Benchmark\";});\/* \u041e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \u0442\u0435\u043a\u0441\u0442\u0443\u0440 *\/ctx.shd.scene = util.compileAndLinkShader(gl, circleAnimation, simpleTexture, [\"offset\", \"radius\"]);\/* \u041e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u0448\u0435\u0439\u0434\u0435\u0440\u0430 bloom *\/ctx.shd.bloom = util.compileAndLinkShader(gl, bloomVert, bloomFrag, [\"texture\", \"textureAdd\", \"offset\", \"radius\"]);\/* \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0440\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 *\/function reCompileBlurShader(blurSize) {ctx.shd.blur = util.compileAndLinkShader(gl, simpleQuad, gaussianBlurFrag, [\"frameSizeRCP\", \"samplePosMult\", \"bloomStrength\", \"sigma\", \"direction\"], \"#define KERNEL_SIZE \" + blurSize + '\\n');}\/* \u0428\u0435\u0439\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f *\/reCompileBlurShader(ui.blur.kernelSize.value)\/* \u041f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0432 GPU *\/util.bindUnitQuad(gl);async function setupTextureBuffers() {ui.display.spinner.style.display = \"block\";ctx.flags.buffersInitialized = true;ctx.flags.initComplete = false;gl.deleteFramebuffer(ctx.fb.scene);gl.deleteFramebuffer(ctx.fb.intermediate);gl.deleteFramebuffer(ctx.fb.final);[ctx.fb.scene, ctx.tex.frame] = util.setupFramebuffer(gl, canvas.width, canvas.height);[ctx.fb.intermediate, ctx.tex.frameIntermediate] = util.setupFramebuffer(gl, canvas.width, canvas.height);[ctx.fb.final, ctx.tex.frameFinal] = util.setupFramebuffer(gl, canvas.width, canvas.height);\/\/ \u0421\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u0443\u044e \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u0443, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043f\u0440\u0438 \u043b\u0435\u043d\u0438\u0432\u043e\u0439 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438gl.bindFramebuffer(gl.FRAMEBUFFER, ctx.fb.intermediate);gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.clear(gl.COLOR_BUFFER_BIT);let [base, selfIllum] = await Promise.all([fetch(\"\/dual-kawase\/img\/SDR_No_Sprite.png\"),fetch(\"\/dual-kawase\/img\/Selfillumination.png\")]);let [baseBlob, selfIllumBlob] = await Promise.all([base.blob(), selfIllum.blob()]);let [baseBitmap, selfIllumBitmap] = await Promise.all([createImageBitmap(baseBlob, { colorSpaceConversion: 'none', resizeWidth: canvas.width * 1.12, resizeHeight: canvas.height * 1.12, resizeQuality: \"high\" }),createImageBitmap(selfIllumBlob, { colorSpaceConversion: 'none', resizeWidth: canvas.width * 1.12, resizeHeight: canvas.height * 1.12, resizeQuality: \"high\" })]);ctx.tex.sdr = util.setupTexture(gl, null, null, ctx.tex.sdr, gl.LINEAR, baseBitmap);ctx.tex.selfIllum = util.setupTexture(gl, null, null, ctx.tex.selfIllum, gl.LINEAR, selfIllumBitmap);baseBitmap.close();selfIllumBitmap.close();ctx.flags.initComplete = true;ui.display.spinner.style.display = \"none\";}let prevNow = performance.now();let lastStatsUpdate = prevNow;let fpsEMA = 60;let msEMA = 16;async function redraw() {if (!ctx.flags.buffersInitialized)await setupTextureBuffers();if (!ctx.flags.initComplete)return;\/* \u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 UI  *\/const KernelSizeSide = ui.blur.kernelSize.value * 2 + 1;\/* \u0420\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0435 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435: pass1\/pass2 = 1 \u043f\u0440\u043e\u0445\u043e\u0434, combined = 2 \u043f\u0440\u043e\u0445\u043e\u0434\u0430 *\/const samplesPerPixel = ctx.passMode == \"combined\" ? KernelSizeSide * 2 : KernelSizeSide;const tapsNewText = (canvas.width * canvas.height * samplesPerPixel \/ 1000000).toFixed(1) + \" Million\";ui.display.tapsCount.value = tapsNewText;ui.display.width.value = canvas.width;ui.display.height.value = canvas.height;\/* \u041a\u0440\u0443\u0433\u043e\u0432\u043e\u0435 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 Motion *\/let radiusSwitch = ui.rendering.animate.checked ? radius : 0.0;let speed = (performance.now() \/ 10000) % Math.PI * 2;const offset = [radiusSwitch * Math.cos(speed), radiusSwitch * Math.sin(speed)];gl.useProgram(ctx.shd.scene.handle);const texture = ctx.mode == \"scene\" ? ctx.tex.sdr : ctx.tex.selfIllum;gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, texture);gl.uniform2fv(ctx.shd.scene.uniforms.offset, offset);gl.uniform1f(ctx.shd.scene.uniforms.radius, radiusSwitch);\/* \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0431\u0443\u0444\u0435\u0440\u0430 \u043a\u0430\u0434\u0440\u043e\u0432 \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 *\/gl.bindFramebuffer(gl.FRAMEBUFFER, ctx.fb.scene);gl.viewport(0, 0, canvas.width, canvas.height);\/* \u0412\u044b\u0437\u043e\u0432 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 *\/gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);\/* \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0433\u043e \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u0430 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f *\/gl.useProgram(ctx.shd.blur.handle);if (ctx.passMode == \"pass1\") {\/* \u0422\u043e\u043b\u044c\u043a\u043e Pass 1: \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d *\/const finalFB = ctx.mode == \"bloom\" ? ctx.fb.final : null;gl.bindFramebuffer(gl.FRAMEBUFFER, finalFB);gl.viewport(0, 0, canvas.width, canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.bloomStrength, ctx.mode == \"scene\" ? 1.0 : ui.rendering.lightBrightness.value);gl.uniform2f(ctx.shd.blur.uniforms.direction, 1.0, 0.0); \/\/ \u0413\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.frame);gl.uniform2f(ctx.shd.blur.uniforms.frameSizeRCP, 1.0 \/ canvas.width, 1.0 \/ canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.samplePosMult, ui.blur.samplePos.value);gl.uniform1f(ctx.shd.blur.uniforms.sigma, Math.max(ui.blur.kernelSize.value \/ ui.blur.sigma.value, 0.001));gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);} else if (ctx.passMode == \"pass2\") {\/* \u0422\u043e\u043b\u044c\u043a\u043e Pass 2: \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d *\/const finalFB = ctx.mode == \"bloom\" ? ctx.fb.final : null;gl.bindFramebuffer(gl.FRAMEBUFFER, finalFB);gl.viewport(0, 0, canvas.width, canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.bloomStrength, ctx.mode == \"scene\" ? 1.0 : ui.rendering.lightBrightness.value);gl.uniform2f(ctx.shd.blur.uniforms.direction, 0.0, 1.0); \/\/ \u0412\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.frame);gl.uniform2f(ctx.shd.blur.uniforms.frameSizeRCP, 1.0 \/ canvas.width, 1.0 \/ canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.samplePosMult, ui.blur.samplePos.value);gl.uniform1f(ctx.shd.blur.uniforms.sigma, Math.max(ui.blur.kernelSize.value \/ ui.blur.sigma.value, 0.001));gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);} else {\/* Combined: \u0434\u0432\u0443\u0445\u043f\u0440\u043e\u0445\u043e\u0434\u043d\u043e\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0435 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 *\/\/* Pass 1: \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u0432 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u0431\u0443\u0444\u0435\u0440 *\/gl.bindFramebuffer(gl.FRAMEBUFFER, ctx.fb.intermediate);gl.viewport(0, 0, canvas.width, canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.bloomStrength, ctx.mode == \"scene\" ? 1.0 : ui.rendering.lightBrightness.value);gl.uniform2f(ctx.shd.blur.uniforms.direction, 1.0, 0.0); \/\/ \u0413\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.frame);gl.uniform2f(ctx.shd.blur.uniforms.frameSizeRCP, 1.0 \/ canvas.width, 1.0 \/ canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.samplePosMult, ui.blur.samplePos.value);gl.uniform1f(ctx.shd.blur.uniforms.sigma, Math.max(ui.blur.kernelSize.value \/ ui.blur.sigma.value, 0.001));gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);\/* Pass 2: \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u0432 final *\/const finalFB = ctx.mode == \"bloom\" ? ctx.fb.final : null;gl.bindFramebuffer(gl.FRAMEBUFFER, finalFB);gl.viewport(0, 0, canvas.width, canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.bloomStrength, ctx.mode == \"scene\" ? 1.0 : ui.rendering.lightBrightness.value);gl.uniform2f(ctx.shd.blur.uniforms.direction, 0.0, 1.0); \/\/ \u0412\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.frameIntermediate);gl.uniform2f(ctx.shd.blur.uniforms.frameSizeRCP, 1.0 \/ canvas.width, 1.0 \/ canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.samplePosMult, ui.blur.samplePos.value);gl.uniform1f(ctx.shd.blur.uniforms.sigma, Math.max(ui.blur.kernelSize.value \/ ui.blur.sigma.value, 0.001));gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);}if (ctx.mode == \"bloom\") {\/* \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u0438\u043d\u0433 bloom \u043d\u0430 \u044d\u043a\u0440\u0430\u043d *\/gl.bindFramebuffer(gl.FRAMEBUFFER, null);gl.useProgram(ctx.shd.bloom.handle);gl.uniform2fv(ctx.shd.bloom.uniforms.offset, offset);gl.uniform1f(ctx.shd.bloom.uniforms.radius, radiusSwitch);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.sdr);gl.uniform1i(ctx.shd.bloom.uniforms.texture, 0);gl.activeTexture(gl.TEXTURE1);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.frameFinal);gl.uniform1i(ctx.shd.bloom.uniforms.textureAdd, 1);gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);}\/* \u041f\u0440\u043e\u0441\u0438\u043c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e CPU-GPU \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0443 GPU \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u0438\u043d\u0433\u0435.   \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u044d\u0442\u043e \u0441 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u0441\u0431\u0440\u043e\u0441\u0443, \u043d\u043e, \u043f\u043e\u0445\u043e\u0436\u0435,    \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043d\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445 \u0441 \u043d\u0438\u0437\u043a\u0438\u043c FPS *\/gl.finish();const now = performance.now();let dt = now - prevNow;if (dt &gt; 0) {const instFPS = 1000 \/ dt;const ALPHA = 0.05;fpsEMA = ALPHA * instFPS + (1 - ALPHA) * fpsEMA;msEMA = ALPHA * dt + (1 - ALPHA) * msEMA;}prevNow = now;if (ui.rendering.animate.checked &amp;&amp; now - lastStatsUpdate &gt;= 1000) {ui.display.fps.value = fpsEMA.toFixed(0);ui.display.ms.value = msEMA.toFixed(2);lastStatsUpdate = now;}}let animationFrameId;\/* \u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c *\/function nativeResize() {const [width, height] = util.getNativeSize(canvas);if (width &amp;&amp; canvas.width !== width || height &amp;&amp; canvas.height !== height) {canvas.width = width;canvas.height = height;if (!ctx.flags.benchMode) {stopRendering();startRendering();}if (!ui.rendering.animate.checked)redraw();}}\/* \u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u0430 *\/nativeResize();let resizePending = false;window.addEventListener('resize', () =&gt; {if (!resizePending) {resizePending = true;requestAnimationFrame(() =&gt; {resizePending = false;nativeResize();});}});function renderLoop() {if (ctx.flags.isRendering &amp;&amp; ui.rendering.animate.checked) {redraw();animationFrameId = requestAnimationFrame(renderLoop);}}function startRendering() {\/* \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433, \u043a\u043e\u0433\u0434\u0430 canvas \u0432\u0438\u0434\u0438\u043c *\/ctx.flags.isRendering = true;renderLoop();}function stopRendering() {\/* \u041e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0432\u044b\u0437\u043e\u0432 \u0435\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0438 *\/ctx.flags.isRendering = false;cancelAnimationFrame(animationFrameId);\/* \u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0441 CPU, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0432\u043c\u0435\u0448\u0430\u0435\u043c\u0441\u044f \u0432 \u043d\u0435\u0433\u043e *\/gl.finish();\/* \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0431\u0443\u0444\u0435\u0440\u044b, \u0447\u0442\u043e\u0431\u044b \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c *\/gl.deleteTexture(ctx.tex.sdr); ctx.tex.sdr = null;gl.deleteTexture(ctx.tex.selfIllum); ctx.tex.selfIllum = null;gl.deleteTexture(ctx.tex.frame); ctx.tex.frame = null;gl.deleteTexture(ctx.tex.frameIntermediate); ctx.tex.frameIntermediate = null;gl.deleteTexture(ctx.tex.frameFinal); ctx.tex.frameFinal = null;gl.deleteFramebuffer(ctx.fb.scene); ctx.fb.scene = null;gl.deleteFramebuffer(ctx.fb.intermediate); ctx.fb.intermediate = null;gl.deleteFramebuffer(ctx.fb.final); ctx.fb.final = null;ctx.flags.buffersInitialized = false;ctx.flags.initComplete = false;ui.display.fps.value = \"-\";ui.display.ms.value = \"-\";}function handleIntersection(entries) {entries.forEach(entry =&gt; {if (entry.isIntersecting) {if (!ctx.flags.isRendering &amp;&amp; !ctx.flags.benchMode) startRendering();} else {stopRendering();}});}\/* \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 canvas \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 *\/let observer = new IntersectionObserver(handleIntersection);observer.observe(canvas);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439 \u0441\u043a\u0430\u0447\u043e\u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u043d\u0430\u0448\u0438\u043c \u0433\u0430\u0443\u0441\u0441\u043e\u0432\u044b\u043c \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435\u043c! \u041d\u043e \u0437\u0434\u0435\u0441\u044c \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e <em>\u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f<\/em> \u0438\u0434\u0442\u0438 \u043d\u0430 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441, \u043f\u0443\u0441\u0442\u044c \u0438 \u043d\u0435 \u0442\u0430\u043a\u043e\u0439 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0439. \u0427\u0442\u043e\u0431\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0434\u0432\u0443\u043c\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u0430\u043c\u0438, \u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u043d\u043e\u0432\u044b\u0439 \u0431\u0443\u0444\u0435\u0440 \u043a\u0430\u0434\u0440\u043e\u0432. \u041f\u043e\u043c\u043d\u0438\u0442\u0435, \u043c\u044b \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0447\u0438\u043f\u044b \u0438\u043c\u0435\u044e\u0442 \u0432\u044b\u0441\u043e\u043a\u0443\u044e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c, \u043d\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043f\u0430\u043c\u044f\u0442\u0438 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u0451 \u043d\u0435 \u0442\u0430\u043a\u0430\u044f \u0431\u043e\u043b\u044c\u0448\u0430\u044f?<\/p>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0438\u0433\u0440 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0430\u0445 4k \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u0440\u043e\u0445\u043e\u0434\u043e\u0432 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u043f\u0430\u043c\u044f\u0442\u044c 8,2 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0438\u0445 \u0441\u043d\u043e\u0432\u0430. \u041f\u0440\u0438 \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u0438 \u044f\u0434\u0435\u0440 \u043d\u0430 \u0434\u0438\u0441\u043f\u043b\u0435\u044f\u0445 \u0432\u044b\u0441\u043e\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0435 \u044f\u0434\u0440\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u0435\u0435. \u041d\u043e \u043f\u0440\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0438 \u044f\u0434\u0435\u0440 \u043e\u043d\u043e \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u044b\u0441\u0442\u0440\u0435\u0435. \u041d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0442\u0430\u043a\u043e\u043c \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u043c \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0438?<\/p>\n<p><em>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442&#8230;<\/em><\/p>\n<\/div>\n<p>\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\/articles\/1041710\/\">https:\/\/habr.com\/ru\/articles\/1041710\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0420\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u2014 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0441\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0431\u043b\u043e\u043a \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432 \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 \u0432\u0438\u0434\u0435\u043e\u0438\u0433\u0440\u0430\u0445, \u0431\u0435\u0437 \u043d\u0435\u0433\u043e \u043d\u0435 \u043e\u0431\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 GUI. \u041e\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u044d\u0444\u0444\u0435\u043a\u0442\u0430\u0445 Depth of Field, Bloom\u00a0\u0438\u043b\u0438 \u043f\u0430\u043d\u0435\u043b\u044f\u0445 \u0441 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u043c \u043c\u0430\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0435\u043a\u043b\u0430 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432.\u042d\u0444\u0444\u0435\u043a\u0442 Bloom \u2014 \u043e\u0434\u0438\u043d \u0438\u0437 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u043b\u0435\u0433\u043a\u043e, \u0435\u0433\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u0441\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a \u0442\u043e\u043c\u0443 \u0438\u043b\u0438 \u0438\u043d\u043e\u043c\u0443 \u0441\u043f\u043e\u0441\u043e\u0431\u0443 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u044f \u0446\u0432\u0435\u0442\u043e\u0432 \u0432 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u043c \u0440\u0430\u0434\u0438\u0443\u0441\u0435. \u041e\u0434\u043d\u0430\u043a\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0435\u0433\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u0438\u0441\u044c \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u043b\u0435\u0442 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0439 \u0438 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 computer science \u0438 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0435. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u044d\u0442\u0430\u043f\u043d\u043e \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u0438\u0445; \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u043f\u0443\u0442\u0435\u0448\u0435\u0441\u0442\u0432\u0438\u0435\u043c \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 \u0441\u0444\u0435\u0440\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u043a\u0438.\u0412 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u0442\u0435\u0445\u043d\u0438\u043a\u0438 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e GPU\u00a0\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c WebGL\u00a0\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430.\u041d\u0430\u0447\u0430\u043b\u043e: \u043f\u043e\u043a\u0430 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f\u0412 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0438\u0434\u0435\u043e\u0438\u0433\u0440 3D-\u0441\u0446\u0435\u043d\u0430 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f (\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u0441\u044f) \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u2014 \u0431\u0443\u0444\u0435\u0440 \u043a\u0430\u0434\u0440\u043e\u0432. \u0412 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u044d\u0442\u043e\u0442 \u0431\u0443\u0444\u0435\u0440 \u043a\u0430\u0434\u0440\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432. \u0422\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430\u00a0\u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u0441\u043b\u0435\u00a0\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 3D-\u0441\u0446\u0435\u043d\u044b, \u043e\u043d\u0430 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439. \u0418 \u043e\u043d\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0443.\u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u0435\u0445\u043d\u0438\u043a \u0431\u0443\u0444\u0435\u0440\u044b \u043a\u0430\u0434\u0440\u043e\u0432 \u043c\u043e\u0433\u0443\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u0435\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0430 \u044d\u0444\u0444\u0435\u043a\u0442\u044b \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430\u043f\u043e\u0434\u043e\u0431\u0438\u0435 \u0446\u0432\u0435\u0442\u043e\u0432\u043e\u0439 \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u0438\u00a0\u0438\u043b\u0438 \u0442\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u0438\u00a0\u0434\u0430\u0436\u0435 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0445 \u0431\u0443\u0444\u0435\u0440\u043e\u0432 \u043a\u0430\u0434\u0440\u043e\u0432: \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u043d\u044b\u043c\u0438\u00a0\u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438 (\u0441\u043c. \u0432\u0438\u0434\u0435\u043e \u0441 35:20)\u041d\u0430\u043c \u0432\u0430\u0436\u0435\u043d \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442: \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0431\u0443\u0444\u0435\u0440 \u043a\u0430\u0434\u0440\u043e\u0432 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 3D-\u0441\u0446\u0435\u043d\u044b. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u0446\u0435\u043d\u0443 \u0438\u0437 \u043c\u043e\u0434\u0430 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c NEOTOKYO\u00b0. \u041f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0432 canvas, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 WebGL 1.0, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0432\u0430\u0448\u0435\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430. \u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0435\u0441\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438, \u0430 \u043d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u043a\u043e\u0434\u0430.\u0421\u0446\u0435\u043d\u0430\u0421\u0432\u0435\u0442Bloom\u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f\/* \u042d\u0442\u043e &#171;\u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440&#187; \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f &#8212; \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u0430\u044f \u043d\u0430 GPU.   \u0412 *\u044d\u0442\u043e\u0439* \u0441\u0442\u0430\u0442\u044c\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u0440\u0430\u0437\u0443   \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430 canvas *\/\/* \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 WebGL 1 \u0438 \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 \u043c\u043e\u0436\u0435\u0442   \u043d\u0438 \u043d\u0430 \u0447\u0442\u043e \u043d\u0435 \u0432\u043b\u0438\u044f\u0442\u044c.   \u041d\u0430 \u0431\u0443\u0434\u0443\u0449\u0435\u0435: \u0432 \u0441\u0438\u043b\u044c\u043d\u044b\u0445 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f\u0445 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043d\u0435\u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0432\u043b\u0438\u044f\u043d\u0438\u0439   \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0446\u0432\u0435\u0442\u043e\u0432, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0437\u0430\u0434\u0430\u0451\u043c \u0437\u0434\u0435\u0441\u044c &#171;highp&#187;, \u0442\u043e \u0435\u0441\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c. *\/precision highp float;\/* UV-\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0438\u0437 \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430 &#171;simpleQuad.vs&#187;.   \u041e\u043d\u0438 \u0441\u043e\u043e\u0431\u0449\u0430\u044e\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u043f\u0438\u043a\u0441\u0435\u043b\u044e \u0432\u044b\u0432\u043e\u0434\u0430, \u043e\u0442\u043a\u0443\u0434\u0430 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u0443. *\/varying vec2 uv;\/* \u0412\u0432\u043e\u0434 lightBrightness. \u042f\u0440\u043a\u043e\u0441\u0442\u044c \u0441\u0432\u0435\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u043e\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u0435   \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f, \u0430 \u043d\u0435 \u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0438, \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u043c \u043d\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c \u044d\u0442\u0430\u043f\u0435, \u0438\u0437-\u0437\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439   \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u0446\u0432\u0435\u0442\u0430. *\/uniform float lightBrightness;\/* \u0422\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0439 \u0432\u0432\u043e\u0434 *\/uniform sampler2D texture;\/* \u0424\u0443\u043d\u043a\u0446\u0438\u044f &#171;main&#187;, \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u0430\u044f \u0432 GPU *\/void main() {\/* gl_FragColor &#8212; \u044d\u0442\u043e \u0432\u044b\u0432\u043e\u0434 \u043d\u0430\u0448\u0435\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430. texture2D &#8212; \u044d\u0442\u043e \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b,   \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u043e\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b &#8216;uv&#8217;. Then multiplied by   our lightBrightness value (a multiplier with eg. 1.0 at 100%, 0.5 at 50%)   In &#171;scene&#187; mode, this value is locked to 1.0 so it has no effect *\/gl_FragColor = texture2D(texture, uv) * lightBrightness;}WebGL Javascriptimport * as util from &#8216;..\/utility.js&#8217;export async function setupSimple() {\/* \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f *\/const WebGLBox = document.getElementById(&#8216;WebGLBox-Simple&#8217;);const canvas = WebGLBox.querySelector(&#8216;canvas&#8217;);\/* \u0420\u0430\u0437\u043c\u0435\u0440 \u043a\u0440\u0443\u0433\u0430 *\/const radius = 0.12;\/* \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 WebGL 1.0 *\/const gl = canvas.getContext(&#8216;webgl&#8217;, {preserveDrawingBuffer: false,antialias: false,alpha: false,});\/* \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b *\/const ctx = {\/* \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043b\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 *\/mode: &#171;scene&#187;,flags: { isRendering: false, buffersInitialized: false, initComplete: false, benchMode: false },\/* \u0422\u0435\u043a\u0441\u0442\u0443\u0440\u044b *\/tex: { sdr: null, selfIllum: null, frame: null, frameFinal: null },\/* \u0411\u0443\u0444\u0435\u0440\u044b \u043a\u0430\u0434\u0440\u043e\u0432 *\/fb: { scene: null, final: null },\/* \u0428\u0435\u0439\u0434\u0435\u0440\u044b \u0438 \u043c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 *\/shd: {scene: { handle: null, uniforms: { offset: null, radius: null } },blur: { handle: null, uniforms: { frameSizeRCP: null, samplePosMult: null, lightBrightness: null } },bloom: { handle: null, uniforms: { offset: null, radius: null, texture: null, textureAdd: null } }}};\/* \u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b UI *\/const ui = {display: {spinner: canvas.parentElement.querySelector(&#8216;svg&#8217;, canvas.parentElement),contextLoss: canvas.parentElement.querySelector(&#8216;div&#8217;, canvas.parentElement),fps: WebGLBox.querySelector(&#8216;#fps&#8217;),ms: WebGLBox.querySelector(&#8216;#ms&#8217;),width: WebGLBox.querySelector(&#8216;#width&#8217;),height: WebGLBox.querySelector(&#8216;#height&#8217;),},rendering: {animate: WebGLBox.querySelector(&#8216;#animateCheck&#8217;),modes: WebGLBox.querySelectorAll(&#8216;input[type=&#187;radio&#187;]&#8217;),lightBrightness: WebGLBox.querySelector(&#8216;#lightBrightness&#8217;),lightBrightnessReset: WebGLBox.querySelector(&#8216;#lightBrightnessReset&#8217;),}};\/* \u0428\u0435\u0439\u0434\u0435\u0440\u044b *\/const circleAnimation = await util.fetchShader(&#171;shader\/circleAnimation.vs&#187;);const simpleTexture = await util.fetchShader(&#171;shader\/simpleTexture.fs&#187;);const bloomVert = await util.fetchShader(&#171;shader\/bloom.vs&#187;);const bloomFrag = await util.fetchShader(&#171;shader\/bloom.fs&#187;);const simpleQuad = await util.fetchShader(&#171;shader\/simpleQuad.vs&#187;);const noBlurYetFrag = await util.fetchShader(&#171;shader\/noBlurYet.fs&#187;);\/* \u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0431\u0435\u0437 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 *\/ui.rendering.lightBrightness.addEventListener(&#8216;input&#8217;, () =&gt; { if (!ui.rendering.animate.checked) redraw() });\/* \u0421\u043e\u0431\u044b\u0442\u0438\u044f *\/ui.rendering.animate.addEventListener(&#171;change&#187;, () =&gt; {if (ui.rendering.animate.checked)startRendering();else {ui.display.fps.value = &#171;-&#171;;ui.display.ms.value = &#171;-&#171;;ctx.flags.isRendering = false;redraw()}});canvas.addEventListener(&#171;webglcontextlost&#187;, () =&gt; {ui.display.contextLoss.style.display = &#171;block&#187;;});\/* \u0420\u0435\u0436\u0438\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 *\/ui.rendering.modes.forEach(radio =&gt; {\/* \u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u0434\u0430\u0451\u043c \u0441\u0446\u0435\u043d\u0443, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u044c \u0431\u0430\u0433 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432 Firefox \u0434\u043b\u044f Android *\/if (radio.value === &#171;scene&#187;)radio.checked = true;radio.addEventListener(&#8216;change&#8217;, (event) =&gt; {ctx.mode = event.target.value;ui.rendering.lightBrightness.disabled = ctx.mode === &#171;scene&#187;;ui.rendering.lightBrightnessReset.disabled = ctx.mode === &#171;scene&#187;;if (!ui.rendering.animate.checked) redraw();});});\/* Draw Texture Shader *\/ctx.shd.scene = util.compileAndLinkShader(gl, circleAnimation, simpleTexture, [&#171;offset&#187;, &#171;radius&#187;]);\/* \u0420\u0438\u0441\u0443\u0435\u043c \u0448\u0435\u0439\u0434\u0435\u0440 bloom *\/ctx.shd.bloom = util.compileAndLinkShader(gl, bloomVert, bloomFrag, [&#171;texture&#187;, &#171;textureAdd&#187;, &#171;offset&#187;, &#171;radius&#187;]);\/* \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0440\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 *\/function reCompileBlurShader() {ctx.shd.blur = util.compileAndLinkShader(gl, simpleQuad, noBlurYetFrag, [&#171;lightBrightness&#187;]);}\/* \u0428\u0435\u0439\u0434\u0435\u0440 \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u044f *\/reCompileBlurShader()\/* \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0432 GPU *\/util.bindUnitQuad(gl);async function setupTextureBuffers() {ui.display.spinner.style.display = &#171;block&#187;;ctx.flags.buffersInitialized = true;ctx.flags.initComplete = false;gl.deleteFramebuffer(ctx.fb.scene);gl.deleteFramebuffer(ctx.fb.final);[ctx.fb.scene, ctx.tex.frame] = util.setupFramebuffer(gl, canvas.width, canvas.height);[ctx.fb.final, ctx.tex.frameFinal] = util.setupFramebuffer(gl, canvas.width, canvas.height);let [base, selfIllum] = await Promise.all([fetch(&#171;\/dual-kawase\/img\/SDR_No_Sprite.png&#187;),fetch(&#171;\/dual-kawase\/img\/Selfillumination.png&#187;)]);let [baseBlob, selfIllumBlob] = await Promise.all([base.blob(), selfIllum.blob()]);let [baseBitmap, selfIllumBitmap] = await Promise.all([createImageBitmap(baseBlob, { colorSpaceConversion: &#8216;none&#8217;, resizeWidth: canvas.width * 1.12, resizeHeight: canvas.height * 1.12, resizeQuality: &#171;high&#187; }),createImageBitmap(selfIllumBlob, { colorSpaceConversion: &#8216;none&#8217;, resizeWidth: canvas.width * 1.12, resizeHeight: canvas.height * 1.12, resizeQuality: &#171;high&#187; })]);ctx.tex.sdr = util.setupTexture(gl, null, null, ctx.tex.sdr, gl.LINEAR, baseBitmap);ctx.tex.selfIllum = util.setupTexture(gl, null, null, ctx.tex.selfIllum, gl.LINEAR, selfIllumBitmap);baseBitmap.close();selfIllumBitmap.close();ctx.flags.initComplete = true;ui.display.spinner.style.display = &#171;none&#187;;}let prevNow = performance.now();let lastStatsUpdate = prevNow;let fpsEMA = 60;let msEMA = 16;async function redraw() {if (!ctx.flags.buffersInitialized)await setupTextureBuffers();if (!ctx.flags.initComplete)return;\/* \u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 UI *\/ui.display.width.value = canvas.width;ui.display.height.value = canvas.height;\/* \u041a\u0440\u0443\u0433\u043e\u0432\u043e\u0435 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 *\/let radiusSwitch = ui.rendering.animate.checked ? radius : 0.0;let speed = (performance.now() \/ 10000) % Math.PI * 2;const offset = [radiusSwitch * Math.cos(speed), radiusSwitch * Math.sin(speed)];gl.useProgram(ctx.shd.scene.handle);const texture = ctx.mode == &#171;scene&#187; ? ctx.tex.sdr : ctx.tex.selfIllum;gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, texture);gl.uniform2fv(ctx.shd.scene.uniforms.offset, offset);gl.uniform1f(ctx.shd.scene.uniforms.radius, radiusSwitch);\/* \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0431\u0443\u0444\u0435\u0440\u0430 \u043a\u0430\u0434\u0440\u043e\u0432 \u043f\u043e\u0441\u0442\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 *\/gl.bindFramebuffer(gl.FRAMEBUFFER, ctx.fb.scene);gl.viewport(0, 0, canvas.width, canvas.height);\/* \u0412\u044b\u0437\u043e\u0432 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 *\/gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);\/* \u0420\u0430\u0437\u043c\u044b\u0442\u0438\u0435 \u043f\u0440\u0438 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0438 *\/gl.useProgram(ctx.shd.blur.handle);const finalFB = ctx.mode == &#171;bloom&#187; ? ctx.fb.final : null;gl.bindFramebuffer(gl.FRAMEBUFFER, finalFB);gl.viewport(0, 0, canvas.width, canvas.height);gl.uniform1f(ctx.shd.blur.uniforms.lightBrightness, ctx.mode == &#171;scene&#187; ? 1.0 : ui.rendering.lightBrightness.value);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.frame);gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);if (ctx.mode == &#171;bloom&#187;) {\/* \u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u0438\u043d\u0433 bloom \u043d\u0430 \u044d\u043a\u0440\u0430\u043d *\/gl.bindFramebuffer(gl.FRAMEBUFFER, null);gl.useProgram(ctx.shd.bloom.handle);gl.uniform2fv(ctx.shd.bloom.uniforms.offset, offset);gl.uniform1f(ctx.shd.bloom.uniforms.radius, radiusSwitch);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.sdr);gl.uniform1i(ctx.shd.bloom.uniforms.texture, 0);gl.activeTexture(gl.TEXTURE1);gl.bindTexture(gl.TEXTURE_2D, ctx.tex.frameFinal);gl.uniform1i(ctx.shd.bloom.uniforms.textureAdd, 1);gl.drawArrays(gl.TRIANGLE_FAN,&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-481753","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/481753","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=481753"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/481753\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=481753"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=481753"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=481753"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}