diff --git a/src/paint/map_element/entrance.c b/src/paint/map_element/entrance.c index 48f0f1e68e..11d98e6803 100644 --- a/src/paint/map_element/entrance.c +++ b/src/paint/map_element/entrance.c @@ -24,6 +24,7 @@ #include "../../ride/ride_data.h" #include "../../world/entrance.h" #include "../../world/footpath.h" +#include "../../drawing/lightfx.h" #include "map_element.h" /** @@ -32,6 +33,7 @@ */ void ride_entrance_exit_paint(uint8 direction, int height, rct_map_element* map_element) { + uint8 is_exit = map_element->properties.entrance.type == ENTRANCE_TYPE_RIDE_EXIT; if (RCT2_GLOBAL(0x9DEA6F, uint8_t) & 1){ @@ -39,6 +41,29 @@ void ride_entrance_exit_paint(uint8 direction, int height, rct_map_element* map_ return; } +#ifdef STOUT_EXPANDED_RENDERING_LIGHT + + if (!is_exit) { + lightfx_add_3d_light_magic_from_drawing_tile(0, 0, height + 45, LIGHTFX_LIGHT_TYPE_LANTERN_3); + } + + switch (map_element->type & MAP_ELEMENT_DIRECTION_MASK) { + case 0: + lightfx_add_3d_light_magic_from_drawing_tile(16, 0, height + 16, LIGHTFX_LIGHT_TYPE_LANTERN_2); + break; + case 1: + lightfx_add_3d_light_magic_from_drawing_tile(0, -16, height + 16, LIGHTFX_LIGHT_TYPE_LANTERN_2); + break; + case 2: + lightfx_add_3d_light_magic_from_drawing_tile(-16, 0, height + 16, LIGHTFX_LIGHT_TYPE_LANTERN_2); + break; + case 3: + lightfx_add_3d_light_magic_from_drawing_tile(0, 16, height + 16, LIGHTFX_LIGHT_TYPE_LANTERN_2); + break; + }; + +#endif + rct_ride* ride = get_ride(map_element->properties.entrance.ride_index); if (ride->entrance_style == RIDE_ENTRANCE_STYLE_NONE) return; @@ -163,6 +188,12 @@ void park_entrance_paint(uint8 direction, int height, rct_map_element* map_eleme if (RCT2_GLOBAL(0x9DEA6F, uint8_t) & 1) return; +#ifdef STOUT_EXPANDED_RENDERING_LIGHT + + lightfx_add_3d_light_magic_from_drawing_tile(0, 0, 155, LIGHTFX_LIGHT_TYPE_LANTERN_3); + +#endif + gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_PARK; RCT2_GLOBAL(0x009E32BC, uint32) = 0; uint32 image_id, ghost_id = 0; diff --git a/src/paint/map_element/path.c b/src/paint/map_element/path.c index ce9b3b83e4..42b5090220 100644 --- a/src/paint/map_element/path.c +++ b/src/paint/map_element/path.c @@ -17,6 +17,9 @@ #include "map_element.h" #include "../../addresses.h" #include "../../world/map.h" +#include "../../world/scenery.h" +#include "../../drawing/lightfx.h" +#include "../../world/footpath.h" // #3628: Until path_paint is implemented, this variable is used by scrolling_text_setup // to use the old string arguments array. Remove when scrolling_text_setup is no @@ -27,4 +30,30 @@ void path_paint(uint8 direction, uint16 height, rct_map_element *mapElement) { TempForScrollText = true; RCT2_CALLPROC_X(0x6A3590, 0, 0, direction, height, (int)mapElement, 0, 0); TempForScrollText = false; -} + +#ifdef STOUT_EXPANDED_RENDERING_LIGHT + + if (footpath_element_has_path_scenery(mapElement)) { + rct_scenery_entry *sceneryEntry; + + sceneryEntry = get_footpath_item_entry(footpath_element_get_path_scenery_index(mapElement)); + + if (sceneryEntry->path_bit.flags & PATH_BIT_FLAG_LAMP) { + + if (!(mapElement->properties.path.edges & (1 << 0))) { + lightfx_add_3d_light_magic_from_drawing_tile(-16, 0, height + 23, LIGHTFX_LIGHT_TYPE_LANTERN_3); + } + if (!(mapElement->properties.path.edges & (1 << 1))) { + lightfx_add_3d_light_magic_from_drawing_tile(0, 16, height + 23, LIGHTFX_LIGHT_TYPE_LANTERN_3); + } + if (!(mapElement->properties.path.edges & (1 << 2))) { + lightfx_add_3d_light_magic_from_drawing_tile(16, 0, height + 23, LIGHTFX_LIGHT_TYPE_LANTERN_3); + } + if (!(mapElement->properties.path.edges & (1 << 3))) { + lightfx_add_3d_light_magic_from_drawing_tile(0, -16, height + 23, LIGHTFX_LIGHT_TYPE_LANTERN_3); + } + } + } +#endif + +} diff --git a/src/paint/sprite/peep.c b/src/paint/sprite/peep.c index 5ce823c651..60d69b384c 100644 --- a/src/paint/sprite/peep.c +++ b/src/paint/sprite/peep.c @@ -18,6 +18,7 @@ #include "../../interface/viewport.h" #include "../../peep/peep.h" #include "../paint.h" +#include "../../drawing/lightfx.h" /** * @@ -25,6 +26,37 @@ */ void peep_paint(rct_peep * peep, int imageDirection) { +#ifdef STOUT_EXPANDED_RENDERING_LIGHT + + if (peep->type == PEEP_TYPE_STAFF){ + sint16 peep_x, peep_y, peep_z; + + peep_x = peep->x; + peep_y = peep->y; + peep_z = peep->z; + + switch (peep->sprite_direction) { + case 0: + peep_x -= 10; + break; + case 8: + peep_y += 10; + break; + case 16: + peep_x += 10; + break; + case 24: + peep_y -= 10; + break; + default: + return; + }; + + lightfx_add_3d_light(peep_x, peep_y, peep_z, LIGHTFX_LIGHT_TYPE_SPOT_1); + } + +#endif + rct_drawpixelinfo * dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*); if (dpi->zoom_level > 2) { return; diff --git a/src/platform/platform.h b/src/platform/platform.h index dccafe8e92..f792d82f6d 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -124,6 +124,7 @@ void platform_update_fullscreen_resolutions(); void platform_get_closest_resolution(int inWidth, int inHeight, int *outWidth, int *outHeight); void platform_init(); void platform_draw(); +void platform_draw_require_end(); void platform_free(); void platform_trigger_resize(); void platform_update_palette(const uint8 *colours, int start_index, int num_colours); diff --git a/src/platform/shared.c b/src/platform/shared.c index fd68199744..e14591b6b0 100644 --- a/src/platform/shared.c +++ b/src/platform/shared.c @@ -31,6 +31,7 @@ #include "../title.h" #include "../util/util.h" #include "../world/climate.h" +#include "../drawing/lightfx.h" #include "platform.h" typedef void(*update_palette_func)(const uint8*, int, int); @@ -55,7 +56,9 @@ SDL_Renderer *gRenderer = NULL; SDL_Texture *gBufferTexture = NULL; SDL_PixelFormat *gBufferTextureFormat = NULL; SDL_Color gPalette[256]; +SDL_Color gPalette_light[256]; uint32 gPaletteHWMapped[256]; +uint32 gPaletteHWMapped_light[256]; bool gHardwareDisplay; bool gSteamOverlayActive = false; @@ -65,6 +68,8 @@ static SDL_Surface *_RGBASurface = NULL; static SDL_Palette *_palette = NULL; static void *_screenBuffer; +static void *_screenBuffer_back; +static rct_drawpixelinfo _screenDPI_back; static int _screenBufferSize; static int _screenBufferWidth; static int _screenBufferHeight; @@ -217,6 +222,120 @@ static void overlay_post_render_check(int width, int height) { overlayActive = newOverlayActive; } +typedef enum { + MTT_STATE_LOCK, + MTT_STATE_WAITING, + MTT_STATE_RENDER +} +dialog_type; + +static int _mtt_screen_width; +static int _mtt_screen_height; +static int _mtt_pitch; +static void* _mtt_screenBuffer; +static void* _mtt_pixels; +static uint8 _mtt_state = MTT_STATE_LOCK; +static SDL_Thread *_mtt_thread; +static uint32 _mtt_palette_base[256]; +static uint32 _mtt_palette_light[256]; +static uint16 _mtt_palette_base_rich[256*4]; +static uint16 _mtt_palette_light_rich[256*4]; + +int platform_draw_hardware(void *dat) +{ + uint8 *src = (uint8*)_mtt_screenBuffer; + int padding = _mtt_pitch - (_mtt_screen_width * 4); + if (_mtt_pitch == _mtt_screen_width * 4) { + uint32 *dst = _mtt_pixels; + +#ifndef STOUT_EXPANDED_RENDERING_LIGHT + + for (int i = _mtt_screen_width * _mtt_screen_height; i > 0; i--) { + *dst++ = *(uint32 *)(&_mtt_palette_base[*src++]); + } + +#else + + lightfx_render_lights_to_frontbuffer(); + + for (int i = 0; i < 256; i++) { + _mtt_palette_base_rich[i * 4 + 0] = (0xFF00 & (_mtt_palette_base[i] >> 8)); + _mtt_palette_base_rich[i * 4 + 1] = (0xFF00 & (_mtt_palette_base[i] >> 0)); + _mtt_palette_base_rich[i * 4 + 2] = (0xFF00 & (_mtt_palette_base[i] << 8)); + _mtt_palette_light_rich[i * 4 + 0] = (0xFF0 & (_mtt_palette_light[i] >> 12)); + _mtt_palette_light_rich[i * 4 + 1] = (0xFF0 & (_mtt_palette_light[i] >> 4)); + _mtt_palette_light_rich[i * 4 + 2] = (0xFF0 & (_mtt_palette_light[i] << 4)); + } + + const uint8 *lightFXBuf = (uint8*)lightfx_get_front_buffer(); + + for (int i = _mtt_screen_width * _mtt_screen_height; i > 0; i--) { + uint32 srcIndex = *src * 4; + + *dst = ((0xFF00 & (min(0xFF00, _mtt_palette_base_rich[srcIndex + 0] + (_mtt_palette_light_rich[srcIndex + 0] * *lightFXBuf)))) << 8) | + ((0xFF00 & (min(0xFF00, _mtt_palette_base_rich[srcIndex + 1] + (_mtt_palette_light_rich[srcIndex + 1] * *lightFXBuf)))) << 0) | + ((0xFF00 & (min(0xFF00, _mtt_palette_base_rich[srcIndex + 2] + (_mtt_palette_light_rich[srcIndex + 2] * *lightFXBuf)))) >> 8); + dst++; + src++; + lightFXBuf++; + } + +#endif + + } + else if (_mtt_pitch == (_mtt_screen_width * 2) + padding) { + uint16 *dst = _mtt_pixels; + for (int y = _mtt_screen_height; y > 0; y--) { + for (int x = _mtt_screen_width; x > 0; x--) { + const uint8 lower = *(uint8 *)(&_mtt_palette_base[*src++]); + const uint8 upper = *(uint8 *)(&_mtt_palette_base[*src++]); + *dst++ = (lower << 8) | upper; + } + dst = (uint16*)(((uint8 *)dst) + padding); + } + } + else if (_mtt_pitch == _mtt_screen_width + padding) { + uint8 *dst = _mtt_pixels; + for (int y = _mtt_screen_height; y > 0; y--) { + for (int x = _mtt_screen_width; x > 0; x--) { *dst++ = *(uint8 *)(&_mtt_palette_base[*src++]); } + dst += padding; + } + } + + return 1; +} + +static void platfrom_do_render() +{ + SDL_UnlockTexture(gBufferTexture); + + SDL_RenderCopy(gRenderer, gBufferTexture, NULL, NULL); + + if (gSteamOverlayActive && gConfigGeneral.steam_overlay_pause) { + overlay_pre_render_check(_mtt_screen_width, _mtt_screen_height); + } + + SDL_RenderPresent(gRenderer); + + if (gSteamOverlayActive && gConfigGeneral.steam_overlay_pause) { + overlay_post_render_check(_mtt_screen_width, _mtt_screen_height); + } + + _mtt_state = MTT_STATE_LOCK; +} + +void platform_draw_require_end() +{ +#ifdef STOUT_EXPANDED_RENDERING_MTT + if (_mtt_state == MTT_STATE_WAITING) { + int out; + SDL_WaitThread(_mtt_thread, &out); + platfrom_do_render(); + } +#endif + +} + void platform_draw() { int width = gScreenWidth; @@ -224,48 +343,57 @@ void platform_draw() if (!gOpenRCT2Headless) { if (gHardwareDisplay) { - void *pixels; - int pitch; - if (SDL_LockTexture(gBufferTexture, NULL, &pixels, &pitch) == 0) { - uint8 *src = (uint8*)_screenBuffer; - int padding = pitch - (width * 4); - if (pitch == width * 4) { - uint32 *dst = pixels; - for (int i = width * height; i > 0; i--) { *dst++ = *(uint32 *)(&gPaletteHWMapped[*src++]); } - } - else - if (pitch == (width * 2) + padding) { - uint16 *dst = pixels; - for (int y = height; y > 0; y--) { - for (int x = width; x > 0; x--) { - const uint8 lower = *(uint8 *)(&gPaletteHWMapped[*src++]); - const uint8 upper = *(uint8 *)(&gPaletteHWMapped[*src++]); - *dst++ = (lower << 8) | upper; - } - dst = (uint16*)(((uint8 *)dst) + padding); - } + _mtt_screen_width = width; + _mtt_screen_height = height; + +#ifdef STOUT_EXPANDED_RENDERING_MTT + platform_draw_require_end(); + if (_mtt_state == MTT_STATE_RENDER) { + platfrom_do_render(); + } +#endif + + if (_mtt_state == MTT_STATE_LOCK) { + if (SDL_LockTexture(gBufferTexture, NULL, &_mtt_pixels, &_mtt_pitch) == 0) { +#ifndef STOUT_EXPANDED_RENDERING_MTT + platform_draw_hardware(0); + platfrom_do_render(); +#else + + // Swap back and front + + void *tmp = _screenBuffer_back; + _screenBuffer_back = _screenBuffer; + _screenBuffer = tmp; + rct_drawpixelinfo tmpPx; + memcpy(&tmpPx, &gScreenDPI, sizeof(rct_drawpixelinfo)); + memcpy(&gScreenDPI, &_screenDPI_back, sizeof(rct_drawpixelinfo)); + memcpy(&_screenDPI_back, &tmpPx, sizeof(rct_drawpixelinfo)); + + // This messes up drawing, so force a full redraw + + gfx_invalidate_screen(); + + lightfx_add_3d_light(gCursorState.x, gCursorState.y, 0x7FFF, LIGHTFX_LIGHT_TYPE_LANTERN_3); + + lightfx_prepare_light_list(); + lightfx_swap_buffers(); + + // Make palette safe + + for (int i = 0; i < 256; i++) { + _mtt_palette_base[i] = gPaletteHWMapped[i]; + _mtt_palette_light[i] = gPaletteHWMapped_light[i]; } - else - if (pitch == width + padding) { - uint8 *dst = pixels; - for (int y = height; y > 0; y--) { - for (int x = width; x > 0; x--) { *dst++ = *(uint8 *)(&gPaletteHWMapped[*src++]); } - dst += padding; - } - } - SDL_UnlockTexture(gBufferTexture); - } - SDL_RenderCopy(gRenderer, gBufferTexture, NULL, NULL); - - if (gSteamOverlayActive && gConfigGeneral.steam_overlay_pause) { - overlay_pre_render_check(width, height); - } - - SDL_RenderPresent(gRenderer); - - if (gSteamOverlayActive && gConfigGeneral.steam_overlay_pause) { - overlay_post_render_check(width, height); + _mtt_screenBuffer = _screenBuffer_back; + _mtt_thread = SDL_CreateThread(&platform_draw_hardware, "Blit", 0); + _mtt_state = MTT_STATE_WAITING; +#endif + } + else { + _mtt_state = MTT_STATE_LOCK; + } } } else { @@ -314,6 +442,8 @@ void platform_draw() static void platform_resize(int width, int height) { + platform_draw_require_end(); + uint32 flags; int dst_w = (int)(width / gConfigGeneral.window_scale); int dst_h = (int)(height / gConfigGeneral.window_scale); @@ -390,8 +520,21 @@ static uint8 lerp(uint8 a, uint8 b, float t) return (uint8)(a + amount); } +static float flerp(float a, float b, float t) +{ + if (t <= 0) return a; + if (t >= 1) return b; + + float range = b - a; + float amount = range * t; + return a + amount; +} + void platform_update_palette(const uint8* colours, int start_index, int num_colours) { + start_index= 0; + num_colours= 256; + SDL_Surface *surface; int i; colours += start_index * 4; @@ -402,16 +545,138 @@ void platform_update_palette(const uint8* colours, int start_index, int num_colo gPalette[i].b = colours[0]; gPalette[i].a = 0; - float night = gDayNightCycle; - if (night >= 0 && gClimateLightningFlash == 0) { + float night = (float)(pow(gDayNightCycle, 1.5)); + +#ifdef STOUT_EXPANDED_RENDERING_LIGHT + + float natLightR = 1.0f; + float natLightG = 1.0f; + float natLightB = 1.0f; + + static float wetness = 0.0f; + static float fogginess = 0.0f; + + float sunLight = max(0.0f, min(1.0f, 2.0f - night * 3.0f)); + + // Night version + natLightR = flerp(natLightR * 4.0f, 0.335f, (float)(pow(night, 0.035f + sunLight * 10.50f))); + natLightG = flerp(natLightG * 4.0f, 0.350f, (float)(pow(night, 0.100f + sunLight * 5.50f))); + natLightB = flerp(natLightB * 4.0f, 0.550f, (float)(pow(night, 0.200f + sunLight * 1.5f))); + + float lightAvg = (natLightR + natLightG + natLightB) / 3.0f; + float lightMax = (natLightR + natLightG + natLightB) / 3.0f; + float overExpose = 0.0f; + + // overExpose += ((lightMax - lightAvg) / lightMax) * 0.01f; + + if (gClimateCurrentTemperature > 20) { + float offset = ((float)(gClimateCurrentTemperature - 20)) * 0.04f; + offset *= 1.0f - night; + lightAvg /= 1.0f + offset; + // overExpose += offset * 0.1f; + } + + // lightAvg += (lightMax - lightAvg) * 0.6f; + + if (lightAvg > 1.0f) { + natLightR /= lightAvg; + natLightG /= lightAvg; + natLightB /= lightAvg; + } + + natLightR *= 1.0f + overExpose; + natLightG *= 1.0f + overExpose; + natLightB *= 1.0f + overExpose; + overExpose *= 255.0f; + + float targetFogginess = (float)(gClimateCurrentRainLevel) / 5.0f; + targetFogginess += (night * night) * 0.35f; + + if (gClimateCurrentTemperature < 10) { + targetFogginess += ((float)(10 - gClimateCurrentTemperature)) * 0.01f; + } + + fogginess -= (fogginess - targetFogginess) * 0.00001f; + + wetness *= 0.999995f; + wetness += fogginess * 0.001f; + wetness = min(wetness, 1.0f); + + float boost = 1.0f; + float envFog = fogginess; + float lightFog = envFog; + + float addLightNatR = 0.0f; + float addLightNatG = 0.0f; + float addLightNatB = 0.0f; + + float reduceColourNat = 1.0f; + float reduceColourLit = 1.0f; + + reduceColourLit *= night / (float)pow(max(1.01f, 0.4f + lightAvg), 2.0); + + reduceColourLit += (float)(gClimateCurrentRainLevel) / 35.0f; + + lightFog *= reduceColourLit; + + reduceColourNat *= 1.0f - envFog; + reduceColourLit *= 1.0f - lightFog; + + float fogR = 35.5f * natLightR * 1.3f; + float fogG = 45.0f * natLightG * 1.3f; + float fogB = 50.0f * natLightB * 1.3f; + lightFog *= 10.0f; + + float wetnessBoost = 1.0f;//1.0f + wetness * wetness * 0.1f; + +#endif + + if (night >= 0 && gClimateLightningFlash != 1) { gPalette[i].r = lerp(gPalette[i].r, soft_light(gPalette[i].r, 8), night); gPalette[i].g = lerp(gPalette[i].g, soft_light(gPalette[i].g, 8), night); gPalette[i].b = lerp(gPalette[i].b, soft_light(gPalette[i].b, 128), night); + +#ifdef STOUT_EXPANDED_RENDERING_LIGHT + + // if (i == 32) + // boost = 300000.0f; + if ((i % 32) == 0) + boost = 1.01f * wetnessBoost; + else if ((i % 16) < 7) + boost = 1.001f * wetnessBoost; + if (i > 230 && i < 232) + boost = ((float)(gPalette[i].b)) / 64.0f; + + if (false) { + // This experiment shifts the colour of pixels as-if they are wet, but it is not a pretty solution at all + if ((i % 16)) { + float iVal = ((float)((i + 12) % 16)) / 16.0f; + float eff = (wetness * ((float)pow(iVal, 1.5) * 0.85f)); + reduceColourNat *= 1.0f - eff; + addLightNatR += fogR * eff * 3.95f; + addLightNatG += fogR * eff * 3.95f; + addLightNatB += fogR * eff * 3.95f; + } + } + + addLightNatR *= 1.0f - envFog; + addLightNatG *= 1.0f - envFog; + addLightNatB *= 1.0f - envFog; + + gPalette[i].r = (uint8)(min(255.0f, max(0.0f, (-overExpose + (float)(gPalette[i].r) * reduceColourNat * natLightR + envFog * fogR + addLightNatR)))); + gPalette[i].g = (uint8)(min(255.0f, max(0.0f, (-overExpose + (float)(gPalette[i].g) * reduceColourNat * natLightG + envFog * fogG + addLightNatG)))); + gPalette[i].b = (uint8)(min(255.0f, max(0.0f, (-overExpose + (float)(gPalette[i].b) * reduceColourNat * natLightB + envFog * fogB + addLightNatB)))); + gPalette_light[i].r = (uint8)(min(0xFF, ((float)(gPalette[i].r) * reduceColourLit * boost + lightFog) * 1.0f)); + gPalette_light[i].g = (uint8)(min(0xFF, ((float)(gPalette[i].g) * reduceColourLit * boost + lightFog) * 0.85f)); + gPalette_light[i].b = (uint8)(min(0xFF, ((float)(gPalette[i].b) * reduceColourLit * boost + lightFog) * 0.30f)); + +#endif } colours += 4; if (gBufferTextureFormat != NULL) { gPaletteHWMapped[i] = SDL_MapRGB(gBufferTextureFormat, gPalette[i].r, gPalette[i].g, gPalette[i].b); + gPaletteHWMapped_light[i] = SDL_MapRGB(gBufferTextureFormat, gPalette_light[i].r, gPalette_light[i].g, gPalette_light[i].b); } } @@ -986,6 +1251,13 @@ void platform_refresh_video() static void platform_refresh_screenbuffer(int width, int height, int pitch) { +#ifdef STOUT_EXPANDED_RENDERING_MTT + + platform_draw_require_end(); + +#endif + + int newScreenBufferSize = pitch * height; char *newScreenBuffer = (char*)malloc(newScreenBufferSize); if (_screenBuffer == NULL) { @@ -1019,6 +1291,17 @@ static void platform_refresh_screenbuffer(int width, int height, int pitch) _screenBufferHeight = height; _screenBufferPitch = pitch; +#ifdef STOUT_EXPANDED_RENDERING_MTT + newScreenBuffer = (char*)malloc(newScreenBufferSize); + if (_screenBuffer_back == NULL) { + memset(newScreenBuffer, 0xFF, newScreenBufferSize); + } + else { + memset(newScreenBuffer, 0xFF, newScreenBufferSize); + } + _screenBuffer_back = newScreenBuffer; +#endif + rct_drawpixelinfo *screenDPI = &gScreenDPI; screenDPI->bits = _screenBuffer; screenDPI->x = 0; @@ -1027,6 +1310,23 @@ static void platform_refresh_screenbuffer(int width, int height, int pitch) screenDPI->height = height; screenDPI->pitch = _screenBufferPitch - width; +#ifdef STOUT_EXPANDED_RENDERING_MTT + screenDPI = &_screenDPI_back; + screenDPI->bits = _screenBuffer_back; + screenDPI->x = 0; + screenDPI->y = 0; + screenDPI->width = width; + screenDPI->height = height; + screenDPI->pitch = _screenBufferPitch - width; + +#ifdef STOUT_EXPANDED_RENDERING_LIGHT + + lightfx_update_buffers(screenDPI); + +#endif + +#endif + gfx_configure_dirty_grid(); } diff --git a/src/rct2.c b/src/rct2.c index 52f7456f08..9e23452eb6 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -51,6 +51,12 @@ #include "world/scenery.h" #include "world/sprite.h" +#ifdef STOUT_EXPANDED_RENDERING_LIGHT + +#include "drawing/lightfx.h" + +#endif + // rct2: 0x0097F67C const char * const RCT2FilePaths[PATH_ID_END] = { "Data\\g1.dat", @@ -184,6 +190,13 @@ int rct2_init() window_guest_list_init_vars_b(); window_staff_list_init_vars(); + +#ifdef STOUT_EXPANDED_RENDERING_LIGHT + + lightfx_init(); + +#endif + if (!gOpenRCT2Headless) { title_load(); diff --git a/src/ride/vehicle_paint.c b/src/ride/vehicle_paint.c index b1f2c34f8f..7307944866 100644 --- a/src/ride/vehicle_paint.c +++ b/src/ride/vehicle_paint.c @@ -21,6 +21,7 @@ #include "../ride/track.h" #include "../interface/viewport.h" #include "../game.h" +#include "../drawing/lightfx.h" #include "vehicle_paint.h" // 0x0098E52C: @@ -891,6 +892,7 @@ const vehicle_boundbox VehicleBoundboxes[16][224] = { // 6D5214 void vehicle_sprite_paint(rct_vehicle *vehicle, int ebx, int ecx, int z, const rct_ride_entry_vehicle *vehicleEntry) { + int baseImage_id = ebx; vehicle_boundbox bb = VehicleBoundboxes[vehicleEntry->draw_order][ecx]; if (vehicleEntry->flags_a & 0x4000) { @@ -2334,7 +2336,7 @@ void vehicle_visual_default(int x, int imageDirection, int y, int z, rct_vehicle */ void vehicle_paint(rct_vehicle *vehicle, int imageDirection) { - rct_ride_entry *rideEntry; + rct_ride_entry *rideEntry = 0; const rct_ride_entry_vehicle *vehicleEntry; int x = vehicle->x; @@ -2359,6 +2361,107 @@ void vehicle_paint(rct_vehicle *vehicle, int imageDirection) } } +#ifdef STOUT_EXPANDED_RENDERING_LIGHT + + sint16 peep_x, peep_y, peep_z; + + peep_x = vehicle->x; + peep_y = vehicle->y; + peep_z = vehicle->z; + + static const sint16 offsetLookup[32] = { 10, 10, 9, 8, 7, 6, 4, 2, 0, -2, -4, -6, -7, -8, -9, -10, -10, -10, -9, -8, -7, -6, -4, -2, 0, 2, 4, 6, 7, 8, 9, 10 }; + + switch (vehicleEntry->car_visual) { + case VEHICLE_VISUAL_MINI_GOLF_PLAYER: { + peep_x -= offsetLookup[(vehicle->sprite_direction + 0) % 32]; + peep_y -= offsetLookup[(vehicle->sprite_direction + 8) % 32]; + lightfx_add_3d_light(peep_x, peep_y, peep_z, LIGHTFX_LIGHT_TYPE_SPOT_1); + break; + }; + default: { + rct_ride *ride = get_ride(vehicle->ride); + switch (ride->type) { + case RIDE_TYPE_OBSERVATION_TOWER: + lightfx_add_3d_light(vehicle->x, vehicle->y + 16, vehicle->z, LIGHTFX_LIGHT_TYPE_SPOT_3); + lightfx_add_3d_light(vehicle->x + 16, vehicle->y, vehicle->z, LIGHTFX_LIGHT_TYPE_SPOT_3); + lightfx_add_3d_light(vehicle->x - 16, vehicle->y, vehicle->z, LIGHTFX_LIGHT_TYPE_SPOT_3); + lightfx_add_3d_light(vehicle->x, vehicle->y - 16, vehicle->z, LIGHTFX_LIGHT_TYPE_SPOT_3); + break; + case RIDE_TYPE_MINE_TRAIN_COASTER: + if (vehicle == vehicle_get_head(vehicle)) { + peep_x -= offsetLookup[(vehicle->sprite_direction + 0) % 32] * 2; + peep_y -= offsetLookup[(vehicle->sprite_direction + 8) % 32] * 2; + lightfx_add_3d_light(peep_x, peep_y, peep_z, LIGHTFX_LIGHT_TYPE_LANTERN_3); + } + break; + case RIDE_TYPE_CHAIRLIFT: + lightfx_add_3d_light(peep_x, peep_y, peep_z - 16, LIGHTFX_LIGHT_TYPE_LANTERN_2); + break; + case RIDE_TYPE_BOAT_RIDE: + case RIDE_TYPE_CAR_RIDE: + case RIDE_TYPE_GO_KARTS: + case RIDE_TYPE_DODGEMS: + case RIDE_TYPE_MINI_HELICOPTERS: + case RIDE_TYPE_MONORAIL_CYCLES: + case RIDE_TYPE_SUBMARINE_RIDE: + case RIDE_TYPE_SPLASH_BOATS: + case RIDE_TYPE_WATER_COASTER: { + rct_vehicle *vehicle_draw = vehicle_get_head(vehicle); + if (vehicle_draw->next_vehicle_on_train != 0xFFFF) { + vehicle_draw = GET_VEHICLE(vehicle_draw->next_vehicle_on_train); + } + peep_x = vehicle_draw->x; + peep_y = vehicle_draw->y; + peep_z = vehicle_draw->z; + peep_x -= offsetLookup[(vehicle_draw->sprite_direction + 0) % 32]; + peep_y -= offsetLookup[(vehicle_draw->sprite_direction + 8) % 32]; + lightfx_add_3d_light(peep_x, peep_y, peep_z, LIGHTFX_LIGHT_TYPE_SPOT_2); + peep_x -= offsetLookup[(vehicle_draw->sprite_direction + 0) % 32]; + peep_y -= offsetLookup[(vehicle_draw->sprite_direction + 8) % 32]; + lightfx_add_3d_light(peep_x, peep_y, peep_z, LIGHTFX_LIGHT_TYPE_SPOT_2); + } + break; + case RIDE_TYPE_MONORAIL: + lightfx_add_3d_light(vehicle->x, vehicle->y, vehicle->z + 12, LIGHTFX_LIGHT_TYPE_LANTERN_2); + if (vehicle == vehicle_get_head(vehicle)) { + peep_x -= offsetLookup[(vehicle->sprite_direction + 0) % 32] * 2; + peep_y -= offsetLookup[(vehicle->sprite_direction + 8) % 32] * 2; + lightfx_add_3d_light(peep_x, peep_y, peep_z + 10, LIGHTFX_LIGHT_TYPE_LANTERN_3); + peep_x -= offsetLookup[(vehicle->sprite_direction + 0) % 32] * 3; + peep_y -= offsetLookup[(vehicle->sprite_direction + 8) % 32] * 3; + lightfx_add_3d_light(peep_x, peep_y, peep_z + 2, LIGHTFX_LIGHT_TYPE_LANTERN_3); + } + if (vehicle == vehicle_get_tail(vehicle)) { + peep_x += offsetLookup[(vehicle->sprite_direction + 0) % 32] * 2; + peep_y += offsetLookup[(vehicle->sprite_direction + 8) % 32] * 2; + lightfx_add_3d_light(peep_x, peep_y, peep_z + 10, LIGHTFX_LIGHT_TYPE_LANTERN_3); + peep_x += offsetLookup[(vehicle->sprite_direction + 0) % 32] * 2; + peep_y += offsetLookup[(vehicle->sprite_direction + 8) % 32] * 2; + lightfx_add_3d_light(peep_x, peep_y, peep_z + 2, LIGHTFX_LIGHT_TYPE_LANTERN_3); + } + break; + case RIDE_TYPE_MINIATURE_RAILWAY: + if (vehicle == vehicle_get_head(vehicle)) { + peep_x -= offsetLookup[(vehicle->sprite_direction + 0) % 32] * 2; + peep_y -= offsetLookup[(vehicle->sprite_direction + 8) % 32] * 2; + lightfx_add_3d_light(peep_x, peep_y, peep_z + 10, LIGHTFX_LIGHT_TYPE_LANTERN_3); + peep_x -= offsetLookup[(vehicle->sprite_direction + 0) % 32] * 2; + peep_y -= offsetLookup[(vehicle->sprite_direction + 8) % 32] * 2; + lightfx_add_3d_light(peep_x, peep_y, peep_z + 2, LIGHTFX_LIGHT_TYPE_LANTERN_3); + } + else { + lightfx_add_3d_light(vehicle->x, vehicle->y, vehicle->z + 16, LIGHTFX_LIGHT_TYPE_LANTERN_2); + } + break; + case RIDE_TYPE_GHOST_TRAIN: + default: + break; + }; + }; + } + +#endif + uint32 rct2VehiclePtrFormat = ((uint32)vehicleEntry) - offsetof(rct_ride_entry, vehicles); RCT2_GLOBAL(0x00F64DFC, uint32) = rct2VehiclePtrFormat; switch (vehicleEntry->car_visual) {