From de81b9bf91e6f4045854ed11b4c51e7119d4aa66 Mon Sep 17 00:00:00 2001 From: Justin Kujawa Date: Wed, 19 Jul 2023 22:39:49 +0200 Subject: [PATCH] Patch 1.0.1 (Bugfixes) Added options to save and load light settings for global lights and weapon lights in the lights debug menu Added options to configure strength of headlights in the raytracing options Added an option for "smooth textures" (bilinear filtering instead of point filtering) in the raytracing options Fixed NaN values (black nanobot swarm) occurring while rendering the level Fixed crashes that sometimes occurred when loading a savegame (both quicksaves and normal saves were affected by this) Fixed the camera in the end level cutscene so now the ship leaving the mine will be shown properly Fixed the lighting in the endlevel cutscenes (most of them were completely dark) Fixed empty energy bar being visible through UI menus and elements --- .gitignore | 3 + CMakeLists.txt | 2 +- RT/Core/Config.cpp | 33 ++ RT/Core/Config.h | 2 + RT/Game/Lights.c | 366 +++++++++++++++++- RT/Game/Lights.h | 25 +- RT/RTgr.c | 304 ++++++++++++--- .../DX12/assets/shaders/direct_lighting.hlsli | 7 +- .../include_shared/shared_tweakvars.hlsl.h | 1 + .../DX12/assets/shaders/primary_ray.hlsli | 4 +- RT/Renderer/Backend/DX12/src/GlobalDX.h | 2 - .../Backend/DX12/src/RenderBackend.cpp | 19 +- .../Backend/DX12/src/ResourceTracker.cpp | 2 +- d1/assets/textures/ceil015.material | 2 - d1/main/bm.c | 1 + d1/main/endlevel.c | 40 +- d1/main/gauges.c | 5 + d1/main/lighting.c | 1 + d1/main/menu.c | 40 +- d1/main/render.c | 23 +- 20 files changed, 779 insertions(+), 103 deletions(-) delete mode 100644 d1/assets/textures/ceil015.material diff --git a/.gitignore b/.gitignore index a956413..ee6efd6 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,6 @@ tags # ctags files used with vim # I don't want to include the noise textures because they originated from the renderer's assets which are kept # elsewhere. d1/assets/textures/noise + +# make sure to include DXC dlls +!RT/Renderer/Backend/DX12/DXC/bin/* diff --git a/CMakeLists.txt b/CMakeLists.txt index d780d3f..4b03ca0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ D1X_RAYTRACER_NAME="D1X_RAYTRACER" D1X_RAYTRACER_VERSION_MAJORi=1 D1X_RAYTRACER_VERSION_MINORi=0 -D1X_RAYTRACER_VERSION_MICROi=0 +D1X_RAYTRACER_VERSION_MICROi=1 #DXX-Retro last used version DXX_VERSION_MAJORi=0 diff --git a/RT/Core/Config.cpp b/RT/Core/Config.cpp index a54f899..75b320f 100644 --- a/RT/Core/Config.cpp +++ b/RT/Core/Config.cpp @@ -202,6 +202,32 @@ bool RT_ConfigReadInt(RT_Config *cfg, RT_String key, int *value) return result; } +bool RT_ConfigReadVec2(RT_Config *cfg, RT_String key, RT_Vec2 *value) +{ + bool result = false; + + RT_String string; + if (RT_ConfigReadString(cfg, key, &string)) + { + RT_ParseFloatResult parse_x = RT_ParseFloat(string); + string = RT_StringAdvance(string, parse_x.advance); + string = RT_StringAdvance(string, RT_StringFindChar(string, ',') + 1); + string = RT_StringAdvance(string, RT_StringFindFirstNonWhitespace(string)); + RT_ParseFloatResult parse_y = RT_ParseFloat(string); + + result = (parse_x.success && + parse_y.success); + + if (result) + { + value->x = parse_x.value; + value->y = parse_y.value; + } + } + + return result; +} + bool RT_ConfigReadVec3(RT_Config *cfg, RT_String key, RT_Vec3 *value) { bool result = false; @@ -264,6 +290,13 @@ void RT_ConfigWriteInt(RT_Config *cfg, RT_String key, int value) cfg->last_modified_time = RT_GetHighResTime().value; } +void RT_ConfigWriteVec2(RT_Config *cfg, RT_String key, RT_Vec2 value) +{ + RT_ConfigKeyValue *kv = RT_ConfigFindOrCreateKeyValue(cfg, key); + kv->value_count = snprintf(kv->value, sizeof(kv->value), "%f, %f", value.x, value.y); + cfg->last_modified_time = RT_GetHighResTime().value; +} + void RT_ConfigWriteVec3(RT_Config *cfg, RT_String key, RT_Vec3 value) { RT_ConfigKeyValue *kv = RT_ConfigFindOrCreateKeyValue(cfg, key); diff --git a/RT/Core/Config.h b/RT/Core/Config.h index 72d67f4..ebde5b8 100644 --- a/RT/Core/Config.h +++ b/RT/Core/Config.h @@ -40,10 +40,12 @@ RT_API void RT_DeserializeConfigFromString(RT_Config *cfg, RT_String string); RT_API bool RT_ConfigReadString(RT_Config *cfg, RT_String key, RT_String *value); RT_API bool RT_ConfigReadFloat(RT_Config *cfg, RT_String key, float *value); RT_API bool RT_ConfigReadInt(RT_Config *cfg, RT_String key, int *value); +RT_API bool RT_ConfigReadVec2(RT_Config *cfg, RT_String key, RT_Vec2 *value); RT_API bool RT_ConfigReadVec3(RT_Config *cfg, RT_String key, RT_Vec3 *value); RT_API void RT_ConfigWriteString(RT_Config *cfg, RT_String key, RT_String value); RT_API void RT_ConfigWriteFloat(RT_Config *cfg, RT_String key, float value); RT_API void RT_ConfigWriteInt(RT_Config *cfg, RT_String key, int value); +RT_API void RT_ConfigWriteVec2(RT_Config *cfg, RT_String key, RT_Vec2 value); RT_API void RT_ConfigWriteVec3(RT_Config *cfg, RT_String key, RT_Vec3 value); RT_API bool RT_ConfigEraseKey(RT_Config *cfg, RT_String key); // Returns true if the key existed RT_API RT_String RT_SerializeConfigToString(RT_Arena *arena, RT_Config *cfg); diff --git a/RT/Game/Lights.c b/RT/Game/Lights.c index 76c6a9f..64f2f8c 100644 --- a/RT/Game/Lights.c +++ b/RT/Game/Lights.c @@ -1,15 +1,56 @@ +#include "physfs.h" + #include "Lights.h" #include "textures.h" -#include "Core/Arena.h" #include "dx12.h" #include "gr.h" #include "RTgr.h" #include "RTmaterials.h" +#include "Core/Arena.h" +#include "Core/Config.h" +#include "Core/String.h" + float g_light_multiplier = 1.0; float g_light_multiplier_default = 1.0; const float FLT_MAX = 3.402823466e+38F; +typedef struct RT_SettingsNotification +{ + float timer; + ImVec4 color; + char *message; +} RT_SettingsNotification; + +static inline void RT_SetSettingsNotification(RT_SettingsNotification *notif, char *name, ImVec4 color) +{ + notif->timer = 2.0f; + notif->color = color; + notif->message = name; +} + +static inline void RT_ShowSettingsNotification(RT_SettingsNotification *notif) +{ + if (notif->timer > 0.0f) + { + ImVec4 color = notif->color; + color.w = notif->timer / 2.0f; + + igPushStyleColor_Vec4(ImGuiCol_Text, color); + igText(notif->message); + igPopStyleColor(1); + + notif->timer -= 1.0f / 60.0f; // hardcoded nonsense + } + else + { + igDummy((ImVec2){0.0f, igGetFontSize()}); + } +} + +static RT_SettingsNotification g_lights_notification; +static RT_SettingsNotification g_headlights_notification; + RT_LightDefinition g_light_definitions[] = { // White light fixtures @@ -152,6 +193,41 @@ RT_LightDefinition g_light_definitions[] = }, }; +static RT_LightDefinition g_default_light_definitions[RT_ARRAY_COUNT(g_light_definitions)]; + +static RT_HeadlightSettings g_default_headlights = { + .pos_offset_horz = 3.0f, + .pos_offset_vert = -2.0f, + .skew_horz = 0.1f, + .skew_vert = 0.06f, + .radius = 0.05f, + .brightness = 1.5f, + .spot_angle = 0.05f, + .spot_softness = 0.05f, +}; + +void RT_InitLightStuff() +{ + memcpy(&g_headlights, &g_default_headlights, sizeof(g_headlights)); + memcpy(g_default_light_definitions, g_light_definitions, sizeof(g_default_light_definitions)); + + RT_LoadLightSettings(); + g_lights_notification.timer = 0.0f; + + RT_LoadHeadLightSettings(); + g_headlights_notification.timer = 0.0f; +} + +void RT_ResetLightSettings() +{ + g_light_multiplier_default = g_light_multiplier = 1.0f; + + memcpy(g_light_definitions, g_default_light_definitions, sizeof(g_default_light_definitions)); + g_pending_light_update = true; + + RT_SetSettingsNotification(&g_lights_notification, "Reset Light Settings", (ImVec4){0.5f, 0.7f, 1.0f, 1.0f}); +} + int RT_IsLight(int tmap) { //TODO: If this starts to become a performance bottleneck, add a hashmap so the lookups can be done in O(1) @@ -228,8 +304,69 @@ RT_Light RT_InitLight(RT_LightDefinition definition, RT_Vertex* vertices, RT_Vec void RT_ShowLightMenu() { - igBegin("Light Explorer", false, ImGuiWindowFlags_AlwaysAutoResize); - if(igSliderFloat("Global brightness: ", &g_light_multiplier_default, 0.000001f, 15.0f, "%f", ImGuiSliderFlags_Logarithmic)){ + igBegin("Light Explorer", NULL, ImGuiWindowFlags_AlwaysAutoResize); + + igText("Headlights"); + igPushID_Str("Headlights"); + { + if (igButton("Load Settings", (ImVec2){0, 0})) + { + RT_LoadHeadLightSettings(); + } + + igSameLine(0.0f, -1.0f); + + if (igButton("Save Settings", (ImVec2){0, 0})) + { + RT_SaveHeadLightSettings(); + } + + igSameLine(0.0f, -1.0f); + + if (igButton("Reset Settings", (ImVec2){0, 0})) + { + RT_ResetHeadLightSettings(); + } + + RT_ShowSettingsNotification(&g_headlights_notification); + + RT_HeadlightSettings *h = &g_headlights; + igSliderFloat("Horizontal Position Offset", &h->pos_offset_horz, 0.0f, 15.0f, "%.02f", 0); + igSliderFloat("Vertical Position Offset", &h->pos_offset_vert, -5.0f, 5.0f, "%.02f", 0); + igSliderFloat("Horizontal Skew", &h->skew_horz, 0.0f, 0.4f, "%.02f", 0); + igSliderFloat("Vertical Skew", &h->skew_vert, -0.2f, 0.2f, "%.02f", 0); + igSliderFloat("Light Radius", &h->radius, 0.01f, 0.4f, "%.02f", 0); + igSliderFloat("Brightness", &h->brightness, 0.0f, 5.0f, "%.02f", 0); + igSliderFloat("Spot Angle", &h->spot_angle, 0.01f, 0.12f, "%.02f", 0); + igSliderFloat("Spot Softness", &h->spot_softness, 0.01f, 0.12f, "%.02f", 0); + igDummy((ImVec2){0.0f, igGetFontSize()}); + } + igPopID(1); + + igText("Level Lights"); + + if (igButton("Load Settings", (ImVec2){0, 0})) + { + RT_LoadLightSettings(); + } + + igSameLine(0.0f, -1.0f); + + if (igButton("Save Settings", (ImVec2){0, 0})) + { + RT_SaveLightSettings(); + } + + igSameLine(0.0f, -1.0f); + + if (igButton("Reset Settings", (ImVec2){0, 0})) + { + RT_ResetLightSettings(); + } + + RT_ShowSettingsNotification(&g_lights_notification); + + if (igSliderFloat("Global brightness", &g_light_multiplier_default, 0.000001f, 15.0f, "%f", ImGuiSliderFlags_Logarithmic)) { g_light_multiplier = g_light_multiplier_default; g_pending_light_update = true; } @@ -321,4 +458,225 @@ void RT_VisualizeLight(RT_Light* light) RT_RasterLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Make(0.0,0.0,-scale.z)), RT_Vec4Make(1.0, 0.0, 0.0, 1.0)); break; } -} \ No newline at end of file +} + +void RT_LoadLightSettings() +{ + PHYSFS_mkdir("lights"); + + bool success = true; + + // ------------------------------------------------------------------ + // Read global light settings + + RT_ArenaMemoryScope(&g_thread_arena) + { + RT_Config *cfg = RT_ArenaAllocStruct(&g_thread_arena, RT_Config); + RT_InitializeConfig(cfg, &g_thread_arena); + + if (RT_DeserializeConfigFromFile(cfg, "lights/global_lights.vars")) + { + RT_ConfigReadFloat(cfg, RT_StringLiteral("global_light_multiplier"), &g_light_multiplier_default); + g_light_multiplier = g_light_multiplier_default; + } + else + { + success = false; + } + } + + // ------------------------------------------------------------------ + // Read all da rest + + for (size_t light_index = 0; light_index < RT_ARRAY_COUNT(g_light_definitions); light_index++) + { + RT_ArenaMemoryScope(&g_thread_arena) + { + RT_LightDefinition *def = &g_light_definitions[light_index]; + + RT_Config *cfg = RT_ArenaAllocStruct(&g_thread_arena, RT_Config); + RT_InitializeConfig(cfg, &g_thread_arena); + + char *file_name = RT_ArenaPrintF(&g_thread_arena, "lights/%s.vars", def->name); + if (RT_DeserializeConfigFromFile(cfg, file_name)) + { + RT_ConfigReadInt(cfg, RT_StringLiteral("kind"), &def->kind); + RT_ConfigReadVec3(cfg, RT_StringLiteral("emission"), &def->emission); + RT_ConfigReadFloat(cfg, RT_StringLiteral("radius"), &def->radius); + RT_ConfigReadVec2(cfg, RT_StringLiteral("size"), &def->size); + RT_ConfigReadFloat(cfg, RT_StringLiteral("spot_angle"), &def->spot_angle); + RT_ConfigReadFloat(cfg, RT_StringLiteral("spot_softness"), &def->spot_softness); + } + else + { + success = false; + } + } + } + + if (success) + { + RT_SetSettingsNotification(&g_lights_notification, "Successfully Loaded Light Settings", (ImVec4){0.5f, 1.0f, 0.7f, 1.0f}); + } + else + { + RT_SetSettingsNotification(&g_lights_notification, "Encountered Problems Loading Light Settings!", (ImVec4){1.0f, 0.2f, 0.2f, 1.0f}); + } + + g_pending_light_update = true; +} + +void RT_SaveLightSettings() +{ + PHYSFS_mkdir("lights"); + + bool success = true; + + // ------------------------------------------------------------------ + // Write global light settings + + RT_ArenaMemoryScope(&g_thread_arena) + { + RT_Config *cfg = RT_ArenaAllocStruct(&g_thread_arena, RT_Config); + RT_InitializeConfig(cfg, &g_thread_arena); + + RT_ConfigWriteFloat(cfg, RT_StringLiteral("global_light_multiplier"), g_light_multiplier_default); + + if (!RT_SerializeConfigToFile(cfg, "lights/global_lights.vars")) + { + success = false; + + RT_LOG(RT_LOGSERVERITY_HIGH, "Failed to serialize global_lights.vars:\n"); + for (RT_StringNode *error = cfg->first_error; error; error = error->next) + { + RT_LOGF(RT_LOGSERVERITY_HIGH, " > %.*s\n", RT_ExpandString(error->string)); + } + } + } + + // ------------------------------------------------------------------ + // Write all da rest + + for (size_t light_index = 0; light_index < RT_ARRAY_COUNT(g_light_definitions); light_index++) + { + RT_ArenaMemoryScope(&g_thread_arena) + { + RT_LightDefinition *def = &g_light_definitions[light_index]; + + RT_Config *cfg = RT_ArenaAllocStruct(&g_thread_arena, RT_Config); + RT_InitializeConfig(cfg, &g_thread_arena); + + RT_ConfigWriteInt(cfg, RT_StringLiteral("kind"), def->kind); + RT_ConfigWriteVec3(cfg, RT_StringLiteral("emission"), def->emission); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("radius"), def->radius); + RT_ConfigWriteVec2(cfg, RT_StringLiteral("size"), def->size); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("spot_angle"), def->spot_angle); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("spot_softness"), def->spot_softness); + + char *file_name = RT_ArenaPrintF(&g_thread_arena, "lights/%s.vars", def->name); + if (!RT_SerializeConfigToFile(cfg, file_name)) + { + success = false; + + RT_LOG(RT_LOGSERVERITY_HIGH, "Failed to serialize %s:\n", file_name); + for (RT_StringNode *error = cfg->first_error; error; error = error->next) + { + RT_LOGF(RT_LOGSERVERITY_HIGH, " > %.*s\n", RT_ExpandString(error->string)); + } + } + } + } + + if (success) + { + RT_SetSettingsNotification(&g_lights_notification, "Successfully Saved Light Settings", (ImVec4){0.7f, 1.0f, 0.5f, 1.0f}); + } + else + { + RT_SetSettingsNotification(&g_lights_notification, "Encountered Problems Saving Light Settings!", (ImVec4){1.0f, 0.2f, 0.2f, 1.0f}); + } +} + +void RT_ResetHeadLightSettings() +{ + memcpy(&g_headlights, &g_default_headlights, sizeof(g_headlights)); + RT_SetSettingsNotification(&g_headlights_notification, "Reset Headlight Settings", (ImVec4){0.5f, 0.7f, 1.0f, 1.0f}); +} + +void RT_LoadHeadLightSettings(void) +{ + bool success = true; + + RT_ArenaMemoryScope(&g_thread_arena) + { + RT_Config *cfg = RT_ArenaAllocStruct(&g_thread_arena, RT_Config); + RT_InitializeConfig(cfg, &g_thread_arena); + + if (RT_DeserializeConfigFromFile(cfg, "lights/headlights.vars")) + { + RT_ConfigReadFloat(cfg, RT_StringLiteral("pos_offset_horz"), &g_headlights.pos_offset_horz); + RT_ConfigReadFloat(cfg, RT_StringLiteral("pos_offset_vert"), &g_headlights.pos_offset_vert); + RT_ConfigReadFloat(cfg, RT_StringLiteral("skew_horz"), &g_headlights.skew_horz); + RT_ConfigReadFloat(cfg, RT_StringLiteral("skew_vert"), &g_headlights.skew_vert); + RT_ConfigReadFloat(cfg, RT_StringLiteral("radius"), &g_headlights.radius); + RT_ConfigReadFloat(cfg, RT_StringLiteral("brightness"), &g_headlights.brightness); + RT_ConfigReadFloat(cfg, RT_StringLiteral("spot_angle"), &g_headlights.spot_angle); + RT_ConfigReadFloat(cfg, RT_StringLiteral("spot_softness"), &g_headlights.spot_softness); + } + else + { + success = false; + } + } + + if (success) + { + RT_SetSettingsNotification(&g_headlights_notification, "Successfully Loaded Headlight Settings", (ImVec4){0.5f, 1.0f, 0.7f, 1.0f}); + } + else + { + RT_SetSettingsNotification(&g_headlights_notification, "Encountered Problems Loading Headlight Settings!", (ImVec4){1.0f, 0.2f, 0.2f, 1.0f}); + } +} + +void RT_SaveHeadLightSettings(void) +{ + PHYSFS_mkdir("lights"); + + bool success = true; + + RT_ArenaMemoryScope(&g_thread_arena) + { + RT_Config *cfg = RT_ArenaAllocStruct(&g_thread_arena, RT_Config); + RT_InitializeConfig(cfg, &g_thread_arena); + + RT_ConfigWriteFloat(cfg, RT_StringLiteral("pos_offset_horz"), g_headlights.pos_offset_horz); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("pos_offset_vert"), g_headlights.pos_offset_vert); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("skew_horz"), g_headlights.skew_horz); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("skew_vert"), g_headlights.skew_vert); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("radius"), g_headlights.radius); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("brightness"), g_headlights.brightness); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("spot_angle"), g_headlights.spot_angle); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("spot_softness"), g_headlights.spot_softness); + + if (!RT_SerializeConfigToFile(cfg, "lights/headlights.vars")) + { + success = false; + + RT_LOG(RT_LOGSERVERITY_HIGH, "Failed to serialize global_lights.vars:\n"); + for (RT_StringNode *error = cfg->first_error; error; error = error->next) + { + RT_LOGF(RT_LOGSERVERITY_HIGH, " > %.*s\n", RT_ExpandString(error->string)); + } + } + } + + if (success) + { + RT_SetSettingsNotification(&g_headlights_notification, "Successfully Saved Headlight Settings", (ImVec4){0.7f, 1.0f, 0.5f, 1.0f}); + } + else + { + RT_SetSettingsNotification(&g_headlights_notification, "Encountered Problems Saving Headlight Settings!", (ImVec4){1.0f, 0.2f, 0.2f, 1.0f}); + } +} diff --git a/RT/Game/Lights.h b/RT/Game/Lights.h index 7dff805..9bb6ecb 100644 --- a/RT/Game/Lights.h +++ b/RT/Game/Lights.h @@ -15,10 +15,22 @@ float g_light_multiplier; // Default light multiplier (not changed during runtime) float g_light_multiplier_default; +typedef struct RT_HeadlightSettings +{ + float pos_offset_horz; + float pos_offset_vert; + float skew_horz; + float skew_vert; + float radius; + float brightness; + float spot_angle; + float spot_softness; +} RT_HeadlightSettings; + +RT_HeadlightSettings g_headlights; + typedef struct RT_LightDefinition { - // TODO(daniel): These would ideally not be parameterized by the tmap index. - // GameBitmap indices are the canonical indices for the _actual_ textures/bitmaps/materials. const char* name; RT_LightKind kind; RT_Vec3 emission; @@ -30,10 +42,17 @@ typedef struct RT_LightDefinition extern RT_LightDefinition g_light_definitions[]; +void RT_InitLightStuff(void); +void RT_ResetLightSettings(void); // Returns g_light_definition index if light, otherwise -1. int RT_IsLight(int tmap); RT_Light RT_InitLight(RT_LightDefinition definition, RT_Vertex* vertices, RT_Vec3 normal); -void RT_ShowLightMenu(); +void RT_ShowLightMenu(void); void RT_VisualizeLight(RT_Light* light); +void RT_LoadLightSettings(void); +void RT_SaveLightSettings(void); +void RT_ResetHeadLightSettings(void); +void RT_LoadHeadLightSettings(void); +void RT_SaveHeadLightSettings(void); #endif \ No newline at end of file diff --git a/RT/RTgr.c b/RT/RTgr.c index da30703..3d2526d 100644 --- a/RT/RTgr.c +++ b/RT/RTgr.c @@ -61,6 +61,7 @@ CockpitSettings g_rt_cockpit_settings = { .back_cockpit_offset = {0.000f, -0.760f, -2.488f}, .back_cockpit_scale = {1.000f, 1.000f, 1.000f}, }; + RT_GLTFNode* g_rt_cockpit_gltf; RT_FreeCamInfo g_rt_free_cam_info = { 0 }; int light_culling_heuristic = 1; @@ -68,6 +69,9 @@ int max_rec_depth = 32; float max_distance = 600; float max_seg_distance = 500; +static RT_DynamicLightInfo g_rt_default_dynamic_light_info; +static RT_WeaponLightAdjusts g_rt_default_light_adjusts[RT_LIGHT_ADJUST_ARRAY_SIZE]; + uint64_t g_rt_frame_index; // #define RT_DUMP_GAME_BITMAPS @@ -206,7 +210,7 @@ int gr_set_mode(u_int32_t mode) bool g3_draw_bitmap_full(vms_vector* pos, fix width, fix height, grs_bitmap* bm, float r, float g, float b) { // NOTE(daniel): Unfortunate! - uint16_t material_index = ((uintptr_t)bm - (uintptr_t)GameBitmaps) / sizeof(grs_bitmap); + uint16_t material_index = (uint16_t)(bm - GameBitmaps); RT_Vec2 rt_dim = { f2fl(width), f2fl(height) }; RT_Vec3 rt_pos = RT_Vec3Fromvms_vector(pos); @@ -388,6 +392,51 @@ void draw_tmap_flat(grs_bitmap* bm, int nv, g3s_point** vertlist) RT_LOG(RT_LOGSERVERITY_HIGH, "draw_tmap_flat: unhandled"); } +// +// NOTE(daniel): Duplicated from Lights.c +// + +typedef struct RT_SettingsNotification +{ + float timer; + ImVec4 color; + char *message; +} RT_SettingsNotification; + +static inline void RT_SetSettingsNotification(RT_SettingsNotification *notif, char *name, ImVec4 color) +{ + notif->timer = 2.0f; + notif->color = color; + notif->message = name; +} + +static inline void RT_ShowSettingsNotification(RT_SettingsNotification *notif) +{ + if (notif->timer > 0.0f) + { + ImVec4 color = notif->color; + color.w = notif->timer / 2.0f; + + igPushStyleColor_Vec4(ImGuiCol_Text, color); + igText(notif->message); + igPopStyleColor(1); + + notif->timer -= 1.0f / 60.0f; // hardcoded nonsense + } + else + { + igDummy((ImVec2){0.0f, igGetFontSize()}); + } +} + +// + +static RT_SettingsNotification g_dynamic_lights_notification; + +static void RT_LoadDynamicLightSettings(void); +static void RT_SaveDynamicLightSettings(void); +static void RT_ResetDynamicLightSettings(void); + int gr_init(int mode) { SDL_WM_SetCaption(DESCENT_VERSION, "Descent"); @@ -448,6 +497,13 @@ int gr_init(int mode) RT_ConfigReadFloat(RT_GetRendererIO()->config, RT_StringLiteral("fov"), &fov); g_cam.vfov = g_free_cam.vfov = fov; + // Awkward place to do this, but I need to do it somewhere + memcpy(&g_rt_default_dynamic_light_info, &g_rt_dynamic_light_info, sizeof(g_rt_dynamic_light_info)); + memcpy(g_rt_default_light_adjusts, rt_light_adjusts, sizeof(RT_WeaponLightAdjusts)*RT_LIGHT_ADJUST_ARRAY_SIZE); + + RT_LoadDynamicLightSettings(); + g_dynamic_lights_notification.timer = 0.0f; + return 0; } @@ -1093,6 +1149,208 @@ void RT_ResetLightEmission() RT_UpdateMaterial(lightTexture, material); } +static void RT_DoDynamicLightEditorMenus(void) +{ + if (igBegin("Dynamic Light Editor", NULL, 0)) + { + igPushID_Str("Dynamic Lights"); + + if (igButton("Load Settings", (ImVec2){0, 0})) + { + RT_LoadDynamicLightSettings(); + } + + igSameLine(0.0f, -1.0f); + + if (igButton("Save Settings", (ImVec2){0, 0})) + { + RT_SaveDynamicLightSettings(); + } + + igSameLine(0.0f, -1.0f); + + if (igButton("Reset Settings", (ImVec2){0, 0})) + { + RT_ResetDynamicLightSettings(); + } + + RT_ShowSettingsNotification(&g_dynamic_lights_notification); + + igSeparator(); + igText("Weapon Lights"); + igSeparator(); + + igPushID_Int(2); + igCheckbox("Enable Weapon and flare lights", &g_rt_dynamic_light_info.weaponFlareLights); + igSliderFloat("Weapon Brightness modifier", &g_rt_dynamic_light_info.weaponBrightMod, 0, 1000.f, "%.3f", 0); + igSliderFloat("Radius modifier", &g_rt_dynamic_light_info.weaponRadiusMod, 0, 4.f, "%.3f", 0); + for (size_t i = 0; i < RT_LIGHT_ADJUST_ARRAY_SIZE; i++) + { + RT_WeaponLightAdjusts* adj = &rt_light_adjusts[i]; + if (igTreeNode_Str(adj->weapon_name)) + { + igSliderFloat("Brightness", &adj->brightMul, 0, 100.f, "%.3f", 0); + igSliderFloat("Radius", &adj->radiusMul, 0, 10.f, "%.3f", 0); + igTreePop(); + } + } + igPopID(); + + igDummy((ImVec2){0.0f, igGetFontSize()}); + + igSeparator(); + igText("Explosion Lights"); + igSeparator(); + + igPushID_Int(3); + igCheckbox("Enable explosion lights", &g_rt_dynamic_light_info.explosionLights); + igSliderFloat("Brightness modifier", &g_rt_dynamic_light_info.explosionBrightMod, 0, 1000.f, "%.3f", 0); + igSliderFloat("Radius modifier", &g_rt_dynamic_light_info.explosionRadiusMod, 0, 4.f, "%.3f", 0); + igSliderFloat("Type bias modifier", &g_rt_dynamic_light_info.explosionTypeBias, 0.10f, 10.f, "%.3f", 0); + igPopID(); + + igDummy((ImVec2){0.0f, igGetFontSize()}); + + igSeparator(); + igText("Muzzle Flare Lights"); + igSeparator(); + + igPushID_Int(4); + igCheckbox("Enable muzzle flare lights", &g_rt_dynamic_light_info.muzzleLights); + igSliderFloat("Brightness modifier", &g_rt_dynamic_light_info.muzzleBrightMod, 0, 1000.f, "%.3f", 0); + igSliderFloat("Radius modifier", &g_rt_dynamic_light_info.muzzleRadiusMod, 0, 4.f, "%.3f", 0); + igPopID(); + + igPopID(); + } igEnd(); +} + +// Bad thing ahead: +static RT_String RT_FormatString(RT_Arena *arena, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + const char *formatted = RT_ArenaPrintF(arena, fmt, args); + + va_end(args); + + RT_String result = + { + .bytes = formatted, + .count = strlen(formatted), // <--- specifically, this is the bad thing. + }; + + return result; +} + +void RT_LoadDynamicLightSettings(void) +{ + bool success = true; + + RT_DynamicLightInfo *info = &g_rt_dynamic_light_info; + + RT_ArenaMemoryScope(&g_thread_arena) + { + RT_Config *cfg = RT_ArenaAllocStruct(&g_thread_arena, RT_Config); + RT_InitializeConfig(cfg, &g_thread_arena); + + if (RT_DeserializeConfigFromFile(cfg, "lights/dynamic_lights.vars")) + { + RT_ConfigReadInt(cfg, RT_StringLiteral("weapon_flare_lights"), &info->weaponFlareLights); + RT_ConfigReadFloat(cfg, RT_StringLiteral("weapon_brightness"), &info->weaponBrightMod); + RT_ConfigReadFloat(cfg, RT_StringLiteral("weapon_radius"), &info->weaponRadiusMod); + + for (size_t i = 0; i < RT_LIGHT_ADJUST_ARRAY_SIZE; i++) + { + RT_WeaponLightAdjusts *adj = &rt_light_adjusts[i]; + + RT_ConfigReadFloat(cfg, RT_FormatString(&g_thread_arena, "%s_brightness", adj->weapon_name), &adj->brightMul); + RT_ConfigReadFloat(cfg, RT_FormatString(&g_thread_arena, "%s_radius", adj->weapon_name), &adj->radiusMul); + } + + RT_ConfigReadInt(cfg, RT_StringLiteral("explosion_lights"), &info->explosionLights); + RT_ConfigReadFloat(cfg, RT_StringLiteral("explosion_brightness"), &info->explosionBrightMod); + RT_ConfigReadFloat(cfg, RT_StringLiteral("explosion_radius"), &info->explosionRadiusMod); + RT_ConfigReadFloat(cfg, RT_StringLiteral("explosion_type_bias"), &info->explosionTypeBias); + + RT_ConfigReadInt(cfg, RT_StringLiteral("muzzle_lights"), &info->muzzleLights); + RT_ConfigReadFloat(cfg, RT_StringLiteral("muzzle_brightness"), &info->muzzleBrightMod); + RT_ConfigReadFloat(cfg, RT_StringLiteral("muzzle_radius"), &info->muzzleRadiusMod); + } + else + { + success = false; + } + } + + if (success) + { + RT_SetSettingsNotification(&g_dynamic_lights_notification, "Successfully loaded dynamic light settings", (ImVec4){0.5f, 1.0f, 0.7f, 1.0f}); + } + else + { + RT_SetSettingsNotification(&g_dynamic_lights_notification, "Nothing to load!", (ImVec4){1.0f, 0.2f, 0.2f, 1.0f}); + } +} + +void RT_SaveDynamicLightSettings(void) +{ + PHYSFS_mkdir("lights"); + + bool success = true; + + RT_DynamicLightInfo *info = &g_rt_dynamic_light_info; + + RT_ArenaMemoryScope(&g_thread_arena) + { + RT_Config *cfg = RT_ArenaAllocStruct(&g_thread_arena, RT_Config); + RT_InitializeConfig(cfg, &g_thread_arena); + + RT_ConfigWriteInt(cfg, RT_StringLiteral("weapon_flare_lights"), info->weaponFlareLights); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("weapon_brightness"), info->weaponBrightMod); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("weapon_radius"), info->weaponRadiusMod); + + for (size_t i = 0; i < RT_LIGHT_ADJUST_ARRAY_SIZE; i++) + { + RT_WeaponLightAdjusts *adj = &rt_light_adjusts[i]; + + RT_ConfigWriteFloat(cfg, RT_FormatString(&g_thread_arena, "%s_brightness", adj->weapon_name), adj->brightMul); + RT_ConfigWriteFloat(cfg, RT_FormatString(&g_thread_arena, "%s_radius", adj->weapon_name), adj->radiusMul); + } + + RT_ConfigWriteInt(cfg, RT_StringLiteral("explosion_lights"), info->explosionLights); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("explosion_brightness"), info->explosionBrightMod); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("explosion_radius"), info->explosionRadiusMod); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("explosion_type_bias"), info->explosionTypeBias); + + RT_ConfigWriteInt(cfg, RT_StringLiteral("muzzle_lights"), info->muzzleLights); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("muzzle_brightness"), info->muzzleBrightMod); + RT_ConfigWriteFloat(cfg, RT_StringLiteral("muzzle_radius"), info->muzzleRadiusMod); + + if (!RT_SerializeConfigToFile(cfg, "lights/dynamic_lights.vars")) + { + success = false; + } + } + + if (success) + { + RT_SetSettingsNotification(&g_dynamic_lights_notification, "Successfully saved dynamic light settings", (ImVec4){0.7f, 1.0f, 0.5f, 1.0f}); + } + else + { + RT_SetSettingsNotification(&g_dynamic_lights_notification, "Encountered problems saving dynamic light settings!", (ImVec4){1.0f, 0.2f, 0.2f, 1.0f}); + } +} + +void RT_ResetDynamicLightSettings(void) +{ + memcpy(&g_rt_dynamic_light_info, &g_rt_default_dynamic_light_info, sizeof(g_rt_dynamic_light_info)); + memcpy(rt_light_adjusts, g_rt_default_light_adjusts, sizeof(RT_WeaponLightAdjusts)*RT_LIGHT_ADJUST_ARRAY_SIZE); + RT_SetSettingsNotification(&g_dynamic_lights_notification, "Reset dynamic light settings", (ImVec4){0.5f, 0.7f, 1.0f, 1.0f}); +} + void RT_StartImGuiFrame(void) { igStartFrameWin32(); @@ -1137,17 +1395,11 @@ void RT_StartImGuiFrame(void) value_changed |= igDragFloat3("Rear View Offset", &g_rt_cockpit_settings.back_cockpit_offset, 0.001f, -10.0, 10.0, "%.3f", ImGuiTreeNodeFlags_None); value_changed |= igDragFloat3("Rear View Scale", &g_rt_cockpit_settings.back_cockpit_scale, 0.001f, -10.0, 10.0, "%.3f", ImGuiTreeNodeFlags_None); -#ifndef RT_StringLiteral -#define RT_StringLiteral(x) (RT_String){x, sizeof(x)-1} -#endif igPopID(); } igEnd(); if (igBegin("Ingame Tools", NULL, 0)) { - igPushID_Str("Dynamic Lights"); - igIndent(0); - if (igCollapsingHeader_TreeNodeFlags("Light Culling", ImGuiTreeNodeFlags_None)) { igPushID_Int(1); igSliderInt("Light Culling Heuristic", &light_culling_heuristic, 0, 1, "%i", 0); @@ -1157,41 +1409,6 @@ void RT_StartImGuiFrame(void) igPopID(); } - if (igCollapsingHeader_TreeNodeFlags("Weapon Light Settings", ImGuiTreeNodeFlags_None)) - { - igPushID_Int(2); - igCheckbox("Enable Weapon and flare lights", &g_rt_dynamic_light_info.weaponFlareLights); - igSliderFloat("Weapon Brightness modifier", &g_rt_dynamic_light_info.weaponBrightMod, 0, 1000.f, "%.3f", 0); - igSliderFloat("Radius modifier", &g_rt_dynamic_light_info.weaponRadiusMod, 0, 4.f, "%.3f", 0); - for (size_t i = 0; i < RT_LIGHT_ADJUST_ARRAY_SIZE; i++) - { - RT_WeaponLightAdjusts* adj = &rt_light_adjusts[i]; - if (igTreeNode_Str(adj->weapon_name)) - { - igSliderFloat("Brightness", &adj->brightMul, 0, 100.f, "%.3f", 0); - igSliderFloat("Radius", &adj->radiusMul, 0, 10.f, "%.3f", 0); - igTreePop(); - } - } - igPopID(); - } - if (igCollapsingHeader_TreeNodeFlags("Explosion Light Settings", ImGuiTreeNodeFlags_None)) - { - igPushID_Int(3); - igCheckbox("Enable explosion lights", &g_rt_dynamic_light_info.explosionLights); - igSliderFloat("Brightness modifier", &g_rt_dynamic_light_info.explosionBrightMod, 0, 1000.f, "%.3f", 0); - igSliderFloat("Radius modifier", &g_rt_dynamic_light_info.explosionRadiusMod, 0, 4.f, "%.3f", 0); - igSliderFloat("Type bias modifier", &g_rt_dynamic_light_info.explosionTypeBias, 0.10f, 10.f, "%.3f", 0); - igPopID(); - } - if (igCollapsingHeader_TreeNodeFlags("Muzzle fire Light Settings", ImGuiTreeNodeFlags_None)) - { - igPushID_Int(4); - igCheckbox("Enable muzzle flare lights", &g_rt_dynamic_light_info.muzzleLights); - igSliderFloat("Brightness modifier", &g_rt_dynamic_light_info.muzzleBrightMod, 0, 1000.f, "%.3f", 0); - igSliderFloat("Radius modifier", &g_rt_dynamic_light_info.muzzleRadiusMod, 0, 4.f, "%.3f", 0); - igPopID(); - } if (igCollapsingHeader_TreeNodeFlags("Miscellaneous", ImGuiTreeNodeFlags_None)) { igPushID_Str("Miscellaneous"); @@ -1208,10 +1425,9 @@ void RT_StartImGuiFrame(void) igCheckbox("Enable free cam clipping", &g_rt_free_cam_info.g_free_cam_clipping_enabled); } - igPopID(); - igUnindent(0); } igEnd(); + RT_DoDynamicLightEditorMenus(); RT_ShowLightMenu(); RT_DoPolymodelViewerMenus(); diff --git a/RT/Renderer/Backend/DX12/assets/shaders/direct_lighting.hlsli b/RT/Renderer/Backend/DX12/assets/shaders/direct_lighting.hlsli index 106959f..4c3efe0 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/direct_lighting.hlsli +++ b/RT/Renderer/Backend/DX12/assets/shaders/direct_lighting.hlsli @@ -272,8 +272,11 @@ void CalculateDirectLightingAtSurface(in GeometryRayOutput IN, inout DirectLight float3 sky_color_bot = g_global_cb.sky_color_bottom;//float3(0.15f, 0.35f, 0.65f); float3 sky_color = lerp(sky_color_top, sky_color_bot, abs(IN.view_dir.y)); - OUT.emissive_lighting = sky_color; - OUT.direct_lighting = sky_color; + if (is_indirect) + { + OUT.emissive_lighting = sky_color; + OUT.direct_lighting = sky_color; + } } OUT.albedo = IN.albedo; diff --git a/RT/Renderer/Backend/DX12/assets/shaders/include_shared/shared_tweakvars.hlsl.h b/RT/Renderer/Backend/DX12/assets/shaders/include_shared/shared_tweakvars.hlsl.h index 33f8e5b..fd5a8fb 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/include_shared/shared_tweakvars.hlsl.h +++ b/RT/Renderer/Backend/DX12/assets/shaders/include_shared/shared_tweakvars.hlsl.h @@ -39,6 +39,7 @@ TWEAK_BOOL ("Use Oren-Nayar BRDF", use_oren_nayar_brdf, false) TWEAK_BOOL ("Path-space Regularization", path_space_regularization, true) TWEAK_BOOL ("Object Motion Vectors", object_motion_vectors, true) TWEAK_BOOL ("Enable Normal Maps", enable_normal_maps, true) +TWEAK_BOOL ("Ignore Me...", smooth_textures, false) TWEAK_OPTIONS("Base Color Sampler", albedo_sample_linear, 0, "Point", "Linear") TWEAK_OPTIONS("Normal Map Sampler", normal_sample_linear, 0, "Point", "Linear") TWEAK_OPTIONS("Metallic/Roughness Sampler",metallic_roughness_sample_linear, 0, "Point", "Linear") diff --git a/RT/Renderer/Backend/DX12/assets/shaders/primary_ray.hlsli b/RT/Renderer/Backend/DX12/assets/shaders/primary_ray.hlsli index 4e047ef..4c3236f 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/primary_ray.hlsli +++ b/RT/Renderer/Backend/DX12/assets/shaders/primary_ray.hlsli @@ -185,8 +185,8 @@ void GetGeometryDataFromPrimaryRay(RayDesc ray_desc, PrimaryRayPayload ray_paylo normal = -normal; } } - - OUT.normal = EncodeNormalOctahedron(normal); + + OUT.normal = clamp(EncodeNormalOctahedron(normal), 0.0, 1.0); // ------------------------------------------------------------------------------------- // Determine gbuffer depth value diff --git a/RT/Renderer/Backend/DX12/src/GlobalDX.h b/RT/Renderer/Backend/DX12/src/GlobalDX.h index a9a5bb6..cb59b73 100644 --- a/RT/Renderer/Backend/DX12/src/GlobalDX.h +++ b/RT/Renderer/Backend/DX12/src/GlobalDX.h @@ -264,8 +264,6 @@ namespace RT RT_Vec2 halton_samples[HALTON_SAMPLE_COUNT]; float viewport_offset_y; - RT_Vec3 sky_color_top; - RT_Vec3 sky_color_bottom; RT_RendererIO io; uint64_t tweakvars_config_last_modified_time; diff --git a/RT/Renderer/Backend/DX12/src/RenderBackend.cpp b/RT/Renderer/Backend/DX12/src/RenderBackend.cpp index c1ed2a8..90f274c 100644 --- a/RT/Renderer/Backend/DX12/src/RenderBackend.cpp +++ b/RT/Renderer/Backend/DX12/src/RenderBackend.cpp @@ -2814,6 +2814,9 @@ void RenderBackend::BeginScene(const RT_SceneSettings* scene_settings) if (!g_d3d.scene.freezeframe) { g_d3d.scene.camera = *scene_settings->camera; + g_d3d.scene.camera.forward = RT_Vec3Normalize(g_d3d.scene.camera.forward); + g_d3d.scene.camera.right = RT_Vec3Normalize(g_d3d.scene.camera.right); + g_d3d.scene.camera.up = RT_Vec3Normalize(g_d3d.scene.camera.up); g_d3d.scene.hitgroups_table_at = 0; g_d3d.tlas_instance_count = 0; g_d3d.lights_count = 0; @@ -3179,7 +3182,8 @@ RT_ResourceHandle RenderBackend::UploadMesh(const RT_UploadMeshParams& mesh_para void RenderBackend::ReleaseTexture(const RT_ResourceHandle texture_handle) { TextureResource* texture_resource = g_texture_slotmap.Find(texture_handle); - RT_RELEASE_RESOURCE(texture_resource->texture); + // Note (Justin): This is a dirty little hack to have the resources released after the current frame finished rendering + RT_TRACK_TEMP_OBJECT(texture_resource->texture, &g_d3d.command_queue_direct->GetCommandList()); g_d3d.cbv_srv_uav.Free(texture_resource->descriptors); g_texture_slotmap.Remove(texture_handle); } @@ -3187,8 +3191,10 @@ void RenderBackend::ReleaseTexture(const RT_ResourceHandle texture_handle) void RenderBackend::ReleaseMesh(const RT_ResourceHandle mesh_handle) { MeshResource* mesh_resource = g_mesh_slotmap.Find(mesh_handle); - RT_RELEASE_RESOURCE(mesh_resource->triangle_buffer); - RT_RELEASE_RESOURCE(mesh_resource->blas); + CommandList* cmd_list = &g_d3d.command_queue_direct->GetCommandList(); + // Note (Justin): This is a dirty little hack to have the resources released after the current frame finished rendering + RT_TRACK_TEMP_OBJECT(mesh_resource->triangle_buffer, cmd_list); + RT_TRACK_TEMP_OBJECT(mesh_resource->blas, cmd_list); g_d3d.cbv_srv_uav.Free(mesh_resource->triangle_buffer_descriptor); g_mesh_slotmap.Remove(mesh_handle); } @@ -4155,9 +4161,10 @@ void RenderBackend::RaytraceRender() g_d3d.command_queue_direct->ExecuteCommandList(command_list); } -void RenderBackend::RaytraceSetSkyColors(const RT_Vec3 top, const RT_Vec3 bottom) { - g_d3d.sky_color_top = top; - g_d3d.sky_color_bottom = bottom; +void RenderBackend::RaytraceSetSkyColors(const RT_Vec3 top, const RT_Vec3 bottom) +{ + CurrentFrameData()->scene_cb.As()->sky_color_top = top; + CurrentFrameData()->scene_cb.As()->sky_color_bottom = bottom; } void RenderBackend::RasterSetViewport(float x, float y, float width, float height) diff --git a/RT/Renderer/Backend/DX12/src/ResourceTracker.cpp b/RT/Renderer/Backend/DX12/src/ResourceTracker.cpp index 7b23d1d..48375f0 100644 --- a/RT/Renderer/Backend/DX12/src/ResourceTracker.cpp +++ b/RT/Renderer/Backend/DX12/src/ResourceTracker.cpp @@ -230,7 +230,7 @@ void RT::D3D12ResourceTracker::ReleaseStaleTempResources(uint64_t fence_value) for (ResourceEntry** entry_at = &m_resource_table[i]; *entry_at;) { ResourceEntry* entry = *entry_at; - + if (entry->command_list && entry->command_list->GetFenceValue() <= fence_value) { diff --git a/d1/assets/textures/ceil015.material b/d1/assets/textures/ceil015.material deleted file mode 100644 index 196bb60..0000000 --- a/d1/assets/textures/ceil015.material +++ /dev/null @@ -1,2 +0,0 @@ -roughness = 0.548000 -metalness = 1.000000 diff --git a/d1/main/bm.c b/d1/main/bm.c index bfae6ee..0eb152e 100644 --- a/d1/main/bm.c +++ b/d1/main/bm.c @@ -140,6 +140,7 @@ int gamedata_init() #ifdef RT_DX12 RT_InitAllPolyModels(); RT_InitAllBitmaps(); + RT_InitLightStuff(); RT_InitglTFModels(); RT_RaytraceSetSkyColors((RT_Vec3){ 0.0f,0.0f,0.000f }, (RT_Vec3){ 0.0f,0.0f,0.000f }); #endif diff --git a/d1/main/endlevel.c b/d1/main/endlevel.c index 9e83d70..6390466 100644 --- a/d1/main/endlevel.c +++ b/d1/main/endlevel.c @@ -67,6 +67,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #include "RTutil.h" #include "Core/Arena.h" #include "Game/lights.h" +#include "globvars.h" #endif #ifdef EDITOR @@ -410,6 +411,10 @@ void stop_endlevel_sequence() Endlevel_sequence = EL_OFF; +#ifdef RT_DX12 + RT_RaytraceSetSkyColors(RT_Vec3Make(0.0, 0.0, 0.0), RT_Vec3Make(0.0, 0.0, 0.0)); +#endif + PlayerFinishedLevel(0); } @@ -572,7 +577,6 @@ void do_endlevel_frame() if (ConsoleObject->segnum == transition_segnum) { int objnum; - Endlevel_sequence = EL_LOOKBACK; objnum = obj_create(OBJ_CAMERA, 0, @@ -908,9 +912,9 @@ void render_external_scene(fix eye_offset) } } - #ifdef STATION_ENABLED +#ifdef STATION_ENABLED draw_polygon_model(&station_pos,&vmd_identity_matrix,NULL,station_modelnum,0,lrgb,NULL,NULL, OBJ_NONE); - #endif +#endif #ifdef OGL ogl_toggle_depth_test(0); @@ -1045,7 +1049,7 @@ void endlevel_render_mine(fix eye_offset) else g3_set_view_matrix(&Viewer_eye,&Viewer->orient,Render_zoom); - render_mine(start_seg_num,eye_offset); + render_mine(start_seg_num, eye_offset); #ifdef RT_DX12 RT_Vec3 player_pos = RT_Vec3Fromvms_vector(&Viewer->pos); RT_RenderLevel(player_pos); @@ -1056,28 +1060,26 @@ void render_endlevel_frame(fix eye_offset) { g3_start_frame(); + #ifdef RT_DX12 RT_Camera camera = { .position = RT_Vec3Fromvms_vector(&Viewer->pos), - .forward = RT_Vec3Fromvms_vector(&Viewer->orient.fvec), - .right = RT_Vec3Fromvms_vector(&Viewer->orient.rvec), - .up = RT_Vec3Fromvms_vector(&Viewer->orient.uvec), + .up = RT_Vec3Fromvms_vector(&View_matrix.uvec), + .forward = RT_Vec3Fromvms_vector(&View_matrix.fvec), + .right = RT_Vec3Fromvms_vector(&View_matrix.rvec), .vfov = 60.0f, .near_plane = 0.1f, .far_plane = 10000.0f - }; - RT_SceneSettings frame_settings = + }; + RT_SceneSettings frame_settings = { - .camera = &camera, - .render_height_override = 0, - .render_width_override = 0, - }; - RT_BeginScene(&frame_settings); - RT_Light light = RT_MakeSphericalLight( - (RT_Vec3){ 10, 10, 10 }, - (RT_Vec3){ f2fl(mine_ground_exit_point.x), f2fl(mine_ground_exit_point.y) + 100.f, f2fl(mine_ground_exit_point.z) }, 10.f); - RT_RaytraceSubmitLight(light); + .camera = &camera, + .render_height_override = 0, + .render_width_override = 0, + }; + RT_BeginScene(&frame_settings); + RT_RaytraceSetSkyColors(RT_Vec3Make(0.5, 0.5, 0.5), RT_Vec3Make(0.5, 0.5, 0.5)); #endif if (Endlevel_sequence < EL_OUTSIDE) @@ -1086,7 +1088,7 @@ void render_endlevel_frame(fix eye_offset) render_external_scene(eye_offset); #ifdef RT_DX12 - RT_EndScene(); + RT_EndScene(); #endif g3_end_frame(); diff --git a/d1/main/gauges.c b/d1/main/gauges.c index 0c6ceb7..fcbff92 100644 --- a/d1/main/gauges.c +++ b/d1/main/gauges.c @@ -3057,6 +3057,11 @@ void render_gauges() draw_player_ship(cloak, SB_SHIP_GAUGE_X, SB_SHIP_GAUGE_Y); draw_weapon_boxes(); } + +#ifdef RT_DX12 + dx12_end_frame(); + dx12_start_frame(); +#endif } // --------------------------------------------------------------------------------------------------------- diff --git a/d1/main/lighting.c b/d1/main/lighting.c index 99ecce3..61c0386 100644 --- a/d1/main/lighting.c +++ b/d1/main/lighting.c @@ -48,6 +48,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #ifdef RT_DX12 #include "RTgr.h" #include "Game/Lights.h" + RT_DynamicLightInfo g_rt_dynamic_light_info = { .explosionLights = true, diff --git a/d1/main/menu.c b/d1/main/menu.c index 8df9fd6..eb6f48e 100644 --- a/d1/main/menu.c +++ b/d1/main/menu.c @@ -80,6 +80,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #define RT_RENDER_SETTINGS_CONFIG_FILE "render_settings.vars" #include "Core/String.h" #include "Core/Config.h" +#include "Game/Lights.h" #endif @@ -1329,11 +1330,11 @@ int raytrace_config_menuset(newmenu *menu, d_event *event, void *userdata) void raytrace_config() { - newmenu_item m[28]; + newmenu_item m[30]; int nitems = 0; // Pathtracing ops - int opt_gr_enable_pathtracing = 0, opt_gr_enable_pbr, opt_gr_important_sample_brdf, opt_gr_use_oren_nayar_brdf, opt_gr_lighting_quality; + int opt_gr_enable_pathtracing = 0, opt_gr_enable_pbr, opt_gr_important_sample_brdf, opt_gr_lighting_quality; // Motion Blur ops int opt_gr_motion_blur_quality = 0, opt_gr_motion_blur_strength; @@ -1366,9 +1367,6 @@ void raytrace_config() opt_gr_enable_pbr = nitems; m[nitems].type = NM_TYPE_CHECK; m[nitems].text = "Enable PBR"; m[nitems].value = RT_GetIntFromConfig(config, RT_StringLiteral("enable_pbr")); nitems++; - opt_gr_use_oren_nayar_brdf = nitems; - m[nitems].type = NM_TYPE_CHECK; m[nitems].text = "Use Oren-Nayar BRD"; m[nitems].value = RT_GetIntFromConfig(config, RT_StringLiteral("use_oren_nayar_brdf")); nitems++; - m[nitems].type = NM_TYPE_TEXT; m[nitems].text = "Lighting Quality:"; nitems++; opt_gr_lighting_quality = nitems; m[nitems].type = NM_TYPE_RADIO; m[nitems].text = " Low"; m[nitems].value = 0; m[nitems].group = 0; nitems++; @@ -1377,6 +1375,9 @@ void raytrace_config() int lighting_mode = RT_GetIntFromConfig(config, RT_StringLiteral("ris")); m[opt_gr_lighting_quality+lighting_mode].value=1; + int opt_gr_bilinear = nitems; + m[nitems].type = NM_TYPE_CHECK; m[nitems].text = "Smooth Textures"; m[nitems].value = RT_GetIntFromConfig(config, RT_StringLiteral("smooth_textures")); nitems++; + // --- MOTION BLUR --- m[nitems].type = NM_TYPE_TEXT; m[nitems].text = ""; nitems++; m[nitems].type = NM_TYPE_TEXT; m[nitems].text = "Motion Blur:"; nitems++; @@ -1417,12 +1418,24 @@ void raytrace_config() opt_gr_vignette_strength = nitems; m[nitems].type = NM_TYPE_SLIDER; m[nitems].text = "Vignette Strength:"; m[nitems].value = (int)(RT_GetFloatFromConfig(config, RT_StringLiteral("vignette_strength")) * 10.f); m[nitems].min_value = 0; m[nitems].max_value = 10; nitems++; + // --- OTHER --- + m[nitems].type = NM_TYPE_TEXT; m[nitems].text = ""; nitems++; + m[nitems].type = NM_TYPE_TEXT; m[nitems].text = "Other:"; nitems++; + + int headlight_brightness = (int)roundf(g_headlights.brightness * 5.0f); + int opt_gr_headlight_brightness = nitems; + m[nitems].type = NM_TYPE_SLIDER; m[nitems].text = "Headlight Brightness:"; m[nitems].value = headlight_brightness; m[nitems].min_value = 0; m[nitems].max_value = 15; nitems++; + + RT_ASSERT(nitems <= RT_ARRAY_COUNT(m)); + newmenu_do1( NULL, "Raytracing Options", nitems, m, raytrace_config_menuset, NULL, 1 ); + g_headlights.brightness = (float)m[opt_gr_headlight_brightness].value / 5.0f; + RT_SaveHeadLightSettings(); + if (!preset_changed){ RT_ConfigWriteInt(config, RT_StringLiteral("enable_pathtracing"), m[opt_gr_enable_pathtracing].value); RT_ConfigWriteInt(config, RT_StringLiteral("enable_pbr"), m[opt_gr_enable_pbr].value); - RT_ConfigWriteInt(config, RT_StringLiteral("use_oren_nayar_brdf"), m[opt_gr_use_oren_nayar_brdf].value); for(int i = 0; i < 3; i++){ if(m[opt_gr_lighting_quality+i].value == 1){ lighting_mode = i; @@ -1455,6 +1468,21 @@ void raytrace_config() RT_ConfigWriteInt(config, RT_StringLiteral("ris"), lighting_mode); + if (m[opt_gr_bilinear].value) + { + RT_ConfigWriteInt(config, RT_StringLiteral("smooth_textures"), true); + RT_ConfigWriteInt(config, RT_StringLiteral("albedo_sample_linear"), 1); + RT_ConfigWriteInt(config, RT_StringLiteral("normal_sample_linear"), 1); + RT_ConfigWriteInt(config, RT_StringLiteral("metallic_roughness_sample_linear"), 1); + } + else + { + RT_ConfigWriteInt(config, RT_StringLiteral("smooth_textures"), false); + RT_ConfigWriteInt(config, RT_StringLiteral("albedo_sample_linear"), 0); + RT_ConfigWriteInt(config, RT_StringLiteral("normal_sample_linear"), 0); + RT_ConfigWriteInt(config, RT_StringLiteral("metallic_roughness_sample_linear"), 0); + } + RT_ConfigWriteInt(config, RT_StringLiteral("motion_blur_quality"), m[opt_gr_motion_blur_quality].value); RT_ConfigWriteFloat(config, RT_StringLiteral("motion_blur_curve"), m[opt_gr_motion_blur_strength].value/10.0f); diff --git a/d1/main/render.c b/d1/main/render.c index debef48..5800c10 100644 --- a/d1/main/render.c +++ b/d1/main/render.c @@ -1627,19 +1627,20 @@ void render_frame(fix eye_offset) // Player light { - // NOTE(daniel): These would be great tweakables for an ImGui menu. - float pos_offset_horz = 3.0f; - float pos_offset_vert = -2.0f; - float skew_horz = 0.12f; - float skew_vert = 0.06f; + RT_HeadlightSettings *h = &g_headlights; + + float pos_offset_horz = h->pos_offset_horz; + float pos_offset_vert = h->pos_offset_vert; + float skew_horz = h->skew_horz; + float skew_vert = h->skew_vert; RT_Vec3 light_pos_left = RT_Vec3Add3(object_pos, RT_Vec3Muls(g_cam.right, -pos_offset_horz), RT_Vec3Muls(g_cam.up, pos_offset_vert)); RT_Vec3 light_pos_right = RT_Vec3Add3(object_pos, RT_Vec3Muls(g_cam.right, +pos_offset_horz), RT_Vec3Muls(g_cam.up, pos_offset_vert)); - RT_Vec3 light_dir_left = RT_Vec3Normalize(RT_Vec3Add3(g_cam.forward, RT_Vec3Muls(g_cam.right, +0.1f), RT_Vec3Muls(g_cam.up, skew_vert))); - RT_Vec3 light_dir_right = RT_Vec3Normalize(RT_Vec3Add3(g_cam.forward, RT_Vec3Muls(g_cam.right, -0.1f), RT_Vec3Muls(g_cam.up, skew_vert))); - RT_Vec3 light_emission = RT_Vec3FromScalar(1.5f); - float light_radius = 0.05f; - float light_spot_angle = 0.05f; - float light_spot_softness = 0.05f; + RT_Vec3 light_dir_left = RT_Vec3Normalize(RT_Vec3Add3(g_cam.forward, RT_Vec3Muls(g_cam.right, skew_horz), RT_Vec3Muls(g_cam.up, skew_vert))); + RT_Vec3 light_dir_right = RT_Vec3Normalize(RT_Vec3Add3(g_cam.forward, RT_Vec3Muls(g_cam.right, -skew_horz), RT_Vec3Muls(g_cam.up, skew_vert))); + RT_Vec3 light_emission = RT_Vec3FromScalar(h->brightness); + float light_radius = h->radius; + float light_spot_angle = h->spot_angle; + float light_spot_softness = h->spot_softness; RT_RaytraceSubmitLight(RT_MakeSphericalSpotlight(light_emission, light_pos_left, light_dir_left, light_radius, light_spot_angle, light_spot_softness, 0.6f)); RT_RaytraceSubmitLight(RT_MakeSphericalSpotlight(light_emission, light_pos_right, light_dir_right, light_radius,