ПрограммированиеФорумГрафика

Помогите с маской для эмиссии частиц [Godot/C++]

#0
11:49, 1 окт 2020

Краткий ввод в проблему: в 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 для шейдера частиц.

#1
12:12, 1 окт 2020

Prescott
> ЧТобы что, зачем, и почему нужны эти строки??
> uint8_t *tw = texdata.ptrw();
> float *twf = (float *)tw;

Это созданный массив (вектор) texdata: преобразование типов для доступа к нему как float.

Prescott
> мне бы только понять


Тебе шейдер частиц нужен, или массив эмитеров?

#2
12:29, 1 окт 2020

rcsim
> Тебе шейдер частиц нужен, или массив эмитеров?
Сам шейдер частиц у меня есть, массив из точек у меня тоже есть. Мне нужно перевести этот массив точек в стандартный формат маски эмиссии Годота - в текстуру 2048x1 RGFloat.

Иными словами, я не понимаю, как эта маска:
InputMask32x32 | Помогите с маской для эмиссии частиц [Godot/C++]
-  (текстура 32 на 32, с 4 чёрными пикселями по углам) после обработки функцией _generate_emission_mask() становится текстурой 2048x1, с таким PoolByteArray:
OutputTexture

#3
13:52, 1 окт 2020

Prescott
> Сам шейдер частиц у меня есть, массив из точек у меня тоже есть. Мне нужно
> перевести этот массив точек в стандартный формат маски

Вообще, тут или у тебя шейдер, или ParticleMaterial.

Т.е. к шейдеру маска эмиссии (с текстурой) уже неприменима.
В шейдере ты сам позиционируешь частицы как хочешь.

#4
14:29, 1 окт 2020

ParticleMaterial можно без проблем конвертировать в ShaderMaterial и в параметрах шейдера будет маска эмиссии. В этом проблемы нет. Проблема как я писал выше в другом

#5
14:31, 1 окт 2020

Давайте проще спрошу, что конкретно ваш код должен делать или чем управлять?

#6
15:23, 1 окт 2020

Prescott
> ParticleMaterial можно без проблем конвертировать в ShaderMaterial и в
> параметрах шейдера будет маска эмиссии.

"Маска эмиссии в виде текстуры" там просто достаётся по наследству от ParticleMaterial, а по сути она
не нужна, можно в шейдер сразу передавать координаты рождения частиц например в виде массива.
Ведь тебе это в конце концов надо?

#7
15:31, 1 окт 2020

rcsim
> можно в шейдер сразу передавать координаты рождения частиц например в виде
> массива.
> Ведь тебе это в конце концов надо?
ДА! Мне именно это и надо, но как это сделать? Ведь в Годоте нельзя в шейдере использовать массив как uniform...

rcsim
> "Маска эмиссии в виде текстуры" там просто достаётся по наследству от
> ParticleMaterial
Да, но разве в этой текстуре и не содержится массив позиций для эмиссии?

#8
17:05, 1 окт 2020

Prescott
> Ведь в Годоте нельзя в шейдере использовать массив как uniform...

Да, ошибся, именно так (я в godot около месяца). Ну тогда да, текстуру передавай.
Собственно с++ код и заполняет вектор, из него делается Image, из него ImageTexture.

Тебе надо это на GDScript?

#9
17:38, 1 окт 2020

rcsim
Фууух, разобрался в итоге...
Нужно было всего лишь перевести мой массив координат рождения частиц в массив байт с помощью метода var2bytes(Variant) и создать из этого массива байт текстуру (img.create_from_data)

Единственное, я так и не понял, где в реализации плагина редактора это делается (point2 в byte переводится), но это уже и не так важно.

#10
18:58, 1 окт 2020

Prescott
С++ код адресует массив байтов, как массив float.

ПрограммированиеФорумГрафика

Тема в архиве.