Generating and saving random 3D cloud animations

Everything else that doesn't fall into one of the other PB categories.
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Generating and saving random 3D cloud animations

Post by Seymour Clufley »

I would like to generate random 3D animations (of moving clouds against a sky) at 1920x1080 resolution and save them as image sequences - numbered PNG files. Unfortunately, I have never done any 3D stuff with PB before. I have plenty of experience with the 2D functions, but none at all with the 3D functions.

Ogre seems capable of rendering good 3D clouds, but so does OpenGL, so I don't know which of these engines to choose. A complicating factor is that I don't know whether PB allows access to enough of the functions of these engines to draw good clouds. What would experienced users say about that?

Then there is the requirement to "record" the animations. Whether I choose OpenGL or Ogre (or some other system), I will need to be able to grab the animation 25 times a second and save it to file. Would screenshotting the window be the way to do this?

I get the feeling that this is not the kind of thing that PB's 3D engine is intended for, so I want to ask: is it insane to pursue this? Are the things I want to do actually possible with the current toolset in PB?

Thank you.
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Generating and saving random 3D cloud animations

Post by IdeasVacuum »

Hi Seymour, Another possible solution would be to take a sequence of time-lapse photos of the real thing?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: Generating and saving random 3D cloud animations

Post by Seymour Clufley »

Yes, but the point of this is to have a program set up so that I can just press F5 and get a new cloud sequence. :)
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Generating and saving random 3D cloud animations

Post by IdeasVacuum »

- take several sets of time lapse photos? :)
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: Generating and saving random 3D cloud animations

Post by Seymour Clufley »

Ha, unfortunately not. I am going to need possibly dozens of cloud animations.

Can anyone advise on the two challenges outlined above? Saving a 3D animation to image file, and generating high-quality 3D clouds? I'd be very grateful for any pointers.
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Generating and saving random 3D cloud animations

Post by davido »

@Seymour Clufley,

I believe Open CV will do this.

JHPJHP has made a huge project of making it accessible from PureBasic, perhaps you could ask him.
http://www.purebasic.fr/english/viewtop ... 12&t=57457

Also try Googling it as it seems that Photoshop can generate clouds, I think.
DE AA EB
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: Generating and saving random 3D cloud animations

Post by Seymour Clufley »

Davido,

Yes, Photoshop can generate clouds, but not 3D clouds, and in any case Photoshop can't be controlled from a PB program.

What do you think OpenCV could do? Rendering of 3D models?
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
User avatar
idle
Always Here
Always Here
Posts: 5093
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Generating and saving random 3D cloud animations

Post by idle »

have a google for cloud shader glsl, would this work?
https://www.shadertoy.com/view/XsjSRt
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
DK_PETER
Addict
Addict
Posts: 898
Joined: Sat Feb 19, 2011 10:06 am
Location: Denmark
Contact:

Re: Generating and saving random 3D cloud animations

Post by DK_PETER »

Or you could do something like this:

Download this image and save it at the same location as the source.

http://s000.tinyupload.com/?file_id=204 ... 9713839147

Code:

Code: Select all

;Modify as needed
;Try different cloud formations and skycolor etc...
;It's all about gfx...

UseJPEGImageDecoder()
UsePNGImageEncoder()

InitEngine3D()
InitSprite()
InitKeyboard()

#SeqMax = 60
#SkyColor = $FF9C39 ;Blue sky
#TexSize = 512

Structure _Object
  id.i
  ma.i
  ms.i
  tx.i
  bg.i
EndStructure

Structure _Scene
  cloudlayer._Object
  box._Object
  node.i
EndStructure

Global  s._Scene, cam.i, ev.i, tx.i, Sequence.i = 0, Begin.i = #False, Quit.i = #False
Global  pa.s = GetPathPart(ProgramFilename())

AntialiasingMode(#PB_AntialiasingMode_x6)
OpenWindow(0, 0, 0, 1024, 768, "Clouds - Space key = create sequence ( Key up / key down for tilt)", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0), 0, 0, 1024, 768)
Add3DArchive(".", #PB_3DArchive_FileSystem)
cam = CreateCamera(#PB_Any, 0, 0, 100, 100)

With s\box
  \ms = CreateCube(#PB_Any, 1)
  \tx = CreateTexture(#PB_Any, 10, 10, "Sky")
  StartDrawing(TextureOutput(\tx))
  Box(0, 0, 10, 10, #SkyColor)
  StopDrawing()
  \ma = CreateMaterial(#PB_Any, TextureID(\tx))
  MaterialBlendingMode(\ma, #PB_Material_Add)
  MaterialCullingMode(\ma, #PB_Material_NoCulling)
  \id = CreateEntity(#PB_Any, MeshID(\ms), MaterialID(\ma), 0, 0, 0)
  ScaleEntity(\id, 1000, 1000, 1000)
EndWith

With s\cloudlayer
  \ms = CreatePlane(#PB_Any, 1, 1, 1, 1, 1, 1)
  \tx = LoadTexture(#PB_Any, "cloud.jpg")
  \ma = CreateMaterial(#PB_Any, TextureID(\tx))
  MaterialBlendingMode(\ma, #PB_Material_Add)
  AddMaterialLayer(\ma, TextureID(\tx), #PB_Material_Replace)
  AddMaterialLayer(\ma, TextureID(\tx), #PB_Material_Modulate)
  ScrollMaterial(\ma, 0.004, 0.003, #PB_Material_Animated,0)
  ScrollMaterial(\ma, -0.002, 0.002, #PB_Material_Animated,1)
  ScrollMaterial(\ma, 0.002, -0.004, #PB_Material_Animated,2)
  \id = CreateEntity(#PB_Any, MeshID(\ms), MaterialID(\ma), 0, 0, -350)
  RotateEntity(\id, 90, 0, 0) ; Change x to rotate
  ScaleEntity(\id, 2000, 1, 2000)
EndWith
s\node = CreateNode(#PB_Any, 0, 0, 0)
AttachNodeObject(s\node, EntityID(s\cloudlayer\id))
AttachNodeObject(s\node, EntityID(s\box\id))

Repeat
  
  Repeat
    ev = WindowEvent()
    If ev = #PB_Event_CloseWindow : Quit = #True : EndIf
  Until ev = 0
  
  ExamineKeyboard()

  If KeyboardPushed(#PB_Key_Up)
    RotateNode(s\node, 0.1, 0, 0, #PB_Relative)
  ElseIf KeyboardPushed(#PB_Key_Down)
    RotateNode(s\node, -0.1, 0, 0, #PB_Relative)
  EndIf
  
  If KeyboardReleased(#PB_Key_Space) 
    Debug "Saving sequence...."
    Sequence = 0
    Begin = #True
  EndIf
  
  RenderWorld()
  
  If Begin = #True
    tx = CreateRenderTexture(#PB_Any, CameraID(cam), #TexSize, #TexSize,  #PB_Texture_CameraViewPort, "Texture_" + Str(Random(200000,100)))
    UpdateRenderTexture(tx)
    result = SaveRenderTexture(tx, pa + "Texture_Sequence_" + Str(Sequence) + ".png")
    Sequence + 1
    If Sequence > #SeqMax
      Begin = #False
      Debug "Sequence Created..."
    EndIf
    FreeTexture(tx)
  EndIf
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or Quit = #True
Current configurations:
Ubuntu 20.04/64 bit - Window 10 64 bit
Intel 6800K, GeForce Gtx 1060, 32 gb ram.
Amd Ryzen 9 5950X, GeForce 3070, 128 gb ram.
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 755
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Generating and saving random 3D cloud animations

Post by Samuel »

Seymour Clufley wrote: Ogre seems capable of rendering good 3D clouds, but so does OpenGL, so I don't know which of these engines to choose.
Ogre is an engine whereas OpenGL is an API. There will be more work involved if you go with OpenGL, but in the end you'll have a lot more control over how everything works. If you use PB/Ogre most of the needed systems are in place, but you might not have enough control depending on your project needs. PB/Ogre might be the better starting point if you are new to 3D.

Seymour Clufley wrote: A complicating factor is that I don't know whether PB allows access to enough of the functions of these engines to draw good clouds. What would experienced users say about that?
You could make many unique cloudlike 2D textures and then use them in particles/billboards to display them into different or random 3D formations. This would be easier in Ogre since it already has the basic requirements in place.

You can also use a shader to generate the clouds like in the link idle posted. Although that specific shader is only for 2D clouds.

Seymour Clufley wrote: I will need to be able to grab the animation 25 times a second and save it to file.
I doubt you'd be able to get 25 screenshots in a second. More likely you'd get one per second (gpu to cpu is a slow process).
What you could do is pause the rendering system between screenshots to prevent the scene from progressing too far ahead.
It might take 25 seconds or more to capture everything, but the scene will have only advanced 1 second throughout the process.
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: Generating and saving random 3D cloud animations

Post by Seymour Clufley »

Thanks to everyone for your answers.

Samuel, thank you for your particularly informative reply.

I googled "3d cloud shader" and found this. The demo is incredibly good and basically what I'm looking to achieve with PB. Can you tell me what would be involved in porting it? Would I have to translate the shader into a language that Ogre understands?

There's also SkyX, which is already written for Ogre. It is also very nice, but is no longer available.

(I also found Simul Truesky, but it is unbelievably expensive (something like $25,000) so it's out of the question.)
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 755
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Generating and saving random 3D cloud animations

Post by Samuel »

Seymour Clufley wrote: I googled "3d cloud shader" and found this.
That's a pretty cool demo. Are you only interested in rendering clouds or will there be other objects being rendered at the same time? Those clouds aren't using an MVP (Model, View, and Projection) matrix which will cause a headache if you try to render a world underneath those clouds.

The example looks like it is using GLSL ES 2.0 which I don't have any experience with, but at first glance it appears to be similar to GLSL. If it can be converted to GLSL then you can use it in OpenGL (supports GLSL shaders) or Ogre (supports HLSL, GLSL, and CG shaders).
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: Generating and saving random 3D cloud animations

Post by Seymour Clufley »

Samuel, thanks again for your expertise.
Are you only interested in rendering clouds or will there be other objects being rendered at the same time? Those clouds aren't using an MVP (Model, View, and Projection) matrix which will cause a headache if you try to render a world underneath those clouds.
I might want to have objects moving through the cloud field, or floating around on top of it. But I doubt there would be anything beneath it. What would be nice would be to have the camera itself be underneath the cloud field, looking up at it.
The example looks like it is using GLSL ES 2.0 which I don't have any experience with, but at first glance it appears to be similar to GLSL. If it can be converted to GLSL then you can use it in OpenGL (supports GLSL shaders) or Ogre (supports HLSL, GLSL, and CG shaders).
GLSL ES 2.0 (and 3.0) seems to be the language implemented in WebGL, for 3D inside web pages. I know nothing about this but found a post outlining the differences between GLSL ES 2.0 and GLSL.

Some further questions regarding this particular shader... I realise you might not know all the answers but I'd be grateful for any light you could shed on this.

The cloud field is the same every time the demo is run. Could the shader be adapted to generate a random cloud field every time, perhaps with parameters for density etc. that could be set in the PB program code? (The cloud field seems to be derived from the noise graphic shown below the shader code. Perhaps just generating a new random noise graphic, customised by the parameters, would solve this problem.)

Could the cloud field be made "infinite", so that, no matter how long the animation lasted (an arbitrary duration set in the PB program code), we never ran out of cloud? (I'm not sure if this is already the case with this code, or whether the model is "looped" at some stage, or whether the clouds would eventually just vanish.)

Could the lighting and colouring be changed so that it looked like night-time?

Could the PB code include gradual camera moves to be executed through the course of the animation?

Given all of these requirements, would you now recommend either Ogre or OpenGL?

Thanks again.
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Generating and saving random 3D cloud animations

Post by IdeasVacuum »

Seymour, re SkyX, try asking about it in the Ogre forum, you never know what might turn up.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 755
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Generating and saving random 3D cloud animations

Post by Samuel »

Seymour Clufley wrote: I might want to have objects moving through the cloud field, or floating around on top of it. But I doubt there would be anything beneath it.
The problem isn't just rendering objects under the clouds. Rendering objects in the clouds and above them could prove difficult as well. Technically rendering the objects isn't the difficult part. The difficult part lies in trying to make objects match the clouds proportionally since they are not using a standard matrix.
You may be able to tweak your objects enough to give nice results though. I guess experimentation will be the best path on this.
Seymour Clufley wrote: What would be nice would be to have the camera itself be underneath the cloud field, looking up at it.
The clouds are only being rendered on one side. If you go under them you will just have a pure sky without any clouds.
If you don't plan on going through to the other side. Then the clouds could probably be flipped upside down which should give you the desired effect.

The clouds may be able to be calculated for above and below, but I don't know enough about this shader to say for sure.
Seymour Clufley wrote: The cloud field is the same every time the demo is run. Could the shader be adapted to generate a random cloud field every time, perhaps with parameters for density etc. that could be set in the PB program code? (The cloud field seems to be derived from the noise graphic shown below the shader code. Perhaps just generating a new random noise graphic, customised by the parameters, would solve this problem.)
Yes, changing the noise image should alter how the clouds are generated. I'm not sure if it was generated in a specific way for any reason, but I believe random noise should give you random clouds.
There are also some parameters for how far away the clouds are rendered, and while I haven't found them yet, there should also be some for the height of the clouds.
Seymour Clufley wrote: Could the cloud field be made "infinite", so that, no matter how long the animation lasted (an arbitrary duration set in the PB program code), we never ran out of cloud? (I'm not sure if this is already the case with this code, or whether the model is "looped" at some stage, or whether the clouds would eventually just vanish.)
The clouds are infinite and they appear to use a seamless loop.
Seymour Clufley wrote: Could the lighting and colouring be changed so that it looked like night-time?
Yep, I'll post some code below for you to test in ShaderToy.
Seymour Clufley wrote: Could the PB code include gradual camera moves to be executed through the course of the animation?
Yep, shouldn't be a problem.
Seymour Clufley wrote: Given all of these requirements, would you now recommend either Ogre or OpenGL?
I'd go with OpenGL, but that's easier for me to say because I've been using it for several years now.
If this is your first 3D project then I'd recommend Ogre. If this is going to be a very large project you're working on. Then Ogre might not be a good permanent solution, but it would give you a base understanding of how 3D engines work. Which would make diving into OpenGL easier.
PB/Ogre is what I originally started with and I worked with it for 2 or so years. Then I swapped to straight OpenGL and all the things I learned with Ogre really helped me in creating my own engine.

Shadertoy example nighttime with extended cloud distance. Just paste this in the block and hit the play button below it to run.

Code: Select all

// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

// Volumetric clouds. It performs level of detail (LOD) for faster rendering

float noise( in vec3 x )
{
    vec3 p = floor(x);
    vec3 f = fract(x);
	f = f*f*(3.0-2.0*f);
    
#if 1
	vec2 uv = (p.xy+vec2(37.0,17.0)*p.z) + f.xy;
    vec2 rg = textureLod( iChannel0, (uv+ 0.5)/256.0, 0. ).yx;
#else
    ivec3 q = ivec3(p);
	ivec2 uv = q.xy + ivec2(37,17)*q.z;

	vec2 rg = mix( mix( texelFetch( iChannel0, (uv           )&255, 0 ),
				        texelFetch( iChannel0, (uv+ivec2(1,0))&255, 0 ), f.x ),
				   mix( texelFetch( iChannel0, (uv+ivec2(0,1))&255, 0 ),
				        texelFetch( iChannel0, (uv+ivec2(1,1))&255, 0 ), f.x ), f.y ).yx;
#endif    
    
	return -1.0+2.0*mix( rg.x, rg.y, f.z );
}

float map5( in vec3 p )
{
	vec3 q = p - vec3(0.0,0.1,1.0)*iGlobalTime;
	float f;
    f  = 0.50000*noise( q ); q = q*2.02;
    f += 0.25000*noise( q ); q = q*2.03;
    f += 0.12500*noise( q ); q = q*2.01;
    f += 0.06250*noise( q ); q = q*2.02;
    f += 0.03125*noise( q );
	return clamp( 1.5 - p.y - 2.0 + 1.75*f, 0.0, 1.0 );
}

float map4( in vec3 p )
{
	vec3 q = p - vec3(0.0,0.1,1.0)*iGlobalTime;
	float f;
    f  = 0.50000*noise( q ); q = q*2.02;
    f += 0.25000*noise( q ); q = q*2.03;
    f += 0.12500*noise( q ); q = q*2.01;
    f += 0.06250*noise( q );
	return clamp( 1.5 - p.y - 2.0 + 1.75*f, 0.0, 1.0 );
}
float map3( in vec3 p )
{
	vec3 q = p - vec3(0.0,0.1,1.0)*iGlobalTime;
	float f;
    f  = 0.50000*noise( q ); q = q*2.02;
    f += 0.25000*noise( q ); q = q*2.03;
    f += 0.12500*noise( q );
	return clamp( 1.5 - p.y - 2.0 + 1.75*f, 0.0, 1.0 );
}
float map2( in vec3 p )
{
	vec3 q = p - vec3(0.0,0.1,1.0)*iGlobalTime;
	float f;
    f  = 0.50000*noise( q ); q = q*2.02;
    f += 0.25000*noise( q );;
	return clamp( 1.5 - p.y - 2.0 + 1.75*f, 0.0, 1.0 );
}

vec3 sundir = normalize( vec3(-1.0,0.0,-1.0) );

vec4 integrate( in vec4 sum, in float dif, in float den, in vec3 bgcol, in float t )
{
    // lighting
    vec3 lin = vec3(0.65,0.7,0.75)*1.4 + vec3(1.0, 1.0, 1.0)*dif;        
    vec4 col = vec4( mix( vec3(1.0,0.95,0.8), vec3(0.1,0.15,0.2), den ), den );
    col.xyz *= lin;
    col.xyz = mix( col.xyz, bgcol, 1.0-exp(-0.003*t*t) );
    // front to back blending    
    col.a *= 0.4;
    col.rgb *= col.a;
    return sum + col*(1.0-sum.a);
}

#define MARCH(STEPS,MAPLOD) for(int i=0; i<STEPS; i++) { vec3  pos = ro + t*rd; if( pos.y<-3.0 || pos.y>2.0 || sum.a > 0.99 ) break; float den = MAPLOD( pos ); if( den>0.01 ) { float dif =  clamp((den - MAPLOD(pos+0.3*sundir))/0.6, 0.0, 1.0 ); sum = integrate( sum, dif, den, bgcol, t ); } t += max(0.05,0.02*t); }

vec4 raymarch( in vec3 ro, in vec3 rd, in vec3 bgcol, in ivec2 px )
{
	vec4 sum = vec4(0.0);

	float t = 0.0;//0.05*texelFetch( iChannel0, px&255, 0 ).x;

    MARCH(60,map5);
    MARCH(60,map4);
    MARCH(60,map3);
    MARCH(60,map2);

    return clamp( sum, 0.0, 1.0 );
}

mat3 setCamera( in vec3 ro, in vec3 ta, float cr )
{
	vec3 cw = normalize(ta-ro);
	vec3 cp = vec3(sin(cr), cos(cr),0.0);
	vec3 cu = normalize( cross(cw,cp) );
	vec3 cv = normalize( cross(cu,cw) );
    return mat3( cu, cv, cw );
}

vec4 render( in vec3 ro, in vec3 rd, in ivec2 px )
{
    // background sky     
	float sun = clamp( dot(sundir,rd), 0.0, 1.0 );
	vec3 col = vec3(0.0,0.0,0.1) - rd.y*0.2*vec3(1.0,1.0,1.0) + 0.15*0.5;
	col += 0.2*vec3(1.0,1.0,1.0)*pow( sun, 64.0 );

    // clouds    
    vec4 res = raymarch( ro, rd, col, px );
    col = col*(1.0-res.w) + res.xyz;
    
    // sun glare    
	col += 0.2*vec3(1.0,1.0,1.0)*pow( sun, 64.0 );

    return vec4( col, 1.0 );
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 p = (-iResolution.xy + 2.0*fragCoord.xy)/ iResolution.y;

    vec2 m = iMouse.xy/iResolution.xy;
    
    // camera
    vec3 ro = 4.0*normalize(vec3(sin(24.0*m.x), 0.4*m.y, cos(24.0*m.x)));
	vec3 ta = vec3(0.0, -1.0, 0.0);
    mat3 ca = setCamera( ro, ta, 0.0 );
    // ray
    vec3 rd = ca * normalize( vec3(p.xy,1.5));
    
    fragColor = render( ro, rd, ivec2(fragCoord-0.5) );
}

void mainVR( out vec4 fragColor, in vec2 fragCoord, in vec3 fragRayOri, in vec3 fragRayDir )
{
    fragColor = render( fragRayOri, fragRayDir, ivec2(fragCoord-0.5) );
}
Post Reply