Water Ripples

Discussions related to graphics (2D and 3D), animation and games programming
David Williams

Water Ripples

Post by David Williams »

http://www.proggies.uk/misc/waterripples2.zip

https://youtu.be/oreComUsg78

Code: Select all

      REM Raindrop Water Ripples 2
      REM Requires BB4W & GfxLib2

      *ESC OFF

      MODE 8 : OFF

      ON ERROR PROCCloseGDIP : PROCerror( REPORT$ + " at line " + STR$ERL )
      ON CLOSE PROCCloseGDIP : QUIT

      N% = 250 : REM no. of ripples

      INSTALL @lib$ + "GDIPLIB.BBC"                          : PROC_gdipinit
      INSTALL @lib$ + "GFXLIB2.BBC"                          : PROCInitGFXLIB( g{}, 0 )
      INSTALL @lib$ + "GFXLIB_modules\ClrLG.BBC"             : PROCInitModule( 0 )
      INSTALL @lib$ + "GFXLIB_modules\BPlotScale.BBC"        : PROCInitModule( 0 )
      INSTALL @lib$ + "GFXLIB_modules\PlotAlphaBlend3.BBC"   : PROCInitModule( 0 )
      INSTALL @lib$ + "GFXLIB_modules\DrawBmFont3.BBC"       : PROCInitModule( 0 )
      INSTALL @lib$ + "GFXLIB_modules\GetBmFontStrWidth.BBC" : PROCInitModule( 0 )

      RESTORE
      READ nQuotes%
      maxQuoteLines% = 10
      DIM quote{( nQuotes%-1 ) nLines%, s$(maxQuoteLines%-1)}
      FOR I% = 0 TO nQuotes%-1
        REPEAT
          READ s$
          IF s$ <> "" THEN
            quote{(I%)}.s$( quote{(I%)}.nLines% ) = s$
            quote{(I%)}.nLines% += 1
          ENDIF
        UNTIL s$ = ""
      NEXT I%

      G% = g{}

      timeGetTime% = FNSYS_NameToAddress( "timeGetTime" )

      font% = FNLoadData( @lib$ + "GFXLIB_media\arial16pt.dat" )

      bm% = FNmalloc( 4 * 640*512 )

      DIM c{(N%-1) pen%, x, z, r, maxr}

      FOR I% = 0 TO N%-1
        PROCnew( I%, FALSE )
      NEXT I%

      quote% = RND(nQuotes%) - 1

      SYS timeGetTime% TO time%
      displayQuoteTime% = time% + 5000

      *REFRESH OFF

      SYS timeGetTime% TO time%

      REPEAT
  
        old_time% = time%
        SYS timeGetTime% TO time%
        dt = 60 * (time% - old_time%) / 1000
  
        SYS GFXLIB_Clr%, g{}, &1060B0
  
        FOR I% = 0 TO N%-1
          PROC_gdipellipse( c{(I%)}.pen%, c{(I%)}.x, c{(I%)}.z, c{(I%)}.r, c{(I%)}.r, 0 )
          c{(I%)}.r += 0.5 * dt
    
          PROC_gdipdeletepen( c{(I%)}.pen% )
    
          t = 2.0 + (5.0 - 2.0)*(1 - c{(I%)}.z / 1024)
          opacity% = FNopacity( c{(I%)}.r, c{(I%)}.maxr, c{(I%)}.z )
          rgb% = FNrgb( opacity% )
          c{(I%)}.pen% = FN_gdipcreatepen( rgb%, 0, t )
    
          IF c{(I%)}.r >= c{(I%)}.maxr THEN
            PROC_gdipdeletepen( c{(I%)}.pen% )
            PROCnew( I%, TRUE )
          ENDIF
        NEXT I%
  
        SYS GFXLIB_DWORDCopy%, g.bmBuffAddr%, bm%, 640*512
  
        SYS GFXLIB_ClrLG%, g{}, &104040, &4050A0
  
        y = 0
        dy = 1.0
        ddy = 0.00375
  
        P% = GFXLIB_BPlotScale%
        FOR Y% = 0 TO 319
          w = 640 * (1 - 0.5*Y%/319)
          SYS P%, G%, bm% + 4*640*INTy, 640, 1, 2*w, 1, 320-2*w/2, Y%
          y += dy
          dy += ddy
        NEXT Y%
  
        IF time% >= displayQuoteTime% PROCDisplayQuote(quote%)
  
        PROCdisplay
  
      UNTIL FALSE
      END

      DEF FNopacity( r, maxr, z )
      = (1 - r/maxr) * (64 + 191 * (1 - z / 1024))

      DEF FNrgb( O% )
      = (O% << 24) OR &A0FF

      DEF PROCnew( I%, R% )
      c{(I%)}.x = 1280 * RND(1)
      c{(I%)}.z = 1024 * RND(1)
      c{(I%)}.maxr = 8 + 48*RND(1)
      IF R% THEN
        c{(I%)}.r = 0.5
      ELSE
        c{(I%)}.r = 0.5 * c{(I%)}.maxr * RND(1)
      ENDIF
      t = 2.0 + (8.0 - 2.0)*(1 - c{(I%)}.z / 1024)
      opacity% = FNopacity( c{(I%)}.r, c{(I%)}.maxr, c{(I%)}.z )
      rgb% = FNrgb( opacity% )
      c{(I%)}.pen% = FN_gdipcreatepen( rgb%, 0, t )
      ENDPROC

      DEF PROCDisplayQuote(i%)
      LOCAL I%, s$
      FOR I% = 0 TO quote{(i%)}.nLines%-1
        s$ = quote{(i%)}.s$(I%)
        SYS GFXLIB_GetBmFontStrWidth%, font%, s$ TO W%
        SYS GFXLIB_DrawBmFont3%, G%, font%, s$, 320-W%/2-1, 332-28*I%-1, 0
        SYS GFXLIB_DrawBmFont3%, G%, font%, s$, 320-W%/2, 332-28*I%, &D0C010
      NEXT I%
      ENDPROC

      DEF PROCCloseGDIP
      LOCAL I%
      `GdiplusStartup` += 0
      IF `GdiplusStartup` <> 0 THEN
        REM FOR I% = 0 TO N%-1
        REM IF c{(I%)}.pen% THEN
        REM PROC_gdipdeletepen( c{(I%)}.pen% )
        REM c{(I%)}.pen% = 0
        REM ENDIF
        REM NEXT I%
        PROC_gdipexit
        `GdiplusStartup` = 0
      ENDIF
      ENDPROC

      DEF PROCerror( s$ )
      OSCLI "REFRESH ON" : CLS : ON : VDU 7 : PRINT '" "+s$;
      REPEAT
        WAIT 1
      UNTIL FALSE
      ENDPROC

      REM Number of quotes:
      DATA 10

      REM Quote 1:
      DATA "Predicting rain doesn't count."
      DATA "Building arks does."
      DATA " "
      DATA "(Warren Buffet)"
      DATA ""

      REM Quote 2:
      DATA "No person has the right to rain on your dreams."
      DATA " "
      DATA "(Marian Wright Edelman)"
      DATA ""

      REM Quote 3:
      DATA "My sorrow, when she's here with me,"
      DATA "thinks these dark days of autumn rain"
      DATA "are beautiful as days can be;"
      DATA "she loves the bare, the withered tree;"
      DATA "she walks the sodden pasture lane."
      DATA " "
      DATA "(Robert Frost)"
      DATA ""

      REM Quote 4:
      DATA "It will never rain roses:"
      DATA "when we want to have more roses"
      DATA "we must plant more trees."
      DATA " "
      DATA "(George Eliot)"
      DATA ""

      REM Quote 5:
      DATA "The way I see it, if you want the rainbow,"
      DATA "you gotta put up with the rain."
      DATA " "
      DATA "(Dolly Parton)"
      DATA ""

      REM Quote 6:
      DATA "Sunshine is delicious, rain is refreshing,"
      DATA "wind braces us up, snow is exhilarating;"
      DATA "there is really no such thing as bad weather,"
      DATA "only different kinds of good weather."
      DATA " "
      DATA "(John Ruskin)"
      DATA ""

      REM Quote 7:
      DATA "Life is the fire that burns"
      DATA "and the sun that gives light."
      DATA "Life is the wind and the rain"
      DATA "and the thunder in the sky."
      DATA "Life is matter and is earth,"
      DATA "what is and what is not,"
      DATA "and what beyond is in Eternity."
      DATA " "
      DATA "(Lucius Annaeus Seneca)"
      DATA ""

      REM Quote 8:
      DATA "Into each life some rain must fall."
      DATA " "
      DATA "(Henry Wadsworth Longfellow)"
      DATA ""

      REM Quote 9:
      DATA "I think fish is nice,"
      DATA "but then I think that rain is wet,"
      DATA "so who am I to judge?"
      DATA " "
      DATA "(Douglas Adams)"
      DATA ""

      REM Quote 10:
      DATA "Meteorologists are pretty faces reading scripts"
      DATA "telling you whether it's going to rain tomorrow."
      DATA " "
      DATA "(Noam Chomsky)"
      DATA ""
http://www.proggies.uk/gfxlib/gfxlibpage.html
KenDown
Posts: 327
Joined: Wed 04 Apr 2018, 06:36

Re: Water Ripples

Post by KenDown »

Hmmmm. I wanted to have a look at this and so, for the first time, downloaded GFXLIB2 (v.2.06). Unfortunately it does not appear to have the module Clrlg.bbc. Any ideas, please?
David Williams

Re: Water Ripples

Post by David Williams »

KenDown wrote: Mon 16 Dec 2019, 14:49 Hmmmm. I wanted to have a look at this and so, for the first time, downloaded GFXLIB2 (v.2.06). Unfortunately it does not appear to have the module Clrlg.bbc. Any ideas, please?
Hmm strange. I expected ClrLG to be in v2.06, but you're right - it's missing. I haven't been very good at keeping the public release of the GfxLib2 package updated.

Here's a link to the missing module:

http://www.proggies.uk/temp/clrlg.zip

With that in place, I hope the program runs ok this time.


David.
--
RichardRussell

Re: Water Ripples

Post by RichardRussell »

I've made a BBCSDL version of this, but the performance of aagfxlib isn't good enough (compared with Windows' GDI+) to support as many as 250 ripples; dropping it to 100 is more acceptable but it still needs a fast PC.

I couldn't figure out why you initially plot the ellipses 'linearly' and then perform a non-linear stretch to their final location and size. I simply adjusted the ellipses' dimensions according to their vertical position, and the end result seemed pretty similar. Am I missing something?

My version is 'pure' BBC BASIC code (plus the aagfxlib library), no SDL2 magic.
KenDown
Posts: 327
Joined: Wed 04 Apr 2018, 06:36

Re: Water Ripples

Post by KenDown »

Thanks, it works fine now.
RichardRussell

Re: Water Ripples

Post by RichardRussell »

RichardRussell wrote: Mon 16 Dec 2019, 17:59Am I missing something?
I'm wondering if you were concerned that a 'tilted circle' doesn't look quite the same as an 'ellipse' (if the line thickness is substantial) but subjectively I don't notice this in practice. Here's my BBCSDL version:

https://www.youtube.com/watch?v=52p-EMoF-Ck

Code: Select all

      REM Raindrop Water Ripples 2
      REM Requires BBCSDL

      *ESC OFF

      MODE 8 : OFF
      ScrW% = 640
      ScrH% = 512

      ON MOVE PROCresize(@msg%, @lparam%) : RETURN
      ON ERROR PROCcleanup : PROCerror( REPORT$ + " at line " + STR$ERL )
      ON CLOSE PROCcleanup : QUIT

      N% = 100 : REM no. of ripples

      INSTALL @lib$ + "aagfxlib"

      RESTORE
      READ nQuotes%
      maxQuoteLines% = 10
      DIM quote{( nQuotes%-1 ) nLines%, s$(maxQuoteLines%-1)}
      FOR I% = 0 TO nQuotes%-1
        REPEAT
          READ s$
          IF s$ <> "" THEN
            quote{(I%)}.s$( quote{(I%)}.nLines% ) = s$
            quote{(I%)}.nLines% += 1
          ENDIF
        UNTIL s$ = ""
      NEXT I%

      OSCLI "font """ + @lib$ + "DejaVuSans"", 16"

      DIM c{(N%-1) rgb%, x, z, r, e, t, maxr}

      FOR I% = 0 TO N%-1
        PROCnew( I%, FALSE )
      NEXT I%

      quote% = RND(nQuotes%) - 1

      SYS "SDL_GetTicks" TO tim%
      displayQuoteTime% = tim% + 5000

      *REFRESH OFF

      SYS "SDL_GetTicks" TO tim%

      VDU 5
      COLOUR 1, &10, &60, &B0
      COLOUR 3, &D0, &C0, &10
      REPEAT

        old_tim% = tim%
        SYS "SDL_GetTicks" TO tim%
        dt = 60 * (tim% - old_tim%) / 1000

        COLOUR 128+1 : CLS

        FOR I% = 0 TO N%-1
          PROC_aaellipse( c{(I%)}.x, c{(I%)}.z, c{(I%)}.r, c{(I%)}.r * c{(I%)}.e, c{(I%)}.t, 0 , c{(I%)}.rgb% )
          c{(I%)}.r += 0.5 * dt

          c{(I%)}.t = 2.0 + (5.0 - 2.0)*(1 - c{(I%)}.z / 640)
          opacity% = FNopacity( c{(I%)}.r, c{(I%)}.maxr, c{(I%)}.z )
          c{(I%)}.rgb% = FNrgb( opacity% )

          IF c{(I%)}.r >= c{(I%)}.maxr THEN
            PROCnew( I%, TRUE )
          ENDIF
        NEXT I%

        FOR Y% = 640 TO 1020 STEP 4
          p = Y% / 1020
          COLOUR 2, &10 + p*&30, &40 + p*&10, &40 + p*&60
          GCOL 2 : RECTANGLE FILL 0, Y%, 1278, 4
        NEXT
        IF tim% >= displayQuoteTime% PROCDisplayQuote(quote%)

        *REFRESH

      UNTIL FALSE
      END

      DEF FNopacity( r, maxr, z )
      = (1 - r/maxr) * (64 + 191 * (1 - z / 640))

      DEF FNrgb( O% )
      = (O% << 24) OR &FFA000

      DEF PROCnew( I%, R% )
      c{(I%)}.x = 1280 * RND(1)
      c{(I%)}.z =  640 * RND(1)
      c{(I%)}.maxr = 8 + 48*RND(1)
      IF R% THEN
        c{(I%)}.r = 0.5
      ELSE
        c{(I%)}.r = 0.5 * c{(I%)}.maxr * RND(1)
      ENDIF

      c{(I%)}.e = 0.5 / (1.0 + 0.00375 * c{(I%)}.z / 2)
      c{(I%)}.r *= 2 - c{(I%)}.z / 640
      c{(I%)}.maxr *= 2 - c{(I%)}.z / 640

      c{(I%)}.t = 2.0 + (8.0 - 2.0)*(1 - c{(I%)}.z / 640)
      c{(I%)}.rgb% = FNrgb( FNopacity( c{(I%)}.r, c{(I%)}.maxr, c{(I%)}.z ) )
      ENDPROC

      DEF PROCDisplayQuote(i%)
      LOCAL I%, W%, s$
      FOR I% = 0 TO quote{(i%)}.nLines%-1
        s$ = quote{(i%)}.s$(I%)
        W% = WIDTH(s$)
        MOVE 640-W%/2-2, 664-56*I%-2 : GCOL 0 : PRINT s$;
        MOVE 640-W%/2,   664-56*I%   : GCOL 3 : PRINT s$;
      NEXT I%
      ENDPROC

      DEF PROCcleanup
      *REFRESH ON
      ENDPROC

      DEF PROCerror( s$ )
      OSCLI "REFRESH ON" : CLS : ON : VDU 7 : PRINT '" "+s$;
      REPEAT
        WAIT 1
      UNTIL FALSE
      ENDPROC

      DEF PROCresize(M%, L%) IF M% <> 5 ENDPROC
      LOCAL W%, H%
      W% = L% AND &FFFF
      H% = L% >>> 16
      IF W%/H% > ScrW%/ScrH% THEN
        @zoom% = &8000 * H% / ScrH%
      ELSE
        @zoom% = &8000 * W% / ScrW%
      ENDIF
      IF @zoom% < &8000 @zoom% = &8000
      IF (@platform% AND 7) < 3 THEN
        @panx% = (ScrW% - W% * &8000 / @zoom%) / 2
        @pany% = (ScrH% - H% * &8000 / @zoom%) / 2
      ENDIF
      ENDPROC

      REM Number of quotes:
      DATA 10

      REM Quote 1:
      DATA "Predicting rain doesn't count."
      DATA "Building arks does."
      DATA " "
      DATA "(Warren Buffet)"
      DATA ""

      REM Quote 2:
      DATA "No person has the right to rain on your dreams."
      DATA " "
      DATA "(Marian Wright Edelman)"
      DATA ""

      REM Quote 3:
      DATA "My sorrow, when she's here with me,"
      DATA "thinks these dark days of autumn rain"
      DATA "are beautiful as days can be;"
      DATA "she loves the bare, the withered tree;"
      DATA "she walks the sodden pasture lane."
      DATA " "
      DATA "(Robert Frost)"
      DATA ""

      REM Quote 4:
      DATA "It will never rain roses:"
      DATA "when we want to have more roses"
      DATA "we must plant more trees."
      DATA " "
      DATA "(George Eliot)"
      DATA ""

      REM Quote 5:
      DATA "The way I see it, if you want the rainbow,"
      DATA "you gotta put up with the rain."
      DATA " "
      DATA "(Dolly Parton)"
      DATA ""

      REM Quote 6:
      DATA "Sunshine is delicious, rain is refreshing,"
      DATA "wind braces us up, snow is exhilarating;"
      DATA "there is really no such thing as bad weather,"
      DATA "only different kinds of good weather."
      DATA " "
      DATA "(John Ruskin)"
      DATA ""

      REM Quote 7:
      DATA "Life is the fire that burns"
      DATA "and the sun that gives light."
      DATA "Life is the wind and the rain"
      DATA "and the thunder in the sky."
      DATA "Life is matter and is earth,"
      DATA "what is and what is not,"
      DATA "and what beyond is in Eternity."
      DATA " "
      DATA "(Lucius Annaeus Seneca)"
      DATA ""

      REM Quote 8:
      DATA "Into each life some rain must fall."
      DATA " "
      DATA "(Henry Wadsworth Longfellow)"
      DATA ""

      REM Quote 9:
      DATA "I think fish is nice,"
      DATA "but then I think that rain is wet,"
      DATA "so who am I to judge?"
      DATA " "
      DATA "(Douglas Adams)"
      DATA ""

      REM Quote 10:
      DATA "Meteorologists are pretty faces reading scripts"
      DATA "telling you whether it's going to rain tomorrow."
      DATA " "
      DATA "(Noam Chomsky)"
      DATA ""
David Williams

Re: Water Ripples

Post by David Williams »

RichardRussell wrote: Mon 16 Dec 2019, 17:59 I couldn't figure out why you initially plot the ellipses 'linearly' and then perform a non-linear stretch to their final location and size.
The effect is supposed to be 3D (or at least pseudo-3D). In that regard, I hope it's pretty convincing.

To create the illusion of depth, I did the following:

* Circle thickness is inversely proportional to its Y coordinate (thick at the bottom of image, thin at the top)
* Circle transparency is proportional to its Y coordinate (opaque at the bottom, transparent at the top)
* 3D perspective effect achieved by scaling the horizontal rows of pixels

(Not too cleverly, admittedly.)

EDIT: I should add that the 'perspectivization' exhibited in the released version of the program was more subtle than originally intended. If you change the following line (940) from

Code: Select all

SYS P%, G%, bm% + 4*640*INTy, 640, 1, 2*w, 1, 320-2*w/2, Y%
to

Code: Select all

SYS P%, G%, bm% + 4*640*INTy, 640, 1, w, 1, 320-w/2, Y%
you'll see exactly what I mean. :)

I simply adjusted the ellipses' dimensions according to their vertical position, and the end result seemed pretty similar. Am I missing something?
That's great, as long as it hasn't destroyed the 3D effect!

You will have noticed that the program was titled 'Raindrop Water Ripples 2', which implies a version 1. Here's Version 1 -- the circles are plotted point-by-point using GFXLIB_PlotSubpixel. To further enhance the 3D effect, I decided that I would need to vary the circle thickness according to apparent distance, but GfxLib lacks a thick circle routine (although I could have faked one), so I resorted to using GDI+ and the end result effectively became Version 2.

"Raindrop Water Ripples 1" (exe)
http://www.proggies.uk/temp/waterripples1.zip

Code: Select all

      REM Raindrop Water Ripples 1
      REM Requires BB4W & GfxLib2

      *ESC OFF

      MODE 8 : OFF

      ON ERROR PROCerror( REPORT$ + " at line " + STR$ERL )

      N% = 250 : REM no. of rings

      INSTALL @lib$+"GFXLIB2.BBC" : PROCInitGFXLIB(g{},0)
      INSTALL @lib$+"GFXLIB_modules\ClrLG"          : PROCInitModule(0)
      INSTALL @lib$+"GFXLIB_modules\PlotSubpixel"   : PROCInitModule(0)
      INSTALL @lib$+"GFXLIB_modules\RectangleSolid" : PROCInitModule(0)
      INSTALL @lib$+"GFXLIB_modules\PlotAND3"       : PROCInitModule(0)
      INSTALL @lib$+"GFXLIB_modules\DrawBmFont4"    : PROCInitModule(0)

      timeGetTime% = FNSYS_NameToAddress( "timeGetTime" )
      Sleep% = FNSYS_NameToAddress( "Sleep" )

      arial12pt% = FNLoadData( @lib$ + "GFXLIB_media/arial12pt.dat" )

      MinR% = 4
      MaxR% = 60

      DIM c{(N%-1) x, z, r, maxr}

      FOR I% = 0 TO N%-1
        PROCnew_ring(I%, FALSE)
      NEXT I%

      A% = g.bmBuffAddr%
      W% = 640
      H% = 512
      P% = GFXLIB_PlotSubpixel%

      frameRate% = 0
      frames% = 0

      *REFRESH OFF

      SYS timeGetTime% TO time0%

      time% = time0% - 16

      REPEAT
  
        time_old% = time%
        SYS timeGetTime% TO time%
        dt = 60 * (time% - time_old%)/1000
  
        SYS GFXLIB_ClrLG%, g{}, &051030, &2050A0
  
        SYS GFXLIB_RectangleSolid%, g{}, 0, 0, 640, 224, &204080
  
        FOR I% = 0 TO N%-1
    
          i% = 256 * (c{(I%)}.r / c{(I%)}.maxr)^2
          SYS GFXLIB_LerpRGB%, &4080FF, &204080, i% TO K%
    
          r = c{(I%)}.r
          x0 = c{(I%)}.x
          z0 = 300 + c{(I%)}.z
          i = 0.5 * ACS(1 - (2/r)^2) : REM angle step
    
          FOR a = 0 TO 2*PI STEP i
            z = &190/(z0+r*COSa)
            SYS P%, A%, W%, H%, &100*(&140+(x0+r*SINa)*z), &100*(&100-&C8*z), K%
          NEXT
    
          c{(I%)}.r += 0.5 * dt
          IF c{(I%)}.r >= c{(I%)}.maxr THEN
            PROCnew_ring(I%, TRUE)
          ENDIF
    
        NEXT I%
  
        SYS GFXLIB_DrawBmFont4%, g{}, arial12pt%, STR$frameRate% + " fps", 4, 484, &4A6AFF
  
        SYS timeGetTime% TO time1%
        IF time1% - time0% >= 1000 THEN
          frameRate% = frames%
          frames% = 0
          SYS timeGetTime% TO time0%
        ENDIF
  
        PROCdisplay(0)
        SYS Sleep%, 1
  
        frames% += 1
  
      UNTIL FALSE
      END

      DEF PROCnew_ring(I%, R%) : REM R% is 'reset flag'
      c{(I%)}.x = 1500*RND(1)*SGN(RND-RND)
      c{(I%)}.z = 2000*RND(1)
      c{(I%)}.maxr = (MaxR%/2) * (1 + RND(1))
      c{(I%)}.r = MinR%
      IF NOT R% THEN
        c{(I%)}.r += (c{(I%)}.maxr - MinR%)*RND(1)
      ENDIF
      ENDPROC

      DEF PROCerror( s$ )
      OSCLI "REFRESH ON" : CLS : ON : PRINT '" ";
      PRINT s$;
      VDU 7
      REPEAT UNTIL INKEY(1)=0
      ENDPROC

David.
--
RichardRussell

Re: Water Ripples

Post by RichardRussell »

David Williams wrote: Tue 17 Dec 2019, 03:04* 3D perspective effect achieved by scaling the horizontal rows of pixels
I'm still not fully understanding. Given that the image contains no 'large scale' objects (which would require perspective transformations) but only ripples (and those ripples presumably cover an 'infinite' area of water), I don't really see how a "3D perspective effect" amounts to any more than the ripples apparently getting smaller and closer together as they get further away.

Subjectively I don't see a huge difference between yours and mine as far as the 'depth effect' is concerned. To the extent that there is a difference, I reckon I could make mine more similar without having to resort to any perspective transformations (e.g. by reducing the ripple spacing towards the top of the image, which I don't currently do).
David Williams

Re: Water Ripples

Post by David Williams »

RichardRussell wrote: Tue 17 Dec 2019, 10:50
David Williams wrote: Tue 17 Dec 2019, 03:04* 3D perspective effect achieved by scaling the horizontal rows of pixels
I'm still not fully understanding. Given that the image contains no 'large scale' objects (which would require perspective transformations) but only ripples (and those ripples presumably cover an 'infinite' area of water), I don't really see how a "3D perspective effect" amounts to any more than the ripples apparently getting smaller and closer together as they get further away.

Subjectively I don't see a huge difference between yours and mine as far as the 'depth effect' is concerned. To the extent that there is a difference, I reckon I could make mine more similar without having to resort to any perspective transformations (e.g. by reducing the ripple spacing towards the top of the image, which I don't currently do).
The program is a little graphical ditty, written hastily as usual, simply to be enjoyed for a minute or two by fellow BBC BASIC users; it's not a mathematical or physically accurate simulation of water ripples. The perspectivization/linear transform, although rather subtle, was obviously intended to enhance the illusion of depth (which I, subjectively, believe it does).

Let's leave it at that.