Author Topic: Rosetta Code: Plasma Effect  (Read 4346 times)

0 Members and 1 Guest are viewing this topic.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Rosetta Code: Plasma Effect
« on: May 24, 2021, 08:57:55 pm »
From: https://rosettacode.org/wiki/Plasma_effect

Looking at the code examples for this rosetta code task, FreeBASIC took their program and converted it over from https://lodev.org/cgtutor/plasma.html.  To help showcase how similar the various BASICs are that are out there, I decided to do the same and translate the last demo from that website over into QB64 for everyone. 

Code: QB64: [Select]
  1. 'converted from https://lodev.org/cgtutor/plasma.html, last example
  2. CONST wide = 256, high = 256
  3. SCREEN _NEWIMAGE(wide, high, 32)
  4. _TITLE "Plasma"
  5.  
  6.     FUNCTION timeGetTime ()
  7.  
  8.     t = timeGetTime / 50 't + .99
  9.     FOR y = 0 TO high - 1
  10.         FOR x = 0 TO wide - 1
  11.             v = SIN(Dist(x + t, y, 128, 128) / 8) _
  12.             + SIN(Dist(x, y , 64, 64) / 8) _
  13.             + SIN(Dist(x, y + t / 7, 192, 64) / 7) _
  14.             + SIN(Dist(x, y, 192, 100) / 8)
  15.             c = INT(4 + v) * 32
  16.             PSET (x, y), _RGB32(c, c * 2, 255 - c)
  17.         NEXT
  18.     NEXT
  19.     _DISPLAY
  20.     _DELAY .01
  21.  
  22. FUNCTION Dist## (x1, y1, x2, y2)
  23.     Dist## = _HYPOT(x1 - x2, y1 - y2)
  24.     'Dist = SQR((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
  25.  

For whatever reason, I can generate the same pattern that the website has as their image, but I'm generating a different palette.  They're creating red and blue, mine is creating green and blue.  I imagine the problem is somewhere in their call to ColorRGB, since all the rest of the examples on page use some sort of color palette with that custom function, but I wouldn't swear to it...

Honestly, I don't even see how the BLEEP the final example on the page works at all, the way it's written!

Code: C++: [Select]
  1. #define dist(a, b, c, d) sqrt(double((a - c) * (a - c) + (b - d) * (b - d)))
  2.  
  3. int main(int argc, char *argv[])
  4. {
  5.   screen(256, 256, 0, "Plasma");
  6.   double time;
  7.   while(!done())
  8.   {
  9.     time = getTime() / 50.0;
  10.     for(int y = 0; y < h; y++)
  11.     for(int x = 0; x < w; x++)
  12.     {
  13.       double value = sin(dist(x + time, y, 128.0, 128.0) / 8.0)
  14.              + sin(dist(x, y, 64.0, 64.0) / 8.0)
  15.              + sin(dist(x, y + time / 7, 192.0, 64) / 7.0)
  16.              + sin(dist(x, y, 192.0, 100.0) / 8.0);
  17.       int color = int((4 + value)) * 32;
  18.       pset(x, y, ColorRGB(color, color * 2, 255 - color));
  19.     }
  20.     redraw();
  21.   }
  22.   return(0);
  23. }

Where do we define w and h at?  Or ColorRGB?  What the heck is getTime?  I don't know and can't find reference to any sort of C++ function with that name at all.  The closest I can get is to go with timeGetTime() which gives us seconds since windows started.  (Note that getTime isn't the same thing as gettime.  C is case sensitive.)

If anyone has a clue about how to correct the color palette to match this demo, I'd love to see it.  Otherwise, this is about as close as I can get to what they've posted on their website, with the link here: https://lodev.org/cgtutor/plasma.html

I've never added code to Rosetta Code before, but since I was  looking at Ashish's example earlier, I thought it might be something which somebody might want to add for us.  For anyone who edits and adds code to RC, feel free to add the above (or Ashish's) onto the site so we'll be represented there forever more.  :)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Rosetta Code: Plasma Effect
« Reply #1 on: May 24, 2021, 10:56:37 pm »
Instead of doing what everybody else has done how about showing off some serious color mixing:
Code: QB64: [Select]
  1. _Title "Plasmatic 5 Color Shading" ' b+ 2020-01-26
  2. ' Hopefully this will add shading to the new color options found in Plasmatic 4.
  3.  
  4. Const xxmax = 800, yymax = 600, xmax = 900, ymax = 740, xoff = (xmax - xxmax) \ 2, yoff = (ymax - yymax) \ 2
  5. Type xy
  6.     x As Single
  7.     y As Single
  8.     dx As Single
  9.     dy As Single
  10. Screen _NewImage(xmax, ymax, 32)
  11. Dim c(360) As _Unsigned Long, p(6) As xy, f(6)
  12. Dim i As Integer, m As Integer, n As Integer, mode As Integer, k$, t, x, y, d, dx, dy, dist, s
  13.  
  14. restart: 'select rgb1 and rgb2 based on mode of color mixing
  15. If mode = 0 Then 'new plasma option ANY color for border and ANY color for middle
  16.     r1 = Rnd * 255: g1 = Rnd * 255: b1 = Rnd * 255: r2 = Rnd * 255: g2 = Rnd * 255: b2 = Rnd * 255
  17. Else ' traditional high contrast plasma black borders, white centers
  18.     r1 = 0: g1 = 0: b1 = 0: r2 = 255: g2 = 255: b2 = 255 'regular Plasma
  19.  
  20. ' create 6 x 60 bands of color palette based on coloring mode (rgb1 set and rgb2 set)
  21. For i = 0 To 360
  22.     If i Mod 60 = 0 Then r = Rnd * 255: g = Rnd * 255: b = Rnd * 255
  23.     m = i Mod 60
  24.     s = 1 - ((30 - m + .5) / 30) ^ 2
  25.     Select Case m
  26.         Case Is < 15: c(i) = midInk(s * r1, s * g1, s * b1, s * r, s * g, s * b, m / 15) '        1st stage increase rgb1 towards rgb color in 15 steps
  27.         Case Is < 30: c(i) = midInk(s * r, s * g, s * b, s * r2, s * g2, s * b2, (m - 15) / 15) ' 2nd stage increase rgb color towards rgb2 set in 15 steps
  28.         Case Is < 45: c(i) = midInk(s * r2, s * g2, s * b2, s * r, s * g, s * b, (m - 30) / 15) ' 3rd stage decrease rgb2 color back to rgb color in 15 steps
  29.         Case Is < 60: c(i) = midInk(s * r, s * g, s * b, s * r1, s * g1, s * b1, (m - 45) / 15) ' 4th and finally decrease rgb back to starting rgb1 set in 15 steps
  30.     End Select
  31.  
  32. ' behind the scenes variables for motion, weighting and shaping color mixing
  33. For n = 0 To 5
  34.     p(n).x = Rnd * xmax: p(n).y = Rnd * yymax: p(n).dx = Rnd * 2 - 1: p(n).dy = Rnd * 2 - 1
  35.     f(n) = .1 * Rnd
  36.  
  37. 'screen labeling 3 lines for title above, 1 line instructions below
  38. If mode = 0 Then
  39.     yCP yoff - 60, "New Color Options for Plasma:"
  40.     yCP yoff - 60, "Traditional High Contrast Plasma: Black Borders and White Centers"
  41. yCP yoff - 40, "Shaded Borders: RGB(" + TS$(r1 \ 1) + ", " + TS$(g1 \ 1) + ", " + TS$(b1 \ 1) + ")"
  42. yCP yoff - 20, "Centers: RGB(" + TS$(r2 \ 1) + ", " + TS$(g2 \ 1) + ", " + TS$(b2 \ 1) + ")"
  43. yCP yoff + yymax + 10, "Press t to toggle between Traditional and New Color Options Plasma"
  44. yCP yoff + yymax + 30, "Press spacebar to get a new color set."
  45.  
  46. While _KeyDown(27) = 0
  47.     k$ = InKey$
  48.     If k$ = " " Then GoTo restart
  49.     If k$ = "t" Then mode = 1 - mode: GoTo restart
  50.     t = Timer(.001)
  51.     For i = 0 To 5
  52.         p(i).x = p(i).x + p(i).dx
  53.         If p(i).x > xxmax Then p(i).dx = -p(i).dx: p(i).x = xxmax
  54.         If p(i).x < 0 Then p(i).dx = -p(i).dx: p(i).x = 0
  55.         p(i).y = p(i).y + p(i).dy
  56.         If p(i).y > xxmax Then p(i).dy = -p(i).dy: p(i).y = yymax
  57.         If p(i).y < 0 Then p(i).dy = -p(i).dy: p(i).y = 0
  58.     Next
  59.     For y = 0 To yymax - 1 Step 2
  60.         For x = 0 To xxmax - 1 Step 2
  61.             d = 0
  62.             For n = 0 To 5
  63.                 dx = x - p(n).x: dy = y - p(n).y
  64.                 dist = Sqr(dx * dx + dy * dy)
  65.                 'dist = _HYPOT(dx, dy)    'this may work faster on another system
  66.                 d = d + (Sin(dist * f(n)) + 1) / 2
  67.             Next n: d = d * 60
  68.             Line (x + xoff, y + yoff)-Step(2, 2), c(d), BF
  69.         Next
  70.     Next
  71.     yCP yoff + yymax + 50, Space$(50)
  72.     yCP yoff + yymax + 50, TS$(Int(1000 * (Timer(.001) - t))) + " ms per frame"
  73.     _Display
  74.  
  75. Function midInk~& (r1%, g1%, b1%, r2%, g2%, b2%, fr##)
  76.     midInk~& = _RGBA32(r1% + (r2% - r1%) * fr##, g1% + (g2% - g1%) * fr##, b1% + (b2% - b1%) * fr##, 255)
  77.  
  78. Sub yCP (y, s$) 'for xmax pixel wide graphics screen Center Print at pixel y row
  79.     _PrintString ((_Width - Len(s$) * 8) / 2, y), s$
  80.  
  81.     TS$ = _Trim$(Str$(n))
  82.  
  83.  

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
    • View Profile
Re: Rosetta Code: Plasma Effect
« Reply #2 on: May 25, 2021, 08:05:21 am »
@bplus Thats lovely!

@SMcNeill I feel it strange that the code you translated correctly but still we can find difference in the colors of plasma in the output.
if (Me.success) {Me.improve()} else {Me.tryAgain()}


My Projects - https://github.com/AshishKingdom?tab=repositories
OpenGL tutorials - https://ashishkingdom.github.io/OpenGL-Tutorials

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Rosetta Code: Plasma Effect
« Reply #3 on: May 25, 2021, 01:37:46 pm »
Thanks Ashish, Steves link is interesting looks to me that that they could do pallets (pallets of palettes, where the heck is Qwerkey?) separately. That is secret to Plasma great color mixing but also you move points around to get Plasma moving, it's sort of like Voronoi on wheels.

I have to study Steve's speed tips to see if I missed any, did he say 18 ms? are we comparing same sized screens? oh and same systems? ...

I did try _Hypot and did not get difference and I know x*x is way faster than x^2, I think SQR was faster than ^.5 and better yet if you can skip it like for comparing distances (Voronoi again you could).
« Last Edit: May 25, 2021, 04:47:29 pm by bplus »

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: Rosetta Code: Plasma Effect
« Reply #4 on: May 25, 2021, 04:31:53 pm »
bplus:

Very smooth transitions - a little slow on my old clunker - 38 to 40ms - but still quite impressive.... The various colour sets where a nice touch as well. Good job!
Logic is the beginning of wisdom.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Rosetta Code: Plasma Effect
« Reply #5 on: May 25, 2021, 06:49:00 pm »
I did try _Hypot and did not get difference and I know x*x is way faster than x^2, I think SQR was faster than ^.5 and better yet if you can skip it like for comparing distances (Voronoi again you could).

In this case, _HYPOT doesn't seem to make that much of a speed difference for us, where it's just SQR(dx * dx + dy * dx).  In Ashish's program, it made quite a bit of difference, but the rest of the math there was quite different as well: ((u - 0.5 + 0.3 * SIN(i2)) ^ 2 + (v - 0.5 + 0.3 * COS(i2)) ^ 2) ^ 0.5.   In this case, _HYPOT(u - 0.5 + 0.3 * SIN(i2), v - 0.5 + 0.3 * COS(i2)) came out to a much faster calculation for whatever reason/optimization that occurred under the hood.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Richard Frost

  • Seasoned Forum Regular
  • Posts: 316
  • Needle nardle noo. - Peter Sellers
    • View Profile
Re: Rosetta Code: Plasma Effect
« Reply #6 on: May 25, 2021, 09:03:34 pm »
I envision a remake of the 1958 movie "The Blob" entitled "The Blob and His Family".
Doubling the step makes it a bit faster.


It works better if you plug it in.

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Rosetta Code: Plasma Effect
« Reply #7 on: June 08, 2021, 03:31:16 am »
I must admit that I hate plasma... and all the other blood derivates!
However I'm trying to be nearer to plasma concept...

Here my bad translation of C example posted by Steve...
Code: QB64: [Select]
  1. Rem this is a duplicate of c program showed at https://www.qb64.org/forum/index.php?topic=3944.0
  2. 'The screen(int width, int height, bool fullscreen, char* text) function sets up the graphical screen. Screen _NewImage(256, 256, 32)
  3. 'The pset(int x, int y, ColorRGB color) function plots a single pixel at location x,y with given RGB color: ColorRGB color has 3 components r, g, b which are values between 0 and 255.
  4. 'The redraw() function uploads all pixels you have drawn to the videocard, so that you can see them.
  5.  
  6. Const h = 256, w = 256
  7. Screen _NewImage(w, h, 32)
  8. _Title "Plasma"
  9. Dim done As Integer, time As Double, x As Integer, y As Integer, value As Double, colors As Integer
  10.  
  11. While Not done
  12.     time = Timer(.001) / 50.0
  13.     For y = 0 To h - 1 Step 1
  14.         For x = 0 To w - 1 Step 1
  15.             value = Sin(dist(x + time, y, 128.0, 128.0) / 8.0) + Sin(dist(x, y, 64.0, 64.0) / 8.0) + Sin(dist(x, y + time / 7, 192.0, 64) / 7.0) + Sin(dist(x, y, 192.0, 100.0) / 8.0)
  16.             colors = Int((4 + value)) * 32
  17.             PSet (x, y), _RGB32(colors, colors * 2, 255 - colors)
  18.         Next x
  19.     Next y
  20.  
  21.     dist = Sqr((a - c) * (a - c) + (b - d) * (b - d))
and YES I admit that I have shaked my head to understand in what library of C or C++  there are those functions...
No Google and No Yahoo  and No Bing have brought to me something of useful !... The most examples of C graphic code are about TurboC !?!
Then searching in the neighbours of https://lodev.org/cgtutor/plasma.html I found this...https://lodev.org/cgtutor/examples.html  and Yes here is the QuickCG library used in this example of plasma code.

@SMcNeill  so if you want to investigate there are the .CPP files of library to see how it works ColorRGB.

See later fantastic boys and girls of QB64

@bplus
your work is wonderful! I need more study to approach to your tecnique of Plasma
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Rosetta Code: Plasma Effect
« Reply #8 on: June 08, 2021, 04:26:07 am »
so close!
Code: QB64: [Select]
  1. Rem this is a duplicate of c program showed at https://www.qb64.org/forum/index.php?topic=3944.0
  2. 'The screen(int width, int height, bool fullscreen, char* text) function sets up the graphical screen. Screen _NewImage(256, 256, 32)
  3. 'The pset(int x, int y, ColorRGB color) function plots a single pixel at location x,y with given RGB color: ColorRGB color has 3 components r, g, b which are values between 0 and 255.
  4. 'The redraw() function uploads all pixels you have drawn to the videocard, so that you can see them.
  5.  
  6. Const h = 256, w = 256
  7. Screen _NewImage(w, h, 32)
  8. _Title "Plasma"
  9. Dim done As Integer, time As Double, x As Integer, y As Integer, value As Double, colors As Integer
  10.  
  11. While Not done
  12.     time = time + 1 ' <<<<<<<<<<<<<<<<<<<<<<<< make simple change here!
  13.     For y = 0 To h - 1 Step 1
  14.         For x = 0 To w - 1 Step 1
  15.             value = Sin(dist(x + time, y, 128.0, 128.0) / 8.0) + Sin(dist(x, y, 64.0, 64.0) / 8.0) + Sin(dist(x, y + time / 7, 192.0, 64) / 7.0) + Sin(dist(x, y, 192.0, 100.0) / 8.0)
  16.             colors = Int((4 + value)) * 32
  17.             PSet (x, y), _RGB32(colors, colors * 2, 255 - colors)
  18.         Next x
  19.     Next y
  20.  
  21.     dist = Sqr((a - c) * (a - c) + (b - d) * (b - d))
  22.  
  23.  

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Rosetta Code: Plasma Effect
« Reply #9 on: June 08, 2021, 04:39:38 am »
@bplus
Thanks!
For an expert eyesight a little change in code and a great changement into graphic effects!
Code: QB64: [Select]
  1.   time = time + 1 ' <<<<<<<<<<<<<<<<<<<<<<<< make simple change here!
Programming isn't difficult, only it's  consuming time and coffee