From 48e534bf19eb4adabd00ed853bdde80b53ce078e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 1 Mar 2018 01:27:12 +0100 Subject: [PATCH] - Add per-pixel model light to the OpenGL 3.3 render path --- src/gl/scene/gl_scene.cpp | 2 ++ src/gl/scene/gl_scenedrawer.h | 4 ++++ src/gl/scene/gl_sprite.cpp | 23 ++++++++++++++++++++-- src/gl/scene/gl_spritelight.cpp | 26 ++++++++++++++++++------ src/gl/scene/gl_wall.h | 4 +++- src/gl/scene/gl_weapon.cpp | 35 ++++++++++++++++++++++++++++++++- 6 files changed, 84 insertions(+), 10 deletions(-) diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 178b39ff7..060eaf6a3 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -331,6 +331,8 @@ void GLSceneDrawer::RenderScene(int recursion) gl_drawinfo->drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(GLPASS_LIGHTSONLY); gl_drawinfo->drawlists[GLDL_TRANSLUCENTBORDER].Draw(GLPASS_LIGHTSONLY); gl_drawinfo->drawlists[GLDL_TRANSLUCENT].Draw(GLPASS_LIGHTSONLY, true); + gl_drawinfo->drawlists[GLDL_MODELS].Draw(GLPASS_LIGHTSONLY); + SetupWeaponLight(); GLRenderer->mLights->Finish(); } diff --git a/src/gl/scene/gl_scenedrawer.h b/src/gl/scene/gl_scenedrawer.h index 9ade64b73..9ca7132f1 100644 --- a/src/gl/scene/gl_scenedrawer.h +++ b/src/gl/scene/gl_scenedrawer.h @@ -14,6 +14,10 @@ class GLSceneDrawer subsector_t *currentsubsector; // used by the line processing code. sector_t *currentsector; + TMap weapondynlightindex; + + void SetupWeaponLight(); + void RenderMultipassStuff(); void UnclipSubsector(subsector_t *sub); diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 920b4d7d9..af7eec06c 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -82,6 +82,7 @@ EXTERN_CVAR (Bool, r_debug_disable_vis_filter) extern TArray sprites; extern TArray SpriteFrames; extern uint32_t r_renderercaps; +extern int modellightindex; enum HWRenderStyle { @@ -263,7 +264,25 @@ void GLSprite::CalculateVertices(FVector3 *v) void GLSprite::Draw(int pass) { - if (pass == GLPASS_DECALS || pass == GLPASS_LIGHTSONLY) return; + if (pass == GLPASS_DECALS) return; + + if (pass == GLPASS_LIGHTSONLY) + { + if (modelframe) + { + if (RenderStyle.BlendOp != STYLEOP_Shadow) + { + if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !fullbright) + { + if (!particle) + { + dynlightindex = gl_SetDynModelLight(gl_light_sprites ? actor : nullptr, -1); + } + } + } + } + return; + } bool additivefog = false; bool foglayer = false; @@ -336,7 +355,7 @@ void GLSprite::Draw(int pass) if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !fullbright) { if (modelframe && !particle) - gl_SetDynModelLight(gl_light_sprites ? actor : NULL); + gl_SetDynModelLight(gl_light_sprites ? actor : NULL, dynlightindex); else gl_SetDynSpriteLight(gl_light_sprites ? actor : NULL, gl_light_particles ? particle : NULL); } diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index 1415ce16c..72f69cb7d 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -198,13 +198,21 @@ void BSPWalkCircle(float x, float y, float radiusSquared, const Callback &callba BSPNodeWalkCircle(level.HeadNode(), x, y, radiusSquared, callback); } -void gl_SetDynModelLight(AActor *self) +int gl_SetDynModelLight(AActor *self, int dynlightindex) { - // Legacy and deferred render paths gets the old flat model light - if (gl.lightmethod != LM_DIRECT) + // For deferred light mode this function gets called twice. First time for list upload, and second for draw. + if (gl.lightmethod == LM_DEFERRED && dynlightindex != -1) + { + gl_RenderState.SetDynLight(0, 0, 0); + modellightindex = dynlightindex; + return dynlightindex; + } + + // Legacy render path gets the old flat model light + if (gl.lightmethod == LM_LEGACY) { gl_SetDynSpriteLight(self, nullptr); - return; + return -1; } modellightdata.Clear(); @@ -249,6 +257,12 @@ void gl_SetDynModelLight(AActor *self) }); } - gl_RenderState.SetDynLight(0, 0, 0); - modellightindex = GLRenderer->mLights->UploadLights(modellightdata); + dynlightindex = GLRenderer->mLights->UploadLights(modellightdata); + + if (gl.lightmethod != LM_DEFERRED) + { + gl_RenderState.SetDynLight(0, 0, 0); + modellightindex = dynlightindex; + } + return dynlightindex; } diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index aa0bbaed4..5d041a55f 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -392,6 +392,8 @@ public: TArray *lightlist; DRotator Angles; + int dynlightindex; + void SplitSprite(sector_t * frontsector, bool translucent); void SetLowerParam(); void PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, float spriteheight); @@ -422,6 +424,6 @@ inline float Dist2(float x1,float y1,float x2,float y2) void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *subsec); void gl_SetDynSpriteLight(AActor *actor, particle_t *particle); -void gl_SetDynModelLight(AActor *self); +int gl_SetDynModelLight(AActor *self, int dynlightindex); #endif diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index 2061d67f3..421517a26 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -183,6 +183,39 @@ static bool isBright(DPSprite *psp) return false; } +void GLSceneDrawer::SetupWeaponLight() +{ + weapondynlightindex.Clear(); + + AActor *camera = r_viewpoint.camera; + AActor * playermo = players[consoleplayer].camera; + player_t * player = playermo->player; + + // this is the same as in DrawPlayerSprites below + if (!player || + !r_drawplayersprites || + !camera->player || + (player->cheats & CF_CHASECAM) || + (r_deathcamera && camera->health <= 0)) + return; + + for (DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext()) + { + if (psp->GetState() != nullptr) + { + // set the lighting parameters + if (gl_lights && GLRenderer->mLightCount && FixedColormap == CM_DEFAULT && gl_light_sprites) + { + FSpriteModelFrame *smf = playermo->player->ReadyWeapon ? gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false) : nullptr; + if (smf) + { + weapondynlightindex[psp] = gl_SetDynModelLight(playermo, -1); + } + } + } + } +} + //========================================================================== // // R_DrawPlayerSprites @@ -422,7 +455,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) { FSpriteModelFrame *smf = playermo->player->ReadyWeapon ? gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false) : nullptr; if (smf) - gl_SetDynModelLight(playermo); + gl_SetDynModelLight(playermo, weapondynlightindex[psp]); else gl_SetDynSpriteLight(playermo, NULL); }