I was writing for fluid simulaiton based on thttps://github.com/983/Fluid-Simulation in Purebasic but only in CPU not GPU... I think I have done from C++ to Purebasic quite good however it doesn't work very well in gl texture 2D as transparency so please checck out this C++ to compare with my source code

Here is my source code inspired from C++ :
Code: Select all
;;;
;;; Fluid Simulation v. 0.1
;;;
w.i = 512
h.i = 512
nx.i = 32
ny.i = 32
dt.f = 0.02
iterations.i = 5
vorticity.f = 10.0
Global texture
Structure vec2f
x.f
y.f
EndStructure
Myvar.vec2f
Structure vecvalue
Array values.vec2f(32*32)
EndStructure
Procedure idx(x.i, y.i)
Shared nx
Shared ny
; wrap around
xd = (x + nx) % nx
yd = (y + ny) % ny
ProcedureReturn xd + yd*nx
EndProcedure
Structure grid
x.i
y.i
EndStructure
Structure gridvalue
Array values.grid(32*32)
EndStructure
Dim old_velocity.vec2f(nx*ny)
Dim new_velocity.vec2f(nx*ny)
Dim old_density.grid(nx*ny)
Dim new_density.grid(nx*ny)
Dim pixels.grid(nx*ny)
Dim pixels_data(nx*ny)
Procedure draw(Array var.vec2f(1), n.i, mode.i)
glEnableClientState_(#GL_VERTEX_ARRAY)
glVertexPointer_(2, #GL_FLOAT, 0, var())
glDrawArrays_(mode, 0, n)
EndProcedure
Procedure draw_circle(x.f, y.f, r.f, n.i = 100)
Dim pos.vec2f(n)
MyVar.vec2f
For i = 1 To n
angle.f = 2.0*3.14159*i/n
MyVar\x = x
MyVar\y = y
pos(i)\x = MyVar\x + r*Cos(angle)
pos(i)\y = MyVar\y + r*Sin(angle)
Next
draw(pos(), n, #GL_LINE_LOOP)
FreeArray(pos())
EndProcedure
Procedure init()
Shared nx
Shared ny
Shared texture
Shared old_density()
Shared old_velocity()
Shared Myvar.vec2f
Myvar\x = 0.0
Myvar\y = 0.0
For y = 0 To ny-1
For n = 0 To nx-1
old_density(idx(n,y))\x = 0
old_density(idx(n,y))\y = 0
old_velocity(idx(n,y))\x = Myvar\x
old_velocity(idx(n,y))\y = Myvar\y
Next
Next
glEnable_(#GL_TEXTURE_2D)
glEnable_(#GL_BLEND)
glBlendFunc_(#GL_SRC_ALPHA, #GL_ONE_MINUS_SRC_ALPHA)
glGenTextures_(1, @texture)
glBindTexture_(#GL_TEXTURE_2D, texture)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_LINEAR)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MAG_FILTER, #GL_LINEAR)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_S, #GL_REPEAT)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_T, #GL_REPEAT)
glTexImage2D_(#GL_TEXTURE_2D, 0, #GL_RGBA, nx, ny, 0, #GL_RGBA, #GL_UNSIGNED_BYTE, #NUL)
EndProcedure
Procedure.f lerp(a.f, b.f, c.f)
ProcedureReturn (1.0 - c)*a + c*b
EndProcedure
Procedure.f interpolationX_d(Array g.grid(1), *var.vec2f, ax.i, ay.i)
ix.i = *var\x
iy.i = *var\y
ux.f = *var\x - ix
uy.f = *var\y - iy
ProcedureReturn lerp(lerp(g(idx(ax+0,ay+0))\x, g(idx(ax+1,ay+0))\x, ux), lerp(g(idx(ax+0,ay+1))\x, g(idx(ax+1,ay+1))\x + 0, ux), uy)
EndProcedure
Procedure.f interpolationY_d(Array g.grid(1), *var.vec2f, ax.i, ay.i)
ix.i = *var\x
iy.i = *var\y
ux.f = *var\x - ix
uy.f = *var\y - iy
ProcedureReturn lerp(lerp(g(idx(ax+0,ay+0))\y, g(idx(ax+1,ay+0))\y, ux), lerp(g(idx(ax+0,ay+1))\y, g(idx(ax+1,ay+1))\y + 0, ux), uy)
EndProcedure
Procedure.f interpolationX_v(Array g.vec2f(1), *var.vec2f, ax.i, ay.i)
ix.i = *var\x
iy.i = *var\y
ux.f = *var\x - ix
uy.f = *var\y - iy
ProcedureReturn lerp(lerp(g(idx(ax+0,ay+0))\x, g(idx(ax+1,ay+0))\x, ux), lerp(g(idx(ax+0,ay+1))\x, g(idx(ax+1,ay+1))\x + 0, ux), uy)
EndProcedure
Procedure.f interpolationY_v(Array g.vec2f(1), *var.vec2f, ax.i, ay.i)
ix.i = *var\x
iy.i = *var\y
ux.f = *var\x - ix
uy.f = *var\y - iy
ProcedureReturn lerp(lerp(g(idx(ax+0,ay+0))\y, g(idx(ax+1,ay+0))\y, ux), lerp(g(idx(ax+0,ay+1))\y, g(idx(ax+1,ay+1))\y + 0, ux), uy)
EndProcedure
Procedure swap_od_2_nd_x(Array od.grid(1), Array nd.grid(1), ax.i, ay.i)
Swap od(idx(ax,ay))\x, nd(idx(ax,ay))\x
EndProcedure
Procedure swap_od_2_nd_y(Array od.grid(1), Array nd.grid(1), ax.i, ay.i)
Swap od(idx(ax,ay))\y, nd(idx(ax,ay))\y
EndProcedure
Procedure swap_ov_2_nv_x(Array ov.vec2f(1), Array nv.vec2f(1), ax.i, ay.i)
Swap ov(idx(ax,ay))\x, nv(idx(ax,ay))\x
EndProcedure
Procedure swap_ov_2_nv_y(Array ov.vec2f(1), Array nv.vec2f(1), ax.i, ay.i)
Swap ov(idx(ax,ay))\y, nv(idx(ax,ay))\y
EndProcedure
Procedure advect_density()
Shared nx
Shared ny
Shared old_density()
Shared new_density()
Shared old_velocity()
Shared Myvar.vec2f
pos.vec2f
For y = 0 To ny-1
For x = 0 To nx-1
pos\x = Myvar\x - dt* old_velocity(idx(x,y))\x
pos\y = Myvar\y - dt* old_velocity(idx(x,y))\y
new_density(idx(x,y))\x = interpolationX_d(old_density(), @pos, x,y)
new_density(idx(x,y))\y = interpolationY_d(old_density(), @pos, y,y)
Next
Next
For y = 0 To ny-1
For x = 0 To nx-1
swap_od_2_nd_x(old_density(), new_density(), x,y)
swap_od_2_nd_y(old_density(), new_density(), x,y)
Next
Next
EndProcedure
Procedure advect_velocity()
Shared nx
Shared ny
Shared old_velocity()
Shared old_density()
Shared new_density()
Shared new_velocity()
Shared Myvar.vec2f
pos.vec2f
For y = 0 To ny-1
For x = 0 To nx-1
pos\x = Myvar\x - dt* old_velocity(idx(x,y))\x
pos\y = Myvar\y - dt* old_velocity(idx(x,y))\y
new_velocity(idx(x,y))\x = interpolationX_v(old_velocity(), @pos, x,y)
new_velocity(idx(x,y))\y = interpolationY_v(old_velocity(), @pos, x,y)
Next
Next
For y = 0 To ny-1
For x = 0 To nx-1
swap_ov_2_nv_x(old_velocity(), new_velocity(), x,y)
swap_ov_2_nv_y(old_velocity(), new_velocity(), x,y)
Next
Next
EndProcedure
Procedure diffuse_density()
Shared dt
Shared nx
Shared ny
Shared old_density()
Shared new_density()
sumX = 0
sumY = 0
diffusion.f = dt * 100.01
For y = 0 To ny-1
For x = 0 To nx-1
sumX = diffusion * ( old_density(idx(x-1,y+0))\x + old_density(idx(x+1,y+0))\x + old_density(idx(x+0,y-1))\x + old_density(idx(x+0,y+1))\x ) + old_density(idx(x+0,y+0))\x
sumY = diffusion * ( old_density(idx(x-1,y+0))\y + old_density(idx(x+1,y+0))\y + old_density(idx(x+0,y-1))\y + old_density(idx(x+0,y+1))\y ) + old_density(idx(x+0,y+0))\y
new_density(idx(x,y))\x = 1.0 / (1.0 + 4.0 * viscosity) * sumX
new_density(idx(x,y))\y = 1.0 / (1.0 + 4.0 * viscosity) * sumY
Next
Next
For y = 0 To ny-1
For x = 0 To nx-1
swap_od_2_nd_x(old_density(), new_density(), x,y)
swap_od_2_nd_y(old_density(), new_density(), x,y)
Next
Next
EndProcedure
Procedure diffuse_velocity()
Shared dt
Shared nx
Shared ny
Shared old_velocity()
Shared new_velocity()
sum.vec2f
viscosity.f = dt * 0.000001
For y = 0 To ny-1
For x = 0 To nx-1
sum\x = viscosity * ( old_velocity(idx(x-1,y+0))\x + old_velocity(idx(x+1,y+0))\x + old_velocity(idx(x+0,y-1))\x + old_velocity(idx(x+0,y+1))\x ) + old_velocity(idx(x+0,y+0))\x
sum\y = viscosity * ( old_velocity(idx(x-1,y+0))\y + old_velocity(idx(x+1,y+0))\y + old_velocity(idx(x+0,y-1))\y + old_velocity(idx(x+0,y+1))\y ) + old_velocity(idx(x+0,y+0))\y
new_velocity(idx(x,y))\x = 1.0 / (1.0 + 4.0 * viscosity) * sum\x
new_velocity(idx(x,y))\y = 1.0 / (1.0 + 4.0 * viscosity) * sum\y
Next
Next
For y = 0 To ny-1
For x = 0 To nx-1
swap_ov_2_nv_x(old_velocity(), new_velocity(), x,y)
swap_ov_2_nv_y(old_velocity(), new_velocity(), x,y)
Next
Next
EndProcedure
Procedure project_velocity()
Shared nx
Shared ny
Shared iterations
Shared old_velocity()
Dim p.grid(nx*ny)
Dim p2.grid(nx*ny)
Dim div.grid(nx*ny)
For y = 0 To ny-1
For x = 0 To nx-1
dx.f = old_velocity(idx(x+1,y+0))\x - old_velocity(idx(x-1,y+0))\x
dy.f = old_velocity(idx(x+0,y+1))\y - old_velocity(idx(x+0,y-1))\y
div(idx(x,y))\x = dx + dy
div(idx(x,y))\y = dx + dy
p(idx(x,y))\x = 0.0
p(idx(x,y))\y = 0.0
Next
Next
For k = 1 To iterations
For y = 0 To ny-1
For x = 0 To nx-1
sumX.f = -div(idx(x,y))\x + p(idx(x+1,y+0))\x + p(idx(x-1,y+0))\x + p(idx(x+0,y+1))\x + p(idx(x+0,y-1))\x
sumY.f = -div(idx(x,y))\y + p(idx(x+1,y+0))\y + p(idx(x-1,y+0))\y + p(idx(x+0,y+1))\y + p(idx(x+0,y-1))\y
p2(idx(x,y))\x = 0.25 * sumX
p2(idx(x,y))\y = 0.25 * sumY
Next
Next
For y = 0 To ny-1
For x = 0 To nx-1
swap_od_2_nd_x(p(), p2(), x,y)
swap_od_2_nd_y(p(), p2(), x,y)
Next
Next
Next
For y = 0 To ny-1
For x = 0 To nx-1
old_velocity(idx(x,y))\x = old_velocity(idx(x,y))\x - 0.5 * p(idx(x+1,y+0))\x - p(idx(x-1,y+0))\x
old_velocity(idx(x,y))\y = old_velocity(idx(x,y))\y - 0.5 * p(idx(x+0,y+1))\y - p(idx(x+0,y-1))\y
Next
Next
FreeArray(p())
FreeArray(p2())
FreeArray(div())
EndProcedure
Procedure.f curl(ax.i, ay.i)
Shared old_velocity()
ProcedureReturn old_velocity(idx(ax,ay+1))\x + old_velocity(idx(ax,ay-1))\x + old_velocity(idx(ax-1,ay))\y + old_velocity(idx(ax+1,ay))\y
EndProcedure
Procedure.f dot(*A_v.vec2f, *B_v.vec2f)
ProcedureReturn *A_v\x * *B_v\x + *B_v\y * *B_v\y
EndProcedure
Procedure.f length(*var.vec2f)
ProcedureReturn Sqr(dot(var, var))
EndProcedure
Procedure vorticity_confinement()
Shared nx
Shared ny
Shared new_velocity()
Shared old_velocity()
Dim abs_curl.grid(nx*ny)
Shared vorticity
For y = 0 To ny-1
For x = 0 To nx-1
abs_curl(idx(x,y))\x = Abs(curl(x,y))
abs_curl(idx(x,y))\y = Abs(curl(x,y))
Next
Next
For y = 0 To ny-1
For x = 0 To nx-1
direction.vec2f
direction\x = abs_curl(idx(x+0,y-1))\x - abs_curl(idx(x+0,y+1))\x
direction\y = abs_curl(idx(x+1,y+0))\y - abs_curl(idx(x-1,y+0))\y
direction\x = vorticity / (direction\x + 1e-5) * direction\x
direction\y = vorticity / (direction\y + 1e-5) * direction\y
If x < nx/2
direction\x = direction\x * 0.0
direction\y = direction\y * 0.0
EndIf
new_velocity(idx(x,y))\x = old_velocity(idx(x,y))\x + dt * curl(x, y) * direction\x
new_velocity(idx(x,y))\y = old_velocity(idx(x,y))\y + dt * curl(x, y) * direction\y
Next
Next
For y = 0 To ny-1
For x = 0 To nx-1
swap_ov_2_nv_x(old_velocity(), new_velocity(), x,y)
swap_ov_2_nv_y(old_velocity(), old_velocity(), x,y)
Next
Next
FreeArray(abs_curl())
EndProcedure
Procedure.f clamp(x.f, a.f, b.f)
If x < a
ProcedureReturn a
ElseIf x > b
ProcedureReturn b
Else
ProcedureReturn x
EndIf
EndProcedure
Procedure.f smoothstep(a.f, b.f, u.f)
t.f = clamp((u-a) / (b-a), 0.0, 1.0)
ProcedureReturn t*t * (3.0 - 2.0 * t)
EndProcedure
Procedure add_density(px.i, py.i, r.i = 10, value.f = 0.5)
Shared old_density()
For y = -r To r
For x = -r To r
d.f = Sqr(x*x + y*y)
u.f = smoothstep((r), 0.0, d)
old_density(idx(x,y))\x = old_density(idx(x,y))\x + u*value
old_density(idx(x,y))\y = old_density(idx(x,y))\y + u*value
Next
Next
EndProcedure
Procedure randf(a.f, b.f)
u.f = Random(1.0)
ProcedureReturn lerp(a, b, u)
EndProcedure
Procedure fluid_simulation_step()
Shared nx
Shared ny
Shared dt
Shared old_velocity()
Shared old_density()
Shared Myvar.vec2f
For y = 0 To ny-1
For x = 0 To nx-1
If (x > nx*0.5)
Continue
EndIf
r.f = 10.0
old_velocity(idx(x,y))\x = old_velocity(idx(x,y))\x + Random(RandomSeed(r))
old_velocity(idx(x,y))\y = old_velocity(idx(x,y))\y + Random(RandomSeed(r))
Next
Next
; dense regions rise up
For y = 0 To ny-1
For x = 0 To nx-1
old_velocity(idx(x,y))\x = ( old_velocity(idx(x,y) )\x * 20.0 - 5.0)*dt
old_velocity(idx(x,y))\y = ( old_velocity(idx(x,y) )\y * 20.0 - 5.0)*dt
Next
Next
;add_density(mouseX, mouseY, 10, 0.5)
; fast movement is dampened
For y = 0 To ny-1
For x = 0 To nx-1
old_velocity(idx(x,y))\x = old_velocity(idx(x,y))\x * 0.999
old_velocity(idx(x,y))\y = old_velocity(idx(x,y))\y * 0.999
Next
Next
; fade away
For y = 0 To ny-1
For x = 0 To nx-1
old_velocity(idx(x,y))\x = old_velocity(idx(x,y))\x * 0.99
old_velocity(idx(x,y))\y = old_velocity(idx(x,y))\y * 0.99
Next
Next
add_density(nx*0.25, 30)
add_density(nx*0.75, 30)
vorticity_confinement()
; diffuse_velocity()
; project_velocity()
advect_velocity()
project_velocity()
; diffuse_density()
advect_density()
Myvar\x = 0.0
Myvar\y = 0.0
; zero out stuff at bottom
For y = 0 To ny-1
For x = 0 To nx-1
If (y < 10)
old_density(idx(x,y))\x = 0.0
old_density(idx(x,y))\y = 0.0
old_velocity(idx(x,y))\x = Myvar\x
old_velocity(idx(x,y))\y = Myvar\y
EndIf
Next
Next
EndProcedure
Procedure My_Clamp(x.i, a.i, b.i)
If x < a
ProcedureReturn a
ElseIf x > b
ProcedureReturn b
Else
ProcedureReturn x
EndIf
EndProcedure
Procedure rgba32(r.i, g.i, b.i, a.i)
r = My_Clamp(r, 0, 255)
g = My_Clamp(g, 0, 255)
b = My_Clamp(b, 0, 255)
a = My_Clamp(a, 0, 255)
ProcedureReturn (a << 24) | (b << 16) | (g << 8) | r
EndProcedure
Procedure My_RGBA(r.f, g.f, b.f, a.f)
ProcedureReturn rgba32(r*256, g*256, b*256, a*256)
EndProcedure
Procedure on_frame()
Shared nx
Shared ny
Shared old_density()
Shared pixels_data()
;Shared pixels()
glClearColor_(0.0, 0.0, 0.0, 0.0)
glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)
fluid_simulation_step()
; density field To pixels
For y = 0 To ny-1
For x = 0 To nx-1
fdx.f = old_density(idx(x,y))\x
fdy.f = old_density(idx(x,y))\y
fd = Log((fdx+fdy)*0.25 + 1.0)
f3.f = fd*fd*fd
r.f = 1.5*fd
g.f = 1.5*f3
b.f = f3*f3
pixels_data(idx(x,y)) = RGBA(r, g, b, 1.0)
Next
Next
; upload pixels To texture
glBindTexture_(#GL_TEXTURE_2D, texture)
glTexSubImage2D_(#GL_TEXTURE_2D, 0, 0, 0, nx, ny, #GL_RGBA, #GL_UNSIGNED_BYTE, pixels_data() )
; draw texture
glBegin_(#GL_QUADS)
;glColor4f_(1.0, 0.0, 0.0, 0.5)
glTexCoord2f_(0.0, 0.0)
glVertex2f_(-1.0, -1.0)
glTexCoord2f_(1.0, 0.0)
glVertex2f_(1.0, -1.0)
glTexCoord2f_(1.0, 1.0)
glVertex2f_(1.0, 1.0)
glTexCoord2f_(0.0, 1.0)
glVertex2f_(-1.0, 1.0)
glEnd_()
EndProcedure
InitKeyboard()
InitSprite()
OpenWindow(0, 0, 0, 800, 600, "OpenGL : Test for Fire Simulation ", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 800, 600)
glMatrixMode_(#GL_PROJECTION)
glLoadIdentity_()
gluPerspective_(45.0, 800/600, 1.0, 60.0)
glMatrixMode_(#GL_MODELVIEW)
; glShadeModel_(#GL_SMOOTH)
; glEnable_(#GL_LIGHT0)
; glEnable_(#GL_LIGHTING)
; glEnable_(#GL_COLOR)
; glEnable_(#GL_TEXTURE)
; glEnable_(#GL_STENCIL)
glDisable_(#GL_DEPTH_TEST)
;glEnable_(#GL_CULL_FACE)
glViewport_(0, 0, 800, 600)
glTranslatef_(0.0, 0.0, -2.0)
Repeat
;glClearColor_(0.0, 0.0, 0.0, 0.0) ; background color
; glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)
Repeat
event = WindowEvent()
Select Event
Case #PB_Event_CloseWindow
quit = 1
EndSelect
Until event = 0
init()
on_frame()
FlipBuffers()
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape) Or quit = 1
FreeArray(old_density())
FreeArray(new_density())
FreeArray(old_velocity())
FreeArray(new_velocity())
FreeArray(pixels())
FreeArray(pixels_data())
Most important thing is my source code in Purebasic are well writing this way ?? Yes or No ?