Author Topic: Old School Plasma Demo Effect  (Read 6778 times)

Pantheon

  • Guest
Old School Plasma Demo Effect
« on: August 15, 2010, 01:14:43 am »
Tonight I have writen a small "Plasma Effect" for the Dingoo as a learning exercise.
I found some code on the web to do a plasma effect, here:
http://luis.net/projects/processing/final/plasmaEffect.pde

It used floats all over the place and also called the raw sin function about 3 times in the main loop.
So I had to speed it up to make it run properly on the Dingoo. You can see loads of optimisations by
comparing the code. Mostly getting rid of all floating point maths, multiplies, and the sin() calls.
My code now uses only shifts, +/-'s, and a array lookup now for the inner loop.

Its probably still slow and ugly compared to those old Demos on the Amiga, etc. but I thought people might
Like to look at the source. The more source for Dingoo programming the better  :D

Binary:
http://www.zshare.net/download/79354680c0702398/

Source:
Code: [Select]
/**
 *
 */
#include <SDL/SDL.h>
#include <math.h>

// convert 0-512 into 0-2pi
#define rad 0.012265625

/**
 *
 */
int main( int argc, char** args )
{
//
if ( SDL_Init( SDL_INIT_VIDEO ) == -1 )
return -1;
//
SDL_Surface* lPix = NULL;
Uint32 lFlag = SDL_HWSURFACE;
lPix = SDL_SetVideoMode( 320, 240, 16, lFlag );
//
if ( lPix == NULL )
return -1;
//
SDL_Event lEvent;
bool active = true;
//
Uint32 frames = 0;
//
Uint8 sint[ 512 ];
for ( int i=0; i<512; i++ )
sint[ i ] = 16+15*sin( rad*i );
//
Uint32 arg;
//
while ( active )
{
//
while ( SDL_PollEvent( &lEvent ) == 1 )
{
if ( lEvent.type == SDL_QUIT )
active = false;
// quit if the escape key is pressed
if ( lEvent.type == SDL_KEYDOWN )
if ( lEvent.key.keysym.sym == SDLK_ESCAPE )
active = false;
}
//
Uint8 c1 = 128+128*sin( ((float)frames) * 0.061655617f );
Uint8 c2 = 128+128*sin( ((float)frames) * 0.36352262f );
// fill with plasma
Uint16* lDat = (Uint16*)lPix->pixels;
//
Uint32 xc = 25;
//
for ( int x = 0; x < 320; x++, xc += 2 )
{
Uint32 yc = 25;
//
arg = ((xc*c1)>>8) & 0x1FF;
Uint8 s1 = sint[ arg ];
//
Uint32 ay = 0;
//
for ( int y = 0; y < 240; y++, yc += 2 )
{
Uint8 s2 = sint[ ((yc*c2)>>8) & 0x1FF ];
Uint8 s3 = sint[ ((xc + yc + frames * 5) >> 1) & 0x1FF ];
Uint8 sX = ((s1 + s2 + s3) >> 2 );
lDat[x+ay] = sX;
ay += 320;
}
}
//
SDL_Flip( lPix );
frames++;
}
//
SDL_Quit( );
return 0;
}

darfgarf

  • Guest
Re: Old School Plasma Demo Effect
« Reply #1 on: August 15, 2010, 08:18:22 am »
if it's counting as a proper release (less has before) this should be in the dingux releases section :P

and uploaded to the dingoo file archive

...shame my dingoo is out of comission again

Pantheon

  • Guest
Re: Old School Plasma Demo Effect
« Reply #2 on: August 15, 2010, 11:21:34 am »
I wasn't thinking of it as a proper release, more just a bit of interesting source
code that others might want to look at. I didn't really know of a better section or
place to put it.

eule

  • * Former Staff
  • Posts: 889
Re: Old School Plasma Demo Effect
« Reply #3 on: August 15, 2010, 12:30:48 pm »
Cool, i love such stuff!  :D
I "ported" a plasma programming example too, it?s a tad more colourful and complex, but quite huge, 45 kb...
And it has a nasty bug, shows some weird artifacts in the bottom part of the screen and bad tearing.
Here?s the source (hope you don?t mind me posting it here).  :-X
Code: [Select]
/*
  Written by Bini Michele <[email protected]>, 1998
  */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "SDL.h"
#include <math.h>
#include <time.h>

#ifndef PI
#define PI 3.14159265358979323846
#endif

#define VIDEOX 320
#define VIDEOY 240

#define TABLEX VIDEOX*2
#define TABLEY VIDEOY*2
#define TONES 256

static void do_plasma(SDL_Surface*surface,
       double x1,
       double y1,
       double x2,
       double y2,
       double x3,
       double y3,
       unsigned char*t)
{
  unsigned int
    X1=x1*(TABLEX/2),
    Y1=y1*(TABLEY/2),
    X2=x2*(TABLEX/2),
    Y2=y2*(TABLEY/2),
    X3=x3*(TABLEX/2),
    Y3=y3*(TABLEY/2);
  unsigned int y;
  unsigned char *t1=t+X1+Y1*TABLEX, *t2=t+X2+Y2*TABLEX, *t3=t+X3+Y3*TABLEX;
  for (y=0; y<VIDEOY; y++) {
    unsigned x;
    unsigned char*tmp= ((Uint8*)surface->pixels) + y * surface->pitch;
    unsigned int t=y*TABLEX, tmax=t+VIDEOX;
    for (x=0; t<tmax; t++, tmp++) {
      tmp[0]=t1[t]+t2[t]+t3[t];
    }
  }
}

main (int argc, char **argv)
{
  Uint32 video_flags;
  double r[3];
  double R[6];
  SDL_Surface *screen;
  SDL_Color colors[TONES*2];
  unsigned char *t;
  time_t starttime;
  int i, state=0;
 
  /* randomized stuff */
  srand(time(NULL));
  {
    int c;
    for (c=0; c<3; c++)
      r[c]=((double)(rand()%1000+1))/300000;
    for (c=0; c<6; c++)
      R[c]=((double)(rand()%1000+1))/5000;
  }

  printf("Precalculating table...\n");
  t = (unsigned char *)malloc(TABLEY*TABLEX);
  if ( t == NULL ) {
    fprintf(stderr, "Out of memory\n");
    exit(1);
  }
  {
    int y;
    for (y=0 ; y<TABLEY ; y++) {
      int x;
      for (x=0 ; x<TABLEX ; x++) {
double tmp=(((double)((x-(TABLEX/2))*(x-(TABLEX/2))+(y-(TABLEX/2))*(y-(TABLEX/2))))
    *(PI/(TABLEX*TABLEX+TABLEY*TABLEY)));
t[y*TABLEX+x]=(sin(sqrt(tmp)*12)+1)*TONES/6;
      }
    }
  }

  /* Inizialize the SDL library */
  if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
    fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
    return 1;
  }

  /* fire and forget... */
  atexit(SDL_Quit);
 
  video_flags = (SDL_SWSURFACE|SDL_HWPALETTE);
  for ( i=1; argv[i]; ++i ) {
    if ( strcmp(argv[i], "-fullscreen") == 0 )
      video_flags |= SDL_FULLSCREEN;
    else
    if ( strcmp(argv[i], "-hw") == 0 )
      video_flags |= SDL_HWSURFACE;
    else
    if ( strcmp(argv[i], "-flip") == 0 )
      video_flags |= SDL_DOUBLEBUF;
  }
  screen=SDL_SetVideoMode(VIDEOX, VIDEOY, 8, video_flags);
  if ( screen == NULL ) {
    fprintf(stderr, "Couldn't initialize video mode: %s\n", SDL_GetError());
    return 1;
  }
  SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
  SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
 
  starttime=time(NULL);

  /* Main loop */
  while (SDL_PollEvent(NULL)==0) {
    state++;
    {
      int c;
      for (c=0 ; c<TONES; c++) {
colors[c].r=(sin(((double)c)/TONES*6*PI+r[0]*PI*state*PI)+1)*127;
colors[c].g=(sin(((double)c)/TONES*6*PI+r[1]*state*PI)+1)*127;
colors[c].b=(sin(((double)c)/TONES*6*PI+r[2]*state*PI)+1)*127;
      }
      SDL_SetColors(screen, colors, 0, TONES);
    }
    if (SDL_LockSurface(screen) <0 ) {
      continue;
    }
    do_plasma(screen,
(sin(((double)state)*R[0])+1)/2,
(sin(((double)state)*R[1])+1)/2,
(sin(((double)state)*R[2])+1)/2,
(sin(((double)state)*R[3])+1)/2,
(sin(((double)state)*R[4])+1)/2,
(sin(((double)state)*R[5])+1)/2, t);
    SDL_UnlockSurface(screen);
    SDL_Flip(screen);
  }
  printf("Frame rate: %g frames/sec\n",((double)state)/difftime(time(NULL),starttime));
  return 0;
}
I read i could get rid of tearing by using SDL_DOUBLEBUF, but the app crashes when i set it. Dingoowiki says to use SDL_Flip to avoid tearing, the app does but it doesn?t help.
Don?t want to rain on your parade, thought you might be interested to have a look. I probably overlooked something i don?t understand yet, so if someone could hit my nose on it i?d be utterly thankful! ;D
Here?s the binary+source, including my stunning makefile skills: http://www.mediafire.com/?fo0v84sqlpni4n1

zear

  • * Moderator
  • Posts: 2381
Re: Old School Plasma Demo Effect
« Reply #4 on: August 15, 2010, 01:01:40 pm »
This is awesome guys! It sure will help game developers to add cool menu effects to their Dingux homebrew :D
Keep them going, we should collect more great gfx effects. ;D
« Last Edit: August 15, 2010, 01:04:28 pm by zear »

SiENcE

  • Posts: 653
    • Crank Gaming (Dingux Apps)
Re: Old School Plasma Demo Effect
« Reply #5 on: August 15, 2010, 04:01:11 pm »
I read i could get rid of tearing by using SDL_DOUBLEBUF, but the app crashes when i set it. Dingoowiki says to use SDL_Flip to avoid tearing, the app does but it doesn?t help.

You can only use SDL_DOUBLEBUF if you use OpenDingux Kernel. For compatility you have to choose not use it.

eule

  • * Former Staff
  • Posts: 889
Re: Old School Plasma Demo Effect
« Reply #6 on: August 15, 2010, 05:05:44 pm »
I see, good to know for the future. SDL_DOUBLEBUF can be triggered by executing plasma -flip, maybe you could have a look if it?s still tearing then, if you want to? Don?t feel like installing a new kernel right now, you know... I always have to reformat then.  :D
If anyone knows how to get rid of the tearing, please spill the beans.  :)

Pantheon

  • Guest
Re: Old School Plasma Demo Effect
« Reply #7 on: August 16, 2010, 01:41:06 pm »
Hey eule,

I tried to run your binary but I got this message:
Code: [Select]
./plasma: can't load library 'difftime'
does anyone have any ideas why this happened?
I thought most things would be staticaly linked so this wouldnt happen.

I'll try and compile from your source.

[edit]
same thing happens when I compile from the source  ???.
Sorry im still a noob with linux and gcc.
[/edit]
« Last Edit: August 16, 2010, 02:13:08 pm by Pantheon »

eule

  • * Former Staff
  • Posts: 889
Re: Old School Plasma Demo Effect
« Reply #8 on: August 16, 2010, 01:50:16 pm »
Err, WTF?!  ??? I don?t know why that is...
I?ll build a static one. Let?s hope i manage it.  ;D
edit: Well, i don?t think i?ll get a static one, get lots of errors when i set the -static flag... will investigate but it will take time. Noob here, you know.  8)
Just recompiled and it works for me, dunno what went wrong...
edit2: The only mention of difftime in the source is in the framerate calculator, i?ll try to take it out and build it again.
OK, i just built without the second last line and it still works, try the attached file (rename to plasma.dge or whatever ^^).
Maybe you use an old rootfs, if so, try elta?s, many games depend on it.

Framerate is 13,5 fps btw, not exactly the fastest.  :D Possibly the cause of the very seeable tearing, will try to optimize a bit.
« Last Edit: August 16, 2010, 02:18:14 pm by eule »

Pantheon

  • Guest
Re: Old School Plasma Demo Effect
« Reply #9 on: August 16, 2010, 02:17:57 pm »
Hmm now i'm getting a seg fault (with the one you uploaded).
Perhaps we have different kernels/librarys or something?
I've been trying to port things all day and i've been getting the strangest linking errors.
I'll keep experimenting.

[edit]
Ok, I made a stupid mistake. I was copying the old exe over instead of the newly compiled one I made.
it seems to work great now. Your demo is totally awesome, I love it. As for the "tearing", I am not sure that is
what it is at all. You might notice that the artefacts are always in the same place where as tearing would move
due to a phase difference between your render fps and the screen refresh rate. Perhaps there is some rounding errors
that could be the cause.

I'll start to poke around in your source to have a look.
[/edit]
« Last Edit: August 16, 2010, 02:27:47 pm by Pantheon »

eule

  • * Former Staff
  • Posts: 889
Re: Old School Plasma Demo Effect
« Reply #10 on: August 16, 2010, 02:25:59 pm »
Hmm, very strange... My guess would be you use an old rootfs, but i?m not sure. Do you use elta?s rootfs (linked above)?

BTW: I know how you feel, i get lots of errors and stuff too, and even if something compiled fine it doesn?t mean it?ll run.  ;D
Currently trying to port two demos (Viagra and Yellow Rose of Texas), both should work from what i can gather, but they don?t!  :'(

edit: Glad you got it to work and like it! But it?s not my demo, i simply ported it, credits go to Bini Michele.  :D

Yeah, the artifacts in the bottom are very weird too, but i can clearly see heavy tearing additionally. Maybe i?m just nitpicking though...
« Last Edit: August 16, 2010, 02:49:20 pm by eule »