QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: johannhowitzer on June 24, 2021, 05:35:25 pm

Title: Need a cheaper way to do clearcolor
Post by: johannhowitzer on June 24, 2021, 05:35:25 pm
I'm having a slowdown issue with my game project, and I've isolated the cause to my use of clearcolor.  My game is a sidescrolling shooter, and when any ship takes a hit, its sprite flashes - each ship has a value hit_flash that is set to 1 when it takes a hit, and then every frame, decays back toward 0.  This value determines the alpha of the overlay drawn on top of the sprite.

This is not a problem when only one ship gets hit, but if four or five get hit, the program has to run that many clearcolor statements every frame, which causes the slowdown.  The following sub shows how this is being done:


Code: QB64: [Select]
  1. sub overlay(d&, h~&)
  2.  
  3. preserve& = dest: preserve2& = source
  4. dest d&: source d&
  5.  
  6. line(0, 0)-(_width, _height), h~&, bf
  7. clearcolor point(width - 1, height - 1), d&
  8.  
  9. dest preserve&: source preserve2&
  10.  


 [ This attachment cannot be displayed inline in 'Print Page' view ]  

The image here shows the steps of the overlay process.  The line statement covers the whole image surface d&, with color h~&, which has an alpha component.  Then the clearcolor statement uses the bottom-right of that surface to mask out all of the overlay except the sprite.  Without the clearcolor, the overlay will look like the middle sprite in the image - just an overlaid rectangle, which looks really ugly.  When I commented out the clearcolor statement, no slowdown occurred.

I'd like to keep the hit flash if possible, there might be a way to do this with pre-draw mask data, but that would be a lot of work that I'd also have to keep doing as the project progresses.  I considered a paint statement, but paint would ignore isolated islands - if I had a donut sprite, paint wouldn't remove the overlay from the donut hole.

So, is there a faster way?  This is simple and elegant, but it seems clearcolor is a very expensive operation.
Title: Re: Need a cheaper way to do clearcolor
Post by: Galleon on June 25, 2021, 01:01:43 am
Keep multiple images of same sprite in memory, one with red, one without
Prepare them once when your program loads, then use them whenever needed
This technique will also make the transition to hardware-based images (33) easier later
Title: Re: Need a cheaper way to do clearcolor
Post by: johannhowitzer on June 25, 2021, 04:02:36 am
It doesn't go from 0 to 1, then back to 0 some frames later...  it goes to 1, then gradually goes away over about 15 frames, a quarter second.  And I have various flashes - red for low health, white for being hit, blue for engine burnout.

Also, I have other modifiers going on with my sprite sheet already - tilt up or down, animation frames, etc.  Having to duplicate my entire sprite sheet, color everything red, then use another modifier, that's a ton of extra busywork for a single-color effect.  I wouldn't just have to color each ship red once, I'd have to color every animation frame three times for every color overlay I want.
Title: Re: Need a cheaper way to do clearcolor
Post by: NOVARSEG on June 25, 2021, 04:34:00 am
In theory you could draw a ship with MEM.   I'm not so sure that alpha channel will allow a total fade out to black for example.

MEM seems to be very fast and is the closest thing to assembler in QB64.  If a ship can be moved with MEM then any effect is possible.

Some code using MEM to draw custom cursors. very basic.   

https://www.qb64.org/forum/index.php?topic=3809.15

Another thing that seems to slow down code is DISPLAY.  With MEM I did not have to use DISPLAY (well I don't understand it anyway)
Title: Re: Need a cheaper way to do clearcolor
Post by: johannhowitzer on June 25, 2021, 05:06:53 am
The standard practical use of DISPLAY is once per frame in your main gameplay loop, so you can draw everything behind the scenes, and have the screen update all at once.  For QB64 game developers, it is essential for anything above a text adventure, without it, you will see crazy flickering.  But once per loop is not terribly expensive.

Regarding MEM, if I have to resort to essentially learning to code assembly for a single visual effect, that visual effect might have to get scrapped.  I'm already putting off learning another programming language until the demo is done.  I was hoping there was a workaround with some clever trick.
Title: Re: Need a cheaper way to do clearcolor
Post by: Cobalt on June 25, 2021, 11:53:58 am
The standard practical use of DISPLAY is once per frame in your main gameplay loop, so you can draw everything behind the scenes, and have the screen update all at once.  For QB64 game developers, it is essential for anything above a text adventure, without it, you will see crazy flickering.  But once per loop is not terribly expensive.

Regarding MEM, if I have to resort to essentially learning to code assembly for a single visual effect, that visual effect might have to get scrapped.  I'm already putting off learning another programming language until the demo is done.  I was hoping there was a workaround with some clever trick.

Some things that really impact speed are , _SETALPHA, _CLEARCOLOR, _DEST\_SOURCE(when used repeatedly), and _PUTIMAGE(when zooming). Those are the 4(5) main power vampires(not the only ones just the MAIN ones) and if you don't want that drain or can't allow for their use you will need to find another way.

Your OVERLAY routine has 5 slowdown routines, you have double _DEST\_SOURCE(I have not see an impact when using these in their FUNCTION form to save the current dest or source just their SUB form when setting thats why I say double not triple but its still not helping the speed when you do it over and over) and a _CLEARCOLOR (plus a POINT routine!).
So that routine itself is going to be very slow(and hard to read with no capitals)

like @Galleon said,
The easiest and most straight forward is to pre-make all the sprites your game will use. If your game makes use of several hundred sprites or images that will need to be duplicated multiple times with each effect, then yes this will take some effort and time but will pay off with dividends!.

Another way is to pre-process the graphics once you load them, set up temporary sheets(I often use the term "Layers") to have everything already done when the game loads up, this is where a nice loading(splash) screen or sequence comes in nice and handy!


As for _DISPLAY, you don't need _DISPLAY, there are other ways too. (you will not see it used in my Dragon Warrior clone nor my up coming Phantasy Star clone)
As for MEM, that is basically our advanced PEEK and POKE of QB64. Doesn't work exactly the same as DirectQB's GETMEM and PUTMEM but isn't too different. I don't believe it will help with what your doing in this instance though.
Title: Re: Need a cheaper way to do clearcolor
Post by: SMcNeill on June 25, 2021, 05:00:27 pm
From what I see, it appears to me as if the easiest, and best, solution here would be to just go with with a single sprite sheet.  Instead of a one image of the ship, like you had originally, you'd have a sprite sheet with say 20 images on it, which would look a lot like what you posted side by side on the forums here.  When the ship gets hit, you'd then _PUTIMAGE the portion of that sheet that you need frame by frame, rather than using _CLEARCOLOR and alpha overlays on the same image over and over.
Title: Re: Need a cheaper way to do clearcolor
Post by: johannhowitzer on June 25, 2021, 06:26:15 pm
I do appreciate the suggestions, though I have to shoot down the "pre-make everything" again because of the orders of magnitude involved here.  Just for the one ship the player flies, we've got 3 versions for tilt, 4 animation frames currently, then if I want 3 color overlays each with a 15-frame decay back to normal color, that is already 540 versions of one ship on the sprite sheet, all arranged in a super complicated venn diagram to account for calculating various modifiers.

Pre-processing on game start would work, I suppose, again it gets pretty complex with the modifiers in the code, but at least the external sprite sheet wouldn't blow up.  However, again it's for one visual effect, so this would be a last resort.  For now, I think I just have to abandon the overlays, maybe find a different effect I can use.

I can see some ways around display, such as alternating between two images with SCREEN.  Prepare on the one not being used, then flip over, and use a toggle variable to keep track.  I might look into that possibility.
Title: Re: Need a cheaper way to do clearcolor
Post by: NOVARSEG on June 26, 2021, 01:34:45 am
@johannhowitzer

Quote
The image here shows the steps of the overlay process.  The line statement covers the whole image surface d&, with color h~&, which has an alpha component.  Then the clearcolor statement uses the bottom-right of that surface to mask out all of the overlay except the sprite.  Without the clearcolor, the overlay will look like the middle sprite in the image - just an overlaid rectangle, which looks really ugly.  When I commented out the clearcolor statement, no slowdown occurred.


One way to speed the code up is to apply the overlay over the image of the ship and not the background.  In that way CLEARCOLOR does not have to be used. This can be done with MEM.

How  to do this.   Ok the sprite image has a start /  stop pixel for every line of pixels that the image has.  I would write custom code to generate these start stop pixels and then store that data in a READ statement.

How to implement
Feed the image into the custom program and set the alpha channel to say 254 so the program knows where the start / stop pixels are.  The program outputs BAS source code consisting of READ statements etc. ready to be pasted into your BAS file.

Now when you run your code it MEMPUTs from the READ data -  the overlay directly on the ship image ONLY.   There is probably better ways.

Another variation of this is to put an overlay behind the ship.  Might require extra coding but MEM is fast.
Title: Re: Need a cheaper way to do clearcolor
Post by: Galleon on June 26, 2021, 09:33:37 am
I find it hard to believe that _CLEARCOLOR is solely responsible for the slowness. If we could see your full code we would be able to give better suggestions.

FYI - This is the core loop of _CLEARCOLOR in C++:
------------------------------------------
for (lp=im->offset32;lp<last;lp++){
     if ((*lp&0xFFFFFF)==c) *lp=c;
}
------------------------------------------
Just trying replace _CLEARCOLOR with something faster is a dead end imo.
Title: Re: Need a cheaper way to do clearcolor
Post by: johannhowitzer on June 26, 2021, 10:04:48 am
Oh believe me, I'd love nothing more than to reveal the full game code, I'm quite the show-off and terrible at keeping my own secrets, haha.  But I've got some convincing reasons for keeping things close to the chest, and have thus far been able to resist giving everything away.  The game is story heavy and very spoiler sensitive, and I'm planning to go full commercial release with this eventually.  Also, the full code is nearing 10k lines, I think... I have released certain key pieces of the code in the past that I thought would be useful in others' projects, like the keybinding / input handling system, or the sprite sheet processor.

In the end, what I'm learning here is that the workarounds involved in getting rid of this slowness are either prohibitively laborious, or involve learning yet another new discipline.  Which, I'm not against learning new disciplines, it's kinda what I've been doing the past two years in developing this game, after all!  But a whole discipline for a one-off visual effect is overkill, so I think I will just have to come up with another effect.

The purpose of this thread is served, I got a convincing answer in the negative, and that lets me move ahead.  I can still use the overlay for things that only happen once per frame, like the engine burnout and low-health alert.  The slowdown was showing up when I fired a laser through 4+ enemies and they all had the effect going off at once.

Definitely was the clearcolor, though.  I commented that one line out, and nothing else, and the slowdown vanished completely.
Title: Re: Need a cheaper way to do clearcolor
Post by: Cobalt on June 26, 2021, 12:00:56 pm
I find it hard to believe that _CLEARCOLOR is solely responsible for the slowness. If we could see your full code we would be able to give better suggestions.
In a scenario where you are calling it over an over as he is, it is a big drop in performance, for what ever reason?

  Also, the full code is nearing 10k lines, I think...
just FYI there is a limit to the size that can be compiled, You may eventually want to go back and rework some areas to condense and simplify your code. Another reason to pre-create all sprite effects or simplify them.(when your sprite sheet exceeds 64kx12k pxls then you will beat my largest, that was a lot of work 1000s of 16x16px sprites\tiles and a several background images before I learned the golden rule of Simplicity)

"Simplicity is good, Simplicity is wonderful, Simplicity is LIFE, Complex code kills!"
(technically 'Complexity kills' but as a programmer I slide in 'code' there. ;D)
Title: Re: Need a cheaper way to do clearcolor
Post by: johannhowitzer on June 26, 2021, 01:06:20 pm
The functional code IS simple.  A lot of the bulk of that is coming from data setting and scripting, which will eventually have to be offloaded to external files.  Right now I'm pushing for demo completion, the full game is going to take quite a bit of optimization and smarter resource organization.  Right now I've got a whole routine dedicated to setting all the dialogue lines, in the end that'll be a resource file too.

I've been coding an engine from scratch, and building my first fully commercial-potential game from scratch at the same time... tons of learning experiences, and I'm definitely aware of some things that are unsustainable the way I started doing them, gotta wait until after the demo to address them though, or I'll keep pushing it back and never get there.
Title: Re: Need a cheaper way to do clearcolor
Post by: Petr on June 26, 2021, 02:18:52 pm
Used POINT function after CLEARCOLOR is the most speed problem.

Lets say, you need 30 overlay frames. You can easy do next frames from 1 picture to RAM:
(in this case is used white square without external file)

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2. Texture = _NEWIMAGE(100, 100, 32)
  3. _DEST Texture
  4. CLS , White
  5.  
  6. DIM Overlays(1 TO 30) AS LONG
  7.  
  8. FOR CreateFrames = 1 TO 30
  9.     Overlays(CreateFrames) = _COPYIMAGE(Texture, 32)
  10.     _DEST Overlays(CreateFrames)
  11.     LINE (0, 0)-(99, 99), _RGBA32(0, 0, 0, CreateFrames / 30 * 255), BF
  12.  
  13. DO UNTIL i$ <> ""
  14.     i$ = INKEY$
  15.     MAX i, 1, 30, 1
  16.     _PUTIMAGE (400, 300), Overlays(i)
  17.     _LIMIT 60
  18.  
  19. SUB MAX (value, minimum, maximum, stp)
  20.     value = value + stp
  21.     IF value > maximum THEN value = minimum
  22.     IF value < minimum THEN value = minimum
  23.  


Title: Re: Need a cheaper way to do clearcolor
Post by: Cobalt on June 26, 2021, 06:25:01 pm
The functional code IS simple.  A lot of the bulk of that is coming from data setting and scripting, which will eventually have to be offloaded to external files.  Right now I'm pushing for demo completion, the full game is going to take quite a bit of optimization and smarter resource organization.  Right now I've got a whole routine dedicated to setting all the dialogue lines, in the end that'll be a resource file too.

I've been coding an engine from scratch, and building my first fully commercial-potential game from scratch at the same time... tons of learning experiences, and I'm definitely aware of some things that are unsustainable the way I started doing them, gotta wait until after the demo to address them though, or I'll keep pushing it back and never get there.
I hear that, I usually start with 2 programs on a project, the MAIN code source and my DATA program that outputs all the data into an external file, I rarely(but sometimes do) attempt to start putting data into the MAIN code cause it quickly becomes messy, It can be a little tricky keeping both in sync but make does it make the main code cleaner.

You might want to look into my MFI file maker to pack all the resources into an external file. Graphix, SFX, Music, fonts, and data in a single package. Could add basic compression or an encryption algo to button it up, but once its out there people will always find ways of accessing it. Thats why I didn't bother, just made it so all the program resources are combined in one file and not directly accessible, as I make clones of old console games and don't want to directly distribute content.
Title: Re: Need a cheaper way to do clearcolor
Post by: NOVARSEG on June 26, 2021, 06:35:24 pm
@Galleon

The C++ code is very interesting.  What does *lp&0xFFFFFF do?

&0xFFFFFF = 16,777,215 decimal.  Is this the size of a memory block? and why is it fixed size of &0xFFFFFF?

Is variable c a color value?.

 I have read that CLEARCOLOR and PUTIMAGE work together. Do they use the same &0xFFFFFF block of memory?

Oh . . . .could lp&0xFFFFFF be a variable name?, assembler directive?

I know lp stands for long pointer and * is some type of memory operator. I have no clue what the C++ code is doing.

Quote
FYI - This is the core loop of _CLEARCOLOR in C++:
------------------------------------------
for (lp=im->offset32;lp<last;lp++){
     if ((*lp&0xFFFFFF)==c) *lp=c;
}
------------------------------------------
Title: Re: Need a cheaper way to do clearcolor
Post by: johannhowitzer on June 26, 2021, 09:01:46 pm
Quote
I hear that, I usually start with 2 programs on a project, the MAIN code source and my DATA program that outputs all the data into an external file, I rarely(but sometimes do) attempt to start putting data into the MAIN code cause it quickly becomes messy, It can be a little tricky keeping both in sync but make does it make the main code cleaner.

Main game code currently contains dialogue data, the demo stage's scripting, the keybinding raw data, movement scripting, sprite references, and all the ships' and shots' preset information for spawning.

Already using your MFI for the images and sounds, I was the guy who asked about that a couple weeks ago - https://www.qb64.org/forum/index.php?topic=3968.0  Much appreciated!
Title: Re: Need a cheaper way to do clearcolor
Post by: SMcNeill on June 26, 2021, 11:34:59 pm
@Galleon

The C++ code is very interesting.  What does *lp&0xFFFFFF do?

&0xFFFFFF = 16,777,215 decimal.  Is this the size of a memory block? and why is it fixed size of &0xFFFFFF?

Is variable c a color value?.

 I have read that CLEARCOLOR and PUTIMAGE work together. Do they use the same &0xFFFFFF block of memory?

Oh . . . .could lp&0xFFFFFF be a variable name?, assembler directive?

I know lp stands for long pointer and * is some type of memory operator. I have no clue what the C++ code is doing.

*lp is basically the _OFFSET of variable lp.
&0xFFFFFF is basically the same as AND &HFFFFFF.

So what you have is a routine that looks at where your image is in memory, goes through it quickly pixel by pixel, and if the _RGB value matches what you specified, it then changes that pixel.

The only way you could possibly do what it’s doing any faster, is to do exactly what it’s doing, except in a limited scope.  (Say from x/y point 100,100 to x/y point 200,200, rather than a whole 1280x720 image.)
Title: Re: Need a cheaper way to do clearcolor
Post by: NOVARSEG on June 27, 2021, 01:25:50 am
@SMcNeill

 So 0xFFFFFF is the RGB color but why is  AND logic used?

As far as fast goes there is an IF statement in the C++ CLEARCOLOR code which checks each pixel in the image.  If a match is found the alpha is changed to 0.  It is still fast but if the code did not have an IF (whatever) then it would go faster.  That is why I think MEM would be faster.

Each sprite could be saved in a data format that stores pixel locations. I was thinking of using READ statements in the BAS file to actually animate or apply effects to a sprite - avoiding IF statements.  Look up table oriented = fast.

A few IFs here and there might not make a difference.  Processing unnecessary pixels is where code might be slower.


Title: Re: Need a cheaper way to do clearcolor
Post by: SMcNeill on June 27, 2021, 02:34:34 am
The AND is there to swap all instances of alpha to the clear color.

RGB(any alpha)
So clear color _RGB(255,255,255) will clear color _RGBA(255,255,255,0) to _RGBA(255,255,255,255).

How would you code it so that it works without an IF statement with _MEM??  You still have to compare to see if each pixel is a match to the one which you want to replace, or not.  It's not like you're simply replacing EVERY pixel on the screen -- just the ones which match the RGB value you specified.

for (lp=im->offset32;lp<last;lp++){
     if ((*lp&0xFFFFFF)==c) *lp=c;
}

The above code would basically translate to basic as:

DIM lp AS _MEM: lp = _MEMIMAGE(0)
DIM c AS _UNSIGNED LONG: c = _RGB32(r, g,b) 'whatever we want
DO UNTIL counter > lp.SIZE
    IF _MEMGET(lp, lp.OFFSET + counter, _UNSIGNED LONG) AND &HFFFFFF = c THEN
       _MEMPUT lp, lp.OFFSET + counter, c 'Notice we put the value WITHOUT any alpha present?
    END IF
    counter = counter +4
LOOP
Title: Re: Need a cheaper way to do clearcolor
Post by: NOVARSEG on June 27, 2021, 02:24:15 pm
@SMcNeill

4 byte unsigned long is ANDed with 0xFFFFFF.  I thought 0xFFFFFF was a color value but looks to be a 3 byte mask for the RGB color values.

So the conditional statement
  if ((*lp&0xFFFFFF)==c) 
 is comparing the alpha value of the image pixel to the alpha value of the the RGB specified  in
clear color _RGB(255,255,255)   where I think the default alpha value is 255?

If there is a match then the new alpha value is still 255 but I thought a transparent pixel was alpha = 0 .

This line of code does not seem to set alpha to zero?
 if ((*lp&0xFFFFFF)==c) *lp=c;

Another thing if say

clear color _RGB(100,100,200)
then how does   if ((*lp&0xFFFFFF)==c) work with that. The0xFFFFFF is masking out the RGB color values anyway so it looks like there is some code missing or Im just not getting this.

So I'm still confused here.

Title: Re: Need a cheaper way to do clearcolor
Post by: NOVARSEG on June 27, 2021, 06:13:53 pm
double post
Title: Re: Need a cheaper way to do clearcolor
Post by: NOVARSEG on June 27, 2021, 06:14:24 pm
I got it backwards

0xFFFFFF masks out the alpha byte but does not mask the RGB bytes.

but how does

if ((*lp&0xFFFFFF)==c) *lp=c;

set the alpha byte to zero?

Quote
DIM c AS _UNSIGNED LONG: c = _RGB32(r, g,b)

Looks like I'm answering my own questions?
Title: Re: Need a cheaper way to do clearcolor
Post by: SMcNeill on June 27, 2021, 06:48:45 pm
What we’re doing is taking a 4 byte unsigned long, and using it for a 32-bit color value.

ARGB — One byte for Alpha, Red, Green, Blue.

Now in hex, those 4 bytes are represented by 8 hex-characters, from 00 to FF (0 to 255)

_RGB(r,g,b) gives us a 3-byte value for color, without an alpha channel.  Since there’s no such thing as a 3-byte long, the value is actually 0RGB — One byte for zero alpha, then a byte for Red, Green, Blue.

Now, when you take a 4-byte ARGB value AND it with a 0RGB value, the result will always be a 0RGB value.  (You stripped out the alpha with the 0 you ANDed it against.).  IF the result is the same 0RGB value that you ANDed against, then you have a perfect color match (minus alpha, of course).  This means that anything from 0 alpha to 255 alpha would be a match, as long as the RGB values match.

IF they do match, we simply set that pixel’s value to the 0RGB value (without any alpha value), and then we move on to the next pixel.

And that’s clearcolor in a nutshell.
Title: Re: Need a cheaper way to do clearcolor
Post by: NOVARSEG on June 27, 2021, 06:56:53 pm
@SMcNeill

Without your explanation I would have never figure that out. Thar 0xFFFFFF really confused me for a while.

Here is another thing.   Clear color changes an old alpha value to a new one.  Now  not sure, but I think clear color can return the  old value and if so does that mean clear color might be keeping copies of the alpha channel?
Title: Re: Need a cheaper way to do clearcolor
Post by: SMcNeill on June 27, 2021, 07:06:25 pm
What you have to remember is that that FFFFFF value is actually a 00FFFFFF value.

And with AND

    AARRGGBB (alpha, red, green, blue)
AND 00FFFFFF
    ========
    00AARRGG


That 0 strips out the alpha, while the FF leaves the red, green, blue values intact.



As for restoring those lost alpha values?  That’s impossible, as far as I know.  There’s no hidden second page in memory, storing those values for us.  We just strip off the alpha channel and then we’re done with it.
Title: Re: Need a cheaper way to do clearcolor
Post by: NOVARSEG on June 28, 2021, 01:26:43 am
The thing is why did johannhowitzer notice a speed increase when clearcolor was commented out?

Petr said that
Quote
Used POINT function after CLEARCOLOR is the most speed problem

This might be true but POINT should be fast as well.   The C++ code posted by Galleon showed that clearcolor is very fast code.

The C++ code for POINT should be even faster because POINT returns a pixel value at a certain location but CLEARCOLOR must look at every pixel in an image.



Title: Re: Need a cheaper way to do clearcolor
Post by: Galleon on June 28, 2021, 06:34:39 am
Quote
The thing is why did johannhowitzer notice a speed increase when clearcolor was commented out?
Exactly. As the OP is not interested in pursuing this neither am I. But I'm inclined to believe that _CLEARCOLOR may have been the proverbial "straw that broke the camel's back" in this case. Also for in-game usage I assume some sort of temporary copy of the original was made, then the operations were performed (adding coloured shading then using _CLEARCOLOR), then the temporary copy was rendered to the screen and probably that temporary image was disposed of at some point (or re-used?). I suspect that entire process is responsible somehow for the slowness. Also given the example of pixel-art provided I wonder if the re-colouring could not have been done before the up-scaling.

Here's an alternative I did code just for fun but didn't share because I'm very sure it provides no speed benefit over _CLEARCOLOR...
Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(1280, 768, 32)
  2. ship = _LOADIMAGE("ship.png")
  3.  
  4.  
  5. shipmask = getMask(ship)
  6. tempShip = _COPYIMAGE(ship)
  7.  
  8.  
  9. x = 0
  10. t = TIMER - 0.01
  11.     CLS , _RGB(0, 0, 128)
  12.     f = f + 1
  13.     PRINT CLNG(f / (TIMER - t))
  14.     FOR y = 10 TO 700 STEP 20
  15.         FOR z = 10 TO 1000 STEP 40
  16.             _DEST tempShip
  17.             _DONTBLEND
  18.             _PUTIMAGE (0, 0), ship
  19.             _BLEND
  20.             LINE (0, 0)-(100, 100), _RGBA(255, 0, 0, ABS(SIN((x + y + z) / 10)) * 255), BF
  21.             _PUTIMAGE (0, 0), shipmask
  22.             _DEST 0
  23.  
  24.  
  25.  
  26.             _PUTIMAGE (x + y + z, y), tempShip
  27.         NEXT
  28.     NEXT
  29.  
  30.     _DISPLAY
  31.     _LIMIT 30
  32.     x = x + 1
  33.  
  34.  
  35. FUNCTION getMask (img)
  36.     mask = _NEWIMAGE(_WIDTH(img), _HEIGHT(img), 256)
  37.     _SOURCE img
  38.     _DEST mask
  39.     FOR y = 0 TO _HEIGHT(mask) - 1
  40.         FOR x = 0 TO _WIDTH(mask) - 1
  41.             c& = POINT(x, y)
  42.             IF _ALPHA32(c&) = 0 THEN c& = 0 ELSE c& = 1
  43.             PSET (x, y), c&
  44.         NEXT
  45.     NEXT
  46.     PALETTE 0, _RGBA(0, 0, 0, 0)
  47.     _CLEARCOLOR 1, mask
  48.     _DONTBLEND mask
  49.     _SOURCE 0
  50.     _DEST 0
  51.     getMask = mask
  52.  

Title: Re: Need a cheaper way to do clearcolor
Post by: johannhowitzer on June 28, 2021, 11:03:38 pm
Quote
Also for in-game usage I assume some sort of temporary copy of the original was made, then the operations were performed (adding coloured shading then using _CLEARCOLOR), then the temporary copy was rendered to the screen and probably that temporary image was disposed of at some point (or re-used?).
That's right, I've been using a dedicated image surface for pre-processing effects.

Quote
Also given the example of pixel-art provided I wonder if the re-colouring could not have been done before the up-scaling.
The upscale was only for visibility on the forum, my game's code does not use putimage to stretch anything - except the laser, which is going to be in the sprite sheet pre-stretched soon.
Title: Re: Need a cheaper way to do clearcolor
Post by: SMcNeill on June 29, 2021, 10:21:58 am
I still don't see why a simple sprite sheet wouldn't work for this.

 [ This attachment cannot be displayed inline in 'Print Page' view ]  

With the above, we have our 25  instances of our base ship blended with red alpha, in increasing levels of 10 alpha.  The whole sheet takes up about 1MB of memory and we don't have to clearcolor anything -- just pop the image we need directly onto the screen where we need it.

The code to create this sheet is very simple, coming in at less than 40 lines, and it'd be easy enough to create another sheet for blue or white scale as well.

Code: QB64: [Select]
  1. '$INCLUDE:'SaveImage.BI'
  2. im = _LoadImage("ship.png", 32)
  3. AlphaSheet = _NewImage(143, 104, 32)
  4. _Dest AlphaSheet
  5.  
  6. 'Strip out the grayscale from the QB64 forum's image so we're left with the bare ship.
  7. For y = 0 To 103
  8.     For x = 0 To 142
  9.         p&& = Point(x, y)
  10.         If _Red32(p&&) = _Green32(p&&) And _Red32(p&&) = _Blue32(p&&) Then
  11.         Else
  12.             PSet (x, y), p&&
  13.         End If
  14.     Next
  15. Screen AlphaSheet
  16. ni = _NewImage(143 * 5, 104 * 5, 32)
  17. For x = 0 To 4
  18.     For y = 0 To 4
  19.         If c Then _Dest 0: _Source 0: _FreeImage c
  20.         c = _CopyImage(AlphaSheet)
  21.         _Dest c: _Source c
  22.         Line (0, 0)-(142, 103), _RGBA32(255, 0, 0, 50 * x + 10 * y), BF
  23.         _DontBlend
  24.         p&& = Point(0, 0)
  25.         For y1 = 0 To 103
  26.             For x1 = 0 To 142
  27.                 If Point(x1, y1) = p&& Then PSet (x1, y1), 0 'Strip out raw alpha
  28.         Next x1, y1
  29.         _Blend
  30.         _PutImage (143 * x, 104 * y)-Step(143, 104), c, ni
  31. Next y, x
  32.  
  33. SaveFullImage ("AlphaShip.png")
  34.  
  35. '$INCLUDE:'SaveImage.BM'
  36.  
Title: Re: Need a cheaper way to do clearcolor
Post by: NOVARSEG on June 30, 2021, 02:49:26 am
The other way to remove grey scale is with alpha channel.

What ELSE?   no ELSE!

Code: QB64: [Select]
  1. 'DIM C AS LONG
  2. DIM hSCREEN AS LONG
  3. DIM hSHIP AS LONG
  4.  
  5. hSCREEN = _NEWIMAGE(1280, 768, 32)
  6. SCREEN hSCREEN
  7.  
  8. hSHIP = _LOADIMAGE("lship.png", 32)
  9.  
  10. _SOURCE hSHIP
  11.  
  12. FOR Y = 0 TO _HEIGHT(hSHIP) - 1
  13.     FOR X = 0 TO _WIDTH(hSHIP) - 1
  14.         C = POINT(X, Y)
  15.  
  16.         IF _ALPHA32(C) = 0 THEN
  17.             C = _RGB(255, 0, 0)
  18.             PSET (X, Y), C
  19.         END IF
  20.  
  21.         IF _ALPHA32(C) <> 0 THEN
  22.             PSET (X, Y), C
  23.         END IF
  24.  
  25.     NEXT X
  26.  
  27.  
  28.