{"id":326383,"date":"2021-07-13T15:00:30","date_gmt":"2021-07-13T15:00:30","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=326383"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=326383","title":{"rendered":"\u0417\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u0430 \u0441 WebGL: \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433, \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f (\u0447\u0430\u0441\u0442\u044c 4)"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<p>\u042d\u0442\u043e \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u0435\u0439:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/567052\/\" rel=\"noopener noreferrer nofollow\">\u0417\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u0430 \u0441 WebGL: \u043f\u043e\u0447\u0435\u043c\u0443 WebGL? (\u0447\u0430\u0441\u0442\u044c 1)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/567082\/\" rel=\"noopener noreferrer nofollow\">\u0417\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u0430 \u0441 WebGL: \u043f\u0435\u0440\u0432\u044b\u0435 \u043d\u0430\u0431\u0440\u043e\u0441\u043a\u0438 (\u0447\u0430\u0441\u0442\u044c 2)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/567174\/\" rel=\"noopener noreferrer nofollow\">\u0417\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u0430 \u0441 WebGL: \u0447\u0435\u0442\u043a\u0438\u0435 \u043b\u0438\u043d\u0438\u0438 (\u0447\u0430\u0441\u0442\u044c 3)<\/a><\/p>\n<\/li>\n<li>\n<p>\u0417\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u0430 \u0441 WebGL: \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433, \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f (\u0447\u0430\u0441\u0442\u044c 4)<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0414\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e \u043f\u0438\u0448\u0443 \u0441\u043f\u0443\u0441\u0442\u044f \u043f\u043e\u043b\u0442\u043e\u0440\u0430 \u0433\u043e\u0434\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043b\u0435\u0442 \u0441\u0432\u0435\u0436\u0435\u0441\u0442\u0438 \u043f\u043e\u0442\u0435\u0440\u044f\u043d.<\/strong><\/p>\n<p>\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0443\u0436\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u0440\u043e \u043a\u043e\u0434, \u043c\u0435\u043d\u044c\u0448\u0435 \u043f\u0440\u043e \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u044f. \u0417\u0434\u0435\u0441\u044c \u043f\u043e \u0441\u0443\u0442\u0438 \u044f \u0432\u044b\u043b\u043e\u0436\u0443 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442. \u0412\u043e\u0442 \u044d\u0442\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0435 \u044f\u0431\u043b\u043e\u043a\u043e:<\/p>\n<p><iframe id=\"60ed87f1da3d598f9a4a5152\" src=\"https:\/\/embedd.srv.habr.com\/iframe\/60ed87f1da3d598f9a4a5152\" class=\"embed_video embed__content\" allowfullscreen=\"true\"><\/iframe><\/p>\n<h3>\u0421\u043e\u0431\u0435\u0440\u0435\u043c \u0432\u0435\u0441\u044c \u043e\u043f\u044b\u0442<\/h3>\n<p>\u0422\u0430\u043a, \u043d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0435\u0444\u0430\u0447\u0438\u0442\u044c \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0441 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043e\u043c. \u041f\u043e \u0437\u0430\u0434\u0443\u043c\u043a\u0435 \u0434\u0438\u0437\u0430\u0439\u043d\u0435\u0440\u0430, \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u0430 \u043e\u0441\u043e\u0431\u043e \u043d\u0435 \u0431\u044b\u043b\u043e, \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0435\u0430\u043a\u0446\u0438\u044f \u043d\u0430 \u043c\u044b\u0448\u043a\u0443.<\/p>\n<p>\u0417\u0430 3 \u0441\u0442\u0430\u0442\u044c\u0438 \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u043e\u0441\u044c \u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u0438\u043b\u0438 \u043c\u0435\u043d\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441. \u0427\u0442\u043e \u0443 \u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c:<\/p>\n<ul>\n<li>\n<p>\u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043c\u0435\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0437\u0430\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0433\u0440\u0430\u043d\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0430\u0440\u0441\u0435\u0440&nbsp;<code>.obj<\/code>&nbsp;\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0443 \u043d\u0430 \u0432\u0435\u0440\u0448\u0438\u043d\u044b, uv \u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u044b.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0431\u043e\u0440 \u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432 \u043e\u0442&nbsp;<a href=\"https:\/\/webglfundamentals.org\/\" rel=\"noopener noreferrer nofollow\">WebGL Fundamentals<\/a>.<\/p>\n<\/li>\n<li>\n<p>animejs \u0434\u043b\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>gl-matrix \u0434\u043b\u044f \u0440\u0430\u0441\u0441\u0447\u0435\u0442\u043e\u0432 \u043c\u0430\u0442\u0440\u0438\u0446\u044b<\/p>\n<\/li>\n<li>\n<p>\u0421\u0430\u043c\u0430 \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043a\u043e\u0433\u0434\u0430 \u044f \u0443\u0436\u0435 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b \u0441 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u043e\u043c \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0438, \u044f \u0437\u043d\u0430\u043b \u043a\u0430\u043a \u0431\u0443\u0434\u0443 \u0440\u0435\u0444\u0430\u0447\u0438\u0442\u044c \u043a\u043e\u0434. \u0412 \u0433\u043e\u043b\u043e\u0432\u0435 \u043a\u0430\u0440\u0442\u0438\u043d\u0430 \u0443\u0436\u0435 \u0431\u044b\u043b\u0430.<\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430 \u043a\u043b\u0430\u0441\u0441\u0430\u0445! \u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0430 \u043a\u043b\u0430\u0441\u0441\u0430\u0445? \u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439, \u0430 \u0435\u0449\u0435 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430.<\/p>\n<p>\u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438&nbsp;<a href=\"https:\/\/animejs.com\/\" rel=\"noopener noreferrer nofollow\">animejs<\/a>, \u043b\u0435\u0433\u043a\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0441 \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0430\u043f\u0438 (\u0434\u043b\u044f \u043c\u0435\u043d\u044f).<\/p>\n<p>\u0412-\u0442\u0440\u0435\u0442\u044c\u0438\u0445, \u044f \u0431\u0443\u0434\u0443 \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0438 \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0432 indexedDb (\u043c\u043d\u0435 \u0442\u043e\u0433\u0434\u0430 \u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u044d\u0442\u043e \u043a\u0440\u0443\u0442\u043e\u0439 \u0438\u0434\u0435\u0435\u0439 \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0435\u0439, \u0430 \u0442\u0430\u043a \u0436\u0435 \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0445\u043e\u0442\u0435\u043b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u044d\u0442\u0438\u043c \u0430\u043f\u0438).<\/p>\n<p>\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u043c\u043d\u043e\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0431\u044b\u043b \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u043c, \u0435\u043c\u0443 \u0431\u044b\u043b\u043e \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043a\u0430\u043a\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0435\u043c\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c, \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u0447\u0442\u043e\u0431 faces (\u0438\u043d\u0434\u0435\u043a\u0441\u044b) \u0441\u043e\u0441\u0442\u043e\u044f\u043b\u0438 \u0438\u0437 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043e\u0432, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u0438\u0437 \u043a\u0430\u043a\u0438\u0445-\u043d\u0438\u0442\u044c \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u0438\u043b\u0438 \u043f\u044f\u0442\u0438\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432, \u0442\u043e \u0432\u0435\u0441\u044c \u043c\u043e\u0439 \u043f\u0430\u0440\u0441\u0435\u0440 \u0438 \u0448\u0435\u0439\u0434\u0435\u0440 \u043f\u043e\u043b\u0435\u0442\u0438\u0442 \u043a \u0447\u0435\u0440\u0442\u044f\u043c.<\/p>\n<p>\u041f\u043e \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u0432\u043e\u043f\u0440\u043e\u0441\u0430 \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u0441\u043c\u0435\u0449\u0430\u0442\u044c \u0444\u0438\u0433\u0443\u0440\u0443 \u0434\u043b\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0443 \u043c\u0435\u043d\u044f \u043d\u0435 \u0431\u044b\u043b\u043e. \u042f \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044e \u043c\u0430\u0442\u0440\u0438\u0446\u0443 \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e \u0435\u0435 \u0432 \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440, \u0430 \u043e\u043d \u0443\u0436\u0435 \u0441\u0430\u043c \u0432\u0441\u0435 \u0442\u0430\u043c \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0438 \u0432\u044b\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0442\u043e\u0447\u043a\u0438.<\/p>\n<p><strong>\u041a\u0430\u043a \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0432 webgl?<\/strong><\/p>\n<ol>\n<li>\n<p>\u0414\u0435\u043b\u0430\u0435\u0448\u044c \u0440\u0430\u0441\u0447\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0448\u044c \u0438\u0445 \u0432 \u0448\u0435\u0439\u0434\u0435\u0440.<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0437\u044b\u0432\u0430\u0435\u0448\u044c&nbsp;<code>drawArray<\/code>, \u0447\u0442\u043e\u0431 \u043a\u0430\u0440\u0442\u0430 \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u043b\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043d\u043e\u0432\u0443\u044e \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c 1 \u043f\u0443\u043d\u043a\u0442 \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u043d\u0443\u0436\u043d\u0430 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u043e\u0442, \u0435\u0441\u043b\u0438 \u0432 css \u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0442\u043e \u0432 webgl \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0430 \u043f\u043e\u0442\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0440\u0435\u043d\u0434\u0435\u0440.<\/p>\n<p><strong>\u0422\u0430\u043a \u0436\u0435 \u0431\u044b\u043b\u0430 \u0435\u0449\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c<\/strong>. \u041c\u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0430\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0438 \u043f\u043e-\u0440\u0430\u0437\u043d\u043e\u043c\u0443.<\/p>\n<h4>\u041a\u0430\u043a \u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0435\u043b\u0438\u043b \u043d\u0430 \u0447\u0430\u0441\u0442\u0438.<\/h4>\n<p>\u0414\u0438\u0437\u0430\u0439\u043d\u0435\u0440 \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u043b \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0444\u0438\u0433\u0443\u0440\u044b \u0447\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u044f\u0431\u043b\u043e\u043a\u043e \u0438 \u043e\u043d \u0445\u043e\u0442\u0435\u043b, \u0447\u0442\u043e\u0431 \u0432\u0441\u0435 \u043a\u0430\u0436\u0434\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0444\u0438\u0433\u0443\u0440\u044b \u0432\u0435\u0440\u0442\u0435\u043b\u0430\u0441\u044c \u0432 \u043d\u0443\u0436\u043d\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443. \u0410 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0434\u0435\u043b\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0430 \u0447\u0430\u0441\u0442\u0438, \u0442\u043e \u0435\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0432\u0435\u0440\u0448\u0438\u043d \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c, \u043d\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0441\u0432\u043e\u044e \u043c\u0430\u0442\u0440\u0438\u0446\u0443 \u0438 \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0435\u0435. \u0412 webgl \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u043e\u043b\u043e\u0442\u043d\u043e \u043d\u0435 \u0441\u0442\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0438 \u0435\u0441\u043b\u0438 \u0432\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0435 drawArray, \u0442\u043e \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0440\u0438\u0441\u0443\u0435\u0442 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u043c\u0438 \u043f\u043e\u0432\u0435\u0440\u0445 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0443\u0436\u0435 \u0431\u044b\u043b\u043e \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u043d\u043e. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0438, \u0447\u0442\u043e-\u0442\u043e \u0441 \u043d\u0435\u0439 \u0434\u0435\u043b\u0430\u0442\u044c, \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c, \u0430 \u043f\u043e\u0442\u043e\u043c \u0434\u0440\u0443\u0433\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0438 \u0442\u0430\u043a \u043f\u043e \u043a\u0440\u0443\u0433\u0443.<\/p>\n<h4>\u0410 \u043a\u0430\u043a \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u0435\u0442\u0430\u043b\u0435\u0439?<\/h4>\n<p>\u0412 3\u0434 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430\u0445 \u043d\u0430\u0431\u043e\u0440\u044b \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0432 \u0433\u0440\u0443\u043f\u043f\u044b, \u0430 \u043f\u0440\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0435 \u044d\u0442\u0438 \u0433\u0440\u0443\u043f\u043f\u044b \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0438\u043c\u0432\u043e\u043b\u0430&nbsp;<code>o<\/code>&nbsp;(object) \u0432&nbsp;<code>.obj<\/code>, \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u044f \u043c\u043e\u0433 \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0443 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u043a.<\/p>\n<p>\u042f \u0432\u044b\u0434\u0435\u043b\u0438\u043b \u0434\u043b\u044f \u0441\u0435\u0431\u044f 3 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p>\u041c\u0430\u0442\u0440\u0438\u0446\u044b<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0434\u0435\u043b\u0438 (Mesh)<\/p>\n<\/li>\n<li>\n<p>\u0421\u0430\u043c \u0440\u0435\u043d\u0434\u0435\u0440<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e, \u043a\u043b\u0430\u0441\u0441\u0430 \u043c\u0430\u0442\u0440\u0438\u0446\u044b, \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0445\u043e\u0442\u0435\u043b \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0441\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u043c\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f\u043c\u0438, \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u043c\u0430\u0433\u0438\u044f \u043c\u0430\u0442\u0440\u0438\u0446. \u041f\u043e\u0447\u0435\u043c\u0443 \u0432\u043e\u043e\u0431\u0449\u0435 \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u0432\u044b\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 js, \u0430 \u043d\u0435 webgl? \u041f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u043d\u0443\u0436\u043d\u043e \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442 \u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0442\u044c, \u0430 \u0432 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c. \u0422\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430, \u044f \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043b, \u0447\u0442\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439. \u0410 \u043f\u043e\u0442\u043e\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<pre><code class=\"javascript\">import { glMatrix, mat4, vec3 } from \"gl-matrix\"; \/\/ \u043b\u0438\u0431\u0430 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c  export class Matrix {   \/\/ \u044f \u0440\u0435\u0448\u0438\u043b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043b\u043b\u0431\u0435\u043a \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043a\u043e\u0433\u0434\u0430 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u0435\u0442\u043e\u0434 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u043b\u0438.   constructor(onUpdate = () =&gt; {}) {}    \/\/ \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043c\u0430\u0442\u0440\u0438\u0446\u0430\u043c\u0438, \u043f\u043e \u0441\u0443\u0442\u0438 \u043a\u0435\u0448 \u0438 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u043c\u0430\u0442\u0440\u0438\u0446\u044b, \u0430 \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u043e!   #matrices = {};    \/\/ \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043a\u0430\u043c\u0435\u0440\u044b, \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u043d\u0435 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0441\u044f \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0444\u0438\u0433\u0443\u0440\u0443 \u043d\u0430 \u043d\u0443\u0436\u043d\u043e\u0439 \u0434\u0438\u0441\u0442\u0430\u043d\u0446\u0438\u0438.   setOrtho(left, right, bottom, top, near, far) {}    \/\/ \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e   #scale = 1;   \/\/ \u0441\u0435\u0442\u0442\u0435\u0440 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 scale   setScale(ratio) {}    \/\/ \u0440\u0435\u0448\u0438\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0433\u0435\u0442\u0442\u043e\u0440 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f,   \/\/ \u0447\u0442\u043e\u0431 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0432\u0441\u044f\u043a\u0438\u0445 \u0440\u0430\u0441\u0441\u0447\u0435\u0442\u043e\u0432 \u0441 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0435\u0439.   getScale() {}    #translate = [0, 0, 0];   \/**    * x, y, z \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435    * @param {[number, number, number]}params    *\/   setTranslate(params) {}   getTranslate() {}    \/\/ \u043d\u0443 \u0438 rotate, \u043d\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u043b \u0432 \u043e\u0434\u0438\u043d \u043c\u0435\u0442\u043e\u0434, \u043f\u043e\u0442\u043e\u043c\u0443, \u0441\u043e\u0431\u0438\u0440\u0430\u043b\u0441\u044f \u0430\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u043e\u0435 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e.   \/\/ \u0435\u0441\u043b\u0438 \u043c\u043d\u0435 \u0432\u0430\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0437\u043d\u0430\u0442\u044c \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 translate \u0438 scale, \u0442\u043e \u043d\u0430 rotate \u0431\u044b\u043b\u043e \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0433\u0435\u0442\u0442\u0435\u0440\u043e\u0432 \u043d\u0435 \u0434\u0435\u043b\u0430\u043b. \u0417\u0430\u0447\u0435\u043c?   setRotateX(deg) {}   setRotateY(deg) {}   setRotateZ(deg) {}    \/\/ \u043f\u0435\u0440\u0435\u043c\u043d\u043e\u0436\u0430\u0435\u043c \u0432\u0441\u0435 \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u0442\u043e\u0433\u043e\u0432\u0443\u044e \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u043a\u0438\u043d\u0443\u0442\u044c \u0432 \u0448\u0435\u0439\u0434\u0435\u0440   getCurrent() {} }<\/code><\/pre>\n<p>\u042f \u0440\u0435\u0448\u0438\u043b \u043d\u0435 \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0432 \u043a\u043e\u043d\u0446\u0435 \u0432\u044b\u043b\u043e\u0436\u0443 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0443 \u0441\u043e \u0432\u0441\u0435\u043c \u043a\u043e\u0434\u043e\u043c.<\/p>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0443 \u043d\u0430\u0441 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439. \u042f \u043d\u0430\u0437\u0432\u0430\u043b \u0435\u0433\u043e Mesh, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0443\u0432\u0438\u0434\u0435\u043b \u0442\u0430\u043a\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0432 Pixi.js. Mesh \u0437\u043d\u0430\u0447\u0438\u0442 \u0441\u0435\u0442\u043a\u0430, \u0441\u0435\u0442\u043a\u0430 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432. \u041f\u043e\u043d\u044f\u043b\u0438 \u0442\u0435\u043c\u0443? \u0422\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u0432\u0435\u0440\u0448\u0438\u043d\u0430 \u0432\u0441\u0435\u0433\u043e!<\/p>\n<p>\u041a\u043b\u0430\u0441\u0441 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0435\u043d\u043d\u044b\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0438 uv, \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043c\u0430\u0442\u0440\u0438\u0446\u0443, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0432 gl \u0431\u0443\u0444\u0435\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u0447\u0442\u043e\u0431 \u043f\u043e\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043b\u0435\u0433\u043a\u043e \u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438. \u0411\u0443\u0444\u0435\u0440 \u044d\u0442\u043e \u043c\u0435\u0441\u0442\u043e, \u043a\u0443\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0431\u0443\u0444\u0435\u0440 \u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b. \u0411\u0443\u0444\u0435\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438 \u043e\u043d\u0438 \u0432\u0441\u0435 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 \u043f\u0430\u043c\u044f\u0442\u0438, \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u043d\u0430 \u043f\u0435\u0440\u0435\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u043e\u0442\u043e\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442.<\/p>\n<pre><code class=\"javascript\">import { Matrix } from \".\/Matrix\";  export class Mesh {   \/**    *    * @param {Float32Array} positions    * @param {Float32Array} uv    *\/   \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0438 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b   constructor({ positions, uv }) {     this.positions = positions;     this.uv = uv;     \/\/ \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c drawArrays \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443 \u043d\u0430\u0441 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432, \u0442\u0430\u043a \u043a\u0430\u043a \u0434\u043b\u044f \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 \u0432\u0441\u0435\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e 3 \u0442\u043e\u0447\u043a\u0438, \u0442\u043e \u043c\u043e\u0436\u0435\u043c \u0441\u043c\u0435\u043b\u043e \u0434\u0435\u043b\u0438\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u0442\u043e\u0447\u043a\u0430\u043c\u0438 \u043d\u0430 3 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432     this.count = this.positions.length \/ 3;     \/\/ \u043b\u0438\u0447\u043d\u0430\u044f \u043c\u0430\u0442\u0440\u0438\u0446\u0430 \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0438     this.matrix = new Matrix();   }    \/\/ \u0441\u0441\u044b\u043b\u043e\u0447\u043a\u0438 \u043d\u0430 \u0431\u0443\u0444\u0435\u0440\u0430   positionsBuffer;   uvBuffer;    \/**    * @param {WebGLRenderingContext} gl    *\/   \/\/ \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043b \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u0442\u0430\u043a\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043a\u0430\u043a \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0438, \u043c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0447\u0442\u043e\u0431 \u043d\u0443\u0436\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0431\u044b\u043b\u0438 \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u044b, \u0438\u0445 \u043d\u0443\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u043a\u0438\u043d\u0443\u0442\u044c \u0432 \u043a\u043b\u0430\u0441\u0441 \u0440\u0435\u043d\u0434\u0435\u0440\u0430.   attachRender(gl) {     this.gl = gl;   }    \/**    * \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0431\u0443\u0444\u0435\u0440\u0430, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0432 \u043d\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0435, \u0445\u0440\u0430\u043d\u0438\u043c \u044d\u0442\u0438 \u0431\u0443\u0444\u0435\u0440\u044b \u043f\u043e\u0442\u043e\u043c \u0432 \u043a\u043b\u0430\u0441\u0441\u0435, \u0447\u0442\u043e\u0431 \u043b\u0435\u0433\u043a\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u044c    *\/   initializeBuffers() {} }<\/code><\/pre>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e. \u041f\u043e\u043b\u0443\u0447\u0438 \u0432\u0435\u0440\u0448\u0438\u043d\u044b, \u0437\u0430\u0433\u0440\u0443\u0437\u0438 \u0432 \u0431\u0443\u0444\u0435\u0440\u0430 \u0438 \u0434\u0430\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043d\u0438\u0445.<\/p>\n<h4>ModelRender<\/h4>\n<p>\u0412\u0441\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043b\u0435\u0436\u0438\u0442 \u043d\u0430 \u043a\u043b\u0430\u0441\u0441\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0430. \u041e\u043d \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0432\u044b\u0434\u0430\u043d\u043d\u044b\u0439 \u0435\u043c\u0443&nbsp;<code>canvas<\/code>&nbsp;\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 webgl, \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0434\u043b\u044f \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432. \u0412\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432\u0441\u044f\u043a\u0438\u0435 \u044d\u043a\u0441\u0442\u0435\u043d\u0448\u0435\u043d\u044b, \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0441\u0435\u0431\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c, \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0446\u0432\u0435\u0442\u0430, \u0442\u043e\u043b\u0449\u0438\u043d\u044b \u043b\u0438\u043d\u0438\u0438 \u043c\u043e\u0434\u0435\u043b\u043a\u0438, \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0440\u0435\u0441\u0430\u0439\u0437\u043e\u043c \u044d\u043a\u0440\u0430\u043d\u0430, \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043a\u0430\u043c\u0435\u0440\u0443 \u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u044b\u0439 \u0432\u0430\u0436\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434&nbsp;<code>drawArrays<\/code>! \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443 \u0432\u043e\u043b\u0448\u0435\u0431\u043d\u043e\u043c\u0443 \u043c\u0435\u0442\u043e\u0434\u0443, \u043a\u0430\u0440\u0442\u0430 \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430&nbsp;<code>\u0445\u043e\u043b\u0441\u0442\u0435<\/code>.<\/p>\n<pre><code class=\"objectivec\">\/\/ \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 precision mediump float; uniform mat4 uMeshMatrix; \/\/ \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 uniform mat4 uCameraMatrix; \/\/ \u043c\u0438\u0440\u043e\u0432\u0430\u044f \u043a\u0430\u043c\u0435\u0440\u0430 attribute vec4 aPosition; \/\/ \u0432\u0435\u0440\u0448\u0438\u043d\u044b attribute vec2 aTextureCoords; \/\/ \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b varying vec2 vTextureCoords; \/\/ \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \/\/ \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u0440\u0448\u0438\u043d\u0430\u043c\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0432 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 void main(){     gl_Position = uCameraMatrix * uMeshMatrix * aPosition;     vTextureCoords = aTextureCoords; }<\/code><\/pre>\n<pre><code class=\"objectivec\">\/\/ \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 #extension GL_OES_standard_derivatives : enable \/\/ \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0448\u0442\u0443\u043a\u0443 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0430\u0448\u0438 \u043b\u0438\u043d\u0438\u0438 \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u043c\u0438 precision mediump float; \/\/ \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u0430\u043a \u043d\u0443\u0436\u043d\u043e \u043e\u043a\u0440\u0443\u0433\u043b\u044f\u0442\u044c float \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f uniform vec3 uLineColor; \/\/ \u0446\u0432\u0435\u0442 \u043b\u0438\u043d\u0438\u0438 uniform vec3 uBgColor; \/\/ \u0446\u0432\u0435\u0442 \u0444\u043e\u043d\u0430 uniform float uLineWidth; \/\/ \u0448\u0438\u0440\u0438\u043d\u0430 \u043b\u0438\u043d\u0438\u0438 varying vec2 vTextureCoords; \/\/ \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u044b \u0447\u0442\u043e\u0431 \u0432\u044b\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0433\u0440\u0430\u043d\u0438  \/\/ \u043c\u043e\u044f \u0441\u0443\u043f\u0435\u0440 \u043b\u043e\u0433\u0438\u043a\u0430 \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u0433\u0440\u0430\u043d\u0438\u0446 \/\/ \u044f \u043d\u0435 \u043c\u043e\u0433\u0443 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043a\u0430\u043a \u044f \u044d\u0442\u043e \u0441\u0447\u0438\u0442\u0430\u043b, \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0442\u043e\u0440\u0430 \u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434 \u044f \u0431\u044b\u043b \u0443\u043c\u043d\u0435\u0439. float border(vec2 uv, float uLineWidth, vec2 gap) {   \/\/ \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f gap \u043d\u0443\u0436\u043d\u0430 \u0431\u044b\u043b\u0430, \u0447\u0442\u043e\u0431 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043b\u0438\u043d\u0438\u0438 \u0431\u043e\u043b\u0435\u0435 \u043f\u043b\u0430\u0432\u043d\u044b\u043c\u0438, \u043e\u043d\u0430 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0435   \/\/ smoothstep \u043f\u043e\u043b\u0443\u0447\u0430\u043b \u0442\u043e\u0447\u043a\u0430 A \u0438 \u0442\u043e\u0447\u043a\u0443 B, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u043b \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u044d\u0442\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u043b \u043f\u043b\u0430\u0432\u043d\u043e\u0435 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0410 \u0418 \u0411.   vec2 xy0 = smoothstep(vec2(uLineWidth) - gap, vec2(uLineWidth) + gap, uv);   vec2 xy1 = smoothstep(vec2(1. - uLineWidth) - gap, vec2(1. - uLineWidth) + gap, uv);   vec2 xy = xy0 - xy1;   return clamp(xy.x * xy.y, 0., 1.); } void main() {   vec2 uv = vTextureCoords;   vec2 fw = vec2(uLineWidth + 0.05);   #ifdef GL_OES_standard_derivatives   \/\/ \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0438\u0432\u043d\u043e\u0435 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435, \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439 \u0435\u0441\u043b\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442     fw = fwidth(uv);   #endif   \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0447\u0442\u043e\u0431 \u043a\u0440\u0430\u0441\u0438\u0442\u044c \u0432 \u043d\u0443\u0436\u043d\u044b\u043c \u0446\u0432\u0435\u0442\u043e\u043c.   float br = border(vTextureCoords, uLineWidth, fw);   \/\/ mix \u0441\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u0442 \u0446\u0432\u0435\u0442\u0430, \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 1 \u0432\u0435\u0440\u043d\u0435\u0442 \u043f\u043e\u043b\u043d\u044b\u0439 \u0446\u0432\u0435\u0442 uLineColor, \u0435\u0441\u043b\u0438 0, \u0442\u043e \u0432\u0435\u0440\u043d\u0435\u0442 uBgColor.   \/\/ \u0410 \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0433\u0434\u0435-\u0442\u043e \u043f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435, \u0442\u043e \u0432\u0435\u0440\u043d\u0435\u0442 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043e\u0431\u0449\u0438\u0439 \u0446\u0432\u0435\u0442 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u0434\u0432\u0443\u043c\u044f.   \/\/ \u0412\u0418\u0412\u0410 \u041c\u0410\u0422\u0415\u041c\u0410\u0422\u0418\u041a\u0410   gl_FragColor = vec4(mix(uLineColor, uBgColor, br), 1.); }<\/code><\/pre>\n<pre><code>import { vertex, fragment } from \".\/shaders\"; \/\/ \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u043c\u0430\u0433\u0438\u0438, \u0442\u0430\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u044b \u0432 \u0441\u0442\u0440\u043e\u043a\u0430\u0445 import { Mesh } from \".\/Mesh\"; import { Matrix } from \".\/Matrix\";  import {   createProgramFromTexts,   resizeCanvasToDisplaySize,   saveRectAspectRatio, } from \".\/helpers\";  export class ModelRender {   \/\/ \u044f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0435\u043b \u0447\u0442\u043e\u0431 \u043a\u043b\u0430\u0441\u0441 \u0441\u0430\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b \u0441\u0435\u0431\u0435 \u043a\u0430\u043d\u0432\u0430\u0441, \u0435\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0443\u0434\u0430 \u0435\u0433\u043e \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c   canvas = document.createElement(\"canvas\");   \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442, \u0442\u0443\u0442 \u0435\u0449\u0435 \u043f\u043e\u043b\u0438\u0444\u0438\u043b \u0434\u043b\u044f ie11   #gl = this.canvas.getContext(\"webgl\");   \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u044d\u043a\u0441\u0442\u0435\u043d\u0448\u0435\u043d, \u0447\u0442\u043e\u0431 \u0434\u0430\u043b\u044c\u0448\u0435 \u0435\u0433\u043e \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c.   \/\/ \u0422\u0443\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u043c\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0447\u0442\u043e\u0431 \u043f\u043e\u043d\u044f\u0442\u044c \u043a\u0430\u043a\u043e\u0439 \u044d\u043a\u0441\u0442\u0435\u043d\u0448\u0435\u043d \u043d\u0443\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c.   #derivatives = this.#gl.getExtension(\"OES_standard_derivatives\");    \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0438\u0437 \u043b\u044e\u0431\u0438\u043c\u044b\u0445 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432   #program = createProgramFromTexts(this.#gl, vertex, fragment);    \/\/ \u0443\u0434\u043e\u0431\u043d\u044b\u0435 \u043c\u0430\u043f\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u043d\u0430 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b   #attrs = {     position: this.#gl.getAttribLocation(this.#program, \"aPosition\"),     textureCoords: this.#gl.getAttribLocation(this.#program, \"aTextureCoords\"),   };    \/\/ \u043c\u0430\u043f\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435   #uniforms = {     meshMatrixLocation: this.#gl.getUniformLocation(       this.#program,       \"uMeshMatrix\"     ),     ...   };    constructor() {     const gl = this.#gl;     \/\/ \u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043a\u0430\u0440\u0442\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432, \u0447\u0442\u043e\u0431 \u0440\u0438\u0441\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e \u0447\u0442\u043e \u043d\u0430 \u043f\u0435\u0440\u0435\u0434\u043d\u0435\u043c \u0444\u043e\u043d\u0435     gl.enable(gl.DEPTH_TEST);     \/\/ \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0432 \u043a\u0430\u0440\u0442\u0443     gl.useProgram(this.#program);     \/\/ \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0412\u0421\u0415 \u041d\u0423\u0416\u041d\u041e \u0412\u041a\u041b\u042e\u0427\u0410\u0422\u042c     gl.enableVertexAttribArray(this.#attrs.position);     gl.enableVertexAttribArray(this.#attrs.textureCoords);   }    meshesByType = {};   models = {};    \/\/ \u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u043b \u0441\u0440\u0430\u0437\u0443 \u0432\u0441\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0432 \u043a\u043b\u0430\u0441\u0441, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u043e \u043a\u043b\u044e\u0447\u0443 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b \u043d\u0443\u0436\u043d\u0443\u044e   #initializeModel = (type) =&gt; {};    \/\/ `div` \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0441\u0442\u0430\u0432\u044f\u0442 `canvas`   \/** @type {HTMLElement} *\/   holder;    #modelName;   \/\/ \u043c\u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u0438\u043a\u043e\u043b\u044c\u043d\u044b\u043c \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0430\u043c\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0435\u0442\u0442\u0435\u0440\u0430   set modelName(type) {}    \/**    * \u0421\u0434\u0435\u043b\u0430\u043b \u0433\u0435\u0442\u0442\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u043b \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c. \u041d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431 \u0431\u044b\u043b\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0430\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0443. \u041c\u0435\u043d\u044f\u0442\u044c \u0435\u0439 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0430\u0442\u0440\u0438\u0446\u044b.    * @returns {Object&lt;string, Mesh&gt;}    *\/   get currentModel() {       return this.meshesByType[this.#modelName]   }    \/\/ \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0447\u0438\u0442\u0430\u043b\u0438\u0441\u044c \u0446\u0432\u0435\u0442 \u0444\u043e\u043d\u0430 \u0438 \u043b\u0438\u043d\u0438\u0438, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0442\u043e\u043b\u0449\u0438\u043d\u0430   \/\/ \u044f \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0437\u043d\u0430\u043b \u043d\u0430 \u043a\u0430\u043a\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043a\u0430\u043a\u0438\u0435 \u0446\u0432\u0435\u0442\u0430 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435 \u0432\u044b\u043d\u043e\u0441\u0438\u043b \u044d\u0442\u043e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 Mesh.   meshParams = {     bgColor: 0,     lineColor: 0,     lineWidth: 0.01,   };    \/\/ \u0445\u0435\u043b\u043f\u0435\u0440 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043f\u043e\u0437\u0438\u0446\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0443 \u043f\u0440\u0438 \u0440\u0435\u0441\u0430\u0439\u0437\u0435 \u044d\u043a\u0440\u0430\u043d   resize = () =&gt; {};    \/\/ \u043f\u0440\u043e\u0441\u0442\u043e \u043c\u0430\u0442\u0440\u0438\u0446\u0430 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e   #cameraMatrix = mat4.create();   \/\/ \u0441\u043e\u0437\u0434\u0430\u043b \u043c\u0430\u0442\u0440\u0438\u0446\u0443 \u0434\u043b\u044f \u043c\u0438\u0440\u043e\u0432\u043e\u0439 \u043a\u0430\u043c\u0435\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u0440\u0430\u0441\u0447\u0435\u0442\u044b \u043c\u0430\u0442\u0440\u0438\u0446\u044b.   cameraMatrix = new Matrix(() =&gt; {       this.#cameraMatrix = this.cameraMatrix.getCurrent();   });    \/\/ \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u0430\u043d\u0432\u0430\u0441 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440, \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u0430\u043c\u0435\u0440\u0443 \u043f\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0434\u0431\u0438\u0440\u0430\u043b \u0432\u0440\u0443\u0447\u043d\u0443\u044e   init() {     const gl = this.#gl;     this.holder.appendChild(this.canvas);     this.cameraMatrix.setOrtho(0, 70, 70, 0, 120, -120);     this.resize() \/\/ \u0432\u0430\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0432\u044b\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043a\u0430\u043d\u0432\u0430\u0441 \u0438 \u043f\u0440\u043e\u0447\u0435\u0435      \/\/ \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0438\u0437 meshParams     const { uLineColorLocation, uBgColorLocation, uLineWidthLocation } =       this.#uniforms;     gl.uniform3fv(uLineColorLocation, this.meshParams.lineColor);     gl.uniform3fv(uBgColorLocation, this.meshParams.bgColor);     gl.uniform1f(uLineWidthLocation, this.meshParams.lineWidth);   }    \/**    * @param {Mesh} mesh    *\/   #renderMesh = (mesh) =&gt; {     const gl = this.#gl;     \/\/ \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b     const { position, textureCoords } = this.#attrs;     \/\/ \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0431\u0443\u0444\u0435\u0440 \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0431\u0443\u0444\u0435\u0440 \u0444\u0438\u0433\u0443\u0440\u044b \u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442     gl.bindBuffer(gl.ARRAY_BUFFER, mesh.positionsBuffer);     gl.vertexAttribPointer(position, 3, gl.FLOAT, false, 0, 0);      gl.bindBuffer(gl.ARRAY_BUFFER, mesh.uvBuffer);     gl.vertexAttribPointer(textureCoords, 2, gl.FLOAT, false, 0, 0);     gl.uniformMatrix4fv(       this.#uniforms.meshMatrixLocation,       false,       mesh.matrix.getCurrent()     );     \/\/ \u0420\u0418\u0421\u0423\u0415\u041c!     gl.drawArrays(gl.TRIANGLES, 0, mesh.count);   };    render() {     const gl = this.#gl;     \/\/ \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u043e\u043c, \u043e\u0447\u0438\u0449\u0430\u0435\u043c \u043f\u043e\u043b\u043e\u0442\u043d\u043e \u043e\u0442 \u0432\u0441\u0435\u0433\u043e.     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);      \/\/ \u043d\u0430 \u0432\u0441\u044f\u043a\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u044e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u0435\u043b \u0440\u0435\u0441\u0430\u0439\u0437 \u043e\u043a\u043d\u0430     gl.uniformMatrix4fv(       this.#uniforms.uCameraMatrixLocation,       false,       this.#cameraMatrix     );      \/\/ \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u0444\u0438\u0433\u0443\u0440\u0430\u043c\u0438     const meshes = this.currentModel();     \/\/ \u043d\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u0444\u0438\u0433\u0443\u0440\u044b \u0432\u044b\u0437\u0432\u0430\u043b \u0440\u0435\u043d\u0434\u0435\u0440 \u0444\u0438\u0433\u0443\u0440\u044b     Object.values(meshes).forEach(this.#renderMesh);   } }<\/code><\/pre>\n<p>\u0424\u0443\u0445! \u041a\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u0447\u0435\u0441\u0442\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f \u0434\u0430\u0436\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u043a \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u0443\u0441\u0442\u0430\u043b.<\/p>\n<p>\u0422\u0430\u043a, \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u0441\u044f\u0442 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<ol>\n<li>\n<p>\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u044c&nbsp;<code>.obj<\/code>. \u041f\u0440\u043e\u0441\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u043c\u0443.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0430\u0440\u0441\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 3 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432 \u0432\u0435\u0440\u0448\u0438\u043d \u0438 faces \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0434\u0435\u043b\u0435\u043d\u044b \u043d\u0430 \u0447\u0430\u0441\u0442\u0438 \u0433\u0440\u0443\u043f\u043f, \u0430 \u043f\u043e\u0442\u043e\u043c \u044d\u0442\u0438 faces \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0432 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u043c \u0432 \u043a\u043b\u0430\u0441\u0441 ModelRender, \u043e\u043d \u0442\u0430\u043c \u0441\u0430\u043c \u0432\u0441\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0432 Mesh. \u041c\u0431 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e? \u041d\u0430\u0432\u0435\u0440\u043d\u043e \u044f \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u0441\u0430\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u041c\u0435\u0448\u0438, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u0440\u0435\u043d\u0434\u0435\u0440? \u042d\u0445, \u043f\u043e\u0437\u0434\u043d\u044f\u043a \u043c\u0435\u0442\u0430\u0442\u044c\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438, \u0430 \u043f\u043e\u0442\u043e\u043c \u043c\u0435\u043d\u044f\u0435\u043c \u043c\u0430\u0442\u0440\u0438\u0446\u0443 \u0432 \u043c\u043e\u0434\u0435\u043b\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c&nbsp;<code>app.render()<\/code><\/p>\n<\/li>\n<li>\n<p>\u0418 \u0432\u043e\u0442 \u0443 \u043d\u0430\u0441 \u043e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0435\u043d\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c!<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u043b\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438, \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c 5-6 \u0448\u0430\u0433 \u0434\u043e \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0441\u0442\u0438.<\/p>\n<pre><code class=\"javascript\">let app = new ModelRender();  app.models = parsedModels; \/\/ \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0435\u043d\u043d\u044b\u043c\u0438 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438, { apple: { apple: { vertexes: [], uv: [] } }. \u041f\u043e\u0447\u0435\u043c\u0443 2 apple? \u041f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043a\u043e\u0434 \u043d\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u0443 \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0438 \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439. app.holder = document.querySelector(\"#place\"); app.modelName = \"apple\"; \/\/ \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u043a\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c app.meshParams = appleParams; \/\/ \u0446\u0432\u0435\u0442, \u0442\u043e\u043b\u0449\u0438\u043d\u0430 \u043b\u0438\u043d\u0438\u0438 app.init(); app.render(); \/\/ \u0440\u0435\u043d\u0434\u0435\u0440 \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. const model = app.currentModel(); const props = { x: 0 }; \/\/ \u0422\u0443\u0442 \u0431\u0443\u0434\u0435\u0442 \u0432\u0441\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f. anime({   targets: props,   easing: \"linear\",   loop: true,   x: { value: [0, 360], duration: 7e3 },   update() {     model.apple.setXRotate(props.x);     app.render();   }, });<\/code><\/pre>\n<p>\u0421 \u0433\u043e\u0440\u0435\u043c \u043f\u043e\u043f\u043e\u043b\u0430\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440<\/p>\n<p><iframe id=\"60ed89606f06c2a29f4b45b0\" src=\"https:\/\/embedd.srv.habr.com\/iframe\/60ed89606f06c2a29f4b45b0\" class=\"embed_video embed__content\" allowfullscreen=\"true\"><\/iframe><\/p>\n<h4>\u0412\u0435\u0449\u0438 \u043f\u0440\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0435\u0449\u0435 \u0443\u0437\u043d\u0430\u043b \u043a\u043e\u0433\u0434\u0430, \u0434\u0435\u043b\u0430\u043b \u0440\u0435\u043d\u0434\u0435\u0440<\/h4>\n<ol>\n<li>\n<p>IE11 \u043f\u043e\u0447\u0442\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 webgl, \u043d\u043e \u0442\u0430\u043c, \u0447\u0442\u043e\u0431 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0443 \u043d\u0443\u0436\u043d\u043e&nbsp;<code>canvas.getContext(\"experimental-webgl\")<\/code>, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u0430\u0440\u0438\u0442\u044c\u0441\u044f \u043d\u0435 \u043d\u0430\u0434\u043e.<\/p>\n<\/li>\n<li>\n<p>\u0422\u0430\u043a \u0436\u0435 \u0432 ie11 \u0438\u043b\u0438 \u0434\u043b\u044f safari \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432, \u0447\u0442\u043e\u0431 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e: <code>#version 100<\/code><\/p>\n<\/li>\n<li>\n<p>\u041c\u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043e\u0447\u0438\u0449\u0430\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043c\u0435\u0436\u0434\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0443 webgl \u0435\u0441\u0442\u044c \u044d\u043a\u0441\u0442\u0435\u043d\u0448\u0435\u043d&nbsp;<code>loseContext<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0431\u0443\u0444\u0435\u0440\u044b \u0438 \u043f\u0440\u043e\u0447\u0435\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0434\u0435\u043b\u044c \u044f\u0431\u043b\u043e\u043a\u0430 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0432\u0435\u0440\u043d\u0443\u0442\u043e\u0439 \u043e\u0441\u0438 Y \u0438 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f\u0431\u043b\u043e\u043a\u043e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432\u0432\u0435\u0440\u0445 \u043d\u043e\u0433\u0430\u043c\u0438. \u0414\u0440\u0443\u0433\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0438\u0437\u0430\u0439\u043d\u0435\u0440 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043b \u0441 \u043f\u0435\u0440\u0435\u0432\u0435\u0440\u043d\u0443\u0442\u043e\u0439 \u043e\u0441\u044c\u044e Y \u0438 \u043f\u043e\u044d\u0442\u043e\u043c\u0443, \u0442\u0430\u043c \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0432\u0441\u0442\u0430\u0432\u0430\u043b\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043c\u043e\u0431\u0438\u043b\u043a\u0430\u0445 webgl \u0432\u044b\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0438\u0437 \u043f\u0430\u043c\u044f\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u044d\u0432\u0435\u043d\u0442:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"java\">app.canvas.addEventListener(\"webglcontextlost\", () =&gt; {   \/\/ your restore logic   console.log(\"restore\"); });<\/code><\/pre>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c \u0442\u043e \u0438 \u0432\u0441\u0435, \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u0441\u043b\u043e\u0436\u043d\u043e, \u043c\u043d\u0435 \u043f\u043e\u043c\u043e\u0433\u0430\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u043b\u044e\u0434\u0435\u0439. \u041a\u043e\u0433\u0434\u0430 \u044f \u0432\u0435\u0440\u043d\u0443\u043b\u0441\u044f \u0441\u043f\u0443\u0441\u0442\u044f \u043f\u043e\u043b\u0442\u043e\u0440\u0430 \u0433\u043e\u0434\u0430 \u043a \u0441\u0442\u0430\u0442\u044c\u0435, \u044f \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043c\u043e\u0433 \u043f\u043e\u043d\u044f\u0442\u044c. \u041d\u043e \u0432\u0441\u0435 \u0436\u0435, \u0444\u0440\u043e\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u0441 webgl, \u0435\u0441\u043b\u0438 \u0437\u0430\u0445\u043e\u0447\u0435\u0442. \u041f\u043e\u043a\u0430 \u043f\u0438\u0441\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438, \u0443\u043f\u0443\u0441\u0442\u0438\u043b \u043d\u0430\u0432\u0435\u0440\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432, \u043d\u043e \u044f \u0441\u0442\u0430\u0440\u0430\u043b\u0441\u044f \u0432\u044b\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u0435\u043d\u044f \u0437\u0430\u0446\u0435\u043f\u0438\u043b\u0438.<\/p>\n<p>\u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0432\u0441\u0435\u043c, \u043a\u0442\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b \u0438 \u0432\u0441\u0435\u043c \u043a\u0442\u043e \u0442\u043e\u0433\u0434\u0430 \u043f\u043e\u043c\u043e\u0433 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0442\u0435\u043c \u043a\u0442\u043e \u043f\u043e\u043c\u043e\u0433 \u043f\u043e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u043e\u0442 \u043b\u0438\u0448\u043d\u0435\u0433\u043e \u0441\u0442\u0430\u0442\u044c\u044e.<\/p>\n<p><strong>P.S. <\/strong>\u043d\u0430 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043c\u043e\u0438\u0445 \u0442\u0440\u0443\u0434\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c<strong>: <\/strong><a href=\"https:\/\/digitalhorizon.vc\/en\/about\" rel=\"noopener noreferrer nofollow\">https:\/\/digitalhorizon.vc\/<\/a> (\u042d\u0442\u043e \u0436\u0435 \u043d\u0435 \u0440\u0435\u043a\u043b\u0430\u043c\u0430?), \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043d\u0430 \u0432\u0441\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043a\u0440\u043e\u043c\u0435 media \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043f\u043e \u043f\u043b\u0430\u0448\u043a\u0430\u043c \u0441 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043d\u0430 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435. \u0422\u0443\u0434\u0430, \u044f \u0442\u043e\u0436\u0435 \u0437\u0430\u043f\u0438\u0445\u043d\u0443\u043b webgl. <\/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\/post\/567528\/\"> https:\/\/habr.com\/ru\/post\/567528\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<p>\u042d\u0442\u043e \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u0435\u0439:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/567052\/\" rel=\"noopener noreferrer nofollow\">\u0417\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u0430 \u0441 WebGL: \u043f\u043e\u0447\u0435\u043c\u0443 WebGL? (\u0447\u0430\u0441\u0442\u044c 1)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/567082\/\" rel=\"noopener noreferrer nofollow\">\u0417\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u0430 \u0441 WebGL: \u043f\u0435\u0440\u0432\u044b\u0435 \u043d\u0430\u0431\u0440\u043e\u0441\u043a\u0438 (\u0447\u0430\u0441\u0442\u044c 2)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/567174\/\" rel=\"noopener noreferrer nofollow\">\u0417\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u0430 \u0441 WebGL: \u0447\u0435\u0442\u043a\u0438\u0435 \u043b\u0438\u043d\u0438\u0438 (\u0447\u0430\u0441\u0442\u044c 3)<\/a><\/p>\n<\/li>\n<li>\n<p>\u0417\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u0430 \u0441 WebGL: \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433, \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f (\u0447\u0430\u0441\u0442\u044c 4)<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0414\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e \u043f\u0438\u0448\u0443 \u0441\u043f\u0443\u0441\u0442\u044f \u043f\u043e\u043b\u0442\u043e\u0440\u0430 \u0433\u043e\u0434\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043b\u0435\u0442 \u0441\u0432\u0435\u0436\u0435\u0441\u0442\u0438 \u043f\u043e\u0442\u0435\u0440\u044f\u043d.<\/strong><\/p>\n<p>\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0443\u0436\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u0440\u043e \u043a\u043e\u0434, \u043c\u0435\u043d\u044c\u0448\u0435 \u043f\u0440\u043e \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u044f. \u0417\u0434\u0435\u0441\u044c \u043f\u043e \u0441\u0443\u0442\u0438 \u044f \u0432\u044b\u043b\u043e\u0436\u0443 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442. \u0412\u043e\u0442 \u044d\u0442\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0435 \u044f\u0431\u043b\u043e\u043a\u043e:<\/p>\n<p><iframe id=\"60ed87f1da3d598f9a4a5152\" src=\"https:\/\/embedd.srv.habr.com\/iframe\/60ed87f1da3d598f9a4a5152\" class=\"embed_video embed__content\" allowfullscreen=\"true\"><\/iframe><\/p>\n<h3>\u0421\u043e\u0431\u0435\u0440\u0435\u043c \u0432\u0435\u0441\u044c \u043e\u043f\u044b\u0442<\/h3>\n<p>\u0422\u0430\u043a, \u043d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0435\u0444\u0430\u0447\u0438\u0442\u044c \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0441 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043e\u043c. \u041f\u043e \u0437\u0430\u0434\u0443\u043c\u043a\u0435 \u0434\u0438\u0437\u0430\u0439\u043d\u0435\u0440\u0430, \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u0430 \u043e\u0441\u043e\u0431\u043e \u043d\u0435 \u0431\u044b\u043b\u043e, \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0435\u0430\u043a\u0446\u0438\u044f \u043d\u0430 \u043c\u044b\u0448\u043a\u0443.<\/p>\n<p>\u0417\u0430 3 \u0441\u0442\u0430\u0442\u044c\u0438 \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u043e\u0441\u044c \u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u0438\u043b\u0438 \u043c\u0435\u043d\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441. \u0427\u0442\u043e \u0443 \u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c:<\/p>\n<ul>\n<li>\n<p>\u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043c\u0435\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0437\u0430\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0433\u0440\u0430\u043d\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0430\u0440\u0441\u0435\u0440&nbsp;<code>.obj<\/code>&nbsp;\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0443 \u043d\u0430 \u0432\u0435\u0440\u0448\u0438\u043d\u044b, uv \u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u044b.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0431\u043e\u0440 \u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432 \u043e\u0442&nbsp;<a href=\"https:\/\/webglfundamentals.org\/\" rel=\"noopener noreferrer nofollow\">WebGL Fundamentals<\/a>.<\/p>\n<\/li>\n<li>\n<p>animejs \u0434\u043b\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>gl-matrix \u0434\u043b\u044f \u0440\u0430\u0441\u0441\u0447\u0435\u0442\u043e\u0432 \u043c\u0430\u0442\u0440\u0438\u0446\u044b<\/p>\n<\/li>\n<li>\n<p>\u0421\u0430\u043c\u0430 \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043a\u043e\u0433\u0434\u0430 \u044f \u0443\u0436\u0435 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b \u0441 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u043e\u043c \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0438, \u044f \u0437\u043d\u0430\u043b \u043a\u0430\u043a \u0431\u0443\u0434\u0443 \u0440\u0435\u0444\u0430\u0447\u0438\u0442\u044c \u043a\u043e\u0434. \u0412 \u0433\u043e\u043b\u043e\u0432\u0435 \u043a\u0430\u0440\u0442\u0438\u043d\u0430 \u0443\u0436\u0435 \u0431\u044b\u043b\u0430.<\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430 \u043a\u043b\u0430\u0441\u0441\u0430\u0445! \u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0430 \u043a\u043b\u0430\u0441\u0441\u0430\u0445? \u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439, \u0430 \u0435\u0449\u0435 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430.<\/p>\n<p>\u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438&nbsp;<a href=\"https:\/\/animejs.com\/\" rel=\"noopener noreferrer nofollow\">animejs<\/a>, \u043b\u0435\u0433\u043a\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0441 \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0430\u043f\u0438 (\u0434\u043b\u044f \u043c\u0435\u043d\u044f).<\/p>\n<p>\u0412-\u0442\u0440\u0435\u0442\u044c\u0438\u0445, \u044f \u0431\u0443\u0434\u0443 \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0438 \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0432 indexedDb (\u043c\u043d\u0435 \u0442\u043e\u0433\u0434\u0430 \u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u044d\u0442\u043e \u043a\u0440\u0443\u0442\u043e\u0439 \u0438\u0434\u0435\u0435\u0439 \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0435\u0439, \u0430 \u0442\u0430\u043a \u0436\u0435 \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0445\u043e\u0442\u0435\u043b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u044d\u0442\u0438\u043c \u0430\u043f\u0438).<\/p>\n<p>\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u043c\u043d\u043e\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0431\u044b\u043b \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u043c, \u0435\u043c\u0443 \u0431\u044b\u043b\u043e \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043a\u0430\u043a\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0435\u043c\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c, \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u0447\u0442\u043e\u0431 faces (\u0438\u043d\u0434\u0435\u043a\u0441\u044b) \u0441\u043e\u0441\u0442\u043e\u044f\u043b\u0438 \u0438\u0437 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043e\u0432, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u0438\u0437 \u043a\u0430\u043a\u0438\u0445-\u043d\u0438\u0442\u044c \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u0438\u043b\u0438 \u043f\u044f\u0442\u0438\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432, \u0442\u043e \u0432\u0435\u0441\u044c \u043c\u043e\u0439 \u043f\u0430\u0440\u0441\u0435\u0440 \u0438 \u0448\u0435\u0439\u0434\u0435\u0440 \u043f\u043e\u043b\u0435\u0442\u0438\u0442 \u043a \u0447\u0435\u0440\u0442\u044f\u043c.<\/p>\n<p>\u041f\u043e \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u0432\u043e\u043f\u0440\u043e\u0441\u0430 \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u0441\u043c\u0435\u0449\u0430\u0442\u044c \u0444\u0438\u0433\u0443\u0440\u0443 \u0434\u043b\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0443 \u043c\u0435\u043d\u044f \u043d\u0435 \u0431\u044b\u043b\u043e. \u042f \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044e \u043c\u0430\u0442\u0440\u0438\u0446\u0443 \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e \u0435\u0435 \u0432 \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440, \u0430 \u043e\u043d \u0443\u0436\u0435 \u0441\u0430\u043c \u0432\u0441\u0435 \u0442\u0430\u043c \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0438 \u0432\u044b\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0442\u043e\u0447\u043a\u0438.<\/p>\n<p><strong>\u041a\u0430\u043a \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0432 webgl?<\/strong><\/p>\n<ol>\n<li>\n<p>\u0414\u0435\u043b\u0430\u0435\u0448\u044c \u0440\u0430\u0441\u0447\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0448\u044c \u0438\u0445 \u0432 \u0448\u0435\u0439\u0434\u0435\u0440.<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0437\u044b\u0432\u0430\u0435\u0448\u044c&nbsp;<code>drawArray<\/code>, \u0447\u0442\u043e\u0431 \u043a\u0430\u0440\u0442\u0430 \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u043b\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043d\u043e\u0432\u0443\u044e \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c 1 \u043f\u0443\u043d\u043a\u0442 \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u043d\u0443\u0436\u043d\u0430 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u043e\u0442, \u0435\u0441\u043b\u0438 \u0432 css \u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0442\u043e \u0432 webgl \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0430 \u043f\u043e\u0442\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0440\u0435\u043d\u0434\u0435\u0440.<\/p>\n<p><strong>\u0422\u0430\u043a \u0436\u0435 \u0431\u044b\u043b\u0430 \u0435\u0449\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c<\/strong>. \u041c\u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0430\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0438 \u043f\u043e-\u0440\u0430\u0437\u043d\u043e\u043c\u0443.<\/p>\n<h4>\u041a\u0430\u043a \u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0435\u043b\u0438\u043b \u043d\u0430 \u0447\u0430\u0441\u0442\u0438.<\/h4>\n<p>\u0414\u0438\u0437\u0430\u0439\u043d\u0435\u0440 \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u043b \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0444\u0438\u0433\u0443\u0440\u044b \u0447\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u044f\u0431\u043b\u043e\u043a\u043e \u0438 \u043e\u043d \u0445\u043e\u0442\u0435\u043b, \u0447\u0442\u043e\u0431 \u0432\u0441\u0435 \u043a\u0430\u0436\u0434\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0444\u0438\u0433\u0443\u0440\u044b \u0432\u0435\u0440\u0442\u0435\u043b\u0430\u0441\u044c \u0432 \u043d\u0443\u0436\u043d\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443. \u0410 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0434\u0435\u043b\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0430 \u0447\u0430\u0441\u0442\u0438, \u0442\u043e \u0435\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0432\u0435\u0440\u0448\u0438\u043d \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c, \u043d\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0441\u0432\u043e\u044e \u043c\u0430\u0442\u0440\u0438\u0446\u0443 \u0438 \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0435\u0435. \u0412 webgl \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u043e\u043b\u043e\u0442\u043d\u043e \u043d\u0435 \u0441\u0442\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0438 \u0435\u0441\u043b\u0438 \u0432\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0435 drawArray, \u0442\u043e \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0440\u0438\u0441\u0443\u0435\u0442 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u043c\u0438 \u043f\u043e\u0432\u0435\u0440\u0445 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0443\u0436\u0435 \u0431\u044b\u043b\u043e \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u043d\u043e. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0438, \u0447\u0442\u043e-\u0442\u043e \u0441 \u043d\u0435\u0439 \u0434\u0435\u043b\u0430\u0442\u044c, \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c, \u0430 \u043f\u043e\u0442\u043e\u043c \u0434\u0440\u0443\u0433\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0438 \u0442\u0430\u043a \u043f\u043e \u043a\u0440\u0443\u0433\u0443.<\/p>\n<h4>\u0410 \u043a\u0430\u043a \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u0435\u0442\u0430\u043b\u0435\u0439?<\/h4>\n<p>\u0412 3\u0434 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430\u0445 \u043d\u0430\u0431\u043e\u0440\u044b \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0432 \u0433\u0440\u0443\u043f\u043f\u044b, \u0430 \u043f\u0440\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0435 \u044d\u0442\u0438 \u0433\u0440\u0443\u043f\u043f\u044b \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0438\u043c\u0432\u043e\u043b\u0430&nbsp;<code>o<\/code>&nbsp;(object) \u0432&nbsp;<code>.obj<\/code>, \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u044f \u043c\u043e\u0433 \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0443 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u043a.<\/p>\n<p>\u042f \u0432\u044b\u0434\u0435\u043b\u0438\u043b \u0434\u043b\u044f \u0441\u0435\u0431\u044f 3 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p>\u041c\u0430\u0442\u0440\u0438\u0446\u044b<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0434\u0435\u043b\u0438 (Mesh)<\/p>\n<\/li>\n<li>\n<p>\u0421\u0430\u043c \u0440\u0435\u043d\u0434\u0435\u0440<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e, \u043a\u043b\u0430\u0441\u0441\u0430 \u043c\u0430\u0442\u0440\u0438\u0446\u044b, \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0445\u043e\u0442\u0435\u043b \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0441\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u043c\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f\u043c\u0438, \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u043c\u0430\u0433\u0438\u044f \u043c\u0430\u0442\u0440\u0438\u0446. \u041f\u043e\u0447\u0435\u043c\u0443 \u0432\u043e\u043e\u0431\u0449\u0435 \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u0432\u044b\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 js, \u0430 \u043d\u0435 webgl? \u041f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u043d\u0443\u0436\u043d\u043e \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442 \u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0442\u044c, \u0430 \u0432 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c. \u0422\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430, \u044f \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043b, \u0447\u0442\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439. \u0410 \u043f\u043e\u0442\u043e\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<pre><code class=\"javascript\">import { glMatrix, mat4, vec3 } from \"gl-matrix\"; \/\/ \u043b\u0438\u0431\u0430 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c  export class Matrix {   \/\/ \u044f \u0440\u0435\u0448\u0438\u043b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043b\u043b\u0431\u0435\u043a \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043a\u043e\u0433\u0434\u0430 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u0435\u0442\u043e\u0434 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u043b\u0438.   constructor(onUpdate = () =&gt; {}) {}    \/\/ \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043c\u0430\u0442\u0440\u0438\u0446\u0430\u043c\u0438, \u043f\u043e \u0441\u0443\u0442\u0438 \u043a\u0435\u0448 \u0438 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u043c\u0430\u0442\u0440\u0438\u0446\u044b, \u0430 \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u043e!   #matrices = {};    \/\/ \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043a\u0430\u043c\u0435\u0440\u044b, \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u043d\u0435 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0441\u044f \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0444\u0438\u0433\u0443\u0440\u0443 \u043d\u0430 \u043d\u0443\u0436\u043d\u043e\u0439 \u0434\u0438\u0441\u0442\u0430\u043d\u0446\u0438\u0438.   setOrtho(left, right, bottom, top, near, far) {}    \/\/ \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e   #scale = 1;   \/\/ \u0441\u0435\u0442\u0442\u0435\u0440 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 scale   setScale(ratio) {}    \/\/ \u0440\u0435\u0448\u0438\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0433\u0435\u0442\u0442\u043e\u0440 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f,   \/\/ \u0447\u0442\u043e\u0431 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0432\u0441\u044f\u043a\u0438\u0445 \u0440\u0430\u0441\u0441\u0447\u0435\u0442\u043e\u0432 \u0441 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0435\u0439.   getScale() {}    #translate = [0, 0, 0];   \/**    * x, y, z \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435    * @param {[number, number, number]}params    *\/   setTranslate(params) {}   getTranslate() {}    \/\/ \u043d\u0443 \u0438 rotate, \u043d\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u043b \u0432 \u043e\u0434\u0438\u043d \u043c\u0435\u0442\u043e\u0434, \u043f\u043e\u0442\u043e\u043c\u0443, \u0441\u043e\u0431\u0438\u0440\u0430\u043b\u0441\u044f \u0430\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u043e\u0435 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e.   \/\/ \u0435\u0441\u043b\u0438 \u043c\u043d\u0435 \u0432\u0430\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0437\u043d\u0430\u0442\u044c \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 translate \u0438 scale, \u0442\u043e \u043d\u0430 rotate \u0431\u044b\u043b\u043e \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0433\u0435\u0442\u0442\u0435\u0440\u043e\u0432 \u043d\u0435 \u0434\u0435\u043b\u0430\u043b. \u0417\u0430\u0447\u0435\u043c?   setRotateX(deg) {}   setRotateY(deg) {}   setRotateZ(deg) {}    \/\/ \u043f\u0435\u0440\u0435\u043c\u043d\u043e\u0436\u0430\u0435\u043c \u0432\u0441\u0435 \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u0442\u043e\u0433\u043e\u0432\u0443\u044e \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u043a\u0438\u043d\u0443\u0442\u044c \u0432 \u0448\u0435\u0439\u0434\u0435\u0440   getCurrent() {} }<\/code><\/pre>\n<p>\u042f \u0440\u0435\u0448\u0438\u043b \u043d\u0435 \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0432 \u043a\u043e\u043d\u0446\u0435 \u0432\u044b\u043b\u043e\u0436\u0443 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0443 \u0441\u043e \u0432\u0441\u0435\u043c \u043a\u043e\u0434\u043e\u043c.<\/p>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0443 \u043d\u0430\u0441 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439. \u042f \u043d\u0430\u0437\u0432\u0430\u043b \u0435\u0433\u043e Mesh, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0443\u0432\u0438\u0434\u0435\u043b \u0442\u0430\u043a\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0432 Pixi.js. Mesh \u0437\u043d\u0430\u0447\u0438\u0442 \u0441\u0435\u0442\u043a\u0430, \u0441\u0435\u0442\u043a\u0430 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432. \u041f\u043e\u043d\u044f\u043b\u0438 \u0442\u0435\u043c\u0443? \u0422\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u0432\u0435\u0440\u0448\u0438\u043d\u0430 \u0432\u0441\u0435\u0433\u043e!<\/p>\n<p>\u041a\u043b\u0430\u0441\u0441 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0435\u043d\u043d\u044b\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0438 uv, \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043c\u0430\u0442\u0440\u0438\u0446\u0443, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0432 gl \u0431\u0443\u0444\u0435\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u0447\u0442\u043e\u0431 \u043f\u043e\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043b\u0435\u0433\u043a\u043e \u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438. \u0411\u0443\u0444\u0435\u0440 \u044d\u0442\u043e \u043c\u0435\u0441\u0442\u043e, \u043a\u0443\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0431\u0443\u0444\u0435\u0440 \u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b. \u0411\u0443\u0444\u0435\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438 \u043e\u043d\u0438 \u0432\u0441\u0435 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 \u043f\u0430\u043c\u044f\u0442\u0438, \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u043d\u0430 \u043f\u0435\u0440\u0435\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u043e\u0442\u043e\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442.<\/p>\n<pre><code class=\"javascript\">import { Matrix } from \".\/Matrix\";  export class Mesh {   \/**    *    * @param {Float32Array} positions    * @param {Float32Array} uv    *\/   \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0438 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b   constructor({ positions, uv }) {     this.positions = positions;     this.uv = uv;     \/\/ \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c drawArrays \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443 \u043d\u0430\u0441 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432, \u0442\u0430\u043a \u043a\u0430\u043a \u0434\u043b\u044f \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 \u0432\u0441\u0435\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e 3 \u0442\u043e\u0447\u043a\u0438, \u0442\u043e \u043c\u043e\u0436\u0435\u043c \u0441\u043c\u0435\u043b\u043e \u0434\u0435\u043b\u0438\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u0442\u043e\u0447\u043a\u0430\u043c\u0438 \u043d\u0430 3 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432     this.count = this.positions.length \/ 3;     \/\/ \u043b\u0438\u0447\u043d\u0430\u044f \u043c\u0430\u0442\u0440\u0438\u0446\u0430 \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0438     this.matrix = new Matrix();   }    \/\/ \u0441\u0441\u044b\u043b\u043e\u0447\u043a\u0438 \u043d\u0430 \u0431\u0443\u0444\u0435\u0440\u0430   positionsBuffer;   uvBuffer;    \/**    * @param {WebGLRenderingContext} gl    *\/   \/\/ \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043b \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u0442\u0430\u043a\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043a\u0430\u043a \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u044c\u043a\u0438, \u043c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0447\u0442\u043e\u0431 \u043d\u0443\u0436\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0431\u044b\u043b\u0438 \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u044b, \u0438\u0445 \u043d\u0443\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u043a\u0438\u043d\u0443\u0442\u044c \u0432 \u043a\u043b\u0430\u0441\u0441 \u0440\u0435\u043d\u0434\u0435\u0440\u0430.   attachRender(gl) {     this.gl = gl;   }    \/**    * \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0431\u0443\u0444\u0435\u0440\u0430, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0432 \u043d\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0435, \u0445\u0440\u0430\u043d\u0438\u043c \u044d\u0442\u0438 \u0431\u0443\u0444\u0435\u0440\u044b \u043f\u043e\u0442\u043e\u043c \u0432 \u043a\u043b\u0430\u0441\u0441\u0435, \u0447\u0442\u043e\u0431 \u043b\u0435\u0433\u043a\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u044c    *\/   initializeBuffers() {} }<\/code><\/pre>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e. \u041f\u043e\u043b\u0443\u0447\u0438 \u0432\u0435\u0440\u0448\u0438\u043d\u044b, \u0437\u0430\u0433\u0440\u0443\u0437\u0438 \u0432 \u0431\u0443\u0444\u0435\u0440\u0430 \u0438 \u0434\u0430\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043d\u0438\u0445.<\/p>\n<h4>ModelRender<\/h4>\n<p>\u0412\u0441\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043b\u0435\u0436\u0438\u0442 \u043d\u0430 \u043a\u043b\u0430\u0441\u0441\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0430. \u041e\u043d \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0432\u044b\u0434\u0430\u043d\u043d\u044b\u0439 \u0435\u043c\u0443&nbsp;<code>canvas<\/code>&nbsp;\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 webgl, \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0434\u043b\u044f \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432. \u0412\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432\u0441\u044f\u043a\u0438\u0435 \u044d\u043a\u0441\u0442\u0435\u043d\u0448\u0435\u043d\u044b, \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0441\u0435\u0431\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c, \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0446\u0432\u0435\u0442\u0430, \u0442\u043e\u043b\u0449\u0438\u043d\u044b \u043b\u0438\u043d\u0438\u0438 \u043c\u043e\u0434\u0435\u043b\u043a\u0438, \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0440\u0435\u0441\u0430\u0439\u0437\u043e\u043c \u044d\u043a\u0440\u0430\u043d\u0430, \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043a\u0430\u043c\u0435\u0440\u0443 \u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u044b\u0439 \u0432\u0430\u0436\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434&nbsp;<code>drawArrays<\/code>! \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443 \u0432\u043e\u043b\u0448\u0435\u0431\u043d\u043e\u043c\u0443 \u043c\u0435\u0442\u043e\u0434\u0443, \u043a\u0430\u0440\u0442\u0430 \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430&nbsp;<code>\u0445\u043e\u043b\u0441\u0442\u0435<\/code>.<\/p>\n<pre><code class=\"objectivec\">\/\/ \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 precision mediump float; uniform mat4 uMeshMatrix; \/\/ \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 uniform mat4 uCameraMatrix; \/\/ \u043c\u0438\u0440\u043e\u0432\u0430\u044f \u043a\u0430\u043c\u0435\u0440\u0430 attribute vec4 aPosition; \/\/ \u0432\u0435\u0440\u0448\u0438\u043d\u044b attribute vec2 aTextureCoords; \/\/ \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b varying vec2 vTextureCoords; \/\/ \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \/\/ \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u0440\u0448\u0438\u043d\u0430\u043c\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0432 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 void main(){     gl_Position = uCameraMatrix * uMeshMatrix * aPosition;     vTextureCoords = aTextureCoords; }<\/code><\/pre>\n<pre><code class=\"objectivec\">\/\/ \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 #extension GL_OES_standard_derivatives : enable \/\/ \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0448\u0442\u0443\u043a\u0443 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0430\u0448\u0438 \u043b\u0438\u043d\u0438\u0438 \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u043c\u0438 precision mediump float; \/\/ \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u0430\u043a \u043d\u0443\u0436\u043d\u043e \u043e\u043a\u0440\u0443\u0433\u043b\u044f\u0442\u044c float \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f uniform vec3 uLineColor; \/\/ \u0446\u0432\u0435\u0442 \u043b\u0438\u043d\u0438\u0438 uniform vec3 uBgColor; \/\/ \u0446\u0432\u0435\u0442 \u0444\u043e\u043d\u0430 uniform float uLineWidth; \/\/ \u0448\u0438\u0440\u0438\u043d\u0430 \u043b\u0438\u043d\u0438\u0438 varying vec2 vTextureCoords; \/\/ \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u044b \u0447\u0442\u043e\u0431 \u0432\u044b\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0433\u0440\u0430\u043d\u0438  \/\/ \u043c\u043e\u044f \u0441\u0443\u043f\u0435\u0440 \u043b\u043e\u0433\u0438\u043a\u0430 \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u0433\u0440\u0430\u043d\u0438\u0446 \/\/ \u044f \u043d\u0435 \u043c\u043e\u0433\u0443 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043a\u0430\u043a \u044f \u044d\u0442\u043e \u0441\u0447\u0438\u0442\u0430\u043b, \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0442\u043e\u0440\u0430 \u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434 \u044f \u0431\u044b\u043b \u0443\u043c\u043d\u0435\u0439. float border(vec2 uv, float uLineWidth, vec2 gap) {   \/\/ \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f gap \u043d\u0443\u0436\u043d\u0430 \u0431\u044b\u043b\u0430, \u0447\u0442\u043e\u0431 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043b\u0438\u043d\u0438\u0438 \u0431\u043e\u043b\u0435\u0435 \u043f\u043b\u0430\u0432\u043d\u044b\u043c\u0438, \u043e\u043d\u0430 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0435   \/\/ smoothstep \u043f\u043e\u043b\u0443\u0447\u0430\u043b \u0442\u043e\u0447\u043a\u0430 A \u0438 \u0442\u043e\u0447\u043a\u0443 B, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u043b \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u044d\u0442\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u043b \u043f\u043b\u0430\u0432\u043d\u043e\u0435 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0410 \u0418 \u0411.   vec2 xy0 = smoothstep(vec2(uLineWidth) - gap, vec2(uLineWidth) + gap, uv);   vec2 xy1 = smoothstep(vec2(1. - uLineWidth) - gap, vec2(1. - uLineWidth) + gap, uv);   vec2 xy = xy0 - xy1;   return clamp(xy.x * xy.y, 0., 1.); } void main() {   vec2 uv = vTextureCoords;   vec2 fw = vec2(uLineWidth + 0.05);   #ifdef GL_OES_standard_derivatives   \/\/ \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0438\u0432\u043d\u043e\u0435 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435, \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439 \u0435\u0441\u043b\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442     fw = fwidth(uv);   #endif   \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0447\u0442\u043e\u0431 \u043a\u0440\u0430\u0441\u0438\u0442\u044c \u0432 \u043d\u0443\u0436\u043d\u044b\u043c \u0446\u0432\u0435\u0442\u043e\u043c.   float br = border(vTextureCoords, uLineWidth, fw);   \/\/ mix \u0441\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u0442 \u0446\u0432\u0435\u0442\u0430, \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 1 \u0432\u0435\u0440\u043d\u0435\u0442 \u043f\u043e\u043b\u043d\u044b\u0439 \u0446\u0432\u0435\u0442 uLineColor, \u0435\u0441\u043b\u0438 0, \u0442\u043e \u0432\u0435\u0440\u043d\u0435\u0442 uBgColor.   \/\/ \u0410 \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0433\u0434\u0435-\u0442\u043e \u043f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435, \u0442\u043e \u0432\u0435\u0440\u043d\u0435\u0442 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043e\u0431\u0449\u0438\u0439 \u0446\u0432\u0435\u0442 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u0434\u0432\u0443\u043c\u044f.   \/\/ \u0412\u0418\u0412\u0410 \u041c\u0410\u0422\u0415\u041c\u0410\u0422\u0418\u041a\u0410   gl_FragColor = vec4(mix(uLineColor, uBgColor, br), 1.); }<\/code><\/pre>\n<pre><code>import { vertex, fragment } from \".\/shaders\"; \/\/ \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u043c\u0430\u0433\u0438\u0438, \u0442\u0430\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u044b \u0432 \u0441\u0442\u0440\u043e\u043a\u0430\u0445 import { Mesh } from \".\/Mesh\"; import { Matrix } from \".\/Matrix\";  import {   createProgramFromTexts,   resizeCanvasToDisplaySize,   saveRectAspectRatio, } from \".\/helpers\";  export class ModelRender {   \/\/ \u044f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0435\u043b \u0447\u0442\u043e\u0431 \u043a\u043b\u0430\u0441\u0441 \u0441\u0430\u043c<\/code><\/pre>\n<p><\/br><\/br><\/br><\/br><\/br><\/p>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-326383","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/326383","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=326383"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/326383\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=326383"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=326383"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=326383"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}