1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-18 04:23:20 +01:00

Major updates to lightfx, enabling light consistency (non-duplication) and culling

This commit is contained in:
Jeroen D Stout
2016-06-04 00:40:25 +02:00
parent 1124b612e3
commit 8ad7ed3ad0
2 changed files with 255 additions and 31 deletions

View File

@@ -39,7 +39,11 @@ static uint32 _lightPolution_front = 0;
typedef struct lightlist_entry {
sint16 x, y, z;
uint8 lightType;
uint8 pad[3];
uint8 lightIntensity;
uint32 lightID;
uint16 lightIDqualifier;
uint8 lightLinger;
uint8 pad[1];
} lightlist_entry;
static lightlist_entry _LightListA[16000];
@@ -78,7 +82,7 @@ uint8 calc_light_intensity_spot(sint32 x, sint32 y) {
light *= min(1.0, max(0.0f, 2.0 - sqrt(distance) / 64));
light *= 0.5f;
return (uint8)(min(255.0, light * 255.0)) >> 3;
return (uint8)(min(255.0, light * 255.0)) >> 4;
}
void calc_rescale_light_half( uint8 *target, uint8 *source,uint32 targetWidth, uint32 targetHeight) {
@@ -140,13 +144,16 @@ void lightfx_update_buffers(rct_drawpixelinfo *info)
memcpy(&_pixelInfo, info, sizeof(rct_drawpixelinfo));
}
extern void sub_68862C();
extern void viewport_paint_setup();
void lightfx_prepare_light_list()
{
for (uint32 light = 0; light < LightListCurrentCountFront; light++) {
lightlist_entry *entry = &_LightListFront[light];
if (entry->z == 0x7FFF) {
entry->lightIntensity = 0xFF;
continue;
}
@@ -158,8 +165,189 @@ void lightfx_prepare_light_list()
rct_xy16 coord_2d = coordinate_3d_to_2d(&coord_3d, _current_view_rotation_front);
entry->x = coord_2d.x - _current_view_x_front;
entry->y = coord_2d.y - _current_view_y_front;
entry->x = coord_2d.x;// - (_current_view_x_front);
entry->y = coord_2d.y;// - (_current_view_y_front);
sint32 posOnScreenX = entry->x - _current_view_x_front;
sint32 posOnScreenY = entry->y - _current_view_y_front;
if ((posOnScreenX < -128) ||
(posOnScreenY < -128) ||
(posOnScreenX > _pixelInfo.width + 128) ||
(posOnScreenY > _pixelInfo.height + 128)) {
entry->lightIntensity = 0xFF;
continue;
}
// entry->x >>= _current_view_zoom_front;
// entry->y >>= _current_view_zoom_front;
static sint16 offsetPattern[26] = { 0, 0, -7, 0, 0, -5, 7, 0, 0, 5,
-3, -1, -1, -2, 3, 1, 1, 2,
-6, -4, -6, 4, 6, -4, 6, 4 };
int mapFrontDiv = 1 << _current_view_zoom_front;
uint32 lightIntensityOccluded = 0x0;
sint32 dirVecX = 707;
sint32 dirVecY = 707;
switch (_current_view_rotation_front) {
case 0:
dirVecX = 707;
dirVecY = 707;
break;
case 1:
dirVecX = -707;
dirVecY = 707;
break;
case 2:
dirVecX = -707;
dirVecY = -707;
break;
case 3:
dirVecX = 707;
dirVecY = -707;
break;
default:
dirVecX = 0;
dirVecY = 0;
break;
}
if (true) {
int totalSamplePoints = 1;
int lastSampleCount = 0;
for (int pat = 0; pat < totalSamplePoints; pat++) {
rct_xy16 mapCoord = { 0 };
rct_map_element *mapElement = 0;
int interactionType;
rct_window *w = window_get_main();
if (w != NULL) {
// get_map_coordinates_from_pos(entry->x + offsetPattern[pat*2] / mapFrontDiv, entry->y + offsetPattern[pat*2+1] / mapFrontDiv, VIEWPORT_INTERACTION_MASK_NONE, &mapCoord.x, &mapCoord.y, &interactionType, &mapElement, NULL);
RCT2_GLOBAL(0x9AC154, uint16_t) = VIEWPORT_INTERACTION_MASK_NONE & 0xFFFF;
RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_ZOOM, uint16_t) = _current_view_zoom_front;
RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_X, int16_t) = entry->x + offsetPattern[0 + pat * 2] / mapFrontDiv;
RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_Y, int16_t) = entry->y + offsetPattern[1 + pat * 2] / mapFrontDiv;
rct_drawpixelinfo* dpi = RCT2_ADDRESS(RCT2_ADDRESS_VIEWPORT_DPI, rct_drawpixelinfo);
dpi->x = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_X, int16_t);
dpi->y = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_Y, int16_t);
dpi->zoom_level = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_ZOOM, uint16_t);
dpi->height = 1;
dpi->width = 1;
RCT2_GLOBAL(0xEE7880, uint32_t) = 0xF1A4CC;
RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*) = dpi;
painter_setup();
viewport_paint_setup();
sub_688217();
sub_68862C();
// log_warning("[%i, %i]", dpi->x, dpi->y);
mapCoord.x = RCT2_GLOBAL(0x9AC14C, int16_t);
mapCoord.y = RCT2_GLOBAL(0x9AC14E, int16_t);
interactionType = RCT2_GLOBAL(0x9AC148, uint8_t);
mapElement = RCT2_GLOBAL(0x9AC150, rct_map_element*);
//RCT2_GLOBAL(0x9AC154, uint16_t) = VIEWPORT_INTERACTION_MASK_NONE;
//RCT2_GLOBAL(0x9AC148, uint8_t) = 0;
//RCT2_GLOBAL(0x9AC138 + 4, int16_t) = screenX;
//RCT2_GLOBAL(0x9AC138 + 6, int16_t) = screenY;
//if (screenX >= 0 && screenX < (int)myviewport->width && screenY >= 0 && screenY < (int)myviewport->height)
//{
// screenX <<= myviewport->zoom;
// screenY <<= myviewport->zoom;
// screenX += (int)myviewport->view_x;
// screenY += (int)myviewport->view_y;
// RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_ZOOM, uint16_t) = myviewport->zoom;
// screenX &= (0xFFFF << myviewport->zoom) & 0xFFFF;
// screenY &= (0xFFFF << myviewport->zoom) & 0xFFFF;
// RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_X, int16_t) = screenX;
// RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_Y, int16_t) = screenY;
// rct_drawpixelinfo* dpi = RCT2_ADDRESS(RCT2_ADDRESS_VIEWPORT_DPI, rct_drawpixelinfo);
// dpi->y = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_Y, int16_t);
// dpi->height = 1;
// dpi->zoom_level = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_ZOOM, uint16_t);
// dpi->x = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_X, int16_t);
// dpi->width = 1;
// RCT2_GLOBAL(0xEE7880, uint32_t) = 0xF1A4CC;
// RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*) = dpi;
// painter_setup();
// viewport_paint_setup();
// sub_688217();
// sub_68862C();
//}
}
sint32 minDist = 0;
sint32 baseHeight = -999;
if (interactionType != VIEWPORT_INTERACTION_ITEM_SPRITE && mapElement) {
baseHeight = mapElement->base_height;
}
minDist = ((baseHeight * 8) - coord_3d.z) / 2;
sint32 deltaX = mapCoord.x - coord_3d.x;
sint32 deltaY = mapCoord.y - coord_3d.y;
sint32 projDot = (dirVecX * deltaX + dirVecY * deltaY) / 1000;
projDot = max(minDist, projDot);
if (projDot < 5) {
lightIntensityOccluded += 100;
}
else {
lightIntensityOccluded += max(0, 200 - (projDot * 20));
}
// log_warning("light %i [%i, %i, %i], [%i, %i] minDist to %i: %i; projdot: %i", light, coord_3d.x, coord_3d.y, coord_3d.z, mapCoord.x, mapCoord.y, baseHeight, minDist, projDot);
// break;
if (pat == 0) {
if (_current_view_zoom_front > 3)
break;
totalSamplePoints += 4;
}
else if (pat == 4) {
if (_current_view_zoom_front > 2)
break;
if (lightIntensityOccluded == 0 || lightIntensityOccluded == 500)
break;
lastSampleCount = lightIntensityOccluded / 500;
// break;
totalSamplePoints += 4;
}
else if (pat == 8) {
if (_current_view_zoom_front > 1)
break;
int newSampleCount = lightIntensityOccluded / 900;
if (abs(newSampleCount - lastSampleCount) < 10)
break;
totalSamplePoints += 4;
}
}
if (lightIntensityOccluded == 0) {
entry->lightType = LIGHTFX_LIGHT_TYPE_NONE;
continue;
}
// log_warning("sample-count: %i, occlusion: %i", totalSamplePoints, lightIntensityOccluded / totalSamplePoints);
entry->lightIntensity = min(0xFF, (entry->lightIntensity * lightIntensityOccluded) / (totalSamplePoints * 100));
// log_warning("lightIntensityOccluded: %i, entry->lightIntensity: %i", lightIntensityOccluded, entry->lightIntensity);
}
if (_current_view_zoom_front > 0) {
if ((entry->lightType & 0x3) < _current_view_zoom_front) {
@@ -167,8 +355,6 @@ void lightfx_prepare_light_list()
continue;
}
entry->x >>= _current_view_zoom_front;
entry->y >>= _current_view_zoom_front;
entry->lightType -= _current_view_zoom_front;
}
}
@@ -222,7 +408,6 @@ void lightfx_render_lights_to_frontbuffer()
// log_warning("%i lights", LightListCurrentCountFront);
for (uint32 light = 0; light < LightListCurrentCountFront; light++) {
const uint8 *bufReadBase = 0;
uint8 *bufWriteBase = _light_rendered_buffer_front;
uint32 bufReadWidth, bufReadHeight;
@@ -232,6 +417,14 @@ void lightfx_render_lights_to_frontbuffer()
lightlist_entry * entry = &_LightListFront[light];
uint32 inRectCentreX = entry->x;
uint32 inRectCentreY = entry->y;
if (entry->z != 0x7FFF) {
inRectCentreX -= _current_view_x_front;
inRectCentreY -= _current_view_y_front;
}
switch (entry->lightType) {
case LIGHTFX_LIGHT_TYPE_LANTERN_0:
bufReadWidth = 32;
@@ -277,8 +470,8 @@ void lightfx_render_lights_to_frontbuffer()
continue;
}
bufWriteX = entry->x - bufReadWidth / 2;
bufWriteY = entry->y - bufReadHeight / 2;
bufWriteX = inRectCentreX - bufReadWidth / 2;
bufWriteY = inRectCentreY - bufReadHeight / 2;
bufWriteWidth = bufReadWidth;
bufWriteHeight = bufReadHeight;
@@ -326,15 +519,29 @@ void lightfx_render_lights_to_frontbuffer()
bufReadSkip = bufReadWidth - bufWriteWidth;
bufWriteSkip = _pixelInfo.width - bufWriteWidth;
for (int y = 0; y < bufWriteHeight; y++) {
for (int x = 0; x < bufWriteWidth; x++) {
*bufWriteBase = min(0xFF, *bufWriteBase + *bufReadBase);
bufWriteBase++;
bufReadBase++;
}
if (entry->lightIntensity == 0xFF) {
for (int y = 0; y < bufWriteHeight; y++) {
for (int x = 0; x < bufWriteWidth; x++) {
*bufWriteBase = min(0xFF, *bufWriteBase + *bufReadBase);
bufWriteBase++;
bufReadBase++;
}
bufWriteBase += bufWriteSkip;
bufReadBase += bufReadSkip;
bufWriteBase += bufWriteSkip;
bufReadBase += bufReadSkip;
}
}
else {
for (int y = 0; y < bufWriteHeight; y++) {
for (int x = 0; x < bufWriteWidth; x++) {
*bufWriteBase = min(0xFF, *bufWriteBase + (((*bufReadBase) * (1 + entry->lightIntensity)) >> 8));
bufWriteBase++;
bufReadBase++;
}
bufWriteBase += bufWriteSkip;
bufReadBase += bufReadSkip;
}
}
}
}
@@ -344,32 +551,45 @@ void* lightfx_get_front_buffer()
return _light_rendered_buffer_front;
}
void lightfx_add_3d_light(sint16 x, sint16 y, uint16 z, uint8 lightType)
void lightfx_add_3d_light(uint32 lightID, uint16 lightIDqualifier, sint16 x, sint16 y, uint16 z, uint8 lightType)
{
if (LightListCurrentCountBack == 15999) {
return;
}
// log_warning("%i lights in back", LightListCurrentCountBack);
for (uint32 i = 0; i < LightListCurrentCountBack; i++) {
lightlist_entry *entry = &_LightListBack[i];
if (entry->x != x)
if (entry->lightID != lightID)
continue;
if (entry->y != y)
continue;
if (entry->z != z)
continue;
if (entry->lightType != lightType)
if (entry->lightIDqualifier != lightIDqualifier)
continue;
entry->x = x;
entry->y = y;
entry->z = z;
entry->lightType = lightType;
entry->lightIntensity = 0xFF;
entry->lightID = lightID;
entry->lightIDqualifier = lightIDqualifier;
entry->lightLinger = 1;
return;
}
lightlist_entry *entry = &_LightListBack[LightListCurrentCountBack++];
entry->x = x;
entry->y = y;
entry->z = z;
entry->lightType = lightType;
entry->x = x;
entry->y = y;
entry->z = z;
entry->lightType = lightType;
entry->lightIntensity = 0xFF;
entry->lightID = lightID;
entry->lightIDqualifier = lightIDqualifier;
entry->lightLinger = 1;
// log_warning("new 3d light");
}
void lightfx_add_3d_light_magic_from_drawing_tile(sint16 offsetX, sint16 offsetY, sint16 offsetZ, uint8 lightType)
@@ -398,7 +618,7 @@ void lightfx_add_3d_light_magic_from_drawing_tile(sint16 offsetX, sint16 offsetY
return;
}
lightfx_add_3d_light(x, y, offsetZ, lightType);
lightfx_add_3d_light((x << 16) | y, offsetZ, x, y, offsetZ, lightType);
}
uint32 lightfx_get_light_polution()

View File

@@ -39,6 +39,10 @@ enum LIGHTFX_LIGHT_TYPE {
LIGHTFX_LIGHT_TYPE_RESERVED_FF = 0xFF
};
enum LIGHTFX_LIGHT_QUALIFIER {
LIGHTFX_LIGHT_QUALIFIER_VEHICLE = 0x1
};
extern void lightfx_init();
extern void lightfx_update_buffers(rct_drawpixelinfo*);
@@ -50,7 +54,7 @@ extern void lightfx_update_viewport_settings();
extern void* lightfx_get_front_buffer();
extern void lightfx_add_3d_light(sint16 x, sint16 y, uint16 z, uint8 lightType);
extern void lightfx_add_3d_light(uint32 lightID, uint16 lightIDqualifier, sint16 x, sint16 y, uint16 z, uint8 lightType);
extern void lightfx_add_3d_light_magic_from_drawing_tile(sint16 offsetX, sint16 offsetY, sint16 offsetZ, uint8 lightType);