Краткий ввод в проблему: в Godot есть встроенная GPU система частиц, и в редакторе можно задавать маску для эмиттера частиц в виде текстуры, для понимания:
- соответственно частицы будут появляться там, где у текстуры были непрозрачные пиксели.
НО такая возможность есть только в редакторе, из кода провернуть тоже самое нельзя. А мне нужно именно из скрипта! Но так как исходники открыты, не проблема найти как это реализовано в редакторе (функция void GPUParticles2DEditorPlugin::_generate_emission_mask() ):
Я не программист, не очень умею в С++, но из того что я понял:
Из текстуры берутся непрозрачные пиксели, их позиции записываются в массив valid_positions, а потом, эти позиции как-то кодируются в текстуру в формате GL_RG32F (FORMAT_RGF), и потом, в шейдере частиц берётся эта текстура, раскодируются позиции и создаются частицы.
НЕ совсем понятен мне этот фрагмент (я так понимаю магия происходит именно тут):
Vector<uint8_t> texdata; int w = 2048; int h = (vpc / 2048) + 1; texdata.resize( w * h * 2 * sizeof( float)); { uint8_t *tw = texdata.ptrw( ); float *twf = ( float *)tw; for ( int i = 0; i < vpc; i++) { twf[i * 2 + 0] = valid_positions[i].x; twf[i * 2 + 1] = valid_positions[i].y; } } img.instance( ); img->create( w, h, false, Image::FORMAT_RGF, texdata);
ЧТобы что, зачем, и почему нужны эти строки??
uint8_t *tw = texdata.ptrw();
float *twf = (float *)tw;
В каком виде позиции из массива valid_positions попадают в img?
У меня задача упрощена, у меня уже есть массив позиций, из которых надо эмитировать частицы, мне бы только понять, как закодировать эти позиции через GDScript в текстуру в формате GL_RG32F для шейдера частиц.
Prescott
> ЧТобы что, зачем, и почему нужны эти строки??
> uint8_t *tw = texdata.ptrw();
> float *twf = (float *)tw;
Это созданный массив (вектор) texdata: преобразование типов для доступа к нему как float.
Prescott
> мне бы только понять
Тебе шейдер частиц нужен, или массив эмитеров?
rcsim
> Тебе шейдер частиц нужен, или массив эмитеров?
Сам шейдер частиц у меня есть, массив из точек у меня тоже есть. Мне нужно перевести этот массив точек в стандартный формат маски эмиссии Годота - в текстуру 2048x1 RGFloat.
Иными словами, я не понимаю, как эта маска:
- (текстура 32 на 32, с 4 чёрными пикселями по углам) после обработки функцией _generate_emission_mask() становится текстурой 2048x1, с таким PoolByteArray:
OutputTexture
Prescott
> Сам шейдер частиц у меня есть, массив из точек у меня тоже есть. Мне нужно
> перевести этот массив точек в стандартный формат маски
Вообще, тут или у тебя шейдер, или ParticleMaterial.
Т.е. к шейдеру маска эмиссии (с текстурой) уже неприменима.
В шейдере ты сам позиционируешь частицы как хочешь.
ParticleMaterial можно без проблем конвертировать в ShaderMaterial и в параметрах шейдера будет маска эмиссии. В этом проблемы нет. Проблема как я писал выше в другом
Давайте проще спрошу, что конкретно ваш код должен делать или чем управлять?
Prescott
> ParticleMaterial можно без проблем конвертировать в ShaderMaterial и в
> параметрах шейдера будет маска эмиссии.
"Маска эмиссии в виде текстуры" там просто достаётся по наследству от ParticleMaterial, а по сути она
не нужна, можно в шейдер сразу передавать координаты рождения частиц например в виде массива.
Ведь тебе это в конце концов надо?
rcsim
> можно в шейдер сразу передавать координаты рождения частиц например в виде
> массива.
> Ведь тебе это в конце концов надо?
ДА! Мне именно это и надо, но как это сделать? Ведь в Годоте нельзя в шейдере использовать массив как uniform...
rcsim
> "Маска эмиссии в виде текстуры" там просто достаётся по наследству от
> ParticleMaterial
Да, но разве в этой текстуре и не содержится массив позиций для эмиссии?
Prescott
> Ведь в Годоте нельзя в шейдере использовать массив как uniform...
Да, ошибся, именно так (я в godot около месяца). Ну тогда да, текстуру передавай.
Собственно с++ код и заполняет вектор, из него делается Image, из него ImageTexture.
Тебе надо это на GDScript?
rcsim
Фууух, разобрался в итоге...
Нужно было всего лишь перевести мой массив координат рождения частиц в массив байт с помощью метода var2bytes(Variant) и создать из этого массива байт текстуру (img.create_from_data)
Единственное, я так и не понял, где в реализации плагина редактора это делается (point2 в byte переводится), но это уже и не так важно.
Prescott
С++ код адресует массив байтов, как массив float.
Тема в архиве.