Plasma Effect

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
Ophelius
Posts: 428
Joined: Feb 26, 2006 1:57

Plasma Effect

Postby Ophelius » Apr 15, 2010 1:22

Here's an attempt at some plasma. I just started learning about how to do this today, so it's unoriginal and unoptimized. You'll need the Allegro 4.0 dll if you haven't got it:
http://www.dlldll.com/downdll/7417.html

Code: Select all

#include "Allegro.bi"

DECLARE SUB Shift_Pal ()


DIM SHARED AS INTEGER SCR_W = 500, SCR_H = 200
DIM SHARED AS RGB Pal(0 to 255), Temp_Col
DIM SHARED Buffer AS BITMAP PTR

Allegro_Init ()

Install_Keyboard

IF SET_GFX_MODE(0, SCR_W, SCR_H, 0, 0) <> 0 then end

Buffer = Create_Bitmap(SCR_W, SCR_H)

dim as integer i, x, y, Style

'Generate Palette

'set entire pal to black
for i = 0 to 255
    Pal(i).R = 0
    Pal(i).G = 0
    Pal(i).B = 0
next i

for i = 0 to 63
    Pal(i).R = 0
    Pal(i).G = i
    Pal(i).B = i
next i

for i = 0 to 63
    Pal(64+i).R = 0
    Pal(64+i).G = 63-i
    Pal(64+i).B = 63-i
next i

Set_Palette @Pal(0)

Style = 1

do
   
    Clear_Bitmap Buffer
       
    for y = 0 to SCR_H - 1
        for x = 0 to SCR_W - 1
           
            Select Case Style
            Case 1
                i = int( (32 + (32 * SIN( y / 16 ) ) ) +_
                         (32 + (32 * SIN( x / 16 ) ) ) +_
                         (32 + (32 * SIN( (SQR(x*x + y*y)) / 16 ) ) ) ) \ 3
            Case 2
                i = int( (32 + (32 * SIN( y * SQR(X)/ 128 ) ) ) +_
                         (32 + (32 * SIN( x * SQR(Y)/ 128 ) ) ) +_
                         (32 + (32 * SIN( (SQR(x*x + y*y)) /32 ) ) ) ) \ 3
            END SELECT
           
            PutPixel Buffer, x, y, i
           
        next x
    next y

    Shift_Pal

    Set_Palette @Pal(0)
       
    Blit Buffer, Screen, 0, 0, 0, 0, Buffer->W, Buffer->H
   
loop until KEY(KEY_ESC)


END



SUB Shift_Pal ()
   
    dim i as integer
   
    Temp_Col.R = Pal(127).R
    Temp_Col.G = Pal(127).G
    Temp_Col.B = Pal(127).B
    for i = 127 to 1 step -1
        Pal(i).R = Pal(i-1).R
        Pal(i).G = Pal(i-1).G
        Pal(i).B = Pal(i-1).B
    NEXT i
    Pal(0).R = Temp_Col.R
    Pal(0).G = Temp_Col.G
    Pal(0).B = Temp_Col.B
   
END SUB



If you have ideas how to make this look better, or more optimized, let me know. ;)

Ophelius
relsoft
Posts: 1767
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Postby relsoft » Apr 15, 2010 2:20

Palette switching is good. But the coolest looking plasmas are ones made in real-time.

http://qbcm.hybd.net/issues/4-1/#plasmas
Ophelius
Posts: 428
Joined: Feb 26, 2006 1:57

Postby Ophelius » Apr 15, 2010 3:54

Thanks Rel, that helped a lot. I updated my code to use both palette shifting and plasma movement. The effect is really cool:

Code: Select all

#include "Allegro.bi"

DECLARE SUB Shift_Pal ()


DIM SHARED AS INTEGER SCR_W = 500, SCR_H = 200
DIM SHARED AS RGB Pal(0 to 255), Temp_Col
DIM SHARED Buffer AS BITMAP PTR

Allegro_Init ()

Install_Keyboard

IF SET_GFX_MODE(0, SCR_W, SCR_H, 0, 0) <> 0 then end

Buffer = Create_Bitmap(SCR_W, SCR_H)

dim as integer i, x, y, Style

'Generate Palette

for i = 0 to 255
    Pal(i).R = 0
    Pal(i).G = 0
    Pal(i).B = 0
next i

for i = 0 to 63
    Pal(i).R = 0
    Pal(i).G = i
    Pal(i).B = i
next i

for i = 0 to 63
    Pal(64+i).R = 0
    Pal(64+i).G = 63-i
    Pal(64+i).B = 63-i
next i

Set_Palette @Pal(0)


dim c as integer
do
   
    Clear_Bitmap Buffer
       
    for y = 0 to SCR_H - 1
        for x = 0 to SCR_W - 1
           
            i = ((32+(SIN((x)/32) * 32)) + (32+(COS((x+y+C)/16) * 32))+(32+(COS((SQR(y*y+x*x))/8) * 32))) / 3
           
            PutPixel Buffer, x, y, i
           
        next x
    next y

    C = (C+2) MOD 100

    Shift_Pal

    Set_Palette @Pal(0)

    Blit Buffer, Screen, 0, 0, 0, 0, Buffer->W, Buffer->H
   
loop until KEY(KEY_ESC)


END



SUB Shift_Pal ()
   
    dim i as integer
   
    Temp_Col.R = Pal(127).R
    Temp_Col.G = Pal(127).G
    Temp_Col.B = Pal(127).B
    for i = 127 to 1 step -1
        Pal(i).R = Pal(i-1).R
        Pal(i).G = Pal(i-1).G
        Pal(i).B = Pal(i-1).B
    NEXT i
    Pal(0).R = Temp_Col.R
    Pal(0).G = Temp_Col.G
    Pal(0).B = Temp_Col.B
   
END SUB


It's a lot of fun trying new equations to see what comes up. Has anyone ever written a manual explaining a lot of the popular graphic tricks, stuff you would find in demos?(roto-zooming, palette tricks, etc). I would like to know more about these techniques.
Merick
Posts: 1038
Joined: May 28, 2007 1:52

Postby Merick » Apr 15, 2010 20:22

Take a look at DBF, it's a demoscene forum with a section dedicated to FB: http://www.dbfinteractive.com/
relsoft
Posts: 1767
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Postby relsoft » Apr 17, 2010 1:38

Ophelius wrote:Thanks Rel, that helped a lot. I updated my code to use both palette shifting and plasma movement. The effect is really cool:



It's a lot of fun trying new equations to see what comes up. Has anyone ever written a manual explaining a lot of the popular graphic tricks, stuff you would find in demos?(roto-zooming, palette tricks, etc). I would like to know more about these techniques.


Here:
http://rel.betterwebber.com/index.php?a ... =Tutorials

Try to read "How to make Blobs(metaballs)" and "lensflares".
Ophelius
Posts: 428
Joined: Feb 26, 2006 1:57

Postby Ophelius » Apr 17, 2010 5:16

I've studied the metaballs code and it's easier than it looks. You had a more complicated Plasma+metaball example too. I was stunned by the plasma in the background. How do you go about finding good equations for a plasma. Yours looks really complex. Do you just stumble on one by trying different numbers/forms, or is it based on some Physics(it looks like fluid dynamics)? I still have so much to learn. :(
relsoft
Posts: 1767
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Postby relsoft » Apr 18, 2010 7:11

Ophelius wrote:I've studied the metaballs code and it's easier than it looks. You had a more complicated Plasma+metaball example too. I was stunned by the plasma in the background. How do you go about finding good equations for a plasma. Yours looks really complex. Do you just stumble on one by trying different numbers/forms, or is it based on some Physics(it looks like fluid dynamics)? I still have so much to learn. :(


I just try to change equations until it looks good while being sure that the offsets and params are not over the scale that I gave the sin luts. It's easy to visualize trig funks since they are periodic in nature.

Here's an example I made for my daughter's Nintendo DS yesterday. Sorry its C++ but I could make it in FB later if you want.

Code: Select all

/*
NDS Translucent Plasma
Relminator

http://rel.betterwebber.com

*/

#include <nds.h>
#include <stdio.h>
#include <math.h>


// some sine LUTs
u8 lsin1[2048];
u8 lsin2[2048];
u8 lsin3[2048];

// RGB palette
u16 pal[256];   

int main(void)
{
   
   // constant sine divisor
   const u8 K1 = 32;
    const u8 K2 = 12;
    const u8 K3 = 28;
   
   // maximum values our dynamic plasmas can move
   u16 KSIN1 = u8(K1 *(360/57.3f));
    u16 KSIN2 = u8(K2 *(360/57.3f));
    u16 KSIN3 = u8(K3 *(360/57.3f));
   
   
          
   // precalculate our luts
   for (int i = 0; i< ((2048) - 1); i++)
   {
        lsin1[i] = sin(i/(float)K1) * 32+32;
        lsin2[i] = sin(i/(float)K2) * 16+16;
        lsin3[i] = sin(i/(float)K3) * 20+20;
    }   

   // generate our 256 color palette
   for (int i=0; i<256; i++)
   {
       u8 r = (u8)(abs(int(16 - 15 * sin(i * M_PI / 16.0f))));
      u8 g = (u8)(abs(int(16 - 15 * sin(i * M_PI / 12.0f))));
      u8 b = (u8)(abs(int(16 - 15 * sin(i * M_PI / 18.0f))));
      pal[i] = RGB15(r,g,b);
   }

   irqInit();
   irqEnable(IRQ_VBLANK);
   
   
   //initialize the DS Dos-like functionality
   consoleDemoInit();
   
   iprintf("\x1b[1;1HTranslucent Plasma!");
   iprintf("\x1b[2;1HFramebuffer madness!");
   iprintf("\x1b[3;1HRelsoft");
   iprintf("\x1b[4;1Hhttp://rel.betterwebber.com");
   iprintf("\x1b[6;1HAnya Therese B. Lope");
 
   //set frame buffer mode 0
   videoSetMode(MODE_FB0);
 
   //enable VRAM A for writting by the cpu and use
   //as a framebuffer by video hardware
   vramSetBankA(VRAM_A_LCD);
 
   u8 rot;                  // translucent factor
   u16 counter =0;            // frame counter
   u16 a = 0, b = 0, ct = 0;   // movement deltas
   u16 c;                  // palette color index
   
   while(1)
   {

      // dynamically move our plasmas
      a= (a + 1) % (KSIN1 + 1);
      b = (b + 1) % (KSIN2 + 1);
      ct = (ct + 1) % (KSIN3 + 1);
      
      // offset 2nd plasma by a factor of 64 * 2 or (-64 to 64)
      rot = 64 * (((counter & 1) == 1) | 1);
      
      // inc frame
      counter++;
      
      //write to vram directly
      short unsigned int *vram_offset = VRAM_A;
      
      for (int ya = 0; ya<SCREEN_HEIGHT; ya++)
      {
         for (int xa = 0; xa <SCREEN_WIDTH-1; xa++)
         {
            rot = -rot;      // draw plasmas every other pixel
            // calculate colors
            c = (lsin1[xa + a + rot] + lsin2[ya + b + rot] +lsin3[1024+xa + ya - ct]);
            c = (lsin1[xa + a + rot+c] + lsin2[ya + b + rot+c] +lsin3[1024+xa + ya - ct+c]);
            // write to vram
            *vram_offset++ = pal[c];
         }
         vram_offset++;      // magic
      }      
      swiWaitForVBlank();
   }
 
   return 0;
}
 
Ophelius
Posts: 428
Joined: Feb 26, 2006 1:57

Postby Ophelius » Apr 18, 2010 16:41

Thanks for that. I converted it to FB for you. Looks real cool. Though I don't know the DS's screen res and what the U8 and U16 meant, I had to improvise, so I think there might be issues with that. The palette was pretty dark, so you'll notice I multiplied it by 8 to get it brighter. I'm sure it's just some mistake in my conversion and wasn't your intention.

I was surprised I got it to work right away because I don't code in C, but it's very similar. I just guessed that % meant Mod and | meant Or, etc:

Code: Select all

DIM AS INTEGER SCR_W = 320, SCR_H=200

DIM LSIN1(2048) AS DOUBLE
DIM LSIN2(2048) AS DOUBLE
DIM LSIN3(2048) AS DOUBLE

'constant sine divisor
Const K1 = 32
Const K2 = 12
Const K3 = 28

const PI = 3.141593

       
'maximum values our dynamic plasmas can move
DIM AS INTEGER KSIN1 = K1 *(360/57.3)
DIM AS INTEGER KSIN2 = K2 *(360/57.3)
DIM AS INTEGER KSIN3 = K3 *(360/57.3)

                   
'precalculate our luts
dim as integer i
For i = 0 to 2047

    lsin1(i) = Sin(i/K1) * 32 + 32
    lsin2(i) = Sin(i/K2) * 16 + 16
    lsin3(i) = Sin(i/K3) * 20 + 20
   
next i


SCREENRES SCR_W, SCR_H, 8


'generate our 256 Color Palette
DIM AS INTEGER r,g,b
For i = 0 to 255

    r = 8*(Abs(Int(16 - 15 * Sin(i * PI / 16.0))))
    g = 8*(Abs(Int(16 - 15 * Sin(i * PI / 12.0))))
    b = 8*(Abs(Int(16 - 15 * Sin(i * PI / 18.0))))
   
    palette i, r, g, b
   
Next i

DIM AS INTEGER rot                              ' translucent factor
DIM AS INTEGER counter =0                       ' frame counter
DIM AS INTEGER d_a = 0, d_b = 0, d_ct = 0       ' movement deltas
DIM AS INTEGER c                                ' Palette Color index
DIM AS INTEGER xa, ya

While INKEY = ""


        'dynamically move our plasmas
        d_a= (d_a + 1) MOD (KSIN1 + 1)
        d_b = (d_b + 1) MOD (KSIN2 + 1)
        d_ct = (d_ct + 1) MOD (KSIN3 + 1)
       
        'offset 2nd plasma by a factor of 64 * 2 Or (-64 To 64)
        rot = 64 * (((counter AND 1) = 1) OR 1)
       
       
        For ya = 0 TO SCR_H - 1
       
                For xa = 0 to SCR_W-1
               
                        rot = -rot        'Draw plasmas every other pixel
                       
                        'calculate colors
                        c = (lsin1(xa + d_a + rot) + lsin2(ya + d_b + rot) + lsin3(1024+xa + ya - d_ct))
                        c = (lsin1(xa + d_a + rot+c) + lsin2(ya + d_b + rot+c) + lsin3(1024+xa + ya - d_ct+c))
                       
                        'SCREENLOCK  'don't know if this is necessary
                        PSET (xa, ya), c
                        'SCREENUNLOCK 'this either

                Next xa
               
        Next ya
       
        'inc frame
        Counter+=1
       
WEND
relsoft
Posts: 1767
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Postby relsoft » Apr 19, 2010 1:03

Nice!! I forgot to tell you that the DS has 16 bit of colors and its RGB15 ranges of only 0-31 per channel as opposed to FB's 32 bit mode where channels range from 0-255.

Anyways, here's a 32 bit version I coded last night.

Code: Select all

''Plazma!!!
''relminator
''http://rel.betterwebber.com

const as integer SCR_WID = 256
const as integer SCR_HEI = 192
const as integer BPP = 32


const as single PI = atn(1) * 4


const as integer K1 = 22
const as integer K2 = 32
const as integer K3 = 58


dim shared as integer ksin1,ksin2,ksin3
   
dim shared as uinteger ptr lsin1
dim shared as uinteger ptr lsin2
dim shared as uinteger ptr lsin3

lsin1 = new uinteger[2048]
lsin2 = new uinteger[2048]
lsin3 = new uinteger[2048]   
   
for i as integer = 0 to 2048 - 1
    lsin1[i] = sin((i-1024)/K1) * 120+120
    lsin2[i] = sin((i-1024)/K2) * 64+64
    lsin3[i] = sin((i-1024)/K3) * 164+164
next i
 

KSIN1 = int(K1 *(360/57.3))
KSIN2 = int(K2 *(360/57.3))
KSIN3 = int(K3 *(360/57.3))





dim as uinteger ptr pal = new uinteger[256]

for i as integer = 0 to 255
    dim as ubyte r = cbyte(abs(INT(128 - 127 * SIN(i * PI / 32))))
    dim as ubyte g = cbyte(abs(INT(128 - 127 * SIN(i * PI / 64))))
    dim as ubyte b = cbyte(abs(INT(128 - 127 * SIN(i * PI / 128))))
    pal[i]=rgb(r,g,b)
next i





dim as integer a = 0, b = 0, ct = 0   
dim as integer rot, counter =0

screenres SCR_WID,SCR_HEI,BPP,2

screenset 1, 0
do
    a = (a + 1) mod (KSIN1 + 1)
    b = (b + 1) mod (KSIN2 + 1)
    ct = (ct + 1) mod (KSIN3 + 1)
   
    rot = 64 * (((counter AND 1) = 1) OR 1)
   counter += 1
   
    screenlock
    Line (0, 0)-(SCR_WID, SCR_HEI), 0, BF
   
    for y as integer = 0 to 191
       for x as integer = 0 to 254                
          rot = -rot          
            dim as integer c = Lsin1[x+a] + Lsin2[y+b] + Lsin3[x+y-ct+1024]
            c = Lsin1[x+a+rot+c] + Lsin2[y+b+rot+c] + Lsin3[x+y-ct+1024]       
            c = c and 255
          pset (x,y), pal[c]
       next x
    next y
    screenunlock
    sleep 1,1
   
    ScreenCopy
Loop While Inkey = ""


delete[] lsin1
delete[] lsin2
delete[] lsin3
delete[] pal


end

joseywales72
Posts: 206
Joined: Aug 27, 2005 2:02
Location: Istanbul, Turkey

Postby joseywales72 » Apr 19, 2010 7:50

Hi,
Great effects... There is something strange though. Ophelius' translation compiles and works fine on my Linux (Arch 32, 2.6.33, Xorg 1.7.5) but Relsofts last one does not compile and gives this error.

Code: Select all

/usr/lib/libsupc++.a(eh_personality.o): In function `__gxx_personality_v0':
(.text.__gxx_personality_v0+0xba): undefined reference to `_Unwind_GetIPInfo'

Any ideas?
Thanks.
Anil
Ophelius
Posts: 428
Joined: Feb 26, 2006 1:57

Postby Ophelius » Apr 19, 2010 18:27

Could be because he's allocating memory for his Luts and Palette with the NEW function. I don't understand why he did that when a simple DIM would work fine. Is it speed increase Rel? So maybe that doesn't work in Linux.
relsoft
Posts: 1767
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Postby relsoft » Apr 21, 2010 2:51

Ophelius wrote:Could be because he's allocating memory for his Luts and Palette with the NEW function. I don't understand why he did that when a simple DIM would work fine. Is it speed increase Rel? So maybe that doesn't work in Linux.


As for the Linux bug, I have no idea. It's been 5 years since I last touched a Linux Distro.

Yeah, I usually use new and delete for speed. Dynamic Arrays in FB or anywhere has a few overheads on access.

BTW, to make it faster, ditch the pset and write directly to the buffer using screenptr+offset.
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Postby anonymous1337 » Apr 21, 2010 21:54

@joseywales: You need GCC to compile FB programs with certain features from now on.

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 1 guest