I was like thinking(tm), and it came to me this. All rockets make exhaust, and its a lot of cpu thinking on how to make it look pwety, and it still sucks. It looks 2003. So i was like thinking. Lets GPU handle rockets and smoke. And before youll jump to navier stokes and such, what if each physics frame we would draw new lines where smoke is made from last physics frame, and then blur and swirl them per each physics frame. I would see it as this:
After frame is rendered and smoke bitmap is rendered.
Smoke bitmap contains UV velocity data per pixel and pressure, and pixel color.
color[] float3
UVvel[] float3
there is a tillable noise texture made in blender with lots of swirls(distortion option),
and theres a normal map made out of it for bump.
swirls[] float3
The pitch consists of the main two buffers are sized third of monitor resolution, and it spans 3x the draw area.
( so effectively its same sized as screen, but main is viewable in middle square of 3x3.
Once the smoke happens from previous location, the line is drawn on UVvel, with UV velocity of 0 and pressure of set pressure, using width of line as needed per camera zoom, so its simple glline on texture using (u,v,pressure) as colors, with UV set as opposite of where the rocket is headed
Smoke is calculated per physics frame.
- theres application of swirls.
swirlpos = mix ( UVvel[].uv ; throw (UVvel[].uv at direction of swirls[].yx with same lenght) ; using pressure )
swirled_UVvel[] = UVvel[ pos + swirlpos ]
swirled_color[] = color[ pos + swirlpos ]
less pressure, more swirl aligned it becomes. same for color[]
yes, yx so its perpendicular to bump slope
what happens here is we use existing swirls in the swirl texture
and throw the speed vector at perpendicular to slope of the swirl from bumpmap.
- blur_UVvel[], blur_color[], vector3 is made (half the size of the pitch)
using gpu default blurring for mipmaps so its quick af.
additionally there need to be adjustments to uv depending on pressure
posN = pos+[ 0, 1]*epsylon; xN = blur_UVvel[ posN ]
posS = pos+[ 0,-1]*epsylon; xS = blur_UVvel[ posS ]
posW = pos+[ 1, 0]*epsylon; xW = blur_UVvel[ posW ]
posE = pos+[-1, 0]*epsylon; xE = blur_UVvel[ posE ]
pressures = ( posN*(1+xN.pressure) + posS*(1+xS.pressure) + posW*(1+xW.pressure) + posE*(1+xE.pressure) )
blur_UVvel[].uv = mix (
blur_UVvel[].uv ;
pressures / ( xN.pressure + xS.pressure + xW.pressure + xE.pressure + 4) ;
blur_UVvel[].pressure )
so it alters the direction, basing on the where the pressure is highest,
using pressure to figure out how strong the alteration is need to be made.
+4 because to avoid div/0
- next is calculated using:
mixer = swirled_UVvel[ swirled_UVVel[].uv ].pressure + entropy
UVvel[] = mix( swirled_UVvel[] ; blur_UVvel[] ; mixer )
color[] = mix( swirled_color[] ; blur_color[] ; mixer )
- and viewport adjustments for perspective and moving it around, so UVvel and color move and scale using simple scale and transform.
higher pressure, the more towards blur it goes.
entropy is constant to keep it going toward blur if there is no pressure, or uv next to a freshly drawn line.
thats why its needed to be done at physics frame
so yeah. its not navier stokes, but. it does its job, at cost of 5 texture lookups and 2x mipmaped blured textures.
as a bonus, you can add pressure eminating points with no color modifications where units are standing per each frame of physics, so you would have the effect of units walking through smoke. and smoke swirling around them.
and you can also use maps wind direction
so, at the end you have a smoke texture, that doesnt need constant calculations of ugly 3d lines, but it creates constant smoke effect that accumulates and swirls and dissipates
prolly some improvements need to be done like if blurred UVvel to 1/16 of UVvel shows no action then drop whole procedure in quadrant, but still it might be cool smoke
:)
i would so code it self but have other stuff to do rn.