Problems with shadows
Closed this issue · 8 comments
Why that same shadow needs to be casted nine times?
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
I’m going to extract code which deals with casting of shadows at its lowest level into ShadowCaster class, possibly simplifying such code
differences between shading free & grid items are
--- a/grid
+++ b/free
@@ -1,9 +1,9 @@
/* static */
-void ShadowCaster::castShadowImageOnGridItem( Item* thatItem, int x, int y, BITMAP* shadow, unsigned short shading, unsigned char transparency )
+void ShadowCaster::castShadowImageOnFreeItem( Item* thatItem, int x, int y, BITMAP* shadow, unsigned short shading, unsigned char transparency )
{
- if ( thatItem->whichKindOfItem() != "grid item" ) return;
+ if ( thatItem->whichKindOfItem() != "free item" ) return;
- GridItem* item = dynamic_cast< GridItem* >( thatItem );
+ FreeItem* item = dynamic_cast< FreeItem* >( thatItem );
// fully transparent stuff doesn’t drop any shadow
if ( transparency >= 100 ) return;
@@ -13,8 +13,8 @@ void ShadowCaster::castShadowImageOnGridItem( Item* thatItem, int x, int y, BITM
BITMAP* rawImage = item->getRawImage() ;
- int width = item->getWidthX() ;
- int deltaW = 0 ; // widths of grid item are always equal
+ int width = ( item->getWidthX() > item->getWidthY() ? item->getWidthX() : item->getWidthY() ) ;
+ int deltaW = static_cast< int >( item->getWidthX() ) - static_cast< int >( item->getWidthY() ) ;
int inix = x - item->getOffsetX(); // initial X
if ( inix < 0 ) inix = 0;
@@ -24,7 +24,7 @@ void ShadowCaster::castShadowImageOnGridItem( Item* thatItem, int x, int y, BITM
if ( endx > rawImage->w ) endx = rawImage->w;
int endy = y - item->getOffsetY() + shadow->h; // final Y
if ( endy > rawImage->h ) endy = rawImage->h;
- int my = rawImage->h - width - item->getHeight() + 1; // intermediate Y
+ int my = rawImage->h - width - item->getHeight (); // intermediate Y
if ( endy < my ) my = endy;
if ( endy > my + width ) endy = my + width;
@@ -43,7 +43,7 @@ void ShadowCaster::castShadowImageOnGridItem( Item* thatItem, int x, int y, BITM
int n2i = inix + item->getOffsetX() - x;
- BITMAP* shadyImage = item->getProcessedImage(); // graphics of shaded item
+ BITMAP* shadyImage = item->getShadedNonmaskedImage(); // graphics of shaded item
if ( ! shadyImage )
{
@@ -371,5 +371,5 @@ void ShadowCaster::castShadowImageOnGridItem( Item* thatItem, int x, int y, BITM
}
}
- item->setProcessedImage( shadyImage );
+ item->setShadedNonmaskedImage( shadyImage );
}
with current master with head commit “there’s no need to care for sequental amount of transparency while casting shadows at least” these same nine shadows are gone
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=0
casting shadow from free item "bars-ns" at x=4 y=127 z=48 on free item "bars-ns" at x=4 y=127 z=0
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=0
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=0
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=96
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=96
next thing: there’s regression~ no shadows from free item on other free items
plus these tristate WhichShady & WhichMask ~ are they really needed or just one boolean would be okay?
First variants of “ add class Shady ... ” commit introduced flickering of shadows on floor tile when there’s more than one item to shade the same tile
This update fixes that
--- a/src/ShadowCaster.cpp
+++ b/src/ShadowCaster.cpp
@@ -417,8 +417,6 @@ void ShadowCaster::castShadowOnItem( Item* item, int x, int y, BITMAP* shadow, u
/* static */
void ShadowCaster::castShadowOnFloor( FloorTile* tile, int x, int y, BITMAP* shadow, unsigned short shading, unsigned char transparency )
{
- if ( ! tile->getWantShadow() ) return;
-
// fully transparent stuff doesn’t drop any shadow
if ( transparency >= 100 ) return;
@@ -458,7 +456,11 @@ void ShadowCaster::castShadowOnFloor( FloorTile* tile, int x, int y, BITMAP* sha
shadyImage = create_bitmap_ex( colorDepthTile, tileImage->w, tileImage->h );
}
- blit( tileImage, shadyImage, 0, 0, 0, 0, tileImage->w, tileImage->h );
+ if ( tile->getWantShadow() )
+ {
+ blit( tileImage, shadyImage, 0, 0, 0, 0, tileImage->w, tileImage->h );
+ tile->setWantShadow( false );
+ }
char iInc = ( colorDepthTile == 32 ? 4 : 3 ); // increment for iRpx, iGpx and iBpx
char sInc = ( colorDepthShadow == 32 ? 4 : 3 ); // increment for sPixel
@@ -575,7 +577,6 @@ void ShadowCaster::castShadowOnFloor( FloorTile* tile, int x, int y, BITMAP* sha
}
tile->setShadyImage( shadyImage );
- tile->setWantShadow( false );
}
}
I got how to fix “ no shadows on free items ”
the problem is >> 1
of unsigned int when it needs to be signed, as example
( freeItem->getWidthX() - freeItem->getWidthY() + 1 ) >> 1
@@ -404,8 +419,12 @@ void Mediator::castShadowOnFloor( FloorTile* floorTile )
ShadowCaster::castShadowOnFloor (
floorTile,
- /* x */ ( ( freeItem->getX() - freeItem->getY() ) << 1 ) + room->getX0() + ( freeItem->getWidthX() + freeItem->getWidthY() ) - ( ( freeItem->getImageOfShadow()->w ) >> 1 ) - 1,
- /* y */ freeItem->getX() + freeItem->getY() + room->getY0() + ( ( freeItem->getWidthX() - freeItem->getWidthY() + 1 ) >> 1 ) - ( ( freeItem->getImageOfShadow()->h ) >> 1 ),
+ /* x */ ( ( freeItem->getX() - freeItem->getY() ) << 1 ) + room->getX0()
+ + static_cast< int >( freeItem->getWidthX() + freeItem->getWidthY() )
+ - ( ( freeItem->getImageOfShadow()->w ) >> 1 ) - 1,
+ /* y */ freeItem->getX() + freeItem->getY() + room->getY0()
+ + ( ( static_cast< int >( freeItem->getWidthX() ) - static_cast< int >( freeItem->getWidthY() ) + 1 ) >> 1 )
+ - ( ( freeItem->getImageOfShadow()->h ) >> 1 ),
/* shadow */ freeItem->getImageOfShadow(),
/* shadingScale */ room->shadingScale,
/* transparency */ freeItem->getTransparency()
@@ -472,8 +491,12 @@ void Mediator::castShadowOnGridItem( GridItem* gridItem )
ShadowCaster::castShadowOnItem (
gridItem,
- /* x */ ( ( freeItem->getX() - freeItem->getY() ) << 1 ) + ( freeItem->getWidthX() + freeItem->getWidthY() ) - ( ( freeItem->getImageOfShadow()->w ) >> 1 ) - 1,
- /* y */ freeItem->getX() + freeItem->getY() + ( ( freeItem->getWidthX() - freeItem->getWidthY() + 1 ) >> 1 ) - ( ( freeItem->getImageOfShadow()->h ) >> 1 ) - gridItem->getZ() - gridItem->getHeight(),
+ /* x */ ( ( freeItem->getX() - freeItem->getY() ) << 1 )
+ + static_cast< int >( freeItem->getWidthX() + freeItem->getWidthY() )
+ - ( ( freeItem->getImageOfShadow()->w ) >> 1 ) - 1,
+ /* y */ freeItem->getX() + freeItem->getY()
+ + ( ( static_cast< int >( freeItem->getWidthX() ) - static_cast< int >( freeItem->getWidthY() ) + 1 ) >> 1 )
+ - ( ( freeItem->getImageOfShadow()->h ) >> 1 ) - gridItem->getZ() - gridItem->getHeight(),
/* shadow */ freeItem->getImageOfShadow(),
/* shadingScale */ room->shadingScale,
/* transparency */ freeItem->getTransparency()
@@ -551,8 +574,11 @@ void Mediator::castShadowOnFreeItem( FreeItem* freeItem )
ShadowCaster::castShadowOnItem (
freeItem,
- /* x */ ( ( shadeItem->getX() - shadeItem->getY() ) << 1 ) + shadeItem->getWidthX() + shadeItem->getWidthY() - ( shadeItem->getImageOfShadow()->w >> 1 ) - 1,
- /* y */ shadeItem->getX() + shadeItem->getY() - freeItem->getZ() - freeItem->getHeight() + ( ( shadeItem->getWidthX() - shadeItem->getWidthY() - shadeItem->getImageOfShadow()->h ) >> 1 ),
+ /* x */ ( ( shadeItem->getX() - shadeItem->getY() ) << 1 )
+ + static_cast< int >( shadeItem->getWidthX() + shadeItem->getWidthY() )
+ - ( shadeItem->getImageOfShadow()->w >> 1 ) - 1,
+ /* y */ shadeItem->getX() + shadeItem->getY() - freeItem->getZ() - freeItem->getHeight()
+ + ( ( static_cast< int >( shadeItem->getWidthX() ) - static_cast< int >( shadeItem->getWidthY() ) - shadeItem->getImageOfShadow()->h ) >> 1 ),
/* shadow */ shadeItem->getImageOfShadow(),
/* shadingScale */ room->shadingScale,
/* transparency */ freeItem->getTransparency()
plus there’s obviously a mistake
freeItem->getY() > freeItem->getY() - static_cast< int >( item->getWidthY() )
is the same as
0 > 0 - static_cast< int >( item->getWidthY() )
or
static_cast< int >( item->getWidthY() ) > 0
which is always true when width is not zero
it needs to be freeItem->getY() > item->getY() - static_cast< int >( item->getWidthY() )
@@ -326,14 +324,26 @@ void Mediator::shadeFreeItemsBeneathItem( Item* item )
{
FreeItem* freeItem = *f ;
- if ( freeItem->getUniqueName () != item->getUniqueName () )
+ if ( freeItem != item &&
+ item->getUniqueName() != freeItem->getUniqueName() + " copy" )
{
- if ( ( freeItem->getX() + static_cast< int >( freeItem->getWidthX() ) > item->getX() )
- && ( freeItem->getX() < item->getX() + static_cast< int >( item->getWidthX() ) )
- && ( freeItem->getY() > freeItem->getY() - static_cast< int >( item->getWidthY() ) )
- && ( freeItem->getY() - static_cast< int >( freeItem->getWidthY() ) < item->getY() )
+ int itemX = item->getX(); int itemY = item->getY();
+ int freeX = freeItem->getX(); int freeY = freeItem->getY();
+ int freeXend = freeX + static_cast< int >( freeItem->getWidthX() );
+ int freeYend = freeY - static_cast< int >( freeItem->getWidthY() );
+ int itemXend = itemX + static_cast< int >( item->getWidthX() );
+ int itemYend = itemY - static_cast< int >( item->getWidthY() );
+
+ if ( ( freeXend > itemX ) && ( freeX < itemXend )
+ && ( freeY > itemYend ) && ( freeYend < itemY )
&& ( freeItem->getZ() < item->getZ() ) )
{
+ # if defined( DEBUG_SHADOWS ) && DEBUG_SHADOWS
+ std::cout << "Mediator::shadeFreeItemsBeneathItem got item \"" << freeItem->getUniqueName ()
+ << "\" to shade from \"" << item->getUniqueName () << "\""
+ << std::endl ;
+ #endif
+
freeItem->setWhichShade( WantReshadow );
}
}
shadows are okay yet