Lazarus

Programming => Graphics => Graphics and Multimedia => BGRABitmap and LazPaint => Topic started by: lainz on April 17, 2021, 07:19:16 pm

Title: Sand Demo
Post by: lainz on April 17, 2021, 07:19:16 pm
Hi, I made a sand demo with BGRABitmap.

Download source code
https://github.com/bgrabitmap/demo/tree/master/sand

Attached screenshot (The starting color is random).

Another I did, web version (not made with FPC, only typescript)
https://lainz.github.io/webapps/sand/

Both the web version and FPC version needs optimization, the web version can use webassembly and webgl. The FPC version can use scanline or opengl.

Feel free to play with the code!
Title: Re: Sand Demo
Post by: circular on April 17, 2021, 07:38:47 pm
One way you can optimize is indeed to use something like ScanLine. You can add a one-pixel border to the image that will never contain sand and then use a pointer to the pixel of the sand particle. You can then just add and subtract 1 for left and right and add and subtract the row size for up and down (the sign may change, so you need to take into account the line order).

Unfortunately I cannot open it with my current version of Lazarus 2.0.10. I presume it is from a newer version?
Title: Re: Sand Demo
Post by: winni on April 17, 2021, 08:48:18 pm
Hi!

What might help is my procedure FillNaturalColor.
As parameter you need the destination BGRAbitmap, a rectangle and the
Hue-Value reduced to a byte:  round (360/Hue360 * 255)

The procedure produces a noisy natural area with your hue.
You can experiment with the 5 const values,  but take care that you dont't get a byte underflow or overflow. Now the const values take care of that.

The hue value of sand is around 55. If the result is too dark or bright you must do that on your own.

Code: Pascal  [Select][+][-]
  1. // fill with noisy color Hue
  2. procedure FillNaturalColor (Dest: TBGRABitmap; R : TRect; Hue: byte);
  3. const RangeHue = 8;
  4.       RangeLight = 58;
  5.       RangeSat = 95;
  6.       BaseLight =  113;
  7.       BaseSat = 157;
  8. var x,y : Integer;
  9.     h,l,s : byte;
  10.     col : TBGRAPixel;
  11.     begin
  12.     For y := R.Top to R.Bottom-1 do
  13.      begin
  14.      for x := R.left to R.Right - 1 do
  15.        begin
  16.         h := byte(Hue + Random(RangeHue +1));
  17.         l := BaseLight + Random (RangeLight+1);
  18.         s := BaseSat+ Random (RangeSat+1);
  19.         col := HSLAToBGRA(HSLA(h*256,s*256,l*256));
  20.         dest.setPixel(x,y,col);
  21.        end;  //x
  22.      end; // y
  23.     end;
  24.  

Example in the attachment.

Winni
Title: Re: Sand Demo
Post by: lainz on April 18, 2021, 02:47:14 am
Hi circular. Try again I fixed it.

Hi winni. Thanks. I already have color noise but it's soften. I've not tweaked the fpc version yet just a quick port from the web version.

Enjoy open source!
Title: Re: Sand Demo
Post by: Fred vS on April 18, 2021, 03:50:50 am
Hello Lainz.

I try to make your sand dance but get a error while compiling, on Linux 64 bit, fpc 3.2.0 and Lazarus 2.0.10.

I use last bgrabitmap V11 and bgracontrols V7.

This is the line that makes problems, in umain.pas(165,27) ;

Code: Pascal  [Select][+][-]
  1.  sand.SetPixel(x, y, p);

This is the error:

Quote
umain.pas(165,27) Error: Can't determine which overloaded function to call
unibitmapgeneric.inc(37,15) Hint: Found declaration: SetPixel(Int64;Int64;const TBGRAPixel);
bgradefaultbitmap.pas(1303,30) Hint: Found declaration: SetPixel(Int64;Int64;TGraphicsColor);

Fre;D
Title: Re: Sand Demo
Post by: lainz on April 18, 2021, 03:54:36 am
Hi. If you add a intermediate variable like a tbgrapixel and convert the hsla before sending to set pixel?
Title: Re: Sand Demo
Post by: Fred vS on April 18, 2021, 03:58:35 am
Hi. If you add a intermediate variable like a tbgrapixel and convert the hsla before sending to set pixel?

Maybe it will work (if you explain me how to do)...
Title: Re: Sand Demo
Post by: lainz on April 18, 2021, 04:04:50 am
Var
Px: tbgrapixel;
...
Px := p;
... Setpixel(..., Px);
Title: Re: Sand Demo
Post by: Fred vS on April 18, 2021, 04:07:33 am
Var
Px: tbgrapixel;
...
Px := p;
... Setpixel(..., Px);

Together!

I did this and it works.

Code: Pascal  [Select][+][-]
  1. procedure TfrmMain.putSand(const x: integer; const y: integer);
  2. var
  3.   p: THSLAPixel;
  4.   p2: tbgrapixel;
  5. begin
  6.   if isWhite(x, y) then
  7.   begin
  8.     p.hue := round(hsla);
  9.     p.saturation := randomRange(32768, 65535 - (32768 div 2));
  10.     p.lightness := 32768;
  11.     p.alpha := 65535;
  12.     p2 := p;
  13.     sand.SetPixel(x, y, p2);
  14.     hsla := hsla + 1 / size;
  15.     if (hsla > 65535) then
  16.       hsla := 0;
  17.   end;
  18. end;    


WOW!
Title: Re: Sand Demo
Post by: lainz on April 18, 2021, 04:19:53 am
Yes it's really cool and easy to code. If you want you can search some videos where is explained how to do water and many more.
Title: Re: Sand Demo
Post by: circular on April 18, 2021, 12:37:38 pm
Hi

I've optimized the code and also to use OpenGL.

It is much faster with OpenGL because the image is stretched. Doing the stretch by software is a bit slow and even using the stretch draw of TBitmap is slow in particular on Retina.
Title: Re: Sand Demo
Post by: lainz on April 18, 2021, 01:16:09 pm
Thanks Johann.  :)

Edit: Seems that doesn't works on Windows.

Attached image, it moves to the left, but that's all it does.
Title: Re: Sand Demo
Post by: circular on April 18, 2021, 06:41:31 pm
Ok, I thought of something that might not work, the actual row size may be different. Please have a try with last change
Title: Re: Sand Demo
Post by: lainz on April 18, 2021, 06:57:09 pm
It works now thanks.
TinyPortal © 2005-2018