diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index db812c0d..bc86c129 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3527,6 +3527,186 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v return false; } +static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float this_scale) +{ + UINT8 i; + float tr_x, tr_y; + FOutVector *wv; + FOutVector swallVerts[4]; + FSurfaceInfo sSurf; + fixed_t floorheight, mobjfloor; + + mobjfloor = HWR_OpaqueFloorAtPos( + spr->mobj->x, spr->mobj->y, + spr->mobj->z, spr->mobj->height); + if (cv_shadowoffs.value) + { + angle_t shadowdir; + + // Set direction + if (splitscreen && stplyr != &players[displayplayer]) + shadowdir = localangle2 + FixedAngle(cv_cam2_rotate.value); + else + shadowdir = localangle + FixedAngle(cv_cam_rotate.value); + + // Find floorheight + floorheight = HWR_OpaqueFloorAtPos( + spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - mobjfloor), + spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - mobjfloor), + spr->mobj->z, spr->mobj->height); + + // The shadow is falling ABOVE it's mobj? + // Don't draw it, then! + if (spr->mobj->z < floorheight) + return; + else + { + fixed_t floorz; + floorz = HWR_OpaqueFloorAtPos( + spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - floorheight), + spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - floorheight), + spr->mobj->z, spr->mobj->height); + // The shadow would be falling on a wall? Don't draw it, then. + // Would draw midair otherwise. + if (floorz < floorheight) + return; + } + + floorheight = FixedInt(spr->mobj->z - floorheight); + } + else + floorheight = FixedInt(spr->mobj->z - mobjfloor); + + // create the sprite billboard + // + // 3--2 + // | /| + // |/ | + // 0--1 + + // x1/x2 were already scaled in HWR_ProjectSprite + swallVerts[0].x = swallVerts[3].x = spr->x1; + swallVerts[2].x = swallVerts[1].x = spr->x2; + + if (spr->mobj && this_scale != 1.0f) + { + // Always a pixel above the floor, perfectly flat. + swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset * this_scale - (floorheight+3); + + swallVerts[0].z = swallVerts[1].z = spr->tz - (gpatch->height-gpatch->topoffset) * this_scale; + swallVerts[2].z = swallVerts[3].z = spr->tz + gpatch->topoffset * this_scale; + } + else + { + // Always a pixel above the floor, perfectly flat. + swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset - (floorheight+3); + + // Spread out top away from the camera. (Fixme: Make it always move out in the same direction!... somehow.) + swallVerts[0].z = swallVerts[1].z = spr->tz - (gpatch->height-gpatch->topoffset); + swallVerts[2].z = swallVerts[3].z = spr->tz + gpatch->topoffset; + } + + // transform + wv = swallVerts; + + for (i = 0; i < 4; i++,wv++) + { + // Offset away from the camera based on height from floor. + if (cv_shadowoffs.value) + wv->z += floorheight; + wv->z += 3; + + //look up/down ----TOTAL SUCKS!!!--- do the 2 in one!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + tr_x = wv->z; + tr_y = wv->y; + wv->y = (tr_x * gr_viewludcos) + (tr_y * gr_viewludsin); + wv->z = (tr_x * gr_viewludsin) - (tr_y * gr_viewludcos); + // ---------------------- mega lame test ---------------------------------- + + //scale y before frustum so that frustum can be scaled to screen height + wv->y *= ORIGINAL_ASPECT * gr_fovlud; + wv->x *= gr_fovlud; + } + + if (spr->flip) + { + swallVerts[0].sow = swallVerts[3].sow = gpatch->max_s; + swallVerts[2].sow = swallVerts[1].sow = 0; + } + else + { + swallVerts[0].sow = swallVerts[3].sow = 0; + swallVerts[2].sow = swallVerts[1].sow = gpatch->max_s; + } + + // flip the texture coords (look familiar?) + if (spr->vflip) + { + swallVerts[3].tow = swallVerts[2].tow = gpatch->max_t; + swallVerts[0].tow = swallVerts[1].tow = 0; + } + else + { + swallVerts[3].tow = swallVerts[2].tow = 0; + swallVerts[0].tow = swallVerts[1].tow = gpatch->max_t; + } + + sSurf.FlatColor.s.red = 0x00; + sSurf.FlatColor.s.blue = 0x00; + sSurf.FlatColor.s.green = 0x00; + + /*if (spr->mobj->frame & FF_TRANSMASK || spr->mobj->flags2 & MF2_SHADOW) + { + sector_t *sector = spr->mobj->subsector->sector; + UINT8 lightlevel = sector->lightlevel; + extracolormap_t *colormap = sector->extra_colormap; + + if (sector->numlights) + { + INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false); + + if (!(spr->mobj->frame & FF_FULLBRIGHT)) + lightlevel = *sector->lightlist[light].lightlevel; + else + lightlevel = 255; + + if (sector->lightlist[light].extra_colormap) + colormap = sector->lightlist[light].extra_colormap; + } + else + { + lightlevel = sector->lightlevel; + + if (sector->extra_colormap) + colormap = sector->extra_colormap; + } + + if (colormap) + sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, colormap->rgba, colormap->fadergba, false, true); + else + sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, NORMALFOG, FADEFOG, false, true); + }*/ + + // shadow is always half as translucent as the sprite itself + if (!cv_translucency.value) // use default translucency (main sprite won't have any translucency) + sSurf.FlatColor.s.alpha = 0x80; // default + else if (spr->mobj->flags2 & MF2_SHADOW) + sSurf.FlatColor.s.alpha = 0x20; + else if (spr->mobj->frame & FF_TRANSMASK) + { + HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &sSurf); + sSurf.FlatColor.s.alpha /= 2; //cut alpha in half! + } + else + sSurf.FlatColor.s.alpha = 0x80; // default + + if (sSurf.FlatColor.s.alpha > floorheight/4) + { + sSurf.FlatColor.s.alpha = (UINT8)(sSurf.FlatColor.s.alpha - floorheight/4); + HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip); + } +} + // -----------------+ // HWR_DrawSprite : Draw flat sprites // : (monsters, bonuses, weapons, lights, ...) @@ -3629,7 +3809,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) // Draw shadow BEFORE sprite if (cv_shadow.value // Shadows enabled - && !(spr->mobj->flags & MF_SCENERY && spr->mobj->flags & MF_SPAWNCEILING && spr->mobj->flags & MF_NOGRAVITY) // Ceiling scenery have no shadow. + && (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow. && !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow. #ifdef ALAM_LIGHTING && !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow. @@ -3640,187 +3820,9 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) //////////////////// // SHADOW SPRITE! // //////////////////// - FOutVector swallVerts[4]; - FSurfaceInfo sSurf; - fixed_t floorheight, mobjfloor; - - mobjfloor = HWR_OpaqueFloorAtPos( - spr->mobj->x, spr->mobj->y, - spr->mobj->z, spr->mobj->height); - if (cv_shadowoffs.value) - { - angle_t shadowdir; - - // Set direction - if (splitscreen && stplyr != &players[displayplayer]) - shadowdir = localangle2 + FixedAngle(cv_cam2_rotate.value); - else - shadowdir = localangle + FixedAngle(cv_cam_rotate.value); - - // Find floorheight - floorheight = HWR_OpaqueFloorAtPos( - spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - mobjfloor), - spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - mobjfloor), - spr->mobj->z, spr->mobj->height); - - // The shadow is falling ABOVE it's mobj? - // Don't draw it, then! - if (spr->mobj->z < floorheight) - goto noshadow; - else - { - fixed_t floorz; - floorz = HWR_OpaqueFloorAtPos( - spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - floorheight), - spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - floorheight), - spr->mobj->z, spr->mobj->height); - // The shadow would be falling on a wall? Don't draw it, then. - // Would draw midair otherwise. - if (floorz < floorheight) - goto noshadow; - } - - floorheight = FixedInt(spr->mobj->z - floorheight); - } - else - floorheight = FixedInt(spr->mobj->z - mobjfloor); - - // create the sprite billboard - // - // 3--2 - // | /| - // |/ | - // 0--1 - - // x1/x2 were already scaled in HWR_ProjectSprite - swallVerts[0].x = swallVerts[3].x = spr->x1; - swallVerts[2].x = swallVerts[1].x = spr->x2; - - if (spr->mobj && this_scale != 1.0f) - { - // Always a pixel above the floor, perfectly flat. - swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset * this_scale - (floorheight+3); - - swallVerts[0].z = swallVerts[1].z = spr->tz - (gpatch->height-gpatch->topoffset) * this_scale; - swallVerts[2].z = swallVerts[3].z = spr->tz + gpatch->topoffset * this_scale; - } - else - { - // Always a pixel above the floor, perfectly flat. - swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset - (floorheight+3); - - // Spread out top away from the camera. (Fixme: Make it always move out in the same direction!... somehow.) - swallVerts[0].z = swallVerts[1].z = spr->tz - (gpatch->height-gpatch->topoffset); - swallVerts[2].z = swallVerts[3].z = spr->tz + gpatch->topoffset; - } - - // transform - wv = swallVerts; - - for (i = 0; i < 4; i++,wv++) - { - // Offset away from the camera based on height from floor. - if (cv_shadowoffs.value) - wv->z += floorheight; - wv->z += 3; - - //look up/down ----TOTAL SUCKS!!!--- do the 2 in one!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - tr_x = wv->z; - tr_y = wv->y; - wv->y = (tr_x * gr_viewludcos) + (tr_y * gr_viewludsin); - wv->z = (tr_x * gr_viewludsin) - (tr_y * gr_viewludcos); - // ---------------------- mega lame test ---------------------------------- - - //scale y before frustum so that frustum can be scaled to screen height - wv->y *= ORIGINAL_ASPECT * gr_fovlud; - wv->x *= gr_fovlud; - } - - if (spr->flip) - { - swallVerts[0].sow = swallVerts[3].sow = gpatch->max_s; - swallVerts[2].sow = swallVerts[1].sow = 0; - } - else - { - swallVerts[0].sow = swallVerts[3].sow = 0; - swallVerts[2].sow = swallVerts[1].sow = gpatch->max_s; - } - - // flip the texture coords (look familiar?) - if (spr->vflip) - { - swallVerts[3].tow = swallVerts[2].tow = gpatch->max_t; - swallVerts[0].tow = swallVerts[1].tow = 0; - } - else - { - swallVerts[3].tow = swallVerts[2].tow = 0; - swallVerts[0].tow = swallVerts[1].tow = gpatch->max_t; - } - - sSurf.FlatColor.s.red = 0x00; - sSurf.FlatColor.s.blue = 0x00; - sSurf.FlatColor.s.green = 0x00; - - /*if (spr->mobj->frame & FF_TRANSMASK || spr->mobj->flags2 & MF2_SHADOW) - { - sector_t *sector = spr->mobj->subsector->sector; - UINT8 lightlevel = sector->lightlevel; - extracolormap_t *colormap = sector->extra_colormap; - - if (sector->numlights) - { - INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false); - - if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = *sector->lightlist[light].lightlevel; - else - lightlevel = 255; - - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; - } - else - { - lightlevel = sector->lightlevel; - - if (sector->extra_colormap) - colormap = sector->extra_colormap; - } - - if (colormap) - sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, colormap->rgba, colormap->fadergba, false, true); - else - sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, NORMALFOG, FADEFOG, false, true); - }*/ - - // shadow is always half as translucent as the sprite itself - if (!cv_translucency.value) - ; // translucency disabled - else if (spr->mobj->flags2 & MF2_SHADOW) - sSurf.FlatColor.s.alpha = 0x20; - else if (spr->mobj->frame & FF_TRANSMASK) - { - HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &sSurf); - sSurf.FlatColor.s.alpha /= 2; //cut alpha in half! - } - else - sSurf.FlatColor.s.alpha = 0x80; // default - - /// \todo do the test earlier - if (!cv_grmd2.value || (md2_models[spr->mobj->sprite].scale < 0.0f) || (md2_models[spr->mobj->sprite].notfound = true) || (md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) || (md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound = true)) - { - if (sSurf.FlatColor.s.alpha > floorheight/4) - { - sSurf.FlatColor.s.alpha = (UINT8)(sSurf.FlatColor.s.alpha - floorheight/4); - HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip); - } - } + HWR_DrawSpriteShadow(spr, gpatch, this_scale); } -noshadow: - // This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black. // sprite lighting by modulating the RGB components /// \todo coloured @@ -3865,11 +3867,14 @@ noshadow: Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); } - /// \todo do the test earlier - if (!cv_grmd2.value || (md2_models[spr->mobj->sprite].scale < 0.0f)) { FBITFIELD blend = 0; - if (spr->mobj->flags2 & MF2_SHADOW) + if (!cv_translucency.value) // translucency disabled + { + Surf.FlatColor.s.alpha = 0xFF; + blend = PF_Translucent|PF_Occlude; + } + else if (spr->mobj->flags2 & MF2_SHADOW) { Surf.FlatColor.s.alpha = 0x40; blend = PF_Translucent; @@ -4390,10 +4395,10 @@ static void HWR_DrawSprites(void) #endif if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { - if (!cv_grmd2.value || (cv_grmd2.value && md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound == true)) + if (!cv_grmd2.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) HWR_DrawSprite(spr); } - else if (!cv_grmd2.value || (cv_grmd2.value && md2_models[spr->mobj->sprite].notfound == true)) + else if (!cv_grmd2.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) HWR_DrawSprite(spr); } } @@ -4419,7 +4424,7 @@ static void HWR_DrawMD2S(void) #endif if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { - if ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound == false) && (md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale > 0.0f)) + if (md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound == false && md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale > 0.0f) HWR_DrawMD2(spr); } else if (md2_models[spr->mobj->sprite].notfound == false && md2_models[spr->mobj->sprite].scale > 0.0f)