{"id":323829,"date":"2021-05-27T09:00:27","date_gmt":"2021-05-27T09:00:27","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=323829"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=323829","title":{"rendered":"\u041c\u0430\u0439\u043d\u043a\u0440\u0430\u0444\u0442 \u0434\u043b\u044f \u0433\u0435\u043e\u043b\u043e\u0433\u043e\u0432: 3D-\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u043c\u0438\u043b\u043b\u0438\u0430\u0440\u0434\u0430 \u044f\u0447\u0435\u0435\u043a \u043d\u0430 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0439 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0435 (\u0447\u0430\u0441\u0442\u044c 2)"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<p><a href=\"https:\/\/habr.com\/ru\/company\/bashnipineft\/blog\/544054\/\">\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438<\/a> \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 (\u0438 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439) \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440 \u0441\u0435\u0442\u043a\u0438 \u0413\u0423\u0422, \u0438 \u043f\u043e\u043e\u0431\u0435\u0449\u0430\u043b\u0438, \u0447\u0442\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440 \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e, \u0447\u0442\u043e \u043e\u043d \u0441\u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 \u043c\u0438\u043b\u043b\u0438\u0430\u0440\u0434 \u044f\u0447\u0435\u0435\u043a.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u043e\u0431\u044a\u0451\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u0435\u043c\u043e\u0439 \u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u0438 \u2014 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0432\u0438\u0434\u0435 \u0434\u0430\u0436\u0435 \u043d\u0430 \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0430\u0445 (\u0435\u0441\u043b\u0438 \u0431\u044b \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043a\u0443\u043f\u0438\u0442\u044c \u0432 \u043d\u0430\u0448\u0435 \u0432\u0440\u0435\u043c\u044f!) \u043f\u0430\u043c\u044f\u0442\u0438 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u0442\u044c, \u043d\u0435 \u0433\u043e\u0432\u043e\u0440\u044f \u0443\u0436 \u043e \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0430\u0445 \u0432 \u043e\u0444\u0438\u0441\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430\u0445.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f34\/be9\/b82\/f34be9b823e2b170a45269590f86507b.jpg\" width=\"1500\" height=\"971\"><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0430\u043c\u044f\u0442\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043d\u0430\u0448 \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440 \u0441\u0435\u0439\u0447\u0430\u0441. \u041a\u0430\u0436\u0434\u0430\u044f \u0433\u0440\u0430\u043d\u044c \u044f\u0447\u0435\u0439\u043a\u0438 \u0437\u0430\u0434\u0430\u043d\u0430 \u043d\u0430 \u0447\u0435\u0442\u044b\u0440\u0451\u0445 \u0432\u0435\u0440\u0448\u0438\u043d\u0430\u0445, \u043a\u0430\u0436\u0434\u0430\u044f \u0432\u0435\u0440\u0448\u0438\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u044f\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u043e\u0431\u0449\u0438\u043c \u043e\u0431\u044a\u0451\u043c\u043e\u043c \u0432 48 \u0431\u0430\u0439\u0442. \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u043d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0441\u0435\u0442\u043a\u0430 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 1000<sup>3<\/sup>. \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e 4*6*1000<sup>2<\/sup> \u0432\u0435\u0440\u0448\u0438\u043d \u0434\u043b\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0433\u0440\u0430\u043d\u0435\u0439 \u0441\u0435\u0442\u043a\u0438, \u043e\u0431\u0449\u0438\u043c \u043e\u0431\u044a\u0451\u043c\u043e\u043c 1098,6 \u041c\u0431. \u041d\u0435 \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u0431\u044b\u0432\u0430\u0442\u044c \u0438 \u043f\u0440\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u044b, \u043a\u043e\u0438\u0445 \u0431\u0443\u0434\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e 6*6*1000<sup>2<\/sup> \u0448\u0442. \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 137,3 \u041c\u0431.<\/p>\n<p>\u0412 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0441\u0435\u0442\u043a\u0438 \u0413\u0423\u0422 \u0447\u0430\u0441\u0442\u043e \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u044b \u0438 \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u043c\u0435\u044e\u0442 \u043c\u0430\u0441\u043a\u0443 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u044f\u0447\u0435\u0435\u043a, \u0438\u0437-\u0437\u0430 \u0447\u0435\u0433\u043e \u043d\u0435 \u043e\u0442\u0441\u0435\u0447\u0451\u043d\u043d\u044b\u0445 \u0433\u0440\u0430\u043d\u0435\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u044c\u0448\u0435. <\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u043f\u0430\u0440\u0443 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0445 \u044f\u0447\u0435\u0435\u043a, \u043e\u0434\u043d\u0430 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0430\u043a\u0442\u0438\u0432\u043d\u0430, \u0430 \u0434\u0440\u0443\u0433\u0430\u044f \u2013 \u043d\u0435\u0442. \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043e\u0442\u0441\u0435\u0447\u0435\u043d\u0438\u044f \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u044b\u0445 \u0433\u0440\u0430\u043d\u0435\u0439 (\u0441\u043c. \u043f\u0435\u0440\u0432\u0443\u044e \u0447\u0430\u0441\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/company\/bashnipineft\/blog\/544054\/\">\u0441\u0442\u0430\u0442\u044c\u0438<\/a>) \u0441\u043a\u0430\u0436\u0435\u0442, \u0447\u0442\u043e \u0434\u043b\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438 \u043d\u0443\u0436\u043d\u043e \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0433\u0440\u0430\u043d\u044c \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0432 \u0441\u0435\u0442\u043a\u0435 <em>\u043d\u0435<\/em>\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u044f\u0447\u0435\u0435\u043a, \u0442\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0433\u0440\u0430\u043d\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u043e.&nbsp;<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439, \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u0443\u044e \u0441\u0435\u0442\u043a\u0443 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430&nbsp;\u2014 \u0432\u0441\u0435\u0433\u043e 200<sup>3<\/sup> \u044f\u0447\u0435\u0435\u043a. \u041f\u043e\u0434\u0432\u043e\u0445 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0440\u043e\u0432\u043d\u043e \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0443 \u0438\u0437 \u044f\u0447\u0435\u0435\u043a \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u2014 \u044d\u0442\u043e \u0445\u0443\u0434\u0448\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u043e\u0442\u0441\u0435\u0447\u0435\u043d\u0438\u044f \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u044b\u0445 \u0433\u0440\u0430\u043d\u0435\u0439. <\/p>\n<p>\u041c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0434\u0443\u043c\u0430\u043d\u043d\u044b\u043c, \u043d\u043e \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043e\u0442\u0441\u0435\u0447\u0435\u043d\u0438\u044f \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u044b\u0445 \u0433\u0440\u0430\u043d\u0435\u0439 \u043d\u0435\u0442 \u0440\u0430\u0437\u043d\u0438\u0446\u044b, \u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u043b\u0438 \u0433\u0440\u0430\u043d\u044c \u0438\u0437-\u0437\u0430 \u043d\u0435\u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u0438 \u0438\u043b\u0438 \u0438\u0437-\u0437\u0430 \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0441\u043e\u0441\u0435\u0434\u043d\u0435\u0439 \u044f\u0447\u0435\u0439\u043a\u0438.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c07\/a93\/f86\/c07a93f8697799033bd2698bb1659a60.png\" width=\"1000\" height=\"814\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0439 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0441\u0435\u0442\u043a\u0438 \u043e\u0431\u044a\u0451\u043c \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u043c\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0434 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u043b 2484,3 \u041c\u0431 \u2014 \u0432 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430 \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u0434\u043b\u044f \u043c\u0438\u043b\u043b\u0438\u0430\u0440\u0434\u0430 \u0441\u043e\u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u044f\u0447\u0435\u0435\u043a!<\/p>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440\u0430 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">\/\/ corner_point_grid.h  template&lt;typename T&gt; struct span3d {      T* const data;     const uint32_t ni;     const uint32_t nj;     const uint32_t nk;      span3d(T* _data, uint32_t _ni, uint32_t _nj, uint32_t _nk)         : data(_data), ni(_ni), nj(_nj), nk(_nk) { }      T at(size_t x, size_t y, size_t z) const {         return data[x * nj * nk + y * nk + z];     }      T&amp; at(size_t x, size_t y, size_t z) {         return data[x * nj * nk + y * nk + z];     } };   struct Palette {     float min_value;     float max_value;     GLuint texture; };   struct CornerPointGrid {     CornerPointGrid(uint32_t ni, uint32_t nj, uint32_t nk,                     const float* coord, const float *zcorn, const float* property, const uint8_t* mask);     ~CornerPointGrid();      void render(GLuint shader,                 const Palette&amp; palette,                 const mat4&amp; proj, const mat4 &amp; view,                 const mat4&amp; model,                 vec3 light_direct,                 bool primitive_picking);  private:      \/\/ \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435     span3d&lt;const float&gt;   _coord;     span3d&lt;const float&gt;   _zcorn;     span3d&lt;const float&gt;   _property;     span3d&lt;const uint8_t&gt; _mask;      \/\/ \u043c\u0430\u0441\u043a\u0430 \u0441\u043e\u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u0438 \u0433\u0440\u0430\u043d\u0435\u0439     std::vector&lt;uint8_t&gt;  _joined_mask_data;     span3d&lt;uint8_t&gt;  _joined_mask; \/\/ \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043c\u0430\u0441\u0441\u0438\u0432 _joined_mask_data;      \/\/ \u043e\u0431\u044a\u0435\u043a\u0442\u044b OpenGL     GLuint _position_vbo;     GLuint _normal_vbo;     GLuint _cell_index_vbo;     GLuint _texcoord_vbo;     GLuint _property_vbo;      GLuint _indexbuffer;     GLuint _vao;      \/\/ \u0447\u0438\u0441\u043b\u043e \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u0434\u043b\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430     size_t _triangle_count;      \/\/ \u0440\u0430\u0441\u0447\u0435\u0442 \u0432\u0435\u0440\u0448\u0438\u043d \u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432     void _gen_vertices_and_indices(size_t quad_count);      \/\/ \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0431\u0443\u0444\u0435\u0440\u043e\u0432 OpenGL     void _create_vertex_index_buffers();      \/\/ \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0431\u0443\u0444\u0435\u0440\u043e\u0432 \u0432 VAO     void _setup_vao(); };   \/\/ corner_point_grid.cpp  \/\/ \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432\u043e\u0441\u044c\u043c\u0438 \u0435\u0451 \u0432\u0435\u0440\u0448\u0438\u043d. \/\/         6-------7 \/\/        \/|     \/ | \/\/       4------5  |    z y \/\/       | 2----|--3    |\/ \/\/       |\/     | \/     0-x \/\/       0------1 \/\/ \u042d\u0442\u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u043e\u0442\u0441\u0442\u0443\u043f\u044b \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0437 8-\u043c\u0438 \u0432\u0435\u0440\u0448\u0438\u043d \/\/ \u044f\u0447\u0435\u0439\u043a\u0438 \u043f\u043e \u043e\u0441\u044f\u043c x, y, z, \u0435\u0441\u043b\u0438 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0443 \u044f\u0447\u0435\u0439\u043a\u0443. static const std::array&lt;uint32_t, 8&gt; cell_vertices_offset_x = {     0, 1, 0, 1, 0, 1, 0, 1 }; static const std::array&lt;uint32_t, 8&gt; cell_vertices_offset_y = {     0, 0, 1, 1, 0, 0, 1, 1 }; static const std::array&lt;uint32_t, 8&gt; cell_vertices_offset_z = {     0, 0, 0, 0, 1, 1, 1, 1 };  \/\/ \u0418\u043d\u0434\u0435\u043a\u0441\u044b \u0432\u0435\u0440\u0448\u0438\u043d, \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u0433\u0440\u0430\u043d\u0438 \u044f\u0447\u0435\u0439\u043a\u0438. \/\/         6-------7 \/\/        \/|     \/ | \/\/       4------5  |    z y \/\/       | 2----|--3    |\/ \/\/       |\/     | \/     0-x \/\/       0------1 static const std::array&lt;std::array&lt;uint32_t, 4&gt;, 6&gt; cell_quads = {     std::array&lt;uint32_t, 4&gt;{0, 1, 5, 4},   \/\/ 1-\u0430\u044f \u0433\u0440\u0430\u043d\u044c     std::array&lt;uint32_t, 4&gt;{1, 3, 7, 5},   \/\/ 2-\u0430\u044f \u0433\u0440\u0430\u043d\u044c     std::array&lt;uint32_t, 4&gt;{3, 2, 6, 7},   \/\/ ...     std::array&lt;uint32_t, 4&gt;{2, 0, 4, 6},     std::array&lt;uint32_t, 4&gt;{3, 1, 0, 2},     std::array&lt;uint32_t, 4&gt;{4, 5, 7, 6}, };  \/\/ \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0430\u043d\u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0441\u043e\u0441\u0435\u0434\u043d\u0435\u0439 \u044f\u0447\u0435\u0439\u043a\u0438 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u044d\u0442\u043e\u0439 \u0433\u0440\u0430\u043d\u0438 static const std::array&lt;std::array&lt;int, 3&gt;, 6&gt; cell_quads_neighbors = {     \/\/ \u043f\u0440\u0438\u0431\u0430\u0432\u0438\u043c \u0438\u0445 \u043a \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c (i,j,k) \u044f\u0447\u0435\u0439\u043a\u0438 - \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0441\u043e\u0441\u0435\u0434\u043d\u0435\u0439 \u044f\u0447\u0435\u0439\u043a\u0438     std::array&lt;int, 3&gt;{ 0, -1,  0},     std::array&lt;int, 3&gt;{ 1,  0,  0},     std::array&lt;int, 3&gt;{ 0,  1,  0},     std::array&lt;int, 3&gt;{-1,  0,  0},     std::array&lt;int, 3&gt;{ 0,  0, -1},     std::array&lt;int, 3&gt;{ 0,  0,  1}, };  \/\/ \u0431\u0438\u0442\u043e\u0432\u044b\u0435 \u043c\u0430\u0441\u043a\u0438, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u0443\u0437\u043d\u0430\u0442\u044c \u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u0430 \u043b\u0438 \u044f\u0447\u0435\u0439\u043a\u0430 \u0441 \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0445 \/\/ (\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043c\u0430\u0441\u043a\u0435 \u0431\u0438\u0442 \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 joined_mask) enum JoinedMaskBits : uint8_t {     I_PREV = 1 &lt;&lt; 0, I_NEXT = 1 &lt;&lt; 1,     J_PREV = 1 &lt;&lt; 2, J_NEXT = 1 &lt;&lt; 3,     K_PREV = 1 &lt;&lt; 4, K_NEXT = 1 &lt;&lt; 5 };  \/\/ \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0430\u043d\u0438 \u0431\u0438\u0442, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0441 \u0441\u043e\u0441\u0435\u0434\u043d\u0435\u0439 \u044f\u0447\u0435\u0439\u043a\u043e\u0439 static const std::array&lt;JoinedMaskBits, 6&gt; cell_quads_joined_mask_bits = {     \/\/ \u0442\u043e \u0435\u0441\u0442\u044c \u044f\u0447\u0435\u0439\u043a\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0441\u0435\u0434\u043d\u0435\u0439 \u043f\u043e \u043e\u0441\u0438 x, y \u0438\u043b\u0438 z     JoinedMaskBits::J_PREV,     JoinedMaskBits::I_NEXT,     JoinedMaskBits::J_NEXT,     JoinedMaskBits::I_PREV,     JoinedMaskBits::K_PREV,     JoinedMaskBits::K_NEXT, };  \/\/ \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0442\u043a\u0443 \u043d\u0430 \u0433\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u044f\u0447\u0435\u0435\u043a, \/\/ \u043d\u0430\u0434\u043e \u0437\u043d\u0430\u0442\u044c \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u043b\u0438\u0437\u043a\u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u043a \u0433\u0440\u0430\u043d\u0438\u0446\u0435. \/\/ \u0422\u0443\u0442 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u044b \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0433\u0440\u0430\u043d\u0438, \/\/ \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043e \u0433\u0440\u0430\u043d\u0438\u0446\u044b \/\/ (\u0435\u0441\u043b\u0438 \u043e\u0434\u0438\u043d \u0438\u0437 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0440\u0430\u0432\u0435\u043d \u043d\u0443\u043b\u044e, \u0442\u043e \u044d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c \u0433\u0440\u0430\u043d\u0438\u0446\u0430). static const std::array&lt;vec2, 4&gt; quad_vertices_texcoords = {     vec2(1, 0),     vec2(0, 0),     vec2(0, 1),     vec2(0, 0), };  \/\/ \u041a\u0430\u043a \u0434\u043b\u044f \u0433\u0440\u0430\u043d\u0438 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0432\u0430 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 static const std::array&lt;uint32_t, 6&gt; quad_to_triangles = {     0, 1, 2, 0, 2, 3 };   static vec3 calc_normal(vec3 v1, vec3 v2){     \/\/ \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043d\u043e\u0440\u043c\u0430\u043b\u044c \u043a \u043a\u0432\u0430\u0434\u0443     vec3 normal = cross(v1, v2);      \/\/ \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043c \u043d\u043e\u0440\u043c\u0430\u043b\u044c \u043a \u0435\u0434\u0438\u043d\u0438\u0447\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u0435     if (length2(normal) &lt; 1e-8f){         normal = vec3(0, 0, 1);     } else {         normal = normalize(normal);     }      return normal; }   static void calc_joined_mask(span3d&lt;const float&gt; zcorn, span3d&lt;uint8_t&gt; joined_mask) {     \/\/ \u0441 \u043a\u0430\u043a\u043e\u0439 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u043d\u0438\u0435 \u0433\u0440\u0430\u043d\u0435\u0439, ~10 \u0441\u043c \u0432\u043f\u043e\u043b\u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.     const float eps = 0.1f;      \/\/ \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u0439 \u043c\u0430\u0441\u043a\u0438     for(uint32_t i = 0; i &lt; joined_mask.ni; ++i) {         for(uint32_t j = 0; j &lt; joined_mask.nj; ++j) {             for(uint32_t k = 0; k &lt; joined_mask.nk; ++k) {                 \/\/ \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u044d\u0442\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438 \u0432 zcorn                 uint32_t iz = i * 2, jz = j * 2, kz = k * 2;                  \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 \u043b\u0438 \u0433\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u044f\u0447\u0435\u0435\u043a (i,j,k) \u0438 (i+1,j,k) \u043f\u043e \u043e\u0441\u0438 X                 if (i + 1 &lt; joined_mask.ni) {                     float d = 0.0f;                     d += std::abs(zcorn.at(iz+1, jz,   kz  ) - zcorn.at(iz+2, jz,   kz  ));                     d += std::abs(zcorn.at(iz+1, jz+1, kz  ) - zcorn.at(iz+2, jz+1, kz  ));                     d += std::abs(zcorn.at(iz+1, jz,   kz+1) - zcorn.at(iz+2, jz,   kz+1));                     d += std::abs(zcorn.at(iz+1, jz+1, kz+1) - zcorn.at(iz+2, jz+1, kz+1));                      if (d &lt; eps) {                         \/\/ \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 - \u043e\u0442\u043c\u0435\u0442\u0438\u043c \u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0432 \u0431\u0438\u0442\u044b I_NEXT \u0438 I_PREV                         joined_mask.at(i,   j, k) |= I_NEXT;                         joined_mask.at(i+1, j, k) |= I_PREV;                     }                 }                  \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 \u043b\u0438 \u0433\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u044f\u0447\u0435\u0435\u043a (i,j,k) \u0438 (i,j+1,k) \u043f\u043e \u043e\u0441\u0438 Y                 if (j + 1 &lt; joined_mask.nj) {                     float d = 0.0f;                     d += std::abs(zcorn.at(iz,   jz+1, kz  ) - zcorn.at(iz,   jz+2, kz  ));                     d += std::abs(zcorn.at(iz+1, jz+1, kz  ) - zcorn.at(iz+1, jz+2, kz  ));                     d += std::abs(zcorn.at(iz,   jz+1, kz+1) - zcorn.at(iz,   jz+2, kz+1));                     d += std::abs(zcorn.at(iz+1, jz+1, kz+1) - zcorn.at(iz+1, jz+2, kz+1));                      if (d &lt; eps) {                         \/\/ \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 - \u043e\u0442\u043c\u0435\u0442\u0438\u043c \u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0432 \u0431\u0438\u0442\u044b J_NEXT \u0438 J_PREV                         joined_mask.at(i, j,   k) |= J_NEXT;                         joined_mask.at(i, j+1, k) |= J_PREV;                     }                 }                  \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 \u043b\u0438 \u0433\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u044f\u0447\u0435\u0435\u043a (i,j,k) \u0438 (i,j,k+1) \u043f\u043e \u043e\u0441\u0438 Z                 if (k + 1 &lt; joined_mask.nk) {                     float d = 0.0f;                     d += std::abs(zcorn.at(iz,   jz,   kz+1) - zcorn.at(iz,   jz,   kz+2));                     d += std::abs(zcorn.at(iz+1, jz,   kz+1) - zcorn.at(iz+1, jz,   kz+2));                     d += std::abs(zcorn.at(iz,   jz+1, kz+1) - zcorn.at(iz,   jz+1, kz+2));                     d += std::abs(zcorn.at(iz+1, jz+1, kz+1) - zcorn.at(iz+1, jz+1, kz+2));                      if (d &lt; eps) {                         \/\/ \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 - \u043e\u0442\u043c\u0435\u0442\u0438\u043c \u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0432 \u0431\u0438\u0442\u044b K_NEXT \u0438 K_PREV                         joined_mask.at(i, j, k)   |= K_NEXT;                         joined_mask.at(i, j, k+1) |= K_PREV;                     }                 }             } \/\/ for k         } \/\/ for j     } \/\/ for i }  static bool check_if_quad_culled(const span3d&lt;const uint8_t&gt;&amp; mask,                                  const span3d&lt;uint8_t&gt;&amp; joined_mask,                                  uint32_t i, uint32_t j, uint32_t k, uint32_t qi) {      \/\/ \u0433\u0440\u0430\u043d\u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0442\u0435\u0445 \u0441\u0442\u043e\u0440\u043e\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0441\u043e\u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u044b \u0441 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u043c\u0438     if (!(joined_mask.at(i, j, k) &amp; cell_quads_joined_mask_bits[qi]))         return false;      \/\/ \u0438\u043b\u0438 \u0435\u0441\u043b\u0438 \u0441\u043e\u0441\u0435\u0434\u043d\u044f\u044f \u044f\u0447\u0435\u0439\u043a\u0430 \u043d\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f     \/\/ (\u0432\u044b\u0445\u043e\u0434 \u0437\u0430 \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u043d\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0442.\u043a. \u043f\u043e \u0433\u0440\u0430\u043d\u0438\u0446\u0435 _joined_mask == 0)     if (!mask.at(i + cell_quads_neighbors[qi][0],                  j + cell_quads_neighbors[qi][1],                  k + cell_quads_neighbors[qi][2]))         return false;      \/\/ \u043e\u0431\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0435 \u043f\u0440\u043e\u0448\u043b\u0438, \u0437\u043d\u0430\u0447\u0438\u0442 \u0433\u0440\u0430\u043d\u044c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u0441\u0435\u0447\u044c     return true; }  static size_t calc_number_of_quads(const span3d&lt;const uint8_t&gt;&amp; mask,                                    const span3d&lt;uint8_t&gt; joined_mask) {     size_t num_of_quads = 0;      for (uint32_t i = 0; i &lt; mask.ni; ++i)         for (uint32_t j = 0; j &lt; mask.nj; ++j)             for (uint32_t k = 0; k &lt; mask.nk; ++k)                  \/\/ \u0435\u0441\u043b\u0438 \u044f\u0447\u0435\u0439\u043a\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u0430                 if (mask.at(i, j, k)){                      \/\/ \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u0438\u0433\u043e\u043d\u0430                     for (uint32_t qi = 0; qi &lt; 6; ++qi){                          \/\/ \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c, \u043d\u0443\u0436\u043d\u043e \u043b\u0438 \u0435\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c                         if (!check_if_quad_culled(mask, joined_mask, i, j, k, qi))                             \/\/ \u0438 \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e, \u0442\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u043c \u0441\u0447\u0435\u0442\u0447\u0438\u043a                             num_of_quads++;                     }                 }      return num_of_quads; }   \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 8 \u0432\u0435\u0440\u0448\u0438\u043d, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u044f\u0447\u0435\u0439\u043a\u0435 (i, j, k). \/\/     6-------7 \/\/    \/|     \/ | \/\/   4------5  | \/\/   | 2----|--3 \/\/   |\/     | \/ \/\/   0------1 static void get_cell_vertices(const span3d&lt;const float&gt;&amp; coord,                               const span3d&lt;const float&gt;&amp; zcorn,                               uint32_t i, uint32_t j, uint32_t k,                               std::array&lt;vec3, 8&gt;&amp; vertices) {      \/\/ \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b     for (int vi = 0; vi &lt; 8; ++vi) {          \/\/ \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u043f\u0438\u043b\u043b\u0430\u0440\u0430 \u043f\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u043c \u044f\u0447\u0435\u0439\u043a\u0438         uint32_t pillar_index_i = i + cell_vertices_offset_x[vi];         uint32_t pillar_index_j = j + cell_vertices_offset_y[vi];          \/\/ p1 - \u043f\u0435\u0440\u0432\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u043f\u0438\u043b\u043b\u0430\u0440\u0430         float p1_x = coord.at(pillar_index_i, pillar_index_j, 0);         float p1_y = coord.at(pillar_index_i, pillar_index_j, 1);         float p1_z = coord.at(pillar_index_i, pillar_index_j, 2);         \/\/ p2 - \u0432\u0442\u043e\u0440\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u043f\u0438\u043b\u043b\u0430\u0440\u0430         float p2_x = coord.at(pillar_index_i, pillar_index_j, 3);         float p2_y = coord.at(pillar_index_i, pillar_index_j, 4);         float p2_z = coord.at(pillar_index_i, pillar_index_j, 5);          \/\/ \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 Z \u0434\u043b\u044f \u044f\u0447\u0435\u0439\u043a\u0438 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c, \u0430 X \u0438 Y \u043d\u0435\u0442,         \/\/ \u0437\u0430\u0442\u043e \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u0447\u0442\u043e (x,y,z) \u043b\u0435\u0436\u0438\u0442 \u043d\u0430 \u043b\u0438\u043d\u0438\u0438 \u043f\u0438\u043b\u043b\u0430\u0440\u0430 p1-p2         float z = zcorn.at(2 * i + cell_vertices_offset_x[vi],                            2 * j + cell_vertices_offset_y[vi],                            2 * k + cell_vertices_offset_z[vi]);          float t = (z - p1_z) \/ (p2_z - p1_z);         float x = p1_x + (p2_x - p1_x) * t;         float y = p1_y + (p2_y - p1_y) * t;         vertices[vi].x = x;         vertices[vi].y = y;         vertices[vi].z = z;     } }  void CornerPointGrid::_gen_vertices_and_indices(size_t quad_count) {      const size_t vertex_count = quad_count * 4;      std::vector&lt;float&gt; a_position, a_index, a_property, a_normal, a_texcoord;     \/\/ \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b 3 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b (x, y \u0438 z)     a_position.reserve(3 * vertex_count);     \/\/ + \u0442\u0440\u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u0430     a_index.reserve(3 * vertex_count);     \/\/ + \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u044f\u0447\u0435\u0439\u043a\u0438     a_property.reserve(vertex_count);     \/\/ + \u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043d\u043e\u0440\u043c\u0430\u043b\u0438     a_normal.reserve(3 * vertex_count);     \/\/ + \u0434\u0432\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b (\u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0442 \u0432\u0435\u0440\u0448\u0438\u043d \u0434\u043e \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u043b\u0435\u0436\u0430\u0449\u0438\u0445 \u0441\u0442\u043e\u0440\u043e\u043d)     a_texcoord.reserve(2 * vertex_count);       \/\/ \u0431\u0443\u0444\u0435\u0440, \u043a\u0443\u0434\u0430 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u044f\u0447\u0435\u0439\u043a\u0438     std::array&lt;vec3, 8&gt; cell_vertices;      \/\/ \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438     for (uint32_t i = 0; i &lt; _property.ni; ++i) {         for (uint32_t j = 0; j &lt; _property.nj; ++j) {             for (uint32_t k = 0; k &lt; _property.nk; ++k) {                  \/\/ \u0435\u0441\u043b\u0438 \u044f\u0447\u0435\u0439\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c\u0441\u044f (\u043e\u043d\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0443\u044e\u0442\u0441\u044f \u043f\u043e \u043c\u0430\u0441\u043a\u0435)                 if (_mask.at(i, j, k)){                      \/\/ \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u0435\u043c 8 \u0432\u0435\u0440\u0448\u0438\u043d, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u044f\u0447\u0435\u0439\u043a\u0435                     get_cell_vertices(_coord, _zcorn, i, j, k, cell_vertices);                      \/\/ \u0438\u0437 \u0432\u0435\u0440\u0448\u0438\u043d \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0433\u0440\u0430\u043d\u0438                     for (int qi = 0; qi &lt; 6; ++qi) {                         \/\/ \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c, \u043d\u0443\u0436\u043d\u043e \u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0433\u0440\u0430\u043d\u044c                         if (!check_if_quad_culled(_mask, _joined_mask, i, j, k, qi)){                              \/\/ 4 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0432\u0435\u0440\u0448\u0438\u043d \u0433\u0440\u0430\u043d\u0438                             const std::array&lt;uint32_t, 4&gt;&amp; quad = cell_quads[qi];                              \/\/ \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043d\u043e\u0440\u043c\u0430\u043b\u044c \u0433\u0440\u0430\u043d\u0438                             vec3 normal = calc_normal(                                         cell_vertices[quad[0]] - cell_vertices[quad[1]],                                         cell_vertices[quad[2]] - cell_vertices[quad[1]]);                              \/\/ \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0432 \u043f\u043e\u043b\u0438\u0433\u043e\u043d\u0435                             for (int vii = 0; vii &lt; 4; ++vii){                                  \/\/ \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b                                 const vec3&amp; v = cell_vertices[quad[vii]];                                  \/\/ \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432\u0435\u0440\u0448\u0438\u043d\u044b                                 a_position.insert(a_position.end(), {v.x, v.y, v.z});                                 a_index.insert(a_index.end(), {(float)i, (float)j, (float)k});                                 a_property.push_back(_property.at(i, j, k));                                 a_normal.insert(a_normal.end(), {normal.x, normal.y, normal.z});                                 vec2 texcoords = quad_vertices_texcoords[vii];                                 a_texcoord.insert(a_texcoord.end(), {texcoords.x, texcoords.y});                             }                         }                     }                 }             }         }     }      assert(a_position.size() == vertex_count * 3);      \/\/ \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 VBO     glNamedBufferStorage(_position_vbo,    a_position.size() * sizeof (float),       a_position.data(), gl::GL_NONE_BIT);     glNamedBufferStorage(_normal_vbo,      a_normal.size() * sizeof (float),     a_normal.data(), gl::GL_NONE_BIT);     glNamedBufferStorage(_cell_index_vbo, a_index.size() * sizeof (float),     a_index.data(), gl::GL_NONE_BIT);     glNamedBufferStorage(_texcoord_vbo,    a_texcoord.size() * sizeof (float),   a_texcoord.data(), gl::GL_NONE_BIT);     glNamedBufferStorage(_property_vbo,   a_property.size() * sizeof (float),    a_property.data(), gl::GL_NONE_BIT);       \/\/ \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 - \u043d\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u0433\u0440\u0430\u043d\u044c \u0434\u0432\u0430 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430     size_t indices_count = quad_count * 6;     std::vector&lt;uint32_t&gt; indices;     indices.reserve(indices_count);      for (size_t i = 0; i &lt; quad_count; ++i)         for (uint32_t j = 0; j &lt; 6; ++j)             \/\/ \u0438\u043d\u0434\u0435\u043a\u0441 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u043f\u0440\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432             indices.push_back(static_cast&lt;uint32_t&gt;(i * 4 + quad_to_triangles[j]));      glNamedBufferStorage(_indexbuffer, indices.size() * sizeof (uint32_t), indices.data(), gl::GL_NONE_BIT);      \/\/ \u0437\u0430\u043f\u043e\u043c\u043d\u0438\u043c \u0447\u0438\u0441\u043b\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432, \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f glDrawElements     _triangle_count = indices.size(); }  void CornerPointGrid::_create_vertex_index_buffers() {     \/\/ \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u044b\u0435 \u0431\u0443\u0444\u0435\u0440\u044b     glCreateBuffers(1, &amp;_position_vbo);     glCreateBuffers(1, &amp;_normal_vbo);     glCreateBuffers(1, &amp;_cell_index_vbo);     glCreateBuffers(1, &amp;_texcoord_vbo);     glCreateBuffers(1, &amp;_property_vbo);      \/\/ \u0438\u043d\u0434\u0435\u043a\u0441\u043d\u044b\u0439 \u0431\u0443\u0444\u0435\u0440     glCreateBuffers(1, &amp;_indexbuffer); }  void CornerPointGrid::_setup_vao() {     \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c VAO     glCreateVertexArrays(1, &amp;_vao);     \/\/ \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u043d\u044b\u0439 \u0431\u0443\u0444\u0435\u0440 \u0432 VAO     glVertexArrayElementBuffer(_vao, _indexbuffer);      \/\/ \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 VAO     \/\/ position     glVertexArrayVertexBuffer(_vao, 0, _position_vbo, 0, sizeof (float) * 3);     glVertexArrayAttribBinding(_vao, 0, 0);     glVertexArrayAttribFormat(_vao, 0, 3, GL_FLOAT, GL_FALSE, 0);     glEnableVertexArrayAttrib(_vao, 0);      \/\/ normal     glVertexArrayVertexBuffer(_vao, 1, _normal_vbo, 0, sizeof (float) * 3);     glVertexArrayAttribBinding(_vao, 1, 1);     glVertexArrayAttribFormat(_vao, 1, 3, GL_FLOAT, GL_FALSE, 0);     glEnableVertexArrayAttrib(_vao, 1);      \/\/ cell index     glVertexArrayVertexBuffer(_vao, 2, _cell_index_vbo, 0, sizeof (float) * 3);     glVertexArrayAttribBinding(_vao, 2, 2);     glVertexArrayAttribFormat(_vao, 2, 3, GL_FLOAT, GL_FALSE, 0);     glEnableVertexArrayAttrib(_vao, 2);      \/\/ texcoord     glVertexArrayVertexBuffer(_vao, 3, _texcoord_vbo, 0, sizeof (float) * 2);     glVertexArrayAttribBinding(_vao, 3, 3);     glVertexArrayAttribFormat(_vao, 3, 2, GL_FLOAT, GL_FALSE, 0);     glEnableVertexArrayAttrib(_vao, 3);      \/\/ property     glVertexArrayVertexBuffer(_vao, 4, _property_vbo, 0, sizeof (float));     glVertexArrayAttribBinding(_vao, 4, 4);     glVertexArrayAttribFormat(_vao, 4, 1, GL_FLOAT, GL_FALSE, 0);     glEnableVertexArrayAttrib(_vao, 4); }  CornerPointGrid::CornerPointGrid(uint32_t ni, uint32_t nj, uint32_t nk,                                  const float* coord, const float* zcorn, const float* property, const uint8_t* mask) :     _coord(coord,       ni+1, nj+1, 6),     _zcorn(zcorn,       ni*2, nj*2, nk*2),     _property(property, ni, nj, nk),     _mask(mask,         ni, nj, nk),     _joined_mask_data(ni*nj*nk, 0),     _joined_mask(_joined_mask_data.data(), ni, nj, nk) {      \/\/ \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043c\u0430\u0441\u043a\u0443 \u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u0438 \u044f\u0447\u0435\u0435\u043a     calc_joined_mask(_zcorn, _joined_mask);      \/\/ \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0447\u0438\u0441\u043b\u043e \u0432\u0438\u0434\u0438\u043c\u044b\u0445 \u0433\u0440\u0430\u043d\u0435\u0439     size_t quad_count = calc_number_of_quads(_mask, _joined_mask);      \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u044b\u0435 \u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u043d\u044b\u0439 \u0431\u0443\u0444\u0435\u0440\u044b     _create_vertex_index_buffers();      \/\/ \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0438\u0445 \u0432 \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u044b\u0435\/\u0438\u043d\u0434\u0435\u043a\u0441\u043d\u044b\u0435 \u0431\u0443\u0444\u0435\u0440\u044b     _gen_vertices_and_indices(quad_count);      \/\/ \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0435\u043c \u043d\u0430\u0448\u0438 \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u044b\u0435 \u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u043d\u044b\u0439 \u0431\u0443\u0444\u0435\u0440 \u0432 VAO     _setup_vao(); }  CornerPointGrid::~CornerPointGrid() {     glDeleteVertexArrays(1, &amp;_vao);     glDeleteBuffers(1, &amp;_position_vbo);     glDeleteBuffers(1, &amp;_normal_vbo);     glDeleteBuffers(1, &amp;_cell_index_vbo);     glDeleteBuffers(1, &amp;_texcoord_vbo);     glDeleteBuffers(1, &amp;_property_vbo);     glDeleteBuffers(1, &amp;_indexbuffer); }  void CornerPointGrid::render(GLuint shader,                             const Palette&amp; palette,                             const mat4&amp; proj,                             const mat4&amp; view,                             const mat4&amp; model,                             vec3 light_direct,                             bool primitive_picking) {     \/\/ \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b \u0444\u0440\u0435\u0439\u043c\u0431\u0443\u0444\u0435\u0440,     \/\/ \u0432\u043a\u043b\u044e\u0447\u0438\u043b \u0442\u0435\u0441\u0442 \u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u0433\u043b\u0443\u0431\u0438\u043d\u044b, \u0432\u043a\u043b\u044e\u0447\u0438\u043b backface culling     glUseProgram(shader);      \/\/ \u043c\u0430\u0442\u0440\u0438\u0446\u0430 MVP     mat4 mvp = proj * view * model;     glProgramUniformMatrix4fv(shader, glGetUniformLocation(shader, \"u_mvp\"), 1, GL_FALSE, &amp;mvp[0][0]);      \/\/ \u043c\u0430\u0442\u0440\u0438\u0446\u0430 \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u0439     mat3 normal_mat = transpose(inverse(mat3{model}));     glProgramUniformMatrix3fv(shader, glGetUniformLocation(shader, \"u_normal_mat\"), 1, GL_FALSE, &amp;normal_mat[0][0]);      \/\/ \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0432\u0435\u0442\u0430 \u0438 \u0440\u0435\u0436\u0438\u043c \u043f\u0438\u043a\u0438\u043d\u0433\u0430     glProgramUniform3fv(shader, glGetUniformLocation(shader, \"u_light_direct\"), 1, &amp;light_direct[0]);     glProgramUniform1i(shader, glGetUniformLocation(shader, \"u_primitive_picking\"), primitive_picking);      \/\/ \u043f\u0430\u043b\u0438\u0442\u0440\u0430     glBindTextureUnit(0, palette.texture);     glProgramUniform2f(shader, glGetUniformLocation(shader, \"u_value_range\"), palette.min_value, palette.max_value);      \/\/ \u0440\u0438\u0441\u0443\u0435\u043c     glBindVertexArray(_vao);     glDrawElements(GL_TRIANGLES, _triangle_count, GL_UNSIGNED_INT, nullptr);      \/\/ \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u0435     glBindVertexArray(0);     glBindTextureUnit(0, 0);     glUseProgram(0); }    \/\/ corner_point_grid.vert #version 440  \/\/ \u043f\u043e\u0437\u0438\u0446\u0438\u044f layout(location=0) in vec3 a_pos; \/\/ \u043d\u043e\u0440\u043c\u0430\u043b\u044c layout(location=1) in vec3 a_normal; \/\/ \u0438\u043d\u0434\u0435\u043a\u0441 \u044f\u0447\u0435\u0439\u043a\u0438 layout(location=2) in vec3 a_ind; \/\/ \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b layout(location=3) in vec2 a_texcoord; \/\/ \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u044f\u0447\u0435\u0439\u043a\u0435, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0446\u0432\u0435\u0442 layout(location=4) in float a_property;  \/\/ \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u0430 \u0441 \u043f\u0430\u043b\u0438\u0442\u0440\u043e\u0439 layout(binding=0) uniform sampler1D u_palette_tex;  \/\/ \u043c\u0430\u0442\u0440\u0438\u0446\u044b MVP-\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f layout(location=0) uniform mat4 u_mvp; \/\/ \u043c\u0430\u0442\u0440\u0438\u0446\u0430 \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u0439 layout(location=1) uniform mat3 u_normal_mat; \/\/ \u043a\u0430\u043a\u043e\u043c\u0443 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u0430 layout(location=2) uniform vec2 u_value_range; \/\/ \u0440\u0435\u0436\u0438\u043c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 layout(location=3) uniform bool u_primitive_picking; \/\/ \u0432\u0435\u043a\u0442\u043e\u0440 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0432\u0435\u0442\u0430 layout(location=4) uniform vec3 u_light_direct;   layout(location=0) out INTERFACE {     \/\/ \u0446\u0432\u0435\u0442 \u0432\u0435\u0440\u0448\u0438\u043d\u044b     vec4 color;     \/\/ \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b     vec2 texcoord; } vs_out;    void main() {      \/\/ \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043c mvp-\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u0438     gl_Position = u_mvp * vec4(a_pos, 1);      \/\/ \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440     vs_out.texcoord = a_texcoord;      \/\/ \u0435\u0441\u043b\u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0438\u043a\u0438\u043d\u0433 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u044f\u0447\u0435\u0435\u043a, \u0432\u043c\u0435\u0441\u0442\u043e \u0446\u0432\u0435\u0442\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0432\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u044f\u0447\u0435\u0439\u043a\u0438     if (u_primitive_picking) {         vs_out.color = vec4(a_ind.x, a_ind.y, a_ind.z, 1);         return;     }      \/\/ \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u044f\u0447\u0435\u0439\u043a\u0438 \u043a \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0443 \u043f\u0430\u043b\u0438\u0442\u0440\u044b     float normalized_value = (a_property - u_value_range.x) \/ (u_value_range.y - u_value_range.x);     \/\/ \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0446\u0432\u0435\u0442 \u0432 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u0435 \u043f\u0430\u043b\u0438\u0442\u0440\u044b     vec4 cell_color = texture(u_palette_tex, normalized_value);      \/\/ \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0443\u044e \u043d\u043e\u0440\u043c\u0430\u043b\u044c     vec3 normal = normalize(u_normal_mat * a_normal);      \/\/ \u043a\u043e\u0441\u0438\u043d\u0443\u0441 \u0443\u0433\u043b\u0430 \u043c\u0435\u0436\u0434\u0443 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u044e \u0438 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u043e\u0441\u0432\u0435\u0449\u0435\u043d\u0438\u044f     float NdotL = max(0, dot(normal, u_light_direct));     \/\/ \u0437\u0430\u043a\u0440\u0430\u0441\u043a\u0430 \u043f\u043e \u0444\u043e\u043d\u0433\u0443     const float ka = 0.1, kd = 0.7;     vs_out.color = vec4((ka + NdotL * kd) * cell_color.rgb, cell_color.a);  }  \/\/ corner_point_grid.frag #version 440  \/\/ \u0440\u0435\u0436\u0438\u043c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 layout(location=3) uniform bool u_primitive_picking;   layout(location = 0) in INTERFACE {     vec4 color;     vec2 texcoord; } fs_in;  layout(location=0) out vec4 FragColor;   \/\/ \u0446\u0432\u0435\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430 \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u044f\u0447\u0435\u0435\u043a vec3 border_color(vec2 dist, vec3 color) {     \/\/ \u043d\u0430 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f dist (1 - \u0432\u0435\u0440\u0448\u0438\u043d\u0430, 0 - \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u043f\u043e\u043b\u043e\u0436\u043d\u0430\u044f \u0433\u0440\u0430\u043d\u0438\u0446\u0430)     \/\/ \u043f\u0440\u0438 \u0441\u0434\u0432\u0438\u0433\u0435 \u043d\u0430 \u043e\u0434\u0438\u043d \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u0432 c\u0442\u043e\u0440\u043e\u043d\u0443 \u0433\u0440\u0430\u043d\u0438\u0446\u044b     vec2 delta = fwidth(dist);     \/\/ \u0432\u044b\u0441\u043e\u0442\u0430 \u0442\u0440\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430, \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u043d\u0430\u044f \u043a \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c\u043e\u0439 \u0433\u0440\u0430\u043d\u0438\u0446\u0435     vec2 len = 1.0 \/ delta;      \/\/ \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043e \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u043c\u0435\u043d\u044c\u0448\u0435 \u043f\u0438\u043a\u0441\u0435\u043b\u044f - \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430 \u043d\u0430\u0434\u043e \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0433\u0440\u0430\u043d\u0438\u0446\u0443,     vec2 edge_factor = smoothstep(0.2, 0.8, len * dist);      \/\/ \u0441\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u043c \u0446\u0432\u0435\u0442 \u0441 \u0441\u0435\u0442\u043a\u043e\u0439     return mix(color * 0.25, color, min(edge_factor.x, edge_factor.y)); }  void main() {     if (u_primitive_picking) {         FragColor = fs_in.color;         return;     }      \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0435\u0442\u043a\u0443     vec3 res_color =  border_color(fs_in.texcoord, fs_in.color.rgb);      FragColor = vec4(res_color, fs_in.color.a); }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>\u0418\u0437\u0431\u0430\u0432\u043b\u044f\u0435\u043c\u0441\u044f \u043e\u0442 \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432<\/strong><\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0435\u0449\u0451 \u0440\u0430\u0437 \u043d\u0430 \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0432\u0435\u0440\u0448\u0438\u043d:<\/p>\n<p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432\u0435\u0440\u0448\u0438\u043d\u044b (3*4 \u0431\u0430\u0439\u0442);<\/p>\n<p>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \u043d\u043e\u0440\u043c\u0430\u043b\u044c \u0433\u0440\u0430\u043d\u0438 (3*4 \u0431\u0430\u0439\u0442);<\/p>\n<p>3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u044f\u0447\u0435\u0439\u043a\u0438 (3*4 \u0431\u0430\u0439\u0442);<\/p>\n<p>4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b (2*4 \u0431\u0430\u0439\u0442);<\/p>\n<p>5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0432 \u044f\u0447\u0435\u0439\u043a\u0435 (4 \u0431\u0430\u0439\u0442\u0430).<\/p>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u044b \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b\u0438, \u0447\u0442\u043e \u00ab\u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0441\u0442\u044c\u00bb \u0441\u0442\u043e\u0438\u0442 \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439 \u043a \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440\u0443. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u0440\u0430\u0442\u0438\u043c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u043d\u043e\u0440\u043c\u0430\u043b\u0438 \u0433\u0440\u0430\u043d\u0435\u0439. \u041d\u0430\u043c \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043d\u043e\u0440\u043c\u0430\u043b\u044c \u0431\u044b\u043b\u0430 \u0433\u043b\u0430\u0434\u043a\u043e\u0439 \u043f\u043e \u0432\u0441\u0435\u0439 \u0433\u0440\u0430\u043d\u0438 \u2014 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0442\u044c \u00ab\u043f\u043b\u043e\u0441\u043a\u0443\u044e\u00bb \u043d\u043e\u0440\u043c\u0430\u043b\u044c \u0432 \u0448\u0435\u0439\u0434\u0435\u0440\u0435, \u0430 \u043e\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u043d\u043e\u0440\u043c\u0430\u043b\u0438 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f, \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0432 12 \u0431\u0430\u0439\u0442 \u043d\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u0432\u0435\u0440\u0448\u0438\u043d\u0443.<\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u0434\u0430\u043b\u0438\u043c \u0432\u0441\u0435 \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u0439 \u0438\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0432\u0435\u0440\u0448\u0438\u043d:<\/p>\n<pre><code class=\"cpp\">void CornerPointGrid::_gen_vertices_and_indices(size_t quad_count) {      const size_t vertex_count = quad_count * 4;      \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ std::vector&lt;float&gt; a_position, a_index, a_property, a_normal, a_texcoord;     std::vector&lt;float&gt; a_position, a_index, a_property, a_texcoord;     \/\/ \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b 3 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b (x, y \u0438 z)     a_position.reserve(3 * vertex_count);     \/\/ + \u0442\u0440\u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u0430     a_index.reserve(3 * vertex_count);     \/\/ + \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u044f\u0447\u0435\u0439\u043a\u0438     a_property.reserve(vertex_count);     \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ + \u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043d\u043e\u0440\u043c\u0430\u043b\u0438     \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ a_normal.reserve(3 * vertex_count);     \/\/ + \u0434\u0432\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b (\u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0442 \u0432\u0435\u0440\u0448\u0438\u043d \u0434\u043e \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u043b\u0435\u0436\u0430\u0449\u0438\u0445 \u0441\u0442\u043e\u0440\u043e\u043d)     a_texcoord.reserve(2 * vertex_count);      \/\/ \u2026      \/\/ \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c, \u043d\u0443\u0436\u043d\u043e \u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0433\u0440\u0430\u043d\u044c     if (!check_if_quad_culled(_mask, _joined_mask, i, j, k, qi)){          \/\/ 4 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0432\u0435\u0440\u0448\u0438\u043d \u0433\u0440\u0430\u043d\u0438         const std::array&lt;uint32_t, 4&gt;&amp; quad = cell_quads[qi];          \/\/ \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043d\u043e\u0440\u043c\u0430\u043b\u044c \u0433\u0440\u0430\u043d\u0438         \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ vec3 normal = calc_normal(         \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/             cell_vertices[quad[0]] - cell_vertices[quad[1]],         \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/             cell_vertices[quad[2]] - cell_vertices[quad[1]]);          \/\/ \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0432 \u043f\u043e\u043b\u0438\u0433\u043e\u043d\u0435         for (int vii = 0; vii &lt; 4; ++vii){              \/\/ \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b             const vec3&amp; v = cell_vertices[quad[vii]];              \/\/ \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432\u0435\u0440\u0448\u0438\u043d\u044b             a_position.insert(a_position.end(), {v.x, v.y, v.z});             a_index.insert(a_index.end(), {(float)i, (float)j, (float)k});             a_property.push_back(_property.at(i, j, k));             \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ a_normal.insert(a_normal.end(), {normal.x, normal.y, normal.z});             vec2 texcoords = quad_vertices_texcoords[vii];             a_texcoord.insert(a_texcoord.end(), {texcoords.x, texcoords.y});         }      \/\/ \u2026      \/\/ \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 VBO     glNamedBufferStorage(_position_vbo,   a_position.size() * sizeof (float),   a_position.data(),  gl::GL_NONE_BIT);     \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ glNamedBufferStorage(_normal_vbo,     a_normal.size() * sizeof (float),     a_normal.data(),    gl::GL_NONE_BIT);     glNamedBufferStorage(_cell_index_vbo, a_index.size() * sizeof (float),      a_index.data(),     gl::GL_NONE_BIT);     glNamedBufferStorage(_texcoord_vbo,   a_texcoord.size() * sizeof (float),   a_texcoord.data(),  gl::GL_NONE_BIT);     glNamedBufferStorage(_property_vbo,   a_property.size() * sizeof (float),   a_property.data(),  gl::GL_NONE_BIT);<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u0438\u0437\u0431\u0430\u0432\u0438\u043c\u0441\u044f \u043e\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 (\u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0441\u0434\u0432\u0438\u043d\u0443\u0442\u044c \u043d\u043e\u043c\u0435\u0440\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432):<\/p>\n<pre><code class=\"cpp\">void CornerPointGrid::_setup_vao() {     \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c VAO     glCreateVertexArrays(1, &amp;_vao);     \/\/ \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u043d\u044b\u0439 \u0431\u0443\u0444\u0435\u0440 \u0432 VAO     glVertexArrayElementBuffer(_vao, _indexbuffer);      \/\/ \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 VAO     \/\/ position     glVertexArrayVertexBuffer(_vao, 0, _position_vbo, 0, sizeof (float) * 3);     glVertexArrayAttribBinding(_vao, 0, 0);     glVertexArrayAttribFormat(_vao, 0, 3, GL_FLOAT, GL_FALSE, 0);     glEnableVertexArrayAttrib(_vao, 0);      \/\/ normal     \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ glVertexArrayVertexBuffer(_vao, 1, _normal_vbo, 0, sizeof (float) * 3);     \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ glVertexArrayAttribBinding(_vao, 1, 1);     \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ glVertexArrayAttribFormat(_vao, 1, 3, GL_FLOAT, GL_FALSE, 0);     \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ glEnableVertexArrayAttrib(_vao, 1);      \/\/ cell index     glVertexArrayVertexBuffer(_vao, 1, _cell_index_vbo, 0, sizeof (float) * 3);     glVertexArrayAttribBinding(_vao, 1, 1);     glVertexArrayAttribFormat(_vao, 1, 3, GL_FLOAT, GL_FALSE, 0);     glEnableVertexArrayAttrib(_vao, 1);      \/\/ texcoord     glVertexArrayVertexBuffer(_vao, 2, _texcoord_vbo, 0, sizeof (float) * 2);     glVertexArrayAttribBinding(_vao, 2, 2);     glVertexArrayAttribFormat(_vao, 2, 2, GL_FLOAT, GL_FALSE, 0);     glEnableVertexArrayAttrib(_vao, 2);      \/\/ property     glVertexArrayVertexBuffer(_vao, 3, _property_vbo, 0, sizeof (float));     glVertexArrayAttribBinding(_vao, 3, 3);     glVertexArrayAttribFormat(_vao, 3, 1, GL_FLOAT, GL_FALSE, 0);     glEnableVertexArrayAttrib(_vao, 3);          \/\/...<\/code><\/pre>\n<p>\u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u044b. \u0412 \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u043e\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u0435 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0438\u0445 \u0432\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440:<\/p>\n<pre><code class=\"cpp\">\/\/ \u2026  \/\/ \u043c\u0430\u0442\u0440\u0438\u0446\u044b MVP-\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f layout(location=0) uniform mat4 u_mvp; \/\/ \u043c\u0430\u0442\u0440\u0438\u0446\u0430 \u043c\u043e\u0434\u0435\u043b\u0438 (\u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u043d\u043e\u0440\u043c\u0430\u043b\u0438) layout(location=1) uniform mat4 u_model; \/\/ \u2026   layout(location=0) out INTERFACE {     \/\/ \u0446\u0432\u0435\u0442 \u0432\u0435\u0440\u0448\u0438\u043d\u044b     vec4 color;     \/\/ \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u044f\u0447\u0435\u0439\u043a\u0438 \u0432 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 (\u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u0438)     vec3 model_pos;     \/\/ \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b     vec2 texcoord; } vs_out;  void main() {      \/\/ \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043c mvp-\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u0438     vec4 pos = vec4(a_pos, 1);     gl_Position = u_mvp * pos;      \/\/ \u0435\u0441\u043b\u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0438\u043a\u0438\u043d\u0433 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u044f\u0447\u0435\u0435\u043a, \u0432\u043c\u0435\u0441\u0442\u043e \u0446\u0432\u0435\u0442\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0432\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u044f\u0447\u0435\u0439\u043a\u0438     if (u_primitive_picking) {         vs_out.color = vec4(a_ind.x, a_ind.y, a_ind.z, 1);         return;     }      \/\/ \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u044f\u0447\u0435\u0439\u043a\u0438 (\u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u0438)     vs_out.model_pos = vec3(u_model * pos);      \/\/ \u2026 }<\/code><\/pre>\n<p>\u0412\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u043e\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u0435 \u0432\u043e\u0437\u044c\u043c\u0451\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438 \u0440\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0438\u0445 \u044d\u043a\u0440\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u0438 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043d\u043e\u0440\u043c\u0430\u043b\u044c \u043a\u0430\u043a \u0432\u0435\u043a\u0442\u043e\u0440\u043d\u043e\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"cpp\">\/\/ \u2026  layout(location = 0) in INTERFACE {     vec4 cell_color;     vec3 model_pos;     vec2 texcoord; } fs_in;  \/\/ \u2026  void main() {     if (u_primitive_picking) {         FragColor = fs_in.cell_color;         return;     }      vec3 normal = normalize(cross(dFdy(fs_in.model_pos), dFdx(fs_in.model_pos)));     \/\/ \u2026 }<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0432\u0441\u0451 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u043c\u044b \u043d\u0435 \u0443\u0432\u0438\u0434\u0438\u043c \u043e\u0441\u043e\u0431\u043e\u0439 \u0440\u0430\u0437\u043d\u0438\u0446\u044b \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0435\u0442\u043a\u0435. \u041d\u043e \u043d\u0430 \u0441\u0435\u0442\u043a\u0430\u0445 \u0441 \u043d\u0435\u043f\u043b\u0430\u043d\u0430\u0440\u043d\u044b\u043c\u0438 \u0433\u0440\u0430\u043d\u044f\u043c\u0438 \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u0441\u0442\u0430\u043d\u0435\u0442 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e\u0439:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ead\/2b7\/5fc\/ead2b75fcbc91902f8c7d6507f4279aa.png\" width=\"976\" height=\"480\"><figcaption><\/figcaption><\/figure>\n<p><em>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 1 \u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043f\u043b\u043e\u0441\u043a\u0438\u0445 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u0439, \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u0445 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u043c, \u0438 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u0439 \u0433\u0440\u0430\u043d\u0438, \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u0445 \u0432\u0435\u0440\u0448\u0438\u043d<\/em><\/p>\n<p>\u041d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0442\u043a\u0430\u0445 \u043c\u0435\u0441\u0442\u043e\u0440\u043e\u0436\u0434\u0435\u043d\u0438\u0439 \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043d\u0435 \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043c\u0435\u0442\u043d\u0430, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u0431\u044b\u0447\u043d\u043e \u0433\u0440\u0430\u043d\u0438 \u044f\u0447\u0435\u0435\u043a \u0431\u043e\u043b\u0435\u0435-\u043c\u0435\u043d\u0435\u0435 \u043f\u043b\u0430\u043d\u0430\u0440\u043d\u044b.<\/p>\n<p>\u0427\u0442\u043e \u0436\u0435 \u0441 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u0438?&nbsp;<\/p>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<\/td>\n<td>\n<p>\u041f\u0430\u043c\u044f\u0442\u044c \u043f\u043e\u0434 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b<\/p>\n<\/td>\n<td>\n<p>FPS \u0432 \u043b\u0443\u0447\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435<\/p>\n<\/td>\n<td>\n<p>FPS \u0432 \u0445\u0443\u0434\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0414\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439<\/p>\n<\/td>\n<td>\n<p>2&nbsp;484,29 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>54,3<\/p>\n<\/td>\n<td>\n<p>17,7<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0411\u0435\u0437 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u0439<\/p>\n<\/td>\n<td>\n<p>1&nbsp;932,23 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>60,8<\/p>\n<\/td>\n<td>\n<p>18,4<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><em>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 1 \u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0441\u0435\u0442\u043a\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 200<sup>3<\/sup> c 50% \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u044f\u0447\u0435\u0435\u043a \u043d\u0430 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0435 AMD RX580 8GB<\/em><\/p>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u043c, \u043e\u0431\u044a\u0451\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u0435\u043c\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u043b\u0441\u044f, \u0430 \u0447\u0430\u0441\u0442\u043e\u0442\u0430 \u043a\u0430\u0434\u0440\u043e\u0432 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u043b\u0430\u0441\u044c \u0434\u0430\u0436\u0435 \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043e\u0441\u0432\u0435\u0449\u0435\u043d\u0438\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u043e\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u0435.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432\u0435\u0440\u0448\u0438\u043d\u044b (3*4 \u0431\u0430\u0439\u0442);<\/p>\n<p>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u044f\u0447\u0435\u0439\u043a\u0438 (3*4 \u0431\u0430\u0439\u0442);<\/p>\n<p>3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b (2*4 \u0431\u0430\u0439\u0442);<\/p>\n<p>4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0432 \u044f\u0447\u0435\u0439\u043a\u0435 (4 \u0431\u0430\u0439\u0442\u0430).<\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u043c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442. \u041a\u0430\u0436\u0434\u0430\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043e\u0434\u043d\u043e \u0438\u0437 \u0434\u0432\u0443\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439: 0 \u0438\u043b\u0438 1. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0446\u0435\u043b\u044b\u0445 \u0432\u043e\u0441\u0435\u043c\u044c \u0431\u0430\u0439\u0442 \u0440\u0430\u0434\u0438 \u0434\u0432\u0443\u0445 \u0431\u0438\u0442 \u2014 \u0440\u0430\u0441\u0442\u043e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u0442\u0430\u043a \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043d\u0430 <s>\u0440\u0430\u0441\u0441\u0442\u0440\u0435\u043b<\/s> \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e.<\/p>\n<p>\u041a\u0443\u0434\u0430 \u0436\u0435 \u0437\u0430\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u0434\u0432\u0430 \u0431\u0438\u0442\u0430? \u041d\u0430\u0438\u043b\u0443\u0447\u0448\u0438\u043c \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u044f\u0447\u0435\u0439\u043a\u0438: \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b \u2014 \u0442\u0430\u043a \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u0431\u0438\u0442\u0443 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u043e\u0439 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432 \u0438\u0445 \u0437\u043d\u0430\u043a\u0438 \u0431\u0435\u0437 \u043f\u043e\u0442\u0435\u0440\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438.<\/p>\n<p>\u041a\u0430\u043a \u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u043d\u043e\u0440\u043c\u0430\u043b\u044f\u043c\u0438, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u0434\u0430\u043b\u0438\u043c \u0438\u0437 \u043c\u0435\u0442\u043e\u0434\u0430 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0432\u0435\u0440\u0448\u0438\u043d \u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \u0432\u0441\u0435 \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442:<\/p>\n<pre><code class=\"cpp\">\/\/ \u2026 \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ std::vector&lt;float&gt; a_position, a_index, a_property, a_texcoord; std::vector&lt;float&gt; a_position, a_index, a_property; \/\/ \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b 3 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b (x, y \u0438 z) a_position.reserve(3 * vertex_count); \/\/ + \u0442\u0440\u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 a_index.reserve(3 * vertex_count); \/\/ + \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u044f\u0447\u0435\u0439\u043a\u0438 a_property.reserve(vertex_count); \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ + \u0434\u0432\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b (\u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0442 \u0432\u0435\u0440\u0448\u0438\u043d \u0434\u043e \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u043b\u0435\u0436\u0430\u0449\u0438\u0445 \u0441\u0442\u043e\u0440\u043e\u043d) \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ a_texcoord.reserve(2 * vertex_count);  \/\/ \u2026  \/\/ \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 VBO glNamedBufferStorage(_position_vbo,   a_position.size() * sizeof (float),  a_position.data(), gl::GL_NONE_BIT); glNamedBufferStorage(_cell_index_vbo, a_index.size() * sizeof (float),     a_index.data(),    gl::GL_NONE_BIT); \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/glNamedBufferStorage(_texcoord_vbo,   a_texcoord.size() * sizeof (float),  a_texcoord.data(), gl::GL_NONE_BIT); glNamedBufferStorage(_property_vbo,   a_property.size() * sizeof (float),  a_property.data(), gl::GL_NONE_BIT);  \/\/ \u2026  \/\/ cell index glVertexArrayVertexBuffer(_vao, 1, _cell_index_vbo, 0, sizeof (float) * 3); glVertexArrayAttribBinding(_vao, 1, 1); glVertexArrayAttribFormat(_vao, 1, 3, GL_FLOAT, GL_FALSE, 0); glEnableVertexArrayAttrib(_vao, 1);  \/\/ texcoord \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/glVertexArrayVertexBuffer(_vao, 2, _texcoord_vbo, 0, sizeof (float) * 2); \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/glVertexArrayAttribBinding(_vao, 2, 2); \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/glVertexArrayAttribFormat(_vao, 2, 2, GL_FLOAT, GL_FALSE, 0); \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/glEnableVertexArrayAttrib(_vao, 2);  \/\/ property glVertexArrayVertexBuffer(_vao, 2, _property_vbo, 0, sizeof (float)); glVertexArrayAttribBinding(_vao, 2, 2); glVertexArrayAttribFormat(_vao, 2, 1, GL_FLOAT, GL_FALSE, 0); glEnableVertexArrayAttrib(_vao, 2);<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u044b \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u2014 \u0442\u0430\u043c, \u0433\u0434\u0435 \u0431\u044b\u043b 0, \u0437\u0430\u043f\u0438\u0448\u0435\u043c -1:<\/p>\n<pre><code class=\"cpp\">\/\/ \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0442\u043a\u0443 \u043d\u0430 \u0433\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u044f\u0447\u0435\u0435\u043a, \/\/ \u043d\u0430\u0434\u043e \u0437\u043d\u0430\u0442\u044c \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u043b\u0438\u0437\u043a\u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u043a \u0433\u0440\u0430\u043d\u0438\u0446\u0435. \/\/ \u0422\u0443\u0442 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u044b \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0433\u0440\u0430\u043d\u0438, \/\/ \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043e \u0433\u0440\u0430\u043d\u0438\u0446\u044b \/\/ (\u0435\u0441\u043b\u0438 \u043e\u0434\u0438\u043d \u0438\u0437 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0440\u0430\u0432\u0435\u043d \u043d\u0443\u043b\u044e, \u0442\u043e \u044d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c \u0433\u0440\u0430\u043d\u0438\u0446\u0430). static const std::array&lt;vec2, 4&gt; quad_vertices_texcoords = {     vec2( 1, -1),     vec2(-1, -1),     vec2(-1,  1),     vec2(-1, -1), };<\/code><\/pre>\n<p>\u0418 \u0443\u043c\u043d\u043e\u0436\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0435 \u0434\u0432\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u044f\u0447\u0435\u0439\u043a\u0438 \u043d\u0430 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u2014 \u0442\u0430\u043a \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">\/\/ \u2026  \/\/ \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432\u0435\u0440\u0448\u0438\u043d\u044b a_position.insert(a_position.end(), {v.x, v.y, v.z}); \/\/ \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432 \u0437\u043d\u0430\u043a\u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u044f\u0447\u0435\u0439\u043a\u0438. a_index.insert(a_index.end(), { i * texcoords[0],                                 j * texcoords[1],                                 k }); \/\/ \u2026<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0432 \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u043e\u043c \u0448\u0435\u0439\u0434\u0435\u0440\u0435 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432, \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u0437\u044f\u0432 \u043c\u043e\u0434\u0443\u043b\u044c, \u0430 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 sign():<\/p>\n<pre><code class=\"cpp\">\/\/ \u2026  \/\/ \u0435\u0441\u043b\u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0438\u043a\u0438\u043d\u0433 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u044f\u0447\u0435\u0435\u043a, \u0432\u043c\u0435\u0441\u0442\u043e \u0446\u0432\u0435\u0442\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0432\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u044f\u0447\u0435\u0439\u043a\u0438 if (u_primitive_picking) {     vs_out.color = vec4(abs(a_ind.x), abs(a_ind.y), a_ind.z, 1);     return; }  \/\/ \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u044f\u0447\u0435\u0439\u043a\u0438 (\u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u0438) vs_out.model_pos = vec3(u_model * pos);  \/\/ \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 vs_out.texcoord = vec2(max(vec2(0), sign(a_ind.xy)));<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0438 \u0437\u0430\u043c\u0435\u0440\u044f\u0435\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c:<\/p>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<\/td>\n<td>\n<p>\u041f\u0430\u043c\u044f\u0442\u044c \u043f\u043e\u0434 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b<\/p>\n<\/td>\n<td>\n<p>FPS \u0432 \u043b\u0443\u0447\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435<\/p>\n<\/td>\n<td>\n<p>FPS \u0432 \u0445\u0443\u0434\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0414\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439<\/p>\n<\/td>\n<td>\n<p>2&nbsp;484,29 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>54,3<\/p>\n<\/td>\n<td>\n<p>17,7<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0411\u0435\u0437 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u0439<\/p>\n<\/td>\n<td>\n<p>1&nbsp;932,23 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>60,8<\/p>\n<\/td>\n<td>\n<p>18,4<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0411\u0435\u0437 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 <\/p>\n<\/td>\n<td>\n<p>1&nbsp;564,18 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>65,8<\/p>\n<\/td>\n<td>\n<p>19,0<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><em>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 2 \u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043d\u0430 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0435 AMD RX580 8GB<\/em><\/p>\n<p>\u041a\u0430\u043a \u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u043d\u043e\u0440\u043c\u0430\u043b\u044f\u043c\u0438, \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438 \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u043b\u043e\u0441\u044c, \u0430 \u0447\u0430\u0441\u0442\u043e\u0442\u0430 \u043a\u0430\u0434\u0440\u043e\u0432 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u043b\u0430\u0441\u044c.<\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u044f\u0447\u0435\u0439\u043a\u0438, \u0435\u0441\u043b\u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438\u0445 \u043d\u0435 \u0432\u043e float, \u0430 \u0432 int16 \u2013 \u0441\u0435\u0442\u043a\u0438 \u0441 \u0447\u0438\u0441\u043b\u043e\u043c \u044f\u0447\u0435\u0435\u043a \u0431\u043e\u043b\u0435\u0435 32767 \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u0435\u0439 \u043d\u0430\u043c \u043d\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u043b\u0438\u0441\u044c, \u043d\u0435 \u0433\u043e\u0432\u043e\u0440\u044f \u0443\u0436 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0441\u0435\u0442\u043a\u0438 \u043d\u0435 \u043f\u0435\u0440\u0435\u0432\u0430\u0440\u0438\u0442 \u043d\u0438 \u043e\u0434\u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0430\u044f \u0441\u0442\u0430\u043d\u0446\u0438\u044f.<\/p>\n<p>\u041c\u0435\u043d\u044f\u0435\u043c \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u043d\u0430 int16 (\u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0441\u0434\u0432\u0438\u043d\u0443\u0442\u044c \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u043d\u0430 1, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u0442\u044c \u0437\u043d\u0430\u043a \u0432 \u043d\u0443\u043b\u0435):<\/p>\n<pre><code class=\"cpp\">\/\/ \u2026 \/\/ \u0423\u0414\u0410\u041b\u0415\u041d\u041e \/\/ std::vector&lt;float&gt; a_position, a_index, a_property; std::vector&lt;float&gt; a_position, a_property; std::vector&lt;int16_t&gt; a_index;  \/\/ \u2026  \/\/ \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432\u0435\u0440\u0448\u0438\u043d\u044b a_position.insert(a_position.end(), {v.x, v.y, v.z}); \/\/ \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432 \u0437\u043d\u0430\u043a\u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u044f\u0447\u0435\u0439\u043a\u0438. \/\/ \u043f\u0440\u0438\u0431\u0430\u0432\u0438\u043c 1 \u043a \u0438\u043d\u0434\u0435\u043a\u0441\u0443, \u0447\u0442\u043e\u0431\u044b \u0437\u043d\u0430\u043a \u043d\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u043b\u0441\u044f \u0432 \u043d\u0443\u043b\u0435 a_index.insert(a_index.end(), {static_cast&lt;int16_t&gt;((i+1) * texcoords[0]),                                static_cast&lt;int16_t&gt;((j+1) * texcoords[1]),                                static_cast&lt;int16_t&gt;(k) });  \/\/ \u2026  \/\/ \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 VBO glNamedBufferStorage(_position_vbo,    a_position.size() * sizeof (float), a_position.data(), gl::GL_NONE_BIT); glNamedBufferStorage(_cell_index_vbo, a_index.size() * sizeof (int16_t),  a_index.data(),    gl::GL_NONE_BIT); glNamedBufferStorage(_property_vbo,   a_property.size() * sizeof (float), a_property.data(), gl::GL_NONE_BIT);  \/\/ \u2026  \/\/ \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 VAO \/\/ position glVertexArrayVertexBuffer(_vao, 0, _position_vbo, 0, sizeof (float) * 3); glVertexArrayAttribBinding(_vao, 0, 0); glVertexArrayAttribFormat(_vao, 0, 3, GL_FLOAT, GL_FALSE, 0); glEnableVertexArrayAttrib(_vao, 0);  \/\/ cell index glVertexArrayVertexBuffer(_vao, 1, _cell_index_vbo, 0, sizeof (int16_t) * 3); glVertexArrayAttribBinding(_vao, 1, 1); glVertexArrayAttribFormat(_vao, 1, 3, GL_SHORT, GL_FALSE, 0); glEnableVertexArrayAttrib(_vao, 1);<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c, \u0438\u2026<\/p>\n<p>\u0412\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440 \u043d\u0435\u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u043b\u0430\u0433\u0430\u0435\u0442 \u2014 \u0431\u043e\u043b\u0435\u0435 200 \u043c\u0441 \u043d\u0430 \u043a\u0430\u0434\u0440. \u041a\u0430\u043a \u0436\u0435 \u0442\u0430\u043a?<\/p>\n<p>\u0412\u0441\u0435 \u0434\u0435\u043b\u043e \u0432 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438. \u0411\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442 \u0442\u0440\u0435\u0431\u0443\u044e\u0442, \u0447\u0442\u043e\u0431\u044b \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0431\u044b\u043b \u0432\u044b\u0440\u0430\u0432\u043d\u0435\u043d \u043f\u043e 32 \u0431\u0438\u0442\u0430\u043c. \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043d\u0430\u0448 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441 \u0442\u0440\u0435\u043c\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u0438\u0437 int16 \u0432\u044b\u0440\u043e\u0432\u043d\u0435\u043d \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u043f\u043e 16 \u0431\u0438\u0442\u0430\u043c, \u0447\u0442\u043e \u0438 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043d\u0435\u0430\u0434\u0435\u043a\u0432\u0430\u0442\u043d\u043e\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438. \u0420\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043f\u0440\u043e\u0441\u0442\u043e \u2014 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0451 \u043e\u0434\u043d\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0443 \u0434\u043b\u044f \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"cpp\">\/\/ \u2026  std::vector&lt;float&gt; a_position, a_property; std::vector&lt;int16_t&gt; a_index; \/\/ \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b 3 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b (x, y \u0438 z) a_position.reserve(3 * vertex_count); \/\/ + \u0442\u0440\u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 (\u0441 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435\u043c) a_index.reserve(4 * vertex_count); \/\/ \u2026  \/\/ \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432\u0435\u0440\u0448\u0438\u043d\u044b a_position.insert(a_position.end(), {v.x, v.y, v.z}); \/\/ \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432 \u0437\u043d\u0430\u043a\u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u044f\u0447\u0435\u0439\u043a\u0438. \/\/ \u043f\u0440\u0438\u0431\u0430\u0432\u0438\u043c 1 \u043a \u0438\u043d\u0434\u0435\u043a\u0441\u0443, \u0447\u0442\u043e\u0431\u044b \u0437\u043d\u0430\u043a \u043d\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u043b\u0441\u044f \u0432 \u043d\u0443\u043b\u0435 a_index.insert(a_index.end(), {static_cast&lt;int16_t&gt;((i+1) * texcoords[0]),                                static_cast&lt;int16_t&gt;((j+1) * texcoords[1]),                                static_cast&lt;int16_t&gt;(k),                                0});  \/\/ \u2026  \/\/ \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 VAO \/\/ position glVertexArrayVertexBuffer(_vao, 0, _position_vbo, 0, sizeof (float) * 3); glVertexArrayAttribBinding(_vao, 0, 0); glVertexArrayAttribFormat(_vao, 0, 3, GL_FLOAT, GL_FALSE, 0); glEnableVertexArrayAttrib(_vao, 0);  \/\/ cell index glVertexArrayVertexBuffer(_vao, 1, _cell_index_vbo, 0, sizeof (int16_t) * 4); glVertexArrayAttribBinding(_vao, 1, 1); glVertexArrayAttribFormat(_vao, 1, 4, GL_SHORT, GL_FALSE, 0); glEnableVertexArrayAttrib(_vao, 1);  \/\/\u2026  \/\/ \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440: #version 440  \/\/ \u043f\u043e\u0437\u0438\u0446\u0438\u044f layout(location=0) in vec3 a_pos; \/\/ \u0438\u043d\u0434\u0435\u043a\u0441 \u044f\u0447\u0435\u0439\u043a\u0438 layout(location=1) in ivec4 a_ind;  \/\/\u2026<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u0444\u0438\u043a\u0441 \u0432\u0435\u0440\u043d\u0443\u043b \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0439:<\/p>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<\/td>\n<td>\n<p>\u041f\u0430\u043c\u044f\u0442\u044c \u043f\u043e\u0434 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b<\/p>\n<\/td>\n<td>\n<p>FPS \u0432 \u043b\u0443\u0447\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435<\/p>\n<\/td>\n<td>\n<p>FPS \u0432 \u0445\u0443\u0434\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0414\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439<\/p>\n<\/td>\n<td>\n<p>2&nbsp;484,29 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>54,3<\/p>\n<\/td>\n<td>\n<p>17,7<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0411\u0435\u0437 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u0439<\/p>\n<\/td>\n<td>\n<p>1&nbsp;932,23 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>60,8<\/p>\n<\/td>\n<td>\n<p>18,4<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0411\u0435\u0437 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 <\/p>\n<\/td>\n<td>\n<p>1&nbsp;564,18 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>65,8<\/p>\n<\/td>\n<td>\n<p>19,0<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>16-\u0431\u0438\u0442\u043d\u044b\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u044b<\/p>\n<\/td>\n<td>\n<p>1&nbsp;380,16 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>70,4<\/p>\n<\/td>\n<td>\n<p>19,3<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><em>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 3 \u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043d\u0430 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0435 AMD RX580 8GB<\/em><\/p>\n<p>\u041e\u0431\u044a\u0451\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u0435\u043c\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u0435\u0449\u0451 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u043b\u0441\u044f, \u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u043b\u0430\u0441\u044c.<\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0432\u0441\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u0438 \u0438\u0445 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432\u0435\u0440\u0448\u0438\u043d\u044b (3*4 \u0431\u0430\u0439\u0442);<\/p>\n<p>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u044f\u0447\u0435\u0439\u043a\u0438 * \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b (4*2 \u0431\u0430\u0439\u0442);<\/p>\n<p>3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0432 \u044f\u0447\u0435\u0439\u043a\u0435 (4 \u0431\u0430\u0439\u0442\u0430).<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043a\u0430\u0436\u0434\u0430\u044f \u0432\u0435\u0440\u0448\u0438\u043d\u0430 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 \u043d\u0435 48 \u0431\u0430\u0439\u0442, \u0430 24 \u0431\u0430\u0439\u0442\u0430 \u2013 \u0432 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430 \u043c\u0435\u043d\u044c\u0448\u0435! \u041e\u0431\u0449\u0438\u0439 \u043e\u0431\u044a\u0451\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u0435\u043c\u043e\u0439 \u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u0438 \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u043b\u0441\u044f \u0432 1,8 \u0440\u0430\u0437\u0430.<\/p>\n<p><strong>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 \u0445\u0443\u0434\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435<\/strong><\/p>\n<p>\u0412 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445 \u0441\u0432\u0435\u0440\u0445\u0443 \u043c\u044b \u0443\u0436\u0435 \u0432\u0438\u0434\u0435\u043b\u0438 \u043a\u043e\u043b\u043e\u043d\u043a\u0443 \u00abFPS \u0432 \u0445\u0443\u0434\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435\u00bb. \u0427\u0442\u043e \u0436\u0435 \u044d\u0442\u043e \u0437\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u0432\u0441\u0451 \u0442\u0430\u043a \u043f\u043b\u043e\u0445\u043e?<\/p>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u044d\u0442\u043e\u0442 \u00ab\u0445\u0443\u0434\u0448\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439\u00bb, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043a\u0430\u043c\u0435\u0440\u0443 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0441\u0435\u0442\u043a\u0443 \u0441 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b. \u0427\u0430\u0441\u0442\u043e\u0442\u0430 \u043a\u0430\u0434\u0440\u043e\u0432 \u0441\u0440\u0430\u0437\u0443 \u043f\u0430\u0434\u0430\u0435\u0442 \u0432 3 \u0440\u0430\u0437\u0430, \u0447\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0441\u0438\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u0434\u0440\u0430\u0436\u0430\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p>\u041f\u0440\u0438\u0447\u0438\u043d\u0430 \u0442\u0430\u043a\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0430\u0434\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u0440\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u0412\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u044b \u043e\u0431\u044f\u0437\u0430\u043d\u044b \u0440\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e (\u0438\u043b\u0438 \u0442\u0430\u043a, \u0447\u0442\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u0435\u043d \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c\u0443) \u2014 \u044d\u0442\u043e \u0432\u0430\u0436\u043d\u043e \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u0438 \u0431\u043b\u0435\u043d\u0434\u0438\u043d\u0433\u0430. \u041a \u0442\u043e\u043c\u0443 \u0436\u0435, \u0447\u0438\u0441\u043b\u043e \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u0432 \u0441\u0435\u0442\u043a\u0435 \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u043b\u0438\u043a\u043e, \u0447\u0442\u043e \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0438\u0445 \u0432\u0441\u0435 \u0440\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0440\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u043b\u0438\u044f\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0431\u043b\u0435\u043d\u0434\u0438\u043d\u0433, \u043d\u043e \u0438 \u0431\u044b\u0441\u0442\u0440\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043f\u0440\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435 \u0441 \u0432\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u044b\u043c \u0442\u0435\u0441\u0442\u043e\u043c \u0433\u043b\u0443\u0431\u0438\u043d\u044b. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/70a\/adf\/bfc\/70aadfbfcdddca82a1de344cfa5d6f10.png\" width=\"1000\" height=\"587\"><figcaption><\/figcaption><\/figure>\n<p><em>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 2. \u041f\u0435\u0440\u0435\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438<\/em><\/p>\n<p>\u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043a\u0430\u043c\u0435\u0440\u044b \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0432\u0430\u044e\u0442 \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0430.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043a\u0430\u043c\u0435\u0440\u044b \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u044f\u0442\u0441\u044f \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043e\u0442 \u0434\u0430\u043b\u044c\u043d\u0435\u0433\u043e \u043a \u0431\u043b\u0438\u0436\u043d\u0435\u043c\u0443, \u0442\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u043f\u0440\u043e\u0439\u0434\u0451\u0442 \u0442\u0435\u0441\u0442 \u0433\u043b\u0443\u0431\u0438\u043d\u044b, \u0438 \u0432\u0441\u0435 \u0435\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u0438 \u0437\u0430\u043f\u0438\u0448\u0443\u0442\u0441\u044f \u0432 \u0444\u0440\u0435\u0439\u043c\u0431\u0443\u0444\u0435\u0440. \u0415\u0441\u043b\u0438 \u0436\u0435 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u044f\u0442\u0441\u044f \u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u2014 \u043e\u0442 \u0431\u043b\u0438\u0436\u043d\u0435\u0433\u043e \u043a \u0434\u0430\u043b\u044c\u043d\u0435\u043c\u0443 \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043a\u0430\u043c\u0435\u0440\u044b, \u0442\u043e \u043f\u0435\u0440\u0432\u044b\u0439 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u043f\u0435\u0440\u0435\u043a\u0440\u043e\u0435\u0442 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0432 \u0431\u0443\u0444\u0435\u0440\u0435 \u0433\u043b\u0443\u0431\u0438\u043d\u044b, \u0430 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u043d\u0435 \u043f\u0440\u043e\u0439\u0434\u0443\u0442 \u0442\u0435\u0441\u0442 \u0433\u043b\u0443\u0431\u0438\u043d\u044b \u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u043f\u0438\u043a\u0441\u0435\u043b\u0438 \u0432 \u0444\u0440\u0435\u0439\u043c\u0431\u0443\u0444\u0435\u0440. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043d\u0430 \u0432\u0441\u0435\u0445 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0430\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f Early Z Rejection, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u0434\u0430\u0436\u0435 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043e\u0432, \u043d\u0435 \u043f\u0440\u043e\u0448\u0435\u0434\u0448\u0438\u0445 \u0442\u0435\u0441\u0442 \u0433\u043b\u0443\u0431\u0438\u043d\u044b.<\/p>\n<p>\u0412\u0435\u0440\u043d\u0451\u043c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440\u0443 \u0438 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u0432 \u043a\u0430\u043a\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043c\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0432\u0435\u0440\u0448\u0438\u043d\u044b:<\/p>\n<pre><code class=\"cpp\">\/\/ \u2026  \/\/ \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438 for (uint32_t i = 0; i &lt; _property.ni; ++i) {     for (uint32_t j = 0; j &lt; _property.nj; ++j) {         for (uint32_t k = 0; k &lt; _property.nk; ++k) {              \/\/ \u0435\u0441\u043b\u0438 \u044f\u0447\u0435\u0439\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c\u0441\u044f (\u043e\u043d\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0443\u044e\u0442\u0441\u044f \u043f\u043e \u043c\u0430\u0441\u043a\u0435)             if (_mask.at(i, j, k)){                 \/\/ \u2026<\/code><\/pre>\n<p>\u0412\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u044f\u0447\u0435\u0435\u043a \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u0438\u0445 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432 \u0442\u0440\u0451\u0445\u043c\u0435\u0440\u043d\u043e\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u0435.<\/p>\n<p>\u042d\u0442\u043e \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0435\u0442, \u043f\u043e\u0447\u0435\u043c\u0443 \u0441 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0441\u0435\u0442\u043a\u0438 \u0447\u0430\u0441\u0442\u043e\u0442\u0430 \u043a\u0430\u0434\u0440\u043e\u0432 \u0432\u044b\u0441\u043e\u043a\u0430\u044f, \u0430 \u0441 \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u043d\u0438\u0437\u043a\u0430\u044f. \u0412\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0441\u0435\u0442\u043a\u0443 \u0441 \u0442\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u0432 \u043a\u0430\u043a\u0443\u044e \u0440\u0430\u0441\u0442\u0443\u0442 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u044f\u0447\u0435\u0435\u043a \u2014 \u0438\u0437-\u0437\u0430 \u044d\u0442\u043e\u0433\u043e \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0433\u0440\u0430\u043d\u044c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0431\u043b\u0438\u0436\u0435 \u043a \u043a\u0430\u043c\u0435\u0440\u0435, \u0447\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f, \u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0442\u0435\u0441\u0442 \u0433\u043b\u0443\u0431\u0438\u043d\u044b.<\/p>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u043e \u2014 \u043d\u0443\u0436\u043d\u043e \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044f\u0447\u0435\u0439\u043a\u0438 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0441 \u043b\u044e\u0431\u043e\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043a\u0430\u043c\u0435\u0440\u044b \u0433\u0440\u0430\u043d\u0438 \u044f\u0447\u0435\u0435\u043a \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u043b\u0438\u0441\u044c \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043e\u0442 \u0431\u043b\u0438\u0436\u043d\u0435\u0439 \u043a \u0434\u0430\u043b\u044c\u043d\u0435\u0439. \u0410 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u043d\u0430\u0448\u0443 \u0441\u0435\u0442\u043a\u0443 \u043a\u0430\u043a \u043b\u0443\u043a\u043e\u0432\u0438\u0446\u0443 \u2014 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u0433\u0440\u0430\u043d\u0438 \u0441\u0430\u043c\u043e\u0433\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0441\u043b\u043e\u044f, \u0437\u0430\u0442\u0435\u043c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u0433\u0440\u0430\u043d\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0441\u043b\u043e\u044f \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435, \u0434\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u0446\u0435\u043d\u0442\u0440\u0430 \u043b\u0443\u043a\u043e\u0432\u0438\u0446\u044b.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0449\u0435 \u0437\u0430\u043a\u043e\u0434\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c, \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0447\u0430\u0441\u0442\u044c \u043a\u043e\u0434\u0430, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0443\u044e \u0437\u0430 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u0433\u0440\u0430\u043d\u0435\u0439 \u043e\u0434\u043d\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438, \u0432 \u043b\u044f\u043c\u0431\u0434\u0443:<\/p>\n<pre><code class=\"cpp\">\/\/ \u2026  \/\/ + \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u044f\u0447\u0435\u0439\u043a\u0438 a_property.reserve(vertex_count);  auto calc_cell = [this, &amp;a_position, &amp;a_index, &amp;a_property](size_t i, size_t j, size_t k) {     \/\/ \u0431\u0443\u0444\u0435\u0440, \u043a\u0443\u0434\u0430 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u044f\u0447\u0435\u0439\u043a\u0438     std::array&lt;vec3, 8&gt; cell_vertices;       \/\/ \u0435\u0441\u043b\u0438 \u044f\u0447\u0435\u0439\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c\u0441\u044f (\u043e\u043d\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0443\u044e\u0442\u0441\u044f \u043f\u043e \u043c\u0430\u0441\u043a\u0435)     if (_mask.at(i, j, k)){         \/\/ \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u0435\u043c 8 \u0432\u0435\u0440\u0448\u0438\u043d, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u044f\u0447\u0435\u0439\u043a\u0435         get_cell_vertices(_coord, _zcorn, i, j, k, cell_vertices);         \/\/ \u2026 };<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0442\u0430\u043a\u043e\u0439, \u0441\u0442\u0440\u0430\u0448\u043d\u044b\u0439 \u043d\u0430 \u0432\u0438\u0434, \u0446\u0438\u043a\u043b:<\/p>\n<pre><code class=\"cpp\">size_t min_dim = std::min({_property.ni, _property.nj, _property.nk}); size_t max_layers = min_dim \/ 2 + 1;  size_t oi = 0, oj = 0, ok = 0; size_t ni = _property.ni, nj = _property.nj, nk = _property.nk;  for (size_t layer = 0; layer &lt; max_layers; ++layer) {      for (size_t k : {ok, nk-1}) {         for (size_t i = oi; i &lt; ni; ++i) {             for (size_t j = oj; j &lt; nj; ++j) {                 calc_cell(i, j, k);             }         }         if (ok &gt;= nk-1) break;     }      for (size_t j : {oj, nj-1}) {         for (size_t i = oi; i &lt; ni; ++i) {             for (size_t k = ok+1; k &lt; nk - 1; ++k) {                 calc_cell(i,j,k);             }         }         if (oj &gt;= nj - 1) break;     }      for (size_t i : {oi, ni-1}) {         for (size_t j = oj+1; j &lt; nj-1; ++j) {             for (size_t k = ok+1; k &lt; nk-1; ++k) {                 calc_cell(i, j ,k);             }         }         if (oi &gt;= ni - 1) break;     }       ++oi; ++oj; ++ok;     --ni; --nj; --nk; }<\/code><\/pre>\n<p>\u041d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0435\u0441\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0445\u043e\u0434\u0438\u0442 \u0442\u0440\u0451\u0445\u043c\u0435\u0440\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0432 \u043b\u0443\u043a\u043e\u0432\u0438\u0447\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u2014 \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043d \u0437\u0430 5 \u043c\u0438\u043d\u0443\u0442. \u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u044d\u0442\u0438\u0445 \u0446\u0438\u043a\u043b\u043e\u0432 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0442. \u043a. \u043a\u0430\u0436\u0434\u0430\u044f \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044f (\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0433\u0440\u0430\u043d\u0435\u0439) \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0440\u043e\u0436\u0435, \u0447\u0435\u043c \u0441\u0430\u043c\u0438 \u0446\u0438\u043a\u043b\u044b.<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440 \u0438 \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0447\u0430\u0441\u0442\u043e\u0442\u0430 \u043a\u0430\u0434\u0440\u043e\u0432 \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f, \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0442\u043e\u0433\u043e, \u0441 \u043a\u0430\u043a\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043c\u044b \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0441\u0435\u0442\u043a\u0443. \u0425\u0443\u0434\u0448\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0442\u0440\u0438 \u0440\u0430\u0437\u0430 \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0447\u0435\u043c \u0434\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438!<\/p>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<\/td>\n<td>\n<p>\u041f\u0430\u043c\u044f\u0442\u044c \u043f\u043e\u0434 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b<\/p>\n<\/td>\n<td>\n<p>FPS \u0432 \u043b\u0443\u0447\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435<\/p>\n<\/td>\n<td>\n<p>FPS \u0432 \u0445\u0443\u0434\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0414\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439<\/p>\n<\/td>\n<td>\n<p>2&nbsp;484,29 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>54,3<\/p>\n<\/td>\n<td>\n<p>17,7<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0411\u0435\u0437 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u0439<\/p>\n<\/td>\n<td>\n<p>1&nbsp;932,23 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>60,8<\/p>\n<\/td>\n<td>\n<p>18,4<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0411\u0435\u0437 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 <\/p>\n<\/td>\n<td>\n<p>1&nbsp;564,18 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>65,8<\/p>\n<\/td>\n<td>\n<p>19,0<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>16-\u0431\u0438\u0442\u043d\u044b\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u044b<\/p>\n<\/td>\n<td>\n<p>1&nbsp;380,16 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>70,4<\/p>\n<\/td>\n<td>\n<p>19,3<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u041b\u0443\u043a\u043e\u0432\u0438\u0447\u043d\u044b\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a<\/p>\n<\/td>\n<td>\n<p>1&nbsp;380,16 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>67,4<\/p>\n<\/td>\n<td>\n<p>64,9<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><em>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 4. \u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043d\u0430 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0435 AMD RX580 8GB<\/em><\/p>\n<p><strong>\u0423\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c \u043f\u0438\u043a\u043e\u0432\u043e\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438<\/strong><\/p>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u044b \u043e\u0431\u0440\u0430\u0442\u0438\u043b\u0438 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0435 \u0431\u0443\u0444\u0435\u0440\u044b \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u043b\u0438\u0448\u044c \u0437\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432 \u0431\u0443\u0444\u0435\u0440\u044b OpenGL. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0432 \u0445\u0443\u0434\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0432\u043e\u0439\u043d\u043e\u0439 \u043e\u0431\u044a\u0451\u043c \u043f\u0430\u043c\u044f\u0442\u0438 \u2014 \u043e\u0434\u043d\u0430 \u043a\u043e\u043f\u0438\u044f \u0432 \u043d\u0430\u0448\u0438\u0445 \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u0445, \u0430 \u0432\u0442\u043e\u0440\u0430\u044f \u043a\u043e\u043f\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c\u0441\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u043c \u043f\u0435\u0440\u0435\u0434 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 \u0432 \u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u044c. <\/p>\n<p>\u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0435\u0449\u0451 \u0432 OpenGL 1.5 \u0431\u044b\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u0431\u0443\u0444\u0435\u0440\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0439 \u0432 \u0430\u0434\u0440\u0435\u0441\u043d\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <a href=\"https:\/\/www.khronos.org\/registry\/OpenGL-Refpages\/gl4\/html\/glMapBuffer.xhtml\">glMapBuffer()<\/a>. \u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0438\u043b\u0438 \u0447\u0438\u0442\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0444\u0435\u0440\u0430 \u00ab\u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e\u00bb. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442, \u044d\u0442\u043e \u043c\u0430\u043b\u043e \u0447\u0435\u043c \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u044c\u044e (\u043e\u0434\u043d\u0430\u043a\u043e, \u0434\u043b\u044f \u0441\u0442\u0430\u0440\u0448\u0438\u0445 \u043f\u043e\u043a\u043e\u043b\u0435\u043d\u0438\u0439 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442 \u044d\u0442\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0442\u0430\u043a). \u0414\u043b\u044f \u0434\u0438\u0441\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0430\u043a\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u044c\u044e \u043e\u0431\u044b\u0447\u043d\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u044b \u0438 \u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0438 \u043d\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d.<\/p>\n<p>\u0418\u0437\u0431\u0430\u0432\u043b\u044f\u0435\u043c\u0441\u044f \u043e\u0442 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0445 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432\u0435\u0440\u0448\u0438\u043d \u043f\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f\u043c, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u0447\u0435\u0440\u0435\u0437 glMapBuffer():<\/p>\n<pre><code class=\"cpp\">void CornerPointGrid::_gen_vertices_and_indices(size_t quad_count) {      const size_t vertex_count = quad_count * 4;      \/\/ \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 VBO     glNamedBufferStorage(_position_vbo,   3 * vertex_count * sizeof (float),   nullptr, gl::GL_MAP_WRITE_BIT);     glNamedBufferStorage(_cell_index_vbo, 4 * vertex_count * sizeof (int16_t), nullptr, gl::GL_MAP_WRITE_BIT);     glNamedBufferStorage(_property_vbo,   vertex_count * sizeof (float),       nullptr, gl::GL_MAP_WRITE_BIT);      auto a_position = reinterpret_cast&lt;float*&gt;(glMapNamedBuffer(_position_vbo,     gl::GL_WRITE_ONLY));     auto a_index    = reinterpret_cast&lt;int16_t*&gt;(glMapNamedBuffer(_cell_index_vbo, gl::GL_WRITE_ONLY));     auto a_property = reinterpret_cast&lt;float*&gt;(glMapNamedBuffer(_property_vbo,     gl::GL_WRITE_ONLY));      \/\/ \u2026      \/\/ \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0432 \u043f\u043e\u043b\u0438\u0433\u043e\u043d\u0435     for (int vii = 0; vii &lt; 4; ++vii){              \/\/ \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b         const vec3&amp; v = cell_vertices[quad[vii]];         ivec2 texcoords = quad_vertices_texcoords[vii];          \/\/ \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432\u0435\u0440\u0448\u0438\u043d\u044b         a_position[0] = v.x;         a_position[1] = v.y;         a_position[2] = v.z;         a_position += 3;         \/\/ \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432 \u0437\u043d\u0430\u043a\u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u044f\u0447\u0435\u0439\u043a\u0438.         \/\/ \u043f\u0440\u0438\u0431\u0430\u0432\u0438\u043c 1 \u043a \u0438\u043d\u0434\u0435\u043a\u0441\u0443, \u0447\u0442\u043e\u0431\u044b \u0437\u043d\u0430\u043a \u043d\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u043b\u0441\u044f \u0432 \u043d\u0443\u043b\u0435         a_index[0] = static_cast&lt;int16_t&gt;((i+1) * texcoords[0]);         a_index[1] = static_cast&lt;int16_t&gt;((j+1) * texcoords[1]);         a_index[2] = static_cast&lt;int16_t&gt;(k);         a_index[3] = 0;         a_index += 4;          a_property[0] = _property.at(i, j, k);         a_property += 1;     }<\/code><\/pre>\n<p>\u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0434\u0435\u043b\u0430\u0435\u043c \u0438 \u0441 \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u043c\u0438:<\/p>\n<pre><code class=\"cpp\">\/\/ \u2026  \/\/ \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 - \u043d\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u0433\u0440\u0430\u043d\u044c \u0434\u0432\u0430 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 size_t indices_count = quad_count * 6; glNamedBufferStorage(_indexbuffer, indices_count * sizeof (uint32_t), nullptr, gl::GL_MAP_WRITE_BIT); auto indices = reinterpret_cast&lt;uint32_t*&gt;(glMapNamedBuffer(_indexbuffer, gl::GL_WRITE_ONLY));  for (size_t i = 0; i &lt; quad_count; ++i)     for (uint32_t j = 0; j &lt; 6; ++j)         \/\/ \u0438\u043d\u0434\u0435\u043a\u0441 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u043f\u0440\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432         *indices++ = static_cast&lt;uint32_t&gt;(i * 4 + quad_to_triangles[j]);  glUnmapNamedBuffer(_indexbuffer); glUnmapNamedBuffer(_position_vbo); glUnmapNamedBuffer(_cell_index_vbo); glUnmapNamedBuffer(_property_vbo);  \/\/ \u2026<\/code><\/pre>\n<p>\u0423\u0431\u0435\u0434\u0438\u0432\u0448\u0438\u0441\u044c, \u0447\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u043d\u0430\u0434\u043e, \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u043f\u0438\u043a\u043e\u0432\u043e\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438:<\/p>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<\/td>\n<td>\n<p>\u041f\u0430\u043c\u044f\u0442\u044c \u043f\u043e\u0434 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b<\/p>\n<\/td>\n<td>\n<p>\u041f\u0430\u043c\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430<\/p>\n<\/td>\n<td>\n<p>\u041f\u0430\u043c\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 (\u043f\u0438\u043a\u043e\u0432\u0430\u044f)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0414\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439<\/p>\n<\/td>\n<td>\n<p>2&nbsp;484,29 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>3&nbsp;258,55 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>5&nbsp;844,64 \u041c\u0431<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0411\u0435\u0437 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u0439<\/p>\n<\/td>\n<td>\n<p>1&nbsp;932,23 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>2&nbsp;704,95 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>4&nbsp;738,06 \u041c\u0431<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>\u0411\u0435\u0437 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 <\/p>\n<\/td>\n<td>\n<p>1&nbsp;564,18 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>2&nbsp;336,84 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>4&nbsp;000,90 \u041c\u0431<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>16-\u0431\u0438\u0442\u043d\u044b\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u044b<\/p>\n<\/td>\n<td>\n<p>1&nbsp;380,16 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>2&nbsp;151,87 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>3&nbsp;631,87 \u041c\u0431<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>glMapBuffer<\/p>\n<\/td>\n<td>\n<p>1&nbsp;380,16 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>2&nbsp;152,14 \u041c\u0431<\/p>\n<\/td>\n<td>\n<p>2&nbsp;618,31 \u041c\u0431<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><em>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 5. \u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438 \u043d\u0430 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0435 AMD RX580 8GB<\/em><\/p>\n<p>\u0412\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043f\u0438\u043a\u043e\u0432\u043e\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0431<em>\u043e<\/em>\u043b\u044c\u0448\u0438\u0435 \u0441\u0435\u0442\u043a\u0438 \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u0438 \u0442\u043e\u0439 \u0436\u0435 \u043c\u0430\u0448\u0438\u043d\u0435.<\/p>\n<p><strong>\u041d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/strong><\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043c\u044b \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0443, \u043e\u0434\u043d\u0430\u043a\u043e \u043f\u0440\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0430\u0445 Nvidia \u0440\u0430\u0437\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0438 \u043f\u043e\u043a\u043e\u043b\u0435\u043d\u0438\u0439 (GTX 1050Ti, RTX 2070) \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b\u0430\u0441\u044c \u0432\u0435\u0441\u044c\u043c\u0430 \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u2014 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u0430\u0442\u0430\u0441\u0442\u0440\u043e\u0444\u0438\u0447\u0435\u0441\u043a\u0438 \u0443\u043f\u0430\u043b\u0430 \u0434\u043e 400+ \u043c\u0441 \u043d\u0430 \u043a\u0430\u0434\u0440. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e git bisect \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438, \u0447\u0442\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 glMapBuffer(). \u0421\u0442\u0440\u0430\u043d\u043d\u044b\u043c \u0431\u044b\u043b\u043e \u0438 \u0442\u043e, \u0447\u0442\u043e \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u0432\u0438\u0436\u043a\u0430 \u044d\u0442\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043d\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043b\u0430\u0441\u044c, \u043a\u0430\u043a \u0438 \u043d\u0430 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0430\u0445 AMD \u0438 Intel.<\/p>\n<p>\u0412 \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u043e\u043c \u0432\u044b\u0432\u043e\u0434\u0435 (<a href=\"https:\/\/www.khronos.org\/registry\/OpenGL\/extensions\/KHR\/KHR_debug.txt\">GL_KHR_debug<\/a>) \u0431\u044b\u043b\u0438 \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u043c\u0435\u0447\u0435\u043d\u044b \u0442\u0430\u043a\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<pre><code>Buffer detailed info: Buffer object 1 (bound to NONE, usage hint is GL_DYNAMIC_DRAW) will use SYSTEM HEAP memory as the source for buffer object operations. Buffer detailed info: Buffer object 1 (bound to NONE, usage hint is GL_DYNAMIC_DRAW) has been mapped WRITE_ONLY in SYSTEM HEAP memory (fast). \u2026<\/code><\/pre>\n<p>\u0421\u0443\u0434\u044f \u043f\u043e \u043b\u043e\u0433\u0443, \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u0440\u0430\u0437 \u0431\u0443\u0444\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u043d \u0441 \u0444\u043b\u0430\u0433\u043e\u043c GL_DYNAMIC_DRAW, \u0442\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u043f\u043e\u0434 \u043d\u0435\u0433\u043e \u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u044c, \u0432\u0435\u0434\u044c \u043e\u043d \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0434 \u0431\u0443\u0444\u0435\u0440 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0430 \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u043f\u0430\u043c\u044f\u0442\u044c, \u0447\u0442\u043e \u0438 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0438\u0437\u043a\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u044b \u043d\u0438\u0433\u0434\u0435 \u043d\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0438 GL_DYNAMIC_DRAW \u2013 \u0443 \u043d\u0430\u0441 \u0434\u0430\u0436\u0435 \u043d\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u0432\u0435\u0434\u044c \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 <a href=\"https:\/\/www.khronos.org\/registry\/OpenGL-Refpages\/gl4\/html\/glBufferStorage.xhtml\">glBufferStorage()<\/a>, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0442\u0430\u043a\u043e\u0433\u043e \u0444\u043b\u0430\u0433\u0430 \u043d\u0435\u0442.<\/p>\n<p>\u0414\u043b\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430 \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u043b\u0438 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438 \u0432 \u0431\u0443\u0444\u0435\u0440\u0435 \u043d\u0430 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u0439 <a href=\"https:\/\/www.khronos.org\/registry\/OpenGL-Refpages\/gl4\/html\/glBufferData.xhtml\">glBufferData(\u2026, GL_STATIC_DRAW)<\/a>, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e \u0438\u0441\u0447\u0435\u0437\u043b\u0430, \u0430 \u0432 \u043b\u043e\u0433\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u0442\u0430\u043a\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f:<\/p>\n<pre><code>Buffer detailed info: Buffer object 1 (bound to NONE, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations. Buffer detailed info: Buffer object 1 (bound to NONE, usage hint is GL_STATIC_DRAW) has been mapped in HOST memory \u2026<\/code><\/pre>\n<p>\u041d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0443\u0434\u0438\u0442\u044c, \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u0443\u0444\u0435\u0440\u043e\u0432 \u0434\u0440\u0430\u0439\u0432\u0435\u0440 Nvidia \u0432\u043e\u0441\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u2013 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 GL_DYNAMIC_DRAW \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u041d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0441\u0438\u043b\u044c\u043d\u043e \u0438\u0445 \u0432\u0438\u043d\u0438\u0442\u044c, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u044d\u0442\u043e \u0432 \u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438 \u043d\u0435\u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 <a href=\"https:\/\/www.khronos.org\/registry\/OpenGL\/extensions\/ARB\/ARB_buffer_storage.txt\">GL_ARB_buffer_storage<\/a>, \u043d\u0435 \u043f\u0440\u0435\u0434\u0432\u0438\u0434\u0435\u0432\u0448\u0435\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0438\u0437-\u0437\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u043e \u0441\u0442\u0430\u0440\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<h3>\u0411\u0435\u043d\u0447\u043c\u0430\u0440\u043a<\/h3>\n<p>\u0421\u0440\u0430\u0432\u043d\u0438\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440\u0430 \u0434\u043e \u0438 \u043f\u043e\u0441\u043b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043c\u043e\u0434\u0435\u043b\u044f\u0445 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442:<\/p>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<p>\u0412\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0430<\/p>\n<\/td>\n<td>\n<p>FPS \u0432 \u043b\u0443\u0447\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435<br \/>   (\u0434\u043e \u2013 \u043f\u043e\u0441\u043b\u0435, \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435 \u0432 %)<\/p>\n<\/td>\n<td>\n<p>FPS \u0432 \u0445\u0443\u0434\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435<br \/>   (\u0434\u043e \u2013 \u043f\u043e\u0441\u043b\u0435, \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435 \u0432 %)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>AMD RX580   <\/p>\n<\/td>\n<td>\n<p>54,3 \u2013 67,4   (+24%)&nbsp;&nbsp;&nbsp; <\/p>\n<\/td>\n<td>\n<p>17,7   \u2013 64,9 (+366%)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>Nvidia GTX   1050Ti<\/p>\n<\/td>\n<td>\n<p>29.9 \u2013 40,2 (+34%)<\/p>\n<\/td>\n<td>\n<p>20.9 \u2013 39,5 (+88%)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>Nvidia RTX 2070<\/p>\n<\/td>\n<td>\n<p>116 \u2013 150   (+29%)<\/p>\n<\/td>\n<td>\n<p>36,3 \u2013 149 (+410%)<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><em>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 6. \u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0434\u043e \u0438 \u043f\u043e\u0441\u043b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439<\/em><\/p>\n<p>\u041d\u0430 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0430\u0445 \u043f\u0440\u0438\u0440\u043e\u0441\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u043b \u043e\u043a\u043e\u043b\u043e 30% \u0434\u043b\u044f \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u0441\u043b\u0443\u0447\u0430\u044f, \u0430 \u0434\u043b\u044f \u0445\u0443\u0434\u0448\u0435\u0433\u043e \u0441\u043b\u0443\u0447\u0430\u044f \u2013 \u043e\u0442 80% \u0434\u043e 410%!<\/p>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440\u0430 \u0443\u0433\u043b\u043e\u0432\u043e\u0439 \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043d\u0438\u0437\u0438\u043b\u0438 \u043e\u0431\u044a\u0451\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u0435\u043c\u043e\u0439 \u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0447\u0442\u0438 \u0432 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430 \u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u043b\u0438 \u0447\u0430\u0441\u0442\u043e\u0442\u0443 \u043a\u0430\u0434\u0440\u043e\u0432 \u0432 \u0442\u0440\u0438 \u0441 \u043b\u0438\u0448\u043d\u0438\u043c \u0440\u0430\u0437\u0430. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448 \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440 \u0441\u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0441\u0435\u0442\u043a\u0438 \u0431<em>\u043e<\/em>\u043b\u044c\u0448\u0435\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u043d\u0430 \u043c\u0430\u043b\u043e\u043c\u043e\u0449\u043d\u044b\u0445 \u043e\u0444\u0438\u0441\u043d\u044b\u0445 \u043c\u0430\u0448\u0438\u043d\u0430\u0445 \u0438 \u0441\u0435\u0442\u043a\u0438 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u043c\u0438\u043b\u043b\u0438\u0430\u0440\u0434\u0430 \u044f\u0447\u0435\u0435\u043a \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u0441\u0442\u0430\u043d\u0446\u0438\u044f\u0445.<\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u044d\u0442\u043e \u043d\u0435 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0436\u043d\u043e \u0435\u0449\u0451 \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u043d\u0430\u043b\u043e\u0436\u0438\u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. \u041c\u043e\u0436\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043e\u0442\u0441\u0435\u0447\u0435\u043d\u0438\u044f \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u044b\u0445 \u0433\u0440\u0430\u043d\u0435\u0439, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b\u043e\u0441\u044c \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438; \u043c\u043e\u0436\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u0447\u0438\u0441\u043b\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0432\u0435\u0440\u0448\u0438\u043d \u043f\u0440\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0433\u0440\u0430\u043d\u0435\u0439 \u043e\u0434\u043d\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438; \u043c\u043e\u0436\u043d\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u043d\u0435 \u0440\u0430\u0437\u043e\u043c, \u0430 \u0447\u0430\u043d\u043a\u0430\u043c\u0438&#8230; \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u0432\u0435\u0440\u0441\u0438\u044f \u0434\u0432\u0438\u0436\u043a\u0430, \u0433\u0434\u0435 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438, \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u0435\u0442 \u0435\u0449\u0451 \u0432 \u043f\u043e\u043b\u0442\u043e\u0440\u0430 \u0440\u0430\u0437\u0430 \u043c\u0435\u043d\u044c\u0448\u0435 \u043f\u0430\u043c\u044f\u0442\u0438, \u0430 \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u2014 \u043f\u043e\u0447\u0442\u0438 \u0432 \u0447\u0435\u0442\u044b\u0440\u0435 \u0440\u0430\u0437\u0430 \u043c\u0435\u043d\u044c\u0448\u0435 \u043f\u0430\u043c\u044f\u0442\u0438!<\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043c\u044b \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u043c \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439 \u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435 \u0443\u0433\u043b\u043e\u0432\u043e\u0439 \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0438. \u041d\u0430\u0434\u0435\u0435\u043c\u0441\u044f, \u0447\u0442\u043e \u043e\u0431\u0435 \u0447\u0430\u0441\u0442\u0438 \u043e\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c\u0438 \u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c\u0438. \u0412 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u0436\u0434\u0435\u043c \u0432\u0430\u0448\u0438\u0445 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432; \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0434\u044b \u043e\u0431\u0441\u0443\u0434\u0438\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0438 \u043d\u043e\u0432\u044b\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440\u0430!<\/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\/company\/bashnipineft\/blog\/559508\/\"> https:\/\/habr.com\/ru\/company\/bashnipineft\/blog\/559508\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<p><a href=\"https:\/\/habr.com\/ru\/company\/bashnipineft\/blog\/544054\/\">\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438<\/a> \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 (\u0438 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439) \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440 \u0441\u0435\u0442\u043a\u0438 \u0413\u0423\u0422, \u0438 \u043f\u043e\u043e\u0431\u0435\u0449\u0430\u043b\u0438, \u0447\u0442\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440 \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e, \u0447\u0442\u043e \u043e\u043d \u0441\u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 \u043c\u0438\u043b\u043b\u0438\u0430\u0440\u0434 \u044f\u0447\u0435\u0435\u043a.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u043e\u0431\u044a\u0451\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u0435\u043c\u043e\u0439 \u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u0438 \u2014 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0432\u0438\u0434\u0435 \u0434\u0430\u0436\u0435 \u043d\u0430 \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0430\u0445 (\u0435\u0441\u043b\u0438 \u0431\u044b \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043a\u0443\u043f\u0438\u0442\u044c \u0432 \u043d\u0430\u0448\u0435 \u0432\u0440\u0435\u043c\u044f!) \u043f\u0430\u043c\u044f\u0442\u0438 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u0442\u044c, \u043d\u0435 \u0433\u043e\u0432\u043e\u0440\u044f \u0443\u0436 \u043e \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0430\u0445 \u0432 \u043e\u0444\u0438\u0441\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430\u0445.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0430\u043c\u044f\u0442\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043d\u0430\u0448 \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440 \u0441\u0435\u0439\u0447\u0430\u0441. \u041a\u0430\u0436\u0434\u0430\u044f \u0433\u0440\u0430\u043d\u044c \u044f\u0447\u0435\u0439\u043a\u0438 \u0437\u0430\u0434\u0430\u043d\u0430 \u043d\u0430 \u0447\u0435\u0442\u044b\u0440\u0451\u0445 \u0432\u0435\u0440\u0448\u0438\u043d\u0430\u0445, \u043a\u0430\u0436\u0434\u0430\u044f \u0432\u0435\u0440\u0448\u0438\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u044f\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u043e\u0431\u0449\u0438\u043c \u043e\u0431\u044a\u0451\u043c\u043e\u043c \u0432 48 \u0431\u0430\u0439\u0442. \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u043d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0441\u0435\u0442\u043a\u0430 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 1000<sup>3<\/sup>. \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e 4*6*1000<sup>2<\/sup> \u0432\u0435\u0440\u0448\u0438\u043d \u0434\u043b\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0433\u0440\u0430\u043d\u0435\u0439 \u0441\u0435\u0442\u043a\u0438, \u043e\u0431\u0449\u0438\u043c \u043e\u0431\u044a\u0451\u043c\u043e\u043c 1098,6 \u041c\u0431. \u041d\u0435 \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u0431\u044b\u0432\u0430\u0442\u044c \u0438 \u043f\u0440\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u044b, \u043a\u043e\u0438\u0445 \u0431\u0443\u0434\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e 6*6*1000<sup>2<\/sup> \u0448\u0442. \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 137,3 \u041c\u0431.<\/p>\n<p>\u0412 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0441\u0435\u0442\u043a\u0438 \u0413\u0423\u0422 \u0447\u0430\u0441\u0442\u043e \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u044b \u0438 \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u043c\u0435\u044e\u0442 \u043c\u0430\u0441\u043a\u0443 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u044f\u0447\u0435\u0435\u043a, \u0438\u0437-\u0437\u0430 \u0447\u0435\u0433\u043e \u043d\u0435 \u043e\u0442\u0441\u0435\u0447\u0451\u043d\u043d\u044b\u0445 \u0433\u0440\u0430\u043d\u0435\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u044c\u0448\u0435. <\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u043f\u0430\u0440\u0443 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0445 \u044f\u0447\u0435\u0435\u043a, \u043e\u0434\u043d\u0430 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0430\u043a\u0442\u0438\u0432\u043d\u0430, \u0430 \u0434\u0440\u0443\u0433\u0430\u044f \u2013 \u043d\u0435\u0442. \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043e\u0442\u0441\u0435\u0447\u0435\u043d\u0438\u044f \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u044b\u0445 \u0433\u0440\u0430\u043d\u0435\u0439 (\u0441\u043c. \u043f\u0435\u0440\u0432\u0443\u044e \u0447\u0430\u0441\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/company\/bashnipineft\/blog\/544054\/\">\u0441\u0442\u0430\u0442\u044c\u0438<\/a>) \u0441\u043a\u0430\u0436\u0435\u0442, \u0447\u0442\u043e \u0434\u043b\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438 \u043d\u0443\u0436\u043d\u043e \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0433\u0440\u0430\u043d\u044c \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0432 \u0441\u0435\u0442\u043a\u0435 <em>\u043d\u0435<\/em>\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u044f\u0447\u0435\u0435\u043a, \u0442\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0433\u0440\u0430\u043d\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u043e.&nbsp;<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439, \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u0443\u044e \u0441\u0435\u0442\u043a\u0443 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430&nbsp;\u2014 \u0432\u0441\u0435\u0433\u043e 200<sup>3<\/sup> \u044f\u0447\u0435\u0435\u043a. \u041f\u043e\u0434\u0432\u043e\u0445 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0440\u043e\u0432\u043d\u043e \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0443 \u0438\u0437 \u044f\u0447\u0435\u0435\u043a \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u2014 \u044d\u0442\u043e \u0445\u0443\u0434\u0448\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u043e\u0442\u0441\u0435\u0447\u0435\u043d\u0438\u044f \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u044b\u0445 \u0433\u0440\u0430\u043d\u0435\u0439. <\/p>\n<p>\u041c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0434\u0443\u043c\u0430\u043d\u043d\u044b\u043c, \u043d\u043e \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043e\u0442\u0441\u0435\u0447\u0435\u043d\u0438\u044f \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u044b\u0445 \u0433\u0440\u0430\u043d\u0435\u0439 \u043d\u0435\u0442 \u0440\u0430\u0437\u043d\u0438\u0446\u044b, \u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u043b\u0438 \u0433\u0440\u0430\u043d\u044c \u0438\u0437-\u0437\u0430 \u043d\u0435\u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u0438 \u0438\u043b\u0438 \u0438\u0437-\u0437\u0430 \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0441\u043e\u0441\u0435\u0434\u043d\u0435\u0439 \u044f\u0447\u0435\u0439\u043a\u0438.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0439 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0441\u0435\u0442\u043a\u0438 \u043e\u0431\u044a\u0451\u043c \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u043c\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0434 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u043b 2484,3 \u041c\u0431 \u2014 \u0432 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430 \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u0434\u043b\u044f \u043c\u0438\u043b\u043b\u0438\u0430\u0440\u0434\u0430 \u0441\u043e\u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u044f\u0447\u0435\u0435\u043a!<\/p>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440\u0430 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">\/\/ corner_point_grid.h  template&lt;typename T&gt; struct span3d {      T* const data;     const uint32_t ni;     const uint32_t nj;     const uint32_t nk;      span3d(T* _data, uint32_t _ni, uint32_t _nj, uint32_t _nk)         : data(_data), ni(_ni), nj(_nj), nk(_nk) { }      T at(size_t x, size_t y, size_t z) const {         return data[x * nj * nk + y * nk + z];     }      T&amp; at(size_t x, size_t y, size_t z) {         return data[x * nj * nk + y * nk + z];     } };   struct Palette {     float min_value;     float max_value;     GLuint texture; };   struct CornerPointGrid {     CornerPointGrid(uint32_t ni, uint32_t nj, uint32_t nk,                     const float* coord, const float *zcorn, const float* property, const uint8_t* mask);     ~CornerPointGrid();      void render(GLuint shader,                 const Palette&amp; palette,                 const mat4&amp; proj, const mat4 &amp; view,                 const mat4&amp; model,                 vec3 light_direct,                 bool primitive_picking);  private:      \/\/ \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435     span3d&lt;const float&gt;   _coord;     span3d&lt;const float&gt;   _zcorn;     span3d&lt;const float&gt;   _property;     span3d&lt;const uint8_t&gt; _mask;      \/\/ \u043c\u0430\u0441\u043a\u0430 \u0441\u043e\u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u0438 \u0433\u0440\u0430\u043d\u0435\u0439     std::vector&lt;uint8_t&gt;  _joined_mask_data;     span3d&lt;uint8_t&gt;  _joined_mask; \/\/ \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043c\u0430\u0441\u0441\u0438\u0432 _joined_mask_data;      \/\/ \u043e\u0431\u044a\u0435\u043a\u0442\u044b OpenGL     GLuint _position_vbo;     GLuint _normal_vbo;     GLuint _cell_index_vbo;     GLuint _texcoord_vbo;     GLuint _property_vbo;      GLuint _indexbuffer;     GLuint _vao;      \/\/ \u0447\u0438\u0441\u043b\u043e \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u0434\u043b\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430     size_t _triangle_count;      \/\/ \u0440\u0430\u0441\u0447\u0435\u0442 \u0432\u0435\u0440\u0448\u0438\u043d \u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432     void _gen_vertices_and_indices(size_t quad_count);      \/\/ \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0431\u0443\u0444\u0435\u0440\u043e\u0432 OpenGL     void _create_vertex_index_buffers();      \/\/ \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0431\u0443\u0444\u0435\u0440\u043e\u0432 \u0432 VAO     void _setup_vao(); };   \/\/ corner_point_grid.cpp  \/\/ \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432\u043e\u0441\u044c\u043c\u0438 \u0435\u0451 \u0432\u0435\u0440\u0448\u0438\u043d. \/\/         6-------7 \/\/        \/|     \/ | \/\/       4------5  |    z y \/\/       | 2----|--3    |\/ \/\/       |\/     | \/     0-x \/\/       0------1 \/\/ \u042d\u0442\u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u043e\u0442\u0441\u0442\u0443\u043f\u044b \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0437 8-\u043c\u0438 \u0432\u0435\u0440\u0448\u0438\u043d \/\/ \u044f\u0447\u0435\u0439\u043a\u0438 \u043f\u043e \u043e\u0441\u044f\u043c x, y, z, \u0435\u0441\u043b\u0438 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0443 \u044f\u0447\u0435\u0439\u043a\u0443. static const std::array&lt;uint32_t, 8&gt; cell_vertices_offset_x = {     0, 1, 0, 1, 0, 1, 0, 1 }; static const std::array&lt;uint32_t, 8&gt; cell_vertices_offset_y = {     0, 0, 1, 1, 0, 0, 1, 1 }; static const std::array&lt;uint32_t, 8&gt; cell_vertices_offset_z = {     0, 0, 0, 0, 1, 1, 1, 1 };  \/\/ \u0418\u043d\u0434\u0435\u043a\u0441\u044b \u0432\u0435\u0440\u0448\u0438\u043d, \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u0433\u0440\u0430\u043d\u0438 \u044f\u0447\u0435\u0439\u043a\u0438. \/\/         6-------7 \/\/        \/|     \/ | \/\/       4------5  |    z y \/\/       | 2----|--3    |\/ \/\/       |\/     | \/     0-x \/\/       0------1 static const std::array&lt;std::array&lt;uint32_t, 4&gt;, 6&gt; cell_quads = {     std::array&lt;uint32_t, 4&gt;{0, 1, 5, 4},   \/\/ 1-\u0430\u044f \u0433\u0440\u0430\u043d\u044c     std::array&lt;uint32_t, 4&gt;{1, 3, 7, 5},   \/\/ 2-\u0430\u044f \u0433\u0440\u0430\u043d\u044c     std::array&lt;uint32_t, 4&gt;{3, 2, 6, 7},   \/\/ ...     std::array&lt;uint32_t, 4&gt;{2, 0, 4, 6},     std::array&lt;uint32_t, 4&gt;{3, 1, 0, 2},     std::array&lt;uint32_t, 4&gt;{4, 5, 7, 6}, };  \/\/ \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0430\u043d\u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0441\u043e\u0441\u0435\u0434\u043d\u0435\u0439 \u044f\u0447\u0435\u0439\u043a\u0438 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u044d\u0442\u043e\u0439 \u0433\u0440\u0430\u043d\u0438 static const std::array&lt;std::array&lt;int, 3&gt;, 6&gt; cell_quads_neighbors = {     \/\/ \u043f\u0440\u0438\u0431\u0430\u0432\u0438\u043c \u0438\u0445 \u043a \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c (i,j,k) \u044f\u0447\u0435\u0439\u043a\u0438 - \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0441\u043e\u0441\u0435\u0434\u043d\u0435\u0439 \u044f\u0447\u0435\u0439\u043a\u0438     std::array&lt;int, 3&gt;{ 0, -1,  0},     std::array&lt;int, 3&gt;{ 1,  0,  0},     std::array&lt;int, 3&gt;{ 0,  1,  0},     std::array&lt;int, 3&gt;{-1,  0,  0},     std::array&lt;int, 3&gt;{ 0,  0, -1},     std::array&lt;int, 3&gt;{ 0,  0,  1}, };  \/\/ \u0431\u0438\u0442\u043e\u0432\u044b\u0435 \u043c\u0430\u0441\u043a\u0438, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u0443\u0437\u043d\u0430\u0442\u044c \u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u0430 \u043b\u0438 \u044f\u0447\u0435\u0439\u043a\u0430 \u0441 \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0445 \/\/ (\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043c\u0430\u0441\u043a\u0435 \u0431\u0438\u0442 \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 joined_mask) enum JoinedMaskBits : uint8_t {     I_PREV = 1 &lt;&lt; 0, I_NEXT = 1 &lt;&lt; 1,     J_PREV = 1 &lt;&lt; 2, J_NEXT = 1 &lt;&lt; 3,     K_PREV = 1 &lt;&lt; 4, K_NEXT = 1 &lt;&lt; 5 };  \/\/ \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0430\u043d\u0438 \u0431\u0438\u0442, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0441 \u0441\u043e\u0441\u0435\u0434\u043d\u0435\u0439 \u044f\u0447\u0435\u0439\u043a\u043e\u0439 static const std::array&lt;JoinedMaskBits, 6&gt; cell_quads_joined_mask_bits = {     \/\/ \u0442\u043e \u0435\u0441\u0442\u044c \u044f\u0447\u0435\u0439\u043a\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0441\u0435\u0434\u043d\u0435\u0439 \u043f\u043e \u043e\u0441\u0438 x, y \u0438\u043b\u0438 z     JoinedMaskBits::J_PREV,     JoinedMaskBits::I_NEXT,     JoinedMaskBits::J_NEXT,     JoinedMaskBits::I_PREV,     JoinedMaskBits::K_PREV,     JoinedMaskBits::K_NEXT, };  \/\/ \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0442\u043a\u0443 \u043d\u0430 \u0433\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u044f\u0447\u0435\u0435\u043a, \/\/ \u043d\u0430\u0434\u043e \u0437\u043d\u0430\u0442\u044c \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u043b\u0438\u0437\u043a\u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u043a \u0433\u0440\u0430\u043d\u0438\u0446\u0435. \/\/ \u0422\u0443\u0442 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u044b \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0433\u0440\u0430\u043d\u0438, \/\/ \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043e \u0433\u0440\u0430\u043d\u0438\u0446\u044b \/\/ (\u0435\u0441\u043b\u0438 \u043e\u0434\u0438\u043d \u0438\u0437 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0440\u0430\u0432\u0435\u043d \u043d\u0443\u043b\u044e, \u0442\u043e \u044d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c \u0433\u0440\u0430\u043d\u0438\u0446\u0430). static const std::array&lt;vec2, 4&gt; quad_vertices_texcoords = {     vec2(1, 0),     vec2(0, 0),     vec2(0, 1),     vec2(0, 0), };  \/\/ \u041a\u0430\u043a \u0434\u043b\u044f \u0433\u0440\u0430\u043d\u0438 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0432\u0430 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 static const std::array&lt;uint32_t, 6&gt; quad_to_triangles = {     0, 1, 2, 0, 2, 3 };   static vec3 calc_normal(vec3 v1, vec3 v2){     \/\/ \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043d\u043e\u0440\u043c\u0430\u043b\u044c \u043a \u043a\u0432\u0430\u0434\u0443     vec3 normal = cross(v1, v2);      \/\/ \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043c \u043d\u043e\u0440\u043c\u0430\u043b\u044c \u043a \u0435\u0434\u0438\u043d\u0438\u0447\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u0435     if (length2(normal) &lt; 1e-8f){         normal = vec3(0, 0, 1);     } else {         normal = normalize(normal);     }      return normal; }   static void calc_joined_mask(span3d&lt;const float&gt; zcorn, span3d&lt;uint8_t&gt; joined_mask) {     \/\/ \u0441 \u043a\u0430\u043a\u043e\u0439 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u043d\u0438\u0435 \u0433\u0440\u0430\u043d\u0435\u0439, ~10 \u0441\u043c \u0432\u043f\u043e\u043b\u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.     const float eps = 0.1f;      \/\/ \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u0439 \u043c\u0430\u0441\u043a\u0438     for(uint32_t i = 0; i &lt; joined_mask.ni; ++i) {         for(uint32_t j = 0; j &lt; joined_mask.nj; ++j) {             for(uint32_t k = 0; k &lt; joined_mask.nk; ++k) {                 \/\/ \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u044d\u0442\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438 \u0432 zcorn                 uint32_t iz = i * 2, jz = j * 2, kz = k * 2;                  \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 \u043b\u0438 \u0433\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u044f\u0447\u0435\u0435\u043a (i,j,k) \u0438 (i+1,j,k) \u043f\u043e \u043e\u0441\u0438 X                 if (i + 1 &lt; joined_mask.ni) {                     float d = 0.0f;                     d += std::abs(zcorn.at(iz+1, jz,   kz  ) - zcorn.at(iz+2, jz,   kz  ));                     d += std::abs(zcorn.at(iz+1, jz+1, kz  ) - zcorn.at(iz+2, jz+1, kz  ));                     d += std::abs(zcorn.at(iz+1, jz,   kz+1) - zcorn.at(iz+2, jz,   kz+1));                     d += std::abs(zcorn.at(iz+1, jz+1, kz+1) - zcorn.at(iz+2, jz+1, kz+1));                      if (d &lt; eps) {                         \/\/ \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 - \u043e\u0442\u043c\u0435\u0442\u0438\u043c \u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0432 \u0431\u0438\u0442\u044b I_NEXT \u0438 I_PREV                         joined_mask.at(i,   j, k) |= I_NEXT;                         joined_mask.at(i+1, j, k) |= I_PREV;                     }                 }                  \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 \u043b\u0438 \u0433\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u044f\u0447\u0435\u0435\u043a (i,j,k) \u0438 (i,j+1,k) \u043f\u043e \u043e\u0441\u0438 Y                 if (j + 1 &lt; joined_mask.nj) {                     float d = 0.0f;                     d += std::abs(zcorn.at(iz,   jz+1, kz  ) - zcorn.at(iz,   jz+2, kz  ));                     d += std::abs(zcorn.at(iz+1, jz+1, kz  ) - zcorn.at(iz+1, jz+2, kz  ));                     d += std::abs(zcorn.at(iz,   jz+1, kz+1) - zcorn.at(iz,   jz+2, kz+1));                     d += std::abs(zcorn.at(iz+1, jz+1, kz+1) - zcorn.at(iz+1, jz+2, kz+1));                      if (d &lt; eps) {                         \/\/ \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 - \u043e\u0442\u043c\u0435\u0442\u0438\u043c \u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0432 \u0431\u0438\u0442\u044b J_NEXT \u0438 J_PREV                         joined_mask.at(i, j,   k) |= J_NEXT;                         joined_mask.at(i, j+1, k) |= J_PREV;                     }                 }                  \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 \u043b\u0438 \u0433\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u044f\u0447\u0435\u0435\u043a (i,j,k) \u0438 (i,j,k+1) \u043f\u043e \u043e\u0441\u0438 Z                 if (k + 1 &lt; joined_mask.nk) {                     float d = 0.0f;                     d += std::abs(zcorn.at(iz,   jz,   kz+1) - zcorn.at(iz,   jz,   kz+2));                     d += std::abs(zcorn.at(iz+1, jz,   kz+1) - zcorn.at(iz+1, jz,   kz+2));                     d += std::abs(zcorn.at(iz,   jz+1, kz+1) - zcorn.at(iz,   jz+1, kz+2));                     d += std::abs(zcorn.at(iz+1, jz+1, kz+1) - zcorn.at(iz+1, jz+1, kz+2));                      if (d &lt; eps) {                         \/\/ \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 - \u043e\u0442\u043c\u0435\u0442\u0438\u043c \u0441\u0442\u044b\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0432 \u0431\u0438\u0442\u044b K_NEXT \u0438 K_PREV  <\/code><\/pre>\n<\/div>\n<\/details>\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-323829","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/323829","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=323829"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/323829\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=323829"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=323829"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=323829"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}