diff --git a/port/include/video.h b/port/include/video.h index c9bb97f92..8a9c7013e 100644 --- a/port/include/video.h +++ b/port/include/video.h @@ -49,6 +49,8 @@ s32 videoGetVsync(void); s32 videoGetFramerateLimit(void); s32 videoGetDisplayFPS(void); s32 videoGetMSAA(void); +f32 videoGetGlareBrightness(void); +f32 videoGetOverexposureScale(void); f32 videoGetAverageFPS(void); @@ -64,6 +66,8 @@ void videoSetVsync(const s32 vsync); void videoSetFramerateLimit(const s32 limit); void videoSetDisplayFPS(const s32 displayfps); void videoSetMSAA(const s32 msaa); +void videoSetGlareBrightness(f32 bright); +void videoSetOverexposureScale(f32 scale); s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize); void videoSetFramebuffer(s32 target); diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index 761b80e8f..6ab58c265 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -1008,6 +1008,34 @@ static MenuItemHandlerResult menuhandlerScreenShake(s32 operation, struct menuit return 0; } +static MenuItemHandlerResult menuhandlerGlareBrightness(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GETSLIDER: + data->slider.value = videoGetGlareBrightness() * 10.f + 0.5f; + break; + case MENUOP_SET: + videoSetGlareBrightness((f32)data->slider.value / 10.f); + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerOverexposureScale(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GETSLIDER: + data->slider.value = videoGetOverexposureScale() * 10.f + 0.5f; + break; + case MENUOP_SET: + videoSetOverexposureScale((f32)data->slider.value / 10.f); + break; + } + + return 0; +} + struct menuitem g_ExtendedVideoMenuItems[] = { { MENUITEMTYPE_CHECKBOX, @@ -1169,6 +1197,30 @@ struct menuitem g_ExtendedVideoMenuItems[] = { 0, NULL, }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, + (uintptr_t)"Glare Brightness", + 10, + menuhandlerGlareBrightness, + }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, + (uintptr_t)"Overexposure Scale", + 10, + menuhandlerOverexposureScale, + }, + { + MENUITEMTYPE_SEPARATOR, + 0, + 0, + 0, + 0, + NULL, + }, { MENUITEMTYPE_SELECTABLE, 0, diff --git a/port/src/video.c b/port/src/video.c index 3f1247d0c..8bc3e9143 100644 --- a/port/src/video.c +++ b/port/src/video.c @@ -50,6 +50,9 @@ static s32 vidNumModes = 1; static displaymode vidModeDefault; static displaymode *vidModes = &vidModeDefault; +static f32 vidGlareBrightness = 1.f; +static f32 vidOverexposureScale = 1.f; + static s32 texFilter = FILTER_LINEAR; static s32 texFilter2D = true; static s32 texDetail = false; @@ -383,6 +386,16 @@ s32 videoGetDetailTextures(void) return texDetail; } +f32 videoGetGlareBrightness(void) +{ + return vidGlareBrightness; +} + +f32 videoGetOverexposureScale(void) +{ + return vidOverexposureScale; +} + void videoSetWindowOffset(s32 x, s32 y) { gfx_current_game_window_viewport.x = x; @@ -462,6 +475,16 @@ void videoSetDetailTextures(s32 detail) gfx_detail_textures_enabled = (bool)texDetail; } +void videoSetGlareBrightness(f32 bright) +{ + vidGlareBrightness = (bright < 0.f ? 0.f : (bright > 1.f ? 1.f : bright)); +} + +void videoSetOverexposureScale(f32 scale) +{ + vidOverexposureScale = (scale < 0.f ? 0.f : (scale > 1.f ? 1.f : scale)); +} + s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize) { return gfx_create_framebuffer(w, h, upscale, autoresize); @@ -560,4 +583,6 @@ PD_CONSTRUCTOR static void videoConfigInit(void) configRegisterInt("Video.DetailTextures", &texDetail, 0, 1); configRegisterInt("Video.MipmapFilter", &texMipmapFilter, 0, 2); configRegisterInt("Video.AnisotropicFilter", &texAnisotropicFilter, 0, 16); + configRegisterFloat("Video.GlareBrightness", &vidGlareBrightness, 0.f, 1.f); + configRegisterFloat("Video.OverexposureScale", &vidOverexposureScale, 0.f, 1.f); } diff --git a/src/game/artifact.c b/src/game/artifact.c index 390c161a6..e2b9b6c65 100644 --- a/src/game/artifact.c +++ b/src/game/artifact.c @@ -21,6 +21,7 @@ #include "lib/lib_17ce0.h" #include "game/player.h" #include "game/prop.h" +#include "video.h" #endif /** @@ -246,6 +247,12 @@ void artifactsCalculateGlaresForRoom(s32 roomnum) struct coord *campos = &g_Vars.currentplayer->cam_pos; struct artifact *artifact; +#ifndef PLATFORM_N64 + if (videoGetGlareBrightness() <= 0.f) { + return; + } +#endif + if (g_Rooms[roomnum].gfxdata != NULL && g_Rooms[roomnum].loaded240) { numlights = g_Rooms[roomnum].gfxdata->numlights; @@ -532,6 +539,13 @@ Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum) f32 f24; bool extra; f32 f26; +#ifndef PLATFORM_N64 + const f32 pfov = g_Vars.currentplayerstats ? PLAYER_DEFAULT_FOV : 60.f; + const f32 brightscale = videoGetGlareBrightness(); + if (brightscale <= 0.f) { + return gdl; + } +#endif artifacts = schedGetFrontArtifacts(); lightop_cur_frac = roomGetLightOpCurFrac(roomnum); @@ -619,7 +633,11 @@ Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum) s3[0] = artifactsClamp(s3[0], numgood * 2); if (numgood > 0) { +#ifndef PLATFORM_N64 + brightness = viGetFovY() / pfov; +#else brightness = viGetFovY() * 0.017453292f; +#endif add = cosf(brightness) / sinf(brightness) * 14.6f; if (lightIsHealthy(roomnum, lightindex - g_Rooms[roomnum].gfxdata->lightsindex)) { @@ -649,6 +667,9 @@ Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum) } f0 = s3[2] * (1.0f / 255.0f); +#ifndef PLATFORM_N64 + f0 *= (60.f / pfov); +#endif skySetOverexposure((s32) ((f32)f0 * r), (s32) ((f32)f0 * g), (s32) ((f32)f0 * b)); @@ -698,6 +719,10 @@ Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum) alpha *= (s3[1] / 255.0f); alpha *= (s3[0] / 8.0f); +#ifndef PLATFORM_N64 + alpha *= brightscale; +#endif + if (USINGDEVICE(DEVICE_NIGHTVISION)) { alpha *= lightop_cur_frac * 7.0f; } diff --git a/src/game/sky.c b/src/game/sky.c index 7adf7b822..0b6903e90 100644 --- a/src/game/sky.c +++ b/src/game/sky.c @@ -3074,6 +3074,13 @@ Gfx *skyRenderArtifacts(Gfx *gdl) void skySetOverexposure(s32 r, s32 g, s32 b) { +#ifndef PLATFORM_N64 + const f32 scale = videoGetOverexposureScale(); + r *= scale; + g *= scale; + b *= scale; +#endif + g_Vars.currentplayer->overexposurered = sqrtf(g_Vars.currentplayer->overexposurered * g_Vars.currentplayer->overexposurered + r * r); g_Vars.currentplayer->overexposuregreen = sqrtf(g_Vars.currentplayer->overexposuregreen * g_Vars.currentplayer->overexposuregreen + g * g); g_Vars.currentplayer->overexposureblue = sqrtf(g_Vars.currentplayer->overexposureblue * g_Vars.currentplayer->overexposureblue + b * b);