Author Topic: Color overlay routine  (Read 3842 times)

0 Members and 1 Guest are viewing this topic.

Offline johannhowitzer

  • Forum Regular
  • Posts: 118
    • View Profile
Color overlay routine
« on: August 11, 2020, 12:14:37 am »
Having a little issue with _clearcolor as related to a routine I'm using in my game project to overlay a semitransparent color over a masked sprite.

Code: QB64: [Select]
  1. sub overlay(d&, h~&)
  2. preserve& = _dest
  3. line(0, 0)-(_width, _height), h~&, bf
  4. _clearcolor h~&, d&
  5. _dest preserve&
  6.  

h~& is the overlay color, which has an alpha component, d& is the image handle, here I'm passing in an image surface I use for assembling graphics before putting them on the screen.  Here's how my program is using it during the sprite drawing:

Code: QB64: [Select]
  1. call clear_image(assembly,  hue(hue_transparent))
  2. _putimage(0, 0)-step(w, h), sprite_image, assembly, (x2, y2)-step(sprite(s).size.x, sprite(s).size.y)
  3.  
  4. ' Overlays
  5. if blink_cd > 1 then call overlay(assembly, _rgba(255, 0, 0, 63)) ' Engine burnout
  6. call overlay(assembly, _rgba(255, 255, 255, int(entity(player).hit_flash * 224))) ' Hit flash
  7.  
  8. _putimage(x1, y1)-step(w, h), assembly, fullscreen, (0, 0)-step(w, h)
  9.  

So first I clear the assembly image to transparent (_rgba(0, 0, 0, 0)), then put the sprite there from a sprite sheet that's got a color keyed out with _clearcolor.  Then I apply the red engine burnout overlay, which works fine.  The overlay() routine should leave the background still fully transparent, using its own _clearcolor that matches the overlay color.  Then the hit flash value - which ranges from 0 to 1 and decays each frame - is used to apply a white overlay that fades down to the ship's normal colors.  The overlay works, the fade works.

The problem is that only for the white overlay, the white is bleeding off the sprite and causing a rectangle around the ship while the flash happens.  Only for the white, not the red burnout overlay.  I've made some attempts at debugging this, tried a few different things like resetting the _clearcolor to _none at the start of overlay(), adding a second assembly surface and copying the sprite over before the white overlay.  Also, the white bleed is happening whether the red overlay is used or not.

Tried to post an image of it here, but I guess this forum doesn't allow images.  Looking closely, some pixels in the ship sprite are being keyed out when they shouldn't be - they're appearing black.
« Last Edit: August 11, 2020, 12:22:31 am by johannhowitzer »

Offline johannhowitzer

  • Forum Regular
  • Posts: 118
    • View Profile
Re: Color overlay routine
« Reply #1 on: August 11, 2020, 01:47:43 am »
Okay, I was wrong, it's happening for the red overlay too, it was just too dim to tell.  Apparently this is not a good method for overlaying a color on a non-rectangular image.  It does work correctly if I use point(0, 0) as the _clearcolor, this just means that every sprite has to have a transparent pixel in the top-left.
« Last Edit: August 11, 2020, 01:56:27 am by johannhowitzer »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Color overlay routine
« Reply #2 on: August 11, 2020, 05:05:21 pm »
Are you using 32 bit color? There is supposedly a difference between _RGBA() and _RGBA32() and I see you are using _RGBA.

Something to try _RGBA32().


Offline johannhowitzer

  • Forum Regular
  • Posts: 118
    • View Profile
Re: Color overlay routine
« Reply #3 on: August 11, 2020, 07:31:10 pm »
I'm in 32-bit, but switching all uses of _rgba to _rgba32 didn't fix this.  Sticking to point(0, 0) for now, probably some weirdness with color addition, and even for the odd rectangular sprite needing an overlay, I can just add a row above and below of transparency.  point(0, 0) should be 100% reliable.

Offline Gets

  • Newbie
  • Posts: 28
    • View Profile
Re: Color overlay routine
« Reply #4 on: August 11, 2020, 08:05:41 pm »
h~& is being blended with black when you draw the box, so you end up with a different color.  You'd have to calculate what the new color is in order to clear it properly, and POINT is perfectly up to the job.

Offline johannhowitzer

  • Forum Regular
  • Posts: 118
    • View Profile
Re: Color overlay routine
« Reply #5 on: August 11, 2020, 08:27:44 pm »
Yeah, I had assumed adding a color to _rgba(0, 0, 0, 0) would just result in the color I added, that seems to be incorrect.  Intuitively it seems like it should be correct, but it isn't.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Color overlay routine
« Reply #6 on: August 11, 2020, 08:29:28 pm »
h~& is being blended with black when you draw the box, so you end up with a different color.  You'd have to calculate what the new color is in order to clear it properly, and POINT is perfectly up to the job.

Or add_DONTBLEND to your sub overlay.

SUB overlay(d&, h~&)
preserve& = _DEST
_DEST d&
_DONTBLEND
LINE(0, 0)-(_WIDTH, _HEIGHT), h~&, bf
_BLEND
_CLEARCOLOR h~&, d&
_DEST preserve&
END SUB
 
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline johannhowitzer

  • Forum Regular
  • Posts: 118
    • View Profile
Re: Color overlay routine
« Reply #7 on: August 11, 2020, 09:13:47 pm »
Thanks, but that defeats the purpose of overlay() entirely.  The result of not blending the color overlay on the sprite at all is an image full of only the one color and no sprite, and then _clearcolor wipes it to nothing, as test confirmed.  This makes overlay() into don't display the sprite ever.

Oh, and I just realized I don't even need to worry about the top left of the sprite being transparent in the first place, silly me.  Just start the sprite at (0, 1) and the top left of the assembly surface will always work.  Or, better yet (can you tell I'm thinking out loud), use point(_width - 1, _height - 1) within the routine so you can work from (0, 0) outside it.  So here's the final routine if anyone wants to use it in something:

Code: QB64: [Select]
  1. sub overlay(d&, h~&)
  2. preserve& = _dest: preserve2& = _source
  3. _dest d&: _source d&
  4. line(0, 0)-(_width, _height), h~&, bf
  5. _dest preserve&: _source preserve2&
  6.  
« Last Edit: August 11, 2020, 09:26:00 pm by johannhowitzer »

Offline Gets

  • Newbie
  • Posts: 28
    • View Profile
Re: Color overlay routine
« Reply #8 on: August 11, 2020, 11:34:48 pm »
Yeah, I had assumed adding a color to _rgba(0, 0, 0, 0) would just result in the color I added, that seems to be incorrect.  Intuitively it seems like it should be correct, but it isn't.


Seems like you can place the color directly with MEM commands when you really need to; PSET didn’t work when I tested it right now...which I’m glad I just realized because I’ve been using PSET to create a gradient map to use with Hardware images