Volumetric clouds [CODE]

Advanced game related topics
User avatar
minimy
Enthusiast
Enthusiast
Posts: 611
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Volumetric clouds [CODE]

Post by minimy »

Hello, after the video, the code is here. This code have a procedure to make the cloud, only one for call.
Have rain and storm effect with lights + particles.
For the clouds i use billboards.
Not tested in 6.2 but must work because is not complex code.

The winter is coming! :mrgreen: (john snow)

Code: Select all

;{ SISTEMA
UsePNGImageDecoder()

InitEngine3D(#PB_Engine3D_DebugLog):InitSprite():InitKeyboard():InitMouse()
OpenWindow(0, 0,0, 1280,720, "Clouds [Arrows= move]",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0),WindowHeight(0), 0, 0, 0)
CreateCamera(0,0,0,100,100):MoveCamera(camara,258.33,22.97,279.69,#PB_Absolute):CameraLookAt(0,0,0,0):CameraBackColor(0,$332211)
CreateLight(0,$ffffff,23,23,23)

Procedure   CameraUserControl(camera,speed.f=0.1,smooth.f=0.1,yfixed.f=1e10)
  Static.f MouseX,Mousey,depx,depz,sdepx,sdepz,     fdf.b
  
  depx=-speed*(KeyboardPushed(#PB_Key_Left)-KeyboardPushed(#PB_Key_Right))
  depz=-speed*(KeyboardPushed(#PB_Key_Down)-KeyboardPushed(#PB_Key_Up)-MouseWheel()*40)
;   depx=-speed*(KeyboardPushed(#PB_Key_A)-KeyboardPushed(#PB_Key_D))
;   depz=-speed*(KeyboardPushed(#PB_Key_S)-KeyboardPushed(#PB_Key_W)-MouseWheel()*20)
  If KeyboardReleased(#PB_Key_F12):fdf=1-fdf:If fdf:CameraRenderMode(0,#PB_Camera_Wireframe):Else:CameraRenderMode(0,#PB_Camera_Textured):EndIf:EndIf
  MouseX = -MouseDeltaX() *  0.05
  MouseY = -MouseDeltaY() *  0.05
  RotateCamera(camera, MouseY, MouseX, 0, #PB_Relative)
  sdepx+(depx-sdepx)*smooth
  sdepz+(depz-sdepz)*smooth
  MoveCamera  (camera, sdepX, 0, -sdepz)
  If yfixed<>1e10:MoveCamera(camera,CameraX(camera),yfixed,CameraZ(camera),#PB_Absolute):EndIf
EndProcedure
;}

;{ NUBES
Structure nube_data
  tt3D.i
  tt3Ddark.i
  mate.i
  mateDark.i
  bill.i
  Array b.i(50)
  billdark.i
  Array bd.i(50)
EndStructure
Global NewList nube.nube_data()
Procedure   nubeAdd(x,y,z, w=20,h=5, quality.a=60)
  Protected.f nx,ny,nz
  Static.f s
  Protected   q= quality*5
  Protected   i=  CreateImage(#PB_Any,q,q,32,#PB_Image_Transparent)
  Protected   ii= CreateImage(#PB_Any,q,q,32,#PB_Image_Transparent)
  AddElement(nube())
  ReDim nube()\b(quality)
  ReDim nube()\bd(quality)
  
  ;oscuro
  nube()\tt3Ddark= CreateTexture(#PB_Any,q,q)
  StartDrawing(ImageOutput(ii))
    DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Gradient)
    BackColor($eedddddd)
    GradientColor(0.7,$eedddddd)
    FrontColor($00dddddd)
    For p= 1 To 10
      nz= Random(q*0.4,q*0.2)
      nx= Random(q-(nz*2))+nz
      ny= Random(q-(nz*2))+nz
      CircularGradient(nx,ny,nz)
      Circle(nx,ny,nz)
    Next p
  StopDrawing()
  StartDrawing(TextureOutput(nube()\tt3Ddark))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Box(0,0,q,q,$00888888)
    DrawAlphaImage(ImageID(ii),0,0)
  StopDrawing()
  
  nube()\mateDark= CreateMaterial(#PB_Any,TextureID(nube()\tt3Ddark))
  MaterialBlendingMode(nube()\mateDark,#PB_Material_AlphaBlend)
  SetMaterialAttribute(nube()\mateDark,#PB_Material_AlphaReject,1)
  SetMaterialAttribute(nube()\mateDark,#PB_Material_DepthCheck,0)
  SetMaterialAttribute(nube()\mateDark,#PB_Material_TAM,1)
  SetMaterialColor(nube()\mateDark,#PB_Material_DiffuseColor, $ffffffff)
  nube()\billdark= CreateBillboardGroup(#PB_Any,MaterialID(nube()\mateDark), 100,100, x,y,z)
  
  For p=0 To quality/2
    nx= Random(w)-(w/2)
    ny= -Random(h*0.75,h*0.25)
    nz= Random(h)-(h/2)
    nube()\bd(p)= AddBillboard(nube()\billdark, nx,ny,nz)
    If p%2=0
    s= Random(h,h*0.5) + (Random(w)*0.1)
    EndIf
    ResizeBillboard(nube()\bd(p), nube()\billdark, s,s)
  Next p
  
  ;claro
  nube()\tt3D= CreateTexture(#PB_Any,q,q)
  StartDrawing(ImageOutput(i))
    DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Gradient)
    BackColor($eeffffff)
    GradientColor(0.7,$eeffffff)
    FrontColor($00ffffff)
    For p= 1 To 10
      nz= Random(q*0.4,q*0.2)
      nx= Random(q-(nz*2))+nz
      ny= Random(q-(nz*2))+nz
      CircularGradient(nx,ny,nz)
      Circle(nx,ny,nz)
    Next p
  StopDrawing()
  StartDrawing(TextureOutput(nube()\tt3D))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Box(0,0,q,q,$00ffffff)
    DrawAlphaImage(ImageID(i),0,0)
  StopDrawing()
;   showImage(i)
  
  nube()\mate= CreateMaterial(#PB_Any,TextureID(nube()\tt3D))
  MaterialBlendingMode(nube()\mate,#PB_Material_AlphaBlend)
  SetMaterialAttribute(nube()\mate,#PB_Material_DepthCheck,0)
  SetMaterialAttribute(nube()\mate,#PB_Material_TAM,1)
  nube()\bill= CreateBillboardGroup(#PB_Any,MaterialID(nube()\mate), 100,100, x,y,z)
  
  For p=0 To quality/2
    nx= Random(w)-(w/2)
    ny= Random(h)-(h/2)
    nz= Random(h)-(h/2)
    nube()\b(p)= AddBillboard(nube()\bill, nx,ny,nz)
    If p%2=0
    s= Random(h,h*0.5) + (Random(w)*0.1)
    EndIf
    ResizeBillboard(nube()\b(p), nube()\bill, s,s)
  Next p
  
EndProcedure

i= CreateImage(#PB_Any,32,128,32,#PB_Image_Transparent)
StartVectorDrawing(ImageVectorOutput(i))
  VectorSourceLinearGradient(0, 0, 32, 128)
  VectorSourceGradientColor($ff999999, 0.0)
  VectorSourceGradientColor($99ff9966, 0.5)
  VectorSourceGradientColor($00000000, 1.0)
  MovePathCursor(0,0):AddPathLine(32,128)
  StrokePath(2)
StopVectorDrawing()
  
tt3d= CreateTexture(#PB_Any,32,128)
StartDrawing(TextureOutput(tt3d))
  DrawingMode(#PB_2DDrawing_AllChannels)
  Box(0,0,OutputWidth(),OutputHeight(),$00000000)
  DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Gradient)
  DrawAlphaImage(ImageID(i),0,0)
StopDrawing()
CreateMaterial(0, TextureID(tt3d))
DisableMaterialLighting(0, 1)
MaterialBlendingMode(0, #PB_Material_AlphaBlend)

Dim l(10)
For p= 1 To 10
  x= Random(400,300)-200
  y= Random(10)+10
  z= Random(400,300)-200
  w= Random(30,20)
  h= Random(20,10)
  nubeAdd(x,y,z,w,h,60)
  l(p)= CreateLight(#PB_Any,$ff8800,x,y,z)
  HideLight(l(p),1)
  
  part= CreateParticleEmitter(#PB_Any, w,w,h, #PB_Particle_Box, x,y-(h*0.6),z)
  ParticleMaterial(part, MaterialID(0))
  ParticleSpeedFactor(part, 6)
  ParticleVelocity(part,#PB_Particle_MinimumVelocity,10)
  ParticleVelocity(part,#PB_Particle_MaximumVelocity,20)
  ParticleEmitterDirection(part, 0.1,-1,-0.1)
  ParticleEmissionRate(part, 20)
  ParticleTimeToLive(part, 4, 6)
  ParticleSize(part, 5,20)
  ParticleColorFader(part,-0.1,-0.1,-0.1,-0.1)
Next p


;}


Repeat
  While WindowEvent():Wend
  ExamineMouse(): ExamineKeyboard()
  
  CompilerIf #PB_Compiler_Version => 620
    CameraUserControl(0,0.5)
  CompilerElse
    CameraUserControl(0,0.05)
  CompilerEndIf

  renderTime= RenderWorld()
  
  For p= 1 To 10
    HideLight(l(p),1)
  Next p
  CameraBackColor(0,$332211)
  For p= 1 To 10
    If Random(200)= p
      SetLightColor(l(p),#PB_Light_DiffuseColor,RGB(Random(55),Random(155),Random(255,155)))
      HideLight(l(p),0)
      If Random(10)=0
        CameraBackColor(0,$664422)
      EndIf
    EndIf
  Next p
  
  FlipBuffers()
  
Until KeyboardPushed(#PB_Key_Escape)
End

If translation=Error: reply="Sorry, Im Spanish": Endif
User avatar
Piero
Addict
Addict
Posts: 905
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Volumetric clouds [CODE]

Post by Piero »

Nice! :D
Works well on Mac 6.21!

PS: It's better here if I "adjust" it to part= CreateParticleEmitter(#PB_Any, w,h …
User avatar
idle
Always Here
Always Here
Posts: 5886
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Volumetric clouds [CODE]

Post by idle »

That works really well. win11 6.20, Thanks for sharing.
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 193
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Re: Volumetric clouds [CODE]

Post by moulder61 »

Works nicely in Linux too using PB 6.21. :D

Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
threedslider
Enthusiast
Enthusiast
Posts: 396
Joined: Sat Feb 12, 2022 7:15 pm

Re: Volumetric clouds [CODE]

Post by threedslider »

Awesome ! Thanks for sharing :D

It works on PB 6.21 very good !
User avatar
minimy
Enthusiast
Enthusiast
Posts: 611
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: Volumetric clouds [CODE]

Post by minimy »

Nice to know work in all OS. Thanks for testing friends!
If translation=Error: reply="Sorry, Im Spanish": Endif
miso
Enthusiast
Enthusiast
Posts: 464
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: Volumetric clouds [CODE]

Post by miso »

Nice one, works here perfectly too.
User avatar
minimy
Enthusiast
Enthusiast
Posts: 611
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: Volumetric clouds [CODE] v2

Post by minimy »

This is my new version of clouds.
Air war games are possible now :mrgreen:
Hope you like it. Please,
if you improve this code, share it. Remember that if no one shares, no one learns. Incluiding you.

Code: Select all

;{ INICIALIZA SISTEMA 3D e INTERFAZ
InitEngine3D(#PB_Engine3D_DebugLog):InitSprite():InitKeyboard():InitMouse()
OpenWindow(0, 0,0, 1280,720, "NUBES (CLOUDS) - minimy 2025 [ARROWS TO MOVE]",#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0),WindowHeight(0), 0, 0, 0)

CreateCamera(0,0,0,100,100)
MoveCamera(camara,0,-10,-50,#PB_Absolute):CameraLookAt(0,0,5,0):CameraBackColor(0,$885533):CameraRange(0,0.1,1000)
CreateLight(0,$ffffff,0,0,0)

Procedure   CameraUserControl(camera,speed.f=0.1,smooth.f=0.1,yfixed.f=1e10)
  ;This procedure is by pf_shadoko (Thanks!!!)
  Static.f MouseX,Mousey,depx,depz,sdepx,sdepz,     fdf.b
  depx=-speed*(KeyboardPushed(#PB_Key_Left)-KeyboardPushed(#PB_Key_Right))
  depz=-speed*(KeyboardPushed(#PB_Key_Down)-KeyboardPushed(#PB_Key_Up)-MouseWheel()*40)
;   depx=-speed*(KeyboardPushed(#PB_Key_A)-KeyboardPushed(#PB_Key_D))
;   depz=-speed*(KeyboardPushed(#PB_Key_S)-KeyboardPushed(#PB_Key_W)-MouseWheel()*20)
  MouseX = -MouseDeltaX() *  0.05
  MouseY = -MouseDeltaY() *  0.05
  RotateCamera(camera, MouseY, MouseX, 0, #PB_Relative)
  sdepx+(depx-sdepx)*smooth
  sdepz+(depz-sdepz)*smooth
  MoveCamera  (camera, sdepX, 0, -sdepz)
  If yfixed<>1e10:MoveCamera(camera,CameraX(camera),yfixed,CameraZ(camera),#PB_Absolute):EndIf
EndProcedure
;}


;{ CLOUDS
Structure cloud_bill
  p.Vector3
  s.Vector3
  b.i
EndStructure
Structure cloud_data
  p.Vector3
  bill.i
  Array b.cloud_bill(50)
EndStructure
Structure cloud_item
  List nube. cloud_data()
  tt3d.i
  mate.i
EndStructure
Global cloud.cloud_item

Procedure   nubeIni(w=256,h=256)
  cloud\tt3d= CreateTexture(#PB_Any,w,h)
  StartDrawing(TextureOutput(cloud\tt3d))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Box(0,0,OutputWidth(),OutputHeight(),$00ffffff)
    DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Gradient)
    For p= 1 To 50
    RandomSeed(2025*p)
      r= Random(OutputWidth()/4,OutputWidth()/8)
      x= r+Random(w-(r*2),r/2)
      y= r+Random(h-(r*2),r/2)
      BackColor( $aaffffff);RGBA(Random(50,10),Random(255,155),Random(255,240), 255 ) )
      FrontColor($00eeeeee)
      CircularGradient(x,y,r)
      Circle(x,y,r)
      Delay(1)
    Next p
  StopDrawing()
  cloud\mate= CreateMaterial(#PB_Any,TextureID(cloud\tt3d))
  MaterialBlendingMode(cloud\mate,#PB_Material_AlphaBlend)
  SetMaterialAttribute(cloud\mate,#PB_Material_DepthWrite,0)
  SetMaterialAttribute(cloud\mate,#PB_Material_AlphaReject,1)
  SetMaterialAttribute(cloud\mate,#PB_Material_TAM,1)
  SetMaterialColor(cloud\mate,#PB_Material_AmbientColor,$ffffffff)
  SetMaterialColor(cloud\mate,#PB_Material_DiffuseColor,$99ffffff)
  SetMaterialColor(cloud\mate,#PB_Material_SelfIlluminationColor,$ffffff)
MaterialFilteringMode(cloud\mate,#PB_Material_Trilinear)
EndProcedure
Procedure   nubeAdd(x.f,y.f,z.f, w=8,h=4, part=5)
  Protected.f bx,by,bz
  AddElement(cloud\nube())
  cloud\nube()\p\x= x
  cloud\nube()\p\y= y
  cloud\nube()\p\z= z
  ReDim cloud\nube()\b(part)
  cloud\nube()\bill= CreateBillboardGroup(#PB_Any,MaterialID(cloud\mate), w,h, x,y,z)
  For p= 1 To part
    cloud\nube()\b(p)\p\x=  Random(w)-(w/2) +(Random(10,1)*0.1)
    cloud\nube()\b(p)\p\y=  Random(h)-(h/2) +(Random(10,1)*0.1)
    cloud\nube()\b(p)\p\z=  Random(h)-(h/2) +(Random(10,1)*0.1)
    cloud\nube()\b(p)\b=    AddBillboard(cloud\nube()\bill, cloud\nube()\b(p)\p\x, cloud\nube()\b(p)\p\y, cloud\nube()\b(p)\p\z)
    cloud\nube()\b(p)\s\x=  Random(w,w/4); -(w/4)
    cloud\nube()\b(p)\s\y=  Random(cloud\nube()\b(p)\s\x,cloud\nube()\b(p)\s\x/2); -(h/4)
    ResizeBillboard(cloud\nube()\b(p)\b, cloud\nube()\bill, cloud\nube()\b(p)\s\x,cloud\nube()\b(p)\s\y)
  Next p
EndProcedure
;}

;---- INICIO

t= CreateTexture(#PB_Any,1024,256)
StartDrawing(TextureOutput(t))
DrawingMode(#PB_2DDrawing_Gradient)
FrontColor($557799)
GradientColor(0.85,$6688aa)
GradientColor(0.5,$ff7733)
GradientColor(0.35,$ff7799)
GradientColor(0.15,$883300)
BackColor($000000)
LinearGradient(0,0,0,OutputHeight())
Box(0,0,OutputWidth(),OutputHeight())
DrawingMode(#PB_2DDrawing_AlphaBlend)
For p= 0 To 100
  Plot(Random(OutputWidth()-1), Random(OutputHeight()/2),RGBA(Random(255),Random(100),Random(255),Random(255,50)))
Next p
StopDrawing()
m= CreateMaterial(#PB_Any,TextureID(t))
DisableMaterialLighting(m,1)
MaterialCullingMode(m,#PB_Material_NoCulling)
b= CreateSphere(#PB_Any,1)
e= CreateEntity(#PB_Any,MeshID(b),MaterialID(m))
ScaleEntity(e,500,20,500)


CreateSpline(0)
nubeIni()
For p= 0 To 360
  For n= 1 To 6
    nx= Cos(Radian(p)) * Random(130.25)
    nz= Sin(Radian(p)) * Random(130,25)
    nubeAdd(nx,Random(10)-20, nz, Random(10,5))
  Next n
  nx= Cos(Radian(p)) * 40
  nz= Sin(Radian(p)) * 40
  If p%15=0:
    AddSplinePoint(0,nx,-5+Random(1)-2,nz)
  EndIf
Next p

tim.f= 0
Repeat
  While WindowEvent():Wend
  
  ExamineMouse(): ExamineKeyboard()
  CompilerIf #PB_Compiler_Version >= 610
    CameraUserControl(0,0.5)
  CompilerElse
    CameraUserControl(0,0.001)
  CompilerEndIf
  
  MoveCamera(0, SplineX(0),SplineY(0),SplineZ(0),#PB_Absolute)
  ComputeSpline(0,tim)
  CameraLookAt(0,SplineX(0),SplineY(0),SplineZ(0))
  tim + 0.0005:If tim>1:tim=0:EndIf
  
  renderTime= RenderWorld()

  FlipBuffers()
  Delay(1)
Until KeyboardPushed(#PB_Key_Escape)
End
If translation=Error: reply="Sorry, Im Spanish": Endif
User avatar
idle
Always Here
Always Here
Posts: 5886
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Volumetric clouds [CODE]

Post by idle »

that looks great!
miso
Enthusiast
Enthusiast
Posts: 464
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: Volumetric clouds [CODE]

Post by miso »

Yes, Looks much better than the first one. Grat.
User avatar
minimy
Enthusiast
Enthusiast
Posts: 611
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: Volumetric clouds [CODE]

Post by minimy »

Thank you guys!!
May look better if load a good texture with more resolution. The generated texture is very simple. The important thing is the idea i think. :D
If translation=Error: reply="Sorry, Im Spanish": Endif
dige
Addict
Addict
Posts: 1404
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: Volumetric clouds [CODE]

Post by dige »

It's incredible; I could watch this for hours.. 👍👍
"Daddy, I'll run faster, then it is not so far..."
Sergey
User
User
Posts: 57
Joined: Wed Jan 12, 2022 2:41 pm

Re: Volumetric clouds [CODE]

Post by Sergey »

I can't control the camera, it constantly turns to the right. The arrows keys don't fart
Clouds look very beautiful. PureBasic 6.21 (Windows - x64)
threedslider
Enthusiast
Enthusiast
Posts: 396
Joined: Sat Feb 12, 2022 7:15 pm

Re: Volumetric clouds [CODE]

Post by threedslider »

Nice fly over the clouds ! :mrgreen:

Thanks for sharing as always !
User avatar
minimy
Enthusiast
Enthusiast
Posts: 611
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: Volumetric clouds [CODE]

Post by minimy »

dige wrote: Mon Aug 25, 2025 7:11 am It's incredible; I could watch this for hours.. 👍👍
Hey Dige! Hahaha me too. Now you're mesmerized! :lol:
I can't control the camera, it constantly turns to the right. The arrows keys don't fart
Hi sergey! Yes, my fault. Movement is automatic. (I forget rename the title :oops: )
Nice fly over the clouds ! :mrgreen:
Hello Threeslider, the effect is nice and not too heavy for the engine. I think billboards is more fast than particles to make clouds.

Thanks to all guys!
If translation=Error: reply="Sorry, Im Spanish": Endif
Post Reply