Adventure Game Studio

AGS Support => Advanced Technical Forum => Topic started by: Calin Leafshade on Tue 03/08/2010 03:41:31

Title: AGSBloom! Another Speed Test
Post by: Calin Leafshade on Tue 03/08/2010 03:41:31
ok so i've written a blurring algorithm for an AGS plugin and it works ok on *some* images but not on all.

if the image is square it blurs it 100% fine
if the image is taller than it is wide then it blurs a weird box in the corner with some artifacts
if the image is wider than it is tall it crashes with an access violation (i.e i've accessed a part of the array that i havent allocated)

So theres obviously a pretty elementary error with the way i calculate the array indices but i cant see it.

It's extremely difficult to debug plugins since you cant add breakpoints or watch values or step through code so i need help

heres my algorithm:

(btw i *know* this is not a quick way to do blurring butI'm just getting to grips with the c++ first then i can alter the algorithm however i please.)


int xytolocale(int x, int y, int width){
   
return (y * width + x);  
   
   
}
int BlurHorizontal (int Sprite, int radius) {
           
   BITMAP* src = engine->GetSpriteGraphic(Sprite);
   long srcWidth, srcHeight;
   
   engine->GetBitmapDimensions(src, &srcWidth, &srcHeight, NULL);

   unsigned char **srccharbuffer = engine->GetRawBitmapSurface (src);
   unsigned long **srclongbuffer = (unsigned long**)srccharbuffer;
   int negrad = -1 * radius;
   
   //use a 1Dimensional array since the array is on the free store, not the stack
   Pixel32 * Pixels = new Pixel32[(srcWidth + (radius * 2)) * (srcHeight + (radius * 2))]; // this defines a copy of the individual channels in class form.
   Pixel32 * Dest = new Pixel32[(srcWidth + (radius * 2)) * (srcHeight + (radius * 2))]; // this is the destination sprite. both have a border all the way round equal to the radius for the blurring.
   

           
   int arraywidth = srcWidth + (radius * 2); //define the array width since its used many times in the algorithm


   for (int y = 0; y<srcHeight; y++){ //copy the sprite to the Pixels class array
       
        for (int x = 0; x<srcWidth; x++){
           
            int locale = xytolocale(x + radius, y + radius, arraywidth);
           
            Pixels[locale].red = getb32(srclongbuffer[x][y]);
            Pixels[locale].green = getg32(srclongbuffer[x][y]);            
            Pixels[locale].blue = getr32(srclongbuffer[x][y]);
            Pixels[locale].alpha = geta32(srclongbuffer[x][y]);  
                                                   

       
        }
       
    }    
           // start of the blurring
    int numofpixels = (radius * 2 + 1) * (radius * 2 + 1);
        for (int y = 0; y < srcHeight; y++) {
           for (int x = 0; x < srcWidth; x++) {
               int totalr = 0;
               int totalg = 0;
               int totalb = 0;                
               int totala = 0;

               for (int ky = negrad; ky <= radius; ky++){
                   for (int kx = negrad; kx <= radius; kx++){
                       int locale = xytolocale(x + kx + radius, y + ky + radius, arraywidth);
                       totalr += Pixels[locale].red; //add the pixel values for the surrounding pixels to a total
                       totalg += Pixels[locale].green;
                       totalb += Pixels[locale].blue;
                       totala += Pixels[locale].alpha;                                                
                       
                   }
               }
               int locale = xytolocale(x + radius, y + radius, arraywidth);
               Dest[locale].red = totalr / numofpixels; // take an average and assign it to the destination array
               Dest[locale].green = totalg / numofpixels;
               Dest[locale].blue = totalb / numofpixels;
               Dest[locale].alpha = totala / numofpixels;                            
           }
       }
       
       
   
       for (int y = 0; y<srcHeight; y++){
           
            for (int x = 0; x<srcWidth; x++){
               int locale = xytolocale(x + radius, y + radius, arraywidth);
               srclongbuffer[x][y] = makeacol32(Dest[locale].blue, Dest[locale].green, Dest[locale].red, Dest[locale].alpha); //write the destination array to the main buffer

            }
           
        }
       
       engine->ReleaseBitmapSurface(src);
}


any ideas?
Title: Re: Blurring algorithm - Why doesn't this work?
Post by: Kweepa on Tue 03/08/2010 03:59:42
Did you try just indexing

srclongbuffer[y][x]
instead of

srclongbuffer[x][y]

?
Title: Re: Blurring algorithm - Why doesn't this work?
Post by: Calin Leafshade on Tue 03/08/2010 04:32:26
I could try but surely that would just reverse the problem?
Title: Re: Blurring algorithm - Why doesn't this work?
Post by: Kweepa on Tue 03/08/2010 04:44:30
Go on, give it a shot.
It sounds to me from the symptoms that this is the cure.
Title: Re: Blurring algorithm - Why doesn't this work?
Post by: Calin Leafshade on Tue 03/08/2010 04:47:55
you are 100% right.... how did i not see this...

Thanks Steve!
Title: AGSBloom! Another Speed Test
Post by: Calin Leafshade on Tue 03/08/2010 17:51:13
would it be possible for people to try out this game and tell me what frame rates they get in both DD and DX9 mode with the default settings.

also your system specs would be greatly appreciated ^_^

http://www.thethoughtradar.com/AGS/Bloomtest4.zip

also, for giggles, you can play with the settings with the 1-8 number keys.
Title: Re: AGSBloom! Another Speed Test
Post by: ddq on Tue 03/08/2010 19:19:37
In both DD and DX9, performance was about the same. No matter what the other settings, I got solid 40 FPS when blur quality was set to 1. Any higher and performance took a big hit. At 2, I was getting mid 30's and when I maxed it out, I was running about 17. The other settings didn't have much effect on the framerate. Honestly, I didn't think higher "quality" blurs looked noticeably better enough to justify the lowed framerate.
Specs:
2.5 GHz Core 2 Duo
4 GB RAM
Nvidia GeForce 8600M GT with 512 MB RAM
Summary: It looked pretty.
Title: Re: AGSBloom! Another Speed Test
Post by: Calin Leafshade on Tue 03/08/2010 19:32:08
That 'quality' setting is a little misleading.

Its really just the number of times the blur function is run on the sprite.
When i was using a different box blur algorithm it needed multiple passes to look good.. now a single pass is pretty much sufficient.
Title: Re: AGSBloom! Another Speed Test
Post by: LimpingFish on Tue 03/08/2010 22:19:21
I got what I suspect will become the norm: 40+ at '1' quality, 30+ at '2', 20+ at '3', etc.

The other settings don't impact on the frame rate.

Nice effect, though. :)

Title: Re: AGSBloom! Another Speed Test
Post by: GarageGothic on Tue 03/08/2010 22:47:32
I had the same experience as LimpingFish, on quality 1 I get 40 fps no matter the other settings, any increase in quality leads to a dramatic drop (but didn't note the exact fps). Looks awesome though, don't see any real need to increase quality.
Title: Re: AGSBloom! Another Speed Test
Post by: Kweepa on Wed 04/08/2010 00:05:20
Q1 = 40
Q2 = 40
Q3 = 33
Q4 = 27
Q5 = 22
Core i7 920 @ 2.67GHz
Title: Re: AGSBloom! Another Speed Test
Post by: Calin Leafshade on Wed 04/08/2010 00:31:23
the i7 cores are insane at computation like this.

Hardware accelerated version comming soon... I hope..
Title: Re: AGSBloom! Another Speed Test
Post by: Wyz on Wed 04/08/2010 00:34:11
(http://spreadsheets.google.com/oimg?key=0AsHX2lXPWJ0YdC11ZTJxaXFYdmNIS01OX1ZaRy1tN0E&oid=1&zx=62wjpket5abu)
P4 2.8GHz
No difference between DD and DX9
Title: Re: AGSBloom! Another Speed Test
Post by: Calin Leafshade on Wed 04/08/2010 00:45:58
It seems like I do need to hardware accelerate this.. its just too intense to do without shaders.
Title: Re: AGSBloom! Another Speed Test
Post by: Crimson Wizard on Wed 04/08/2010 04:48:40
I tried, but... I see pretty much visual difference between quality 0 and 1,but other quality levels simply lower the effect, as it seems (while downgrading fps). Is this an expected behavior? Sorry, do not know much about Bloom.
Title: Re: AGSBloom! Another Speed Test
Post by: Calin Leafshade on Wed 04/08/2010 05:13:08
Yes, bloom is essentially a 3 part process.

1 - run a high pass filter on the texture
2 - blur the result.
3 - additively blend the result over the original image.

"quality" refers to the number of times step 2 is done and if you continue to blur something you dilute its intensity.
Title: Re: AGSBloom! Another Speed Test
Post by: Shane 'ProgZmax' Stevens on Wed 04/08/2010 06:36:46
It's a bit buggy/crashy (straying too far up on the screen causes a CTD) but so far the performance doesn't drop significantly for me.

With default settings I get 33 fps in DDRAW and 40 in D3D.

With no bloom I get 34/41.

With full (hold down 2 until the whole screen is glowing) I get 30/37.

High quality above about 2 seems to diminish the effect...  on 2 it seems to render the areas as blended squares.

I think the result is pretty neat without a significant performance hit (for me).

Title: Re: AGSBloom! Another Speed Test
Post by: Gilbert on Wed 04/08/2010 08:00:16
With this crappy office computer I got around 14 FPS, without touching any of the in-game settings and using the default configuration (i.e. DX5 and 3X zoom). I got around 15 FPS if I didn't use any zoom for the window though.

This is a bit meaningless anyway, as D3D9 won't work with AGS on this machine, so no comparison can be made.

Anyway, specs:

2.4 GHz P4
1GB RAM
Win XP Professional SP3
Extraordinary Awesome Super Powerful Onboard Intel 82845(something) graphics, stealing some 32MB (I think) of system memory :=
Direct X 9 (yeah...)