Difference between revisions of "Medusa effect"

From DoomWiki.org

[checked revision][unchecked revision]
(Undo revision 74641 by 200.220.200.180 (talk))
(Why medusa occurs)
Line 1: Line 1:
 
The '''Medusa effect''' occurs when there is more than one [[wall patch|patch]] occupying the same column in any middle [[wall texture|texture]] of a two-sided [[linedef]] that is visible in the display window. Due to a game engine limitation, these will not display properly. The area where the middle texture would be displayed is instead a series of multicolored horizontal lines. This 'wall' of multicolored lines appears to extend infinitely into the floor. Moving close to the wall will make the framerate in [[vanilla Doom]] slow to a crawl and make play nearly impossible until the offending wall is out of view.
 
The '''Medusa effect''' occurs when there is more than one [[wall patch|patch]] occupying the same column in any middle [[wall texture|texture]] of a two-sided [[linedef]] that is visible in the display window. Due to a game engine limitation, these will not display properly. The area where the middle texture would be displayed is instead a series of multicolored horizontal lines. This 'wall' of multicolored lines appears to extend infinitely into the floor. Moving close to the wall will make the framerate in [[vanilla Doom]] slow to a crawl and make play nearly impossible until the offending wall is out of view.
 +
 +
The effect is due to the way multi-patch textures are loaded in memory. The game renders all middle textures on two sided walls with the drawing function as sprites, which is R_DrawMaskedColumn(). This function correctly handles each column and the posts that are contained within the column. The problem does not exist in this function, but instead exists in the code that loads the texture into memory.
 +
 +
When a normal wall is drawn, the function R_DrawColumn() is used. This column drawer is only capable of drawing single post patches. When drawing it takes the height of the actual texture and uses that instead of the column data. This limitation also causes the [[Tutti-frutti effect]]. Whereas R_DrawMaskedColumn() takes into consideration the column data.
 +
 +
When a texture needs to be loaded into memory, the function R_GenerateComposite() is called. This function loads the texture data from the WAD. When loading a texture, it runs through a list that was determined at load time. The list contains the number of patches that exist on each column, or rather the number of lumps for each column. When a column that has multiple patches for a column is encountered, the game then calls R_DrawColumnInCache(). The problem arises in this function. The function R_DrawColumnInCache() takes a shortcut, it renders the column of the patch on top of the existing cache without checking the end of the column and does not update the existing column data. Thus, the height of the column is never changed nor is the offset. Then once the game draws the texture with R_DrawMaskedColumn() it uses the invalid column height. In short, after drawing a column the function checks to see if there are no more columns afterwards. It will continue to draw columns of varying length until the byte marker 255 is hit, which it will then terminate drawing. Since patches vary in actual data this marker may be hit early reducing the slow down or it may be hit later thus causing extreme slow down. The drawing function eventually would exceeds the bound of the texture data and start to draw data from other memory positions until it reaches the end condition. Due to this, the distorted texture that extends through the floor may animate. It is possible for the game to enter an infinite loop or eventually crash provided all of the conditions are perfect and memory is laid out in a way to cause such an event.
  
 
The effect is named for [[Wikipedia:Medusa|Medusa]], the creature in Greek mythology who had live snakes for hair and was so ugly that a single glance at her would turn the beholder to stone.
 
The effect is named for [[Wikipedia:Medusa|Medusa]], the creature in Greek mythology who had live snakes for hair and was so ugly that a single glance at her would turn the beholder to stone.

Revision as of 22:06, 21 February 2012

The Medusa effect occurs when there is more than one patch occupying the same column in any middle texture of a two-sided linedef that is visible in the display window. Due to a game engine limitation, these will not display properly. The area where the middle texture would be displayed is instead a series of multicolored horizontal lines. This 'wall' of multicolored lines appears to extend infinitely into the floor. Moving close to the wall will make the framerate in vanilla Doom slow to a crawl and make play nearly impossible until the offending wall is out of view.

The effect is due to the way multi-patch textures are loaded in memory. The game renders all middle textures on two sided walls with the drawing function as sprites, which is R_DrawMaskedColumn(). This function correctly handles each column and the posts that are contained within the column. The problem does not exist in this function, but instead exists in the code that loads the texture into memory.

When a normal wall is drawn, the function R_DrawColumn() is used. This column drawer is only capable of drawing single post patches. When drawing it takes the height of the actual texture and uses that instead of the column data. This limitation also causes the Tutti-frutti effect. Whereas R_DrawMaskedColumn() takes into consideration the column data.

When a texture needs to be loaded into memory, the function R_GenerateComposite() is called. This function loads the texture data from the WAD. When loading a texture, it runs through a list that was determined at load time. The list contains the number of patches that exist on each column, or rather the number of lumps for each column. When a column that has multiple patches for a column is encountered, the game then calls R_DrawColumnInCache(). The problem arises in this function. The function R_DrawColumnInCache() takes a shortcut, it renders the column of the patch on top of the existing cache without checking the end of the column and does not update the existing column data. Thus, the height of the column is never changed nor is the offset. Then once the game draws the texture with R_DrawMaskedColumn() it uses the invalid column height. In short, after drawing a column the function checks to see if there are no more columns afterwards. It will continue to draw columns of varying length until the byte marker 255 is hit, which it will then terminate drawing. Since patches vary in actual data this marker may be hit early reducing the slow down or it may be hit later thus causing extreme slow down. The drawing function eventually would exceeds the bound of the texture data and start to draw data from other memory positions until it reaches the end condition. Due to this, the distorted texture that extends through the floor may animate. It is possible for the game to enter an infinite loop or eventually crash provided all of the conditions are perfect and memory is laid out in a way to cause such an event.

The effect is named for Medusa, the creature in Greek mythology who had live snakes for hair and was so ugly that a single glance at her would turn the beholder to stone.

Sources

This article is based on information in the Unofficial Doom Specs.