|
|||||||||||||||
Как запоминать данные в GLSL шейдерах в текстурах
Время создания: 11.08.2021 01:16
Текстовые метки: glsl, шейдер, данные, массив, переменная, текстура, запомнить, передача, хранение, данные
Раздел: Компьютер - Программирование - Шейдеры - Шейдеры GLSL
Запись: xintrea/mytetra_syncro/master/base/1628633780zwhuhnonzj/text.html на raw.github.com
|
|||||||||||||||
|
|||||||||||||||
Здесь собирается информация о том, как в шейдерах передавать данные между кадрами через текстуру. Автор этой заметки знаком с шейдерами две недели, урывками по ночам, и многого не понимает. * * * Иногда в шейдерах нужно иметь возможность запоминать данные между кадрами. Сделать это можно с помощью текстур. Идея в том, что в текстуре можо организовывать хранение данных в определенном программистом формате. Далее идет разбор кода в web-среде ShaderToy. Чтение и запись в текстуру может выглядеть так: #define txBuf iChannel0 #define txSize iChannelResolution[0].xy const float txRow = 32.; vec4 Loadv4 (int idVar) { float fi = float (idVar); return texture (txBuf, (vec2 (mod (fi, txRow), floor (fi / txRow)) + 0.5) / txSize); } void Savev4 (int idVar, vec4 val, inout vec4 fCol, vec2 fCoord) { float fi = float (idVar); vec2 d = abs (fCoord - vec2 (mod (fi, txRow), floor (fi / txRow)) - 0.5); if (max (d.x, d.y) < 0.5) fCol = val; } Здесь предполагается, что в текстуру записывается массив значений типа vec4. У функции Savev4() следующие параметры:
Запоминание и чтение происходит через указание номера элемента массива. Пример записи значения: vec4 p; ... Savev4 (mId, p, fragColor, fragCoord); А чтение происходит просто путем вызова функции Loadv4() с указанием индекса значения. Как видно из кода, сохранение значения происходит в цвет текущего пикселя fragColor. И это не совсем то, что надо. Совершенно непонятно, как в этом случае формируется изображение, если fragColor используется и для задания цвета точки изображения, и для сохранения каких-то пользовательских данных. Пример работы с текстурой как с хранилищем данных можно найти по ссылке: https://www.shadertoy.com/view/4dG3RW. Похоже, что такой подход работает только в ShaderToy, так как он позволяет задать сразу несколько шейдеров, и они друг другу по кругу передают данные. При этом непонятно, как формируется цвет пикселя, который видит пользователь. А как сделать то же самое используя один шейдер, как в Bonzomatic, пока что непонятно. Нужно подумать, возможно можно сделать более простой механизм запоминания, без использования fragColor и fragCoord. * * * Возможно, что для Bonzomatic подойдет возможность, которая появилась в OpenGL 4.2. Это пара функций для работы не с текстурами, а с изображениями: imageStore() и imageLoad(). Понять, что такое изображение в отличие от текстуры, достаточно сложно, и этот вопрос пока остается открытым. В любом случае, в Bonzomatic без ошибок компилируется такой код: #version 420 core layout(r8ui) uniform uimage2D emptyTexture; void main(void) { imageStore(emptyTexture, ivec2( floor(gl_FragCoord.x*1024), floor(gl_FragCoord.y*1024)), uvec4(128)); float value = imageLoad(emptyTexture, ivec2( floor(gl_FragCoord.x*1024), floor(gl_FragCoord.y*1024))).r; ... } Здесь текстура emptyTexture - это заранее подготовленная текстура в виде *.png-файла, залитого черным цветом или полностью прозрачного, размером 1024x1024 pix. Данная текстура по задумке, должна быть просто промежуточным хранилищем данных. Текстура подключается к Bonzomatic в файле config.json стандартным для Bonzomatic способом: { "skipSetupDialog": "window":{ "fullscreen":true, }, "textures": { "textureLabel": "textures/label.png", "emptyTexture": "textures/emptyTexture.png" }, } Пока что сделать работающий пример не удалось. При первом вызове функции main() нужно сделать инициализацию этого "хранилища" какими-то данными, и в конце работы кода шейдера надо сделать imageStore(). При последующих вызовах main() код каким-то образом должен узнать, что он вызывается не в первый раз, и вместо инициализации сделать считываение предыдущих данных с помощью imageLoad(). Говорят, что данный метод не очень эффективен с точки зрения производительности, потому что сохранение и считывание данных происходит с помощью центрального процессора, а не в GPU. В общем, с этим методом нужно разбираться отдельно. |
|||||||||||||||
Так же в этом разделе:
|
|||||||||||||||
|
|||||||||||||||
|