Particle rendering revisited

crossposted to zeuxcg.blogspot.com

Recently I was doing particle rendering for different platforms (D3D9, PS3, XBox360), and I wanted to share my experience. The method I came with (which is more or less the same for all 3 platforms) is nothing new or complex – in fact, I know people were and are doing it already – but nevertheless I’ve never seen it described anywhere, so it might help somebody.

The prerequisites are that we want a pretty flexible simulation (such as, all parameters are controlled by splines, and splines come from some particle editor – perhaps also there is some collision detection, or instead particles are driven by some complex physics only) – which means that (a) we don’t have a simple function position(time) (and likewise for other particle parameters), and (b) we don’t want to implement a fully GPU-based solution, with rendering to vertex buffer/streamout. After all, next-gen GPUs are not *that* powerful, we don’t have that many particles, and we often do not use all available cores (in case of PS3/360 at least) efficiently.

Also let’s suppose for the sake of simplicity that our particles are actually billboards that can only rotate around view Z axis – i.e. they are always camera-facing. This does not really matter so much, but it will make things easier.

What we’d like to do ideally is to upload particles to a buffer, and have GPU render from it. To keep the amount of data low, we’d like to copy exactly one instance of each particle, without duplication. The classical (trivial) approach is to fill VB with particle data, 4 vertices per each particle, while doing all computations on CPU – that is, vertex shader only transforms particle in clip space. This is of course not very wise (after all, we’re trying to save some CPU clocks here), so another classical (slightly less trivial) approach is to fill VB with particle data, 4 vertices per each particle, where those 4 vertices differ only in their UV coordinates. UVs act like corner identifications – you know UV coordinate in vertex shader, and you know the corner of the particle you’re processing ((0, 0) = upper left corner, etc.). Thus you can easily perform actual coordinate position calculation in vertex shader like this:

float3 corner_position = particle_position + camera_axis_x * (uv.x – 0.5) * size + camera_axis_y * (uv.y – 0.5) * size;

Also we have point sprites that *seem* to achieve the same thing we need – you upload exactly 1 vertex per each particle. However, they have lots of disadvantages – point size is limited, you can’t rotate them, etc.

The method I am talking about goes slightly further. Let’s divide our particle data in two parts, actual particle data (position, color, angle of rotation, etc.) and UV coordinates. Now we notice, that what we really want is to have two streams of data, one stream contains particle data without duplication, the other stream contains ONLY UV coordinates – moreover, this buffer consists of the same data, repeated many times – you have 4 vertices (0, 0), (1, 0), (1, 1), (0, 1) for the first particle, 4 vertices (0, 0), (1, 0), (1, 1), (0, 1) for the second one, etc. – so we’d like to be able to specify it once and have GPU “loop” over them.

In effect, we want something like this:

Fortunately, there is a solution that can solve it – it’s hardware instancing. Unfortunately, it’s not available everywhere – you (usually) need SM3.0 support for it. We’re going to accept this disadvantage however.

Thus we have a static stream with 4 “vertices” representing corner data (each “vertex” consists of a single float2), and a dynamic stream with N “instances” representing particles (each “instance” consists of, in our example, a position, color and angle). We render N quads, so the vertex shader gets executed 4*N times – every time we have 1 piece of instance data, and 1 piece of corner data. We compute actual particle corner position as shown above, and output it.

Note that it looks like point sprites. It has a disadvantage in that we have 4 vertex shader runs per each particle, instead of 1 with point sprites – but I have yet to see vertex processing becoming a limiting factor for particles. Also it has a more limited hardware scope. What we get in return is much more flexibility (you are not even limited to screen-facing particles; you can pass orientation (i.e. a quaternion) instead of a single angle). The amount of data that has to be uploaded by the application per frame is the same.

Now let’s go over platform-specific implementation details.

Direct3D 9

Unfortunately, D3D9 does not have “quad” primitive type, so we’ll have to use a dummy index buffer. The setup is as follows:

  1. For all particle systems, create a single index buffer with 6 indices describing a quad (0, 1, 2, 2, 1, 3), and a single corner stream that will contain corner values. I chose to store UV coordinates in D3DCOLOR, though FLOAT2 is ok too.
  2. Create a proper vertex declaration, that says that corner (UV) data goes in stream 0, and particle data goes in stream 1.
  3. For each particle system, create a dynamic vertex buffer (note: it’s usually better to create 2 buffers and to use buffer 0 on first frame, buffer 1 on second frame, buffer 0 on third frame, etc. – thus making synchronization costs lower and lowering chance for buffer renaming), which will hold particle data.
  4. Every frame, lock your buffer, upload particle data in it as is (i.e. 1 copy of data per particle).
  5. Draw as follows:
    device->SetStreamSource(0, shared_buffer_with_corner_data, 0, sizeof(CornerVertex));
    device->SetStreamSourceFreq(0, D3DSTREAMSOURCE_INDEXEDDATA | particle_count);
    device->SetStreamSource(1, buffer_with_particle_data, 0, sizeof(ParticleData));
    device->SetStreamSourceFreq(1, D3DSTREAMSOURCE_INSTANCEDATA | 1);
    device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2);

Note, that:

  1. You have to set corner data as stream 0 due to D3D9 restrictions
  2. You pass parameters to DIP as if you want to render a single quad

In theory, this method uses hardware instancing, and hardware instancing is supported only for SM3.0-compliant cards. However, in practice, all SM2.0-capable ATi cards support hardware instancing – it’s just that Direct3D9 does not let you use it. ATi engineers made a hack that lets you enable instancing for their cards – just do this once at application startup:

if (SUCCEEDED(d3d->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, (D3DFORMAT)MAKEFOURCC(‘I’,'N’,'S’,'T’))))
{
// Enable instancing
device->SetRenderState(D3DRS_POINTSIZE, MAKEFOURCC(‘I’,'N’,'S’,'T’));
}

I love ATi D3D9 hacks, they are ingenious.

XBox 360

You can perform rendering with the proposed method as is – the only difference is that you’ll have to fetch vertex data manually in vertex shader via vfetch command because there is no explicit instancing support. For further reference, look at CustomVFetch sample.

PS3

You can perform rendering with the proposed method as is – you’ll have to set frequency divider operation to MODULO with frequency = 4 for corner stream, and to DIVIDE with frequency = 4 for particle data stream.

Direct3D 10

I have not actually implemented this for Direct3D 10, but it should be pretty straightforward – you’ll have to create proper input layout (with D3D10_INPUT_PER_INSTANCE_DATA set for all elements except corner data), create index buffer with 6 indices as for D3D9, and then render via DrawIndexedInstanced(6, particle_count, 0, 0, 0);

Note that for Direct3D 10 you can also render from your particle data stream with D3D10_PRIMITIVE_TOPOLOGY_POINTLIST, and perform quad expansion with geometry shader. This in theory should somewhat speed up vertex processing part, but in practice I have very bad experience with geometry shaders on NVidia cards performance-wise. If you have an ATi R600 or (perhaps) next-generation NVidia card, I’d be happy to hear that things are okay there.

  • CEMEH

    Не настораживает ли то, что рендеринг получился одинаковым для таких разных платформ? :)

  • http://zeux.livejournal.com/ Zeux

    Нууу… D3D9 это как бы PS3/360 с т.з. GPU :) D3D10 это как бы D3D9 + несколько nifty features, из которых для партиклов пригодились бы разве GS, но увы…
    Остается вопрос – не настораживает ли то, что рендеринг получился одинаковым для PS3 и 360? :) Не знаю. К PS3 на данный момент я отношусь как к PPU + RSX, может быть в реальности разумнее и для частиц использовать RSX лишь как растеризатор – не знаю, не пробовал.

  • http://zeux.livejournal.com/ Zeux

    А вообще – мне наоборот очень радостно, что рендеринг получился одинаковым, вот.

  • lordmaze

    > Also let’s suppose for the sake of simplicity that our particles are actually billboards that can only rotate around view Z axis – i.e. they are always
    > camera-facing. This does not really matter so much, but it will make things easier.

    Кстати как показывает практика художники хотят разных партикл типов – включая Rays, beams, trails, arbitary oriented quads ну и даже меши.

    Те в принципе если рассматривать particle system как robust effects system – то camera oriented quads уже не катят.

    В общем я к тому говорю – что вот мне пришлось переписать практически с нуля PS для того чтобы все вышеперечисленное поддерживать с разумной скоростью.

    Понятно что на боксе и ps3 основной затык – это fillrate, на писи еще и драйвера – те lock/unlock.

  • http://zeux.livejournal.com/ Zeux

    Угу, не вопрос – задачи у всех разные. Кое-что из этого разумно делать так же, как написано, кое-что – вроде как совсем другой рендер.

  • IronPeter

    Я основного поинта не понял. Поделить данные на два стрима – оно очевидно. Если утверждается, что партиклов немного, то совершенно нет разницы, рисовать из двух стримов или одного. Если не понравится – можно резко переделать, поменять два на один, потом заюзать SPU.

    Другие решения важны, которые влияют на способ производства арта. Скажем, such as, all parameters are controlled by splines, and splines come from some particle editor – perhaps also there is some collision detection. Это серьезное решение, так как сразу встает вопрос, внутренний редактор или внешний. perhaps тоже важен – так как интеграция с физикой может требовать крови.

    Сравнительно важны решения вроде использования smooth particles ( для всех партиклов, для части ?), так как требуют отдельного прохода для глубины и являются комплексными. Важны решения по сортировке партиклов ( внутри эффектов, глобально ? ), так как влияют на менеджмент текстур. Важны решения по взаимодействию с прочей полупрозрачной сценой. Скорее всего, твой проход для партиклов будет разбит рисованиями полупрозрачных мешей. Причем часть этих мешей будет иметь похожее поведение, в стиле поста от 11:41, и тебе надо будет принимать волевые решения, объединять архитектурно или делать совсем другой рендер. Rays c анимированными параметрами – он в том же редакторе анимируется, или это mesh со скелетной анимацией? Решения “разделить или объединить” – они требуют большой крови.

    Художники хотят странного. Например, они хотят брать системы частиц и проектировать как деколы на геометрию. С одной этой маленькой заморочкой тебе надо будет писать кода больше, чем для всех 3 рендеров. Или меньше, если у тебя есть буфер глубины как текстура.

  • http://zeux.livejournal.com/ Zeux

    Немного – оно относительно. Экономия – не в рисовании, в заполнении.

    Все остальное, о чем ты пишешь – к посту просто не относится, это совсем другие проблемы.

    Пойнт простой – инстансинг типично рекламируется как решение для уменьшения draw calls – было 100 мешей, стал 1 draw call. Инстансинг в малом в этом свете далеко не для всех очевиден. Все.

  • Sergei_am

    Да, пост про партиклъ в виде – все кроме инстансинга – ето тоже будет интересно… :)

    Вот про rays партиклами – я етого не понимаю, дайте пример из жизни где их много и они что-то делают? Меш + скелетка тут подойдет на ура имхо.
    Трейлс в виде партиклов – ето прикольно. Но – ето очень очень характерное.
    Я про то – что у *людей*, в *движках*, есть партиклъ с 10-12 UI бутонами для настройки *всей* системъ. И живут, типа 90% ефектов покръли гравитацией и анимацией размера,альфъ,угла партиклов…
    С другой сторонъ есть ETQW, где трейлъ настоящий next-gen.

  • IronPeter

    >инстансинг типично рекламируется как решение для уменьшения draw calls

    первая же строчка по гуглю “instancing particles DX9″ выдает вот что в pdf-ке:

    Many Instance of Same Model– Forest of trees, particle systems, sprites• Encode per-instance data in auxiliary stream– Colors, texture coordinates, per-instance consts•

    Вроде как неважно, что ставить в делитель частоты – 4 или 4096?

    Вот лично у меня размер particle – 32 байта, координата там 12 байт. Сокращение в 4 раза потока вершин даст 24 байта на вершину. Такого сокращения размера проще добиться снижением битности.

    Один стрим на старом железе – сильно лучше чем два. Тем более с делителями частоты.

    >Все остальное, о чем ты пишешь – к посту просто не относится, это совсем другие проблемы.

    проблемы, которые сочатся кровью – сильно интереснее тех, которые минорны и не сочатся.

  • IronPeter

    rays партиклами – легко. MMO игра, а которой много заклинаний вроде молний. В том же HL было очень много эффектов в виде изломанных полос с натянутыми текстурами. Они должны рисоваться вместе с партиклами.

  • http://zeux.livejournal.com/ Zeux

    В общем, я честно написал, что как бы nothing new or complex. Никакой конкретики не видел – теперь она есть, все просто.

    > Вот лично у меня размер particle – 32 байта, координата там 12 байт. Сокращение в 4 раза потока
    > вершин даст 24 байта на вершину. Такого сокращения размера проще добиться снижением битности.
    Ну, эээ, количество вершин вообще-то уменьшится в 4 раза.

    > Один стрим на старом железе – сильно лучше чем два. Тем более с делителями частоты.
    Это не будет проблемой. К тому же, второй стрим – очень маленький. Совсем не уверен в том, что будет сильно отличаться скорость vertex processing.

    > проблемы, которые сочатся кровью – сильно интереснее тех, которые минорны и не сочатся.
    Ну вот я пишу о том, на что знаю ответы. Почему ты не пишешь про те, которые сочатся кровью? ;-)

  • IronPeter

    >Ну, эээ, количество вершин вообще-то уменьшится в 4 раза.

    А если в краевых точках партикла уникальные данные? By design.

  • Sergei_am

    Про рисоватся вместе – без проблем, если не нужна сортировка между отдельнъми квадами обоих типов ефектов. В таком случае, почему ето партиклъ, а не кастомнъй построитель геометрии?
    Вообще-то, есть такое что все ето квадъ, некоторъе ориентируются к камере, некоторъе к камере по оси. *Если* не проблем, что на стъках кусков молнии скажем, будут зазоръ или неодинакого ориентираннъе квадъ (т.е. молния не цельнъй стрип), то да – все ето можно закодать единной системой, где единная сортировка, по необходимости когда системъ пересекаются их можно сортировать вместе и т.д.
    Вот интересно, когда разнъе типъ блендинга и надо сортировать – как бъть? Premultiplied alpha – ето прекрасно, но как ету красоту фейдить на расстоянии…

  • http://zeux.livejournal.com/ Zeux

    > А если в краевых точках партикла уникальные данные? By design.
    Тогда это совсем не те партиклы, про которые я говорю. Более того, вполне допускаю, что есть и те, и другие, и что нужно два солюшена.
    Уникальные кстати это какие?

  • IronPeter

    Сойдемся на том, у меня другие партиклы, не твои. Два солюшена – это плохо из-за проблем с сортировкой.

  • lordmaze

    Mozhno kstati vspomnit chto u particle mogut bit animated textures – te po suti UV animation. Nu ili dazhe ne animated a tupo UV Scrolling..

    V obschem – skazhem tak proposed solution – on naverno horosh v kakom to sluchae, no esli delat realno complex particle system – dazhe urovnya UE3 – to budet zhopa.

    U nas naprimer seychas Editor dlya particlov – on na neskolkih Tabs okna tipa 700×1024. No zato umeet delat voobsche vsio chto mozhet pridti v bolnuu golovu artista :). I kak oni govoryat easy to use.

  • CEMEH

    Ну, разумеется, это не “универсальное решение для патиклов”. Насколько я понимаю, пойнт поста что в некоторых довольно распространенных требованиях можно эффективно пользовать инстансинг.

    lordmaze, кстати интересно какое там разнообразие у вас. И как вы его оптимизяете, если артист не выбрал какие-то возможности. Т.е. если уникальных атрибутов в каждой вершине скажем нет, вполне можно и нужно делать инстансинг.

  • lordmaze

    > lordmaze, кстати интересно какое там разнообразие у вас.
    > И как вы его оптимизяете, если артист не выбрал какие-то возможности.

    Znachit tak. Particle system sostoit iz Particle Elements. Features kazhdogo elementa :

    - Type: Camera Oriented quad, arbitary oriented quad ( te ugol v X/Y/Z ), Ray, Beam, Screen2D quad, static mesh.
    - Kucha over life values – size, velocity, color, alpha, etc… – vsego okolo 15 parametrov – vse controlled by spline.
    - UV scrolling. Otdelno spline controlled po U i V
    - UV Animation – te texture atlas tipa. Eto usaet blending between frames – te na vertex – 2 seta UV’s

    Nu tam est globalnie parametri – sort/ne srot, soft particle/ne soft particles, etc…

    Vse raschioti delautsya na CPU. Na PC – esli est dva core – to otdelniy thread na vtorom core. Na xbox – vsegda na 3em core. na ps3 – tam chuvak seychas codit chtobi na spu vsio delalos :)

    Razmer vertexa – 36byte. Position, Color, float2 UV, float3 UV.

    Experimentirovali s UV v byte – ie color – v 90% normalno, v 10% teryatesya precision.

    Odin zdoroviy indexed vertex buffer – na danniy moment razmer fiksirovan na 10000 quads – quad sootvetstvenno 4 vertexa – te 1.4mb + index.

    Itak :) – na boxe srazu CPU pishet v vertex/index buffer. Sootvetstvenno poka on pishet oblast nedostupna dlya chteniya/rendering. Na PC – standartniy lock/unlock.

    Dalee tantsi s bubnami. U nas mnogoprohodoviy rendering. Te naprimer Glow pass – on renderitsya v separate RGB buffer ( buffer tochnee odin na raznie operations ). Eschio est distortion pass. Pochemu ne v odin prohod ? Potomu chto odnogo buffera ne hvatit store vsio chto nado, a MRT – dorogoe. Na PC vo vsyakom sluchae.

    Itak v samom plohom sluchae PS renderitsya za kadr 3 raza. Raznimi shaders.

    LOD i shaderov net. Est LOD na urvone renderit ili net prohod + skolko particles renderit.

    Samoe plohoe – Meshes. Est dva rezhima – v odnom – mesh renderitsya bez vsyakogo sveta/materials/shadow. Te tupo DIP na mesh. Tochnee – ne DIP na mesh – a DIP na special vertex buffer array v kotorom copii 16 meshes – te takoy vot tupoy “instancing” – te esli u tebya 17 meshes – to budet 2 DIP.

    Vtoroy mode – kogda mesh – polnotsenniy mesh s collisions, materials, lighting i shadows. Nu tut vsio ploho i mi ne osobo pooschryaem takie PS :)))

    Pro instancing – moy point v tom chto u nas skazhem na ekrane mozhet bit 40 raznih particle systems. I dazhe esli delat hitrozhopie vertex streams – kstati eto tormoznee chem single stream. Nu tak vot – prosto tupo setup etih PS s lock/unlocks ub’et ves performance gain. imho konechno.

    Nu i eta – tak ili inache vsio upretsya v fillrate. Te ochen slozhnaya bolshaya PS s tisyachami particles – ona ub’et performance na fillrate….

  • CEMEH

    36 – плохо. Может, можно UV в short?
    А так, есть мнение, что можно ужимать до параметров одного вертуха. Т.е. задавать в ветрексе парой параметров положение в texture map, и потом в vertex shader реконструировать координаты.
    И делать инстансинг. В общем смысле, на все системы.

    Частично может и не в филлрейт упираться, вдалеке скажем.

  • IronPeter

    Инстансинг на все системы – это сомнительно. Часто хочется свободы. Эффекты в стиле QUAD_STRIP хочется сортировать вместе с партиклами. Идешь ты по пещере – из стен ебошатся молнии маленькие с дымом, красиво.

    Иногда хочется совсем странного. Скажем, чтобы меш с “партикл” материалом ( простенький шейдерец, текстуры в атласе ) взял и отсортировался вместе с партиклами. По треугольникам.

    Если не упирается в филлрейт – берешь и выкидываешь партиклы размером меньше пикселя. Оно перестает упираться.

    Предложенный инстансинк – это хорошо еще. Мы, старые пердуны, по инерции протестуем. В душе понимаем, что можно и так, параметров достаточно для артистов.

    А вот взять какие-нибудь “1M Particle System On The GPU”. Кто-то серьезно такие мануалы пишет.

  • Sergei_am

    А кто-то делал апдейтъ НЕ каждъй кадр. Соответно Lock/Unlock, раз 5-8 в сек. Все интерполируется (ну, хотя самое важное, т.е. цвет – нет, альфа – да)?
    Соответно, таже CPU работа тоже 5-8 раз в сек.
    Единственно vs более тяжел, как и сам вертекс.

    lordmaze, а у вас есть оптимизации формата вертекса, когда там простой ефект, т.е. цвет + альфа скажем, или формат фиксирован?
    И что с кодом? Т.е. как код адаптируется под конкретную партикл систему – codegen или чисто if/switch/virtual решение?

  • lordmaze

    > 36 – плохо. Может, можно UV в short?

    Как сказали тут недавно умные дяди из нвидии и ати – уже пофиг :). Если вертексы идут более менее последовательно – выравнивать уже ничего не нужно.

    > А так, есть мнение, что можно ужимать до параметров одного вертуха

    Ну ты пальцем покажи как :). Чтобы еще и инстансинг работал. Ты не забывай что например several streams – это performance hit – от 3-5% на мощных картах до 20% на древнем говне – это про PC конечно.

  • lordmaze

    > lordmaze, а у вас есть оптимизации формата вертекса, когда там простой ефект, т.е. цвет + альфа скажем, или формат
    > фиксирован?

    Нет формат фиксирован – ибо один буффер на все. Я игрался на боксе с несколькими форматами на один буффер – ускорения не увидел.

    > И что с кодом? Т.е. как код адаптируется под конкретную партикл систему – codegen или
    > чисто if/switch/virtual решение?

    Практически тупой switch. Собственно в одной системе как я писал могут быть партиклы разных видов – точнее в 90% так и есть. Собственно сам обсчет и генерация партиклов практически бесплатная – когда делали синтетический тест – те только расчет партиклов и генерация quadов – то типа 1M particles per frame занимает меньше 5% frame time ( в реальной игре ) на PC Core Duo 2GHZ.

    Про расчет не каждый кадр – на самом деле примерно так и происходит. Те есть PS процессится ( те тред wake up ) каждые 10 милисекунд. Далее есть параметр – частота обновления VI buffers. Это опять же валидно только для PC. На боксе все сразу пишется в буффер. Ну а рисование на каждом таки фрейме.

    Те – считаем PS в одном треде, а заполняем/рисуем – в основном game…

  • Sergei_am

    Я говорил про частоту обновления, но рендеринг продолжает интерполировать параметръ.
    Если обновление завязано с рендерингом, то вблизи очень видно разницу, когда fps въсокое.

  • http://zeux.livejournal.com/ Zeux

    > Nu tak vot – prosto tupo setup etih PS s lock/unlocks ub’et ves performance gain. imho konechno.
    Ммм… сетап этих PS… кол-во локов – то же, что и single stream. Сетап от обычного отличается вроде только еще одним стримом на боксе и еще двумя SetStreamSourceFreq на PC.
    > Инстансинг на все системы – это сомнительно. Часто хочется свободы. Эффекты в стиле QUAD_STRIP хочется сортировать вместе с партиклами. Идешь ты по пещере – из стен ебошатся молнии маленькие с дымом, красиво.
    Ну вот молнии вроде как – это просто arbitrary oriented quad, та же логика применима. Иногда молнии это тупо полоска честная, с как бы разными позициями – я и не претендую на универсальность решения, про пойнт уже сказано :)
    > когда делали синтетический тест – те только расчет партиклов и генерация quadов – то типа 1M particles per frame занимает меньше 5% frame time ( в реальной игре ) на PC Core Duo 2GHZ.
    Это какое-то очень странное число. Frame time на 30 fps – 33 msec. 5 процентов от этого – полторы мсек, или 3 миллиона тактов. Т.е. по 3 такта на партикл. С расчетом, quad expansion, заливкой тех 36 байтовых вертексов? Не верю.

  • http://zeux.livejournal.com/ Zeux

    Впрочем, если 5% от времени кадра это только заливка уже готового стрима, и партиклы считаются на втором ядре, то верю. Особенно, если апдейт занимает больше, чем 1 кадр :)

  • lordmaze

    > С расчетом, quad expansion, заливкой тех 36 байтовых вертексов?

    с генерацией вертексов но без заливки их в буффер.

    Но в общем да – глобально 5% – это по сути заливка вертексов.

    Смысл собственно в том что расчитать 1M партиклов можно – нарисовать уже нельзя никак и нигде.

  • IronPeter

    >Ну вот молнии вроде как – это просто arbitrary oriented quad, та же логика применима. Иногда молнии это тупо полоска честная, с как бы разными позициями – я и не претендую на универсальность решения, про пойнт уже сказано :)

    В HL2 очень много изломанных молний. Screen aligned расширение ломаной. Часто нужны вот какие партиклы, которые по сути представляют собой цилиндрик, quad ориентируется по оси так, чтобы занимать максимальную площадь. При виде в торец – или совсем плоский ( при этом полезно увести его прозрачность ) или кругляшок. Если кругляшок, то можно заблендать в другую текстурку. Оно можно на твоем подходе такое сэмулировать. Но для этого надо будет каким-то странным образом считать srceen space угол поворота, точку крепления партикла, так далее.

  • look4awhile

    “нарисовать” 1м в кадр при 60 фпс тоже можно – если учесть кулинг, отброс партиклов меньше пиксела итп. т.е. порядка 400-600к видимых партиклов вообщем-то реально. за исключением пустяка – смысла в таких партиклах, размером в пиксель, крайне мало. грамотный LOD на эффектах решает куда больше. “меньше качественных партиклов” на практике выглядит и работает значительно лучше.

  • lordmaze

    > “меньше качественных партиклов” на практике выглядит и работает значительно лучше.

    Vot vot :)

    Ya hudozhnikov “ubezhdau” chto nado ne delat PS s bolshe chem 100-300 active particles at any given moment.

    Rabotaet vpolne sebe.

  • lordmaze

    > “нарисовать” 1м в кадр при 60 фпс тоже можно

    Narisovat imenno 1M nelzya. Esli ne “uchitivat”…

    Te vot skazhi – nu kak ti s vmenyaenin fps narisuesh na lubom hardware 2M triangles kazhdiy nu skazhem tupo 100 pixeley ? i vse oni alpha blended ?

  • look4awhile

    200 мегапикселей? там quad-ы а не треугольники.
    причём ориентированные, скажем пойнтспрайты. такое можно.

    на “любом” хардваре я не знаю.
    на PC я вообще не понимаю как их в видеокарту засунуть с разумной скоростью.

  • lordmaze

    > 200 мегапикселей? там quad-ы а не треугольники.
    > причём ориентированные, скажем пойнтспрайты. такое можно.

    kakie orientirovannie ?

    Net v smisle – vot u tebya est neevicheskogo razmera buffer iz 2M triangles – 4M vertices. Triangles – sovsem randomnie. Skazhem net sovsem nmalenkih ( te menshe 20 pix mi cull ) i sootvetstvenno bolshih ( te 20% screen and more ) – ih ne bolshe 5-10%.

    200mpix fillrate s blendingom – pro eto ne zabivay.

    vot :)

    > на “любом” хардваре я не знаю.

    ya imel v vidu hardware kakoy hochesh. Na boxe ne rabotaet, na pc ne rabotaet, na ps3 – skazhem tak ya ne znau – u menya na ps3 zatiki s fillrate nachinautsya na menshem kolichestve triangles…

  • look4awhile

    point sprite надо, а не треугольники

  • lordmaze

    > point sprite надо, а не треугольники

    Чем они тебе помогут то ?

  • Knives

    36 байт вертекс плох для пс3, как мне сказали знающие люди потому я на пс3 забиваю простой буфер (28 байт на вертекс, если напишу халфовую арифметику то будет 24) на СПУ без всяких инстансингов. На боксе у меня, впрочем тоже нет инстансинга, я так понимаю, что гемморой с двумя стримами выйдет дороже чем один байт с индексом вершины. Хотя может быть перепишу под инстансинг потому как запись вертекс буфера у меня почему-то страшно тормозит.

    Филрейт я поборол как Моторсторм – рендерю патиклы в половинный буфер (могу и в четверной а могу вообще интерполировать его размеры), но затык у меня в другом – простая набивка вертексов (с лукапами текстур и цвета из табличек) дохуища времени занимает – я считал что 400 тактов на один сраный патикл о 4 вертексах, таблички вроде маленькие, непонятно. Наверное какие-нибудь флажки дурацкие стоят на памяти и с кэшем облом происходит или просто хбокс сосет так по жизни. Ну и еще сортировка неслабо жрет (потому как копируются патиклы туда-сюда, опять же из за памяти, думаю). На пс3 все пиздато работает.

  • Sergei_am

    Еще раз про ауторинг – вот кто-то все-таки сумел заюзать Max/Maya для етой цели. В связи с чем вопрос:
    – Оно трейлъ может?
    – Поддерживается ли блендинг и анимация текстур? В Max-е мне сказали, что не знают как такое можно сделать per-particle.
    – Можно ли зациклить партикл систему и смотреть на нее? В Max-е вроде нет.
    – Нормалмаппед партиклъ в Max-е можно смотреть? А du/dv? Или envmap? Т.е. интересует насколько оно будет не-WYSIWYG…

    Я лично все больше убеждаюсь, что писать редактор партиклов ето неправильно, но все еще есть вот ети моментъ, что въше.

  • IronPeter

    Ну я чуть знаю про Майку.

    Оно трейлы может, но в рантайме тебе скорее всего надо будет делать фичу “ориентация партикла по направлению скорости”.

    Анимация текстур поддерживается. Блендинг – неа, делай руками.

    Систему зациклить сложно, у нас в рантайме залупливается специальной мега-системой.

    Нормалмаппед и прочие вкусности – пиши джыдайский кастом рендер. В партикл систему можешь добавить per-particles attributes, заюзать на них всю машинерию mel. Для джыдаев.

  • lordmaze

    > 36 байт вертекс плох для пс3

    na ps3 mi ne derzhim 2 nabora UV. Posemu tozhe 28 bytes poluchaetsya. A prev frame UV v pixel shadere schitaetsya.

    > затык у меня в другом – простая набивка вертексов (с лукапами текстур и цвета из табличек)

    v smisle texture lookup v vertex shadere ? Nu da ono nebistroe na bokse. Te ono ne takoy kamatoz kak na 8series na PC, no vsio ravno ne free operation. Te – esli ih tam tipa 1 na vertex – to net problem voobsche. Esli ih 4 i bolshe – to SILNO medlenno.

    > Филрейт я поборол как Моторсторм – рендерю патиклы в половинный буфер

    Rabotaet tolko dlya Low Frequence particles. Hotya naverno zavisit ot genre eschio – te naprimer dumau v shooter – tam 90% particle low frequence.

    Ya delal odno vremya imposters – te particle systems kotorie tipa daleko renderil v odin buffer tozhe half size screen i potom prosto blendil quad s scenoy po depth. Nu i updatil tozhe ne kazhdiy frame.

  • Knives

    Не, я не делаю текстурные лукапы в вертекс шейдере – я в табличке смотрю текстурные координаты для данного патикла (у меня все патиклы замаплены в разные части одной большой текстуры).

    abotaet tolko dlya Low Frequence particles.
    Это чиго за зверь такой? Типо мало деталей в текстуре на патикле? Да, у меня редкий патикл замаплен больше чем на 32*32 кусочек, но у меня патиклы маленькие все равно и их дохуища (просто если стоять и смотреть, ни с кем не воевать – в кадре 1000 патиклов), половинный буффер совершенно незаметен, на четверном – некоторые эффекты начинают дрожать если знать куда смотреть.

  • lordmaze

    > Не, я не делаю текстурные лукапы в вертекс шейдере – я в табличке смотрю текстурные координаты для данного патикла (у меня все патиклы
    > замаплены в разные части одной большой текстуры).

    Тогда непонятно. В смысле что медленно.

    > Типо мало деталей в текстуре на патикле?

    Типа размазано все – дым там или glow какое. А например там текст – это high frequence потому что деталей надо много.

  • IronPeter

    Вот что интересно. А пытались сделать рисование партиклов на SPU? Блендинг может быть сильно быстрее RSX – за счет тайла в LS. Отсутствуют всякие неприятные Read-Write латентности блендинга.

    Наложение текстуры – опять можно серьезно думать. Потому что надо всего лишь вращать текстуру, параметры UV маппинга очень простые и регулярные.