diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ad71bc..d780d3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,92 +1,92 @@ -# CMakeList.txt : Top-level CMake project file, do global configuration -# and include sub-projects here. -# -cmake_minimum_required (VERSION 3.13) -project ("DXX-Raytracer") -set (CMAKE_CXX_STANDARD 17) - -set(CMAKE_C_COMPILER_ID, "MSVC") -set(CMAKE_CXX_COMPILER_ID, "MSVC") -set(BUILD_ARGS "-w" "dupbuild=warn") - -#Version Control & Identification -message("Build the Descent 1") -add_compile_definitions(PUBLIC - -#This enum decides if we are in the shipping build or not, this is for the future. -#SHIPPING_BUILD - -D1X_RAYTRACER_NAME="D1X_RAYTRACER" - -D1X_RAYTRACER_VERSION_MAJORi=0 -D1X_RAYTRACER_VERSION_MINORi=9 -D1X_RAYTRACER_VERSION_MICROi=2 - -#DXX-Retro last used version -DXX_VERSION_MAJORi=0 -DXX_VERSION_MINORi=58 -DXX_VERSION_MICROi=1 - -BASE_SCREEN_SIZE_X=1280 -BASE_SCREEN_SIZE_Y=720 -BASE_SCREEN_ASPECT_X=4 -BASE_SCREEN_ASPECT_Y=3 -BASE_SCREEN_WINDOWED=1 -BASE_FPS_INDICATOR=1) - -#compile Definitions. -if (WIN32) -add_compile_definitions(PUBLIC -_WIN32 WINDOWS_IGNORE_PACKING_MISMATCH -WIN32_LEAN_AND_MEAN -NOMINMAX -) -endif () -if(DEFINED ENV{EDITOR}) -message("Using editor") -add_compile_definitions(PUBLIC EDITOR) -endif() - -if(${GRAPHICS_API} STREQUAL "DirectX12") -message("Render api is ${GRAPHICS_API}") -add_compile_definitions(PUBLIC RT_DX12) -elseif(${GRAPHICS_API} STREQUAL "OpenGL") -message("Render api is ${GRAPHICS_API}") -add_compile_definitions(PUBLIC OGL) -else() -message(FATAL_ERROR "No graphic API selected!") -endif() - -if(CMAKE_BUILD_TYPE MATCHES Debug) -add_compile_definitions(PUBLIC -DEBUG -_DEBUG) -message(STATUS, "Build type selected: Debug") -elseif(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) -add_compile_definitions(PUBLIC -RELEASE -_RELEASE) -message(STATUS, "Build type selected: RelWithDebInfo") -elseif(CMAKE_BUILD_TYPE MATCHES Release) -add_compile_definitions(PUBLIC -RELEASE -_RELEASE -SHIPPING_BUILD) -message(STATUS, "Build type selected: Release") -else() -message(FATAL_ERROR, "No build type selected!") -endif() - -if(DEFINED ENV{QUICK_START}) -add_compile_definitions(PUBLIC QUICK_START) -message(STATUS "quick build selected, will immediatly go to level select.") -message(STATUS ${QUICKSTART}) -else() -message(STATUS "normal build selected") -message(STATUS ${QUICKSTART}) -endif() - -add_subdirectory ("sdl-master") -add_subdirectory ("physfs-main") -add_subdirectory ("RT") -add_subdirectory ("d1") \ No newline at end of file +# CMakeList.txt : Top-level CMake project file, do global configuration +# and include sub-projects here. +# +cmake_minimum_required (VERSION 3.13) +project ("DXX-Raytracer") +set (CMAKE_CXX_STANDARD 17) + +set(CMAKE_C_COMPILER_ID, "MSVC") +set(CMAKE_CXX_COMPILER_ID, "MSVC") +set(BUILD_ARGS "-w" "dupbuild=warn") + +#Version Control & Identification +message("Build the Descent 1") +add_compile_definitions(PUBLIC + +#This enum decides if we are in the shipping build or not, this is for the future. +#SHIPPING_BUILD + +D1X_RAYTRACER_NAME="D1X_RAYTRACER" + +D1X_RAYTRACER_VERSION_MAJORi=1 +D1X_RAYTRACER_VERSION_MINORi=0 +D1X_RAYTRACER_VERSION_MICROi=0 + +#DXX-Retro last used version +DXX_VERSION_MAJORi=0 +DXX_VERSION_MINORi=58 +DXX_VERSION_MICROi=1 + +BASE_SCREEN_SIZE_X=1280 +BASE_SCREEN_SIZE_Y=720 +BASE_SCREEN_ASPECT_X=4 +BASE_SCREEN_ASPECT_Y=3 +BASE_SCREEN_WINDOWED=1 +BASE_FPS_INDICATOR=1) + +#compile Definitions. +if (WIN32) +add_compile_definitions(PUBLIC +_WIN32 WINDOWS_IGNORE_PACKING_MISMATCH +WIN32_LEAN_AND_MEAN +NOMINMAX +) +endif () +if(DEFINED ENV{EDITOR}) +message("Using editor") +add_compile_definitions(PUBLIC EDITOR) +endif() + +if(${GRAPHICS_API} STREQUAL "DirectX12") +message("Render api is ${GRAPHICS_API}") +add_compile_definitions(PUBLIC RT_DX12) +elseif(${GRAPHICS_API} STREQUAL "OpenGL") +message("Render api is ${GRAPHICS_API}") +add_compile_definitions(PUBLIC OGL) +else() +message(FATAL_ERROR "No graphic API selected!") +endif() + +if(CMAKE_BUILD_TYPE MATCHES Debug) +add_compile_definitions(PUBLIC +DEBUG +_DEBUG) +message(STATUS, "Build type selected: Debug") +elseif(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) +add_compile_definitions(PUBLIC +RELEASE +_RELEASE) +message(STATUS, "Build type selected: RelWithDebInfo") +elseif(CMAKE_BUILD_TYPE MATCHES Release) +add_compile_definitions(PUBLIC +RELEASE +_RELEASE +SHIPPING_BUILD) +message(STATUS, "Build type selected: Release") +else() +message(FATAL_ERROR, "No build type selected!") +endif() + +if(DEFINED ENV{QUICK_START}) +add_compile_definitions(PUBLIC QUICK_START) +message(STATUS "quick build selected, will immediatly go to level select.") +message(STATUS ${QUICKSTART}) +else() +message(STATUS "normal build selected") +message(STATUS ${QUICKSTART}) +endif() + +add_subdirectory ("sdl-master") +add_subdirectory ("physfs-main") +add_subdirectory ("RT") +add_subdirectory ("d1") diff --git a/CMakePresets.json b/CMakePresets.json index 2f0ce2f..d515527 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,83 +1,83 @@ -{ - "cmakeMinimumRequired": { - "major": 3, - "minor": 21, - "patch": 0 - }, - "version": 3, - "configurePresets": [ - { - "hidden": true, - "name": "default", - "description": "default-for-all", - "generator": "Ninja", - "binaryDir": "${sourceDir}/out/build/${presetName}", - "cacheVariables": { - "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}" - } - }, - { - "name": "directx12-win-ship", - "description": "The shipping build for descent.", - "inherits": "default", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "GRAPHICS_API": "DirectX12" - } - }, - { - "name": "directx12-win-debug", - "description": "Normal directx12 raytrace debug build.", - "inherits": "default", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "GRAPHICS_API": "DirectX12" - } - }, - { - "name": "directx12-win-release", - "description": "Directx12_build", - "inherits": "default", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithDebInfo ", - "GRAPHICS_API": "DirectX12" - } - }, - { - "name": "directx12-win-debug-quick", - "description": "Directx12_build that skips skips the menu", - "inherits": "directx12-win-debug", - "cacheVariables": { - "QUICK_START": "true", - "GRAPHICS_API": "DirectX12" - } - }, - { - "name": "directx12-win-release-quick", - "description": "Directx12_build that skips skips the menu", - "inherits": "directx12-win-release", - "cacheVariables": { - "QUICK_START": "true", - "GRAPHICS_API": "DirectX12" - } - }, - { - "name": "openGL-x64-debug", - "description": "OpenGL Build for x64, no x86 build exists", - "inherits": "default", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "GRAPHICS_API": "OpenGL" - } - }, - { - "name": "openGL-x64-release", - "description": "OpenGL Build for x64, no x86 build exists", - "inherits": "default", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "GRAPHICS_API": "OpenGL" - } - } - ] +{ + "cmakeMinimumRequired": { + "major": 3, + "minor": 21, + "patch": 0 + }, + "version": 3, + "configurePresets": [ + { + "hidden": true, + "name": "default", + "description": "default-for-all", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}" + } + }, + { + "name": "directx12-win-ship", + "description": "The shipping build for descent.", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "GRAPHICS_API": "DirectX12" + } + }, + { + "name": "directx12-win-debug", + "description": "Normal directx12 raytrace debug build.", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "GRAPHICS_API": "DirectX12" + } + }, + { + "name": "directx12-win-release", + "description": "Directx12_build", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "GRAPHICS_API": "DirectX12" + } + }, + { + "name": "directx12-win-debug-quick", + "description": "Directx12_build that skips skips the menu", + "inherits": "directx12-win-debug", + "cacheVariables": { + "QUICK_START": "true", + "GRAPHICS_API": "DirectX12" + } + }, + { + "name": "directx12-win-release-quick", + "description": "Directx12_build that skips skips the menu", + "inherits": "directx12-win-release", + "cacheVariables": { + "QUICK_START": "true", + "GRAPHICS_API": "DirectX12" + } + }, + { + "name": "openGL-x64-debug", + "description": "OpenGL Build for x64, no x86 build exists", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "GRAPHICS_API": "OpenGL" + } + }, + { + "name": "openGL-x64-release", + "description": "OpenGL Build for x64, no x86 build exists", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "GRAPHICS_API": "OpenGL" + } + } + ] } \ No newline at end of file diff --git a/RT/CMakeLists.txt b/RT/CMakeLists.txt index 8e23134..dba3df1 100644 --- a/RT/CMakeLists.txt +++ b/RT/CMakeLists.txt @@ -1,13 +1,13 @@ -# CMakeList.txt : Cmake project for including the RT code -cmake_minimum_required (VERSION 3.8) - -set(ENV{RT_EXT_CODE_DIR} -"${CMAKE_CURRENT_LIST_DIR}" -) - -message("RT Dir is: $ENV{RT_EXT_CODE_DIR}") - -add_subdirectory("Core") -target_include_directories(RT_CORE INTERFACE ${CMAKE_CURRENT_LIST_DIR}) -add_subdirectory("Renderer/Backend/Common") -add_subdirectory("Renderer/Backend/DX12") +# CMakeList.txt : Cmake project for including the RT code +cmake_minimum_required (VERSION 3.8) + +set(ENV{RT_EXT_CODE_DIR} +"${CMAKE_CURRENT_LIST_DIR}" +) + +message("RT Dir is: $ENV{RT_EXT_CODE_DIR}") + +add_subdirectory("Core") +target_include_directories(RT_CORE INTERFACE ${CMAKE_CURRENT_LIST_DIR}) +add_subdirectory("Renderer/Backend/Common") +add_subdirectory("Renderer/Backend/DX12") diff --git a/RT/Core/Arena.c b/RT/Core/Arena.c index 7fdbc5a..6519897 100644 --- a/RT/Core/Arena.c +++ b/RT/Core/Arena.c @@ -139,7 +139,7 @@ void *RT_ArenaAllocNoZero_(RT_ARENA_DEBUG_PARAMS RT_Arena *arena, size_t size, s char *result = NULL; - if (ALWAYS(RT_ArenaSizeRemainingForAlign(arena, align) >= size)) + if (size > 0 && ALWAYS(RT_ArenaSizeRemainingForAlign(arena, align) >= size)) { #if defined(RT_ARENA_DEBUG) { diff --git a/RT/Core/CMakeLists.txt b/RT/Core/CMakeLists.txt index 414aad0..5dbd8e3 100644 --- a/RT/Core/CMakeLists.txt +++ b/RT/Core/CMakeLists.txt @@ -1,19 +1,19 @@ -# CMakeList.txt : Cmake project for including the RT code -cmake_minimum_required (VERSION 3.8) -add_library(RT_CORE INTERFACE -"Arena.h" -"Common.h" -"VirtualMemory.h" -"MemoryScope.hpp" -"SlotMap.hpp" -"Config.h" -"String.h" -"Hash.h") - -target_sources(RT_CORE INTERFACE -"${CMAKE_CURRENT_LIST_DIR}/Config.cpp" -"${CMAKE_CURRENT_LIST_DIR}/Arena.c" -"${CMAKE_CURRENT_LIST_DIR}/Common.c" -"${CMAKE_CURRENT_LIST_DIR}/String.c" -"${CMAKE_CURRENT_LIST_DIR}/VirtualMemory.c" +# CMakeList.txt : Cmake project for including the RT code +cmake_minimum_required (VERSION 3.8) +add_library(RT_CORE INTERFACE +"Arena.h" +"Common.h" +"VirtualMemory.h" +"MemoryScope.hpp" +"SlotMap.hpp" +"Config.h" +"String.h" +"Hash.h" ) + +target_sources(RT_CORE INTERFACE +"${CMAKE_CURRENT_LIST_DIR}/Config.cpp" +"${CMAKE_CURRENT_LIST_DIR}/Arena.c" +"${CMAKE_CURRENT_LIST_DIR}/Common.c" +"${CMAKE_CURRENT_LIST_DIR}/String.c" +"${CMAKE_CURRENT_LIST_DIR}/VirtualMemory.c" ) \ No newline at end of file diff --git a/RT/Core/Common.c b/RT/Core/Common.c index 8665847..5e1541a 100644 --- a/RT/Core/Common.c +++ b/RT/Core/Common.c @@ -24,3 +24,26 @@ void RT_FATAL_ERROR_(const char *explanation, const char *title, const char *fil ExitProcess(1); // goodbye forever } + +static LARGE_INTEGER perf_freq; + +RT_HighResTime RT_GetHighResTime(void) +{ + LARGE_INTEGER value; + QueryPerformanceCounter(&value); + + RT_HighResTime result; + result.value = value.QuadPart; + return result; +} + +double RT_SecondsElapsed(RT_HighResTime start, RT_HighResTime end) +{ + if (!perf_freq.QuadPart) + { + QueryPerformanceFrequency(&perf_freq); + } + + double result = (double)(end.value - start.value) / (double)perf_freq.QuadPart; + return result; +} diff --git a/RT/Core/Common.h b/RT/Core/Common.h index 0dda3bf..caf156d 100644 --- a/RT/Core/Common.h +++ b/RT/Core/Common.h @@ -3,6 +3,7 @@ #include "ApiTypes.h" #include +#include #define RT_ASSERT(x) assert(x) #define RT_INVALID_DEFAULT_CASE default: { RT_ASSERT(!"Invalid default case!"); } break; @@ -10,6 +11,15 @@ RT_API void RT_FATAL_ERROR_(const char *explanation, const char *title, const char *file, int line); #define RT_FATAL_ERROR(explanation) RT_FATAL_ERROR_(explanation, "Fatal Error", __FILE__, __LINE__) +// A wrapper over QueryPerformanceCounter, the high resolution timer Windows provides, that doesn't require you to include Windows.h +typedef struct RT_HighResTime +{ + uint64_t value; +} RT_HighResTime; + +RT_API RT_HighResTime RT_GetHighResTime(void); +RT_API double RT_SecondsElapsed(RT_HighResTime start, RT_HighResTime end); + #define ALWAYS(x) (RT_ASSERT(x), x) #define NEVER(x) (RT_ASSERT(!(x)), x) diff --git a/RT/Core/Config.cpp b/RT/Core/Config.cpp index fc14a06..a54f899 100644 --- a/RT/Core/Config.cpp +++ b/RT/Core/Config.cpp @@ -9,7 +9,7 @@ #include "Core/MemoryScope.hpp" #include "Core/String.h" -static void ConfigError(RT_Config *cfg, char *error) +static inline void ConfigError(RT_Config *cfg, char *error) { RT_StringNode *error_node = RT_ArenaAllocStruct(cfg->arena, RT_StringNode); error_node->string.count = strlen(error); // booo... @@ -17,215 +17,11 @@ static void ConfigError(RT_Config *cfg, char *error) RT_SLL_PUSH(cfg->first_error, error_node); } -typedef enum RT_ConfigTokenKind -{ - /* ascii ... */ - RT_ConfigToken_Identifier = 128, - RT_ConfigToken_Number, - RT_ConfigToken_String, - RT_ConfigToken_Error, - RT_ConfigToken_EOF, -} RT_ConfigTokenKind; - -typedef struct RT_ConfigToken -{ - RT_ConfigTokenKind kind; - RT_String string; -} RT_ConfigToken; - -typedef struct RT_ConfigTokenizer -{ - char *start; - char *end; - char *at; - - RT_ConfigToken token; - RT_Config *cfg; -} RT_ConfigTokenizer; - -static void TokenizeError(RT_ConfigTokenizer *tok, const char *error) -{ - int line = 1; - - char *at = tok->start; - char *end = tok->end; - - while (at < end) - { - if (*at++ == '\n') - { - line++; - } - } - - ConfigError(tok->cfg, RT_ArenaPrintF(tok->cfg->arena, "line %d: %s", line, error)); -} - -static void SkipWhitespace(RT_ConfigTokenizer *tok) -{ - char *at = tok->at; - char *end = tok->end; - - while (at < end) - { - switch (*at) - { - case '#': - { - while (at < end && *at != '\n') at++; - } break; - - default: - { - if (!isspace(*at)) - goto done; - at++; - } break; - } - } -done: - - tok->at = at; - tok->end = end; -} - -static bool NextToken(RT_ConfigTokenizer *tok) -{ - SkipWhitespace(tok); - - char *at = tok->at; - char *end = tok->end; - - char *token_start = tok->at; - tok->token.kind = RT_ConfigToken_EOF; - - bool result = false; - - if (at < end) - { - result = true; - - tok->token.kind = RT_ConfigToken_Error; - - char c = *at++; - switch (c) - { - case '=': - { - tok->token.kind = (RT_ConfigTokenKind)'='; - } break; - - case '"': - { - tok->token.kind = RT_ConfigToken_String; - while (at < end && *at != '"') - { - if (*at == '\n') - { - TokenizeError(tok, "Unterminated string (newline)."); - break; - } - at++; - } - - if (at[-1] != '"') - TokenizeError(tok, "Unterminated string (eof)."); - } break; - - case '0': - case '1': case '2': case '3': - case '4': case '5': case '6': - case '7': case '8': case '9': - { - tok->token.kind = RT_ConfigToken_Number; - - // NOTE: fairly unrobust float parsing - while (at < end && isalnum(*at)) at++; - if (*at == '.') at++; - while (at < end && isalnum(*at)) at++; - if (*at == 'f') at++; - } break; - - default: - { - if (isalpha(c) || c == '_') - { - tok->token.kind = RT_ConfigToken_Identifier; - while (at < end && isalnum(*at) || *at == '_') at++; - } - } break; - } - } - - char *token_end = at; - - tok->token.string.bytes = token_start; - tok->token.string.count = token_end - token_start; - - tok->at = at; - tok->end = end; - - return result; -} - -static bool ExpectKey(RT_ConfigTokenizer *tok, RT_ConfigToken *token) -{ - if (tok->token.kind != RT_ConfigToken_Identifier) - { - TokenizeError(tok, "Expected key."); - return false; - } - - *token = tok->token; - NextToken(tok); - - return true; -} - -static bool ExpectOperator(RT_ConfigTokenizer *tok, char op, RT_ConfigToken *token) -{ - if (tok->token.kind != op) - { - TokenizeError(tok, RT_ArenaPrintF(tok->cfg->arena, "Expected character '%c' after key.", op)); - return false; - } - - *token = tok->token; - NextToken(tok); - - return true; -} - -static bool ExpectValue(RT_ConfigTokenizer *tok, RT_ConfigToken *token) -{ - if (tok->token.kind != RT_ConfigToken_Identifier && - tok->token.kind != RT_ConfigToken_String && - tok->token.kind != RT_ConfigToken_Number) - { - TokenizeError(tok, "Expected valid value."); - return false; - } - - *token = tok->token; - NextToken(tok); - - return true; -} - -static void InitTokenizer(RT_ConfigTokenizer *tok, RT_Config *cfg, RT_String string) -{ - tok->start = string.bytes; - tok->at = tok->start; - tok->end = tok->start + string.count; - tok->cfg = cfg; - - NextToken(tok); -} - void RT_InitializeConfig(RT_Config *cfg, RT_Arena *arena) { memset(cfg, 0, sizeof(*cfg)); cfg->arena = arena; + cfg->last_modified_time = RT_GetHighResTime().value; } bool RT_DeserializeConfigFromFile(RT_Config *cfg, const char *file_name) @@ -264,25 +60,26 @@ bool RT_DeserializeConfigFromFile(RT_Config *cfg, const char *file_name) void RT_DeserializeConfigFromString(RT_Config *cfg, RT_String string) { - RT_ConfigTokenizer tok = {0}; - InitTokenizer(&tok, cfg, string); - - while (tok.token.kind != RT_ConfigToken_EOF) + while (string.count > 0) { - RT_ConfigToken token; + RT_String line; + string = RT_StringSplitLine(string, &line); - if (!ExpectKey(&tok, &token)) - break; + line = RT_StringTrim(line); - RT_String key = token.string; + if (line.count > 0 && line.bytes[0] == '#') + continue; - if (!ExpectOperator(&tok, '=', &token)) - break; + RT_String key; + line = RT_StringSplitAroundChar(line, '=', &key); - if (!ExpectValue(&tok, &token)) - break; + key = RT_StringTrim(key); + + RT_String value; + line = RT_StringSplitAroundChar(line, '#', &value); - RT_String value = token.string; + value = RT_StringTrim(value); + value = RT_StringUnquoteString(value); RT_ConfigWriteString(cfg, key, value); } @@ -322,7 +119,15 @@ RT_ConfigKeyValue *RT_ConfigFindOrCreateKeyValue(RT_Config *cfg, RT_String key) if (!kv) { - kv = RT_ArenaAllocStruct(cfg->arena, RT_ConfigKeyValue); + if (!cfg->first_free_key_value) + { + cfg->first_free_key_value = RT_ArenaAllocStructNoZero(cfg->arena, RT_ConfigKeyValue); + cfg->first_free_key_value->next = NULL; + } + + kv = RT_SLL_POP(cfg->first_free_key_value); + memset(kv, 0, sizeof(*kv)); + kv->hash = hash; kv->key_count = key.count; if (kv->key_count > sizeof(kv->key) - 1) @@ -406,11 +211,11 @@ bool RT_ConfigReadVec3(RT_Config *cfg, RT_String key, RT_Vec3 *value) { RT_ParseFloatResult parse_x = RT_ParseFloat(string); string = RT_StringAdvance(string, parse_x.advance); - string = RT_StringAdvance(string, RT_StringFindChar(string, ',')); + string = RT_StringAdvance(string, RT_StringFindChar(string, ',') + 1); string = RT_StringAdvance(string, RT_StringFindFirstNonWhitespace(string)); RT_ParseFloatResult parse_y = RT_ParseFloat(string); string = RT_StringAdvance(string, parse_y.advance); - string = RT_StringAdvance(string, RT_StringFindChar(string, ',')); + string = RT_StringAdvance(string, RT_StringFindChar(string, ',') + 1); string = RT_StringAdvance(string, RT_StringFindFirstNonWhitespace(string)); RT_ParseFloatResult parse_z = RT_ParseFloat(string); @@ -441,24 +246,62 @@ void RT_ConfigWriteString(RT_Config *cfg, RT_String key, RT_String value) (int)value.count, value.bytes, 255, value.bytes)); } RT_CopyStringToBufferNullTerm(value, sizeof(kv->value), kv->value); + + cfg->last_modified_time = RT_GetHighResTime().value; } void RT_ConfigWriteFloat(RT_Config *cfg, RT_String key, float value) { RT_ConfigKeyValue *kv = RT_ConfigFindOrCreateKeyValue(cfg, key); kv->value_count = snprintf(kv->value, sizeof(kv->value), "%f", value); + cfg->last_modified_time = RT_GetHighResTime().value; } void RT_ConfigWriteInt(RT_Config *cfg, RT_String key, int value) { RT_ConfigKeyValue *kv = RT_ConfigFindOrCreateKeyValue(cfg, key); kv->value_count = snprintf(kv->value, sizeof(kv->value), "%d", value); + 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); kv->value_count = snprintf(kv->value, sizeof(kv->value), "%f, %f, %f", value.x, value.y, value.z); + cfg->last_modified_time = RT_GetHighResTime().value; +} + +bool RT_ConfigEraseKey(RT_Config *cfg, RT_String key) +{ + bool result = false; + + uint32_t hash = RT_Murmur3(key.bytes, (uint32_t)key.count, 0xBEEFD00D); + uint32_t slot = hash % RT_ARRAY_COUNT(cfg->table); + + for (RT_ConfigKeyValue **kv_at = &cfg->table[slot]; *kv_at; kv_at = &(*kv_at)->next) + { + RT_ConfigKeyValue *kv = *kv_at; + + if (kv->hash == hash && + strncmp(key.bytes, kv->key, RT_MIN(key.count, kv->key_count)) == 0) + { + *kv_at = (*kv_at)->next; + + // Add kv to freelist + kv->next = cfg->first_free_key_value; + cfg->first_free_key_value = kv; + + if (ALWAYS(cfg->kv_count > 0)) + cfg->kv_count -= 1; + + result = true; + cfg->last_modified_time = RT_GetHighResTime().value; + + break; + } + } + + return result; } RT_String RT_SerializeConfigToString(RT_Arena *arena, RT_Config *cfg) diff --git a/RT/Core/Config.h b/RT/Core/Config.h index e5fbec6..72d67f4 100644 --- a/RT/Core/Config.h +++ b/RT/Core/Config.h @@ -25,8 +25,11 @@ typedef struct RT_Config { RT_Arena *arena; + uint64_t last_modified_time; + size_t kv_count; RT_ConfigKeyValue *table[1024]; + RT_ConfigKeyValue *first_free_key_value; RT_StringNode *first_error; } RT_Config; @@ -42,6 +45,7 @@ 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_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); RT_API bool RT_SerializeConfigToFile(RT_Config *cfg, char *file_name); @@ -49,4 +53,76 @@ RT_API bool RT_SerializeConfigToFile(RT_Config *cfg, char *file_name); RT_API RT_ConfigKeyValue *RT_ConfigFindKeyValue(RT_Config *cfg, RT_String key); RT_API RT_ConfigKeyValue *RT_ConfigFindOrCreateKeyValue(RT_Config *cfg, RT_String key); +// ------------------------------------------------------------------ +// Config Iterator + +// Usage: +/* + for (RT_ConfigIterator it = RT_IterateConfig(cfg); + RT_ConfigIterValid(&it); + RT_ConfigIterNext(&it)) + { + size_t index = it.index; + RT_ConfigKeyValue *kv = it.at; + + printf("%zuth key: %s\n", index, kv->key); + printf("%zuth value: %s\n", index, kv->value); + } +*/ + +typedef struct RT_ConfigIterator +{ + RT_Config *cfg; + + size_t index; // iteration index + size_t slot; // table slot currently pointed at + RT_ConfigKeyValue *at; // key-value currently pointed at +} RT_ConfigIterator; + +static inline RT_ConfigIterator RT_IterateConfig(RT_Config *cfg) +{ + RT_ConfigIterator it = {0}; + it.cfg = cfg; + + for (size_t i = 0; i < RT_ARRAY_COUNT(cfg->table); i++) + { + RT_ConfigKeyValue *kv = cfg->table[i]; + if (kv) + { + it.slot = i; + it.at = kv; + break; + } + } + + return it; +} + +static inline bool RT_ConfigIterValid(RT_ConfigIterator *it) +{ + return !!it->at; +} + +static inline void RT_ConfigIterNext(RT_ConfigIterator *it) +{ + if (it->at) + { + it->at = it->at->next; + if (!it->at) + { + it->slot += 1; + for (size_t i = it->slot; i < RT_ARRAY_COUNT(it->cfg->table); i++) + { + if (it->cfg->table[i]) + { + it->slot = i; + it->at = it->cfg->table[i]; + break; + } + } + } + it->index += 1; + } +} + #pragma pack(pop) diff --git a/RT/Core/String.h b/RT/Core/String.h index 0004ea5..48d9f4a 100644 --- a/RT/Core/String.h +++ b/RT/Core/String.h @@ -111,6 +111,25 @@ typedef struct RT_ParseIntResult RT_API RT_ParseIntResult RT_ParseInt(RT_String string, int base); +static inline bool RT_StringsAreEqual(RT_String a, RT_String b) +{ + bool result = a.count == b.count; + + if (result) + { + for (size_t i = 0; i < a.count; i++) + { + if (a.bytes[i] != b.bytes[i]) + { + result = false; + break; + } + } + } + + return result; +} + static inline size_t RT_StringFindChar(RT_String string, char c) { for (size_t i = 0; i < string.count; i++) @@ -123,14 +142,38 @@ static inline size_t RT_StringFindChar(RT_String string, char c) return RT_String_NPOS; } +static inline bool RT_IsWhitespace(char c) +{ + return (c == ' ' || + c == '\t' || + c == '\n' || + c == '\r'); +} + +static inline bool RT_IsNewline(char c) +{ + return (c == '\n' || c == '\r'); +} + static inline size_t RT_StringFindFirstNonWhitespace(RT_String string) { for (size_t i = 0; i < string.count; i++) { - if (string.bytes[i] != ' ' && - string.bytes[i] != '\t' && - string.bytes[i] != '\n' && - string.bytes[i] != '\r') + if (!RT_IsWhitespace(string.bytes[i])) + { + return i; + } + } + return RT_String_NPOS; +} + +static inline size_t RT_StringFindLastNonWhitespace(RT_String string) +{ + for (size_t j = 0; j < string.count; j++) + { + size_t i = string.count - j - 1; // unsigned reverse for loops :)) + + if (!RT_IsWhitespace(string.bytes[i])) { return i; } @@ -147,3 +190,99 @@ static inline RT_String RT_StringAdvance(RT_String string, size_t advance) string.count -= advance; return string; } + +static inline RT_String RT_StringSplitLine(RT_String string, RT_String *line) +{ + char *start = string.bytes; + char *end = string.bytes + string.count; + char *at = start; + + while (at < end && !RT_IsNewline(*at)) + { + at++; + } + + if (line) + { + line->bytes = start; + line->count = at - start; + } + + while (at < end && RT_IsNewline(*at)) + { + at++; + } + + RT_String result; + result.bytes = at; + result.count = end - at; + return result; +} + +// Returns string to the right of the char as a return value, returns left side through lhs parameter +static inline RT_String RT_StringSplitAroundChar(RT_String string, char c, RT_String *lhs) +{ + RT_String result = {0}; + + size_t pos = RT_StringFindChar(string, c); + + if (pos != RT_String_NPOS) + { + if (lhs) + { + lhs->bytes = string.bytes; + lhs->count = pos; + } + result = RT_StringAdvance(string, pos + 1); + } + else + { + if (lhs) + { + *lhs = string; + } + } + + return result; +} + +// If the string is in the form "This is a string", it removes the quotes: This is a string +static inline RT_String RT_StringUnquoteString(RT_String string) +{ + if (string.count >= 2) + { + if (string.bytes[0] == '"' && + string.bytes[string.count - 1] == '"') + { + string.bytes += 1; + string.count -= 2; + } + } + return string; +} + +static inline RT_String RT_StringTrimLeft(RT_String string) +{ + while (string.count > 0 && RT_IsWhitespace(string.bytes[0])) + { + string.bytes++; + string.count--; + } + return string; +} + +static inline RT_String RT_StringTrimRight(RT_String string) +{ + while (string.count > 0 && RT_IsWhitespace(string.bytes[string.count - 1])) + { + string.count--; + } + return string; +} + +static inline RT_String RT_StringTrim(RT_String string) +{ + string = RT_StringTrimLeft(string); + string = RT_StringTrimRight(string); + return string; +} diff --git a/RT/Game/Lights.c b/RT/Game/Lights.c index 337f175..76c6a9f 100644 --- a/RT/Game/Lights.c +++ b/RT/Game/Lights.c @@ -6,6 +6,8 @@ #include "RTgr.h" #include "RTmaterials.h" +float g_light_multiplier = 1.0; +float g_light_multiplier_default = 1.0; const float FLT_MAX = 3.402823466e+38F; RT_LightDefinition g_light_definitions[] = @@ -227,6 +229,11 @@ 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)){ + g_light_multiplier = g_light_multiplier_default; + g_pending_light_update = true; + } + igText("Current active light count: %i / %i", g_active_lights, RT_MAX_LIGHTS); if (igCollapsingHeader_TreeNodeFlags("Light definitions", ImGuiTreeNodeFlags_None)) { @@ -237,7 +244,11 @@ void RT_ShowLightMenu() { igPushID_Int(i); RT_LightDefinition* light = &g_light_definitions[i]; - ushort texture_index = piggy_find_bitmap(light->name).index; + + char light_name[128]; + strncpy(light_name, light->name, 128); + + ushort texture_index = piggy_find_bitmap(light_name).index; if (texture_index > 0){ char* light_name_buffer = RT_ArenaPrintF(&g_thread_arena, "Light: %s", light->name); @@ -283,31 +294,31 @@ void RT_VisualizeLight(RT_Light* light) { case RT_LightKind_Area_Rect: RT_Vec3 normal = RT_Vec3Make(light->transform.r0.y, light->transform.r1.y, light->transform.r2.y); - RT_DrawLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Muls(normal, 10.0)), RT_Vec4Make(1.0, 0.0, 1.0, 1.0)); + RT_RasterLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Muls(normal, 10.0)), RT_Vec4Make(1.0, 0.0, 1.0, 1.0)); RT_Vec3 tangent = RT_Vec3Make(light->transform.e[0][0],light->transform.e[1][0],light->transform.e[2][0]); RT_Vec3 bitangent = RT_Vec3Make(light->transform.e[0][2],light->transform.e[1][2],light->transform.e[2][2]); RT_Vec3 emission_unpack = RT_UnpackRGBE(light->emission); RT_Vec4 emission = RT_Vec4Make(emission_unpack.x, emission_unpack.y, emission_unpack.z, 1.0); - RT_DrawLineWorld(RT_Vec3Sub(RT_Vec3Sub(pos, tangent),bitangent), RT_Vec3Sub(RT_Vec3Add(pos, tangent),bitangent), emission); - RT_DrawLineWorld(RT_Vec3Sub(RT_Vec3Sub(pos, tangent),bitangent), RT_Vec3Sub(RT_Vec3Add(pos, bitangent),tangent), emission); - RT_DrawLineWorld(RT_Vec3Add(RT_Vec3Add(pos, tangent),bitangent), RT_Vec3Sub(RT_Vec3Add(pos, tangent),bitangent), emission); - RT_DrawLineWorld(RT_Vec3Add(RT_Vec3Add(pos, tangent),bitangent), RT_Vec3Sub(RT_Vec3Add(pos, bitangent),tangent), emission); + RT_RasterLineWorld(RT_Vec3Sub(RT_Vec3Sub(pos, tangent),bitangent), RT_Vec3Sub(RT_Vec3Add(pos, tangent),bitangent), emission); + RT_RasterLineWorld(RT_Vec3Sub(RT_Vec3Sub(pos, tangent),bitangent), RT_Vec3Sub(RT_Vec3Add(pos, bitangent),tangent), emission); + RT_RasterLineWorld(RT_Vec3Add(RT_Vec3Add(pos, tangent),bitangent), RT_Vec3Sub(RT_Vec3Add(pos, tangent),bitangent), emission); + RT_RasterLineWorld(RT_Vec3Add(RT_Vec3Add(pos, tangent),bitangent), RT_Vec3Sub(RT_Vec3Add(pos, bitangent),tangent), emission); - RT_DrawLineWorld(RT_Vec3Sub(pos, tangent), RT_Vec3Add(pos, tangent), RT_Vec4Make(0.0, 1.0, 0.0, 1.0)); - RT_DrawLineWorld(RT_Vec3Sub(pos, bitangent), RT_Vec3Add(pos, bitangent), RT_Vec4Make(0.0, 0.0, 1.0, 1.0)); + RT_RasterLineWorld(RT_Vec3Sub(pos, tangent), RT_Vec3Add(pos, tangent), RT_Vec4Make(0.0, 1.0, 0.0, 1.0)); + RT_RasterLineWorld(RT_Vec3Sub(pos, bitangent), RT_Vec3Add(pos, bitangent), RT_Vec4Make(0.0, 0.0, 1.0, 1.0)); break; case RT_LightKind_Area_Sphere: RT_Vec3 scale = RT_ScaleFromMat34(light->transform); - RT_DrawLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Make(scale.x,0.0,0.0)), RT_Vec4Make(1.0, 0.0, 0.0, 1.0)); - RT_DrawLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Make(-scale.x,0.0,0.0)), RT_Vec4Make(1.0, 0.0, 0.0, 1.0)); - RT_DrawLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Make(0.0,scale.y,0.0)), RT_Vec4Make(1.0, 0.0, 0.0, 1.0)); - RT_DrawLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Make(0.0,-scale.y,0.0)), RT_Vec4Make(1.0, 0.0, 0.0, 1.0)); - RT_DrawLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Make(0.0,0.0,scale.z)), RT_Vec4Make(1.0, 0.0, 0.0, 1.0)); - RT_DrawLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Make(0.0,0.0,-scale.z)), RT_Vec4Make(1.0, 0.0, 0.0, 1.0)); + RT_RasterLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Make(scale.x,0.0,0.0)), RT_Vec4Make(1.0, 0.0, 0.0, 1.0)); + RT_RasterLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Make(-scale.x,0.0,0.0)), RT_Vec4Make(1.0, 0.0, 0.0, 1.0)); + RT_RasterLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Make(0.0,scale.y,0.0)), RT_Vec4Make(1.0, 0.0, 0.0, 1.0)); + RT_RasterLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Make(0.0,-scale.y,0.0)), RT_Vec4Make(1.0, 0.0, 0.0, 1.0)); + RT_RasterLineWorld(pos, RT_Vec3Add(pos, RT_Vec3Make(0.0,0.0,scale.z)), RT_Vec4Make(1.0, 0.0, 0.0, 1.0)); + 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 diff --git a/RT/Game/Lights.h b/RT/Game/Lights.h index 86b346d..7dff805 100644 --- a/RT/Game/Lights.h +++ b/RT/Game/Lights.h @@ -9,6 +9,11 @@ bool g_pending_light_update; bool g_light_visual_debug; int g_active_lights; +// Light multiplier to tweak brightness of all the lights. +// Because this might change in runtime (end of level sequence), the ImGui windows should make use of the g_light_multiplier_default. +float g_light_multiplier; +// Default light multiplier (not changed during runtime) +float g_light_multiplier_default; typedef struct RT_LightDefinition { diff --git a/RT/Game/level.c b/RT/Game/level.c index 32ac83e..f204c93 100644 --- a/RT/Game/level.c +++ b/RT/Game/level.c @@ -29,7 +29,10 @@ RT_Light m_lights[1024] = {0}; int m_lights_definitions[1024] = {0}; side* m_extracted_light_sides[1024] = {0}; -void RT_ExtractLightsFromSide(side *side, RT_Vertex *vertices, RT_Vec3 normal); +short m_lights_seg_ids[1024] = {-1}; +short m_lights_relevance_score[1024] = { 0.0f }; +short m_lights_to_sort[1024]; +int m_lights_found = 0; RT_Triangle RT_TriangleFromIndices(RT_Vertex* verts, int vert_offset, int v0, int v1, int v2, int tmap) { @@ -60,6 +63,53 @@ RT_Triangle RT_TriangleFromIndices(RT_Vertex* verts, int vert_offset, int v0, in return triangle; } +void RT_ExtractLightsFromSide(side *side, RT_Vertex *vertices, RT_Vec3 normal, int seg_id) +{ + int light_index = RT_IsLight(side->tmap_num2); + if (light_index > -1) + { + RT_Vec2 uv_min = RT_Vec2Make(INFINITY, INFINITY); + RT_Vec2 uv_max = RT_Vec2Make(-INFINITY, -INFINITY); + for (int i = 0; i < 4; i++) + { + RT_Vec2 uv = RT_Vec2Make((f2fl(side->uvls[i].u)),(f2fl(side->uvls[i].v))); + + uv_min = RT_Vec2Min(uv, uv_min); + uv_max = RT_Vec2Max(uv, uv_max); + } + + bool multiple_lights = false; + if(uv_min.x < -1.0 || uv_min.y < -1.0 || uv_max.x > 1.0 || uv_max.y > 1.0) + { + RT_Vec2 uv = RT_Vec2Sub(uv_max, uv_min); + RT_Vec2 light_size = g_light_definitions[light_index].size; + + int num_x = max((int)(uv.x / light_size.x),1); + int num_y = max((int)(uv.y / light_size.y),1); + + RT_LOGF(RT_LOGSERVERITY_INFO, "Creating lights in the following directions. {X: %i, Y: %i}", num_x, num_y); + if(num_x > 1 && num_y > 1) + { + RT_LOGF(RT_LOGSERVERITY_INFO, "Multiple lights created!"); + multiple_lights = true; + } + } + + if (!multiple_lights) + { + if (ALWAYS(m_light_count < RT_ARRAY_COUNT(m_lights))) + { + m_lights[m_light_count] = RT_InitLight(g_light_definitions[light_index], vertices, normal); + m_lights_definitions[m_light_count] = light_index; + m_extracted_light_sides[m_light_count] = side; + + m_lights_seg_ids[m_light_count] = seg_id; + m_light_count++; + } + } + } +} + RT_ResourceHandle RT_UploadLevelGeometry() { RT_ResourceHandle level_handle = {0}; @@ -69,6 +119,11 @@ RT_ResourceHandle RT_UploadLevelGeometry() RT_Vertex* verts = RT_ArenaAllocArray(&g_thread_arena, Num_segments * 6 * 4, RT_Vertex); RT_Triangle* triangles = RT_ArenaAllocArray(&g_thread_arena, Num_segments * 6 * 2, RT_Triangle); + // Init lights segment id list + for (size_t i = 0; i < _countof(m_lights_seg_ids); ++i) { + m_lights_seg_ids[i] = -1; + } + int num_verts = 0; int num_indices = 0; int num_triangles = 0; @@ -110,7 +165,7 @@ RT_ResourceHandle RT_UploadLevelGeometry() verts[vertex_offset + v] = vert; num_verts++; - assert(vert.uv.x >= -10.0 && vert.uv.x <= 10.0); + //assert(vert.uv.x >= -10.0 && vert.uv.x <= 10.0); } // Ignore invisible walls @@ -135,7 +190,7 @@ RT_ResourceHandle RT_UploadLevelGeometry() triangles[num_triangles++] = RT_TriangleFromIndices(verts, vertex_offset, 0, 1, 2, absolute_side_index); triangles[num_triangles++] = RT_TriangleFromIndices(verts, vertex_offset, 0, 2, 3, absolute_side_index); - RT_ExtractLightsFromSide(s, &verts[vertex_offset], triangles[num_triangles-1].normal0); + RT_ExtractLightsFromSide(s, &verts[vertex_offset], triangles[num_triangles - 1].normal0, seg_id); } } @@ -157,116 +212,44 @@ RT_ResourceHandle RT_UploadLevelGeometry() return level_handle; } -void RT_ExtractLightsFromSide(side *side, RT_Vertex *vertices, RT_Vec3 normal) +bool RT_UnloadLevel() { - int light_index = RT_IsLight(side->tmap_num2); - if (light_index > -1) + // Only unload if a level acceleration structure actually exists + if (RT_RESOURCE_HANDLE_VALID(g_level_resource)) { - RT_Vec2 uv_min = RT_Vec2Make(INFINITY, INFINITY); - RT_Vec2 uv_max = RT_Vec2Make(-INFINITY, -INFINITY); - for (int i = 0; i < 4; i++) - { - RT_Vec2 uv = RT_Vec2Make((f2fl(side->uvls[i].u)),(f2fl(side->uvls[i].v))); - - uv_min = RT_Vec2Min(uv, uv_min); - uv_max = RT_Vec2Max(uv, uv_max); - } + RT_ReleaseMesh(g_level_resource); + g_level_resource = RT_RESOURCE_HANDLE_NULL; - bool multiple_lights = false; - if(uv_min.x < -1.0 || uv_min.y < -1.0 || uv_max.x > 1.0 || uv_max.y > 1.0) - { - RT_Vec2 uv = RT_Vec2Sub(uv_max, uv_min); - RT_Vec2 light_size = g_light_definitions[light_index].size; - - int num_x = max((int)(uv.x / light_size.x),1); - int num_y = max((int)(uv.y / light_size.y),1); + m_light_count = 0; + memset(m_lights, 0, sizeof(RT_Light) * 1024); - RT_LOGF(RT_LOGSERVERITY_INFO, "Creating lights in the following directions. {X: %i, Y: %i}", num_x, num_y); - if(num_x > 1 && num_y > 1) - { - RT_LOGF(RT_LOGSERVERITY_INFO, "Multiple lights created!"); - multiple_lights = true; - } - } - - if (!multiple_lights) - { - if (ALWAYS(m_light_count < RT_ARRAY_COUNT(m_lights))) - { - m_lights[m_light_count] = RT_InitLight(g_light_definitions[light_index], vertices, normal); - m_lights_definitions[m_light_count] = light_index; - m_extracted_light_sides[m_light_count] = side; - m_light_count++; - } - } + return true; } + + return false; } bool RT_LoadLevel() { + // Load a level only if a level acceleration structure does not exist yet + if (!RT_RESOURCE_HANDLE_VALID(g_level_resource)) + { + assert(!RT_RESOURCE_HANDLE_VALID(g_level_resource)); + // Load level geometry + g_level_resource = RT_UploadLevelGeometry(); + g_active_level = Current_level_num; + return RT_RESOURCE_HANDLE_VALID(g_level_resource); + } - assert(!RT_RESOURCE_HANDLE_VALID(g_level_resource)); - // Load level geometry - g_level_resource = RT_UploadLevelGeometry(); - g_active_level = Current_level_num; - - return RT_RESOURCE_HANDLE_VALID(g_level_resource); + return false; } void RT_RenderLevel(RT_Vec3 player_pos) { // ------------------------------------------------------------------ - // TODO(daniel): Figure out the right time to update these arrays - - RT_MaterialEdge *g_rt_material_edges = RT_GetMaterialEdgesArray(); - uint16_t *g_rt_material_indices = RT_GetMaterialIndicesArray(); - - for (int segment_index = 0; segment_index < Num_segments; segment_index++) - { - segment *seg = &Segments[segment_index]; - - for (int side_index = 0; side_index < MAX_SIDES_PER_SEGMENT; side_index++) - { - side *sd = &seg->sides[side_index]; - - int absolute_side_index = MAX_SIDES_PER_SEGMENT*segment_index + side_index; - - RT_MaterialEdge *side_edge = &g_rt_material_edges[absolute_side_index]; - side_edge->mat1 = sd->tmap_num; - side_edge->mat2 = sd->tmap_num2; - } - } - - for (int texture_index = 0; texture_index < MAX_TEXTURES; texture_index++) - { - g_rt_material_indices[texture_index] = Textures[texture_index].index; - } - - for (int texture_index = 0; texture_index < MAX_OBJ_BITMAPS; texture_index++) - { - g_rt_material_indices[texture_index + MAX_TEXTURES] = ObjBitmaps[texture_index].index; - } - - // The way this system was set up is really not the best, this is my hack to easily - // use these special built in materials in other code. - g_rt_material_indices[RT_MATERIAL_FLAT_WHITE] = RT_MATERIAL_FLAT_WHITE; - g_rt_material_indices[RT_MATERIAL_EMISSIVE_WHITE] = RT_MATERIAL_EMISSIVE_WHITE; - - // ------------------------------------------------------------------ - - // Unload current level if other level becomes active. - if (g_active_level != Current_level_num && RT_RESOURCE_HANDLE_VALID(g_level_resource)) - { - RT_UnloadLevel(); - } - - // Load level if not loaded. - // TODO: RT_LoadLevel should be called after menu interactions, this should be removed at some point. - if (!RT_RESOURCE_HANDLE_VALID(g_level_resource)) - { - RT_LoadLevel(); - } + RT_UpdateMaterialEdges(); + RT_UpdateMaterialIndices(); RT_FindAndSubmitNearbyLights(player_pos); @@ -274,15 +257,84 @@ void RT_RenderLevel(RT_Vec3 player_pos) RT_RaytraceMesh(g_level_resource, &mat, &mat); } -bool RT_UnloadLevel() -{ - RT_ReleaseMesh(g_level_resource); - g_level_resource = RT_RESOURCE_HANDLE_NULL; +void TraverseSegmentsForLights(short seg_num, uint8_t* visit_list, uint8_t* lights_added, int curr_rec_depth, RT_Vec3 curr_seg_entry_pos, float curr_segment_distance) { + // Did we reach max recursion depth already? then we skip + if (curr_rec_depth >= max_rec_depth) + return; + + // Did we visit this segment already? then we skip it + if (visit_list[seg_num] == 1) + return; + + // Mark this segment as visited + visit_list[seg_num] = 1; + + // For the current segment, go over all the sides + segment* seg = &Segments[seg_num]; + for (size_t i = 0; i < MAX_SIDES_PER_SEGMENT; ++i) { + // Assuming that RENDPAST means "render past this wall", if that is 0, we stop the traversal here + const int wid = WALL_IS_DOORWAY(seg, i); + if ((wid & WID_RENDPAST_FLAG) == 0) + continue; + + // Get the segment number of this child segment + const short seg_num_child = seg->children[i]; + + // If it's -1 or -2, there is no segment on this side, skip it + if (seg_num_child < 0) + continue; + + // Upload all the lights in this segment + for (int j = 0; j < m_light_count; ++j) { + // Filter out lights that aren't in this segment + if (m_lights_seg_ids[j] == -1) + continue; + if (m_lights_seg_ids[j] != seg_num_child) + continue; + + // Filter out lights that have already been added - this should fix the issue with lights being added twice + if (lights_added[j] != 0) + continue; + + // Filter out lights that are too far away from the camera - direct path + const float distance_from_player = RT_Vec3Length(RT_Vec3Sub(RT_Vec3Fromvms_vector(&Viewer->pos), RT_TranslationFromMat34(m_lights[j].transform))); + if (distance_from_player > max_distance) + continue; + + // Filter out lights that are too far away from the camera - segment distance - this is broken, don't use it + //const float distance_from_seg_entry_pos = RT_Vec3Length(RT_Vec3Sub(curr_seg_entry_pos, RT_TranslationFromMat34(m_lights[j].transform))); + //if (distance_from_seg_entry_pos > max_seg_distance) + // continue; + + // Mark this light as added + lights_added[j] = 1; + + // The lower the value, the more relevant the light is + m_lights_relevance_score[m_lights_found] = (float)curr_rec_depth; + m_lights_to_sort[m_lights_found] = j; + ++m_lights_found; + + } + + // Find the current segment's side's vertices + RT_Vec3 verts[4]; + for (size_t j = 0; j < _countof(Side_to_verts_int[j]); ++j) { + // Get one of the vertices of the side + verts[j] = RT_Vec3Fromvms_vector(&Vertices[Segments[seg_num_child].verts[Side_to_verts_int[i][j]]]); + } + + // Calculate center + const RT_Vec3 tmp1 = RT_Vec3Add(verts[0], verts[1]); + const RT_Vec3 tmp2 = RT_Vec3Add(verts[2], verts[3]); + const RT_Vec3 center = RT_Vec3Add(tmp1, tmp2); - m_light_count = 0; - memset(m_lights, 0, sizeof(RT_Light) * 1024); + // Find distance between segment entry + const RT_Vec3 vector_from_entry_to_curr_segment = RT_Vec3Sub(center, curr_seg_entry_pos); + const float distance_from_entry_to_curr_segment_squared = RT_Vec3Length(vector_from_entry_to_curr_segment); - return true; + // Traverse all the children + TraverseSegmentsForLights(seg_num_child, visit_list, lights_added, curr_rec_depth + 1, center, distance_from_entry_to_curr_segment_squared); + } } void RT_UpdateLight(int index) @@ -294,7 +346,7 @@ void RT_UpdateLight(int index) light->spot_angle = RT_Uint8FromFloat(definition.spot_angle); light->spot_softness = RT_Uint8FromFloat(definition.spot_softness); - light->emission = RT_PackRGBE(definition.emission); + light->emission = RT_PackRGBE(RT_Vec3Muls(definition.emission, g_light_multiplier)); if(light->kind == RT_LightKind_Area_Sphere) { @@ -317,12 +369,9 @@ void RT_UpdateLight(int index) void RT_FindAndSubmitNearbyLights(RT_Vec3 player_pos) { - // NOTE(daniel): I rewrote this to call RT_RaytraceSubmitLight because I updated that API - // to allow you to incrementally submit lights. This way, no extra array has to be - // made and you can just submit lights so long as you don't exceed the maximum. - int total = 0; - for (int i = 0; i < m_light_count; i++) + + for (int i = 0; i < m_light_count; i++) { if (g_pending_light_update) { @@ -333,17 +382,61 @@ void RT_FindAndSubmitNearbyLights(RT_Vec3 player_pos) { RT_VisualizeLight(&m_lights[i]); } + } - //TODO: Replace with better culling heuristic - float distance = RT_Vec3Length(RT_Vec3Sub(RT_TranslationFromMat34(m_lights[i].transform), player_pos)); - if (distance < 200.0) + if (light_culling_heuristic == 0){ + for (int i = 0; i < m_light_count; i++) { - RT_RaytraceSubmitLight(m_lights[i]); - total++; + const float distance = RT_Vec3Length(RT_Vec3Sub(RT_TranslationFromMat34(m_lights[i].transform), player_pos)); + if (distance < max_distance) + { + RT_RaytraceSubmitLight(m_lights[i]); + total++; + } } + } + // Segment based + else if (light_culling_heuristic == 1) { + const auto max_lights = RT_MAX_LIGHTS - RT_RaytraceGetCurrentLightCount(); // keep some room for dynamic lights + m_lights_found = 0; + uint8_t visit_list[MAX_SEGMENTS] = { 0 }; + uint8_t lights_added[_countof(m_lights)] = { 0 }; + + // Find all the lights that the player has a direct path towards + TraverseSegmentsForLights(Viewer->segnum, visit_list, lights_added, 0, RT_Vec3Fromvms_vector(&Viewer->pos), 0.0f); + + // If the number of lights exceeds the max number of lights, we need to pick the best ones + if (m_lights_found > max_lights) { + // Bubble sort them based on segment distance. We want the ones with the lowest number to appear first in the list + for (int end = m_lights_found - 1; end > 0; --end) { + for (int i = 0; i < end; ++i) { + if (m_lights_relevance_score[i + 0] > m_lights_relevance_score[i + 1]) { + // Swap the scores + const short temp1 = m_lights_relevance_score[i + 0]; + m_lights_relevance_score[i + 0] = m_lights_relevance_score[i + 1]; + m_lights_relevance_score[i + 1] = temp1; + + // Swap the indices in the list + const short temp2 = m_lights_to_sort[i + 0]; + m_lights_to_sort[i + 0] = m_lights_to_sort[i + 1]; + m_lights_to_sort[i + 1] = temp2; + } + } + } + + // We only want to upload the best ones + m_lights_found = max_lights; + } + + total = m_lights_found; + + // Submit the lights + for (int i = 0; i < m_lights_found; ++i) { + RT_RaytraceSubmitLight(m_lights[m_lights_to_sort[i]]); + } } - + g_pending_light_update = false; g_active_lights = total; } \ No newline at end of file diff --git a/RT/RText.h b/RT/RText.h index 08fc5d2..6f3591c 100644 --- a/RT/RText.h +++ b/RT/RText.h @@ -1,24 +1,25 @@ -/* - * - * RT standard Extensions of the descent engine. - * - */ - -#ifndef _RT_EXT_H -#define _RT_EXT_H - -#ifdef RT_DX12 -#define _RT_DRAW_POLY const int objNum, ubyte object_type, -#define _RT_DRAW_POLY_SEND obj->objNum, obj->type, -#define _RT_DRAW_POLY_SEND_NULL 0, OBJ_NONE, -#else -#define _RT_DRAW_POLY -#define _RT_DRAW_POLY_SEND -#define _RT_DRAW_POLY_SEND_NULL -#endif - - //Pauses the game without showing a window like do_pause does in gamecntl.c - //TODO, maybe still resume the renderer if that is blocking it. -int RT_DoRealPause(); - +/* + * + * RT standard Extensions of the descent engine. + * + */ + +#ifndef _RT_EXT_H +#define _RT_EXT_H + +#ifdef RT_DX12 +// NOTE(daniel): This makes me very sad I wish it didn't exist +#define _RT_DRAW_POLY const int signature, ubyte object_type, +#define _RT_DRAW_POLY_SEND obj->signature, obj->type, +#define _RT_DRAW_POLY_SEND_NULL 0, OBJ_NONE, +#else +#define _RT_DRAW_POLY +#define _RT_DRAW_POLY_SEND +#define _RT_DRAW_POLY_SEND_NULL +#endif + + //Pauses the game without showing a window like do_pause does in gamecntl.c + //TODO, maybe still resume the renderer if that is blocking it. +int RT_DoRealPause(); + #endif //_RT_EXT_H \ No newline at end of file diff --git a/RT/RTgr.c b/RT/RTgr.c index 906e831..da30703 100644 --- a/RT/RTgr.c +++ b/RT/RTgr.c @@ -1,1060 +1,1261 @@ -#include "gr.h" -#include "internal.h" -#include "RTgr.h" -#include "u_mem.h" -#include "config.h" -#include "args.h" -#include "palette.h" -#include "3d.h" -#include "segment.h" -#include "maths.h" -#include "dxxerror.h" -#include "polyobj.h" -#include "logger.h" -#include "maths.h" -#include "hudmsg.h" -#include "text.h" -#include "render.h" -#include "gamefont.h" -#include "piggy.h" - -#include "Core/Arena.h" -#include "Core/MiniMath.h" - -#include -#include - -#include "dx12.h" -#include "globvars.h" -#include "GLTFLoader.h" -#include "rle.h" -#include "textures.h" -#include "object.h" -#include -#include -#include - -#include "ImageReadWrite.h" -#include "RTmaterials.h" -#include "polymodel_viewer.h" -#include "material_viewer.h" -#include "Game/Lights.h" - -#include "vers_id.h" - -#pragma warning(error: 4431) // default-int (variables) -#pragma warning(error: 4013) // default-int (function returns) - -int sdl_video_flags = 0; -bool g_rt_enable_debug_menu; -RT_GLTFNode* g_rt_cockpit_gltf; - -uint64_t g_rt_frame_index; - -// #define RT_DUMP_GAME_BITMAPS - -#define BM_RTDX12 5 //whatever value, replaces BM_OGL. - -RT_ResourceHandle mesh_handles[MAX_POLYGON_MODELS]; - -RT_Mat4 old_poly_matrix[MAX_OBJECTS]; - -#define OP_EOF 0 //eof -#define OP_DEFPOINTS 1 //defpoints -#define OP_FLATPOLY 2 //flat-shaded polygon -#define OP_TMAPPOLY 3 //texture-mapped polygon -#define OP_SORTNORM 4 //sort by normal -#define OP_RODBM 5 //rod bitmap -#define OP_SUBCALL 6 //call a subobject -#define OP_DEFP_START 7 //defpoints with start -#define OP_GLOW 8 //glow value for next poly - -#define MAX_POINTS_PER_POLY 25 -//Some jank inherited from interp.c, might change it but likely not. -g3s_point* point_list[MAX_POINTS_PER_POLY]; - - -#define w(p) (*((short *) (p))) -#define wp(p) ((short *) (p)) -#define fp(p) ((fix *) (p)) -#define vp(p) ((vms_vector *) (p)) - -//some defines -int gr_installed = 0; -int gl_initialized = 0; -int linedotscale = 1; // scalar of glLinewidth and glPointSize - only calculated once when resolution changes -int sdl_no_modeswitch = 0; - -RT_Arena g_arena = { 0 }; - -int gr_list_modes(u_int32_t gsmodes[]) -{ - SDL_Rect** modes; - int i = 0, modesnum = 0; - - int sdl_check_flags = SDL_FULLSCREEN; // always use Fullscreen as lead. - - modes = SDL_ListModes(NULL, sdl_check_flags); - - if (modes == (SDL_Rect**)0) // check if we get any modes - if not, return 0 - return 0; - - - if (modes == (SDL_Rect**)-1) - { - return 0; // can obviously use any resolution... strange! - } - else - { - for (i = 0; modes[i]; ++i) - { - if (modes[i]->w > 0xFFF0 || modes[i]->h > 0xFFF0 // resolutions saved in 32bits. so skip bigger ones (unrealistic in 2010) (changed to 0xFFF0 to fix warning) - || modes[i]->w < 320 || modes[i]->h < 200) // also skip everything smaller than 320x200 - continue; - gsmodes[modesnum] = SM(modes[i]->w, modes[i]->h); - modesnum++; - if (modesnum >= 50) // that really seems to be enough big boy. - break; - } - return modesnum; - } -} - -int gr_check_mode(u_int32_t mode) -{ - unsigned int w, h; - - w = SM_W(mode); - h = SM_H(mode); - - if (sdl_no_modeswitch == 0) { - return SDL_VideoModeOK(w, h, GameArg.DbgBpp, 0); - } - else { - // just tell the caller that any mode is valid... - return 32; - } -} - -int gr_set_mode(u_int32_t mode) -{ - unsigned int w, h; - char* gr_bm_data; - - if (mode <= 0) - return 0; - - w = SM_W(mode); - h = SM_H(mode); - - GameCfg.ResolutionX = w; - GameCfg.ResolutionY = h; - - if (!gr_check_mode(mode)) - { - RT_LOGF(RT_LOGSERVERITY_HIGH, "Cannot set %ix%i. Fallback to 640x480\n", w, h); - w = 640; - h = 480; - Game_screen_mode = mode = SM(w, h); - } - - gr_bm_data = (char*)grd_curscreen->sc_canvas.cv_bitmap.bm_data;//since we use realloc, we want to keep this pointer around. - memset(grd_curscreen, 0, sizeof(grs_screen)); - grd_curscreen->sc_mode = mode; - grd_curscreen->sc_w = w; - grd_curscreen->sc_h = h; - grd_curscreen->sc_aspect = fixdiv(GameCfg.AspectX, GameCfg.AspectY); - gr_init_canvas(&grd_curscreen->sc_canvas, d_realloc(gr_bm_data, w * h), BM_RTDX12, w, h); - gr_set_current_canvas(NULL); - - if (w != last_width || h != last_height) - { - last_width = w; - last_height = h; - } - - //Set the video or resize it. The renderer handles the resize event. - SDL_SetVideoMode(w, h, 32, sdl_video_flags); - RT_RasterSetViewport(0.0f, 0.0f, w, h); - gamefont_choose_game_font(w, h); - - return 0; -} - -/* - * 2d Sprites (Fireaballs, powerups, explosions). NOT hostages - */ -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); - - RT_Vec2 rt_dim = { f2fl(width), f2fl(height) }; - RT_Vec3 rt_pos = RT_Vec3Fromvms_vector(pos); - - RT_RaytraceBillboardColored(material_index, RT_Vec3Make(r, g, b), rt_dim, rt_pos, rt_pos); - - return 0; -} - -void draw_object_tmap_rod(object *obj, bitmap_index bmi, int lighted) -{ - float size = f2fl(obj->size); - - vms_vector delta; - vm_vec_copy_scale(&delta,&obj->orient.uvec,obj->size); - - vms_vector top_v; - vm_vec_add(&top_v,&obj->pos,&delta); - - vms_vector bot_v; - vm_vec_sub(&bot_v,&obj->pos,&delta); - - RT_Vec3 bot_p = RT_Vec3Fromvms_vector(&bot_v); - RT_Vec3 top_p = RT_Vec3Fromvms_vector(&top_v); - - RT_RaytraceRod(bmi.index, bot_p, top_p, f2fl(obj->size)); -} - -bool g3_draw_bitmap_colorwarp(vms_vector* pos, fix width, fix height, grs_bitmap* bm, - float r, float g, float b) -{ - return g3_draw_bitmap_full(pos, width, height, bm, r, g, b); -} - -bool g3_draw_bitmap(vms_vector *pos, fix width, fix height, grs_bitmap *bm) -{ - return g3_draw_bitmap_full(pos, width, height, bm, 1, 1, 1); -} - -void gr_set_attributes(void) -{ - //Nothing for us to do here -} - -void gr_close(void) -{ - RT_RendererExit(); -} - -void gr_palette_load(ubyte* pal) -{ - int i; - - for (i = 0; i < 768; i++) - { - gr_current_pal[i] = pal[i]; - if (gr_current_pal[i] > 63) - gr_current_pal[i] = 63; - } - - gr_palette_step_up(0, 0, 0); // make ogl_setbrightness_internal get run so that menus get brightened too. - init_computed_colors(); -} - -void gr_palette_read(ubyte* pal) -{ - int i; - for (i = 0; i < 768; i++) - { - pal[i] = gr_current_pal[i]; - if (pal[i] > 63) - pal[i] = 63; - } -} - -int screen_flash_mul = 1; - -void gr_palette_step_up(int r, int g, int b) -{ - RT_Vec4 screen_flash_color = { 0, 0, 0, 1 }; - - r = r * screen_flash_mul; - g = g * screen_flash_mul; - b = b * screen_flash_mul; - - screen_flash_color.x = (float)max((r + gr_palette_gamma), 0); - screen_flash_color.y = (float)max((g + gr_palette_gamma), 0); - screen_flash_color.z = (float)max((b + gr_palette_gamma), 0); - - screen_flash_color.x = screen_flash_color.x / 63.0f; - screen_flash_color.y = screen_flash_color.y / 63.0f; - screen_flash_color.z = screen_flash_color.z / 63.0f; - - RT_RendererIO* io = RT_GetRendererIO(); - io->screen_overlay_color = screen_flash_color; -} - -void gr_flip(void) -{ - //flip - RT_RasterRender(); - RT_RenderImGui(); - RT_SwapBuffers(); -} - -int gr_check_fullscreen(void) -{ - //Check if screen is fullscreen, add this option to the renderer itself. - return (sdl_video_flags & SDL_FULLSCREEN) ? 1 : 0; -} - -int gr_toggle_fullscreen(void) -{ - //Send call to renderer to make it full screen. - if (sdl_video_flags & SDL_FULLSCREEN) - sdl_video_flags &= ~SDL_FULLSCREEN; - else - sdl_video_flags |= SDL_FULLSCREEN; - - if (!SDL_SetVideoMode(SM_W(Game_screen_mode), SM_H(Game_screen_mode), GameArg.DbgBpp, sdl_video_flags)) - { - // Setting video mode went wrong - } - - GameCfg.WindowMode = (sdl_video_flags & SDL_FULLSCREEN) ? 0 : 1; - return (sdl_video_flags & SDL_FULLSCREEN)?1:0; -} - -void gr_upoly_tmap(int nverts, int* vert) -{ - //never call this, maybe log this like DXX-Retro does in arch/ogl.c? - RT_LOG(RT_LOGSERVERITY_HIGH, "gr_upoly_tmap: unhandled"); -} - -void draw_tmap_flat(grs_bitmap* bm, int nv, g3s_point** vertlist) -{ - //never call this, maybe log this like DXX-Retro does in arch/ogl.c? - RT_LOG(RT_LOGSERVERITY_HIGH, "draw_tmap_flat: unhandled"); -} - -int gr_init(int mode) -{ - SDL_WM_SetCaption(DESCENT_VERSION, "Descent"); - //Note SAM: Maybe we can create our own bmp later on, would be cool. - SDL_WM_SetIcon(SDL_LoadBMP("dxx-raytracer.bmp"), NULL); - - if (!GameCfg.WindowMode && !GameArg.SysWindow) - sdl_video_flags |= SDL_FULLSCREEN; - - if (GameArg.SysNoBorders) - sdl_video_flags |= SDL_NOFRAME; - - MALLOC(grd_curscreen, grs_screen, 1); - memset(grd_curscreen, 0, sizeof(grs_screen)); - grd_curscreen->sc_canvas.cv_bitmap.bm_data = NULL; - - grd_curscreen->sc_canvas.cv_color = 0; - grd_curscreen->sc_canvas.cv_fade_level = GR_FADE_OFF; - grd_curscreen->sc_canvas.cv_blend_func = GR_BLEND_NORMAL; - grd_curscreen->sc_canvas.cv_drawmode = 0; - grd_curscreen->sc_canvas.cv_font = NULL; - grd_curscreen->sc_canvas.cv_font_fg_color = 0; - grd_curscreen->sc_canvas.cv_font_bg_color = 0; - gr_set_current_canvas(&grd_curscreen->sc_canvas); - - unsigned int w, h; - w = SM_W(mode); - h = SM_H(mode); - - //Init video here, sadly it's wrong but it will be resized in gr_set_mode. - SDL_Surface* surf = SDL_SetVideoMode(w, h, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_ANYFORMAT); - - SDL_EventState(SDL_IGNORE, NULL); - RT_RendererInitParams initParams; - SDL_SysWMinfo info; - - SDL_VERSION(&info.version); - SDL_GetWMInfo(&info); - - initParams.arena = &g_arena; - initParams.window_handle = info.window; - - igCreateContext(NULL); - - ImGuiIO *io = igGetIO(); - io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; - io->Fonts->Flags |= ImFontAtlasFlags_NoBakedLines; - - igInitWin32(info.window); - RT_RendererInit(&initParams); - - return 0; -} - -void RT_VertexFixToFloat_Fan(RT_TriangleBuffer *buf, int nv, g3s_point** pointlist, uint16_t texture_id, uint32_t triangle_color) -{ - RT_Triangle first_triangle = {0}; - - first_triangle.pos0.x = f2fl(pointlist[0]->p3_vec.x); - first_triangle.pos0.y = f2fl(pointlist[0]->p3_vec.y); - first_triangle.pos0.z = f2fl(pointlist[0]->p3_vec.z); - - first_triangle.uv0.x = f2fl(pointlist[0]->p3_u); - first_triangle.uv0.y = f2fl(pointlist[0]->p3_v); - - first_triangle.color = triangle_color; - - RT_ASSERT(texture_id & RT_TRIANGLE_HOLDS_MATERIAL_EDGE); - - first_triangle.material_edge_index = texture_id; - - int start_count = buf->count; - - for (int point_index = 1; point_index + 1 < nv; point_index++) - { - RT_Triangle triangle = first_triangle; - - triangle.pos1.x = f2fl(pointlist[point_index]->p3_vec.x); - triangle.pos1.y = f2fl(pointlist[point_index]->p3_vec.y); - triangle.pos1.z = f2fl(pointlist[point_index]->p3_vec.z); - - triangle.uv1.x = f2fl(pointlist[point_index]->p3_u); - triangle.uv1.y = f2fl(pointlist[point_index]->p3_v); - - triangle.pos2.x = f2fl(pointlist[point_index + 1]->p3_vec.x); - triangle.pos2.y = f2fl(pointlist[point_index + 1]->p3_vec.y); - triangle.pos2.z = f2fl(pointlist[point_index + 1]->p3_vec.z); - - triangle.uv2.x = f2fl(pointlist[point_index + 1]->p3_u); - triangle.uv2.y = f2fl(pointlist[point_index + 1]->p3_v); - - triangle.material_edge_index = texture_id; - - //Now do the normals - RT_Vec3 p10 = RT_Vec3Normalize(RT_Vec3Sub(triangle.pos1, triangle.pos0)); - RT_Vec3 p20 = RT_Vec3Normalize(RT_Vec3Sub(triangle.pos2, triangle.pos0)); - - RT_Vec3 normal = RT_Vec3Normalize(RT_Vec3Cross(p10, p20)); - - triangle.normal0 = normal; - triangle.normal1 = normal; - triangle.normal2 = normal; - - RT_PushTriangle(buf, triangle); - } - - int end_count = buf->count; - - // NOTE(daniel): This is a separate call, because I don't want to do something tweaky like - // detecting whether tangents need to be calculated in RT_UploadMesh. You, the uploader, should know. - RT_GenerateTangents(&buf->triangles[start_count], end_count - start_count); -} - -void RT_SetPointList(g3s_point* dest, vms_vector* src, int n) -{ - // NOTE(daniel): Ok so for submodels I guess we're relying on behaviour related - // to the view matrix and position being set. Very janky intermingling of code - // meant for rasterization, but I guess that's that. So we need to rotate the - // points. - - while (n--) - g3_rotate_point(dest++, src++); -} - -vms_angvec zero_angles; - -g3s_point* point_list[MAX_POINTS_PER_POLY]; - -// NOTE(daniel): Here for hardcoding certain materials for flat polys -// for different meshes. It's not the best. -static int jank_currently_loading_poly_model; - -static void RT_GetPolyData(RT_TriangleBuffer *buf, - g3s_point *interp_point_list, - void *model_ptr, - vms_angvec *anim_angles, - int first_texture) -{ - ubyte* p = model_ptr; - - while (w(p) != OP_EOF) - { - switch (w(p)) - { - case OP_DEFPOINTS: - { - int n = w(p + 2); - - RT_SetPointList(interp_point_list, vp(p + 4), n); - p += n*sizeof(struct vms_vector) + 4; - } break; - - case OP_DEFP_START: - { - int n = w(p + 2); - int s = w(p + 4); - - RT_SetPointList(&interp_point_list[s], vp(p + 8), n); - p += n*sizeof(struct vms_vector) + 8; - } break; - - case OP_FLATPOLY: - { - int nv = w(p + 2); - - for (int i = 0; i < nv; i++) - { - point_list[i] = interp_point_list + wp(p + 30)[i]; - } - - short color = w(p + 28); - - // NOTE(daniel): I hope the palette is initialized correctly! - ubyte r = gr_palette[color*3 + 0]*4; - ubyte g = gr_palette[color*3 + 1]*4; - ubyte b = gr_palette[color*3 + 2]*4; - ubyte a = 255; - - // RGBA! - uint32_t color_packed = (r << 0)|(g << 8)|(b << 16)|(a << 24); - - int material_index = RT_MATERIAL_FLAT_WHITE|RT_TRIANGLE_HOLDS_MATERIAL_EDGE; - - // wow. good code. - - bool should_be_emissive = false; - - if (PCSharePig) - { - // pointy melee guy - if (jank_currently_loading_poly_model == 2) should_be_emissive = true; - if (jank_currently_loading_poly_model == 3) should_be_emissive = true; - - if (jank_currently_loading_poly_model == 8) should_be_emissive = true; - - if ((jank_currently_loading_poly_model >= 28 && - jank_currently_loading_poly_model <= 43) || - (jank_currently_loading_poly_model >= 46 && - jank_currently_loading_poly_model <= 47) || - (jank_currently_loading_poly_model >= 52 && - jank_currently_loading_poly_model <= 55)) - - { - should_be_emissive = true; - } - - } - else - { - // pointy melee guy - if (jank_currently_loading_poly_model == 2) should_be_emissive = true; - // pointy blue-purple guy - if (jank_currently_loading_poly_model == 7) should_be_emissive = true; - - if ((jank_currently_loading_poly_model >= 46 && - jank_currently_loading_poly_model <= 61) || - (jank_currently_loading_poly_model >= 63 && - jank_currently_loading_poly_model <= 67) || - (jank_currently_loading_poly_model >= 73 && - jank_currently_loading_poly_model <= 76)) - { - // Laser. - should_be_emissive = true; - } - } - - if (should_be_emissive) - { - material_index = RT_MATERIAL_EMISSIVE_WHITE|RT_TRIANGLE_HOLDS_MATERIAL_EDGE; - } - - RT_VertexFixToFloat_Fan(buf, nv, point_list, material_index, color_packed); - - p += 30 + ((nv & ~1) + 1) * 2; - } break; - - case OP_TMAPPOLY: - { - int nv = w(p + 2); - - Assert(nv < MAX_POINTS_PER_POLY); - - // Lights were done here previously, no needed now. - // NOTE(daniel): Again, that's nice, but do we know that we don't care about those light values? - // Are they used anywhere, or do we just ignore them entirely? (We might, and that might be - // totally valid). - - // Get the UV coordinates (allegedly) // NOTE(daniel): Why allegedly? - g3s_uvl* uvl_list = (g3s_uvl*)(p + 30 + ((nv & ~1) + 1) * 2); - - for (int i = 0; i < nv; i++) - { - point_list[i] = interp_point_list + wp(p + 30)[i]; - point_list[i]->p3_u = uvl_list[i].u; - point_list[i]->p3_v = uvl_list[i].v; - } - - // Get texture index - p+28 would be the magic offset for the texture id relative to first_texture - short texture_index = w(p + 28) + first_texture; - - // NOTE(daniel): For poly objects, RT_TRIANGLE_HOLDS_MATERIAL_EDGE is or'd into the material index - // assigned to the triangle to indicate to the renderer to skip the double indirection - // through the material edge array, because it's only needed for segments. - int material_index = (ObjBitmapPtrs[texture_index] + MAX_TEXTURES) | RT_TRIANGLE_HOLDS_MATERIAL_EDGE; - RT_VertexFixToFloat_Fan(buf, nv, point_list, material_index, 0xFFFFFFFF); - - p += 30 + ((nv & ~1) + 1) * 2 + nv * 12; - } break; - - case OP_SORTNORM: - { - if (g3_check_normal_facing(vp(p + 16), vp(p + 4)) > 0) // facing - { - // draw back then front - // NOTE(daniel): This is about sorting polys according to the view matrix, what does this - // have to do with loading models ahead of time? - RT_GetPolyData(buf, interp_point_list, p + w(p + 30), anim_angles, first_texture); - RT_GetPolyData(buf, interp_point_list, p + w(p + 28), anim_angles, first_texture); - - } - else // not facing. draw front then back - { - RT_GetPolyData(buf, interp_point_list, p + w(p + 28), anim_angles, first_texture); - RT_GetPolyData(buf, interp_point_list, p + w(p + 30), anim_angles, first_texture); - } - - p += 32; - } break; - - case OP_RODBM: - { - //Not needed here - p += 36; - } break; - - case OP_SUBCALL: - { - typedef struct RT_SubcallStruct - { - uint16_t opcode; // = OP_SUBCALL - uint16_t anim_angles_index; - vms_vector position_offset; - uint16_t model_ptr; - uint16_t unknown7; // always 0? - } RT_SubcallStruct; - - RT_SubcallStruct *command_data = (RT_SubcallStruct *)p; - - // Not needed here - // NOTE(daniel): If it's not needed here, why is it still here? - vms_angvec* a; - - if (anim_angles) - { - a = &anim_angles[command_data->anim_angles_index]; - } - else - { - a = &zero_angles; - } - - g3_start_instance_angles(&command_data->position_offset, a); - - RT_GetPolyData(buf, interp_point_list, p + command_data->model_ptr, anim_angles, first_texture); - - g3_done_instance(); - p += 20; - } break; - - case OP_GLOW: - { - // We aint doing glow here - // NOTE(daniel): Ok, but then where are the glow values going? When are they used? - // Should we care? - p += 4; - } break; - - default: - { - /* ... */ - } break; - } - } -} - -void RT_InitglTFModels(void) -{ - g_rt_cockpit_gltf = RT_LoadGLTF(&g_arena, "assets/cockpit_prototype.gltf"); -} - -void RT_InitBasePolyModel(const int polymodel_index, g3s_point* interp_point_list, void* model_ptr, vms_angvec* anim_angles, int first_texture) -{ - RT_ArenaMemoryScope(&g_thread_arena) - { - int triangle_buffer_size = 2048; - - RT_TriangleBuffer triangles = - { - .triangles = RT_ArenaAllocArray(&g_thread_arena, triangle_buffer_size, RT_Triangle), - .count = 0, - .capacity = triangle_buffer_size, - }; - - View_position = vmd_zero_vector; - View_matrix = vmd_identity_matrix; - - RT_GetPolyData(&triangles, interp_point_list, model_ptr, anim_angles, first_texture); - - if (triangles.count > 0) - { - mesh_handles[polymodel_index] = RT_UploadMesh(&(RT_UploadMeshParams){ - .triangles = triangles.triangles, - .triangle_count = triangles.count, - .name = RT_ArenaPrintF(&g_thread_arena, "Polymodel %d", polymodel_index), - }); - - // NOTE(daniel): If we're going to keep the triangles around for some hacking, we should - // make a copy to a permanent arena. - RT_UploadMeshParams hacky_params = - { - .triangles = RT_ArenaCopyArray(&g_arena, triangles.triangles, triangles.count), - .triangle_count = triangles.count, - }; - meshVerticesRawHack[polymodel_index] = hacky_params; - } - } -} - -RT_ResourceHandle RT_InitSubPolyModel(g3s_point* interp_point_list, void* model_ptr, vms_angvec* anim_angles, int first_texture) -{ - RT_ResourceHandle result = RT_RESOURCE_HANDLE_NULL; - - RT_ArenaMemoryScope(&g_thread_arena) - { - int triangle_buffer_size = 2048; - - RT_TriangleBuffer triangles = - { - .triangles = RT_ArenaAllocArray(&g_thread_arena, triangle_buffer_size, RT_Triangle), - .count = 0, - .capacity = triangle_buffer_size, - }; - - View_position = vmd_zero_vector; - View_matrix = vmd_identity_matrix; - - RT_GetPolyData(&triangles, interp_point_list, model_ptr, anim_angles, first_texture); - - if (triangles.count > 0) - { - result = RT_UploadMesh(&(RT_UploadMeshParams){ - .triangles = triangles.triangles, - .triangle_count = triangles.count, - .name = "Sub-Polymodel", - }); - } - } - - return result; -} - -void RT_InitPolyModelAndSubModels(int pm_index) -{ - polymodel *pm = &Polygon_models[pm_index]; - - // TODO(daniel): Figure out something better - jank_currently_loading_poly_model = pm_index; - - RT_InitBasePolyModel(pm_index, robot_points, pm->model_data, NULL, pm->first_texture); - for (size_t i = 0; i < pm->n_models; i++) - { - int t_ModelPtr = pm->submodel_ptrs[i]; - pm->submodel[i] = RT_InitSubPolyModel(robot_points, pm->model_data + t_ModelPtr, NULL, pm->first_texture); - } - - // TODO(daniel): Figure out something better - jank_currently_loading_poly_model = 0; - - // Find tree structure of submodels - memset(pm->model_tree, 0, sizeof(pm->model_tree)); - - for (int i = 0; i < pm->n_models; ++i) - { - // Parent - pm->model_tree[i].parent_index = pm->submodel_parents[i]; - - // Add this model's index to the list of child indices of the parent - if (pm->submodel_parents[i] != 255) - { - RT_ModelTree *parent = &pm->model_tree[pm->submodel_parents[i]]; - parent->child_indices[parent->n_children] = i; - parent->n_children++; - } - } -} - -void RT_InitAllPolyModels(void) -{ - for (int pm_index = 0; pm_index < N_polygon_models; pm_index++) - { - RT_InitPolyModelAndSubModels(pm_index); - } -} - -void RT_DrawPolyModel(const int meshnumber, const int objNum, ubyte object_type, const vms_vector* pos, const vms_matrix* orient) -{ - // NOTE(daniel): I am only seeing completely correct textures on enemies when I defer the loading of poly models - // to when they're actually being drawn. Not sure why, but I don't mind _except_ for that this causes stuttering. - // It could probably quite easily not cause stuttering with an architectural change in the renderer, or we can go - // find the best place to actually init the poly model. - - if (!RT_RESOURCE_HANDLE_VALID(mesh_handles[meshnumber])) - { - RT_InitPolyModelAndSubModels(meshnumber); - } - - if (RT_RESOURCE_HANDLE_VALID(mesh_handles[meshnumber])) - { - // Create model matrix - RT_Mat4 mat = RT_Mat4Identity(); - - // Apply translation - mat = RT_Mat4Mul(mat, RT_Mat4FromTranslation(RT_Vec3Fromvms_vector(pos))); - - // Apply rotation - RT_Mat4 rot = RT_Mat4Fromvms_matrix(orient); - mat = RT_Mat4Mul(mat, RT_Mat4Fromvms_matrix(orient)); - - assert(objNum > 0 || objNum < MAX_OBJECTS); - - RT_ResourceHandle handle = mesh_handles[meshnumber]; - - // Render mesh - RT_RaytraceMesh(handle, &mat, &old_poly_matrix[objNum]); - old_poly_matrix[objNum] = mat; - } -} - -void RT_DrawSubPolyModel(RT_ResourceHandle submodel, const RT_Mat4* const submodel_transform, const RT_Mat4* const submodel_transform_prev) -{ - if (RT_RESOURCE_HANDLE_VALID(submodel)) - { - RT_RaytraceMesh(submodel, submodel_transform, submodel_transform_prev); - } -} - -void RT_DrawPolySubModelTree(const polymodel* model, const vms_angvec* const anim_angles, int index, const int obj_num, const RT_Mat4 submodel_transform) -{ - RT_SubmodelTransforms* prev_transforms = &g_rt_prev_submodel_transforms[obj_num]; - - RT_Mat4 prev_transform = prev_transforms->transforms[index]; - - // NOTE (Sam) - // I think this is not an issue anymore as the double draw only happened when shooting the lasers. - // Even before we make a new system for the motion vectors it will still not effect anything. -#if 0 - typedef struct RT_ObjRenderDebug - { - uint64_t submodels[MAX_SUBMODELS]; - } RT_ObjRenderDebug; - static RT_ObjRenderDebug obj_num_last_frame_rendered[MAX_OBJECTS]; - if (g_rt_frame_index != 0 && obj_num_last_frame_rendered[obj_num].submodels[index] == g_rt_frame_index) - { - prev_transform = submodel_transform; - // NOTE(daniel): This issue of different rendered meshes not being properly uniquely identified will be fixed - // differently, so for now just render things twice and bust the motion vectors a little bit. - RT_LOGF(RT_LOGSERVERITY_INFO, "Submodel %d, %d was rendered more than once on frame %llu", obj_num, index, g_rt_frame_index); - - } - obj_num_last_frame_rendered[obj_num].submodels[index] = g_rt_frame_index; -#endif - - // Draw the submodel - RT_DrawSubPolyModel(model->submodel[index], &submodel_transform, &prev_transform); - prev_transforms->transforms[index] = submodel_transform; - - // Traverse tree structure - for (int i = 0; i < model->model_tree[index].n_children; ++i) { - // anim_angles is an array, where the indices into that array allegedly correspond directly to the child indices :D - const int child_index = model->model_tree[index].child_indices[i]; - - vms_angvec anim_angles_final; - if (anim_angles) { - anim_angles_final.p = anim_angles[child_index].p; - anim_angles_final.b = anim_angles[child_index].b; - anim_angles_final.h = anim_angles[child_index].h; - } - else { - anim_angles_final.p = zero_angles.p; - anim_angles_final.b = zero_angles.b; - anim_angles_final.h = zero_angles.h; - } - - // Get matrix from local position offset - const vms_vector offset_vms = model->submodel_offsets[child_index]; - const RT_Vec3 offset_vec3 = RT_Vec3Fromvms_vector(&offset_vms); - RT_Mat4 offset_mat4 = RT_Mat4FromTranslation(offset_vec3); - offset_mat4 = RT_Mat4Mul(submodel_transform, offset_mat4); - - // Get matrix from rotation offset - vms_matrix rotation_vms; - vm_angles_2_matrix(&rotation_vms, &anim_angles_final); - RT_Mat4 rotation_mat4 = RT_Mat4Fromvms_matrix(&rotation_vms); - - // Combine them into one big matrix - RT_Mat4 combined_matrix = RT_Mat4Mul(offset_mat4, rotation_mat4); - - RT_DrawPolySubModelTree(model, anim_angles, child_index, obj_num, combined_matrix); - } -} - -void RT_DrawPolyModelTree(const int meshnumber, const int objNum, ubyte object_type, const vms_vector* pos, const vms_matrix* orient, vms_angvec* anim_angles) { - if (!RT_RESOURCE_HANDLE_VALID(mesh_handles[meshnumber])) - { - RT_InitPolyModelAndSubModels(meshnumber); - } - - // Get model to render - polymodel* model = &Polygon_models[meshnumber]; - - // Get matrix from local position offset - const vms_vector offset_vms = *pos; - const RT_Vec3 offset_vec3 = RT_Vec3Fromvms_vector(&offset_vms); - RT_Mat4 offset_mat4 = RT_Mat4FromTranslation(offset_vec3); - - // Get matrix from rotation offset - RT_Mat4 rotation_mat4 = RT_Mat4Fromvms_matrix(orient); - - // Combine them into one big matrix - RT_Mat4 combined_matrix = RT_Mat4Mul(offset_mat4, rotation_mat4); - - RT_DrawPolySubModelTree(model, anim_angles, 0, objNum, combined_matrix); -} - -void RT_DrawGLTF(const RT_GLTFNode* node, RT_Mat4 transform, RT_Mat4 prev_transform) -{ - if (!node) - return; - - transform = RT_Mat4Mul(transform, node->transform); - prev_transform = RT_Mat4Mul(prev_transform, node->transform); - - if (node->model) - { - RT_GLTFModel* model = node->model; - RT_RaytraceMesh(model->handle, &transform, &prev_transform); - } - - for (size_t i = 0; i < node->children_count; i++) - { - RT_GLTFNode* child = node->children[i]; - RT_DrawGLTF(child, transform, prev_transform); - } -} - -void RT_StartImGuiFrame(void) -{ - igStartFrameWin32(); - igNewFrame(); - - if (g_rt_enable_debug_menu) - { - RT_DoRendererDebugMenuParams params = { - .ui_has_cursor_focus = true, - }; - RT_DoRendererDebugMenus(¶ms); - - if (igBegin("Dynamic Lights", NULL, 0)) - { - igPushID_Str("Dynamic Lights"); - igIndent(0); - - if (igCollapsingHeader_TreeNodeFlags("Weapon Light Settings", ImGuiTreeNodeFlags_None)) - { - igPushID_Str("Dynamic Lights"); - igIndent(0); - - if (igCollapsingHeader_TreeNodeFlags("Weapon Light Settings", ImGuiTreeNodeFlags_None)) - { - igPushID_Int(1); - 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("Flare Brightness modifier", &g_rt_dynamic_light_info.weaponFlareBrightMod, 0, 10000.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(2); - 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); - igPopID(); - } - if (igCollapsingHeader_TreeNodeFlags("Muzzle fire Light Settings", ImGuiTreeNodeFlags_None)) - { - igPushID_Int(3); - 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(); - igUnindent(0); - } - if (igCollapsingHeader_TreeNodeFlags("Miscellaneous", ImGuiTreeNodeFlags_None)) - { - igPushID_Str("Miscellaneous"); - igIndent(0); - - igSliderInt("Flash screen multiplier", &screen_flash_mul, 1, 100, "%d", 0); - - igPopID(); - igUnindent(0); - } - - igUnindent(0); - igPopID(); - } igEnd(); - - RT_ShowLightMenu(); - - RT_DoPolymodelViewerMenus(); - RT_DoMaterialViewerMenus(); - - // Moved to render.c! - // RT_RenderPolyModelViewer(); - // RT_RenderMaterialViewer(); - } -} - -void RT_EndImguiFrame(void) -{ - igRender(); - igEndFrame(); -} - -void save_screen_shot(int automap_flag) -{ - static int savenum=0; - char savename[FILENAME_LEN+sizeof(SCRNS_DIR)]; - - stop_time(); - - if (!PHYSFSX_exists(SCRNS_DIR,0)) - PHYSFS_mkdir(SCRNS_DIR); //try making directory - - do - { - sprintf(savename, "%sscrn%04d.png",SCRNS_DIR, savenum++); - } while (PHYSFSX_exists(savename,0)); - - if (!automap_flag) - HUD_init_message(HM_DEFAULT, "%s 'scrn%04d.png'", TXT_DUMPING_SCREEN, savenum-1 ); - - RT_QueueScreenshot(savename); - - start_time(); -} +#include "gr.h" +#include "internal.h" +#include "RTgr.h" +#include "u_mem.h" +#include "config.h" +#include "args.h" +#include "palette.h" +#include "3d.h" +#include "segment.h" +#include "maths.h" +#include "dxxerror.h" +#include "polyobj.h" +#include "logger.h" +#include "maths.h" +#include "hudmsg.h" +#include "text.h" +#include "render.h" +#include "gamefont.h" +#include "piggy.h" +#include "playsave.h" + +#include "Core/Arena.h" +#include "Core/MiniMath.h" +#include "Core/Config.h" +#include "Core/String.h" + +#include +#include + +#include "dx12.h" +#include "globvars.h" +#include "GLTFLoader.h" +#include "rle.h" +#include "textures.h" +#include "object.h" +#include +#include +#include + +#include "ImageReadWrite.h" +#include "RTmaterials.h" +#include "polymodel_viewer.h" +#include "material_viewer.h" +#include "Game/Lights.h" + +#include "vers_id.h" +#include "Core/Config.h" +#include "Core/String.h" + +#pragma warning(error: 4431) // default-int (variables) +#pragma warning(error: 4013) // default-int (function returns) + +int sdl_video_flags = 0; +bool g_rt_enable_debug_menu; + +CockpitSettings g_rt_cockpit_settings = { + .front_cockpit_rotation = {0.247f, -RT_PI32, 0.000f}, + .front_cockpit_offset = {0.000f, -0.033f, -2.411f}, + .front_cockpit_scale = {1.182f, 1.000f, 1.000f}, + .back_cockpit_rotation = {-0.159f, -RT_PI32, 0.000f}, + .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; +int max_rec_depth = 32; +float max_distance = 600; +float max_seg_distance = 500; + +uint64_t g_rt_frame_index; + +// #define RT_DUMP_GAME_BITMAPS + +#define BM_RTDX12 5 //whatever value, replaces BM_OGL. + +RT_ResourceHandle mesh_handles[MAX_POLYGON_MODELS]; + +RT_Mat4 old_poly_matrix[MAX_OBJECTS]; + +#define OP_EOF 0 //eof +#define OP_DEFPOINTS 1 //defpoints +#define OP_FLATPOLY 2 //flat-shaded polygon +#define OP_TMAPPOLY 3 //texture-mapped polygon +#define OP_SORTNORM 4 //sort by normal +#define OP_RODBM 5 //rod bitmap +#define OP_SUBCALL 6 //call a subobject +#define OP_DEFP_START 7 //defpoints with start +#define OP_GLOW 8 //glow value for next poly + +#define MAX_POINTS_PER_POLY 25 +//Some jank inherited from interp.c, might change it but likely not. +g3s_point* point_list[MAX_POINTS_PER_POLY]; + + +#define w(p) (*((short *) (p))) +#define wp(p) ((short *) (p)) +#define fp(p) ((fix *) (p)) +#define vp(p) ((vms_vector *) (p)) + +//some defines +int gr_installed = 0; +int gl_initialized = 0; +int linedotscale = 1; // scalar of glLinewidth and glPointSize - only calculated once when resolution changes +int sdl_no_modeswitch = 0; + +RT_Arena g_arena = { 0 }; + +int gr_list_modes(u_int32_t gsmodes[]) +{ + SDL_Rect** modes; + int i = 0, modesnum = 0; + + int sdl_check_flags = SDL_FULLSCREEN; // always use Fullscreen as lead. + + modes = SDL_ListModes(NULL, sdl_check_flags); + + if (modes == (SDL_Rect**)0) // check if we get any modes - if not, return 0 + return 0; + + + if (modes == (SDL_Rect**)-1) + { + return 0; // can obviously use any resolution... strange! + } + else + { + for (i = 0; modes[i]; ++i) + { + if (modes[i]->w > 0xFFF0 || modes[i]->h > 0xFFF0 // resolutions saved in 32bits. so skip bigger ones (unrealistic in 2010) (changed to 0xFFF0 to fix warning) + || modes[i]->w < 320 || modes[i]->h < 200) // also skip everything smaller than 320x200 + continue; + gsmodes[modesnum] = SM(modes[i]->w, modes[i]->h); + modesnum++; + if (modesnum >= 50) // that really seems to be enough big boy. + break; + } + return modesnum; + } +} + +int gr_check_mode(u_int32_t mode) +{ + unsigned int w, h; + + w = SM_W(mode); + h = SM_H(mode); + + if (sdl_no_modeswitch == 0) { + return SDL_VideoModeOK(w, h, GameArg.DbgBpp, 0); + } + else { + // just tell the caller that any mode is valid... + return 32; + } +} + +int gr_set_mode(u_int32_t mode) +{ + unsigned int w, h; + char* gr_bm_data; + + if (mode <= 0) + return 0; + + w = SM_W(mode); + h = SM_H(mode); + + GameCfg.ResolutionX = w; + GameCfg.ResolutionY = h; + + if (!gr_check_mode(mode)) + { + RT_LOGF(RT_LOGSERVERITY_HIGH, "Cannot set %ix%i. Fallback to 640x480\n", w, h); + w = 640; + h = 480; + Game_screen_mode = mode = SM(w, h); + } + + gr_bm_data = (char*)grd_curscreen->sc_canvas.cv_bitmap.bm_data;//since we use realloc, we want to keep this pointer around. + memset(grd_curscreen, 0, sizeof(grs_screen)); + grd_curscreen->sc_mode = mode; + grd_curscreen->sc_w = w; + grd_curscreen->sc_h = h; + grd_curscreen->sc_aspect = fixdiv(GameCfg.AspectX, GameCfg.AspectY); + gr_init_canvas(&grd_curscreen->sc_canvas, d_realloc(gr_bm_data, w * h), BM_RTDX12, w, h); + gr_set_current_canvas(NULL); + + if (w != last_width || h != last_height) + { + last_width = w; + last_height = h; + } + + //Set the video or resize it. The renderer handles the resize event. + SDL_SetVideoMode(w, h, 32, sdl_video_flags); + RT_RasterSetViewport(0.0f, 0.0f, w, h); + gamefont_choose_game_font(w, h); + + return 0; +} + +/* + * 2d Sprites (Fireaballs, powerups, explosions). NOT hostages + */ +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); + + RT_Vec2 rt_dim = { f2fl(width), f2fl(height) }; + RT_Vec3 rt_pos = RT_Vec3Fromvms_vector(pos); + + RT_RaytraceBillboardColored(material_index, RT_Vec3Make(r, g, b), rt_dim, rt_pos, rt_pos); + + return 0; +} + +void draw_object_tmap_rod(object *obj, bitmap_index bmi, int lighted) +{ + float size = f2fl(obj->size); + + vms_vector delta; + vm_vec_copy_scale(&delta,&obj->orient.uvec,obj->size); + + vms_vector top_v; + vm_vec_add(&top_v,&obj->pos,&delta); + + vms_vector bot_v; + vm_vec_sub(&bot_v,&obj->pos,&delta); + + RT_Vec3 bot_p = RT_Vec3Fromvms_vector(&bot_v); + RT_Vec3 top_p = RT_Vec3Fromvms_vector(&top_v); + + RT_RaytraceRod(bmi.index, bot_p, top_p, f2fl(obj->size)); +} + +bool g3_draw_bitmap_colorwarp(vms_vector* pos, fix width, fix height, grs_bitmap* bm, + float r, float g, float b) +{ + return g3_draw_bitmap_full(pos, width, height, bm, r, g, b); +} + +bool g3_draw_bitmap(vms_vector *pos, fix width, fix height, grs_bitmap *bm) +{ + return g3_draw_bitmap_full(pos, width, height, bm, 1, 1, 1); +} + +void gr_set_attributes(void) +{ + //Nothing for us to do here +} + +void gr_close(void) +{ + RT_RendererExit(); +} + +void gr_palette_load(ubyte* pal) +{ + int i; + + for (i = 0; i < 768; i++) + { + gr_current_pal[i] = pal[i]; + if (gr_current_pal[i] > 63) + gr_current_pal[i] = 63; + } + + gr_palette_step_up(0, 0, 0); // make ogl_setbrightness_internal get run so that menus get brightened too. + init_computed_colors(); +} + +void gr_palette_read(ubyte* pal) +{ + int i; + for (i = 0; i < 768; i++) + { + pal[i] = gr_current_pal[i]; + if (pal[i] > 63) + pal[i] = 63; + } +} + +int screen_flash_mul = 1; + +void gr_palette_step_up(int r, int g, int b) +{ + RT_Vec4 screen_flash_color = { 0, 0, 0, 1 }; + + r = r * screen_flash_mul; + g = g * screen_flash_mul; + b = b * screen_flash_mul; + + screen_flash_color.x = (float)max((r + gr_palette_gamma), 0); + screen_flash_color.y = (float)max((g + gr_palette_gamma), 0); + screen_flash_color.z = (float)max((b + gr_palette_gamma), 0); + + screen_flash_color.x = screen_flash_color.x / 63.0f; + screen_flash_color.y = screen_flash_color.y / 63.0f; + screen_flash_color.z = screen_flash_color.z / 63.0f; + + RT_RendererIO* io = RT_GetRendererIO(); + io->screen_overlay_color = screen_flash_color; +} + +void RT_UpdateMaterialEdges(void) +{ + RT_MaterialEdge* g_rt_material_edges = RT_GetMaterialEdgesArray(); + + for (int segment_index = 0; segment_index < Num_segments; segment_index++) + { + segment* seg = &Segments[segment_index]; + + for (int side_index = 0; side_index < MAX_SIDES_PER_SEGMENT; side_index++) + { + side* sd = &seg->sides[side_index]; + + int absolute_side_index = MAX_SIDES_PER_SEGMENT * segment_index + side_index; + + RT_MaterialEdge* side_edge = &g_rt_material_edges[absolute_side_index]; + side_edge->mat1 = sd->tmap_num; + side_edge->mat2 = sd->tmap_num2; + } + } +} + +void RT_UpdateMaterialIndices(void) +{ + uint16_t* g_rt_material_indices = RT_GetMaterialIndicesArray(); + + for (int texture_index = 0; texture_index < MAX_TEXTURES; texture_index++) + { + g_rt_material_indices[texture_index] = Textures[texture_index].index; + } + + for (int texture_index = 0; texture_index < MAX_OBJ_BITMAPS; texture_index++) + { + g_rt_material_indices[texture_index + MAX_TEXTURES] = ObjBitmaps[texture_index].index; + } + + // The way this system was set up is really not the best, this is my hack to easily + // use these special built in materials in other code. + g_rt_material_indices[RT_MATERIAL_FLAT_WHITE] = RT_MATERIAL_FLAT_WHITE; + g_rt_material_indices[RT_MATERIAL_EMISSIVE_WHITE] = RT_MATERIAL_EMISSIVE_WHITE; +} + +void gr_flip(void) +{ + //flip + RT_RasterRender(); + RT_RenderImGui(); + RT_SwapBuffers(); +} + +int gr_check_fullscreen(void) +{ + //Check if screen is fullscreen, add this option to the renderer itself. + return (sdl_video_flags & SDL_FULLSCREEN) ? 1 : 0; +} + +int gr_toggle_fullscreen(void) +{ + //Send call to renderer to make it full screen. + if (sdl_video_flags & SDL_FULLSCREEN) + sdl_video_flags &= ~SDL_FULLSCREEN; + else + sdl_video_flags |= SDL_FULLSCREEN; + + if (!SDL_SetVideoMode(SM_W(Game_screen_mode), SM_H(Game_screen_mode), GameArg.DbgBpp, sdl_video_flags)) + { + // Setting video mode went wrong + } + + GameCfg.WindowMode = (sdl_video_flags & SDL_FULLSCREEN) ? 0 : 1; + return (sdl_video_flags & SDL_FULLSCREEN)?1:0; +} + +void gr_upoly_tmap(int nverts, int* vert) +{ + //never call this, maybe log this like DXX-Retro does in arch/ogl.c? + RT_LOG(RT_LOGSERVERITY_HIGH, "gr_upoly_tmap: unhandled"); +} + +void draw_tmap_flat(grs_bitmap* bm, int nv, g3s_point** vertlist) +{ + //never call this, maybe log this like DXX-Retro does in arch/ogl.c? + RT_LOG(RT_LOGSERVERITY_HIGH, "draw_tmap_flat: unhandled"); +} + +int gr_init(int mode) +{ + SDL_WM_SetCaption(DESCENT_VERSION, "Descent"); + //Note SAM: Maybe we can create our own bmp later on, would be cool. + SDL_WM_SetIcon(SDL_LoadBMP("dxx-raytracer.bmp"), NULL); + + if (!GameCfg.WindowMode && !GameArg.SysWindow) + sdl_video_flags |= SDL_FULLSCREEN; + + if (GameArg.SysNoBorders) + sdl_video_flags |= SDL_NOFRAME; + + g_rt_free_cam_info.g_free_cam_enabled = false; + g_rt_free_cam_info.g_free_cam_clipping_enabled = false; + g_rt_free_cam_info.g_free_cam_obj = 0; + g_rt_free_cam_info.g_old_cockpit = 0; + + MALLOC(grd_curscreen, grs_screen, 1); + memset(grd_curscreen, 0, sizeof(grs_screen)); + grd_curscreen->sc_canvas.cv_bitmap.bm_data = NULL; + + grd_curscreen->sc_canvas.cv_color = 0; + grd_curscreen->sc_canvas.cv_fade_level = GR_FADE_OFF; + grd_curscreen->sc_canvas.cv_blend_func = GR_BLEND_NORMAL; + grd_curscreen->sc_canvas.cv_drawmode = 0; + grd_curscreen->sc_canvas.cv_font = NULL; + grd_curscreen->sc_canvas.cv_font_fg_color = 0; + grd_curscreen->sc_canvas.cv_font_bg_color = 0; + gr_set_current_canvas(&grd_curscreen->sc_canvas); + + unsigned int w, h; + w = SM_W(mode); + h = SM_H(mode); + + //Init video here, sadly it's wrong but it will be resized in gr_set_mode. + SDL_Surface* surf = SDL_SetVideoMode(w, h, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_ANYFORMAT); + + SDL_EventState(SDL_IGNORE, NULL); + RT_RendererInitParams initParams; + SDL_SysWMinfo info; + + SDL_VERSION(&info.version); + SDL_GetWMInfo(&info); + + initParams.arena = &g_arena; + initParams.window_handle = info.window; + + igCreateContext(NULL); + + ImGuiIO *io = igGetIO(); + io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; + io->Fonts->Flags |= ImFontAtlasFlags_NoBakedLines; + + igInitWin32(info.window); + RT_RendererInit(&initParams); + + float fov; + RT_ConfigReadFloat(RT_GetRendererIO()->config, RT_StringLiteral("fov"), &fov); + g_cam.vfov = g_free_cam.vfov = fov; + + return 0; +} + +void RT_VertexFixToFloat_Fan(RT_TriangleBuffer *buf, int nv, g3s_point** pointlist, uint32_t texture_id, uint32_t triangle_color) +{ + RT_Triangle first_triangle = {0}; + + first_triangle.pos0.x = f2fl(pointlist[0]->p3_vec.x); + first_triangle.pos0.y = f2fl(pointlist[0]->p3_vec.y); + first_triangle.pos0.z = f2fl(pointlist[0]->p3_vec.z); + + first_triangle.uv0.x = f2fl(pointlist[0]->p3_u); + first_triangle.uv0.y = f2fl(pointlist[0]->p3_v); + + first_triangle.color = triangle_color; + + RT_ASSERT(texture_id & RT_TRIANGLE_HOLDS_MATERIAL_EDGE); + + first_triangle.material_edge_index = texture_id; + + int start_count = buf->count; + + for (int point_index = 1; point_index + 1 < nv; point_index++) + { + RT_Triangle triangle = first_triangle; + + triangle.pos1.x = f2fl(pointlist[point_index]->p3_vec.x); + triangle.pos1.y = f2fl(pointlist[point_index]->p3_vec.y); + triangle.pos1.z = f2fl(pointlist[point_index]->p3_vec.z); + + triangle.uv1.x = f2fl(pointlist[point_index]->p3_u); + triangle.uv1.y = f2fl(pointlist[point_index]->p3_v); + + triangle.pos2.x = f2fl(pointlist[point_index + 1]->p3_vec.x); + triangle.pos2.y = f2fl(pointlist[point_index + 1]->p3_vec.y); + triangle.pos2.z = f2fl(pointlist[point_index + 1]->p3_vec.z); + + triangle.uv2.x = f2fl(pointlist[point_index + 1]->p3_u); + triangle.uv2.y = f2fl(pointlist[point_index + 1]->p3_v); + + triangle.material_edge_index = texture_id; + + //Now do the normals + RT_Vec3 p10 = RT_Vec3Normalize(RT_Vec3Sub(triangle.pos1, triangle.pos0)); + RT_Vec3 p20 = RT_Vec3Normalize(RT_Vec3Sub(triangle.pos2, triangle.pos0)); + + RT_Vec3 normal = RT_Vec3Normalize(RT_Vec3Cross(p10, p20)); + + triangle.normal0 = normal; + triangle.normal1 = normal; + triangle.normal2 = normal; + + RT_PushTriangle(buf, triangle); + } + + int end_count = buf->count; + + // NOTE(daniel): This is a separate call, because I don't want to do something tweaky like + // detecting whether tangents need to be calculated in RT_UploadMesh. You, the uploader, should know. + RT_GenerateTangents(&buf->triangles[start_count], end_count - start_count); +} + +void RT_SetPointList(g3s_point* dest, vms_vector* src, int n) +{ + // NOTE(daniel): Ok so for submodels I guess we're relying on behaviour related + // to the view matrix and position being set. Very janky intermingling of code + // meant for rasterization, but I guess that's that. So we need to rotate the + // points. + + while (n--) + g3_rotate_point(dest++, src++); +} + +vms_angvec zero_angles; + +g3s_point* point_list[MAX_POINTS_PER_POLY]; + +// NOTE(daniel): Here for hardcoding certain materials for flat polys +// for different meshes. It's not the best. +static int jank_currently_loading_poly_model; + +static void RT_GetPolyData(RT_TriangleBuffer *buf, + g3s_point *interp_point_list, + void *model_ptr, + vms_angvec *anim_angles, + int first_texture) +{ + ubyte* p = model_ptr; + + while (w(p) != OP_EOF) + { + switch (w(p)) + { + case OP_DEFPOINTS: + { + int n = w(p + 2); + + RT_SetPointList(interp_point_list, vp(p + 4), n); + p += n*sizeof(struct vms_vector) + 4; + } break; + + case OP_DEFP_START: + { + int n = w(p + 2); + int s = w(p + 4); + + RT_SetPointList(&interp_point_list[s], vp(p + 8), n); + p += n*sizeof(struct vms_vector) + 8; + } break; + + case OP_FLATPOLY: + { + int nv = w(p + 2); + + for (int i = 0; i < nv; i++) + { + point_list[i] = interp_point_list + wp(p + 30)[i]; + } + + short color = w(p + 28); + + // NOTE(daniel): I hope the palette is initialized correctly! + ubyte r = gr_palette[color*3 + 0]*4; + ubyte g = gr_palette[color*3 + 1]*4; + ubyte b = gr_palette[color*3 + 2]*4; + ubyte a = 255; + + // RGBA! + uint32_t color_packed = (r << 0)|(g << 8)|(b << 16)|(a << 24); + + uint32_t material_index = RT_MATERIAL_FLAT_WHITE|RT_TRIANGLE_HOLDS_MATERIAL_EDGE; + + // wow. good code. + + bool should_be_emissive = false; + + if (PCSharePig) + { + // pointy melee guy + if (jank_currently_loading_poly_model == 2) should_be_emissive = true; + if (jank_currently_loading_poly_model == 3) should_be_emissive = true; + + if (jank_currently_loading_poly_model == 8) should_be_emissive = true; + + if ((jank_currently_loading_poly_model >= 28 && + jank_currently_loading_poly_model <= 43) || + (jank_currently_loading_poly_model >= 46 && + jank_currently_loading_poly_model <= 47) || + (jank_currently_loading_poly_model >= 52 && + jank_currently_loading_poly_model <= 55)) + + { + should_be_emissive = true; + } + + } + else + { + // pointy melee guy + if (jank_currently_loading_poly_model == 2) should_be_emissive = true; + // pointy blue-purple guy + if (jank_currently_loading_poly_model == 7) should_be_emissive = true; + + if ((jank_currently_loading_poly_model >= 46 && + jank_currently_loading_poly_model <= 61) || + (jank_currently_loading_poly_model >= 63 && + jank_currently_loading_poly_model <= 67) || + (jank_currently_loading_poly_model >= 73 && + jank_currently_loading_poly_model <= 76)) + { + // Laser. + should_be_emissive = true; + } + } + + if (should_be_emissive) + { + material_index = RT_MATERIAL_EMISSIVE_WHITE|RT_TRIANGLE_HOLDS_MATERIAL_EDGE; + } + + RT_VertexFixToFloat_Fan(buf, nv, point_list, material_index, color_packed); + + p += 30 + ((nv & ~1) + 1) * 2; + } break; + + case OP_TMAPPOLY: + { + int nv = w(p + 2); + + Assert(nv < MAX_POINTS_PER_POLY); + + // Lights were done here previously, no needed now. + // NOTE(daniel): Again, that's nice, but do we know that we don't care about those light values? + // Are they used anywhere, or do we just ignore them entirely? (We might, and that might be + // totally valid). + + // Get the UV coordinates (allegedly) // NOTE(daniel): Why allegedly? + g3s_uvl* uvl_list = (g3s_uvl*)(p + 30 + ((nv & ~1) + 1) * 2); + + for (int i = 0; i < nv; i++) + { + point_list[i] = interp_point_list + wp(p + 30)[i]; + point_list[i]->p3_u = uvl_list[i].u; + point_list[i]->p3_v = uvl_list[i].v; + } + + // Get texture index - p+28 would be the magic offset for the texture id relative to first_texture + short texture_index = w(p + 28) + first_texture; + + // NOTE(daniel): For poly objects, RT_TRIANGLE_HOLDS_MATERIAL_EDGE is or'd into the material index + // assigned to the triangle to indicate to the renderer to skip the double indirection + // through the material edge array, because it's only needed for segments. + uint32_t material_index = (ObjBitmapPtrs[texture_index] + MAX_TEXTURES) | RT_TRIANGLE_HOLDS_MATERIAL_EDGE; + RT_VertexFixToFloat_Fan(buf, nv, point_list, material_index, 0xFFFFFFFF); + + p += 30 + ((nv & ~1) + 1) * 2 + nv * 12; + } break; + + case OP_SORTNORM: + { + if (g3_check_normal_facing(vp(p + 16), vp(p + 4)) > 0) // facing + { + // draw back then front + // NOTE(daniel): This is about sorting polys according to the view matrix, what does this + // have to do with loading models ahead of time? + RT_GetPolyData(buf, interp_point_list, p + w(p + 30), anim_angles, first_texture); + RT_GetPolyData(buf, interp_point_list, p + w(p + 28), anim_angles, first_texture); + + } + else // not facing. draw front then back + { + RT_GetPolyData(buf, interp_point_list, p + w(p + 28), anim_angles, first_texture); + RT_GetPolyData(buf, interp_point_list, p + w(p + 30), anim_angles, first_texture); + } + + p += 32; + } break; + + case OP_RODBM: + { + //Not needed here + p += 36; + } break; + + case OP_SUBCALL: + { + typedef struct RT_SubcallStruct + { + uint16_t opcode; // = OP_SUBCALL + uint16_t anim_angles_index; + vms_vector position_offset; + uint16_t model_ptr; + uint16_t unknown7; // always 0? + } RT_SubcallStruct; + + RT_SubcallStruct *command_data = (RT_SubcallStruct *)p; + + // Not needed here + // NOTE(daniel): If it's not needed here, why is it still here? + vms_angvec* a; + + if (anim_angles) + { + a = &anim_angles[command_data->anim_angles_index]; + } + else + { + a = &zero_angles; + } + + g3_start_instance_angles(&command_data->position_offset, a); + + RT_GetPolyData(buf, interp_point_list, p + command_data->model_ptr, anim_angles, first_texture); + + g3_done_instance(); + p += 20; + } break; + + case OP_GLOW: + { + // We aint doing glow here + // NOTE(daniel): Ok, but then where are the glow values going? When are they used? + // Should we care? + p += 4; + } break; + + default: + { + /* ... */ + } break; + } + } +} + +void RT_InitglTFModels(void) +{ + g_rt_cockpit_settings.cockpit_hud_texture = RT_UploadTexture(&(RT_UploadTextureParams) { + .width = 1024, + .height = 1024, + .name = "Cockpit UI", + .format = RT_TextureFormat_SRGBA8, + .pixels = RT_ArenaAllocArray(&g_thread_arena, 1024 * 1024, uint32_t) + }); + + RT_Material cockpit_material = { 0 }; + cockpit_material.albedo_texture = RT_GetDefaultBlackTexture(); + cockpit_material.emissive_texture = g_rt_cockpit_settings.cockpit_hud_texture; + cockpit_material.emissive_strength = 1.0f; + cockpit_material.emissive_color.x = 1.0f; + cockpit_material.emissive_color.y = 1.0f; + cockpit_material.emissive_color.z = 1.0f; + cockpit_material.flags = RT_MaterialFlag_NoCastingShadow; + RT_UpdateMaterial(RT_MATERIAL_COCKPIT_UI, &cockpit_material); + + RT_MaterialOverride material_override = { + RT_MATERIAL_COCKPIT_UI, + "Screens_and_keycard_buttons" + }; + + g_rt_cockpit_settings.cockpit_gltf = RT_LoadGLTF(&g_arena, "assets/cockpit_prototype.gltf", &material_override); + + RT_Config cfg; + RT_InitializeConfig(&cfg, &g_thread_arena); + if (RT_DeserializeConfigFromFile(&cfg, "cockpit_3d.cfg")) { + RT_ConfigReadVec3(&cfg, RT_StringLiteral("front_cockpit_rotation"), &g_rt_cockpit_settings.front_cockpit_rotation); + RT_ConfigReadVec3(&cfg, RT_StringLiteral("front_cockpit_offset"), &g_rt_cockpit_settings.front_cockpit_offset); + RT_ConfigReadVec3(&cfg, RT_StringLiteral("front_cockpit_scale"), &g_rt_cockpit_settings.front_cockpit_scale); + RT_ConfigReadVec3(&cfg, RT_StringLiteral("back_cockpit_rotation"), &g_rt_cockpit_settings.back_cockpit_rotation); + RT_ConfigReadVec3(&cfg, RT_StringLiteral("back_cockpit_offset"), &g_rt_cockpit_settings.back_cockpit_offset); + RT_ConfigReadVec3(&cfg, RT_StringLiteral("back_cockpit_scale"), &g_rt_cockpit_settings.back_cockpit_scale); + } +} + +void RT_InitBasePolyModel(const int polymodel_index, g3s_point* interp_point_list, void* model_ptr, vms_angvec* anim_angles, int first_texture) +{ + RT_ArenaMemoryScope(&g_thread_arena) + { + int triangle_buffer_size = 2048; + + RT_TriangleBuffer triangles = + { + .triangles = RT_ArenaAllocArray(&g_thread_arena, triangle_buffer_size, RT_Triangle), + .count = 0, + .capacity = triangle_buffer_size, + }; + + View_position = vmd_zero_vector; + View_matrix = vmd_identity_matrix; + + RT_GetPolyData(&triangles, interp_point_list, model_ptr, anim_angles, first_texture); + + if (triangles.count > 0) + { + mesh_handles[polymodel_index] = RT_UploadMesh(&(RT_UploadMeshParams){ + .triangles = triangles.triangles, + .triangle_count = triangles.count, + .name = RT_ArenaPrintF(&g_thread_arena, "Polymodel %d", polymodel_index), + }); + + // NOTE(daniel): If we're going to keep the triangles around for some hacking, we should + // make a copy to a permanent arena. + RT_UploadMeshParams hacky_params = + { + .triangles = RT_ArenaCopyArray(&g_arena, triangles.triangles, triangles.count), + .triangle_count = triangles.count, + }; + meshVerticesRawHack[polymodel_index] = hacky_params; + } + } +} + +RT_ResourceHandle RT_InitSubPolyModel(g3s_point* interp_point_list, void* model_ptr, vms_angvec* anim_angles, int first_texture) +{ + RT_ResourceHandle result = RT_RESOURCE_HANDLE_NULL; + + RT_ArenaMemoryScope(&g_thread_arena) + { + int triangle_buffer_size = 2048; + + RT_TriangleBuffer triangles = + { + .triangles = RT_ArenaAllocArray(&g_thread_arena, triangle_buffer_size, RT_Triangle), + .count = 0, + .capacity = triangle_buffer_size, + }; + + View_position = vmd_zero_vector; + View_matrix = vmd_identity_matrix; + + RT_GetPolyData(&triangles, interp_point_list, model_ptr, anim_angles, first_texture); + + if (triangles.count > 0) + { + result = RT_UploadMesh(&(RT_UploadMeshParams){ + .triangles = triangles.triangles, + .triangle_count = triangles.count, + .name = "Sub-Polymodel", + }); + } + } + + return result; +} + +void RT_InitPolyModelAndSubModels(int pm_index) +{ + polymodel *pm = &Polygon_models[pm_index]; + + // TODO(daniel): Figure out something better + jank_currently_loading_poly_model = pm_index; + + RT_InitBasePolyModel(pm_index, robot_points, pm->model_data, NULL, pm->first_texture); + for (size_t i = 0; i < pm->n_models; i++) + { + int t_ModelPtr = pm->submodel_ptrs[i]; + pm->submodel[i] = RT_InitSubPolyModel(robot_points, pm->model_data + t_ModelPtr, NULL, pm->first_texture); + } + + // TODO(daniel): Figure out something better + jank_currently_loading_poly_model = 0; + + // Find tree structure of submodels + memset(pm->model_tree, 0, sizeof(pm->model_tree)); + + for (int i = 0; i < pm->n_models; ++i) + { + // Parent + pm->model_tree[i].parent_index = pm->submodel_parents[i]; + + // Add this model's index to the list of child indices of the parent + if (pm->submodel_parents[i] != 255) + { + RT_ModelTree *parent = &pm->model_tree[pm->submodel_parents[i]]; + parent->child_indices[parent->n_children] = i; + parent->n_children++; + } + } +} + +void RT_InitAllPolyModels(void) +{ + for (int pm_index = 0; pm_index < N_polygon_models; pm_index++) + { + RT_InitPolyModelAndSubModels(pm_index); + } +} + +void RT_DrawPolyModel(const int meshnumber, const int signature, ubyte object_type, const vms_vector* pos, const vms_matrix* orient) +{ + // NOTE(daniel): This is never used, is it. + + if (!RT_RESOURCE_HANDLE_VALID(mesh_handles[meshnumber])) + { + RT_InitPolyModelAndSubModels(meshnumber); + } + + if (RT_RESOURCE_HANDLE_VALID(mesh_handles[meshnumber])) + { + // Create model matrix + RT_Mat4 mat = RT_Mat4Identity(); + + // Apply translation + mat = RT_Mat4Mul(mat, RT_Mat4FromTranslation(RT_Vec3Fromvms_vector(pos))); + + // Apply rotation + RT_Mat4 rot = RT_Mat4Fromvms_matrix(orient); + mat = RT_Mat4Mul(mat, RT_Mat4Fromvms_matrix(orient)); + + // assert(objNum > 0 || objNum < MAX_OBJECTS); + + RT_ResourceHandle handle = mesh_handles[meshnumber]; + + // Render mesh + // RT_RaytraceMesh(handle, &mat, &old_poly_matrix[objNum]); + + RT_RenderMeshParams params = + { + .key = signature, + .mesh_handle = handle, + .transform = &mat, + .color = 0xFFFFFFFF, + }; + RT_RaytraceMeshEx(¶ms); + } +} + +void RT_DrawSubPolyModel(RT_ResourceHandle submodel, const RT_Mat4* const submodel_transform, RT_RenderKey key) +{ + if (RT_RESOURCE_HANDLE_VALID(submodel)) + { + float alpha = 1.0f; + if (grd_curcanv->cv_fade_level < GR_FADE_OFF) + { + alpha = 1.0f - (float)grd_curcanv->cv_fade_level / ((float)GR_FADE_LEVELS - 1.0f); + } + + RT_Vec4 color = { 1, 1, 1, alpha }; + + RT_RenderMeshParams params = + { + .key = key, + .mesh_handle = submodel, + .transform = submodel_transform, + .color = RT_PackRGBA(color), + }; + RT_RaytraceMeshEx(¶ms); + } +} + +void RT_DrawPolySubModelTree(const polymodel* model, const vms_angvec* const anim_angles, int submodel_index, const int signature, const RT_Mat4 submodel_transform) +{ + RT_RenderKey key = + { + .signature = signature, + .submodel_index = submodel_index, + }; + + // Draw the submodel + RT_DrawSubPolyModel(model->submodel[submodel_index], &submodel_transform, key); + + // Traverse tree structure + for (int i = 0; i < model->model_tree[submodel_index].n_children; ++i) { + // anim_angles is an array, where the indices into that array allegedly correspond directly to the child indices :D + const int child_index = model->model_tree[submodel_index].child_indices[i]; + + vms_angvec anim_angles_final; + if (anim_angles) { + anim_angles_final.p = anim_angles[child_index].p; + anim_angles_final.b = anim_angles[child_index].b; + anim_angles_final.h = anim_angles[child_index].h; + } + else { + anim_angles_final.p = zero_angles.p; + anim_angles_final.b = zero_angles.b; + anim_angles_final.h = zero_angles.h; + } + + // Get matrix from local position offset + const vms_vector offset_vms = model->submodel_offsets[child_index]; + const RT_Vec3 offset_vec3 = RT_Vec3Fromvms_vector(&offset_vms); + RT_Mat4 offset_mat4 = RT_Mat4FromTranslation(offset_vec3); + offset_mat4 = RT_Mat4Mul(submodel_transform, offset_mat4); + + // Get matrix from rotation offset + vms_matrix rotation_vms; + vm_angles_2_matrix(&rotation_vms, &anim_angles_final); + RT_Mat4 rotation_mat4 = RT_Mat4Fromvms_matrix(&rotation_vms); + + // Combine them into one big matrix + RT_Mat4 combined_matrix = RT_Mat4Mul(offset_mat4, rotation_mat4); + + RT_DrawPolySubModelTree(model, anim_angles, child_index, signature, combined_matrix); + } +} + +void RT_DrawPolyModelTree(const int meshnumber, const int signature, ubyte object_type, const vms_vector* pos, const vms_matrix* orient, vms_angvec* anim_angles) { + if (!RT_RESOURCE_HANDLE_VALID(mesh_handles[meshnumber])) + { + RT_InitPolyModelAndSubModels(meshnumber); + } + + // Get model to render + polymodel* model = &Polygon_models[meshnumber]; + + // Get matrix from local position offset + const vms_vector offset_vms = *pos; + const RT_Vec3 offset_vec3 = RT_Vec3Fromvms_vector(&offset_vms); + RT_Mat4 offset_mat4 = RT_Mat4FromTranslation(offset_vec3); + + // Get matrix from rotation offset + RT_Mat4 rotation_mat4 = RT_Mat4Fromvms_matrix(orient); + + // Combine them into one big matrix + RT_Mat4 combined_matrix = RT_Mat4Mul(offset_mat4, rotation_mat4); + + RT_DrawPolySubModelTree(model, anim_angles, 0, signature, combined_matrix); +} + +void RT_DrawGLTF(const RT_GLTFNode* node, RT_Mat4 transform, RT_Mat4 prev_transform) +{ + if (!node) + return; + + transform = RT_Mat4Mul(transform, node->transform); + prev_transform = RT_Mat4Mul(prev_transform, node->transform); + + if (node->model) + { + RT_GLTFModel* model = node->model; + RT_RaytraceMesh(model->handle, &transform, &prev_transform); + } + + for (size_t i = 0; i < node->children_count; i++) + { + RT_GLTFNode* child = node->children[i]; + RT_DrawGLTF(child, transform, prev_transform); + } +} + +void RT_EnableFreeCam() +{ + g_rt_free_cam_info.g_free_cam_enabled = true; + g_rt_free_cam_info.g_old_cockpit = PlayerCfg.CockpitMode[1]; + + g_rt_free_cam_info.g_free_cam_obj = obj_create(OBJ_CAMERA, 0, + ConsoleObject->segnum, &ConsoleObject->pos, &ConsoleObject->orient, 0, + CT_FLYING, MT_PHYSICS, RT_NONE); + + Objects[g_rt_free_cam_info.g_free_cam_obj].mtype.phys_info.drag = 2162; + Objects[g_rt_free_cam_info.g_free_cam_obj].mtype.phys_info.mass = 262144; + Objects[g_rt_free_cam_info.g_free_cam_obj].mtype.phys_info.flags = PF_USES_THRUST; + Objects[g_rt_free_cam_info.g_free_cam_obj].size = 310325.0F; + + CollisionResult[OBJ_CAMERA][OBJ_WALL] = RESULT_CHECK; CollisionResult[OBJ_CAMERA][OBJ_WALL] = RESULT_CHECK; + + Viewer = &Objects[g_rt_free_cam_info.g_free_cam_obj]; + + PlayerCfg.HudMode = 3; // NO HUD mode + select_cockpit(CM_FULL_SCREEN); + PlayerCfg.CockpitMode[0] = CM_FULL_SCREEN; +} + +void RT_DisableFreeCam() +{ + g_rt_free_cam_info.g_free_cam_enabled = false; + + Viewer = ConsoleObject; + + CollisionResult[OBJ_CAMERA][OBJ_WALL] = RESULT_NOTHING; CollisionResult[OBJ_CAMERA][OBJ_WALL] = RESULT_NOTHING; + + PlayerCfg.HudMode = 0; // Standard HUD mode + select_cockpit(g_rt_free_cam_info.g_old_cockpit); + PlayerCfg.CockpitMode[0] = g_rt_free_cam_info.g_old_cockpit; + + obj_delete(g_rt_free_cam_info.g_free_cam_obj); +} + +void RT_ResetLightEmission() +{ + int lightTexture = PCSharePig ? 774 : 997; + RT_Material* material = &g_rt_materials[lightTexture]; + material->emissive_strength = 3.5f; + RT_UpdateMaterial(lightTexture, material); +} + +void RT_StartImGuiFrame(void) +{ + igStartFrameWin32(); + igNewFrame(); + + // NOTE(Justin): It is times like these you realize that you are under a lot of time pressure + // and write code like this. There is definitely a quite simple mathematical way to solve this, but whatever. + bool value_changed = false; + float fov; + RT_ConfigReadFloat(RT_GetRendererIO()->config, RT_StringLiteral("fov"), &fov); + float fov_delta = fov - g_cam.vfov; + if (fov_delta != 0.0) + { + float multiplier = 0.8 / 30.0; + g_cam.vfov = g_free_cam.vfov = fov; + g_rt_cockpit_settings.front_cockpit_offset.z += fov_delta * multiplier; + g_rt_cockpit_settings.back_cockpit_offset.z -= fov_delta * multiplier; + value_changed = true; + } + + if (g_rt_enable_debug_menu) + { + RT_DoRendererDebugMenuParams params = { + .ui_has_cursor_focus = true, + }; + RT_DoRendererDebugMenus(¶ms); + + if (igBegin("HUD Texture Debug", NULL, 0)) { + igPushID_Str("HUD Texture Debug"); + igIndent(0); + RT_RenderImGuiTexture(g_rt_cockpit_settings.cockpit_hud_texture, 1024, 1024); + igPopID(); + } igEnd(); + + if (igBegin("3D Cockpit", NULL, 0)) { + igPushID_Str("Dynamic Lights"); + igIndent(0); + value_changed |= igDragFloat3("Front View Rotation", &g_rt_cockpit_settings.front_cockpit_rotation, 0.001f, -RT_PI32, +RT_PI32, "%.3f", ImGuiTreeNodeFlags_None); + value_changed |= igDragFloat3("Front View Offset", &g_rt_cockpit_settings.front_cockpit_offset, 0.001f, -10.0, 10.0, "%.3f", ImGuiTreeNodeFlags_None); + value_changed |= igDragFloat3("Front View Scale", &g_rt_cockpit_settings.front_cockpit_scale, 0.001f, -10.0, 10.0, "%.3f", ImGuiTreeNodeFlags_None); + value_changed |= igDragFloat3("Rear View Rotation", &g_rt_cockpit_settings.back_cockpit_rotation, 0.001f, -RT_PI32, +RT_PI32, "%.3f", ImGuiTreeNodeFlags_None); + 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); + igSliderInt("Max Segment Recursion Depth", &max_rec_depth, 0, 50, "%i segments", 0); + //igSliderFloat("Max Segment Distance", &max_seg_distance, 0.0f, 5000.0f, "%.1f units", 0); // note(lily): this is broken so I commented it out + igSliderFloat("Max Light Distance", &max_distance, 0.0f, 1000.0f, "%.1f units", 0); + 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"); + igIndent(0); + + igSliderInt("Flash screen multiplier", &screen_flash_mul, 1, 100, "%d", 0); + + igPopID(); + igUnindent(0); + } + + if (igCollapsingHeader_TreeNodeFlags("Free cam settings", ImGuiTreeNodeFlags_None)) + { + igCheckbox("Enable free cam clipping", &g_rt_free_cam_info.g_free_cam_clipping_enabled); + } + + igPopID(); + igUnindent(0); + } igEnd(); + + RT_ShowLightMenu(); + + RT_DoPolymodelViewerMenus(); + RT_DoMaterialViewerMenus(); + } + + if (value_changed) { + RT_Config cfg; + RT_InitializeConfig(&cfg, &g_thread_arena); + RT_ConfigWriteVec3(&cfg, RT_StringLiteral("front_cockpit_rotation"), g_rt_cockpit_settings.front_cockpit_rotation); + RT_ConfigWriteVec3(&cfg, RT_StringLiteral("front_cockpit_offset"), g_rt_cockpit_settings.front_cockpit_offset); + RT_ConfigWriteVec3(&cfg, RT_StringLiteral("front_cockpit_scale"), g_rt_cockpit_settings.front_cockpit_scale); + RT_ConfigWriteVec3(&cfg, RT_StringLiteral("back_cockpit_rotation"), g_rt_cockpit_settings.back_cockpit_rotation); + RT_ConfigWriteVec3(&cfg, RT_StringLiteral("back_cockpit_offset"), g_rt_cockpit_settings.back_cockpit_offset); + RT_ConfigWriteVec3(&cfg, RT_StringLiteral("back_cockpit_scale"), g_rt_cockpit_settings.back_cockpit_scale); + RT_SerializeConfigToFile(&cfg, "cockpit_3d.cfg"); + } +} + +void RT_EndImguiFrame(void) +{ + igRender(); + igEndFrame(); +} + +void save_screen_shot(int automap_flag) +{ + static int savenum=0; + char savename[FILENAME_LEN+sizeof(SCRNS_DIR)]; + + stop_time(); + + if (!PHYSFSX_exists(SCRNS_DIR,0)) + PHYSFS_mkdir(SCRNS_DIR); //try making directory + + do + { + sprintf(savename, "%sscrn%04d.png",SCRNS_DIR, savenum++); + } while (PHYSFSX_exists(savename,0)); + + if (!automap_flag) + HUD_init_message(HM_DEFAULT, "%s 'scrn%04d.png'", TXT_DUMPING_SCREEN, savenum-1 ); + + RT_QueueScreenshot(savename); + + start_time(); +} diff --git a/RT/RTgr.h b/RT/RTgr.h index a4ddcaa..1f52134 100644 --- a/RT/RTgr.h +++ b/RT/RTgr.h @@ -1,84 +1,116 @@ -/* - * - * RT Extensions of the definitions for graphics lib. - * - */ - -#ifndef _RT_GR_H -#define _RT_GR_H - -#include "Renderer.h" -#include "ApiTypes.h" -#include "Core/MiniMath.h" -#include "piggy.h" -#include "RTutil.h" -#include "laser.h" - -#include "Core/Common.h" - -#define MAX_TEXTURE_COUNT 2048 - -typedef struct -{ - bool explosionLights; - float explosionBrightMod; - float explosionRadiusMod; - - bool weaponFlareLights; - float weaponBrightMod; - float weaponRadiusMod; - float weaponFlareBrightMod; - - bool muzzleLights; - float muzzleBrightMod; - float muzzleRadiusMod; -} RT_DynamicLightInfo; - - -typedef struct RT_WeaponLightAdjusts -{ - const char* weapon_name; - float brightMul; - float radiusMul; -} RT_WeaponLightAdjusts; -#define RT_LIGHT_ADJUST_ARRAY_SIZE (SPREADFIRE_ID - CONCUSSION_ID + 1) - - - -typedef struct RT_GLTFNode RT_GLTFNode; - -extern bool g_rt_enable_debug_menu; -//I sure love globals -extern RT_GLTFNode* g_rt_cockpit_gltf; -extern RT_DynamicLightInfo g_rt_dynamic_light_info; -extern RT_WeaponLightAdjusts rt_light_adjusts[]; -RT_Camera g_cam; - -extern uint64_t g_rt_frame_index; - -//The imgui structs should be 8 bytes packed. -//Note: REMEMBER TO USE PUSH SAM >:( I messed up accidently. -#pragma pack(push, 8) -#define CIMGUI_DEFINE_ENUMS_AND_STRUCTS -//For some reason the global include path doesn't work. Ah well then we use this! -#include "../../RT/Renderer/Backend/DX12/cimgui/cimgui.h" -#pragma pack(pop) - -void RT_VertexFixToFloat_Fan(RT_TriangleBuffer *buf, int nv, g3s_point** pointlist, uint16_t texture_index, uint32_t triangle_color); - -//Inits the glTF models that extend on the raytrace version. -void RT_InitglTFModels(void); -//Creates the polymodel on the index of polygonModelIndex. -void RT_InitBasePolyModel(const int polygonModelIndex, g3s_point* interp_point_list, void* model_ptr, vms_angvec* anim_angles, int first_texture); -RT_ResourceHandle RT_InitSubPolyModel(g3s_point* interp_point_list, void* model_ptr, vms_angvec* anim_angles, int first_texture); -void RT_InitPolyModelAndSubModels(int polymodel_index); - -void RT_DrawPolyModel(const int meshnumber, const int objNum, ubyte object_type, const vms_vector* pos, const vms_matrix* orient); -void RT_DrawSubPolyModel(const RT_ResourceHandle submodel, const RT_Mat4* const submodel_transform, const RT_Mat4* const submodel_transform_prev); -void RT_DrawPolyModelTree(const int meshnumber, const int objNum, ubyte object_type, const vms_vector* pos, const vms_matrix* orient, vms_angvec* anim_angles); -void RT_DrawGLTF(const RT_GLTFNode* basenode, RT_Mat4 transform, RT_Mat4 prev_transform); - -void RT_StartImGuiFrame(void); -void RT_EndImguiFrame(void); - +/* + * + * RT Extensions of the definitions for graphics lib. + * + */ + +#ifndef _RT_GR_H +#define _RT_GR_H + +#include "Renderer.h" +#include "ApiTypes.h" +#include "Core/MiniMath.h" +#include "piggy.h" +#include "RTutil.h" +#include "laser.h" + +#include "Core/Common.h" + +#define MAX_TEXTURE_COUNT 2048 + +typedef struct +{ + bool explosionLights; + float explosionBrightMod; + float explosionRadiusMod; + float explosionTypeBias; + + bool weaponFlareLights; + float weaponBrightMod; + float weaponRadiusMod; + + bool muzzleLights; + float muzzleBrightMod; + float muzzleRadiusMod; +} RT_DynamicLightInfo; + + +typedef struct RT_WeaponLightAdjusts +{ + const char* weapon_name; + float brightMul; + float radiusMul; +} RT_WeaponLightAdjusts; +#define RT_LIGHT_ADJUST_ARRAY_SIZE (SPREADFIRE_ID - CONCUSSION_ID + 1) + +typedef struct RT_FreeCamInfo { + int g_free_cam_obj; + bool g_free_cam_enabled; + bool g_free_cam_clipping_enabled; + int g_old_cockpit; +} RT_FreeCamInfo; + +typedef struct RT_GLTFNode RT_GLTFNode; + +typedef struct CockpitSettings { + RT_GLTFNode* cockpit_gltf; + RT_ResourceHandle cockpit_hud_texture; + RT_Vec3 front_cockpit_rotation; + RT_Vec3 front_cockpit_offset; + RT_Vec3 front_cockpit_scale; + RT_Vec3 back_cockpit_rotation; + RT_Vec3 back_cockpit_offset; + RT_Vec3 back_cockpit_scale; +} CockpitSettings; +extern CockpitSettings g_rt_cockpit_settings; + +extern bool g_rt_enable_debug_menu; +//I sure love globals +extern RT_DynamicLightInfo g_rt_dynamic_light_info; +extern RT_WeaponLightAdjusts rt_light_adjusts[]; +extern RT_FreeCamInfo g_rt_free_cam_info; +RT_Camera g_cam; +RT_Camera g_free_cam; + +extern uint64_t g_rt_frame_index; + +// light culling variables +extern int light_culling_heuristic; +extern int max_rec_depth; +extern float max_distance; +extern float max_seg_distance; + +//The imgui structs should be 8 bytes packed. +//Note: REMEMBER TO USE PUSH SAM >:( I messed up accidently. +#pragma pack(push, 8) +#define CIMGUI_DEFINE_ENUMS_AND_STRUCTS +//For some reason the global include path doesn't work. Ah well then we use this! +#include "../../RT/Renderer/Backend/DX12/cimgui/cimgui.h" +#pragma pack(pop) + +void RT_VertexFixToFloat_Fan(RT_TriangleBuffer *buf, int nv, g3s_point** pointlist, uint16_t texture_index, uint32_t triangle_color); + +//Inits the glTF models that extend on the raytrace version. +void RT_InitglTFModels(void); +//Creates the polymodel on the index of polygonModelIndex. +void RT_InitBasePolyModel(const int polygonModelIndex, g3s_point* interp_point_list, void* model_ptr, vms_angvec* anim_angles, int first_texture); +RT_ResourceHandle RT_InitSubPolyModel(g3s_point* interp_point_list, void* model_ptr, vms_angvec* anim_angles, int first_texture); +void RT_InitPolyModelAndSubModels(int polymodel_index); + +void RT_DrawPolyModel(const int meshnumber, const int objNum, ubyte object_type, const vms_vector* pos, const vms_matrix* orient); +void RT_DrawSubPolyModel(const RT_ResourceHandle submodel, const RT_Mat4* const submodel_transform, RT_RenderKey key); +void RT_DrawPolyModelTree(const int meshnumber, const int objNum, ubyte object_type, const vms_vector* pos, const vms_matrix* orient, vms_angvec* anim_angles); +void RT_DrawGLTF(const RT_GLTFNode* basenode, RT_Mat4 transform, RT_Mat4 prev_transform); + +void RT_EnableFreeCam(); +void RT_DisableFreeCam(); + +void RT_ResetLightEmission(); + +void RT_UpdateMaterialEdges(void); +void RT_UpdateMaterialIndices(void); + +void RT_StartImGuiFrame(void); +void RT_EndImguiFrame(void); + #endif //_RT_GR_H \ No newline at end of file diff --git a/RT/RTmaterials.c b/RT/RTmaterials.c index 3270371..5530cdd 100644 --- a/RT/RTmaterials.c +++ b/RT/RTmaterials.c @@ -23,6 +23,8 @@ #pragma pack(push, 8) +// #define RT_DUMP_GAME_BITMAPS + // NOTE(daniel): These warnings, the second one especially, are really useful when writing C. // They prevent you from accidentally using functions from headers you never included and such other hilarious jokes C gets up to. #pragma warning(error: 4431) // default-int (variables) @@ -130,6 +132,11 @@ static void RT_ParseMaterialDefinitionFile(int bm_index, RT_Material *material, material->flags = RT_SET_FLAG(material->flags, RT_MaterialFlag_BlackbodyRadiator, blackbody); + int no_casting_shadow = 0; + RT_ConfigReadInt(&cfg, RT_StringLiteral("no_casting_shadow"), &no_casting_shadow); + + material->flags = RT_SET_FLAG(material->flags, RT_MaterialFlag_NoCastingShadow, no_casting_shadow); + if (default_roughness) *default_roughness = !has_roughness; if (default_metalness) *default_metalness = !has_metalness; } @@ -158,6 +165,19 @@ static int RT_LoadMaterialTexturesFromPaths(uint16_t bm_index, RT_Material *mate int w = 0, h = 0, c = 0; unsigned char *pixels = RT_LoadImageFromDisk(&g_thread_arena, file, &w, &h, &c, bpp); + if (i == RT_MaterialTextureSlot_Emissive) + { + // Premultiply emissive by alpha to avoid white transparent backgrounds from showing... + + uint32_t *at = (uint32_t *)pixels; + for (int i = 0; i < w*h; i++) + { + RT_Vec4 color = RT_UnpackRGBA(*at); + color.xyz = RT_Vec3Muls(color.xyz, color.w); + *at++ = RT_PackRGBA(color); + } + } + if (pixels) { material->textures[i] = RT_UploadTexture(&(RT_UploadTextureParams){ @@ -277,14 +297,14 @@ void RT_InitAllBitmaps(void) .name = RT_ArenaPrintF(&g_thread_arena, "Game Texture %hu:basecolor (original)", bm_index), .format = g_rt_material_texture_slot_formats[RT_MaterialTextureSlot_Albedo], }); - } #ifdef RT_DUMP_GAME_BITMAPS - { - const char *png_path = RT_ArenaPrintF(&g_thread_arena, "assets/texture_dump/%s.png", bitmap_name); - RT_WritePNGToDisk(png_path, bitmap->bm_w, bitmap->bm_h, 4, pixels, 4*bitmap->bm_w); - } + { + const char *png_path = RT_ArenaPrintF(&g_thread_arena, "assets/texture_dump/%s.png", bitmap_name); + RT_WritePNGToDisk(png_path, bitmap->bm_w, bitmap->bm_h, 4, pixels, 4*bitmap->bm_w); + } #endif + } RT_UpdateMaterial(bm_index, material); } @@ -369,6 +389,8 @@ int RT_ReloadMaterials(void) if (!RT_RESOURCE_HANDLE_VALID(material->textures[i]) || // always try to load textures if there weren't any for this kind TextureFileIsOutdated(paths->textures[i])) { + if (RT_RESOURCE_HANDLE_VALID(material->textures[i])) + RT_ReleaseTexture(material->textures[i]); needs_reload |= (1u << i); } } diff --git a/RT/Renderer/Backend/Common/CMakeLists.txt b/RT/Renderer/Backend/Common/CMakeLists.txt index b338e43..0c8ce37 100644 --- a/RT/Renderer/Backend/Common/CMakeLists.txt +++ b/RT/Renderer/Backend/Common/CMakeLists.txt @@ -1,8 +1,8 @@ -# CMakeList.txt : Cmake project for the common renderer headers. -cmake_minimum_required (VERSION 3.8) - -#for now no headers due to the export headers for the dll. However, we still want the include directories. -add_library(Renderer_Common INTERFACE) - -target_include_directories(Renderer_Common INTERFACE +# CMakeList.txt : Cmake project for the common renderer headers. +cmake_minimum_required (VERSION 3.8) + +#for now no headers due to the export headers for the dll. However, we still want the include directories. +add_library(Renderer_Common INTERFACE) + +target_include_directories(Renderer_Common INTERFACE "${CMAKE_CURRENT_LIST_DIR}/include") \ No newline at end of file diff --git a/RT/Renderer/Backend/Common/include/GLTFLoader.h b/RT/Renderer/Backend/Common/include/GLTFLoader.h index 0dc736c..b451fc9 100644 --- a/RT/Renderer/Backend/Common/include/GLTFLoader.h +++ b/RT/Renderer/Backend/Common/include/GLTFLoader.h @@ -2,6 +2,7 @@ #include "ApiTypes.h" +#pragma pack(push, 8) typedef struct RT_Arena RT_Arena; typedef struct RT_Material RT_Material; @@ -10,6 +11,11 @@ typedef struct RT_GLTFModel RT_ResourceHandle handle; } RT_GLTFModel; +typedef struct RT_MaterialOverride { + uint16_t material_index; + char* name; +} RT_MaterialOverride; + typedef struct RT_GLTFNode { char *name; @@ -23,4 +29,5 @@ typedef struct RT_GLTFNode RT_Mat4 transform; } RT_GLTFNode; -RT_API RT_GLTFNode *RT_LoadGLTF(RT_Arena* arena, const char* path); \ No newline at end of file +RT_API RT_GLTFNode *RT_LoadGLTF(RT_Arena* arena, const char* path, RT_MaterialOverride* material_override); +#pragma pack(pop) \ No newline at end of file diff --git a/RT/Renderer/Backend/Common/include/Renderer.h b/RT/Renderer/Backend/Common/include/Renderer.h index 825a99e..8fc626d 100644 --- a/RT/Renderer/Backend/Common/include/Renderer.h +++ b/RT/Renderer/Backend/Common/include/Renderer.h @@ -9,9 +9,12 @@ // ------------------------------------------------------------------ -#define RT_MAX_TEXTURES (2010) -#define RT_MAX_MATERIALS (2010) +#define RT_MAX_TEXTURES (3*2010) +#define RT_MAX_BITMAP_FILES (1800) // mirrored from the game to avoid dependency on game headers #define RT_MAX_OBJ_BITMAPS (210) // mirrored from the game to avoid dependency on game headers +#define RT_EXTRA_BITMAP_COUNT (100) // for GLTF loading and such, some extra headroom +#define RT_EXTRA_BITMAPS_START (RT_MAX_BITMAP_FILES + RT_MAX_OBJ_BITMAPS) +#define RT_MAX_MATERIALS (RT_MAX_BITMAP_FILES + RT_MAX_OBJ_BITMAPS + RT_EXTRA_BITMAP_COUNT) #define RT_MAX_SEGMENTS (9000) // mirrored from the game to avoid dependency on game headers #define RT_SIDES_PER_SEGMENT (6) #define RT_TRIANGLES_PER_SIDE (2) @@ -21,15 +24,19 @@ // OR this in for triangle->material_edge_index for poly objects and have them // skip the material edges array... -#define RT_TRIANGLE_HOLDS_MATERIAL_EDGE (1 << 15) +#define RT_TRIANGLE_HOLDS_MATERIAL_EDGE (1 << 31) +#define RT_TRIANGLE_HOLDS_MATERIAL_INDEX (1 << 30) #define RT_TRIANGLE_MATERIAL_INSTANCE_OVERRIDE (0xFFFF) // Some built in materials to use #define RT_MATERIAL_FLAT_WHITE (RT_MAX_MATERIALS - 1) #define RT_MATERIAL_EMISSIVE_WHITE (RT_MAX_MATERIALS - 2) #define RT_MATERIAL_ENDLEVEL_TERRAIN (RT_MAX_MATERIALS - 3) +#define RT_MATERIAL_COCKPIT_UI (RT_MAX_MATERIALS - 4) +#define RT_MATERIAL_SATELLITE (RT_MAX_MATERIALS - 5) typedef struct RT_Arena RT_Arena; +typedef struct RT_Config RT_Config; typedef struct RT_MaterialEdge { @@ -56,17 +63,32 @@ typedef struct RT_RendererInitParams enum RT_RenderMeshFlags { - RT_RenderMeshFlags_ReverseCulling = (1 << 0) + RT_RenderMeshFlags_ReverseCulling = (1 << 0), + RT_RenderMeshFlags_Teleport = (1 << 1), // signifies that the prev transform should be discarded, because the mesh moved in a discontinuous way. }; +typedef struct RT_RenderKey +{ + union + { + struct + { + int signature; + int submodel_index; + }; + uint64_t value; + }; +} RT_RenderKey; + typedef struct RT_RenderMeshParams { + RT_RenderKey key; // unique identifier to automatically track prev transforms (adding this to the renderer was maybe a mistake, but it's here now) + uint32_t flags; RT_ResourceHandle mesh_handle; const RT_Mat4* transform; - const RT_Mat4* prev_transform; + const RT_Mat4* prev_transform; // if you supply this the renderer uses it instead of the tracked prev transform it knows from the key uint32_t color; uint16_t material_override; - uint32_t flags; } RT_RenderMeshParams; // Volatile: Must match common.hlsl @@ -106,6 +128,7 @@ typedef struct RT_RendererIO // in/out: int debug_render_mode; + RT_Config *config; // out: bool frame_frozen; @@ -125,6 +148,11 @@ static char g_rt_texture_format_bpp[] = 1, }; +typedef enum RT_TextureFlag +{ + RT_TextureFlag_None +} RT_TextureFlag; + typedef struct RT_UploadTextureParams { RT_TextureFormat format; @@ -133,6 +161,7 @@ typedef struct RT_UploadTextureParams uint32_t height; uint32_t pitch; uint32_t* pixels; + uint8_t flags; const char *name; // Optional, used for enhanced graphics debugging } RT_UploadTextureParams; @@ -202,9 +231,12 @@ typedef struct RT_DoRendererDebugMenuParams bool ui_has_cursor_focus; } RT_DoRendererDebugMenuParams; +// @Volatile: Must match definition in common.hlsl typedef enum RT_MaterialFlags { RT_MaterialFlag_BlackbodyRadiator = 0x1, // things like lava, basically just treats the albedo as an emissive map and skips all shading + RT_MaterialFlag_NoCastingShadow = 0x2, + RT_MaterialFlag_Light = 0x4, } RT_MaterialFlags; typedef enum RT_MaterialTextureSlot @@ -243,6 +275,7 @@ typedef struct RT_SceneSettings RT_Camera* camera; uint32_t render_width_override; uint32_t render_height_override; + bool render_blit; } RT_SceneSettings; typedef struct RT_RasterTrianglesParams @@ -281,11 +314,14 @@ RT_API RT_ResourceHandle RT_UploadTexture(const RT_UploadTextureParams* params); // Returns the material_index you passed in, or UINT16_MAX if it was out of bounds. RT_API uint16_t RT_UpdateMaterial(uint16_t material_index, const RT_Material *material); RT_API RT_ResourceHandle RT_UploadMesh(const RT_UploadMeshParams* params); +RT_API void RT_ReleaseTexture(const RT_ResourceHandle texture_handle); RT_API void RT_ReleaseMesh(const RT_ResourceHandle mesh_handle); RT_API bool RT_GenerateTangents(RT_Triangle *triangles, size_t triangle_count); // Will modify triangles in-place to add tangent vectors RT_API RT_ResourceHandle RT_GetDefaultWhiteTexture(void); RT_API RT_ResourceHandle RT_GetDefaultBlackTexture(void); +RT_API RT_ResourceHandle RT_GetBillboardMesh(void); +RT_API RT_ResourceHandle RT_GetCubeMesh(void); RT_API int RT_CheckWindowMinimized(void); @@ -310,6 +346,7 @@ static inline void RT_RaytraceSubmitLight(RT_Light light) { RT_RaytraceSubmitLights(1, &light); } +RT_API uint32_t RT_RaytraceGetCurrentLightCount(); RT_API void RT_RaytraceSetVerticalOffset(float new_offset); RT_API float RT_RaytraceGetVerticalOffset(); RT_API void RT_RaytraceSetSkyColors(RT_Vec3 sky_top, RT_Vec3 sky_bottom); @@ -317,15 +354,20 @@ RT_API void RT_RaytraceSetSkyColors(RT_Vec3 sky_top, RT_Vec3 sky_bottom); // ------------------------------------------------------------------------------- // Rasterizer functions -// This sets the rasterizers viewport (UI) +// Sets the rasterization viewport for the upcoming rasterization submissions RT_API void RT_RasterSetViewport(float x, float y, float width, float height); -// Used to rasterize UI triangles +// Sets the render target for the upcoming rasterization submissions. Also clears the render target +RT_API void RT_RasterSetRenderTarget(RT_ResourceHandle texture); +// Used to rasterize triangles to the currently set render target RT_API void RT_RasterTriangles(RT_RasterTrianglesParams* params, uint32_t num_params); -// Used to rasterize UI lines +// Used to rasterize lines to the currently set render target RT_API void RT_RasterLines(RT_RasterLineVertex* vertices, uint32_t num_vertices); -// Used to rasterize debug lines in the actual 3D world -RT_API void RT_DrawLineWorld(RT_Vec3 a, RT_Vec3 b, RT_Vec4 color); +// Used to rasterize debug lines in the actual 3D world. This will always render to the final ouput, not the currently set rasterization target +RT_API void RT_RasterLineWorld(RT_Vec3 a, RT_Vec3 b, RT_Vec4 color); RT_API void RT_RasterLinesWorld(RT_RasterLineVertex* vertices, uint32_t num_vertices); +RT_API void RT_RasterBlitScene(const RT_Vec2* top_left, const RT_Vec2* bottom_right, bool blit_blend); +RT_API void RT_RasterBlit(RT_ResourceHandle src, const RT_Vec2* top_left, const RT_Vec2* bottom_right, bool blit_blend); +// Used to flush the rasterizer with all pending geometry that needs to be drawn RT_API void RT_RasterRender(); // ------------------------------------------------------------------------------- diff --git a/RT/Renderer/Backend/DX12/CMakeLists.txt b/RT/Renderer/Backend/DX12/CMakeLists.txt index 8ac98d9..4c073ca 100644 --- a/RT/Renderer/Backend/DX12/CMakeLists.txt +++ b/RT/Renderer/Backend/DX12/CMakeLists.txt @@ -1,141 +1,142 @@ -# CMakeList.txt : Cmake project for the DirectX12DLL -cmake_minimum_required (VERSION 3.8) - -if (MSVC) - add_compile_options(/W4 /WX /wd4201 /wd4324) -else() - add_compile_options(-Wall -Wextra -pedantic -Werror /wd4201 /wd4324) -endif() -set (CMAKE_COMPILE_WARNING_AS_ERROR ON) - -#general settings -set (IMGUI_SOURCE_FILES - "cimgui/cimgui.cpp" - "cimgui/imgui/imgui.cpp" - "cimgui/imgui/imgui_draw.cpp" - "cimgui/imgui/imgui_demo.cpp" - "cimgui/imgui/imgui_widgets.cpp" - "cimgui/imgui/imgui_tables.cpp" - "cimgui/imgui/backends/imgui_impl_win32.cpp" - "cimgui/imgui/backends/imgui_impl_dx12.cpp" -) - -set (IMPLOT_SOURCE_FILES - "implot/implot.cpp" - "implot/implot_items.cpp" -) - -set (Renderer_HEADER -"src/RenderBackend.h" -"src/CommandQueue.h" -"src/CommandList.h" -"src/GPUProfiler.h" -"src/Resource.h" -"src/RingBuffer.h" -"src/ShaderTable.h" -"src/GlobalDX.h" -"D3DX/d3dx12.h" -"CGLTF/cgltf.h" -"src/DescriptorArena.hpp" -"src/mikktspace.h") - -#I hate cmake for not allowing me to link interface libs. Ah well, now we do this indirection! -set (Renderer_PUBLIC_HEADER -"../Common/include/Renderer.h" -"../Common/include/ApiTypes.h" -"../Common/include/GLTFLoader.h" -"../Common/include/ImageReadWrite.h") - -set (Renderer_SOURCE -"src/Renderer.cpp" -"src/RenderBackend.cpp" -"src/CommandQueue.cpp" -"src/CommandList.cpp" -"src/GPUProfiler.cpp" -"src/Resource.cpp" -"src/RingBuffer.cpp" -"src/ShaderTable.cpp" -"src/GLTFLoader.cpp" -"src/ImageReadWrite.cpp" -"src/DescriptorArena.cpp" -"src/ResourceTracker.cpp" -"src/mikktspace.c" -${IMGUI_SOURCE_FILES} -${IMPLOT_SOURCE_FILES} -) - -add_subdirectory("DXC") - -# Export all Symbols by default (on Windows creates '.lib'+ '.dll'). -set ( CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON ) - -message("Building the renderer as an .dll file.") -#Add source to this project's executable. -add_library (Renderer SHARED -${Renderer_SOURCE} -${Renderer_HEADER}) - -install(TARGETS Renderer - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -install(FILES "DXC/bin/x64/dxcompiler.dll" "DXC/bin/x64/dxil.dll" DESTINATION ${CMAKE_INSTALL_BINDIR}) -install(FILES ${Renderer_PUBLIC_HEADER} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - -#Executable-Object -set_target_properties ( Renderer PROPERTIES - PUBLIC_HEADER "${Renderer_PUBLIC_HEADER}" - RUNTIME_OUTPUT_DIRECTORY $ -) - -set_property(TARGET Renderer PROPERTY CXX_STANDARD 17) - -add_compile_definitions(UNICODE=1) -add_compile_definitions(_CRT_SECURE_NO_WARNINGS) # microsoft is a menace - -target_include_directories(Renderer PUBLIC - "include" - "assets/shaders/include_shared" -) - -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/cimgui -) -target_include_directories( - Renderer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/cimgui/imgui - Renderer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/implot -) - -target_link_libraries(Renderer - DX12_ShaderCompiler - d3d12.lib - dxgi.lib - dxguid.lib - Renderer_Common - RT_CORE - "${CMAKE_CURRENT_SOURCE_DIR}/DXC/lib/x64/dxcompiler.lib" -) - -add_custom_command(TARGET Renderer POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - "${CMAKE_CURRENT_SOURCE_DIR}/DXC/bin/x64/dxcompiler.dll" - $) - -add_custom_command(TARGET Renderer POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - "${CMAKE_CURRENT_SOURCE_DIR}/DXC/bin/x64/dxil.dll" - $) - -add_executable(Showcase_Renderer -"src/main.cpp") - -target_link_libraries(Showcase_Renderer -Renderer) - -set_target_properties ( Showcase_Renderer PROPERTIES - RUNTIME_OUTPUT_DIRECTORY $ -) - -#copies over external assets if they are changed. +# CMakeList.txt : Cmake project for the DirectX12DLL +cmake_minimum_required (VERSION 3.8) + +if (MSVC) + add_compile_options(/W4 /WX /wd4201 /wd4324) +else() + add_compile_options(-Wall -Wextra -pedantic -Werror /wd4201 /wd4324) +endif() +set (CMAKE_COMPILE_WARNING_AS_ERROR ON) + +#general settings +set (IMGUI_SOURCE_FILES + "cimgui/cimgui.cpp" + "cimgui/imgui/imgui.cpp" + "cimgui/imgui/imgui_draw.cpp" + "cimgui/imgui/imgui_demo.cpp" + "cimgui/imgui/imgui_widgets.cpp" + "cimgui/imgui/imgui_tables.cpp" + "cimgui/imgui/backends/imgui_impl_win32.cpp" + "cimgui/imgui/backends/imgui_impl_dx12.cpp" +) + +set (IMPLOT_SOURCE_FILES + "implot/implot.cpp" + "implot/implot_items.cpp" +) + +set (Renderer_HEADER +"src/RenderBackend.h" +"src/CommandQueue.h" +"src/CommandList.h" +"src/GPUProfiler.h" +"src/Resource.h" +"src/RingBuffer.h" +"src/ShaderTable.h" +"src/GlobalDX.h" +"D3DX/d3dx12.h" +"CGLTF/cgltf.h" +"src/DescriptorArena.hpp" +"src/mikktspace.h") + +#I hate cmake for not allowing me to link interface libs. Ah well, now we do this indirection! +set (Renderer_PUBLIC_HEADER +"../Common/include/Renderer.h" +"../Common/include/ApiTypes.h" +"../Common/include/GLTFLoader.h" +"../Common/include/ImageReadWrite.h") + +set (Renderer_SOURCE +"src/Renderer.cpp" +"src/RenderBackend.cpp" +"src/CommandQueue.cpp" +"src/CommandList.cpp" +"src/GPUProfiler.cpp" +"src/Resource.cpp" +"src/RingBuffer.cpp" +"src/ShaderTable.cpp" +"src/GLTFLoader.cpp" +"src/ImageReadWrite.cpp" +"src/DescriptorArena.cpp" +"src/ResourceTracker.cpp" +"src/mikktspace.c" +"src/MeshTracker.cpp" +${IMGUI_SOURCE_FILES} +${IMPLOT_SOURCE_FILES} +) + +add_subdirectory("DXC") + +# Export all Symbols by default (on Windows creates '.lib'+ '.dll'). +set ( CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON ) + +message("Building the renderer as an .dll file.") +#Add source to this project's executable. +add_library (Renderer SHARED +${Renderer_SOURCE} +${Renderer_HEADER}) + +install(TARGETS Renderer + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +install(FILES "DXC/bin/x64/dxcompiler.dll" "DXC/bin/x64/dxil.dll" DESTINATION ${CMAKE_INSTALL_BINDIR}) +install(FILES ${Renderer_PUBLIC_HEADER} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +#Executable-Object +set_target_properties ( Renderer PROPERTIES + PUBLIC_HEADER "${Renderer_PUBLIC_HEADER}" + RUNTIME_OUTPUT_DIRECTORY $ +) + +set_property(TARGET Renderer PROPERTY CXX_STANDARD 17) + +add_compile_definitions(UNICODE=1) +add_compile_definitions(_CRT_SECURE_NO_WARNINGS) # microsoft is a menace + +target_include_directories(Renderer PUBLIC + "include" + "assets/shaders/include_shared" +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/cimgui +) +target_include_directories( + Renderer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/cimgui/imgui + Renderer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/implot +) + +target_link_libraries(Renderer + DX12_ShaderCompiler + d3d12.lib + dxgi.lib + dxguid.lib + Renderer_Common + RT_CORE + "${CMAKE_CURRENT_SOURCE_DIR}/DXC/lib/x64/dxcompiler.lib" +) + +add_custom_command(TARGET Renderer POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/DXC/bin/x64/dxcompiler.dll" + $) + +add_custom_command(TARGET Renderer POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/DXC/bin/x64/dxil.dll" + $) + +add_executable(Showcase_Renderer +"src/main.cpp") + +target_link_libraries(Showcase_Renderer +Renderer) + +set_target_properties ( Showcase_Renderer PROPERTIES + RUNTIME_OUTPUT_DIRECTORY $ +) + +#copies over external assets if they are changed. add_subdirectory("assets") \ No newline at end of file diff --git a/RT/Renderer/Backend/DX12/DXC/CMakeLists.txt b/RT/Renderer/Backend/DX12/DXC/CMakeLists.txt index d979544..4cccf80 100644 --- a/RT/Renderer/Backend/DX12/DXC/CMakeLists.txt +++ b/RT/Renderer/Backend/DX12/DXC/CMakeLists.txt @@ -1,7 +1,7 @@ -#Cmake for all the third_party libraries, they will be compiled or collected here. -cmake_minimum_required (VERSION 3.8) - -add_library(DX12_ShaderCompiler INTERFACE -"inc/dxcapi.h" -"inc/d3d12shader.h") +#Cmake for all the third_party libraries, they will be compiled or collected here. +cmake_minimum_required (VERSION 3.8) + +add_library(DX12_ShaderCompiler INTERFACE +"inc/dxcapi.h" +"inc/d3d12shader.h") target_include_directories(DX12_ShaderCompiler INTERFACE ${CMAKE_CURRENT_LIST_DIR}) \ No newline at end of file diff --git a/RT/Renderer/Backend/DX12/DXC/inc/d3d12shader.h b/RT/Renderer/Backend/DX12/DXC/inc/d3d12shader.h index 749e933..808bfc0 100644 --- a/RT/Renderer/Backend/DX12/DXC/inc/d3d12shader.h +++ b/RT/Renderer/Backend/DX12/DXC/inc/d3d12shader.h @@ -1,487 +1,487 @@ -////////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -// -// File: D3D12Shader.h -// Content: D3D12 Shader Types and APIs -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef __D3D12SHADER_H__ -#define __D3D12SHADER_H__ - -#include "d3dcommon.h" - -typedef enum D3D12_SHADER_VERSION_TYPE -{ - D3D12_SHVER_PIXEL_SHADER = 0, - D3D12_SHVER_VERTEX_SHADER = 1, - D3D12_SHVER_GEOMETRY_SHADER = 2, - - // D3D11 Shaders - D3D12_SHVER_HULL_SHADER = 3, - D3D12_SHVER_DOMAIN_SHADER = 4, - D3D12_SHVER_COMPUTE_SHADER = 5, - - // D3D12 Shaders - D3D12_SHVER_LIBRARY = 6, - - D3D12_SHVER_RAY_GENERATION_SHADER = 7, - D3D12_SHVER_INTERSECTION_SHADER = 8, - D3D12_SHVER_ANY_HIT_SHADER = 9, - D3D12_SHVER_CLOSEST_HIT_SHADER = 10, - D3D12_SHVER_MISS_SHADER = 11, - D3D12_SHVER_CALLABLE_SHADER = 12, - - D3D12_SHVER_MESH_SHADER = 13, - D3D12_SHVER_AMPLIFICATION_SHADER = 14, - - D3D12_SHVER_RESERVED0 = 0xFFF0, -} D3D12_SHADER_VERSION_TYPE; - -#define D3D12_SHVER_GET_TYPE(_Version) \ - (((_Version) >> 16) & 0xffff) -#define D3D12_SHVER_GET_MAJOR(_Version) \ - (((_Version) >> 4) & 0xf) -#define D3D12_SHVER_GET_MINOR(_Version) \ - (((_Version) >> 0) & 0xf) - -// Slot ID for library function return -#define D3D_RETURN_PARAMETER_INDEX (-1) - -typedef D3D_RESOURCE_RETURN_TYPE D3D12_RESOURCE_RETURN_TYPE; - -typedef D3D_CBUFFER_TYPE D3D12_CBUFFER_TYPE; - - -typedef struct _D3D12_SIGNATURE_PARAMETER_DESC -{ - LPCSTR SemanticName; // Name of the semantic - UINT SemanticIndex; // Index of the semantic - UINT Register; // Number of member variables - D3D_NAME SystemValueType;// A predefined system value, or D3D_NAME_UNDEFINED if not applicable - D3D_REGISTER_COMPONENT_TYPE ComponentType; // Scalar type (e.g. uint, float, etc.) - BYTE Mask; // Mask to indicate which components of the register - // are used (combination of D3D10_COMPONENT_MASK values) - BYTE ReadWriteMask; // Mask to indicate whether a given component is - // never written (if this is an output signature) or - // always read (if this is an input signature). - // (combination of D3D_MASK_* values) - UINT Stream; // Stream index - D3D_MIN_PRECISION MinPrecision; // Minimum desired interpolation precision -} D3D12_SIGNATURE_PARAMETER_DESC; - -typedef struct _D3D12_SHADER_BUFFER_DESC -{ - LPCSTR Name; // Name of the constant buffer - D3D_CBUFFER_TYPE Type; // Indicates type of buffer content - UINT Variables; // Number of member variables - UINT Size; // Size of CB (in bytes) - UINT uFlags; // Buffer description flags -} D3D12_SHADER_BUFFER_DESC; - -typedef struct _D3D12_SHADER_VARIABLE_DESC -{ - LPCSTR Name; // Name of the variable - UINT StartOffset; // Offset in constant buffer's backing store - UINT Size; // Size of variable (in bytes) - UINT uFlags; // Variable flags - LPVOID DefaultValue; // Raw pointer to default value - UINT StartTexture; // First texture index (or -1 if no textures used) - UINT TextureSize; // Number of texture slots possibly used. - UINT StartSampler; // First sampler index (or -1 if no textures used) - UINT SamplerSize; // Number of sampler slots possibly used. -} D3D12_SHADER_VARIABLE_DESC; - -typedef struct _D3D12_SHADER_TYPE_DESC -{ - D3D_SHADER_VARIABLE_CLASS Class; // Variable class (e.g. object, matrix, etc.) - D3D_SHADER_VARIABLE_TYPE Type; // Variable type (e.g. float, sampler, etc.) - UINT Rows; // Number of rows (for matrices, 1 for other numeric, 0 if not applicable) - UINT Columns; // Number of columns (for vectors & matrices, 1 for other numeric, 0 if not applicable) - UINT Elements; // Number of elements (0 if not an array) - UINT Members; // Number of members (0 if not a structure) - UINT Offset; // Offset from the start of structure (0 if not a structure member) - LPCSTR Name; // Name of type, can be NULL -} D3D12_SHADER_TYPE_DESC; - -typedef D3D_TESSELLATOR_DOMAIN D3D12_TESSELLATOR_DOMAIN; - -typedef D3D_TESSELLATOR_PARTITIONING D3D12_TESSELLATOR_PARTITIONING; - -typedef D3D_TESSELLATOR_OUTPUT_PRIMITIVE D3D12_TESSELLATOR_OUTPUT_PRIMITIVE; - -typedef struct _D3D12_SHADER_DESC -{ - UINT Version; // Shader version - LPCSTR Creator; // Creator string - UINT Flags; // Shader compilation/parse flags - - UINT ConstantBuffers; // Number of constant buffers - UINT BoundResources; // Number of bound resources - UINT InputParameters; // Number of parameters in the input signature - UINT OutputParameters; // Number of parameters in the output signature - - UINT InstructionCount; // Number of emitted instructions - UINT TempRegisterCount; // Number of temporary registers used - UINT TempArrayCount; // Number of temporary arrays used - UINT DefCount; // Number of constant defines - UINT DclCount; // Number of declarations (input + output) - UINT TextureNormalInstructions; // Number of non-categorized texture instructions - UINT TextureLoadInstructions; // Number of texture load instructions - UINT TextureCompInstructions; // Number of texture comparison instructions - UINT TextureBiasInstructions; // Number of texture bias instructions - UINT TextureGradientInstructions; // Number of texture gradient instructions - UINT FloatInstructionCount; // Number of floating point arithmetic instructions used - UINT IntInstructionCount; // Number of signed integer arithmetic instructions used - UINT UintInstructionCount; // Number of unsigned integer arithmetic instructions used - UINT StaticFlowControlCount; // Number of static flow control instructions used - UINT DynamicFlowControlCount; // Number of dynamic flow control instructions used - UINT MacroInstructionCount; // Number of macro instructions used - UINT ArrayInstructionCount; // Number of array instructions used - UINT CutInstructionCount; // Number of cut instructions used - UINT EmitInstructionCount; // Number of emit instructions used - D3D_PRIMITIVE_TOPOLOGY GSOutputTopology; // Geometry shader output topology - UINT GSMaxOutputVertexCount; // Geometry shader maximum output vertex count - D3D_PRIMITIVE InputPrimitive; // GS/HS input primitive - UINT PatchConstantParameters; // Number of parameters in the patch constant signature - UINT cGSInstanceCount; // Number of Geometry shader instances - UINT cControlPoints; // Number of control points in the HS->DS stage - D3D_TESSELLATOR_OUTPUT_PRIMITIVE HSOutputPrimitive; // Primitive output by the tessellator - D3D_TESSELLATOR_PARTITIONING HSPartitioning; // Partitioning mode of the tessellator - D3D_TESSELLATOR_DOMAIN TessellatorDomain; // Domain of the tessellator (quad, tri, isoline) - // instruction counts - UINT cBarrierInstructions; // Number of barrier instructions in a compute shader - UINT cInterlockedInstructions; // Number of interlocked instructions - UINT cTextureStoreInstructions; // Number of texture writes -} D3D12_SHADER_DESC; - -typedef struct _D3D12_SHADER_INPUT_BIND_DESC -{ - LPCSTR Name; // Name of the resource - D3D_SHADER_INPUT_TYPE Type; // Type of resource (e.g. texture, cbuffer, etc.) - UINT BindPoint; // Starting bind point - UINT BindCount; // Number of contiguous bind points (for arrays) - - UINT uFlags; // Input binding flags - D3D_RESOURCE_RETURN_TYPE ReturnType; // Return type (if texture) - D3D_SRV_DIMENSION Dimension; // Dimension (if texture) - UINT NumSamples; // Number of samples (0 if not MS texture) - UINT Space; // Register space - UINT uID; // Range ID in the bytecode -} D3D12_SHADER_INPUT_BIND_DESC; - -#define D3D_SHADER_REQUIRES_DOUBLES 0x00000001 -#define D3D_SHADER_REQUIRES_EARLY_DEPTH_STENCIL 0x00000002 -#define D3D_SHADER_REQUIRES_UAVS_AT_EVERY_STAGE 0x00000004 -#define D3D_SHADER_REQUIRES_64_UAVS 0x00000008 -#define D3D_SHADER_REQUIRES_MINIMUM_PRECISION 0x00000010 -#define D3D_SHADER_REQUIRES_11_1_DOUBLE_EXTENSIONS 0x00000020 -#define D3D_SHADER_REQUIRES_11_1_SHADER_EXTENSIONS 0x00000040 -#define D3D_SHADER_REQUIRES_LEVEL_9_COMPARISON_FILTERING 0x00000080 -#define D3D_SHADER_REQUIRES_TILED_RESOURCES 0x00000100 -#define D3D_SHADER_REQUIRES_STENCIL_REF 0x00000200 -#define D3D_SHADER_REQUIRES_INNER_COVERAGE 0x00000400 -#define D3D_SHADER_REQUIRES_TYPED_UAV_LOAD_ADDITIONAL_FORMATS 0x00000800 -#define D3D_SHADER_REQUIRES_ROVS 0x00001000 -#define D3D_SHADER_REQUIRES_VIEWPORT_AND_RT_ARRAY_INDEX_FROM_ANY_SHADER_FEEDING_RASTERIZER 0x00002000 -#define D3D_SHADER_REQUIRES_WAVE_OPS 0x00004000 -#define D3D_SHADER_REQUIRES_INT64_OPS 0x00008000 -#define D3D_SHADER_REQUIRES_VIEW_ID 0x00010000 -#define D3D_SHADER_REQUIRES_BARYCENTRICS 0x00020000 -#define D3D_SHADER_REQUIRES_NATIVE_16BIT_OPS 0x00040000 -#define D3D_SHADER_REQUIRES_SHADING_RATE 0x00080000 -#define D3D_SHADER_REQUIRES_RAYTRACING_TIER_1_1 0x00100000 -#define D3D_SHADER_REQUIRES_SAMPLER_FEEDBACK 0x00200000 -#define D3D_SHADER_REQUIRES_ATOMIC_INT64_ON_TYPED_RESOURCE 0x00400000 -#define D3D_SHADER_REQUIRES_ATOMIC_INT64_ON_GROUP_SHARED 0x00800000 -#define D3D_SHADER_REQUIRES_DERIVATIVES_IN_MESH_AND_AMPLIFICATION_SHADERS 0x01000000 -#define D3D_SHADER_REQUIRES_RESOURCE_DESCRIPTOR_HEAP_INDEXING 0x02000000 -#define D3D_SHADER_REQUIRES_SAMPLER_DESCRIPTOR_HEAP_INDEXING 0x04000000 -#define D3D_SHADER_REQUIRES_WAVE_MMA 0x08000000 -#define D3D_SHADER_REQUIRES_ATOMIC_INT64_ON_DESCRIPTOR_HEAP_RESOURCE 0x10000000 - -typedef struct _D3D12_LIBRARY_DESC -{ - LPCSTR Creator; // The name of the originator of the library. - UINT Flags; // Compilation flags. - UINT FunctionCount; // Number of functions exported from the library. -} D3D12_LIBRARY_DESC; - -typedef struct _D3D12_FUNCTION_DESC -{ - UINT Version; // Shader version - LPCSTR Creator; // Creator string - UINT Flags; // Shader compilation/parse flags - - UINT ConstantBuffers; // Number of constant buffers - UINT BoundResources; // Number of bound resources - - UINT InstructionCount; // Number of emitted instructions - UINT TempRegisterCount; // Number of temporary registers used - UINT TempArrayCount; // Number of temporary arrays used - UINT DefCount; // Number of constant defines - UINT DclCount; // Number of declarations (input + output) - UINT TextureNormalInstructions; // Number of non-categorized texture instructions - UINT TextureLoadInstructions; // Number of texture load instructions - UINT TextureCompInstructions; // Number of texture comparison instructions - UINT TextureBiasInstructions; // Number of texture bias instructions - UINT TextureGradientInstructions; // Number of texture gradient instructions - UINT FloatInstructionCount; // Number of floating point arithmetic instructions used - UINT IntInstructionCount; // Number of signed integer arithmetic instructions used - UINT UintInstructionCount; // Number of unsigned integer arithmetic instructions used - UINT StaticFlowControlCount; // Number of static flow control instructions used - UINT DynamicFlowControlCount; // Number of dynamic flow control instructions used - UINT MacroInstructionCount; // Number of macro instructions used - UINT ArrayInstructionCount; // Number of array instructions used - UINT MovInstructionCount; // Number of mov instructions used - UINT MovcInstructionCount; // Number of movc instructions used - UINT ConversionInstructionCount; // Number of type conversion instructions used - UINT BitwiseInstructionCount; // Number of bitwise arithmetic instructions used - D3D_FEATURE_LEVEL MinFeatureLevel; // Min target of the function byte code - UINT64 RequiredFeatureFlags; // Required feature flags - - LPCSTR Name; // Function name - INT FunctionParameterCount; // Number of logical parameters in the function signature (not including return) - BOOL HasReturn; // TRUE, if function returns a value, false - it is a subroutine - BOOL Has10Level9VertexShader; // TRUE, if there is a 10L9 VS blob - BOOL Has10Level9PixelShader; // TRUE, if there is a 10L9 PS blob -} D3D12_FUNCTION_DESC; - -typedef struct _D3D12_PARAMETER_DESC -{ - LPCSTR Name; // Parameter name. - LPCSTR SemanticName; // Parameter semantic name (+index). - D3D_SHADER_VARIABLE_TYPE Type; // Element type. - D3D_SHADER_VARIABLE_CLASS Class; // Scalar/Vector/Matrix. - UINT Rows; // Rows are for matrix parameters. - UINT Columns; // Components or Columns in matrix. - D3D_INTERPOLATION_MODE InterpolationMode; // Interpolation mode. - D3D_PARAMETER_FLAGS Flags; // Parameter modifiers. - - UINT FirstInRegister; // The first input register for this parameter. - UINT FirstInComponent; // The first input register component for this parameter. - UINT FirstOutRegister; // The first output register for this parameter. - UINT FirstOutComponent; // The first output register component for this parameter. -} D3D12_PARAMETER_DESC; - - -////////////////////////////////////////////////////////////////////////////// -// Interfaces //////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -typedef interface ID3D12ShaderReflectionType ID3D12ShaderReflectionType; -typedef interface ID3D12ShaderReflectionType *LPD3D12SHADERREFLECTIONTYPE; - -typedef interface ID3D12ShaderReflectionVariable ID3D12ShaderReflectionVariable; -typedef interface ID3D12ShaderReflectionVariable *LPD3D12SHADERREFLECTIONVARIABLE; - -typedef interface ID3D12ShaderReflectionConstantBuffer ID3D12ShaderReflectionConstantBuffer; -typedef interface ID3D12ShaderReflectionConstantBuffer *LPD3D12SHADERREFLECTIONCONSTANTBUFFER; - -typedef interface ID3D12ShaderReflection ID3D12ShaderReflection; -typedef interface ID3D12ShaderReflection *LPD3D12SHADERREFLECTION; - -typedef interface ID3D12LibraryReflection ID3D12LibraryReflection; -typedef interface ID3D12LibraryReflection *LPD3D12LIBRARYREFLECTION; - -typedef interface ID3D12FunctionReflection ID3D12FunctionReflection; -typedef interface ID3D12FunctionReflection *LPD3D12FUNCTIONREFLECTION; - -typedef interface ID3D12FunctionParameterReflection ID3D12FunctionParameterReflection; -typedef interface ID3D12FunctionParameterReflection *LPD3D12FUNCTIONPARAMETERREFLECTION; - - -// {E913C351-783D-48CA-A1D1-4F306284AD56} -interface DECLSPEC_UUID("E913C351-783D-48CA-A1D1-4F306284AD56") ID3D12ShaderReflectionType; -DEFINE_GUID(IID_ID3D12ShaderReflectionType, -0xe913c351, 0x783d, 0x48ca, 0xa1, 0xd1, 0x4f, 0x30, 0x62, 0x84, 0xad, 0x56); - -#undef INTERFACE -#define INTERFACE ID3D12ShaderReflectionType - -DECLARE_INTERFACE(ID3D12ShaderReflectionType) -{ - STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_SHADER_TYPE_DESC *pDesc) PURE; - - STDMETHOD_(ID3D12ShaderReflectionType*, GetMemberTypeByIndex)(THIS_ _In_ UINT Index) PURE; - STDMETHOD_(ID3D12ShaderReflectionType*, GetMemberTypeByName)(THIS_ _In_ LPCSTR Name) PURE; - STDMETHOD_(LPCSTR, GetMemberTypeName)(THIS_ _In_ UINT Index) PURE; - - STDMETHOD(IsEqual)(THIS_ _In_ ID3D12ShaderReflectionType* pType) PURE; - STDMETHOD_(ID3D12ShaderReflectionType*, GetSubType)(THIS) PURE; - STDMETHOD_(ID3D12ShaderReflectionType*, GetBaseClass)(THIS) PURE; - STDMETHOD_(UINT, GetNumInterfaces)(THIS) PURE; - STDMETHOD_(ID3D12ShaderReflectionType*, GetInterfaceByIndex)(THIS_ _In_ UINT uIndex) PURE; - STDMETHOD(IsOfType)(THIS_ _In_ ID3D12ShaderReflectionType* pType) PURE; - STDMETHOD(ImplementsInterface)(THIS_ _In_ ID3D12ShaderReflectionType* pBase) PURE; -}; - -// {8337A8A6-A216-444A-B2F4-314733A73AEA} -interface DECLSPEC_UUID("8337A8A6-A216-444A-B2F4-314733A73AEA") ID3D12ShaderReflectionVariable; -DEFINE_GUID(IID_ID3D12ShaderReflectionVariable, -0x8337a8a6, 0xa216, 0x444a, 0xb2, 0xf4, 0x31, 0x47, 0x33, 0xa7, 0x3a, 0xea); - -#undef INTERFACE -#define INTERFACE ID3D12ShaderReflectionVariable - -DECLARE_INTERFACE(ID3D12ShaderReflectionVariable) -{ - STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_SHADER_VARIABLE_DESC *pDesc) PURE; - - STDMETHOD_(ID3D12ShaderReflectionType*, GetType)(THIS) PURE; - STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetBuffer)(THIS) PURE; - - STDMETHOD_(UINT, GetInterfaceSlot)(THIS_ _In_ UINT uArrayIndex) PURE; -}; - -// {C59598B4-48B3-4869-B9B1-B1618B14A8B7} -interface DECLSPEC_UUID("C59598B4-48B3-4869-B9B1-B1618B14A8B7") ID3D12ShaderReflectionConstantBuffer; -DEFINE_GUID(IID_ID3D12ShaderReflectionConstantBuffer, -0xc59598b4, 0x48b3, 0x4869, 0xb9, 0xb1, 0xb1, 0x61, 0x8b, 0x14, 0xa8, 0xb7); - -#undef INTERFACE -#define INTERFACE ID3D12ShaderReflectionConstantBuffer - -DECLARE_INTERFACE(ID3D12ShaderReflectionConstantBuffer) -{ - STDMETHOD(GetDesc)(THIS_ D3D12_SHADER_BUFFER_DESC *pDesc) PURE; - - STDMETHOD_(ID3D12ShaderReflectionVariable*, GetVariableByIndex)(THIS_ _In_ UINT Index) PURE; - STDMETHOD_(ID3D12ShaderReflectionVariable*, GetVariableByName)(THIS_ _In_ LPCSTR Name) PURE; -}; - -// The ID3D12ShaderReflection IID may change from SDK version to SDK version -// if the reflection API changes. This prevents new code with the new API -// from working with an old binary. Recompiling with the new header -// will pick up the new IID. - -// {5A58797D-A72C-478D-8BA2-EFC6B0EFE88E} -interface DECLSPEC_UUID("5A58797D-A72C-478D-8BA2-EFC6B0EFE88E") ID3D12ShaderReflection; -DEFINE_GUID(IID_ID3D12ShaderReflection, -0x5a58797d, 0xa72c, 0x478d, 0x8b, 0xa2, 0xef, 0xc6, 0xb0, 0xef, 0xe8, 0x8e); - -#undef INTERFACE -#define INTERFACE ID3D12ShaderReflection - -DECLARE_INTERFACE_(ID3D12ShaderReflection, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ _In_ REFIID iid, - _Out_ LPVOID *ppv) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - - STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_SHADER_DESC *pDesc) PURE; - - STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetConstantBufferByIndex)(THIS_ _In_ UINT Index) PURE; - STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetConstantBufferByName)(THIS_ _In_ LPCSTR Name) PURE; - - STDMETHOD(GetResourceBindingDesc)(THIS_ _In_ UINT ResourceIndex, - _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) PURE; - - STDMETHOD(GetInputParameterDesc)(THIS_ _In_ UINT ParameterIndex, - _Out_ D3D12_SIGNATURE_PARAMETER_DESC *pDesc) PURE; - STDMETHOD(GetOutputParameterDesc)(THIS_ _In_ UINT ParameterIndex, - _Out_ D3D12_SIGNATURE_PARAMETER_DESC *pDesc) PURE; - STDMETHOD(GetPatchConstantParameterDesc)(THIS_ _In_ UINT ParameterIndex, - _Out_ D3D12_SIGNATURE_PARAMETER_DESC *pDesc) PURE; - - STDMETHOD_(ID3D12ShaderReflectionVariable*, GetVariableByName)(THIS_ _In_ LPCSTR Name) PURE; - - STDMETHOD(GetResourceBindingDescByName)(THIS_ _In_ LPCSTR Name, - _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) PURE; - - STDMETHOD_(UINT, GetMovInstructionCount)(THIS) PURE; - STDMETHOD_(UINT, GetMovcInstructionCount)(THIS) PURE; - STDMETHOD_(UINT, GetConversionInstructionCount)(THIS) PURE; - STDMETHOD_(UINT, GetBitwiseInstructionCount)(THIS) PURE; - - STDMETHOD_(D3D_PRIMITIVE, GetGSInputPrimitive)(THIS) PURE; - STDMETHOD_(BOOL, IsSampleFrequencyShader)(THIS) PURE; - - STDMETHOD_(UINT, GetNumInterfaceSlots)(THIS) PURE; - STDMETHOD(GetMinFeatureLevel)(THIS_ _Out_ enum D3D_FEATURE_LEVEL* pLevel) PURE; - - STDMETHOD_(UINT, GetThreadGroupSize)(THIS_ - _Out_opt_ UINT* pSizeX, - _Out_opt_ UINT* pSizeY, - _Out_opt_ UINT* pSizeZ) PURE; - - STDMETHOD_(UINT64, GetRequiresFlags)(THIS) PURE; -}; - -// {8E349D19-54DB-4A56-9DC9-119D87BDB804} -interface DECLSPEC_UUID("8E349D19-54DB-4A56-9DC9-119D87BDB804") ID3D12LibraryReflection; -DEFINE_GUID(IID_ID3D12LibraryReflection, -0x8e349d19, 0x54db, 0x4a56, 0x9d, 0xc9, 0x11, 0x9d, 0x87, 0xbd, 0xb8, 0x4); - -#undef INTERFACE -#define INTERFACE ID3D12LibraryReflection - -DECLARE_INTERFACE_(ID3D12LibraryReflection, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ _In_ REFIID iid, _Out_ LPVOID * ppv) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - - STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_LIBRARY_DESC * pDesc) PURE; - - STDMETHOD_(ID3D12FunctionReflection *, GetFunctionByIndex)(THIS_ _In_ INT FunctionIndex) PURE; -}; - -// {1108795C-2772-4BA9-B2A8-D464DC7E2799} -interface DECLSPEC_UUID("1108795C-2772-4BA9-B2A8-D464DC7E2799") ID3D12FunctionReflection; -DEFINE_GUID(IID_ID3D12FunctionReflection, -0x1108795c, 0x2772, 0x4ba9, 0xb2, 0xa8, 0xd4, 0x64, 0xdc, 0x7e, 0x27, 0x99); - -#undef INTERFACE -#define INTERFACE ID3D12FunctionReflection - -DECLARE_INTERFACE(ID3D12FunctionReflection) -{ - STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_FUNCTION_DESC * pDesc) PURE; - - STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByIndex)(THIS_ _In_ UINT BufferIndex) PURE; - STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByName)(THIS_ _In_ LPCSTR Name) PURE; - - STDMETHOD(GetResourceBindingDesc)(THIS_ _In_ UINT ResourceIndex, - _Out_ D3D12_SHADER_INPUT_BIND_DESC * pDesc) PURE; - - STDMETHOD_(ID3D12ShaderReflectionVariable *, GetVariableByName)(THIS_ _In_ LPCSTR Name) PURE; - - STDMETHOD(GetResourceBindingDescByName)(THIS_ _In_ LPCSTR Name, - _Out_ D3D12_SHADER_INPUT_BIND_DESC * pDesc) PURE; - - // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. - STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter)(THIS_ _In_ INT ParameterIndex) PURE; -}; - -// {EC25F42D-7006-4F2B-B33E-02CC3375733F} -interface DECLSPEC_UUID("EC25F42D-7006-4F2B-B33E-02CC3375733F") ID3D12FunctionParameterReflection; -DEFINE_GUID(IID_ID3D12FunctionParameterReflection, -0xec25f42d, 0x7006, 0x4f2b, 0xb3, 0x3e, 0x2, 0xcc, 0x33, 0x75, 0x73, 0x3f); - -#undef INTERFACE -#define INTERFACE ID3D12FunctionParameterReflection - -DECLARE_INTERFACE(ID3D12FunctionParameterReflection) -{ - STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_PARAMETER_DESC * pDesc) PURE; -}; - - -////////////////////////////////////////////////////////////////////////////// -// APIs ////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -extern "C" { -#endif //__cplusplus - -#ifdef __cplusplus -} -#endif //__cplusplus - -#endif //__D3D12SHADER_H__ - +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +// File: D3D12Shader.h +// Content: D3D12 Shader Types and APIs +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef __D3D12SHADER_H__ +#define __D3D12SHADER_H__ + +#include "d3dcommon.h" + +typedef enum D3D12_SHADER_VERSION_TYPE +{ + D3D12_SHVER_PIXEL_SHADER = 0, + D3D12_SHVER_VERTEX_SHADER = 1, + D3D12_SHVER_GEOMETRY_SHADER = 2, + + // D3D11 Shaders + D3D12_SHVER_HULL_SHADER = 3, + D3D12_SHVER_DOMAIN_SHADER = 4, + D3D12_SHVER_COMPUTE_SHADER = 5, + + // D3D12 Shaders + D3D12_SHVER_LIBRARY = 6, + + D3D12_SHVER_RAY_GENERATION_SHADER = 7, + D3D12_SHVER_INTERSECTION_SHADER = 8, + D3D12_SHVER_ANY_HIT_SHADER = 9, + D3D12_SHVER_CLOSEST_HIT_SHADER = 10, + D3D12_SHVER_MISS_SHADER = 11, + D3D12_SHVER_CALLABLE_SHADER = 12, + + D3D12_SHVER_MESH_SHADER = 13, + D3D12_SHVER_AMPLIFICATION_SHADER = 14, + + D3D12_SHVER_RESERVED0 = 0xFFF0, +} D3D12_SHADER_VERSION_TYPE; + +#define D3D12_SHVER_GET_TYPE(_Version) \ + (((_Version) >> 16) & 0xffff) +#define D3D12_SHVER_GET_MAJOR(_Version) \ + (((_Version) >> 4) & 0xf) +#define D3D12_SHVER_GET_MINOR(_Version) \ + (((_Version) >> 0) & 0xf) + +// Slot ID for library function return +#define D3D_RETURN_PARAMETER_INDEX (-1) + +typedef D3D_RESOURCE_RETURN_TYPE D3D12_RESOURCE_RETURN_TYPE; + +typedef D3D_CBUFFER_TYPE D3D12_CBUFFER_TYPE; + + +typedef struct _D3D12_SIGNATURE_PARAMETER_DESC +{ + LPCSTR SemanticName; // Name of the semantic + UINT SemanticIndex; // Index of the semantic + UINT Register; // Number of member variables + D3D_NAME SystemValueType;// A predefined system value, or D3D_NAME_UNDEFINED if not applicable + D3D_REGISTER_COMPONENT_TYPE ComponentType; // Scalar type (e.g. uint, float, etc.) + BYTE Mask; // Mask to indicate which components of the register + // are used (combination of D3D10_COMPONENT_MASK values) + BYTE ReadWriteMask; // Mask to indicate whether a given component is + // never written (if this is an output signature) or + // always read (if this is an input signature). + // (combination of D3D_MASK_* values) + UINT Stream; // Stream index + D3D_MIN_PRECISION MinPrecision; // Minimum desired interpolation precision +} D3D12_SIGNATURE_PARAMETER_DESC; + +typedef struct _D3D12_SHADER_BUFFER_DESC +{ + LPCSTR Name; // Name of the constant buffer + D3D_CBUFFER_TYPE Type; // Indicates type of buffer content + UINT Variables; // Number of member variables + UINT Size; // Size of CB (in bytes) + UINT uFlags; // Buffer description flags +} D3D12_SHADER_BUFFER_DESC; + +typedef struct _D3D12_SHADER_VARIABLE_DESC +{ + LPCSTR Name; // Name of the variable + UINT StartOffset; // Offset in constant buffer's backing store + UINT Size; // Size of variable (in bytes) + UINT uFlags; // Variable flags + LPVOID DefaultValue; // Raw pointer to default value + UINT StartTexture; // First texture index (or -1 if no textures used) + UINT TextureSize; // Number of texture slots possibly used. + UINT StartSampler; // First sampler index (or -1 if no textures used) + UINT SamplerSize; // Number of sampler slots possibly used. +} D3D12_SHADER_VARIABLE_DESC; + +typedef struct _D3D12_SHADER_TYPE_DESC +{ + D3D_SHADER_VARIABLE_CLASS Class; // Variable class (e.g. object, matrix, etc.) + D3D_SHADER_VARIABLE_TYPE Type; // Variable type (e.g. float, sampler, etc.) + UINT Rows; // Number of rows (for matrices, 1 for other numeric, 0 if not applicable) + UINT Columns; // Number of columns (for vectors & matrices, 1 for other numeric, 0 if not applicable) + UINT Elements; // Number of elements (0 if not an array) + UINT Members; // Number of members (0 if not a structure) + UINT Offset; // Offset from the start of structure (0 if not a structure member) + LPCSTR Name; // Name of type, can be NULL +} D3D12_SHADER_TYPE_DESC; + +typedef D3D_TESSELLATOR_DOMAIN D3D12_TESSELLATOR_DOMAIN; + +typedef D3D_TESSELLATOR_PARTITIONING D3D12_TESSELLATOR_PARTITIONING; + +typedef D3D_TESSELLATOR_OUTPUT_PRIMITIVE D3D12_TESSELLATOR_OUTPUT_PRIMITIVE; + +typedef struct _D3D12_SHADER_DESC +{ + UINT Version; // Shader version + LPCSTR Creator; // Creator string + UINT Flags; // Shader compilation/parse flags + + UINT ConstantBuffers; // Number of constant buffers + UINT BoundResources; // Number of bound resources + UINT InputParameters; // Number of parameters in the input signature + UINT OutputParameters; // Number of parameters in the output signature + + UINT InstructionCount; // Number of emitted instructions + UINT TempRegisterCount; // Number of temporary registers used + UINT TempArrayCount; // Number of temporary arrays used + UINT DefCount; // Number of constant defines + UINT DclCount; // Number of declarations (input + output) + UINT TextureNormalInstructions; // Number of non-categorized texture instructions + UINT TextureLoadInstructions; // Number of texture load instructions + UINT TextureCompInstructions; // Number of texture comparison instructions + UINT TextureBiasInstructions; // Number of texture bias instructions + UINT TextureGradientInstructions; // Number of texture gradient instructions + UINT FloatInstructionCount; // Number of floating point arithmetic instructions used + UINT IntInstructionCount; // Number of signed integer arithmetic instructions used + UINT UintInstructionCount; // Number of unsigned integer arithmetic instructions used + UINT StaticFlowControlCount; // Number of static flow control instructions used + UINT DynamicFlowControlCount; // Number of dynamic flow control instructions used + UINT MacroInstructionCount; // Number of macro instructions used + UINT ArrayInstructionCount; // Number of array instructions used + UINT CutInstructionCount; // Number of cut instructions used + UINT EmitInstructionCount; // Number of emit instructions used + D3D_PRIMITIVE_TOPOLOGY GSOutputTopology; // Geometry shader output topology + UINT GSMaxOutputVertexCount; // Geometry shader maximum output vertex count + D3D_PRIMITIVE InputPrimitive; // GS/HS input primitive + UINT PatchConstantParameters; // Number of parameters in the patch constant signature + UINT cGSInstanceCount; // Number of Geometry shader instances + UINT cControlPoints; // Number of control points in the HS->DS stage + D3D_TESSELLATOR_OUTPUT_PRIMITIVE HSOutputPrimitive; // Primitive output by the tessellator + D3D_TESSELLATOR_PARTITIONING HSPartitioning; // Partitioning mode of the tessellator + D3D_TESSELLATOR_DOMAIN TessellatorDomain; // Domain of the tessellator (quad, tri, isoline) + // instruction counts + UINT cBarrierInstructions; // Number of barrier instructions in a compute shader + UINT cInterlockedInstructions; // Number of interlocked instructions + UINT cTextureStoreInstructions; // Number of texture writes +} D3D12_SHADER_DESC; + +typedef struct _D3D12_SHADER_INPUT_BIND_DESC +{ + LPCSTR Name; // Name of the resource + D3D_SHADER_INPUT_TYPE Type; // Type of resource (e.g. texture, cbuffer, etc.) + UINT BindPoint; // Starting bind point + UINT BindCount; // Number of contiguous bind points (for arrays) + + UINT uFlags; // Input binding flags + D3D_RESOURCE_RETURN_TYPE ReturnType; // Return type (if texture) + D3D_SRV_DIMENSION Dimension; // Dimension (if texture) + UINT NumSamples; // Number of samples (0 if not MS texture) + UINT Space; // Register space + UINT uID; // Range ID in the bytecode +} D3D12_SHADER_INPUT_BIND_DESC; + +#define D3D_SHADER_REQUIRES_DOUBLES 0x00000001 +#define D3D_SHADER_REQUIRES_EARLY_DEPTH_STENCIL 0x00000002 +#define D3D_SHADER_REQUIRES_UAVS_AT_EVERY_STAGE 0x00000004 +#define D3D_SHADER_REQUIRES_64_UAVS 0x00000008 +#define D3D_SHADER_REQUIRES_MINIMUM_PRECISION 0x00000010 +#define D3D_SHADER_REQUIRES_11_1_DOUBLE_EXTENSIONS 0x00000020 +#define D3D_SHADER_REQUIRES_11_1_SHADER_EXTENSIONS 0x00000040 +#define D3D_SHADER_REQUIRES_LEVEL_9_COMPARISON_FILTERING 0x00000080 +#define D3D_SHADER_REQUIRES_TILED_RESOURCES 0x00000100 +#define D3D_SHADER_REQUIRES_STENCIL_REF 0x00000200 +#define D3D_SHADER_REQUIRES_INNER_COVERAGE 0x00000400 +#define D3D_SHADER_REQUIRES_TYPED_UAV_LOAD_ADDITIONAL_FORMATS 0x00000800 +#define D3D_SHADER_REQUIRES_ROVS 0x00001000 +#define D3D_SHADER_REQUIRES_VIEWPORT_AND_RT_ARRAY_INDEX_FROM_ANY_SHADER_FEEDING_RASTERIZER 0x00002000 +#define D3D_SHADER_REQUIRES_WAVE_OPS 0x00004000 +#define D3D_SHADER_REQUIRES_INT64_OPS 0x00008000 +#define D3D_SHADER_REQUIRES_VIEW_ID 0x00010000 +#define D3D_SHADER_REQUIRES_BARYCENTRICS 0x00020000 +#define D3D_SHADER_REQUIRES_NATIVE_16BIT_OPS 0x00040000 +#define D3D_SHADER_REQUIRES_SHADING_RATE 0x00080000 +#define D3D_SHADER_REQUIRES_RAYTRACING_TIER_1_1 0x00100000 +#define D3D_SHADER_REQUIRES_SAMPLER_FEEDBACK 0x00200000 +#define D3D_SHADER_REQUIRES_ATOMIC_INT64_ON_TYPED_RESOURCE 0x00400000 +#define D3D_SHADER_REQUIRES_ATOMIC_INT64_ON_GROUP_SHARED 0x00800000 +#define D3D_SHADER_REQUIRES_DERIVATIVES_IN_MESH_AND_AMPLIFICATION_SHADERS 0x01000000 +#define D3D_SHADER_REQUIRES_RESOURCE_DESCRIPTOR_HEAP_INDEXING 0x02000000 +#define D3D_SHADER_REQUIRES_SAMPLER_DESCRIPTOR_HEAP_INDEXING 0x04000000 +#define D3D_SHADER_REQUIRES_WAVE_MMA 0x08000000 +#define D3D_SHADER_REQUIRES_ATOMIC_INT64_ON_DESCRIPTOR_HEAP_RESOURCE 0x10000000 + +typedef struct _D3D12_LIBRARY_DESC +{ + LPCSTR Creator; // The name of the originator of the library. + UINT Flags; // Compilation flags. + UINT FunctionCount; // Number of functions exported from the library. +} D3D12_LIBRARY_DESC; + +typedef struct _D3D12_FUNCTION_DESC +{ + UINT Version; // Shader version + LPCSTR Creator; // Creator string + UINT Flags; // Shader compilation/parse flags + + UINT ConstantBuffers; // Number of constant buffers + UINT BoundResources; // Number of bound resources + + UINT InstructionCount; // Number of emitted instructions + UINT TempRegisterCount; // Number of temporary registers used + UINT TempArrayCount; // Number of temporary arrays used + UINT DefCount; // Number of constant defines + UINT DclCount; // Number of declarations (input + output) + UINT TextureNormalInstructions; // Number of non-categorized texture instructions + UINT TextureLoadInstructions; // Number of texture load instructions + UINT TextureCompInstructions; // Number of texture comparison instructions + UINT TextureBiasInstructions; // Number of texture bias instructions + UINT TextureGradientInstructions; // Number of texture gradient instructions + UINT FloatInstructionCount; // Number of floating point arithmetic instructions used + UINT IntInstructionCount; // Number of signed integer arithmetic instructions used + UINT UintInstructionCount; // Number of unsigned integer arithmetic instructions used + UINT StaticFlowControlCount; // Number of static flow control instructions used + UINT DynamicFlowControlCount; // Number of dynamic flow control instructions used + UINT MacroInstructionCount; // Number of macro instructions used + UINT ArrayInstructionCount; // Number of array instructions used + UINT MovInstructionCount; // Number of mov instructions used + UINT MovcInstructionCount; // Number of movc instructions used + UINT ConversionInstructionCount; // Number of type conversion instructions used + UINT BitwiseInstructionCount; // Number of bitwise arithmetic instructions used + D3D_FEATURE_LEVEL MinFeatureLevel; // Min target of the function byte code + UINT64 RequiredFeatureFlags; // Required feature flags + + LPCSTR Name; // Function name + INT FunctionParameterCount; // Number of logical parameters in the function signature (not including return) + BOOL HasReturn; // TRUE, if function returns a value, false - it is a subroutine + BOOL Has10Level9VertexShader; // TRUE, if there is a 10L9 VS blob + BOOL Has10Level9PixelShader; // TRUE, if there is a 10L9 PS blob +} D3D12_FUNCTION_DESC; + +typedef struct _D3D12_PARAMETER_DESC +{ + LPCSTR Name; // Parameter name. + LPCSTR SemanticName; // Parameter semantic name (+index). + D3D_SHADER_VARIABLE_TYPE Type; // Element type. + D3D_SHADER_VARIABLE_CLASS Class; // Scalar/Vector/Matrix. + UINT Rows; // Rows are for matrix parameters. + UINT Columns; // Components or Columns in matrix. + D3D_INTERPOLATION_MODE InterpolationMode; // Interpolation mode. + D3D_PARAMETER_FLAGS Flags; // Parameter modifiers. + + UINT FirstInRegister; // The first input register for this parameter. + UINT FirstInComponent; // The first input register component for this parameter. + UINT FirstOutRegister; // The first output register for this parameter. + UINT FirstOutComponent; // The first output register component for this parameter. +} D3D12_PARAMETER_DESC; + + +////////////////////////////////////////////////////////////////////////////// +// Interfaces //////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +typedef interface ID3D12ShaderReflectionType ID3D12ShaderReflectionType; +typedef interface ID3D12ShaderReflectionType *LPD3D12SHADERREFLECTIONTYPE; + +typedef interface ID3D12ShaderReflectionVariable ID3D12ShaderReflectionVariable; +typedef interface ID3D12ShaderReflectionVariable *LPD3D12SHADERREFLECTIONVARIABLE; + +typedef interface ID3D12ShaderReflectionConstantBuffer ID3D12ShaderReflectionConstantBuffer; +typedef interface ID3D12ShaderReflectionConstantBuffer *LPD3D12SHADERREFLECTIONCONSTANTBUFFER; + +typedef interface ID3D12ShaderReflection ID3D12ShaderReflection; +typedef interface ID3D12ShaderReflection *LPD3D12SHADERREFLECTION; + +typedef interface ID3D12LibraryReflection ID3D12LibraryReflection; +typedef interface ID3D12LibraryReflection *LPD3D12LIBRARYREFLECTION; + +typedef interface ID3D12FunctionReflection ID3D12FunctionReflection; +typedef interface ID3D12FunctionReflection *LPD3D12FUNCTIONREFLECTION; + +typedef interface ID3D12FunctionParameterReflection ID3D12FunctionParameterReflection; +typedef interface ID3D12FunctionParameterReflection *LPD3D12FUNCTIONPARAMETERREFLECTION; + + +// {E913C351-783D-48CA-A1D1-4F306284AD56} +interface DECLSPEC_UUID("E913C351-783D-48CA-A1D1-4F306284AD56") ID3D12ShaderReflectionType; +DEFINE_GUID(IID_ID3D12ShaderReflectionType, +0xe913c351, 0x783d, 0x48ca, 0xa1, 0xd1, 0x4f, 0x30, 0x62, 0x84, 0xad, 0x56); + +#undef INTERFACE +#define INTERFACE ID3D12ShaderReflectionType + +DECLARE_INTERFACE(ID3D12ShaderReflectionType) +{ + STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_SHADER_TYPE_DESC *pDesc) PURE; + + STDMETHOD_(ID3D12ShaderReflectionType*, GetMemberTypeByIndex)(THIS_ _In_ UINT Index) PURE; + STDMETHOD_(ID3D12ShaderReflectionType*, GetMemberTypeByName)(THIS_ _In_ LPCSTR Name) PURE; + STDMETHOD_(LPCSTR, GetMemberTypeName)(THIS_ _In_ UINT Index) PURE; + + STDMETHOD(IsEqual)(THIS_ _In_ ID3D12ShaderReflectionType* pType) PURE; + STDMETHOD_(ID3D12ShaderReflectionType*, GetSubType)(THIS) PURE; + STDMETHOD_(ID3D12ShaderReflectionType*, GetBaseClass)(THIS) PURE; + STDMETHOD_(UINT, GetNumInterfaces)(THIS) PURE; + STDMETHOD_(ID3D12ShaderReflectionType*, GetInterfaceByIndex)(THIS_ _In_ UINT uIndex) PURE; + STDMETHOD(IsOfType)(THIS_ _In_ ID3D12ShaderReflectionType* pType) PURE; + STDMETHOD(ImplementsInterface)(THIS_ _In_ ID3D12ShaderReflectionType* pBase) PURE; +}; + +// {8337A8A6-A216-444A-B2F4-314733A73AEA} +interface DECLSPEC_UUID("8337A8A6-A216-444A-B2F4-314733A73AEA") ID3D12ShaderReflectionVariable; +DEFINE_GUID(IID_ID3D12ShaderReflectionVariable, +0x8337a8a6, 0xa216, 0x444a, 0xb2, 0xf4, 0x31, 0x47, 0x33, 0xa7, 0x3a, 0xea); + +#undef INTERFACE +#define INTERFACE ID3D12ShaderReflectionVariable + +DECLARE_INTERFACE(ID3D12ShaderReflectionVariable) +{ + STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_SHADER_VARIABLE_DESC *pDesc) PURE; + + STDMETHOD_(ID3D12ShaderReflectionType*, GetType)(THIS) PURE; + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetBuffer)(THIS) PURE; + + STDMETHOD_(UINT, GetInterfaceSlot)(THIS_ _In_ UINT uArrayIndex) PURE; +}; + +// {C59598B4-48B3-4869-B9B1-B1618B14A8B7} +interface DECLSPEC_UUID("C59598B4-48B3-4869-B9B1-B1618B14A8B7") ID3D12ShaderReflectionConstantBuffer; +DEFINE_GUID(IID_ID3D12ShaderReflectionConstantBuffer, +0xc59598b4, 0x48b3, 0x4869, 0xb9, 0xb1, 0xb1, 0x61, 0x8b, 0x14, 0xa8, 0xb7); + +#undef INTERFACE +#define INTERFACE ID3D12ShaderReflectionConstantBuffer + +DECLARE_INTERFACE(ID3D12ShaderReflectionConstantBuffer) +{ + STDMETHOD(GetDesc)(THIS_ D3D12_SHADER_BUFFER_DESC *pDesc) PURE; + + STDMETHOD_(ID3D12ShaderReflectionVariable*, GetVariableByIndex)(THIS_ _In_ UINT Index) PURE; + STDMETHOD_(ID3D12ShaderReflectionVariable*, GetVariableByName)(THIS_ _In_ LPCSTR Name) PURE; +}; + +// The ID3D12ShaderReflection IID may change from SDK version to SDK version +// if the reflection API changes. This prevents new code with the new API +// from working with an old binary. Recompiling with the new header +// will pick up the new IID. + +// {5A58797D-A72C-478D-8BA2-EFC6B0EFE88E} +interface DECLSPEC_UUID("5A58797D-A72C-478D-8BA2-EFC6B0EFE88E") ID3D12ShaderReflection; +DEFINE_GUID(IID_ID3D12ShaderReflection, +0x5a58797d, 0xa72c, 0x478d, 0x8b, 0xa2, 0xef, 0xc6, 0xb0, 0xef, 0xe8, 0x8e); + +#undef INTERFACE +#define INTERFACE ID3D12ShaderReflection + +DECLARE_INTERFACE_(ID3D12ShaderReflection, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ _In_ REFIID iid, + _Out_ LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_SHADER_DESC *pDesc) PURE; + + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetConstantBufferByIndex)(THIS_ _In_ UINT Index) PURE; + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetConstantBufferByName)(THIS_ _In_ LPCSTR Name) PURE; + + STDMETHOD(GetResourceBindingDesc)(THIS_ _In_ UINT ResourceIndex, + _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) PURE; + + STDMETHOD(GetInputParameterDesc)(THIS_ _In_ UINT ParameterIndex, + _Out_ D3D12_SIGNATURE_PARAMETER_DESC *pDesc) PURE; + STDMETHOD(GetOutputParameterDesc)(THIS_ _In_ UINT ParameterIndex, + _Out_ D3D12_SIGNATURE_PARAMETER_DESC *pDesc) PURE; + STDMETHOD(GetPatchConstantParameterDesc)(THIS_ _In_ UINT ParameterIndex, + _Out_ D3D12_SIGNATURE_PARAMETER_DESC *pDesc) PURE; + + STDMETHOD_(ID3D12ShaderReflectionVariable*, GetVariableByName)(THIS_ _In_ LPCSTR Name) PURE; + + STDMETHOD(GetResourceBindingDescByName)(THIS_ _In_ LPCSTR Name, + _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) PURE; + + STDMETHOD_(UINT, GetMovInstructionCount)(THIS) PURE; + STDMETHOD_(UINT, GetMovcInstructionCount)(THIS) PURE; + STDMETHOD_(UINT, GetConversionInstructionCount)(THIS) PURE; + STDMETHOD_(UINT, GetBitwiseInstructionCount)(THIS) PURE; + + STDMETHOD_(D3D_PRIMITIVE, GetGSInputPrimitive)(THIS) PURE; + STDMETHOD_(BOOL, IsSampleFrequencyShader)(THIS) PURE; + + STDMETHOD_(UINT, GetNumInterfaceSlots)(THIS) PURE; + STDMETHOD(GetMinFeatureLevel)(THIS_ _Out_ enum D3D_FEATURE_LEVEL* pLevel) PURE; + + STDMETHOD_(UINT, GetThreadGroupSize)(THIS_ + _Out_opt_ UINT* pSizeX, + _Out_opt_ UINT* pSizeY, + _Out_opt_ UINT* pSizeZ) PURE; + + STDMETHOD_(UINT64, GetRequiresFlags)(THIS) PURE; +}; + +// {8E349D19-54DB-4A56-9DC9-119D87BDB804} +interface DECLSPEC_UUID("8E349D19-54DB-4A56-9DC9-119D87BDB804") ID3D12LibraryReflection; +DEFINE_GUID(IID_ID3D12LibraryReflection, +0x8e349d19, 0x54db, 0x4a56, 0x9d, 0xc9, 0x11, 0x9d, 0x87, 0xbd, 0xb8, 0x4); + +#undef INTERFACE +#define INTERFACE ID3D12LibraryReflection + +DECLARE_INTERFACE_(ID3D12LibraryReflection, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ _In_ REFIID iid, _Out_ LPVOID * ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_LIBRARY_DESC * pDesc) PURE; + + STDMETHOD_(ID3D12FunctionReflection *, GetFunctionByIndex)(THIS_ _In_ INT FunctionIndex) PURE; +}; + +// {1108795C-2772-4BA9-B2A8-D464DC7E2799} +interface DECLSPEC_UUID("1108795C-2772-4BA9-B2A8-D464DC7E2799") ID3D12FunctionReflection; +DEFINE_GUID(IID_ID3D12FunctionReflection, +0x1108795c, 0x2772, 0x4ba9, 0xb2, 0xa8, 0xd4, 0x64, 0xdc, 0x7e, 0x27, 0x99); + +#undef INTERFACE +#define INTERFACE ID3D12FunctionReflection + +DECLARE_INTERFACE(ID3D12FunctionReflection) +{ + STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_FUNCTION_DESC * pDesc) PURE; + + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByIndex)(THIS_ _In_ UINT BufferIndex) PURE; + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByName)(THIS_ _In_ LPCSTR Name) PURE; + + STDMETHOD(GetResourceBindingDesc)(THIS_ _In_ UINT ResourceIndex, + _Out_ D3D12_SHADER_INPUT_BIND_DESC * pDesc) PURE; + + STDMETHOD_(ID3D12ShaderReflectionVariable *, GetVariableByName)(THIS_ _In_ LPCSTR Name) PURE; + + STDMETHOD(GetResourceBindingDescByName)(THIS_ _In_ LPCSTR Name, + _Out_ D3D12_SHADER_INPUT_BIND_DESC * pDesc) PURE; + + // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. + STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter)(THIS_ _In_ INT ParameterIndex) PURE; +}; + +// {EC25F42D-7006-4F2B-B33E-02CC3375733F} +interface DECLSPEC_UUID("EC25F42D-7006-4F2B-B33E-02CC3375733F") ID3D12FunctionParameterReflection; +DEFINE_GUID(IID_ID3D12FunctionParameterReflection, +0xec25f42d, 0x7006, 0x4f2b, 0xb3, 0x3e, 0x2, 0xcc, 0x33, 0x75, 0x73, 0x3f); + +#undef INTERFACE +#define INTERFACE ID3D12FunctionParameterReflection + +DECLARE_INTERFACE(ID3D12FunctionParameterReflection) +{ + STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_PARAMETER_DESC * pDesc) PURE; +}; + + +////////////////////////////////////////////////////////////////////////////// +// APIs ////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__D3D12SHADER_H__ + diff --git a/RT/Renderer/Backend/DX12/DXC/inc/dxcapi.h b/RT/Renderer/Backend/DX12/DXC/inc/dxcapi.h index 0457003..f3f058a 100644 --- a/RT/Renderer/Backend/DX12/DXC/inc/dxcapi.h +++ b/RT/Renderer/Backend/DX12/DXC/inc/dxcapi.h @@ -1,807 +1,807 @@ - -/////////////////////////////////////////////////////////////////////////////// -// // -// dxcapi.h // -// Copyright (C) Microsoft Corporation. All rights reserved. // -// This file is distributed under the University of Illinois Open Source // -// License. See LICENSE.TXT for details. // -// // -// Provides declarations for the DirectX Compiler API entry point. // -// // -/////////////////////////////////////////////////////////////////////////////// - -#ifndef __DXC_API__ -#define __DXC_API__ - -#ifdef _WIN32 -#ifndef DXC_API_IMPORT -#define DXC_API_IMPORT __declspec(dllimport) -#endif -#else -#ifndef DXC_API_IMPORT -#define DXC_API_IMPORT __attribute__ ((visibility ("default"))) -#endif -#endif - -#ifdef _WIN32 - -#ifndef CROSS_PLATFORM_UUIDOF -// Warning: This macro exists in WinAdapter.h as well -#define CROSS_PLATFORM_UUIDOF(interface, spec) \ - struct __declspec(uuid(spec)) interface; -#endif - -#else - -#include -#include "dxc/Support/WinAdapter.h" -#endif - -struct IMalloc; - -struct IDxcIncludeHandler; - -typedef HRESULT (__stdcall *DxcCreateInstanceProc)( - _In_ REFCLSID rclsid, - _In_ REFIID riid, - _Out_ LPVOID* ppv -); - -typedef HRESULT(__stdcall *DxcCreateInstance2Proc)( - _In_ IMalloc *pMalloc, - _In_ REFCLSID rclsid, - _In_ REFIID riid, - _Out_ LPVOID* ppv - ); - -/// -/// Creates a single uninitialized object of the class associated with a specified CLSID. -/// -/// -/// The CLSID associated with the data and code that will be used to create the object. -/// -/// -/// A reference to the identifier of the interface to be used to communicate -/// with the object. -/// -/// -/// Address of pointer variable that receives the interface pointer requested -/// in riid. Upon successful return, *ppv contains the requested interface -/// pointer. Upon failure, *ppv contains NULL. -/// -/// While this function is similar to CoCreateInstance, there is no COM involvement. -/// - -extern "C" -DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance( - _In_ REFCLSID rclsid, - _In_ REFIID riid, - _Out_ LPVOID* ppv - ); - -extern "C" -DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance2( - _In_ IMalloc *pMalloc, - _In_ REFCLSID rclsid, - _In_ REFIID riid, - _Out_ LPVOID* ppv -); - -// For convenience, equivalent definitions to CP_UTF8 and CP_UTF16. -#define DXC_CP_UTF8 65001 -#define DXC_CP_UTF16 1200 -#define DXC_CP_UTF32 12000 -// Use DXC_CP_ACP for: Binary; ANSI Text; Autodetect UTF with BOM -#define DXC_CP_ACP 0 - -#ifdef _WIN32 -#define DXC_CP_WIDE DXC_CP_UTF16 -#else -#define DXC_CP_WIDE DXC_CP_UTF32 -#endif - -// This flag indicates that the shader hash was computed taking into account source information (-Zss) -#define DXC_HASHFLAG_INCLUDES_SOURCE 1 - -// Hash digest type for ShaderHash -typedef struct DxcShaderHash { - UINT32 Flags; // DXC_HASHFLAG_* - BYTE HashDigest[16]; -} DxcShaderHash; - -#define DXC_FOURCC(ch0, ch1, ch2, ch3) ( \ - (UINT32)(UINT8)(ch0) | (UINT32)(UINT8)(ch1) << 8 | \ - (UINT32)(UINT8)(ch2) << 16 | (UINT32)(UINT8)(ch3) << 24 \ - ) -#define DXC_PART_PDB DXC_FOURCC('I', 'L', 'D', 'B') -#define DXC_PART_PDB_NAME DXC_FOURCC('I', 'L', 'D', 'N') -#define DXC_PART_PRIVATE_DATA DXC_FOURCC('P', 'R', 'I', 'V') -#define DXC_PART_ROOT_SIGNATURE DXC_FOURCC('R', 'T', 'S', '0') -#define DXC_PART_DXIL DXC_FOURCC('D', 'X', 'I', 'L') -#define DXC_PART_REFLECTION_DATA DXC_FOURCC('S', 'T', 'A', 'T') -#define DXC_PART_SHADER_HASH DXC_FOURCC('H', 'A', 'S', 'H') -#define DXC_PART_INPUT_SIGNATURE DXC_FOURCC('I', 'S', 'G', '1') -#define DXC_PART_OUTPUT_SIGNATURE DXC_FOURCC('O', 'S', 'G', '1') -#define DXC_PART_PATCH_CONSTANT_SIGNATURE DXC_FOURCC('P', 'S', 'G', '1') - -// Some option arguments are defined here for continuity with D3DCompile interface -#define DXC_ARG_DEBUG L"-Zi" -#define DXC_ARG_SKIP_VALIDATION L"-Vd" -#define DXC_ARG_SKIP_OPTIMIZATIONS L"-Od" -#define DXC_ARG_PACK_MATRIX_ROW_MAJOR L"-Zpr" -#define DXC_ARG_PACK_MATRIX_COLUMN_MAJOR L"-Zpc" -#define DXC_ARG_AVOID_FLOW_CONTROL L"-Gfa" -#define DXC_ARG_PREFER_FLOW_CONTROL L"-Gfp" -#define DXC_ARG_ENABLE_STRICTNESS L"-Ges" -#define DXC_ARG_ENABLE_BACKWARDS_COMPATIBILITY L"-Gec" -#define DXC_ARG_IEEE_STRICTNESS L"-Gis" -#define DXC_ARG_OPTIMIZATION_LEVEL0 L"-O0" -#define DXC_ARG_OPTIMIZATION_LEVEL1 L"-O1" -#define DXC_ARG_OPTIMIZATION_LEVEL2 L"-O2" -#define DXC_ARG_OPTIMIZATION_LEVEL3 L"-O3" -#define DXC_ARG_WARNINGS_ARE_ERRORS L"-WX" -#define DXC_ARG_RESOURCES_MAY_ALIAS L"-res_may_alias" -#define DXC_ARG_ALL_RESOURCES_BOUND L"-all_resources_bound" -#define DXC_ARG_DEBUG_NAME_FOR_SOURCE L"-Zss" -#define DXC_ARG_DEBUG_NAME_FOR_BINARY L"-Zsb" - -// IDxcBlob is an alias of ID3D10Blob and ID3DBlob -CROSS_PLATFORM_UUIDOF(IDxcBlob, "8BA5FB08-5195-40e2-AC58-0D989C3A0102") -struct IDxcBlob : public IUnknown { -public: - virtual LPVOID STDMETHODCALLTYPE GetBufferPointer(void) = 0; - virtual SIZE_T STDMETHODCALLTYPE GetBufferSize(void) = 0; -}; - -CROSS_PLATFORM_UUIDOF(IDxcBlobEncoding, "7241d424-2646-4191-97c0-98e96e42fc68") -struct IDxcBlobEncoding : public IDxcBlob { -public: - virtual HRESULT STDMETHODCALLTYPE GetEncoding(_Out_ BOOL *pKnown, - _Out_ UINT32 *pCodePage) = 0; -}; - -// Notes on IDxcBlobWide and IDxcBlobUtf8 -// These guarantee null-terminated text and eithre utf8 or the native wide char encoding. -// GetBufferSize() will return the size in bytes, including null-terminator -// GetStringLength() will return the length in characters, excluding the null-terminator -// Name strings will use IDxcBlobWide, while other string output blobs, -// such as errors/warnings, preprocessed HLSL, or other text will be based -// on the -encoding option. - -// The API will use this interface for output name strings -CROSS_PLATFORM_UUIDOF(IDxcBlobWide, "A3F84EAB-0FAA-497E-A39C-EE6ED60B2D84") -struct IDxcBlobWide : public IDxcBlobEncoding { -public: - virtual LPCWSTR STDMETHODCALLTYPE GetStringPointer(void) = 0; - virtual SIZE_T STDMETHODCALLTYPE GetStringLength(void) = 0; -}; -CROSS_PLATFORM_UUIDOF(IDxcBlobUtf8, "3DA636C9-BA71-4024-A301-30CBF125305B") -struct IDxcBlobUtf8 : public IDxcBlobEncoding { -public: - virtual LPCSTR STDMETHODCALLTYPE GetStringPointer(void) = 0; - virtual SIZE_T STDMETHODCALLTYPE GetStringLength(void) = 0; -}; - -// Define legacy name IDxcBlobUtf16 as IDxcBlobWide for Win32 -#ifdef _WIN32 -typedef IDxcBlobWide IDxcBlobUtf16; -#endif - -CROSS_PLATFORM_UUIDOF(IDxcIncludeHandler, "7f61fc7d-950d-467f-b3e3-3c02fb49187c") -struct IDxcIncludeHandler : public IUnknown { - virtual HRESULT STDMETHODCALLTYPE LoadSource( - _In_z_ LPCWSTR pFilename, // Candidate filename. - _COM_Outptr_result_maybenull_ IDxcBlob **ppIncludeSource // Resultant source object for included file, nullptr if not found. - ) = 0; -}; - -// Structure for supplying bytes or text input to Dxc APIs. -// Use Encoding = 0 for non-text bytes, ANSI text, or unknown with BOM. -typedef struct DxcBuffer { - LPCVOID Ptr; - SIZE_T Size; - UINT Encoding; -} DxcText; - -struct DxcDefine { - LPCWSTR Name; - _Maybenull_ LPCWSTR Value; -}; - -CROSS_PLATFORM_UUIDOF(IDxcCompilerArgs, "73EFFE2A-70DC-45F8-9690-EFF64C02429D") -struct IDxcCompilerArgs : public IUnknown { - // Pass GetArguments() and GetCount() to Compile - virtual LPCWSTR* STDMETHODCALLTYPE GetArguments() = 0; - virtual UINT32 STDMETHODCALLTYPE GetCount() = 0; - - // Add additional arguments or defines here, if desired. - virtual HRESULT STDMETHODCALLTYPE AddArguments( - _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments to add - _In_ UINT32 argCount // Number of arguments to add - ) = 0; - virtual HRESULT STDMETHODCALLTYPE AddArgumentsUTF8( - _In_opt_count_(argCount)LPCSTR *pArguments, // Array of pointers to UTF-8 arguments to add - _In_ UINT32 argCount // Number of arguments to add - ) = 0; - virtual HRESULT STDMETHODCALLTYPE AddDefines( - _In_count_(defineCount) const DxcDefine *pDefines, // Array of defines - _In_ UINT32 defineCount // Number of defines - ) = 0; -}; - -////////////////////////// -// Legacy Interfaces -///////////////////////// - -// NOTE: IDxcUtils replaces IDxcLibrary -CROSS_PLATFORM_UUIDOF(IDxcLibrary, "e5204dc7-d18c-4c3c-bdfb-851673980fe7") -struct IDxcLibrary : public IUnknown { - virtual HRESULT STDMETHODCALLTYPE SetMalloc(_In_opt_ IMalloc *pMalloc) = 0; - virtual HRESULT STDMETHODCALLTYPE CreateBlobFromBlob( - _In_ IDxcBlob *pBlob, UINT32 offset, UINT32 length, _COM_Outptr_ IDxcBlob **ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE CreateBlobFromFile( - _In_z_ LPCWSTR pFileName, _In_opt_ UINT32* codePage, - _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; - virtual HRESULT STDMETHODCALLTYPE CreateBlobWithEncodingFromPinned( - _In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage, - _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; - virtual HRESULT STDMETHODCALLTYPE CreateBlobWithEncodingOnHeapCopy( - _In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage, - _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; - virtual HRESULT STDMETHODCALLTYPE CreateBlobWithEncodingOnMalloc( - _In_bytecount_(size) LPCVOID pText, IMalloc *pIMalloc, UINT32 size, UINT32 codePage, - _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; - virtual HRESULT STDMETHODCALLTYPE CreateIncludeHandler( - _COM_Outptr_ IDxcIncludeHandler **ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE CreateStreamFromBlobReadOnly( - _In_ IDxcBlob *pBlob, _COM_Outptr_ IStream **ppStream) = 0; - virtual HRESULT STDMETHODCALLTYPE GetBlobAsUtf8( - _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; - - // Renamed from GetBlobAsUtf16 to GetBlobAsWide - virtual HRESULT STDMETHODCALLTYPE GetBlobAsWide( - _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; - -#ifdef _WIN32 - // Alias to GetBlobAsWide on Win32 - inline HRESULT GetBlobAsUtf16( - _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) { - return this->GetBlobAsWide(pBlob, pBlobEncoding); - } -#endif -}; - -// NOTE: IDxcResult replaces IDxcOperationResult -CROSS_PLATFORM_UUIDOF(IDxcOperationResult, "CEDB484A-D4E9-445A-B991-CA21CA157DC2") -struct IDxcOperationResult : public IUnknown { - virtual HRESULT STDMETHODCALLTYPE GetStatus(_Out_ HRESULT *pStatus) = 0; - - // GetResult returns the main result of the operation. - // This corresponds to: - // DXC_OUT_OBJECT - Compile() with shader or library target - // DXC_OUT_DISASSEMBLY - Disassemble() - // DXC_OUT_HLSL - Compile() with -P - // DXC_OUT_ROOT_SIGNATURE - Compile() with rootsig_* target - virtual HRESULT STDMETHODCALLTYPE GetResult(_COM_Outptr_result_maybenull_ IDxcBlob **ppResult) = 0; - - // GetErrorBuffer Corresponds to DXC_OUT_ERRORS. - virtual HRESULT STDMETHODCALLTYPE GetErrorBuffer(_COM_Outptr_result_maybenull_ IDxcBlobEncoding **ppErrors) = 0; -}; - -// NOTE: IDxcCompiler3 replaces IDxcCompiler and IDxcCompiler2 -CROSS_PLATFORM_UUIDOF(IDxcCompiler, "8c210bf3-011f-4422-8d70-6f9acb8db617") -struct IDxcCompiler : public IUnknown { - // Compile a single entry point to the target shader model - virtual HRESULT STDMETHODCALLTYPE Compile( - _In_ IDxcBlob *pSource, // Source text to compile - _In_opt_z_ LPCWSTR pSourceName, // Optional file name for pSource. Used in errors and include handlers. - _In_opt_z_ LPCWSTR pEntryPoint, // entry point name - _In_z_ LPCWSTR pTargetProfile, // shader profile to compile - _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments - _In_ UINT32 argCount, // Number of arguments - _In_count_(defineCount) - const DxcDefine *pDefines, // Array of defines - _In_ UINT32 defineCount, // Number of defines - _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional) - _COM_Outptr_ IDxcOperationResult **ppResult // Compiler output status, buffer, and errors - ) = 0; - - // Preprocess source text - virtual HRESULT STDMETHODCALLTYPE Preprocess( - _In_ IDxcBlob *pSource, // Source text to preprocess - _In_opt_z_ LPCWSTR pSourceName, // Optional file name for pSource. Used in errors and include handlers. - _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments - _In_ UINT32 argCount, // Number of arguments - _In_count_(defineCount) - const DxcDefine *pDefines, // Array of defines - _In_ UINT32 defineCount, // Number of defines - _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional) - _COM_Outptr_ IDxcOperationResult **ppResult // Preprocessor output status, buffer, and errors - ) = 0; - - // Disassemble a program. - virtual HRESULT STDMETHODCALLTYPE Disassemble( - _In_ IDxcBlob *pSource, // Program to disassemble. - _COM_Outptr_ IDxcBlobEncoding **ppDisassembly // Disassembly text. - ) = 0; -}; - -// NOTE: IDxcCompiler3 replaces IDxcCompiler and IDxcCompiler2 -CROSS_PLATFORM_UUIDOF(IDxcCompiler2, "A005A9D9-B8BB-4594-B5C9-0E633BEC4D37") -struct IDxcCompiler2 : public IDxcCompiler { - // Compile a single entry point to the target shader model with debug information. - virtual HRESULT STDMETHODCALLTYPE CompileWithDebug( - _In_ IDxcBlob *pSource, // Source text to compile - _In_opt_z_ LPCWSTR pSourceName, // Optional file name for pSource. Used in errors and include handlers. - _In_opt_z_ LPCWSTR pEntryPoint, // Entry point name - _In_z_ LPCWSTR pTargetProfile, // Shader profile to compile - _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments - _In_ UINT32 argCount, // Number of arguments - _In_count_(defineCount) - const DxcDefine *pDefines, // Array of defines - _In_ UINT32 defineCount, // Number of defines - _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional) - _COM_Outptr_ IDxcOperationResult **ppResult, // Compiler output status, buffer, and errors - _Outptr_opt_result_z_ LPWSTR *ppDebugBlobName,// Suggested file name for debug blob. (Must be CoTaskMemFree()'d!) - _COM_Outptr_opt_ IDxcBlob **ppDebugBlob // Debug blob - ) = 0; -}; - -CROSS_PLATFORM_UUIDOF(IDxcLinker, "F1B5BE2A-62DD-4327-A1C2-42AC1E1E78E6") -struct IDxcLinker : public IUnknown { -public: - // Register a library with name to ref it later. - virtual HRESULT RegisterLibrary( - _In_opt_ LPCWSTR pLibName, // Name of the library. - _In_ IDxcBlob *pLib // Library blob. - ) = 0; - - // Links the shader and produces a shader blob that the Direct3D runtime can - // use. - virtual HRESULT STDMETHODCALLTYPE Link( - _In_opt_ LPCWSTR pEntryName, // Entry point name - _In_ LPCWSTR pTargetProfile, // shader profile to link - _In_count_(libCount) - const LPCWSTR *pLibNames, // Array of library names to link - _In_ UINT32 libCount, // Number of libraries to link - _In_opt_count_(argCount) const LPCWSTR *pArguments, // Array of pointers to arguments - _In_ UINT32 argCount, // Number of arguments - _COM_Outptr_ - IDxcOperationResult **ppResult // Linker output status, buffer, and errors - ) = 0; -}; - -///////////////////////// -// Latest interfaces. Please use these -//////////////////////// - -// NOTE: IDxcUtils replaces IDxcLibrary -CROSS_PLATFORM_UUIDOF(IDxcUtils, "4605C4CB-2019-492A-ADA4-65F20BB7D67F") -struct IDxcUtils : public IUnknown { - // Create a sub-blob that holds a reference to the outer blob and points to its memory. - virtual HRESULT STDMETHODCALLTYPE CreateBlobFromBlob( - _In_ IDxcBlob *pBlob, UINT32 offset, UINT32 length, _COM_Outptr_ IDxcBlob **ppResult) = 0; - - // For codePage, use 0 (or DXC_CP_ACP) for raw binary or ANSI code page - - // Creates a blob referencing existing memory, with no copy. - // User must manage the memory lifetime separately. - // (was: CreateBlobWithEncodingFromPinned) - virtual HRESULT STDMETHODCALLTYPE CreateBlobFromPinned( - _In_bytecount_(size) LPCVOID pData, UINT32 size, UINT32 codePage, - _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; - - // Create blob, taking ownership of memory allocated with supplied allocator. - // (was: CreateBlobWithEncodingOnMalloc) - virtual HRESULT STDMETHODCALLTYPE MoveToBlob( - _In_bytecount_(size) LPCVOID pData, IMalloc *pIMalloc, UINT32 size, UINT32 codePage, - _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; - - //// - // New blobs and copied contents are allocated with the current allocator - - // Copy blob contents to memory owned by the new blob. - // (was: CreateBlobWithEncodingOnHeapCopy) - virtual HRESULT STDMETHODCALLTYPE CreateBlob( - _In_bytecount_(size) LPCVOID pData, UINT32 size, UINT32 codePage, - _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; - - // (was: CreateBlobFromFile) - virtual HRESULT STDMETHODCALLTYPE LoadFile( - _In_z_ LPCWSTR pFileName, _In_opt_ UINT32* pCodePage, - _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateReadOnlyStreamFromBlob( - _In_ IDxcBlob *pBlob, _COM_Outptr_ IStream **ppStream) = 0; - - // Create default file-based include handler - virtual HRESULT STDMETHODCALLTYPE CreateDefaultIncludeHandler( - _COM_Outptr_ IDxcIncludeHandler **ppResult) = 0; - - // Convert or return matching encoded text blobs - virtual HRESULT STDMETHODCALLTYPE GetBlobAsUtf8( - _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobUtf8 **pBlobEncoding) = 0; - - // Renamed from GetBlobAsUtf16 to GetBlobAsWide - virtual HRESULT STDMETHODCALLTYPE GetBlobAsWide( - _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobWide **pBlobEncoding) = 0; - -#ifdef _WIN32 - // Alias to GetBlobAsWide on Win32 - inline HRESULT GetBlobAsUtf16( - _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobWide **pBlobEncoding) { - return this->GetBlobAsWide(pBlob, pBlobEncoding); - } -#endif - - virtual HRESULT STDMETHODCALLTYPE GetDxilContainerPart( - _In_ const DxcBuffer *pShader, - _In_ UINT32 DxcPart, - _Outptr_result_nullonfailure_ void **ppPartData, - _Out_ UINT32 *pPartSizeInBytes) = 0; - - // Create reflection interface from serialized Dxil container, or DXC_PART_REFLECTION_DATA. - // TBD: Require part header for RDAT? (leaning towards yes) - virtual HRESULT STDMETHODCALLTYPE CreateReflection( - _In_ const DxcBuffer *pData, REFIID iid, void **ppvReflection) = 0; - - virtual HRESULT STDMETHODCALLTYPE BuildArguments( - _In_opt_z_ LPCWSTR pSourceName, // Optional file name for pSource. Used in errors and include handlers. - _In_opt_z_ LPCWSTR pEntryPoint, // Entry point name. (-E) - _In_z_ LPCWSTR pTargetProfile, // Shader profile to compile. (-T) - _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments - _In_ UINT32 argCount, // Number of arguments - _In_count_(defineCount) - const DxcDefine *pDefines, // Array of defines - _In_ UINT32 defineCount, // Number of defines - _COM_Outptr_ IDxcCompilerArgs **ppArgs // Arguments you can use with Compile() method - ) = 0; - - // Takes the shader PDB and returns the hash and the container inside it - virtual HRESULT STDMETHODCALLTYPE GetPDBContents( - _In_ IDxcBlob *pPDBBlob, _COM_Outptr_ IDxcBlob **ppHash, _COM_Outptr_ IDxcBlob **ppContainer) = 0; -}; - -// For use with IDxcResult::[Has|Get]Output dxcOutKind argument -// Note: text outputs returned from version 2 APIs are UTF-8 or UTF-16 based on -encoding option -typedef enum DXC_OUT_KIND { - DXC_OUT_NONE = 0, - DXC_OUT_OBJECT = 1, // IDxcBlob - Shader or library object - DXC_OUT_ERRORS = 2, // IDxcBlobUtf8 or IDxcBlobWide - DXC_OUT_PDB = 3, // IDxcBlob - DXC_OUT_SHADER_HASH = 4, // IDxcBlob - DxcShaderHash of shader or shader with source info (-Zsb/-Zss) - DXC_OUT_DISASSEMBLY = 5, // IDxcBlobUtf8 or IDxcBlobWide - from Disassemble - DXC_OUT_HLSL = 6, // IDxcBlobUtf8 or IDxcBlobWide - from Preprocessor or Rewriter - DXC_OUT_TEXT = 7, // IDxcBlobUtf8 or IDxcBlobWide - other text, such as -ast-dump or -Odump - DXC_OUT_REFLECTION = 8, // IDxcBlob - RDAT part with reflection data - DXC_OUT_ROOT_SIGNATURE = 9, // IDxcBlob - Serialized root signature output - DXC_OUT_EXTRA_OUTPUTS = 10,// IDxcExtraResults - Extra outputs - DXC_OUT_REMARKS = 11, // IDxcBlobUtf8 or IDxcBlobWide - text directed at stdout - DXC_OUT_TIME_REPORT = 12, // IDxcBlobUtf8 or IDxcBlobWide - text directed at stdout - DXC_OUT_TIME_TRACE = 13, // IDxcBlobUtf8 or IDxcBlobWide - text directed at stdout - - DXC_OUT_LAST = DXC_OUT_TIME_TRACE, // Last value for a counter - - DXC_OUT_NUM_ENUMS, - DXC_OUT_FORCE_DWORD = 0xFFFFFFFF -} DXC_OUT_KIND; - -static_assert(DXC_OUT_NUM_ENUMS == DXC_OUT_LAST + 1, - "DXC_OUT_* Enum added and last value not updated."); - -CROSS_PLATFORM_UUIDOF(IDxcResult, "58346CDA-DDE7-4497-9461-6F87AF5E0659") -struct IDxcResult : public IDxcOperationResult { - virtual BOOL STDMETHODCALLTYPE HasOutput(_In_ DXC_OUT_KIND dxcOutKind) = 0; - virtual HRESULT STDMETHODCALLTYPE GetOutput(_In_ DXC_OUT_KIND dxcOutKind, - _In_ REFIID iid, _COM_Outptr_opt_result_maybenull_ void **ppvObject, - _COM_Outptr_ IDxcBlobWide **ppOutputName) = 0; - - virtual UINT32 GetNumOutputs() = 0; - virtual DXC_OUT_KIND GetOutputByIndex(UINT32 Index) = 0; - virtual DXC_OUT_KIND PrimaryOutput() = 0; -}; - -// Special names for extra output that should get written to specific streams -#define DXC_EXTRA_OUTPUT_NAME_STDOUT L"*stdout*" -#define DXC_EXTRA_OUTPUT_NAME_STDERR L"*stderr*" - -CROSS_PLATFORM_UUIDOF(IDxcExtraOutputs, "319b37a2-a5c2-494a-a5de-4801b2faf989") -struct IDxcExtraOutputs : public IUnknown { - - virtual UINT32 STDMETHODCALLTYPE GetOutputCount() = 0; - virtual HRESULT STDMETHODCALLTYPE GetOutput(_In_ UINT32 uIndex, - _In_ REFIID iid, _COM_Outptr_opt_result_maybenull_ void **ppvObject, - _COM_Outptr_opt_result_maybenull_ IDxcBlobWide **ppOutputType, - _COM_Outptr_opt_result_maybenull_ IDxcBlobWide **ppOutputName) = 0; -}; - -CROSS_PLATFORM_UUIDOF(IDxcCompiler3, "228B4687-5A6A-4730-900C-9702B2203F54") -struct IDxcCompiler3 : public IUnknown { - // Compile a single entry point to the target shader model, - // Compile a library to a library target (-T lib_*), - // Compile a root signature (-T rootsig_*), or - // Preprocess HLSL source (-P) - virtual HRESULT STDMETHODCALLTYPE Compile( - _In_ const DxcBuffer *pSource, // Source text to compile - _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments - _In_ UINT32 argCount, // Number of arguments - _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional) - _In_ REFIID riid, _Out_ LPVOID *ppResult // IDxcResult: status, buffer, and errors - ) = 0; - - // Disassemble a program. - virtual HRESULT STDMETHODCALLTYPE Disassemble( - _In_ const DxcBuffer *pObject, // Program to disassemble: dxil container or bitcode. - _In_ REFIID riid, _Out_ LPVOID *ppResult // IDxcResult: status, disassembly text, and errors - ) = 0; -}; - -static const UINT32 DxcValidatorFlags_Default = 0; -static const UINT32 DxcValidatorFlags_InPlaceEdit = 1; // Validator is allowed to update shader blob in-place. -static const UINT32 DxcValidatorFlags_RootSignatureOnly = 2; -static const UINT32 DxcValidatorFlags_ModuleOnly = 4; -static const UINT32 DxcValidatorFlags_ValidMask = 0x7; - -CROSS_PLATFORM_UUIDOF(IDxcValidator, "A6E82BD2-1FD7-4826-9811-2857E797F49A") -struct IDxcValidator : public IUnknown { - // Validate a shader. - virtual HRESULT STDMETHODCALLTYPE Validate( - _In_ IDxcBlob *pShader, // Shader to validate. - _In_ UINT32 Flags, // Validation flags. - _COM_Outptr_ IDxcOperationResult **ppResult // Validation output status, buffer, and errors - ) = 0; -}; - -CROSS_PLATFORM_UUIDOF(IDxcValidator2, "458e1fd1-b1b2-4750-a6e1-9c10f03bed92") -struct IDxcValidator2 : public IDxcValidator { - // Validate a shader. - virtual HRESULT STDMETHODCALLTYPE ValidateWithDebug( - _In_ IDxcBlob *pShader, // Shader to validate. - _In_ UINT32 Flags, // Validation flags. - _In_opt_ DxcBuffer *pOptDebugBitcode, // Optional debug module bitcode to provide line numbers - _COM_Outptr_ IDxcOperationResult **ppResult // Validation output status, buffer, and errors - ) = 0; -}; - -CROSS_PLATFORM_UUIDOF(IDxcContainerBuilder, "334b1f50-2292-4b35-99a1-25588d8c17fe") -struct IDxcContainerBuilder : public IUnknown { - virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pDxilContainerHeader) = 0; // Loads DxilContainer to the builder - virtual HRESULT STDMETHODCALLTYPE AddPart(_In_ UINT32 fourCC, _In_ IDxcBlob *pSource) = 0; // Part to add to the container - virtual HRESULT STDMETHODCALLTYPE RemovePart(_In_ UINT32 fourCC) = 0; // Remove the part with fourCC - virtual HRESULT STDMETHODCALLTYPE SerializeContainer(_Out_ IDxcOperationResult **ppResult) = 0; // Builds a container of the given container builder state -}; - -CROSS_PLATFORM_UUIDOF(IDxcAssembler, "091f7a26-1c1f-4948-904b-e6e3a8a771d5") -struct IDxcAssembler : public IUnknown { - // Assemble dxil in ll or llvm bitcode to DXIL container. - virtual HRESULT STDMETHODCALLTYPE AssembleToContainer( - _In_ IDxcBlob *pShader, // Shader to assemble. - _COM_Outptr_ IDxcOperationResult **ppResult // Assembly output status, buffer, and errors - ) = 0; -}; - -CROSS_PLATFORM_UUIDOF(IDxcContainerReflection, "d2c21b26-8350-4bdc-976a-331ce6f4c54c") -struct IDxcContainerReflection : public IUnknown { - virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pContainer) = 0; // Container to load. - virtual HRESULT STDMETHODCALLTYPE GetPartCount(_Out_ UINT32 *pResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetPartKind(UINT32 idx, _Out_ UINT32 *pResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetPartContent(UINT32 idx, _COM_Outptr_ IDxcBlob **ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE FindFirstPartKind(UINT32 kind, _Out_ UINT32 *pResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetPartReflection(UINT32 idx, REFIID iid, void **ppvObject) = 0; -}; - -CROSS_PLATFORM_UUIDOF(IDxcOptimizerPass, "AE2CD79F-CC22-453F-9B6B-B124E7A5204C") -struct IDxcOptimizerPass : public IUnknown { - virtual HRESULT STDMETHODCALLTYPE GetOptionName(_COM_Outptr_ LPWSTR *ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetDescription(_COM_Outptr_ LPWSTR *ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetOptionArgCount(_Out_ UINT32 *pCount) = 0; - virtual HRESULT STDMETHODCALLTYPE GetOptionArgName(UINT32 argIndex, _COM_Outptr_ LPWSTR *ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetOptionArgDescription(UINT32 argIndex, _COM_Outptr_ LPWSTR *ppResult) = 0; -}; - -CROSS_PLATFORM_UUIDOF(IDxcOptimizer, "25740E2E-9CBA-401B-9119-4FB42F39F270") -struct IDxcOptimizer : public IUnknown { - virtual HRESULT STDMETHODCALLTYPE GetAvailablePassCount(_Out_ UINT32 *pCount) = 0; - virtual HRESULT STDMETHODCALLTYPE GetAvailablePass(UINT32 index, _COM_Outptr_ IDxcOptimizerPass** ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE RunOptimizer(IDxcBlob *pBlob, - _In_count_(optionCount) LPCWSTR *ppOptions, UINT32 optionCount, - _COM_Outptr_ IDxcBlob **pOutputModule, - _COM_Outptr_opt_ IDxcBlobEncoding **ppOutputText) = 0; -}; - -static const UINT32 DxcVersionInfoFlags_None = 0; -static const UINT32 DxcVersionInfoFlags_Debug = 1; // Matches VS_FF_DEBUG -static const UINT32 DxcVersionInfoFlags_Internal = 2; // Internal Validator (non-signing) - -CROSS_PLATFORM_UUIDOF(IDxcVersionInfo, "b04f5b50-2059-4f12-a8ff-a1e0cde1cc7e") -struct IDxcVersionInfo : public IUnknown { - virtual HRESULT STDMETHODCALLTYPE GetVersion(_Out_ UINT32 *pMajor, _Out_ UINT32 *pMinor) = 0; - virtual HRESULT STDMETHODCALLTYPE GetFlags(_Out_ UINT32 *pFlags) = 0; -}; - -CROSS_PLATFORM_UUIDOF(IDxcVersionInfo2, "fb6904c4-42f0-4b62-9c46-983af7da7c83") -struct IDxcVersionInfo2 : public IDxcVersionInfo { - virtual HRESULT STDMETHODCALLTYPE GetCommitInfo( - _Out_ UINT32 *pCommitCount, // The total number commits. - _Outptr_result_z_ char **pCommitHash // The SHA of the latest commit. (Must be CoTaskMemFree()'d!) - ) = 0; -}; - -CROSS_PLATFORM_UUIDOF(IDxcVersionInfo3, "5e13e843-9d25-473c-9ad2-03b2d0b44b1e") -struct IDxcVersionInfo3 : public IUnknown { - virtual HRESULT STDMETHODCALLTYPE GetCustomVersionString( - _Outptr_result_z_ char **pVersionString // Custom version string for compiler. (Must be CoTaskMemFree()'d!) - ) = 0; -}; - -struct DxcArgPair { - const WCHAR *pName; - const WCHAR *pValue; -}; - -CROSS_PLATFORM_UUIDOF(IDxcPdbUtils, "E6C9647E-9D6A-4C3B-B94C-524B5A6C343D") -struct IDxcPdbUtils : public IUnknown { - virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pPdbOrDxil) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSourceCount(_Out_ UINT32 *pCount) = 0; - virtual HRESULT STDMETHODCALLTYPE GetSource(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobEncoding **ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetSourceName(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFlagCount(_Out_ UINT32 *pCount) = 0; - virtual HRESULT STDMETHODCALLTYPE GetFlag(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetArgCount(_Out_ UINT32 *pCount) = 0; - virtual HRESULT STDMETHODCALLTYPE GetArg(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetArgPairCount(_Out_ UINT32 *pCount) = 0; - virtual HRESULT STDMETHODCALLTYPE GetArgPair(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pName, _Outptr_result_z_ BSTR *pValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDefineCount(_Out_ UINT32 *pCount) = 0; - virtual HRESULT STDMETHODCALLTYPE GetDefine(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTargetProfile(_Outptr_result_z_ BSTR *pResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetEntryPoint(_Outptr_result_z_ BSTR *pResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetMainFileName(_Outptr_result_z_ BSTR *pResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHash(_COM_Outptr_ IDxcBlob **ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetName(_Outptr_result_z_ BSTR *pResult) = 0; - - virtual BOOL STDMETHODCALLTYPE IsFullPDB() = 0; - virtual HRESULT STDMETHODCALLTYPE GetFullPDB(_COM_Outptr_ IDxcBlob **ppFullPDB) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVersionInfo(_COM_Outptr_ IDxcVersionInfo **ppVersionInfo) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetCompiler(_In_ IDxcCompiler3 *pCompiler) = 0; - virtual HRESULT STDMETHODCALLTYPE CompileForFullPDB(_COM_Outptr_ IDxcResult **ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE OverrideArgs(_In_ DxcArgPair *pArgPairs, UINT32 uNumArgPairs) = 0; - virtual HRESULT STDMETHODCALLTYPE OverrideRootSignature(_In_ const WCHAR *pRootSignature) = 0; -}; - -CROSS_PLATFORM_UUIDOF(IDxcPdbUtils2, "4315D938-F369-4F93-95A2-252017CC3807") -struct IDxcPdbUtils2 : public IUnknown { - virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pPdbOrDxil) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSourceCount(_Out_ UINT32 *pCount) = 0; - virtual HRESULT STDMETHODCALLTYPE GetSource(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobEncoding **ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetSourceName(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobWide **ppResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLibraryPDBCount(UINT32 *pCount) = 0; - virtual HRESULT STDMETHODCALLTYPE GetLibraryPDB(_In_ UINT32 uIndex, _COM_Outptr_ IDxcPdbUtils2 **ppOutPdbUtils, _COM_Outptr_opt_result_maybenull_ IDxcBlobWide **ppLibraryName) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFlagCount(_Out_ UINT32 *pCount) = 0; - virtual HRESULT STDMETHODCALLTYPE GetFlag(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobWide **ppResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetArgCount(_Out_ UINT32 *pCount) = 0; - virtual HRESULT STDMETHODCALLTYPE GetArg(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobWide **ppResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetArgPairCount(_Out_ UINT32 *pCount) = 0; - virtual HRESULT STDMETHODCALLTYPE GetArgPair(_In_ UINT32 uIndex, _COM_Outptr_result_maybenull_ IDxcBlobWide **ppName, _COM_Outptr_result_maybenull_ IDxcBlobWide **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDefineCount(_Out_ UINT32 *pCount) = 0; - virtual HRESULT STDMETHODCALLTYPE GetDefine(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobWide **ppResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTargetProfile(_COM_Outptr_result_maybenull_ IDxcBlobWide **ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetEntryPoint(_COM_Outptr_result_maybenull_ IDxcBlobWide **ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetMainFileName(_COM_Outptr_result_maybenull_ IDxcBlobWide **ppResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHash(_COM_Outptr_result_maybenull_ IDxcBlob **ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE GetName(_COM_Outptr_result_maybenull_ IDxcBlobWide **ppResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVersionInfo(_COM_Outptr_result_maybenull_ IDxcVersionInfo **ppVersionInfo) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCustomToolchainID(_Out_ UINT32 *pID) = 0; - virtual HRESULT STDMETHODCALLTYPE GetCustomToolchainData(_COM_Outptr_result_maybenull_ IDxcBlob **ppBlob) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetWholeDxil(_COM_Outptr_result_maybenull_ IDxcBlob **ppResult) = 0; - - virtual BOOL STDMETHODCALLTYPE IsFullPDB() = 0; - virtual BOOL STDMETHODCALLTYPE IsPDBRef() = 0; -}; - -// Note: __declspec(selectany) requires 'extern' -// On Linux __declspec(selectany) is removed and using 'extern' results in link error. -#ifdef _MSC_VER -#define CLSID_SCOPE __declspec(selectany) extern -#else -#define CLSID_SCOPE -#endif - -CLSID_SCOPE const CLSID CLSID_DxcCompiler = { - 0x73e22d93, - 0xe6ce, - 0x47f3, - {0xb5, 0xbf, 0xf0, 0x66, 0x4f, 0x39, 0xc1, 0xb0}}; - -// {EF6A8087-B0EA-4D56-9E45-D07E1A8B7806} -CLSID_SCOPE const GUID CLSID_DxcLinker = { - 0xef6a8087, - 0xb0ea, - 0x4d56, - {0x9e, 0x45, 0xd0, 0x7e, 0x1a, 0x8b, 0x78, 0x6}}; - -// {CD1F6B73-2AB0-484D-8EDC-EBE7A43CA09F} -CLSID_SCOPE const CLSID CLSID_DxcDiaDataSource = { - 0xcd1f6b73, - 0x2ab0, - 0x484d, - {0x8e, 0xdc, 0xeb, 0xe7, 0xa4, 0x3c, 0xa0, 0x9f}}; - -// {3E56AE82-224D-470F-A1A1-FE3016EE9F9D} -CLSID_SCOPE const CLSID CLSID_DxcCompilerArgs = { - 0x3e56ae82, - 0x224d, - 0x470f, - {0xa1, 0xa1, 0xfe, 0x30, 0x16, 0xee, 0x9f, 0x9d}}; - -// {6245D6AF-66E0-48FD-80B4-4D271796748C} -CLSID_SCOPE const GUID CLSID_DxcLibrary = { - 0x6245d6af, - 0x66e0, - 0x48fd, - {0x80, 0xb4, 0x4d, 0x27, 0x17, 0x96, 0x74, 0x8c}}; - -CLSID_SCOPE const GUID CLSID_DxcUtils = CLSID_DxcLibrary; - -// {8CA3E215-F728-4CF3-8CDD-88AF917587A1} -CLSID_SCOPE const GUID CLSID_DxcValidator = { - 0x8ca3e215, - 0xf728, - 0x4cf3, - {0x8c, 0xdd, 0x88, 0xaf, 0x91, 0x75, 0x87, 0xa1}}; - -// {D728DB68-F903-4F80-94CD-DCCF76EC7151} -CLSID_SCOPE const GUID CLSID_DxcAssembler = { - 0xd728db68, - 0xf903, - 0x4f80, - {0x94, 0xcd, 0xdc, 0xcf, 0x76, 0xec, 0x71, 0x51}}; - -// {b9f54489-55b8-400c-ba3a-1675e4728b91} -CLSID_SCOPE const GUID CLSID_DxcContainerReflection = { - 0xb9f54489, - 0x55b8, - 0x400c, - {0xba, 0x3a, 0x16, 0x75, 0xe4, 0x72, 0x8b, 0x91}}; - -// {AE2CD79F-CC22-453F-9B6B-B124E7A5204C} -CLSID_SCOPE const GUID CLSID_DxcOptimizer = { - 0xae2cd79f, - 0xcc22, - 0x453f, - {0x9b, 0x6b, 0xb1, 0x24, 0xe7, 0xa5, 0x20, 0x4c}}; - -// {94134294-411f-4574-b4d0-8741e25240d2} -CLSID_SCOPE const GUID CLSID_DxcContainerBuilder = { - 0x94134294, - 0x411f, - 0x4574, - {0xb4, 0xd0, 0x87, 0x41, 0xe2, 0x52, 0x40, 0xd2}}; - -// {54621dfb-f2ce-457e-ae8c-ec355faeec7c} -CLSID_SCOPE const GUID CLSID_DxcPdbUtils = { - 0x54621dfb, - 0xf2ce, - 0x457e, - {0xae, 0x8c, 0xec, 0x35, 0x5f, 0xae, 0xec, 0x7c}}; - -#endif + +/////////////////////////////////////////////////////////////////////////////// +// // +// dxcapi.h // +// Copyright (C) Microsoft Corporation. All rights reserved. // +// This file is distributed under the University of Illinois Open Source // +// License. See LICENSE.TXT for details. // +// // +// Provides declarations for the DirectX Compiler API entry point. // +// // +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __DXC_API__ +#define __DXC_API__ + +#ifdef _WIN32 +#ifndef DXC_API_IMPORT +#define DXC_API_IMPORT __declspec(dllimport) +#endif +#else +#ifndef DXC_API_IMPORT +#define DXC_API_IMPORT __attribute__ ((visibility ("default"))) +#endif +#endif + +#ifdef _WIN32 + +#ifndef CROSS_PLATFORM_UUIDOF +// Warning: This macro exists in WinAdapter.h as well +#define CROSS_PLATFORM_UUIDOF(interface, spec) \ + struct __declspec(uuid(spec)) interface; +#endif + +#else + +#include +#include "dxc/Support/WinAdapter.h" +#endif + +struct IMalloc; + +struct IDxcIncludeHandler; + +typedef HRESULT (__stdcall *DxcCreateInstanceProc)( + _In_ REFCLSID rclsid, + _In_ REFIID riid, + _Out_ LPVOID* ppv +); + +typedef HRESULT(__stdcall *DxcCreateInstance2Proc)( + _In_ IMalloc *pMalloc, + _In_ REFCLSID rclsid, + _In_ REFIID riid, + _Out_ LPVOID* ppv + ); + +/// +/// Creates a single uninitialized object of the class associated with a specified CLSID. +/// +/// +/// The CLSID associated with the data and code that will be used to create the object. +/// +/// +/// A reference to the identifier of the interface to be used to communicate +/// with the object. +/// +/// +/// Address of pointer variable that receives the interface pointer requested +/// in riid. Upon successful return, *ppv contains the requested interface +/// pointer. Upon failure, *ppv contains NULL. +/// +/// While this function is similar to CoCreateInstance, there is no COM involvement. +/// + +extern "C" +DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance( + _In_ REFCLSID rclsid, + _In_ REFIID riid, + _Out_ LPVOID* ppv + ); + +extern "C" +DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance2( + _In_ IMalloc *pMalloc, + _In_ REFCLSID rclsid, + _In_ REFIID riid, + _Out_ LPVOID* ppv +); + +// For convenience, equivalent definitions to CP_UTF8 and CP_UTF16. +#define DXC_CP_UTF8 65001 +#define DXC_CP_UTF16 1200 +#define DXC_CP_UTF32 12000 +// Use DXC_CP_ACP for: Binary; ANSI Text; Autodetect UTF with BOM +#define DXC_CP_ACP 0 + +#ifdef _WIN32 +#define DXC_CP_WIDE DXC_CP_UTF16 +#else +#define DXC_CP_WIDE DXC_CP_UTF32 +#endif + +// This flag indicates that the shader hash was computed taking into account source information (-Zss) +#define DXC_HASHFLAG_INCLUDES_SOURCE 1 + +// Hash digest type for ShaderHash +typedef struct DxcShaderHash { + UINT32 Flags; // DXC_HASHFLAG_* + BYTE HashDigest[16]; +} DxcShaderHash; + +#define DXC_FOURCC(ch0, ch1, ch2, ch3) ( \ + (UINT32)(UINT8)(ch0) | (UINT32)(UINT8)(ch1) << 8 | \ + (UINT32)(UINT8)(ch2) << 16 | (UINT32)(UINT8)(ch3) << 24 \ + ) +#define DXC_PART_PDB DXC_FOURCC('I', 'L', 'D', 'B') +#define DXC_PART_PDB_NAME DXC_FOURCC('I', 'L', 'D', 'N') +#define DXC_PART_PRIVATE_DATA DXC_FOURCC('P', 'R', 'I', 'V') +#define DXC_PART_ROOT_SIGNATURE DXC_FOURCC('R', 'T', 'S', '0') +#define DXC_PART_DXIL DXC_FOURCC('D', 'X', 'I', 'L') +#define DXC_PART_REFLECTION_DATA DXC_FOURCC('S', 'T', 'A', 'T') +#define DXC_PART_SHADER_HASH DXC_FOURCC('H', 'A', 'S', 'H') +#define DXC_PART_INPUT_SIGNATURE DXC_FOURCC('I', 'S', 'G', '1') +#define DXC_PART_OUTPUT_SIGNATURE DXC_FOURCC('O', 'S', 'G', '1') +#define DXC_PART_PATCH_CONSTANT_SIGNATURE DXC_FOURCC('P', 'S', 'G', '1') + +// Some option arguments are defined here for continuity with D3DCompile interface +#define DXC_ARG_DEBUG L"-Zi" +#define DXC_ARG_SKIP_VALIDATION L"-Vd" +#define DXC_ARG_SKIP_OPTIMIZATIONS L"-Od" +#define DXC_ARG_PACK_MATRIX_ROW_MAJOR L"-Zpr" +#define DXC_ARG_PACK_MATRIX_COLUMN_MAJOR L"-Zpc" +#define DXC_ARG_AVOID_FLOW_CONTROL L"-Gfa" +#define DXC_ARG_PREFER_FLOW_CONTROL L"-Gfp" +#define DXC_ARG_ENABLE_STRICTNESS L"-Ges" +#define DXC_ARG_ENABLE_BACKWARDS_COMPATIBILITY L"-Gec" +#define DXC_ARG_IEEE_STRICTNESS L"-Gis" +#define DXC_ARG_OPTIMIZATION_LEVEL0 L"-O0" +#define DXC_ARG_OPTIMIZATION_LEVEL1 L"-O1" +#define DXC_ARG_OPTIMIZATION_LEVEL2 L"-O2" +#define DXC_ARG_OPTIMIZATION_LEVEL3 L"-O3" +#define DXC_ARG_WARNINGS_ARE_ERRORS L"-WX" +#define DXC_ARG_RESOURCES_MAY_ALIAS L"-res_may_alias" +#define DXC_ARG_ALL_RESOURCES_BOUND L"-all_resources_bound" +#define DXC_ARG_DEBUG_NAME_FOR_SOURCE L"-Zss" +#define DXC_ARG_DEBUG_NAME_FOR_BINARY L"-Zsb" + +// IDxcBlob is an alias of ID3D10Blob and ID3DBlob +CROSS_PLATFORM_UUIDOF(IDxcBlob, "8BA5FB08-5195-40e2-AC58-0D989C3A0102") +struct IDxcBlob : public IUnknown { +public: + virtual LPVOID STDMETHODCALLTYPE GetBufferPointer(void) = 0; + virtual SIZE_T STDMETHODCALLTYPE GetBufferSize(void) = 0; +}; + +CROSS_PLATFORM_UUIDOF(IDxcBlobEncoding, "7241d424-2646-4191-97c0-98e96e42fc68") +struct IDxcBlobEncoding : public IDxcBlob { +public: + virtual HRESULT STDMETHODCALLTYPE GetEncoding(_Out_ BOOL *pKnown, + _Out_ UINT32 *pCodePage) = 0; +}; + +// Notes on IDxcBlobWide and IDxcBlobUtf8 +// These guarantee null-terminated text and eithre utf8 or the native wide char encoding. +// GetBufferSize() will return the size in bytes, including null-terminator +// GetStringLength() will return the length in characters, excluding the null-terminator +// Name strings will use IDxcBlobWide, while other string output blobs, +// such as errors/warnings, preprocessed HLSL, or other text will be based +// on the -encoding option. + +// The API will use this interface for output name strings +CROSS_PLATFORM_UUIDOF(IDxcBlobWide, "A3F84EAB-0FAA-497E-A39C-EE6ED60B2D84") +struct IDxcBlobWide : public IDxcBlobEncoding { +public: + virtual LPCWSTR STDMETHODCALLTYPE GetStringPointer(void) = 0; + virtual SIZE_T STDMETHODCALLTYPE GetStringLength(void) = 0; +}; +CROSS_PLATFORM_UUIDOF(IDxcBlobUtf8, "3DA636C9-BA71-4024-A301-30CBF125305B") +struct IDxcBlobUtf8 : public IDxcBlobEncoding { +public: + virtual LPCSTR STDMETHODCALLTYPE GetStringPointer(void) = 0; + virtual SIZE_T STDMETHODCALLTYPE GetStringLength(void) = 0; +}; + +// Define legacy name IDxcBlobUtf16 as IDxcBlobWide for Win32 +#ifdef _WIN32 +typedef IDxcBlobWide IDxcBlobUtf16; +#endif + +CROSS_PLATFORM_UUIDOF(IDxcIncludeHandler, "7f61fc7d-950d-467f-b3e3-3c02fb49187c") +struct IDxcIncludeHandler : public IUnknown { + virtual HRESULT STDMETHODCALLTYPE LoadSource( + _In_z_ LPCWSTR pFilename, // Candidate filename. + _COM_Outptr_result_maybenull_ IDxcBlob **ppIncludeSource // Resultant source object for included file, nullptr if not found. + ) = 0; +}; + +// Structure for supplying bytes or text input to Dxc APIs. +// Use Encoding = 0 for non-text bytes, ANSI text, or unknown with BOM. +typedef struct DxcBuffer { + LPCVOID Ptr; + SIZE_T Size; + UINT Encoding; +} DxcText; + +struct DxcDefine { + LPCWSTR Name; + _Maybenull_ LPCWSTR Value; +}; + +CROSS_PLATFORM_UUIDOF(IDxcCompilerArgs, "73EFFE2A-70DC-45F8-9690-EFF64C02429D") +struct IDxcCompilerArgs : public IUnknown { + // Pass GetArguments() and GetCount() to Compile + virtual LPCWSTR* STDMETHODCALLTYPE GetArguments() = 0; + virtual UINT32 STDMETHODCALLTYPE GetCount() = 0; + + // Add additional arguments or defines here, if desired. + virtual HRESULT STDMETHODCALLTYPE AddArguments( + _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments to add + _In_ UINT32 argCount // Number of arguments to add + ) = 0; + virtual HRESULT STDMETHODCALLTYPE AddArgumentsUTF8( + _In_opt_count_(argCount)LPCSTR *pArguments, // Array of pointers to UTF-8 arguments to add + _In_ UINT32 argCount // Number of arguments to add + ) = 0; + virtual HRESULT STDMETHODCALLTYPE AddDefines( + _In_count_(defineCount) const DxcDefine *pDefines, // Array of defines + _In_ UINT32 defineCount // Number of defines + ) = 0; +}; + +////////////////////////// +// Legacy Interfaces +///////////////////////// + +// NOTE: IDxcUtils replaces IDxcLibrary +CROSS_PLATFORM_UUIDOF(IDxcLibrary, "e5204dc7-d18c-4c3c-bdfb-851673980fe7") +struct IDxcLibrary : public IUnknown { + virtual HRESULT STDMETHODCALLTYPE SetMalloc(_In_opt_ IMalloc *pMalloc) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateBlobFromBlob( + _In_ IDxcBlob *pBlob, UINT32 offset, UINT32 length, _COM_Outptr_ IDxcBlob **ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateBlobFromFile( + _In_z_ LPCWSTR pFileName, _In_opt_ UINT32* codePage, + _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateBlobWithEncodingFromPinned( + _In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage, + _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateBlobWithEncodingOnHeapCopy( + _In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage, + _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateBlobWithEncodingOnMalloc( + _In_bytecount_(size) LPCVOID pText, IMalloc *pIMalloc, UINT32 size, UINT32 codePage, + _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateIncludeHandler( + _COM_Outptr_ IDxcIncludeHandler **ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateStreamFromBlobReadOnly( + _In_ IDxcBlob *pBlob, _COM_Outptr_ IStream **ppStream) = 0; + virtual HRESULT STDMETHODCALLTYPE GetBlobAsUtf8( + _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; + + // Renamed from GetBlobAsUtf16 to GetBlobAsWide + virtual HRESULT STDMETHODCALLTYPE GetBlobAsWide( + _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; + +#ifdef _WIN32 + // Alias to GetBlobAsWide on Win32 + inline HRESULT GetBlobAsUtf16( + _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) { + return this->GetBlobAsWide(pBlob, pBlobEncoding); + } +#endif +}; + +// NOTE: IDxcResult replaces IDxcOperationResult +CROSS_PLATFORM_UUIDOF(IDxcOperationResult, "CEDB484A-D4E9-445A-B991-CA21CA157DC2") +struct IDxcOperationResult : public IUnknown { + virtual HRESULT STDMETHODCALLTYPE GetStatus(_Out_ HRESULT *pStatus) = 0; + + // GetResult returns the main result of the operation. + // This corresponds to: + // DXC_OUT_OBJECT - Compile() with shader or library target + // DXC_OUT_DISASSEMBLY - Disassemble() + // DXC_OUT_HLSL - Compile() with -P + // DXC_OUT_ROOT_SIGNATURE - Compile() with rootsig_* target + virtual HRESULT STDMETHODCALLTYPE GetResult(_COM_Outptr_result_maybenull_ IDxcBlob **ppResult) = 0; + + // GetErrorBuffer Corresponds to DXC_OUT_ERRORS. + virtual HRESULT STDMETHODCALLTYPE GetErrorBuffer(_COM_Outptr_result_maybenull_ IDxcBlobEncoding **ppErrors) = 0; +}; + +// NOTE: IDxcCompiler3 replaces IDxcCompiler and IDxcCompiler2 +CROSS_PLATFORM_UUIDOF(IDxcCompiler, "8c210bf3-011f-4422-8d70-6f9acb8db617") +struct IDxcCompiler : public IUnknown { + // Compile a single entry point to the target shader model + virtual HRESULT STDMETHODCALLTYPE Compile( + _In_ IDxcBlob *pSource, // Source text to compile + _In_opt_z_ LPCWSTR pSourceName, // Optional file name for pSource. Used in errors and include handlers. + _In_opt_z_ LPCWSTR pEntryPoint, // entry point name + _In_z_ LPCWSTR pTargetProfile, // shader profile to compile + _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments + _In_ UINT32 argCount, // Number of arguments + _In_count_(defineCount) + const DxcDefine *pDefines, // Array of defines + _In_ UINT32 defineCount, // Number of defines + _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional) + _COM_Outptr_ IDxcOperationResult **ppResult // Compiler output status, buffer, and errors + ) = 0; + + // Preprocess source text + virtual HRESULT STDMETHODCALLTYPE Preprocess( + _In_ IDxcBlob *pSource, // Source text to preprocess + _In_opt_z_ LPCWSTR pSourceName, // Optional file name for pSource. Used in errors and include handlers. + _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments + _In_ UINT32 argCount, // Number of arguments + _In_count_(defineCount) + const DxcDefine *pDefines, // Array of defines + _In_ UINT32 defineCount, // Number of defines + _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional) + _COM_Outptr_ IDxcOperationResult **ppResult // Preprocessor output status, buffer, and errors + ) = 0; + + // Disassemble a program. + virtual HRESULT STDMETHODCALLTYPE Disassemble( + _In_ IDxcBlob *pSource, // Program to disassemble. + _COM_Outptr_ IDxcBlobEncoding **ppDisassembly // Disassembly text. + ) = 0; +}; + +// NOTE: IDxcCompiler3 replaces IDxcCompiler and IDxcCompiler2 +CROSS_PLATFORM_UUIDOF(IDxcCompiler2, "A005A9D9-B8BB-4594-B5C9-0E633BEC4D37") +struct IDxcCompiler2 : public IDxcCompiler { + // Compile a single entry point to the target shader model with debug information. + virtual HRESULT STDMETHODCALLTYPE CompileWithDebug( + _In_ IDxcBlob *pSource, // Source text to compile + _In_opt_z_ LPCWSTR pSourceName, // Optional file name for pSource. Used in errors and include handlers. + _In_opt_z_ LPCWSTR pEntryPoint, // Entry point name + _In_z_ LPCWSTR pTargetProfile, // Shader profile to compile + _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments + _In_ UINT32 argCount, // Number of arguments + _In_count_(defineCount) + const DxcDefine *pDefines, // Array of defines + _In_ UINT32 defineCount, // Number of defines + _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional) + _COM_Outptr_ IDxcOperationResult **ppResult, // Compiler output status, buffer, and errors + _Outptr_opt_result_z_ LPWSTR *ppDebugBlobName,// Suggested file name for debug blob. (Must be CoTaskMemFree()'d!) + _COM_Outptr_opt_ IDxcBlob **ppDebugBlob // Debug blob + ) = 0; +}; + +CROSS_PLATFORM_UUIDOF(IDxcLinker, "F1B5BE2A-62DD-4327-A1C2-42AC1E1E78E6") +struct IDxcLinker : public IUnknown { +public: + // Register a library with name to ref it later. + virtual HRESULT RegisterLibrary( + _In_opt_ LPCWSTR pLibName, // Name of the library. + _In_ IDxcBlob *pLib // Library blob. + ) = 0; + + // Links the shader and produces a shader blob that the Direct3D runtime can + // use. + virtual HRESULT STDMETHODCALLTYPE Link( + _In_opt_ LPCWSTR pEntryName, // Entry point name + _In_ LPCWSTR pTargetProfile, // shader profile to link + _In_count_(libCount) + const LPCWSTR *pLibNames, // Array of library names to link + _In_ UINT32 libCount, // Number of libraries to link + _In_opt_count_(argCount) const LPCWSTR *pArguments, // Array of pointers to arguments + _In_ UINT32 argCount, // Number of arguments + _COM_Outptr_ + IDxcOperationResult **ppResult // Linker output status, buffer, and errors + ) = 0; +}; + +///////////////////////// +// Latest interfaces. Please use these +//////////////////////// + +// NOTE: IDxcUtils replaces IDxcLibrary +CROSS_PLATFORM_UUIDOF(IDxcUtils, "4605C4CB-2019-492A-ADA4-65F20BB7D67F") +struct IDxcUtils : public IUnknown { + // Create a sub-blob that holds a reference to the outer blob and points to its memory. + virtual HRESULT STDMETHODCALLTYPE CreateBlobFromBlob( + _In_ IDxcBlob *pBlob, UINT32 offset, UINT32 length, _COM_Outptr_ IDxcBlob **ppResult) = 0; + + // For codePage, use 0 (or DXC_CP_ACP) for raw binary or ANSI code page + + // Creates a blob referencing existing memory, with no copy. + // User must manage the memory lifetime separately. + // (was: CreateBlobWithEncodingFromPinned) + virtual HRESULT STDMETHODCALLTYPE CreateBlobFromPinned( + _In_bytecount_(size) LPCVOID pData, UINT32 size, UINT32 codePage, + _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; + + // Create blob, taking ownership of memory allocated with supplied allocator. + // (was: CreateBlobWithEncodingOnMalloc) + virtual HRESULT STDMETHODCALLTYPE MoveToBlob( + _In_bytecount_(size) LPCVOID pData, IMalloc *pIMalloc, UINT32 size, UINT32 codePage, + _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; + + //// + // New blobs and copied contents are allocated with the current allocator + + // Copy blob contents to memory owned by the new blob. + // (was: CreateBlobWithEncodingOnHeapCopy) + virtual HRESULT STDMETHODCALLTYPE CreateBlob( + _In_bytecount_(size) LPCVOID pData, UINT32 size, UINT32 codePage, + _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; + + // (was: CreateBlobFromFile) + virtual HRESULT STDMETHODCALLTYPE LoadFile( + _In_z_ LPCWSTR pFileName, _In_opt_ UINT32* pCodePage, + _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateReadOnlyStreamFromBlob( + _In_ IDxcBlob *pBlob, _COM_Outptr_ IStream **ppStream) = 0; + + // Create default file-based include handler + virtual HRESULT STDMETHODCALLTYPE CreateDefaultIncludeHandler( + _COM_Outptr_ IDxcIncludeHandler **ppResult) = 0; + + // Convert or return matching encoded text blobs + virtual HRESULT STDMETHODCALLTYPE GetBlobAsUtf8( + _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobUtf8 **pBlobEncoding) = 0; + + // Renamed from GetBlobAsUtf16 to GetBlobAsWide + virtual HRESULT STDMETHODCALLTYPE GetBlobAsWide( + _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobWide **pBlobEncoding) = 0; + +#ifdef _WIN32 + // Alias to GetBlobAsWide on Win32 + inline HRESULT GetBlobAsUtf16( + _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobWide **pBlobEncoding) { + return this->GetBlobAsWide(pBlob, pBlobEncoding); + } +#endif + + virtual HRESULT STDMETHODCALLTYPE GetDxilContainerPart( + _In_ const DxcBuffer *pShader, + _In_ UINT32 DxcPart, + _Outptr_result_nullonfailure_ void **ppPartData, + _Out_ UINT32 *pPartSizeInBytes) = 0; + + // Create reflection interface from serialized Dxil container, or DXC_PART_REFLECTION_DATA. + // TBD: Require part header for RDAT? (leaning towards yes) + virtual HRESULT STDMETHODCALLTYPE CreateReflection( + _In_ const DxcBuffer *pData, REFIID iid, void **ppvReflection) = 0; + + virtual HRESULT STDMETHODCALLTYPE BuildArguments( + _In_opt_z_ LPCWSTR pSourceName, // Optional file name for pSource. Used in errors and include handlers. + _In_opt_z_ LPCWSTR pEntryPoint, // Entry point name. (-E) + _In_z_ LPCWSTR pTargetProfile, // Shader profile to compile. (-T) + _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments + _In_ UINT32 argCount, // Number of arguments + _In_count_(defineCount) + const DxcDefine *pDefines, // Array of defines + _In_ UINT32 defineCount, // Number of defines + _COM_Outptr_ IDxcCompilerArgs **ppArgs // Arguments you can use with Compile() method + ) = 0; + + // Takes the shader PDB and returns the hash and the container inside it + virtual HRESULT STDMETHODCALLTYPE GetPDBContents( + _In_ IDxcBlob *pPDBBlob, _COM_Outptr_ IDxcBlob **ppHash, _COM_Outptr_ IDxcBlob **ppContainer) = 0; +}; + +// For use with IDxcResult::[Has|Get]Output dxcOutKind argument +// Note: text outputs returned from version 2 APIs are UTF-8 or UTF-16 based on -encoding option +typedef enum DXC_OUT_KIND { + DXC_OUT_NONE = 0, + DXC_OUT_OBJECT = 1, // IDxcBlob - Shader or library object + DXC_OUT_ERRORS = 2, // IDxcBlobUtf8 or IDxcBlobWide + DXC_OUT_PDB = 3, // IDxcBlob + DXC_OUT_SHADER_HASH = 4, // IDxcBlob - DxcShaderHash of shader or shader with source info (-Zsb/-Zss) + DXC_OUT_DISASSEMBLY = 5, // IDxcBlobUtf8 or IDxcBlobWide - from Disassemble + DXC_OUT_HLSL = 6, // IDxcBlobUtf8 or IDxcBlobWide - from Preprocessor or Rewriter + DXC_OUT_TEXT = 7, // IDxcBlobUtf8 or IDxcBlobWide - other text, such as -ast-dump or -Odump + DXC_OUT_REFLECTION = 8, // IDxcBlob - RDAT part with reflection data + DXC_OUT_ROOT_SIGNATURE = 9, // IDxcBlob - Serialized root signature output + DXC_OUT_EXTRA_OUTPUTS = 10,// IDxcExtraResults - Extra outputs + DXC_OUT_REMARKS = 11, // IDxcBlobUtf8 or IDxcBlobWide - text directed at stdout + DXC_OUT_TIME_REPORT = 12, // IDxcBlobUtf8 or IDxcBlobWide - text directed at stdout + DXC_OUT_TIME_TRACE = 13, // IDxcBlobUtf8 or IDxcBlobWide - text directed at stdout + + DXC_OUT_LAST = DXC_OUT_TIME_TRACE, // Last value for a counter + + DXC_OUT_NUM_ENUMS, + DXC_OUT_FORCE_DWORD = 0xFFFFFFFF +} DXC_OUT_KIND; + +static_assert(DXC_OUT_NUM_ENUMS == DXC_OUT_LAST + 1, + "DXC_OUT_* Enum added and last value not updated."); + +CROSS_PLATFORM_UUIDOF(IDxcResult, "58346CDA-DDE7-4497-9461-6F87AF5E0659") +struct IDxcResult : public IDxcOperationResult { + virtual BOOL STDMETHODCALLTYPE HasOutput(_In_ DXC_OUT_KIND dxcOutKind) = 0; + virtual HRESULT STDMETHODCALLTYPE GetOutput(_In_ DXC_OUT_KIND dxcOutKind, + _In_ REFIID iid, _COM_Outptr_opt_result_maybenull_ void **ppvObject, + _COM_Outptr_ IDxcBlobWide **ppOutputName) = 0; + + virtual UINT32 GetNumOutputs() = 0; + virtual DXC_OUT_KIND GetOutputByIndex(UINT32 Index) = 0; + virtual DXC_OUT_KIND PrimaryOutput() = 0; +}; + +// Special names for extra output that should get written to specific streams +#define DXC_EXTRA_OUTPUT_NAME_STDOUT L"*stdout*" +#define DXC_EXTRA_OUTPUT_NAME_STDERR L"*stderr*" + +CROSS_PLATFORM_UUIDOF(IDxcExtraOutputs, "319b37a2-a5c2-494a-a5de-4801b2faf989") +struct IDxcExtraOutputs : public IUnknown { + + virtual UINT32 STDMETHODCALLTYPE GetOutputCount() = 0; + virtual HRESULT STDMETHODCALLTYPE GetOutput(_In_ UINT32 uIndex, + _In_ REFIID iid, _COM_Outptr_opt_result_maybenull_ void **ppvObject, + _COM_Outptr_opt_result_maybenull_ IDxcBlobWide **ppOutputType, + _COM_Outptr_opt_result_maybenull_ IDxcBlobWide **ppOutputName) = 0; +}; + +CROSS_PLATFORM_UUIDOF(IDxcCompiler3, "228B4687-5A6A-4730-900C-9702B2203F54") +struct IDxcCompiler3 : public IUnknown { + // Compile a single entry point to the target shader model, + // Compile a library to a library target (-T lib_*), + // Compile a root signature (-T rootsig_*), or + // Preprocess HLSL source (-P) + virtual HRESULT STDMETHODCALLTYPE Compile( + _In_ const DxcBuffer *pSource, // Source text to compile + _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments + _In_ UINT32 argCount, // Number of arguments + _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional) + _In_ REFIID riid, _Out_ LPVOID *ppResult // IDxcResult: status, buffer, and errors + ) = 0; + + // Disassemble a program. + virtual HRESULT STDMETHODCALLTYPE Disassemble( + _In_ const DxcBuffer *pObject, // Program to disassemble: dxil container or bitcode. + _In_ REFIID riid, _Out_ LPVOID *ppResult // IDxcResult: status, disassembly text, and errors + ) = 0; +}; + +static const UINT32 DxcValidatorFlags_Default = 0; +static const UINT32 DxcValidatorFlags_InPlaceEdit = 1; // Validator is allowed to update shader blob in-place. +static const UINT32 DxcValidatorFlags_RootSignatureOnly = 2; +static const UINT32 DxcValidatorFlags_ModuleOnly = 4; +static const UINT32 DxcValidatorFlags_ValidMask = 0x7; + +CROSS_PLATFORM_UUIDOF(IDxcValidator, "A6E82BD2-1FD7-4826-9811-2857E797F49A") +struct IDxcValidator : public IUnknown { + // Validate a shader. + virtual HRESULT STDMETHODCALLTYPE Validate( + _In_ IDxcBlob *pShader, // Shader to validate. + _In_ UINT32 Flags, // Validation flags. + _COM_Outptr_ IDxcOperationResult **ppResult // Validation output status, buffer, and errors + ) = 0; +}; + +CROSS_PLATFORM_UUIDOF(IDxcValidator2, "458e1fd1-b1b2-4750-a6e1-9c10f03bed92") +struct IDxcValidator2 : public IDxcValidator { + // Validate a shader. + virtual HRESULT STDMETHODCALLTYPE ValidateWithDebug( + _In_ IDxcBlob *pShader, // Shader to validate. + _In_ UINT32 Flags, // Validation flags. + _In_opt_ DxcBuffer *pOptDebugBitcode, // Optional debug module bitcode to provide line numbers + _COM_Outptr_ IDxcOperationResult **ppResult // Validation output status, buffer, and errors + ) = 0; +}; + +CROSS_PLATFORM_UUIDOF(IDxcContainerBuilder, "334b1f50-2292-4b35-99a1-25588d8c17fe") +struct IDxcContainerBuilder : public IUnknown { + virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pDxilContainerHeader) = 0; // Loads DxilContainer to the builder + virtual HRESULT STDMETHODCALLTYPE AddPart(_In_ UINT32 fourCC, _In_ IDxcBlob *pSource) = 0; // Part to add to the container + virtual HRESULT STDMETHODCALLTYPE RemovePart(_In_ UINT32 fourCC) = 0; // Remove the part with fourCC + virtual HRESULT STDMETHODCALLTYPE SerializeContainer(_Out_ IDxcOperationResult **ppResult) = 0; // Builds a container of the given container builder state +}; + +CROSS_PLATFORM_UUIDOF(IDxcAssembler, "091f7a26-1c1f-4948-904b-e6e3a8a771d5") +struct IDxcAssembler : public IUnknown { + // Assemble dxil in ll or llvm bitcode to DXIL container. + virtual HRESULT STDMETHODCALLTYPE AssembleToContainer( + _In_ IDxcBlob *pShader, // Shader to assemble. + _COM_Outptr_ IDxcOperationResult **ppResult // Assembly output status, buffer, and errors + ) = 0; +}; + +CROSS_PLATFORM_UUIDOF(IDxcContainerReflection, "d2c21b26-8350-4bdc-976a-331ce6f4c54c") +struct IDxcContainerReflection : public IUnknown { + virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pContainer) = 0; // Container to load. + virtual HRESULT STDMETHODCALLTYPE GetPartCount(_Out_ UINT32 *pResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPartKind(UINT32 idx, _Out_ UINT32 *pResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPartContent(UINT32 idx, _COM_Outptr_ IDxcBlob **ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE FindFirstPartKind(UINT32 kind, _Out_ UINT32 *pResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPartReflection(UINT32 idx, REFIID iid, void **ppvObject) = 0; +}; + +CROSS_PLATFORM_UUIDOF(IDxcOptimizerPass, "AE2CD79F-CC22-453F-9B6B-B124E7A5204C") +struct IDxcOptimizerPass : public IUnknown { + virtual HRESULT STDMETHODCALLTYPE GetOptionName(_COM_Outptr_ LPWSTR *ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDescription(_COM_Outptr_ LPWSTR *ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetOptionArgCount(_Out_ UINT32 *pCount) = 0; + virtual HRESULT STDMETHODCALLTYPE GetOptionArgName(UINT32 argIndex, _COM_Outptr_ LPWSTR *ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetOptionArgDescription(UINT32 argIndex, _COM_Outptr_ LPWSTR *ppResult) = 0; +}; + +CROSS_PLATFORM_UUIDOF(IDxcOptimizer, "25740E2E-9CBA-401B-9119-4FB42F39F270") +struct IDxcOptimizer : public IUnknown { + virtual HRESULT STDMETHODCALLTYPE GetAvailablePassCount(_Out_ UINT32 *pCount) = 0; + virtual HRESULT STDMETHODCALLTYPE GetAvailablePass(UINT32 index, _COM_Outptr_ IDxcOptimizerPass** ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE RunOptimizer(IDxcBlob *pBlob, + _In_count_(optionCount) LPCWSTR *ppOptions, UINT32 optionCount, + _COM_Outptr_ IDxcBlob **pOutputModule, + _COM_Outptr_opt_ IDxcBlobEncoding **ppOutputText) = 0; +}; + +static const UINT32 DxcVersionInfoFlags_None = 0; +static const UINT32 DxcVersionInfoFlags_Debug = 1; // Matches VS_FF_DEBUG +static const UINT32 DxcVersionInfoFlags_Internal = 2; // Internal Validator (non-signing) + +CROSS_PLATFORM_UUIDOF(IDxcVersionInfo, "b04f5b50-2059-4f12-a8ff-a1e0cde1cc7e") +struct IDxcVersionInfo : public IUnknown { + virtual HRESULT STDMETHODCALLTYPE GetVersion(_Out_ UINT32 *pMajor, _Out_ UINT32 *pMinor) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFlags(_Out_ UINT32 *pFlags) = 0; +}; + +CROSS_PLATFORM_UUIDOF(IDxcVersionInfo2, "fb6904c4-42f0-4b62-9c46-983af7da7c83") +struct IDxcVersionInfo2 : public IDxcVersionInfo { + virtual HRESULT STDMETHODCALLTYPE GetCommitInfo( + _Out_ UINT32 *pCommitCount, // The total number commits. + _Outptr_result_z_ char **pCommitHash // The SHA of the latest commit. (Must be CoTaskMemFree()'d!) + ) = 0; +}; + +CROSS_PLATFORM_UUIDOF(IDxcVersionInfo3, "5e13e843-9d25-473c-9ad2-03b2d0b44b1e") +struct IDxcVersionInfo3 : public IUnknown { + virtual HRESULT STDMETHODCALLTYPE GetCustomVersionString( + _Outptr_result_z_ char **pVersionString // Custom version string for compiler. (Must be CoTaskMemFree()'d!) + ) = 0; +}; + +struct DxcArgPair { + const WCHAR *pName; + const WCHAR *pValue; +}; + +CROSS_PLATFORM_UUIDOF(IDxcPdbUtils, "E6C9647E-9D6A-4C3B-B94C-524B5A6C343D") +struct IDxcPdbUtils : public IUnknown { + virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pPdbOrDxil) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSourceCount(_Out_ UINT32 *pCount) = 0; + virtual HRESULT STDMETHODCALLTYPE GetSource(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobEncoding **ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetSourceName(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFlagCount(_Out_ UINT32 *pCount) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFlag(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArgCount(_Out_ UINT32 *pCount) = 0; + virtual HRESULT STDMETHODCALLTYPE GetArg(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArgPairCount(_Out_ UINT32 *pCount) = 0; + virtual HRESULT STDMETHODCALLTYPE GetArgPair(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pName, _Outptr_result_z_ BSTR *pValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDefineCount(_Out_ UINT32 *pCount) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDefine(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTargetProfile(_Outptr_result_z_ BSTR *pResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetEntryPoint(_Outptr_result_z_ BSTR *pResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetMainFileName(_Outptr_result_z_ BSTR *pResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHash(_COM_Outptr_ IDxcBlob **ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetName(_Outptr_result_z_ BSTR *pResult) = 0; + + virtual BOOL STDMETHODCALLTYPE IsFullPDB() = 0; + virtual HRESULT STDMETHODCALLTYPE GetFullPDB(_COM_Outptr_ IDxcBlob **ppFullPDB) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVersionInfo(_COM_Outptr_ IDxcVersionInfo **ppVersionInfo) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetCompiler(_In_ IDxcCompiler3 *pCompiler) = 0; + virtual HRESULT STDMETHODCALLTYPE CompileForFullPDB(_COM_Outptr_ IDxcResult **ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE OverrideArgs(_In_ DxcArgPair *pArgPairs, UINT32 uNumArgPairs) = 0; + virtual HRESULT STDMETHODCALLTYPE OverrideRootSignature(_In_ const WCHAR *pRootSignature) = 0; +}; + +CROSS_PLATFORM_UUIDOF(IDxcPdbUtils2, "4315D938-F369-4F93-95A2-252017CC3807") +struct IDxcPdbUtils2 : public IUnknown { + virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pPdbOrDxil) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSourceCount(_Out_ UINT32 *pCount) = 0; + virtual HRESULT STDMETHODCALLTYPE GetSource(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobEncoding **ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetSourceName(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobWide **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLibraryPDBCount(UINT32 *pCount) = 0; + virtual HRESULT STDMETHODCALLTYPE GetLibraryPDB(_In_ UINT32 uIndex, _COM_Outptr_ IDxcPdbUtils2 **ppOutPdbUtils, _COM_Outptr_opt_result_maybenull_ IDxcBlobWide **ppLibraryName) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFlagCount(_Out_ UINT32 *pCount) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFlag(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobWide **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArgCount(_Out_ UINT32 *pCount) = 0; + virtual HRESULT STDMETHODCALLTYPE GetArg(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobWide **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArgPairCount(_Out_ UINT32 *pCount) = 0; + virtual HRESULT STDMETHODCALLTYPE GetArgPair(_In_ UINT32 uIndex, _COM_Outptr_result_maybenull_ IDxcBlobWide **ppName, _COM_Outptr_result_maybenull_ IDxcBlobWide **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDefineCount(_Out_ UINT32 *pCount) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDefine(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobWide **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTargetProfile(_COM_Outptr_result_maybenull_ IDxcBlobWide **ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetEntryPoint(_COM_Outptr_result_maybenull_ IDxcBlobWide **ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetMainFileName(_COM_Outptr_result_maybenull_ IDxcBlobWide **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHash(_COM_Outptr_result_maybenull_ IDxcBlob **ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE GetName(_COM_Outptr_result_maybenull_ IDxcBlobWide **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVersionInfo(_COM_Outptr_result_maybenull_ IDxcVersionInfo **ppVersionInfo) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCustomToolchainID(_Out_ UINT32 *pID) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCustomToolchainData(_COM_Outptr_result_maybenull_ IDxcBlob **ppBlob) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetWholeDxil(_COM_Outptr_result_maybenull_ IDxcBlob **ppResult) = 0; + + virtual BOOL STDMETHODCALLTYPE IsFullPDB() = 0; + virtual BOOL STDMETHODCALLTYPE IsPDBRef() = 0; +}; + +// Note: __declspec(selectany) requires 'extern' +// On Linux __declspec(selectany) is removed and using 'extern' results in link error. +#ifdef _MSC_VER +#define CLSID_SCOPE __declspec(selectany) extern +#else +#define CLSID_SCOPE +#endif + +CLSID_SCOPE const CLSID CLSID_DxcCompiler = { + 0x73e22d93, + 0xe6ce, + 0x47f3, + {0xb5, 0xbf, 0xf0, 0x66, 0x4f, 0x39, 0xc1, 0xb0}}; + +// {EF6A8087-B0EA-4D56-9E45-D07E1A8B7806} +CLSID_SCOPE const GUID CLSID_DxcLinker = { + 0xef6a8087, + 0xb0ea, + 0x4d56, + {0x9e, 0x45, 0xd0, 0x7e, 0x1a, 0x8b, 0x78, 0x6}}; + +// {CD1F6B73-2AB0-484D-8EDC-EBE7A43CA09F} +CLSID_SCOPE const CLSID CLSID_DxcDiaDataSource = { + 0xcd1f6b73, + 0x2ab0, + 0x484d, + {0x8e, 0xdc, 0xeb, 0xe7, 0xa4, 0x3c, 0xa0, 0x9f}}; + +// {3E56AE82-224D-470F-A1A1-FE3016EE9F9D} +CLSID_SCOPE const CLSID CLSID_DxcCompilerArgs = { + 0x3e56ae82, + 0x224d, + 0x470f, + {0xa1, 0xa1, 0xfe, 0x30, 0x16, 0xee, 0x9f, 0x9d}}; + +// {6245D6AF-66E0-48FD-80B4-4D271796748C} +CLSID_SCOPE const GUID CLSID_DxcLibrary = { + 0x6245d6af, + 0x66e0, + 0x48fd, + {0x80, 0xb4, 0x4d, 0x27, 0x17, 0x96, 0x74, 0x8c}}; + +CLSID_SCOPE const GUID CLSID_DxcUtils = CLSID_DxcLibrary; + +// {8CA3E215-F728-4CF3-8CDD-88AF917587A1} +CLSID_SCOPE const GUID CLSID_DxcValidator = { + 0x8ca3e215, + 0xf728, + 0x4cf3, + {0x8c, 0xdd, 0x88, 0xaf, 0x91, 0x75, 0x87, 0xa1}}; + +// {D728DB68-F903-4F80-94CD-DCCF76EC7151} +CLSID_SCOPE const GUID CLSID_DxcAssembler = { + 0xd728db68, + 0xf903, + 0x4f80, + {0x94, 0xcd, 0xdc, 0xcf, 0x76, 0xec, 0x71, 0x51}}; + +// {b9f54489-55b8-400c-ba3a-1675e4728b91} +CLSID_SCOPE const GUID CLSID_DxcContainerReflection = { + 0xb9f54489, + 0x55b8, + 0x400c, + {0xba, 0x3a, 0x16, 0x75, 0xe4, 0x72, 0x8b, 0x91}}; + +// {AE2CD79F-CC22-453F-9B6B-B124E7A5204C} +CLSID_SCOPE const GUID CLSID_DxcOptimizer = { + 0xae2cd79f, + 0xcc22, + 0x453f, + {0x9b, 0x6b, 0xb1, 0x24, 0xe7, 0xa5, 0x20, 0x4c}}; + +// {94134294-411f-4574-b4d0-8741e25240d2} +CLSID_SCOPE const GUID CLSID_DxcContainerBuilder = { + 0x94134294, + 0x411f, + 0x4574, + {0xb4, 0xd0, 0x87, 0x41, 0xe2, 0x52, 0x40, 0xd2}}; + +// {54621dfb-f2ce-457e-ae8c-ec355faeec7c} +CLSID_SCOPE const GUID CLSID_DxcPdbUtils = { + 0x54621dfb, + 0xf2ce, + 0x457e, + {0xae, 0x8c, 0xec, 0x35, 0x5f, 0xae, 0xec, 0x7c}}; + +#endif diff --git a/RT/Renderer/Backend/DX12/assets/CMakeLists.txt b/RT/Renderer/Backend/DX12/assets/CMakeLists.txt index 04ddec1..7407699 100644 --- a/RT/Renderer/Backend/DX12/assets/CMakeLists.txt +++ b/RT/Renderer/Backend/DX12/assets/CMakeLists.txt @@ -1,10 +1,10 @@ -cmake_minimum_required (VERSION 3.8) - -#copy shaders when a change happened. -add_custom_target(copy_shaders ALL - COMMAND ${CMAKE_COMMAND} -E copy_directory - ${CMAKE_CURRENT_SOURCE_DIR} - $/assets - COMMENT "Change found in shaders or the asset folder, copying over Assets folder to output directory.") - +cmake_minimum_required (VERSION 3.8) + +#copy shaders when a change happened. +add_custom_target(copy_shaders ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_SOURCE_DIR} + $/assets + COMMENT "Change found in shaders or the asset folder, copying over Assets folder to output directory.") + add_dependencies(Showcase_Renderer copy_shaders) \ No newline at end of file diff --git a/RT/Renderer/Backend/DX12/assets/shaders/bloom.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/bloom.hlsl index 826457d..3e398c0 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/bloom.hlsl +++ b/RT/Renderer/Backend/DX12/assets/shaders/bloom.hlsl @@ -58,6 +58,15 @@ float3 GaussianBlur(RWTexture2D source, int2 pixel_pos, int2 direction) [numthreads(GROUP_X, GROUP_Y, 1)] void Bloom_BlurHorz(COMPUTE_ARGS) { +#ifdef DO_EARLY_OUT_IN_COMPUTE_SHADERS + int scale = 1L << (g_bloom_cb.iteration + 1); + int w = (g_global_cb.render_dim.x + scale - 1) / scale; + int h = (g_global_cb.render_dim.y + scale - 1) / scale; + if (pixel_pos.x >= w || pixel_pos.y >= h) + { + return; + } +#endif switch (g_bloom_cb.iteration) { case 0: img_bloom_pong[pixel_pos].rgb = GaussianBlur(img_bloom_prepass, pixel_pos, int2(1, 0)); break; @@ -74,6 +83,15 @@ void Bloom_BlurHorz(COMPUTE_ARGS) [numthreads(GROUP_X, GROUP_Y, 1)] void Bloom_BlurVert(COMPUTE_ARGS) { +#ifdef DO_EARLY_OUT_IN_COMPUTE_SHADERS + int scale = 1L << (g_bloom_cb.iteration + 1); + int w = (g_global_cb.render_dim.x + scale - 1) / scale; + int h = (g_global_cb.render_dim.y + scale - 1) / scale; + if (pixel_pos.x >= w || pixel_pos.y >= h) + { + return; + } +#endif switch (g_bloom_cb.iteration) { case 0: img_bloom0[pixel_pos].rgb = GaussianBlur(img_bloom_pong, pixel_pos, int2(0, 1)); break; diff --git a/RT/Renderer/Backend/DX12/assets/shaders/composite.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/composite.hlsl index b98d1b0..110c137 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/composite.hlsl +++ b/RT/Renderer/Backend/DX12/assets/shaders/composite.hlsl @@ -3,9 +3,11 @@ //------------------------------------------------------------------------ [numthreads(GROUP_X, GROUP_Y, 1)] -void CompositeCS(uint3 thread_id : SV_DispatchThreadID) +void CompositeCS(COMPUTE_ARGS) { - int2 co = thread_id.xy; + EARLY_OUT + + int2 co = pixel_pos.xy; float3 albedo = img_albedo [co].rgb; float3 emissive = img_emissive[co].rgb; diff --git a/RT/Renderer/Backend/DX12/assets/shaders/denoise.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/denoise.hlsl index 7eb8be2..da492f1 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/denoise.hlsl +++ b/RT/Renderer/Backend/DX12/assets/shaders/denoise.hlsl @@ -155,6 +155,8 @@ void DoSvgfFilterStep(int2 center_pos, [numthreads(GROUP_X, GROUP_Y, 1)] void DenoiseDirectCS(int2 pixel_pos : SV_DispatchThreadID) { + EARLY_OUT + float3 filtered_direct, filtered_spec; float4 filtered_moments; switch (g_denoise_cb.iteration) diff --git a/RT/Renderer/Backend/DX12/assets/shaders/denoiser/post_resample.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/denoiser/post_resample.hlsl index 6e66349..8334548 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/denoiser/post_resample.hlsl +++ b/RT/Renderer/Backend/DX12/assets/shaders/denoiser/post_resample.hlsl @@ -21,6 +21,7 @@ void Preload(uint2 shared_pos, uint2 global_pos) void Denoise_PostResample(COMPUTE_ARGS) { PRELOAD_INTO_SHARED + EARLY_OUT // ------------------------------------------------------------------ @@ -61,27 +62,72 @@ void Denoise_PostResample(COMPUTE_ARGS) float2 uv = (float2(pixel_pos) + 0.5) / float2(g_global_cb.render_dim); float2 uv_prev = uv + motion; + float3 curr_norm = DecodeNormalOctahedron(img_normal[pixel_pos].xy); + float3 curr_world = ReconstructWorldPosFromGBuffer(pixel_pos); + float3 diff_prev = diff_curr; float3 spec_prev = spec_curr; if (all(and(uv_prev >= 0, uv_prev < 1))) { - if (tweak.diff_stabilize_sharp) - { - diff_prev = max(0, SampleTextureCatmullRom(tex_diff_stable_hist, g_sampler_linear_clamp, uv_prev, g_global_cb.render_dim).rgb); - } - else - { - diff_prev = tex_diff_stable_hist.SampleLevel(g_sampler_linear_clamp, uv_prev, 0).rgb; - } +#define BLEED_FIX 1 +#if BLEED_FIX + BilinearSamples samples; + GetBilinearSamples(float2(pixel_pos) + motion*g_global_cb.render_dim, samples); - if (tweak.spec_stabilize_sharp) + float4 geom_weights = 1; + for (int i = 0; i < 4; i++) { - spec_prev = max(0, SampleTextureCatmullRom(tex_spec_stable_hist, g_sampler_linear_clamp, uv_prev, g_global_cb.render_dim).rgb); + int2 pos = samples.positions[i]; + float w = samples.weights [i]; + + float3 world = ReconstructPrevWorldPosFromGBuffer(pos); + + float plane_distance = abs(dot(curr_norm, curr_world) - dot(curr_norm, world)); + float disocclusion_threshold = 1.0f; + + geom_weights[i] = plane_distance < disocclusion_threshold; } - else + + float geom_sum = dot(geom_weights, 1); + if (geom_sum > 0.001) { - spec_prev = tex_spec_stable_hist.SampleLevel(g_sampler_linear_clamp, uv_prev, 0).rgb; + if (geom_sum < 4.0) + { + for (int i = 0; i < 4; i++) + { + int2 pos = samples.positions[i]; + float w = samples.weights [i]; + w *= geom_weights[i]; + diff_prev += w*tex_diff_stable_hist.Load(uint3(pos, 0)).rgb; + spec_prev += w*tex_spec_stable_hist.Load(uint3(pos, 0)).rgb; + } + diff_prev *= rcp(geom_sum); + spec_prev *= rcp(geom_sum); + } + else + { +#endif + if (tweak.diff_stabilize_sharp) + { + diff_prev = max(0, SampleTextureCatmullRom(tex_diff_stable_hist, g_sampler_linear_clamp, uv_prev, g_global_cb.render_dim).rgb); + } + else + { + diff_prev = tex_diff_stable_hist.SampleLevel(g_sampler_linear_clamp, uv_prev, 0).rgb; + } + + if (tweak.spec_stabilize_sharp) + { + spec_prev = max(0, SampleTextureCatmullRom(tex_spec_stable_hist, g_sampler_linear_clamp, uv_prev, g_global_cb.render_dim).rgb); + } + else + { + spec_prev = tex_spec_stable_hist.SampleLevel(g_sampler_linear_clamp, uv_prev, 0).rgb; + } +#if BLEED_FIX + } } +#endif } float3 diff_sigma = max(0, sqrt(diff_m2 - diff_m1*diff_m1)); diff --git a/RT/Renderer/Backend/DX12/assets/shaders/direct_lighting.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/direct_lighting.hlsl index 2c2682b..780a03b 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/direct_lighting.hlsl +++ b/RT/Renderer/Backend/DX12/assets/shaders/direct_lighting.hlsl @@ -30,6 +30,7 @@ void DirectLightingRaygen() geo_ray_output.roughness = img_roughness[dispatch_idx].x; geo_ray_output.vis_prim = img_visibility_prim[dispatch_idx].xy; geo_ray_output.vis_bary = img_visibility_bary[dispatch_idx].xy; + geo_ray_output.world_p = ReconstructWorldPosFromGBuffer(dispatch_idx); geo_ray_output.instance_data = g_instance_data_buffer[geo_ray_output.vis_prim.x]; geo_ray_output.hit_triangle = GetHitTriangle(geo_ray_output.instance_data.triangle_buffer_idx, geo_ray_output.vis_prim.y); diff --git a/RT/Renderer/Backend/DX12/assets/shaders/direct_lighting.hlsli b/RT/Renderer/Backend/DX12/assets/shaders/direct_lighting.hlsli index 8cc22db..106959f 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/direct_lighting.hlsli +++ b/RT/Renderer/Backend/DX12/assets/shaders/direct_lighting.hlsli @@ -153,7 +153,7 @@ void CalculateDirectLightingAtSurface(in GeometryRayOutput IN, inout DirectLight if (HasHitGeometry(IN.vis_prim)) { float3 unpacked_normal = DecodeNormalOctahedron(IN.normal); - float3 geo_world_p = ReconstructWorldPosFromGBuffer(co); + float3 geo_world_p = IN.world_p; // ReconstructWorldPosFromGBuffer(co); if (!(all(material_desc.albedo == 0) && material_desc.metallic == 1)) { @@ -176,7 +176,7 @@ void CalculateDirectLightingAtSurface(in GeometryRayOutput IN, inout DirectLight if (tweak.ris && (!is_indirect || tweak.ris_indirect)) { - if (tweak.ris == 1) + if (tweak.ris == 2) { for (uint light_index = 0; light_index < lights_count; light_index++) { @@ -198,7 +198,7 @@ void CalculateDirectLightingAtSurface(in GeometryRayOutput IN, inout DirectLight W = r.w_y > 0.001 ? rcp(r.w_y)*r.w_sum : 0.0; } - else if (tweak.ris == 2) + else if (tweak.ris == 1) { for (uint sample_index = 0; sample_index < min(tweak.ris_spp, lights_count); sample_index++) { @@ -234,10 +234,10 @@ void CalculateDirectLightingAtSurface(in GeometryRayOutput IN, inout DirectLight float ndotl = max(0, dot(unpacked_normal, s.L)); - if (any(s.e > 0.001f) && ndotl > 0.001f) + if (any(s.e > 0.001) && ndotl > 0.001) { RayDesc occlusion_ray; - occlusion_ray.Origin = geo_world_p + 0.01f * unpacked_normal; + occlusion_ray.Origin = geo_world_p + 0.01 * unpacked_normal; occlusion_ray.Direction = s.L; occlusion_ray.TMin = RT_RAY_T_MIN; occlusion_ray.TMax = s.L_dist; @@ -252,8 +252,16 @@ void CalculateDirectLightingAtSurface(in GeometryRayOutput IN, inout DirectLight float3 brdf_diffuse, brdf_specular; EvaluateBRDF(-IN.view_dir, unpacked_normal, s.L, material_desc, brdf_diffuse, brdf_specular); + float direct_light_specular_weight = 1.0f; + if (!is_indirect) + { + direct_light_specular_weight = smoothstep(tweak.direct_specular_threshold - 0.1, + tweak.direct_specular_threshold + 0.1, + material_desc.roughness); + } + OUT.direct_lighting += c * brdf_diffuse; - OUT.direct_specular += c * brdf_specular; + OUT.direct_specular += c * brdf_specular * direct_light_specular_weight; } } } diff --git a/RT/Renderer/Backend/DX12/assets/shaders/gen_mipmap.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/gen_mipmap.hlsl new file mode 100644 index 0000000..8553fe0 --- /dev/null +++ b/RT/Renderer/Backend/DX12/assets/shaders/gen_mipmap.hlsl @@ -0,0 +1,150 @@ +#include "include_shared/shared_common.hlsl.h" + +#define GEN_MIPMAP_WIDTH_HEIGHT_EVEN 0 +#define GEN_MIPMAP_WIDTH_ODD_HEIGHT_EVEN 1 +#define GEN_MIPMAP_WIDTH_EVEN_HEIGHT_ODD 2 +#define GEN_MIPMAP_WIDTH_HEIGHT_ODD 3 + +ConstantBuffer g_mipmap_cb : register(b0); + +Texture2D g_src_mip : register(t0); + +RWTexture2D g_dst_mip0 : register(u0); +RWTexture2D g_dst_mip1 : register(u1); +RWTexture2D g_dst_mip2 : register(u2); +RWTexture2D g_dst_mip3 : register(u3); + +SamplerState g_samp_linear_clamp : register(s0); + +groupshared float g_R[64]; +groupshared float g_G[64]; +groupshared float g_B[64]; +groupshared float g_A[64]; + +void StoreColorGroupShared(uint idx, float4 color) +{ + g_R[idx] = color.r; + g_G[idx] = color.g; + g_B[idx] = color.b; + g_A[idx] = color.a; +} + +float4 LoadColorGroupShared(uint idx) +{ + return float4(g_R[idx], g_G[idx], g_B[idx], g_A[idx]); +} + +float3 ConvertToSRGB(float3 lin) +{ + return select(lin < 0.0031308, 12.92 * lin, 1.055 * pow(abs(lin), 1.0 / 2.4) - 0.055); +} + +float4 PackColor(float4 color) +{ + if (g_mipmap_cb.is_srgb) + return float4(ConvertToSRGB(color.rgb), color.a); + else + return color; +} + +[numthreads(8, 8, 1)] +void GenMipMapCS(uint3 dispatch_idx : SV_DispatchThreadID, uint group_idx : SV_GroupIndex) +{ + float4 src0 = (float4)0; + switch (g_mipmap_cb.src_dim) + { + case GEN_MIPMAP_WIDTH_HEIGHT_EVEN: + { + float2 uv = g_mipmap_cb.texel_size * (dispatch_idx.xy + 0.5); + src0 = g_src_mip.SampleLevel(g_samp_linear_clamp, uv, g_mipmap_cb.src_mip); + } break; + case GEN_MIPMAP_WIDTH_ODD_HEIGHT_EVEN: + { + float2 uv = g_mipmap_cb.texel_size * (dispatch_idx.xy + float2(0.25f, 0.5f)); + float2 off = g_mipmap_cb.texel_size * float2(0.5f, 0.0f); + + src0 = 0.5f * (g_src_mip.SampleLevel(g_samp_linear_clamp, uv, g_mipmap_cb.src_mip) + + g_src_mip.SampleLevel(g_samp_linear_clamp, uv + off, g_mipmap_cb.src_mip)); + } + break; + case GEN_MIPMAP_WIDTH_EVEN_HEIGHT_ODD: + { + float2 uv = g_mipmap_cb.texel_size * (dispatch_idx.xy + float2(0.5f, 0.25f)); + float2 off = g_mipmap_cb.texel_size * float2(0.0f, 0.5f); + + src0 = 0.5f * (g_src_mip.SampleLevel(g_samp_linear_clamp, uv, g_mipmap_cb.src_mip) + + g_src_mip.SampleLevel(g_samp_linear_clamp, uv + off, g_mipmap_cb.src_mip)); + } + break; + case GEN_MIPMAP_WIDTH_HEIGHT_ODD: + { + float2 uv = g_mipmap_cb.texel_size * (dispatch_idx.xy + float2(0.25f, 0.25f)); + float2 off = g_mipmap_cb.texel_size * 0.5f; + + src0 = g_src_mip.SampleLevel(g_samp_linear_clamp, uv, g_mipmap_cb.src_mip); + src0 += g_src_mip.SampleLevel(g_samp_linear_clamp, uv + float2(off.x, 0.0f), g_mipmap_cb.src_mip); + src0 += g_src_mip.SampleLevel(g_samp_linear_clamp, uv + float2(0.0f, off.y), g_mipmap_cb.src_mip); + src0 += g_src_mip.SampleLevel(g_samp_linear_clamp, uv + float2(off.x, off.y), g_mipmap_cb.src_mip); + src0 *= 0.25f; + } + break; + } + + g_dst_mip0[dispatch_idx.xy] = PackColor(src0); + + // Exit all threads if we are done + if (g_mipmap_cb.num_mips == 1) + return; + + StoreColorGroupShared(group_idx, src0); + + // Need to wait here until all threads have executed all instructions until this point + GroupMemoryBarrierWithGroupSync(); + + if ((group_idx & 0x9) == 0) + { + float4 src1 = LoadColorGroupShared(group_idx + 0x01); + float4 src2 = LoadColorGroupShared(group_idx + 0x08); + float4 src3 = LoadColorGroupShared(group_idx + 0x09); + + src0 = 0.25 * (src0 + src1 + src2 + src3); + + g_dst_mip1[dispatch_idx.xy / 2] = PackColor(src0); + StoreColorGroupShared(group_idx, src0); + } + + // Exit all threads if we are done + if (g_mipmap_cb.num_mips == 2) + return; + + GroupMemoryBarrierWithGroupSync(); + + if ((group_idx & 0x1B) == 0) + { + float4 src1 = LoadColorGroupShared(group_idx + 0x02); + float4 src2 = LoadColorGroupShared(group_idx + 0x10); + float4 src3 = LoadColorGroupShared(group_idx + 0x12); + + src0 = 0.25 * (src0 + src1 + src2 + src3); + + g_dst_mip2[dispatch_idx.xy / 4] = PackColor(src0); + StoreColorGroupShared(group_idx, src0); + } + + // Exit all threads if we are done + if (g_mipmap_cb.num_mips == 3) + return; + + GroupMemoryBarrierWithGroupSync(); + + if (group_idx == 0) + { + float4 src1 = LoadColorGroupShared(group_idx + 0x04); + float4 src2 = LoadColorGroupShared(group_idx + 0x20); + float4 src3 = LoadColorGroupShared(group_idx + 0x24); + + src0 = 0.25 * (src0 + src1 + src2 + src3); + + g_dst_mip3[dispatch_idx.xy / 8] = PackColor(src0); + } +} diff --git a/RT/Renderer/Backend/DX12/assets/shaders/include/common.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/include/common.hlsl index a44d419..c56bf09 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/include/common.hlsl +++ b/RT/Renderer/Backend/DX12/assets/shaders/include/common.hlsl @@ -6,6 +6,12 @@ using namespace RT; +#ifdef DO_EARLY_OUT_IN_COMPUTE_SHADERS +#define EARLY_OUT if (pixel_pos.x >= g_global_cb.render_dim.x || pixel_pos.y >= g_global_cb.render_dim.y) return; +#else +#define EARLY_OUT +#endif + // ------------------------------------------------------------------ // Preload stuff @@ -71,7 +77,8 @@ static const float PI = 3.14159265359; #define LARGE_NUMBER 1000000000 // @Volatile: Must match Renderer.h -#define RT_TRIANGLE_HOLDS_MATERIAL_EDGE (1 << 15) +#define RT_TRIANGLE_HOLDS_MATERIAL_EDGE (1u << 31) +#define RT_TRIANGLE_HOLDS_MATERIAL_INDEX (1u << 30) #define RT_TRIANGLE_MATERIAL_INSTANCE_OVERRIDE (0xFFFF) #define RT_RAY_T_MIN 0.001 @@ -100,6 +107,11 @@ struct RT_Triangle uint material_edge_index; }; +// @Volatile: Must match RT_MaterialFlags in Renderer.h +#define RT_MaterialFlag_BlackbodyRadiator (0x1) // things like lava, basically just treats the albedo as an emissive map and skips all shading +#define RT_MaterialFlag_NoCastingShadow (0x2) // some materials/meshes we do not want to cast shadows (like the 3D cockpit) +#define RT_MaterialFlag_Light (0x4) + // @Volatile: Must match RT_LightKind in ApiTypes.h #define RT_LightKind_Area_Sphere (0) #define RT_LightKind_Area_Rect (1) @@ -581,7 +593,11 @@ void GetMaterialIndicesAndOrient(uint material_edge_index, out uint material_ind } else { - if (material_edge_index & RT_TRIANGLE_HOLDS_MATERIAL_EDGE) + if (material_edge_index & RT_TRIANGLE_HOLDS_MATERIAL_INDEX) + { + material_index = material_edge_index & ~RT_TRIANGLE_HOLDS_MATERIAL_INDEX; + } + else if (material_edge_index & RT_TRIANGLE_HOLDS_MATERIAL_EDGE) { material_index = GetMaterialIndex(material_edge_index & ~RT_TRIANGLE_HOLDS_MATERIAL_EDGE); } @@ -661,7 +677,7 @@ void GetHitMaterialAndUVs(InstanceData instance_data, RT_Triangle hit_triangle, } } -bool IsHitTransparent(uint instance_idx, uint primitive_idx, float2 barycentrics) +bool IsHitTransparent(uint instance_idx, uint primitive_idx, float2 barycentrics, inout Material material) { InstanceData instance_data = g_instance_data_buffer[instance_idx]; RT_Triangle hit_triangle = GetHitTriangle(instance_data.triangle_buffer_idx, primitive_idx); @@ -678,7 +694,11 @@ bool IsHitTransparent(uint instance_idx, uint primitive_idx, float2 barycentrics } else { - if (material_edge_index & RT_TRIANGLE_HOLDS_MATERIAL_EDGE) + if (material_edge_index & RT_TRIANGLE_HOLDS_MATERIAL_INDEX) + { + material_index = material_edge_index & ~RT_TRIANGLE_HOLDS_MATERIAL_INDEX; + } + else if (material_edge_index & RT_TRIANGLE_HOLDS_MATERIAL_EDGE) { material_index = GetMaterialIndex(material_edge_index & ~RT_TRIANGLE_HOLDS_MATERIAL_EDGE); } @@ -723,7 +743,7 @@ bool IsHitTransparent(uint instance_idx, uint primitive_idx, float2 barycentrics } } - Material material = g_materials[material_index]; + material = g_materials[material_index]; Texture2D tex_albedo = GetTextureFromIndex(material.albedo_index); float4 albedo = tex_albedo.SampleLevel(g_sampler_point_wrap, uv, 0); @@ -873,4 +893,83 @@ float3 ReconstructPrevWorldPosFromGBuffer(uint2 dispatch_idx) return ReconstructWorldPosition(g_global_cb.prev_view_inv, img_view_dir_prev[dispatch_idx].xyz, img_depth_prev[dispatch_idx]) * img_view_dir_prev[dispatch_idx].w; } +RayDesc GetRayDesc(uint2 dispatch_idx, uint2 dispatch_dim) +{ + // Calculate UV + float2 dispatch_uv = (dispatch_idx + 0.5) / dispatch_dim; + dispatch_uv.y = 1.0f - dispatch_uv.y; + dispatch_uv.y -= g_global_cb.viewport_offset_y; + + // Apply TAA jitter if TAA is enabled or reference mode is enabled + if (tweak.reference_mode || tweak.taa_enabled) + { + dispatch_uv += GetTAAJitter(dispatch_idx); + } + + float3 curr_view_d = Unproject(g_global_cb.proj_inv, dispatch_uv, 1); + float3 curr_world_d = mul(g_global_cb.view_inv, float4(curr_view_d, 0)).xyz; + float3 curr_world_p = mul(g_global_cb.view_inv, float4(0, 0, 0, 1)).xyz; + + // Set up geometry input for primary ray trace + RayDesc ray_desc = (RayDesc)0; + ray_desc.Origin = curr_world_p; + ray_desc.Direction = curr_world_d; + ray_desc.TMin = RT_RAY_T_MIN; + ray_desc.TMax = RT_RAY_T_MAX; + + return ray_desc; +} + +// Paper: https://jcgt.org/published/0010/01/01/ +// ray_dir is the ray direction in world space +// ray_cone_radius is the cone radius on the intersection plane with the triangle +// hit_bary are the barycentric coordinates at the intersection point +// hit_position is the world space position of the intersection point +// hit_normal is the interpolated normal at the intersection point +// triangle_pos are the three triangle vertex positions in world space +// triangle_uv are the three triangle vertex uv coordinates +// tex_gradient1 and tex_gradient2 are the two texture gradients in the ray cone ellipse axes, which can be used in SampleGrad for anisotropic filtering +void ComputeTextureGradientRayCone(float3 ray_dir, float ray_cone_radius, float2 hit_bary, float3 hit_position, float3 hit_normal, + float3 triangle_pos[3], float2 triangle_uv[3], out float2 tex_gradient1, out float2 tex_gradient2) +{ + float2 intersect_uv = GetHitAttribute(triangle_uv, hit_bary); + + // Calculate both ellipse axes + float3 a1 = ray_dir - dot(hit_normal, ray_dir) * hit_normal; + float3 p1 = a1 - dot(ray_dir, a1) * ray_dir; + a1 *= ray_cone_radius / max(tweak.angle_cutoff, length(p1)); + + float3 a2 = cross(hit_normal, a1); + float3 p2 = a2 - dot(ray_dir, a2) * ray_dir; + a2 *= ray_cone_radius / max(tweak.angle_cutoff, length(p2)); + + // Compute texture coordinate gradients + float3 eP, delta = hit_position - triangle_pos[0]; + float3 e1 = triangle_pos[1] - triangle_pos[0]; + float3 e2 = triangle_pos[2] - triangle_pos[0]; + float one_over_area_triangle = 1.0 / dot(hit_normal, cross(e1, e2)); + + eP = delta + a1; + float u1 = dot(hit_normal, cross(eP, e2)) * one_over_area_triangle; + float v1 = dot(hit_normal, cross(e1, eP)) * one_over_area_triangle; + tex_gradient1 = (1.0 - u1 - v1) * triangle_uv[0] + u1 * triangle_uv[1] + v1 * triangle_uv[2] - intersect_uv; + + eP = delta + a2; + float u2 = dot(hit_normal, cross(eP, e2)) * one_over_area_triangle; + float v2 = dot(hit_normal, cross(e1, eP)) * one_over_area_triangle; + tex_gradient2 = (1.0 - u2 - v2) * triangle_uv[0] + u2 * triangle_uv[1] + v2 * triangle_uv[2] - intersect_uv; +} + +// This function will sample a texture anisotropically, using ray cones to determine which mips will be sampled +float4 SampleTextureAnisotropic(Texture2D tex, SamplerState samp, float2 tex_gradient1, float2 tex_gradient2, float2 uv) +{ + if (tweak.mip_bias != 0) + { + tex_gradient1 *= pow(2.0, tweak.mip_bias); + tex_gradient2 *= pow(2.0, tweak.mip_bias); + } + + return tex.SampleGrad(samp, uv, tex_gradient1, tex_gradient2); +} + #endif /* COMMON_HLSL */ \ No newline at end of file diff --git a/RT/Renderer/Backend/DX12/assets/shaders/include_shared/shared_common.hlsl.h b/RT/Renderer/Backend/DX12/assets/shaders/include_shared/shared_common.hlsl.h index 7441ba6..1086236 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/include_shared/shared_common.hlsl.h +++ b/RT/Renderer/Backend/DX12/assets/shaders/include_shared/shared_common.hlsl.h @@ -26,9 +26,6 @@ #define TaaNeighborhoodMode_Clip (2) #define TaaNeighborhoodMode_VarianceClip (3) -// MaterialFlag -#define RT_MaterialFlag_BlackbodyRadiator (0x1) // things like lava, basically just treats the albedo as an emissive map and skips all shading - // ------------------------------------------------------------------ // Common structs @@ -89,6 +86,15 @@ struct GlobalConstantBuffer float3 sky_color_bottom; }; +struct GenMipMapSettings +{ + uint src_mip; + uint num_mips; + float2 texel_size; + uint src_dim; + uint is_srgb; +}; + struct PixelDebugData { float4 uv_barycentrics; @@ -107,7 +113,11 @@ struct PixelDebugData #define TWEAK_BOOL(name, var, value) int var; #define TWEAK_INT(name, var, value, min, max) int var; #define TWEAK_FLOAT(name, var, value, min, max) float var; +#ifdef __cplusplus +#define TWEAK_COLOR(name, var, value) alignas(16) float4 var; +#else #define TWEAK_COLOR(name, var, value) float4 var; +#endif #define TWEAK_OPTIONS(name, var, value, ...) int var; struct TweakVars diff --git a/RT/Renderer/Backend/DX12/assets/shaders/include_shared/shared_rendertargets.hlsl.h b/RT/Renderer/Backend/DX12/assets/shaders/include_shared/shared_rendertargets.hlsl.h index 72748f8..f10eaa1 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/include_shared/shared_rendertargets.hlsl.h +++ b/RT/Renderer/Backend/DX12/assets/shaders/include_shared/shared_rendertargets.hlsl.h @@ -57,6 +57,7 @@ _(bloom5, 47, 128, 128, float4, DXGI_FORMAT_R11G11B10_FLOAT) \ _(bloom6, 48, 256, 256, float4, DXGI_FORMAT_R11G11B10_FLOAT) \ _(bloom7, 49, 512, 512, float4, DXGI_FORMAT_R11G11B10_FLOAT) \ - _(color_reference, 50, 1, 1, float4, DXGI_FORMAT_R32G32B32A32_FLOAT) \ - _(color_final, 51, 1, 1, float4, DXGI_FORMAT_R8G8B8A8_UNORM) \ - _(debug, 52, 1, 1, float4, DXGI_FORMAT_R32G32B32A32_FLOAT) + _(scene, 50, 1, 1, float4, DXGI_FORMAT_R8G8B8A8_UNORM) \ + _(color_reference, 51, 1, 1, float4, DXGI_FORMAT_R32G32B32A32_FLOAT) \ + _(color_final, 52, 1, 1, float4, DXGI_FORMAT_R8G8B8A8_UNORM) \ + _(debug, 52, 1, 1, float4, DXGI_FORMAT_R8G8B8A8_UNORM) 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 26a56a9..33f8e5b 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 @@ -15,6 +15,13 @@ // TWEAK_COLOR(name, default_value) // RGB color picker // TWEAK_OPTIONS(name, default_value, list of options as name-value pairs) // dropdown box +TWEAK_BOOL("Vsync", vsync, true) + +TWEAK_CATEGORY_BEGIN("Camera"); +// ---------- name ----------------------- variable ----------------- default - min - max --------------------------- +TWEAK_FLOAT ("FOV", fov, 60.0, 60.0, 90.0) +// ------------------------------------------------------------------------------------------------------------------ +TWEAK_CATEGORY_END(); TWEAK_CATEGORY_BEGIN("Pathtracer") // ---------- name ----------------------- variable ----------------- default - min - max --------------------------- @@ -24,9 +31,10 @@ TWEAK_BOOL ("Enable PBR", enable_pbr, true) TWEAK_BOOL ("Enable Pathtracing", enable_pathtracing, true) TWEAK_COLOR ("Ambient Color", ambient_color, (0.05f, 0.07f, 0.1f)) TWEAK_BOOL ("Importance Sample BRDF", importance_sample_brdf, true) -TWEAK_OPTIONS("RIS", ris, 2, "Off", "Full", "Subset") +TWEAK_FLOAT ("Direct Specular Threshold", direct_specular_threshold, 0.25, 0, 1) +TWEAK_OPTIONS("RIS", ris, 2, "Off", "Subset", "Full") TWEAK_BOOL ("RIS Indirect", ris_indirect, true) -TWEAK_INT ("RIS SPP", ris_spp, 4, 1, 16) +TWEAK_INT ("RIS SPP", ris_spp, 4, 1, 16) 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) @@ -97,10 +105,19 @@ TWEAK_FLOAT ("Threshold", bloom_threshold, 0.0, // ------------------------------------------------------------------------------------------------------------------ TWEAK_CATEGORY_END() +TWEAK_CATEGORY_BEGIN("Tonemap") +// ---------- name ----------------------- variable ----------------- default - min - max --------------------------- +TWEAK_FLOAT("Exposure", exposure, 0.1, -2, 2) +TWEAK_FLOAT("Linear Section", tonemap_linear_section, 0.25, 0.0, 1.0) +TWEAK_FLOAT("Whitepoint", tonemap_whitepoint, 8.0, 1.0, 16.0) +TWEAK_FLOAT("Hue Shift", tonemap_hue_shift, 0.7, 0.0, 1.0) +// ------------------------------------------------------------------------------------------------------------------ +TWEAK_CATEGORY_END() + TWEAK_CATEGORY_BEGIN("Post-Processing") // ---------- name ----------------------- variable ----------------- default - min - max --------------------------- TWEAK_FLOAT ("Sharpen", sharpen_amount, 2.0, 0, 8) -TWEAK_FLOAT ("Gamma", gamma, 0.0, -1, 1) +TWEAK_FLOAT ("Gamma", gamma, -0.3, -1, 1) TWEAK_FLOAT ("White Level", white_level, 1.0, 0, 1) TWEAK_FLOAT ("Black Level", black_level, 0.0, 0, 1) TWEAK_FLOAT ("Vignette Scale", vignette_scale, 0.875, 0.5, 1.5) @@ -113,3 +130,11 @@ TWEAK_CATEGORY_BEGIN("Debug render") TWEAK_FLOAT ("Debug render blend factor", debug_render_blend_factor, 1.0, 0.0, 1.0) // ------------------------------------------------------------------------------------------------------------------ TWEAK_CATEGORY_END() + +TWEAK_CATEGORY_BEGIN("Mipmaps") +// ---------- name ----------------------- variable ----------------- default - min - max --------------------------- +TWEAK_INT ("Mip Bias", mip_bias, -1, -10, 10) +TWEAK_FLOAT ("Secondary bounce bias", secondary_bounce_bias, 0.0005, 0.00001, 1.0) +TWEAK_FLOAT ("Angle cutoff", angle_cutoff, 0.125, 0.0000001, 1.0) +// ------------------------------------------------------------------------------------------------------------------ +TWEAK_CATEGORY_END(); diff --git a/RT/Renderer/Backend/DX12/assets/shaders/indirect_lighting.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/indirect_lighting.hlsl index ebdffef..0e1efdc 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/indirect_lighting.hlsl +++ b/RT/Renderer/Backend/DX12/assets/shaders/indirect_lighting.hlsl @@ -12,23 +12,23 @@ void IndirectLightingRaygen() uint2 dispatch_idx = DispatchRaysIndex().xy; // Get G-buffer values - float3 gbuf_albedo = img_albedo[dispatch_idx].xyz; - float3 gbuf_normal = DecodeNormalOctahedron(img_normal[dispatch_idx].xy); - float3 gbuf_view_dir = img_view_dir[dispatch_idx].xyz; - float gbuf_depth = img_depth[dispatch_idx]; - float gbuf_metallic = img_metallic[dispatch_idx].x; - float gbuf_roughness = img_roughness[dispatch_idx].x; - uint gbuf_material = img_material[dispatch_idx].x; - uint2 gbuf_instance_idx_prim_idx = img_visibility_prim[dispatch_idx].xy; + float3 gbuf_albedo = img_albedo[dispatch_idx].xyz; + float3 gbuf_normal = DecodeNormalOctahedron(img_normal[dispatch_idx].xy); + float3 gbuf_view_dir = img_view_dir[dispatch_idx].xyz; + float gbuf_depth = img_depth[dispatch_idx]; + float gbuf_metallic = img_metallic[dispatch_idx].x; + float gbuf_roughness = img_roughness[dispatch_idx].x; + uint gbuf_material = img_material[dispatch_idx].x; + uint2 gbuf_instance_idx_prim_idx = img_visibility_prim[dispatch_idx].xy; if (HasHitGeometry(gbuf_instance_idx_prim_idx)) { // Get instance data and hit triangle/material InstanceData instance_data = g_instance_data_buffer[gbuf_instance_idx_prim_idx.x]; - RT_Triangle hit_triangle = GetHitTriangle(instance_data.triangle_buffer_idx, gbuf_instance_idx_prim_idx.y); - Material mat = g_materials[gbuf_material]; + RT_Triangle hit_triangle = GetHitTriangle(instance_data.triangle_buffer_idx, gbuf_instance_idx_prim_idx.y); + Material mat = g_materials[gbuf_material]; - float4 color_mod = UnpackRGBA(instance_data.material_color) * UnpackRGBA(hit_triangle.color); + float4 color_mod = UnpackRGBA(instance_data.material_color)*UnpackRGBA(hit_triangle.color); // If material is a black body radiator, we do not want to calculate any indirect lighting for that surface if (!(mat.flags & RT_MaterialFlag_BlackbodyRadiator)) @@ -37,43 +37,32 @@ void IndirectLightingRaygen() gbuf_albedo *= color_mod.rgb; MaterialDesc material_desc = (MaterialDesc)0; - material_desc.ior = 0.04; - material_desc.albedo = gbuf_albedo; - material_desc.metallic = gbuf_metallic; + material_desc.ior = 0.04; + material_desc.albedo = gbuf_albedo; + material_desc.metallic = gbuf_metallic; material_desc.roughness = gbuf_roughness; - float3x3 basis = ConstructOrthonormalBasis(gbuf_normal); + float3x3 basis = ConstructOrthonormalBasis(gbuf_normal); float3x3 basis_inv = transpose(basis); - // Note(Justin): Do we still need the recursion depth here? Dont think we do - float r1 = RandomSample(dispatch_idx, Random_IndirectJitterX + 3 * 0/*payload.recursion*/); - float r2 = RandomSample(dispatch_idx, Random_IndirectJitterY + 3 * 0/*payload.recursion*/); + float r1 = RandomSample(dispatch_idx, Random_IndirectJitterX); + float r2 = RandomSample(dispatch_idx, Random_IndirectJitterY); - float3 bounce_direction = float3(0, 1, 0); + float3 bounce_direction = float3(0, 1, 0); float3 specular_throughput = 0; - float3 diffuse_throughput = 0; + float3 diffuse_throughput = 0; - float3 N = gbuf_normal; + float3 N = gbuf_normal; float3 V = -gbuf_view_dir; + bool specular_bounce = false; + if (tweak.enable_pbr && tweak.importance_sample_brdf) { + float r_specular = RandomSample(dispatch_idx, Random_IndirectSpecular); + float specular_probability = lerp(0.5, 1.0, material_desc.metallic); - // Note(Justin): Do we still need the recursion depth here? Dont think we do - //if (/*payload.recursion*/0 > 0) - //{ - // specular_probability = 0; - //} - - // Note(Justin): Do we still need the recursion depth here? Dont think we do - float r_specular = RandomSample(dispatch_idx, Random_IndirectSpecular + 3 * 0/*payload.recursion*/); - - bool specular_bounce = r_specular <= specular_probability; - // Note(Justin): Do we still need the recursion depth here? Dont think we do - //if (/*payload.recursion*/0 > 0) - //{ - // specular_bounce = false; - //} + specular_bounce = r_specular <= specular_probability; if (specular_bounce) { @@ -173,11 +162,11 @@ void IndirectLightingRaygen() // Set up geometry input for primary ray trace PrimaryRayPayload ray_payload = (PrimaryRayPayload)0; - RayDesc ray_desc = (RayDesc)0; - ray_desc.Origin = gbuf_world_p + 0.01f * gbuf_normal; + RayDesc ray_desc = (RayDesc)0; + ray_desc.Origin = gbuf_world_p + 0.01f * gbuf_normal; ray_desc.Direction = bounce_direction; - ray_desc.TMin = RT_RAY_T_MIN; - ray_desc.TMax = RT_RAY_T_MAX; + ray_desc.TMin = RT_RAY_T_MIN; + ray_desc.TMax = RT_RAY_T_MAX; // Trace the primary ray TracePrimaryRay(ray_desc, ray_payload); @@ -187,17 +176,39 @@ void IndirectLightingRaygen() // Get geometry data from primary ray trace GetGeometryDataFromPrimaryRay(ray_desc, ray_payload, 1, geo_ray_output); + geo_ray_output.world_p = gbuf_world_p + ray_payload.hit_distance*bounce_direction; // Set up direct lighting output DirectLightingOutput direct_lighting_output = (DirectLightingOutput)0; CalculateDirectLightingAtSurface(geo_ray_output, direct_lighting_output, true); + // TODO(daniel): Fetching the material again? Should be optimized away by the compiler + Material material = g_materials[geo_ray_output.material_index]; + float3 indirect_color; if (HasHitGeometry(geo_ray_output.vis_prim)) { - indirect_color = direct_lighting_output.albedo * direct_lighting_output.direct_lighting + - direct_lighting_output.emissive_lighting + direct_lighting_output.direct_specular; + float direct_light_specular_weight = 1.0f; + + if (material.flags & RT_MaterialFlag_Light) + { + direct_light_specular_weight = saturate(1.0 - smoothstep(tweak.direct_specular_threshold - 0.1, + tweak.direct_specular_threshold, + geo_ray_output.roughness)); + } + + indirect_color = (direct_lighting_output.albedo*direct_lighting_output.direct_lighting + + direct_lighting_output.direct_specular); + + if (specular_bounce) + { + indirect_color += direct_light_specular_weight*geo_ray_output.emissive; + } + else // if(!(material.flags & RT_MaterialFlag_Light)) // This would be more correct stopping the double counting of lights. But in practice I think it just looks darker but not better, so meh. + { + indirect_color += geo_ray_output.emissive; + } } else { @@ -205,8 +216,8 @@ void IndirectLightingRaygen() indirect_color = direct_lighting_output.direct_lighting; } - float3 indirect_specular = specular_throughput * indirect_color; - float3 indirect_diffuse = diffuse_throughput * indirect_color; + float3 indirect_specular = indirect_color*specular_throughput; + float3 indirect_diffuse = indirect_color*diffuse_throughput; if (!tweak.reference_mode && tweak.svgf_enabled) { diff --git a/RT/Renderer/Backend/DX12/assets/shaders/occlusion.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/occlusion.hlsl index f07ef00..1bcfc0a 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/occlusion.hlsl +++ b/RT/Renderer/Backend/DX12/assets/shaders/occlusion.hlsl @@ -14,7 +14,13 @@ void TraceOcclusionRay(RayDesc ray, inout OcclusionRayPayload payload) [shader("anyhit")] void OcclusionAnyhit(inout OcclusionRayPayload payload, in BuiltInTriangleIntersectionAttributes attr) { - if (IsHitTransparent(InstanceIndex(), PrimitiveIndex(), attr.barycentrics)) + Material hit_material; + if (IsHitTransparent(InstanceIndex(), PrimitiveIndex(), attr.barycentrics, hit_material)) + { + IgnoreHit(); + } + + if (hit_material.flags & RT_MaterialFlag_NoCastingShadow) { IgnoreHit(); } diff --git a/RT/Renderer/Backend/DX12/assets/shaders/post_process.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/post_process.hlsl index 8a3d163..9e2cd5a 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/post_process.hlsl +++ b/RT/Renderer/Backend/DX12/assets/shaders/post_process.hlsl @@ -2,20 +2,68 @@ //------------------------------------------------------------------------ +float LinearTosRGB(float x) +{ + return x <= 0.0031308 ? x*12.92 : pow(1.055*x, 1.0 / 2.4) - 0.055; +} + +float3 LinearTosRGB(float3 x) +{ + return float3(LinearTosRGB(x.x), LinearTosRGB(x.y), LinearTosRGB(x.z)); +} + +float NaturalShoulder(float x) +{ + return 1.0 - exp(-x); +} + +float NaturalShoulder(float x, float t) +{ + float v1 = x; + float v2 = t + (1.0 - t) * NaturalShoulder((x - t) / (1.0 - t)); + return x <= t ? v1 : v2; +} + +float3 NaturalShoulder(float3 x, float t) +{ + return float3( + NaturalShoulder(x.x, t), + NaturalShoulder(x.y, t), + NaturalShoulder(x.z, t) + ); +} + float3 ApplyTonemappingCurve(float3 color) { - // TODO(daniel): What kind of tonemapping do we desire? - float3 result = 1.0 - exp(-color); - return result; + return NaturalShoulder(color.xyz, tweak.tonemap_linear_section) * rcp(NaturalShoulder(tweak.tonemap_whitepoint, tweak.tonemap_linear_section)); +} + +float3 ColorPreservingTonemap(float3 color) +{ + float3 per_channel = ApplyTonemappingCurve(color.xyz); + + float peak = max(color.x, max(color.y, color.z)); + color.xyz *= rcp(peak + 1e-6); + color.xyz *= ApplyTonemappingCurve(peak); + + color.xyz = lerp(color.xyz, per_channel, tweak.tonemap_hue_shift); + + return color; } [numthreads(GROUP_X, GROUP_Y, 1)] -void PostProcessCS(int2 co : SV_DispatchThreadID) +void PostProcessCS(COMPUTE_ARGS) { + EARLY_OUT + + int2 co = pixel_pos; + float2 uv = (float2(co) + 0.5) / float2(g_global_cb.render_dim); float3 color = tex_taa_result[co].rgb; + // Adding the color overlay for picking stuff up/damaged to the final color. + if (tweak.motion_blur_quality > 0) { // TODO(daniel): Think about per-object motion blur extending out from the object silhouette @@ -79,8 +127,15 @@ void PostProcessCS(int2 co : SV_DispatchThreadID) //------------------------------------------------------------------------ // Tonemap and sRGB - color = ApplyTonemappingCurve(color); - color = pow(abs(color), 1.0 / 2.22); + color *= exp2(tweak.exposure); + + color = ColorPreservingTonemap(color); + color = LinearTosRGB(color); + + // NOTE(daniel): Moved up here from where it was before, because it was being applied + // over top the debug display which isn't helpful. Adding it after tonemap/srgb conversion + // is maybe questionable but it probably matches the game's original rendering better + color += g_global_cb.screen_color_overlay.xyz; //------------------------------------------------------------------------ // Debug texture view @@ -133,7 +188,7 @@ void PostProcessCS(int2 co : SV_DispatchThreadID) case RT_DebugRenderMode_Motion: { float4 motion = img_motion[co]; - debug_color = float3(abs(motion.xy) * 10.0, 0); + debug_color = float3(abs(motion.xy) * 100.0, 0); } break; case RT_DebugRenderMode_MetallicRoughness: @@ -236,9 +291,5 @@ void PostProcessCS(int2 co : SV_DispatchThreadID) } float3 final_color = lerp(color, debug_color, debug_blend_factor); - - //Adding the color overlay for picking stuff up/damaged to the final color. - final_color = final_color + g_global_cb.screen_color_overlay.xyz; - img_color[co] = float4(final_color, 1.0); } \ No newline at end of file diff --git a/RT/Renderer/Backend/DX12/assets/shaders/primary_ray.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/primary_ray.hlsl index a6ed045..04366e7 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/primary_ray.hlsl +++ b/RT/Renderer/Backend/DX12/assets/shaders/primary_ray.hlsl @@ -6,6 +6,7 @@ // ----------------------------------------------------------- // Misc. + float2 BrownConradyDistortion(float2 uv, float amount, float width_over_height) { uv.y /= width_over_height; @@ -37,49 +38,9 @@ void PrimaryRaygen() uint2 dispatch_idx = DispatchRaysIndex().xy; uint2 dispatch_dim = DispatchRaysDimensions().xy; - // Calculate UV - float2 dispatch_uv = (dispatch_idx + 0.5) / dispatch_dim; - dispatch_uv.y = 1.0f - dispatch_uv.y; - dispatch_uv.y -= g_global_cb.viewport_offset_y; - - // Apply TAA jitter if TAA is enabled or reference mode is enabled - if (tweak.reference_mode || tweak.taa_enabled) - { - dispatch_uv += GetTAAJitter(dispatch_idx); - } - - float3 curr_view_d = Unproject(g_global_cb.proj_inv, dispatch_uv, 1); - float3 curr_world_d = mul(g_global_cb.view_inv, float4(curr_view_d, 0)).xyz; - float3 curr_world_p = mul(g_global_cb.view_inv, float4(0, 0, 0, 1)).xyz; - - float3 world_d = curr_world_d; - float3 world_p = curr_world_p; - -#if 0 - // Ray jitter based motion blur is too harmful to temporal resampling - if (tweak.motion_blur) - { - // Project current view direction and origin to previous frame's view direction and origin - float3 prev_view_d = Unproject(g_global_cb.prev_proj_inv, dispatch_uv, 1); - float3 prev_world_d = mul(g_global_cb.prev_view_inv, float4(prev_view_d, 0)).xyz; - float3 prev_world_p = mul(g_global_cb.prev_view_inv, float4(0, 0, 0, 1)).xyz; - - // Lerp between previous frame's and current frame's view direction and origin, also apply motion blur jitter - float motion_blur_jitter = RandomSample(dispatch_idx, Random_MotionBlur); - world_d = lerp(prev_world_d, curr_world_d, motion_blur_jitter); - world_p = lerp(prev_world_p, curr_world_p, motion_blur_jitter); - } -#endif - - // Set up geometry input for primary ray trace - PrimaryRayPayload ray_payload = (PrimaryRayPayload)0; - RayDesc ray_desc = (RayDesc)0; - ray_desc.Origin = world_p; - ray_desc.Direction = world_d; - ray_desc.TMin = RT_RAY_T_MIN; - ray_desc.TMax = RT_RAY_T_MAX; - // Trace the primary ray + RayDesc ray_desc = GetRayDesc(dispatch_idx, dispatch_dim); + PrimaryRayPayload ray_payload = (PrimaryRayPayload)0; TracePrimaryRay(ray_desc, ray_payload); // Set up geometry output from primary ray trace and set non-zero defaults where necessary @@ -170,7 +131,8 @@ void PrimaryClosesthit(inout PrimaryRayPayload payload, in BuiltInTriangleInters [shader("anyhit")] void PrimaryAnyhit(inout PrimaryRayPayload payload, in BuiltInTriangleIntersectionAttributes attr) { - if (IsHitTransparent(InstanceIndex(), PrimitiveIndex(), attr.barycentrics)) + Material hit_material; + if (IsHitTransparent(InstanceIndex(), PrimitiveIndex(), attr.barycentrics, hit_material)) { IgnoreHit(); } diff --git a/RT/Renderer/Backend/DX12/assets/shaders/primary_ray.hlsli b/RT/Renderer/Backend/DX12/assets/shaders/primary_ray.hlsli index 4a94b46..4e047ef 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/primary_ray.hlsli +++ b/RT/Renderer/Backend/DX12/assets/shaders/primary_ray.hlsli @@ -23,6 +23,7 @@ struct GeometryRayOutput uint material_index; float3 albedo; float3 emissive; + float3 world_p; // bullshit because it's not geometry ray output, but it's because in here because this struct is also direct lighting input float2 normal; float depth; float2 motion; @@ -55,7 +56,7 @@ void GetGeometryDataFromPrimaryRay(RayDesc ray_desc, PrimaryRayPayload ray_paylo // ------------------------------------------------------------------------------------- // Set up hit material - float2 uv = 0; + float2 uv = (float2)0; GetHitMaterialAndUVs(OUT.instance_data, OUT.hit_triangle, ray_payload.barycentrics, OUT.material_index, uv); Material hit_material = g_materials[OUT.material_index]; @@ -90,32 +91,9 @@ void GetGeometryDataFromPrimaryRay(RayDesc ray_desc, PrimaryRayPayload ray_paylo Texture2D tex_roughness = GetTextureFromIndex(hit_material.roughness_index); Texture2D tex_emissive = GetTextureFromIndex(hit_material.emissive_index); - // ------------------------------------------------------------------------------------- - // Determine gbuffer albedo value - - if (tweak.albedo_sample_linear) - { - OUT.albedo = tex_albedo.SampleLevel(g_sampler_linear_wrap, uv, 0).xyz; - } - else - { - OUT.albedo = tex_albedo.SampleLevel(g_sampler_point_wrap, uv, 0).xyz; - } - - // ----------------------------------------------------------- - // Emissive - - if (tweak.albedo_sample_linear) - { - OUT.emissive = emissive_factor*tex_emissive.SampleLevel(g_sampler_linear_wrap, uv, 0).rgb; - } - else - { - OUT.emissive = emissive_factor*tex_emissive.SampleLevel(g_sampler_point_wrap, uv, 0).rgb; - } - - OUT.albedo *= color_mod.rgb; - OUT.emissive *= color_mod.rgb; + // Get object to world space transform (instance transform) and make 3x3 matrix + float4x4 to_world = OUT.instance_data.object_to_world; + float3x3 to_world_no_translate = float3x3(to_world[0].xyz, to_world[1].xyz, to_world[2].xyz); // ------------------------------------------------------------------------------------- // Determine gbuffer normal value @@ -129,6 +107,36 @@ void GetGeometryDataFromPrimaryRay(RayDesc ray_desc, PrimaryRayPayload ray_paylo float3 interpolated_normal = GetHitAttribute(normals, ray_payload.barycentrics); float3 normal = interpolated_normal; + // ------------------------------------------------------------------------------------- + // Compute texture gradients using ray cones to sample textures anisotropically + + float3 triangle_pos_world[3] = { OUT.hit_triangle.pos0, OUT.hit_triangle.pos1, OUT.hit_triangle.pos2 }; + float3 interpolated_pos_world = GetHitAttribute(triangle_pos_world, ray_payload.barycentrics); + interpolated_pos_world = mul(to_world, float4(interpolated_pos_world, 1)).xyz; + triangle_pos_world[0] = mul(to_world, float4(triangle_pos_world[0], 1)).xyz; + triangle_pos_world[1] = mul(to_world, float4(triangle_pos_world[1], 1)).xyz; + triangle_pos_world[2] = mul(to_world, float4(triangle_pos_world[2], 1)).xyz; + + float3 interpolated_normal_world = normalize(mul(to_world_no_translate, interpolated_normal)); + + float2 triangle_uv[3] = { OUT.hit_triangle.uv0, OUT.hit_triangle.uv1, OUT.hit_triangle.uv2 }; + float half_cone_angle = 0; + + if (recursion_depth == 0) + { + RayDesc ray_desc_x = GetRayDesc(DispatchRaysIndex().xy + uint2(1, 0), DispatchRaysDimensions().xy); + RayDesc ray_desc_y = GetRayDesc(DispatchRaysIndex().xy + uint2(0, 1), DispatchRaysDimensions().xy); + half_cone_angle = sqrt(1.0 - square(min(dot(ray_desc.Direction, ray_desc_x.Direction), dot(ray_desc.Direction, ray_desc_y.Direction)))); + } + else + { + half_cone_angle = ray_payload.hit_distance * tweak.secondary_bounce_bias + img_roughness[DispatchRaysIndex().xy].r * tweak.secondary_bounce_bias; + } + + float2 tex_gradient1, tex_gradient2; + ComputeTextureGradientRayCone(ray_desc.Direction, ray_payload.hit_distance * half_cone_angle, ray_payload.barycentrics, + interpolated_pos_world, interpolated_normal_world, triangle_pos_world, triangle_uv, tex_gradient1, tex_gradient2); + // Calculate normal from normal map if (tweak.enable_normal_maps) { @@ -142,25 +150,23 @@ void GetGeometryDataFromPrimaryRay(RayDesc ray_desc, PrimaryRayPayload ray_paylo // Bring the normal map sample from tangent space to world space float3x3 TBN = transpose(float3x3(tangent.xyz, bitangent, interpolated_normal)); - float3 sampled_normal; - if (tweak.normal_sample_linear) - { - sampled_normal = tex_normal.SampleLevel(g_sampler_linear_wrap, uv, 0).xyz; - } - else - { - sampled_normal = tex_normal.SampleLevel(g_sampler_point_wrap, uv, 0).xyz; - } + float3 sampled_normal; + if (tweak.normal_sample_linear) + { + sampled_normal = SampleTextureAnisotropic(tex_normal, g_sampler_linear_wrap, tex_gradient1, tex_gradient2, uv).xyz; + //sampled_normal = tex_normal.SampleLevel(g_sampler_linear_wrap, uv, 0).xyz; + } + else + { + sampled_normal = SampleTextureAnisotropic(tex_normal, g_sampler_point_wrap, tex_gradient1, tex_gradient2, uv).xyz; + //sampled_normal = tex_normal.SampleLevel(g_sampler_point_wrap, uv, 0).xyz; + } sampled_normal = 2.0 * sampled_normal - 1.0; sampled_normal = normalize(mul(TBN, sampled_normal)); normal = sampled_normal; } - // Get object to world space transform (instance transform) and make 3x3 matrix - float4x4 to_world = OUT.instance_data.object_to_world; - float3x3 to_world_no_translate = float3x3(to_world[0].xyz, to_world[1].xyz, to_world[2].xyz); - // Transform normal to world space normal = normalize(mul(to_world_no_translate, normal)); @@ -194,13 +200,17 @@ void GetGeometryDataFromPrimaryRay(RayDesc ray_desc, PrimaryRayPayload ray_paylo float sampled_roughness; if (tweak.metallic_roughness_sample_linear) { - sampled_metalness = tex_metalness.SampleLevel(g_sampler_linear_wrap, uv, 0).r; - sampled_roughness = tex_roughness.SampleLevel(g_sampler_linear_wrap, uv, 0).r; + sampled_metalness = SampleTextureAnisotropic(tex_metalness, g_sampler_linear_wrap, tex_gradient1, tex_gradient2, uv).r; + sampled_roughness = SampleTextureAnisotropic(tex_roughness, g_sampler_linear_wrap, tex_gradient1, tex_gradient2, uv).r; + //sampled_metalness = tex_metalness.SampleLevel(g_sampler_linear_wrap, uv, 0).r; + //sampled_roughness = tex_roughness.SampleLevel(g_sampler_linear_wrap, uv, 0).r; } else { - sampled_metalness = tex_metalness.SampleLevel(g_sampler_point_wrap, uv, 0).r; - sampled_roughness = tex_roughness.SampleLevel(g_sampler_point_wrap, uv, 0).r; + sampled_metalness = SampleTextureAnisotropic(tex_metalness, g_sampler_point_wrap, tex_gradient1, tex_gradient2, uv).r; + sampled_roughness = SampleTextureAnisotropic(tex_roughness, g_sampler_point_wrap, tex_gradient1, tex_gradient2, uv).r; + //sampled_metalness = tex_metalness.SampleLevel(g_sampler_point_wrap, uv, 0).r; + //sampled_roughness = tex_roughness.SampleLevel(g_sampler_point_wrap, uv, 0).r; } OUT.metallic = sampled_metalness*hit_material.metalness_factor; OUT.roughness = clamp(sampled_roughness*hit_material.roughness_factor, 0.02f, 1.0f); @@ -218,6 +228,38 @@ void GetGeometryDataFromPrimaryRay(RayDesc ray_desc, PrimaryRayPayload ray_paylo { OUT.roughness = 1.0; // max(lerp(0.5, 0.2, metallic_roughness.y), metallic_roughness.y); } + + // ------------------------------------------------------------------------------------- + // Determine gbuffer albedo value + + if (tweak.albedo_sample_linear) + { + OUT.albedo = SampleTextureAnisotropic(tex_albedo, g_sampler_linear_wrap, tex_gradient1, tex_gradient2, uv).rgb; + //OUT.albedo = tex_albedo.SampleLevel(g_sampler_linear_wrap, uv, 0).xyz; + } + else + { + OUT.albedo = SampleTextureAnisotropic(tex_albedo, g_sampler_point_wrap, tex_gradient1, tex_gradient2, uv).rgb; + //OUT.albedo = tex_albedo.SampleLevel(g_sampler_point_wrap, uv, 0).xyz; + } + + // ----------------------------------------------------------- + // Emissive + + if (tweak.albedo_sample_linear) + { + OUT.emissive = SampleTextureAnisotropic(tex_emissive, g_sampler_linear_wrap, tex_gradient1, tex_gradient2, uv).rgb; + //OUT.emissive = emissive_factor * tex_emissive.SampleLevel(g_sampler_linear_wrap, uv, 0).rgb; + } + else + { + OUT.emissive = SampleTextureAnisotropic(tex_emissive, g_sampler_point_wrap, tex_gradient1, tex_gradient2, uv).rgb; + //OUT.emissive = emissive_factor * tex_emissive.SampleLevel(g_sampler_point_wrap, uv, 0).rgb; + } + + OUT.albedo *= color_mod.rgb; + OUT.emissive *= color_mod.rgb; + OUT.emissive *= emissive_factor; } } } diff --git a/RT/Renderer/Backend/DX12/assets/shaders/raster_blit.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/raster_blit.hlsl new file mode 100644 index 0000000..d8b7d38 --- /dev/null +++ b/RT/Renderer/Backend/DX12/assets/shaders/raster_blit.hlsl @@ -0,0 +1,72 @@ +// Since DirectX 12 does not have a vkCmdBlitImage equivalent, +// we have to make do with a quad-based blit technique +// ------------------------------------------------------ +// Vertex shader + +struct Vertex +{ + float2 pos; + float2 uv; +}; + +static Vertex g_quad_verts[6] = { + { float2(-1.0f, 1.0f), float2(0.0f, 0.0f) }, + { float2(1.0f, 1.0f), float2(1.0f, 0.0f) }, + { float2(1.0f, -1.0f), float2(1.0f, 1.0f) }, + { float2(-1.0f, 1.0f), float2(0.0f, 0.0f) }, + { float2(1.0f, -1.0f), float2(1.0f, 1.0f) }, + { float2(-1.0f, -1.0f), float2(0.0f, 1.0f) } +}; + +struct Constants +{ + uint blit_x; + uint blit_y; + uint blit_width; + uint blit_height; + uint blit_blend; +}; + +ConstantBuffer g_constants : register(b0); + +struct VertexShaderOutput +{ + float4 position : SV_POSITION; + float2 uv : TEX_COORDS; +}; + +VertexShaderOutput VertexShaderEntry(uint vertex_id : SV_VertexID) +{ + VertexShaderOutput OUT; + OUT.position = float4(g_quad_verts[vertex_id].pos, 0.0f, 1.0f); + OUT.uv = g_quad_verts[vertex_id].uv; + OUT.position.x *= (float)g_constants.blit_width / (float)g_constants.blit_height; + return OUT; +} + +// ------------------------------------------------------ +// Pixel shader + +#define BLIT_BLEND_INNER 0.5 +#define BLIT_BLEND_OUTER 1.0 +#define BLIT_BLEND_STRENGTH 1.0 +// Shape will make the blend form more circular with higher values (vignette) +#define BLIT_BLEND_SHAPE 0.5 + +Texture2D g_source_texture : register(t0); +SamplerState g_sampler : register(s0); + +float4 PixelShaderEntry(VertexShaderOutput IN) : SV_Target +{ + float blend_factor = 0.0; + if (g_constants.blit_blend) + { + float2 uv = (IN.position.xy - float2(g_constants.blit_x, g_constants.blit_y)) / float2(g_constants.blit_width, g_constants.blit_height); + float2 blend_curve = pow(abs(uv * 2.0 - 1.0), float2(1.0 / BLIT_BLEND_SHAPE, 1.0 / BLIT_BLEND_SHAPE)); + float blend_edge = pow(length(blend_curve), BLIT_BLEND_SHAPE); + blend_factor = 1.0 - BLIT_BLEND_STRENGTH * smoothstep(BLIT_BLEND_INNER, BLIT_BLEND_OUTER, blend_edge); + } + + float4 sampled_color = g_source_texture.SampleLevel(g_sampler, IN.uv, 0); + return float4(sampled_color.xyz, blend_factor); +} diff --git a/RT/Renderer/Backend/DX12/assets/shaders/raster_tri.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/raster_tri.hlsl index 9ead7c9..de0eed5 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/raster_tri.hlsl +++ b/RT/Renderer/Backend/DX12/assets/shaders/raster_tri.hlsl @@ -35,6 +35,11 @@ VertexShaderOutput VertexShaderEntry(VertexInput IN) Texture2D g_bindless_srvs[] : register(t0); SamplerState g_sampler : register(s0); +float3 ConvertToLinear(float3 x) +{ + return select(x < 0.04045f, x / 12.92, pow((x + 0.055) / 1.055, 2.4)); +} + float4 PixelShaderEntry(VertexShaderOutput IN) : SV_Target { float4 sampled_color = g_bindless_srvs[NonUniformResourceIndex(IN.TextureIndex)].SampleLevel(g_sampler, IN.TexCoord, 0); diff --git a/RT/Renderer/Backend/DX12/assets/shaders/resolve_final_color.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/resolve_final_color.hlsl index 9da463b..8a2fa47 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/resolve_final_color.hlsl +++ b/RT/Renderer/Backend/DX12/assets/shaders/resolve_final_color.hlsl @@ -24,6 +24,7 @@ void Preload(uint2 shared_pos, uint2 global_pos) void ResolveFinalColorCS(COMPUTE_ARGS) { PRELOAD_INTO_SHARED + EARLY_OUT float3 color = shared_color[thread_pos.y + BORDER][thread_pos.x + BORDER]; @@ -60,5 +61,5 @@ void ResolveFinalColorCS(COMPUTE_ARGS) dither_noise = dither_noise.rgb - dither_noise.gbr; color += dither_noise / 255.0; - img_color_final[pixel_pos] = float4(color, 1); + img_scene[pixel_pos] = float4(color, 1); } diff --git a/RT/Renderer/Backend/DX12/assets/shaders/taa.hlsl b/RT/Renderer/Backend/DX12/assets/shaders/taa.hlsl index b19541e..025411a 100644 --- a/RT/Renderer/Backend/DX12/assets/shaders/taa.hlsl +++ b/RT/Renderer/Backend/DX12/assets/shaders/taa.hlsl @@ -33,9 +33,9 @@ groupshared float2 shared_motion[SHARED_Y][SHARED_X]; void Preload(uint2 shared_pos, uint2 global_pos) { - shared_depth [shared_pos.y][shared_pos.x] = img_depth [global_pos].x; - shared_color [shared_pos.y][shared_pos.x] = img_color [global_pos].rgb; - shared_motion[shared_pos.y][shared_pos.x] = img_motion [global_pos].xy; + shared_depth [shared_pos.y][shared_pos.x] = img_depth [global_pos].x; + shared_color [shared_pos.y][shared_pos.x] = img_color [global_pos].rgb; + shared_motion[shared_pos.y][shared_pos.x] = img_motion[global_pos].xy; } [numthreads(GROUP_X, GROUP_Y, 1)] @@ -48,6 +48,8 @@ void TemporalAntiAliasingCS(COMPUTE_ARGS) //------------------------------------------------------------------------ + EARLY_OUT + float2 dim = g_global_cb.render_dim; float3 neighborhood_min = LARGE_NUMBER; diff --git a/RT/Renderer/Backend/DX12/cimgui/imgui/examples/example_win32_directx12/build_win32.bat b/RT/Renderer/Backend/DX12/cimgui/imgui/examples/example_win32_directx12/build_win32.bat index 48dadb2..198e6e5 100644 --- a/RT/Renderer/Backend/DX12/cimgui/imgui/examples/example_win32_directx12/build_win32.bat +++ b/RT/Renderer/Backend/DX12/cimgui/imgui/examples/example_win32_directx12/build_win32.bat @@ -1,9 +1,9 @@ -@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. -@REM Important: to build on 32-bit systems, the DX12 backends needs '#define ImTextureID ImU64', so we pass it here. -@set OUT_DIR=Debug -@set OUT_EXE=example_win32_directx12 -@set INCLUDES=/I..\.. /I..\..\backends /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" -@set SOURCES=main.cpp ..\..\backends\imgui_impl_dx12.cpp ..\..\backends\imgui_impl_win32.cpp ..\..\imgui*.cpp -@set LIBS=d3d12.lib d3dcompiler.lib dxgi.lib -mkdir Debug -cl /nologo /Zi /MD %INCLUDES% /D ImTextureID=ImU64 /D UNICODE /D _UNICODE %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +@REM Important: to build on 32-bit systems, the DX12 backends needs '#define ImTextureID ImU64', so we pass it here. +@set OUT_DIR=Debug +@set OUT_EXE=example_win32_directx12 +@set INCLUDES=/I..\.. /I..\..\backends /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" +@set SOURCES=main.cpp ..\..\backends\imgui_impl_dx12.cpp ..\..\backends\imgui_impl_win32.cpp ..\..\imgui*.cpp +@set LIBS=d3d12.lib d3dcompiler.lib dxgi.lib +mkdir Debug +cl /nologo /Zi /MD %INCLUDES% /D ImTextureID=ImU64 /D UNICODE /D _UNICODE %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% diff --git a/RT/Renderer/Backend/DX12/cimgui/imgui/examples/example_win32_directx12/main.cpp b/RT/Renderer/Backend/DX12/cimgui/imgui/examples/example_win32_directx12/main.cpp index 029b1f9..2bdf760 100644 --- a/RT/Renderer/Backend/DX12/cimgui/imgui/examples/example_win32_directx12/main.cpp +++ b/RT/Renderer/Backend/DX12/cimgui/imgui/examples/example_win32_directx12/main.cpp @@ -1,485 +1,485 @@ -// Dear ImGui: standalone example application for DirectX 12 -// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. -// Read online: https://github.com/ocornut/imgui/tree/master/docs - -// Important: to compile on 32-bit systems, the DirectX12 backend requires code to be compiled with '#define ImTextureID ImU64'. -// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*. -// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file. - -#include "imgui.h" -#include "imgui_impl_win32.h" -#include "imgui_impl_dx12.h" -#include -#include -#include - -#ifdef _DEBUG -#define DX12_ENABLE_DEBUG_LAYER -#endif - -#ifdef DX12_ENABLE_DEBUG_LAYER -#include -#pragma comment(lib, "dxguid.lib") -#endif - -struct FrameContext -{ - ID3D12CommandAllocator* CommandAllocator; - UINT64 FenceValue; -}; - -// Data -static int const NUM_FRAMES_IN_FLIGHT = 3; -static FrameContext g_frameContext[NUM_FRAMES_IN_FLIGHT] = {}; -static UINT g_frameIndex = 0; - -static int const NUM_BACK_BUFFERS = 3; -static ID3D12Device* g_pd3dDevice = NULL; -static ID3D12DescriptorHeap* g_pd3dRtvDescHeap = NULL; -static ID3D12DescriptorHeap* g_pd3dSrvDescHeap = NULL; -static ID3D12CommandQueue* g_pd3dCommandQueue = NULL; -static ID3D12GraphicsCommandList* g_pd3dCommandList = NULL; -static ID3D12Fence* g_fence = NULL; -static HANDLE g_fenceEvent = NULL; -static UINT64 g_fenceLastSignaledValue = 0; -static IDXGISwapChain3* g_pSwapChain = NULL; -static HANDLE g_hSwapChainWaitableObject = NULL; -static ID3D12Resource* g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {}; -static D3D12_CPU_DESCRIPTOR_HANDLE g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = {}; - -// Forward declarations of helper functions -bool CreateDeviceD3D(HWND hWnd); -void CleanupDeviceD3D(); -void CreateRenderTarget(); -void CleanupRenderTarget(); -void WaitForLastSubmittedFrame(); -FrameContext* WaitForNextFrameResources(); -LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - -// Main code -int main(int, char**) -{ - // Create application window - //ImGui_ImplWin32_EnableDpiAwareness(); - WNDCLASSEXW wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"ImGui Example", NULL }; - ::RegisterClassExW(&wc); - HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui DirectX12 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL); - - // Initialize Direct3D - if (!CreateDeviceD3D(hwnd)) - { - CleanupDeviceD3D(); - ::UnregisterClassW(wc.lpszClassName, wc.hInstance); - return 1; - } - - // Show the window - ::ShowWindow(hwnd, SW_SHOWDEFAULT); - ::UpdateWindow(hwnd); - - // Setup Dear ImGui context - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); (void)io; - io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking - io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows - //io.ConfigViewportsNoAutoMerge = true; - //io.ConfigViewportsNoTaskBarIcon = true; - - // Setup Dear ImGui style - ImGui::StyleColorsDark(); - //ImGui::StyleColorsLight(); - - // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones. - ImGuiStyle& style = ImGui::GetStyle(); - if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) - { - style.WindowRounding = 0.0f; - style.Colors[ImGuiCol_WindowBg].w = 1.0f; - } - - // Setup Platform/Renderer backends - ImGui_ImplWin32_Init(hwnd); - ImGui_ImplDX12_Init(g_pd3dDevice, NUM_FRAMES_IN_FLIGHT, - DXGI_FORMAT_R8G8B8A8_UNORM, g_pd3dSrvDescHeap, - g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(), - g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart()); - - // Load Fonts - // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. - // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. - // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). - // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. - // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering. - // - Read 'docs/FONTS.md' for more instructions and details. - // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f); - //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); - //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); - //IM_ASSERT(font != NULL); - - // Our state - bool show_demo_window = true; - bool show_another_window = false; - ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); - - // Main loop - bool done = false; - while (!done) - { - // Poll and handle messages (inputs, window resize, etc.) - // See the WndProc() function below for our to dispatch events to the Win32 backend. - MSG msg; - while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) - { - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - if (msg.message == WM_QUIT) - done = true; - } - if (done) - break; - - // Start the Dear ImGui frame - ImGui_ImplDX12_NewFrame(); - ImGui_ImplWin32_NewFrame(); - ImGui::NewFrame(); - - // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). - if (show_demo_window) - ImGui::ShowDemoWindow(&show_demo_window); - - // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window. - { - static float f = 0.0f; - static int counter = 0; - - ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. - - ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) - ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state - ImGui::Checkbox("Another Window", &show_another_window); - - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color - - if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) - counter++; - ImGui::SameLine(); - ImGui::Text("counter = %d", counter); - - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); - ImGui::End(); - } - - // 3. Show another simple window. - if (show_another_window) - { - ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) - ImGui::Text("Hello from another window!"); - if (ImGui::Button("Close Me")) - show_another_window = false; - ImGui::End(); - } - - // Rendering - ImGui::Render(); - - FrameContext* frameCtx = WaitForNextFrameResources(); - UINT backBufferIdx = g_pSwapChain->GetCurrentBackBufferIndex(); - frameCtx->CommandAllocator->Reset(); - - D3D12_RESOURCE_BARRIER barrier = {}; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barrier.Transition.pResource = g_mainRenderTargetResource[backBufferIdx]; - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; - g_pd3dCommandList->Reset(frameCtx->CommandAllocator, NULL); - g_pd3dCommandList->ResourceBarrier(1, &barrier); - - // Render Dear ImGui graphics - const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w }; - g_pd3dCommandList->ClearRenderTargetView(g_mainRenderTargetDescriptor[backBufferIdx], clear_color_with_alpha, 0, NULL); - g_pd3dCommandList->OMSetRenderTargets(1, &g_mainRenderTargetDescriptor[backBufferIdx], FALSE, NULL); - g_pd3dCommandList->SetDescriptorHeaps(1, &g_pd3dSrvDescHeap); - ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), g_pd3dCommandList); - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; - g_pd3dCommandList->ResourceBarrier(1, &barrier); - g_pd3dCommandList->Close(); - - g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&g_pd3dCommandList); - - // Update and Render additional Platform Windows - if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) - { - ImGui::UpdatePlatformWindows(); - ImGui::RenderPlatformWindowsDefault(NULL, (void*)g_pd3dCommandList); - } - - g_pSwapChain->Present(1, 0); // Present with vsync - //g_pSwapChain->Present(0, 0); // Present without vsync - - UINT64 fenceValue = g_fenceLastSignaledValue + 1; - g_pd3dCommandQueue->Signal(g_fence, fenceValue); - g_fenceLastSignaledValue = fenceValue; - frameCtx->FenceValue = fenceValue; - } - - WaitForLastSubmittedFrame(); - - // Cleanup - ImGui_ImplDX12_Shutdown(); - ImGui_ImplWin32_Shutdown(); - ImGui::DestroyContext(); - - CleanupDeviceD3D(); - ::DestroyWindow(hwnd); - ::UnregisterClassW(wc.lpszClassName, wc.hInstance); - - return 0; -} - -// Helper functions - -bool CreateDeviceD3D(HWND hWnd) -{ - // Setup swap chain - DXGI_SWAP_CHAIN_DESC1 sd; - { - ZeroMemory(&sd, sizeof(sd)); - sd.BufferCount = NUM_BACK_BUFFERS; - sd.Width = 0; - sd.Height = 0; - sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - sd.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; - sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - sd.SampleDesc.Count = 1; - sd.SampleDesc.Quality = 0; - sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - sd.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; - sd.Scaling = DXGI_SCALING_STRETCH; - sd.Stereo = FALSE; - } - - // [DEBUG] Enable debug interface -#ifdef DX12_ENABLE_DEBUG_LAYER - ID3D12Debug* pdx12Debug = NULL; - if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&pdx12Debug)))) - pdx12Debug->EnableDebugLayer(); -#endif - - // Create device - D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0; - if (D3D12CreateDevice(NULL, featureLevel, IID_PPV_ARGS(&g_pd3dDevice)) != S_OK) - return false; - - // [DEBUG] Setup debug interface to break on any warnings/errors -#ifdef DX12_ENABLE_DEBUG_LAYER - if (pdx12Debug != NULL) - { - ID3D12InfoQueue* pInfoQueue = NULL; - g_pd3dDevice->QueryInterface(IID_PPV_ARGS(&pInfoQueue)); - pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); - pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true); - pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, true); - pInfoQueue->Release(); - pdx12Debug->Release(); - } -#endif - - { - D3D12_DESCRIPTOR_HEAP_DESC desc = {}; - desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - desc.NumDescriptors = NUM_BACK_BUFFERS; - desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - desc.NodeMask = 1; - if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dRtvDescHeap)) != S_OK) - return false; - - SIZE_T rtvDescriptorSize = g_pd3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = g_pd3dRtvDescHeap->GetCPUDescriptorHandleForHeapStart(); - for (UINT i = 0; i < NUM_BACK_BUFFERS; i++) - { - g_mainRenderTargetDescriptor[i] = rtvHandle; - rtvHandle.ptr += rtvDescriptorSize; - } - } - - { - D3D12_DESCRIPTOR_HEAP_DESC desc = {}; - desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - desc.NumDescriptors = 1; - desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dSrvDescHeap)) != S_OK) - return false; - } - - { - D3D12_COMMAND_QUEUE_DESC desc = {}; - desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; - desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; - desc.NodeMask = 1; - if (g_pd3dDevice->CreateCommandQueue(&desc, IID_PPV_ARGS(&g_pd3dCommandQueue)) != S_OK) - return false; - } - - for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++) - if (g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&g_frameContext[i].CommandAllocator)) != S_OK) - return false; - - if (g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, g_frameContext[0].CommandAllocator, NULL, IID_PPV_ARGS(&g_pd3dCommandList)) != S_OK || - g_pd3dCommandList->Close() != S_OK) - return false; - - if (g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&g_fence)) != S_OK) - return false; - - g_fenceEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if (g_fenceEvent == NULL) - return false; - - { - IDXGIFactory4* dxgiFactory = NULL; - IDXGISwapChain1* swapChain1 = NULL; - if (CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)) != S_OK) - return false; - if (dxgiFactory->CreateSwapChainForHwnd(g_pd3dCommandQueue, hWnd, &sd, NULL, NULL, &swapChain1) != S_OK) - return false; - if (swapChain1->QueryInterface(IID_PPV_ARGS(&g_pSwapChain)) != S_OK) - return false; - swapChain1->Release(); - dxgiFactory->Release(); - g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS); - g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject(); - } - - CreateRenderTarget(); - return true; -} - -void CleanupDeviceD3D() -{ - CleanupRenderTarget(); - if (g_pSwapChain) { g_pSwapChain->SetFullscreenState(false, NULL); g_pSwapChain->Release(); g_pSwapChain = NULL; } - if (g_hSwapChainWaitableObject != NULL) { CloseHandle(g_hSwapChainWaitableObject); } - for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++) - if (g_frameContext[i].CommandAllocator) { g_frameContext[i].CommandAllocator->Release(); g_frameContext[i].CommandAllocator = NULL; } - if (g_pd3dCommandQueue) { g_pd3dCommandQueue->Release(); g_pd3dCommandQueue = NULL; } - if (g_pd3dCommandList) { g_pd3dCommandList->Release(); g_pd3dCommandList = NULL; } - if (g_pd3dRtvDescHeap) { g_pd3dRtvDescHeap->Release(); g_pd3dRtvDescHeap = NULL; } - if (g_pd3dSrvDescHeap) { g_pd3dSrvDescHeap->Release(); g_pd3dSrvDescHeap = NULL; } - if (g_fence) { g_fence->Release(); g_fence = NULL; } - if (g_fenceEvent) { CloseHandle(g_fenceEvent); g_fenceEvent = NULL; } - if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } - -#ifdef DX12_ENABLE_DEBUG_LAYER - IDXGIDebug1* pDebug = NULL; - if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&pDebug)))) - { - pDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_SUMMARY); - pDebug->Release(); - } -#endif -} - -void CreateRenderTarget() -{ - for (UINT i = 0; i < NUM_BACK_BUFFERS; i++) - { - ID3D12Resource* pBackBuffer = NULL; - g_pSwapChain->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer)); - g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, g_mainRenderTargetDescriptor[i]); - g_mainRenderTargetResource[i] = pBackBuffer; - } -} - -void CleanupRenderTarget() -{ - WaitForLastSubmittedFrame(); - - for (UINT i = 0; i < NUM_BACK_BUFFERS; i++) - if (g_mainRenderTargetResource[i]) { g_mainRenderTargetResource[i]->Release(); g_mainRenderTargetResource[i] = NULL; } -} - -void WaitForLastSubmittedFrame() -{ - FrameContext* frameCtx = &g_frameContext[g_frameIndex % NUM_FRAMES_IN_FLIGHT]; - - UINT64 fenceValue = frameCtx->FenceValue; - if (fenceValue == 0) - return; // No fence was signaled - - frameCtx->FenceValue = 0; - if (g_fence->GetCompletedValue() >= fenceValue) - return; - - g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent); - WaitForSingleObject(g_fenceEvent, INFINITE); -} - -FrameContext* WaitForNextFrameResources() -{ - UINT nextFrameIndex = g_frameIndex + 1; - g_frameIndex = nextFrameIndex; - - HANDLE waitableObjects[] = { g_hSwapChainWaitableObject, NULL }; - DWORD numWaitableObjects = 1; - - FrameContext* frameCtx = &g_frameContext[nextFrameIndex % NUM_FRAMES_IN_FLIGHT]; - UINT64 fenceValue = frameCtx->FenceValue; - if (fenceValue != 0) // means no fence was signaled - { - frameCtx->FenceValue = 0; - g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent); - waitableObjects[1] = g_fenceEvent; - numWaitableObjects = 2; - } - - WaitForMultipleObjects(numWaitableObjects, waitableObjects, TRUE, INFINITE); - - return frameCtx; -} - -// Forward declare message handler from imgui_impl_win32.cpp -extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - -// Win32 message handler -// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. -// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. -// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. -// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. -LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) - return true; - - switch (msg) - { - case WM_SIZE: - if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED) - { - WaitForLastSubmittedFrame(); - CleanupRenderTarget(); - HRESULT result = g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT); - assert(SUCCEEDED(result) && "Failed to resize swapchain."); - CreateRenderTarget(); - } - return 0; - case WM_SYSCOMMAND: - if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu - return 0; - break; - case WM_DESTROY: - ::PostQuitMessage(0); - return 0; - } - return ::DefWindowProc(hWnd, msg, wParam, lParam); -} +// Dear ImGui: standalone example application for DirectX 12 +// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. +// Read online: https://github.com/ocornut/imgui/tree/master/docs + +// Important: to compile on 32-bit systems, the DirectX12 backend requires code to be compiled with '#define ImTextureID ImU64'. +// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*. +// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file. + +#include "imgui.h" +#include "imgui_impl_win32.h" +#include "imgui_impl_dx12.h" +#include +#include +#include + +#ifdef _DEBUG +#define DX12_ENABLE_DEBUG_LAYER +#endif + +#ifdef DX12_ENABLE_DEBUG_LAYER +#include +#pragma comment(lib, "dxguid.lib") +#endif + +struct FrameContext +{ + ID3D12CommandAllocator* CommandAllocator; + UINT64 FenceValue; +}; + +// Data +static int const NUM_FRAMES_IN_FLIGHT = 3; +static FrameContext g_frameContext[NUM_FRAMES_IN_FLIGHT] = {}; +static UINT g_frameIndex = 0; + +static int const NUM_BACK_BUFFERS = 3; +static ID3D12Device* g_pd3dDevice = NULL; +static ID3D12DescriptorHeap* g_pd3dRtvDescHeap = NULL; +static ID3D12DescriptorHeap* g_pd3dSrvDescHeap = NULL; +static ID3D12CommandQueue* g_pd3dCommandQueue = NULL; +static ID3D12GraphicsCommandList* g_pd3dCommandList = NULL; +static ID3D12Fence* g_fence = NULL; +static HANDLE g_fenceEvent = NULL; +static UINT64 g_fenceLastSignaledValue = 0; +static IDXGISwapChain3* g_pSwapChain = NULL; +static HANDLE g_hSwapChainWaitableObject = NULL; +static ID3D12Resource* g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {}; +static D3D12_CPU_DESCRIPTOR_HANDLE g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = {}; + +// Forward declarations of helper functions +bool CreateDeviceD3D(HWND hWnd); +void CleanupDeviceD3D(); +void CreateRenderTarget(); +void CleanupRenderTarget(); +void WaitForLastSubmittedFrame(); +FrameContext* WaitForNextFrameResources(); +LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +// Main code +int main(int, char**) +{ + // Create application window + //ImGui_ImplWin32_EnableDpiAwareness(); + WNDCLASSEXW wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"ImGui Example", NULL }; + ::RegisterClassExW(&wc); + HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui DirectX12 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL); + + // Initialize Direct3D + if (!CreateDeviceD3D(hwnd)) + { + CleanupDeviceD3D(); + ::UnregisterClassW(wc.lpszClassName, wc.hInstance); + return 1; + } + + // Show the window + ::ShowWindow(hwnd, SW_SHOWDEFAULT); + ::UpdateWindow(hwnd); + + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking + io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows + //io.ConfigViewportsNoAutoMerge = true; + //io.ConfigViewportsNoTaskBarIcon = true; + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsLight(); + + // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones. + ImGuiStyle& style = ImGui::GetStyle(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + style.WindowRounding = 0.0f; + style.Colors[ImGuiCol_WindowBg].w = 1.0f; + } + + // Setup Platform/Renderer backends + ImGui_ImplWin32_Init(hwnd); + ImGui_ImplDX12_Init(g_pd3dDevice, NUM_FRAMES_IN_FLIGHT, + DXGI_FORMAT_R8G8B8A8_UNORM, g_pd3dSrvDescHeap, + g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(), + g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart()); + + // Load Fonts + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering. + // - Read 'docs/FONTS.md' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); + + // Our state + bool show_demo_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + // Main loop + bool done = false; + while (!done) + { + // Poll and handle messages (inputs, window resize, etc.) + // See the WndProc() function below for our to dispatch events to the Win32 backend. + MSG msg; + while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) + { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + if (msg.message == WM_QUIT) + done = true; + } + if (done) + break; + + // Start the Dear ImGui frame + ImGui_ImplDX12_NewFrame(); + ImGui_ImplWin32_NewFrame(); + ImGui::NewFrame(); + + // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + + // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window. + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + + ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + ImGui::End(); + } + + // 3. Show another simple window. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // Rendering + ImGui::Render(); + + FrameContext* frameCtx = WaitForNextFrameResources(); + UINT backBufferIdx = g_pSwapChain->GetCurrentBackBufferIndex(); + frameCtx->CommandAllocator->Reset(); + + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier.Transition.pResource = g_mainRenderTargetResource[backBufferIdx]; + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; + g_pd3dCommandList->Reset(frameCtx->CommandAllocator, NULL); + g_pd3dCommandList->ResourceBarrier(1, &barrier); + + // Render Dear ImGui graphics + const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w }; + g_pd3dCommandList->ClearRenderTargetView(g_mainRenderTargetDescriptor[backBufferIdx], clear_color_with_alpha, 0, NULL); + g_pd3dCommandList->OMSetRenderTargets(1, &g_mainRenderTargetDescriptor[backBufferIdx], FALSE, NULL); + g_pd3dCommandList->SetDescriptorHeaps(1, &g_pd3dSrvDescHeap); + ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), g_pd3dCommandList); + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; + g_pd3dCommandList->ResourceBarrier(1, &barrier); + g_pd3dCommandList->Close(); + + g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&g_pd3dCommandList); + + // Update and Render additional Platform Windows + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(NULL, (void*)g_pd3dCommandList); + } + + g_pSwapChain->Present(1, 0); // Present with vsync + //g_pSwapChain->Present(0, 0); // Present without vsync + + UINT64 fenceValue = g_fenceLastSignaledValue + 1; + g_pd3dCommandQueue->Signal(g_fence, fenceValue); + g_fenceLastSignaledValue = fenceValue; + frameCtx->FenceValue = fenceValue; + } + + WaitForLastSubmittedFrame(); + + // Cleanup + ImGui_ImplDX12_Shutdown(); + ImGui_ImplWin32_Shutdown(); + ImGui::DestroyContext(); + + CleanupDeviceD3D(); + ::DestroyWindow(hwnd); + ::UnregisterClassW(wc.lpszClassName, wc.hInstance); + + return 0; +} + +// Helper functions + +bool CreateDeviceD3D(HWND hWnd) +{ + // Setup swap chain + DXGI_SWAP_CHAIN_DESC1 sd; + { + ZeroMemory(&sd, sizeof(sd)); + sd.BufferCount = NUM_BACK_BUFFERS; + sd.Width = 0; + sd.Height = 0; + sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.SampleDesc.Count = 1; + sd.SampleDesc.Quality = 0; + sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + sd.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + sd.Scaling = DXGI_SCALING_STRETCH; + sd.Stereo = FALSE; + } + + // [DEBUG] Enable debug interface +#ifdef DX12_ENABLE_DEBUG_LAYER + ID3D12Debug* pdx12Debug = NULL; + if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&pdx12Debug)))) + pdx12Debug->EnableDebugLayer(); +#endif + + // Create device + D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0; + if (D3D12CreateDevice(NULL, featureLevel, IID_PPV_ARGS(&g_pd3dDevice)) != S_OK) + return false; + + // [DEBUG] Setup debug interface to break on any warnings/errors +#ifdef DX12_ENABLE_DEBUG_LAYER + if (pdx12Debug != NULL) + { + ID3D12InfoQueue* pInfoQueue = NULL; + g_pd3dDevice->QueryInterface(IID_PPV_ARGS(&pInfoQueue)); + pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); + pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true); + pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, true); + pInfoQueue->Release(); + pdx12Debug->Release(); + } +#endif + + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + desc.NumDescriptors = NUM_BACK_BUFFERS; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + desc.NodeMask = 1; + if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dRtvDescHeap)) != S_OK) + return false; + + SIZE_T rtvDescriptorSize = g_pd3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = g_pd3dRtvDescHeap->GetCPUDescriptorHandleForHeapStart(); + for (UINT i = 0; i < NUM_BACK_BUFFERS; i++) + { + g_mainRenderTargetDescriptor[i] = rtvHandle; + rtvHandle.ptr += rtvDescriptorSize; + } + } + + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + desc.NumDescriptors = 1; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dSrvDescHeap)) != S_OK) + return false; + } + + { + D3D12_COMMAND_QUEUE_DESC desc = {}; + desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + desc.NodeMask = 1; + if (g_pd3dDevice->CreateCommandQueue(&desc, IID_PPV_ARGS(&g_pd3dCommandQueue)) != S_OK) + return false; + } + + for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++) + if (g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&g_frameContext[i].CommandAllocator)) != S_OK) + return false; + + if (g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, g_frameContext[0].CommandAllocator, NULL, IID_PPV_ARGS(&g_pd3dCommandList)) != S_OK || + g_pd3dCommandList->Close() != S_OK) + return false; + + if (g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&g_fence)) != S_OK) + return false; + + g_fenceEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (g_fenceEvent == NULL) + return false; + + { + IDXGIFactory4* dxgiFactory = NULL; + IDXGISwapChain1* swapChain1 = NULL; + if (CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)) != S_OK) + return false; + if (dxgiFactory->CreateSwapChainForHwnd(g_pd3dCommandQueue, hWnd, &sd, NULL, NULL, &swapChain1) != S_OK) + return false; + if (swapChain1->QueryInterface(IID_PPV_ARGS(&g_pSwapChain)) != S_OK) + return false; + swapChain1->Release(); + dxgiFactory->Release(); + g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS); + g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject(); + } + + CreateRenderTarget(); + return true; +} + +void CleanupDeviceD3D() +{ + CleanupRenderTarget(); + if (g_pSwapChain) { g_pSwapChain->SetFullscreenState(false, NULL); g_pSwapChain->Release(); g_pSwapChain = NULL; } + if (g_hSwapChainWaitableObject != NULL) { CloseHandle(g_hSwapChainWaitableObject); } + for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++) + if (g_frameContext[i].CommandAllocator) { g_frameContext[i].CommandAllocator->Release(); g_frameContext[i].CommandAllocator = NULL; } + if (g_pd3dCommandQueue) { g_pd3dCommandQueue->Release(); g_pd3dCommandQueue = NULL; } + if (g_pd3dCommandList) { g_pd3dCommandList->Release(); g_pd3dCommandList = NULL; } + if (g_pd3dRtvDescHeap) { g_pd3dRtvDescHeap->Release(); g_pd3dRtvDescHeap = NULL; } + if (g_pd3dSrvDescHeap) { g_pd3dSrvDescHeap->Release(); g_pd3dSrvDescHeap = NULL; } + if (g_fence) { g_fence->Release(); g_fence = NULL; } + if (g_fenceEvent) { CloseHandle(g_fenceEvent); g_fenceEvent = NULL; } + if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } + +#ifdef DX12_ENABLE_DEBUG_LAYER + IDXGIDebug1* pDebug = NULL; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&pDebug)))) + { + pDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_SUMMARY); + pDebug->Release(); + } +#endif +} + +void CreateRenderTarget() +{ + for (UINT i = 0; i < NUM_BACK_BUFFERS; i++) + { + ID3D12Resource* pBackBuffer = NULL; + g_pSwapChain->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer)); + g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, g_mainRenderTargetDescriptor[i]); + g_mainRenderTargetResource[i] = pBackBuffer; + } +} + +void CleanupRenderTarget() +{ + WaitForLastSubmittedFrame(); + + for (UINT i = 0; i < NUM_BACK_BUFFERS; i++) + if (g_mainRenderTargetResource[i]) { g_mainRenderTargetResource[i]->Release(); g_mainRenderTargetResource[i] = NULL; } +} + +void WaitForLastSubmittedFrame() +{ + FrameContext* frameCtx = &g_frameContext[g_frameIndex % NUM_FRAMES_IN_FLIGHT]; + + UINT64 fenceValue = frameCtx->FenceValue; + if (fenceValue == 0) + return; // No fence was signaled + + frameCtx->FenceValue = 0; + if (g_fence->GetCompletedValue() >= fenceValue) + return; + + g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent); + WaitForSingleObject(g_fenceEvent, INFINITE); +} + +FrameContext* WaitForNextFrameResources() +{ + UINT nextFrameIndex = g_frameIndex + 1; + g_frameIndex = nextFrameIndex; + + HANDLE waitableObjects[] = { g_hSwapChainWaitableObject, NULL }; + DWORD numWaitableObjects = 1; + + FrameContext* frameCtx = &g_frameContext[nextFrameIndex % NUM_FRAMES_IN_FLIGHT]; + UINT64 fenceValue = frameCtx->FenceValue; + if (fenceValue != 0) // means no fence was signaled + { + frameCtx->FenceValue = 0; + g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent); + waitableObjects[1] = g_fenceEvent; + numWaitableObjects = 2; + } + + WaitForMultipleObjects(numWaitableObjects, waitableObjects, TRUE, INFINITE); + + return frameCtx; +} + +// Forward declare message handler from imgui_impl_win32.cpp +extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +// Win32 message handler +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. +LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) + return true; + + switch (msg) + { + case WM_SIZE: + if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED) + { + WaitForLastSubmittedFrame(); + CleanupRenderTarget(); + HRESULT result = g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT); + assert(SUCCEEDED(result) && "Failed to resize swapchain."); + CreateRenderTarget(); + } + return 0; + case WM_SYSCOMMAND: + if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu + return 0; + break; + case WM_DESTROY: + ::PostQuitMessage(0); + return 0; + } + return ::DefWindowProc(hWnd, msg, wParam, lParam); +} diff --git a/RT/Renderer/Backend/DX12/src/DescriptorArena.cpp b/RT/Renderer/Backend/DX12/src/DescriptorArena.cpp index c1d119c..4052a7e 100644 --- a/RT/Renderer/Backend/DX12/src/DescriptorArena.cpp +++ b/RT/Renderer/Backend/DX12/src/DescriptorArena.cpp @@ -99,13 +99,13 @@ DescriptorAllocation DescriptorArenaFreelist::Allocate(UINT count) DescriptorBlock* previous_freeblock = nullptr; DescriptorBlock* freeblock = m_current_block; - while (m_current_block != nullptr) + while (freeblock != nullptr) { - RT_ASSERT(m_current_block != m_current_block->next); + RT_ASSERT(freeblock != freeblock->next); if (count > freeblock->descriptor_count) { previous_freeblock = freeblock; - freeblock->next = previous_freeblock; + freeblock = freeblock->next; continue; } diff --git a/RT/Renderer/Backend/DX12/src/GLTFLoader.cpp b/RT/Renderer/Backend/DX12/src/GLTFLoader.cpp index 95ef85c..94e8330 100644 --- a/RT/Renderer/Backend/DX12/src/GLTFLoader.cpp +++ b/RT/Renderer/Backend/DX12/src/GLTFLoader.cpp @@ -19,9 +19,8 @@ using namespace RT; // ------------------------------------------------------------------ -static uint16_t running_material_edge_index; -static uint16_t running_material_index_index; static uint16_t running_material_index; +static uint32_t running_image_index; template static T *GetBufferViewPointer(const cgltf_buffer_view *buffer_view) @@ -88,7 +87,7 @@ static int GLTFNodeIndex(const cgltf_data *gltf, const cgltf_node *node) // ------------------------------------------------------------------ -RT_GLTFNode *RT_LoadGLTF(RT_Arena *arena, const char *path) +RT_GLTFNode *RT_LoadGLTF(RT_Arena *arena, const char *path, RT_MaterialOverride* material_override) { MemoryScope temp; @@ -205,7 +204,7 @@ RT_GLTFNode *RT_LoadGLTF(RT_Arena *arena, const char *path) params.width = (uint32_t)w; params.height = (uint32_t)h; params.pixels = (uint32_t *)pixels; - params.name = image->uri; + params.name = image->uri ? image->uri : RT_ArenaPrintF(image_temp, "GLTF Texture #%d", running_image_index++); loaded_images[index]->handle = RT_UploadTexture(¶ms); } @@ -243,76 +242,72 @@ RT_GLTFNode *RT_LoadGLTF(RT_Arena *arena, const char *path) size_t prim_triangle_count = primitive->indices->count / 3; RT_Material material = {}; + uint16_t material_index; - if (primitive->material->pbr_metallic_roughness.base_color_texture.texture) - { - LoadedImage *loaded_image = LoadImage(primitive->material->pbr_metallic_roughness.base_color_texture.texture->image, true, false); - if (loaded_image) + // note(lily): quick ugly hack to make the cockpit no longer cast shadows, but it works so there ya go + if (strcmp(path, "assets/cockpit_prototype.gltf") == 0) { + material.flags |= RT_MaterialFlag_NoCastingShadow; + } + + if (material_override != nullptr && strcmp(primitive->material->name, material_override->name) == 0) { + material_index = material_override->material_index; + } + else { + if (primitive->material->pbr_metallic_roughness.base_color_texture.texture) { - material.albedo_texture = loaded_image->handle; + LoadedImage* loaded_image = LoadImage(primitive->material->pbr_metallic_roughness.base_color_texture.texture->image, true, false); + if (loaded_image) + { + material.albedo_texture = loaded_image->handle; + } } - } - if (primitive->material->normal_texture.texture) - { - LoadedImage *loaded_image = LoadImage(primitive->material->normal_texture.texture->image, false, false); - if (loaded_image) + if (primitive->material->normal_texture.texture) { - material.normal_texture = loaded_image->handle; + LoadedImage* loaded_image = LoadImage(primitive->material->normal_texture.texture->image, false, false); + if (loaded_image) + { + material.normal_texture = loaded_image->handle; + } } - } - if (primitive->material->pbr_metallic_roughness.metallic_roughness_texture.texture) - { - LoadedImage *loaded_image = LoadImage(primitive->material->pbr_metallic_roughness.metallic_roughness_texture.texture->image, false, true); - if (loaded_image) + if (primitive->material->pbr_metallic_roughness.metallic_roughness_texture.texture) { - material.metalness_texture = loaded_image->handle; - material.roughness_texture = loaded_image->handle2; + LoadedImage* loaded_image = LoadImage(primitive->material->pbr_metallic_roughness.metallic_roughness_texture.texture->image, false, true); + if (loaded_image) + { + material.metalness_texture = loaded_image->handle; + material.roughness_texture = loaded_image->handle2; + } } - } - material.metalness = primitive->material->pbr_metallic_roughness.metallic_factor; - material.roughness = primitive->material->pbr_metallic_roughness.roughness_factor; + material.metalness = primitive->material->pbr_metallic_roughness.metallic_factor; + material.roughness = primitive->material->pbr_metallic_roughness.roughness_factor; - if (primitive->material->emissive_texture.texture) - { - LoadedImage *loaded_image = LoadImage(primitive->material->emissive_texture.texture->image, true, false); - if (loaded_image) + if (primitive->material->emissive_texture.texture) { - material.emissive_texture = loaded_image->handle; + LoadedImage* loaded_image = LoadImage(primitive->material->emissive_texture.texture->image, true, false); + if (loaded_image) + { + material.emissive_texture = loaded_image->handle; + } } - } - material.emissive_color = RT_Vec3Make(primitive->material->emissive_factor[0], - primitive->material->emissive_factor[1], - primitive->material->emissive_factor[2]); - material.emissive_strength = 1.0f; - if (primitive->material->has_emissive_strength) - { - material.emissive_strength = primitive->material->emissive_strength.emissive_strength; - } + material.emissive_color = RT_Vec3Make(primitive->material->emissive_factor[0], + primitive->material->emissive_factor[1], + primitive->material->emissive_factor[2]); + material.emissive_strength = 1.0f; + if (primitive->material->has_emissive_strength) + { + material.emissive_strength = primitive->material->emissive_strength.emissive_strength; + } + material_index = RT_UpdateMaterial(RT_EXTRA_BITMAPS_START + running_material_index++, &material); + }; - uint16_t material_index = RT_UpdateMaterial(running_material_index++, &material); RT_ASSERT(material_index != UINT16_MAX); - // TODO(daniel): Fix this situation - // If this show up in a pull request, fire me out of a cannon! - RT_MaterialEdge *g_rt_material_edges = RT_GetMaterialEdgesArray(); - uint16_t *g_rt_material_indices = RT_GetMaterialIndicesArray(); - - uint16_t material_index_index = running_material_index_index++; - - // Store this material index for this material - g_rt_material_indices[material_index_index] = material_index; - - uint16_t material_edge_index = running_material_edge_index++; - - // Store the material edges for this set of triangles - g_rt_material_edges[material_edge_index] = { material_index_index, 0 }; - // All the triangles point into the material edge for (size_t triangle_index = 0; triangle_index < prim_triangle_count; triangle_index++) { - prim_triangles[triangle_index].material_edge_index = material_edge_index; + prim_triangles[triangle_index].material_edge_index = material_index|RT_TRIANGLE_HOLDS_MATERIAL_INDEX; } size_t index_count = primitive->indices->count; diff --git a/RT/Renderer/Backend/DX12/src/GlobalDX.h b/RT/Renderer/Backend/DX12/src/GlobalDX.h index dc88026..a9a5bb6 100644 --- a/RT/Renderer/Backend/DX12/src/GlobalDX.h +++ b/RT/Renderer/Backend/DX12/src/GlobalDX.h @@ -6,9 +6,12 @@ #include "Core/Arena.h" #include "Core/MemoryScope.hpp" #include "Core/SlotMap.hpp" +#include "Core/Config.h" +#include "Core/String.h" #include "Renderer.h" #include "ResourceTracker.hpp" +#include "MeshTracker.hpp" #include "DescriptorArena.hpp" #include "RingBuffer.h" #include "ShaderTable.h" @@ -34,8 +37,9 @@ namespace RT constexpr uint32_t MAX_BOTTOM_LEVELS = 1000; constexpr uint32_t HALTON_SAMPLE_COUNT = 128; constexpr uint32_t MAX_RASTER_TRIANGLES = 10000; - constexpr uint32_t MAX_RASTER_LINES = 2000; + constexpr uint32_t MAX_RASTER_LINES = 5000; constexpr uint32_t MAX_DEBUG_LINES_WORLD = 5000; + constexpr uint32_t CBV_SRV_UAV_HEAP_SIZE = 65536; struct RaytracingShader { @@ -120,6 +124,7 @@ namespace RT ID3D12Resource* texture; DescriptorAllocation descriptors; + DescriptorAllocation rtv_descriptor; }; struct PrimaryRayPayload @@ -263,8 +268,10 @@ namespace RT RT_Vec3 sky_color_bottom; RT_RendererIO io; + uint64_t tweakvars_config_last_modified_time; D3D12ResourceTracker resource_tracker; + MeshTracker mesh_tracker; TextureResource *white_texture; RT_ResourceHandle white_texture_handle; @@ -325,6 +332,8 @@ namespace RT ID3D12RootSignature* global_root_sig; + RT_Config global_shader_defines; + union { struct @@ -356,6 +365,8 @@ namespace RT RaytracingPipeline rt_pipelines_all[sizeof(rt_pipelines) / sizeof(RaytracingPipeline)]; }; + ID3D12RootSignature* gen_mipmap_root_sig; + struct { ComputeShader restir_gen_candidates; @@ -375,6 +386,8 @@ namespace RT ComputeShader composite; ComputeShader post_process; ComputeShader resolve_final_color; + + ComputeShader gen_mipmaps; } cs; ID3D12Resource* raygen_shader_table; @@ -395,7 +408,7 @@ namespace RT }; DXGI_FORMAT render_target_formats[RenderTarget_COUNT]; - D3D12_CPU_DESCRIPTOR_HANDLE color_final_rtv; + DescriptorAllocation color_final_rtv; ID3D12Resource *blue_noise_textures[BLUE_NOISE_TEX_COUNT]; struct @@ -420,6 +433,7 @@ namespace RT int freezeframe; size_t hitgroups_table_at; + bool render_blit; } scene; RingBuffer resource_upload_ring_buffer; @@ -433,9 +447,12 @@ namespace RT D3D12_CPU_DESCRIPTOR_HANDLE depth_target_dsv; D3D12_VIEWPORT viewport; + ID3D12Resource* render_target; + D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle; // UI quad rendering ID3D12PipelineState* tri_state; + ID3D12PipelineState* tri_state_srgb; ID3D12RootSignature* tri_root_sig; ID3D12Resource* tri_vertex_buffer; @@ -461,6 +478,9 @@ namespace RT size_t debug_line_at; size_t debug_line_count; RT_RasterLineVertex* debug_line_vertex_buf_ptr; + + ID3D12PipelineState* blit_state; + ID3D12RootSignature* blit_root_sig; }; extern D3D12RasterState g_d3d_raster; diff --git a/RT/Renderer/Backend/DX12/src/MeshTracker.cpp b/RT/Renderer/Backend/DX12/src/MeshTracker.cpp new file mode 100644 index 0000000..9136a5e --- /dev/null +++ b/RT/Renderer/Backend/DX12/src/MeshTracker.cpp @@ -0,0 +1,76 @@ +#include "MeshTracker.hpp" + +#include "Core/Arena.h" + +using namespace RT; + +void MeshTracker::Init(RT_Arena *arena) +{ + m_arena = arena; + m_first_free = nullptr; +} + +bool MeshTracker::GetTrackedMeshData(uint64_t key, uint64_t frame_index, TrackedMeshData **data) +{ + bool result = false; + + uint64_t slot = key % RT_ARRAY_COUNT(m_table); + + Entry *entry = nullptr; + for (Entry *test_entry = m_table[slot]; test_entry; test_entry = test_entry->next) + { + if (test_entry->key == key) + { + entry = test_entry; + result = true; + break; + } + } + + if (!entry) + { + if (!m_first_free) + { + m_first_free = RT_ArenaAllocStructNoZero(m_arena, Entry); + m_first_free->next = nullptr; + } + + entry = RT_SLL_POP(m_first_free); + RT_ZERO_STRUCT(entry); + + entry->next = m_table[slot]; + m_table[slot] = entry; + } + + entry->key = key; + entry->last_touched_frame_index = frame_index; + + if (data) + { + *data = &entry->data; + } + + return result; +} + +void MeshTracker::PruneOldEntries(uint64_t frame_index) +{ + for (size_t index = 0; index < RT_ARRAY_COUNT(m_table); index++) + { + for (Entry **entry_at = &m_table[index]; *entry_at;) + { + Entry *entry = *entry_at; + + uint64_t frame_difference = frame_index - entry->last_touched_frame_index; + if (frame_difference > 1) + { + *entry_at = entry->next; + RT_SLL_PUSH(m_first_free, entry); + } + else + { + entry_at = &entry->next; + } + } + } +} \ No newline at end of file diff --git a/RT/Renderer/Backend/DX12/src/MeshTracker.hpp b/RT/Renderer/Backend/DX12/src/MeshTracker.hpp new file mode 100644 index 0000000..c29bfe7 --- /dev/null +++ b/RT/Renderer/Backend/DX12/src/MeshTracker.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "ApiTypes.h" + +namespace RT +{ + + struct TrackedMeshData + { + RT_Mat4 prev_transform; + }; + + class MeshTracker + { + public: + void Init(RT_Arena *arena); + bool GetTrackedMeshData(uint64_t key, uint64_t frame_index, TrackedMeshData **data); + void PruneOldEntries(uint64_t frame_index); + + private: + struct Entry + { + Entry *next; + uint64_t key; + uint64_t last_touched_frame_index; + TrackedMeshData data; + }; + + RT_Arena *m_arena; + Entry *m_first_free; + Entry *m_table[1024]; + }; + +} diff --git a/RT/Renderer/Backend/DX12/src/RenderBackend.cpp b/RT/Renderer/Backend/DX12/src/RenderBackend.cpp index f5186c7..c1ed2a8 100644 --- a/RT/Renderer/Backend/DX12/src/RenderBackend.cpp +++ b/RT/Renderer/Backend/DX12/src/RenderBackend.cpp @@ -21,6 +21,9 @@ #include using namespace DirectX; +#define RT_RENDER_SETTINGS_CONFIG_FILE "render_settings.vars" +#define RT_DEFAULT_RENDER_SETTINGS_CONFIG_FILE "assets/render_presets/default.vars" + // ------------------------------------------------------------------ // These global arrays are directly accessible through calls in // Renderer.h and mirrored to the GPU per-frame (see Renderer.h for @@ -115,7 +118,37 @@ void RT::ResourceTransitions(ID3D12GraphicsCommandList* list, size_t num_resourc namespace { + struct ShaderDefineSettings + { + uint64_t last_modified_time; + + bool early_out_of_bounds = true; + }; + + ShaderDefineSettings g_shader_defines; + + void WriteTweakvarsToIOConfig(); + void UpdateTweakvarsFromIOConfig(); + void ResetTweakvarsToDefault(); + void InitTweakVars() + { + g_d3d.io.config = RT_ArenaAllocStructNoZero(g_d3d.arena, RT_Config); + RT_InitializeConfig(g_d3d.io.config, g_d3d.arena); + + ResetTweakvarsToDefault(); + WriteTweakvarsToIOConfig(); + + RT_InitializeConfig(&g_d3d.global_shader_defines, g_d3d.arena); + RT_ConfigWriteString(&g_d3d.global_shader_defines, RT_StringLiteral("DO_EARLY_OUT_IN_COMPUTE_SHADERS"), RT_StringLiteral("1")); + + if (RT_DeserializeConfigFromFile(g_d3d.io.config, RT_RENDER_SETTINGS_CONFIG_FILE)) + { + UpdateTweakvarsFromIOConfig(); + } + } + + void ResetTweakvarsToDefault() { #define TWEAK_CATEGORY_BEGIN(name) #define TWEAK_CATEGORY_END() @@ -136,6 +169,59 @@ namespace #undef TWEAK_OPTIONS } + void WriteTweakvarsToIOConfig() + { + RT_Config *cfg = g_d3d.io.config; + + #define TWEAK_CATEGORY_BEGIN(name) + #define TWEAK_CATEGORY_END() + #define TWEAK_BOOL(name, var, value) RT_ConfigWriteInt(cfg, RT_StringLiteral(#var), tweak_vars.var); + #define TWEAK_INT(name, var, value, min, max) RT_ConfigWriteInt(cfg, RT_StringLiteral(#var), tweak_vars.var); + #define TWEAK_FLOAT(name, var, value, min, max) RT_ConfigWriteFloat(cfg, RT_StringLiteral(#var), tweak_vars.var); + #define TWEAK_COLOR(name, var, value) RT_ConfigWriteVec3(cfg, RT_StringLiteral(#var), tweak_vars.var.xyz); + #define TWEAK_OPTIONS(name, var, value, ...) RT_ConfigWriteInt(cfg, RT_StringLiteral(#var), tweak_vars.var); + + #include "shared_tweakvars.hlsl.h" + + #undef TWEAK_CATEGORY_BEGIN + #undef TWEAK_CATEGORY_END + #undef TWEAK_BOOL + #undef TWEAK_INT + #undef TWEAK_FLOAT + #undef TWEAK_COLOR + #undef TWEAK_OPTIONS + + g_d3d.tweakvars_config_last_modified_time = cfg->last_modified_time; + } + + void UpdateTweakvarsFromIOConfig() + { + if (g_d3d.tweakvars_config_last_modified_time != g_d3d.io.config->last_modified_time) + { + g_d3d.tweakvars_config_last_modified_time = g_d3d.io.config->last_modified_time; + + RT_Config *cfg = g_d3d.io.config; + + #define TWEAK_CATEGORY_BEGIN(name) + #define TWEAK_CATEGORY_END() + #define TWEAK_BOOL(name, var, value) { int result = tweak_vars.var; RT_ConfigReadInt(cfg, RT_StringLiteral(#var), &result); tweak_vars.var = result; } + #define TWEAK_INT(name, var, value, min, max) RT_ConfigReadInt(cfg, RT_StringLiteral(#var), &tweak_vars.var); + #define TWEAK_FLOAT(name, var, value, min, max) RT_ConfigReadFloat(cfg, RT_StringLiteral(#var), &tweak_vars.var); + #define TWEAK_COLOR(name, var, value) { RT_ConfigReadVec3(cfg, RT_StringLiteral(#var), &tweak_vars.var.xyz); tweak_vars.var.w = 1.0f; } + #define TWEAK_OPTIONS(name, var, value, ...) RT_ConfigReadInt(cfg, RT_StringLiteral(#var), &tweak_vars.var); + + #include "shared_tweakvars.hlsl.h" + + #undef TWEAK_CATEGORY_BEGIN + #undef TWEAK_CATEGORY_END + #undef TWEAK_BOOL + #undef TWEAK_INT + #undef TWEAK_FLOAT + #undef TWEAK_COLOR + #undef TWEAK_OPTIONS + } + } + float Halton(int i, int base) { float f = 1; @@ -202,7 +288,7 @@ namespace return result; } - IDxcBlob *CompileShader(const wchar_t *file_name, const wchar_t *entry_point, const wchar_t *target_profile, uint32_t num_defines = 0, const wchar_t **defines = nullptr) + IDxcBlob *CompileShader(const wchar_t *file_name, const wchar_t *entry_point, const wchar_t *target_profile, uint32_t num_defines = 0, const DxcDefine *defines = nullptr) { HRESULT hr; @@ -229,16 +315,9 @@ namespace }; IDxcOperationResult *result; - DxcDefine* dxc_defines = RT_ArenaAllocArray(&g_thread_arena, num_defines, DxcDefine); - for (size_t i = 0; i < num_defines; ++i) - { - dxc_defines[i].Name = (LPCWSTR)defines[i]; - dxc_defines[i].Value = (LPCWSTR)defines[i]; - } - DX_CALL(g_d3d.dxc_compiler->Compile(shader_text, file_name, entry_point, target_profile, arguments, RT_ARRAY_COUNT(arguments), - dxc_defines, num_defines, + defines, num_defines, g_d3d.dxc_include_handler, &result)); DeferRelease(result); @@ -260,9 +339,23 @@ namespace return blob; } - ID3D12PipelineState *CreateComputePipeline(const wchar_t *source, const wchar_t *entry_point) + ID3D12PipelineState *CreateComputePipeline(const wchar_t *source, const wchar_t *entry_point, ID3D12RootSignature* root_sig) { - IDxcBlob *blob = CompileShader(source, entry_point, L"cs_6_3"); + MemoryScope temp; + + size_t defines_count = g_d3d.global_shader_defines.kv_count; + DxcDefine *defines = RT_ArenaAllocArrayNoZero(temp, defines_count, DxcDefine); + + for (RT_ConfigIterator it = RT_IterateConfig(&g_d3d.global_shader_defines); + RT_ConfigIterValid(&it); + RT_ConfigIterNext(&it)) + { + RT_ConfigKeyValue *kv = it.at; + defines[it.index].Name = Utf16FromUtf8(temp, kv->key); + defines[it.index].Value = Utf16FromUtf8(temp, kv->value); + } + + IDxcBlob *blob = CompileShader(source, entry_point, L"cs_6_3", (UINT)defines_count, defines); if (!blob) return nullptr; @@ -274,7 +367,7 @@ namespace }; D3D12_COMPUTE_PIPELINE_STATE_DESC pipeline_desc = {}; - pipeline_desc.pRootSignature = g_d3d.global_root_sig; + pipeline_desc.pRootSignature = root_sig; pipeline_desc.CS = bytecode; ID3D12PipelineState *result = nullptr; @@ -432,6 +525,8 @@ namespace void CreateCommandQueues() { + // TODO(Justin): This is a relic from the past. Why does this call new? Idk + // Also we want to refactor command lists and have multiple command queues potentially, but we might not end up having time for this. g_d3d.command_queue_direct = new CommandQueue(D3D12_COMMAND_LIST_TYPE_DIRECT); } @@ -483,9 +578,10 @@ namespace void CreateDescriptorHeaps() { - g_d3d.rtv.Init(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1, D3D12_DESCRIPTOR_HEAP_FLAG_NONE); + // Since any texture could - in theory - be used as a render target, we will mimic the size of the CBV_SRV_UAV heap for the RTV heap + g_d3d.rtv.Init(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, CBV_SRV_UAV_HEAP_SIZE, D3D12_DESCRIPTOR_HEAP_FLAG_NONE); g_d3d.dsv.Init(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1, D3D12_DESCRIPTOR_HEAP_FLAG_NONE); - g_d3d.cbv_srv_uav.Init(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 4096, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); + g_d3d.cbv_srv_uav.Init(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, CBV_SRV_UAV_HEAP_SIZE, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); g_d3d.cbv_srv_uav_staging.Init(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12GlobalDescriptors_COUNT*BACK_BUFFER_COUNT, D3D12_DESCRIPTOR_HEAP_FLAG_NONE); } @@ -549,14 +645,14 @@ namespace D3D12_DESCRIPTOR_RANGE1 bindless_ranges[2] = {}; bindless_ranges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - bindless_ranges[0].NumDescriptors = 4096; + bindless_ranges[0].NumDescriptors = CBV_SRV_UAV_HEAP_SIZE; bindless_ranges[0].OffsetInDescriptorsFromTableStart = 0; bindless_ranges[0].BaseShaderRegister = 0; bindless_ranges[0].RegisterSpace = 3; bindless_ranges[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE|D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE; bindless_ranges[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - bindless_ranges[1].NumDescriptors = 4096; + bindless_ranges[1].NumDescriptors = CBV_SRV_UAV_HEAP_SIZE; bindless_ranges[1].OffsetInDescriptorsFromTableStart = 0; bindless_ranges[1].BaseShaderRegister = 0; bindless_ranges[1].RegisterSpace = 4; @@ -585,7 +681,7 @@ namespace static_samplers[0].RegisterSpace = 0; static_samplers[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - static_samplers[1].Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; + static_samplers[1].Filter = D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR; static_samplers[1].AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; static_samplers[1].AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; static_samplers[1].AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; @@ -1119,7 +1215,7 @@ namespace graphics_state_desc.pRootSignature = g_d3d_raster.tri_root_sig; DX_CALL(g_d3d.device->CreateGraphicsPipelineState(&graphics_state_desc, IID_PPV_ARGS(&g_d3d_raster.tri_state))); - g_d3d_raster.tri_state->SetName(L"Raster triangle state"); + g_d3d_raster.tri_state->SetName(L"Raster triangle state (Non-SRGB render target)"); SafeRelease(vertex_shader_blob); SafeRelease(pixel_shader_blob); @@ -1274,9 +1370,9 @@ namespace SafeRelease(vertex_shader_blob); SafeRelease(pixel_shader_blob); - const wchar_t* defines[1] = + const DxcDefine defines[1] = { - L"DEPTH_ENABLED" + { L"DEPTH_ENABLED" }, }; vertex_shader_blob = CompileShader(L"assets/shaders/raster_line_world.hlsl", L"VertexShaderEntry", L"vs_6_3", RT_ARRAY_COUNT(defines), defines); @@ -1304,6 +1400,97 @@ namespace g_d3d_raster.debug_line_vertex_buf_ptr = reinterpret_cast(debug_line_vertex_buf_ptr); } + { + // ------------------------------------------------------------------------------------------------- + // Create raster blit root signature and pipeline state + + D3D12_DESCRIPTOR_RANGE1 ranges[1] = {}; + ranges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + ranges[0].BaseShaderRegister = 0; + ranges[0].RegisterSpace = 0; + ranges[0].NumDescriptors = 1; + ranges[0].OffsetInDescriptorsFromTableStart = 0; + ranges[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE; + + D3D12_ROOT_PARAMETER1 root_parameters[2] = {}; + root_parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + root_parameters[0].Constants.Num32BitValues = 5; + root_parameters[0].Constants.ShaderRegister = 0; + root_parameters[0].Constants.RegisterSpace = 0; + root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + root_parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE ; + root_parameters[1].DescriptorTable.NumDescriptorRanges = 1; + root_parameters[1].DescriptorTable.pDescriptorRanges = ranges; + root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + D3D12_STATIC_SAMPLER_DESC static_samplers[1] = {}; + static_samplers[0].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + static_samplers[0].AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + static_samplers[0].AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + static_samplers[0].BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; + static_samplers[0].ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; + static_samplers[0].Filter = D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR; + static_samplers[0].MaxAnisotropy = 0; + static_samplers[0].MinLOD = 0; + static_samplers[0].MaxLOD = 0; + static_samplers[0].MipLODBias = 0; + static_samplers[0].ShaderRegister = 0; + static_samplers[0].RegisterSpace = 0; + static_samplers[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + D3D12_VERSIONED_ROOT_SIGNATURE_DESC graphics_root_sig_desc = {}; + graphics_root_sig_desc.Desc_1_1.NumParameters = RT_ARRAY_COUNT(root_parameters); + graphics_root_sig_desc.Desc_1_1.pParameters = root_parameters; + graphics_root_sig_desc.Desc_1_1.NumStaticSamplers = RT_ARRAY_COUNT(static_samplers); + graphics_root_sig_desc.Desc_1_1.pStaticSamplers = static_samplers; + graphics_root_sig_desc.Desc_1_1.Flags = + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS; + graphics_root_sig_desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1; + + ID3DBlob* serialized_root_sig = CompileVersionedRootSignature(graphics_root_sig_desc); + DX_CALL(g_d3d.device->CreateRootSignature(0, serialized_root_sig->GetBufferPointer(), serialized_root_sig->GetBufferSize(), IID_PPV_ARGS(&g_d3d_raster.blit_root_sig))); + g_d3d_raster.blit_root_sig->SetName(L"Raster blit root signature"); + SafeRelease(serialized_root_sig); + + IDxcBlob* vertex_shader_blob = CompileShader(L"assets/shaders/raster_blit.hlsl", L"VertexShaderEntry", L"vs_6_3"); + IDxcBlob* pixel_shader_blob = CompileShader(L"assets/shaders/raster_blit.hlsl", L"PixelShaderEntry", L"ps_6_3"); + + D3D12_GRAPHICS_PIPELINE_STATE_DESC graphics_state_desc = {}; + graphics_state_desc.InputLayout.NumElements = 0; + graphics_state_desc.InputLayout.pInputElementDescs = nullptr; + graphics_state_desc.VS.BytecodeLength = vertex_shader_blob->GetBufferSize(); + graphics_state_desc.VS.pShaderBytecode = vertex_shader_blob->GetBufferPointer(); + graphics_state_desc.PS.BytecodeLength = pixel_shader_blob->GetBufferSize(); + graphics_state_desc.PS.pShaderBytecode = pixel_shader_blob->GetBufferPointer(); + graphics_state_desc.NumRenderTargets = 1; + graphics_state_desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; + graphics_state_desc.DepthStencilState.DepthEnable = FALSE; + graphics_state_desc.DepthStencilState.StencilEnable = FALSE; + graphics_state_desc.DSVFormat = DXGI_FORMAT_UNKNOWN; + graphics_state_desc.BlendState.AlphaToCoverageEnable = FALSE; + graphics_state_desc.BlendState.IndependentBlendEnable = FALSE; + graphics_state_desc.BlendState.RenderTarget[0] = rt_blend_desc; + graphics_state_desc.SampleDesc.Count = 1; + graphics_state_desc.SampleDesc.Quality = 0; + graphics_state_desc.SampleMask = UINT_MAX; + graphics_state_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; + graphics_state_desc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK; + graphics_state_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + graphics_state_desc.NodeMask = 0; + graphics_state_desc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + graphics_state_desc.pRootSignature = g_d3d_raster.blit_root_sig; + + DX_CALL(g_d3d.device->CreateGraphicsPipelineState(&graphics_state_desc, IID_PPV_ARGS(&g_d3d_raster.blit_state))); + g_d3d_raster.blit_state->SetName(L"Raster blit graphics pipeline state"); + + SafeRelease(vertex_shader_blob); + SafeRelease(pixel_shader_blob); + } + RenderBackend::RasterSetViewport(0.0f, 0.0f, (float)g_d3d.render_width, (float)g_d3d.render_height); } @@ -1314,7 +1501,8 @@ namespace clear_value.DepthStencil.Depth = 1.0f; clear_value.DepthStencil.Stencil = 0; - g_d3d_raster.depth_target = CreateTexture(L"Raster depth target", DXGI_FORMAT_D32_FLOAT, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, g_d3d.render_width, g_d3d.render_height, 1, &clear_value); + g_d3d_raster.depth_target = RT_CreateTexture(L"Raster depth target", DXGI_FORMAT_D32_FLOAT, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, + g_d3d.render_width, g_d3d.render_height, D3D12_RESOURCE_STATE_DEPTH_WRITE, 1, &clear_value); CreateTextureDSV(g_d3d_raster.depth_target, g_d3d_raster.depth_target_dsv, DXGI_FORMAT_D32_FLOAT); } @@ -1340,12 +1528,15 @@ namespace { uint64_t timestamp = GetLastWriteTime(file); + bool shader_file_updated = timestamp != cs->timestamp; + bool shader_defines_updated = g_shader_defines.last_modified_time != g_d3d.global_shader_defines.last_modified_time; + // NOTE(daniel): For reasons opaque to me, it seems sometimes the new file's timestamp // is less than the current. So this tested (timestamp > cs->timestamp) before, but // that turns out to be unreliable. - if (timestamp != cs->timestamp) + if (shader_file_updated || shader_defines_updated) { - ID3D12PipelineState *new_pso = CreateComputePipeline(file, entry_point); + ID3D12PipelineState *new_pso = CreateComputePipeline(file, entry_point, g_d3d.global_root_sig); if (new_pso) { RenderBackend::Flush(); @@ -1397,40 +1588,233 @@ namespace } } + void CreateGenMipMapComputeShader() + { + D3D12_DESCRIPTOR_RANGE1 ranges[2] = {}; + ranges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + ranges[0].NumDescriptors = 1; + ranges[0].OffsetInDescriptorsFromTableStart = 0; + ranges[0].BaseShaderRegister = 0; + ranges[0].RegisterSpace = 0; + ranges[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE; + + ranges[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + ranges[1].NumDescriptors = 4; + ranges[1].OffsetInDescriptorsFromTableStart = 0; + ranges[1].BaseShaderRegister = 0; + ranges[1].RegisterSpace = 0; + ranges[1].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE; + + D3D12_ROOT_PARAMETER1 root_parameters[3] = {}; + root_parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + root_parameters[0].Constants.Num32BitValues = sizeof(GenMipMapSettings) / 4; + root_parameters[0].Constants.ShaderRegister = 0; + root_parameters[0].Constants.RegisterSpace = 0; + root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + root_parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + root_parameters[1].DescriptorTable.NumDescriptorRanges = 1; + root_parameters[1].DescriptorTable.pDescriptorRanges = &ranges[0]; + root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + root_parameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + root_parameters[2].DescriptorTable.NumDescriptorRanges = 1; + root_parameters[2].DescriptorTable.pDescriptorRanges = &ranges[1]; + root_parameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + D3D12_STATIC_SAMPLER_DESC static_samplers[1] = {}; + static_samplers[0].Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + static_samplers[0].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + static_samplers[0].AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + static_samplers[0].AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + static_samplers[0].ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; + static_samplers[0].BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; + static_samplers[0].MinLOD = 0.0f; + static_samplers[0].MaxLOD = D3D12_FLOAT32_MAX; + static_samplers[0].MipLODBias = 0; + static_samplers[0].ShaderRegister = 0; + static_samplers[0].RegisterSpace = 0; + static_samplers[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + D3D12_VERSIONED_ROOT_SIGNATURE_DESC gen_mipmap_root_sig_desc = {}; + gen_mipmap_root_sig_desc.Desc_1_1.NumParameters = RT_ARRAY_COUNT(root_parameters); + gen_mipmap_root_sig_desc.Desc_1_1.pParameters = &root_parameters[0]; + gen_mipmap_root_sig_desc.Desc_1_1.NumStaticSamplers = RT_ARRAY_COUNT(static_samplers); + gen_mipmap_root_sig_desc.Desc_1_1.pStaticSamplers = &static_samplers[0]; + gen_mipmap_root_sig_desc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + gen_mipmap_root_sig_desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1; + + ID3DBlob* serialized_root_sig = CompileVersionedRootSignature(gen_mipmap_root_sig_desc); + DX_CALL(g_d3d.device->CreateRootSignature(0, serialized_root_sig->GetBufferPointer(), serialized_root_sig->GetBufferSize(), IID_PPV_ARGS(&g_d3d.gen_mipmap_root_sig))); + g_d3d.gen_mipmap_root_sig->SetName(L"Gen mip maps root signature"); + + SafeRelease(serialized_root_sig); + + g_d3d.cs.gen_mipmaps.pso = CreateComputePipeline(L"assets/shaders/gen_mipmap.hlsl", L"GenMipMapCS", g_d3d.gen_mipmap_root_sig); + } + + D3D12_RESOURCE_BARRIER AliasingBarrier(ID3D12Resource* resource_before, ID3D12Resource* resource_after) + { + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING; + barrier.Aliasing.pResourceBefore = resource_before; + barrier.Aliasing.pResourceAfter = resource_after; + + return barrier; + } + + uint32_t DivideUp(uint32_t x, uint32_t div) + { + return (x + div - 1) / div; + } + + void GenerateMips(TextureResource* resource) + { + if (!resource->texture || resource->texture->GetDesc().MipLevels == 1) + return; + + CommandList& command_list = *g_d3d.resource_upload_ring_buffer.command_list; + + ID3D12Resource* uav_resource = resource->texture; + ID3D12Resource* aliased_resource = nullptr; + + // If the source texture does not allow unordered access, we will alias the source texture with another texture + if ((resource->texture->GetDesc().Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS) == 0) + { + D3D12_RESOURCE_DESC alias_resource_desc = resource->texture->GetDesc(); + alias_resource_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + D3D12_RESOURCE_DESC uav_desc = alias_resource_desc; + D3D12_RESOURCE_DESC alias_uav_descs[] = { alias_resource_desc, uav_desc }; + + D3D12_RESOURCE_ALLOCATION_INFO alloc_info = g_d3d.device->GetResourceAllocationInfo(0, RT_ARRAY_COUNT(alias_uav_descs), alias_uav_descs); + + D3D12_HEAP_DESC heap_desc = {}; + heap_desc.SizeInBytes = alloc_info.SizeInBytes; + heap_desc.Alignment = alloc_info.Alignment; + heap_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES; + heap_desc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heap_desc.Properties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heap_desc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT; + + ID3D12Heap* heap; + DX_CALL(g_d3d.device->CreateHeap(&heap_desc, IID_PPV_ARGS(&heap))); + heap->SetName(L"Temporary mipmap gen heap"); + RT_TRACK_TEMP_OBJECT(heap, &command_list); + + DX_CALL(g_d3d.device->CreatePlacedResource( + heap, 0, &alias_resource_desc, D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(&aliased_resource) + )); + aliased_resource->SetName(L"Temporary aliasing resource mipmap gen"); + RT_TRACK_TEMP_RESOURCE(aliased_resource, &command_list); + + DX_CALL(g_d3d.device->CreatePlacedResource( + heap, 0, &uav_desc, D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(&uav_resource) + )); + uav_resource->SetName(L"Temporary UAV resource mipmap gen"); + RT_TRACK_TEMP_RESOURCE(uav_resource, &command_list); + + D3D12_RESOURCE_BARRIER alias_barrier_before = AliasingBarrier(nullptr, aliased_resource); + command_list->ResourceBarrier(1, &alias_barrier_before); + CopyResource(command_list, aliased_resource, resource->texture); + D3D12_RESOURCE_BARRIER alias_barrier_after = AliasingBarrier(aliased_resource, uav_resource); + command_list->ResourceBarrier(1, &alias_barrier_after); + } + + // TODO(Justin): These are temporary descriptor allocations and should ideally be freed when the mips are done + // However, since descriptor heaps can be quite big in size, we won't care about this. + DescriptorAllocation srv = g_d3d.cbv_srv_uav.Allocate(1); + DescriptorAllocation uavs = g_d3d.cbv_srv_uav.Allocate(resource->texture->GetDesc().MipLevels - 1); + + command_list->SetPipelineState(g_d3d.cs.gen_mipmaps.pso); + command_list->SetComputeRootSignature(g_d3d.gen_mipmap_root_sig); + + GenMipMapSettings gen_mipmap_settings = {}; + gen_mipmap_settings.is_srgb = resource->texture->GetDesc().Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + + for (uint32_t src_mip = 0; src_mip < ((uint32_t)resource->texture->GetDesc().MipLevels - 1);) + { + uint64_t src_width = resource->texture->GetDesc().Width >> src_mip; + uint32_t src_height = resource->texture->GetDesc().Height >> src_mip; + uint32_t dst_width = uint32_t(src_width >> 1); + uint32_t dst_height = src_height >> 1; + + gen_mipmap_settings.src_dim = (src_height & 1) << 1 | (src_width & 1); + DWORD mip_count = 0; + + // Determine how many mips we want to generate now (max of 4) + _BitScanForward(&mip_count, (dst_width == 1 ? dst_width : dst_height) | + (dst_height == 1 ? dst_width : dst_height)); + + mip_count = RT_MIN(4, mip_count + 1); + mip_count = (src_mip + mip_count) >= resource->texture->GetDesc().MipLevels ? + resource->texture->GetDesc().MipLevels - src_mip - 1 : mip_count; + + dst_width = RT_MAX(1u, dst_width); + dst_height = RT_MAX(1u, dst_height); + + gen_mipmap_settings.src_mip = src_mip; + gen_mipmap_settings.num_mips = mip_count; + gen_mipmap_settings.texel_size.x = 1.0f / (float)dst_width; + gen_mipmap_settings.texel_size.y = 1.0f / (float)dst_height; + + D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {}; + srv_desc.Format = resource->texture->GetDesc().Format; + srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srv_desc.Texture2D.MostDetailedMip = 0; + srv_desc.Texture2D.MipLevels = resource->texture->GetDesc().MipLevels; + + g_d3d.device->CreateShaderResourceView(uav_resource, &srv_desc, srv.cpu); + CreateTextureSRV(uav_resource, srv.cpu, resource->texture->GetDesc().Format); + for (uint32_t mip = 0; mip < mip_count; ++mip) + { + D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = {}; + uav_desc.Format = resource->texture->GetDesc().Format == DXGI_FORMAT_R8_UNORM ? DXGI_FORMAT_R8_UNORM : DXGI_FORMAT_R8G8B8A8_UNORM; + uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + uav_desc.Texture2D.MipSlice = src_mip + mip + 1; + + g_d3d.device->CreateUnorderedAccessView(uav_resource, nullptr, &uav_desc, uavs.GetCPUDescriptor(src_mip + mip)); + } + + ID3D12DescriptorHeap* heap = { g_d3d.cbv_srv_uav.GetHeap() }; + command_list->SetDescriptorHeaps(1, &heap); + // Set the constant buffer data for the mip map settings constant buffer + command_list->SetComputeRoot32BitConstants(0, sizeof(GenMipMapSettings) / 4, &gen_mipmap_settings, 0); + // Set both descriptor tables for the source texture SRV and the target texture UAVs + command_list->SetComputeRootDescriptorTable(1, srv.GetGPUDescriptor(0)); + command_list->SetComputeRootDescriptorTable(2, uavs.GetGPUDescriptor(src_mip)); + + command_list->Dispatch(DivideUp(dst_width, 8), DivideUp(dst_height, 8), 1); + UAVBarrier(command_list, uav_resource); + + src_mip += mip_count; + } + + if (aliased_resource) + { + D3D12_RESOURCE_BARRIER barriers[] = { + AliasingBarrier(uav_resource, aliased_resource), + GetTransitionBarrier(aliased_resource, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE), + GetTransitionBarrier(resource->texture, g_d3d.resource_tracker.GetResourceState(resource->texture), D3D12_RESOURCE_STATE_COPY_DEST) + }; + command_list->ResourceBarrier(3, barriers); + command_list->CopyResource(resource->texture, aliased_resource); + + if (g_d3d.resource_tracker.GetResourceState(resource->texture) != D3D12_RESOURCE_STATE_COPY_DEST) + { + D3D12_RESOURCE_BARRIER barrier = GetTransitionBarrier(resource->texture, + D3D12_RESOURCE_STATE_COPY_DEST, g_d3d.resource_tracker.GetResourceState(resource->texture)); + command_list->ResourceBarrier(1, &barrier); + } + } + } + void CreateIntermediateRendertargets() { - // TODO: This should call CreateTexture() - // NOTE(daniel): If it should call CreateTexture, CreateTexture shouldn't create an SRV for you automatically - auto CreateRenderTarget = [](const wchar_t *name, int scale_x, int scale_y, DXGI_FORMAT format, ID3D12Resource **result) { - D3D12_HEAP_PROPERTIES prop = {}; - prop.Type = D3D12_HEAP_TYPE_DEFAULT; - - D3D12_RESOURCE_DESC desc = {}; - desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; - desc.Width = (g_d3d.render_width + scale_x - 1) / scale_x; - desc.Height = (g_d3d.render_height + scale_y - 1) / scale_y; - desc.DepthOrArraySize = 1; - desc.MipLevels = 1; - desc.Format = format; - desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS | D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; - desc.SampleDesc = { 1, 0 }; - - g_d3d.device->CreateCommittedResource( - &prop, - D3D12_HEAP_FLAG_NONE, - &desc, - D3D12_RESOURCE_STATE_UNORDERED_ACCESS, - nullptr, - IID_PPV_ARGS(result) - ); - - (*result)->SetName(name); - - RT_TRACK_RESOURCE(*result, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + (*result) = RT_CreateTexture(name, format, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS | D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET + , (g_d3d.render_width + scale_x - 1) / scale_x, (g_d3d.render_height + scale_y - 1) / scale_y, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); }; #define RT_CREATE_RENDER_TARGETS(name, reg, scale_x, scale_y, type, format) \ @@ -1439,7 +1823,7 @@ namespace RT_RENDER_TARGETS(RT_CREATE_RENDER_TARGETS) - CreateTextureRTV(g_d3d.rt.color_final, g_d3d.color_final_rtv, g_d3d.render_target_formats[RenderTarget_color_final]); + CreateTextureRTV(g_d3d.rt.color_final, g_d3d.color_final_rtv.cpu, g_d3d.render_target_formats[RenderTarget_color_final]); } void InitDearImGui() @@ -1606,7 +1990,7 @@ namespace int w, h, n; unsigned char *pixels = RT_LoadImageFromDisk(temp, path, &w, &h, &n, 4); - g_d3d.blue_noise_textures[blue_noise_index] = CreateTexture(Utf16FromUtf8(temp, path), DXGI_FORMAT_R8G8B8A8_UNORM, D3D12_RESOURCE_FLAG_NONE, (size_t)w, (uint32_t)h); + g_d3d.blue_noise_textures[blue_noise_index] = RT_CreateTexture(Utf16FromUtf8(temp, path), DXGI_FORMAT_R8G8B8A8_UNORM, D3D12_RESOURCE_FLAG_NONE, (size_t)w, (uint32_t)h); UploadTextureData(g_d3d.blue_noise_textures[blue_noise_index], 4*w, h, pixels); for (size_t frame_index = 0; frame_index < BACK_BUFFER_COUNT; frame_index++) @@ -1640,6 +2024,8 @@ namespace CreateIntermediateRendertargets(); CreatePixelDebugResources(); CreateRasterDepthTarget(); + + g_d3d_raster.render_target = g_d3d.rt.color_final; } void InitializeFrameResources() @@ -1801,6 +2187,8 @@ void RenderBackend::Init(const RT_RendererInitParams* render_init_params) g_d3d.halton_samples[i].y = Halton(i, 3) - 0.5f; } + g_d3d.mesh_tracker.Init(g_d3d.arena); + InitTweakVars(); EnableDebugLayer(); @@ -1830,16 +2218,20 @@ void RenderBackend::Init(const RT_RendererInitParams* render_init_params) g_d3d.instance_data_buffer = RT_CreateReadOnlyBuffer(L"Instance Data Buffer", sizeof(InstanceData) * MAX_INSTANCES); // Gotta allocate this one for creating the intermediate render targets - g_d3d.color_final_rtv = g_d3d.rtv.Allocate(1).GetCPUDescriptor(0); + g_d3d.color_final_rtv = g_d3d.rtv.Allocate(1); CreateIntermediateRendertargets(); CreatePixelDebugResources(); ReloadComputeShadersIfThereAreNewOnes(); + CreateGenMipMapComputeShader(); LoadBlueNoiseTextures(); CreateDefaultTextures(); + g_d3d_raster.render_target = g_d3d.rt.color_final; + g_d3d_raster.rtv_handle = g_d3d.color_final_rtv.cpu; + // ------------------------------------------------------------------ // Initialize all materials to have default textures @@ -1882,10 +2274,10 @@ void RenderBackend::Init(const RT_RendererInitParams* render_init_params) RT_Vec2 uvs[] = { - { 0, 0 }, - { 1, 0 }, { 1, 1 }, { 0, 1 }, + { 0, 0 }, + { 1, 0 }, }; RT_Triangle triangles[2] = {}; @@ -2182,6 +2574,81 @@ void RenderBackend::DoDebugMenus(const RT_DoRendererDebugMenuParams *params) { if (ImGui::Begin("Render Settings")) { + static float loaded_timer = 0.0f; + static float saved_timer = 0.0f; + static char* preset_name; + + if (ImGui::Button("Load Settings")) + { + if (RT_DeserializeConfigFromFile(g_d3d.io.config, RT_RENDER_SETTINGS_CONFIG_FILE)) + { + UpdateTweakvarsFromIOConfig(); + loaded_timer = 2.0f; + } + } + + ImGui::SameLine(); + + if (ImGui::Button("Save Settings")) + { + RT_SerializeConfigToFile(g_d3d.io.config, RT_RENDER_SETTINGS_CONFIG_FILE); + saved_timer = 2.0f; + } + + ImGui::SameLine(); + + if (ImGui::Button("Save as preset")) + { + ImGui::OpenPopup("Preset name"); + preset_name = (char*)malloc(128); + memset(preset_name, 0, 128); + saved_timer = 2.0f; + } + + if (ImGui::BeginPopupModal("Preset name")) { + ImGui::InputText("name", preset_name, 128); + + char path[23] = "assets/render_presets/"; + + if (ImGui::Button("Done")) + { + ImGui::CloseCurrentPopup(); + char buff[157]; + strcpy(buff, path); + strcat(buff, preset_name); + strcat(buff, ".vars"); + RT_SerializeConfigToFile(g_d3d.io.config, buff); + free(preset_name); + } + + ImGui::EndPopup(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Reset Default Settings")) + { + ResetTweakvarsToDefault(); + } + + if (loaded_timer > 0.0f) + { + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 1.0f, 0.5f, 1.0f)); + ImGui::Text("Loaded Renderer Settings"); + ImGui::PopStyleColor(); + + loaded_timer -= 1.0f / 60.0f; + } + + if (saved_timer > 0.0f) + { + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 0.5f, 1.0f, 1.0f)); + ImGui::Text("Saved Renderer Settings"); + ImGui::PopStyleColor(); + + saved_timer -= 1.0f / 60.0f; + } + #if RT_PIXEL_DEBUG ImGui::Text("Pixel debug mode is enabled"); ImGui::Text("Hold Middle Mouse Button to debug pixels"); @@ -2191,8 +2658,6 @@ void RenderBackend::DoDebugMenus(const RT_DoRendererDebugMenuParams *params) ImGui::Text("Lights: %u/%u", g_d3d.prev_lights_count, RT_MAX_LIGHTS); - ImGui::Checkbox("Vsync", &g_d3d.vsync); - if (ImGui::Button("Clear Render Targets")) { g_d3d.accum_frame_index = 0; @@ -2282,10 +2747,30 @@ void RenderBackend::DoDebugMenus(const RT_DoRendererDebugMenuParams *params) #undef TWEAK_COLOR #undef TWEAK_OPTIONS + WriteTweakvarsToIOConfig(); + if (tweak_vars.reference_mode != current_reference_mode) { g_d3d.accum_frame_index = 0; } + + // NOTE(daniel): This is a bit half-baked because I just wanted to try the early out thing. + if (ImGui::CollapsingHeader("Compile Time Shader Settings")) + { + ImGui::Indent(); + if (ImGui::Checkbox("Early Out when Out of Bounds in Compute Shaders", &g_shader_defines.early_out_of_bounds)) + { + if (g_shader_defines.early_out_of_bounds) + { + RT_ConfigWriteString(&g_d3d.global_shader_defines, RT_StringLiteral("DO_EARLY_OUT_IN_COMPUTE_SHADERS"), RT_StringLiteral("1")); + } + else + { + RT_ConfigEraseKey(&g_d3d.global_shader_defines, RT_StringLiteral("DO_EARLY_OUT_IN_COMPUTE_SHADERS")); + } + } + ImGui::Unindent(); + } } ImGui::End(); RT_Vec2i pixel = { (int)io.MousePos.x, (int)io.MousePos.y }; @@ -2314,6 +2799,7 @@ void RenderBackend::BeginScene(const RT_SceneSettings* scene_settings) } g_d3d.scene.freezeframe = false; + g_d3d.scene.render_blit = scene_settings->render_blit; if (tweak_vars.reference_mode) { @@ -2338,6 +2824,8 @@ void RenderBackend::BeginScene(const RT_SceneSettings* scene_settings) void RenderBackend::EndScene() { + UpdateTweakvarsFromIOConfig(); + if (!g_d3d.scene.freezeframe) { // ------------------------------------------------------------------ @@ -2419,6 +2907,7 @@ void RenderBackend::EndScene() void RenderBackend::EndFrame() { + g_shader_defines.last_modified_time = g_d3d.global_shader_defines.last_modified_time; } void RenderBackend::SwapBuffers() @@ -2440,8 +2929,8 @@ void RenderBackend::SwapBuffers() // ------------------------------------------------------------------ // Swap buffers - uint32_t sync_interval = g_d3d.vsync ? 1 : 0; - uint32_t present_flags = g_d3d.tearing_supported && !g_d3d.vsync ? DXGI_PRESENT_ALLOW_TEARING : 0; + uint32_t sync_interval = tweak_vars.vsync ? 1 : 0; + uint32_t present_flags = g_d3d.tearing_supported && !tweak_vars.vsync ? DXGI_PRESENT_ALLOW_TEARING : 0; HRESULT hr = g_d3d.dxgi_swapchain4->Present(sync_interval, present_flags); @@ -2565,6 +3054,8 @@ void RenderBackend::SwapBuffers() g_d3d_raster.line_at = g_d3d.current_back_buffer_index * MAX_RASTER_LINES; g_d3d_raster.debug_line_at = g_d3d.current_back_buffer_index * MAX_DEBUG_LINES_WORLD; + g_d3d.mesh_tracker.PruneOldEntries(g_d3d.frame_index); + RECT client_rect; GetClientRect(g_d3d.hWnd, &client_rect); @@ -2623,8 +3114,12 @@ int RenderBackend::CheckWindowMinimized() RT_ResourceHandle RenderBackend::UploadTexture(const RT_UploadTextureParams& texture_params) { RT::MemoryScope temp; + + if (!texture_params.pixels) + return g_d3d.pink_checkerboard_texture; + TextureResource resource = {}; - + char *texture_resource_name = RT_ArenaPrintF(temp, "Texture: %s", texture_params.name); static int n_textures_uploaded_please_remove_me_later = 0; printf("textures loaded: %d\n", ++n_textures_uploaded_please_remove_me_later); @@ -2638,8 +3133,19 @@ RT_ResourceHandle RenderBackend::UploadTexture(const RT_UploadTextureParams& tex case RT_TextureFormat_R8: format = DXGI_FORMAT_R8_UNORM; bpp = 1; break; } - resource.texture = CreateTexture(Utf16FromUtf8(temp, texture_resource_name), format, D3D12_RESOURCE_FLAG_NONE, (size_t)texture_params.width, (uint32_t)texture_params.height); + uint32_t w = texture_params.width, h = texture_params.height, num_mips = 0; + while (w >= 1 && h >= 1) + { + num_mips++; + w /= 2; + h /= 2; + } + + resource.texture = RT_CreateTexture(Utf16FromUtf8(temp, texture_resource_name), format, D3D12_RESOURCE_FLAG_NONE, (size_t)texture_params.width, (uint32_t)texture_params.height, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, (uint16_t)num_mips); + UploadTextureData(resource.texture, bpp*texture_params.width, texture_params.height, texture_params.pixels); + GenerateMips(&resource); resource.descriptors = g_d3d.cbv_srv_uav.Allocate(1); CreateTextureSRV(resource.texture, resource.descriptors.GetCPUDescriptor(0), format); @@ -2659,6 +3165,9 @@ RT_ResourceHandle RenderBackend::UploadMesh(const RT_UploadMeshParams& mesh_para ID3D12Resource* blas = BuildBLAS(mesh_params.triangle_count, mesh_params.triangles, D3D12_RAYTRACING_GEOMETRY_FLAG_NONE); + static uint32_t blas_index = 0; + blas->SetName(Utf16FromUtf8(temp_arena, RT_ArenaPrintF(temp_arena, "BLAS %u (%s)", blas_index++, mesh_params.name))); + MeshResource resource = {}; resource.blas = blas; resource.triangle_buffer = result.triangle_buffer; @@ -2667,6 +3176,14 @@ RT_ResourceHandle RenderBackend::UploadMesh(const RT_UploadMeshParams& mesh_para return g_mesh_slotmap.Insert(resource); } +void RenderBackend::ReleaseTexture(const RT_ResourceHandle texture_handle) +{ + TextureResource* texture_resource = g_texture_slotmap.Find(texture_handle); + RT_RELEASE_RESOURCE(texture_resource->texture); + g_d3d.cbv_srv_uav.Free(texture_resource->descriptors); + g_texture_slotmap.Remove(texture_handle); +} + void RenderBackend::ReleaseMesh(const RT_ResourceHandle mesh_handle) { MeshResource* mesh_resource = g_mesh_slotmap.Find(mesh_handle); @@ -2737,6 +3254,16 @@ RT_ResourceHandle RenderBackend::GetDefaultBlackTexture() return g_d3d.black_texture_handle; } +RT_ResourceHandle RenderBackend::GetBillboardMesh() +{ + return g_d3d.billboard_quad; +} + +RT_ResourceHandle RenderBackend::GetCubeMesh() +{ + return g_d3d.cube; +} + void RenderBackend::RaytraceSubmitLights(size_t count, const RT_Light* lights) { if (g_d3d.scene.freezeframe) @@ -2764,7 +3291,11 @@ float RenderBackend::RaytraceGetVerticalOffset() { return g_d3d.viewport_offset_y; } -void RenderBackend::RaytraceMesh(const RT_RenderMeshParams& render_mesh_params) +uint32_t RenderBackend::RaytraceGetCurrentLightCount() { + return g_d3d.lights_count; +} + +void RenderBackend::RaytraceMesh(const RT_RenderMeshParams& params) { if (g_d3d.scene.freezeframe) return; @@ -2772,7 +3303,7 @@ void RenderBackend::RaytraceMesh(const RT_RenderMeshParams& render_mesh_params) if (ALWAYS(g_d3d.tlas_instance_count < MAX_INSTANCES)) { FrameData *frame = CurrentFrameData(); - MeshResource* mesh_resource = g_mesh_slotmap.Find(render_mesh_params.mesh_handle); + MeshResource* mesh_resource = g_mesh_slotmap.Find(params.mesh_handle); if (!mesh_resource) { @@ -2802,23 +3333,44 @@ void RenderBackend::RaytraceMesh(const RT_RenderMeshParams& render_mesh_params) D3D12_RAYTRACING_INSTANCE_DESC *instance_desc = frame->instance_descs.As() + instance_index; instance_desc->InstanceMask = 1; - memcpy(instance_desc->Transform, render_mesh_params.transform, sizeof(float)*12); + memcpy(instance_desc->Transform, params.transform, sizeof(float)*12); instance_desc->AccelerationStructure = mesh_resource->blas->GetGPUVirtualAddress(); instance_desc->InstanceContributionToHitGroupIndex = base_hitgroup_index * 2; instance_desc->Flags = 0; - if (render_mesh_params.flags & RT_RenderMeshFlags_ReverseCulling) + if (params.flags & RT_RenderMeshFlags_ReverseCulling) { instance_desc->Flags |= D3D12_RAYTRACING_INSTANCE_FLAG_TRIANGLE_FRONT_COUNTERCLOCKWISE; } + TrackedMeshData *tracked = nullptr; + bool tracked_data_valid = g_d3d.mesh_tracker.GetTrackedMeshData(params.key.value, g_d3d.frame_index, &tracked); + InstanceData *instance_data = frame->instance_data.As() + instance_index; - instance_data->object_to_world = *render_mesh_params.transform; - instance_data->world_to_object = RT_Mat4Inverse(*render_mesh_params.transform); - instance_data->object_to_world_prev = *render_mesh_params.prev_transform; - instance_data->material_override = render_mesh_params.material_override; - instance_data->material_color = render_mesh_params.color; + instance_data->object_to_world = *params.transform; + instance_data->world_to_object = RT_Mat4Inverse(*params.transform); + + if (params.prev_transform) + { + instance_data->object_to_world_prev = *params.prev_transform; + } + else + { + if (tracked_data_valid && !(params.flags & RT_RenderMeshFlags_Teleport)) + { + instance_data->object_to_world_prev = tracked->prev_transform; + } + else + { + instance_data->object_to_world_prev = *params.transform; + } + } + + instance_data->material_override = params.material_override; + instance_data->material_color = params.color; instance_data->triangle_buffer_idx = mesh_resource->triangle_buffer_descriptor.heap_offset; + + tracked->prev_transform = *params.transform; } } @@ -2859,7 +3411,7 @@ void RenderBackend::RaytraceRod(uint16_t material_index, RT_Vec3 bot_p, RT_Vec3 { RT_Vec3 z = RT_Vec3Negate(g_d3d.scene.camera.forward); - RT_Vec3 y = RT_Vec3Muls(RT_Vec3Sub(bot_p, top_p), 0.5f); + RT_Vec3 y = RT_Vec3Muls(RT_Vec3Sub(top_p, bot_p), 0.5f); RT_Vec3 x = RT_Vec3Normalize(RT_Vec3Cross(y, z)); x = RT_Vec3Muls(x, width); @@ -3051,6 +3603,7 @@ void RenderBackend::RaytraceRender() CreateRenderTargetUAV(RenderTarget_bloom5, D3D12GlobalDescriptors_UAV_bloom5); CreateRenderTargetUAV(RenderTarget_bloom6, D3D12GlobalDescriptors_UAV_bloom6); CreateRenderTargetUAV(RenderTarget_bloom7, D3D12GlobalDescriptors_UAV_bloom7); + CreateRenderTargetUAV(RenderTarget_scene, D3D12GlobalDescriptors_UAV_scene); CreateRenderTargetUAV(RenderTarget_color_reference, D3D12GlobalDescriptors_UAV_color_reference); CreateRenderTargetUAV(RenderTarget_color_final, D3D12GlobalDescriptors_UAV_color_final); CreateRenderTargetUAV(RenderTarget_debug, D3D12GlobalDescriptors_UAV_debug); @@ -3074,6 +3627,7 @@ void RenderBackend::RaytraceRender() CreateRenderTargetSRV(RenderTarget_bloom5, D3D12GlobalDescriptors_SRV_bloom5); CreateRenderTargetSRV(RenderTarget_bloom6, D3D12GlobalDescriptors_SRV_bloom6); CreateRenderTargetSRV(RenderTarget_bloom7, D3D12GlobalDescriptors_SRV_bloom7); + ResourceTransition(command_list, g_d3d.rt.scene, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); // ------------------------------------------------------------------ // Create unordered access view for the pixel debug buffer @@ -3372,17 +3926,6 @@ void RenderBackend::RaytraceRender() if (!tweak_vars.reference_mode) { -#if 0 - command_list->SetPipelineState(g_d3d.cs.svgf_prepass.pso); - command_list->Dispatch(dispatch_w, dispatch_h, 1); - - ID3D12Resource* uav_render_targets[] = - { - g_d3d.rt.diff_denoise_ping, g_d3d.rt.spec_denoise_ping, - }; - UAVBarriers(command_list, RT_ARRAY_COUNT(uav_render_targets), uav_render_targets); -#endif - command_list->SetPipelineState(g_d3d.cs.svgf_resample.pso); command_list->Dispatch(dispatch_w, dispatch_h, 1); @@ -3392,17 +3935,6 @@ void RenderBackend::RaytraceRender() g_d3d.rt.moments, g_d3d.rt.history_length }; UAVBarriers(command_list, RT_ARRAY_COUNT(uav_render_targets), uav_render_targets); - -#if 0 - command_list->SetPipelineState(g_d3d.cs.svgf_history_fix.pso); - command_list->Dispatch(dispatch_w, dispatch_h, 1); - - ID3D12Resource* uav_render_targets[] = - { - g_d3d.rt.diff_denoise_ping, g_d3d.rt.spec_denoise_ping, - }; - UAVBarriers(command_list, RT_ARRAY_COUNT(uav_render_targets), uav_render_targets); -#endif } else { @@ -3592,7 +4124,8 @@ void RenderBackend::RaytraceRender() // ------------------------------------------------------------------ // Do tonemapping / gamma correction / other post processing effects - + + UAVBarrier(command_list, g_d3d.rt.debug); GPUProfiler::BeginTimestampQuery(command_list, GPUProfiler::GPUTimer_PostProcess); ResourceTransition(command_list, g_d3d.render_targets[rt_taa_result[a]], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); @@ -3612,7 +4145,10 @@ void RenderBackend::RaytraceRender() command_list->SetPipelineState(g_d3d.cs.resolve_final_color.pso); command_list->Dispatch(dispatch_w, dispatch_h, 1); - UAVBarrier(command_list, g_d3d.rt.color_final); + UAVBarrier(command_list, g_d3d.rt.scene); + + if (!g_d3d.scene.render_blit) + CopyResource(command_list, g_d3d.rt.color_final, g_d3d.rt.scene); GPUProfiler::EndTimestampQuery(command_list, GPUProfiler::GPUTimer_FrameTime); GPUProfiler::ResolveTimestampQueries(command_list); @@ -3629,6 +4165,67 @@ void RenderBackend::RasterSetViewport(float x, float y, float width, float heigh g_d3d_raster.viewport = { x, y, width, height, 0.1f, 5000.0f }; } +void RenderBackend::RasterSetRenderTarget(RT_ResourceHandle texture) +{ + if (RT_RESOURCE_HANDLE_VALID(texture)) + { + TextureResource* texture_resource = g_texture_slotmap.Find(texture); + if (ALWAYS(texture_resource)) + { + CommandList& command_list = g_d3d.command_queue_direct->GetCommandList(); + + // Check texture flags if render target usage is allowed + if (!(texture_resource->texture->GetDesc().Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)) + { + // Get name of the texture + wchar_t texture_name[128] = {}; + UINT name_size = (UINT)RT_ARRAY_COUNT(texture_name); + texture_resource->texture->GetPrivateData(WKPDID_D3DDebugObjectNameW, &name_size, texture_name); + + // Use the same resource desc to create the render target clone, plus add the render target allow flag + D3D12_RESOURCE_DESC render_target_desc = texture_resource->texture->GetDesc(); + render_target_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + render_target_desc.MipLevels = 1; + + D3D12_CLEAR_VALUE clear_value = {}; + float clear_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + memcpy(clear_value.Color, &clear_color, sizeof(float) * 4); + clear_value.Format = render_target_desc.Format; + + ID3D12Resource* rt_texture = RT_CreateTexture(texture_name, &render_target_desc, &clear_value); + + // Track the old resource as a temporary resource, which means it will be released once all pending commands with that resource are finished + RT_TRACK_TEMP_RESOURCE(texture_resource->texture, &command_list); + + // Set texture_resource->texture to the new render target version of the d3d12 resource + // Also allocate a render target descriptor for this new texture in the TextureResource + texture_resource->texture = rt_texture; + texture_resource->rtv_descriptor = g_d3d.rtv.Allocate(1); + + // Create the RTV, and also re-create the SRV, since it now needs to point to the new resource + CreateTextureSRV(texture_resource->texture, texture_resource->descriptors.cpu, texture_resource->texture->GetDesc().Format); + CreateTextureRTV(texture_resource->texture, texture_resource->rtv_descriptor.cpu, DXGI_FORMAT_R8G8B8A8_UNORM); + } + + g_d3d_raster.render_target = texture_resource->texture; + g_d3d_raster.rtv_handle = texture_resource->rtv_descriptor.cpu; + + // Clear the render target + ResourceTransition(command_list, g_d3d_raster.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET); + + // Set the current raster render target to the new render target texture, and create the render target view + float clear_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + command_list->ClearRenderTargetView(g_d3d_raster.rtv_handle, clear_color, 0, nullptr); + g_d3d.command_queue_direct->ExecuteCommandList(command_list); + + return; + } + } + + g_d3d_raster.render_target = g_d3d.rt.color_final; + g_d3d_raster.rtv_handle = g_d3d.color_final_rtv.cpu; +} + void RenderBackend::RasterTriangles(RT_RasterTrianglesParams* params, uint32_t num_params) { for (uint32_t i = 0; i < num_params; ++i) @@ -3693,58 +4290,65 @@ void RenderBackend::RasterRender() // Flush the ring buffer for any pending resource uploads FlushRingBuffer(&g_d3d.resource_upload_ring_buffer); - ResourceTransition(command_list, g_d3d.rt.color_final, D3D12_RESOURCE_STATE_RENDER_TARGET); + ResourceTransition(command_list, g_d3d_raster.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET); command_list->RSSetViewports(1, &g_d3d_raster.viewport); - D3D12_RECT scissor_rect = { 0, 0, LONG_MAX, LONG_MAX }; command_list->RSSetScissorRects(1, &scissor_rect); + command_list->OMSetRenderTargets(1, &g_d3d_raster.rtv_handle, FALSE, nullptr); - command_list->OMSetRenderTargets(1, &g_d3d.color_final_rtv, FALSE, nullptr); + size_t vertex_buffer_offset = 0; - command_list->SetGraphicsRootSignature(g_d3d_raster.tri_root_sig); - command_list->SetPipelineState(g_d3d_raster.tri_state); - command_list->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + if (g_d3d_raster.tri_count) + { + command_list->SetGraphicsRootSignature(g_d3d_raster.tri_root_sig); + command_list->SetPipelineState(g_d3d_raster.tri_state); - size_t vertex_buffer_offset = g_d3d_raster.tri_at * 3 * sizeof(RT_RasterTriVertex); + command_list->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - // Setup vertex and index buffer views - D3D12_VERTEX_BUFFER_VIEW vertex_vbv = {}; - vertex_vbv.BufferLocation = g_d3d_raster.tri_vertex_buffer->GetGPUVirtualAddress() + vertex_buffer_offset; - vertex_vbv.SizeInBytes = (UINT)(g_d3d_raster.tri_count * 3 * sizeof(RT_RasterTriVertex)); - vertex_vbv.StrideInBytes = sizeof(RT_RasterTriVertex); - command_list->IASetVertexBuffers(0, 1, &vertex_vbv); + vertex_buffer_offset = g_d3d_raster.tri_at * 3 * sizeof(RT_RasterTriVertex); - // Setup bindless SRV descriptor table - ID3D12DescriptorHeap* const heaps[] = {g_d3d.cbv_srv_uav.GetHeap()}; - command_list->SetDescriptorHeaps(1, heaps); - command_list->SetGraphicsRootDescriptorTable(0, g_d3d.cbv_srv_uav.GetGPUBase()); + // Setup vertex and index buffer views + D3D12_VERTEX_BUFFER_VIEW vertex_vbv = {}; + vertex_vbv.BufferLocation = g_d3d_raster.tri_vertex_buffer->GetGPUVirtualAddress() + vertex_buffer_offset; + vertex_vbv.SizeInBytes = (UINT)(g_d3d_raster.tri_count * 3 * sizeof(RT_RasterTriVertex)); + vertex_vbv.StrideInBytes = sizeof(RT_RasterTriVertex); + command_list->IASetVertexBuffers(0, 1, &vertex_vbv); - // Draw - command_list->DrawInstanced((UINT)(g_d3d_raster.tri_count * 3), 1, 0, 0); + // Setup bindless SRV descriptor table + ID3D12DescriptorHeap* const heaps[] = { g_d3d.cbv_srv_uav.GetHeap() }; + command_list->SetDescriptorHeaps(1, heaps); + command_list->SetGraphicsRootDescriptorTable(0, g_d3d.cbv_srv_uav.GetGPUBase()); - g_d3d_raster.tri_at += g_d3d_raster.tri_count; - g_d3d_raster.tri_count = 0; + // Draw + command_list->DrawInstanced((UINT)(g_d3d_raster.tri_count * 3), 1, 0, 0); + + g_d3d_raster.tri_at += g_d3d_raster.tri_count; + g_d3d_raster.tri_count = 0; + } // ------------------------------------------------------------------ // Render lines - command_list->SetGraphicsRootSignature(g_d3d_raster.line_root_sig); - command_list->SetPipelineState(g_d3d_raster.line_state); - command_list->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_LINELIST); + if (g_d3d_raster.line_count) + { + command_list->SetGraphicsRootSignature(g_d3d_raster.line_root_sig); + command_list->SetPipelineState(g_d3d_raster.line_state); + command_list->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_LINELIST); - vertex_buffer_offset = g_d3d_raster.line_at * 2 * sizeof(RT_RasterLineVertex); + vertex_buffer_offset = g_d3d_raster.line_at * 2 * sizeof(RT_RasterLineVertex); - D3D12_VERTEX_BUFFER_VIEW vbv = {}; - vbv.BufferLocation = g_d3d_raster.line_vertex_buffer->GetGPUVirtualAddress() + vertex_buffer_offset; - vbv.SizeInBytes = (UINT)(g_d3d_raster.line_count * 2 * sizeof(RT_RasterLineVertex)); - vbv.StrideInBytes = sizeof(RT_RasterLineVertex); + D3D12_VERTEX_BUFFER_VIEW vbv = {}; + vbv.BufferLocation = g_d3d_raster.line_vertex_buffer->GetGPUVirtualAddress() + vertex_buffer_offset; + vbv.SizeInBytes = (UINT)(g_d3d_raster.line_count * 2 * sizeof(RT_RasterLineVertex)); + vbv.StrideInBytes = sizeof(RT_RasterLineVertex); - command_list->IASetVertexBuffers(0, 1, &vbv); - command_list->DrawInstanced((UINT)(g_d3d_raster.line_count * 2), 1, 0, 0); + command_list->IASetVertexBuffers(0, 1, &vbv); + command_list->DrawInstanced((UINT)(g_d3d_raster.line_count * 2), 1, 0, 0); - g_d3d_raster.line_at += g_d3d_raster.line_count; - g_d3d_raster.line_count = 0; + g_d3d_raster.line_at += g_d3d_raster.line_count; + g_d3d_raster.line_count = 0; + } g_d3d.command_queue_direct->ExecuteCommandList(command_list); } @@ -3773,12 +4377,12 @@ void RenderBackend::RasterRenderDebugLines() if (g_d3d.io.debug_line_depth_enabled) { - command_list->OMSetRenderTargets(1, &g_d3d.color_final_rtv, FALSE, &g_d3d_raster.depth_target_dsv); + command_list->OMSetRenderTargets(1, &g_d3d.color_final_rtv.cpu, FALSE, &g_d3d_raster.depth_target_dsv); command_list->SetPipelineState(g_d3d_raster.debug_line_state_depth); } else { - command_list->OMSetRenderTargets(1, &g_d3d.color_final_rtv, FALSE, nullptr); + command_list->OMSetRenderTargets(1, &g_d3d.color_final_rtv.cpu, FALSE, nullptr); command_list->SetPipelineState(g_d3d_raster.debug_line_state); } @@ -3809,6 +4413,88 @@ void RenderBackend::RasterRenderDebugLines() g_d3d.command_queue_direct->ExecuteCommandList(command_list); } +void RenderBackend::RasterBlitScene(const RT_Vec2* top_left, const RT_Vec2* bottom_right, bool blit_blend) +{ + // NOTES(Justin): + // - Raster blit will cause aliasing (currently using linear sampler to counter this a bit, but still) + + FlushRingBuffer(&g_d3d.resource_upload_ring_buffer); + + CommandList& command_list = g_d3d.command_queue_direct->GetCommandList(); + ResourceTransition(command_list, g_d3d.rt.scene, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + ResourceTransition(command_list, g_d3d.rt.color_final, D3D12_RESOURCE_STATE_RENDER_TARGET); + + FrameData* frame = CurrentFrameData(); + auto CreateRenderTargetSRV = [&](RenderTarget rt, D3D12GlobalDescriptors descriptor) + { + RT_ASSERT((descriptor >= D3D12GlobalDescriptors_SRV_START && descriptor < D3D12GlobalDescriptors_CBV_START) || + (descriptor >= D3D12GlobalDescriptors_SRV_RT_START && descriptor < D3D12GlobalDescriptors_COUNT)); + CreateTextureSRV(g_d3d.render_targets[rt], frame->descriptors.GetCPUDescriptor(descriptor), g_d3d.render_target_formats[rt]); + }; + CreateRenderTargetSRV(RenderTarget_scene, D3D12GlobalDescriptors_SRV_scene); + + ID3D12DescriptorHeap* heaps[] = { g_d3d.cbv_srv_uav.GetHeap() }; + command_list->SetDescriptorHeaps(1, heaps); + + // TopLeftX, TopLeftY, width, height, minDepth, maxDepth + D3D12_VIEWPORT viewport = { top_left->x, top_left->y, bottom_right->x - top_left->x, bottom_right->y - top_left->y, 0.0f, 1.0f }; + command_list->RSSetViewports(1, &viewport); + D3D12_RECT scissor_rect = { 0, 0, LONG_MAX, LONG_MAX }; + command_list->RSSetScissorRects(1, &scissor_rect); + command_list->OMSetRenderTargets(1, &g_d3d.color_final_rtv.cpu, FALSE, nullptr); + + command_list->SetPipelineState(g_d3d_raster.blit_state); + command_list->SetGraphicsRootSignature(g_d3d_raster.blit_root_sig); + command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + command_list->SetGraphicsRoot32BitConstant(0, (UINT)top_left->x, 0); + command_list->SetGraphicsRoot32BitConstant(0, (UINT)top_left->y, 1); + command_list->SetGraphicsRoot32BitConstant(0, (UINT)viewport.Width, 2); + command_list->SetGraphicsRoot32BitConstant(0, (UINT)viewport.Height, 3); + command_list->SetGraphicsRoot32BitConstant(0, (UINT)blit_blend, 4); + command_list->SetGraphicsRootDescriptorTable(1, frame->descriptors.GetGPUDescriptor(D3D12GlobalDescriptors_SRV_scene)); + command_list->DrawInstanced(6, 1, 0, 0); + + g_d3d.command_queue_direct->ExecuteCommandList(command_list); +} + +void RenderBackend::RasterBlit(RT_ResourceHandle src, const RT_Vec2* top_left, const RT_Vec2* bottom_right, bool blit_blend) +{ + FlushRingBuffer(&g_d3d.resource_upload_ring_buffer); + + TextureResource* src_texture = g_texture_slotmap.Find(src); + if (ALWAYS(src_texture)) + { + CommandList& command_list = g_d3d.command_queue_direct->GetCommandList(); + ResourceTransition(command_list, g_d3d.rt.scene, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + ResourceTransition(command_list, g_d3d.rt.color_final, D3D12_RESOURCE_STATE_RENDER_TARGET); + + ID3D12DescriptorHeap* heaps[] = { g_d3d.cbv_srv_uav.GetHeap() }; + command_list->SetDescriptorHeaps(1, heaps); + + // TopLeftX, TopLeftY, width, height, minDepth, maxDepth + D3D12_VIEWPORT viewport = { top_left->x, top_left->y, bottom_right->x - top_left->x, bottom_right->y - top_left->y, 0.0f, 1.0f }; + command_list->RSSetViewports(1, &viewport); + D3D12_RECT scissor_rect = { 0, 0, LONG_MAX, LONG_MAX }; + command_list->RSSetScissorRects(1, &scissor_rect); + command_list->OMSetRenderTargets(1, &g_d3d.color_final_rtv.cpu, FALSE, nullptr); + + command_list->SetPipelineState(g_d3d_raster.blit_state); + command_list->SetGraphicsRootSignature(g_d3d_raster.blit_root_sig); + command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + command_list->SetGraphicsRoot32BitConstant(0, (UINT)top_left->x, 0); + command_list->SetGraphicsRoot32BitConstant(0, (UINT)top_left->y, 1); + command_list->SetGraphicsRoot32BitConstant(0, (UINT)viewport.Width, 2); + command_list->SetGraphicsRoot32BitConstant(0, (UINT)viewport.Height, 3); + command_list->SetGraphicsRoot32BitConstant(0, (UINT)blit_blend, 4); + command_list->SetGraphicsRootDescriptorTable(1, src_texture->descriptors.gpu); + command_list->DrawInstanced(6, 1, 0, 0); + + g_d3d.command_queue_direct->ExecuteCommandList(command_list); + } +} + void RenderBackend::RenderImGuiTexture(RT_ResourceHandle texture_handle, float width, float height) { TextureResource *res = g_texture_slotmap.Find(texture_handle); @@ -3831,7 +4517,7 @@ void RenderBackend::RenderImGui() ImDrawData* draw_data = ImGui::GetDrawData(); if (draw_data) { - command_list->OMSetRenderTargets(1, &g_d3d.color_final_rtv, FALSE, nullptr); + command_list->OMSetRenderTargets(1, &g_d3d.color_final_rtv.cpu, FALSE, nullptr); ID3D12DescriptorHeap* imgui_heaps[] = { g_d3d.cbv_srv_uav.GetHeap() }; command_list->SetDescriptorHeaps(RT_ARRAY_COUNT(imgui_heaps), imgui_heaps); diff --git a/RT/Renderer/Backend/DX12/src/RenderBackend.h b/RT/Renderer/Backend/DX12/src/RenderBackend.h index e2b4f7f..3906c18 100644 --- a/RT/Renderer/Backend/DX12/src/RenderBackend.h +++ b/RT/Renderer/Backend/DX12/src/RenderBackend.h @@ -1,14 +1,13 @@ #pragma once #include "ApiTypes.h" -#include "Renderer.h" +#include "Renderer.h" extern RT_MaterialEdge g_rt_material_edges [RT_MAX_MATERIAL_EDGES]; extern uint16_t g_rt_material_indices[RT_MAX_MATERIALS]; namespace RenderBackend { - void Init(const RT_RendererInitParams* params); void Exit(); void Flush(); @@ -27,11 +26,14 @@ namespace RenderBackend RT_ResourceHandle UploadTexture(const RT_UploadTextureParams& texture_params); RT_ResourceHandle UploadMesh(const RT_UploadMeshParams& mesh_params); + void ReleaseTexture(const RT_ResourceHandle texture_handle); void ReleaseMesh(const RT_ResourceHandle mesh_handle); uint16_t UpdateMaterial(uint16_t material_index, const RT_Material *material); RT_ResourceHandle GetDefaultWhiteTexture(); RT_ResourceHandle GetDefaultBlackTexture(); + RT_ResourceHandle GetBillboardMesh(); + RT_ResourceHandle GetCubeMesh(); // ----------------------------------------------------------------------------------------------- // Raytracing @@ -39,6 +41,7 @@ namespace RenderBackend void RaytraceSubmitLights(size_t size, const RT_Light* lights); void RaytraceSetVerticalOffset(float new_offset); float RaytraceGetVerticalOffset(); + uint32_t RaytraceGetCurrentLightCount(); void RaytraceMesh(const RT_RenderMeshParams& render_mesh_params); void RaytraceBillboardColored(uint16_t material_index, RT_Vec3 color, RT_Vec2 dim, RT_Vec3 pos, RT_Vec3 prev_pos); void RaytraceRod(uint16_t material_index, RT_Vec3 bot_p, RT_Vec3 top_p, float width); @@ -49,11 +52,14 @@ namespace RenderBackend // Rasterization (UI, debug rendering) void RasterSetViewport(float x, float y, float width, float height); + void RasterSetRenderTarget(RT_ResourceHandle texture); void RasterTriangles(RT_RasterTrianglesParams* params, uint32_t num_params); void RasterLines(RT_RasterLineVertex* vertices, uint32_t num_vertices); void RasterLinesWorld(RT_RasterLineVertex* vertices, uint32_t num_vertices); void RasterRender(); void RasterRenderDebugLines(); + void RasterBlitScene(const RT_Vec2* top_left, const RT_Vec2* bottom_right, bool blit_blend); + void RasterBlit(RT_ResourceHandle src, const RT_Vec2* top_left, const RT_Vec2* bottom_right, bool blit_blend); // ----------------------------------------------------------------------------------------------- // Dear ImGui diff --git a/RT/Renderer/Backend/DX12/src/Renderer.cpp b/RT/Renderer/Backend/DX12/src/Renderer.cpp index 77f961b..b82bca3 100644 --- a/RT/Renderer/Backend/DX12/src/Renderer.cpp +++ b/RT/Renderer/Backend/DX12/src/Renderer.cpp @@ -84,6 +84,16 @@ RT_ResourceHandle RT_GetDefaultBlackTexture(void) return RenderBackend::GetDefaultBlackTexture(); } +RT_ResourceHandle RT_GetBillboardMesh(void) +{ + return RenderBackend::GetBillboardMesh(); +} + +RT_ResourceHandle RT_GetCubeMesh(void) +{ + return RenderBackend::GetCubeMesh(); +} + int RT_CheckWindowMinimized(void) { return RenderBackend::CheckWindowMinimized(); } @@ -175,6 +185,11 @@ RT_ResourceHandle RT_UploadMesh(const RT_UploadMeshParams* params) return RenderBackend::UploadMesh(*params); } +void RT_ReleaseTexture(const RT_ResourceHandle texture_handle) +{ + RenderBackend::ReleaseTexture(texture_handle); +} + void RT_ReleaseMesh(const RT_ResourceHandle mesh_handle) { RenderBackend::ReleaseMesh(mesh_handle); @@ -261,6 +276,15 @@ void RT_RasterSetViewport(float x, float y, float width, float height) RenderBackend::RasterSetViewport(x, y, width, height); } +void RT_RasterSetRenderTarget(RT_ResourceHandle texture) +{ + RenderBackend::RasterSetRenderTarget(texture); +} + +uint32_t RT_RaytraceGetCurrentLightCount() { + return RenderBackend::RaytraceGetCurrentLightCount(); +} + void RT_RaytraceSetVerticalOffset(const float new_offset) { RenderBackend::RaytraceSetVerticalOffset(new_offset); } @@ -284,7 +308,7 @@ void RT_RasterLines(RT_RasterLineVertex* vertices, uint32_t num_vertices) RenderBackend::RasterLines(vertices, num_vertices); } -void RT_DrawLineWorld(RT_Vec3 a, RT_Vec3 b, RT_Vec4 color) +void RT_RasterLineWorld(RT_Vec3 a, RT_Vec3 b, RT_Vec4 color) { RT_RasterLineVertex vertices[2]; vertices[0].pos = a; @@ -300,6 +324,16 @@ void RT_RasterLinesWorld(RT_RasterLineVertex* vertices, uint32_t num_vertices) RenderBackend::RasterLinesWorld(vertices, num_vertices); } +void RT_RasterBlitScene(const RT_Vec2* top_left, const RT_Vec2* bottom_right, bool blit_blend) +{ + RenderBackend::RasterBlitScene(top_left, bottom_right, blit_blend); +} + +void RT_RasterBlit(RT_ResourceHandle src, const RT_Vec2* top_left, const RT_Vec2* bottom_right, bool blit_blend) +{ + RenderBackend::RasterBlit(src, top_left, bottom_right, blit_blend); +} + void RT_RasterRender() { RenderBackend::RasterRender(); diff --git a/RT/Renderer/Backend/DX12/src/Resource.cpp b/RT/Renderer/Backend/DX12/src/Resource.cpp index f75db3d..2bb4b53 100644 --- a/RT/Renderer/Backend/DX12/src/Resource.cpp +++ b/RT/Renderer/Backend/DX12/src/Resource.cpp @@ -50,7 +50,7 @@ namespace RT DX_CALL(g_d3d.device->CreateCommittedResource(&heap_props, D3D12_HEAP_FLAG_NONE, &resource_desc, initial_state, nullptr, IID_PPV_ARGS(&buffer))); buffer->SetName(name); - g_d3d.resource_tracker.Track(RT_RESOURCE_TRACKER_FWD_ARGS buffer, initial_state); + g_d3d.resource_tracker.TrackObject(RT_RESOURCE_TRACKER_FWD_ARGS buffer, initial_state); return buffer; } @@ -168,7 +168,22 @@ namespace RT // ------------------------------------------------------------------------- // Textures - ID3D12Resource* CreateTexture(const wchar_t* name, DXGI_FORMAT format, D3D12_RESOURCE_FLAGS flags, size_t width, uint32_t height, uint16_t mips, D3D12_CLEAR_VALUE* clear_value) + ID3D12Resource* CreateTexture(RT_RESOURCE_TRACKER_DEBUG_PARAMS const wchar_t* name, const D3D12_RESOURCE_DESC* resource_desc, D3D12_CLEAR_VALUE* clear_value) + { + D3D12_HEAP_PROPERTIES heap_props = {}; + heap_props.Type = D3D12_HEAP_TYPE_DEFAULT; + + ID3D12Resource* texture; + g_d3d.device->CreateCommittedResource(&heap_props, D3D12_HEAP_FLAG_NONE, resource_desc, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, clear_value, IID_PPV_ARGS(&texture)); + + texture->SetName(name); + g_d3d.resource_tracker.TrackObject(RT_RESOURCE_TRACKER_FWD_ARGS texture, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + + return texture; + } + + ID3D12Resource* CreateTexture(RT_RESOURCE_TRACKER_DEBUG_PARAMS const wchar_t* name, DXGI_FORMAT format, D3D12_RESOURCE_FLAGS flags, size_t width, uint32_t height, D3D12_RESOURCE_STATES state, uint16_t mips, D3D12_CLEAR_VALUE* clear_value) { D3D12_HEAP_PROPERTIES heap_props = {}; heap_props.Type = D3D12_HEAP_TYPE_DEFAULT; @@ -188,10 +203,10 @@ namespace RT ID3D12Resource* texture; g_d3d.device->CreateCommittedResource(&heap_props, D3D12_HEAP_FLAG_NONE, &resource_desc, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, clear_value, IID_PPV_ARGS(&texture)); + state, clear_value, IID_PPV_ARGS(&texture)); texture->SetName(name); - RT_TRACK_RESOURCE(texture, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + g_d3d.resource_tracker.TrackObject(RT_RESOURCE_TRACKER_FWD_ARGS texture, state); return texture; } @@ -256,7 +271,7 @@ namespace RT srv_desc.Format = format; srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - srv_desc.Texture2D.MipLevels = mips; + srv_desc.Texture2D.MipLevels = mips == UINT32_MAX ? resource->GetDesc().MipLevels : mips; srv_desc.Texture2D.MostDetailedMip = 0; srv_desc.Texture2D.PlaneSlice = 0; srv_desc.Texture2D.ResourceMinLODClamp = 0; diff --git a/RT/Renderer/Backend/DX12/src/Resource.h b/RT/Renderer/Backend/DX12/src/Resource.h index e30677d..3069f87 100644 --- a/RT/Renderer/Backend/DX12/src/Resource.h +++ b/RT/Renderer/Backend/DX12/src/Resource.h @@ -37,14 +37,18 @@ namespace RT // ------------------------------------------------------------------------- // Textures - ID3D12Resource* CreateTexture(const wchar_t* name, DXGI_FORMAT format, D3D12_RESOURCE_FLAGS flags, size_t width, uint32_t height, uint16_t mips = 1, D3D12_CLEAR_VALUE* clear_value = nullptr); + ID3D12Resource* CreateTexture(RT_RESOURCE_TRACKER_DEBUG_PARAMS const wchar_t* name, const D3D12_RESOURCE_DESC* resource_desc, D3D12_CLEAR_VALUE* clear_value = nullptr); + ID3D12Resource* CreateTexture(RT_RESOURCE_TRACKER_DEBUG_PARAMS const wchar_t* name, DXGI_FORMAT format, D3D12_RESOURCE_FLAGS flags, size_t width, uint32_t height, + D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, uint16_t mips = 1, D3D12_CLEAR_VALUE* clear_value = nullptr); + +#define RT_CreateTexture(...) CreateTexture(RT_RESOURCE_TRACKER_DEBUG_ARGS __VA_ARGS__) void CopyTexture(ID3D12GraphicsCommandList* command_list, ID3D12Resource* dst, ID3D12Resource* src); void CopyTextureRegion(ID3D12GraphicsCommandList* command_list, ID3D12Resource* dst, uint32_t dst_x, uint32_t dst_y, uint32_t dst_z, const D3D12_TEXTURE_COPY_LOCATION* src_loc, const D3D12_BOX* src_box); void UploadTextureData(ID3D12Resource* dst, size_t row_pitch, size_t row_count, const void* data_ptr); - void CreateTextureSRV(ID3D12Resource* resource, D3D12_CPU_DESCRIPTOR_HANDLE descriptor, DXGI_FORMAT format, uint32_t mips = 1); + void CreateTextureSRV(ID3D12Resource* resource, D3D12_CPU_DESCRIPTOR_HANDLE descriptor, DXGI_FORMAT format, uint32_t mips = UINT32_MAX); void CreateTextureUAV(ID3D12Resource* resource, D3D12_CPU_DESCRIPTOR_HANDLE descriptor, DXGI_FORMAT format); void CreateTextureRTV(ID3D12Resource* resource, D3D12_CPU_DESCRIPTOR_HANDLE descriptor, DXGI_FORMAT format); void CreateTextureDSV(ID3D12Resource* resource, D3D12_CPU_DESCRIPTOR_HANDLE descriptor, DXGI_FORMAT format); diff --git a/RT/Renderer/Backend/DX12/src/ResourceTracker.cpp b/RT/Renderer/Backend/DX12/src/ResourceTracker.cpp index 324c77f..7b23d1d 100644 --- a/RT/Renderer/Backend/DX12/src/ResourceTracker.cpp +++ b/RT/Renderer/Backend/DX12/src/ResourceTracker.cpp @@ -10,7 +10,7 @@ using namespace RT; namespace { - uint64_t HashResource(ID3D12Resource *resource) + uint64_t HashResource(ID3D12Object *resource) { // Bottom bits of a pointer tend to be 0 because of alignment uint64_t result = (uint64_t)resource >> 4; @@ -18,9 +18,9 @@ namespace } } -void D3D12ResourceTracker::Track(RT_RESOURCE_TRACKER_DEBUG_PARAMS ID3D12Resource *resource, D3D12_RESOURCE_STATES initial_state) +void D3D12ResourceTracker::TrackObject(RT_RESOURCE_TRACKER_DEBUG_PARAMS ID3D12Object* object, D3D12_RESOURCE_STATES initial_state) { - if (NEVER(!resource)) + if (NEVER(!object)) return; // allocate entry @@ -30,9 +30,9 @@ void D3D12ResourceTracker::Track(RT_RESOURCE_TRACKER_DEBUG_PARAMS ID3D12Resource } // initialize entry - ResourceEntry *entry = RT_SLL_POP(m_first_free_resource); - entry->resource = resource; - entry->state = initial_state; + ResourceEntry* entry = RT_SLL_POP(m_first_free_resource); + entry->resource = object; + entry->state = initial_state; entry->command_list = nullptr; // debug info @@ -40,18 +40,23 @@ void D3D12ResourceTracker::Track(RT_RESOURCE_TRACKER_DEBUG_PARAMS ID3D12Resource entry->track_file = file__; // insert entry into hashtable - uint64_t hash = HashResource(resource); + uint64_t hash = HashResource(object); uint64_t slot = hash % RT_ARRAY_COUNT(m_resource_table); RT_SLL_PUSH(m_resource_table[slot], entry); } -// This will effectively turn a persistently tracked resource into a temporary resource, simply by overriding its fence value from UINT64_MAX to an actual value -void D3D12ResourceTracker::TrackTemp(RT_RESOURCE_TRACKER_DEBUG_PARAMS ID3D12Resource* resource, CommandList* command_list) +void D3D12ResourceTracker::TrackTempObject(RT_RESOURCE_TRACKER_DEBUG_PARAMS ID3D12Object* object, CommandList* command_list) { - if (NEVER(!resource)) + if (NEVER(!object)) return; - ResourceEntry* entry = FindResourceEntry(resource); + ResourceEntry* entry = FindResourceEntry(object); + if (!entry) + { + TrackObject(RT_RESOURCE_TRACKER_FWD_ARGS object); + entry = FindResourceEntry(object); + } + entry->command_list = command_list; entry->temp_track_line = line__; entry->temp_track_file = file__; @@ -92,7 +97,7 @@ D3D12_RESOURCE_STATES D3D12ResourceTracker::Transition(ID3D12GraphicsCommandList // resources in the UPLOAD_HEAP. Maybe we should do this more elegantly? if (dst_state != entry->state && entry->state != D3D12_RESOURCE_STATE_GENERIC_READ) { - D3D12_RESOURCE_BARRIER barrier = GetTransitionBarrier(entry->resource, entry->state, dst_state); + D3D12_RESOURCE_BARRIER barrier = GetTransitionBarrier((ID3D12Resource*)entry->resource, entry->state, dst_state); list->ResourceBarrier(1, &barrier); entry->state = dst_state; } @@ -127,7 +132,7 @@ void D3D12ResourceTracker::Transitions(ID3D12GraphicsCommandList* list, size_t n if (dst_state != entry->state) { // Add barrier - barriers[num_barriers++] = GetTransitionBarrier(entry->resource, entry->state, dst_state); + barriers[num_barriers++] = GetTransitionBarrier((ID3D12Resource*)entry->resource, entry->state, dst_state); entry->state = dst_state; } } @@ -160,7 +165,7 @@ void D3D12ResourceTracker::Transitions(ID3D12GraphicsCommandList* list, size_t n if (dst_states[res_index] != entry->state) { // Add barrier - barriers[num_barriers++] = GetTransitionBarrier(entry->resource, entry->state, dst_states[res_index]); + barriers[num_barriers++] = GetTransitionBarrier((ID3D12Resource*)entry->resource, entry->state, dst_states[res_index]); entry->state = dst_states[res_index]; } } @@ -169,7 +174,7 @@ void D3D12ResourceTracker::Transitions(ID3D12GraphicsCommandList* list, size_t n list->ResourceBarrier(num_barriers, barriers); } -void D3D12ResourceTracker::Release(ID3D12Resource *resource) +void D3D12ResourceTracker::Release(ID3D12Object *resource) { ResourceEntry **entry_slot = FindResourceEntrySlot(resource); @@ -222,32 +227,31 @@ void RT::D3D12ResourceTracker::ReleaseStaleTempResources(uint64_t fence_value) { // Release temp resources if their fence value has been reached // (operation has been executed on the GPU and the resource is no longer in-flight) - for (ResourceEntry** resource_at = &m_resource_table[i]; *resource_at;) + for (ResourceEntry** entry_at = &m_resource_table[i]; *entry_at;) { - ResourceEntry* resource = *resource_at; + ResourceEntry* entry = *entry_at; - if (resource->command_list) + if (entry->command_list && + entry->command_list->GetFenceValue() <= fence_value) { - if (resource->command_list->GetFenceValue() <= fence_value) - { - ResourceEntry* entry = RT_SLL_POP(*resource_at); + entry->resource->Release(); + entry->resource = nullptr; - entry->resource->Release(); - entry->resource = nullptr; + *entry_at = entry->next; - RT_SLL_PUSH(m_first_free_resource, entry); - continue; - } + RT_SLL_PUSH(m_first_free_resource, entry); + } + else + { + entry_at = &entry->next; } - - resource_at = &resource->next; } } } //------------------------------------------------------------------------ -D3D12ResourceTracker::ResourceEntry **D3D12ResourceTracker::FindResourceEntrySlot(ID3D12Resource *resource) +D3D12ResourceTracker::ResourceEntry **D3D12ResourceTracker::FindResourceEntrySlot(ID3D12Object *resource) { ResourceEntry **result = nullptr; @@ -268,7 +272,7 @@ D3D12ResourceTracker::ResourceEntry **D3D12ResourceTracker::FindResourceEntrySlo return result; } -D3D12ResourceTracker::ResourceEntry *D3D12ResourceTracker::FindResourceEntry(ID3D12Resource *resource) +D3D12ResourceTracker::ResourceEntry *D3D12ResourceTracker::FindResourceEntry(ID3D12Object *resource) { RT_ASSERT(resource); diff --git a/RT/Renderer/Backend/DX12/src/ResourceTracker.hpp b/RT/Renderer/Backend/DX12/src/ResourceTracker.hpp index 1932cea..150e251 100644 --- a/RT/Renderer/Backend/DX12/src/ResourceTracker.hpp +++ b/RT/Renderer/Backend/DX12/src/ResourceTracker.hpp @@ -16,9 +16,19 @@ namespace RT #define RT_RESOURCE_TRACKER_DEBUG_PARAMS int line__, const char *file__, #define RT_RESOURCE_TRACKER_DEBUG_ARGS __LINE__, __FILE__, #define RT_RESOURCE_TRACKER_FWD_ARGS line__, file__, - #define RT_TRACK_RESOURCE(resource, state) g_d3d.resource_tracker.Track(RT_RESOURCE_TRACKER_DEBUG_ARGS resource, state) + + // This will track any ID3D12Object* as a peristent object + #define RT_TRACK_OBJECT(object) g_d3d.resource_tracker.TrackObject(RT_RESOURCE_TRACKER_DEBUG_ARGS object) + // This will track any ID3D12Resource* as a persistent resource, and set its inital state for automatic state detection when doing resource transitions + #define RT_TRACK_RESOURCE(resource, state) g_d3d.resource_tracker.TrackObject(RT_RESOURCE_TRACKER_DEBUG_ARGS resource, state) + // This will track an object as temporary, meaning that it will be released auomatically when the fence value of the command list has been reached. + // Note: If the object passed in here has not been tracked as persistent before, it will create a new resource entry for this resource + #define RT_TRACK_TEMP_OBJECT(object, command_list) g_d3d.resource_tracker.TrackTempObject(RT_RESOURCE_TRACKER_DEBUG_ARGS object, command_list) + // This will track a resource as temporary, meaning that it will be released auomatically when the fence value of the command list has been reached. + // Note: If the resource passed in here has not been tracked as persistent before, it will create a new resource entry for this resource and set its state to D3D12_RESOURCE_STATE_COMMON + #define RT_TRACK_TEMP_RESOURCE(resource, command_list) g_d3d.resource_tracker.TrackTempObject(RT_RESOURCE_TRACKER_DEBUG_ARGS resource, command_list) #define RT_RELEASE_RESOURCE(resource) g_d3d.resource_tracker.Release(resource) - #define RT_TRACK_TEMP_RESOURCE(resource, command_list) g_d3d.resource_tracker.TrackTemp(RT_RESOURCE_TRACKER_DEBUG_ARGS resource, command_list) + #define RT_RELEASE_OBJECT(object) g_d3d.resource_tracker.Release(object) class D3D12ResourceTracker { @@ -27,8 +37,8 @@ namespace RT // Public Methods // You have to pass RT_RESOURCE_TRACKER_DEBUG_ARGS before any other arguments. No comma after the macro. - void Track(RT_RESOURCE_TRACKER_DEBUG_PARAMS ID3D12Resource *resource, D3D12_RESOURCE_STATES initial_state); - void TrackTemp(RT_RESOURCE_TRACKER_DEBUG_PARAMS ID3D12Resource* resource, CommandList* command_list); + void TrackObject(RT_RESOURCE_TRACKER_DEBUG_PARAMS ID3D12Object* object, D3D12_RESOURCE_STATES initial_state = D3D12_RESOURCE_STATE_COMMON); + void TrackTempObject(RT_RESOURCE_TRACKER_DEBUG_PARAMS ID3D12Object* object, CommandList* command_list); D3D12_RESOURCE_STATES GetResourceState(ID3D12Resource *resource); D3D12_RESOURCE_STATES Transition(ID3D12GraphicsCommandList *list, ID3D12Resource *resource, D3D12_RESOURCE_STATES dst_state); @@ -37,7 +47,7 @@ namespace RT // Calls ->Release() on the resource and stops tracking it. // Safe to call on untracked resource or nullptrs. - void Release(ID3D12Resource *resource); + void Release(ID3D12Object* object); void ReleaseAllResources(); void ReleaseStaleTempResources(uint64_t fence_value); @@ -48,7 +58,7 @@ namespace RT { ResourceEntry *next; - ID3D12Resource *resource; + ID3D12Object *resource; D3D12_RESOURCE_STATES state; CommandList* command_list; @@ -63,14 +73,15 @@ namespace RT //------------------------------------------------------------------------ // Private Methods - ResourceEntry **FindResourceEntrySlot(ID3D12Resource *resource); - ResourceEntry *FindResourceEntry (ID3D12Resource *resource); + ResourceEntry **FindResourceEntrySlot(ID3D12Object *resource); + ResourceEntry *FindResourceEntry (ID3D12Object *resource); //------------------------------------------------------------------------ // Data ResourceEntry *m_first_free_resource; ResourceEntry *m_resource_table[1024]; + }; } \ No newline at end of file diff --git a/RT/Renderer/Backend/DX12/src/main.cpp b/RT/Renderer/Backend/DX12/src/main.cpp index 4812c4b..45963eb 100644 --- a/RT/Renderer/Backend/DX12/src/main.cpp +++ b/RT/Renderer/Backend/DX12/src/main.cpp @@ -633,12 +633,12 @@ int main(int argc, char **argv) // ------------------------------------------------------------------ // Load test meshes - RT_GLTFNode *duck = RT_LoadGLTF(&renderer_arena, "assets/models/duck/Duck.gltf"); - RT_GLTFNode *helmet = RT_LoadGLTF(&renderer_arena, "assets/models/helmet/DamagedHelmet.gltf"); - // RT_GLTFNode *sponza = RT_LoadGLTF(&renderer_arena, "assets/models/NewSponza/NewSponza_Main_glTF_002.gltf"); - RT_GLTFNode *sponza = RT_LoadGLTF(&renderer_arena, "assets/models/sponza/Sponza.gltf"); - RT_GLTFNode *chess = RT_LoadGLTF(&renderer_arena, "assets/models/ABeautifulGame/ABeautifulGame.gltf"); - RT_GLTFNode *metal_rough_spheres = RT_LoadGLTF(&renderer_arena, "assets/models/MetalRoughSpheres/MetalRoughSpheres.gltf"); + RT_GLTFNode *duck = RT_LoadGLTF(&renderer_arena, "assets/models/duck/Duck.gltf", nullptr); + RT_GLTFNode *helmet = RT_LoadGLTF(&renderer_arena, "assets/models/helmet/DamagedHelmet.gltf", nullptr); + // RT_GLTFNode *sponza = RT_LoadGLTF(&renderer_arena, "assets/models/NewSponza/NewSponza_Main_glTF_002.gltf", nullptr); + RT_GLTFNode *sponza = RT_LoadGLTF(&renderer_arena, "assets/models/sponza/Sponza.gltf", nullptr); + RT_GLTFNode *chess = RT_LoadGLTF(&renderer_arena, "assets/models/ABeautifulGame/ABeautifulGame.gltf", nullptr); + RT_GLTFNode *metal_rough_spheres = RT_LoadGLTF(&renderer_arena, "assets/models/MetalRoughSpheres/MetalRoughSpheres.gltf", nullptr); RT_TrackedMesh sponza_duck = RT_AddTrackedMesh(duck); RT_TrackedMesh beam_duck = RT_AddTrackedMesh(duck); diff --git a/RT/dx12.c b/RT/dx12.c index c3bd939..1a2b48d 100644 --- a/RT/dx12.c +++ b/RT/dx12.c @@ -46,11 +46,19 @@ void dx12_end_frame() { // Flush rasterizer RT_RasterRender(); - // Reset viewport to default RT_RasterSetViewport(0.0f, 0.0f, grd_curscreen->sc_w, grd_curscreen->sc_h); } +void dx12_set_render_target(RT_ResourceHandle texture) +{ + // Flush rasterizer + RT_RasterRender(); + + // Set the render target texture for the next raster commands + RT_RasterSetRenderTarget(texture); +} + void dx12_init_texture(grs_bitmap* bm) { bm->dxtexture = RT_ArenaAllocStruct(&g_arena, dx_texture); @@ -561,7 +569,10 @@ void dx12_ulinec(int left, int top, int right, int bot, int c) { .pos = RT_Vec3Make(xf, yf, 0.0f), .color = col }, }; - RT_RasterLines(vertices, 2); + //if (RT_RESOURCE_HANDLE_VALID(hud_render_target)) + // RT_RasterLinesToHUD(hud_render_target, vertices, 2); + //else + RT_RasterLines(vertices, 2); } // Use: render.c, terrain.c, automap.c, meddraw.c, draw.c @@ -591,6 +602,7 @@ bool g3_draw_line(g3s_point* p0, g3s_point* p1) }; RT_RasterLines(vertices, 2); + return 1; } @@ -858,6 +870,11 @@ int dx12_internal_string(int x, int y, const char* s) uint32_t* dx12_load_bitmap_pixel_data(RT_Arena* arena, grs_bitmap* bitmap) { + if (bitmap->bm_type == BM_RGBA8) + { + return bitmap->bm_data; + } + if (bitmap->bm_flags & BM_FLAG_RLE) { bitmap = rle_expand_texture(bitmap); @@ -934,7 +951,7 @@ bool dx12_ubitmapm_cs(int x, int y, int dw, int dh, grs_bitmap* bm, int c, int s dx12_loadbmtexture_f(bm, GameCfg.TexFilt); } - float xo, yo, xf, yf, u1, u2, v1, v2, color_r, color_g, color_b, h; + float xo, yo, xf, yf, u1, u2, v1, v2, color_r, color_g, color_b, color_a, h; x += grd_curcanv->cv_bitmap.bm_x; y += grd_curcanv->cv_bitmap.bm_y; @@ -994,7 +1011,16 @@ bool dx12_ubitmapm_cs(int x, int y, int dw, int dh, grs_bitmap* bm, int c, int s color_b = CPAL2Tb(c); } - RT_Vec4 col = { color_r, color_g, color_b, 1.0f }; + //NOTE (sam) + //the normal fade calculation does not seem to work here. The calculation is on the bottom of the comments.. + //so I just check that if the fade level is 0 then do not fade. Seems to be consistent with the code here. + //color_a = 1.0f - (float)grd_curcanv->cv_fade_level / ((float)GR_FADE_LEVELS - 1.0) + if (grd_curcanv->cv_fade_level >= GR_FADE_OFF || grd_curcanv->cv_fade_level == 0) + color_a = 1.0; + else + color_a = (float)grd_curcanv->cv_fade_level / ((float)GR_FADE_LEVELS - 1.0); + + RT_Vec4 col = { color_r, color_g, color_b, color_a }; RT_RasterTriVertex vertices[6] = { {.pos = { xf, yo, 0.0f }, .uv = { u2, v1 }, .color = col, .texture_index = 0 }, {.pos = { xf, yf, 0.0f }, .uv = { u2, v2 }, .color = col, .texture_index = 0 }, diff --git a/RT/dx12.h b/RT/dx12.h index 4739939..5c2a9b8 100644 --- a/RT/dx12.h +++ b/RT/dx12.h @@ -16,6 +16,7 @@ typedef struct _dx_texture void dx12_start_frame(); void dx12_end_frame(); +void dx12_set_render_target(RT_ResourceHandle hud_texture); void dx12_urect(int left, int top, int right, int bot); void dx12_init_texture(grs_bitmap* bm); diff --git a/RT/material_viewer.cpp b/RT/material_viewer.cpp index 46f9b58..064362c 100644 --- a/RT/material_viewer.cpp +++ b/RT/material_viewer.cpp @@ -11,6 +11,8 @@ extern "C" { #include "piggy.h" + #include "3d.h" + #include "globvars.h" }; #include "material_viewer.h" @@ -47,6 +49,8 @@ struct RT_MaterialViewer bool picker_open; bool highlight_blackbodies; + bool highlight_no_casting_shadows; + bool highlight_lights; bool highlight_has_normal_map; bool highlight_has_metalness_map; bool highlight_has_roughness_map; @@ -56,6 +60,23 @@ struct RT_MaterialViewer bool editing; bool recenter_on_selection; + bool suppress_hotkeys; + + float model_distance = 20.0f; + float model_offset_x = 5.5f; + float model_rotation_x; + float model_rotation_dx; + float model_rotation_y = 42.0f; + float model_rotation_dy; + float model_rotation_z; + + bool show_3d_preview = true; + uint32_t currently_rendering_material_index; + float render_next_material_timer; + float render_next_material_speed = 2.0f; + + float spin_speed; + float spin_offset; RT_MaterialMeta meta[RT_MAX_TEXTURES]; @@ -199,6 +220,56 @@ static void SelectMaterial(uint16_t bm_index) viewer.selected_material_count++; } +static void DeselectMaterial(uint16_t bm_index) +{ + if (viewer.selected_material_count > 0) + { + size_t remove_index; + for (remove_index = 0; remove_index < viewer.selected_material_count; remove_index++) + { + if (bm_index == viewer.selected_materials[remove_index]) + { + break; + } + } + + if (remove_index != viewer.selected_material_count) + { + memmove(&viewer.selected_materials[remove_index], + &viewer.selected_materials[remove_index + 1], + sizeof(uint16_t)*(viewer.selected_material_count - (remove_index + 1))); + viewer.selected_material_count--; + } + } +} + +static bool MaterialIsSelected(uint16_t bm_index) +{ + bool is_selected = false; + for (size_t i = 0; i < viewer.selected_material_count; i++) + { + if (viewer.selected_materials[i] == bm_index) + { + is_selected = true; + break; + } + } + + return is_selected; +} + +static void ToggleSelectMaterial(uint16_t bm_index) +{ + if (MaterialIsSelected(bm_index)) + { + DeselectMaterial(bm_index); + } + else + { + SelectMaterial(bm_index); + } +} + static void SelectAll() { viewer.selected_material_count = 0; @@ -374,14 +445,9 @@ static void SaveIfModified(uint16_t bm_index) if (changes & RT_MaterialModifiedFlags_Flags) { - if (material->flags & RT_MaterialFlag_BlackbodyRadiator) - { - RT_ConfigWriteInt(&cfg, RT_StringLiteral("blackbody"), 1); - } - else - { - RT_ConfigWriteInt(&cfg, RT_StringLiteral("blackbody"), 0); - } + RT_ConfigWriteInt(&cfg, RT_StringLiteral("blackbody"), !!(material->flags & RT_MaterialFlag_BlackbodyRadiator)); + RT_ConfigWriteInt(&cfg, RT_StringLiteral("no_casting_shadow"), !!(material->flags & RT_MaterialFlag_NoCastingShadow)); + RT_ConfigWriteInt(&cfg, RT_StringLiteral("is_light"), !!(material->flags & RT_MaterialFlag_Light)); } char bitmap_name[13]; @@ -442,7 +508,7 @@ void RT_DoMaterialViewerMenus() viewer.initialized = true; } - if (io.WantCaptureKeyboard) + if (io.WantCaptureKeyboard && !viewer.suppress_hotkeys) { if (io.KeyCtrl && io.KeyShift && ImGui::IsKeyPressed(ImGuiKey_A)) { @@ -544,6 +610,8 @@ void RT_DoMaterialViewerMenus() { ImGui::Checkbox("Filter on Highlighted", &viewer.filter_on_highlighted); ImGui::Checkbox("Highlight: Is Blackbody", &viewer.highlight_blackbodies); + ImGui::Checkbox("Highlight: Not casting shadows", &viewer.highlight_no_casting_shadows); + ImGui::Checkbox("Highlight: Is Light", &viewer.highlight_lights); ImGui::Checkbox("Highlight: Has Normal Map", &viewer.highlight_has_normal_map); ImGui::Checkbox("Highlight: Has Metalness Map", &viewer.highlight_has_metalness_map); ImGui::Checkbox("Highlight: Has Roughness Map", &viewer.highlight_has_roughness_map); @@ -603,6 +671,8 @@ void RT_DoMaterialViewerMenus() bool rejected_by_filter = false; bool is_blackbody = (material->flags & RT_MaterialFlag_BlackbodyRadiator); + bool is_no_casting_shadow = (material->flags & RT_MaterialFlag_NoCastingShadow); + bool is_light = (material->flags & RT_MaterialFlag_Light); bool has_normal = RT_RESOURCE_HANDLE_VALID(material->normal_texture); bool has_metalness = RT_RESOURCE_HANDLE_VALID(material->metalness_texture); bool has_roughness = RT_RESOURCE_HANDLE_VALID(material->roughness_texture); @@ -611,6 +681,8 @@ void RT_DoMaterialViewerMenus() if (viewer.filter_on_highlighted) { if (viewer.highlight_blackbodies && !is_blackbody) rejected_by_filter = true; + if (viewer.highlight_no_casting_shadows && !is_no_casting_shadow) rejected_by_filter = true; + if (viewer.highlight_lights && !is_light) rejected_by_filter = true; if (viewer.highlight_has_normal_map && !has_normal) rejected_by_filter = true; if (viewer.highlight_has_metalness_map && !has_metalness) rejected_by_filter = true; if (viewer.highlight_has_roughness_map && !has_roughness) rejected_by_filter = true; @@ -668,14 +740,19 @@ void RT_DoMaterialViewerMenus() } RT_RenderImGuiTexture(material->albedo_texture, 64, height); - ImGui::SetCursorPos(image_cursor_pos); + if (RT_RESOURCE_HANDLE_VALID(material->emissive_texture)) + { + RT_RenderImGuiTexture(material->emissive_texture, 64, height); + ImGui::SetCursorPos(image_cursor_pos); + } + if (ImGui::InvisibleButton(RT_ArenaPrintF(temp, "material_button_%d", bm_index), ImVec2(64, 64))) { if (io.KeyCtrl) { - SelectMaterial(bm_index); + ToggleSelectMaterial(bm_index); } else if (io.KeyShift) { @@ -694,8 +771,23 @@ void RT_DoMaterialViewerMenus() } else { - viewer.selected_material_count = 0; - SelectMaterial(bm_index); + if (viewer.selected_material_count > 1) + { + viewer.selected_material_count = 0; + SelectMaterial(bm_index); + } + else + { + if (MaterialIsSelected(bm_index)) + { + DeselectMaterial(bm_index); + } + else + { + viewer.selected_material_count = 0; + SelectMaterial(bm_index); + } + } } } @@ -733,6 +825,16 @@ void RT_DoMaterialViewerMenus() draw_list->AddRect(img_min, img_max, ImColor(0.5f, 1.0f, 1.0f, 0.25f)); } + if (viewer.highlight_no_casting_shadows && is_no_casting_shadow) + { + draw_list->AddRect(img_min, img_max, ImColor(0.5f, 1.0f, 1.0f, 0.25f)); + } + + if (viewer.highlight_lights && is_light) + { + draw_list->AddRect(img_min, img_max, ImColor(1.0f, 1.0f, 0.0f, 0.25f)); + } + if (viewer.highlight_has_normal_map && has_normal) { draw_list->AddRect(img_min, img_max, ImColor(0.5f, 0.5f, 1.0f, 0.25f)); @@ -785,6 +887,8 @@ void RT_DoMaterialViewerMenus() } ImGui::EndChild(); viewer.recenter_on_selection |= ImGui::InputText("Filter Textures", viewer.texture_filter, sizeof(viewer.texture_filter)); + viewer.suppress_hotkeys = ImGui::IsItemActive(); + ImGui::SameLine(); ImGui::TextDisabled("(?)"); if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort)) @@ -795,6 +899,10 @@ void RT_DoMaterialViewerMenus() ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } + if (ImGui::Button("Recenter Selection")) + { + viewer.recenter_on_selection = true; + } ImGui::Separator(); if (viewer.selected_material_count == 1) @@ -806,7 +914,17 @@ void RT_DoMaterialViewerMenus() } else if (viewer.selected_material_count > 1) { - ImGui::Text("Bitmap: Multiple"); + uint16_t first_bitmap_index = viewer.selected_materials[0]; + + char first_bitmap[13] = "Invalid"; + piggy_get_bitmap_name(first_bitmap_index, first_bitmap); + + uint16_t last_bitmap_index = viewer.selected_materials[viewer.selected_material_count - 1]; + + char last_bitmap[13] = "Invalid"; + piggy_get_bitmap_name(last_bitmap_index, last_bitmap); + + ImGui::Text("Bitmap #%hu..#%hu: %s .. %s", first_bitmap_index, last_bitmap_index, first_bitmap, last_bitmap); } else { @@ -871,6 +989,34 @@ void RT_DoMaterialViewerMenus() ImGui::EndTooltip(); } + bool no_casting_shadow = first_material->flags & RT_MaterialFlag_NoCastingShadow; + bool no_casting_shadow_changed = ImGui::Checkbox("No casting shadow", &no_casting_shadow); + active |= ImGui::IsItemActive(); + ImGui::SameLine(); + ImGui::TextDisabled("(?)"); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort)) + { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted("Determines if the mesh using this material should cast a shadow."); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + + bool is_light = first_material->flags & RT_MaterialFlag_Light; + bool is_light_changed = ImGui::Checkbox("Is Light", &is_light); + active |= ImGui::IsItemActive(); + ImGui::SameLine(); + ImGui::TextDisabled("(?)"); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort)) + { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted("Whether this material is represented in the scene as an actual area light."); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + if (!flags_equal) ImGui::PopStyleColor(); @@ -1003,6 +1149,8 @@ void RT_DoMaterialViewerMenus() } if (blackbody_changed || + no_casting_shadow_changed || + is_light_changed || metalness_changed || roughness_changed || emissive_changed) @@ -1026,16 +1174,13 @@ void RT_DoMaterialViewerMenus() RT_Material *material = &g_rt_materials[material_index]; if (blackbody_changed) - { - if (blackbody) - { - material->flags |= RT_MaterialFlag_BlackbodyRadiator; - } - else - { - material->flags &= ~RT_MaterialFlag_BlackbodyRadiator; - } - } + material->flags = RT_SET_FLAG(material->flags, RT_MaterialFlag_BlackbodyRadiator, blackbody); + + if (no_casting_shadow_changed) + material->flags = RT_SET_FLAG(material->flags, RT_MaterialFlag_NoCastingShadow, no_casting_shadow); + + if (is_light_changed) + material->flags = RT_SET_FLAG(material->flags, RT_MaterialFlag_Light, is_light); if (metalness_changed) { @@ -1069,6 +1214,21 @@ void RT_DoMaterialViewerMenus() } } + ImGui::Separator(); + ImGui::Text("3D Preview"); + ImGui::SameLine(); + ImGui::TextDisabled("(?)"); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort)) + { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted("Hold LMB to rotate the plane, RMB to move it left/right and forward/back."); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + ImGui::Checkbox("Show 3D Preview", &viewer.show_3d_preview); + ImGui::SliderFloat("Animation Speed", &viewer.render_next_material_speed, 1.0f, 60.0f); + if (viewer.show_undo_redo_debug) { ImGui::Separator(); @@ -1147,5 +1307,106 @@ void RT_DoMaterialViewerMenus() void RT_RenderMaterialViewer() { + float dt = 1.0f / 60.0f; + + if (viewer.show_3d_preview && viewer.selected_material_count > 0) + { + int current_index = viewer.currently_rendering_material_index; + + if (viewer.render_next_material_timer <= 0.0f) + { + float time_per_material = 1.0f / viewer.render_next_material_speed; + viewer.render_next_material_timer = time_per_material; + } + else + { + viewer.render_next_material_timer -= dt; + if (viewer.render_next_material_timer <= 0.0f) + { + viewer.currently_rendering_material_index++; + if (viewer.currently_rendering_material_index >= viewer.selected_material_count) + { + viewer.currently_rendering_material_index = 0; + } + } + } + + grs_bitmap *bitmap = &GameBitmaps[viewer.selected_materials[current_index]]; + + float width = 5.0f; + float height = 5.0f; + if (bitmap->bm_w > bitmap->bm_h) + { + float aspect = (float)bitmap->bm_h / (float)bitmap->bm_w; + height *= aspect; + } + else + { + float aspect = (float)bitmap->bm_w / (float)bitmap->bm_h; + height *= aspect; + } + + ImGuiIO &io = ImGui::GetIO(); + + if (!io.WantCaptureMouse) + { + if (io.MouseDown[1]) + { + viewer.model_distance -= 0.001f*io.MouseDelta.y*viewer.model_distance; + viewer.model_offset_x += 0.01f*io.MouseDelta.x; + } + else if (io.MouseDown[0]) + { + viewer.model_rotation_dy -= io.MouseDelta.x; + viewer.model_rotation_dx += io.MouseDelta.y; + } + } + + viewer.model_rotation_x += dt*viewer.model_rotation_dx; + viewer.model_rotation_y += dt*viewer.model_rotation_dy; + viewer.model_rotation_dx *= 0.95f; + viewer.model_rotation_dy *= 0.95f; + + if (viewer.model_rotation_x < -180.0f) + viewer.model_rotation_x += 360.0f; + + if (viewer.model_rotation_x > 180.0f) + viewer.model_rotation_x -= 360.0f; + + if (viewer.model_rotation_y < -180.0f) + viewer.model_rotation_y += 360.0f; + + if (viewer.model_rotation_y > 180.0f) + viewer.model_rotation_y -= 360.0f; + + viewer.model_distance = RT_CLAMP(viewer.model_distance, 10.0f, 200.0f); + + RT_Vec3 view_p = RT_Vec3Make(f2fl(View_position.x), f2fl(View_position.y), f2fl(View_position.z)); + RT_Vec3 view_f = RT_Vec3Normalize(RT_Vec3Make(f2fl(View_matrix.fvec.x), f2fl(View_matrix.fvec.y), f2fl(View_matrix.fvec.z))); + RT_Vec3 view_u = RT_Vec3Normalize(RT_Vec3Make(f2fl(View_matrix.uvec.x), f2fl(View_matrix.uvec.y), f2fl(View_matrix.uvec.z))); + RT_Vec3 view_r = RT_Vec3Normalize(RT_Vec3Make(f2fl(View_matrix.rvec.x), f2fl(View_matrix.rvec.y), f2fl(View_matrix.rvec.z))); + RT_Mat4 T = RT_Mat4FromTranslation(view_p + viewer.model_distance*view_f + viewer.model_offset_x*view_r); + RT_Mat4 basis = RT_Mat4FromBasisVectors(view_r, view_u, view_f); + RT_Mat4 Rx = RT_Mat4FromXRotation(RT_RadiansFromDegrees(viewer.model_rotation_x)); + RT_Mat4 Ry = RT_Mat4FromYRotation(RT_RadiansFromDegrees(viewer.model_rotation_y + 180.0f - viewer.spin_offset)); + RT_Mat4 Rz = RT_Mat4FromZRotation(RT_RadiansFromDegrees(viewer.model_rotation_z)); + RT_Mat4 R = basis*Ry*Rx*Rz; + RT_Mat4 S = RT_Mat4FromScale(RT_Vec3Make(width, height, 1.0f)); + RT_Mat4 transform = T*R*S; + + RT_RenderMeshParams params = {}; + params.mesh_handle = RT_GetBillboardMesh(); + params.color = 0xFFFFFFFF; + params.key.value = 0x800815; + params.material_override = viewer.selected_materials[current_index]; + params.transform = &transform; + RT_RaytraceMeshEx(¶ms); + + viewer.spin_offset += 45.0f*viewer.spin_speed / 60.0f; // Assumes hardcoded 60 fps. Silly but it's a debug tool, don't care to figure out where frametime is kept. + if (viewer.spin_offset > 360.0f) + { + viewer.spin_offset -= 360.0f; + } + } } diff --git a/d1/2d/pcx.c b/d1/2d/pcx.c index 2ede821..32e61d9 100644 --- a/d1/2d/pcx.c +++ b/d1/2d/pcx.c @@ -26,6 +26,10 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #include "pcx.h" #include "physfsx.h" +#ifdef RT_DX12 +#include "Core/Arena.h" +#include "ImageReadWrite.h" +#endif int pcx_encode_byte(ubyte byt, ubyte cnt, PHYSFS_file *fid); int pcx_encode_line(ubyte *inBuff, int inLen, PHYSFS_file *fp); @@ -183,6 +187,29 @@ int bald_guy_load( char * filename, grs_bitmap * bmp,int bitmap_type ,ubyte * pa int pcx_read_bitmap( char * filename, grs_bitmap * bmp,int bitmap_type ,ubyte * palette ) { +#ifdef RT_DX12 + // Just call me Butch Cassidy because this is a hijacking + char *ext = strchr(filename, '.'); + if (strcmp(ext, ".png") == 0) + { + RT_ArenaMemoryScope(&g_thread_arena) + { + int w, h, c; + unsigned char *pixels = RT_LoadImageFromDisk(&g_thread_arena, filename, &w, &h, &c, 4); + + if (!pixels) + return PCX_ERROR_OPENING; + + // haha im going to hell + unsigned char *pixels_copy = d_malloc(w*h*sizeof(uint32_t)); + memcpy(pixels_copy, pixels, w*h*sizeof(uint32_t)); + + gr_init_bitmap(bmp, BM_RGBA8, 0, 0, w, h, 4*w, pixels_copy); + } + return PCX_ERROR_NONE; + } +#endif + PCXHeader header; PHYSFS_file * PCXfile; int i, row, col, count, xsize, ysize; diff --git a/d1/CMakeLists.txt b/d1/CMakeLists.txt index 3e59550..3dcd6e5 100644 --- a/d1/CMakeLists.txt +++ b/d1/CMakeLists.txt @@ -1,295 +1,295 @@ -# CMakeList.txt : CMake project for D1-Raytraced, include source and define -# project specific logic here. -# -cmake_minimum_required (VERSION 3.13) -project(descent1) -add_compile_definitions(PUBLIC -HAVE_STRUCT_TIMEVAL -IPv6 -NETWORK -NO_ASM -WINDOWS_IGNORE_PACKING_MISMATCH -USE_TRACKER) - -if(${GRAPHICS_API} STREQUAL "DirectX12") - #Raytracing interface Source code -set(Graphic_Includes - "$ENV{RT_EXT_CODE_DIR}/RTgr.c" - "$ENV{RT_EXT_CODE_DIR}/RTgr.h" - "$ENV{RT_EXT_CODE_DIR}/Game/Level.h" - "$ENV{RT_EXT_CODE_DIR}/Game/Level.c" - "$ENV{RT_EXT_CODE_DIR}/Game/Lights.h" - "$ENV{RT_EXT_CODE_DIR}/Game/Lights.c" - "$ENV{RT_EXT_CODE_DIR}/dx12.c" - "$ENV{RT_EXT_CODE_DIR}/dx12.h" - "$ENV{RT_EXT_CODE_DIR}/polymodel_viewer.cpp" - "$ENV{RT_EXT_CODE_DIR}/polymodel_viewer.h" - "$ENV{RT_EXT_CODE_DIR}/material_viewer.cpp" - "$ENV{RT_EXT_CODE_DIR}/material_viewer.h" - "$ENV{RT_EXT_CODE_DIR}/RTmaterials.c" - "$ENV{RT_EXT_CODE_DIR}/RTmaterials.h" -) -set (Graphic_Libs -Renderer -) -elseif(${GRAPHICS_API} STREQUAL "OpenGL") -set(Graphic_Includes - "arch/ogl/gr.c" - "arch/ogl/ogl.c" -) -set (Graphic_Libs - opengl32 - glu32 -) -endif() - -if(DEFINED ENV{EDITOR}) -file(GLOB EDITOR_SOURCES - "editor/*.c" -) - -file(GLOB UI_SOURCES - "ui/*.c" -) -endif() - -if(CMAKE_BUILD_TYPE MATCHES Release) -#disable console on release. -add_executable(descent1 WIN32) -else() -add_executable(descent1) -endif() - -target_sources(descent1 PRIVATE - ${UI_SOURCES} - ${EDITOR_SOURCES} - - #non-raytracing extensions on the engine. - $ENV{RT_EXT_CODE_DIR}/RText.c - $ENV{RT_EXT_CODE_DIR}/RText.h - - "2d/2dsline.c" - "2d/bitblt.c" - "2d/bitmap.c" - "2d/box.c" - "2d/canvas.c" - "2d/circle.c" - "2d/disc.c" - "2d/font.c" - "2d/gpixel.c" - "2d/line.c" - "2d/palette.c" - "2d/pcx.c" - "2d/pixel.c" - "2d/poly.c" - "2d/rect.c" - "2d/rle.c" - "2d/scalec.c" - "3d/clipper.c" - "3d/draw.c" - "3d/globvars.c" - "3d/instance.c" - "3d/interp.c" - "3d/matrix.c" - "3d/points.c" - "3d/rod.c" - "3d/setup.c" - "arch/sdl/event.c" - "arch/sdl/init.c" - "arch/sdl/joy.c" - "arch/sdl/key.c" - "arch/sdl/mouse.c" - "arch/sdl/rbaudio.c" - "arch/sdl/timer.c" - "arch/sdl/window.c" - "arch/sdl/digi.c" - "arch/sdl/digi_audio.c" - "iff/iff.c" - "main/ai.c" - "main/aipath.c" - "main/automap.c" - "main/bm.c" - "main/bmread.c" - "main/cntrlcen.c" - "main/collide.c" - "main/config.c" - "main/console.c" - "main/controls.c" - "main/credits.c" - "main/custom.c" - "main/digiobj.c" - "main/dumpmine.c" - "main/effects.c" - "main/endlevel.c" - "main/fireball.c" - "main/fuelcen.c" - "main/fvi.c" - "main/game.c" - "main/gamecntl.c" - "main/gamefont.c" - "main/gamemine.c" - "main/gamerend.c" - "main/gamesave.c" - "main/gameseg.c" - "main/gameseq.c" - "main/gauges.c" - "main/hostage.c" - "main/hud.c" - "main/inferno.c" - "main/kconfig.c" - "main/kmatrix.c" - "main/laser.c" - "main/lighting.c" - "main/menu.c" - "main/mglobal.c" - "main/mission.c" - "main/morph.c" - "main/multi.c" - "main/multibot.c" - "main/newdemo.c" - "main/newmenu.c" - "main/object.c" - "main/paging.c" - "main/physics.c" - "main/piggy.c" - "main/player.c" - "main/playsave.c" - "main/polyobj.c" - "main/powerup.c" - "main/render.c" - "main/robot.c" - "main/scores.c" - "main/slew.c" - "main/snddecom.c" - "main/songs.c" - "main/state.c" - "main/switch.c" - "main/terrain.c" - "main/texmerge.c" - "main/text.c" - "main/titles.c" - "main/vclip.c" - "main/wall.c" - "main/weapon.c" - "maths/fixc.c" - "maths/rand.c" - "maths/tables.c" - "maths/vecmat.c" - "mem/mem.c" - "misc/args.c" - "misc/dl_list.c" - "misc/error.c" - "misc/hash.c" - "misc/hmp.c" - "misc/ignorecase.c" - "misc/physfsx.c" - "misc/strio.c" - "misc/strutil.c" - "misc/logger.c" - "texmap/ntmap.c" - "texmap/scanline.c" - - #network - "main/net_udp.c" - - ${Graphic_Includes} -) - - - -target_include_directories(descent1 PRIVATE -"include" -"include/editor" -"main" -"arch/include" -"arch" -"3d" -"../SDL" -"../sdl-master" -"../sdl-master/sdl" -"../sdl-master/sdl/include" -"../physfs-main/src" -$ENV{RT_EXT_CODE_DIR} -) - -target_link_libraries(descent1 -physfs-static -sdlmain -sdl -dxguid -Winmm -Ws2_32 -dinput8 -${Graphic_Libs} -) - -install(TARGETS descent1 - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - -if(${GRAPHICS_API} STREQUAL "DirectX12") -#copy shaders when a change happened. -add_custom_target(game_copy_shaders ALL - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${CMAKE_SOURCE_DIR}/RT/Renderer/Backend/DX12/assets/shaders" - ${PROJECT_BINARY_DIR}/assets/shaders - COMMENT "Copying DX12 asset folder to output d1 folder") - -add_dependencies(descent1 game_copy_shaders) - -install(DIRECTORY "${CMAKE_SOURCE_DIR}/RT/Renderer/Backend/DX12/assets/shaders" DESTINATION "${CMAKE_INSTALL_BINDIR}/assets") - - -add_custom_target(game_copy_textures ALL - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${CMAKE_SOURCE_DIR}/RT/Renderer/Backend/DX12/assets/textures" - ${PROJECT_BINARY_DIR}/assets/textures - COMMENT "Copying DX12 asset folder to output d1 folder") - -add_dependencies(descent1 game_copy_textures) - -install(DIRECTORY "${CMAKE_SOURCE_DIR}/RT/Renderer/Backend/DX12/assets/textures" DESTINATION "${CMAKE_INSTALL_BINDIR}/assets") - -#copy assets when a change happened. -add_custom_target(game_copy_custom_assets ALL - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${PROJECT_SOURCE_DIR}/assets" - ${PROJECT_BINARY_DIR}/assets - COMMENT "Copying Descent custom assets folder to output d1 folder") - -add_dependencies(descent1 game_copy_custom_assets) - -install(DIRECTORY "${CMAKE_SOURCE_DIR}/d1/assets" DESTINATION ${CMAKE_INSTALL_BINDIR}) -else() - -#copy only the splash screens for OpenGL. -add_custom_target(game_copy_splash_logo ALL - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${PROJECT_SOURCE_DIR}/assets/splash-logo" - ${PROJECT_BINARY_DIR}/assets/splash-logo - COMMENT "Copying Descent custom assets folder to output d1 folder") - - -install(DIRECTORY "${PROJECT_SOURCE_DIR}/d1/assets/splash-logo" DESTINATION ${CMAKE_INSTALL_BINDIR}/assets/splash-logo) - -add_dependencies(descent1 game_copy_splash_logo) -endif() - - - -if(EXISTS "${CMAKE_SOURCE_DIR}/descent.hog") -add_custom_command(TARGET descent1 POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - "${CMAKE_SOURCE_DIR}/descent.hog" - $ - COMMENT "copying descent.hog to output d1 folder") -endif() -if(EXISTS "${CMAKE_SOURCE_DIR}/descent.pig") -add_custom_command(TARGET descent1 POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - "${CMAKE_SOURCE_DIR}/descent.pig" - $ - COMMENT "copying descent.pig to output d1 folder") +# CMakeList.txt : CMake project for D1-Raytraced, include source and define +# project specific logic here. +# +cmake_minimum_required (VERSION 3.13) +project(descent1) +add_compile_definitions(PUBLIC +HAVE_STRUCT_TIMEVAL +IPv6 +NETWORK +NO_ASM +WINDOWS_IGNORE_PACKING_MISMATCH +USE_TRACKER) + +if(${GRAPHICS_API} STREQUAL "DirectX12") + #Raytracing interface Source code +set(Graphic_Includes + "$ENV{RT_EXT_CODE_DIR}/RTgr.c" + "$ENV{RT_EXT_CODE_DIR}/RTgr.h" + "$ENV{RT_EXT_CODE_DIR}/Game/Level.h" + "$ENV{RT_EXT_CODE_DIR}/Game/Level.c" + "$ENV{RT_EXT_CODE_DIR}/Game/Lights.h" + "$ENV{RT_EXT_CODE_DIR}/Game/Lights.c" + "$ENV{RT_EXT_CODE_DIR}/dx12.c" + "$ENV{RT_EXT_CODE_DIR}/dx12.h" + "$ENV{RT_EXT_CODE_DIR}/polymodel_viewer.cpp" + "$ENV{RT_EXT_CODE_DIR}/polymodel_viewer.h" + "$ENV{RT_EXT_CODE_DIR}/material_viewer.cpp" + "$ENV{RT_EXT_CODE_DIR}/material_viewer.h" + "$ENV{RT_EXT_CODE_DIR}/RTmaterials.c" + "$ENV{RT_EXT_CODE_DIR}/RTmaterials.h" +) +set (Graphic_Libs +Renderer +) +elseif(${GRAPHICS_API} STREQUAL "OpenGL") +set(Graphic_Includes + "arch/ogl/gr.c" + "arch/ogl/ogl.c" +) +set (Graphic_Libs + opengl32 + glu32 +) +endif() + +if(DEFINED ENV{EDITOR}) +file(GLOB EDITOR_SOURCES + "editor/*.c" +) + +file(GLOB UI_SOURCES + "ui/*.c" +) +endif() + +if(CMAKE_BUILD_TYPE MATCHES Release) +#disable console on release. +add_executable(descent1 WIN32) +else() +add_executable(descent1) +endif() + +target_sources(descent1 PRIVATE + ${UI_SOURCES} + ${EDITOR_SOURCES} + + #non-raytracing extensions on the engine. + $ENV{RT_EXT_CODE_DIR}/RText.c + $ENV{RT_EXT_CODE_DIR}/RText.h + + "2d/2dsline.c" + "2d/bitblt.c" + "2d/bitmap.c" + "2d/box.c" + "2d/canvas.c" + "2d/circle.c" + "2d/disc.c" + "2d/font.c" + "2d/gpixel.c" + "2d/line.c" + "2d/palette.c" + "2d/pcx.c" + "2d/pixel.c" + "2d/poly.c" + "2d/rect.c" + "2d/rle.c" + "2d/scalec.c" + "3d/clipper.c" + "3d/draw.c" + "3d/globvars.c" + "3d/instance.c" + "3d/interp.c" + "3d/matrix.c" + "3d/points.c" + "3d/rod.c" + "3d/setup.c" + "arch/sdl/event.c" + "arch/sdl/init.c" + "arch/sdl/joy.c" + "arch/sdl/key.c" + "arch/sdl/mouse.c" + "arch/sdl/rbaudio.c" + "arch/sdl/timer.c" + "arch/sdl/window.c" + "arch/sdl/digi.c" + "arch/sdl/digi_audio.c" + "iff/iff.c" + "main/ai.c" + "main/aipath.c" + "main/automap.c" + "main/bm.c" + "main/bmread.c" + "main/cntrlcen.c" + "main/collide.c" + "main/config.c" + "main/console.c" + "main/controls.c" + "main/credits.c" + "main/custom.c" + "main/digiobj.c" + "main/dumpmine.c" + "main/effects.c" + "main/endlevel.c" + "main/fireball.c" + "main/fuelcen.c" + "main/fvi.c" + "main/game.c" + "main/gamecntl.c" + "main/gamefont.c" + "main/gamemine.c" + "main/gamerend.c" + "main/gamesave.c" + "main/gameseg.c" + "main/gameseq.c" + "main/gauges.c" + "main/hostage.c" + "main/hud.c" + "main/inferno.c" + "main/kconfig.c" + "main/kmatrix.c" + "main/laser.c" + "main/lighting.c" + "main/menu.c" + "main/mglobal.c" + "main/mission.c" + "main/morph.c" + "main/multi.c" + "main/multibot.c" + "main/newdemo.c" + "main/newmenu.c" + "main/object.c" + "main/paging.c" + "main/physics.c" + "main/piggy.c" + "main/player.c" + "main/playsave.c" + "main/polyobj.c" + "main/powerup.c" + "main/render.c" + "main/robot.c" + "main/scores.c" + "main/slew.c" + "main/snddecom.c" + "main/songs.c" + "main/state.c" + "main/switch.c" + "main/terrain.c" + "main/texmerge.c" + "main/text.c" + "main/titles.c" + "main/vclip.c" + "main/wall.c" + "main/weapon.c" + "maths/fixc.c" + "maths/rand.c" + "maths/tables.c" + "maths/vecmat.c" + "mem/mem.c" + "misc/args.c" + "misc/dl_list.c" + "misc/error.c" + "misc/hash.c" + "misc/hmp.c" + "misc/ignorecase.c" + "misc/physfsx.c" + "misc/strio.c" + "misc/strutil.c" + "misc/logger.c" + "texmap/ntmap.c" + "texmap/scanline.c" + + #network + "main/net_udp.c" + + ${Graphic_Includes} +) + + + +target_include_directories(descent1 PRIVATE +"include" +"include/editor" +"main" +"arch/include" +"arch" +"3d" +"../SDL" +"../sdl-master" +"../sdl-master/sdl" +"../sdl-master/sdl/include" +"../physfs-main/src" +$ENV{RT_EXT_CODE_DIR} +) + +target_link_libraries(descent1 +physfs-static +sdlmain +sdl +dxguid +Winmm +Ws2_32 +dinput8 +${Graphic_Libs} +) + +install(TARGETS descent1 + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +if(${GRAPHICS_API} STREQUAL "DirectX12") +#copy shaders when a change happened. +add_custom_target(game_copy_shaders ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_SOURCE_DIR}/RT/Renderer/Backend/DX12/assets/shaders" + ${PROJECT_BINARY_DIR}/assets/shaders + COMMENT "Copying DX12 asset folder to output d1 folder") + +add_dependencies(descent1 game_copy_shaders) + +install(DIRECTORY "${CMAKE_SOURCE_DIR}/RT/Renderer/Backend/DX12/assets/shaders" DESTINATION "${CMAKE_INSTALL_BINDIR}/assets") + + +add_custom_target(game_copy_textures ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_SOURCE_DIR}/RT/Renderer/Backend/DX12/assets/textures" + ${PROJECT_BINARY_DIR}/assets/textures + COMMENT "Copying DX12 asset folder to output d1 folder") + +add_dependencies(descent1 game_copy_textures) + +install(DIRECTORY "${CMAKE_SOURCE_DIR}/RT/Renderer/Backend/DX12/assets/textures" DESTINATION "${CMAKE_INSTALL_BINDIR}/assets") + +#copy assets when a change happened. +add_custom_target(game_copy_custom_assets ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${PROJECT_SOURCE_DIR}/assets" + ${PROJECT_BINARY_DIR}/assets + COMMENT "Copying Descent custom assets folder to output d1 folder") + +add_dependencies(descent1 game_copy_custom_assets) + +install(DIRECTORY "${CMAKE_SOURCE_DIR}/d1/assets" DESTINATION ${CMAKE_INSTALL_BINDIR}) +else() + +#copy only the splash screens for OpenGL. +add_custom_target(game_copy_splash_logo ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${PROJECT_SOURCE_DIR}/assets/splash-logo" + ${PROJECT_BINARY_DIR}/assets/splash-logo + COMMENT "Copying Descent custom assets folder to output d1 folder") + + +install(DIRECTORY "${PROJECT_SOURCE_DIR}/d1/assets/splash-logo" DESTINATION ${CMAKE_INSTALL_BINDIR}/assets/splash-logo) + +add_dependencies(descent1 game_copy_splash_logo) +endif() + + + +if(EXISTS "${CMAKE_SOURCE_DIR}/descent.hog") +add_custom_command(TARGET descent1 POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_SOURCE_DIR}/descent.hog" + $ + COMMENT "copying descent.hog to output d1 folder") +endif() +if(EXISTS "${CMAKE_SOURCE_DIR}/descent.pig") +add_custom_command(TARGET descent1 POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_SOURCE_DIR}/descent.pig" + $ + COMMENT "copying descent.pig to output d1 folder") endif() \ No newline at end of file diff --git a/d1/assets/cockpit_prototype.bin b/d1/assets/cockpit_prototype.bin new file mode 100644 index 0000000..6ec3507 Binary files /dev/null and b/d1/assets/cockpit_prototype.bin differ diff --git a/d1/assets/cockpit_prototype.gltf b/d1/assets/cockpit_prototype.gltf index f21355b..136e6cc 100644 --- a/d1/assets/cockpit_prototype.gltf +++ b/d1/assets/cockpit_prototype.gltf @@ -1,120 +1,364 @@ { - "asset" : { - "generator" : "Khronos glTF Blender I/O v3.4.50", - "version" : "2.0" - }, - "scene" : 0, - "scenes" : [ - { - "name" : "Scene", - "nodes" : [ - 0 - ] - } - ], - "nodes" : [ - { - "mesh" : 0, - "name" : "SM_Cockpit" - } - ], - "materials" : [ - { - "doubleSided" : true, - "name" : "lambert1", - "pbrMetallicRoughness" : { - "baseColorFactor" : [ - 0.5, - 0.5, - 0.5, - 1 - ], - "roughnessFactor" : 0.036363635212183 - } - } - ], - "meshes" : [ - { - "name" : "Mesh", - "primitives" : [ - { - "attributes" : { - "POSITION" : 0, - "TEXCOORD_0" : 1, - "NORMAL" : 2 - }, - "indices" : 3, - "material" : 0 - } - ] - } - ], - "accessors" : [ - { - "bufferView" : 0, - "componentType" : 5126, - "count" : 1978, - "max" : [ - 1.6401258707046509, - 1.0565125942230225, - 1.7131730318069458 - ], - "min" : [ - -1.6401267051696777, - -0.8210800290107727, - -2.021381284578183e-08 - ], - "type" : "VEC3" - }, - { - "bufferView" : 1, - "componentType" : 5126, - "count" : 1978, - "type" : "VEC2" - }, - { - "bufferView" : 2, - "componentType" : 5126, - "count" : 1978, - "type" : "VEC3" - }, - { - "bufferView" : 3, - "componentType" : 5123, - "count" : 4776, - "type" : "SCALAR" - } - ], - "bufferViews" : [ - { - "buffer" : 0, - "byteLength" : 23736, - "byteOffset" : 0, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 15824, - "byteOffset" : 23736, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 23736, - "byteOffset" : 39560, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 9552, - "byteOffset" : 63296, - "target" : 34963 - } - ], - "buffers" : [ - { - "byteLength" : 72848, - "uri" : "data:application/octet-stream;base64,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rTeMv6umDL84+xk/rTeMv6umDL84+xk/rTeMv6umDL84+xk/zvdov3a7pb2qgGKysDeMv0Dmt77+//8+S6pKv00yUr/8//8+S6pKv00yUr/8//8+rTeMvzsK5L45+xk/rTeMvzsK5L45+xk/rTeMvzsK5L45+xk/NRrIvz/mt75mChU/NRrIvz/mt75mChU/NGdUv2jFEb/9//8+NGdUv2jFEb/9//8+NGdUv2jFEb/9//8+1ZOLv08XCr+Vihw/1ZOLv08XCr+Vihw/1ZOLv08XCr+Vihw/sDeMv8zM2b7+//8+sDeMv8zM2b7+//8+sDeMv8zM2b7+//8+2lWSv9deTr7///8+2lWSv9deTr7///8+2lWSv9deTr7///8+2lWSv+Y+ar7///8+2lWSvz0Z/r1lZuY+2lWSvz0Z/r1lZuY+2lWSvz0Z/r1lZuY+2lWSv9deTr5lZuY+2lWSv9deTr5lZuY+2lWSv9deTr5lZuY+2lWSv9deTr5lZuY+/++Kv6umDL84+xk//++Kv6umDL84+xk//++Kv6umDL84+xk//++Kv08XCr+Vihw//++Kv08XCr+Vihw//++Kv08XCr+Vihw/V5WHvzMZ/r2loq2yV5WHvzMZ/r2loq2y11WSv0Dmt77+//8+11WSv0Dmt77+//8+11WSv0Dmt77+//8+sDeMv2fFEb/9//8+sDeMv2fFEb/9//8+sDeMv2fFEb/9//8+NRrIv0Dmt77+//8+NRrIv0Dmt77+//8+11WSv8zM2b7+//8+11WSv8zM2b7+//8+11WSv8zM2b7+//8+2lWSvzMZ/r2loq2yNGdUv+8hUr/8//8+NGdUv+8hUr/8//8+OBrIvz0Z/r1lZuY+OBrIvz0Z/r1lZuY+OBrIv9deTr5lZuY+OBrIv9deTr5lZuY+OBrIv9deTr7///8+OBrIv9deTr7///8+OBrIv1FNar7///8+sDeMv+whUr/8//8+sDeMv+whUr/8//8+OBrIvzMZ/r2loq2ycDUIPiZnA79BSds/mTUIviZnA79BSds/bZdHPmTgt741moY/bZdHPmTgt741moY/b5dHPvY4nL40moY/b5dHPvY4nL40moY/lZdHvmTgt740moY/lZdHvmTgt740moY/mJdHvvY4nL40moY/mJdHvvY4nL40moY/lZdHvkogqr76Dng/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K4GavZpm973/3gI/K4GavZpm973/3gI/2YCaPfH1173///8+2YCaPfH1173///8+2YCaPfH1173///8+2YCaPZpm973/3gI/2YCaPZpm973/3gI/8igCPvH1173///8+8igCPvH1173///8+8igCPppm973/3gI/uwkzPvH1173///8+uwkzPvH1173///8+uwkzPvH1173///8+uwkzPppm973/3gI/uwkzPppm973/3gI/K4GaveoRAL59FQI/K4GaveoRAL59FQI/K4GavYBN272icP0+K4GavYBN272icP0+dtajtOoRAL59FQI/dtajtIBN272icP0+2YCaPeoRAL59FQI/2YCaPeoRAL59FQI/2YCaPYBN272icP0+2YCaPYBN272icP0+K4GavTKEIr5XER0/K4GavTKEIr5XER0/K4GavTKEIr5XER0/dtajtDKEIr5XER0/dtajtDKEIr5XER0/2YCaPTKEIr5XER0/2YCaPTKEIr5XER0/2YCaPTKEIr5XER0/dtajtIaLvL2icP0+dtajtIaLvL2icP0+LIGavYaLvL2icP0+LIGavYaLvL2icP0+LIGavYaLvL2icP0+2oCaPYaLvL2icP0+2oCaPYaLvL2icP0+2oCaPYaLvL2icP0+NRrIv0Xmt77nL9s/11WSv0Hmt77tTk8/11WSv0Hmt77tTk8/sDeMv8nM2b7tTk8/sDeMv8nM2b7tTk8/2VWSv8nM2b7tTk8/2VWSv8nM2b7tTk8/sDeMv+0hUr/sTk8/rzeMv2bFEb/sTk8/AfCKvzIK5L7tTk8/AfCKvzIK5L7tTk8//++Kv+so6b7tTk8//++Kv+so6b7tTk8/15OLv+0o6b7tTk8/15OLv+0o6b7tTk8/rTeMv62mDL/sTk8/rTeMv62mDL/sTk8/sDeMvzYK5L7tTk8/sDeMvzYK5L7tTk8/1JOLv1EXCr/tTk8/1JOLv1EXCr/tTk8//++Kv1EXCr/tTk8//++Kv1EXCr/tTk8//++Kv62mDL/sTk8//++Kv62mDL/sTk8/NRrIv0Dmt77tTk8/sDeMv+bcI7/gGUE/sDeMv+bcI7/gGUE/sDeMv+bcI7/gGUE/rzeMv4ZSE7/gGUE/rzeMv4ZSE7/gGUE/rzeMv4ZSE7/gGUE/sDeMv+bcI784+xk/sDeMv+bcI784+xk/sDeMv+bcI784+xk/sDeMv4ZSE784+xk/sDeMv4ZSE784+xk/sDeMv4ZSE784+xk/SdGFv+fcI7/gGUE/SdGFv+fcI7/gGUE/SdGFv+fcI7/gGUE/SdGFv4dSE7/gGUE/SdGFv4dSE7/gGUE/SdGFv4dSE7/gGUE/SdGFv+fcI784+xk/SdGFv+fcI784+xk/SdGFv+fcI784+xk/SdGFv4dSE784+xk/SdGFv4dSE784+xk/SdGFv4dSE784+xk/sDeMv4dSE7812Is/sDeMv4dSE7812Is/sDeMv4dSE7812Is/sDeMv+fcI7812Is/sDeMv+fcI7812Is/sDeMv+fcI7812Is/sDeMv+fcI78WsWw/sDeMv+fcI78WsWw/sDeMv+fcI78WsWw/rzeMv4ZSE78WsWw/rzeMv4ZSE78WsWw/rzeMv4ZSE78WsWw/SdGFv4lSE7812Is/SdGFv4lSE7812Is/SdGFv4lSE7812Is/SdGFv+jcI7812Is/SdGFv+jcI7812Is/SdGFv+jcI7812Is/SdGFv+jcI78WsWw/SdGFv+jcI78WsWw/SdGFv+jcI78WsWw/SdGFv4dSE78WsWw/SdGFv4dSE78WsWw/SdGFv4dSE78WsWw/fASJv+bcI7/gGUE/fASJv+bcI7/gGUE/fASJv4ZSE7/gGUE/fASJv4ZSE7/gGUE/fASJv4ZSE784+xk/fASJv4ZSE784+xk/fASJv+bcI784+xk/fASJv+bcI784+xk/fQSJv4hSE7812Is/fQSJv4hSE7812Is/fASJv4dSE78WsWw/fASJv4dSE78WsWw/fQSJv+fcI78WsWw/fQSJv+fcI78WsWw/fQSJv+fcI7812Is/fQSJv+fcI7812Is/sDeMv6rzMb/8//8+sDeMv6rzMb/8//8+sDeMv7mXG7/mL9s/sDeMv7eXG7812Is/sDeMv7eXG7812Is/fQSJv7eXG7812Is/SdGFv7iXG7812Is/SdGFv7iXG7812Is/SdGFv7eXG78WsWw/SdGFv7eXG78WsWw/rzeMv7eXG78WsWw/rzeMv7eXG78WsWw/rzeMv7aXG7/sTk8/rzeMv7aXG7/gGUE/rzeMv7aXG7/gGUE/SdGFv7eXG7/gGUE/SdGFv7eXG7/gGUE/SdGFv7eXG784+xk/SdGFv7eXG784+xk/fASJv7aXG784+xk/sDeMv7aXG784+xk/sDeMv7aXG784+xk/sDeMv6nzMb9lChU/fASJv28KIL/gGUE/fASJv28KIL/gGUE/fASJv/4kF78VsWw/fASJv/4kF78VsWw/fQSJv3AKIL8VsWw/fQSJv3AKIL8VsWw/fQSJv/0kF7/gGUE/fQSJv/0kF7/gGUE/IMuGv7iXG78VsWw/IMuGv7iXG78VsWw/2T2Lv7WXG78VsWw/2T2Lv7WXG78VsWw/2T2Lv7iXG7/gGUE/2T2Lv7iXG7/gGUE/IMuGv7WXG7/gGUE/IMuGv7WXG7/gGUE/5HGHv4JyGL/gGUE/5HGHv4JyGL/gGUE/FpeKv+q8Hr/gGUE/FpeKv+q8Hr/gGUE/FpeKv+q8Hr/gGUE/FpeKv4RyGL/gGUE/FpeKv4RyGL/gGUE/43GHv+i8Hr/gGUE/43GHv+i8Hr/gGUE/FpeKv4NyGL8VsWw/FpeKv4NyGL8VsWw/5HGHv+q8Hr8VsWw/5HGHv+q8Hr8VsWw/43GHv4VyGL8VsWw/43GHv4VyGL8VsWw/FpeKv+m8Hr8VsWw/FpeKv+m8Hr8VsWw/FpeKv+m8Hr8VsWw/q6k9v2nFUD2w2Ss+q6k9v2nFUD2w2Ss+JlM2vzFNaLt7dxQ+JlM2vzFNaLt7dxQ+JlM2vzFNaLt7dxQ+JlM2vzFNaLt7dxQ+UCdRv2xo8DxwmCs+UCdRv2xo8DxwmCs+gCRJvw0U77woFBU+gCRJvw0U77woFBU+gCRJvw0U77woFBU+gCRJvw0U77woFBU+vnBpv8QaUj6FD5g+vnBpv8QaUj6FD5g+oGdVv/21Zj4NuJY+oGdVv/21Zj4NuJY+oYaGv8dC3D4sngw/oYaGv8dC3D4sngw/jzh5v38O6D7lJAw/jzh5v38O6D7lJAw/MRiOv+RNHz9nRk8/MRiOv+RNHz9nRk8/IhuYv8dvGT+UGFE/IhuYv8dvGT+UGFE/Uruov79vOT/iYIg/Uruov79vOT/iYIg/Wd+ev0R9Pz9hPoc/Wd+ev0R9Pz9hPoc/K1m3v+DXUD/VMag/K1m3v+DXUD/VMag/DZqtv1pYVz9CIqc/DZqtv1pYVz9CIqc/0mvJvzg2bT/1Kdc/0mvJvzg2bT/1Kdc/i5S/v0CadD+6Ydc/i5S/v0CadD+6Ydc/HFM2PzFNaLt6dxQ+HFM2PzFNaLt6dxQ+HFM2PzFNaLt6dxQ+HFM2PzFNaLt6dxQ+dSRJPw0U77woFBU+dSRJPw0U77woFBU+dSRJPw0U77woFBU+dSRJPw0U77woFBU+RSdRP2xo8DxwmCs+RSdRP2xo8DxwmCs+oak9P2nFUD2w2Ss+oak9P2nFUD2w2Ss+tHBpP8QaUj6FD5g+tHBpP8QaUj6FD5g+lWdVP/21Zj4NuJY+lWdVP/21Zj4NuJY+nIaGP8dC3D4sngw/nIaGP8dC3D4sngw/hTh5P38O6D7lJAw/hTh5P38O6D7lJAw/HRuYP8dvGT+UGFE/HRuYP8dvGT+UGFE/LBiOP+RNHz9nRk8/LBiOP+RNHz9nRk8/TbuoP79vOT/iYIg/TbuoP79vOT/iYIg/VN+eP0R9Pz9iPoc/VN+eP0R9Pz9iPoc/Jlm3P+DXUD/VMag/Jlm3P+DXUD/VMag/B5qtP1pYVz9CIqc/B5qtP1pYVz9CIqc/zWvJPzs2bT/1Kdc/zWvJPzs2bT/1Kdc/hpS/P0KadD+6Ydc/hpS/P0KadD+6Ydc/rk8+v1SRLT0eUzk+rk8+v1SRLT0eUzk+F7g3v/BWvLuLnSQ+F7g3v/BWvLuLnSQ+F7g3v/BWvLuLnSQ+goBPv/qCzTzN1Tk+goBPv/qCzTzN1Tk+nhlIvyJe5rx5SyU+nhlIvyJe5rx5SyU+nhlIvyJe5rx5SyU+lZVnv230Sj7qWZ4+lZVnv230Sj7qWZ4+fdxVv6ZQWz41cZw+fdxVv6ZQWz41cZw+YIKFvxvi1z6uXQ8/YIKFvxvi1z6uXQ8/Znh5v7984T7ugQ4/Znh5v7984T7ugQ4/tB+OvyDGGz/wQVE/tB+OvyDGGz/wQVE/1wWXv84SFz/xklM/1wWXv84SFz/xklM/bZinv5TqNj+ifIk/bZinv5TqNj+ifIk/BNaev8LJOz+gEYg/BNaev8LJOz+gEYg/siy2vzQkTj9lJKk/siy2vzQkTj9lJKk/gIutv76FUz94zac/gIutv76FUz94zac/nfbHvysBaj8zU9c/nfbHvysBaj8zU9c/lVm/v9x0cD/WhNc/lVm/v9x0cD/WhNc/Dbg3P/BWvLuKnSQ+Dbg3P/BWvLuKnSQ+Dbg3P/BWvLuKnSQ+lBlIPyJe5rx5SyU+lBlIPyJe5rx5SyU+lBlIPyJe5rx5SyU+d4BPP/qCzTzN1Tk+d4BPP/qCzTzN1Tk+pE8+P2iRLT0eUzk+pE8+P2iRLT0eUzk+i5VnP230Sj7qWZ4+i5VnP230Sj7qWZ4+c9xVP6ZQWz41cZw+c9xVP6ZQWz41cZw+W4KFPxvi1z6vXQ8/W4KFPxvi1z6vXQ8/W3h5P7984T7wgQ4/W3h5P7984T7wgQ4/0gWXP84SFz/xklM/0gWXP84SFz/xklM/rx+OPyDGGz/wQVE/rx+OPyDGGz/wQVE/Z5inP5TqNj+ifIk/Z5inP5TqNj+ifIk//tWeP8LJOz+gEYg//tWeP8LJOz+gEYg/rSy2PzQkTj9lJKk/rSy2PzQkTj9lJKk/e4utP76FUz94zac/e4utP76FUz94zac/mPbHPy4Baj8zU9c/mPbHPy4Baj8zU9c/klm/P950cD/WhNc/klm/P950cD/WhNc/IvtAPpbawT5qfEI+rM3DPgDU7z6I9z0+QLPRPmAukTxAs9E+YC6RPHn55T5gAjo+3P3APoAukTzc/cA+gC6RPCBE1T4ECTo+ckTVPlxvPz4AHzs9GOLNPgAfOz0Y4s0+uKX8PlAfCD2AvuY8junIPoC+5jyO6cg+TKj8PhAHZT1MqPw+EAdlPaYc/z4gldc8AKaxPRqWwD4AprE9GpbAPgB4sj2ua6k+AHiyPa5rqT5gT489XtPEPmBPjz1e08Q+4DeRPfijqz7gN5E9+KOrPsD3PD3onMU+wPc8PeicxT5aezQ/CNu1PgLDND9aarY+Lew1P/65pT7ZXDU/kDKbPtlcNT+QMps+2Vw1P5Aymz7bXDU/rNimPttcNT+s2KY+21w1P6zYpj5Ocwc++JT2PlE9LT+ow60++xYuP2wSrT4EMuI9ciEHP00mFz9Ew+Q+yGwHPkwhBz9y++4+QF5nPgDW1z4cFAc/9DzzPhSMWT6ORgE/ACmqPk5A8z5YOYs+TkDzPlg5iz6ORgE/RpzIPo5GAT9GnMg+nibiPXzK0j7wntc+l9wXPx8PEj8AKao+gKr0PHYQwT6AqvQ8dhDBPlh7ND9Gcqw+AsM0P/Liqz4r7DU/OlGcPvwz4j3olfY+8xkVP4BwzT7zGRU/gHDNPlrM6z4ghf89ONfsPoBCDD441+w+gEIMPsBItD2aYsg+wEi0PZpiyD5APO4+0B9lPUA87j7QH2U9AsM0P0ZyrD4CwzQ/RnKsPgLDND9Gcqw+AsM0PwjbtT4CwzQ/CNu1PgLDND8I27U+o4dCP5y0/j6jh0I/nLT+PrHgej+PlRU/o4dCP5yhPj/GfUM/h5oVP/vgej811Bg/++B6PzXUGD+FzTQ/kDKbPtlcNT/gE5o+4hlqPzooHD+FzTQ/ptimPtlcNT9Q96c+WhpqP05BIT/4Ltw+sBcHP/gu3D6wFwc/kk/2PmBlUz4FQg8+tCX+PlU8GT+8a/I+PMcZPzBW8z7QRNg+wC2RPNBE2D7ALZE8rPjlPjzfLD7QRNg+AGTeO9BE2D4AZN47ENnjPli1FT4Q2eM+WLUVPhDZ4z5YtRU+QLPRPoBm3jtAs9E+gGbeO4La4z582CI+wLjqPTQe7j70fSg/5p2kPpq1KD90UaU+1Cf/Pvhz/z3UJ/8++HP/PdQn/z74c/89ZLrhPkAukTxkuuE+QC6RPIT37j44BSc+wJRCPVoZrT7AlEI9WhmtPhMJKT+4baQ+EwkpP7htpD4TCSk/uG2kPnqOLT8Y46w+eo4tPxjjrD56ji0/GOOsPl39GT9Y0PE+KskZP+Dy6j4qyRk/4PLqPn3HGT+0O/I+fccZP7Q78j59xxk/tDvyPqtCDz543fY+Bj4ZP+4i6z5xgB0/RD/yPnGAHT9EP/I+VnHuPXCrzz7A+Ns+1JsXP8D42z7Umxc/DQkbP7i67z4OWE4/AL/wPtRzTz9cY/M+Bf8ZP1bh6j7rWU4/cubrPsCMAD1spao+wIwAPWylqj4hgR0/lNLxPmsiUj+kZPM+v59OP3i+8D78c08//NPyPhmqTz/4vvA+gp9OP0jO6z6Cn04/SM7rPkh+Qz/KMBs/SH5DP8owGz8x4Xo/zisbPzHhej/OKxs/eyJSP0TV8j57IlI/RNXyPpAEKT9YUYs+kAQpP1hRiz6QBCk/WFGLPmYlHj70IAc/0ycePogl/j7AgB0/pFnzPlxf4j5ojf89pNjjPpjlET6k2OM+mOURPmS64T4AZt47ZLrhPgBm3juc1+w+fNkPPpzX7D582Q8+joctP85Kiz6Ohy0/zkqLPo6HLT/OSos+9GsHPoT+1D6HiC0/bDCKPrASLj8Ie4s+zTwPPvgl2T7xRBk/9mnNPhLQGT/qOc0+EtAZP+o5zT7gr+o9wALVPlZ5KD+QgYs+iwMpP8I2ij7SROI+qhwHP9JE4j6qHAc/d2X8PuhjUz7K3es+jiQHP8rd6z6OJAc/zF4BP5D8RD56o04/CELJPnqjTj8IQsk+IIGzPSY8hj4ggbM9JjyGPqCBkz1Mvog+oIGTPUy+iD5Zr2Q/+MjwPvjkZD843vI+57hlP3jJ8D4KBxo/vD3IPs1bTj/aQck+VmQDPuyqzz6eDuI+06AXP54O4j7ToBc/X3xCPvauwj5ffEI+9q7CPl98Qj72rsI+R19YPh7CuD5HX1g+HsK4PkdfWD4ewrg+Kt5WPtDttz43X1g+cqO3PjXE+j4YGyo+gxVAPoquoz6tlkE+gKGlPjRKSD5SkME+xAdRPuL+mz7+iFI+nLSbPng8WT684Lk+pJZBPtSCpD6klkE+1IKkPqSWQT7UgqQ+9ohSPjzTnD72iFI+PNOcPvaIUj4805w+FH5DPyzZGD8UfkM/LNkYP/ANDD4qABU/8A0MPioAFT+Q+AI+eK4vP5D4Aj54ri8/4BIMPlyuLz/gEgw+XK4vPzW7ZT9I2es+NbtlP0jZ6z5jNmI/8NzyPmM2Yj/w3PI+4I4NPvgUFT/Akw0+WK4vP3A6Dz7E0Mw+0kcZPxAUwT4S0xk/psm/PoBFBj3OxIc+gEUGPc7Ehz7v0hk/COTAPu/SGT8I5MA+79IZPwjkwD62o04/Il3EPjt+Tz+iUsI+7rFPP6RdxD4A40U9sFGKPgDjRT2wUYo+pB4ePnRbyD6OrvI+cw4XP8EUED4cXMg+pqnrPrUIFz+mqes+tQgXP8d0pj4Wwrg+x3SmPhbCuD7HdKY+FsK4PpcIGj+4T8E+CRYbP4xawz4LXE4/jF3EPmR+Tz9Gw8E+635DP60/Ij9ItfM+IC6RPEi18z4gLpE8HOj/Plj3Gj6JlC0/fOHxPlI2Yj9EbPM+SLXzPoBl3jtItfM+gGXeO5bH/T44yAM+lsf9PjjIAz7zky0/OE7yPvOTLT84TvI+YBgxP+zl8T4rKFI/wlTCPisoUj/CVMI+sJ0dPw7nwD6wnR0/DufAPm6MHT9gU8E+OihSP2TFwT6qDTA/VM7vPv7kZD+QbfM+lwBmP3TK8D5uTjE/pFHyPm5OMT+kUfI+bk4xP6RR8j7uHx4+eM/MPo+MHT88zr8+3WlePrIhBz/Vd14+QCX+PjGULT+gaPM+cOtAPr+tLz8A50A+690XPyKUHT9sU8E+7S9SP2rFwT6g8wI+SpcUP6DzAj5KlxQ/mMMDPkRtij7rkHU+fiUHPzjwCz6EomY+m711PgjM9j7VX20+1CX+Ps1NMT8UbPM+N9oxPwSD8j4LGjE/5vbqPr8AZj/o8es+aU8xP9T26j5pTzE/1PbqPhtqXj58WMg+OmoJP9UoFz+Tdm0+FMn2PmjVMT+SJus+xbFkP1ZlxD7N5WQ/Bl3CPrXAZT/aZcQ+AO+1PQRISj4A77U9BEhKPt0GDT90Sgc/3QYNP3RKBz/ldhg/WPFEPhM8Yj/uWsI+EzxiP+5awj4xv2U/2ErJPjG/ZT/YSsk+AMmTPZQXTT4AyZM9lBdNPr10pj50o7c+L4qnPpIKuT6yhBo/6AwqPtyfLT/iYME+JDxiP5bLwT4KIjE/NGrIPtoGZj82ZMk+w1cxP/xpyD7DVzE//GnIPphCWz5qdIo+Z8QaP2xfpz6YQls+hKJmPv/CGj8+PJA+mEJbPoQ/FD6iQhA/xE8HP3/AGj+QFU4+QFrSPVzYCz9AWtI9XNgLP2AmHD8sVj8+AVVtPnw81D7u4TE/FJvIPnXdoz6uzcM+s/KkPmD3wj6nORk/UOc9Pmndoz76rsI+ad2jPvquwj5p3aM++q7CPsybLT/E88A+zJstP8TzwD5Opp8+fqGlPqG7oD4+y6Q+BwCjPlKQwT7FFBs/QEP/PcUUGz9AQ/89xRQbP0BD/z0xDxs/4NHWPE6mnz7SgqQ+TqafPtKCpD5Opp8+0oKkPsAMDD72hw4/wAwMPvaHDj/ADAw+9ocOP8AMDD72hw4/KXRsPkhXyD7J7Aw/ly4XP8nsDD+XLhc/wI0NPqemDj/AjQ0+p6YOP8Bc0j1oHRM/QyccP2hqXD4gZ9I9xK4vP7wqHD/wV6c+pmtePvDLzD78ny0/itO/PoBpAz0UbU8+gGkDPRRtTz6Aukc9GP9RPoC6Rz0Y/1E+UPICPmfmDT9Q8gI+Z+YNP1DyAj5n5g0/UPICPmfmDT8YpBc+GJUiPjOgdT5kQNQ+0PECPkDgCj/Q8QI+QOAKP+BY0j000gg/ACYcP6A9Mz5BFTA/4mvDPsPlZD+wzcE+ZAhmP7pmxD70p6E+PtOcPvSnoT4+05w+9KehPj7TnD4g5kA+ZtISPyDmQD5m0hI/IBsaPoQ/FD4NnHU+lPrMPucnED+KmRc/oiMxP1ZiwT7eCxY/QC6RPN4LFj9ALpE8QyUcPzjoGj4gDAw+zoELPyAMDD7OgQs/hlkxP/j2wD6GWTE/+PbAPoZZMT/49sA+gGO2PVSDDz6AY7Y9VIMPPhtRbT50ycw+l1kxP3bcvz6i5DE/ZijBPsDhkT18+RA+wOGRPXz5ED72p6E+kLSbPme9oj6qG50+pwGlPrzguT4487w+lNkhPzjzvD6U2SE/pOuJPn4sBz8m7Yk+kDv+PvPoNz90ZPM+uKd8PvorBz+ISpw+ZE2KPiR6gj7kOv4+c6QzP0B58j5vLzQ/AGPzPuirfD7QyvY+kEKYPlAyZj7MdD4/gBqPPsx0Pj+AGo8+zHQ+P4Aajz7MdD4/gBqPPsx0Pj+AGo8+CLA+P3iIiD4IsD4/eIiIPgCNDT4+GAs/KOQ6P3yMiD4o5Do/fIyIPphCWz4UlSI+7sAaPwxrXD4IROw9wN1WPUFmsz7YXXU+fhVDP9SEiD5+FUM/1ISIPlNlND8Y3fE+RTA0P5TV6j5FMDQ/lNXqPokvND+MSPI+iS80P4xI8j6JLzQ/jEjyPqByHj7pQQk/ZS8+PwwFkD5lLz4/DAWQPrjw+T0QOac9gCUlPlRVCD+ikz8/1KSSPrDmNz8USvI+sOY3PxRK8j7keoI+8Mf2PjOlMz9IBus+MNH5PSARgj3qFkM/RhePPuoWQz9GF48+6hZDP0YXjz62cDU/9MbvPg8fZz8gy/A+BztoP5Rt8z76ZTQ/CNbqPgocZz9i2us+Guk3P2Td8T6y6Wo/xGrzPoCW+TzMfRU+gJb5PMx9FT74Yv09IHakPfhi/T0gdqQ9bdo/P+C0kT5t2j8/4LSRPm3aPz/gtJE+umNnP8zZ6z66Y2c/zNnrPr5mZz/4yfA++TpoPzje8j5JcGg/5MjwPo3paj9s2/I+jelqP2zb8j5AFUY9jIkWPkAVRj2MiRY+GBZhPsT/Ez7J1dc+1nUZP20hMT8oCU4+X03ePvp4GT9fTd4++ngZP2pqMz9s4kQ+YGjiPrfhLj9gaOI+t+EuP4u6Lz9MSz8+ePS8Pp6rLz/eCxY/AGbeO94LFj8AZt47/RQbP+CtAz79FBs/4K0DPixaBT5A6r89LFoFPkDqvz0wJw0+8IrUPTAnDT7witQ94Cq3PfgesT3gKrc9+B6xPZKxfD4MXtQ+MF6SPvBcIj6IUBY+AJXmPYhQFj4AleY9v1pnP1xLyT6/Wmc/XEvJPrQzND+qZcg+tDM0P6plyD4mfoI+DFjUPqaoMz9clsg+df16P3zK8j51/Xo/fMryPlCmID4A0fU9UKYgPgDR9T24JUM+XmWpPrglQz5eZak+uCVDPl5lqT7OKUY+qpqzPmRUSD7qcLQ+LKcyP0TZPT5yVEg+TFKzPnJUSD5MUrM+clRIPkxSsz6Ad5A9CGGzPYB3kD0IYbM95PpAPsqtqT7KJUM+skaoPsVaMT9EACo+IGbiPpDbKz8Xui8/wDIzPmp/fj94wes+an9+P3jB6z6g8is+bAIBPqDyKz5sAgE+ZOyCPqRvyD5/Lt4+L10pP38u3j4vXSk/FqGSPpBEgT2gh0g/iBKPPqCHSD+IEo8+oIdIP4gSjz6yzCs/QC6RPLLMKz9ALpE8K7kvP1TdGj5Yux0/IL/WPOvAHT+IPv8968AdP4g+/z1oaTQ/FGbIPhYTZz+aaMk+OPs3PsBxBT44+zc+wHEFPrwpTT+0DY8+vClNP7QNjz68KU0/tA2PPrwpTT+0DY8+vClNP7QNjz7t+5U+wBxVPaJHvj4oWXU+LIZIPxCAiD4shkg/EICIPqTrTD8KfIg+pOtMPwp8iD6Wsnw+zBPNPsAekT7E/xM+KrbXPq6/KT/YxpE+ELCjPdjGkT4QsKM9QMVLP3yqkT5AxUs/fKqRPkDFSz98qpE+rKOSPkBtpj0oacQ+7mQrP3QMTD/0mZI+hXV9P8Cy8D7xq30/sMfyPuB/fj+ksfA+wDfQPmMlLj+Gt1A/cnmIPoa3UD9yeYg+rIJEPtAbCD6sgkQ+0BsIPgBR6jxIj7w9AFHqPEiPvD3lnyA/wKrWPHulID9gOf89e6UgP2A5/z2A1kI9KBC+PYDWQj0oEL49PnKOPoANvz0+co4+gA2/PYAm7zy8d08/gCbvPLx3Tz9XllI/sPQGPRYkSj+ghNU8QMpcPfrxTz9Aylw9+vFPP1ZgSz8wDgc9QImSPVqFTT9AiZI9WoVNP59hSz9g9WM9n2FLP2D1Yz2DWGc/ZmbEPiQzaD8YXcI+d2doP0RlxD4sajQ/sFrBPvBJUT64/Qg+8ElRPrj9CD7YfoI+vOHMPmWpMz/AH8E+vTQ0P6TUvz7S0VM/oD/VPKLxiT60b8g+nzPlPpZgKT9kbLU+ZO4CP1ARqj4CLgc/aGu1PrIuBz95NDQ/CO/APnk0ND8I78A+eTQ0PwjvwD4IE6o+jD7+Pg/8Rz+kavM+Wp+KPpDI0z1an4o+kMjTPdN3NT+UZcM+1hBnP25nxD4XM2g/us3BPnR2fj88Nck+dHZ+Pzw1yT7AbeI+rig2P6S7Lz80Z1w+MIzVPlBwNz8wjNU+UHA3P3ig1T6CulI/eKDVPoK6Uj/wguI+HLhSP+6/Lz96Uqc+eBFePvAOCD54EV4+8A4IPi/8Rz+Y4/E+mf16P9xZ8z6L90c/RFDyPov3Rz9EUPI+3H9LPwTm8T4pEoY+QPDlPSkShj5A8OU93NxqP3RZwj7c3Go/dFnCPhgWYT70M2Y+gSQxP6oekD4YFmE+ilSKPkImMT84Wac+dfw3P+TwwD51/Dc/5PDAPtLtNz8EXsE+t9xqPxbKwT6g1Lc9ADO5O6DUtz0AM7k743RKPxDP7z4srH0/DFfzPpHHfj8EsvA+eJdqPoBTBT54l2o+gFMFPoRoiz7getY9CKu8PmRNMT+RtUs/pFHyPpG1Sz+kUfI+kbVLP6RR8j4AlfQ8GFVLPwCV9DwYVUs/yoWxPnA//j55tUs/FGzzPqZATD9ogvI+9PGJPpTizD437jc//NS/PjPZJD+gjNY8x94kP/Ax/z3H3iQ/8DH/PU7sgD7ARvU9TuyAPsBG9T0A3D88pAxNPwDcPzykDE0/oZdSP/DbYz2hl1I/8NtjPaB7jz1Xl0k/oHuPPVeXST88l3Y+KM4APjyXdj4ozgA+gNhbPQvPSz+A2Fs9C89LPyBttT4sYP8+fYBLP/Te6j4ax34/RMHrPtSYwD4U7wI/qylKP+jv/j2rKUo/6O/+PaspSj/o7/49xLZLP/j75T7Etks/+PvlPtSXwD5mLwc/wm21PtTQ+T5sAWs+YL4GPn6C7z6Mors++HuBPmC9+D2FdPc+eL2wPu5ttT4gFPg+Ko9KPzzQoD59Hks/AO+hPiKHsT7Y6fE+1kFMP8Is5j4AVVg8qidJPwBVWDyqJ0k/wv3IPuwvBz9Qaf0+gvOlPoSUFD8A+3o+hJQUPwD7ej7TRVI/XiGCPtNFUj9eIYI+LJzAPpim6D749wE/CPp6Pvj3AT8I+no+cJQUP5jMiT5wlBQ/mMyJPnp5Vj/WH4s+SWd9P3RRxD6ymn0/VkbCPoF1fj9aUMQ+kpnAPpxh/z5I/9A+a7A3P0j/0D5rsDc/WBPRPli7Uj9YE9E+WLtSP80ASD+AZcE+n/B6P566wT4oPDQ+Vv9EPyg8ND5W/0Q/MJW2PtCbOj+wkbY+5OQ1P7CRtj7k5DU/jG61PkSd8j5Xj0o/LFmbPrseSz+MOpo+IKOQPQDu7jsgo5A9AO7uO1SawD4UFvg++bRQP5zvoT7I/sg+yu8CP+Lf/j62k50+fR5LP1bQoD59Hks/VtCgPn0eSz9W0KA+CbVQP/jQoD4JtVA/+NCgPqkeSz8+WZs+qR5LPz5Zmz6pHks/PlmbPhBvtT6UNu4+lw0zP0LgkT6XDTM/QuCRPjKawD5A0vk+WlNTPzjwCz5aU1M/OPALPmbXUz/A3v49fBmqPixuyD7nrAI/LnApPxcYKT9wKv89FxgpP3Aq/z2BEik/oG7WPCe5Sz+2UM0+J7lLP7ZQzT7gPtA+98U3P9hS0D58u1I/AGnfPACwNDwAad88ALA0PDYLCz8MlBk/NgsLPwyUGT+Or00/iDhTPp7Jpj7scLQ+MYqnPhB+sj7Q9lM/QMU9PrY+Bj9jjxk/tj4GP2OPGT99gko/nNREPjCNDT6KoAs/MI0NPoqgCz+cnjo/4naJPtDxAj79Vwo/0PECPv1XCj+kAjw/zJmDPtBwtT5wc+c+ahAzPzA4iT5qEDM/MDiJPsKawD6onvI+1bRQPzA7mj6O/8g+PGP/Pqj9/z4aMJc+xLRQP85Zmz7EtFA/zlmbPge4GD8AZt47B7gYPwBm3jsmwR0/eKsDPp55vj54OO4+yJY4P5zokT7Iljg/nOiRPsl2Mz9UFJE+yXYzP1QUkT7JdjM/VBSRPtM3OD+QCJE+0zc4P5AIkT7TNzg/kAiRPge4GD9ALpE8B7gYP0AukTxq0R4/8OYaPioByT4kyvE+dioBP/jKiT52KgE/+MqJPrb7Rz8m+cA+tvtHPyb5wD7UibE+dD7ZPjhETD94gc0+1a4+PySXgz7E8Ho//EnCPsTwej/8ScI+DIXGPhgY+D51qlM/fPChPt85VD+U0aA+14NLP1hUyD4gvn4/5jTJPqlwMz9sAYo+qXAzP2wBij6pcDM/bAGKPmcbOD+k6Ik+Zxs4P6ToiT5nGzg/pOiJPioWDj//lhk/KhYOP/+WGT+AulA/jDZTPqRCED8amRk/ppQUP9gTUD43RFI/rFtZPuCWjT2UYD4/4JaNPZRgPj8uAMk+HNT5Pk15AD8utpE+kBiqPkzhzD4/AUg/zOS/PoyqUz/M0aA+jKpTP8zRoD6MqlM/zNGgPgAMDD6L+Qo/AAwMPov5Cj/04zo/bMKHPvTjOj9swoc+AG3yPPW8Pj8AbfI89bw+P1+qUz8UWps+X6pTPxRamz5fqlM/FFqbPvqyHD8AZt47+rIcPwBm3jtQpiA/cJgOPlh6vj7MdOc+koc4PywIiT6Shzg/LAiJPivYmz6wRqg+z5icPgSRqD5cfU4/rO4pPrpwtT7wA+U+MRYzP8C0cz4xFjM/wLRzPvqyHD9ALpE8+rIcP0AukTxQtiE//NQlPqyFxj6soPI+fapTP2I7mj6zOVQ/2lmbPo5/Mz+kFnI+jn8zP6QWcj6OfzM/pBZyPvslOD8oOnI++yU4Pyg6cj77JTg/KDpyPqb8Kz9YJf89pvwrP1gl/z2m/Cs/WCX/PRL3Kz9gWtY8joy9PjDFzz4iBg4/MhsqPyIGDj8yGyo/62EzP9RqYz7rYTM/1GpjPuthMz/UamM+zHC1Plj33T5yADM/wOVhPnIAMz/A5WE+M9ibPlhlqT4z2Js+WGWpPjPYmz5YZak+vHi+PugE5T4NgTg/FAV0Pg2BOD8UBXQ+vrchP4DWTj4VKSM/KFJlPmiTQT98lIM+aJNBP3yUgz7Wrz4/bL6HPtavPj9svoc+1q8+P2y+hz7Wrz4/bL6HPkD6PT0A20w8QPo9PQDbTDyIH7E+hHPIPkwvBj+Xcyk/TC8GP5dzKT+ACBU+YNvpPYDlQD42zA8/gOVAPjbMDz+G58w+FvepPsZxtT7ok9s+XB0zP+K5hT5cHTM/4rmFPgDWWzyikj0/ANZbPKKSPT93dko/6G/DPnaafT/4tsE+Lr1+P5ZQxD6tKDg/rFZjPq0oOD+sVmM+rSg4P6xWYz7nbTM/8FR8PudtMz/wVHw+520zP/BUfD7LfDM/wOyEPst8Mz/A7IQ+y3wzP8DshD5oi7E+tOjMPoy6Sz/A4L8+aUVMP8grwT5ccrU+VBfVPvkBMz8Ix3o++QEzPwjHej6InMA+NAXlPihGAj+Q0XM+SOwgP0AukTyZ7yU/vNIlPkjsID8AZt47nN8kP7CUDj5Xuks/EPvAPle6Sz8Q+8A+V7pLPxD7wD6RhEs/hGbBPv0bSD+U6wQ/uplQP1AVkD4OKVE/pPaOPiZjRz/Q4Ac/zhtIP/jlBj+8mVA/ZJqUPg4pUT8QuZU+Vyg4PwT0hD5XKDg/BPSEPlcoOD8E9IQ+nnu+PnyW2z4Zhjg/rNWFPhmGOD+s1YU+GKe2Pj3AUj98Y0c/m/ADP8yoLj+QIP89zKguP5Ag/z3MqC4/kCD/PTWjLj9AR9Y8AOVYPUuMPz8A5Vg9S4w/Px57vj5o+t0+yJY4P8SfYT7Iljg/xJ9hPhApUT9QFZA+EClRP1AVkD4QKVE/UBWQPhApUT9kmpQ+EClRP2SalD4QKVE/ZJqUPo50Uz9KFZA+jnRTP0oVkD6OdFM/ShWQPo50Uz9smpQ+jnRTP2yalD6OdFM/bJqUPmH7UD9ALpE8YftQP0AukTx+Y1Q/iNImPvqewD5s5NI+GswDP/wSUD5aMhA/omEqP5idwD6oNdw+lAADPwBwYj43Hko/wOsEP450Uz+o9o4+5ANUP1AVkD58fL4+jBzVPsiWOD8Iano+yJY4Pwhqej5QFUM/wLqHPlAVQz/Auoc+UBVDP8C6hz5QFUM/wLqHPiwsOD8wMnw+LCw4PzAyfD4sLDg/MDJ8Poh2tz4sxM8+MvsKPz8YKj8y+wo/PxgqPxgWYT78XCI+9yExP2BmXD4N8SU/CNROPsLMRT/okIM+4C5gP1x5Ij7gLmA/XHkiPqhZYT8AZd47qFlhPwBl3jsutlU/AGTeOy62VT8AZN47eNNXPxBbFT5401c/EFsVPnjTVz8QWxU+MdRXPzR+Ij72/lg/AGTeO/b+WD8AZN47cJwLPtBF1z3AqzQ+IjwOPySkAz5gEMI9QAUrPo7SCz+YJSU/QC6RPJglJT9ALpE84SgqP0DQJT6YJSU/AGbeO5glJT8AZt476hgpP/SQDj6ozUU/XLiHPqjNRT9cuIc+YIfVPnPyMD9gh9U+c/IwP2CH1T5z8jA/YIfVPnPyMD/v1rg+gFt1PtbNRT9qgog+S/0fP7C/cz5gKio/kNFOPhoGSj8kjYM+GgZKPySNgz6LICk/AGbeO4sgKT8AZt473fwrP+CeAz7d/Cs/4J4DPmqjaz+p8wM/aqNrP6nzAz9qo2s/qfMDP8j60D7ylDE/yPrQPvKUMT/I+tA+8pQxP8j60D7ylDE/iyApP0AukTyLICk/QC6RPAcNLT8A3xo+AoZIPwS2hz4Chkg/BLaHPgKGSD8Etoc+AoZIPwS2hz6/Y0c/7tEAP79jRz/u0QA/rqNrP/vUAD+uo2s/+9QAP66jaz/71AA/rqNrP/vUAD+/aSk/oLT+PhflET+agPU+HV1DP6x29j4o9GU/ACFnPhflET+gtP4+N2RHP1h39j4IFys+iNwCPlwM0T4YwbY+XAzRPhjBtj7cjB8+kFX5PfD3zT6mqrA+sepMP7yKgz5gOtA+zbMxP2A60D7NszE/KIXVPkvsLT8ohdU+S+wtP94YRD4ql5c+pENGPm5tmD5ED0o+mjOyPrIVQD6S548+XEBCPnyAjj74C0Y+BISqPphDRj7ETpc+mENGPsROlz6YQ0Y+xE6XPlhAQj4un48+WEBCPi6fjz5YQEI+Lp+PPgCXjD0S7yw/AJeMPRLvLD+yzCs/AGbeO7LMKz8AZt47A6kuP4ScAz4DqS4/hJwDPgC28DzFSS0/ALbwPMVJLT/NnFg/PkanPiycWD9y5p4+bpQUP7qUnT71elY/8ueePmiUFD/C+qU+mHtWPwhOpz7IhNU+CWQtP8iE1T4JZC0/45ZPP7SIgz5+60w/BLKHPn7rTD8Esoc+futMPwSyhz5+60w/BLKHPvNjRz+o9Pw+82NHP6j0/D4X5RE/lcQoPxflET+VxCg/JKRrP2x99j4kpGs/bH32Pr9pKT+agPU+znh9P+ASZz4Ah2I8hfsrPwCHYjyF+ys/kPjQPs6OLj+Q+NA+zo4uP0jDxz7JUCw/jm9NP7r3jz6Ob00/uvePPiD40D6JBi4/IPjQPokGLj9it1A/aK+HPmK3UD9or4c+IDjQPqitLj8gONA+qK0uP3T9UD9oY4k+r5tYP9SCmD6vm1g/1IKYPm6UFD+mMJc+e3pWP+iDmD4ATlk94ycuPwBOWT3jJy4/+PK8Pm7THj/Un8w+ypoFPwNbQz+JMhQ//EpjP/xCpz5QW0M/WIgQP1xKYz8u454+SptYP+YIkz5Km1g/5giTPm6UFD9CtpE+FHpWP5QJkz76uIY+AC3pPXiPtj693jI/eI+2Pr3eMj8Ci/g+3gqqPuGjaz+4+vw+4aNrP7j6/D7ho2s/uPr8PuGjaz+4+vw+qE2PPjAnwT1AfME+yOIuP5hMUT64eQo+Zq/iPtTGvz78T0Q+eJUJPtLy2z6Usr4+XKPWPhmLBT8Ilzc+EOAGPhjg1T7wlrs+sppYPzgfiz6ymlg/OB+LPopbQz+LvA0/4EljP5p/mD6/aSk/lcQoP79pKT+VxCg/BGdUP8Iggj4EZ1Q/wiCCPgRnVD/CIII+AgjOPlCbBT8CCM4+UJsFP75bQz/9Vgs/e0ljP7oFkz5krtA+xIkFP2Su0D7EiQU/KKkvPuggBD4oxdI+OHm4PijF0j44ebg+qFA0PmLRUj9KMEQ/Jpo2P2piRz+siBA/2i9EP543Oj8eYkc/4DIUP3ZmVD+g/3U+kpQUPxC5bD5MRVI/8AB2PoUKRz/3Nzo/hQpHP/c3Oj/3Ckc/fZo2P/cKRz99mjY/9wpHP32aNj8NXEM/e+AHP99IYz8EHIs+30hjPwQciz44fXc+2KcCPpRa9D4a0bY+lFr0PhrRtj7qZVQ/hCtnPp6UFD/w5F0+vERSP8QsZz6gMEQ/DtgzP4MLRz/kZDI/qmJHP968DT8As489uegcPwCzjz256Bw/QupEPyXYMz9pC0c/gx4zP2kLRz+DHjM/AL72PO0wHD8AvvY87TAcP2NcQz9G8AM/MkhjP0Ycgj4ySGM/RhyCPgDmXDwkbxs/AOZcPCRvGz/dYkc/VFcLP6JcQz+b0QA/olxDP5vRAD+qR2M/pPZ1PkLTVz9YixE+QtNXP1iLET7kjVg/eNb+PU6IWD9gHtU8gPRaPbJ+HT+A9Fo9sn4dP8L8oT7ETpc+wvyhPsROlz7C/KE+xE6XPqGDmT4sn48+oYOZPiyfjz6hg5k+LJ+PPp+DmT6GgI4+QUSaPtTKjj6QaZs+BISqPsj8oT5qbZg+X72iPnJ6lj674qM+mjOyPu39Rz+AZd477f1HP4Bl3js52ko/9IQDPjnaSj/0hAM+HEdjP5AiZz6eyaY+VFKzPp7Jpj5UUrM+nsmmPlRSsz7t/Uc/IC6RPO39Rz8gLpE8YupLP+TNGj6wNzQ+MPlBP5N6+D69pAU/ei5gP5wtGz56LmA/nC0bPjBAYT/Qxv49MEBhP9DG/j2aOmE/AOHUPJo6YT8A4dQ8kElePkCJCT7obOk+qri+PjB37j6BkAU/JWz0PtqRBT8lbPQ+2pEFP8ztcj4Y8QM+PqDyPqiHuD4+oPI+qIe4PmYS9z6cpAU/ZhL3PpykBT8KHko/JOYGP5B0Uz8OuZU+5gNUP2ialD5h+1A/AGbeO2H7UD8AZt47jlNTPySHDz6OU1M/JIcPPq8+YT+wLj8+b+JkP4QpGz4q9GU/oL7+PZHuZT/gvtQ8+cxqPwyfNj/5zGo/DJ82P/nMaj8MnzY/+cxqPwyfNj+FzGo/gjw6P4XMaj+CPDo/11xDP/jz/D7XXEM/+PP8Prn0ZT8U9XU+zuNYP8TKOT72/lg/AC6RPPb+WD8ALpE8LrZVPwAukTwutlU/AC6RPE7jWD+0pyw+QIiUPQZvDj9AiJQ9Bm8OPwCcZTxMvQw/AJxlPEy9DD9AVQI9SyoNP0BVAj1LKg0/ac1qPxAjMz9pzWo/ECMzP2nNaj8QIzM/ac1qPxAjMz98PmE/TMg5PqZZYT8ALpE8pllhPwAukTwXo2s/3eMHPxejaz/d4wc/F6NrP93jBz8Q82U/iOtJPoPNaj9waTI/g81qP3BpMj+Zoms/6r8NP5miaz/qvw0/wLdfPTaiDj/At189NqIOP8yiaz9eWgs/zKJrP15aCz/W8mU/1NJDPr6uZj+ALpE8vq5mP4AukTxo42Q/nIIsPr6uZj8AZ947vq5mPwBn3jsVZ3w/pBQbPs14fT/glP49OXN9PwAZ1Dzg1Zk9w6MAP+DVmT3DowA/tnd9P4zgST4ASWs8rv/9PgBJazyu//0+ACgIPa6x/j4AKAg9rrH+Pnx3fT/AxEM+aDN+P4AukTwOaHw/zG0sPmgzfj8AZ947wPRlPQ7DAD/A9GU9DsMAP3RMUT7EeQo+ZK/iPuTGvz79rH0/6j46P3GtfT9woTY/ca19P3ChNj/g0J490MzXPuDQnj3QzNc+AP13PPCc1D4A/Xc88JzUPuStfT90JTM/5K19P3QlMz8ASQw93JXVPgBJDD3cldU+/a19P9VrMj+PxX4/hsENP8BIbz0SbNg+wEhvPRJs2D5EjeI+zo0FP8DFfj/5Wws/C8Z+P3jlBz8Lxn4/eOUHP1/Gfj9E9QM/X8Z+P0T1Az+ixn4/ltYAP6LGfj+W1gA/1MZ+P/L9/D7Uxn4/8v38PhflET+coT4/G8d+P6KA9j6/aSk/nKE+P9z9wD4AZ9473P3APgBn3jsqJdM+dOIiPiol0z504iI+KiXTPnTiIj4FgEM/upEuP+3iej/BjC4/0eF6P7Q6Ij/G+tA+AJ3/Pcb60D4Anf89WCTTPsSWGz5YJNM+xJYbPq1zRz+UMps+rXNHP5Qymz6tc0c/lDKbPii7RT/s4qs+1gJGP0ByrD5Z5EY/PFGcPjDB6z6g2dc8KrtFP0ByrD4qu0U/QHKsPiq7RT9Acqw+gDeQPZoZzT6AN5A9mhnNPqw57j7wOAg9r3NHP1D3pz4CA0g/pNimPp3veT/iPyE/NFTiPmD71zwJOdE+kGVnPr1D8z6AZ6c+jkYBP3bK5D6vc0c/9BOaPv8CSD+UMps+J+95P9ImHD/+Ais/nLT+Pv4CKz+ctP4+4/3uPuQ5iz7j/e4+5DmLPuP97j7kOYs+KrtFPwDbtT4qu0U/ANu1Piq7RT8A27U+8znRPpQ5dj5J6H4/dCsbP0nofj90Kxs/sFO2PgAukTywU7Y+AC6RPMjcyz6wGEQ+KN3LPmAxSj7Wksc+QKX/PWq8yT7kmhs+arzJPuSaGz6wU7Y+AGXeO7BTtj4AZd47VL7JPgT0LD5Uvsk+BPQsPqxzRz+g2KY+rHNHP6DYpj6sc0c/oNimPiq7RT9QarY+1AJGP/7atT5Y5EY//LmlPpjv0D5gONg8mO/QPmA42Dzx3ss+0GZnPqOHQj+UgPU+yed+PzKVFT/nO9E+gj2LPuc70T6CPYs+7Oh+P1g6Ij+k1Zw+SHJnPv4CKz+UgPU+29/LPtw6dj4S6H4/2NMYPxLofj/Y0xg/qofHPsBZ2DxQAe8+2GCnPlAB7z7YYKc+iImYPgDP/z0cs5o+zK8bPlhKhz4AZd47CLWaPsQILT5YSoc+QC6RPHvTnD40JEQ+19OcPgBASj5WP9E+eGSnPgfqfj9ljC4/YH6YPqAA2TyscfE+LJEFP9yo0z5wigU/LBSkPi7qOD8sFKQ+Luo4P/ARpD4J5DU/u4f4Psh9vT5A5mU+1NMVP0DmZT7U0xU/oOVlPq7NEj8s2cw++mm9PjBmUz4eUxQ/MGZTPh5TFD+QZVM+9kwRP1rgzD6GsLM+9FKtPohnNz/0Uq0+iGc3P7hQrT5iYTQ/X4n4PlTEsz5ksRM+EO/IPWSxEz4Q78g9rMEMPiCJtj2swQw+IIm2PaS8Bj5QT6I9pLwGPlBPoj0qrUA/RlOVPpzvGz6wPNk9nO8bPrA82T2kRCU+cAbnPaREJT5wBuc9KDkBPohIkD0oOQE+iEiQPYAXQz/gO5M+tHkvPnAU8j20eS8+cBTyPR1+kD7YiI89HX6QPtiIjz3WiEg/HDeTPrxVOj4wF/o9vFU6PjAX+j2AqEU+oO/+PYCoRT6g7/49IMONPiCgoT0gw40+IKChPRj0Sj9OSpU+PtGKPrATtj0+0Yo+sBO2PXQ1UT6ARgA+dDVRPoBGAD5lT4c+mHvIPWVPhz6Ye8g9zMBcPgDh/j3MwFw+AOH+Pbkygz5A0tg9uTKDPkDS2D1oD2g+APX5PWgPaD4A9fk9pBZ9Pvis5j2kFn0++KzmPWTlcj7QzvE9ZOVyPtDO8T14cHI+OMHvPQf9xj7swqA+4H18PqDF5D1gdsk+OOWbPmPeuD7q6Js+et+4PhLGoD6I2Lg+vM6BPojYuD68zoE+D9e4Phh6dj4P17g+GHp2PtAx7j2AjlQ9XGazPox8dj5cZrM+jHx2Pvi9+z3w54A90mezPu7PgT7SZ7M+7s+BPnElkj5wHoA9Okm+PoTNgT46Sb4+hM2BPgyAlT5g01I9wUe+PrR3dj7BR74+tHd2PnbZuD6A8oU+0wKQPkhgjj3TApA+SGCOPRtKvj5E8YU+3C4CPhgdjz3cLgI+GB2PPc5osz6y84U+9dq4PihDjD4H3Lg+bCCRPhDkhj5w/MY993PJPrQckT4mWoo+MM+0PWb4xj78P4w+Nt24PqiElj7U1YI+EBvXPclPyj7IgJY+tMBnPpDL9z25IcM+9J+kPlTguD5AoqQ+6DdRPsBN/j0S4bg+SvenPlCaXD7gpvw9IUW+PnQbpz702bg+ZAmIPuJHjT4weKA9yx/DPgAGiD4Isgc+yCShPQyUrj6UCog+WIsUPnB3xz3zQ6g+GiSRPjywDT5gR7U9VL2qPkhGjD4QrRw+4IvXPY1qpz6OiJY+jOElPmAk5T1cRqg+pOybPuzyLz7YCvA94sGqPkDJoD7IqDo+cPD3Peeerj6EpKQ+zNNFPgC3/D2cfLM+4B2nPpslHD9oAiY+wtEePxgBJj59tiE/eHcrPn22IT94dys+BqAmPxwXfz7H7yU/JHUrPsfvJT8kdSs+O3QjP8j6WT4YKSo/qHIrPhgpKj+ocis+cw0tPxz5JT6auS8/fPclPgliFD+ALpE8bHsaPyjpGj4JYhQ/AGfeOyVrGT94rwM+j3wZPyBG/z2PfBk/IEb/Pft2GT9g3dY8bjswPyA81jwAQTA/wB3/PQBBMD/AHf89jXYtPwBm3jvcUjA/MJsDPo12LT9ALpE8BmMxP4jcGj6gWNI9NqEHP94lHD+geS4+NP87P7CHaj4AX9c9OH0IP7f/Oz/AyW4+A9IeP1h4Lj5cqz4/hIJqPt+rPj+IxG4+k7YhP+R2Lj4o4CU/HBd/PuuPQT/wfGo+HwQlPyiUfD5ykEE/+L5uPl20Ij/Q+lk+MykqPxRyLj5WA0o/QG5qPlTYIT/AfVw+wANKPzSwbj7CDS0/aHAuPuznTD+0aWo+VuhMP7irbj5AZeI+lKoqP+q5Lz+8bi4+EZRPP6Blaj5gJOE+2IYrP32UTz+Qp24+0rYhP1TwND73xiQ/aER9PqK2IT8k8y8+xcglP+QagD4i8CU/8O00PvXvJT/Y8C8+K5shP3jNWz5tKSo/fOs0PvmcIj8g3Fg+QykqP0zuLz60tyE/vLdNPrS3IT+8t00+z+QiP1ipZT4D8SU/VLVNPgPxJT9UtU0+B7kfP4hocz5TKio/8LJNPlMqKj/wsk0+0+8lP+CTLD7T7yU/4JMsPoa2IT8Yliw+hrYhPxiWLD4GoCY/5BqAPjt0Iz8g3Fg+ISkqP1CRLD4hKSo/UJEsPv4CKz+coT4/o4dCP54YDD9DuW8/j5YVP8O5bz/SLBs/w7lvP9IsGz+LuW8/NtUYP4u5bz821Rg/gbtvP8ONLj9jum8/tjsiP/zJOz+QMps+/Mk7P5Aymz7OoDo/8OKrPv3JOz88UZw+zqA6P0RyrD7OoDo/RHKsPvvJOz9Q96c+TbpvP8tAIT/8yTs/6BOaPtm5bz+7Jxw/zqA6PwTbtT7OoDo/BNu1PtCgOj9WarY++sk7P/65pT77yTs/rNimPvvJOz+s2KY+/gIrP54YDD9GZWU/Lv6XPkZlZT8u/pc+73JyPw6yJT9EZWU/+sGQPkRlZT/6wZA+pXJyP3yHIj+WZWU/uBqpPpZlZT+4Gqk+BfB5P2SxJT9AZWU/8Ep/PrtlZT/YVrA+u+95P9CGIj/sMWg/HP6XPuwxaD8c/pc+7DFoPxz+lz7vMWg//MGQPu8xaD/8wZA+7zFoP/zBkD47Mmg/hBqpPjsyaD+EGqk+L8BwPyT+lz7nMWg/6Ep/PlwyaD+kVrA+LcBwP/jBkD5e32E/9ogiP4D9dT9OMqM+gP11P04yoz6p32E/jLMlP57+dT8s9ps+nv51Pyz2mz7BGmo/zrIlP3f5dT8sPb0+iwF2P3gniT50Gmo/PIgiP5P6dT/+ALY+k/p1P/4Atj7cMHM/kDCjPtwwcz+QMKM+3DBzP5Awoz74MXM/bPSbPvgxcz9s9Js++DFzP2z0mz6fymk/mO6bPtIscz9sO70+5TRzP7wliT5/yWk/vCqjPu4tcz9C/7U+7i1zP0L/tT6ay2Y/Iv6XPprLZj8i/pc+mstmP/zBkD6ay2Y//MGQPpTLZj/kSn8+CcxmP8BWsD7py2Y/nBqpPunLZj+cGqk+LJd0P3Axoz4sl3Q/cDGjPkGUdD8kALY+QZR0PyQAtj4hk3Q/TDy9PjmbdD+UJok+Tph0P1D1mz5OmHQ/UPWbPqA90T72UJk+eel+P15jKD8Uf0M/+yAkP4XfYT9CHiQ/D/51PzyUnz6+l3Q/WpOfPmgxcz98kp8+aDFzP3ySnz4Qymk/qIyfPmEtcz9gnbk+nRpqP4QdJD8D+nU/GJ+5PpG6bz8DHSQ/RGVlPxBglD7LcnI/xhwkP+wxaD8MYJQ+7DFoPwxglD5MMmg/mLisPi7AcD8MYJQ++8tmP6q4rD6nZWU/zLisPt/veT8aHCQ/X+J6P7pjKD/qcC0/HBNaPprLZj8kUpY+GnUqP9AZgD7/k3Q/JKy3PopvLT+sGoA+ZZN0P1CQuz56dio/ZBFaPpzLZj/ybZI+UvIrP0IagD6lmnM/oJ25PuL3KD9oGYA+vYx1P9CeuT5A+Sg/kBBaPo7SZT8MYJQ+sPMrP0ASWj6ixGc/EGCUPhQ1Kz/MEVo+tHtnP9j/kj6mOig/CBBaPoQvLj+EE1o+ghtmPz7AlT7ctyk/8BBaPoIbZj/a/5I+TrIsP6gSWj60e2c/SMCVPn62KT+cGYA+AUR1P3A+uD7ssCw/dhqAPmHjcz8A/ro+uDMrPwgagD7P43M/mD24PkY5KD8wGYA+KC4uP+QagD6XQ3U/2P66PgAJzzz22cA+AAnPPPbZwD6Ae7Q8bNvHPoBnyDx2B8c+gGfIPHYHxz58G/o+EI1XPWAbuz0qfMA+YBu7PSp8wD4AEAQ8NjzGPoAcvz0eAsc+gBy/PR4Cxz7CY/E+MJ1XPeDTuz2Gb6k+4NO7PYZvqT4Aods8/JKqPgCh2zz8kqo+YOy8PaJGhj5g7Lw9okaGPoDt5jwqxIc+gO3mPCrEhz6AROE8TIZPPoBE4TxMhk8+oFi/PVRUSj6gWL89VFRKPgDKvz2kiQ8+AMq/PaSJDz4A+NM8ZKQVPgD40zxkpBU+QJDAPfg4sT1AkMA9+DixPQCmxDxQ37w9AKbEPFDfvD1ANsE9QMo6PEA2wT1Ayjo8AEC6PEBJdDwAQLo8QEl0PAA5mj2Wl0w/ADmaPZaXTD9AKJ89ugNNP6mnTD8wclY9ALLTO7xXTD8AstM7vFdMP+Dauz2aQEw/iANRP5BkVj0Atww8lxZJPwC3DDyXFkk/gOaYPSuAST+A5pg9K4BJPwD3EDyWkD0/APcQPJaQPT/A9ZY9bVs+P8D1lj1tWz4/ADkXPOj8Kz8AORc86PwrP8D8lT3U8iw/wPyVPdTyLD8AhRE8Zm4bPwCFETxmbhs/4BaZPQLzHD/gFpk9AvMcPwBoGjzsugw/AGgaPOy6DD/A7p09u3wOP8DunT27fA4/AB4gPBj+/T4AHiA8GP79PoA/oz3WsQA/gD+jPdaxAD8Aqis8OIbXPgCqKzw4htc+QP+nPZjR2T5A/6c9mNHZPoAotzxutMA+gCi3PG60wD6A7LA8FErGPoDssDwUSsY+gOywPBRKxj4A7iM8cuq+PmARwT0cV8A+AJoaPB7dxD4Amho8Ht3EPsDRxD2CYMY+AL06PNCOqD7gxME9MGypPoDzwzzuhKo+gPPDPO6Eqj4AB1A83viFPuDgwj22TIY+gC3PPGLFhz6ALc88YsWHPoCPyTwMmk8+gI/JPAyaTz4AK0g8DKNKPoBLxT1EWko+ALkxPMBbED6AvsU9VIsPPoAmvDyMwBU+gCa8PIzAFT4AORE84E2zPUCBxj34Q7E9ANisPKgLvT0A2Kw8qAu9PQBk4DvAy1o8oCfHPQAiTjyAhaI8wNmAPICFojzA2YA84CGgPXI7TD/gIaA9cjtMP+AhoD1yO0w/AOBxO3gETD/gHLk92I9LP+AcuT3Yj0s/ADS6O4YBST8gRbg9CpZIP8Dgnj0IcEk/wOCePQhwST8A4sI7Yow9PyChtj0MZz0/gOGcPfZWPj+A4Zw99lY+PwAozzuK/Ss/4M61PesaLD+A7Js9AfYsP4Dsmz0B9iw/AODDO35tGz/ggrg9yccbP6ADnz2B+hw/oAOfPYH6HD8AiNU70rgMP0DZvD30Nw0/gOKjPVWGDj+A4qM9VYYOPwAs4Tuw+/0+YGLCPVoa/z5gMqk997kAP2AyqT33uQA/ALb3O7ob2D4gk8g99CHZPsDnrT0QQto+wOetPRBC2j7p/Cs/AJ89vwAAAIAAAAAAAACAPwAAAIBFD4uzLdYjtAAAgD8AAIC/AAAAABt5qrXJmJ25/v9/PwAAAIDrBoezeFFzNQAAgD8nTfG+RslhPwAAAIDJmJ25/v9/PwAAAIAAAAAAGKqNNQAAgD9tRzUyY0W8NAAAgD/wh/S9Bq/HPti8ab/+yms/vDfHPv8IfjyGVaW+CUlyPxARDTWDalQ+1qjkvpPPXj/+yms/vDfHPv8IfjyUVaW+B0lyP4GuVTSDalQ+1qjkvpPPXj+AGwO85/1/P5E8Yzjpy2a/3WTcvsBPM70kz+89eXD8vsaxXD+jH2S//3PlvvYVkr38vEI+Hq8dvzW1Qz/gIGi/FBTXvpLYFb03/RK+6OH4PkiuXL8ug2S/1FDkvjdOh73aAUC+PUwdP80vRL+x6xG+Qr32PmpTXb/1d2g/n6TVPgU3Ej0AAAAAAAAAAAAAgL8AAAAAAACAP1GzGDUAAIA/POQUNhOhQzcFz1m3AACAP5dmi7V3UXAsAAAAAAAAgD8AAIA/7uqJNy7CXDcAAAAAAACAv/FlC7Z3UXAsAAAAAAAAgD8AAIA/ieMUNh2gQzeO2iI6Q/UwPgAmfD9FtS0/dws8P1ShT7sW+n+/vm0LO0FcWTyGCfg5ul0xPmshfD8AAIC/QYOENripCzi3xMo5lboxPlQdfD94WZQzFHBDtAAAgD8ABTW/6AQ1Pw4oZ7Px5J4xWXWLtAAAgD8AAIC/CKazN+SqrTedntWvAAAAAAAAgD+/S9cziDVatAAAgD8AAIC/QYOENripCzgAAIC/CKazN+SqrTeeJdY7gaUtPm1JfD8ABTW/6AQ1Pw4oZ7MAAIC/CKazN+SqrTfd0Cg+GUT4vnvgWz+4LWc/IdPaPohLMD0AAAAAAAAAAAAAgL9rl+42AACAv6fKqzUAAIA/8OqJNyrCXDd633s6mwcxPjAlfD8AAIC/QYOENripCzgAAIC/CKazN+SqrTf+mZ++kj5zP2VLqDMAAAAAAAAAAAAAgD/gsdozAAAAAAAAgD/0xWu/kk/Hvs0/frz44V89+onjvjvnZD8qVaW+GElyP+tkDTT44V89+onjvjvnZD8AAAAAAAAAAAAAgL9rl+42AACAv6fKqzUAAIA/bJymNtgoYzUAAAAAAAAAAAAAgL8AAAAAAACAP1GzGDUAAIA/bJymNtgoYzUAAAAAAACAP8OrQrQAAAAAAACAP7KXDDQAAIA/5qVxtQCIHzVSzagzAACAP/JDMTQAAIA/E6bxtsfchTQAAAAAAACAP6rR5bQAAIA/4qVxtf6HHzV3UXAsAAAAAAAAgD8Fz1m3AACAP5dmi7UAAIA/euVStsS6XjV3UXAsAAAAAAAAgD8AAAAAAACAv/FlC7YAAIA/xdDgtlAzCzQABTW/6AQ1Pw4oZ7MAAAAAAACAPwAAAIAkqqe03PfatAAAgD9+5nE6EcYxPs8cfD8AAIA/UgeYtf3IXrgAAAAAAACAPwEHy7YAAIC/AAAAABt5qrU7I56+u3tzPzuNlzQIyjO0CSETtQAAgD8AAIC/AAAAABt5qrU7I56+u3tzPzuNlzQAAAAAAAAAAAAAgD/gsdozAAAAAAAAgD/o+eEzzSEHtgAAgD8AAIC/AAAAABt5qrXJmJ25/v9/PwAAAIAAAAAAAAAAAAAAgD8ZhL47iIkuPuI/fD/r/38/hxJyuWcszrpFtS0/dws8P1ShT7uon2+9xI9/P45owjMAAAAAth7stQAAgD8AAAAAAAAAAAAAgD9rZau+2DpxPwAAAIA7I56+u3tzPzuNlzQg4LKzLjt3tP//fz/CFju+HPwZPywXR78p12Q/awzjPrPuhT01DBI7SyEvPkU6fD9FtS0/dws8P1ShT7vr/38/hxJyuWcszroW+n+/vm0LO0FcWTw1DBI7SyEvPkU6fD9FtS0/dws8P1ShT7v3MeM757k4PjfLez/vIrU8gSMwPu4efD///38/K4nnt9a3WLkAAAAAAACAPwEHy7aBpzE8g3Y+PniEez8AAIA/UgeYtf3IXri4Wn06hmswPgMsfD///38/MYe7t5zNOLkAAAAAAACAP+cGy7bIa505PfliPtGheT8Lhoo7sDgoPgiFfD8ABTW/6AQ1Pw4oZ7MAAAAAAACAPwAAAICjRQ87EGExPiAhfD+RUWs/quHIPp6FCL0D48Y+9KFoP9dpHL55qqY8sjswPl0gfD/4en8/GuWBPWR1vLs6qUE+5lgdv58LRD9FaGQ/J2DkPsu3kD2YNR46ZQBePk7peT+QsWU9Hx98P4IHKL6RUWs/quHIPp6FCL0D48Y+9KFoP9dpHL4APuK1fksuPrFDfD80bO057HUwPpYrfD+dwH8/yVMzPfYwhrsAAAAAAACAPwHQDbQAAIA/u7yaNhyhqjQAAAAAAACAP6zR5bQAAIA/GTIgNqaNobYMP9+05BkoPueGfD/AnmU9dBl8PyyRKL56mo85//9/v83k9LY1DBI7SyEvPkU6fD/r/38/hxJyuWcszroAAAAAyT4yPoIXfD8AAAAAyT4yPoIXfD8AAAAAAACAP+cGy7bZ6pG+K2J1P/8KJTTgsdozAAAAAAAAgD/o+eEzzSEHtgAAgD9rZau+2DpxPwAAAIA7I56+u3tzPzuNlzQAAAAAAAAAAAAAgD/gsdozAAAAAAAAgD8W+n+/vm0LO0FcWTx6mo85//9/v83k9LY1DBI7SyEvPkU6fD8o8587VdYsPvJSfD96mo85//9/v83k9LYW+n+/vm0LO0FcWTwAsZg6BaYvPpw0fD///38/LqKYuPT487m0SLY8VsEvPgEjfD/+/38/rQ2luObEArqtPdY7uSYsPtBZfD/r/38/hxJyuWcszrp6mo85//9/v83k9LaAA0C/BVApPxfXeTMAAAAAAACAPwAAAIAAAAAAAAAAAAAAgD+AA0C/BVApPxfXeTNYt7c0AACAPw1RoTMAAAAA/lO7tP//fz+SHiM6G58wPsYpfD94oH8/cGNavY6MCTzzoF+/hbPyvipO4r2KMnA+uNQ1v5nnKT/R4WC/5Bvvvtsxz70W5Wy+IMo0P81MK7+A69q1+RkuPtRFfD/T3ca+BqNoP6tqHL68Tmu//+7IPoWBCL1UpO46O/8vPqswfD8moH8/YYlavWUKDzwslOc7d2spPiV3fD+AA0C/BVApPxfXeTMAAAAAAACAPwAAAIAAAAAAAACAPwAAAIASXgY1AAAAAAAAgD/p/Cs/AJ89vwAAAIBdNfCz//9/v8P/x7aeVwY1AAAAAAAAgD/p/Cs/AJ89vwAAAIDp/Cs/AJ89vwAAAIBdNfCz//9/v8P/x7YDtY+yAAAAAAAAgD+s/is/ZZ09vwAAAIAAAAAA//9/PwAAAICJVgY1AAAAAAAAgD+s/is/ZZ09vwAAAIAAAAAAAACAv/f/R7XsVwY1AAAAAP//fz8AAAAAMOZaNQAAgD8AAAAA//9/PwAAAICs/is/ZZ09vwAAAIAAAAAAAACAv/f/R7UAAAAAMOZaNQAAgD+s/is/ZZ09vwAAAIAAAAAAAACAPwHQDbQAAIA/E6bxtsfchTQAAIC/Q6eAs3JnjrW8ml6/BYWqMpjZ/L4AAIC/AAAAACsYXzO7ml6/7fJMNJjZ/L4AAIC/hoIGMzlhlrW7ml6/7fJMNJjZ/L5bwH+/8/EzPdThW7tceu05AXYwPpUrfD80tWW9HR98P5YHKL4MP9+05BkoPueGfD8AAIC/FoZks3KrD7UAAIC/7VUKM9rmDbWtvBc8EfQgPobOfD/8/38/4UvXuJNMJroAAAAAAACAvwAAAID5dG0+9PI0vzIVKz9zu18/W2DyPotT4T0AAAAAAACAvwAAAIC5B9Q5qKI5PhvCez/8/38/4UvXuJNMJrrbGWs/q7zHvk8wiD1B5sM+Dzxpv+8lHT5TMJY6Ri0vPt45fD8y/Gi+IEUzP6g4Lb+CAmE/Ra/uPjwlzj2b3uY5Bp8WPig3fT/D+wg1AACAP4bUkDOT9Yk7RJIZPjYafT+AA0C/BVApPxfXeTOI0GA1AACAP497YTP8sne/vlKBPhdzCDYZhEG1AAAAAAAAgD9dNfCz//9/v8P/x7YgxiO5QsE1Pmbvez+idYW6s/QvPjQxfD/bGWs/q7zHvk8wiD1B5sM+Dzxpv+8lHT4AAIA/YeEVNvpMIjRrZau+2DpxPwAAAIDvhkW4AACAP6EKSDTeWa2xAAAAAAAAgD8WiCC6StpdPmvreT+AmGW9exl8P+6QKL5rZau+2DpxPwAAAIDvhkW4AACAP6EKSDQAAAAAth7stQAAgD8AAAAAAAAAAAAAgD8kuZq5bBBjPoGgeT8AAAAAAACAP9cGy7bz7ks6eiw5PonHez9H1ZU6J9YoPgN/fD+EbGE9WBt8v66+KD4AAAAAAACAvwAAAIANTIs6tx1kPh2ReT/39CK43SlBPm9nez/ke2E9PhR8v5VmKT42UA+7BF0xPkwhfD/T3ca+BqNoP6tqHL68Tmu//+7IPoWBCL0AAIC/1h3gNZbUZjgAAAAAAACAP98Gy7akVlE75kc/Ph9+ez/x8OY5NJ8WPic3fT8AAAAAAACAvwAAAIAAAAAAxj4yPoIXfD8AAAAAyD4yPoIXfD8AAAAAAACAP9cGy7b//3+/R0wmMwqp1TIAAIC/60fks06eDrETuII6MLhhPvmzeT/6JjI5Fn98v4jVKD4AAIC/AAAAAD4vtzO8ml6/aK7NspjZ/L4AAIA/dvnyMViS5DNRLbS5aHwyPscUfD///38/6kj+MV1h1DP+Onq8rWAwPsMkfD/GcHG6+uMyPiwQfD8AAAAAAACAP98Gy7YAAIC/1h3gNZbUZjgouWk8oXwxPkwZfD9Ben+/JF2CPcKipbv+/3+/5sEFOKzEbjlfpYI8c1wxPgUZfD+tMSg6otUUPg1IfT+7+Ag1AACAP+tEETTlV3u8K1wwPuUkfD8AAIC/7XnYN75QSjmKMZY68UUvPsw4fD/2qcO+6T5pvxQOHj4aUWu/Z93IvtreCj31CVu/j+H7vrPGJL6hz4o+sOJEvw4sFD/Atrc0AACAP4Mf0DP0BDU/8wQ1P4QA8TMAAAAAXeEatQAAgD80/V+9XBZ8v+VTKT5H1ZU6J9YoPgN/fD+9dH+/4eGEvcY+wzsDyg867r4wPmMofD+fZlu/kJH7vvbfHr4hTIm+mFlBPzYZGb9dNfCz//9/v8P/x7b8sne/vlKBPhdzCDbkE300y6ButAAAgD8XAAg7fSpgPj/KeT8zzV+9WRt8v9zgKD435Hw8A0cxPn8afD+pvX+/pmw3vYo2izv+/3+/RPGyOI7KCzqBFIc8HigxPrwafD8AAIA/dvnyMViS5DOnIvUzwr+cswAAgD8AAIA/663/MU9i0jOnIvUzwr+cswAAgD8AAIA/O4IUMtR0/DP0BDU/8wQ1P4QA8TN3zpk0BYv9tAAAgD8AAIC/d6jLtXpacbX//3+/AAAAAL5pCzSV30gzPI6ztAAAgD/QGsG8EtguPiIrfD/+/3+/J72mOCYQAzoAAAAAAACAPwAAAID8sne/vlKBPhdzCDYXdIkzV74MtQAAgD/8sne/vlKBPhdzCDYJhEG1AAAAAAAAgD8AAAAAAACAPwAAAIAAAAAAAACAvwAAAIDzb9E6fN9lPkR3eT8AAAAA//9/PwAAAIAAs3e/pVKBPgAAAIB0hEG1AAAAAAAAgD8AAAAAtK7ttQAAgD8AAAAAAAAAAAAAgD8AAAAAAACAP0zvLjQAAAAAAACAP0zvLjQAs3e/pVKBPgAAAIAAAAAAMOZaNQAAgD8AAAAA//9/PwAAAIAAAIC/eixetSNo17QAAIC/b+EKtG5ViLXCml6//tKqtYLZ/L68ml6/GVhRtJTZ/L75JwG7Y28PPsJ5fT8rymA1AACAP257YTT0BDU/8wQ1P4QA8TMAAIC/dixetYcgt7T//3+/lskRtNmwJ7UAAIC/AAAAAFQwzzNQU4s0moh1tAAAgD8AAIC/AAAAACsYXzOnIvUzwr+cswAAgD/KRiw6rsoUPnRIfT8AAAAA//9/vwAAAID9YYk+CxhEv1qMFT/0zlo/82f8PiV0Jj4XJIe+FChAP2sRG7+mNls/TAP8PvUwID4AAIC/d6jLtXpacbX//3+/AAAAAL5pCzTCml6//tKqtYLZ/L68ml6/GVhRtJTZ/L4AAIA/CJMMMk8P2zNzpcC8CNguPjcrfD8AAIC/mGtItfVoELXGml6/x2INtW/Z/L4AAIC/wFMItQXjwbR7TMM0Oj4xtQAAgD9QErs7yVUyPmkVfD/2qcO+6T5pvxQOHj4aUWu/Z93IvtreCj0As3e/pVKBPgAAAIAAAAAAAACAv/f/R7UAAAAAMOZaNQAAgD8AAIC/dyxetXAYx7T//3+/TbZrtJRRzLIAAIA/O4IUMtR0/DOU6Q+9ISMqPg1IfD/0BDU/8wQ1P4QA8TPAUdc7vY07Puupez8/Ma+4//9/Pw4QSDQAAAAA//9/P/r/RzQAAAAAAAAAAAAAgD8AAIC/FnuytG+1PbXFml6/OUNItXXZ/L79/3+/jRnkOPzyLjoAAAAAAACAvwAAAIANlO47bcdCPrdRez/vRlq/9+f2vj/uTb4zQJo+b59Pv09gAD/Mwp28dhccPtX1fD8AAAAAAACAvwAAAID9/3+/jRnkOPzyLjqWMFq/8H/3viSOTL5ZjZm+lfBMP+jRBL8AAAAAAACAv/f/R7UAs3e/pVKBPgAAAIBkhEG1AAAAAP//fz8AAIC/kSxetXIfRLQAAIC/pkPPMoP5prIAAAAAwT4yPoMXfD8AAAAAwj4yPoMXfD8AAAAAAACAP6MGy7YdVGE6LxMyPmkZfD8AAIC/u4buMczf4jPuC6M7zEExPtUhfD8AAIA/Mli4NVHyXzgAAAAAAACAP3QGy7YFXKg8EiMwPishfD///3+/Zev8MUyM6TOCuim/AAAAAGalPz9uDim/AAAAAEI9QD8AAAAApOFzPxqqmz5nSBU0ouFzPyuqmz6NwgE18uByP1/QoT4AAAAAvOFzP4mpmz6SoZgzt+FzP6Opmz4AAIC/AAAAAKLCdLVuDim/AAAAAEI9QD8AAAAAw+FzP1upmz4AAIA/tVkNMo1T3jNfU4s0u4h1tAAAgD8AAIA/AAAAAAAAAIAAAAAAsqmbvrbhcz8AAAAA0OFzPwepmz5oSJUzueFzP6Gpmz4ItJ26wvk3Po7Vez+kz5O8sFExPiAXfD///38/g7sCOG5UajkrPqC7vjc+PpKKez8AAAAAAACAP3QGy7YAAIA/Mli4NVHyXziwiRa7pFtzPy/nnj6Cuim/AAAAAGalPz9uDim/AAAAAEI9QD/eTim/MPPmPcnVPb9dPBo85/tyP7kboT6Cuim/AAAAAGalPz8AAAAAAACAP6EGy7bA66M5ZcFiPvykeT9Wkag8ZCMwPh4hfD8AAIA/IpbTN2K9RjkAAIA/N9miOPSpbTdZAS+7xGRzP+uunj5nSBU0ouFzPyuqmz6NwgE18uByP1/QoT7tMF07RSkwPpEufD/ly2s/jHrEPssRh73Q3cY+A6NoPzNrHL5YZIK85DQxPsoafD80pH8/7NhVPV6vDLyM/Ro6XTVePl3meT+omWU9MR98P+UHKL51aZk+XzBPvzBTAT+aIVo/gz73PlTHTj7eTim/MPPmPcnVPb/ERtK6GG1zP6x8nj6Cuim/AAAAAGalPz/ERtK6GG1zP6x8nj6NwgE18uByP1/QoT5Ncu256nUwPpcrfD99pH8/N4FVPTLHDLzly2s/jHrEPssRh73Q3cY+A6NoPzNrHL4AHOE1NEsuPrJDfD8UP980SBkoPu+GfD/ss2U9YRl8PzWRKL7fWJe+Tw5LP+1MCL/WBlo/r9v3PoWZTT4AAIC/UP4VMso8vDP0BDW/8wQ1P930HDRtmJm09LCstAAAgD/0BDW/8wQ1P930HDRN/XK0AACAP8IrlTQAAAAAQ0EoNQAAgD///38/AAAAAF8IVDQAAIA/KyxetfzmoLQHmUizfe76swAAgD8AAIC/OW8+MzOLZrI/Ma+4//9/Pw4QSDQAAAAA//9/P/r/RzQAAAAAtK7ttQAAgD8AAAAAAAAAAAAAgD+0jEi/CQsDPkezG7+ZMBy583pzPwoonj71iXO/8oHHPWu0lb599Ww0nn5zP3IRnj4PBl2/O1TsvtStUL5P7KY+GIVZv4ku1D48NtY8ikowPr4WfD///3+/aukNMmf82TOR/X+/bcULPA92nboAAAAAnn5zP24Rnj5SHyO66Z4wPskpfD9TcH8/fx2HveKPqju35o68i4IxPrEVfD/+/38/DTGyOIDPCjrZltY8eUowPqsWfD/9/38/uaelOKzrAToco2W9Ch98P8AKKL4UP980SBkoPu+GfD/kZnO/b0C5vTG6lz579Ww0nX5zP3IRnj5dNfAz//9/v8X/x7YKhEE1AAAAAAAAgD/8snc/vlKBPiNbATb8snc/vlKBPiNbATYAAAAAAACAPwAAAIAYdImzKAVCNAAAgD8AAAAAAACAPwAAAID7g0E1vlgXtQAAgD/8snc/vlKBPiNbATaa6Fy/cJ/svt5LUb6a4KS+H6VZP+xD1b78snc/vlKBPiNbATZdNfAz//9/v8X/x7bkE320y6ButAAAgD8AAIA/anqytLPniLN7TMO0ND4xtQAAgD+BpH+/1DVVPbIrE7wGZu251nUwPpYrfD9T61u/atIhvihH+T5T9ew0nn5zP2wRnj6GikY7w6kNPoaJfT/0BDW/8wQ1P930HDQAAAAAAACAP257YTQAAIC/bdmiOEOqbTd9wgG19OByP0vQoT7oUVO0oeFzPyuqmz5rAy87w2RzP+2unj4AAAAA//9/P/r/RzQ/Ma84//9/P9UASDQAAAAAAAAAAAAAgD8AAAAAAACAP0zvLjQAAAAAAAAAAAAAgD8AAAAAAACAP0zvLjSf94W8KJgxPvQVfD+pwn8/q5MwvRT8aDslLRS/f+eAvh2PRj+29Wy0nn5zP2oRnj59wgG19OByP0vQoT7oUVO0oeFzPyuqmz4AAAAApOFzPyKqmz5wDik/AAAAAEA9QD+Cuik/AAAAAGalPz8AAIC/AAAAAAAAAIAAAAAAsqmbvrbhcz/pUdOzueFzP6Gpmz4AAAAA0OFzPwepmz5KD9izt+FzP6Opmz4AAAAAuuFzP42pmz4lTxE9pG0rPkU5fD8AAIC/UP4VMso8vDP0BDW/8wQ1P930HDRHTNI6Fm1zP718nj65Tik/VPbmPdzVPb99wgG19OByP0vQoT5HTNI6Fm1zP718nj6Cuik/AAAAAGalPz+5Tik/VPbmPdzVPb8APhq86PtyP68boT6Cuik/AAAAAGalPz+ARN81YDIuPsdEfD/B48a+zqFoP7lpHL6gzmu/2W3EPjUIh70AAIA/AAAAAAAAAIAAAAAAweFzP16pmz5wDik/AAAAAEA9QD9tN56+0VWWvpuTZz9U9eyznH5zP3cRnj5K+aY+A5VZv/fi0z5mqV0/7CnrPkQKSz4AAAAAAACAP0vvLjQAAAAAAAAAAAAAgD8AAAAAAACAP0vvLjSP/aO+R0tYPxVc276ug10/CYXrPvv1Sz4tTRw58npzPwsonj6YjEg/1wsDPmCzG7/vh/Q9Ba/HPtm8ab/yxWs/kU/HvoZAfrw/VaU+FUlyP6Of6TTAGgM85/1/PzB7qTT+ymu/vDfHPv8Ifjzvh/Q9Ba/HPtm8ab94VaU+DUlyP/OB1jT+ymu/vDfHPv8IfjybaVS+QKPkvg7RXj+baVS+QKPkvg7RXj+DVaU+CUlyP2SlIzS9U2s/ygXJvuqH7Dz6qcM+6D5pvw8OHj71LZa6+SwvPuE5fD9JSb67srY7PlOoez+Zch6rmn5zP4QRnj5egvc0ihCevsJ+cz9MYKM8wOAbPg33fD/8/38/3HbkON11LjoAAAAAAACAvwAAAICTO5o+1Rt0P35DrTTPVOG5Y1YRPotofT8YhiC0AACAP7HOiDSGi9a5IKUxPkcefD/J1Iu5PQ4yPqcZfD+Nx4+5Sn8xPvIffD/2w7+7gEhDPhVMez8AAAAAAACAvwAAAID8/38/3HbkON11Ljrff9+5EzkyPsIXfD8AAAAAAACAP8UGy7Zk9Wy0oH5zP2QRnj7nh3M/lpHHPYHAlb4zBLu771YyPlsVfD+9U2s/ygXJvuqH7Dz6qcM+6D5pvw8OHj7Non+/doRXvbOIDDyRGiO69J4wPskpfD8AAIA/AAAAAPaADzR9oYq0wkJ1tAAAgD+3ml4/P908M6XZ/L4AAIA/AAAAAH04+DO4ml4/qNTKM6LZ/L7//38/AAAAAFRTXjP//38/AAAAAFRTXjPQxPCzRcqcswAAgD929eyzmn5zP4cRnj6EN54+4lSWvryTZz+2nSi6c1FdPgDzeT+Ys2W9YBl8PwiRKL64/I25EX1jPlGaeT8AAAAAAACAP8UGy7Zv1xO7TSA3Plffez8AAAAAnX5zP3sRnj6m/X8/IhwKPGvEYLpZ1ZW6oNYoPv9+fD8O/189SBt8v0beKD4AAIC/DLD+MS9e6jPQxPCzRcqcswAAgD8AAIC/u4buMczf4jPQxPCzRcqcswAAgD8qSci6wX5mPhhueT/OGj4zAACAvwAAAIAiMw+7WAFfPt3aeT+Qy189iBZ8v8RTKT4EKl6/yWDpvtF+Sr4qwak+FjFcv/Z3xj6jKV27Gi4wPloufD/B48a+zqFoP7lpHL6gzmu/2W3EPjUIh71DCdcrnX5zP3IRnj4vLRQ/A+aAvlWPRj/HjHM/O27HPb+jlb6puJk78XNzP3dOnj4AAIC/ShD/tqkHvrj77cG6Uww8PmKlez8AAAAAAACAP7wGy7Y7/RI+7OH4PkeuXL/lIGg/9xPXvmzaFb3opAa7MSoyPkcYfD8AAAAAAACAP7wGy7YAAIC/ShD/tqkHvrhcLOe5eEoRPvlofT+uISczAACAvwAAAIAAAAAAAACAP0vvLjQAAAAAAAAAAAAAgD8AAAAAAACAP0vvLjRt9ew0nH5zP34Rnj4hbnM/fgK5vWCQlz734V+9DYrjvjrnZD/yxWs/kU/HvoZAfrz34V+9DYrjvjrnZD8/VaU+FUlyP3kDUjRkLWe/xdTaPps1MD3X0Ci+FUT4vnvgWz+c9Ww0nn5zP2wRnj5Z61s/NNUhvqVG+T72d2i/nKTVPhM3Ej2w6xE+Q732PmpTXb9I+/m5aI4xPkYffD9KDtK6hBwwPmkvfD+XpH+/W+JUPfhzGLwFy+C5ieowPnsmfD8AAAAArpYfNQAAgD8AAAAA9Ng/NQAAgD++n289w49/Py7JFTkAAIC/n4QOuMc6fbnkXNe61QwwPhgwfD/f4G25WuYwPqsmfD/GIgy6WxIxPrskfD85WBQ/GtOAvkByRj8cHJQ7nehzP/h5mz57aHM/XjK5vQ6xlz7tMoY7GnRzP6BOnj6OBve6fIswPogqfD8AAIA/76wst5sTgLjDs0Q5gyd8PxrTML5a5p65ms8wPqonfD8AAIC/BS7xt/zeXbkQz++9e3D8vsWxXD8bzWY/KWDcvhg2M70s++W56aswPjopfD///38/AAAAAG+CBLMmITs/FLIuPzi/Y7gAAIA/AAAAACtz/rMAAAAAgntOtf//fz8AAAAAAAAAAAAAgD893tG5MZgwPhYqfD8mITs/FLIuPzi/Y7gAAIA/AAAAACtz/rMmITs/FLIuPzi/Y7gAAIA/AAAAAKKTwLMAAAAAAAAAAAAAgD8sLpa6Ci0vPuE5fD9P5sO+Ejxpv1glHT7xGWu/CrzHvnk1iD14Bq654w4xPuMkfD+3ml4/EsxYM6fZ/L7//38/AAAAANBBErS4ml4/qNTKM6LZ/L4AAIA/AAAAAAAAAIDY/1O6iFFdPvzyeT/QeGG9UBt8vyy+KD4AAIA/wB0Utf0jYLQAAIA/AAAAAB5MerH//38/AAAAAIZHK7L//38/AAAAAAJmWbMAAIA/ox0UtQJlZ7RNNQC7s4AzPhsJfD8AAIA/76wst5sTgLjE/5M3gCd8v3XTMD4EKl6/yWDpvtF+Sr7AA6e+eu1cPweFxb4geaK6jzgwPjkufD9DPQQ6UCh8P6PAML6OeFu6rq8wPgspfD8AAIA/AAAAAAC5UbMVAyg4YOwwPmgmfD/Ds0Q5gyd8PxrTML4AAIA/76wst5sTgLgL+oa6NNAwPpsnfD8hOAQ6USh8P6PAML7E/5M3gCd8v3XTMD4VAyg4YOwwPmgmfD8AAIA/76wst5sTgLi0bTQ7fZUyPmsTfD8ZYOw5UTp8P8YjL75H/X8/MwVwOtl3FDylFmO69tEwPognfD/gsdqzAAAAAAAAgD8AAAAArpYfNQAAgD//mZ8+kj5zPxMfuDN4Eyi6tRQTPnJYfT8M22m1AACAP+7BSDQAAAAAAAAAAAAAgD8AAAAAAACAP0vvLjQAAAAAAACAP0vvLjT+/3+/V6SquAGRBboOjNS6TQwwPh0wfD8AAIA/AAAAAN4AorMAAIA/AAAAAAAAAIAQLao+onRcvxDuxD4FIV8/qIznPn66QT4AAAAAAACAPwAAAICAA0A/BlApPwAAAIAAAAAAdjbgNAAAgD8AAAAAAACAPwAAAIDo/Cu/AJ89vwAAAICgKJMzAvchswAAgD+E7/W0AACAP/d4iTSAA0A/BlApPwAAAIAAAAAAHf+aNf//fz8AAIC/im0etYtUC7Ug0qK7MHJzP7NYnj5uDim/AAAAAEI9QD8AAIC/e47XNAAAAIDLml6/AAAAAGXZ/L4AAAAAm+FzP1Cqmz5JTo86fFcvPgk4fD/HaU+5Sjp8v6EkLz5H/X8/MwVwOtl3FDymrhu7veMyPgYQfD+R1NS5SSh8v1vBMD6RnM2667MwPs0ofD8AAIA/AAAAAEM4AbQR2Ia6NdAwPponfD8srdS5SSh8v13BMD4AAAAA//9/P/r/RzQb1i8/2Q46P77uWDQAAAAAAAAAAAAAgD8lfFK6154zPt8HfD8AAIC/yL6bty7I6LgZYOw5UTp8P8YjL773lxC7u84tPulIfD8ZYOw5UTp8P8YjL75H/X8/MwVwOtl3FDwAAIC/yL6bty7I6Lj3lxC7u84tPulIfD8ZYOw5UTp8P8YjL74AAAAA//9/P/r/RzQb1i8/2Q46P77uWDQTrQYxAAAAAAAAgD+lIJ66elQxPsghfD8mITs/FLIuPzi/Y7gAAIA/AAAAAKKTwLOAaYm6PZdjPsqYeT9MhyizAACAvwAAAIAdVZq7oO0uPu47fD///3+/KLyfuHva+7kAAAAAneFzP02qmz4gbGG9UxR8vwpmKT5Z1ZW6oNYoPv9+fD9TvOa6j+MvPuExfD90SFc6HCl8PyquML7J/3+/6XTkuc+HI7uGctW5QgUwPoEwfD9son+/uCdYvXjxBzz3lxC7u84tPulIfD/HaU+5Sjp8v6EkLz5H/X8/MwVwOtl3FDwAAIC/yL6bty7I6Lj3lxC7u84tPulIfD/HaU+5Sjp8v6EkLz4AAAAAAACAPwAAAID1BDU/8gQ1Pzc4LTT2qac0a3xEtAAAgD/1BDU/8gQ1Pzc4LTQAAIA/AAAAAPKrcrSIGdMyVDd4tAAAgD9JaGS/IWDkPu+3kD1BqUG+41gdv6ALRD/NA+G6X1gwPsosfD8AAIA/AAAAAJkQF7TATCi6chUTPmpYfT8iv0OzAACAvwAAAIDJ/3+/6XTkuc+HI7uifFS7tZUwPtspfD90SFc6HCl8PyquML4AAIC/AAAAAKLCdLXLml6/AAAAAGXZ/L4AAAAAl+FzP3Gqmz4AAAAA0eFzPwCpmz7XAUA+QEwdP8kvRL8ug2Q/1lDkvnFOh73J/3+/6XTkuc+HI7uifFS7tZUwPtspfD/gYFm6ECl8v0CvMD4AAAAAAACAPwIAIDQb1i8/2Q46P77uWDQAAAAAAAAAAAAAgD9kH924I2kuPmhCfD8AAIC/yL6bty7I6LjHaU+5Sjp8v6EkLz5dNfAz//9/v8X/x7bo/Cu/AJ89vwAAAIAKtY8yAAAAAAAAgD8eN/Q5TKQvPrs0fD96fYi5GVB8PyQrLb4z/X8/oAwBOwn1EzwAAAAAAACAPwIAIDQb1i8/2Q46P77uWDQ3qmsxVUVUtQAAgD+7jOS6208xPu8hfD/gYFm6ECl8v0CvMD7J/3+/6XTkuc+HI7tI/C+7HM4tPttIfD96fYi5GVB8PyQrLb4z/X8/oAwBOwn1Ezzi/3+/YRUdOsnV5bpI/C+7HM4tPttIfD96fYi5GVB8PyQrLb4AAAAAAAAAAP//fz8AAAAAAAAAAAAAgD8AAAAAAACAP0zvLjQAAAAAAACAP0zvLjSGL4u7VS0oPoCFfD8AAAAAAACAPwAAAID1BDU/8gQ1Pzc4LTRI/C+7HM4tPttIfD+YhhG6GlB8v9IqLT4z/X8/oAwBOwn1Ezw7ej67Gp8sPtJVfD+YhhG6GlB8v9IqLT4z/X8/oAwBOwn1Ezzo/Cu/AJ89vwAAAICUVwa1dyggNQAAgD9dNfAz//9/v8X/x7YkJgO7fUssPolZfD/i/3+/YRUdOsnV5bp6fYi5GVB8PyQrLb4AAAAAQqqbPp7hc78AAIA/AAAAAAAAAIAAAAAAleFzP36qmz4AAAAAmuFzP1Sqmz4AAAAAleFzP3eqmz4AAAAAl+FzP3Gqmz4AAAAAzeFzPxSpmz4AAAAA0eFzPwCpmz7AA6e+eu1cPweFxb4FIV8/qIznPn66QT4Fqqq7EdsXPnYqfT+91eC1AACAP7t7YTOAA0A/BlApPwAAAIB1/X+/xJnOO+kayTsAAIC/dixetV6QurQkvZm77nNzP49Onj7vQ4a7HHRzP5NOnj4Olpm7OagrPuRffD/A/mA520h8P6bTLb6o9n8/4/1IO6cFiDzivEK+EK8dv0G1Qz+iH2Q//3PlviMWkr2ldYU6SPQvPjgxfD9P5sO+Ejxpv1glHT7xGWu/CrzHvnk1iD3i/3+/YRUdOsnV5bpI/C+7HM4tPttIfD+YhhG6GlB8v9IqLT5HRqO7UxwvPtM5fD+iLKu64Uh8v9DRLT6o9n8/4/1IO6cFiDxHRqO7UxwvPtM5fD/A/mA520h8P6bTLb6o9n8/4/1IO6cFiDymnh+8DywgPirWfD9jSjS0AACAvwAAAID9/3+/s8PWuMN4JLr3mOi7MZYrPrdffD+iLKu64Uh8v9DRLT6o9n8/4/1IO6cFiDwsvnS7IvUqPsJnfD8AAIA/AAAAAN5W3bMAAAAAAACAPwIAIDQAAAAAILcDtgAAgD8AAAAAAACAPwIAIDQAAAAAAAAAAAAAgD/9/3+/s8PWuMN4JLqcqN65a3s5PurDez9jSjS0AACAvwAAAIAqIyU5f6A1PuDwez8AAIC/ugRjN4XNhrbK/sc2w3CENgAAgL8AAAAAAACAP2crwzYAAIC/Y8wetn8DM7UAAIC/xt7jttzWX7bK/sc2w3CENgAAgL8AAAAA//9/v/wrQ7ay/3+/LMgPurqTQrtHRqO7UxwvPtM5fD/A/mA520h8P6bTLb5dLrW7O94rPk9dfD+y/3+/LMgPurqTQrvA/mA520h8P6bTLb7//38/AAAAAMDFA7H//3+/7VrYNlttZ7UAAAAAAAAAAP//fz8AAAAA6vhPNQAAgD8AAAAAAACAP0zvLjQAAAAAAACAP0zvLjQr12S/ZwzjPs3uhT3FFjs+H/wZPywXR78koJa7tHgqPsZsfD/i/3+/YRUdOsnV5bqYhhG6GlB8v9IqLT4AAIC/EjLGNYmUzrYAAAAAAACAP2crwzbK/sc2w3CENgAAgL8AAIC/EjLGNYmUzrYAAAAA//9/v/wrQ7bK/sc2w3CENgAAgL8AAIC/EjLGNYmUzraV/8e2HJODtgAAgD8AAAAAAACAP2crwzYAAIC/EjLGNYmUzraV/8e2HJODtgAAgD8AAAAA//9/v/wrQ7Y7I54+u3tzP9rA7DR0Zas+1TpxP4V8FzQz4LIzSjt3tP//fz+EcJy7kmktPqpMfD8AAIA/AAAAAPKrcrT1BDU/8gQ1Pzc4LTTUSuC7JU4sPv9XfD///38/AAAAAKuAGbQAAIC/NLtzN+1YbbUAAAAAAACAP2crwzaV/8e2HJODtgAAgD/q4a67nGgqPjZtfD+y/3+/LMgPurqTQruiLKu64Uh8v9DRLT4AAAAAleFzP3eqmz4AAAAAleFzP36qmz4AAAAAzeFzPxSpmz4AAAAA0OFzPwepmz6y/3+/LMgPurqTQrtHRqO7UxwvPtM5fD+iLKu64Uh8v9DRLT5clee7XWspPid3fD8AAAAAAACAPwAAAICAA0A/BlApPwAAAIAAAIC/m7UOMsgM1zNeoYq0gUJ1tAAAgD8AAAAAQqqbPp7hc78AAAAAlOFzP4Kqmz7Z+eGzxCEHtgAAgD8AAAAAAAAAAAAAgD/JmJ05/v9/PwAAAIAnTfE+RslhPwAAAIA7I54+u3tzP9rA7DQAAIA/AAAAAAAAAIDZ+eGzxCEHtgAAgD/gsdqzAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD/JmJ05/v9/PwAAAIAAAIA/AAAAAAAAAIDTjnO/hV7HPaqXlb5kuJm773NzP4dOnj5Ui0i/cwoDPhO1G783vX67OmxzP2F/nj4b1i+/2Q46PxmqjDQAAAAAAACAPwIAIDQ3qmuxVUVUtQAAgD8b1i+/2Q46PxmqjDQAAAAAAACAPwIAIDQAAAAAAAAAAAAAgD8AAAAAlOFzP4Kqmz4AAAAA0OFzPwepmz62ml4/AAAAAKrZ/L69ml4/oy8otZDZ/L7//38/AAAAAF8IVDQAAIA/KyxetfzmoLQAAAAAsambvrXhcz8AAAAA0OFzPwepmz4AAIC/AAAAAAAAAIAAAAAAQqqbPp7hc78AAAAAlOFzP4aqmz4AAAAAmuFzP1Gqmz4b1i+/2Q46PxmqjDQAAAAA//9/P/r/RzQAAAAAAAAAAP//fz8AAAAAAAAAAAAAgD8AAIC/r934tgAAAIAAAIC/y//MNdzSTTMAAIC/WROdNwAAAIC2ml4/AAAAAKrZ/L69ml4/oy8otZDZ/L4AAIA/qB0UtVBTLLYAAIA/AAAAAGpfgLQb1i+/2Q46PxmqjDQAAAAA//9/P/r/RzQTrQaxAAAAAAAAgD8AAAAAlOFzP4aqmz4AAAAAluFzP3Gqmz4AAAAAzeFzPxSpmz4AAAAA0OFzPwepmz4AAIC/hBOdNuGC6rIAAAAAAACAPykwB7UAAIC/hhMdN+SCarMAAIC/WROdNwAAAIAAAAAA//9/P4jkIzQAAAAAAACAPyBpl7QAAAAAAACAP4P5IqkAAAAAAACAP8OrQrQAAIC/AAAAANjBt7V2QtKyzT1qtAAAgD8AAAAAAACAP4P5IqkAAIC/yQcXtmqzDrWMtV6/IuYbvn4l8D6BA1y+jnduPzZBlj5lyF67lnNzP99Snj5+aHO/4jK5veuwlz6rQ4a7HHRzP41Onj4AAAAAneFzP0yqmz7//38/AAAAAOorPrQAAIA/pB0UtZZWnLW+ml4/zjOLtIzZ/L4AAIA/9O4EtbgXwLMAs3c/pVKBPs68ujQAAAAA//9/PwAAAIBkhEE1a1gXtQAAgD8As3c/pVKBPs68ujQAAAAAAACAv/f/R7VUhEE1AAAAAP//fz8AAAAAaok/NQAAgD8AAAAA//9/PwAAAIAAs3c/pVKBPs68ujQAAAAAAACAv/f/R7UAAAAAaok/NQAAgD8As3c/pVKBPs68ujSvt1+/CGvyPnCL4T0NdW2+7fI0vzkVKz8AAAAA//9/P/r/RzQ/Ma84//9/P9UASDQAAAAAAAAAAP//fz8AAAAA6vhPNQAAgD8352w+4Mk0P+JMK7/Q4WA/5Rvvvscxz70AAAAAAAAAAP//fz8AAAAAAAAAAAAAgD8AAIA/AAAAAE5EW7MAAAAAAAAAAAAAgD///38/AAAAAG+CBLMAAAAAAAAAAP//fz/Aml4/AAAAAIvZ/L4AAIA/AAAAABFAcDQAAAAAnOFzP1Cqmz4AAAAAluFzP3Gqmz4AAAAAluFzP3Kqmz4AAAAAzeFzPxSpmz4AAAAA0eFzPwKpmz7//3+/xwcXtm2zDrUAAAAAAACAPygwB7UAAAAAAACAP4nkIzQAAAAAAACAP76rQjQAAIC/4QcXtwAAAIAAAIC/ygeXtr45pDQAAAAAAACAP8OrQrQMgoOtfQ6StP//fz9qMnC+q9Q1v6nnKT8nkV8/6d/yvvc64729ml4/eCvFtI3Z/L4AAIA/dPlttIxvirWSiBY7oltzPz3nnj5wDik/AAAAAEA9QD+Cuik/AAAAAGalPz/Aml4/AAAAAIvZ/L4AAIA/AAAAAAAAAIAAAAAAluFzP3Kqmz4AAAAA0eFzPwKpmz4x0qI7LnJzP8JYnj4AAIA/uDzTtGn0m7VwDik/AAAAAEA9QD8AAAAAT2DWtAAAgD9WWYUuAAAAAAAAgD8AAIA/AAAAACy9B7Q/SIUuAAAAAAAAgD+HAmG/Oq/uPmYlzj2l+Wg+aUUzP5Q4Lb8AAIC/kSxetXIfRLRdp0S7QnNzP3pVnj4AAIC/AAAAAFTZmTQAAAAAAAAAAP//fz8AAIC/AAAAAN2/sTQAAAAAAAAAAAAAgD8AAAAAT2DWtAAAgD+wUIUuAAAAAAAAgD8AAIA/AAAAAGehEbTkUIUuAAAAAAAAgD9Q/X8/j8vJO6092Tt3vZk783NzP3pOnj4AAIA/ox0UtU0Ga7RBMYY7GHRzP7BOnj4AAIC/4QcXtwAAAIAAAIC/ygeXtr45pDQAAAAA//9/P4jkIzQAAAAAAACAPyBpl7REi0g/RAsDPhy1G78ZEnM7zGpzP2uInj55P+I2ihCevsN+cz/KrrQ5lOdzP9mEmz50NJ6+HlaWvhGUZz/1f6c6yuRzPwyWmz4F1pw6COVzP4yUmz4tWBS/TdSAvhdyRj8WiZK7lehzP0N6mz4AAAAAAAAAAAAAgD8AAAAAIw3aNAAAgD8AAIC/AAAAAGOmSTQAAAAAT2DWtAAAgD8AAAAAAACAP4nkIzQAAAAAAACAP76rQjQAAAAAAAAAAAAAgD8AAAAAIw3aNAAAgD+BauwoAnNdtQAAgD+BA1y+jnduPzZBlj5dp0S7QnNzP3pVnj4AAIC/AAAAAAAAAIAAAAAAT2DWtAAAgD+BA1y+jnduPzZBlj5TqxO8M+tzP6Ncmz4UBTW/GIpfvictLD+BA1y+jnduPzZBlj5TqxO8M+tzP6Ncmz4AAIA/AAAAAL/Fg7EAAAAAAAAAAAAAgL8AAIC/AAAAANy/sTQAAAAAAAAAAP//f78AAIC/AAAAAFTZmTSEamwoAnPdtAAAgD///38/AAAAAGY01LMAAAAAg3vOtAAAgD///3+/AAAAAJSEcTMAAAAAAAAAAP//f7///3+/AAAAAJSEcTPPpUq/um0cPzerCTQAAAAAAAAAAAAAgL8AAIC/AAAAAAAAAIAAAAAAAAAAAAAAgD8AAAAAIw3aNAAAgD+PtV4/twscvlgf8D5ztF47l3NzP+FSnj4IBFw+hnduPyxBlj5YJlqzpQQ0swAAgD8AAIA/AAAAALg9KLQnqd2zAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAACAP3AKLTQAAIC/AAAAAPJuBjRX0Vq/rGX8PqZPJj4OYIm+dRZEv+COFT8AAAAAAAAAAAAAgL/PpUq/um0cPzerCTQAAAAAAACAP3AKLTTeTok+DVtBP8AWGb+dZls/npH7vrrfHr4AAIC/AAAAAAAAAIAAAAAAIw3aNAAAgD+Damwpg2pstQAAgD+Wz4q+uOJEvwYsFD/0CVs/n+H7vnLGJL4AAIC/AAAAADkMGbMAAIC/AAAAAAAAAIAAAAAAAACAP8GrQrVWnJ0oVpydtAAAgD/Z+eGzxCEHtgAAgD/gsdqzAAAAAAAAgD/X6pE+K2J1P9zZKjTW6pE+KmJ1PzEPKjQ0OFu/wAH8PrUYID7RJoc+kClAP/kOG7+s/iu/ZZ09v13K1zUAAAAAaok/NQAAgD8AAAAA//9/PwAAAICs/iu/ZZ09v13K1zUAAAAAAACAv/f/R7UAAAAAaok/NQAAgD8AAAAAAACAv/f/R7Ws/iu/ZZ09v13K1zXhVwa11CggNf//fz8AAAAA//9/PwAAAICs/iu/ZZ09v13K1zV/Vga1VNcMMwAAgD/3hkU4AACAP/b7RzR0Zas+1TpxP4V8FzQAAAAArpYfNQAAgD8AAAAA9Ng/NQAAgD9ss7Wyg/8ZtAAAgD/o/Cu/AJ89vwAAAIAHXga1le4NMwAAgD8AAAAAAACAPwAAAID3hkU4AACAP/b7RzR0Zas+1TpxP4V8FzTmWa0xAAAAAAAAgD8AAIA/wB0Utf0jYLSylUQ7QHNzP3pVnj7Z+eGzxCEHtgAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPyHHMTTeOY4+t+x1P1AzIDQAAAAAAACAPyHHMTTeOY4+t+x1P1AzIDSLNJ4+L1WWvjOUZz/2f6e6yeRzPwyWmz4H1py6COVzP42Umz5PqxM8MetzP6hcmz4IBFw+hnduPyxBlj4gBTU/zIdfvkktLD9PqxM8MetzP6hcmz4IBFw+hnduPyxBlj6ylUQ7QHNzP3pVnj4IBFw+hnduPyxBlj4AAIC/QYNtt1JbqDMAAAAA//9/v/wrQ7aV/8e2HJODtgAAgD87I54+u3tzP9rA7DR0Zas+1TpxP4V8FzTgsdqzAAAAAAAAgD8AAAAArpYfNQAAgD8sRzWyJP+1NAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPx/HMTQAAAAAAACAPx/HMTQAAIC/AAAAAAAAAID//3+/AAAAAJSEcTPWpUq/sG0cPwAAAIDPpUq/um0cPzerCTQAAIC/AAAAAAAAAID//3+/AAAAAJSEcTMAAIC/AAAAANjBt7UAAAAAAACAP8GrQrUAAAAAAAAAAP//fz/9Boczc1FzNQAAgD/JmJ05/v9/PwAAAIAAAIA/AAAAAAAAAIA7I54+u3tzP9rA7DQAAIA/AAAAAAAAAIAiyjM0HiETtQAAgD+YIVq/hj73PlnHTj7iZ5m+/C5Pv95VAT9GQJq+fZ9PvzBgAD/uRlo/Buj2vg7uTb5gjZk+kfBMP+vRBL+WMFo/AID3vvKNTL7WpUq/sG0cPwAAAIDPpUq/um0cPzerCTQAAAAAAACAP4rkIzQAAAAAAACAP3AKLTQAAAAAGKqNNQAAgD/JmJ05/v9/PwAAAIAnTfE+RslhPwAAAIAAAIC/r934tgAAAIAAAIC/T8ZutgJ4ljIAAIC/AAAAAAAAAIBHzNGyaJlRtAAAgD8AAAAAAACAP4rkIzQAAAAAAACAP3AKLTQAAIC/AAAAAAAAAID//3+/AAAAAAAAAIDSBlq/tNv3PpOZTT6hWpc+yA9LPzpKCL8AAIC/AAAAADcMmbMAAIC/AAAAAAAAAIAAAAAAAAAAAAAAgD8AAAAA//9/PwAAAIAnTfE+RslhPwAAAIAAAAAAAAAAAAAAgD8AAAAA//9/PwAAAIAnTfE+RslhPwAAAIAAAAAAAAAAAAAAgD8AAAAAAACAPx3HMTQAAAAAAACAPx3HMTRqqV2/4inrPiIKSz4q+Ka+2pNZv5vo0z7UhAOtlBEStAAAgD9E66a+9YNZv/4z1D6SBF0/Dljsvs61UL6g4KQ+IKVZP+JD1b4Z6lw/oZvsvrBDUb4AAAAAAAAAAAAAgD8AAAAA//9/PwAAAIAAAAAAAAAAAAAAgD8AAAAA//9/PwAAAIBIgl2/b4jrPp7+Sz6T/aM+RktYPwxc277nMCA+bh2cvnF/cD+BqYm3ledzP9qEmz4AAIC/AAAAAAAAAIAAAIC/AAAAAAAAAIDWpUq/sG0cPwAAAIAKIV+/loznPmq6QT5kLaq+lnRcvwXuxD5xwam+DzFcv9p3xj4OKl4/o2Dpvsh+Sr7WpUq/sG0cPwAAAIAAAAAAAACAP4rkIzTHA6c+fu1cP/SExb4OKl4/o2Dpvsh+Sr4AAAAAAACAP4rkIzQAAIC/AAAAAAAAAIAKIV+/loznPmq6QT7HA6c+fu1cP/SExb4AAAAAludzP9uEmz4AAIC/AAAAAAAAAIAAAIC/r934tgAAAIAAAIC/AAAAAAAAAIAAAIC/r934tgAAAIAAAIC/WROdNwAAAIAAAIC/WROdNwAAAIAAAAAA//9/P4jkIzQAAIC/4QcXtwAAAIAAAAAA//9/P4jkIzQAAAAAAACAP4nkIzQAAIC/4QcXtwAAAIAAAAAAAACAP4nkIzQnTfG+RslhPwAAAIDJmJ25/v9/PwAAAIAAAAAAAAAAAP//fz8AAAAAAAAAAAAAgD/o+eEzzSEHtgAAgD8AAIA/AAAAALmIDrQAAIA/AAAAAJsVJDUAAIA/+z3xtV2clbbiOY6+t+x1P02uKzQAAAAAAACAPxTHMTQAAAAAAAAAAP//fz/o+eEzzSEHtgAAgD9EBTS3AACAP9/SLLVuUnCsblJwNQAAgL8AAIA/JTJwNwnEW7Z0IPw2AACAvxQN8jQAAAAA2brftAAAgD8AAIA/9jFwN0DEW7aPO5q+1ht0P0fmvDQAAAAA2brftAAAgD90IPw2AACAvxQN8jQAAIA/vGm+NeYymTX0xWu/kk/Hvs0/frzwh/S9Bq/HPti8ab8vVaW+GElyP7VU/DQAAAAAAACAv0meGbVuUnCsblJwNQAAgL8AAIA/9uj1tm1sJLfX6pG+KWJ1P1PpJDSus7UyHm8QtAAAgD+dntWvAAAAAAAAgD8AAIC/QYOENripCzhEBTS3AACAP9/SLLVuUnCsblJwNQAAgL8AAIA/FHWbNoyaHrcAAAAAAACAP8OrQrQAAAAAAACAP7KXDDSRFi2zAAAAAAAAgD+dntWvAAAAAAAAgD8ZJoIz6YeLtAAAgD8AAAAA2brftAAAgD8AAAAAAACAP+BcITUAAIA/vGm+NeYymTWRrgoyQuoCtAAAgD8AAAAAAACAP8GrQrUAAIA/AAAAAPICAbUnTfG+RslhPwAAAIAAAAAA//9/PwAAAIAAAAAAAAAAAAAAgD+WzNEy55lRtAAAgD8AAAAAAACAPxjHMTQAAAAAAAAAAP//fz8AAAAAAAAAAAAAgD8nTfG+RslhPwAAAIAAAAAA//9/PwAAAIAAAAAAAAAAAP//fz8AAAAAAAAAAAAAgD9uUnCsblJwNQAAgL8AAAAAAACAv0meGbUAAIA/9T5/tY7whLYAAAAAAACAP+BcITUAAAAA2brftAAAgD8AAIA/sD5/tWnwhLbiOY6+t+x1P02uKzQAAAAAAACAPxTHMTTFQtIyTj5qtAAAgD8AAAAAAACAP8OrQrQAAIA/AAAAALCQVjTFee+pAAAAAAAAgD+YCbQyXPSptAAAgD8AAIA/AAAAAM1pCrUKgoMtjQ6StAAAgD8AAAAAAACAP8OrQrQAAAAAAAAAAP//fz8AAAAAAACAP8GrQrUAAIA/AAAAALCQVjQAAAAAAACAPxjHMTSKFi2zAAAAAAAAgD+dntWvAAAAAAAAgD8AAAAAAACAPx3HMTQAAAAAAAAAAAAAgD8AAAAA//9/PwAAAIAAAAAAAAAAAAAAgD8AAAAA//9/PwAAAIAAAAAAAAAAAAAAgD/RhAMtoxEStAAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAACpXbzUAAAAAAACAPx3HMTTBwC07KudzP+qFmz7IwC27LOdzP+aFmz4AAIA/tR0UteYjYLQAAIA/AAAAACDotTIAAIA/rR0UtdkjYLRRY1E7a3NzPzpUnj4AAIC/hSxetTh8lLT//3+/apCxtDBF37MAAIC/fyxetUi3rbSRdVG7anNzPztUnj4AAIC/dCxetcgj4LQAAIC/epCxtAAAAIAAAIC/dCxetckj4LTvQoa7H3RzP31Onj4AAIA/ox0UtcYjYLQAAIA/AAAAAK44yzMAAIA/oh0UtcgjYLSPN4Y7IXRzP3JOnj5k9Ww0nX5zP3MRnj6PeHM/2HnDvTZ6lj7OQBy583pzPw0onj7IN1I/J/00vgLqCj8Y7LG6BG9zPwhxnj4bqRY/T7GAvia3RD8Y7LG6BG9zPwhxnj4AAAAAn35zP28Rnj4AAIA/3PFDs3ixGjRm9Ww0nX5zP3MRnj5weHM/PGHDPfh8lr7k1co++GWSvqpdXz8AAIA/H9kiOdGp7TdZAS+7xGRzP+uunj5U9ew0nn5zP2wRnj7CG08/9tE5PlYfD78AAIC/VdkiOSCq7TcE1sq+V2aSvpZdXz9rAy87w2RzP+2unj4s9Wy0n35zP2sRnj4qeRY/j8N/Pp/9RL+K9eyznX5zP3cRnj58N54+p1WWPp+TZ78KqRa/e7GAviu3RD/98bE6AG9zPx1xnj798bE6AG9zPx1xnj67N1K/Mf80vuzpCj9uXRw58npzPw4onj6TAaWxLxKePn5+c7+4rSarmn5zP4QRnj6aeHO/s3fDvRd6lj4y9Wy0oH5zP2QRnj5+N56+qlWWPp6TZ7869eyzmn5zP4gRnj7//3+/xKG5MkcRBrYAAAAAnH5zP3oRnj4ueRa/lMN/Ppz9RL+UowEqnn5zP3URnj5meHO/R2PDPRJ9lr5x9ew0m35zP34Rnj67G0+/99I5PkwfD7+j9Ww0nn5zP20Rnj6/G0+/8tI5PkcfD78AAAAAoX5zP10Rnj5oeHO/NGPDPQR9lr52/6azoH5zP2YRnj4gN78xn35zP2QRnj4AAAAAnH5zP30Rnj5zMYu0hWdzP3Ofnj4AAAAAn+FzPzqqmz4AAAAAsambvrXhcz8AAAAAn+FzPzqqmz4AAIA/AAAAAAAAAIAAAAAAsqmbvrbhcz8AAAAAoOFzPzqqmz4AAIA/CNmiOLCpbTd0MQu1g2dzP4afnj4AAAAAoOFzPzqqmz4AAIC/ONmiOPapbTcAAAAAiWdzP2Kfnj4AAAAAoOFzPzuqmz4AAIC/AAAAAAAAAIAAAAAAsqmbvrbhcz8AAAAAoOFzPzuqmz7Oy5G0FURzP1l4nz4AAIC/VdkiOSCq7TcE1sq+V2aSvpZdXz/sLtA5dzpzP/Cynz7k1co++GWSvqpdXz8AAIA/H9kiOdGp7TdfddC5dzpzP++ynz4jBJgz521zP094nj5dSyUznX5zP3sRnj6ZeHO/yHfDvSd6lj4Ur5GynH5zP30Rnj5XNFK/WwI1vszuCj+73vQ48HRzPw1Nnj5AKL8xnX5zP3sRnj7//3+/KeJis0Iy7bV3ogi0m35zP4MRnj4veRa/k8N/Ppz9RL8ShJCzmn5zP4sRnj63hRCzn35zP3MRnj6XASWyLhKePn1+c7/TgpCzo35zP0sRnj6EN56+qlWWPp6TZ78Axti0pH5zP0MRnj6gVeiykUxzP4VEnz7ioha/NbSAvnC7RD+qjeQ5DVRzP8IWnz7tohY/HLSAvmu7RD92jOS5DlRzP7YWnz6NeHM/6XnDvUN6lj5J/KQznH5zP4ARnj5PNFI/XgY1voXuCj/pk/S47nRzPxJNnj4AAIA/Z/UStCRO4DQSlRQ0nn5zP3IRnj5yeHM/K2HDPel8lr4/NcQzoH5zP2cRnj7GG08/8tE5PlIfD78AAAAAm35zP4IRnj4reRY/i8N/Pp79RL/ar0AzmX5zP40Rnj6BN54+qFWWPp+TZ7/Ug5A0on5zP1MRnj7hp6kzr42KtAAAgD9Ms/gy7TwJtQAAgD8AAAAAAACAvwAAAIBLR40zTomotQAAgD8AAIA/BtIMNeEH3DUAAAAAAACAvwAAAIAAAAAAILcDtgAAgD8AAIC/BtIMNeEH3LVQR42zUYmotQAAgD8AAAAAAACAvwAAAIBWs/iy7jwJtQAAgD/ip6mzq42KtAAAgD9d+oi4AACAP1kNSDQAAAAAAAAAAAAAgD9a+oi4AACAP1kNSDQAAAAAC97stQAAgD+TBgCAAACAP0zvLjQAAAAAXe/stQAAgD+TBgCAAACAP0zvLjQAAAAAAACAP0zvLjQAAAAAOkJINQAAgD8AAAAAAACAP0zvLjRe+og4AACAP2b+RzQAAAAAj49HNQAAgD9e+og4AACAP2b+RzQAAAAAAAAAAAAAgD8AAIC/AAAAAAAAAICfyoQ0aje+Pbbkfj+fyoQ0aje+Pbbkfj///3+/HhOGNAAAAIAouaG45edrP0zXxj63bII2HppuPhX0eD+3bII2HppuPhX0eD8AAAAABehrP7rWxj6oXPIz1UGHPtXndj8AAIA/AdKMNNoHXDWoXPIz1UGHPtXndj8AAIA/AAAAAAAAAIAAAAAA4udrP1zXxj4AAIC/AdKMNNoHXLXIgKez1UGHPtXndj/IgKez1UGHPtXndj8AAIC/AAAAAAAAAICU9OQ44edrP17Xxj7Uin82HJpuPhT0eD/Uin82HJpuPhT0eD8AAAAABOhrP7rWxj4AAIA/AAAAAAAAAIAHZIq0ZTe+Pbbkfj8HZIq0ZTe+Pbbkfj///38/AAAAABlvFTQAAAAA5udrP0/Xxj4fNBU5aLVqP/htzD4AAIA/AAAAAAAAAIDK8Jg432S9PmDXbT8AAIA/DtKMNO0HXDUAAAAA8rVqP4BrzD4Yz0o2H2S9PoTXbT8AAIC/AAAAAAAAAIAAAAAAabVqP/ZtzD4AAIC/DtKMNO0HXLWIGQ4z4mS9Pl/XbT8AAAAAQqqbPp7hc78AAAAApuFzPx2qmz4AAIA/AAAAAAAAAIAAAAAAQqqbPp7hc78AAAAApOFzPxyqmz4AAIC/AAAAAAAAAIAAAAAAQqqbPp7hc78AAAAApuFzPx2qmz4AAAAAAACAvwAAAIAAAAAA4TeNsgAAgD8AAAAAAACAvwAAAIAAAAAA4TcNswAAgD8AAIA/BtIMNeEH3DUAAIC/BtIMNeEH3LUAAAAAAACAvwAAAIAAAAAAAAAAAAAAgD9SzagzAACAP/JDMTRSzSgzAACAP9LtHjQAAIA/xQeXth0tJjUAAAAAAACAP9kzDbQAAIA/onOONfdCcTUAAAAAAACAP9kzDbQAAIA/xgeXthwtJjX//38/yW2PtECfUzMAAIA/rQ/ntgCFUrQi6ka3//9/PwHQYbX//38/YmH3N7uCAzbxW/U2AACAv+JNaDUAAIA/ZmH3N7qCAzbwW/U2AACAv/ZNaDUAAIA/3jZWNqhjhTUAAAAAAACAv4PNsbUAAIA/uIhltwgEqzIl6ka3//9/PwvQYbUAAIA/1HOONfVCcTUAAAAA//9/PxgIHTUAAIA/3jZWNqljhTUAAAAAAACAPxgIHTUAAIA/AAAAAEP3cbQAAAAAAACAv4PNsbUAAIA/AAAAAN32cbRSzSgzAACAP9LtHjQAAAAA//9/vwAAAIAAAAAAiVuQswAAgD8AAIA/qWgdtQAAAIAAAAAAl6X9swAAgD8AAAAA//9/PwAAAIAAAIA/ebGhNRiYC7UAAAAA//9/vwAAAIAAAAAAAAAAAP//f78AAIA/AAAAAAw1UzYAAAAA//9/PwAAAIAAAAAAAAAAAP//f78AAIA/mEWXNUaRhrZc4QK2AACAvwAAAIAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAIAAAAAAJIgyNQAAgD9c4QI2AACAPwAAAIAAAIA/AAAAAAAAAIBc4QK2AACAvwAAAIAAAAAAAAAAAAAAgL8AAIA/AAAAAAAAAIBc4QI2AACAPwAAAIAAAAAAAAAAAAAAgL8AAIA/AAAAAAAAAIAAAIA/LPrOtsWbNjQAAAAAAAAAAAAAgD+hnbI2AACAPzCGvjQAAIA/AAAAACPwizIAAAAAAACAvwAAAIAAAAAAAAAAAAAAgD8AAIA/rJQOtVD3lTMyaxK2apEhtgAAgL8AAAAAAACAvwAAAIAAAIA/LyPMth1s6rOUaxK274cyNQAAgL+hnbI2AACAPzCGvjQAAAAAAAAAAP//fz8AAAAAAACAP47kDjUAAIA/AAAAABNMOLUxJ+61//9/vwAAAIAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAIAAAIA/AAAAAAAAAICsaxI2Mt7ptQAAgL8xJ+61//9/vwAAAIAAAIA/AAAAABNMOLUAAAAAAACAP47kDjWoaxI2097pNf//f79d4YK1AACAvwAAAIAAAAAAAAAAAAAAgD8AAAAA1UsktQAAgD9d4YI1AACAPwAAAIBd4YI1AACAPwAAAIAAAAAAAAAAAAAAgL9d4YK1AACAvwAAAIAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD+nnTI2AACAP6Qn7jR8+SIt6MS2NQAAgL+bnTI2AACAP6cn7jTD6/+s8cQ2tgAAgL8zJ261AACAvwAAAIAzJ261AACAvwAAAIAAAAAAAAAAAAAAgD8ne4eyAAAAAAAAgD8AAIA/AAAAAB0NNzQAAIA/AAAAAKRo0rMAAIA/AAAAAKFo0rMAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAABBMuLQAAIA/AAAAABVMuLToz7A2AAAAAAAAgL8AAIA/vWwCtcO917Tkz7C2/o15rAAAgL8AAIA/t2wCtcu9V7QAAAAAwcVeNQAAgD8AAIA/uGwCtQAAAIAAAAAAs9B3NQAAgD8AAIA/AAAAAAAAAIAAAAAAAAAAAAAAgL8AAIA/AAAAAAAAAIAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAIA/AAAAACGgBLcAAIA/AAAAAIXBCTYfroU2AACAv4n/7rQAAAAAAAAAAP//fz+LmJc1//9/P71fFTX/vz8tFMW2NQAAgL+R7nM2AACAv4P/7rTlFw6t8cQ2tgAAgL9belE1AACAP7ZfFTUAAAAAR0wktQAAgD8AAIA/V4fnNAJ0xirnz7A2AAAAAAAAgL8AAIC/s1MPNvieoqzlz7C2xC8TLgAAgL8AAIC/jf3WNaaNcqwAAAAAhcReNQAAgD8AAIA/uouBNTuUfSsAAAAA+dF3NQAAgD/XBDU/EQU1P6U/MzUAAAAAAsSJNQAAgD8ABTW/6AQ1vzk/szQABTW/6AQ1vzk/szQAAAAAA8veswAAgD/pBDW//gQ1P8g/s7QAAAAA1ZwBNQAAgD8KBTU/3QQ1v4tfFbUAAAAAAAAAAAAAgD/nBDW/AAU1P8E/s7Q/zlG2osSJNQAAgL8FBTU/5AQ1v45fFbWdzVE2JVSitQAAgL/dBDU/CQU1P6E/MzUczlE2G1SiNf//f78BBTW/5QQ1vz0/szQBBTW/5QQ1vz0/szSYzVG2MgwWtgAAgL+ygig+kOj4vri1Wz+fBWc/yll/PnLisz7Yrag+zadxvyOFobwfrVc+rGX6vliwWD/u22A/+CWhPpkyuD4frVc+rGX6vliwWD+1wE6/De8Ov5lJQj6nJO09NtH7vsDqXD/Yrag+zadxvyOFobxmKVG/DxYHvy32bT5BQ+49XE4Ev3wgWT9BQ+49XE4Ev3wgWT9sTEu/B6UXv1AeCz6IsEI+a6cdvy28Qz8xtUE+YWAdv+MERD8EkWo/RXBQPiigsD65P0W/JS0ivyPSkD1lMHA+xNM1v83oKT8bd20+6vM0vwAUKz+2EWs/1Wg+PmsGsz7vYYk+ARhEv2iMFT+E72g/+0tCPpvdvD5tQT2/ymMsvyc1iTq4z4o+wOJEv/MrFD+0fzi/afQwvziPWL37Ppo+mJ5PvwpiAD/Dapk+QzFPv2FRAT+8IGk/xlY4PuZnvj47hDm/5FYvvwsRm70X7KY+5IRZv4sv1D6a+aY+SJVZv5/h0z7Lj24/JQUVPkUiqj647jq/0dAtv5IFnL0qwak+FjFcv/Z3xj4QLao+onRcvxDuxD5l9nA/vfIFPjNlnz7t22C/+SWhPpsyuD4mrVe+vGX6vlKwWD/Yrai+zadxv72BobwmrVe+vGX6vlKwWD9tQ+69ZU4Ev3MgWT9vKVE//xUHvzf2bT7Yrai+zadxv72BobxtQ+69ZU4Ev3MgWT+PJO29NdH7vsLqXD+9wE4/Du8OvxxJQj6UBWe/oFl/Prfisz6Lgii+iuj4vru1Wz93sEK+X6cdvzi8Qz9sTEs/EqUXv3UdCz4DkWq/ZXBQPiOgsD49tUG+XWAdv+QERD9IMHC+udM1v97oKT+4P0U/JS0iv8zRkD23EWu/eGk+PjAGsz4wd22+5PM0vwYUKz+tz4q+yOJEv+wrFD9SQT0/5WMsv4GHiToo8mi/VkVCPkbSvD5fZIm+axlEv/6JFT/oQJq+8J9Pv0pfAD8cgDg/PvQwvzFZWL3EGGm/fZc4PkR/vj4Ja5m+LjFPv2tRAT8K66a+woNZv/801D5BhDk/4VYvvwAQm72wjm6/RgkVPo4nqj62+aa+QJVZv6Xh0z5xwam+DzFcv9p3xj7c7jo/qtAtv28FnL1N9nC/vfAFPiFmnz5kLaq+lnRcvwXuxD68JhI+NWH0vkr4XT9FDGc/iQl/Prbcsz4nK9Y9wOaivkI3cT/Yrag+zadxvyOFobzu22A/+CWhPpkyuD7dnhY+2tX9vqIcWz8YxE6/gOUOv12AQj4nK9Y9wOaivkI3cT/Yrag+zadxvyOFobxmKVG/DxYHvy32bT4090I+Jr8gv5IvQT9PS0u/bKcXvxcOCz7zxDo+ngwbvxFIRj+sj2o/+4NQPoqhsD7fWXA+VFs3vz8+KD+BOkW/zTQiv1tzkD0Remc+Z+Azv9i3LD9lGms/d2U+PqLZsj4MkYk+eNBCv2orFz9d9mg/uDpCPjvAvD4EJ44+uPFEv61MEz9SPT2/VGgsvzA3bTrV5J0+iYRQv7+V+z7ufTi/dfUwvzU4Wb1JS5o+HvdMv7WQBD8+F2k/zaM4PqmDvj5Vc6Q+zzxbvzr6zj6zhDm/ZVYvv10Rm71L2aM+2C1Zv+7w1z5Ijm4/KA4VPsQoqj5kEaU+8IFdv0SOxD647jq/0dAtv5IFnL1kEaU+8IFdv0SOxD5l9nA/vfIFPjNlnz7t22C/+SWhPpsyuD7Yrai+zadxv72BobxIK9a9reaivkc3cT9vKVE//xUHvzf2bT7Yrai+zadxv72BobxIK9a9reaivkc3cT+Bw04/O+cOv+d1Qj7snha+09X9vqMcWz88DGe/Ugl/Pvzcsz7SJhK+L2H0vkr4XT9TS0s/eacXvz0NCz4j90K+Lb8gv48vQT+qj2q/F4RQPoehsD7wxDq+pAwbvwxIRj+RO0U/PzMiv1WGkD3aWXC+WVs3vz0+KD9yEmu/N2k+PnoCsz4Deme+a+Azv9W3LD84PT0/bmgsvwncbTobJ46+t/FEv6lMEz+Y+2i/Sy1CPtqpvD4ikYm+eNBCv2YrFz/TfTg/mPUwvwUzWb3W5J2+jIRQv7WV+z7gE2m/4744PpqNvj5SS5q+IfdMv7CQBD+Sgjk/rVgvv9sOm70vc6S+1Dxbvz36zj5Kjm6/ugsVPkMpqj4s2aO+3C1Zv+/w1z7c7jo/qtAtv28FnL1JEaW+9IFdv02OxD5N9nC/vfAFPiFmnz5JEaW+9IFdv02OxD4CAAUACAACAAgACQARAAwADwARAA8AbAAWABIAFAAWABQAGAAaABcAGQAaABkAcgAhACQAHgAhAB4AOgAoACoAJQAoACUAOwArAC0AAgA1AC4AMgA1ADIAPQALABsANwALADcADgAPAEMAPgAPAD4AbABFADgAHABFABwASAB4B3YHewd4B3sHfQdRAE0AnQZRAJ0GoQYgAFIAVQAgAFUAIwBaAAIALQCAB3sHdgeAB3YHggclACoAWwAlAFsAgABeAGEAZgBeAGYAAwAlAGkAOwB1AGsAJgB1ACYAeQB7AH4AegB7AHoAigCBAFwAfwCBAH8AfAB6AH4AgwB6AIMAjgCFAFgALACFACwANAB6AIcAigCNADcAGwCNABsAcwB6AI4AhwCIAJAAlACIAJQAiwAzADsAaQAzAGkAsgCRAIkAjwCRAI8AmgCYAJ8GrQaYAK0GmgVqAHYAnQBqAJ0AswCeAJ8AWwCeAFsAKgACAHEAYAACAGAABQCiAGQApwCiAKcAQAB0AHgAqgB0AKoAnAB3ACcArQB3AK0AqABwAKUAYgBwAGIAXwAlAIAArgAlAK4AqwCwAHsAigCwAIoAxACvAIEAfACvAHwAsQBaALcAugBaALoAAgCLAJQAvACLALwAxQAYABQAvQAYAL0AvwBXAFQAlgBXAJYABQFyABkAwAByAMAA9wCTAJIAwQCTAMEA5wDBAJIAmQDBAJkA6QCgAIIAfQCgAH0AXQCEADMAsgCEB4AHggeEB4IHhgesALQAmwCsAJsAqQDGAIQAsgDGALIAqwDLAM4AzwDLAM8AAADUANcAzQDUAM0AygDaAN0A1QDaANUA0gBQAKAGngZQAJ4GlwDjAOUA4QDjAOEAKAG7AJMA5wC7AOcAQwHkAOsA6gDkAOoA4ADtAK8AsQDtALEA8wDwAI0AcwDwAHMA+ACrAK4A7ACrAOwAxgDyALAAxADyAMQAAQHFALwA9ADFAPQAAwH6ALkA/QC2AFkAhgC2AIYAyADQAMwAAAHQAAABRgEBAcQAAgECANEACAECAAgBcQDGAOwA+wDCAOgACgHCAAoBGQGmAA4BbgCmAG4APwARAQkBDwERAQ8BHQEEAfUAEwEEARMBFwElARUB8gDyAAEBFgHyABYBJQEWAQEBAgFvAAYBCwFvAAsBpAARARgBCQH7AOwAHgH7AB4B+QAgASEBnwAgAZ8AngDrACMBJAHrACQB6gBKASYBFwEXARMBQAEXAUABSgHmAMMAGgHmABoBMQEtASoBLAEtASwBNgERATABGAERAR0BMwERATMBMAEyARsBLwEyAS8BNwG5APoANQG5ADUBPQE4AfYAuwA4AbsAQwFEAb8AvQBEAb0AOwG1AMcA/AC1APwAuABBARIB9gBBAfYAOAEKAegAmgAKAZoAjwAPAQkBjgAPAY4AgwD3AMAARQH3AEUBfgEiARABggAiAYIAoAAVASUBSQEVAUkBYgGIB4oHhAeIB4QHhgfmADEBTAHmAEwBQgE0AfkAHgE0AR4BegFLATABMwFLATMBTgFNATIBNwFNATcBWgEpAU8BUQEpAVEBKwE/AVUBWAE/AVgBXQFZATYBLAFZASwBhQH+AF4BXAH+AFwBRwEBAFsBYAEBAGAByQDKAF8BZQHKAGUB1ABsAF0GXwZsAF8GEQDTAGMBbAHTAGwB2QAoAeEAcAEoAXABgwFUAT4BcwFUAXMBlAHgAOoAdQHgAHUBbgEnAXYBeAEnAXgB4gB9AfAA+AB9AfgAfwE9ATUBcgFWAYABhgFWAYYBiAFIAV0BiQFIAYkBaAaLAUoBQAGLAUABOQHYAGsBjwHYAI8B3AA6AUIBTAE6AUwBjAGRAXUB6gCRAeoAJAFiAUkBlQFiAZUBnQFIAU0GmAFIAZgBWgaCAW8BmgGCAZoBhwEqAS0BIQEqASEBIAGVAUsBTgGVAU4BnQGVAUkBigFLAZUBigGbAU0BWgGbAVoBogFEATsBngFEAZ4BowFxATQBegFxAXoBoAFZAYUBkwFZAZMBoAF+AUUBpAF+AaQB7QFxAaABkwEuARwBEAEuARABIgHuAPEAFAHuABQBHwGMB4oHiAeMB4gHjgfbAI4BpQHbAKUB1gAkAakB2AXXAKcB/wDXAP8AzQCtAaoBqwGtAasBrwGyAa0BrwGyAa8B0gG2AbkBvQF5AXcBvwFSAVABeQG/AVIBeQHDAboBtwHDAbcB1gHFAccBxAHFAcQB2wHEAccB0QHEAdEB3QHTAbAByQHTAckBxgHEAdgB2wHEAd0B2AF/Ae4B4AF/AeABfQHhAc0BEwThARME/QHZAegB5wHZAecB3AHpAdoB3gHpAd4B7AH3AfEB9AH3AfQBFgIrAVEBvgErAb4BhAENAVwGXgYNAV4GbQCjAZ4BAQKjAQECGgIDArIB0gEDAtIBCwIHAVkGWwYHAVsGDAHcAecBCALcAQgCMwIJAsUB2wEJAtsBMgIMAtMBxgEMAsYBCgLqAesBDgLqAQ4CTAIUAhkCEwIUAhMCHAJVAb8BdwFVAXcBWAHtAaQBGwLtARsCWQKQB4wHjgeQB44HkgceAn0GIAIeAiACFgIiAuYB6gEiAuoBTAImAvIB8AEmAvABQwIvAmkBaAEvAmgBMQI9AioCNwI9AjcCPwIfARQBYQEfAWEBewE4AlACQAJVAuAB7gFVAu4BWgJWAi8CMQJWAjECWAJXAXYBJwFXAScBgQEOBhAGEQYOBhEGEgZBAgMCCwJBAgsCbgJkAaYBjQFkAY0BagFgAmMCXwJgAl8CcQJnAmMCYAJnAmACxgIzAggCaAIzAmgCfwIJAjICawIJAmsCdwJfAf8ApwFfAacBZQFvAgwCCgJvAgoCeQLzAScCcwJ1AnYCdAJ1AnQCegIyAn4CawKCAgcC5gGCAuYBIgKDAoYCiAKDAogCiQIlAkECbgJNAg0CjgJNAo4CoQKRAo0CjwKRAo8CqAKAAmkClQKAApUCnQKzAZYCmAKzAZgCrgGaAncCawKaAmsCnAJrAn4CnAKEAb4BUwGEAVMBkgEaAgECngIaAp4C9ALDAnQCdgLDAnYCyQJ9AqUCngR9Ap4EXAKRAqACjQKqAl0CYgKqAmICvwKsAnoCdAKsAnQCwAIlAm4CrwIlAq8CcgKxAlYCWAKxAlgCswJxAl8CuQJxArkCCANhAmQCugJhAroCvgIhAk4CogIhAqICwgKRAsECoALBApECqALBAqgCyAKUB5AHkgeUB5IHlgfHAqcCrgLHAq4C0wJqAgcCggJqAoIC4gLAAnQCwwLAAsMC5QKsAsACygKkAssCDAWkAgwFvQK1As0ClgS1ApYEkwKsAsoCzwLSAqwCzwLSAs8C8QLVArcCXgLVAl4CqwLDAskC1gLDAtYC+ALfAtgC3QLfAt0CPAOaB50HnweaB58HoQeUAmoC4gKUAuICRAPKAsAC5QLKAuUCBQOFAuYC6AKFAugChwKaApwC6gKaAuoCPgPuAu8C4AX2As8CygL2AsoCBQP7AtEC9wL7AvcC/gIAA/oC/QIAA/0CKgPSAvECAgOBAiECwgKBAsICSQPlAsMC+ALlAvgCKAMJA3ICrwIJA68CWgOxArMCDAOxAgwDDQPBAsgCDwPBAg8DSAPnAhADEQPnAhED6QJ7AWEBnAF7AZwBoQETA1UCWgITA1oCnAMZAxwDFgMZAxYDUgMdA5kBbQEdA20BdAEIA7kCZwIIA2cCxgIgA2oGiAEgA4gBhgEOA8cC0wIOA9MCQQPSAgIDIwMnA/MC/wInA/8CKwNnAfwBLgNnAS4DMAIFA+UCKAMFAygDWAMvAwID8QIvA/ECJgM3AzMDAwM3AwMDMQOYAU0GTgaYAU4GOgNAA9ICIwNAAyMDcQNFA/YCBQNFAwUDWAM4AywD+gE4A/oBlwH+AvcCRgP+AkYDXgNOA0oDMgNOAzIDNgNSA1UDGQO+AroCVgO+AlYD2ANgAyEDhwFgA4cBmgFjA6oCvwJjA78C2QNmAyoD/QJmA/0CXQO7AV8DmQG7AZkBHQMwAi4DagMwAmoDVwJtAyQDSwNtA0sDTwOPA24DHQKPAx0CEQJ1A2kDLQN1Ay0DOQN4AycDKwN4AysDZwNxAyMDawNxA2sDkANOBlAGdgNOBnYDOgN/A3sDcgN/A3IDkgMNAwwDggMNA4IDgwNNAzUDMANNAzADbAMvAyYD3AIvA9wCawNTA1EDhgNTA4YD7gOHA3oDfgOHA34DrQNAA3EDigNFA1gDOwNFAzsDdwMmA3cD3AKYA0IDIgOYAyIDYQMaAwoDngMdA3QBkAEdA5ABoQNAA4oDpAOoA9UCqwKoA6sCZAOhB58HowehB6MHpQe5AZoDYgO5AWIDvQGqA+sCQwOqA0MD4wLcAncDOwOLA4gDrgOLA64D3APkAoECSQPkAkkDqwOmA7QDsQOmA7EDugMOA0EDtwMOA7cDwQNAA6QDuANrA9wCuwNrA7sDkAO9A78DaAO9A2gDdANIAw8DwgNIA8IDxAM+A+oCxAM+A8QDwgPIA8kDxQPIA8UD0wPOA7MDpQPOA6UD0QPPA6QDigPPA4oD2gPqAqkDxAPEA6kDSAPuAtIDEQPuAhEDEANXAmoDwANXAsADsgIfA8wBtQEfA7UBvAGDA4ID1gODA9YD1wOvA7IDzQOvA80D/AO1A0ADuAO1A7gD/gPaA5ADuwPaA7sD7wNQBlMGvgNQBr4DdgPjA90D4APjA+AD5gOdAwkDWgOdA1oDtQPTA8UD8QPTA/EDLAT2A7kDsAP2A7AD/QP3A5YDQgP3A0IDlwMEAgEElgIEApYCswHaA+8DzwP7A8wD0AP7A9AD9QP+A50DtQP+A7gD9AP+A/QDhAPDAfkDmQPDAZkDugH0A88D7wP0A+8D7APxAfcBhALxAYQCAgQGBA0EDgSEA/QD7AMRBP8B/QERBP0BEwS9AxYEGQS9AxkEvwOxAawB0AGxAdAByAELA7ICwAMLA8ADGgQbBAQElQMbBJUD+ANTBlUGFwRTBhcEvgMeAxIEFAT1AR8EhgL1AYYCgwIiBBwE+gMiBPoDwgEUBhYGGQYUBhkGHAaBAwsDGgSBAxoEKgSXAgIEhAKEAooCmQKEApkClwIdBC4E5gIdBOYChQIVBDIEJwQVBCcEGARVBlcGNARVBjQEFwQbBDUEJQQbBCUEBAQ7BDkE0wM7BNMDLARABEMEPwRABD8EdgRFBCMCDwJFBA8CSAQiBD4COAQiBDgEHAQxBEsEEAMxBBAD5wJCAu8BAQRCAgEEBAJ1AnoCqwF1AqsBqgH2AR8CTgT2AU4EIAQYAlEEVAQYAlQEEgJPBFcEWgRPBFoEUgTYA1YDWwTYA1sEigTUA4ADKQTUAykEXwQuAjQEVwYuAlcGWAZhBGMD2QNhBNkDiwRgAmAGYgZgAmIGxgJjBGQEZgRjBGYEaAQzBCwCXQQzBF0EKAQ2BGwESgQ2BEoEJgR1BEQEcAR1BHAEmwSlB6MHpwelB6cHqQfeAY4CDQLeAQ0C7AFqBE4EHwJqBB8CfwbdAdEBjwLdAY8CjQI9Aj8CbgQ9Am4ENwR5BKgDZAN5BGQDYgTQAawBewLQAXsCkAJ6BC8EHgR6BB4ETQTvAu4CEAPvAhADSwRtBIEEawRtBGsESgSEBEwEMASEBDAEewSHBIkEZgSHBGYEZARAAlACggRAAoIEbwR/BHoETQR/BE0EaQSFBFECOQKFBDkCfQShA5AB2wWhA9sF3QVPAoQEewRPAnsEgASPBJEEZASPBGQEYwSTBJUEiQSTBIkEhwSEBJgE8AKEBPACTARcAp4ESQJcAkkCRQKgBG0CUgKgBFICogTSBaYEuATSBbgEtQRlBPkC1wJlBNcCZwSnBOEClQSnBJUEkwRkBJEEqgRkBKoEhgRWBFAE8QRWBPEE6gSsBD8EQwSsBEMEcwRRBBgC+gRRBPoE8wQXAhUCFwMXAhcD+wRZBFUE6QRZBOkE7QSQAnsCrQKQAq0CqQKbArACcAKbAnACeAJTBFgE7ARTBOwE7gSOAxICVASOA1QE8AStBNsC4QKtBOECpwRhBmQG9wRhBvcExQKNBLEERwSNBEcE2gX5AmUEiAT5AogEKQOGBKoEswSGBLMEkgRjBmUG/ARjBvwE9ARGBLAEtARGBLQEtwRmBh4CcANmBnAD/gS7BJAEjgS7BI4EvQTaAq8EvgTaAr4EwASfBIMEfATCBMUEugTCBLoEvATzAXMCCgPzAQoDGgMpA4gElAQpA5QEWQOSBLMExwSSBMcEpwTNArUCvQLNAr0CyQTABL4EzATABMwEzgTRBKkEkATRBJAEuwSKBFsE0gSKBNIE5gTyAtAC/ALyAvwCAQNZA5QE4AJZA+ACPQPPBLoExQTPBMUE1ATXBGEEiwTXBIsE5wTIBNoErgTIBK4EqASpB6cHqwepB6sHrQdZAhsC9QJZAvUCmwPdBHkEYgTdBGIE2ASyBKkE0QSyBNEE3gTrAp0ClQLrApUCQwM/A1sDsAI/A7ACmwLeAtkCvwTeAr8EvAOvBNsE4QSvBOEEvgTOBMwEGQPOBBkDVQMlAwQDNAMlAzQDTANxAggD5ARxAuQE5QTGBLIE3gTGBN4EyAO8A78EzQS8A80E8AO+BOEE+AS+BPgEzASMA3MDfAOMA3wDiQOgAwUC/wGgA/8BEQQVAxsDnwMVA58DAARHA3kDZQNHA2UDXAPTBdUF/wTTBf8E7AIEBQYF5QQEBeUE5ATZBMYEyAPZBMgD0wPwA80EVAPwA1QD7QPoBPIE7wToBO8E6wQUA/8DhQMUA4UDUAMIBQkF0QUIBdEFzALzBPoEjgPzBI4D8ARIBA8CBQJIBAUCoAP5BBgDbwP5BG8DjQMOBQsFEAUOBRAFywTOAuIFmQTGA8oD4gPGA+ID3wPLAxIF6APLA+gD4QORA9sDrAORA6wDfQO2A1sDPwO2Az8DwwMXBQcDxAIXBcQC9gQZA+sD/gQZA/4EcAPfBNkE0wPfBNMDOQTMBPgEGAXMBBgFGQPqAxUF9QTqA/UE/QTyA8cD3gPyA94D5QMTBfMD5AMTBeQD5wMFBQMFGgUFBRoFGwUdBcMEwQQdBcEEIQXhBCQFQgThBEIE+AQjBeAEOgQjBToEcQQZAyUFKgUZAyoF6wPjBAYDFgXjBBYFDATmBNIEKwXmBCsFQAUpBScFEAQpBRAECgTpAygFCQTpAwkEFAWtB6sHrwetB68HsQcvBdcE5wQvBecEQQUuBd0E2AQuBdgEMAVBBCIFcARBBHAERAQyBdUExAQyBcQEHwUZAxgFNQUZAzUFJQUmBTYFBwQmBQcEDwQFBAEF4gQFBOIECwTIAzkFEQXIAxEFyQP4BEIEOwX4BDsFGAU9BdAE1gQ9BdYENAXeBNEEPwXeBD8FQgU3BUYFSQU3BUkFCAQZBQIFBgQZBQYERwUYBTsFRAUYBUQFNQWiBFICNAKiBDQCpQTIA94EQgXIA0IFOQUbBRoFSwUbBUsFTAVABSsFTQVABU0FWAU5BSwE8QM5BfEDEQVCBHcETwVCBE8FOwWxB68HswexB7MHtQdRBS4FMAVRBTAFUwVSBS8FQQVSBUEFWQVFBVUFVwVFBVcFSAVaBQcFjAKMAm0CoASMAqAEWgVUBUQFOwVUBTsFTwVKBRkFRwVKBUcFVgVxBDoEPgRxBD4EnQSlAn0CkwKlApMClgRcBV0FHAVcBRwFIAVYBU0FXwVYBV8FaQW1B7MHtwe1B7cHuQdiBVEFUwViBVMFZgUxBR4FXgUxBV4FYwVlBVIFWQVlBVkFagU8BTMFZAU8BWQFZwVbBWsFCQVbBQkFCAVDBT4FaAVDBWgFbAU6BUMFbAU6BWwFbgUrBDgFbQUrBG0FbwU8BC0EcAU8BHAFcQWcBD0EcgWcBHIFdAV0BJoEcwV0BHMFdgWrBHIEdQWrBHUFdwXLAqQCjALLAowCBwWhBKMEpASkBGsFWwWkBFsFoQS2BCMCRQR7BWgAYwDbBvwG/QbbBv0G4gZ8BWUAowB8BaMAgwUXABoACgAXAAoAjwVTAB8ApAZTAKQGrAYhADoApwYhAKcGpQaKBT4AQwCKBUMAkAU5AEYAqAY5AKgGpgYEAGcAeQUEAHkFBwCNBakGrwaNBa8GogWQBQwAEQCQBREAigUFAaMGqwYFAasGVwCOBUEAEgCOBRIAFgCKBZQFoQCKBaEAPgArAAIACQArAAkAlQWXBSkAPACXBTwAMQArAJ8FMAArADAALQCjBSsAlQUJAAgAqAUJAKgFqQWrBa8FegWrBXoFggUGAHgFrQUGAK0FpgWzBYYFiQWzBYkFtgUdALAGrgYdAK4GSQAkALMGsQYkALEGHgBWAKoGsgZWALIGIgCABaEAlAWABZQFtwWbBUsAugWbBboFwAWVBQkAqQWVBakFuQWjBb0FnwWjBZ8FKwCLBaAFtQWLBbUFiAWxBZIFmQWxBZkFhQW7BU0AUQC7BVEAwwW4BcQFqgW4BaoFgQWTBX8FmACTBZgAmgXCBVAAlwDCBZcApAWeBcYFlgWeBZYFLwCjBZUFuQWjBbkFwQV/Bb4FpQV/BaUFmADIBcoFsAXIBbAFrAXMBc0FqQXMBakFqAWnBa4FyQWnBckFywW5BakFzQW5Bc0FvwWdBfUGxQV+Bc8F9gZ+BfYGCwfEBdAFxwXEBccFqgWlBDQCIwKlBCMCtgS9AgwFyQTMAtEFCgXMAgoFDQWkBKMEpgSkBKYE0gUUBh8GIgYUBiIGFgYeAxQEygGiAxIEHgOXBIMEpgKmAoMEnwTfBeEF1QXfBdUF0wXZBdcFqAHZBagBjATdBdsF1wXdBdcF2QXwApgE4QXwAuEF3wXKBNYF4gXKBOIFzgLKBA8FAAXKBAAF1gXeBUkEowPaBUcESQTaBUkE3gXPAeMBtAHPAbQBywHXAbgB5QFIAksCfgRIAn4EOgI2AikCRgLKARQEzgGfBHwESgK8ArQCCga8AgoGDAa0ApICBga0AgYGCgaSAnwCAgaSAgIGBgZ8AlsC/gV8Av4FAgZbAkQC+wVbAvsF/gUrAvUF/AUrAvwFRwITBiMGJgYTBiYGHgYbBikGIwYbBiMGEwbVAeQB6QXVAekF8AXiAf4B5QXiAeUF5wX+AQAC4wX+AeMF5QUAAgYC6gUAAuoF4wUGAhAC7AUGAuwF6gUQAiQC8QUQAvEF7AUkAjUC9gUkAvYF8QU1AlMC+AU1AvgF9gVTAmwCAAZTAgAG+AVsAosCBAZsAgQGAAaLAqMCCAaLAggGBAajArwCDAajAgwGCAYqBisGLQYqBi0GLwYrBjAGMgYrBjIGLQYwBhEGEAYwBhAGMgY0BjUGNwY0BjcGOQYjBjoGPAYjBjwGJgY+BjoGIwY+BiMGKQZABisGKgZABioGQgZEBjAGKwZEBisGQAZGBhEGMAZGBjAGRAYSBhEGRgYSBkYGSAY3BjUGSgY3BkoGTAYOBhIGNQYOBjUGNAZKBjUGEgZKBhIGSAZCBioGOgZCBjoGPgY8BjoGKgY8BioGLwYLBgkGDwYLBg8GDQYhBMEBGAYhBBgGFQbAAdQBGgbAARoGFwYoAjsCIAYoAiAGHQY8AiEEFQY8AhUGIQbzBSgCHQbzBR0GJAbUAe8FKAbUASgGGgYBBv0FLgYBBi4GLAYFBgEGLAYFBiwGMQYJBgUGMQYJBjEGDwb/BQMGOAb/BTgGNgYDBgcGMwYDBjMGOAb6BfQFJQb6BSUGOwbuBegFPQbuBT0GJwbmBeQFPwbmBT8GQQbkBesFQwbkBUMGPwbrBe0FRQbrBUUGQwbtBfIFRwbtBUcGRQb3BfkFSwb3BUsGSQb5Bf8FNgb5BTYGSwYHBgsGDQYHBg0GMwbyBfcFSQbyBUkGRwboBeYFQQboBUEGPQb9BfoFOwb9BTsGLgY/AV0BAgA/AQIAugAWAvQBHAMWAhwDGQMuAlgGHgIuAh4CZgZbBlkGlgFbBpYB+QFeBlwG+wFeBvsBZgFfBl0GaAFfBmgBaQFiBmAG1wNiBtcD1gPVA2AEZAbVA2QGYQZeBC0CZQZeBGUGYwbRAEgBWgbRAFoGCAFpBmsGbgZpBm4GbQZtBm4GcwZtBnMGcQaDBoEGhQaDBoUGhgaGBoUGiAaGBogGigZ2BngGewZ2BnsGegZ6BnsGgAZ6BoAGfgZuBmsGIgNuBiIDQgNuBkIDlgNuBpYDcwaBBowGjwaBBo8GhQaIBoUGjwaIBo8GkgZ7BngGJgR7BiYESgSABnsGSgSABkoEawROBk0GaAZOBmgGbAZvBlAGTgZvBk4GbAaGBpQGlgaGBpYGgwaGBooGmgaGBpoGlAZ1BnkGVwZ1BlcGVQZYBlcGeQZYBnkGfQZnBogBagZ8Bn8GHwIeAlgGfQYWAiAC9wGJAV0BWAFIAWgGTQZwBnIGggZwBoIGhAZ3BnQGiQZ3BokGhwZyBpQDjQZyBo0GggaTAwMEjgaTA44GiwYDBCQEkQYDBJEGjgYjBHcGhwYjBIcGkAZSBk8GlQZSBpUGkwZRBnAGhAZRBoQGlwZ0BlQGmAZ0BpgGiQZWBlIGkwZWBpMGmQZMAJwFtAZMALQGnAahBp0GTwChBk8A3wCtBp8GlgCtBpYAVACeBqAG3gCeBt4AlQDGBgUHBwfGBgcHzAasBqQGhAWsBoQFmAWlBqcGiQWlBokFhgWmBqgGjAWmBowFhwWvBqkGRwCvBkcASgCrBqMGfwWrBn8FkwWuBrAGtAWuBrQFoQWxBrMGswWxBrMFtgWyBqoGkQWyBpEFsgWcBrQGmwacBpsGTgCjBgEHAwejBgMHugaiBn4FvQaiBr0GtwYKBwsHfwUKB38FwAZ/BaMGugZ/BboGwAa1BrsG6wa1BusG5QYIBwkHvwYIB78G6ga+BrkG6Aa+BugG6QYFAfcG+AYFAfgGzQZ9BaIG0wZ9BdMG0Ab/BgEHowb/BqMG1gajBgUBzQajBs0G1gbOBvkG+gbOBvoG7QbRBtUG8gbRBvIG8wbYBs8G7gbYBu4G8AbpBugGxQbpBsUGygYGBwgH6gYGB+oGywblBusGxwblBscGwQbwBu4G2gbwBtoG4wbzBvIG4QbzBuEG3AbtBvoG+wbtBvsG2Qa8BfUGnQXFBfUGzgX4BvcGfQX4Bn0F0Ab6BvkG0gb6BtIG9Ab7BvoG9Ab7BvQG3Qb9BvwG3gb9Bt4G3waiBgEH/waiBv8G0wYDBwEHogYDB6IGtwYHBwUHwwYHB8MGyQbsBggHBgfsBgYHyAa8BgkHCAe8BggH7AZ+BQsHCgd+BQoHvQYLB/YGvgULB74FfwX+BhUHKgf+BioH5AbgBigHFQfgBhUH/gbxBhEHKAfxBigH4AbUBi0HEQfUBhEH8QbUBgAHFwfUBhcHLQcmBxcHAAcmBwAH1wYPByYH1wYPB9cG7wbkBioHDwfkBg8H7wa4BgIHGQe4BhkHIgcgBxkHAgcgBwIHtgYNByAHtgYNB7YG5gbCBiQHDQfCBg0H5gYEBxsHJAcEByQHwgbEBh0HGwfEBhsHBAfnBhMHHQfnBh0HxAa4BiIHEwe4BhMH5wYUBycHIwcUByMHGgcnBxAHDAcnBwwHIwcQBywHHwcQBx8HDAcrBxYHGAcrBxgHHgcWByUHIQcWByEHGAclBw4HEgclBxIHIQcOBykHHAcOBxwHEgcpBxQHGgcpBxoHHAcNADYALgcNAC4HMQcTAEIAOAcTADgHNQdEABAAMwdEADMHOQcVABMANQcVADUHOwc2AIwAPAc2ADwHLge+ABUAOwe+ADsHPweMAO8AQAeMAEAHPAc8Ab4APwc8AT8HRQfvAHwBQgfvAEIHQAefATwBRQefAUUHRwd8Ad8BSAd8AUgHQgcCAp8BRwcCAkcHSwffAVQCTAffAUwHSAefAgICSwefAksHTwdUAhIDUAdUAlAHTAdmArgCWQdmAlkHVQe2AtQCWge2AloHVge7AmUCUwe7AlMHXQfUAqcDXgfUAl4HWgdXA7sCXQdXA10HYQenA3gEYgenA2IHXgdcBFcDYQdcBGEHZQd4BNwEZgd4BGYHYgfTBFwEZQfTBGUHaQfcBC0FagfcBGoHZgcsBdMEaQcsBWkHbQctBVAFbgctBW4HagdOBSwFbQdOBW0HcQdQBWEFcgdQBXIHbgdgBU4FcQdgBXEHdQcyBy8HdwcyB3cHegc0BzcHfwc0B38HfAc2BzAHeQc2B3kHfgc6BzQHfAc6B3wHgQcvBz0HgwcvB4MHdwc+BzoHgQc+B4EHhQc9B0EHhwc9B4cHgwdEBz4HhQdEB4UHiwdBB0MHiQdBB4kHhwdGB0QHiwdGB4sHjQdDB0kHjwdDB48HiQdKB0YHjQdKB40HkQdJB00HkwdJB5MHjwdOB0oHkQdOB5EHlQdNB1EHlwdNB5cHkwdUB1gHnAdUB5wHmQdXB1sHngdXB54HmwdcB1IHmAdcB5gHoAdbB18HogdbB6IHngdgB1wHoAdgB6AHpAdfB2MHpgdfB6YHogdkB2AHpAdkB6QHqAdjB2cHqgdjB6oHpgdoB2QHqAdoB6gHrAdnB2sHrgdnB64HqgdsB2gHrAdsB6wHsAdrB28HsgdrB7IHrgdwB2wHsAdwB7AHtAdvB3MHtgdvB7YHsgd0B3AHtAd0B7QHuAckASMB+AEkAfgBqQEkAdwFkQEkAdgF3AXuAu0CuQTuArkE0gPuAuAF1AXuAtQF7QI=" - } - ] + "asset":{ + "generator":"Khronos glTF Blender I/O v3.5.30", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 1 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Ship_n_Cockpit", + "translation":[ + 0, + -0.19999998807907104, + 0 + ] + }, + { + "children":[ + 0 + ], + "name":"SM_RaytracerShip", + "rotation":[ + 0.70710688829422, + 0, + 0, + 0.7071066498756409 + ], + "scale":[ + 0.009999999776482582, + 0.009999999776482582, + 0.009999999776482582 + ], + "translation":[ + 0, + -0.20000000298023224, + 0 + ] + } + ], + "materials":[ + { + "doubleSided":true, + "name":"Metal", + "normalTexture":{ + "index":0 + }, + "pbrMetallicRoughness":{ + "baseColorTexture":{ + "index":1 + }, + "metallicRoughnessTexture":{ + "index":2 + } + } + }, + { + "doubleSided":true, + "name":"Screens_and_keycard_buttons", + "pbrMetallicRoughness":{ + "baseColorFactor":[ + 0, + 0.05480000004172325, + 1, + 1 + ], + "metallicFactor":0, + "roughnessFactor":0.5527864098548889 + } + }, + { + "doubleSided":true, + "name":"Ship", + "pbrMetallicRoughness":{ + "baseColorTexture":{ + "index":3 + }, + "metallicRoughnessTexture":{ + "index":4 + } + } + } + ], + "meshes":[ + { + "name":"Mesh", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "TEXCOORD_0":1, + "NORMAL":2 + }, + "indices":3, + "material":0 + }, + { + "attributes":{ + "POSITION":4, + "TEXCOORD_0":5, + "NORMAL":6 + }, + "indices":7, + "material":1 + }, + { + "attributes":{ + "POSITION":8, + "TEXCOORD_0":9, + "NORMAL":10 + }, + "indices":11, + "material":2 + } + ] + } + ], + "textures":[ + { + "sampler":0, + "source":0 + }, + { + "sampler":0, + "source":1 + }, + { + "sampler":0, + "source":2 + }, + { + "sampler":0, + "source":3 + }, + { + "sampler":0, + "source":4 + } + ], + "images":[ + { + "mimeType":"image/png", + "name":"T_Cockpit_Normal", + "uri":"cockpit_textures/T_Cockpit_Normal.png" + }, + { + "mimeType":"image/png", + "name":"T_cockpit_basecolor", + "uri":"cockpit_textures/T_cockpit_basecolor.png" + }, + { + "mimeType":"image/png", + "name":"T_Cockpit_Metallic-T_cockpit_roughness", + "uri":"cockpit_textures/T_Cockpit_Metallic-T_cockpit_roughness.png" + }, + { + "mimeType":"image/png", + "name":"T_ship_basecolor", + "uri":"cockpit_textures/T_ship_basecolor.png" + }, + { + "mimeType":"image/png", + "name":"T_ship_metal-T_ship_roughness", + "uri":"cockpit_textures/T_ship_metal-T_ship_roughness.png" + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":1715, + "max":[ + 142.99900817871094, + 171.31732177734375, + 62.76094436645508 + ], + "min":[ + -142.9990692138672, + -155.11480712890625, + -19.347057342529297 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":1715, + "type":"VEC2" + }, + { + "bufferView":2, + "componentType":5126, + "count":1715, + "type":"VEC3" + }, + { + "bufferView":3, + "componentType":5123, + "count":4083, + "type":"SCALAR" + }, + { + "bufferView":4, + "componentType":5126, + "count":107, + "max":[ + 79.61268615722656, + 103.55489349365234, + 48.27692794799805 + ], + "min":[ + -109.04495239257812, + 48, + -10.140766143798828 + ], + "type":"VEC3" + }, + { + "bufferView":5, + "componentType":5126, + "count":107, + "type":"VEC2" + }, + { + "bufferView":6, + "componentType":5126, + "count":107, + "type":"VEC3" + }, + { + "bufferView":7, + "componentType":5123, + "count":258, + "type":"SCALAR" + }, + { + "bufferView":8, + "componentType":5126, + "count":8608, + "max":[ + 772.93115234375, + 1009.2373657226562, + 201.8388214111328 + ], + "min":[ + -772.93115234375, + -556.0827026367188, + -258.2313232421875 + ], + "type":"VEC3" + }, + { + "bufferView":9, + "componentType":5126, + "count":8608, + "type":"VEC2" + }, + { + "bufferView":10, + "componentType":5126, + "count":8608, + "type":"VEC3" + }, + { + "bufferView":11, + "componentType":5123, + "count":30162, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":20580, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":13720, + "byteOffset":20580, + "target":34962 + }, + { + "buffer":0, + "byteLength":20580, + "byteOffset":34300, + "target":34962 + }, + { + "buffer":0, + "byteLength":8166, + "byteOffset":54880, + "target":34963 + }, + { + "buffer":0, + "byteLength":1284, + "byteOffset":63048, + "target":34962 + }, + { + "buffer":0, + "byteLength":856, + "byteOffset":64332, + "target":34962 + }, + { + "buffer":0, + "byteLength":1284, + "byteOffset":65188, + "target":34962 + }, + { + "buffer":0, + "byteLength":516, + "byteOffset":66472, + "target":34963 + }, + { + "buffer":0, + "byteLength":103296, + "byteOffset":66988, + "target":34962 + }, + { + "buffer":0, + "byteLength":68864, + "byteOffset":170284, + "target":34962 + }, + { + "buffer":0, + "byteLength":103296, + "byteOffset":239148, + "target":34962 + }, + { + "buffer":0, + "byteLength":60324, + "byteOffset":342444, + "target":34963 + } + ], + "samplers":[ + { + "magFilter":9729, + "minFilter":9987 + } + ], + "buffers":[ + { + "byteLength":402768, + "uri":"cockpit_prototype.bin" + } + ] } diff --git a/d1/assets/cockpit_textures/T_Cockpit_Metallic-T_cockpit_roughness.png b/d1/assets/cockpit_textures/T_Cockpit_Metallic-T_cockpit_roughness.png new file mode 100644 index 0000000..14500d2 Binary files /dev/null and b/d1/assets/cockpit_textures/T_Cockpit_Metallic-T_cockpit_roughness.png differ diff --git a/d1/assets/cockpit_textures/T_Cockpit_Metallic.png b/d1/assets/cockpit_textures/T_Cockpit_Metallic.png new file mode 100644 index 0000000..8f13c9e Binary files /dev/null and b/d1/assets/cockpit_textures/T_Cockpit_Metallic.png differ diff --git a/d1/assets/cockpit_textures/T_Cockpit_Normal.png b/d1/assets/cockpit_textures/T_Cockpit_Normal.png new file mode 100644 index 0000000..ebabf54 Binary files /dev/null and b/d1/assets/cockpit_textures/T_Cockpit_Normal.png differ diff --git a/d1/assets/cockpit_textures/T_cockpit_basecolor.png b/d1/assets/cockpit_textures/T_cockpit_basecolor.png new file mode 100644 index 0000000..f56a0d2 Binary files /dev/null and b/d1/assets/cockpit_textures/T_cockpit_basecolor.png differ diff --git a/d1/assets/cockpit_textures/T_cockpit_metal.png b/d1/assets/cockpit_textures/T_cockpit_metal.png new file mode 100644 index 0000000..aebd434 Binary files /dev/null and b/d1/assets/cockpit_textures/T_cockpit_metal.png differ diff --git a/d1/assets/cockpit_textures/T_cockpit_roughness.png b/d1/assets/cockpit_textures/T_cockpit_roughness.png new file mode 100644 index 0000000..711c6e8 Binary files /dev/null and b/d1/assets/cockpit_textures/T_cockpit_roughness.png differ diff --git a/d1/assets/cockpit_textures/T_ship_basecolor.png b/d1/assets/cockpit_textures/T_ship_basecolor.png new file mode 100644 index 0000000..132d4d2 Binary files /dev/null and b/d1/assets/cockpit_textures/T_ship_basecolor.png differ diff --git a/d1/assets/cockpit_textures/T_ship_metal-T_ship_roughness.png b/d1/assets/cockpit_textures/T_ship_metal-T_ship_roughness.png new file mode 100644 index 0000000..f581c9d Binary files /dev/null and b/d1/assets/cockpit_textures/T_ship_metal-T_ship_roughness.png differ diff --git a/d1/assets/cockpit_textures/T_ship_metal.png b/d1/assets/cockpit_textures/T_ship_metal.png new file mode 100644 index 0000000..64cf712 Binary files /dev/null and b/d1/assets/cockpit_textures/T_ship_metal.png differ diff --git a/d1/assets/cockpit_textures/T_ship_roughness.png b/d1/assets/cockpit_textures/T_ship_roughness.png new file mode 100644 index 0000000..71a9ce7 Binary files /dev/null and b/d1/assets/cockpit_textures/T_ship_roughness.png differ diff --git a/d1/assets/render_presets/default.vars b/d1/assets/render_presets/default.vars new file mode 100644 index 0000000..25b5512 --- /dev/null +++ b/d1/assets/render_presets/default.vars @@ -0,0 +1,68 @@ +svgf_stabilize = 1 +tonemap_hue_shift = 0.700000 +black_level = 0.000000 +taa_feedback_min = 0.800000 +reference_mode = 0 +svgf_luma_sigma_spec = 10.000000 +importance_sample_brdf = 1 +svgf_antilag = 1 +diff_stabilize_sharp = 1 +taa_variance_clip_gamma = 1.000000 +taa_catmull_rom = 1 +taa_neighborhood_mode = 3 +sharpen_amount = 2.000000 +svgf_luma_sigma_diff = 48.000000 +diff_stabilize_gamma = 2.000000 +freezeframe = 0 +spec_stabilize_sharp = 1 +debug_render_blend_factor = 1.000000 +taa_per_pixel_jitter = 0 +ris = 2 +vignette_scale = 0.875000 +diff_stabilize_alpha = 0.010000 +normal_sample_linear = 0 +object_motion_vectors = 1 +spec_stabilize_alpha = 0.010000 +spec_stabilize_gamma = 2.000000 +ris_spp = 4 +svgf_max_hist_len_diff = 4 +enable_pathtracing = 1 +mip_bias = -1 +secondary_bounce_bias = 0.000500 +override_materials = 0 +vignette_strength = 0.750000 +ambient_color = 0.050000, 0.070000, 0.100000 +svgf_history_fix_frames = 2 +motion_blur_curve = 0.500000 +svgf_max_hist_len_spec = 4 +bloom_threshold = 0.000000 +svgf_normal_sigma = 8.000000 +svgf_history_fix_scale = 4.000000 +enable_pbr = 1 +svgf_jitter = 1.000000 +bloom_blend_mode = 0 +motion_blur_quality = 1 +direct_specular_threshold = 0.250000 +use_oren_nayar_brdf = 0 +svgf_enabled = 1 +vsync = 1 +override_metallic = 0.000000 +svgf_depth_sigma = 2.000000 +taa_enabled = 1 +tonemap_linear_section = 0.250000 +taa_feedback_max = 0.950000 +taa_tonemapped_blend = 1 +metallic_roughness_sample_linear = 0 +svgf_metallic_sigma = 0.250000 +angle_cutoff = 0.125000 +override_roughness = 0.300000 +ris_indirect = 1 +white_level = 1.000000 +path_space_regularization = 1 +tonemap_whitepoint = 8.000000 +enable_normal_maps = 1 +motion_blur_jitter = 1.000000 +albedo_sample_linear = 0 +gamma = -0.300000 +bloom_amount = 0.025000 +exposure = 0.100000 diff --git a/d1/assets/render_presets/gamer.vars b/d1/assets/render_presets/gamer.vars new file mode 100644 index 0000000..6d8003b --- /dev/null +++ b/d1/assets/render_presets/gamer.vars @@ -0,0 +1,61 @@ +svgf_stabilize = 1 +black_level = 0.000000 +taa_feedback_min = 0.800000 +reference_mode = 0 +svgf_luma_sigma_spec = 10.000000 +importance_sample_brdf = 1 +svgf_antilag = 1 +diff_stabilize_sharp = 1 +taa_variance_clip_gamma = 1.000000 +taa_catmull_rom = 1 +taa_neighborhood_mode = 3 +sharpen_amount = 1.000000 +svgf_luma_sigma_diff = 48.000000 +diff_stabilize_gamma = 2.000000 +freezeframe = 0 +spec_stabilize_sharp = 1 +debug_render_blend_factor = 1.000000 +taa_per_pixel_jitter = 0 +ris = 2 +vignette_scale = 0.800000 +diff_stabilize_alpha = 0.010000 +normal_sample_linear = 0 +object_motion_vectors = 1 +spec_stabilize_alpha = 0.010000 +spec_stabilize_gamma = 2.000000 +ris_spp = 4 +svgf_max_hist_len_diff = 4 +enable_pathtracing = 1 +override_materials = 0 +vignette_strength = 0.600000 +ambient_color = 0.050000, 0.070000, 0.100000 +svgf_history_fix_frames = 2 +motion_blur_curve = 0.800000 +svgf_max_hist_len_spec = 4 +bloom_threshold = 0.100000 +bloom_mode = -858993460 +svgf_normal_sigma = 8.000000 +svgf_history_fix_scale = 4.000000 +enable_pbr = 1 +svgf_jitter = 1.000000 +bloom_blend_mode = 0 +motion_blur_quality = 1 +use_oren_nayar_brdf = 1 +svgf_enabled = 1 +vsync = 1 +override_metallic = 0.000000 +svgf_depth_sigma = 2.000000 +taa_enabled = 1 +taa_feedback_max = 0.950000 +taa_tonemapped_blend = 1 +metallic_roughness_sample_linear = 0 +svgf_metallic_sigma = 0.250000 +override_roughness = 0.300000 +ris_indirect = 1 +white_level = 1.000000 +path_space_regularization = 1 +enable_normal_maps = 1 +motion_blur_jitter = 1.000000 +albedo_sample_linear = 0 +gamma = -0.300000 +bloom_amount = 0.150000 diff --git a/d1/assets/splash-logo/Logo.png b/d1/assets/splash-logo/Logo.png new file mode 100644 index 0000000..1ce8421 Binary files /dev/null and b/d1/assets/splash-logo/Logo.png differ diff --git a/d1/assets/splash-logo/LogoRaytraced.png b/d1/assets/splash-logo/LogoRaytraced.png new file mode 100644 index 0000000..3ded47f Binary files /dev/null and b/d1/assets/splash-logo/LogoRaytraced.png differ diff --git a/d1/assets/splash-logo/Logo_With_Line.png b/d1/assets/splash-logo/Logo_With_Line.png new file mode 100644 index 0000000..a01bd0e Binary files /dev/null and b/d1/assets/splash-logo/Logo_With_Line.png differ diff --git a/d1/assets/splash-logo/Logo_With_Line_And_Dot.png b/d1/assets/splash-logo/Logo_With_Line_And_Dot.png new file mode 100644 index 0000000..4dbe6b0 Binary files /dev/null and b/d1/assets/splash-logo/Logo_With_Line_And_Dot.png differ diff --git a/d1/assets/splash-logo/MenuRaytraced.png b/d1/assets/splash-logo/MenuRaytraced.png new file mode 100644 index 0000000..9637552 Binary files /dev/null and b/d1/assets/splash-logo/MenuRaytraced.png differ diff --git a/d1/assets/textures/arw01_0.material b/d1/assets/textures/arw01_0.material index c1f878f..838b3be 100644 --- a/d1/assets/textures/arw01_0.material +++ b/d1/assets/textures/arw01_0.material @@ -1,2 +1,4 @@ -blackbody = 1 emissive_strength = 3.500000 +albedo_texture = arw01_basecolor.png +metallic_texture = arw01_metallic.png +roughness_texture = arw01_roughness.png diff --git a/d1/assets/textures/arw01_0_emissive.png b/d1/assets/textures/arw01_0_emissive.png new file mode 100644 index 0000000..bea9951 Binary files /dev/null and b/d1/assets/textures/arw01_0_emissive.png differ diff --git a/d1/assets/textures/arw01_1.material b/d1/assets/textures/arw01_1.material index c1f878f..838b3be 100644 --- a/d1/assets/textures/arw01_1.material +++ b/d1/assets/textures/arw01_1.material @@ -1,2 +1,4 @@ -blackbody = 1 emissive_strength = 3.500000 +albedo_texture = arw01_basecolor.png +metallic_texture = arw01_metallic.png +roughness_texture = arw01_roughness.png diff --git a/d1/assets/textures/arw01_1_emissive.png b/d1/assets/textures/arw01_1_emissive.png new file mode 100644 index 0000000..7479997 Binary files /dev/null and b/d1/assets/textures/arw01_1_emissive.png differ diff --git a/d1/assets/textures/arw01_2.material b/d1/assets/textures/arw01_2.material index c1f878f..838b3be 100644 --- a/d1/assets/textures/arw01_2.material +++ b/d1/assets/textures/arw01_2.material @@ -1,2 +1,4 @@ -blackbody = 1 emissive_strength = 3.500000 +albedo_texture = arw01_basecolor.png +metallic_texture = arw01_metallic.png +roughness_texture = arw01_roughness.png diff --git a/d1/assets/textures/arw01_2_emissive.png b/d1/assets/textures/arw01_2_emissive.png new file mode 100644 index 0000000..1c07608 Binary files /dev/null and b/d1/assets/textures/arw01_2_emissive.png differ diff --git a/d1/assets/textures/arw01_3.material b/d1/assets/textures/arw01_3.material index c1f878f..838b3be 100644 --- a/d1/assets/textures/arw01_3.material +++ b/d1/assets/textures/arw01_3.material @@ -1,2 +1,4 @@ -blackbody = 1 emissive_strength = 3.500000 +albedo_texture = arw01_basecolor.png +metallic_texture = arw01_metallic.png +roughness_texture = arw01_roughness.png diff --git a/d1/assets/textures/arw01_3_emissive.png b/d1/assets/textures/arw01_3_emissive.png new file mode 100644 index 0000000..4a90825 Binary files /dev/null and b/d1/assets/textures/arw01_3_emissive.png differ diff --git a/d1/assets/textures/arw01_4.material b/d1/assets/textures/arw01_4.material index c1f878f..838b3be 100644 --- a/d1/assets/textures/arw01_4.material +++ b/d1/assets/textures/arw01_4.material @@ -1,2 +1,4 @@ -blackbody = 1 emissive_strength = 3.500000 +albedo_texture = arw01_basecolor.png +metallic_texture = arw01_metallic.png +roughness_texture = arw01_roughness.png diff --git a/d1/assets/textures/arw01_4_emissive.png b/d1/assets/textures/arw01_4_emissive.png new file mode 100644 index 0000000..5aac041 Binary files /dev/null and b/d1/assets/textures/arw01_4_emissive.png differ diff --git a/d1/assets/textures/arw01_5.material b/d1/assets/textures/arw01_5.material index c1f878f..838b3be 100644 --- a/d1/assets/textures/arw01_5.material +++ b/d1/assets/textures/arw01_5.material @@ -1,2 +1,4 @@ -blackbody = 1 emissive_strength = 3.500000 +albedo_texture = arw01_basecolor.png +metallic_texture = arw01_metallic.png +roughness_texture = arw01_roughness.png diff --git a/d1/assets/textures/arw01_5_emissive.png b/d1/assets/textures/arw01_5_emissive.png new file mode 100644 index 0000000..e8277c3 Binary files /dev/null and b/d1/assets/textures/arw01_5_emissive.png differ diff --git a/d1/assets/textures/arw01_basecolor.png b/d1/assets/textures/arw01_basecolor.png new file mode 100644 index 0000000..9aadadb Binary files /dev/null and b/d1/assets/textures/arw01_basecolor.png differ diff --git a/d1/assets/textures/arw01_metallic.png b/d1/assets/textures/arw01_metallic.png new file mode 100644 index 0000000..e2c0336 Binary files /dev/null and b/d1/assets/textures/arw01_metallic.png differ diff --git a/d1/assets/textures/arw01_roughness.png b/d1/assets/textures/arw01_roughness.png new file mode 100644 index 0000000..a0a8217 Binary files /dev/null and b/d1/assets/textures/arw01_roughness.png differ diff --git a/d1/assets/textures/blob01.material b/d1/assets/textures/blob01.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/blob01.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/blob01_0.material b/d1/assets/textures/blob01_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob01_0.material +++ b/d1/assets/textures/blob01_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob01_1.material b/d1/assets/textures/blob01_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob01_1.material +++ b/d1/assets/textures/blob01_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob01_2.material b/d1/assets/textures/blob01_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob01_2.material +++ b/d1/assets/textures/blob01_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob01_3.material b/d1/assets/textures/blob01_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob01_3.material +++ b/d1/assets/textures/blob01_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob01_4.material b/d1/assets/textures/blob01_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob01_4.material +++ b/d1/assets/textures/blob01_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob02_0.material b/d1/assets/textures/blob02_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob02_0.material +++ b/d1/assets/textures/blob02_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob02_1.material b/d1/assets/textures/blob02_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob02_1.material +++ b/d1/assets/textures/blob02_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob02_2.material b/d1/assets/textures/blob02_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob02_2.material +++ b/d1/assets/textures/blob02_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob02_3.material b/d1/assets/textures/blob02_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob02_3.material +++ b/d1/assets/textures/blob02_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob02_4.material b/d1/assets/textures/blob02_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob02_4.material +++ b/d1/assets/textures/blob02_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob03_0.material b/d1/assets/textures/blob03_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob03_0.material +++ b/d1/assets/textures/blob03_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob03_1.material b/d1/assets/textures/blob03_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob03_1.material +++ b/d1/assets/textures/blob03_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob03_2.material b/d1/assets/textures/blob03_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob03_2.material +++ b/d1/assets/textures/blob03_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob03_3.material b/d1/assets/textures/blob03_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob03_3.material +++ b/d1/assets/textures/blob03_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blob03_4.material b/d1/assets/textures/blob03_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/blob03_4.material +++ b/d1/assets/textures/blob03_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/blown01_basecolor.png b/d1/assets/textures/blown01_basecolor.png new file mode 100644 index 0000000..d61c5bc Binary files /dev/null and b/d1/assets/textures/blown01_basecolor.png differ diff --git a/d1/assets/textures/blown01_metallic.png b/d1/assets/textures/blown01_metallic.png new file mode 100644 index 0000000..5f7fd00 Binary files /dev/null and b/d1/assets/textures/blown01_metallic.png differ diff --git a/d1/assets/textures/blown01_roughness.png b/d1/assets/textures/blown01_roughness.png new file mode 100644 index 0000000..62414bb Binary files /dev/null and b/d1/assets/textures/blown01_roughness.png differ diff --git a/d1/assets/textures/blown02_basecolor.png b/d1/assets/textures/blown02_basecolor.png new file mode 100644 index 0000000..43ef95d Binary files /dev/null and b/d1/assets/textures/blown02_basecolor.png differ diff --git a/d1/assets/textures/blown02_metallic.png b/d1/assets/textures/blown02_metallic.png new file mode 100644 index 0000000..0e1f335 Binary files /dev/null and b/d1/assets/textures/blown02_metallic.png differ diff --git a/d1/assets/textures/blown02_roughness.png b/d1/assets/textures/blown02_roughness.png new file mode 100644 index 0000000..17372b9 Binary files /dev/null and b/d1/assets/textures/blown02_roughness.png differ diff --git a/d1/assets/textures/blown03_basecolor.png b/d1/assets/textures/blown03_basecolor.png new file mode 100644 index 0000000..4d413ef Binary files /dev/null and b/d1/assets/textures/blown03_basecolor.png differ diff --git a/d1/assets/textures/blown03_metallic.png b/d1/assets/textures/blown03_metallic.png new file mode 100644 index 0000000..8c327e0 Binary files /dev/null and b/d1/assets/textures/blown03_metallic.png differ diff --git a/d1/assets/textures/blown03_roughness.png b/d1/assets/textures/blown03_roughness.png new file mode 100644 index 0000000..a775894 Binary files /dev/null and b/d1/assets/textures/blown03_roughness.png differ diff --git a/d1/assets/textures/blown04_basecolor.png b/d1/assets/textures/blown04_basecolor.png new file mode 100644 index 0000000..41e7a75 Binary files /dev/null and b/d1/assets/textures/blown04_basecolor.png differ diff --git a/d1/assets/textures/blown04_metallic.png b/d1/assets/textures/blown04_metallic.png new file mode 100644 index 0000000..53b83b7 Binary files /dev/null and b/d1/assets/textures/blown04_metallic.png differ diff --git a/d1/assets/textures/blown04_roughness.png b/d1/assets/textures/blown04_roughness.png new file mode 100644 index 0000000..9b1d2b1 Binary files /dev/null and b/d1/assets/textures/blown04_roughness.png differ diff --git a/d1/assets/textures/blown05_metallic.png b/d1/assets/textures/blown05_metallic.png new file mode 100644 index 0000000..3e87000 Binary files /dev/null and b/d1/assets/textures/blown05_metallic.png differ diff --git a/d1/assets/textures/blown05_roughness.png b/d1/assets/textures/blown05_roughness.png new file mode 100644 index 0000000..a94e4a0 Binary files /dev/null and b/d1/assets/textures/blown05_roughness.png differ diff --git a/d1/assets/textures/blown06_basecolor.png b/d1/assets/textures/blown06_basecolor.png new file mode 100644 index 0000000..db713b6 Binary files /dev/null and b/d1/assets/textures/blown06_basecolor.png differ diff --git a/d1/assets/textures/blown06_metallic.png b/d1/assets/textures/blown06_metallic.png new file mode 100644 index 0000000..f153e82 Binary files /dev/null and b/d1/assets/textures/blown06_metallic.png differ diff --git a/d1/assets/textures/blown06_roughness.png b/d1/assets/textures/blown06_roughness.png new file mode 100644 index 0000000..5effba1 Binary files /dev/null and b/d1/assets/textures/blown06_roughness.png differ diff --git a/d1/assets/textures/blown07_basecolor.png b/d1/assets/textures/blown07_basecolor.png new file mode 100644 index 0000000..520afe5 Binary files /dev/null and b/d1/assets/textures/blown07_basecolor.png differ diff --git a/d1/assets/textures/blown07_metallic.png b/d1/assets/textures/blown07_metallic.png new file mode 100644 index 0000000..23758cc Binary files /dev/null and b/d1/assets/textures/blown07_metallic.png differ diff --git a/d1/assets/textures/blown07_roughness.png b/d1/assets/textures/blown07_roughness.png new file mode 100644 index 0000000..a9ceea8 Binary files /dev/null and b/d1/assets/textures/blown07_roughness.png differ diff --git a/d1/assets/textures/ceil002.material b/d1/assets/textures/ceil002.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil002.material +++ b/d1/assets/textures/ceil002.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil003.material b/d1/assets/textures/ceil003.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil003.material +++ b/d1/assets/textures/ceil003.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil008.material b/d1/assets/textures/ceil008.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil008.material +++ b/d1/assets/textures/ceil008.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil014_basecolor.png b/d1/assets/textures/ceil014_basecolor.png new file mode 100644 index 0000000..5eb2cfe Binary files /dev/null and b/d1/assets/textures/ceil014_basecolor.png differ diff --git a/d1/assets/textures/ceil014_metallic.png b/d1/assets/textures/ceil014_metallic.png new file mode 100644 index 0000000..727d09f Binary files /dev/null and b/d1/assets/textures/ceil014_metallic.png differ diff --git a/d1/assets/textures/ceil014_normal.png b/d1/assets/textures/ceil014_normal.png new file mode 100644 index 0000000..7f7b495 Binary files /dev/null and b/d1/assets/textures/ceil014_normal.png differ diff --git a/d1/assets/textures/ceil014_roughness.png b/d1/assets/textures/ceil014_roughness.png new file mode 100644 index 0000000..0030cbd Binary files /dev/null and b/d1/assets/textures/ceil014_roughness.png differ diff --git a/d1/assets/textures/ceil015_basecolor.png b/d1/assets/textures/ceil015_basecolor.png new file mode 100644 index 0000000..9734b44 Binary files /dev/null and b/d1/assets/textures/ceil015_basecolor.png differ diff --git a/d1/assets/textures/ceil015_metallic.png b/d1/assets/textures/ceil015_metallic.png new file mode 100644 index 0000000..081c15b Binary files /dev/null and b/d1/assets/textures/ceil015_metallic.png differ diff --git a/d1/assets/textures/ceil015_normal.png b/d1/assets/textures/ceil015_normal.png new file mode 100644 index 0000000..8dfe524 Binary files /dev/null and b/d1/assets/textures/ceil015_normal.png differ diff --git a/d1/assets/textures/ceil015_roughness.png b/d1/assets/textures/ceil015_roughness.png new file mode 100644 index 0000000..5b238e4 Binary files /dev/null and b/d1/assets/textures/ceil015_roughness.png differ diff --git a/d1/assets/textures/ceil016_basecolor.png b/d1/assets/textures/ceil016_basecolor.png new file mode 100644 index 0000000..e7a3a12 Binary files /dev/null and b/d1/assets/textures/ceil016_basecolor.png differ diff --git a/d1/assets/textures/ceil016_metallic.png b/d1/assets/textures/ceil016_metallic.png new file mode 100644 index 0000000..ca4086c Binary files /dev/null and b/d1/assets/textures/ceil016_metallic.png differ diff --git a/d1/assets/textures/ceil016_normal.png b/d1/assets/textures/ceil016_normal.png new file mode 100644 index 0000000..0194e73 Binary files /dev/null and b/d1/assets/textures/ceil016_normal.png differ diff --git a/d1/assets/textures/ceil016_roughness.png b/d1/assets/textures/ceil016_roughness.png new file mode 100644 index 0000000..f516ec4 Binary files /dev/null and b/d1/assets/textures/ceil016_roughness.png differ diff --git a/d1/assets/textures/ceil017_basecolor.png b/d1/assets/textures/ceil017_basecolor.png new file mode 100644 index 0000000..4be3d53 Binary files /dev/null and b/d1/assets/textures/ceil017_basecolor.png differ diff --git a/d1/assets/textures/ceil017_metallic.png b/d1/assets/textures/ceil017_metallic.png new file mode 100644 index 0000000..081c15b Binary files /dev/null and b/d1/assets/textures/ceil017_metallic.png differ diff --git a/d1/assets/textures/ceil017_normal.png b/d1/assets/textures/ceil017_normal.png new file mode 100644 index 0000000..476db53 Binary files /dev/null and b/d1/assets/textures/ceil017_normal.png differ diff --git a/d1/assets/textures/ceil017_roughness.png b/d1/assets/textures/ceil017_roughness.png new file mode 100644 index 0000000..91226f4 Binary files /dev/null and b/d1/assets/textures/ceil017_roughness.png differ diff --git a/d1/assets/textures/ceil018_basecolor.png b/d1/assets/textures/ceil018_basecolor.png new file mode 100644 index 0000000..7b94b71 Binary files /dev/null and b/d1/assets/textures/ceil018_basecolor.png differ diff --git a/d1/assets/textures/ceil018_metallic.png b/d1/assets/textures/ceil018_metallic.png new file mode 100644 index 0000000..5fe2741 Binary files /dev/null and b/d1/assets/textures/ceil018_metallic.png differ diff --git a/d1/assets/textures/ceil018_normal.png b/d1/assets/textures/ceil018_normal.png new file mode 100644 index 0000000..3a2d14f Binary files /dev/null and b/d1/assets/textures/ceil018_normal.png differ diff --git a/d1/assets/textures/ceil018_roughness.png b/d1/assets/textures/ceil018_roughness.png new file mode 100644 index 0000000..90fb951 Binary files /dev/null and b/d1/assets/textures/ceil018_roughness.png differ diff --git a/d1/assets/textures/ceil019_basecolor.png b/d1/assets/textures/ceil019_basecolor.png new file mode 100644 index 0000000..a2baeaf Binary files /dev/null and b/d1/assets/textures/ceil019_basecolor.png differ diff --git a/d1/assets/textures/ceil019_metallic.png b/d1/assets/textures/ceil019_metallic.png new file mode 100644 index 0000000..25763e1 Binary files /dev/null and b/d1/assets/textures/ceil019_metallic.png differ diff --git a/d1/assets/textures/ceil019_normal.png b/d1/assets/textures/ceil019_normal.png new file mode 100644 index 0000000..2d4432d Binary files /dev/null and b/d1/assets/textures/ceil019_normal.png differ diff --git a/d1/assets/textures/ceil019_roughness.png b/d1/assets/textures/ceil019_roughness.png new file mode 100644 index 0000000..988dacf Binary files /dev/null and b/d1/assets/textures/ceil019_roughness.png differ diff --git a/d1/assets/textures/ceil01_basecolor.png b/d1/assets/textures/ceil01_basecolor.png new file mode 100644 index 0000000..7b94b71 Binary files /dev/null and b/d1/assets/textures/ceil01_basecolor.png differ diff --git a/d1/assets/textures/ceil01_metallic.png b/d1/assets/textures/ceil01_metallic.png new file mode 100644 index 0000000..5fe2741 Binary files /dev/null and b/d1/assets/textures/ceil01_metallic.png differ diff --git a/d1/assets/textures/ceil01_normal.png b/d1/assets/textures/ceil01_normal.png new file mode 100644 index 0000000..3a2d14f Binary files /dev/null and b/d1/assets/textures/ceil01_normal.png differ diff --git a/d1/assets/textures/ceil01_roughness.png b/d1/assets/textures/ceil01_roughness.png new file mode 100644 index 0000000..0d8458e Binary files /dev/null and b/d1/assets/textures/ceil01_roughness.png differ diff --git a/d1/assets/textures/ceil020.material b/d1/assets/textures/ceil020.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil020.material +++ b/d1/assets/textures/ceil020.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil021.material b/d1/assets/textures/ceil021.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil021.material +++ b/d1/assets/textures/ceil021.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil023.material b/d1/assets/textures/ceil023.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil023.material +++ b/d1/assets/textures/ceil023.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil024.material b/d1/assets/textures/ceil024.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil024.material +++ b/d1/assets/textures/ceil024.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil025.material b/d1/assets/textures/ceil025.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil025.material +++ b/d1/assets/textures/ceil025.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil026.material b/d1/assets/textures/ceil026.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil026.material +++ b/d1/assets/textures/ceil026.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil027.material b/d1/assets/textures/ceil027.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil027.material +++ b/d1/assets/textures/ceil027.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil028.material b/d1/assets/textures/ceil028.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil028.material +++ b/d1/assets/textures/ceil028.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil029.material b/d1/assets/textures/ceil029.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil029.material +++ b/d1/assets/textures/ceil029.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil030.material b/d1/assets/textures/ceil030.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil030.material +++ b/d1/assets/textures/ceil030.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil031.material b/d1/assets/textures/ceil031.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil031.material +++ b/d1/assets/textures/ceil031.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil034.material b/d1/assets/textures/ceil034.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil034.material +++ b/d1/assets/textures/ceil034.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil035.material b/d1/assets/textures/ceil035.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil035.material +++ b/d1/assets/textures/ceil035.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/ceil036.material b/d1/assets/textures/ceil036.material index c1f878f..7d202af 100644 --- a/d1/assets/textures/ceil036.material +++ b/d1/assets/textures/ceil036.material @@ -1,2 +1,4 @@ blackbody = 1 +is_light = 1 +no_casting_shadow = 0 emissive_strength = 3.500000 diff --git a/d1/assets/textures/cmissil1_0.material b/d1/assets/textures/cmissil1_0.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_0.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_1.material b/d1/assets/textures/cmissil1_1.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_1.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_10.material b/d1/assets/textures/cmissil1_10.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_10.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_11.material b/d1/assets/textures/cmissil1_11.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_11.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_12.material b/d1/assets/textures/cmissil1_12.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_12.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_13.material b/d1/assets/textures/cmissil1_13.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_13.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_14.material b/d1/assets/textures/cmissil1_14.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_14.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_2.material b/d1/assets/textures/cmissil1_2.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_2.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_3.material b/d1/assets/textures/cmissil1_3.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_3.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_4.material b/d1/assets/textures/cmissil1_4.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_4.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_5.material b/d1/assets/textures/cmissil1_5.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_5.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_6.material b/d1/assets/textures/cmissil1_6.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_6.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_7.material b/d1/assets/textures/cmissil1_7.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_7.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_8.material b/d1/assets/textures/cmissil1_8.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_8.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil1_9.material b/d1/assets/textures/cmissil1_9.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil1_9.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_0.material b/d1/assets/textures/cmissil2_0.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_0.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_1.material b/d1/assets/textures/cmissil2_1.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_1.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_10.material b/d1/assets/textures/cmissil2_10.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_10.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_11.material b/d1/assets/textures/cmissil2_11.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_11.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_12.material b/d1/assets/textures/cmissil2_12.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_12.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_13.material b/d1/assets/textures/cmissil2_13.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_13.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_14.material b/d1/assets/textures/cmissil2_14.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_14.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_2.material b/d1/assets/textures/cmissil2_2.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_2.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_3.material b/d1/assets/textures/cmissil2_3.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_3.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_4.material b/d1/assets/textures/cmissil2_4.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_4.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_5.material b/d1/assets/textures/cmissil2_5.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_5.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_6.material b/d1/assets/textures/cmissil2_6.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_6.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_7.material b/d1/assets/textures/cmissil2_7.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_7.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_8.material b/d1/assets/textures/cmissil2_8.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_8.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/cmissil2_9.material b/d1/assets/textures/cmissil2_9.material new file mode 100644 index 0000000..f80ca1f --- /dev/null +++ b/d1/assets/textures/cmissil2_9.material @@ -0,0 +1,2 @@ +roughness = 0.449000 +metalness = 1.000000 diff --git a/d1/assets/textures/ctrl01_0_basecolor.png b/d1/assets/textures/ctrl01_0_basecolor.png new file mode 100644 index 0000000..d63f5fe Binary files /dev/null and b/d1/assets/textures/ctrl01_0_basecolor.png differ diff --git a/d1/assets/textures/ctrl01_0_emissive.png b/d1/assets/textures/ctrl01_0_emissive.png new file mode 100644 index 0000000..1081bb1 Binary files /dev/null and b/d1/assets/textures/ctrl01_0_emissive.png differ diff --git a/d1/assets/textures/ctrl01_1_basecolor.png b/d1/assets/textures/ctrl01_1_basecolor.png new file mode 100644 index 0000000..d63f5fe Binary files /dev/null and b/d1/assets/textures/ctrl01_1_basecolor.png differ diff --git a/d1/assets/textures/ctrl01_1_emissive.png b/d1/assets/textures/ctrl01_1_emissive.png new file mode 100644 index 0000000..b57cba3 Binary files /dev/null and b/d1/assets/textures/ctrl01_1_emissive.png differ diff --git a/d1/assets/textures/ctrl01_2_basecolor.png b/d1/assets/textures/ctrl01_2_basecolor.png new file mode 100644 index 0000000..d63f5fe Binary files /dev/null and b/d1/assets/textures/ctrl01_2_basecolor.png differ diff --git a/d1/assets/textures/ctrl01_2_emissive.png b/d1/assets/textures/ctrl01_2_emissive.png new file mode 100644 index 0000000..104d7d8 Binary files /dev/null and b/d1/assets/textures/ctrl01_2_emissive.png differ diff --git a/d1/assets/textures/ctrl01_3_basecolor.png b/d1/assets/textures/ctrl01_3_basecolor.png new file mode 100644 index 0000000..d63f5fe Binary files /dev/null and b/d1/assets/textures/ctrl01_3_basecolor.png differ diff --git a/d1/assets/textures/ctrl01_3_emissive.png b/d1/assets/textures/ctrl01_3_emissive.png new file mode 100644 index 0000000..7b5c7a1 Binary files /dev/null and b/d1/assets/textures/ctrl01_3_emissive.png differ diff --git a/d1/assets/textures/ctrl01_4_basecolor.png b/d1/assets/textures/ctrl01_4_basecolor.png new file mode 100644 index 0000000..d63f5fe Binary files /dev/null and b/d1/assets/textures/ctrl01_4_basecolor.png differ diff --git a/d1/assets/textures/ctrl01_4_emissive.png b/d1/assets/textures/ctrl01_4_emissive.png new file mode 100644 index 0000000..c25c5e2 Binary files /dev/null and b/d1/assets/textures/ctrl01_4_emissive.png differ diff --git a/d1/assets/textures/ctrl01_5_basecolor.png b/d1/assets/textures/ctrl01_5_basecolor.png new file mode 100644 index 0000000..d63f5fe Binary files /dev/null and b/d1/assets/textures/ctrl01_5_basecolor.png differ diff --git a/d1/assets/textures/ctrl01_5_emissive.png b/d1/assets/textures/ctrl01_5_emissive.png new file mode 100644 index 0000000..e8024e7 Binary files /dev/null and b/d1/assets/textures/ctrl01_5_emissive.png differ diff --git a/d1/assets/textures/ctrl01_6_basecolor.png b/d1/assets/textures/ctrl01_6_basecolor.png new file mode 100644 index 0000000..d63f5fe Binary files /dev/null and b/d1/assets/textures/ctrl01_6_basecolor.png differ diff --git a/d1/assets/textures/ctrl01_6_emissive.png b/d1/assets/textures/ctrl01_6_emissive.png new file mode 100644 index 0000000..afe2114 Binary files /dev/null and b/d1/assets/textures/ctrl01_6_emissive.png differ diff --git a/d1/assets/textures/ctrl01_7_basecolor.png b/d1/assets/textures/ctrl01_7_basecolor.png new file mode 100644 index 0000000..d63f5fe Binary files /dev/null and b/d1/assets/textures/ctrl01_7_basecolor.png differ diff --git a/d1/assets/textures/ctrl01_7_emissive.png b/d1/assets/textures/ctrl01_7_emissive.png new file mode 100644 index 0000000..d50794e Binary files /dev/null and b/d1/assets/textures/ctrl01_7_emissive.png differ diff --git a/d1/assets/textures/ctrl02_0_basecolor.png b/d1/assets/textures/ctrl02_0_basecolor.png new file mode 100644 index 0000000..553b9e0 Binary files /dev/null and b/d1/assets/textures/ctrl02_0_basecolor.png differ diff --git a/d1/assets/textures/ctrl02_0_emissive.png b/d1/assets/textures/ctrl02_0_emissive.png new file mode 100644 index 0000000..658e191 Binary files /dev/null and b/d1/assets/textures/ctrl02_0_emissive.png differ diff --git a/d1/assets/textures/ctrl02_1_basecolor.png b/d1/assets/textures/ctrl02_1_basecolor.png new file mode 100644 index 0000000..553b9e0 Binary files /dev/null and b/d1/assets/textures/ctrl02_1_basecolor.png differ diff --git a/d1/assets/textures/ctrl02_1_emissive.png b/d1/assets/textures/ctrl02_1_emissive.png new file mode 100644 index 0000000..30e53b2 Binary files /dev/null and b/d1/assets/textures/ctrl02_1_emissive.png differ diff --git a/d1/assets/textures/ctrl02_2_basecolor.png b/d1/assets/textures/ctrl02_2_basecolor.png new file mode 100644 index 0000000..553b9e0 Binary files /dev/null and b/d1/assets/textures/ctrl02_2_basecolor.png differ diff --git a/d1/assets/textures/ctrl02_2_emissive.png b/d1/assets/textures/ctrl02_2_emissive.png new file mode 100644 index 0000000..51a6220 Binary files /dev/null and b/d1/assets/textures/ctrl02_2_emissive.png differ diff --git a/d1/assets/textures/ctrl02_3_basecolor.png b/d1/assets/textures/ctrl02_3_basecolor.png new file mode 100644 index 0000000..553b9e0 Binary files /dev/null and b/d1/assets/textures/ctrl02_3_basecolor.png differ diff --git a/d1/assets/textures/ctrl02_3_emissive.png b/d1/assets/textures/ctrl02_3_emissive.png new file mode 100644 index 0000000..9244e11 Binary files /dev/null and b/d1/assets/textures/ctrl02_3_emissive.png differ diff --git a/d1/assets/textures/ctrl02_4_basecolor.png b/d1/assets/textures/ctrl02_4_basecolor.png new file mode 100644 index 0000000..553b9e0 Binary files /dev/null and b/d1/assets/textures/ctrl02_4_basecolor.png differ diff --git a/d1/assets/textures/ctrl02_4_emissive.png b/d1/assets/textures/ctrl02_4_emissive.png new file mode 100644 index 0000000..4b90ff6 Binary files /dev/null and b/d1/assets/textures/ctrl02_4_emissive.png differ diff --git a/d1/assets/textures/ctrl02_5_basecolor.png b/d1/assets/textures/ctrl02_5_basecolor.png new file mode 100644 index 0000000..553b9e0 Binary files /dev/null and b/d1/assets/textures/ctrl02_5_basecolor.png differ diff --git a/d1/assets/textures/ctrl02_5_emissive.png b/d1/assets/textures/ctrl02_5_emissive.png new file mode 100644 index 0000000..69fe900 Binary files /dev/null and b/d1/assets/textures/ctrl02_5_emissive.png differ diff --git a/d1/assets/textures/ctrl02_6_basecolor.png b/d1/assets/textures/ctrl02_6_basecolor.png new file mode 100644 index 0000000..553b9e0 Binary files /dev/null and b/d1/assets/textures/ctrl02_6_basecolor.png differ diff --git a/d1/assets/textures/ctrl02_6_emissive.png b/d1/assets/textures/ctrl02_6_emissive.png new file mode 100644 index 0000000..2721068 Binary files /dev/null and b/d1/assets/textures/ctrl02_6_emissive.png differ diff --git a/d1/assets/textures/ctrl02_7_basecolor.png b/d1/assets/textures/ctrl02_7_basecolor.png new file mode 100644 index 0000000..553b9e0 Binary files /dev/null and b/d1/assets/textures/ctrl02_7_basecolor.png differ diff --git a/d1/assets/textures/ctrl02_7_emissive.png b/d1/assets/textures/ctrl02_7_emissive.png new file mode 100644 index 0000000..3978e7e Binary files /dev/null and b/d1/assets/textures/ctrl02_7_emissive.png differ diff --git a/d1/assets/textures/ctrl03_0_basecolor.png b/d1/assets/textures/ctrl03_0_basecolor.png new file mode 100644 index 0000000..84e6c25 Binary files /dev/null and b/d1/assets/textures/ctrl03_0_basecolor.png differ diff --git a/d1/assets/textures/ctrl03_0_emissive.png b/d1/assets/textures/ctrl03_0_emissive.png new file mode 100644 index 0000000..71f1731 Binary files /dev/null and b/d1/assets/textures/ctrl03_0_emissive.png differ diff --git a/d1/assets/textures/ctrl03_1_basecolor.png b/d1/assets/textures/ctrl03_1_basecolor.png new file mode 100644 index 0000000..84e6c25 Binary files /dev/null and b/d1/assets/textures/ctrl03_1_basecolor.png differ diff --git a/d1/assets/textures/ctrl03_1_emissive.png b/d1/assets/textures/ctrl03_1_emissive.png new file mode 100644 index 0000000..5dacd1b Binary files /dev/null and b/d1/assets/textures/ctrl03_1_emissive.png differ diff --git a/d1/assets/textures/ctrl03_2_basecolor.png b/d1/assets/textures/ctrl03_2_basecolor.png new file mode 100644 index 0000000..84e6c25 Binary files /dev/null and b/d1/assets/textures/ctrl03_2_basecolor.png differ diff --git a/d1/assets/textures/ctrl03_2_emissive.png b/d1/assets/textures/ctrl03_2_emissive.png new file mode 100644 index 0000000..17c56e5 Binary files /dev/null and b/d1/assets/textures/ctrl03_2_emissive.png differ diff --git a/d1/assets/textures/ctrl03_3_basecolor.png b/d1/assets/textures/ctrl03_3_basecolor.png new file mode 100644 index 0000000..84e6c25 Binary files /dev/null and b/d1/assets/textures/ctrl03_3_basecolor.png differ diff --git a/d1/assets/textures/ctrl03_3_emissive.png b/d1/assets/textures/ctrl03_3_emissive.png new file mode 100644 index 0000000..b83f20d Binary files /dev/null and b/d1/assets/textures/ctrl03_3_emissive.png differ diff --git a/d1/assets/textures/ctrl03_4_basecolor.png b/d1/assets/textures/ctrl03_4_basecolor.png new file mode 100644 index 0000000..84e6c25 Binary files /dev/null and b/d1/assets/textures/ctrl03_4_basecolor.png differ diff --git a/d1/assets/textures/ctrl03_4_emissive.png b/d1/assets/textures/ctrl03_4_emissive.png new file mode 100644 index 0000000..72a977a Binary files /dev/null and b/d1/assets/textures/ctrl03_4_emissive.png differ diff --git a/d1/assets/textures/ctrl03_5_basecolor.png b/d1/assets/textures/ctrl03_5_basecolor.png new file mode 100644 index 0000000..84e6c25 Binary files /dev/null and b/d1/assets/textures/ctrl03_5_basecolor.png differ diff --git a/d1/assets/textures/ctrl03_5_emissive.png b/d1/assets/textures/ctrl03_5_emissive.png new file mode 100644 index 0000000..c77e802 Binary files /dev/null and b/d1/assets/textures/ctrl03_5_emissive.png differ diff --git a/d1/assets/textures/ctrl03_6_basecolor.png b/d1/assets/textures/ctrl03_6_basecolor.png new file mode 100644 index 0000000..84e6c25 Binary files /dev/null and b/d1/assets/textures/ctrl03_6_basecolor.png differ diff --git a/d1/assets/textures/ctrl03_6_emissive.png b/d1/assets/textures/ctrl03_6_emissive.png new file mode 100644 index 0000000..21e62d5 Binary files /dev/null and b/d1/assets/textures/ctrl03_6_emissive.png differ diff --git a/d1/assets/textures/ctrl03_7_basecolor.png b/d1/assets/textures/ctrl03_7_basecolor.png new file mode 100644 index 0000000..84e6c25 Binary files /dev/null and b/d1/assets/textures/ctrl03_7_basecolor.png differ diff --git a/d1/assets/textures/ctrl03_7_emissive.png b/d1/assets/textures/ctrl03_7_emissive.png new file mode 100644 index 0000000..b3c087a Binary files /dev/null and b/d1/assets/textures/ctrl03_7_emissive.png differ diff --git a/d1/assets/textures/ctrl04_0_basecolor.png b/d1/assets/textures/ctrl04_0_basecolor.png new file mode 100644 index 0000000..ee687bb Binary files /dev/null and b/d1/assets/textures/ctrl04_0_basecolor.png differ diff --git a/d1/assets/textures/ctrl04_0_emissive.png b/d1/assets/textures/ctrl04_0_emissive.png new file mode 100644 index 0000000..b285831 Binary files /dev/null and b/d1/assets/textures/ctrl04_0_emissive.png differ diff --git a/d1/assets/textures/ctrl04_1_basecolor.png b/d1/assets/textures/ctrl04_1_basecolor.png new file mode 100644 index 0000000..ee687bb Binary files /dev/null and b/d1/assets/textures/ctrl04_1_basecolor.png differ diff --git a/d1/assets/textures/ctrl04_1_emissive.png b/d1/assets/textures/ctrl04_1_emissive.png new file mode 100644 index 0000000..124b806 Binary files /dev/null and b/d1/assets/textures/ctrl04_1_emissive.png differ diff --git a/d1/assets/textures/ctrl04_2_basecolor.png b/d1/assets/textures/ctrl04_2_basecolor.png new file mode 100644 index 0000000..ee687bb Binary files /dev/null and b/d1/assets/textures/ctrl04_2_basecolor.png differ diff --git a/d1/assets/textures/ctrl04_2_emissive.png b/d1/assets/textures/ctrl04_2_emissive.png new file mode 100644 index 0000000..0294f1a Binary files /dev/null and b/d1/assets/textures/ctrl04_2_emissive.png differ diff --git a/d1/assets/textures/ctrl04_3_basecolor.png b/d1/assets/textures/ctrl04_3_basecolor.png new file mode 100644 index 0000000..ee687bb Binary files /dev/null and b/d1/assets/textures/ctrl04_3_basecolor.png differ diff --git a/d1/assets/textures/ctrl04_3_emissive.png b/d1/assets/textures/ctrl04_3_emissive.png new file mode 100644 index 0000000..9aba2b3 Binary files /dev/null and b/d1/assets/textures/ctrl04_3_emissive.png differ diff --git a/d1/assets/textures/ctrl04_4_basecolor.png b/d1/assets/textures/ctrl04_4_basecolor.png new file mode 100644 index 0000000..ee687bb Binary files /dev/null and b/d1/assets/textures/ctrl04_4_basecolor.png differ diff --git a/d1/assets/textures/ctrl04_4_emissive.png b/d1/assets/textures/ctrl04_4_emissive.png new file mode 100644 index 0000000..e05090a Binary files /dev/null and b/d1/assets/textures/ctrl04_4_emissive.png differ diff --git a/d1/assets/textures/ctrl04_5_basecolor.png b/d1/assets/textures/ctrl04_5_basecolor.png new file mode 100644 index 0000000..ee687bb Binary files /dev/null and b/d1/assets/textures/ctrl04_5_basecolor.png differ diff --git a/d1/assets/textures/ctrl04_5_emissive.png b/d1/assets/textures/ctrl04_5_emissive.png new file mode 100644 index 0000000..d8e424d Binary files /dev/null and b/d1/assets/textures/ctrl04_5_emissive.png differ diff --git a/d1/assets/textures/ctrl04_6_basecolor.png b/d1/assets/textures/ctrl04_6_basecolor.png new file mode 100644 index 0000000..ee687bb Binary files /dev/null and b/d1/assets/textures/ctrl04_6_basecolor.png differ diff --git a/d1/assets/textures/ctrl04_6_emissive.png b/d1/assets/textures/ctrl04_6_emissive.png new file mode 100644 index 0000000..bf3c62a Binary files /dev/null and b/d1/assets/textures/ctrl04_6_emissive.png differ diff --git a/d1/assets/textures/ctrl04_7_basecolor.png b/d1/assets/textures/ctrl04_7_basecolor.png new file mode 100644 index 0000000..ee687bb Binary files /dev/null and b/d1/assets/textures/ctrl04_7_basecolor.png differ diff --git a/d1/assets/textures/ctrl04_7_emissive.png b/d1/assets/textures/ctrl04_7_emissive.png new file mode 100644 index 0000000..505a1fd Binary files /dev/null and b/d1/assets/textures/ctrl04_7_emissive.png differ diff --git a/d1/assets/textures/door14_0.material b/d1/assets/textures/door14_0.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_0.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/door14_1.material b/d1/assets/textures/door14_1.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_1.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/door14_10.material b/d1/assets/textures/door14_10.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_10.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/door14_11.material b/d1/assets/textures/door14_11.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_11.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/door14_12.material b/d1/assets/textures/door14_12.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_12.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/door14_13.material b/d1/assets/textures/door14_13.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_13.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/door14_2.material b/d1/assets/textures/door14_2.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_2.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/door14_3.material b/d1/assets/textures/door14_3.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_3.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/door14_4.material b/d1/assets/textures/door14_4.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_4.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/door14_5.material b/d1/assets/textures/door14_5.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_5.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/door14_6.material b/d1/assets/textures/door14_6.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_6.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/door14_7.material b/d1/assets/textures/door14_7.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_7.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/door14_8.material b/d1/assets/textures/door14_8.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_8.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/door14_9.material b/d1/assets/textures/door14_9.material new file mode 100644 index 0000000..ed7c865 --- /dev/null +++ b/d1/assets/textures/door14_9.material @@ -0,0 +1,2 @@ +roughness = 0.317000 +metalness = 1.000000 diff --git a/d1/assets/textures/exit01.material b/d1/assets/textures/exit01.material new file mode 100644 index 0000000..9e85060 --- /dev/null +++ b/d1/assets/textures/exit01.material @@ -0,0 +1,2 @@ +roughness = 0.463000 +metalness = 1.000000 diff --git a/d1/assets/textures/exit02.material b/d1/assets/textures/exit02.material new file mode 100644 index 0000000..5eb7ca1 --- /dev/null +++ b/d1/assets/textures/exit02.material @@ -0,0 +1,2 @@ +roughness = 0.580000 +metalness = 1.000000 diff --git a/d1/assets/textures/exp03_0.material b/d1/assets/textures/exp03_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp03_0.material +++ b/d1/assets/textures/exp03_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp03_1.material b/d1/assets/textures/exp03_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp03_1.material +++ b/d1/assets/textures/exp03_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp03_2.material b/d1/assets/textures/exp03_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp03_2.material +++ b/d1/assets/textures/exp03_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp03_3.material b/d1/assets/textures/exp03_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp03_3.material +++ b/d1/assets/textures/exp03_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp03_4.material b/d1/assets/textures/exp03_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp03_4.material +++ b/d1/assets/textures/exp03_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp06_0.material b/d1/assets/textures/exp06_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp06_0.material +++ b/d1/assets/textures/exp06_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp06_1.material b/d1/assets/textures/exp06_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp06_1.material +++ b/d1/assets/textures/exp06_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp06_10.material b/d1/assets/textures/exp06_10.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp06_10.material +++ b/d1/assets/textures/exp06_10.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp06_11.material b/d1/assets/textures/exp06_11.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp06_11.material +++ b/d1/assets/textures/exp06_11.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp06_2.material b/d1/assets/textures/exp06_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp06_2.material +++ b/d1/assets/textures/exp06_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp06_3.material b/d1/assets/textures/exp06_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp06_3.material +++ b/d1/assets/textures/exp06_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp06_4.material b/d1/assets/textures/exp06_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp06_4.material +++ b/d1/assets/textures/exp06_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp06_5.material b/d1/assets/textures/exp06_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp06_5.material +++ b/d1/assets/textures/exp06_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp06_6.material b/d1/assets/textures/exp06_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp06_6.material +++ b/d1/assets/textures/exp06_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp06_7.material b/d1/assets/textures/exp06_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp06_7.material +++ b/d1/assets/textures/exp06_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp06_8.material b/d1/assets/textures/exp06_8.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp06_8.material +++ b/d1/assets/textures/exp06_8.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp06_9.material b/d1/assets/textures/exp06_9.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp06_9.material +++ b/d1/assets/textures/exp06_9.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp09_0.material b/d1/assets/textures/exp09_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp09_0.material +++ b/d1/assets/textures/exp09_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp09_1.material b/d1/assets/textures/exp09_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp09_1.material +++ b/d1/assets/textures/exp09_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp09_2.material b/d1/assets/textures/exp09_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp09_2.material +++ b/d1/assets/textures/exp09_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp09_3.material b/d1/assets/textures/exp09_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp09_3.material +++ b/d1/assets/textures/exp09_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp09_4.material b/d1/assets/textures/exp09_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp09_4.material +++ b/d1/assets/textures/exp09_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp10_0.material b/d1/assets/textures/exp10_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp10_0.material +++ b/d1/assets/textures/exp10_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp10_1.material b/d1/assets/textures/exp10_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp10_1.material +++ b/d1/assets/textures/exp10_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp10_2.material b/d1/assets/textures/exp10_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp10_2.material +++ b/d1/assets/textures/exp10_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp10_3.material b/d1/assets/textures/exp10_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp10_3.material +++ b/d1/assets/textures/exp10_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp10_4.material b/d1/assets/textures/exp10_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp10_4.material +++ b/d1/assets/textures/exp10_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp11_0.material b/d1/assets/textures/exp11_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp11_0.material +++ b/d1/assets/textures/exp11_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp11_1.material b/d1/assets/textures/exp11_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp11_1.material +++ b/d1/assets/textures/exp11_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp11_2.material b/d1/assets/textures/exp11_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp11_2.material +++ b/d1/assets/textures/exp11_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp11_3.material b/d1/assets/textures/exp11_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp11_3.material +++ b/d1/assets/textures/exp11_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp11_4.material b/d1/assets/textures/exp11_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp11_4.material +++ b/d1/assets/textures/exp11_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_0.material b/d1/assets/textures/exp13_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_0.material +++ b/d1/assets/textures/exp13_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_1.material b/d1/assets/textures/exp13_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_1.material +++ b/d1/assets/textures/exp13_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_10.material b/d1/assets/textures/exp13_10.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_10.material +++ b/d1/assets/textures/exp13_10.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_11.material b/d1/assets/textures/exp13_11.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_11.material +++ b/d1/assets/textures/exp13_11.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_12.material b/d1/assets/textures/exp13_12.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_12.material +++ b/d1/assets/textures/exp13_12.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_13.material b/d1/assets/textures/exp13_13.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_13.material +++ b/d1/assets/textures/exp13_13.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_14.material b/d1/assets/textures/exp13_14.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_14.material +++ b/d1/assets/textures/exp13_14.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_15.material b/d1/assets/textures/exp13_15.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_15.material +++ b/d1/assets/textures/exp13_15.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_16.material b/d1/assets/textures/exp13_16.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_16.material +++ b/d1/assets/textures/exp13_16.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_2.material b/d1/assets/textures/exp13_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_2.material +++ b/d1/assets/textures/exp13_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_3.material b/d1/assets/textures/exp13_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_3.material +++ b/d1/assets/textures/exp13_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_4.material b/d1/assets/textures/exp13_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_4.material +++ b/d1/assets/textures/exp13_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_5.material b/d1/assets/textures/exp13_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_5.material +++ b/d1/assets/textures/exp13_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_6.material b/d1/assets/textures/exp13_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_6.material +++ b/d1/assets/textures/exp13_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_7.material b/d1/assets/textures/exp13_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_7.material +++ b/d1/assets/textures/exp13_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_8.material b/d1/assets/textures/exp13_8.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_8.material +++ b/d1/assets/textures/exp13_8.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp13_9.material b/d1/assets/textures/exp13_9.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp13_9.material +++ b/d1/assets/textures/exp13_9.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_0.material b/d1/assets/textures/exp15_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_0.material +++ b/d1/assets/textures/exp15_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_1.material b/d1/assets/textures/exp15_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_1.material +++ b/d1/assets/textures/exp15_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_10.material b/d1/assets/textures/exp15_10.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_10.material +++ b/d1/assets/textures/exp15_10.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_11.material b/d1/assets/textures/exp15_11.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_11.material +++ b/d1/assets/textures/exp15_11.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_12.material b/d1/assets/textures/exp15_12.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_12.material +++ b/d1/assets/textures/exp15_12.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_13.material b/d1/assets/textures/exp15_13.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_13.material +++ b/d1/assets/textures/exp15_13.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_14.material b/d1/assets/textures/exp15_14.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_14.material +++ b/d1/assets/textures/exp15_14.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_15.material b/d1/assets/textures/exp15_15.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_15.material +++ b/d1/assets/textures/exp15_15.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_16.material b/d1/assets/textures/exp15_16.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_16.material +++ b/d1/assets/textures/exp15_16.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_2.material b/d1/assets/textures/exp15_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_2.material +++ b/d1/assets/textures/exp15_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_3.material b/d1/assets/textures/exp15_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_3.material +++ b/d1/assets/textures/exp15_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_4.material b/d1/assets/textures/exp15_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_4.material +++ b/d1/assets/textures/exp15_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_5.material b/d1/assets/textures/exp15_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_5.material +++ b/d1/assets/textures/exp15_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_6.material b/d1/assets/textures/exp15_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_6.material +++ b/d1/assets/textures/exp15_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_7.material b/d1/assets/textures/exp15_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_7.material +++ b/d1/assets/textures/exp15_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_8.material b/d1/assets/textures/exp15_8.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_8.material +++ b/d1/assets/textures/exp15_8.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp15_9.material b/d1/assets/textures/exp15_9.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp15_9.material +++ b/d1/assets/textures/exp15_9.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_0.material b/d1/assets/textures/exp17_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_0.material +++ b/d1/assets/textures/exp17_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_1.material b/d1/assets/textures/exp17_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_1.material +++ b/d1/assets/textures/exp17_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_10.material b/d1/assets/textures/exp17_10.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_10.material +++ b/d1/assets/textures/exp17_10.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_11.material b/d1/assets/textures/exp17_11.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_11.material +++ b/d1/assets/textures/exp17_11.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_12.material b/d1/assets/textures/exp17_12.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_12.material +++ b/d1/assets/textures/exp17_12.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_13.material b/d1/assets/textures/exp17_13.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_13.material +++ b/d1/assets/textures/exp17_13.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_14.material b/d1/assets/textures/exp17_14.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_14.material +++ b/d1/assets/textures/exp17_14.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_15.material b/d1/assets/textures/exp17_15.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_15.material +++ b/d1/assets/textures/exp17_15.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_16.material b/d1/assets/textures/exp17_16.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_16.material +++ b/d1/assets/textures/exp17_16.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_2.material b/d1/assets/textures/exp17_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_2.material +++ b/d1/assets/textures/exp17_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_3.material b/d1/assets/textures/exp17_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_3.material +++ b/d1/assets/textures/exp17_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_4.material b/d1/assets/textures/exp17_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_4.material +++ b/d1/assets/textures/exp17_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_5.material b/d1/assets/textures/exp17_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_5.material +++ b/d1/assets/textures/exp17_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_6.material b/d1/assets/textures/exp17_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_6.material +++ b/d1/assets/textures/exp17_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_7.material b/d1/assets/textures/exp17_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_7.material +++ b/d1/assets/textures/exp17_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_8.material b/d1/assets/textures/exp17_8.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_8.material +++ b/d1/assets/textures/exp17_8.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp17_9.material b/d1/assets/textures/exp17_9.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp17_9.material +++ b/d1/assets/textures/exp17_9.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp18_0.material b/d1/assets/textures/exp18_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp18_0.material +++ b/d1/assets/textures/exp18_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp18_1.material b/d1/assets/textures/exp18_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp18_1.material +++ b/d1/assets/textures/exp18_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp18_2.material b/d1/assets/textures/exp18_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp18_2.material +++ b/d1/assets/textures/exp18_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp18_3.material b/d1/assets/textures/exp18_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp18_3.material +++ b/d1/assets/textures/exp18_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp18_4.material b/d1/assets/textures/exp18_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp18_4.material +++ b/d1/assets/textures/exp18_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp18_5.material b/d1/assets/textures/exp18_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp18_5.material +++ b/d1/assets/textures/exp18_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp18_6.material b/d1/assets/textures/exp18_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp18_6.material +++ b/d1/assets/textures/exp18_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp18_7.material b/d1/assets/textures/exp18_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp18_7.material +++ b/d1/assets/textures/exp18_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp18_8.material b/d1/assets/textures/exp18_8.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp18_8.material +++ b/d1/assets/textures/exp18_8.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp19_0.material b/d1/assets/textures/exp19_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp19_0.material +++ b/d1/assets/textures/exp19_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp19_1.material b/d1/assets/textures/exp19_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp19_1.material +++ b/d1/assets/textures/exp19_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp19_10.material b/d1/assets/textures/exp19_10.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp19_10.material +++ b/d1/assets/textures/exp19_10.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp19_2.material b/d1/assets/textures/exp19_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp19_2.material +++ b/d1/assets/textures/exp19_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp19_3.material b/d1/assets/textures/exp19_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp19_3.material +++ b/d1/assets/textures/exp19_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp19_4.material b/d1/assets/textures/exp19_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp19_4.material +++ b/d1/assets/textures/exp19_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp19_5.material b/d1/assets/textures/exp19_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp19_5.material +++ b/d1/assets/textures/exp19_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp19_6.material b/d1/assets/textures/exp19_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp19_6.material +++ b/d1/assets/textures/exp19_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp19_7.material b/d1/assets/textures/exp19_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp19_7.material +++ b/d1/assets/textures/exp19_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp19_8.material b/d1/assets/textures/exp19_8.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp19_8.material +++ b/d1/assets/textures/exp19_8.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp19_9.material b/d1/assets/textures/exp19_9.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp19_9.material +++ b/d1/assets/textures/exp19_9.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp20_0.material b/d1/assets/textures/exp20_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp20_0.material +++ b/d1/assets/textures/exp20_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp20_1.material b/d1/assets/textures/exp20_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp20_1.material +++ b/d1/assets/textures/exp20_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp20_2.material b/d1/assets/textures/exp20_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp20_2.material +++ b/d1/assets/textures/exp20_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp20_3.material b/d1/assets/textures/exp20_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp20_3.material +++ b/d1/assets/textures/exp20_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp20_4.material b/d1/assets/textures/exp20_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp20_4.material +++ b/d1/assets/textures/exp20_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp20_5.material b/d1/assets/textures/exp20_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp20_5.material +++ b/d1/assets/textures/exp20_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp20_6.material b/d1/assets/textures/exp20_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp20_6.material +++ b/d1/assets/textures/exp20_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp20_7.material b/d1/assets/textures/exp20_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp20_7.material +++ b/d1/assets/textures/exp20_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp20_8.material b/d1/assets/textures/exp20_8.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp20_8.material +++ b/d1/assets/textures/exp20_8.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp20_9.material b/d1/assets/textures/exp20_9.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp20_9.material +++ b/d1/assets/textures/exp20_9.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp21_0.material b/d1/assets/textures/exp21_0.material index c1f878f..f5b2c29 100644 --- a/d1/assets/textures/exp21_0.material +++ b/d1/assets/textures/exp21_0.material @@ -1,2 +1,4 @@ blackbody = 1 -emissive_strength = 3.500000 +is_light = 0 +no_casting_shadow = 1 +emissive_strength = 35.000000 diff --git a/d1/assets/textures/exp21_1.material b/d1/assets/textures/exp21_1.material index c1f878f..f5b2c29 100644 --- a/d1/assets/textures/exp21_1.material +++ b/d1/assets/textures/exp21_1.material @@ -1,2 +1,4 @@ blackbody = 1 -emissive_strength = 3.500000 +is_light = 0 +no_casting_shadow = 1 +emissive_strength = 35.000000 diff --git a/d1/assets/textures/exp21_10.material b/d1/assets/textures/exp21_10.material index c1f878f..f5b2c29 100644 --- a/d1/assets/textures/exp21_10.material +++ b/d1/assets/textures/exp21_10.material @@ -1,2 +1,4 @@ blackbody = 1 -emissive_strength = 3.500000 +is_light = 0 +no_casting_shadow = 1 +emissive_strength = 35.000000 diff --git a/d1/assets/textures/exp21_11.material b/d1/assets/textures/exp21_11.material index c1f878f..f5b2c29 100644 --- a/d1/assets/textures/exp21_11.material +++ b/d1/assets/textures/exp21_11.material @@ -1,2 +1,4 @@ blackbody = 1 -emissive_strength = 3.500000 +is_light = 0 +no_casting_shadow = 1 +emissive_strength = 35.000000 diff --git a/d1/assets/textures/exp21_12.material b/d1/assets/textures/exp21_12.material index c1f878f..f5b2c29 100644 --- a/d1/assets/textures/exp21_12.material +++ b/d1/assets/textures/exp21_12.material @@ -1,2 +1,4 @@ blackbody = 1 -emissive_strength = 3.500000 +is_light = 0 +no_casting_shadow = 1 +emissive_strength = 35.000000 diff --git a/d1/assets/textures/exp21_2.material b/d1/assets/textures/exp21_2.material index c1f878f..f5b2c29 100644 --- a/d1/assets/textures/exp21_2.material +++ b/d1/assets/textures/exp21_2.material @@ -1,2 +1,4 @@ blackbody = 1 -emissive_strength = 3.500000 +is_light = 0 +no_casting_shadow = 1 +emissive_strength = 35.000000 diff --git a/d1/assets/textures/exp21_3.material b/d1/assets/textures/exp21_3.material index c1f878f..f5b2c29 100644 --- a/d1/assets/textures/exp21_3.material +++ b/d1/assets/textures/exp21_3.material @@ -1,2 +1,4 @@ blackbody = 1 -emissive_strength = 3.500000 +is_light = 0 +no_casting_shadow = 1 +emissive_strength = 35.000000 diff --git a/d1/assets/textures/exp21_4.material b/d1/assets/textures/exp21_4.material index c1f878f..f5b2c29 100644 --- a/d1/assets/textures/exp21_4.material +++ b/d1/assets/textures/exp21_4.material @@ -1,2 +1,4 @@ blackbody = 1 -emissive_strength = 3.500000 +is_light = 0 +no_casting_shadow = 1 +emissive_strength = 35.000000 diff --git a/d1/assets/textures/exp21_5.material b/d1/assets/textures/exp21_5.material index c1f878f..f5b2c29 100644 --- a/d1/assets/textures/exp21_5.material +++ b/d1/assets/textures/exp21_5.material @@ -1,2 +1,4 @@ blackbody = 1 -emissive_strength = 3.500000 +is_light = 0 +no_casting_shadow = 1 +emissive_strength = 35.000000 diff --git a/d1/assets/textures/exp21_6.material b/d1/assets/textures/exp21_6.material index c1f878f..f5b2c29 100644 --- a/d1/assets/textures/exp21_6.material +++ b/d1/assets/textures/exp21_6.material @@ -1,2 +1,4 @@ blackbody = 1 -emissive_strength = 3.500000 +is_light = 0 +no_casting_shadow = 1 +emissive_strength = 35.000000 diff --git a/d1/assets/textures/exp21_7.material b/d1/assets/textures/exp21_7.material index c1f878f..f5b2c29 100644 --- a/d1/assets/textures/exp21_7.material +++ b/d1/assets/textures/exp21_7.material @@ -1,2 +1,4 @@ blackbody = 1 -emissive_strength = 3.500000 +is_light = 0 +no_casting_shadow = 1 +emissive_strength = 35.000000 diff --git a/d1/assets/textures/exp21_8.material b/d1/assets/textures/exp21_8.material index c1f878f..f5b2c29 100644 --- a/d1/assets/textures/exp21_8.material +++ b/d1/assets/textures/exp21_8.material @@ -1,2 +1,4 @@ blackbody = 1 -emissive_strength = 3.500000 +is_light = 0 +no_casting_shadow = 1 +emissive_strength = 35.000000 diff --git a/d1/assets/textures/exp21_9.material b/d1/assets/textures/exp21_9.material index c1f878f..f5b2c29 100644 --- a/d1/assets/textures/exp21_9.material +++ b/d1/assets/textures/exp21_9.material @@ -1,2 +1,4 @@ blackbody = 1 -emissive_strength = 3.500000 +is_light = 0 +no_casting_shadow = 1 +emissive_strength = 35.000000 diff --git a/d1/assets/textures/exp22_0.material b/d1/assets/textures/exp22_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp22_0.material +++ b/d1/assets/textures/exp22_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp22_1.material b/d1/assets/textures/exp22_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp22_1.material +++ b/d1/assets/textures/exp22_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp22_2.material b/d1/assets/textures/exp22_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp22_2.material +++ b/d1/assets/textures/exp22_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp22_3.material b/d1/assets/textures/exp22_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp22_3.material +++ b/d1/assets/textures/exp22_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp22_4.material b/d1/assets/textures/exp22_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp22_4.material +++ b/d1/assets/textures/exp22_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp22_5.material b/d1/assets/textures/exp22_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp22_5.material +++ b/d1/assets/textures/exp22_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp22_6.material b/d1/assets/textures/exp22_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp22_6.material +++ b/d1/assets/textures/exp22_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp22_7.material b/d1/assets/textures/exp22_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp22_7.material +++ b/d1/assets/textures/exp22_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp22_8.material b/d1/assets/textures/exp22_8.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp22_8.material +++ b/d1/assets/textures/exp22_8.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/exp22_9.material b/d1/assets/textures/exp22_9.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/exp22_9.material +++ b/d1/assets/textures/exp22_9.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/fram06.material b/d1/assets/textures/fram06.material new file mode 100644 index 0000000..ed89d95 --- /dev/null +++ b/d1/assets/textures/fram06.material @@ -0,0 +1,2 @@ +roughness = 0.320000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_0.material b/d1/assets/textures/fusion_0.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_0.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_1.material b/d1/assets/textures/fusion_1.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_1.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_10.material b/d1/assets/textures/fusion_10.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_10.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_11.material b/d1/assets/textures/fusion_11.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_11.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_12.material b/d1/assets/textures/fusion_12.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_12.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_13.material b/d1/assets/textures/fusion_13.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_13.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_14.material b/d1/assets/textures/fusion_14.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_14.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_2.material b/d1/assets/textures/fusion_2.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_2.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_3.material b/d1/assets/textures/fusion_3.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_3.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_4.material b/d1/assets/textures/fusion_4.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_4.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_5.material b/d1/assets/textures/fusion_5.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_5.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_6.material b/d1/assets/textures/fusion_6.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_6.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_7.material b/d1/assets/textures/fusion_7.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_7.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_8.material b/d1/assets/textures/fusion_8.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_8.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/fusion_9.material b/d1/assets/textures/fusion_9.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/fusion_9.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_0.material b/d1/assets/textures/hmissil1_0.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_0.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_1.material b/d1/assets/textures/hmissil1_1.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_1.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_10.material b/d1/assets/textures/hmissil1_10.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_10.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_11.material b/d1/assets/textures/hmissil1_11.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_11.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_12.material b/d1/assets/textures/hmissil1_12.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_12.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_13.material b/d1/assets/textures/hmissil1_13.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_13.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_14.material b/d1/assets/textures/hmissil1_14.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_14.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_2.material b/d1/assets/textures/hmissil1_2.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_2.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_3.material b/d1/assets/textures/hmissil1_3.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_3.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_4.material b/d1/assets/textures/hmissil1_4.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_4.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_5.material b/d1/assets/textures/hmissil1_5.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_5.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_6.material b/d1/assets/textures/hmissil1_6.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_6.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_7.material b/d1/assets/textures/hmissil1_7.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_7.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_8.material b/d1/assets/textures/hmissil1_8.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_8.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil1_9.material b/d1/assets/textures/hmissil1_9.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil1_9.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_0.material b/d1/assets/textures/hmissil2_0.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_0.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_1.material b/d1/assets/textures/hmissil2_1.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_1.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_10.material b/d1/assets/textures/hmissil2_10.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_10.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_11.material b/d1/assets/textures/hmissil2_11.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_11.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_12.material b/d1/assets/textures/hmissil2_12.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_12.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_13.material b/d1/assets/textures/hmissil2_13.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_13.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_14.material b/d1/assets/textures/hmissil2_14.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_14.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_2.material b/d1/assets/textures/hmissil2_2.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_2.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_3.material b/d1/assets/textures/hmissil2_3.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_3.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_4.material b/d1/assets/textures/hmissil2_4.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_4.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_5.material b/d1/assets/textures/hmissil2_5.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_5.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_6.material b/d1/assets/textures/hmissil2_6.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_6.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_7.material b/d1/assets/textures/hmissil2_7.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_7.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_8.material b/d1/assets/textures/hmissil2_8.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_8.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/hmissil2_9.material b/d1/assets/textures/hmissil2_9.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/hmissil2_9.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_0.material b/d1/assets/textures/laser_0.material index b522be0..1cea2c5 100644 --- a/d1/assets/textures/laser_0.material +++ b/d1/assets/textures/laser_0.material @@ -1 +1,2 @@ -blackbody = 0 +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_1.material b/d1/assets/textures/laser_1.material index b522be0..1cea2c5 100644 --- a/d1/assets/textures/laser_1.material +++ b/d1/assets/textures/laser_1.material @@ -1 +1,2 @@ -blackbody = 0 +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_10.material b/d1/assets/textures/laser_10.material new file mode 100644 index 0000000..1cea2c5 --- /dev/null +++ b/d1/assets/textures/laser_10.material @@ -0,0 +1,2 @@ +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_11.material b/d1/assets/textures/laser_11.material new file mode 100644 index 0000000..1cea2c5 --- /dev/null +++ b/d1/assets/textures/laser_11.material @@ -0,0 +1,2 @@ +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_12.material b/d1/assets/textures/laser_12.material new file mode 100644 index 0000000..1cea2c5 --- /dev/null +++ b/d1/assets/textures/laser_12.material @@ -0,0 +1,2 @@ +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_13.material b/d1/assets/textures/laser_13.material new file mode 100644 index 0000000..1cea2c5 --- /dev/null +++ b/d1/assets/textures/laser_13.material @@ -0,0 +1,2 @@ +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_14.material b/d1/assets/textures/laser_14.material new file mode 100644 index 0000000..1cea2c5 --- /dev/null +++ b/d1/assets/textures/laser_14.material @@ -0,0 +1,2 @@ +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_2.material b/d1/assets/textures/laser_2.material index b522be0..1cea2c5 100644 --- a/d1/assets/textures/laser_2.material +++ b/d1/assets/textures/laser_2.material @@ -1 +1,2 @@ -blackbody = 0 +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_3.material b/d1/assets/textures/laser_3.material index b522be0..1cea2c5 100644 --- a/d1/assets/textures/laser_3.material +++ b/d1/assets/textures/laser_3.material @@ -1 +1,2 @@ -blackbody = 0 +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_4.material b/d1/assets/textures/laser_4.material index b522be0..1cea2c5 100644 --- a/d1/assets/textures/laser_4.material +++ b/d1/assets/textures/laser_4.material @@ -1 +1,2 @@ -blackbody = 0 +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_5.material b/d1/assets/textures/laser_5.material index b522be0..1cea2c5 100644 --- a/d1/assets/textures/laser_5.material +++ b/d1/assets/textures/laser_5.material @@ -1 +1,2 @@ -blackbody = 0 +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_6.material b/d1/assets/textures/laser_6.material index b522be0..1cea2c5 100644 --- a/d1/assets/textures/laser_6.material +++ b/d1/assets/textures/laser_6.material @@ -1 +1,2 @@ -blackbody = 0 +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_7.material b/d1/assets/textures/laser_7.material index b522be0..1cea2c5 100644 --- a/d1/assets/textures/laser_7.material +++ b/d1/assets/textures/laser_7.material @@ -1 +1,2 @@ -blackbody = 0 +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_8.material b/d1/assets/textures/laser_8.material index b522be0..1cea2c5 100644 --- a/d1/assets/textures/laser_8.material +++ b/d1/assets/textures/laser_8.material @@ -1 +1,2 @@ -blackbody = 0 +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/laser_9.material b/d1/assets/textures/laser_9.material new file mode 100644 index 0000000..1cea2c5 --- /dev/null +++ b/d1/assets/textures/laser_9.material @@ -0,0 +1,2 @@ +roughness = 0.529000 +metalness = 1.000000 diff --git a/d1/assets/textures/metl078_basecolor.png b/d1/assets/textures/metl078_basecolor.png new file mode 100644 index 0000000..0d533db Binary files /dev/null and b/d1/assets/textures/metl078_basecolor.png differ diff --git a/d1/assets/textures/metl078_emissive.png b/d1/assets/textures/metl078_emissive.png new file mode 100644 index 0000000..4956b43 Binary files /dev/null and b/d1/assets/textures/metl078_emissive.png differ diff --git a/d1/assets/textures/metl079_basecolor.png b/d1/assets/textures/metl079_basecolor.png new file mode 100644 index 0000000..19c3145 Binary files /dev/null and b/d1/assets/textures/metl079_basecolor.png differ diff --git a/d1/assets/textures/metl079_emissive.png b/d1/assets/textures/metl079_emissive.png new file mode 100644 index 0000000..030e6f7 Binary files /dev/null and b/d1/assets/textures/metl079_emissive.png differ diff --git a/d1/assets/textures/metl080_basecolor.png b/d1/assets/textures/metl080_basecolor.png new file mode 100644 index 0000000..4cd53db Binary files /dev/null and b/d1/assets/textures/metl080_basecolor.png differ diff --git a/d1/assets/textures/metl080_emissive.png b/d1/assets/textures/metl080_emissive.png new file mode 100644 index 0000000..affa6da Binary files /dev/null and b/d1/assets/textures/metl080_emissive.png differ diff --git a/d1/assets/textures/metl088_basecolor.png b/d1/assets/textures/metl088_basecolor.png new file mode 100644 index 0000000..1c7ec78 Binary files /dev/null and b/d1/assets/textures/metl088_basecolor.png differ diff --git a/d1/assets/textures/metl088_emissive.png b/d1/assets/textures/metl088_emissive.png new file mode 100644 index 0000000..979351f Binary files /dev/null and b/d1/assets/textures/metl088_emissive.png differ diff --git a/d1/assets/textures/metl088_metallic.png b/d1/assets/textures/metl088_metallic.png new file mode 100644 index 0000000..4f5af03 Binary files /dev/null and b/d1/assets/textures/metl088_metallic.png differ diff --git a/d1/assets/textures/metl088_roughness.png b/d1/assets/textures/metl088_roughness.png new file mode 100644 index 0000000..0974f2e Binary files /dev/null and b/d1/assets/textures/metl088_roughness.png differ diff --git a/d1/assets/textures/metl089_basecolor.png b/d1/assets/textures/metl089_basecolor.png new file mode 100644 index 0000000..534fa5c Binary files /dev/null and b/d1/assets/textures/metl089_basecolor.png differ diff --git a/d1/assets/textures/metl089_emissive.png b/d1/assets/textures/metl089_emissive.png new file mode 100644 index 0000000..030e6f7 Binary files /dev/null and b/d1/assets/textures/metl089_emissive.png differ diff --git a/d1/assets/textures/metl090_basecolor.png b/d1/assets/textures/metl090_basecolor.png new file mode 100644 index 0000000..7ec8524 Binary files /dev/null and b/d1/assets/textures/metl090_basecolor.png differ diff --git a/d1/assets/textures/metl090_emissive.png b/d1/assets/textures/metl090_emissive.png new file mode 100644 index 0000000..affa6da Binary files /dev/null and b/d1/assets/textures/metl090_emissive.png differ diff --git a/d1/assets/textures/metl126.material b/d1/assets/textures/metl126.material index c1f878f..17012ad 100644 --- a/d1/assets/textures/metl126.material +++ b/d1/assets/textures/metl126.material @@ -1,2 +1 @@ -blackbody = 1 -emissive_strength = 3.500000 +emissive_strength = 2.000000 diff --git a/d1/assets/textures/metl126_basecolor.png b/d1/assets/textures/metl126_basecolor.png new file mode 100644 index 0000000..b31f934 Binary files /dev/null and b/d1/assets/textures/metl126_basecolor.png differ diff --git a/d1/assets/textures/metl126_emissive.png b/d1/assets/textures/metl126_emissive.png new file mode 100644 index 0000000..38908cd Binary files /dev/null and b/d1/assets/textures/metl126_emissive.png differ diff --git a/d1/assets/textures/metl133.material b/d1/assets/textures/metl133.material index c1f878f..17012ad 100644 --- a/d1/assets/textures/metl133.material +++ b/d1/assets/textures/metl133.material @@ -1,2 +1 @@ -blackbody = 1 -emissive_strength = 3.500000 +emissive_strength = 2.000000 diff --git a/d1/assets/textures/metl133_basecolor.png b/d1/assets/textures/metl133_basecolor.png new file mode 100644 index 0000000..b31f934 Binary files /dev/null and b/d1/assets/textures/metl133_basecolor.png differ diff --git a/d1/assets/textures/metl133_emissive.png b/d1/assets/textures/metl133_emissive.png new file mode 100644 index 0000000..e52f3fe Binary files /dev/null and b/d1/assets/textures/metl133_emissive.png differ diff --git a/d1/assets/textures/metl134.material b/d1/assets/textures/metl134.material index c1f878f..17012ad 100644 --- a/d1/assets/textures/metl134.material +++ b/d1/assets/textures/metl134.material @@ -1,2 +1 @@ -blackbody = 1 -emissive_strength = 3.500000 +emissive_strength = 2.000000 diff --git a/d1/assets/textures/metl134_basecolor.png b/d1/assets/textures/metl134_basecolor.png new file mode 100644 index 0000000..b31f934 Binary files /dev/null and b/d1/assets/textures/metl134_basecolor.png differ diff --git a/d1/assets/textures/metl134_emissive.png b/d1/assets/textures/metl134_emissive.png new file mode 100644 index 0000000..0db5a96 Binary files /dev/null and b/d1/assets/textures/metl134_emissive.png differ diff --git a/d1/assets/textures/metl135.material b/d1/assets/textures/metl135.material index c1f878f..17012ad 100644 --- a/d1/assets/textures/metl135.material +++ b/d1/assets/textures/metl135.material @@ -1,2 +1 @@ -blackbody = 1 -emissive_strength = 3.500000 +emissive_strength = 2.000000 diff --git a/d1/assets/textures/metl135_basecolor.png b/d1/assets/textures/metl135_basecolor.png new file mode 100644 index 0000000..b31f934 Binary files /dev/null and b/d1/assets/textures/metl135_basecolor.png differ diff --git a/d1/assets/textures/metl135_emissive.png b/d1/assets/textures/metl135_emissive.png new file mode 100644 index 0000000..744a299 Binary files /dev/null and b/d1/assets/textures/metl135_emissive.png differ diff --git a/d1/assets/textures/misc010_basecolor.png b/d1/assets/textures/misc010_basecolor.png new file mode 100644 index 0000000..31bf8fa Binary files /dev/null and b/d1/assets/textures/misc010_basecolor.png differ diff --git a/d1/assets/textures/misc010_emissive.png b/d1/assets/textures/misc010_emissive.png new file mode 100644 index 0000000..d2f5c42 Binary files /dev/null and b/d1/assets/textures/misc010_emissive.png differ diff --git a/d1/assets/textures/misc060_0.material b/d1/assets/textures/misc060_0.material new file mode 100644 index 0000000..509dab3 --- /dev/null +++ b/d1/assets/textures/misc060_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc060_basecolor.png +metalness_texture = misc060_metallic.png +roughness_texture = misc060_roughness.png diff --git a/d1/assets/textures/misc060_0_emissive.png b/d1/assets/textures/misc060_0_emissive.png new file mode 100644 index 0000000..fce5e23 Binary files /dev/null and b/d1/assets/textures/misc060_0_emissive.png differ diff --git a/d1/assets/textures/misc060_1.material b/d1/assets/textures/misc060_1.material new file mode 100644 index 0000000..509dab3 --- /dev/null +++ b/d1/assets/textures/misc060_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc060_basecolor.png +metalness_texture = misc060_metallic.png +roughness_texture = misc060_roughness.png diff --git a/d1/assets/textures/misc060_1_emissive.png b/d1/assets/textures/misc060_1_emissive.png new file mode 100644 index 0000000..7075df0 Binary files /dev/null and b/d1/assets/textures/misc060_1_emissive.png differ diff --git a/d1/assets/textures/misc060_2.material b/d1/assets/textures/misc060_2.material new file mode 100644 index 0000000..509dab3 --- /dev/null +++ b/d1/assets/textures/misc060_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc060_basecolor.png +metalness_texture = misc060_metallic.png +roughness_texture = misc060_roughness.png diff --git a/d1/assets/textures/misc060_2_emissive.png b/d1/assets/textures/misc060_2_emissive.png new file mode 100644 index 0000000..323fc87 Binary files /dev/null and b/d1/assets/textures/misc060_2_emissive.png differ diff --git a/d1/assets/textures/misc060_basecolor.png b/d1/assets/textures/misc060_basecolor.png new file mode 100644 index 0000000..732eac3 Binary files /dev/null and b/d1/assets/textures/misc060_basecolor.png differ diff --git a/d1/assets/textures/misc060_metallic.png b/d1/assets/textures/misc060_metallic.png new file mode 100644 index 0000000..72c6d28 Binary files /dev/null and b/d1/assets/textures/misc060_metallic.png differ diff --git a/d1/assets/textures/misc060_roughness.png b/d1/assets/textures/misc060_roughness.png new file mode 100644 index 0000000..4c03ccd Binary files /dev/null and b/d1/assets/textures/misc060_roughness.png differ diff --git a/d1/assets/textures/misc060b_0.material b/d1/assets/textures/misc060b_0.material new file mode 100644 index 0000000..4bd40b6 --- /dev/null +++ b/d1/assets/textures/misc060b_0.material @@ -0,0 +1,3 @@ +albedo_texture = blown01_basecolor.png +metalness_texture = blown01_metallic.png +roughness_texture = blown01_roughness.png diff --git a/d1/assets/textures/misc060b_0_emissive.png b/d1/assets/textures/misc060b_0_emissive.png new file mode 100644 index 0000000..cedd092 Binary files /dev/null and b/d1/assets/textures/misc060b_0_emissive.png differ diff --git a/d1/assets/textures/misc060b_1.material b/d1/assets/textures/misc060b_1.material new file mode 100644 index 0000000..4bd40b6 --- /dev/null +++ b/d1/assets/textures/misc060b_1.material @@ -0,0 +1,3 @@ +albedo_texture = blown01_basecolor.png +metalness_texture = blown01_metallic.png +roughness_texture = blown01_roughness.png diff --git a/d1/assets/textures/misc060b_1_emissive.png b/d1/assets/textures/misc060b_1_emissive.png new file mode 100644 index 0000000..91c4234 Binary files /dev/null and b/d1/assets/textures/misc060b_1_emissive.png differ diff --git a/d1/assets/textures/misc060b_2.material b/d1/assets/textures/misc060b_2.material new file mode 100644 index 0000000..4bd40b6 --- /dev/null +++ b/d1/assets/textures/misc060b_2.material @@ -0,0 +1,3 @@ +albedo_texture = blown01_basecolor.png +metalness_texture = blown01_metallic.png +roughness_texture = blown01_roughness.png diff --git a/d1/assets/textures/misc060b_2_emissive.png b/d1/assets/textures/misc060b_2_emissive.png new file mode 100644 index 0000000..1473d59 Binary files /dev/null and b/d1/assets/textures/misc060b_2_emissive.png differ diff --git a/d1/assets/textures/misc060d_0.material b/d1/assets/textures/misc060d_0.material new file mode 100644 index 0000000..509dab3 --- /dev/null +++ b/d1/assets/textures/misc060d_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc060_basecolor.png +metalness_texture = misc060_metallic.png +roughness_texture = misc060_roughness.png diff --git a/d1/assets/textures/misc060d_0_emissive.png b/d1/assets/textures/misc060d_0_emissive.png new file mode 100644 index 0000000..f50d905 Binary files /dev/null and b/d1/assets/textures/misc060d_0_emissive.png differ diff --git a/d1/assets/textures/misc060d_1.material b/d1/assets/textures/misc060d_1.material new file mode 100644 index 0000000..509dab3 --- /dev/null +++ b/d1/assets/textures/misc060d_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc060_basecolor.png +metalness_texture = misc060_metallic.png +roughness_texture = misc060_roughness.png diff --git a/d1/assets/textures/misc060d_1_emissive.png b/d1/assets/textures/misc060d_1_emissive.png new file mode 100644 index 0000000..77ba86d Binary files /dev/null and b/d1/assets/textures/misc060d_1_emissive.png differ diff --git a/d1/assets/textures/misc060d_2.material b/d1/assets/textures/misc060d_2.material new file mode 100644 index 0000000..509dab3 --- /dev/null +++ b/d1/assets/textures/misc060d_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc060_basecolor.png +metalness_texture = misc060_metallic.png +roughness_texture = misc060_roughness.png diff --git a/d1/assets/textures/misc060d_2_emissive.png b/d1/assets/textures/misc060d_2_emissive.png new file mode 100644 index 0000000..3a963dc Binary files /dev/null and b/d1/assets/textures/misc060d_2_emissive.png differ diff --git a/d1/assets/textures/misc061_0.material b/d1/assets/textures/misc061_0.material new file mode 100644 index 0000000..5053004 --- /dev/null +++ b/d1/assets/textures/misc061_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc061_basecolor.png +metalness_texture = misc061_metallic.png +roughness_texture = misc061_roughness.png diff --git a/d1/assets/textures/misc061_0_emissive.png b/d1/assets/textures/misc061_0_emissive.png new file mode 100644 index 0000000..4711e62 Binary files /dev/null and b/d1/assets/textures/misc061_0_emissive.png differ diff --git a/d1/assets/textures/misc061_1.material b/d1/assets/textures/misc061_1.material new file mode 100644 index 0000000..5053004 --- /dev/null +++ b/d1/assets/textures/misc061_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc061_basecolor.png +metalness_texture = misc061_metallic.png +roughness_texture = misc061_roughness.png diff --git a/d1/assets/textures/misc061_1_emissive.png b/d1/assets/textures/misc061_1_emissive.png new file mode 100644 index 0000000..1f8892b Binary files /dev/null and b/d1/assets/textures/misc061_1_emissive.png differ diff --git a/d1/assets/textures/misc061_2.material b/d1/assets/textures/misc061_2.material new file mode 100644 index 0000000..5053004 --- /dev/null +++ b/d1/assets/textures/misc061_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc061_basecolor.png +metalness_texture = misc061_metallic.png +roughness_texture = misc061_roughness.png diff --git a/d1/assets/textures/misc061_2_emissive.png b/d1/assets/textures/misc061_2_emissive.png new file mode 100644 index 0000000..991729d Binary files /dev/null and b/d1/assets/textures/misc061_2_emissive.png differ diff --git a/d1/assets/textures/misc061_3.material b/d1/assets/textures/misc061_3.material new file mode 100644 index 0000000..5053004 --- /dev/null +++ b/d1/assets/textures/misc061_3.material @@ -0,0 +1,3 @@ +albedo_texture = misc061_basecolor.png +metalness_texture = misc061_metallic.png +roughness_texture = misc061_roughness.png diff --git a/d1/assets/textures/misc061_3_emissive.png b/d1/assets/textures/misc061_3_emissive.png new file mode 100644 index 0000000..7170064 Binary files /dev/null and b/d1/assets/textures/misc061_3_emissive.png differ diff --git a/d1/assets/textures/misc061_4.material b/d1/assets/textures/misc061_4.material new file mode 100644 index 0000000..5053004 --- /dev/null +++ b/d1/assets/textures/misc061_4.material @@ -0,0 +1,3 @@ +albedo_texture = misc061_basecolor.png +metalness_texture = misc061_metallic.png +roughness_texture = misc061_roughness.png diff --git a/d1/assets/textures/misc061_4_emissive.png b/d1/assets/textures/misc061_4_emissive.png new file mode 100644 index 0000000..1557d7d Binary files /dev/null and b/d1/assets/textures/misc061_4_emissive.png differ diff --git a/d1/assets/textures/misc061_5.material b/d1/assets/textures/misc061_5.material new file mode 100644 index 0000000..5053004 --- /dev/null +++ b/d1/assets/textures/misc061_5.material @@ -0,0 +1,3 @@ +albedo_texture = misc061_basecolor.png +metalness_texture = misc061_metallic.png +roughness_texture = misc061_roughness.png diff --git a/d1/assets/textures/misc061_basecolor.png b/d1/assets/textures/misc061_basecolor.png new file mode 100644 index 0000000..ddcf1d7 Binary files /dev/null and b/d1/assets/textures/misc061_basecolor.png differ diff --git a/d1/assets/textures/misc061_metallic.png b/d1/assets/textures/misc061_metallic.png new file mode 100644 index 0000000..ff6d936 Binary files /dev/null and b/d1/assets/textures/misc061_metallic.png differ diff --git a/d1/assets/textures/misc061_roughness.png b/d1/assets/textures/misc061_roughness.png new file mode 100644 index 0000000..17372b9 Binary files /dev/null and b/d1/assets/textures/misc061_roughness.png differ diff --git a/d1/assets/textures/misc061b_0.material b/d1/assets/textures/misc061b_0.material new file mode 100644 index 0000000..57f7e91 --- /dev/null +++ b/d1/assets/textures/misc061b_0.material @@ -0,0 +1,3 @@ +albedo_texture = blown02_basecolor.png +metalness_texture = blown02_metallic.png +roughness_texture = blown02_roughness.png diff --git a/d1/assets/textures/misc061b_0_emissive.png b/d1/assets/textures/misc061b_0_emissive.png new file mode 100644 index 0000000..c093f86 Binary files /dev/null and b/d1/assets/textures/misc061b_0_emissive.png differ diff --git a/d1/assets/textures/misc061b_1.material b/d1/assets/textures/misc061b_1.material new file mode 100644 index 0000000..57f7e91 --- /dev/null +++ b/d1/assets/textures/misc061b_1.material @@ -0,0 +1,3 @@ +albedo_texture = blown02_basecolor.png +metalness_texture = blown02_metallic.png +roughness_texture = blown02_roughness.png diff --git a/d1/assets/textures/misc061b_1_emissive.png b/d1/assets/textures/misc061b_1_emissive.png new file mode 100644 index 0000000..795c444 Binary files /dev/null and b/d1/assets/textures/misc061b_1_emissive.png differ diff --git a/d1/assets/textures/misc061b_2.material b/d1/assets/textures/misc061b_2.material new file mode 100644 index 0000000..57f7e91 --- /dev/null +++ b/d1/assets/textures/misc061b_2.material @@ -0,0 +1,3 @@ +albedo_texture = blown02_basecolor.png +metalness_texture = blown02_metallic.png +roughness_texture = blown02_roughness.png diff --git a/d1/assets/textures/misc061b_2_emissive.png b/d1/assets/textures/misc061b_2_emissive.png new file mode 100644 index 0000000..c6131c6 Binary files /dev/null and b/d1/assets/textures/misc061b_2_emissive.png differ diff --git a/d1/assets/textures/misc061d_0.material b/d1/assets/textures/misc061d_0.material new file mode 100644 index 0000000..5053004 --- /dev/null +++ b/d1/assets/textures/misc061d_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc061_basecolor.png +metalness_texture = misc061_metallic.png +roughness_texture = misc061_roughness.png diff --git a/d1/assets/textures/misc061d_0_emissive.png b/d1/assets/textures/misc061d_0_emissive.png new file mode 100644 index 0000000..31e7b42 Binary files /dev/null and b/d1/assets/textures/misc061d_0_emissive.png differ diff --git a/d1/assets/textures/misc061d_1.material b/d1/assets/textures/misc061d_1.material new file mode 100644 index 0000000..5053004 --- /dev/null +++ b/d1/assets/textures/misc061d_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc061_basecolor.png +metalness_texture = misc061_metallic.png +roughness_texture = misc061_roughness.png diff --git a/d1/assets/textures/misc061d_1_emissive.png b/d1/assets/textures/misc061d_1_emissive.png new file mode 100644 index 0000000..ebec140 Binary files /dev/null and b/d1/assets/textures/misc061d_1_emissive.png differ diff --git a/d1/assets/textures/misc061d_2.material b/d1/assets/textures/misc061d_2.material new file mode 100644 index 0000000..5053004 --- /dev/null +++ b/d1/assets/textures/misc061d_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc061_basecolor.png +metalness_texture = misc061_metallic.png +roughness_texture = misc061_roughness.png diff --git a/d1/assets/textures/misc061d_2_emissive.png b/d1/assets/textures/misc061d_2_emissive.png new file mode 100644 index 0000000..4f1b865 Binary files /dev/null and b/d1/assets/textures/misc061d_2_emissive.png differ diff --git a/d1/assets/textures/misc062_0.material b/d1/assets/textures/misc062_0.material new file mode 100644 index 0000000..79aae47 --- /dev/null +++ b/d1/assets/textures/misc062_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc062_basecolor.png +metalness_texture = misc062_metallic.png +roughness_texture = misc062_roughness.png diff --git a/d1/assets/textures/misc062_0_emissive.png b/d1/assets/textures/misc062_0_emissive.png new file mode 100644 index 0000000..10df1a2 Binary files /dev/null and b/d1/assets/textures/misc062_0_emissive.png differ diff --git a/d1/assets/textures/misc062_1.material b/d1/assets/textures/misc062_1.material new file mode 100644 index 0000000..79aae47 --- /dev/null +++ b/d1/assets/textures/misc062_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc062_basecolor.png +metalness_texture = misc062_metallic.png +roughness_texture = misc062_roughness.png diff --git a/d1/assets/textures/misc062_1_emissive.png b/d1/assets/textures/misc062_1_emissive.png new file mode 100644 index 0000000..0aeb2e3 Binary files /dev/null and b/d1/assets/textures/misc062_1_emissive.png differ diff --git a/d1/assets/textures/misc062_2.material b/d1/assets/textures/misc062_2.material new file mode 100644 index 0000000..79aae47 --- /dev/null +++ b/d1/assets/textures/misc062_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc062_basecolor.png +metalness_texture = misc062_metallic.png +roughness_texture = misc062_roughness.png diff --git a/d1/assets/textures/misc062_2_emissive.png b/d1/assets/textures/misc062_2_emissive.png new file mode 100644 index 0000000..2857cc6 Binary files /dev/null and b/d1/assets/textures/misc062_2_emissive.png differ diff --git a/d1/assets/textures/misc062_basecolor.png b/d1/assets/textures/misc062_basecolor.png new file mode 100644 index 0000000..541aa2b Binary files /dev/null and b/d1/assets/textures/misc062_basecolor.png differ diff --git a/d1/assets/textures/misc062_metallic.png b/d1/assets/textures/misc062_metallic.png new file mode 100644 index 0000000..9802989 Binary files /dev/null and b/d1/assets/textures/misc062_metallic.png differ diff --git a/d1/assets/textures/misc062_roughness.png b/d1/assets/textures/misc062_roughness.png new file mode 100644 index 0000000..a9ceea8 Binary files /dev/null and b/d1/assets/textures/misc062_roughness.png differ diff --git a/d1/assets/textures/misc062b_0.material b/d1/assets/textures/misc062b_0.material new file mode 100644 index 0000000..69e46c1 --- /dev/null +++ b/d1/assets/textures/misc062b_0.material @@ -0,0 +1,3 @@ +albedo_texture = blown07_basecolor.png +metalness_texture = blown07_metallic.png +roughness_texture = blown07_roughness.png diff --git a/d1/assets/textures/misc062b_0_emissive.png b/d1/assets/textures/misc062b_0_emissive.png new file mode 100644 index 0000000..0c5ca9e Binary files /dev/null and b/d1/assets/textures/misc062b_0_emissive.png differ diff --git a/d1/assets/textures/misc062b_1.material b/d1/assets/textures/misc062b_1.material new file mode 100644 index 0000000..69e46c1 --- /dev/null +++ b/d1/assets/textures/misc062b_1.material @@ -0,0 +1,3 @@ +albedo_texture = blown07_basecolor.png +metalness_texture = blown07_metallic.png +roughness_texture = blown07_roughness.png diff --git a/d1/assets/textures/misc062b_1_emissive.png b/d1/assets/textures/misc062b_1_emissive.png new file mode 100644 index 0000000..c043cb5 Binary files /dev/null and b/d1/assets/textures/misc062b_1_emissive.png differ diff --git a/d1/assets/textures/misc062b_2.material b/d1/assets/textures/misc062b_2.material new file mode 100644 index 0000000..69e46c1 --- /dev/null +++ b/d1/assets/textures/misc062b_2.material @@ -0,0 +1,3 @@ +albedo_texture = blown07_basecolor.png +metalness_texture = blown07_metallic.png +roughness_texture = blown07_roughness.png diff --git a/d1/assets/textures/misc062b_2_emissive.png b/d1/assets/textures/misc062b_2_emissive.png new file mode 100644 index 0000000..1d6c523 Binary files /dev/null and b/d1/assets/textures/misc062b_2_emissive.png differ diff --git a/d1/assets/textures/misc062d_0.material b/d1/assets/textures/misc062d_0.material new file mode 100644 index 0000000..79aae47 --- /dev/null +++ b/d1/assets/textures/misc062d_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc062_basecolor.png +metalness_texture = misc062_metallic.png +roughness_texture = misc062_roughness.png diff --git a/d1/assets/textures/misc062d_0_emissive.png b/d1/assets/textures/misc062d_0_emissive.png new file mode 100644 index 0000000..cd13621 Binary files /dev/null and b/d1/assets/textures/misc062d_0_emissive.png differ diff --git a/d1/assets/textures/misc062d_1.material b/d1/assets/textures/misc062d_1.material new file mode 100644 index 0000000..79aae47 --- /dev/null +++ b/d1/assets/textures/misc062d_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc062_basecolor.png +metalness_texture = misc062_metallic.png +roughness_texture = misc062_roughness.png diff --git a/d1/assets/textures/misc062d_1_emissive.png b/d1/assets/textures/misc062d_1_emissive.png new file mode 100644 index 0000000..db7d885 Binary files /dev/null and b/d1/assets/textures/misc062d_1_emissive.png differ diff --git a/d1/assets/textures/misc062d_2.material b/d1/assets/textures/misc062d_2.material new file mode 100644 index 0000000..79aae47 --- /dev/null +++ b/d1/assets/textures/misc062d_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc062_basecolor.png +metalness_texture = misc062_metallic.png +roughness_texture = misc062_roughness.png diff --git a/d1/assets/textures/misc062d_2_emissive.png b/d1/assets/textures/misc062d_2_emissive.png new file mode 100644 index 0000000..b2745c6 Binary files /dev/null and b/d1/assets/textures/misc062d_2_emissive.png differ diff --git a/d1/assets/textures/misc063.material b/d1/assets/textures/misc063.material new file mode 100644 index 0000000..542cfcb --- /dev/null +++ b/d1/assets/textures/misc063.material @@ -0,0 +1 @@ +metalness = 1.0 diff --git a/d1/assets/textures/misc063_normal.png b/d1/assets/textures/misc063_normal.png new file mode 100644 index 0000000..80a3628 Binary files /dev/null and b/d1/assets/textures/misc063_normal.png differ diff --git a/d1/assets/textures/misc063_roughness.png b/d1/assets/textures/misc063_roughness.png new file mode 100644 index 0000000..99cc858 Binary files /dev/null and b/d1/assets/textures/misc063_roughness.png differ diff --git a/d1/assets/textures/misc065_0.material b/d1/assets/textures/misc065_0.material new file mode 100644 index 0000000..c9fa3ec --- /dev/null +++ b/d1/assets/textures/misc065_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc065_basecolor.png +metalness_texture = misc065_metallic.png +roughness_texture = misc065_roughness.png diff --git a/d1/assets/textures/misc065_0_emissive.png b/d1/assets/textures/misc065_0_emissive.png new file mode 100644 index 0000000..9101f8d Binary files /dev/null and b/d1/assets/textures/misc065_0_emissive.png differ diff --git a/d1/assets/textures/misc065_1.material b/d1/assets/textures/misc065_1.material new file mode 100644 index 0000000..c9fa3ec --- /dev/null +++ b/d1/assets/textures/misc065_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc065_basecolor.png +metalness_texture = misc065_metallic.png +roughness_texture = misc065_roughness.png diff --git a/d1/assets/textures/misc065_1_emissive.png b/d1/assets/textures/misc065_1_emissive.png new file mode 100644 index 0000000..9101f8d Binary files /dev/null and b/d1/assets/textures/misc065_1_emissive.png differ diff --git a/d1/assets/textures/misc065_2.material b/d1/assets/textures/misc065_2.material new file mode 100644 index 0000000..c9fa3ec --- /dev/null +++ b/d1/assets/textures/misc065_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc065_basecolor.png +metalness_texture = misc065_metallic.png +roughness_texture = misc065_roughness.png diff --git a/d1/assets/textures/misc065_2_emissive.png b/d1/assets/textures/misc065_2_emissive.png new file mode 100644 index 0000000..ef4d9d2 Binary files /dev/null and b/d1/assets/textures/misc065_2_emissive.png differ diff --git a/d1/assets/textures/misc065_3.material b/d1/assets/textures/misc065_3.material new file mode 100644 index 0000000..c9fa3ec --- /dev/null +++ b/d1/assets/textures/misc065_3.material @@ -0,0 +1,3 @@ +albedo_texture = misc065_basecolor.png +metalness_texture = misc065_metallic.png +roughness_texture = misc065_roughness.png diff --git a/d1/assets/textures/misc065_3_emissive.png b/d1/assets/textures/misc065_3_emissive.png new file mode 100644 index 0000000..c3f8427 Binary files /dev/null and b/d1/assets/textures/misc065_3_emissive.png differ diff --git a/d1/assets/textures/misc065_4.material b/d1/assets/textures/misc065_4.material new file mode 100644 index 0000000..c9fa3ec --- /dev/null +++ b/d1/assets/textures/misc065_4.material @@ -0,0 +1,3 @@ +albedo_texture = misc065_basecolor.png +metalness_texture = misc065_metallic.png +roughness_texture = misc065_roughness.png diff --git a/d1/assets/textures/misc065_4_emissive.png b/d1/assets/textures/misc065_4_emissive.png new file mode 100644 index 0000000..337058a Binary files /dev/null and b/d1/assets/textures/misc065_4_emissive.png differ diff --git a/d1/assets/textures/misc065_5.material b/d1/assets/textures/misc065_5.material new file mode 100644 index 0000000..c9fa3ec --- /dev/null +++ b/d1/assets/textures/misc065_5.material @@ -0,0 +1,3 @@ +albedo_texture = misc065_basecolor.png +metalness_texture = misc065_metallic.png +roughness_texture = misc065_roughness.png diff --git a/d1/assets/textures/misc065_5_emissive.png b/d1/assets/textures/misc065_5_emissive.png new file mode 100644 index 0000000..2945b2c Binary files /dev/null and b/d1/assets/textures/misc065_5_emissive.png differ diff --git a/d1/assets/textures/misc065_6.material b/d1/assets/textures/misc065_6.material new file mode 100644 index 0000000..c9fa3ec --- /dev/null +++ b/d1/assets/textures/misc065_6.material @@ -0,0 +1,3 @@ +albedo_texture = misc065_basecolor.png +metalness_texture = misc065_metallic.png +roughness_texture = misc065_roughness.png diff --git a/d1/assets/textures/misc065_6_emissive.png b/d1/assets/textures/misc065_6_emissive.png new file mode 100644 index 0000000..2df1450 Binary files /dev/null and b/d1/assets/textures/misc065_6_emissive.png differ diff --git a/d1/assets/textures/misc065_basecolor.png b/d1/assets/textures/misc065_basecolor.png new file mode 100644 index 0000000..896f38a Binary files /dev/null and b/d1/assets/textures/misc065_basecolor.png differ diff --git a/d1/assets/textures/misc065_metallic.png b/d1/assets/textures/misc065_metallic.png new file mode 100644 index 0000000..456e220 Binary files /dev/null and b/d1/assets/textures/misc065_metallic.png differ diff --git a/d1/assets/textures/misc065_roughness.png b/d1/assets/textures/misc065_roughness.png new file mode 100644 index 0000000..a775894 Binary files /dev/null and b/d1/assets/textures/misc065_roughness.png differ diff --git a/d1/assets/textures/misc065b_0.material b/d1/assets/textures/misc065b_0.material new file mode 100644 index 0000000..c7de063 --- /dev/null +++ b/d1/assets/textures/misc065b_0.material @@ -0,0 +1,3 @@ +albedo_texture = blown03_basecolor.png +metalness_texture = blown03_metallic.png +roughness_texture = blown03_roughness.png diff --git a/d1/assets/textures/misc065b_0_emissive.png b/d1/assets/textures/misc065b_0_emissive.png new file mode 100644 index 0000000..6775b97 Binary files /dev/null and b/d1/assets/textures/misc065b_0_emissive.png differ diff --git a/d1/assets/textures/misc065b_1.material b/d1/assets/textures/misc065b_1.material new file mode 100644 index 0000000..c7de063 --- /dev/null +++ b/d1/assets/textures/misc065b_1.material @@ -0,0 +1,3 @@ +albedo_texture = blown03_basecolor.png +metalness_texture = blown03_metallic.png +roughness_texture = blown03_roughness.png diff --git a/d1/assets/textures/misc065b_1_emissive.png b/d1/assets/textures/misc065b_1_emissive.png new file mode 100644 index 0000000..e417a5d Binary files /dev/null and b/d1/assets/textures/misc065b_1_emissive.png differ diff --git a/d1/assets/textures/misc065b_2.material b/d1/assets/textures/misc065b_2.material new file mode 100644 index 0000000..c7de063 --- /dev/null +++ b/d1/assets/textures/misc065b_2.material @@ -0,0 +1,3 @@ +albedo_texture = blown03_basecolor.png +metalness_texture = blown03_metallic.png +roughness_texture = blown03_roughness.png diff --git a/d1/assets/textures/misc065b_2_emissive.png b/d1/assets/textures/misc065b_2_emissive.png new file mode 100644 index 0000000..ab44e86 Binary files /dev/null and b/d1/assets/textures/misc065b_2_emissive.png differ diff --git a/d1/assets/textures/misc065d_0.material b/d1/assets/textures/misc065d_0.material new file mode 100644 index 0000000..c9fa3ec --- /dev/null +++ b/d1/assets/textures/misc065d_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc065_basecolor.png +metalness_texture = misc065_metallic.png +roughness_texture = misc065_roughness.png diff --git a/d1/assets/textures/misc065d_0_emissive.png b/d1/assets/textures/misc065d_0_emissive.png new file mode 100644 index 0000000..3e77bdb Binary files /dev/null and b/d1/assets/textures/misc065d_0_emissive.png differ diff --git a/d1/assets/textures/misc065d_1.material b/d1/assets/textures/misc065d_1.material new file mode 100644 index 0000000..c9fa3ec --- /dev/null +++ b/d1/assets/textures/misc065d_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc065_basecolor.png +metalness_texture = misc065_metallic.png +roughness_texture = misc065_roughness.png diff --git a/d1/assets/textures/misc065d_1_emissive.png b/d1/assets/textures/misc065d_1_emissive.png new file mode 100644 index 0000000..482abc9 Binary files /dev/null and b/d1/assets/textures/misc065d_1_emissive.png differ diff --git a/d1/assets/textures/misc065d_2.material b/d1/assets/textures/misc065d_2.material new file mode 100644 index 0000000..c9fa3ec --- /dev/null +++ b/d1/assets/textures/misc065d_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc065_basecolor.png +metalness_texture = misc065_metallic.png +roughness_texture = misc065_roughness.png diff --git a/d1/assets/textures/misc065d_2_emissive.png b/d1/assets/textures/misc065d_2_emissive.png new file mode 100644 index 0000000..2837ff6 Binary files /dev/null and b/d1/assets/textures/misc065d_2_emissive.png differ diff --git a/d1/assets/textures/misc066_0.material b/d1/assets/textures/misc066_0.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc066_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc066_0_emissive.png b/d1/assets/textures/misc066_0_emissive.png new file mode 100644 index 0000000..dd3bd9b Binary files /dev/null and b/d1/assets/textures/misc066_0_emissive.png differ diff --git a/d1/assets/textures/misc066_1.material b/d1/assets/textures/misc066_1.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc066_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc066_1_emissive.png b/d1/assets/textures/misc066_1_emissive.png new file mode 100644 index 0000000..dd3bd9b Binary files /dev/null and b/d1/assets/textures/misc066_1_emissive.png differ diff --git a/d1/assets/textures/misc066_2.material b/d1/assets/textures/misc066_2.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc066_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc066_2_emissive.png b/d1/assets/textures/misc066_2_emissive.png new file mode 100644 index 0000000..30b2f0c Binary files /dev/null and b/d1/assets/textures/misc066_2_emissive.png differ diff --git a/d1/assets/textures/misc066_3.material b/d1/assets/textures/misc066_3.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc066_3.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc066_3_emissive.png b/d1/assets/textures/misc066_3_emissive.png new file mode 100644 index 0000000..472c22f Binary files /dev/null and b/d1/assets/textures/misc066_3_emissive.png differ diff --git a/d1/assets/textures/misc066_4.material b/d1/assets/textures/misc066_4.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc066_4.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc066_4_emissive.png b/d1/assets/textures/misc066_4_emissive.png new file mode 100644 index 0000000..88d46b5 Binary files /dev/null and b/d1/assets/textures/misc066_4_emissive.png differ diff --git a/d1/assets/textures/misc066_5.material b/d1/assets/textures/misc066_5.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc066_5.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc066_5_emissive.png b/d1/assets/textures/misc066_5_emissive.png new file mode 100644 index 0000000..560f460 Binary files /dev/null and b/d1/assets/textures/misc066_5_emissive.png differ diff --git a/d1/assets/textures/misc066_6.material b/d1/assets/textures/misc066_6.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc066_6.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc066_6_emissive.png b/d1/assets/textures/misc066_6_emissive.png new file mode 100644 index 0000000..4dfd292 Binary files /dev/null and b/d1/assets/textures/misc066_6_emissive.png differ diff --git a/d1/assets/textures/misc066_7.material b/d1/assets/textures/misc066_7.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc066_7.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc066_7_emissive.png b/d1/assets/textures/misc066_7_emissive.png new file mode 100644 index 0000000..90b32a5 Binary files /dev/null and b/d1/assets/textures/misc066_7_emissive.png differ diff --git a/d1/assets/textures/misc066_8.material b/d1/assets/textures/misc066_8.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc066_8.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc066_8_emissive.png b/d1/assets/textures/misc066_8_emissive.png new file mode 100644 index 0000000..dfa4211 Binary files /dev/null and b/d1/assets/textures/misc066_8_emissive.png differ diff --git a/d1/assets/textures/misc066_basecolor.png b/d1/assets/textures/misc066_basecolor.png new file mode 100644 index 0000000..915bb15 Binary files /dev/null and b/d1/assets/textures/misc066_basecolor.png differ diff --git a/d1/assets/textures/misc066_metallic.png b/d1/assets/textures/misc066_metallic.png new file mode 100644 index 0000000..20731d6 Binary files /dev/null and b/d1/assets/textures/misc066_metallic.png differ diff --git a/d1/assets/textures/misc066_roughness.png b/d1/assets/textures/misc066_roughness.png new file mode 100644 index 0000000..9b1d2b1 Binary files /dev/null and b/d1/assets/textures/misc066_roughness.png differ diff --git a/d1/assets/textures/misc066b_0.material b/d1/assets/textures/misc066b_0.material new file mode 100644 index 0000000..ad2f179 --- /dev/null +++ b/d1/assets/textures/misc066b_0.material @@ -0,0 +1,3 @@ +albedo_texture = blown04_basecolor.png +metalness_texture = blown04_metallic.png +roughness_texture = blown04_roughness.png diff --git a/d1/assets/textures/misc066b_0_emissive.png b/d1/assets/textures/misc066b_0_emissive.png new file mode 100644 index 0000000..041bd91 Binary files /dev/null and b/d1/assets/textures/misc066b_0_emissive.png differ diff --git a/d1/assets/textures/misc066b_1.material b/d1/assets/textures/misc066b_1.material new file mode 100644 index 0000000..ad2f179 --- /dev/null +++ b/d1/assets/textures/misc066b_1.material @@ -0,0 +1,3 @@ +albedo_texture = blown04_basecolor.png +metalness_texture = blown04_metallic.png +roughness_texture = blown04_roughness.png diff --git a/d1/assets/textures/misc066b_1_emissive.png b/d1/assets/textures/misc066b_1_emissive.png new file mode 100644 index 0000000..b8c389d Binary files /dev/null and b/d1/assets/textures/misc066b_1_emissive.png differ diff --git a/d1/assets/textures/misc066b_2.material b/d1/assets/textures/misc066b_2.material new file mode 100644 index 0000000..ad2f179 --- /dev/null +++ b/d1/assets/textures/misc066b_2.material @@ -0,0 +1,3 @@ +albedo_texture = blown04_basecolor.png +metalness_texture = blown04_metallic.png +roughness_texture = blown04_roughness.png diff --git a/d1/assets/textures/misc066b_2_emissive.png b/d1/assets/textures/misc066b_2_emissive.png new file mode 100644 index 0000000..13df3ba Binary files /dev/null and b/d1/assets/textures/misc066b_2_emissive.png differ diff --git a/d1/assets/textures/misc066d_0.material b/d1/assets/textures/misc066d_0.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc066d_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc066d_0_emissive.png b/d1/assets/textures/misc066d_0_emissive.png new file mode 100644 index 0000000..94278ee Binary files /dev/null and b/d1/assets/textures/misc066d_0_emissive.png differ diff --git a/d1/assets/textures/misc066d_1.material b/d1/assets/textures/misc066d_1.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc066d_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc066d_1_emissive.png b/d1/assets/textures/misc066d_1_emissive.png new file mode 100644 index 0000000..b504670 Binary files /dev/null and b/d1/assets/textures/misc066d_1_emissive.png differ diff --git a/d1/assets/textures/misc066d_2.material b/d1/assets/textures/misc066d_2.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc066d_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc066d_2_emissive.png b/d1/assets/textures/misc066d_2_emissive.png new file mode 100644 index 0000000..3c4fdac Binary files /dev/null and b/d1/assets/textures/misc066d_2_emissive.png differ diff --git a/d1/assets/textures/misc066d_3.material b/d1/assets/textures/misc066d_3.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc066d_3.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc066d_3_emissive.png b/d1/assets/textures/misc066d_3_emissive.png new file mode 100644 index 0000000..ed1825b Binary files /dev/null and b/d1/assets/textures/misc066d_3_emissive.png differ diff --git a/d1/assets/textures/misc067_0.material b/d1/assets/textures/misc067_0.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc067_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc067_0_emissive.png b/d1/assets/textures/misc067_0_emissive.png new file mode 100644 index 0000000..ac2e17c Binary files /dev/null and b/d1/assets/textures/misc067_0_emissive.png differ diff --git a/d1/assets/textures/misc067_1.material b/d1/assets/textures/misc067_1.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc067_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc067_1_emissive.png b/d1/assets/textures/misc067_1_emissive.png new file mode 100644 index 0000000..06c8f88 Binary files /dev/null and b/d1/assets/textures/misc067_1_emissive.png differ diff --git a/d1/assets/textures/misc067_2.material b/d1/assets/textures/misc067_2.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc067_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc067_2_emissive.png b/d1/assets/textures/misc067_2_emissive.png new file mode 100644 index 0000000..c9e8b48 Binary files /dev/null and b/d1/assets/textures/misc067_2_emissive.png differ diff --git a/d1/assets/textures/misc067_3.material b/d1/assets/textures/misc067_3.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc067_3.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc067_3_emissive.png b/d1/assets/textures/misc067_3_emissive.png new file mode 100644 index 0000000..17d838b Binary files /dev/null and b/d1/assets/textures/misc067_3_emissive.png differ diff --git a/d1/assets/textures/misc067_4.material b/d1/assets/textures/misc067_4.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc067_4.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc067_4_emissive.png b/d1/assets/textures/misc067_4_emissive.png new file mode 100644 index 0000000..396386e Binary files /dev/null and b/d1/assets/textures/misc067_4_emissive.png differ diff --git a/d1/assets/textures/misc067_5.material b/d1/assets/textures/misc067_5.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc067_5.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc067_5_emissive.png b/d1/assets/textures/misc067_5_emissive.png new file mode 100644 index 0000000..ac70c59 Binary files /dev/null and b/d1/assets/textures/misc067_5_emissive.png differ diff --git a/d1/assets/textures/misc067_6.material b/d1/assets/textures/misc067_6.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc067_6.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc067_6_emissive.png b/d1/assets/textures/misc067_6_emissive.png new file mode 100644 index 0000000..47b5566 Binary files /dev/null and b/d1/assets/textures/misc067_6_emissive.png differ diff --git a/d1/assets/textures/misc067_7.material b/d1/assets/textures/misc067_7.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc067_7.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc067_7_emissive.png b/d1/assets/textures/misc067_7_emissive.png new file mode 100644 index 0000000..7a18777 Binary files /dev/null and b/d1/assets/textures/misc067_7_emissive.png differ diff --git a/d1/assets/textures/misc067_8.material b/d1/assets/textures/misc067_8.material new file mode 100644 index 0000000..52901c8 --- /dev/null +++ b/d1/assets/textures/misc067_8.material @@ -0,0 +1,3 @@ +albedo_texture = misc066_basecolor.png +metalness_texture = misc066_metallic.png +roughness_texture = misc066_roughness.png diff --git a/d1/assets/textures/misc067_8_emissive.png b/d1/assets/textures/misc067_8_emissive.png new file mode 100644 index 0000000..7c6217b Binary files /dev/null and b/d1/assets/textures/misc067_8_emissive.png differ diff --git a/d1/assets/textures/misc068_0.material b/d1/assets/textures/misc068_0.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068_0_emissive.png b/d1/assets/textures/misc068_0_emissive.png new file mode 100644 index 0000000..dcaec96 Binary files /dev/null and b/d1/assets/textures/misc068_0_emissive.png differ diff --git a/d1/assets/textures/misc068_1.material b/d1/assets/textures/misc068_1.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068_10.material b/d1/assets/textures/misc068_10.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068_10.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068_10_emissive.png b/d1/assets/textures/misc068_10_emissive.png new file mode 100644 index 0000000..eb1db25 Binary files /dev/null and b/d1/assets/textures/misc068_10_emissive.png differ diff --git a/d1/assets/textures/misc068_1_emissive.png b/d1/assets/textures/misc068_1_emissive.png new file mode 100644 index 0000000..e2623b8 Binary files /dev/null and b/d1/assets/textures/misc068_1_emissive.png differ diff --git a/d1/assets/textures/misc068_2.material b/d1/assets/textures/misc068_2.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068_2_emissive.png b/d1/assets/textures/misc068_2_emissive.png new file mode 100644 index 0000000..33b96b9 Binary files /dev/null and b/d1/assets/textures/misc068_2_emissive.png differ diff --git a/d1/assets/textures/misc068_3.material b/d1/assets/textures/misc068_3.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068_3.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068_3_emissive.png b/d1/assets/textures/misc068_3_emissive.png new file mode 100644 index 0000000..7d5f009 Binary files /dev/null and b/d1/assets/textures/misc068_3_emissive.png differ diff --git a/d1/assets/textures/misc068_4.material b/d1/assets/textures/misc068_4.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068_4.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068_4_emissive.png b/d1/assets/textures/misc068_4_emissive.png new file mode 100644 index 0000000..a1fbe12 Binary files /dev/null and b/d1/assets/textures/misc068_4_emissive.png differ diff --git a/d1/assets/textures/misc068_5.material b/d1/assets/textures/misc068_5.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068_5.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068_5_emissive.png b/d1/assets/textures/misc068_5_emissive.png new file mode 100644 index 0000000..3a0a43b Binary files /dev/null and b/d1/assets/textures/misc068_5_emissive.png differ diff --git a/d1/assets/textures/misc068_6.material b/d1/assets/textures/misc068_6.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068_6.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068_6_emissive.png b/d1/assets/textures/misc068_6_emissive.png new file mode 100644 index 0000000..8172c3e Binary files /dev/null and b/d1/assets/textures/misc068_6_emissive.png differ diff --git a/d1/assets/textures/misc068_7.material b/d1/assets/textures/misc068_7.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068_7.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068_7_emissive.png b/d1/assets/textures/misc068_7_emissive.png new file mode 100644 index 0000000..ea420da Binary files /dev/null and b/d1/assets/textures/misc068_7_emissive.png differ diff --git a/d1/assets/textures/misc068_8.material b/d1/assets/textures/misc068_8.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068_8.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068_8_emissive.png b/d1/assets/textures/misc068_8_emissive.png new file mode 100644 index 0000000..0d36522 Binary files /dev/null and b/d1/assets/textures/misc068_8_emissive.png differ diff --git a/d1/assets/textures/misc068_9.material b/d1/assets/textures/misc068_9.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068_9.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068_9_emissive.png b/d1/assets/textures/misc068_9_emissive.png new file mode 100644 index 0000000..03f4e68 Binary files /dev/null and b/d1/assets/textures/misc068_9_emissive.png differ diff --git a/d1/assets/textures/misc068_basecolor.png b/d1/assets/textures/misc068_basecolor.png new file mode 100644 index 0000000..4875b8c Binary files /dev/null and b/d1/assets/textures/misc068_basecolor.png differ diff --git a/d1/assets/textures/misc068_metallic.png b/d1/assets/textures/misc068_metallic.png new file mode 100644 index 0000000..5d3a32e Binary files /dev/null and b/d1/assets/textures/misc068_metallic.png differ diff --git a/d1/assets/textures/misc068_roughness.png b/d1/assets/textures/misc068_roughness.png new file mode 100644 index 0000000..a94e4a0 Binary files /dev/null and b/d1/assets/textures/misc068_roughness.png differ diff --git a/d1/assets/textures/misc068b_0.material b/d1/assets/textures/misc068b_0.material new file mode 100644 index 0000000..e309169 --- /dev/null +++ b/d1/assets/textures/misc068b_0.material @@ -0,0 +1,3 @@ +albedo_texture = blown05_basecolor.png +metalness_texture = blown05_metallic.png +roughness_texture = blown05_roughness.png diff --git a/d1/assets/textures/misc068b_0_emissive.png b/d1/assets/textures/misc068b_0_emissive.png new file mode 100644 index 0000000..82c4551 Binary files /dev/null and b/d1/assets/textures/misc068b_0_emissive.png differ diff --git a/d1/assets/textures/misc068b_1.material b/d1/assets/textures/misc068b_1.material new file mode 100644 index 0000000..e309169 --- /dev/null +++ b/d1/assets/textures/misc068b_1.material @@ -0,0 +1,3 @@ +albedo_texture = blown05_basecolor.png +metalness_texture = blown05_metallic.png +roughness_texture = blown05_roughness.png diff --git a/d1/assets/textures/misc068b_1_emissive.png b/d1/assets/textures/misc068b_1_emissive.png new file mode 100644 index 0000000..794979d Binary files /dev/null and b/d1/assets/textures/misc068b_1_emissive.png differ diff --git a/d1/assets/textures/misc068b_2.material b/d1/assets/textures/misc068b_2.material new file mode 100644 index 0000000..e309169 --- /dev/null +++ b/d1/assets/textures/misc068b_2.material @@ -0,0 +1,3 @@ +albedo_texture = blown05_basecolor.png +metalness_texture = blown05_metallic.png +roughness_texture = blown05_roughness.png diff --git a/d1/assets/textures/misc068b_2_emissive.png b/d1/assets/textures/misc068b_2_emissive.png new file mode 100644 index 0000000..c17e40a Binary files /dev/null and b/d1/assets/textures/misc068b_2_emissive.png differ diff --git a/d1/assets/textures/misc068b_3.material b/d1/assets/textures/misc068b_3.material new file mode 100644 index 0000000..e309169 --- /dev/null +++ b/d1/assets/textures/misc068b_3.material @@ -0,0 +1,3 @@ +albedo_texture = blown05_basecolor.png +metalness_texture = blown05_metallic.png +roughness_texture = blown05_roughness.png diff --git a/d1/assets/textures/misc068b_3_emissive.png b/d1/assets/textures/misc068b_3_emissive.png new file mode 100644 index 0000000..06804e7 Binary files /dev/null and b/d1/assets/textures/misc068b_3_emissive.png differ diff --git a/d1/assets/textures/misc068d_0.material b/d1/assets/textures/misc068d_0.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068d_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068d_0_emissive.png b/d1/assets/textures/misc068d_0_emissive.png new file mode 100644 index 0000000..dd03561 Binary files /dev/null and b/d1/assets/textures/misc068d_0_emissive.png differ diff --git a/d1/assets/textures/misc068d_1.material b/d1/assets/textures/misc068d_1.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068d_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068d_1_emissive.png b/d1/assets/textures/misc068d_1_emissive.png new file mode 100644 index 0000000..759f0d4 Binary files /dev/null and b/d1/assets/textures/misc068d_1_emissive.png differ diff --git a/d1/assets/textures/misc068d_2.material b/d1/assets/textures/misc068d_2.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068d_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068d_2_emissive.png b/d1/assets/textures/misc068d_2_emissive.png new file mode 100644 index 0000000..5f555e2 Binary files /dev/null and b/d1/assets/textures/misc068d_2_emissive.png differ diff --git a/d1/assets/textures/misc068d_3.material b/d1/assets/textures/misc068d_3.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068d_3.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068d_3_emissive.png b/d1/assets/textures/misc068d_3_emissive.png new file mode 100644 index 0000000..b6bca0b Binary files /dev/null and b/d1/assets/textures/misc068d_3_emissive.png differ diff --git a/d1/assets/textures/misc068d_4.material b/d1/assets/textures/misc068d_4.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068d_4.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068d_4_emissive.png b/d1/assets/textures/misc068d_4_emissive.png new file mode 100644 index 0000000..956ca3d Binary files /dev/null and b/d1/assets/textures/misc068d_4_emissive.png differ diff --git a/d1/assets/textures/misc068d_5.material b/d1/assets/textures/misc068d_5.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068d_5.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068d_5_emissive.png b/d1/assets/textures/misc068d_5_emissive.png new file mode 100644 index 0000000..a04b565 Binary files /dev/null and b/d1/assets/textures/misc068d_5_emissive.png differ diff --git a/d1/assets/textures/misc068d_6.material b/d1/assets/textures/misc068d_6.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068d_6.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068d_6_emissive.png b/d1/assets/textures/misc068d_6_emissive.png new file mode 100644 index 0000000..0680566 Binary files /dev/null and b/d1/assets/textures/misc068d_6_emissive.png differ diff --git a/d1/assets/textures/misc068d_7.material b/d1/assets/textures/misc068d_7.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068d_7.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068d_7_emissive.png b/d1/assets/textures/misc068d_7_emissive.png new file mode 100644 index 0000000..c582024 Binary files /dev/null and b/d1/assets/textures/misc068d_7_emissive.png differ diff --git a/d1/assets/textures/misc068d_8.material b/d1/assets/textures/misc068d_8.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068d_8.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068d_8_emissive.png b/d1/assets/textures/misc068d_8_emissive.png new file mode 100644 index 0000000..7a1553f Binary files /dev/null and b/d1/assets/textures/misc068d_8_emissive.png differ diff --git a/d1/assets/textures/misc068d_9.material b/d1/assets/textures/misc068d_9.material new file mode 100644 index 0000000..81b565c --- /dev/null +++ b/d1/assets/textures/misc068d_9.material @@ -0,0 +1,3 @@ +albedo_texture = misc068_basecolor.png +metalness_texture = misc068_metallic.png +roughness_texture = misc068_roughness.png diff --git a/d1/assets/textures/misc068d_9_emissive.png b/d1/assets/textures/misc068d_9_emissive.png new file mode 100644 index 0000000..94e3e1a Binary files /dev/null and b/d1/assets/textures/misc068d_9_emissive.png differ diff --git a/d1/assets/textures/misc069_0.material b/d1/assets/textures/misc069_0.material new file mode 100644 index 0000000..cb03130 --- /dev/null +++ b/d1/assets/textures/misc069_0.material @@ -0,0 +1,3 @@ +albedo_texture = misc069_basecolor.png +metalness_texture = misc069_metallic.png +roughness_texture = misc069_roughness.png diff --git a/d1/assets/textures/misc069_0_emissive.png b/d1/assets/textures/misc069_0_emissive.png new file mode 100644 index 0000000..c263db1 Binary files /dev/null and b/d1/assets/textures/misc069_0_emissive.png differ diff --git a/d1/assets/textures/misc069_1.material b/d1/assets/textures/misc069_1.material new file mode 100644 index 0000000..cb03130 --- /dev/null +++ b/d1/assets/textures/misc069_1.material @@ -0,0 +1,3 @@ +albedo_texture = misc069_basecolor.png +metalness_texture = misc069_metallic.png +roughness_texture = misc069_roughness.png diff --git a/d1/assets/textures/misc069_1_emissive.png b/d1/assets/textures/misc069_1_emissive.png new file mode 100644 index 0000000..5ec304d Binary files /dev/null and b/d1/assets/textures/misc069_1_emissive.png differ diff --git a/d1/assets/textures/misc069_2.material b/d1/assets/textures/misc069_2.material new file mode 100644 index 0000000..cb03130 --- /dev/null +++ b/d1/assets/textures/misc069_2.material @@ -0,0 +1,3 @@ +albedo_texture = misc069_basecolor.png +metalness_texture = misc069_metallic.png +roughness_texture = misc069_roughness.png diff --git a/d1/assets/textures/misc069_2_emissive.png b/d1/assets/textures/misc069_2_emissive.png new file mode 100644 index 0000000..4019337 Binary files /dev/null and b/d1/assets/textures/misc069_2_emissive.png differ diff --git a/d1/assets/textures/misc069_3.material b/d1/assets/textures/misc069_3.material new file mode 100644 index 0000000..cb03130 --- /dev/null +++ b/d1/assets/textures/misc069_3.material @@ -0,0 +1,3 @@ +albedo_texture = misc069_basecolor.png +metalness_texture = misc069_metallic.png +roughness_texture = misc069_roughness.png diff --git a/d1/assets/textures/misc069_3_emissive.png b/d1/assets/textures/misc069_3_emissive.png new file mode 100644 index 0000000..20772a1 Binary files /dev/null and b/d1/assets/textures/misc069_3_emissive.png differ diff --git a/d1/assets/textures/misc069_4.material b/d1/assets/textures/misc069_4.material new file mode 100644 index 0000000..cb03130 --- /dev/null +++ b/d1/assets/textures/misc069_4.material @@ -0,0 +1,3 @@ +albedo_texture = misc069_basecolor.png +metalness_texture = misc069_metallic.png +roughness_texture = misc069_roughness.png diff --git a/d1/assets/textures/misc069_4_emissive.png b/d1/assets/textures/misc069_4_emissive.png new file mode 100644 index 0000000..8578ec7 Binary files /dev/null and b/d1/assets/textures/misc069_4_emissive.png differ diff --git a/d1/assets/textures/misc069_5.material b/d1/assets/textures/misc069_5.material new file mode 100644 index 0000000..cb03130 --- /dev/null +++ b/d1/assets/textures/misc069_5.material @@ -0,0 +1,3 @@ +albedo_texture = misc069_basecolor.png +metalness_texture = misc069_metallic.png +roughness_texture = misc069_roughness.png diff --git a/d1/assets/textures/misc069_5_emissive.png b/d1/assets/textures/misc069_5_emissive.png new file mode 100644 index 0000000..04e6e75 Binary files /dev/null and b/d1/assets/textures/misc069_5_emissive.png differ diff --git a/d1/assets/textures/misc069_6.material b/d1/assets/textures/misc069_6.material new file mode 100644 index 0000000..cb03130 --- /dev/null +++ b/d1/assets/textures/misc069_6.material @@ -0,0 +1,3 @@ +albedo_texture = misc069_basecolor.png +metalness_texture = misc069_metallic.png +roughness_texture = misc069_roughness.png diff --git a/d1/assets/textures/misc069_6_emissive.png b/d1/assets/textures/misc069_6_emissive.png new file mode 100644 index 0000000..4fff469 Binary files /dev/null and b/d1/assets/textures/misc069_6_emissive.png differ diff --git a/d1/assets/textures/misc069_7.material b/d1/assets/textures/misc069_7.material new file mode 100644 index 0000000..cb03130 --- /dev/null +++ b/d1/assets/textures/misc069_7.material @@ -0,0 +1,3 @@ +albedo_texture = misc069_basecolor.png +metalness_texture = misc069_metallic.png +roughness_texture = misc069_roughness.png diff --git a/d1/assets/textures/misc069_7_emissive.png b/d1/assets/textures/misc069_7_emissive.png new file mode 100644 index 0000000..238f9ad Binary files /dev/null and b/d1/assets/textures/misc069_7_emissive.png differ diff --git a/d1/assets/textures/misc069_8.material b/d1/assets/textures/misc069_8.material new file mode 100644 index 0000000..cb03130 --- /dev/null +++ b/d1/assets/textures/misc069_8.material @@ -0,0 +1,3 @@ +albedo_texture = misc069_basecolor.png +metalness_texture = misc069_metallic.png +roughness_texture = misc069_roughness.png diff --git a/d1/assets/textures/misc069_8_emissive.png b/d1/assets/textures/misc069_8_emissive.png new file mode 100644 index 0000000..29cf05d Binary files /dev/null and b/d1/assets/textures/misc069_8_emissive.png differ diff --git a/d1/assets/textures/misc069_9.material b/d1/assets/textures/misc069_9.material new file mode 100644 index 0000000..cb03130 --- /dev/null +++ b/d1/assets/textures/misc069_9.material @@ -0,0 +1,3 @@ +albedo_texture = misc069_basecolor.png +metalness_texture = misc069_metallic.png +roughness_texture = misc069_roughness.png diff --git a/d1/assets/textures/misc069_9_emissive.png b/d1/assets/textures/misc069_9_emissive.png new file mode 100644 index 0000000..b68f0e2 Binary files /dev/null and b/d1/assets/textures/misc069_9_emissive.png differ diff --git a/d1/assets/textures/misc069_basecolor.png b/d1/assets/textures/misc069_basecolor.png new file mode 100644 index 0000000..c2d1e4e Binary files /dev/null and b/d1/assets/textures/misc069_basecolor.png differ diff --git a/d1/assets/textures/misc069_metallic.png b/d1/assets/textures/misc069_metallic.png new file mode 100644 index 0000000..1ca791c Binary files /dev/null and b/d1/assets/textures/misc069_metallic.png differ diff --git a/d1/assets/textures/misc069_roughness.png b/d1/assets/textures/misc069_roughness.png new file mode 100644 index 0000000..7f42704 Binary files /dev/null and b/d1/assets/textures/misc069_roughness.png differ diff --git a/d1/assets/textures/misc14_0_basecolor.png b/d1/assets/textures/misc14_0_basecolor.png new file mode 100644 index 0000000..cdbc2f2 Binary files /dev/null and b/d1/assets/textures/misc14_0_basecolor.png differ diff --git a/d1/assets/textures/misc14_0_emissive.png b/d1/assets/textures/misc14_0_emissive.png new file mode 100644 index 0000000..0eecde4 Binary files /dev/null and b/d1/assets/textures/misc14_0_emissive.png differ diff --git a/d1/assets/textures/misc14_1_basecolor.png b/d1/assets/textures/misc14_1_basecolor.png new file mode 100644 index 0000000..cdbc2f2 Binary files /dev/null and b/d1/assets/textures/misc14_1_basecolor.png differ diff --git a/d1/assets/textures/misc14_1_emissive.png b/d1/assets/textures/misc14_1_emissive.png new file mode 100644 index 0000000..3fe46aa Binary files /dev/null and b/d1/assets/textures/misc14_1_emissive.png differ diff --git a/d1/assets/textures/misc14_2_basecolor.png b/d1/assets/textures/misc14_2_basecolor.png new file mode 100644 index 0000000..cdbc2f2 Binary files /dev/null and b/d1/assets/textures/misc14_2_basecolor.png differ diff --git a/d1/assets/textures/misc14_2_emissive.png b/d1/assets/textures/misc14_2_emissive.png new file mode 100644 index 0000000..4028e85 Binary files /dev/null and b/d1/assets/textures/misc14_2_emissive.png differ diff --git a/d1/assets/textures/misc14_3_basecolor.png b/d1/assets/textures/misc14_3_basecolor.png new file mode 100644 index 0000000..cdbc2f2 Binary files /dev/null and b/d1/assets/textures/misc14_3_basecolor.png differ diff --git a/d1/assets/textures/misc14_3_emissive.png b/d1/assets/textures/misc14_3_emissive.png new file mode 100644 index 0000000..f521040 Binary files /dev/null and b/d1/assets/textures/misc14_3_emissive.png differ diff --git a/d1/assets/textures/misc14_4_basecolor.png b/d1/assets/textures/misc14_4_basecolor.png new file mode 100644 index 0000000..cdbc2f2 Binary files /dev/null and b/d1/assets/textures/misc14_4_basecolor.png differ diff --git a/d1/assets/textures/misc14_4_emissive.png b/d1/assets/textures/misc14_4_emissive.png new file mode 100644 index 0000000..f8b2419 Binary files /dev/null and b/d1/assets/textures/misc14_4_emissive.png differ diff --git a/d1/assets/textures/misc14_5_basecolor.png b/d1/assets/textures/misc14_5_basecolor.png new file mode 100644 index 0000000..cdbc2f2 Binary files /dev/null and b/d1/assets/textures/misc14_5_basecolor.png differ diff --git a/d1/assets/textures/misc14_5_emissive.png b/d1/assets/textures/misc14_5_emissive.png new file mode 100644 index 0000000..f521040 Binary files /dev/null and b/d1/assets/textures/misc14_5_emissive.png differ diff --git a/d1/assets/textures/misc14_6_basecolor.png b/d1/assets/textures/misc14_6_basecolor.png new file mode 100644 index 0000000..cdbc2f2 Binary files /dev/null and b/d1/assets/textures/misc14_6_basecolor.png differ diff --git a/d1/assets/textures/misc14_6_emissive.png b/d1/assets/textures/misc14_6_emissive.png new file mode 100644 index 0000000..4028e85 Binary files /dev/null and b/d1/assets/textures/misc14_6_emissive.png differ diff --git a/d1/assets/textures/misc14_7_basecolor.png b/d1/assets/textures/misc14_7_basecolor.png new file mode 100644 index 0000000..cdbc2f2 Binary files /dev/null and b/d1/assets/textures/misc14_7_basecolor.png differ diff --git a/d1/assets/textures/misc14_7_emissive.png b/d1/assets/textures/misc14_7_emissive.png new file mode 100644 index 0000000..3fe46aa Binary files /dev/null and b/d1/assets/textures/misc14_7_emissive.png differ diff --git a/d1/assets/textures/misc16_0_basecolor.png b/d1/assets/textures/misc16_0_basecolor.png new file mode 100644 index 0000000..00e6f4c Binary files /dev/null and b/d1/assets/textures/misc16_0_basecolor.png differ diff --git a/d1/assets/textures/misc16_0_emissive.png b/d1/assets/textures/misc16_0_emissive.png new file mode 100644 index 0000000..abfa7d4 Binary files /dev/null and b/d1/assets/textures/misc16_0_emissive.png differ diff --git a/d1/assets/textures/misc16_1_basecolor.png b/d1/assets/textures/misc16_1_basecolor.png new file mode 100644 index 0000000..00e6f4c Binary files /dev/null and b/d1/assets/textures/misc16_1_basecolor.png differ diff --git a/d1/assets/textures/misc16_1_emissive.png b/d1/assets/textures/misc16_1_emissive.png new file mode 100644 index 0000000..6dc1cdf Binary files /dev/null and b/d1/assets/textures/misc16_1_emissive.png differ diff --git a/d1/assets/textures/misc16_2_basecolor.png b/d1/assets/textures/misc16_2_basecolor.png new file mode 100644 index 0000000..00e6f4c Binary files /dev/null and b/d1/assets/textures/misc16_2_basecolor.png differ diff --git a/d1/assets/textures/misc16_2_emissive.png b/d1/assets/textures/misc16_2_emissive.png new file mode 100644 index 0000000..54aedd5 Binary files /dev/null and b/d1/assets/textures/misc16_2_emissive.png differ diff --git a/d1/assets/textures/misc16_3_basecolor.png b/d1/assets/textures/misc16_3_basecolor.png new file mode 100644 index 0000000..00e6f4c Binary files /dev/null and b/d1/assets/textures/misc16_3_basecolor.png differ diff --git a/d1/assets/textures/misc16_3_emissive.png b/d1/assets/textures/misc16_3_emissive.png new file mode 100644 index 0000000..a4feb38 Binary files /dev/null and b/d1/assets/textures/misc16_3_emissive.png differ diff --git a/d1/assets/textures/misc16_4_basecolor.png b/d1/assets/textures/misc16_4_basecolor.png new file mode 100644 index 0000000..00e6f4c Binary files /dev/null and b/d1/assets/textures/misc16_4_basecolor.png differ diff --git a/d1/assets/textures/misc16_4_emissive.png b/d1/assets/textures/misc16_4_emissive.png new file mode 100644 index 0000000..26d646d Binary files /dev/null and b/d1/assets/textures/misc16_4_emissive.png differ diff --git a/d1/assets/textures/misc16_5_basecolor.png b/d1/assets/textures/misc16_5_basecolor.png new file mode 100644 index 0000000..00e6f4c Binary files /dev/null and b/d1/assets/textures/misc16_5_basecolor.png differ diff --git a/d1/assets/textures/misc16_5_emissive.png b/d1/assets/textures/misc16_5_emissive.png new file mode 100644 index 0000000..a4feb38 Binary files /dev/null and b/d1/assets/textures/misc16_5_emissive.png differ diff --git a/d1/assets/textures/misc16_6_basecolor.png b/d1/assets/textures/misc16_6_basecolor.png new file mode 100644 index 0000000..00e6f4c Binary files /dev/null and b/d1/assets/textures/misc16_6_basecolor.png differ diff --git a/d1/assets/textures/misc16_6_emissive.png b/d1/assets/textures/misc16_6_emissive.png new file mode 100644 index 0000000..54aedd5 Binary files /dev/null and b/d1/assets/textures/misc16_6_emissive.png differ diff --git a/d1/assets/textures/misc16_7_basecolor.png b/d1/assets/textures/misc16_7_basecolor.png new file mode 100644 index 0000000..00e6f4c Binary files /dev/null and b/d1/assets/textures/misc16_7_basecolor.png differ diff --git a/d1/assets/textures/misc16_7_emissive.png b/d1/assets/textures/misc16_7_emissive.png new file mode 100644 index 0000000..6dc1cdf Binary files /dev/null and b/d1/assets/textures/misc16_7_emissive.png differ diff --git a/d1/assets/textures/misc17_0.material b/d1/assets/textures/misc17_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_0.material +++ b/d1/assets/textures/misc17_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_1.material b/d1/assets/textures/misc17_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_1.material +++ b/d1/assets/textures/misc17_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_10.material b/d1/assets/textures/misc17_10.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_10.material +++ b/d1/assets/textures/misc17_10.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_11.material b/d1/assets/textures/misc17_11.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_11.material +++ b/d1/assets/textures/misc17_11.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_12.material b/d1/assets/textures/misc17_12.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_12.material +++ b/d1/assets/textures/misc17_12.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_13.material b/d1/assets/textures/misc17_13.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_13.material +++ b/d1/assets/textures/misc17_13.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_14.material b/d1/assets/textures/misc17_14.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_14.material +++ b/d1/assets/textures/misc17_14.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_15.material b/d1/assets/textures/misc17_15.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_15.material +++ b/d1/assets/textures/misc17_15.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_2.material b/d1/assets/textures/misc17_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_2.material +++ b/d1/assets/textures/misc17_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_3.material b/d1/assets/textures/misc17_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_3.material +++ b/d1/assets/textures/misc17_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_4.material b/d1/assets/textures/misc17_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_4.material +++ b/d1/assets/textures/misc17_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_5.material b/d1/assets/textures/misc17_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_5.material +++ b/d1/assets/textures/misc17_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_6.material b/d1/assets/textures/misc17_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_6.material +++ b/d1/assets/textures/misc17_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_7.material b/d1/assets/textures/misc17_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_7.material +++ b/d1/assets/textures/misc17_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_8.material b/d1/assets/textures/misc17_8.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_8.material +++ b/d1/assets/textures/misc17_8.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/misc17_9.material b/d1/assets/textures/misc17_9.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/misc17_9.material +++ b/d1/assets/textures/misc17_9.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mmissile_0.material b/d1/assets/textures/mmissile_0.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_0.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_1.material b/d1/assets/textures/mmissile_1.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_1.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_10.material b/d1/assets/textures/mmissile_10.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_10.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_11.material b/d1/assets/textures/mmissile_11.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_11.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_12.material b/d1/assets/textures/mmissile_12.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_12.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_13.material b/d1/assets/textures/mmissile_13.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_13.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_14.material b/d1/assets/textures/mmissile_14.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_14.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_2.material b/d1/assets/textures/mmissile_2.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_2.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_3.material b/d1/assets/textures/mmissile_3.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_3.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_4.material b/d1/assets/textures/mmissile_4.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_4.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_5.material b/d1/assets/textures/mmissile_5.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_5.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_6.material b/d1/assets/textures/mmissile_6.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_6.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_7.material b/d1/assets/textures/mmissile_7.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_7.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_8.material b/d1/assets/textures/mmissile_8.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_8.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mmissile_9.material b/d1/assets/textures/mmissile_9.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/mmissile_9.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/mntr04_0.material b/d1/assets/textures/mntr04_0.material new file mode 100644 index 0000000..6ddde9c --- /dev/null +++ b/d1/assets/textures/mntr04_0.material @@ -0,0 +1,3 @@ +albedo_texture = mntr04_basecolor.png +metalness_texture = mntr04_metallic.png +roughness_texture = mntr04_roughness.png diff --git a/d1/assets/textures/mntr04_0_emissive.png b/d1/assets/textures/mntr04_0_emissive.png new file mode 100644 index 0000000..87cf725 Binary files /dev/null and b/d1/assets/textures/mntr04_0_emissive.png differ diff --git a/d1/assets/textures/mntr04_1.material b/d1/assets/textures/mntr04_1.material new file mode 100644 index 0000000..6ddde9c --- /dev/null +++ b/d1/assets/textures/mntr04_1.material @@ -0,0 +1,3 @@ +albedo_texture = mntr04_basecolor.png +metalness_texture = mntr04_metallic.png +roughness_texture = mntr04_roughness.png diff --git a/d1/assets/textures/mntr04_1_emissive.png b/d1/assets/textures/mntr04_1_emissive.png new file mode 100644 index 0000000..e4ec07b Binary files /dev/null and b/d1/assets/textures/mntr04_1_emissive.png differ diff --git a/d1/assets/textures/mntr04_2.material b/d1/assets/textures/mntr04_2.material new file mode 100644 index 0000000..6ddde9c --- /dev/null +++ b/d1/assets/textures/mntr04_2.material @@ -0,0 +1,3 @@ +albedo_texture = mntr04_basecolor.png +metalness_texture = mntr04_metallic.png +roughness_texture = mntr04_roughness.png diff --git a/d1/assets/textures/mntr04_2_emissive.png b/d1/assets/textures/mntr04_2_emissive.png new file mode 100644 index 0000000..dd74120 Binary files /dev/null and b/d1/assets/textures/mntr04_2_emissive.png differ diff --git a/d1/assets/textures/mntr04_basecolor.png b/d1/assets/textures/mntr04_basecolor.png new file mode 100644 index 0000000..54c6e51 Binary files /dev/null and b/d1/assets/textures/mntr04_basecolor.png differ diff --git a/d1/assets/textures/mntr04_metallic.png b/d1/assets/textures/mntr04_metallic.png new file mode 100644 index 0000000..6a677cf Binary files /dev/null and b/d1/assets/textures/mntr04_metallic.png differ diff --git a/d1/assets/textures/mntr04_roughness.png b/d1/assets/textures/mntr04_roughness.png new file mode 100644 index 0000000..5effba1 Binary files /dev/null and b/d1/assets/textures/mntr04_roughness.png differ diff --git a/d1/assets/textures/mntr04b_0.material b/d1/assets/textures/mntr04b_0.material new file mode 100644 index 0000000..aeca6a6 --- /dev/null +++ b/d1/assets/textures/mntr04b_0.material @@ -0,0 +1,3 @@ +albedo_texture = blown06_basecolor.png +metalness_texture = blown06_metallic.png +roughness_texture = blown06_roughness.png diff --git a/d1/assets/textures/mntr04b_0_emissive.png b/d1/assets/textures/mntr04b_0_emissive.png new file mode 100644 index 0000000..4fed944 Binary files /dev/null and b/d1/assets/textures/mntr04b_0_emissive.png differ diff --git a/d1/assets/textures/mntr04b_1.material b/d1/assets/textures/mntr04b_1.material new file mode 100644 index 0000000..aeca6a6 --- /dev/null +++ b/d1/assets/textures/mntr04b_1.material @@ -0,0 +1,3 @@ +albedo_texture = blown06_basecolor.png +metalness_texture = blown06_metallic.png +roughness_texture = blown06_roughness.png diff --git a/d1/assets/textures/mntr04b_1_emissive.png b/d1/assets/textures/mntr04b_1_emissive.png new file mode 100644 index 0000000..202db6a Binary files /dev/null and b/d1/assets/textures/mntr04b_1_emissive.png differ diff --git a/d1/assets/textures/mntr04b_2.material b/d1/assets/textures/mntr04b_2.material new file mode 100644 index 0000000..aeca6a6 --- /dev/null +++ b/d1/assets/textures/mntr04b_2.material @@ -0,0 +1,3 @@ +albedo_texture = blown06_basecolor.png +metalness_texture = blown06_metallic.png +roughness_texture = blown06_roughness.png diff --git a/d1/assets/textures/mntr04b_2_emissive.png b/d1/assets/textures/mntr04b_2_emissive.png new file mode 100644 index 0000000..f723ada Binary files /dev/null and b/d1/assets/textures/mntr04b_2_emissive.png differ diff --git a/d1/assets/textures/mntr04d_0.material b/d1/assets/textures/mntr04d_0.material new file mode 100644 index 0000000..8074a1a --- /dev/null +++ b/d1/assets/textures/mntr04d_0.material @@ -0,0 +1,3 @@ +albedo_texture = mntr04_basecolor.png +metalness_texture = mntr04_metallic.png +roughness_texture = mntr04_roughness.png diff --git a/d1/assets/textures/mntr04d_0_emissive.png b/d1/assets/textures/mntr04d_0_emissive.png new file mode 100644 index 0000000..994a94a Binary files /dev/null and b/d1/assets/textures/mntr04d_0_emissive.png differ diff --git a/d1/assets/textures/mntr04d_1.material b/d1/assets/textures/mntr04d_1.material new file mode 100644 index 0000000..8074a1a --- /dev/null +++ b/d1/assets/textures/mntr04d_1.material @@ -0,0 +1,3 @@ +albedo_texture = mntr04_basecolor.png +metalness_texture = mntr04_metallic.png +roughness_texture = mntr04_roughness.png diff --git a/d1/assets/textures/mntr04d_1_emissive.png b/d1/assets/textures/mntr04d_1_emissive.png new file mode 100644 index 0000000..9b1130a Binary files /dev/null and b/d1/assets/textures/mntr04d_1_emissive.png differ diff --git a/d1/assets/textures/mntr04d_2.material b/d1/assets/textures/mntr04d_2.material new file mode 100644 index 0000000..8074a1a --- /dev/null +++ b/d1/assets/textures/mntr04d_2.material @@ -0,0 +1,3 @@ +albedo_texture = mntr04_basecolor.png +metalness_texture = mntr04_metallic.png +roughness_texture = mntr04_roughness.png diff --git a/d1/assets/textures/mntr04d_2_emissive.png b/d1/assets/textures/mntr04d_2_emissive.png new file mode 100644 index 0000000..52e3743 Binary files /dev/null and b/d1/assets/textures/mntr04d_2_emissive.png differ diff --git a/d1/assets/textures/mtrl01_0.material b/d1/assets/textures/mtrl01_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_0.material +++ b/d1/assets/textures/mtrl01_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_1.material b/d1/assets/textures/mtrl01_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_1.material +++ b/d1/assets/textures/mtrl01_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_10.material b/d1/assets/textures/mtrl01_10.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_10.material +++ b/d1/assets/textures/mtrl01_10.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_11.material b/d1/assets/textures/mtrl01_11.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_11.material +++ b/d1/assets/textures/mtrl01_11.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_12.material b/d1/assets/textures/mtrl01_12.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_12.material +++ b/d1/assets/textures/mtrl01_12.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_13.material b/d1/assets/textures/mtrl01_13.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_13.material +++ b/d1/assets/textures/mtrl01_13.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_14.material b/d1/assets/textures/mtrl01_14.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_14.material +++ b/d1/assets/textures/mtrl01_14.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_15.material b/d1/assets/textures/mtrl01_15.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_15.material +++ b/d1/assets/textures/mtrl01_15.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_16.material b/d1/assets/textures/mtrl01_16.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_16.material +++ b/d1/assets/textures/mtrl01_16.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_17.material b/d1/assets/textures/mtrl01_17.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_17.material +++ b/d1/assets/textures/mtrl01_17.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_2.material b/d1/assets/textures/mtrl01_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_2.material +++ b/d1/assets/textures/mtrl01_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_3.material b/d1/assets/textures/mtrl01_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_3.material +++ b/d1/assets/textures/mtrl01_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_4.material b/d1/assets/textures/mtrl01_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_4.material +++ b/d1/assets/textures/mtrl01_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_5.material b/d1/assets/textures/mtrl01_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_5.material +++ b/d1/assets/textures/mtrl01_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_6.material b/d1/assets/textures/mtrl01_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_6.material +++ b/d1/assets/textures/mtrl01_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_7.material b/d1/assets/textures/mtrl01_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_7.material +++ b/d1/assets/textures/mtrl01_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_8.material b/d1/assets/textures/mtrl01_8.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_8.material +++ b/d1/assets/textures/mtrl01_8.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl01_9.material b/d1/assets/textures/mtrl01_9.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl01_9.material +++ b/d1/assets/textures/mtrl01_9.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl02_0.material b/d1/assets/textures/mtrl02_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl02_0.material +++ b/d1/assets/textures/mtrl02_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl02_1.material b/d1/assets/textures/mtrl02_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl02_1.material +++ b/d1/assets/textures/mtrl02_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl02_10.material b/d1/assets/textures/mtrl02_10.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl02_10.material +++ b/d1/assets/textures/mtrl02_10.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl02_11.material b/d1/assets/textures/mtrl02_11.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl02_11.material +++ b/d1/assets/textures/mtrl02_11.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl02_2.material b/d1/assets/textures/mtrl02_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl02_2.material +++ b/d1/assets/textures/mtrl02_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl02_3.material b/d1/assets/textures/mtrl02_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl02_3.material +++ b/d1/assets/textures/mtrl02_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl02_4.material b/d1/assets/textures/mtrl02_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl02_4.material +++ b/d1/assets/textures/mtrl02_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl02_5.material b/d1/assets/textures/mtrl02_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl02_5.material +++ b/d1/assets/textures/mtrl02_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl02_6.material b/d1/assets/textures/mtrl02_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl02_6.material +++ b/d1/assets/textures/mtrl02_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl02_7.material b/d1/assets/textures/mtrl02_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl02_7.material +++ b/d1/assets/textures/mtrl02_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl02_8.material b/d1/assets/textures/mtrl02_8.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl02_8.material +++ b/d1/assets/textures/mtrl02_8.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl02_9.material b/d1/assets/textures/mtrl02_9.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl02_9.material +++ b/d1/assets/textures/mtrl02_9.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl03_0.material b/d1/assets/textures/mtrl03_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl03_0.material +++ b/d1/assets/textures/mtrl03_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl03_1.material b/d1/assets/textures/mtrl03_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl03_1.material +++ b/d1/assets/textures/mtrl03_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl03_2.material b/d1/assets/textures/mtrl03_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl03_2.material +++ b/d1/assets/textures/mtrl03_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl03_3.material b/d1/assets/textures/mtrl03_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl03_3.material +++ b/d1/assets/textures/mtrl03_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl03_4.material b/d1/assets/textures/mtrl03_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl03_4.material +++ b/d1/assets/textures/mtrl03_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl03_5.material b/d1/assets/textures/mtrl03_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl03_5.material +++ b/d1/assets/textures/mtrl03_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl03_6.material b/d1/assets/textures/mtrl03_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl03_6.material +++ b/d1/assets/textures/mtrl03_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl03_7.material b/d1/assets/textures/mtrl03_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl03_7.material +++ b/d1/assets/textures/mtrl03_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/mtrl03_8.material b/d1/assets/textures/mtrl03_8.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/mtrl03_8.material +++ b/d1/assets/textures/mtrl03_8.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/muzl02_0.material b/d1/assets/textures/muzl02_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/muzl02_0.material +++ b/d1/assets/textures/muzl02_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/muzl02_1.material b/d1/assets/textures/muzl02_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/muzl02_1.material +++ b/d1/assets/textures/muzl02_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/muzl02_2.material b/d1/assets/textures/muzl02_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/muzl02_2.material +++ b/d1/assets/textures/muzl02_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/muzl03_0.material b/d1/assets/textures/muzl03_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/muzl03_0.material +++ b/d1/assets/textures/muzl03_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/muzl03_1.material b/d1/assets/textures/muzl03_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/muzl03_1.material +++ b/d1/assets/textures/muzl03_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/muzl03_2.material b/d1/assets/textures/muzl03_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/muzl03_2.material +++ b/d1/assets/textures/muzl03_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/muzl05_0.material b/d1/assets/textures/muzl05_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/muzl05_0.material +++ b/d1/assets/textures/muzl05_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/muzl05_1.material b/d1/assets/textures/muzl05_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/muzl05_1.material +++ b/d1/assets/textures/muzl05_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/muzl05_2.material b/d1/assets/textures/muzl05_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/muzl05_2.material +++ b/d1/assets/textures/muzl05_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/muzl06_0.material b/d1/assets/textures/muzl06_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/muzl06_0.material +++ b/d1/assets/textures/muzl06_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/muzl06_1.material b/d1/assets/textures/muzl06_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/muzl06_1.material +++ b/d1/assets/textures/muzl06_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/muzl06_2.material b/d1/assets/textures/muzl06_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/muzl06_2.material +++ b/d1/assets/textures/muzl06_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/plasblob_0.material b/d1/assets/textures/plasblob_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/plasblob_0.material +++ b/d1/assets/textures/plasblob_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/plasblob_1.material b/d1/assets/textures/plasblob_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/plasblob_1.material +++ b/d1/assets/textures/plasblob_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/plasblob_2.material b/d1/assets/textures/plasblob_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/plasblob_2.material +++ b/d1/assets/textures/plasblob_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/plasblob_3.material b/d1/assets/textures/plasblob_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/plasblob_3.material +++ b/d1/assets/textures/plasblob_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/plasblob_4.material b/d1/assets/textures/plasblob_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/plasblob_4.material +++ b/d1/assets/textures/plasblob_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/plasblob_5.material b/d1/assets/textures/plasblob_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/plasblob_5.material +++ b/d1/assets/textures/plasblob_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/plasma_0.material b/d1/assets/textures/plasma_0.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_0.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_1.material b/d1/assets/textures/plasma_1.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_1.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_10.material b/d1/assets/textures/plasma_10.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_10.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_11.material b/d1/assets/textures/plasma_11.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_11.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_12.material b/d1/assets/textures/plasma_12.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_12.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_13.material b/d1/assets/textures/plasma_13.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_13.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_14.material b/d1/assets/textures/plasma_14.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_14.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_2.material b/d1/assets/textures/plasma_2.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_2.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_3.material b/d1/assets/textures/plasma_3.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_3.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_4.material b/d1/assets/textures/plasma_4.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_4.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_5.material b/d1/assets/textures/plasma_5.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_5.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_6.material b/d1/assets/textures/plasma_6.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_6.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_7.material b/d1/assets/textures/plasma_7.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_7.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_8.material b/d1/assets/textures/plasma_8.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_8.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/plasma_9.material b/d1/assets/textures/plasma_9.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/plasma_9.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/pwr01_0.material b/d1/assets/textures/pwr01_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_0.material +++ b/d1/assets/textures/pwr01_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_1.material b/d1/assets/textures/pwr01_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_1.material +++ b/d1/assets/textures/pwr01_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_10.material b/d1/assets/textures/pwr01_10.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_10.material +++ b/d1/assets/textures/pwr01_10.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_11.material b/d1/assets/textures/pwr01_11.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_11.material +++ b/d1/assets/textures/pwr01_11.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_12.material b/d1/assets/textures/pwr01_12.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_12.material +++ b/d1/assets/textures/pwr01_12.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_13.material b/d1/assets/textures/pwr01_13.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_13.material +++ b/d1/assets/textures/pwr01_13.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_14.material b/d1/assets/textures/pwr01_14.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_14.material +++ b/d1/assets/textures/pwr01_14.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_2.material b/d1/assets/textures/pwr01_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_2.material +++ b/d1/assets/textures/pwr01_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_3.material b/d1/assets/textures/pwr01_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_3.material +++ b/d1/assets/textures/pwr01_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_4.material b/d1/assets/textures/pwr01_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_4.material +++ b/d1/assets/textures/pwr01_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_5.material b/d1/assets/textures/pwr01_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_5.material +++ b/d1/assets/textures/pwr01_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_6.material b/d1/assets/textures/pwr01_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_6.material +++ b/d1/assets/textures/pwr01_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_7.material b/d1/assets/textures/pwr01_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_7.material +++ b/d1/assets/textures/pwr01_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_8.material b/d1/assets/textures/pwr01_8.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_8.material +++ b/d1/assets/textures/pwr01_8.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr01_9.material b/d1/assets/textures/pwr01_9.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr01_9.material +++ b/d1/assets/textures/pwr01_9.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr02_0.material b/d1/assets/textures/pwr02_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr02_0.material +++ b/d1/assets/textures/pwr02_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr02_1.material b/d1/assets/textures/pwr02_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr02_1.material +++ b/d1/assets/textures/pwr02_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr02_2.material b/d1/assets/textures/pwr02_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr02_2.material +++ b/d1/assets/textures/pwr02_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr02_3.material b/d1/assets/textures/pwr02_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr02_3.material +++ b/d1/assets/textures/pwr02_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr02_4.material b/d1/assets/textures/pwr02_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr02_4.material +++ b/d1/assets/textures/pwr02_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr02_5.material b/d1/assets/textures/pwr02_5.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr02_5.material +++ b/d1/assets/textures/pwr02_5.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr02_6.material b/d1/assets/textures/pwr02_6.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr02_6.material +++ b/d1/assets/textures/pwr02_6.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/pwr02_7.material b/d1/assets/textures/pwr02_7.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/pwr02_7.material +++ b/d1/assets/textures/pwr02_7.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/quad_0.material b/d1/assets/textures/quad_0.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_0.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_1.material b/d1/assets/textures/quad_1.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_1.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_10.material b/d1/assets/textures/quad_10.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_10.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_11.material b/d1/assets/textures/quad_11.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_11.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_12.material b/d1/assets/textures/quad_12.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_12.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_13.material b/d1/assets/textures/quad_13.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_13.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_14.material b/d1/assets/textures/quad_14.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_14.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_2.material b/d1/assets/textures/quad_2.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_2.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_3.material b/d1/assets/textures/quad_3.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_3.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_4.material b/d1/assets/textures/quad_4.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_4.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_5.material b/d1/assets/textures/quad_5.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_5.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_6.material b/d1/assets/textures/quad_6.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_6.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_7.material b/d1/assets/textures/quad_7.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_7.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_8.material b/d1/assets/textures/quad_8.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_8.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/quad_9.material b/d1/assets/textures/quad_9.material new file mode 100644 index 0000000..5a70408 --- /dev/null +++ b/d1/assets/textures/quad_9.material @@ -0,0 +1,2 @@ +roughness = 0.436000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_0.material b/d1/assets/textures/smissile_0.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_0.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_1.material b/d1/assets/textures/smissile_1.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_1.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_10.material b/d1/assets/textures/smissile_10.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_10.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_11.material b/d1/assets/textures/smissile_11.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_11.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_12.material b/d1/assets/textures/smissile_12.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_12.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_13.material b/d1/assets/textures/smissile_13.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_13.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_14.material b/d1/assets/textures/smissile_14.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_14.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_2.material b/d1/assets/textures/smissile_2.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_2.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_3.material b/d1/assets/textures/smissile_3.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_3.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_4.material b/d1/assets/textures/smissile_4.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_4.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_5.material b/d1/assets/textures/smissile_5.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_5.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_6.material b/d1/assets/textures/smissile_6.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_6.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_7.material b/d1/assets/textures/smissile_7.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_7.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_8.material b/d1/assets/textures/smissile_8.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_8.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/smissile_9.material b/d1/assets/textures/smissile_9.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/smissile_9.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/spark01_0.material b/d1/assets/textures/spark01_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/spark01_0.material +++ b/d1/assets/textures/spark01_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/spark01_1.material b/d1/assets/textures/spark01_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/spark01_1.material +++ b/d1/assets/textures/spark01_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/spark01_2.material b/d1/assets/textures/spark01_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/spark01_2.material +++ b/d1/assets/textures/spark01_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/spark01_3.material b/d1/assets/textures/spark01_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/spark01_3.material +++ b/d1/assets/textures/spark01_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/spark01_4.material b/d1/assets/textures/spark01_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/spark01_4.material +++ b/d1/assets/textures/spark01_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/spark02_0.material b/d1/assets/textures/spark02_0.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark02_0.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark02_1.material b/d1/assets/textures/spark02_1.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark02_1.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark02_2.material b/d1/assets/textures/spark02_2.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark02_2.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark02_3.material b/d1/assets/textures/spark02_3.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark02_3.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark02_4.material b/d1/assets/textures/spark02_4.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark02_4.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark03_0.material b/d1/assets/textures/spark03_0.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark03_0.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark03_1.material b/d1/assets/textures/spark03_1.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark03_1.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark03_2.material b/d1/assets/textures/spark03_2.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark03_2.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark03_3.material b/d1/assets/textures/spark03_3.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark03_3.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark03_4.material b/d1/assets/textures/spark03_4.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark03_4.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark04_0.material b/d1/assets/textures/spark04_0.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark04_0.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark04_1.material b/d1/assets/textures/spark04_1.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark04_1.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark04_2.material b/d1/assets/textures/spark04_2.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark04_2.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark04_3.material b/d1/assets/textures/spark04_3.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark04_3.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark04_4.material b/d1/assets/textures/spark04_4.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/spark04_4.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spark05_0.material b/d1/assets/textures/spark05_0.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/spark05_0.material +++ b/d1/assets/textures/spark05_0.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/spark05_1.material b/d1/assets/textures/spark05_1.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/spark05_1.material +++ b/d1/assets/textures/spark05_1.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/spark05_2.material b/d1/assets/textures/spark05_2.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/spark05_2.material +++ b/d1/assets/textures/spark05_2.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/spark05_3.material b/d1/assets/textures/spark05_3.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/spark05_3.material +++ b/d1/assets/textures/spark05_3.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/spark05_4.material b/d1/assets/textures/spark05_4.material index c1f878f..2ba24d5 100644 --- a/d1/assets/textures/spark05_4.material +++ b/d1/assets/textures/spark05_4.material @@ -1,2 +1,3 @@ blackbody = 1 +no_casting_shadow = 1 emissive_strength = 3.500000 diff --git a/d1/assets/textures/sprdblob.material b/d1/assets/textures/sprdblob.material new file mode 100644 index 0000000..74bea1f --- /dev/null +++ b/d1/assets/textures/sprdblob.material @@ -0,0 +1,2 @@ +blackbody = 1 +no_casting_shadow = 1 diff --git a/d1/assets/textures/spread_0.material b/d1/assets/textures/spread_0.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_0.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_1.material b/d1/assets/textures/spread_1.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_1.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_10.material b/d1/assets/textures/spread_10.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_10.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_11.material b/d1/assets/textures/spread_11.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_11.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_12.material b/d1/assets/textures/spread_12.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_12.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_13.material b/d1/assets/textures/spread_13.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_13.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_14.material b/d1/assets/textures/spread_14.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_14.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_2.material b/d1/assets/textures/spread_2.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_2.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_3.material b/d1/assets/textures/spread_3.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_3.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_4.material b/d1/assets/textures/spread_4.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_4.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_5.material b/d1/assets/textures/spread_5.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_5.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_6.material b/d1/assets/textures/spread_6.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_6.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_7.material b/d1/assets/textures/spread_7.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_7.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_8.material b/d1/assets/textures/spread_8.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_8.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/spread_9.material b/d1/assets/textures/spread_9.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/spread_9.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_0.material b/d1/assets/textures/vammo_0.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_0.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_1.material b/d1/assets/textures/vammo_1.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_1.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_10.material b/d1/assets/textures/vammo_10.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_10.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_11.material b/d1/assets/textures/vammo_11.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_11.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_12.material b/d1/assets/textures/vammo_12.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_12.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_13.material b/d1/assets/textures/vammo_13.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_13.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_14.material b/d1/assets/textures/vammo_14.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_14.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_2.material b/d1/assets/textures/vammo_2.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_2.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_3.material b/d1/assets/textures/vammo_3.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_3.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_4.material b/d1/assets/textures/vammo_4.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_4.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_5.material b/d1/assets/textures/vammo_5.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_5.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_6.material b/d1/assets/textures/vammo_6.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_6.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_7.material b/d1/assets/textures/vammo_7.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_7.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_8.material b/d1/assets/textures/vammo_8.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_8.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vammo_9.material b/d1/assets/textures/vammo_9.material new file mode 100644 index 0000000..0cf457f --- /dev/null +++ b/d1/assets/textures/vammo_9.material @@ -0,0 +1,2 @@ +roughness = 0.424000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_0.material b/d1/assets/textures/vulcan_0.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_0.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_1.material b/d1/assets/textures/vulcan_1.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_1.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_10.material b/d1/assets/textures/vulcan_10.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_10.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_11.material b/d1/assets/textures/vulcan_11.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_11.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_12.material b/d1/assets/textures/vulcan_12.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_12.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_13.material b/d1/assets/textures/vulcan_13.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_13.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_14.material b/d1/assets/textures/vulcan_14.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_14.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_2.material b/d1/assets/textures/vulcan_2.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_2.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_3.material b/d1/assets/textures/vulcan_3.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_3.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_4.material b/d1/assets/textures/vulcan_4.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_4.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_5.material b/d1/assets/textures/vulcan_5.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_5.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_6.material b/d1/assets/textures/vulcan_6.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_6.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_7.material b/d1/assets/textures/vulcan_7.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_7.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_8.material b/d1/assets/textures/vulcan_8.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_8.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/assets/textures/vulcan_9.material b/d1/assets/textures/vulcan_9.material new file mode 100644 index 0000000..9f4d19f --- /dev/null +++ b/d1/assets/textures/vulcan_9.material @@ -0,0 +1,2 @@ +roughness = 0.475000 +metalness = 1.000000 diff --git a/d1/include/gr.h b/d1/include/gr.h index 41fb3f5..b1b29af 100644 --- a/d1/include/gr.h +++ b/d1/include/gr.h @@ -66,6 +66,7 @@ typedef struct _grs_point { #define BM_SVGA15 4 #if defined(OGL) || defined(RT_DX12) #define BM_OGL 5 +#define BM_RGBA8 6 #endif /* def OGL */ #define SM(w,h) ((((u_int32_t)w)<<16)+(((u_int32_t)h)&0xFFFF)) diff --git a/d1/main/bm.c b/d1/main/bm.c index 28e77e1..bfae6ee 100644 --- a/d1/main/bm.c +++ b/d1/main/bm.c @@ -141,7 +141,7 @@ int gamedata_init() RT_InitAllPolyModels(); RT_InitAllBitmaps(); RT_InitglTFModels(); - RT_RaytraceSetSkyColors((RT_Vec3){ 0.1f,0.1f,0.125f }, (RT_Vec3){ 0.1f,0.1f,0.125f }); + RT_RaytraceSetSkyColors((RT_Vec3){ 0.0f,0.0f,0.000f }, (RT_Vec3){ 0.0f,0.0f,0.000f }); #endif return 0; diff --git a/d1/main/controls.c b/d1/main/controls.c index a02a2bb..258cc11 100644 --- a/d1/main/controls.c +++ b/d1/main/controls.c @@ -65,7 +65,6 @@ void read_flying_controls( object * obj ) vm_vec_scale_add2(&obj->mtype.phys_info.thrust,&obj->orient.uvec, Controls.vertical_thrust_time ); } - if (obj->mtype.phys_info.flags & PF_WIGGLE) { fix swiggle; fix_fastsincos(((fix)GameTime64), &swiggle, NULL); diff --git a/d1/main/endlevel.c b/d1/main/endlevel.c index 9b3f5c9..9e83d70 100644 --- a/d1/main/endlevel.c +++ b/d1/main/endlevel.c @@ -66,6 +66,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #include "dx12.h" #include "RTutil.h" #include "Core/Arena.h" +#include "Game/lights.h" #endif #ifdef EDITOR @@ -315,6 +316,12 @@ void start_endlevel_sequence() flash_scale = f1_0; +#ifdef RT_DX12 + g_light_multiplier = g_light_multiplier_default; //Needs to be changed to RTconfig + g_pending_light_update = true; + RT_ResetLightEmission(); +#endif + //init_endlevel(); mine_destroyed=0; @@ -888,6 +895,13 @@ void render_external_scene(fix eye_offset) if (! (p.p3_flags & PF_OVERFLOW)) { Interpolation_method = 0; //gr_bitmapm(f2i(p.p3_sx)-32,f2i(p.p3_sy)-32,satellite_bitmap); +#ifdef RT_DX12 + RT_Vec3 bot = RT_Vec3Fromvms_vector(&p.p3_vec); + RT_Vec3 top = RT_Vec3Fromvms_vector(&top_pnt.p3_vec); + RT_Vec3 mid = RT_Vec3Muls(RT_Vec3Add(bot, top), 0.5f); + //RT_RaytraceRod(RT_MATERIAL_SATELLITE, bot, top, f2fl(SATELLITE_WIDTH)); + RT_RaytraceBillboard(RT_MATERIAL_SATELLITE, (RT_Vec2){ f2fl(SATELLITE_WIDTH), f2fl(SATELLITE_HEIGHT) }, mid, mid); +#endif g3_draw_rod_tmap(satellite_bitmap,&p,SATELLITE_WIDTH,&top_pnt,SATELLITE_WIDTH,lrgb); Interpolation_method = save_im; } @@ -1060,6 +1074,10 @@ void render_endlevel_frame(fix eye_offset) .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); #endif if (Endlevel_sequence < EL_OUTSIDE) @@ -1439,6 +1457,7 @@ void load_endlevel_data(int level_num) // todo(lily): maybe make this compatible with external game textures instead of hardcoding? // todo(lily): does this leak memory? RT_ArenaMemoryScope(&g_thread_arena) { + // Load terrain bitmap const uint32_t* pixels = dx12_load_bitmap_pixel_data(&g_thread_arena, terrain_bitmap); const RT_UploadTextureParams terrain_tex_params = { .format = RT_TextureFormat_RGBA8, @@ -1492,6 +1511,28 @@ void load_endlevel_data(int level_num) satellite_bitmap = &satellite_bm_instance; gr_remap_bitmap_good( satellite_bitmap, pal, iff_transparent_color, -1); +#ifdef RT_DX12 + // todo(lily): maybe make this compatible with external game textures instead of hardcoding? + // todo(lily): does this leak memory? + RT_ArenaMemoryScope(&g_thread_arena) { + // Load satellite bitmap + const uint32_t* pixels = dx12_load_bitmap_pixel_data(&g_thread_arena, satellite_bitmap); + const RT_UploadTextureParams terrain_tex_params = { + .format = RT_TextureFormat_RGBA8, + .height = terrain_bitmap->bm_h, + .width = terrain_bitmap->bm_w, + .name = "satellite texture", + .pixels = pixels, + }; + const RT_Material material_definition = (RT_Material){ + .albedo_texture = RT_UploadTexture(&terrain_tex_params), + .roughness = 1.0f, + .metalness = 0.0f, + .flags = RT_MaterialFlag_BlackbodyRadiator + }; + RT_UpdateMaterial(RT_MATERIAL_SATELLITE, &material_definition); + } +#endif break; } diff --git a/d1/main/game.c b/d1/main/game.c index fa8c858..1e5f86e 100644 --- a/d1/main/game.c +++ b/d1/main/game.c @@ -103,6 +103,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #ifdef RT_DX12 #include "polymodel_viewer.h" #include "globvars.h" +#include "Game/Lights.h" #endif @@ -1012,6 +1013,12 @@ window *game_setup(void) init_gauges(); netplayerinfo_on = 0; +#ifdef RT_DX12 + g_light_multiplier = g_light_multiplier_default; //Needs to be changed to RTconfig + g_pending_light_update = true; + RT_ResetLightEmission(); +#endif + #ifdef EDITOR if (!Cursegp) { @@ -1083,7 +1090,7 @@ int game_handler(window *wind, d_event *event, void *data) if (!((Game_mode & GM_MULTI) && (Newdemo_state != ND_STATE_PLAYBACK))) palette_save(); - + event_toggle_focus(0); key_toggle_repeat(1); break; @@ -1100,6 +1107,7 @@ int game_handler(window *wind, d_event *event, void *data) return ReadControls(event); case EVENT_WINDOW_DRAW: + if (!time_paused) { calc_frame_time(); @@ -1130,6 +1138,9 @@ int game_handler(window *wind, d_event *event, void *data) digi_stop_digi_sounds(); #ifdef RT_DX12 g_rt_enable_debug_menu = false; + + if (g_rt_free_cam_info.g_free_cam_enabled) + RT_DisableFreeCam(); #endif if ( (Newdemo_state == ND_STATE_RECORDING) || (Newdemo_state == ND_STATE_PAUSED) ) newdemo_stop_recording(); @@ -1203,6 +1214,13 @@ void GameProcessFrame(void) fix player_shields = Players[Player_num].shields; int player_was_dead = Player_is_dead; +#ifdef RT_DX12 + if (g_rt_free_cam_info.g_free_cam_enabled) { + object_move_one(&Objects[g_rt_free_cam_info.g_free_cam_obj]); + return; + } +#endif + update_player_stats(); diminish_palette_towards_normal(); // Should leave palette effect up for as long as possible by putting right before render. do_cloak_stuff(); diff --git a/d1/main/gamecntl.c b/d1/main/gamecntl.c index 3029a8e..daa521a 100644 --- a/d1/main/gamecntl.c +++ b/d1/main/gamecntl.c @@ -534,6 +534,17 @@ int HandleSystemKey(int key) { gr_toggle_fullscreen(); } break; + + case KEY_SHIFTED + KEY_ALTED + KEY_F: + { + if (!g_rt_free_cam_info.g_free_cam_enabled) { + RT_EnableFreeCam(); + } + else { + RT_DisableFreeCam(); + } + break; + } #endif KEY_MAC( case KEY_COMMAND+KEY_P: ) @@ -579,8 +590,13 @@ int HandleSystemKey(int key) KEY_MAC(case KEY_COMMAND+KEY_3:) case KEY_F3: - if (!Player_is_dead) + if (!Player_is_dead) { +#ifdef RT_DX12 + if (g_rt_free_cam_info.g_free_cam_enabled) + break; +#endif toggle_cockpit(); + } break; KEY_MAC(case KEY_COMMAND+KEY_5:) @@ -1350,19 +1366,20 @@ int ReadControls(d_event *event) } else { exploding_flag=0; } - if (Player_is_dead && !( (Game_mode & GM_MULTI) && (multi_sending_message[Player_num] || multi_defining_message) )) + if (Player_is_dead && !((Game_mode & GM_MULTI) && (multi_sending_message[Player_num] || multi_defining_message))) { if (HandleDeathInput(event)) { - if( (Game_mode & GM_MULTI) && (Netgame.SpawnStyle == SPAWN_STYLE_PREVIEW) ) { + if ((Game_mode & GM_MULTI) && (Netgame.SpawnStyle == SPAWN_STYLE_PREVIEW)) { // fall through to normal key handler // Make sure flares/shots go in direction of preview ConsoleObject->orient = Dead_player_camera->orient; - } else { + } + else { return 1; } } - + } if (Game_mode & GM_OBSERVER && Newdemo_state < ND_STATE_PLAYBACK) { // Force the observer to a certain camera based on whether they are freely observing or observing a specific player. @@ -1512,6 +1529,11 @@ int ReadControls(d_event *event) } } +#ifdef RT_DX12 + if (g_rt_free_cam_info.g_free_cam_enabled) { + return; + } +#endif do_weapon_n_item_stuff(); } diff --git a/d1/main/gamerend.c b/d1/main/gamerend.c index 9f8a7ec..6c4b719 100644 --- a/d1/main/gamerend.c +++ b/d1/main/gamerend.c @@ -509,8 +509,12 @@ void game_render_frame_mono(int flip) if (Newdemo_state == ND_STATE_PLAYBACK) Game_mode = Newdemo_game_mode; - if (PlayerCfg.CockpitMode[1]==CM_FULL_COCKPIT || PlayerCfg.CockpitMode[1]==CM_STATUS_BAR) + if (PlayerCfg.CockpitMode[1] == CM_FULL_COCKPIT || PlayerCfg.CockpitMode[1] == CM_STATUS_BAR) + render_gauges(); +#ifdef RT_DX12 + if (PlayerCfg.CockpitMode[1] == CM_MODEL_3D) render_gauges(); +#endif if (Newdemo_state == ND_STATE_PLAYBACK) Game_mode = GM_NORMAL | (Game_mode & GM_OBSERVER); @@ -562,6 +566,13 @@ int last_drawn_cockpit = -1; extern void ogl_loadbmtexture(grs_bitmap *bm); // This actually renders the new cockpit onto the screen. +#ifdef OGL +#define UBITMAPM ogl_ubitmapm_cs +#elif RT_DX12 +#define UBITMAPM dx12_ubitmapm_cs +#else +#define UBITMAPM(x, y, dw, dh, bm, c, scale) gr_ubitmapm(x, y, bm) +#endif void update_cockpits() { grs_bitmap *bm; @@ -571,35 +582,17 @@ void update_cockpits() switch( PlayerCfg.CockpitMode[1] ) { case CM_FULL_COCKPIT: gr_set_current_canvas(NULL); -#ifdef OGL - ogl_ubitmapm_cs (0, 0, -1, grd_curcanv->cv_bitmap.bm_h, bm,255, F1_0); -#elif RT_DX12 - dx12_ubitmapm_cs(0, 0, -1, grd_curcanv->cv_bitmap.bm_h, bm, 255, F1_0); -#else - gr_ubitmapm(0,0, bm); -#endif + UBITMAPM(0, 0, -1, grd_curcanv->cv_bitmap.bm_h, bm,255, F1_0); break; case CM_REAR_VIEW: gr_set_current_canvas(NULL); -#ifdef OGL - ogl_ubitmapm_cs (0, 0, -1, grd_curcanv->cv_bitmap.bm_h, bm,255, F1_0); -#elif RT_DX12 - dx12_ubitmapm_cs(0, 0, -1, grd_curcanv->cv_bitmap.bm_h, bm, 255, F1_0); -#else - gr_ubitmapm(0,0, bm); -#endif + UBITMAPM(0, 0, -1, grd_curcanv->cv_bitmap.bm_h, bm,255, F1_0); break; case CM_FULL_SCREEN: break; case CM_STATUS_BAR: gr_set_current_canvas(NULL); -#ifdef OGL - ogl_ubitmapm_cs (0, (HIRESMODE?(SHEIGHT*2)/2.6:(SHEIGHT*2)/2.72), -1, ((int) ((double) (bm->bm_h) * (HIRESMODE?(double)SHEIGHT/480:(double)SHEIGHT/200) + 0.5)), bm,255, F1_0); -#elif RT_DX12 - dx12_ubitmapm_cs(0, (HIRESMODE ? (SHEIGHT * 2) / 2.6 : (SHEIGHT * 2) / 2.72), -1, ((int)((double)(bm->bm_h) * (HIRESMODE ? (double)SHEIGHT / 480 : (double)SHEIGHT / 200) + 0.5)), bm, 255, F1_0); -#else - gr_ubitmapm(0,SHEIGHT-bm->bm_h,bm); -#endif + UBITMAPM(0, (HIRESMODE?(SHEIGHT*2)/2.6:(SHEIGHT*2)/2.72), -1, ((int) ((double) (bm->bm_h) * (HIRESMODE?(double)SHEIGHT/480:(double)SHEIGHT/200) + 0.5)), bm,255, F1_0); break; case CM_LETTERBOX: gr_set_current_canvas(NULL); diff --git a/d1/main/gameseq.c b/d1/main/gameseq.c index 73de166..5d85a62 100644 --- a/d1/main/gameseq.c +++ b/d1/main/gameseq.c @@ -631,7 +631,15 @@ void LoadLevel(int level_num,int page_in_textures) level_name = get_level_file(level_num); if (!load_level(level_name)) - Current_level_num=level_num; + { + Current_level_num = level_num; +#ifdef RT_DX12 + // Unload the previous level acceleration structure, if there is any + RT_UnloadLevel(); + // Load the new level and create the acceleration structure + RT_LoadLevel(); +#endif + } gr_use_palette_table( "palette.256" ); diff --git a/d1/main/gauges.c b/d1/main/gauges.c index 2e25bcf..0c6ceb7 100644 --- a/d1/main/gauges.c +++ b/d1/main/gauges.c @@ -53,10 +53,15 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #ifdef OGL #include "ogl_init.h" #endif +#include "globvars.h" +#include "internal.h" #include "net_udp.h" #ifdef RT_DX12 #include "dx12.h" +#include "Core/Arena.h" +#include "grdef.h" +#include "RTgr.h" #endif //bitmap numbers for gauges @@ -316,12 +321,37 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #define SB_PRIMARY_BOX (!HIRESMODE?2:6) #define SB_SECONDARY_BOX (!HIRESMODE?3:7) +// Let's define all the UI's UV locations here; they're all in the range from 0 to 1023 +#ifdef RT_DX12 +const float pos_red_key[4] = { 829, 22, 928, 96 }; +const float pos_gold_key[4] = { 720, 21, 815, 96 }; +const float pos_blue_key[4] = { 604, 21, 705, 95 }; +const float pos_energy_left[4] = { 175, 120, 1002, 220 }; +const float pos_energy_right[4] = { 175, 231, 1002, 331 }; +const float pos_energy_left_x[2] = { 175, 1002 }; +const float pos_energy_right_x[2] = { 1002, 175 }; +const float pos_energy_left_y[2] = { 120, 220 }; +const float pos_energy_right_y[2] = { 231, 331 }; +const int pos_homing_text[2] = { 214, 13 }; +const RT_Vec2 pos_ship_center = { 227, 806 }; +const float scl_ship = 100; +const float scl_shield = 144; +const float scale_text_homing[2] = { 18, 18 }; +const float scale_text_misc[2] = { 8, 16 }; +const float pos_shield_text[2] = { 226, 532 }; +const float pos_energy_text[2] = { 92, 40 }; +const float pos_text_weapon_primary[2] = { 549, 412 }; +const float pos_text_weapon_secondary[2] = { 701, 764 }; +#endif + // scaling gauges #define BASE_WIDTH (HIRESMODE? 640 : 320) #define BASE_HEIGHT (HIRESMODE? 480 : 200) #if defined(OGL) || defined(RT_DX12) #define HUD_SCALE_X(x) ((int) ((double) (x) * ((double)grd_curscreen->sc_w/BASE_WIDTH) + 0.5)) #define HUD_SCALE_Y(y) ((int) ((double) (y) * ((double)grd_curscreen->sc_h/BASE_HEIGHT) + 0.5)) +#define HUD_SCALE_X_1024(x) ((int) ((double) (x) * ((double)grd_curscreen->sc_w) + 0.5)) +#define HUD_SCALE_Y_1024(y) ((int) ((double) (y) * ((double)grd_curscreen->sc_h) + 0.5)) #define HUD_SCALE_X_AR(x) (HUD_SCALE_X(100) > HUD_SCALE_Y(100) ? HUD_SCALE_Y(x) : HUD_SCALE_X(x)) #define HUD_SCALE_Y_AR(y) (HUD_SCALE_Y(100) > HUD_SCALE_X(100) ? HUD_SCALE_X(y) : HUD_SCALE_Y(y)) #else @@ -1692,20 +1722,34 @@ void draw_keys() } } +#ifdef RT_DX12 +void render_ui_bitmap(bitmap_index bitmap, float x1, float y1, float x2, float y2) { + grs_bitmap* bm = &GameBitmaps[bitmap.index]; + dx12_ubitmapm_cs(x1, y1, (x2 - x1), (y2 - y1), bm, -1, F1_0); +} +#endif void draw_weapon_info_sub(int info_index,gauge_box *box,int pic_x,int pic_y,char *name,int text_x,int text_y) { grs_bitmap *bm; //clear the window - gr_setcolor(BM_XRGB(0,0,0)); - gr_rect(HUD_SCALE_X(box->left),HUD_SCALE_Y(box->top),HUD_SCALE_X(box->right),HUD_SCALE_Y(box->bot+1)); + if (PlayerCfg.CockpitMode[1] != CM_MODEL_3D) { + gr_setcolor(BM_XRGB(0, 0, 0)); + gr_rect(HUD_SCALE_X(box->left), HUD_SCALE_Y(box->top), HUD_SCALE_X(box->right), HUD_SCALE_Y(box->bot + 1)); + } bm=&GameBitmaps[Weapon_info[info_index].picture.index]; Assert(bm != NULL); PIGGY_PAGE_IN( Weapon_info[info_index].picture ); - hud_bitblt(HUD_SCALE_X(pic_x), HUD_SCALE_Y(pic_y), bm); + if (PlayerCfg.CockpitMode[1] == CM_MODEL_3D) { +#ifdef RT_DX12 + render_ui_bitmap(Weapon_info[info_index].picture, pic_x, pic_y, pic_x + bm->bm_w * 6, pic_y + bm->bm_h * 6); +#endif + } + else + hud_bitblt(HUD_SCALE_X(pic_x), HUD_SCALE_Y(pic_y), bm); if (PlayerCfg.HudMode == 0) { @@ -1740,6 +1784,20 @@ void draw_weapon_info(int weapon_type,int weapon_num) x=SB_PRIMARY_AMMO_X; y=SB_PRIMARY_AMMO_Y; } +#ifdef RT_DX12 + else if (PlayerCfg.CockpitMode[1] == CM_MODEL_3D) { + int temp = grd_curcanv->cv_fade_level; + int fade_value = f2i(weapon_box_fade_values[0]); + if (weapon_box_states[0] == WS_SET) + gr_settransblend(GR_FADE_OFF, GR_BLEND_NORMAL); + else + gr_settransblend(fade_value, GR_BLEND_NORMAL); + draw_weapon_info_sub(Primary_weapon_to_weapon_info[weapon_num], &gauge_boxes[COCKPIT_PRIMARY_BOX], 404, 405, PRIMARY_WEAPON_NAMES_SHORT(weapon_num), pos_text_weapon_primary[0], pos_text_weapon_primary[1]); + x = pos_text_weapon_primary[0] + 36; + y = pos_text_weapon_primary[1] + 75; + gr_settransblend(temp, GR_BLEND_NORMAL); + } +#endif else { draw_weapon_info_sub(Primary_weapon_to_weapon_info[weapon_num],&gauge_boxes[COCKPIT_PRIMARY_BOX],PRIMARY_W_PIC_X,PRIMARY_W_PIC_Y, PRIMARY_WEAPON_NAMES_SHORT(weapon_num),PRIMARY_W_TEXT_X,PRIMARY_W_TEXT_Y); @@ -1755,6 +1813,20 @@ void draw_weapon_info(int weapon_type,int weapon_num) x=SB_SECONDARY_AMMO_X; y=SB_SECONDARY_AMMO_Y; } +#ifdef RT_DX12 + else if (PlayerCfg.CockpitMode[1] == CM_MODEL_3D) { + int temp = grd_curcanv->cv_fade_level; + int fade_value = f2i(weapon_box_fade_values[1]); + if (weapon_box_states[1] == WS_SET) + gr_settransblend(GR_FADE_OFF, GR_BLEND_NORMAL); + else + gr_settransblend(fade_value, GR_BLEND_NORMAL); + draw_weapon_info_sub(Secondary_weapon_to_weapon_info[weapon_num], &gauge_boxes[SB_SECONDARY_BOX], 849, 747, SECONDARY_WEAPON_NAMES_SHORT(weapon_num), pos_text_weapon_secondary[0], pos_text_weapon_secondary[1]); + x = pos_text_weapon_secondary[0] + 36; + y = pos_text_weapon_secondary[1] + 75; + gr_settransblend(temp, GR_BLEND_NORMAL); + } +#endif else { draw_weapon_info_sub(Secondary_weapon_to_weapon_info[weapon_num],&gauge_boxes[COCKPIT_SECONDARY_BOX],SECONDARY_W_PIC_X,SECONDARY_W_PIC_Y,SECONDARY_WEAPON_NAMES_SHORT(weapon_num),SECONDARY_W_TEXT_X,SECONDARY_W_TEXT_Y); @@ -1783,6 +1855,8 @@ void draw_primary_ammo_info(int ammo_count) { if (PlayerCfg.CockpitMode[1] == CM_STATUS_BAR) draw_ammo_info(SB_PRIMARY_AMMO_X,SB_PRIMARY_AMMO_Y,ammo_count,1); + else if (PlayerCfg.CockpitMode[1] == CM_MODEL_3D) + draw_ammo_info(549 + 36, 412 + 75, ammo_count, 1); else draw_ammo_info(PRIMARY_AMMO_X,PRIMARY_AMMO_Y,ammo_count,1); } @@ -1791,31 +1865,82 @@ void draw_secondary_ammo_info(int ammo_count) { if (PlayerCfg.CockpitMode[1] == CM_STATUS_BAR) draw_ammo_info(SB_SECONDARY_AMMO_X,SB_SECONDARY_AMMO_Y,ammo_count,0); + else if (PlayerCfg.CockpitMode[1] == CM_MODEL_3D) + draw_ammo_info(701 + 36, 764 + 75, ammo_count, 0); else draw_ammo_info(SECONDARY_AMMO_X,SECONDARY_AMMO_Y,ammo_count,0); } +void draw_weapon_box_hud_3d_cockpit(int weapon_type, int weapon_num) +{ + if (weapon_num != old_weapon[weapon_type] && weapon_box_states[weapon_type] == WS_SET && (old_weapon[weapon_type] != -1) && !PlayerCfg.HudMode) + { + weapon_box_states[weapon_type] = WS_FADING_OUT; + weapon_box_fade_values[weapon_type] = i2f(GR_FADE_LEVELS - 1); + } + + if (old_weapon[weapon_type] == -1) + { + //draw_weapon_info(weapon_type, weapon_num); + old_weapon[weapon_type] = weapon_num; + weapon_box_states[weapon_type] = WS_SET; + } + + if (weapon_box_states[weapon_type] == WS_FADING_OUT) { + //draw_weapon_info(weapon_type, old_weapon[weapon_type]); + weapon_box_fade_values[weapon_type] -= FrameTime * FADE_SCALE; + if (weapon_box_fade_values[weapon_type] <= 0) + { + weapon_box_states[weapon_type] = WS_FADING_IN; + old_weapon[weapon_type] = weapon_num; + old_weapon[weapon_type] = weapon_num; + weapon_box_fade_values[weapon_type] = 0; + } + } + else if (weapon_box_states[weapon_type] == WS_FADING_IN) + { + if (weapon_num != old_weapon[weapon_type]) + { + weapon_box_states[weapon_type] = WS_FADING_OUT; + } + else + { + //draw_weapon_info(weapon_type, weapon_num); + weapon_box_fade_values[weapon_type] += FrameTime * FADE_SCALE; + if (weapon_box_fade_values[weapon_type] >= i2f(GR_FADE_LEVELS - 1)) { + weapon_box_states[weapon_type] = WS_SET; + old_weapon[weapon_type] = -1; + } + } + } + else + { + draw_weapon_info(weapon_type, weapon_num); + old_weapon[weapon_type] = weapon_num; + } +} + void draw_weapon_box(int weapon_type,int weapon_num) { gr_set_current_canvas(NULL); + gr_set_curfont(GAME_FONT); - gr_set_curfont( GAME_FONT ); if (weapon_num != old_weapon[weapon_type] && weapon_box_states[weapon_type] == WS_SET && (old_weapon[weapon_type] != -1) && !PlayerCfg.HudMode) { weapon_box_states[weapon_type] = WS_FADING_OUT; - weapon_box_fade_values[weapon_type]=i2f(GR_FADE_LEVELS-1); + weapon_box_fade_values[weapon_type] = i2f(GR_FADE_LEVELS - 1); } if (old_weapon[weapon_type] == -1) { - draw_weapon_info(weapon_type,weapon_num); + draw_weapon_info(weapon_type, weapon_num); old_weapon[weapon_type] = weapon_num; weapon_box_states[weapon_type] = WS_SET; } if (weapon_box_states[weapon_type] == WS_FADING_OUT) { - draw_weapon_info(weapon_type,old_weapon[weapon_type]); + draw_weapon_info(weapon_type, old_weapon[weapon_type]); weapon_box_fade_values[weapon_type] -= FrameTime * FADE_SCALE; if (weapon_box_fade_values[weapon_type] <= 0) { @@ -1833,9 +1958,9 @@ void draw_weapon_box(int weapon_type,int weapon_num) } else { - draw_weapon_info(weapon_type,weapon_num); + draw_weapon_info(weapon_type, weapon_num); weapon_box_fade_values[weapon_type] += FrameTime * FADE_SCALE; - if (weapon_box_fade_values[weapon_type] >= i2f(GR_FADE_LEVELS-1)) { + if (weapon_box_fade_values[weapon_type] >= i2f(GR_FADE_LEVELS - 1)) { weapon_box_states[weapon_type] = WS_SET; old_weapon[weapon_type] = -1; } @@ -1854,7 +1979,8 @@ void draw_weapon_box(int weapon_type,int weapon_num) int boxofs = (PlayerCfg.CockpitMode[1]==CM_STATUS_BAR)?SB_PRIMARY_BOX:COCKPIT_PRIMARY_BOX; gr_settransblend(fade_value, GR_BLEND_NORMAL); - gr_rect(HUD_SCALE_X(gauge_boxes[boxofs+weapon_type].left),HUD_SCALE_Y(gauge_boxes[boxofs+weapon_type].top),HUD_SCALE_X(gauge_boxes[boxofs+weapon_type].right),HUD_SCALE_Y(gauge_boxes[boxofs+weapon_type].bot)); + if (PlayerCfg.CockpitMode[1] != CM_MODEL_3D) + gr_rect(HUD_SCALE_X(gauge_boxes[boxofs+weapon_type].left),HUD_SCALE_Y(gauge_boxes[boxofs+weapon_type].top),HUD_SCALE_X(gauge_boxes[boxofs+weapon_type].right),HUD_SCALE_Y(gauge_boxes[boxofs+weapon_type].bot)); gr_settransblend(GR_FADE_OFF, GR_BLEND_NORMAL); } @@ -2712,22 +2838,26 @@ void render_gauges() { int energy = f2ir(Players[Player_num].energy); int shields = f2ir(Players[Player_num].shields); - int cloak = ((Players[Player_num].flags&PLAYER_FLAGS_CLOAKED) != 0); + int cloak = ((Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) != 0); - Assert(PlayerCfg.CockpitMode[1]==CM_FULL_COCKPIT || PlayerCfg.CockpitMode[1]==CM_STATUS_BAR); +#ifdef RT_DX12 + Assert(PlayerCfg.CockpitMode[1] == CM_FULL_COCKPIT || PlayerCfg.CockpitMode[1] == CM_STATUS_BAR || PlayerCfg.CockpitMode[1] == CM_MODEL_3D); +#else + Assert(PlayerCfg.CockpitMode[1] == CM_FULL_COCKPIT || PlayerCfg.CockpitMode[1] == CM_STATUS_BAR); +#endif - if (shields < 0 ) shields = 0; + if (shields < 0) shields = 0; gr_set_current_canvas(NULL); - gr_set_curfont( GAME_FONT ); + gr_set_curfont(GAME_FONT); if (Newdemo_state == ND_STATE_RECORDING) if (Players[Player_num].homing_object_dist >= 0) newdemo_record_homing_distance(Players[Player_num].homing_object_dist); - draw_weapon_boxes(); if (PlayerCfg.CockpitMode[1] == CM_FULL_COCKPIT) { + draw_weapon_boxes(); if (Newdemo_state == ND_STATE_RECORDING) newdemo_record_player_energy(energy); @@ -2752,7 +2882,9 @@ void render_gauges() show_homing_warning(); draw_wbu_overlay(); - } else if (PlayerCfg.CockpitMode[1] == CM_STATUS_BAR) { + } + else if (PlayerCfg.CockpitMode[1] == CM_STATUS_BAR) { + draw_weapon_boxes(); if (Newdemo_state == ND_STATE_RECORDING) newdemo_record_player_energy(energy); @@ -2768,7 +2900,7 @@ void render_gauges() sb_draw_shield_bar(shields); sb_draw_shield_num(shields); - if (Newdemo_state==ND_STATE_RECORDING) + if (Newdemo_state == ND_STATE_RECORDING) { newdemo_record_player_shields(shields); newdemo_record_player_flags(Players[Player_num].flags); @@ -2777,7 +2909,7 @@ void render_gauges() sb_show_lives(); - if ((Game_mode&GM_MULTI) && !((Game_mode & GM_MULTI_COOP) || (Game_mode & GM_MULTI_ROBOTS))) + if ((Game_mode & GM_MULTI) && !((Game_mode & GM_MULTI_COOP) || (Game_mode & GM_MULTI_ROBOTS))) { sb_show_score(); } @@ -2786,8 +2918,145 @@ void render_gauges() sb_show_score(); sb_show_score_added(); } - } else + } +#ifdef RT_DX12 + + // If we're using the 3d cockpit model, render every UI element to the cockpit's screen textures + else if (PlayerCfg.CockpitMode[1] == CM_MODEL_3D) { + // note(lily): this might be the most giga scuffed code I've ever written, but don't worry about it :D + const float tmp_x = FNTScaleX; + const float tmp_y = FNTScaleY; + const auto tmp_bm_w = grd_curcanv->cv_bitmap.bm_w; + const auto tmp_bm_h = grd_curcanv->cv_bitmap.bm_h; + const auto tmp_last_width = last_width; + const auto tmp_last_height = last_height; + + grd_curcanv->cv_bitmap.bm_w = 1024; + grd_curcanv->cv_bitmap.bm_h = 1024; + last_width = 1024; + last_height = 1024; + FNTScaleX = 6; + FNTScaleY = 6; + dx12_set_render_target(g_rt_cockpit_settings.cockpit_hud_texture); + RT_RasterSetViewport(0, 0, 1024, 1024); + draw_weapon_boxes(); + + // Now define a silly little macro that expands those positions to 4 parameters + #define PLACE(pos) pos[0], pos[1], pos[2], pos[3] + + // Render keys + if (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY) { + render_ui_bitmap(Gauges[GAUGE_RED_KEY], PLACE(pos_red_key)); + } else { + render_ui_bitmap(Gauges[GAUGE_RED_KEY_OFF], PLACE(pos_red_key)); + } + if (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY) { + render_ui_bitmap(Gauges[GAUGE_GOLD_KEY], PLACE(pos_gold_key)); + } else { + render_ui_bitmap(Gauges[GAUGE_GOLD_KEY_OFF], PLACE(pos_gold_key)); + } + if (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY) { + render_ui_bitmap(Gauges[GAUGE_BLUE_KEY], PLACE(pos_blue_key)); + } else { + render_ui_bitmap(Gauges[GAUGE_BLUE_KEY_OFF], PLACE(pos_blue_key)); + } + + // Render full energy bars + render_ui_bitmap(Gauges[GAUGE_ENERGY_LEFT], PLACE(pos_energy_left)); + render_ui_bitmap(Gauges[GAUGE_ENERGY_RIGHT], PLACE(pos_energy_right)); + + // Hide corners + if (energy < 100) { + // Erase part of energy bar to indicate the actual energy level + const float t = (float)energy / 100.f; + const float right_black_bar_x = RT_Lerp(pos_energy_right_x[1], pos_energy_right_x[0], t); + const float left_black_bar_x = RT_Lerp(pos_energy_left_x[1], pos_energy_left_x[0], t); + const float bar_skew_scalar = RT_Lerp(0.25f, 1.125f, t); + const float right_max_h = pos_energy_right_y[1] - pos_energy_right_y[0]; + const float left_max_h = pos_energy_left_y[1] - pos_energy_left_y[0]; + + const RT_RasterTriVertex verts_right[4] = { + {.pos = {right_black_bar_x - right_max_h * bar_skew_scalar, pos_energy_right_y[0], 0.0f}, .color = {0, 0, 0, 1}}, + {.pos = {pos_energy_right_x[0], pos_energy_right_y[0], 0.0f}, .color = {0, 0, 0, 1}}, + {.pos = {pos_energy_right_x[0], pos_energy_right_y[1], 0.0f}, .color = {0, 0, 0, 1}}, + {.pos = {right_black_bar_x, pos_energy_right_y[1], 0.0f}, .color = {0, 0, 0, 1}}, + }; + const RT_RasterTriVertex verts_left[4] = { + {.pos = {left_black_bar_x, pos_energy_left_y[1], 0.0f}, .color = {0, 0, 0, 1}}, + {.pos = {pos_energy_left_x[0], pos_energy_left_y[1], 0.0f}, .color = {0, 0, 0, 1}}, + {.pos = {pos_energy_left_x[0], pos_energy_left_y[0], 0.0f}, .color = {0, 0, 0, 1}}, + {.pos = {left_black_bar_x + left_max_h * bar_skew_scalar, pos_energy_left_y[0], 0.0f}, .color = {0, 0, 0, 1}}, + }; + RT_RasterTriVertex triangles[12] = { + verts_right[0],verts_right[1],verts_right[2], + verts_right[0],verts_right[2],verts_right[3], + verts_left[0],verts_left[1],verts_left[2], + verts_left[0],verts_left[2],verts_left[3] + }; + for (size_t i = 0; i < 12; ++i) { + triangles[i].pos.x /= (float)grd_curcanv->cv_bitmap.bm_w / 2.0f; + triangles[i].pos.x -= 1.0f; + triangles[i].pos.y /= (float)grd_curcanv->cv_bitmap.bm_h / 2.0f; + triangles[i].pos.y -= 1.0f; + triangles[i].pos.y *= -1.0f; + } + RT_RasterTriangles(&(RT_RasterTrianglesParams) { .num_vertices = 12, .vertices = triangles, .texture_handle = { 0 } }, 1); + + } + + // Draw homing warning + FNTScaleX = scale_text_homing[0]; + FNTScaleY = scale_text_homing[1]; + const bool flash_timer_is_toggled_on = (GameTime64 & 0x4000); + const bool object_is_homing_in = (Players[Player_num].homing_object_dist >= 0); + const bool not_in_end_level_sequence = !Endlevel_sequence; + + if (not_in_end_level_sequence && object_is_homing_in && flash_timer_is_toggled_on) + gr_set_fontcolor(BM_XRGB(49, 35, 11), -1); + else + gr_set_fontcolor(BM_XRGB(15, 12, 3), -1); + gr_printf(pos_homing_text[0], pos_homing_text[1], "LOCK"); + + // Render player ship and shield + const int color = Netgame.players[Player_num].color; + render_ui_bitmap(Gauges[GAUGE_SHIPS + color], pos_ship_center.x - scl_ship, pos_ship_center.y - scl_ship, pos_ship_center.x + scl_ship, pos_ship_center.y + scl_ship); + const int bm_num = shields >= 100 ? 9 : (shields / 10); + render_ui_bitmap(Gauges[GAUGE_SHIELDS + 9 - bm_num], pos_ship_center.x - scl_shield, pos_ship_center.y - scl_shield, pos_ship_center.x + scl_shield, pos_ship_center.y + scl_shield); + + // Draw weapons + gr_set_curfont(GAME_FONT); + + // Render shield number text + FNTScaleX = scale_text_misc[0]; + FNTScaleY = scale_text_misc[1]; + int sw, sh, saw, ew, eh, eaw; + gr_set_fontcolor(BM_XRGB(14, 14, 23), -1); + gr_get_string_size((shields > 199) ? "200" : (shields > 99) ? "100" : (shields > 9) ? "00" : "0", &sw, &sh, &saw); + gr_printf((pos_shield_text[0]) - (sw / 2), + (pos_shield_text[1]), "%d", shields); + + // Render energy number text + gr_set_fontcolor(BM_XRGB(25, 18, 6), -1); + gr_get_string_size((energy > 199) ? "200" : (energy > 99) ? "100" : (energy > 9) ? "00" : "0", &ew, &eh, &eaw); + gr_printf((pos_energy_text[0]) - (ew / 2), + (pos_energy_text[1]), "%d", energy); + + // end of scuffed + FNTScaleX = tmp_x; + FNTScaleY = tmp_y; + grd_curcanv->cv_bitmap.bm_w = tmp_bm_w; + grd_curcanv->cv_bitmap.bm_h = tmp_bm_h; + last_width = tmp_last_width; + last_height = tmp_last_height; + dx12_set_render_target(RT_RESOURCE_HANDLE_NULL); + RT_RasterSetViewport(grd_curcanv->cv_bitmap.bm_x, grd_curcanv->cv_bitmap.bm_y, Canvas_width, Canvas_height); + } +#endif + else + { draw_player_ship(cloak, SB_SHIP_GAUGE_X, SB_SHIP_GAUGE_Y); + draw_weapon_boxes(); + } } // --------------------------------------------------------------------------------------------------------- diff --git a/d1/main/laser.c b/d1/main/laser.c index e871b87..7ea5d9e 100644 --- a/d1/main/laser.c +++ b/d1/main/laser.c @@ -1,1627 +1,1627 @@ -/* -THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX -SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO -END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A -ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS -IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS -SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE -FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE -CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS -AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. -COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. -*/ - -/* - * - * This will contain the laser code - * - */ - -#include -#include - -#include "inferno.h" -#include "game.h" -#include "bm.h" -#include "object.h" -#include "laser.h" -#include "segment.h" -#include "fvi.h" -#include "segpoint.h" -#include "dxxerror.h" -#include "key.h" -#include "texmap.h" -#include "textures.h" -#include "render.h" -#include "vclip.h" -#include "fireball.h" -#include "polyobj.h" -#include "robot.h" -#include "weapon.h" -#include "timer.h" -#include "player.h" -#include "sounds.h" -#include "ai.h" -#include "powerup.h" -#include "multi.h" -#include "physics.h" -#include "hudmsg.h" -#include "playsave.h" -#include "logger.h" -#include "palette.h" - -#define NEWHOMER - -int Network_laser_track = -1; - -int find_homing_object_complete(vms_vector *curpos, object *tracker, int track_obj_type1, int track_obj_type2); - -//--------------------------------------------------------------------------------- -// Called by render code.... determines if the laser is from a robot or the -// player and calls the appropriate routine. - -void Laser_render(object *obj) -{ - -// Commented out by John (sort of, typed by Mike) on 6/8/94 -#if 0 - switch( obj->id ) { - case WEAPON_TYPE_WEAK_LASER: - case WEAPON_TYPE_STRONG_LASER: - case WEAPON_TYPE_CANNON_BALL: - case WEAPON_TYPE_MISSILE: - break; - default: - RT_LOGF(RT_LOGSERVERITY_HIGH, "Invalid weapon type in Laser_render\n" ); - } -#endif - - switch( Weapon_info[obj->id].render_type ) { - case WEAPON_RENDER_LASER: - Int3(); // Not supported anymore! - //Laser_draw_one(obj-Objects, Weapon_info[obj->id].bitmap ); - break; - case WEAPON_RENDER_BLOB: - draw_object_blob(obj, Weapon_info[obj->id].bitmap ); - break; - case WEAPON_RENDER_POLYMODEL: - break; - case WEAPON_RENDER_VCLIP: - Int3(); // Oops, not supported, type added by mk on 09/09/94, but not for lasers... - default: - RT_LOG(RT_LOGSERVERITY_HIGH, "Invalid weapon render type in Laser_render\n" ); - } - -} - -//--------------------------------------------------------------------------------- -// Draws a texture-mapped laser bolt - -//void Laser_draw_one( int objnum, grs_bitmap * bmp ) -//{ -// int t1, t2, t3; -// g3s_point p1, p2; -// object *obj; -// vms_vector start_pos,end_pos; -// -// obj = &Objects[objnum]; -// -// start_pos = obj->pos; -// vm_vec_scale_add(&end_pos,&start_pos,&obj->orient.fvec,-Laser_length); -// -// g3_rotate_point(&p1,&start_pos); -// g3_rotate_point(&p2,&end_pos); -// -// t1 = Lighting_on; -// t2 = Interpolation_method; -// t3 = Transparency_on; -// -// Lighting_on = 0; -// //Interpolation_method = 3; // Full perspective -// Interpolation_method = 1; // Linear -// Transparency_on = 1; -// -// //gr_setcolor( gr_getcolor(31,15,0)); -// //g3_draw_line_ptrs(p1,p2); -// //g3_draw_rod(p1,0x2000,p2,0x2000); -// //g3_draw_rod(p1,Laser_width,p2,Laser_width); -// g3_draw_rod_tmap(bmp,&p2,Laser_width,&p1,Laser_width,0); -// Lighting_on = t1; -// Interpolation_method = t2; -// Transparency_on = t3; -// -//} - -// Changed by MK on 09/07/94 -// I want you to be able to blow up your own bombs. -// AND...Your proximity bombs can blow you up if they're 2.0 seconds or more old. -int laser_are_related( int o1, int o2 ) -{ - if ( (o1<0) || (o2<0) ) - return 0; - - // See if o2 is the parent of o1 - if ( Objects[o1].type == OBJ_WEAPON ) - if ( (Objects[o1].ctype.laser_info.parent_num==o2) && (Objects[o1].ctype.laser_info.parent_signature==Objects[o2].signature) ) - { - // o1 is a weapon, o2 is the parent of 1, so if o1 is PROXIMITY_BOMB and o2 is player, they are related only if o1 < 2.0 seconds old - if ((Objects[o1].id != PROXIMITY_ID) || (Objects[o1].ctype.laser_info.creation_time + F1_0*2 >= GameTime64)) { - return 1; - } else - return 0; - } - - // See if o1 is the parent of o2 - if ( Objects[o2].type == OBJ_WEAPON ) - if ( (Objects[o2].ctype.laser_info.parent_num==o1) && (Objects[o2].ctype.laser_info.parent_signature==Objects[o1].signature) ) - return 1; - - // They must both be weapons - if ( Objects[o1].type != OBJ_WEAPON || Objects[o2].type != OBJ_WEAPON ) - return 0; - - // Here is the 09/07/94 change -- Siblings must be identical, others can hurt each other - // See if they're siblings... - if ( Objects[o1].ctype.laser_info.parent_signature==Objects[o2].ctype.laser_info.parent_signature ) - { - if (is_proximity_bomb_or_smart_mine(Objects[o1].id) || is_proximity_bomb_or_smart_mine(Objects[o2].id)) - return 0; //if either is proximity, then can blow up, so say not related - else - return 1; - } - return 0; -} - -void do_muzzle_stuff(int segnum, vms_vector *pos, vms_vector* color) -{ - Muzzle_data[Muzzle_queue_index].create_time = timer_query(); - Muzzle_data[Muzzle_queue_index].segnum = segnum; - Muzzle_data[Muzzle_queue_index].pos = *pos; -#ifdef RT_DX12 - Muzzle_data[Muzzle_queue_index].RT_muzzleColor = *color; -#endif RT_DX12 - Muzzle_queue_index++; - if (Muzzle_queue_index >= MUZZLE_QUEUE_MAX) - Muzzle_queue_index = 0; -} - -//--------------------------------------------------------------------------------- -// Initializes a laser after Fire is pressed - -// Returns object number. -int Laser_create_new( vms_vector * direction, vms_vector * position, int segnum, int parent, int weapon_type, int make_sound ) -{ - int objnum; - object *obj; - int rtype=-1; - fix parent_speed, weapon_speed; - fix volume; - fix laser_radius = -1; - fix laser_length=0; - - Assert( weapon_type < N_weapon_types ); - - if ( (weapon_type<0) || (weapon_type>=N_weapon_types) ) - weapon_type = 0; - - switch( Weapon_info[weapon_type].render_type ) { - case WEAPON_RENDER_BLOB: - rtype = RT_LASER; // Render as a laser even if blob (see render code above for explanation) - laser_radius = Weapon_info[weapon_type].blob_size; - laser_length = 0; - break; - case WEAPON_RENDER_POLYMODEL: - laser_radius = 0; // Filled in below. - rtype = RT_POLYOBJ; - break; - case WEAPON_RENDER_LASER: - Int3(); // Not supported anymore - break; - case WEAPON_RENDER_NONE: - rtype = RT_NONE; - laser_radius = F1_0; - laser_length = 0; - break; - case WEAPON_RENDER_VCLIP: - rtype = RT_WEAPON_VCLIP; - laser_radius = Weapon_info[weapon_type].blob_size; - laser_length = 0; - break; - default: - RT_LOG(RT_LOGSERVERITY_HIGH, "Invalid weapon render type in Laser_create_new\n" ); - } - - // Add to object list - Assert(laser_radius != -1); - Assert(rtype != -1); - objnum = obj_create( OBJ_WEAPON, weapon_type, segnum, position, NULL, laser_radius, CT_WEAPON, MT_PHYSICS, rtype ); - - if ( objnum < 0 ) { - Int3(); - return -1; - } - - obj = &Objects[objnum]; - - if (Objects[parent].type == OBJ_PLAYER) { - if (weapon_type == FUSION_ID) { - int fusion_scale; - - if (Game_mode & GM_MULTI) - fusion_scale = 2; - else - fusion_scale = 4; - - if (Fusion_charge <= 0) - obj->ctype.laser_info.multiplier = F1_0; - else if (Fusion_charge <= F1_0*fusion_scale) - obj->ctype.laser_info.multiplier = F1_0 + Fusion_charge/2; - else - obj->ctype.laser_info.multiplier = F1_0*fusion_scale; - - // Fusion damage was boosted by mk on 3/27 (for reg 1.1 release), but we only want it to apply to single player games. - if (Game_mode & GM_MULTI) - obj->ctype.laser_info.multiplier /= 2; - } else if ((weapon_type == LASER_ID) && (Players[Objects[parent].id].flags & PLAYER_FLAGS_QUAD_LASERS)) - obj->ctype.laser_info.multiplier = F1_0*3/4; - } - - - // This is strange: Make children of smart bomb bounce so if they hit a wall right away, they - // won't detonate. The frame interval code will clear this bit after 1/2 second. - if ((weapon_type == PLAYER_SMART_HOMING_ID) || (weapon_type == ROBOT_SMART_HOMING_ID)) - obj->mtype.phys_info.flags |= PF_BOUNCE; - - if (Weapon_info[weapon_type].render_type == WEAPON_RENDER_POLYMODEL) { - obj->rtype.pobj_info.model_num = Weapon_info[obj->id].model_num; - laser_radius = fixdiv(Polygon_models[obj->rtype.pobj_info.model_num].rad,Weapon_info[obj->id].po_len_to_width_ratio); - laser_length = Polygon_models[obj->rtype.pobj_info.model_num].rad * 2; - obj->size = laser_radius; - } - - obj->mtype.phys_info.mass = Weapon_info[weapon_type].mass; - obj->mtype.phys_info.drag = Weapon_info[weapon_type].drag; - if (Weapon_info[weapon_type].bounce) - obj->mtype.phys_info.flags |= PF_BOUNCE; - - vm_vec_zero(&obj->mtype.phys_info.thrust); - - if (weapon_type == FLARE_ID) - obj->mtype.phys_info.flags |= PF_STICK; //this obj sticks to walls - - obj->shields = Weapon_info[obj->id].strength[Difficulty_level]; - - // Fill in laser-specific data - - obj->lifeleft = Weapon_info[obj->id].lifetime; - obj->ctype.laser_info.parent_type = Objects[parent].type; - obj->ctype.laser_info.parent_signature = Objects[parent].signature; - obj->ctype.laser_info.parent_num = parent; - - // Assign parent type to highest level creator. This propagates parent type down from - // the original creator through weapons which create children of their own (ie, smart missile) - if (Objects[parent].type == OBJ_WEAPON) { - int highest_parent = parent; - - while (Objects[highest_parent].type == OBJ_WEAPON) { - highest_parent = Objects[highest_parent].ctype.laser_info.parent_num; - obj->ctype.laser_info.parent_num = highest_parent; - obj->ctype.laser_info.parent_type = Objects[highest_parent].type; - obj->ctype.laser_info.parent_signature = Objects[highest_parent].signature; - } - } - - // Create orientation matrix so we can look from this pov - // Homing missiles also need an orientation matrix so they know if they can make a turn. - if ((obj->render_type == RT_POLYOBJ) || (Weapon_info[obj->id].homing_flag)) - vm_vector_2_matrix( &obj->orient,direction, &Objects[parent].orient.uvec ,NULL); - - if (( &Objects[parent] != Viewer ) && (Objects[parent].type != OBJ_WEAPON)) { - // Muzzle flash - if (Weapon_info[obj->id].flash_vclip > -1 ) - object_create_muzzle_flash( obj->segnum, &obj->pos, Weapon_info[obj->id].flash_size, Weapon_info[obj->id].flash_vclip ); - } - -// Re-enable, 09/09/94: - volume = F1_0; - if (Weapon_info[obj->id].flash_sound > -1 ) { - if (make_sound) { - if ( parent == (Viewer-Objects) ) { - if (weapon_type == VULCAN_ID) // Make your own vulcan gun 1/2 as loud. - volume = F1_0 / 2; - if(weapon_type == PLASMA_ID && PlayerCfg.QuietPlasma) // Plasma's a bit loud, too - volume = F1_0 * 3 / 4; - digi_play_sample( Weapon_info[obj->id].flash_sound, volume ); - } else { - if(weapon_type == PLASMA_ID && PlayerCfg.QuietPlasma) // Plasma's a bit loud, too - volume = F1_0 * 3 / 4; - - if(Weapon_info[obj->id].flash_sound == 22) { // Reactor ball - if ((Game_mode & GM_OBSERVER) != 0) - volume = F1_0 * 3 / 16; - else - volume = F1_0 * 3 / 4; - } - - digi_link_sound_to_pos( Weapon_info[obj->id].flash_sound, obj->segnum, 0, &obj->pos, 0, volume ); - } - } - } - - // WARNING! NOTE! HEY! DEBUG! ETC! --MK 10/26/94 - // This is John's new code to fire the laser from the gun tip so that the back end of the laser bolt is - // at the gun tip. A problem that needs to be fixed is that the laser bolt might be in another segment. - // Use find_vector_interesection to detect the segment. - - // Move 1 frame, so that the end-tip of the laser is touching the gun barrel. - // This also jitters the laser a bit so that it doesn't alias. - // Don't do for weapons created by weapons. - if ((Objects[parent].type != OBJ_WEAPON) && (Weapon_info[weapon_type].render_type != WEAPON_RENDER_NONE) && (weapon_type != FLARE_ID)) { -// if ((Objects[parent].type != OBJ_WEAPON) && (weapon_type != FLARE_ID) ) { - vms_vector end_pos; - int end_segnum; - - vm_vec_scale_add( &end_pos, &obj->pos, direction, (laser_length/2) ); - end_segnum = find_point_seg(&end_pos, obj->segnum); - if (end_segnum != obj->segnum) { - if (end_segnum != -1) { - obj->pos = end_pos; - obj_relink(obj-Objects, end_segnum); - } - } else - obj->pos = end_pos; - } - - // Here's where to fix the problem with objects which are moving backwards imparting higher velocity to their weaponfire. - // Find out if moving backwards. - if (is_proximity_bomb_or_smart_mine(weapon_type)) { - parent_speed = vm_vec_mag_quick(&Objects[parent].mtype.phys_info.velocity); - if (vm_vec_dot(&Objects[parent].mtype.phys_info.velocity, &Objects[parent].orient.fvec) < 0) - parent_speed = -parent_speed; -// if(parent_speed>(F1_0*60)) -// parent_speed=F1_0*1600; -/* { char *murp; - sprintf(murp,"%i.%i",parent_speed>>16,(parent_speed<<16)>>16); - nm_messagebox(NULL,1,"OK",murp); - }*/ - } else - parent_speed = 0; - - weapon_speed = Weapon_info[obj->id].speed[Difficulty_level]; - - // Ugly hack (too bad we're on a deadline), for homing missiles dropped by smart bomb, start them out slower. - if ((obj->id == PLAYER_SMART_HOMING_ID) || (obj->id == ROBOT_SMART_HOMING_ID)) - weapon_speed /= 4; - - if (Weapon_info[obj->id].thrust != 0) - weapon_speed /= 2; - - vm_vec_copy_scale( &obj->mtype.phys_info.velocity, direction, weapon_speed + parent_speed ); - - // Set thrust - if (Weapon_info[weapon_type].thrust != 0) { - obj->mtype.phys_info.thrust = obj->mtype.phys_info.velocity; - vm_vec_scale(&obj->mtype.phys_info.thrust, fixdiv(Weapon_info[obj->id].thrust, weapon_speed+parent_speed)); - } - -// THIS CODE MAY NOT BE NEEDED... it was used to move the lasers out of the gun, since the -// laser pos is acutally the head of the laser, and we want the tail to be at the starting -// point, not the head. -// object_move_one( obj ); -// This next, apparently redundant line, appears necessary due to a hack in render.c -// obj->lifeleft = Weapon_info[obj->id].lifetime; - - if ((obj->type == OBJ_WEAPON) && (obj->id == FLARE_ID)) - obj->lifeleft += (d_rand()-16384) << 2; // add in -2..2 seconds - - - - // Don't let homing blobs make muzzle flash. - if (Objects[parent].type == OBJ_ROBOT || Objects[parent].type == OBJ_PLAYER) - { - vms_vector lasercolor = {0}; - polymodel* polyModel = &Polygon_models[obj->rtype.pobj_info.model_num]; - - polymodel* po = &Polygon_models[obj->rtype.pobj_info.model_num]; - if (po->n_textures <= 0) - { - int color = g3_poly_get_color(po->model_data); - if (color) - { - lasercolor.x = gr_current_pal[color * 3] * 500; - lasercolor.y = gr_current_pal[color * 3 + 1] * 500; - lasercolor.z = gr_current_pal[color * 3 + 2] * 500; - } - } - - do_muzzle_stuff(segnum, position, &lasercolor); - } - - - - return objnum; -} - -// ----------------------------------------------------------------------------------------------------------- -// Calls Laser_create_new, but takes care of the segment and point computation for you. -int Laser_create_new_easy( vms_vector * direction, vms_vector * position, int parent, int weapon_type, int make_sound ) -{ - fvi_query fq; - fvi_info hit_data; - object *pobjp = &Objects[parent]; - int fate; - - // Find segment containing laser fire position. If the robot is straddling a segment, the position from - // which it fires may be in a different segment, which is bad news for find_vector_intersection. So, cast - // a ray from the object center (whose segment we know) to the laser position. Then, in the call to Laser_create_new - // use the data returned from this call to find_vector_intersection. - // Note that while find_vector_intersection is pretty slow, it is not terribly slow if the destination point is - // in the same segment as the source point. - - fq.p0 = &pobjp->pos; - fq.startseg = pobjp->segnum; - fq.p1 = position; - fq.rad = 0; - fq.thisobjnum = pobjp-Objects; - fq.ignore_obj_list = NULL; - fq.flags = FQ_TRANSWALL | FQ_CHECK_OBJS; //what about trans walls??? - - fate = find_vector_intersection(&fq, &hit_data); - if (fate != HIT_NONE || hit_data.hit_seg==-1) { - return -1; - } - - return Laser_create_new( direction, &hit_data.hit_pnt, hit_data.hit_seg, parent, weapon_type, make_sound ); - -} - -int Muzzle_queue_index = 0; - -muzzle_info Muzzle_data[MUZZLE_QUEUE_MAX]; - -// ----------------------------------------------------------------------------------------------------------- -// Determine if two objects are on a line of sight. If so, return true, else return false. -// Calls fvi. -int object_to_object_visibility(object *obj1, object *obj2, int trans_type) -{ - fvi_query fq; - fvi_info hit_data; - int fate; - - fq.p0 = &obj1->pos; - fq.startseg = obj1->segnum; - fq.p1 = &obj2->pos; - fq.rad = 0x10; - fq.thisobjnum = obj1-Objects; - fq.ignore_obj_list = NULL; - fq.flags = trans_type; - - fate = find_vector_intersection(&fq, &hit_data); - - if (fate == HIT_WALL) - return 0; - else if (fate == HIT_NONE) - return 1; - else - Int3(); // Contact Mike: Oops, what happened? What is fate? - // 2 = hit object (impossible), 3 = bad starting point (bad) - - return 0; -} - -fix Min_trackable_dot = 3*(F1_0 - MIN_TRACKABLE_DOT)/4 + MIN_TRACKABLE_DOT; //MIN_TRACKABLE_DOT; - -// ----------------------------------------------------------------------------------------------------------- -// Return true if weapon *tracker is able to track object Objects[track_goal], else return false. -// In order for the object to be trackable, it must be within a reasonable turning radius for the missile -// and it must not be obstructed by a wall. -int object_is_trackable(int track_goal, object *tracker, fix *dot) -{ - vms_vector vector_to_goal; - object *objp; - - if (track_goal == -1) - return 0; - - if (Game_mode & GM_MULTI_COOP) - return 0; - - objp = &Objects[track_goal]; - - // Don't track player if he's cloaked. - if ((track_goal == Players[Player_num].objnum) && (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED)) - return 0; - - // Can't track AI object if he's cloaked. - if (objp->type == OBJ_ROBOT) - if (objp->ctype.ai_info.CLOAKED) - return 0; - - vm_vec_sub(&vector_to_goal, &objp->pos, &tracker->pos); - vm_vec_normalize_quick(&vector_to_goal); - *dot = vm_vec_dot(&vector_to_goal, &tracker->orient.fvec); - - if ((*dot < Min_trackable_dot) && (*dot > F1_0*9/10)) { - vm_vec_normalize(&vector_to_goal); - *dot = vm_vec_dot(&vector_to_goal, &tracker->orient.fvec); - } - - if (*dot >= Min_trackable_dot) { - int rval; - // dot is in legal range, now see if object is visible - rval = object_to_object_visibility(tracker, objp, FQ_TRANSWALL); - return rval; - } else { - return 0; - } -} - -// -------------------------------------------------------------------------------------------- -// Find object to home in on. -// Scan list of objects rendered last frame, find one that satisfies function of nearness to center and distance. -int find_homing_object(vms_vector *curpos, object *tracker) -{ - int i; - fix max_dot = -F1_0*2; - int best_objnum = -1; - - if (!Weapon_info[tracker->id].homing_flag) { - Int3(); // Contact Mike: This is a bad and stupid thing. Who called this routine with an illegal laser type?? - return 0; // Track the damn stupid player for causing this problem! - } - - // Find an object to track based on game mode (eg, whether in network play) and who fired it. - if (Game_mode & GM_MULTI) { - // In network mode. - if (tracker->ctype.laser_info.parent_type == OBJ_PLAYER) { - // It's fired by a player, so if robots present, track robot, else track player. - if (Game_mode & GM_MULTI_COOP) - return find_homing_object_complete( curpos, tracker, OBJ_ROBOT, -1); - else - return find_homing_object_complete( curpos, tracker, OBJ_PLAYER, OBJ_ROBOT); - } else { - Assert(tracker->ctype.laser_info.parent_type == OBJ_ROBOT); - return find_homing_object_complete(curpos, tracker, OBJ_PLAYER, -1); - } - } - else { - // Not in network mode. If not fired by player, then track player. - if (tracker->ctype.laser_info.parent_num != Players[Player_num].objnum) { - if (!(Players[Player_num].flags & PLAYER_FLAGS_CLOAKED)) - best_objnum = ConsoleObject - Objects; - } else { - // Not in network mode and fired by player. - for (i=Num_rendered_objects-1; i>=0; i--) { - fix dot; //, dist; - vms_vector vec_to_curobj; - int objnum = Ordered_rendered_object_list[i]; - object *curobjp = &Objects[objnum]; - - if (objnum == Players[Player_num].objnum) - continue; - - // Can't track AI object if he's cloaked. - if (curobjp->type == OBJ_ROBOT) - if (curobjp->ctype.ai_info.CLOAKED) - continue; - - vm_vec_sub(&vec_to_curobj, &curobjp->pos, curpos); - vm_vec_normalize_quick(&vec_to_curobj); - dot = vm_vec_dot(&vec_to_curobj, &tracker->orient.fvec); - - // Note: This uses the constant, not-scaled-by-frametime value, because it is only used - // to determine if an object is initially trackable. find_homing_object is called on subsequent - // frames to determine if the object remains trackable. - if (dot > MIN_TRACKABLE_DOT) { - if (dot > max_dot) { - if (object_to_object_visibility(tracker, &Objects[objnum], FQ_TRANSWALL)) { - max_dot = dot; - best_objnum = objnum; - } - } - } - } - } - } - - return best_objnum; -} - -// -------------------------------------------------------------------------------------------- -// Find object to home in on. -// Scan list of objects rendered last frame, find one that satisfies function of nearness to center and distance. -// Can track two kinds of objects. If you are only interested in one type, set track_obj_type2 to NULL -int find_homing_object_complete(vms_vector *curpos, object *tracker, int track_obj_type1, int track_obj_type2) -{ - int objnum; - fix max_dot = -F1_0*2; - int best_objnum = -1; - - fix max_trackable_dist = MAX_TRACKABLE_DIST; - fix min_trackable_dot = MIN_TRACKABLE_DOT; - - if (!Weapon_info[tracker->id].homing_flag) { - Int3(); // Contact Mike: This is a bad and stupid thing. Who called this routine with an illegal laser type?? - return 0; // Track the damn stupid player for causing this problem! - } - - for (objnum=0; objnum<=Highest_object_index; objnum++) { - int is_proximity = 0; - fix dot, dist; - vms_vector vec_to_curobj; - object *curobjp = &Objects[objnum]; - - if ((curobjp->type != track_obj_type1) && (curobjp->type != track_obj_type2)) - { - if ((curobjp->type == OBJ_WEAPON) && (is_proximity_bomb_or_smart_mine(curobjp->id))) { - if (curobjp->ctype.laser_info.parent_signature != tracker->ctype.laser_info.parent_signature) - is_proximity = 1; - else - continue; - } else - continue; - } - - if (objnum == tracker->ctype.laser_info.parent_num) // Don't track shooter - continue; - - // Don't track cloaked players. - if (curobjp->type == OBJ_PLAYER) - { - if (Players[curobjp->id].flags & PLAYER_FLAGS_CLOAKED) - continue; - // Don't track teammates in team games - #ifdef NETWORK - if ((Game_mode & GM_TEAM) && (Objects[tracker->ctype.laser_info.parent_num].type == OBJ_PLAYER) && (get_team(curobjp->id) == get_team(Objects[tracker->ctype.laser_info.parent_num].id))) - continue; - #endif - } - - // Can't track AI object if he's cloaked. - if (curobjp->type == OBJ_ROBOT) - if (curobjp->ctype.ai_info.CLOAKED) - continue; - - vm_vec_sub(&vec_to_curobj, &curobjp->pos, curpos); - dist = vm_vec_mag(&vec_to_curobj); - - if (dist < max_trackable_dist) { - vm_vec_normalize(&vec_to_curobj); - dot = vm_vec_dot(&vec_to_curobj, &tracker->orient.fvec); - if (is_proximity) - continue; // CED -- don't track proxies - //dot = ((dot << 3) + dot) >> 3; // I suspect Watcom would be too stupid to figure out the obvious... - - // Note: This uses the constant, not-scaled-by-frametime value, because it is only used - // to determine if an object is initially trackable. find_homing_object is called on subsequent - // frames to determine if the object remains trackable. - if (dot > min_trackable_dot) { - if (dot > max_dot) { - if (object_to_object_visibility(tracker, &Objects[objnum], FQ_TRANSWALL)) { - max_dot = dot; - best_objnum = objnum; - } - } - } - } - - } - - return best_objnum; -} - -// ------------------------------------------------------------------------------------------------------------ -// See if legal to keep tracking currently tracked object. If not, see if another object is trackable. If not, return -1, -// else return object number of tracking object. -int track_track_goal(int track_goal, object *tracker, fix *dot, unsigned int homerFrameCount) -{ -#ifdef NEWHOMER - if (object_is_trackable(track_goal, tracker, dot)) { // CED -- && (tracker - Objects) is useless - return track_goal; - } else if ((((tracker-Objects) ^ homerFrameCount) % 4) == 0) // CED -- Reverted to 1994 original release code, with homer frame count -#else - // Every 8 frames for each object, scan all objects. - if (object_is_trackable(track_goal, tracker, dot) && ((((tracker-Objects) ^ d_tick_count) % 8) != 0)) { - return track_goal; - } else if ((((tracker-Objects) ^ d_tick_count) % 4) == 0) -#endif - { - int rval = -2; - - // If player fired missile, then search for an object, if not, then give up. - if (Objects[tracker->ctype.laser_info.parent_num].type == OBJ_PLAYER) { - int goal_type; - - if (track_goal == -1) - { - if (Game_mode & GM_MULTI) - { - if (Game_mode & GM_MULTI_COOP) - rval = find_homing_object_complete( &tracker->pos, tracker, OBJ_ROBOT, -1); - else if (Game_mode & GM_MULTI_ROBOTS) // Not cooperative, if robots, track either robot or player - rval = find_homing_object_complete( &tracker->pos, tracker, OBJ_PLAYER, OBJ_ROBOT); - else // Not cooperative and no robots, track only a player - rval = find_homing_object_complete( &tracker->pos, tracker, OBJ_PLAYER, -1); - } - else - rval = find_homing_object_complete(&tracker->pos, tracker, OBJ_PLAYER, OBJ_ROBOT); - } - else - { - goal_type = Objects[tracker->ctype.laser_info.track_goal].type; - if ((goal_type == OBJ_PLAYER) || (goal_type == OBJ_ROBOT)) - rval = find_homing_object_complete(&tracker->pos, tracker, goal_type, -1); - else - rval = -1; - } - } - else { - int goal_type; - - if (track_goal == -1) - rval = find_homing_object_complete(&tracker->pos, tracker, OBJ_PLAYER, -1); - else { - goal_type = Objects[tracker->ctype.laser_info.track_goal].type; - rval = find_homing_object_complete(&tracker->pos, tracker, goal_type, -1); - } - } - - Assert(rval != -2); // This means it never got set which is bad! Contact Mike. - return rval; - } - - return -1; -} - - -//-------------- Initializes a laser after Fire is pressed ----------------- - -void Laser_player_fire_spread_delay(object *obj, int laser_type, int gun_num, fix spreadr, fix spreadu, fix delay_time, int make_sound, int harmless, vms_vector shot_orientation) -{ - int LaserSeg, Fate; - vms_vector LaserPos, LaserDir; - fvi_query fq; - fvi_info hit_data; - vms_vector gun_point, *pnt; - vms_matrix m; - int objnum; - - // Find the initial position of the laser - pnt = &Player_ship->gun_points[gun_num]; - - // double gx = (double)(pnt->x) / (double)(F1_0); - // double gy = (double)(pnt->y) / (double)(F1_0); - // double gz = (double)(pnt->z) / (double)(F1_0); - // RT_LOGF(RT_LOGSERVERITY_MEDIUM, "Creating weapon at offset %f, %f, %f\n", gx, gy, gz); - - vm_copy_transpose_matrix(&m,&obj->orient); - vm_vec_rotate(&gun_point,pnt,&m); - - vm_vec_add(&LaserPos,&obj->pos,&gun_point); - - // If supposed to fire at a delayed time (delay_time), then move this point backwards. - if (delay_time) - /* CED sniperpackets */ - //vm_vec_scale_add2(&LaserPos, &obj->orient.fvec, -fixmul(delay_time, Weapon_info[laser_type].speed[Difficulty_level])); - vm_vec_scale_add2(&LaserPos, &shot_orientation, -fixmul(delay_time, Weapon_info[laser_type].speed[Difficulty_level])); - -// do_muzzle_stuff(obj, &Pos); - - //--------------- Find LaserPos and LaserSeg ------------------ - fq.p0 = &obj->pos; - fq.startseg = obj->segnum; - fq.p1 = &LaserPos; - fq.rad = 0x10; - fq.thisobjnum = obj-Objects; - fq.ignore_obj_list = NULL; - fq.flags = FQ_CHECK_OBJS; - - Fate = find_vector_intersection(&fq, &hit_data); - - LaserSeg = hit_data.hit_seg; - - if (LaserSeg == -1) //some sort of annoying error - return; - - //SORT OF HACK... IF ABOVE WAS CORRECT THIS WOULDNT BE NECESSARY. - if ( vm_vec_dist_quick(&LaserPos, &obj->pos) > 0x50000 ) - return; - - if (Fate==HIT_WALL) { - return; - } - - if (Fate==HIT_OBJECT) { -// if ( Objects[hit_data.hit_object].type == OBJ_ROBOT ) -// Objects[hit_data.hit_object].flags |= OF_SHOULD_BE_DEAD; -// if ( Objects[hit_data.hit_object].type != OBJ_POWERUP ) -// return; - //as of 12/6/94, we don't care if the laser is stuck in an object. We - //just fire away normally - } - - // Now, make laser spread out. - LaserDir = shot_orientation; /* CED sniperpackets */ //obj->orient.fvec; - if ((spreadr != 0) || (spreadu != 0)) { - vm_vec_scale_add2(&LaserDir, &obj->orient.rvec, spreadr); - vm_vec_scale_add2(&LaserDir, &obj->orient.uvec, spreadu); - } - - objnum = Laser_create_new( &LaserDir, &LaserPos, LaserSeg, obj-Objects, laser_type, make_sound ); - if (objnum == -1) - return; - - // If this weapon is supposed to be silent, set that bit! - if (!make_sound) - Objects[objnum].flags |= OF_SILENT; - - // If this weapon is supposed to be harmless, set that bit! - if (harmless) - Objects[objnum].flags |= OF_HARMLESS; - - // If the object firing the laser is the player, then indicate the laser object so robots can dodge. - if (obj == ConsoleObject) - Player_fired_laser_this_frame = objnum; - - if (Weapon_info[laser_type].homing_flag) { - if (obj == ConsoleObject) - { - Objects[objnum].ctype.laser_info.track_goal = find_homing_object(&LaserPos, &Objects[objnum]); - #ifdef NETWORK - Network_laser_track = Objects[objnum].ctype.laser_info.track_goal; - #endif - } - #ifdef NETWORK - else // Some other player shot the homing thing - { - Assert(Game_mode & GM_MULTI); - Objects[objnum].ctype.laser_info.track_goal = Network_laser_track; - } - #endif - } -} - -// ----------------------------------------------------------------------------------------------------------- -void Laser_player_fire_spread(object *obj, int laser_type, int gun_num, fix spreadr, fix spreadu, int make_sound, int harmless, vms_vector shot_orientation) -{ - Laser_player_fire_spread_delay(obj, laser_type, gun_num, spreadr, spreadu, 0, make_sound, harmless, shot_orientation); /* CED sniperpackets */ -} - - -// ----------------------------------------------------------------------------------------------------------- -void Laser_player_fire(object *obj, int laser_type, int gun_num, int make_sound, int harmless, vms_vector shot_orientation) -{ - Laser_player_fire_spread(obj, laser_type, gun_num, 0, 0, make_sound, harmless, shot_orientation); /* CED sniperpackets */ -} - -// ----------------------------------------------------------------------------------------------------------- -void Flare_create(object *obj) -{ - fix energy_usage; - - energy_usage = Weapon_info[FLARE_ID].energy_usage; - - if (Difficulty_level < 2) - energy_usage = fixmul(energy_usage, i2f(Difficulty_level+2)/4); - - if (Players[Player_num].energy > 0) { - Players[Player_num].energy -= energy_usage; - - if (Players[Player_num].energy <= 0) { - Players[Player_num].energy = 0; - auto_select_weapon(0); - } - - Laser_player_fire( obj, FLARE_ID, 6, 1, 0, Objects[Players[Player_num].objnum].orient.fvec); /* CED sniperpackets */ - - #ifdef NETWORK - if (Game_mode & GM_MULTI) - multi_send_fire(FLARE_ID+MISSILE_ADJUST, 0, 0, 1, -1); - #endif - } - -} - -#define HOMING_MISSILE_SCALE 8 - -//------------------------------------------------------------------------------------------- -// Set object *objp's orientation to (or towards if I'm ambitious) its velocity. -void homing_missile_turn_towards_velocity(object *objp, vms_vector *norm_vel) -{ - vms_vector new_fvec; - - new_fvec = *norm_vel; - - vm_vec_scale(&new_fvec, FrameTime * HOMING_MISSILE_SCALE); - vm_vec_add2(&new_fvec, &objp->orient.fvec); - vm_vec_normalize_quick(&new_fvec); - -// if ((norm_vel->x == 0) && (norm_vel->y == 0) && (norm_vel->z == 0)) -// return; - - vm_vector_2_matrix(&objp->orient, &new_fvec, NULL, NULL); -} - -#ifdef NEWHOMER -/* - * In the original game homers turned sharper in higher FPS-values. We do not want that so we need to scale vector_to_object to FrameTime. - * For each difficulty setting we have a base value the homers will align to. This we express in a FPS value representing the homers turn radius of the original game (i.e. "The homer will turn like on XXFPS"). - * NOTE: Old homers only get valid track_goal every 8 frames. This does not apply anymore so these values are divided by 4 to compensate this. - */ -fix homing_turn_base[NDL] = { 4, 5, 6, 7, 8 }; -#endif - -//------------------------------------------------------------------------------------------- -//sequence this laser object for this _frame_ (underscores added here to aid MK in his searching!) -void Laser_do_weapon_sequence(object *obj, int doHomerFrame, fix idealHomerFrameTime, unsigned int homerFrameCount) -{ - Assert(obj->control_type == CT_WEAPON); - - if (obj->lifeleft < 0 ) { // We died of old age - obj->flags |= OF_SHOULD_BE_DEAD; - if ( Weapon_info[obj->id].damage_radius ) - explode_badass_weapon(obj); - return; - } - - //delete weapons that are not moving - if ( !((d_tick_count ^ obj->signature) & 3) && - (obj->id != FLARE_ID) && - (Weapon_info[obj->id].speed[Difficulty_level] > 0) && - (vm_vec_mag_quick(&obj->mtype.phys_info.velocity) < F2_0)) { - obj_delete(obj-Objects); - return; - } - - if ( obj->id == FUSION_ID ) { //always set fusion weapon to max vel - - vm_vec_normalize_quick(&obj->mtype.phys_info.velocity); - - vm_vec_scale(&obj->mtype.phys_info.velocity, Weapon_info[obj->id].speed[Difficulty_level]); - } - - // For homing missiles, turn towards target. - if (Weapon_info[obj->id].homing_flag) { - vms_vector vector_to_object, temp_vec; - fix dot=F1_0; - fix speed, max_speed; - - // For first 1/2 second of life, missile flies straight. - if (obj->ctype.laser_info.creation_time + HOMING_MISSILE_STRAIGHT_TIME < GameTime64) { - - int track_goal = obj->ctype.laser_info.track_goal; - - // If it's time to do tracking, then it's time to grow up, stop bouncing and start exploding!. - if ((obj->id == ROBOT_SMART_HOMING_ID) || (obj->id == PLAYER_SMART_HOMING_ID)) { - obj->mtype.phys_info.flags &= ~PF_BOUNCE; - } - - // Make sure the object we are tracking is still trackable. - if(doHomerFrame) { - track_goal = track_track_goal(track_goal, obj, &dot, homerFrameCount); - - - if (track_goal == Players[Player_num].objnum) { - fix dist_to_player; - - dist_to_player = vm_vec_dist_quick(&obj->pos, &Objects[track_goal].pos); - if ((dist_to_player < Players[Player_num].homing_object_dist) || (Players[Player_num].homing_object_dist < 0)) - Players[Player_num].homing_object_dist = dist_to_player; - - } - } - - if ((track_goal != -1) && doHomerFrame) { -// CED -- I'm going to mod the NEWHOMER to keep the diffs clean, even though that's confusing -// This should be refactored if we decide to keep the change. -#ifdef NEWHOMER - vm_vec_sub(&vector_to_object, &Objects[track_goal].pos, &obj->pos); - - vm_vec_normalize_quick(&vector_to_object); - temp_vec = obj->mtype.phys_info.velocity; - speed = vm_vec_normalize(&temp_vec); - max_speed = Weapon_info[obj->id].speed[Difficulty_level]; - if (speed+F1_0 < max_speed) { - speed += fixmul(max_speed, idealHomerFrameTime/2); // CED - if (speed > max_speed) - speed = max_speed; - } - - // Scale vector to object to current FrameTime. - // CED -- Removed - //vm_vec_scale(&vector_to_object, F1_0/((float)(F1_0/homing_turn_base[Difficulty_level])/FrameTime)); - - vm_vec_add2(&temp_vec, &vector_to_object); - // The boss' smart children track better... - if (Weapon_info[obj->id].render_type != WEAPON_RENDER_POLYMODEL) - vm_vec_add2(&temp_vec, &vector_to_object); - vm_vec_normalize(&temp_vec); - vm_vec_scale(&temp_vec, speed); - obj->mtype.phys_info.velocity = temp_vec; - - // Subtract off life proportional to amount turned. - // For hardest turn, it will lose 2 seconds per second. - { - fix lifelost, absdot; - - absdot = abs(F1_0 - dot); - - lifelost = fixmul(absdot*32, idealHomerFrameTime); // CED -- did anyone even know they did this? - obj->lifeleft -= lifelost; - } - - // Only polygon objects have visible orientation, so only they should turn. - if (Weapon_info[obj->id].render_type == WEAPON_RENDER_POLYMODEL) - homing_missile_turn_towards_velocity(obj, &temp_vec); // temp_vec is normalized velocity. -#else // OLD - ORIGINAL - MISSILE TRACKING CODE -/* // CED -- pardon the comment -- I keep looking at the wrong code - vm_vec_sub(&vector_to_object, &Objects[track_goal].pos, &obj->pos); - - vm_vec_normalize_quick(&vector_to_object); - temp_vec = obj->mtype.phys_info.velocity; - speed = vm_vec_normalize_quick(&temp_vec); - max_speed = Weapon_info[obj->id].speed[Difficulty_level]; - if (speed+F1_0 < max_speed) { - speed += fixmul(max_speed, FrameTime/2); - if (speed > max_speed) - speed = max_speed; - } - - dot = vm_vec_dot(&temp_vec, &vector_to_object); - - vm_vec_add2(&temp_vec, &vector_to_object); - // The boss' smart children track better... - if (Weapon_info[obj->id].render_type != WEAPON_RENDER_POLYMODEL) - vm_vec_add2(&temp_vec, &vector_to_object); - vm_vec_normalize_quick(&temp_vec); - vm_vec_scale(&temp_vec, speed); - obj->mtype.phys_info.velocity = temp_vec; - - // Subtract off life proportional to amount turned. - // For hardest turn, it will lose 2 seconds per second. - { - fix lifelost, absdot; - - absdot = abs(F1_0 - dot); - - if (absdot > F1_0/8) { - if (absdot > F1_0/4) - absdot = F1_0/4; - lifelost = fixmul(absdot*16, FrameTime); - obj->lifeleft -= lifelost; - } - //added 8/14/98 by Victor Rachels to make homers lose life while going straight, too - obj->lifeleft -= fixmul(F1_0, FrameTime); - //end addition - Victor Rachels - } - - // Only polygon objects have visible orientation, so only they should turn. - if (Weapon_info[obj->id].render_type == WEAPON_RENDER_POLYMODEL) - homing_missile_turn_towards_velocity(obj, &temp_vec); // temp_vec is normalized velocity. -*/ -#endif - } - } - } - - // Make sure weapon is not moving faster than allowed speed. - if (Weapon_info[obj->id].thrust != 0) { - fix weapon_speed; - - weapon_speed = vm_vec_mag_quick(&obj->mtype.phys_info.velocity); - if (weapon_speed > Weapon_info[obj->id].speed[Difficulty_level]) { - fix scale_factor; - - scale_factor = fixdiv(Weapon_info[obj->id].speed[Difficulty_level], weapon_speed); - vm_vec_scale(&obj->mtype.phys_info.velocity, scale_factor); - } - - } -} - -int Spreadfire_toggle=0; -fix64 Last_laser_fired_time = 0; - -extern int Player_fired_laser_this_frame; - -// -------------------------------------------------------------------------------------------------- -// Assumption: This is only called by the actual console player, not for -// network players - -void do_laser_firing_player(void) -{ - player *plp = &Players[Player_num]; - fix energy_used; - int ammo_used; - int weapon_index; - int rval = 0; - int nfires = 1; - - if (Player_is_dead) - return; - - weapon_index = Primary_weapon_to_weapon_info[Primary_weapon]; - energy_used = Weapon_info[weapon_index].energy_usage; - - if (Difficulty_level < 2) - energy_used = fixmul(energy_used, i2f(Difficulty_level+2)/4); - - ammo_used = Weapon_info[weapon_index].ammo_usage; - - while (Next_laser_fire_time <= GameTime64) { - if ((plp->energy >= energy_used) || ((Primary_weapon == VULCAN_INDEX) && (plp->primary_ammo[Primary_weapon] >= ammo_used)) ) { - int laser_level, flags, fire_frame_overhead = 0; - - if (GameTime64 - Next_laser_fire_time <= FrameTime) // if firing is prolonged by FrameTime overhead, let's try to fix that. - fire_frame_overhead = GameTime64 - Next_laser_fire_time; - - Last_laser_fired_time = GameTime64; - - if (!cheats.rapidfire) - Next_laser_fire_time = GameTime64 + Weapon_info[weapon_index].fire_wait - fire_frame_overhead; - else - Next_laser_fire_time = GameTime64 + (F1_0/25) - fire_frame_overhead; - - laser_level = Players[Player_num].laser_level; - - flags = 0; - - if (Primary_weapon == SPREADFIRE_INDEX) { - if (Spreadfire_toggle) - flags |= LASER_SPREADFIRE_TOGGLED; - Spreadfire_toggle = !Spreadfire_toggle; - } - - if (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS) - flags |= LASER_QUAD; - - /* CED sniperpackets */ - rval += do_laser_firing(Players[Player_num].objnum, Primary_weapon, laser_level, flags, nfires, Objects[Players[Player_num].objnum].orient.fvec); - - int warning_increment = 250/12; - int pre_ammo = plp->primary_ammo[VULCAN_INDEX]; - int post_ammo = plp->primary_ammo[VULCAN_INDEX] - ammo_used; - - //int bump = 1; - if(Primary_weapon == VULCAN_INDEX && PlayerCfg.VulcanAmmoWarnings) { - //if(pre_ammo > warning_increment*4 + bump && post_ammo <= warning_increment*4 + bump) { - // digi_play_sample(SOUND_HUD_MESSAGE, F1_0); - //} - - if(pre_ammo >= warning_increment*4 && post_ammo < warning_increment*4) { - HUD_init_message_literal(HM_MULTI, "Vulcan ammo warning."); - digi_play_sample(SOUND_BAD_SELECTION, F1_0); - } - - //if(pre_ammo > warning_increment*2 + bump && post_ammo <= warning_increment*2 + bump) { - // digi_play_sample(SOUND_HUD_MESSAGE, F1_0); - //} - - - if(pre_ammo >= warning_increment*2 && post_ammo < warning_increment*2) { - HUD_init_message_literal(HM_MULTI, "Vulcan ammo low."); - digi_play_sample(SOUND_BAD_SELECTION, F1_0); - } - - //if(pre_ammo > warning_increment*1 + bump && post_ammo <= warning_increment*1 + bump) { - // digi_play_sample(SOUND_HUD_MESSAGE, F1_0); - //} - - - if(pre_ammo >= warning_increment*1 && post_ammo < warning_increment*1) { - HUD_init_message_literal(HM_MULTI, "Vulcan ammo critical!"); - digi_play_sample(SOUND_BAD_SELECTION, F1_0); - } - } - - pre_ammo = (Players[Player_num].energy)/F1_0; - post_ammo = (Players[Player_num].energy - (energy_used * rval) / Weapon_info[weapon_index].fire_count)/F1_0; - warning_increment = 5; - if(Primary_weapon != VULCAN_INDEX && PlayerCfg.VulcanAmmoWarnings) { - - if(pre_ammo >= warning_increment*4 && post_ammo < warning_increment*4) { - HUD_init_message_literal(HM_MULTI, "Energy warning."); - digi_play_sample(SOUND_BAD_SELECTION, F1_0); - } - - - if(pre_ammo >= warning_increment*2 && post_ammo < warning_increment*2) { - HUD_init_message_literal(HM_MULTI, "Energy low."); - digi_play_sample(SOUND_BAD_SELECTION, F1_0); - } - - - if(pre_ammo >= warning_increment*1 && post_ammo < warning_increment*1) { - HUD_init_message_literal(HM_MULTI, "Energy critical!"); - digi_play_sample(SOUND_BAD_SELECTION, F1_0); - } - } - - plp->energy -= (energy_used * rval) / Weapon_info[weapon_index].fire_count; - if (plp->energy < 0) - plp->energy = 0; - - if (ammo_used > plp->primary_ammo[Primary_weapon]) - plp->primary_ammo[Primary_weapon] = 0; - else - plp->primary_ammo[Primary_weapon] -= ammo_used; - - auto_select_weapon(0); // Make sure the player can fire from this weapon. - - } else - break; // Couldn't fire weapon, so abort. - } - - Global_laser_firing_count = 0; - - return; -} - -// -------------------------------------------------------------------------------------------------- -// Object "objnum" fires weapon "weapon_num" of level "level". (Right now (9/24/94) level is used only for type 0 laser. -// Flags are the player flags. For network mode, set to 0. -// It is assumed that this is a player object (as in multiplayer), and therefore the gun positions are known. -// Returns number of times a weapon was fired. This is typically 1, but might be more for low frame rates. -// More than one shot is fired with a pseudo-delay so that players on slow machines can fire (for themselves -// or other players) often enough for things like the vulcan cannon. -int do_laser_firing(int objnum, int weapon_num, int level, int flags, int nfires, vms_vector shot_orientation) /* CED sniperpackets */ -{ - object *objp = &Objects[objnum]; - - switch (weapon_num) { - case LASER_INDEX: { - Laser_player_fire( objp, level, 0, 1, 0, shot_orientation); - Laser_player_fire( objp, level, 1, 0, 0, shot_orientation); - - if (flags & LASER_QUAD) { - // hideous system to make quad laser 1.5x powerful as normal laser, make every other quad laser bolt harmless - Laser_player_fire( objp, level, 2, 0, 0, shot_orientation); - Laser_player_fire( objp, level, 3, 0, 0, shot_orientation); - } - break; - } - case VULCAN_INDEX: { - // Only make sound for 1/4 of vulcan bullets. - int make_sound = 1; - //if (d_rand() > 24576) - // make_sound = 1; - Laser_player_fire_spread( objp, VULCAN_ID, 6, d_rand()/8 - 32767/16, d_rand()/8 - 32767/16, make_sound, 0, shot_orientation); - if (nfires > 1) { - Laser_player_fire_spread( objp, VULCAN_ID, 6, d_rand()/8 - 32767/16, d_rand()/8 - 32767/16, 0, 0, shot_orientation); - if (nfires > 2) { - Laser_player_fire_spread( objp, VULCAN_ID, 6, d_rand()/8 - 32767/16, d_rand()/8 - 32767/16, 0, 0, shot_orientation); - } - } - break; - } - case SPREADFIRE_INDEX: - if (flags & LASER_SPREADFIRE_TOGGLED) { - Laser_player_fire_spread( objp, SPREADFIRE_ID, 6, F1_0/16, 0, 0, 0, shot_orientation); - Laser_player_fire_spread( objp, SPREADFIRE_ID, 6, -F1_0/16, 0, 0, 0, shot_orientation); - Laser_player_fire_spread( objp, SPREADFIRE_ID, 6, 0, 0, 1, 0, shot_orientation); - } else { - Laser_player_fire_spread( objp, SPREADFIRE_ID, 6, 0, F1_0/16, 0, 0, shot_orientation); - Laser_player_fire_spread( objp, SPREADFIRE_ID, 6, 0, -F1_0/16, 0, 0, shot_orientation); - Laser_player_fire_spread( objp, SPREADFIRE_ID, 6, 0, 0, 1, 0, shot_orientation); - } - break; - -#ifndef SHAREWARE - case PLASMA_INDEX: - Laser_player_fire( objp, PLASMA_ID, 0, 1, 0, shot_orientation); - Laser_player_fire( objp, PLASMA_ID, 1, 0, 0, shot_orientation); - if (nfires > 1) { - Laser_player_fire_spread_delay( objp, PLASMA_ID, 0, 0, 0, FrameTime/2, 1, 0, shot_orientation); - Laser_player_fire_spread_delay( objp, PLASMA_ID, 1, 0, 0, FrameTime/2, 0, 0, shot_orientation); - } - break; - - case FUSION_INDEX: { - vms_vector force_vec; - - Laser_player_fire( objp, FUSION_ID, 0, 1, 0, shot_orientation); - Laser_player_fire( objp, FUSION_ID, 1, 1, 0, shot_orientation); - - flags = (sbyte)(Fusion_charge >> 12); - - Fusion_charge = 0; - - force_vec.x = -(objp->orient.fvec.x << 7); - force_vec.y = -(objp->orient.fvec.y << 7); - force_vec.z = -(objp->orient.fvec.z << 7); - phys_apply_force(objp, &force_vec); - - force_vec.x = (force_vec.x >> 4) + d_rand() - 16384; - force_vec.y = (force_vec.y >> 4) + d_rand() - 16384; - force_vec.z = (force_vec.z >> 4) + d_rand() - 16384; - phys_apply_rot(objp, &force_vec); - - } - break; -#endif - - default: - Int3(); // Contact Mike: Unknown Primary weapon type, setting to 0. - Primary_weapon = 0; - } - - // Set values to be recognized during comunication phase, if we are the - // one shooting -#ifdef NETWORK - if ((Game_mode & GM_MULTI) && (objnum == Players[Player_num].objnum)) - multi_send_fire(weapon_num, level, flags, nfires, -1); -#endif - - return nfires; -} - -#define MAX_SMART_DISTANCE (F1_0*150) -#define MAX_OBJDISTS 30 - -typedef struct { - int objnum; - fix dist; -} objdist; - -// ------------------------------------------------------------------------------------------- -// if goal_obj == -1, then create random vector -int create_homing_missile(object *objp, int goal_obj, int objtype, int make_sound) -{ - int objnum; - vms_vector vector_to_goal; - vms_vector random_vector; - //vms_vector goal_pos; - - if (goal_obj == -1) { - make_random_vector(&vector_to_goal); - } else { - vm_vec_sub(&vector_to_goal, &Objects[goal_obj].pos, &objp->pos); - vm_vec_normalize_quick(&vector_to_goal); - make_random_vector(&random_vector); - vm_vec_scale_add2(&vector_to_goal, &random_vector, F1_0/4); - vm_vec_normalize_quick(&vector_to_goal); - } - - // Create a vector towards the goal, then add some noise to it. - objnum = Laser_create_new(&vector_to_goal, &objp->pos, objp->segnum, objp-Objects, objtype, make_sound); - if (objnum == -1) - return -1; - - // Fixed to make sure the right person gets credit for the kill - -// Objects[objnum].ctype.laser_info.parent_num = objp->ctype.laser_info.parent_num; -// Objects[objnum].ctype.laser_info.parent_type = objp->ctype.laser_info.parent_type; -// Objects[objnum].ctype.laser_info.parent_signature = objp->ctype.laser_info.parent_signature; - - Objects[objnum].ctype.laser_info.track_goal = goal_obj; - - return objnum; -} - -// ------------------------------------------------------------------------------------------- -// Create the children of a smart bomb, which is a bunch of homing missiles. -void create_smart_children(object *objp, int num_smart_children) -{ - int parent_type; - int numobjs=0, objnum = 0, sel_objnum, last_sel_objnum = -1; - int objlist[MAX_OBJDISTS]; - int blob_id; - - parent_type = objp->ctype.laser_info.parent_type; - - if (objp->id == SMART_ID) { - int i; - - if (Game_mode & GM_MULTI) - d_srand(8321L); - - for (objnum=0; objnum<=Highest_object_index; objnum++) { - object *curobjp = &Objects[objnum]; - - if ((((curobjp->type == OBJ_ROBOT) && (!curobjp->ctype.ai_info.CLOAKED)) || (curobjp->type == OBJ_PLAYER)) && (objnum != objp->ctype.laser_info.parent_num)) { - fix dist; - - if (curobjp->type == OBJ_PLAYER) - { - if ((parent_type == OBJ_PLAYER) && (Game_mode & GM_MULTI_COOP)) - continue; - if ((Game_mode & GM_TEAM) && (get_team(curobjp->id) == get_team(Objects[objp->ctype.laser_info.parent_num].id))) - continue; - if (Players[curobjp->id].flags & PLAYER_FLAGS_CLOAKED) - continue; - } - - // Robot blobs can't track robots. - if (curobjp->type == OBJ_ROBOT) - if (parent_type == OBJ_ROBOT) - continue; - - dist = vm_vec_dist_quick(&objp->pos, &curobjp->pos); - if (dist < MAX_SMART_DISTANCE) { - int oovis; - - oovis = object_to_object_visibility(objp, curobjp, FQ_TRANSWALL); - - if (oovis) { //object_to_object_visibility(objp, curobjp, FQ_TRANSWALL)) { - objlist[numobjs] = objnum; - numobjs++; - if (numobjs >= MAX_OBJDISTS) { - numobjs = MAX_OBJDISTS; - break; - } - } - } - } - } - - // Get type of weapon for child from parent. - if (parent_type == OBJ_PLAYER) { - blob_id = PLAYER_SMART_HOMING_ID; - Assert(blob_id != -1); // Hmm, missing data in bitmaps.tbl. Need "children=NN" parameter. - } else { - blob_id = ((N_weapon_types> 15]; - if (numobjs > 1) - while (sel_objnum == last_sel_objnum) - sel_objnum = objlist[(d_rand() * numobjs) >> 15]; - create_homing_missile(objp, sel_objnum, blob_id, (i==0)?1:0); - last_sel_objnum = sel_objnum; - } - } -} - -#define CONCUSSION_GUN 4 -#define HOMING_GUN 4 - -#define PROXIMITY_GUN 7 -#define SMART_GUN 7 -#define MEGA_GUN 7 - - -int Missile_gun=0, Proximity_dropped = 0; - -// ------------------------------------------------------------------------------------------- -//changed on 9/16/98 by adb to distinguish between drop bomb and secondary fire -void do_missile_firing(int drop_bomb) -{ - int bomb = which_bomb(); - int weapon = (drop_bomb) ? bomb : Secondary_weapon; - fix fire_frame_overhead = 0; - - Network_laser_track = -1; - - Assert(weapon < MAX_SECONDARY_WEAPONS); - - if (GameTime64 - Next_missile_fire_time <= FrameTime) // if firing is prolonged by FrameTime overhead, let's try to fix that. - fire_frame_overhead = GameTime64 - Next_missile_fire_time; - - if (!Player_is_dead && (Players[Player_num].secondary_ammo[weapon] > 0)) { - - int weapon_index; - - Players[Player_num].secondary_ammo[weapon]--; - - weapon_index = Secondary_weapon_to_weapon_info[weapon]; - - if (!cheats.rapidfire) - Next_missile_fire_time = GameTime64 + Weapon_info[weapon_index].fire_wait - fire_frame_overhead; - else - Next_missile_fire_time = GameTime64 + (F1_0/25) - fire_frame_overhead; - - vms_vector orient = Objects[Players[Player_num].objnum].orient.fvec; - - switch (weapon) { - case CONCUSSION_INDEX: - Laser_player_fire( ConsoleObject, CONCUSSION_ID, CONCUSSION_GUN+(Missile_gun & 1), 1, 0 , orient); - Missile_gun++; - - #ifdef NETWORK - if(Game_mode & GM_MULTI && Netgame.RespawnConcs && RespawningConcussions[Player_num] > 0 ) { - maybe_drop_net_powerup(POW_MISSILE_1); - RespawningConcussions[Player_num]--; - } - #endif - - break; - - case PROXIMITY_INDEX: - Proximity_dropped ++; - if (Proximity_dropped == 4) - { - Proximity_dropped = 0; -#ifdef NETWORK - maybe_drop_net_powerup(POW_PROXIMITY_WEAPON); -#endif - } - Laser_player_fire( ConsoleObject, PROXIMITY_ID, PROXIMITY_GUN, 1, 0, orient); - break; - - case HOMING_INDEX: - Laser_player_fire( ConsoleObject, HOMING_ID, HOMING_GUN+(Missile_gun & 1), 1, 0, orient ); - Missile_gun++; - #ifdef NETWORK - maybe_drop_net_powerup(POW_HOMING_AMMO_1); - #endif - break; - -#ifndef SHAREWARE - case SMART_INDEX: - Laser_player_fire( ConsoleObject, SMART_ID, SMART_GUN, 1, 0, orient); -#ifdef NETWORK - maybe_drop_net_powerup(POW_SMARTBOMB_WEAPON); -#endif - break; - - case MEGA_INDEX: - Laser_player_fire( ConsoleObject, MEGA_ID, MEGA_GUN, 1, 0, orient); -#ifdef NETWORK - maybe_drop_net_powerup(POW_MEGA_WEAPON); -#endif - - { vms_vector force_vec; - force_vec.x = -(ConsoleObject->orient.fvec.x << 7); - force_vec.y = -(ConsoleObject->orient.fvec.y << 7); - force_vec.z = -(ConsoleObject->orient.fvec.z << 7); - phys_apply_force(ConsoleObject, &force_vec); - - force_vec.x = (force_vec.x >> 4) + d_rand() - 16384; - force_vec.y = (force_vec.y >> 4) + d_rand() - 16384; - force_vec.z = (force_vec.z >> 4) + d_rand() - 16384; - phys_apply_rot(ConsoleObject, &force_vec); - } - break; -#endif - } - -#ifdef NETWORK - if (Game_mode & GM_MULTI) - multi_send_fire(weapon+MISSILE_ADJUST, 0, (Missile_gun-1), 1, Network_laser_track); -#endif - - // don't autoselect if dropping prox and prox not current weapon - if (!drop_bomb || Secondary_weapon == PROXIMITY_INDEX) - auto_select_weapon(1); //select next missile, if this one out of ammo - } -} - -#ifdef NETWORK -void net_missile_firing(int player, int gun, int flags, vms_vector shot_orientation) /* CED sniperpackets */ -{ - /* CED sniperpackets */ - switch (gun-MISSILE_ADJUST) { - case CONCUSSION_INDEX: - Laser_player_fire( Objects+Players[player].objnum, CONCUSSION_ID, CONCUSSION_GUN+(flags & 1), 1, 0, shot_orientation ); - break; - - case PROXIMITY_INDEX: - Laser_player_fire( Objects+Players[player].objnum, PROXIMITY_ID, PROXIMITY_GUN, 1, 0, shot_orientation); - break; - - case HOMING_INDEX: - Laser_player_fire( Objects+Players[player].objnum, HOMING_ID, HOMING_GUN+(flags & 1), 1, 0, shot_orientation); - break; - - case SMART_INDEX: - Laser_player_fire( Objects+Players[player].objnum, SMART_ID, SMART_GUN, 1, 0, shot_orientation); - break; - - case MEGA_INDEX: - Laser_player_fire( Objects+Players[player].objnum, MEGA_ID, MEGA_GUN, 1, 0, shot_orientation); - break; - - case FLARE_ID: - Laser_player_fire( Objects+Players[player].objnum, FLARE_ID, 6, 1, 0, shot_orientation); - break; - - default: - break; - } - -} -#endif - - - +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +/* + * + * This will contain the laser code + * + */ + +#include +#include + +#include "inferno.h" +#include "game.h" +#include "bm.h" +#include "object.h" +#include "laser.h" +#include "segment.h" +#include "fvi.h" +#include "segpoint.h" +#include "dxxerror.h" +#include "key.h" +#include "texmap.h" +#include "textures.h" +#include "render.h" +#include "vclip.h" +#include "fireball.h" +#include "polyobj.h" +#include "robot.h" +#include "weapon.h" +#include "timer.h" +#include "player.h" +#include "sounds.h" +#include "ai.h" +#include "powerup.h" +#include "multi.h" +#include "physics.h" +#include "hudmsg.h" +#include "playsave.h" +#include "logger.h" +#include "palette.h" + +#define NEWHOMER + +int Network_laser_track = -1; + +int find_homing_object_complete(vms_vector *curpos, object *tracker, int track_obj_type1, int track_obj_type2); + +//--------------------------------------------------------------------------------- +// Called by render code.... determines if the laser is from a robot or the +// player and calls the appropriate routine. + +void Laser_render(object *obj) +{ + +// Commented out by John (sort of, typed by Mike) on 6/8/94 +#if 0 + switch( obj->id ) { + case WEAPON_TYPE_WEAK_LASER: + case WEAPON_TYPE_STRONG_LASER: + case WEAPON_TYPE_CANNON_BALL: + case WEAPON_TYPE_MISSILE: + break; + default: + RT_LOGF(RT_LOGSERVERITY_HIGH, "Invalid weapon type in Laser_render\n" ); + } +#endif + + switch( Weapon_info[obj->id].render_type ) { + case WEAPON_RENDER_LASER: + Int3(); // Not supported anymore! + //Laser_draw_one(obj-Objects, Weapon_info[obj->id].bitmap ); + break; + case WEAPON_RENDER_BLOB: + draw_object_blob(obj, Weapon_info[obj->id].bitmap ); + break; + case WEAPON_RENDER_POLYMODEL: + break; + case WEAPON_RENDER_VCLIP: + Int3(); // Oops, not supported, type added by mk on 09/09/94, but not for lasers... + default: + RT_LOG(RT_LOGSERVERITY_HIGH, "Invalid weapon render type in Laser_render\n" ); + } + +} + +//--------------------------------------------------------------------------------- +// Draws a texture-mapped laser bolt + +//void Laser_draw_one( int objnum, grs_bitmap * bmp ) +//{ +// int t1, t2, t3; +// g3s_point p1, p2; +// object *obj; +// vms_vector start_pos,end_pos; +// +// obj = &Objects[objnum]; +// +// start_pos = obj->pos; +// vm_vec_scale_add(&end_pos,&start_pos,&obj->orient.fvec,-Laser_length); +// +// g3_rotate_point(&p1,&start_pos); +// g3_rotate_point(&p2,&end_pos); +// +// t1 = Lighting_on; +// t2 = Interpolation_method; +// t3 = Transparency_on; +// +// Lighting_on = 0; +// //Interpolation_method = 3; // Full perspective +// Interpolation_method = 1; // Linear +// Transparency_on = 1; +// +// //gr_setcolor( gr_getcolor(31,15,0)); +// //g3_draw_line_ptrs(p1,p2); +// //g3_draw_rod(p1,0x2000,p2,0x2000); +// //g3_draw_rod(p1,Laser_width,p2,Laser_width); +// g3_draw_rod_tmap(bmp,&p2,Laser_width,&p1,Laser_width,0); +// Lighting_on = t1; +// Interpolation_method = t2; +// Transparency_on = t3; +// +//} + +// Changed by MK on 09/07/94 +// I want you to be able to blow up your own bombs. +// AND...Your proximity bombs can blow you up if they're 2.0 seconds or more old. +int laser_are_related( int o1, int o2 ) +{ + if ( (o1<0) || (o2<0) ) + return 0; + + // See if o2 is the parent of o1 + if ( Objects[o1].type == OBJ_WEAPON ) + if ( (Objects[o1].ctype.laser_info.parent_num==o2) && (Objects[o1].ctype.laser_info.parent_signature==Objects[o2].signature) ) + { + // o1 is a weapon, o2 is the parent of 1, so if o1 is PROXIMITY_BOMB and o2 is player, they are related only if o1 < 2.0 seconds old + if ((Objects[o1].id != PROXIMITY_ID) || (Objects[o1].ctype.laser_info.creation_time + F1_0*2 >= GameTime64)) { + return 1; + } else + return 0; + } + + // See if o1 is the parent of o2 + if ( Objects[o2].type == OBJ_WEAPON ) + if ( (Objects[o2].ctype.laser_info.parent_num==o1) && (Objects[o2].ctype.laser_info.parent_signature==Objects[o1].signature) ) + return 1; + + // They must both be weapons + if ( Objects[o1].type != OBJ_WEAPON || Objects[o2].type != OBJ_WEAPON ) + return 0; + + // Here is the 09/07/94 change -- Siblings must be identical, others can hurt each other + // See if they're siblings... + if ( Objects[o1].ctype.laser_info.parent_signature==Objects[o2].ctype.laser_info.parent_signature ) + { + if (is_proximity_bomb_or_smart_mine(Objects[o1].id) || is_proximity_bomb_or_smart_mine(Objects[o2].id)) + return 0; //if either is proximity, then can blow up, so say not related + else + return 1; + } + return 0; +} + +void do_muzzle_stuff(int segnum, vms_vector *pos, vms_vector* color) +{ + Muzzle_data[Muzzle_queue_index].create_time = timer_query(); + Muzzle_data[Muzzle_queue_index].segnum = segnum; + Muzzle_data[Muzzle_queue_index].pos = *pos; +#ifdef RT_DX12 + Muzzle_data[Muzzle_queue_index].RT_muzzleColor = *color; +#endif RT_DX12 + Muzzle_queue_index++; + if (Muzzle_queue_index >= MUZZLE_QUEUE_MAX) + Muzzle_queue_index = 0; +} + +//--------------------------------------------------------------------------------- +// Initializes a laser after Fire is pressed + +// Returns object number. +int Laser_create_new( vms_vector * direction, vms_vector * position, int segnum, int parent, int weapon_type, int make_sound ) +{ + int objnum; + object *obj; + int rtype=-1; + fix parent_speed, weapon_speed; + fix volume; + fix laser_radius = -1; + fix laser_length=0; + + Assert( weapon_type < N_weapon_types ); + + if ( (weapon_type<0) || (weapon_type>=N_weapon_types) ) + weapon_type = 0; + + switch( Weapon_info[weapon_type].render_type ) { + case WEAPON_RENDER_BLOB: + rtype = RT_LASER; // Render as a laser even if blob (see render code above for explanation) + laser_radius = Weapon_info[weapon_type].blob_size; + laser_length = 0; + break; + case WEAPON_RENDER_POLYMODEL: + laser_radius = 0; // Filled in below. + rtype = RT_POLYOBJ; + break; + case WEAPON_RENDER_LASER: + Int3(); // Not supported anymore + break; + case WEAPON_RENDER_NONE: + rtype = RT_NONE; + laser_radius = F1_0; + laser_length = 0; + break; + case WEAPON_RENDER_VCLIP: + rtype = RT_WEAPON_VCLIP; + laser_radius = Weapon_info[weapon_type].blob_size; + laser_length = 0; + break; + default: + RT_LOG(RT_LOGSERVERITY_HIGH, "Invalid weapon render type in Laser_create_new\n" ); + } + + // Add to object list + Assert(laser_radius != -1); + Assert(rtype != -1); + objnum = obj_create( OBJ_WEAPON, weapon_type, segnum, position, NULL, laser_radius, CT_WEAPON, MT_PHYSICS, rtype ); + + if ( objnum < 0 ) { + Int3(); + return -1; + } + + obj = &Objects[objnum]; + + if (Objects[parent].type == OBJ_PLAYER) { + if (weapon_type == FUSION_ID) { + int fusion_scale; + + if (Game_mode & GM_MULTI) + fusion_scale = 2; + else + fusion_scale = 4; + + if (Fusion_charge <= 0) + obj->ctype.laser_info.multiplier = F1_0; + else if (Fusion_charge <= F1_0*fusion_scale) + obj->ctype.laser_info.multiplier = F1_0 + Fusion_charge/2; + else + obj->ctype.laser_info.multiplier = F1_0*fusion_scale; + + // Fusion damage was boosted by mk on 3/27 (for reg 1.1 release), but we only want it to apply to single player games. + if (Game_mode & GM_MULTI) + obj->ctype.laser_info.multiplier /= 2; + } else if ((weapon_type == LASER_ID) && (Players[Objects[parent].id].flags & PLAYER_FLAGS_QUAD_LASERS)) + obj->ctype.laser_info.multiplier = F1_0*3/4; + } + + + // This is strange: Make children of smart bomb bounce so if they hit a wall right away, they + // won't detonate. The frame interval code will clear this bit after 1/2 second. + if ((weapon_type == PLAYER_SMART_HOMING_ID) || (weapon_type == ROBOT_SMART_HOMING_ID)) + obj->mtype.phys_info.flags |= PF_BOUNCE; + + if (Weapon_info[weapon_type].render_type == WEAPON_RENDER_POLYMODEL) { + obj->rtype.pobj_info.model_num = Weapon_info[obj->id].model_num; + laser_radius = fixdiv(Polygon_models[obj->rtype.pobj_info.model_num].rad,Weapon_info[obj->id].po_len_to_width_ratio); + laser_length = Polygon_models[obj->rtype.pobj_info.model_num].rad * 2; + obj->size = laser_radius; + } + + obj->mtype.phys_info.mass = Weapon_info[weapon_type].mass; + obj->mtype.phys_info.drag = Weapon_info[weapon_type].drag; + if (Weapon_info[weapon_type].bounce) + obj->mtype.phys_info.flags |= PF_BOUNCE; + + vm_vec_zero(&obj->mtype.phys_info.thrust); + + if (weapon_type == FLARE_ID) + obj->mtype.phys_info.flags |= PF_STICK; //this obj sticks to walls + + obj->shields = Weapon_info[obj->id].strength[Difficulty_level]; + + // Fill in laser-specific data + + obj->lifeleft = Weapon_info[obj->id].lifetime; + obj->ctype.laser_info.parent_type = Objects[parent].type; + obj->ctype.laser_info.parent_signature = Objects[parent].signature; + obj->ctype.laser_info.parent_num = parent; + + // Assign parent type to highest level creator. This propagates parent type down from + // the original creator through weapons which create children of their own (ie, smart missile) + if (Objects[parent].type == OBJ_WEAPON) { + int highest_parent = parent; + + while (Objects[highest_parent].type == OBJ_WEAPON) { + highest_parent = Objects[highest_parent].ctype.laser_info.parent_num; + obj->ctype.laser_info.parent_num = highest_parent; + obj->ctype.laser_info.parent_type = Objects[highest_parent].type; + obj->ctype.laser_info.parent_signature = Objects[highest_parent].signature; + } + } + + // Create orientation matrix so we can look from this pov + // Homing missiles also need an orientation matrix so they know if they can make a turn. + if ((obj->render_type == RT_POLYOBJ) || (Weapon_info[obj->id].homing_flag)) + vm_vector_2_matrix( &obj->orient,direction, &Objects[parent].orient.uvec ,NULL); + + if (( &Objects[parent] != Viewer ) && (Objects[parent].type != OBJ_WEAPON)) { + // Muzzle flash + if (Weapon_info[obj->id].flash_vclip > -1 ) + object_create_muzzle_flash( obj->segnum, &obj->pos, Weapon_info[obj->id].flash_size, Weapon_info[obj->id].flash_vclip ); + } + +// Re-enable, 09/09/94: + volume = F1_0; + if (Weapon_info[obj->id].flash_sound > -1 ) { + if (make_sound) { + if ( parent == (Viewer-Objects) ) { + if (weapon_type == VULCAN_ID) // Make your own vulcan gun 1/2 as loud. + volume = F1_0 / 2; + if(weapon_type == PLASMA_ID && PlayerCfg.QuietPlasma) // Plasma's a bit loud, too + volume = F1_0 * 3 / 4; + digi_play_sample( Weapon_info[obj->id].flash_sound, volume ); + } else { + if(weapon_type == PLASMA_ID && PlayerCfg.QuietPlasma) // Plasma's a bit loud, too + volume = F1_0 * 3 / 4; + + if(Weapon_info[obj->id].flash_sound == 22) { // Reactor ball + if ((Game_mode & GM_OBSERVER) != 0) + volume = F1_0 * 3 / 16; + else + volume = F1_0 * 3 / 4; + } + + digi_link_sound_to_pos( Weapon_info[obj->id].flash_sound, obj->segnum, 0, &obj->pos, 0, volume ); + } + } + } + + // WARNING! NOTE! HEY! DEBUG! ETC! --MK 10/26/94 + // This is John's new code to fire the laser from the gun tip so that the back end of the laser bolt is + // at the gun tip. A problem that needs to be fixed is that the laser bolt might be in another segment. + // Use find_vector_interesection to detect the segment. + + // Move 1 frame, so that the end-tip of the laser is touching the gun barrel. + // This also jitters the laser a bit so that it doesn't alias. + // Don't do for weapons created by weapons. + if ((Objects[parent].type != OBJ_WEAPON) && (Weapon_info[weapon_type].render_type != WEAPON_RENDER_NONE) && (weapon_type != FLARE_ID)) { +// if ((Objects[parent].type != OBJ_WEAPON) && (weapon_type != FLARE_ID) ) { + vms_vector end_pos; + int end_segnum; + + vm_vec_scale_add( &end_pos, &obj->pos, direction, (laser_length/2) ); + end_segnum = find_point_seg(&end_pos, obj->segnum); + if (end_segnum != obj->segnum) { + if (end_segnum != -1) { + obj->pos = end_pos; + obj_relink(obj-Objects, end_segnum); + } + } else + obj->pos = end_pos; + } + + // Here's where to fix the problem with objects which are moving backwards imparting higher velocity to their weaponfire. + // Find out if moving backwards. + if (is_proximity_bomb_or_smart_mine(weapon_type)) { + parent_speed = vm_vec_mag_quick(&Objects[parent].mtype.phys_info.velocity); + if (vm_vec_dot(&Objects[parent].mtype.phys_info.velocity, &Objects[parent].orient.fvec) < 0) + parent_speed = -parent_speed; +// if(parent_speed>(F1_0*60)) +// parent_speed=F1_0*1600; +/* { char *murp; + sprintf(murp,"%i.%i",parent_speed>>16,(parent_speed<<16)>>16); + nm_messagebox(NULL,1,"OK",murp); + }*/ + } else + parent_speed = 0; + + weapon_speed = Weapon_info[obj->id].speed[Difficulty_level]; + + // Ugly hack (too bad we're on a deadline), for homing missiles dropped by smart bomb, start them out slower. + if ((obj->id == PLAYER_SMART_HOMING_ID) || (obj->id == ROBOT_SMART_HOMING_ID)) + weapon_speed /= 4; + + if (Weapon_info[obj->id].thrust != 0) + weapon_speed /= 2; + + vm_vec_copy_scale( &obj->mtype.phys_info.velocity, direction, weapon_speed + parent_speed ); + + // Set thrust + if (Weapon_info[weapon_type].thrust != 0) { + obj->mtype.phys_info.thrust = obj->mtype.phys_info.velocity; + vm_vec_scale(&obj->mtype.phys_info.thrust, fixdiv(Weapon_info[obj->id].thrust, weapon_speed+parent_speed)); + } + +// THIS CODE MAY NOT BE NEEDED... it was used to move the lasers out of the gun, since the +// laser pos is acutally the head of the laser, and we want the tail to be at the starting +// point, not the head. +// object_move_one( obj ); +// This next, apparently redundant line, appears necessary due to a hack in render.c +// obj->lifeleft = Weapon_info[obj->id].lifetime; + + if ((obj->type == OBJ_WEAPON) && (obj->id == FLARE_ID)) + obj->lifeleft += (d_rand()-16384) << 2; // add in -2..2 seconds + + + + // Don't let homing blobs make muzzle flash. + if (Objects[parent].type == OBJ_ROBOT || Objects[parent].type == OBJ_PLAYER) + { + vms_vector lasercolor = {0}; + polymodel* polyModel = &Polygon_models[obj->rtype.pobj_info.model_num]; + + polymodel* po = &Polygon_models[obj->rtype.pobj_info.model_num]; + if (po->n_textures <= 0) + { + int color = g3_poly_get_color(po->model_data); + if (color) + { + lasercolor.x = gr_current_pal[color * 3] * 500; + lasercolor.y = gr_current_pal[color * 3 + 1] * 500; + lasercolor.z = gr_current_pal[color * 3 + 2] * 500; + } + } + + do_muzzle_stuff(segnum, position, &lasercolor); + } + + + + return objnum; +} + +// ----------------------------------------------------------------------------------------------------------- +// Calls Laser_create_new, but takes care of the segment and point computation for you. +int Laser_create_new_easy( vms_vector * direction, vms_vector * position, int parent, int weapon_type, int make_sound ) +{ + fvi_query fq; + fvi_info hit_data; + object *pobjp = &Objects[parent]; + int fate; + + // Find segment containing laser fire position. If the robot is straddling a segment, the position from + // which it fires may be in a different segment, which is bad news for find_vector_intersection. So, cast + // a ray from the object center (whose segment we know) to the laser position. Then, in the call to Laser_create_new + // use the data returned from this call to find_vector_intersection. + // Note that while find_vector_intersection is pretty slow, it is not terribly slow if the destination point is + // in the same segment as the source point. + + fq.p0 = &pobjp->pos; + fq.startseg = pobjp->segnum; + fq.p1 = position; + fq.rad = 0; + fq.thisobjnum = pobjp-Objects; + fq.ignore_obj_list = NULL; + fq.flags = FQ_TRANSWALL | FQ_CHECK_OBJS; //what about trans walls??? + + fate = find_vector_intersection(&fq, &hit_data); + if (fate != HIT_NONE || hit_data.hit_seg==-1) { + return -1; + } + + return Laser_create_new( direction, &hit_data.hit_pnt, hit_data.hit_seg, parent, weapon_type, make_sound ); + +} + +int Muzzle_queue_index = 0; + +muzzle_info Muzzle_data[MUZZLE_QUEUE_MAX]; + +// ----------------------------------------------------------------------------------------------------------- +// Determine if two objects are on a line of sight. If so, return true, else return false. +// Calls fvi. +int object_to_object_visibility(object *obj1, object *obj2, int trans_type) +{ + fvi_query fq; + fvi_info hit_data; + int fate; + + fq.p0 = &obj1->pos; + fq.startseg = obj1->segnum; + fq.p1 = &obj2->pos; + fq.rad = 0x10; + fq.thisobjnum = obj1-Objects; + fq.ignore_obj_list = NULL; + fq.flags = trans_type; + + fate = find_vector_intersection(&fq, &hit_data); + + if (fate == HIT_WALL) + return 0; + else if (fate == HIT_NONE) + return 1; + else + Int3(); // Contact Mike: Oops, what happened? What is fate? + // 2 = hit object (impossible), 3 = bad starting point (bad) + + return 0; +} + +fix Min_trackable_dot = 3*(F1_0 - MIN_TRACKABLE_DOT)/4 + MIN_TRACKABLE_DOT; //MIN_TRACKABLE_DOT; + +// ----------------------------------------------------------------------------------------------------------- +// Return true if weapon *tracker is able to track object Objects[track_goal], else return false. +// In order for the object to be trackable, it must be within a reasonable turning radius for the missile +// and it must not be obstructed by a wall. +int object_is_trackable(int track_goal, object *tracker, fix *dot) +{ + vms_vector vector_to_goal; + object *objp; + + if (track_goal == -1) + return 0; + + if (Game_mode & GM_MULTI_COOP) + return 0; + + objp = &Objects[track_goal]; + + // Don't track player if he's cloaked. + if ((track_goal == Players[Player_num].objnum) && (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED)) + return 0; + + // Can't track AI object if he's cloaked. + if (objp->type == OBJ_ROBOT) + if (objp->ctype.ai_info.CLOAKED) + return 0; + + vm_vec_sub(&vector_to_goal, &objp->pos, &tracker->pos); + vm_vec_normalize_quick(&vector_to_goal); + *dot = vm_vec_dot(&vector_to_goal, &tracker->orient.fvec); + + if ((*dot < Min_trackable_dot) && (*dot > F1_0*9/10)) { + vm_vec_normalize(&vector_to_goal); + *dot = vm_vec_dot(&vector_to_goal, &tracker->orient.fvec); + } + + if (*dot >= Min_trackable_dot) { + int rval; + // dot is in legal range, now see if object is visible + rval = object_to_object_visibility(tracker, objp, FQ_TRANSWALL); + return rval; + } else { + return 0; + } +} + +// -------------------------------------------------------------------------------------------- +// Find object to home in on. +// Scan list of objects rendered last frame, find one that satisfies function of nearness to center and distance. +int find_homing_object(vms_vector *curpos, object *tracker) +{ + int i; + fix max_dot = -F1_0*2; + int best_objnum = -1; + + if (!Weapon_info[tracker->id].homing_flag) { + Int3(); // Contact Mike: This is a bad and stupid thing. Who called this routine with an illegal laser type?? + return 0; // Track the damn stupid player for causing this problem! + } + + // Find an object to track based on game mode (eg, whether in network play) and who fired it. + if (Game_mode & GM_MULTI) { + // In network mode. + if (tracker->ctype.laser_info.parent_type == OBJ_PLAYER) { + // It's fired by a player, so if robots present, track robot, else track player. + if (Game_mode & GM_MULTI_COOP) + return find_homing_object_complete( curpos, tracker, OBJ_ROBOT, -1); + else + return find_homing_object_complete( curpos, tracker, OBJ_PLAYER, OBJ_ROBOT); + } else { + Assert(tracker->ctype.laser_info.parent_type == OBJ_ROBOT); + return find_homing_object_complete(curpos, tracker, OBJ_PLAYER, -1); + } + } + else { + // Not in network mode. If not fired by player, then track player. + if (tracker->ctype.laser_info.parent_num != Players[Player_num].objnum) { + if (!(Players[Player_num].flags & PLAYER_FLAGS_CLOAKED)) + best_objnum = ConsoleObject - Objects; + } else { + // Not in network mode and fired by player. + for (i=Num_rendered_objects-1; i>=0; i--) { + fix dot; //, dist; + vms_vector vec_to_curobj; + int objnum = Ordered_rendered_object_list[i]; + object *curobjp = &Objects[objnum]; + + if (objnum == Players[Player_num].objnum) + continue; + + // Can't track AI object if he's cloaked. + if (curobjp->type == OBJ_ROBOT) + if (curobjp->ctype.ai_info.CLOAKED) + continue; + + vm_vec_sub(&vec_to_curobj, &curobjp->pos, curpos); + vm_vec_normalize_quick(&vec_to_curobj); + dot = vm_vec_dot(&vec_to_curobj, &tracker->orient.fvec); + + // Note: This uses the constant, not-scaled-by-frametime value, because it is only used + // to determine if an object is initially trackable. find_homing_object is called on subsequent + // frames to determine if the object remains trackable. + if (dot > MIN_TRACKABLE_DOT) { + if (dot > max_dot) { + if (object_to_object_visibility(tracker, &Objects[objnum], FQ_TRANSWALL)) { + max_dot = dot; + best_objnum = objnum; + } + } + } + } + } + } + + return best_objnum; +} + +// -------------------------------------------------------------------------------------------- +// Find object to home in on. +// Scan list of objects rendered last frame, find one that satisfies function of nearness to center and distance. +// Can track two kinds of objects. If you are only interested in one type, set track_obj_type2 to NULL +int find_homing_object_complete(vms_vector *curpos, object *tracker, int track_obj_type1, int track_obj_type2) +{ + int objnum; + fix max_dot = -F1_0*2; + int best_objnum = -1; + + fix max_trackable_dist = MAX_TRACKABLE_DIST; + fix min_trackable_dot = MIN_TRACKABLE_DOT; + + if (!Weapon_info[tracker->id].homing_flag) { + Int3(); // Contact Mike: This is a bad and stupid thing. Who called this routine with an illegal laser type?? + return 0; // Track the damn stupid player for causing this problem! + } + + for (objnum=0; objnum<=Highest_object_index; objnum++) { + int is_proximity = 0; + fix dot, dist; + vms_vector vec_to_curobj; + object *curobjp = &Objects[objnum]; + + if ((curobjp->type != track_obj_type1) && (curobjp->type != track_obj_type2)) + { + if ((curobjp->type == OBJ_WEAPON) && (is_proximity_bomb_or_smart_mine(curobjp->id))) { + if (curobjp->ctype.laser_info.parent_signature != tracker->ctype.laser_info.parent_signature) + is_proximity = 1; + else + continue; + } else + continue; + } + + if (objnum == tracker->ctype.laser_info.parent_num) // Don't track shooter + continue; + + // Don't track cloaked players. + if (curobjp->type == OBJ_PLAYER) + { + if (Players[curobjp->id].flags & PLAYER_FLAGS_CLOAKED) + continue; + // Don't track teammates in team games + #ifdef NETWORK + if ((Game_mode & GM_TEAM) && (Objects[tracker->ctype.laser_info.parent_num].type == OBJ_PLAYER) && (get_team(curobjp->id) == get_team(Objects[tracker->ctype.laser_info.parent_num].id))) + continue; + #endif + } + + // Can't track AI object if he's cloaked. + if (curobjp->type == OBJ_ROBOT) + if (curobjp->ctype.ai_info.CLOAKED) + continue; + + vm_vec_sub(&vec_to_curobj, &curobjp->pos, curpos); + dist = vm_vec_mag(&vec_to_curobj); + + if (dist < max_trackable_dist) { + vm_vec_normalize(&vec_to_curobj); + dot = vm_vec_dot(&vec_to_curobj, &tracker->orient.fvec); + if (is_proximity) + continue; // CED -- don't track proxies + //dot = ((dot << 3) + dot) >> 3; // I suspect Watcom would be too stupid to figure out the obvious... + + // Note: This uses the constant, not-scaled-by-frametime value, because it is only used + // to determine if an object is initially trackable. find_homing_object is called on subsequent + // frames to determine if the object remains trackable. + if (dot > min_trackable_dot) { + if (dot > max_dot) { + if (object_to_object_visibility(tracker, &Objects[objnum], FQ_TRANSWALL)) { + max_dot = dot; + best_objnum = objnum; + } + } + } + } + + } + + return best_objnum; +} + +// ------------------------------------------------------------------------------------------------------------ +// See if legal to keep tracking currently tracked object. If not, see if another object is trackable. If not, return -1, +// else return object number of tracking object. +int track_track_goal(int track_goal, object *tracker, fix *dot, unsigned int homerFrameCount) +{ +#ifdef NEWHOMER + if (object_is_trackable(track_goal, tracker, dot)) { // CED -- && (tracker - Objects) is useless + return track_goal; + } else if ((((tracker-Objects) ^ homerFrameCount) % 4) == 0) // CED -- Reverted to 1994 original release code, with homer frame count +#else + // Every 8 frames for each object, scan all objects. + if (object_is_trackable(track_goal, tracker, dot) && ((((tracker-Objects) ^ d_tick_count) % 8) != 0)) { + return track_goal; + } else if ((((tracker-Objects) ^ d_tick_count) % 4) == 0) +#endif + { + int rval = -2; + + // If player fired missile, then search for an object, if not, then give up. + if (Objects[tracker->ctype.laser_info.parent_num].type == OBJ_PLAYER) { + int goal_type; + + if (track_goal == -1) + { + if (Game_mode & GM_MULTI) + { + if (Game_mode & GM_MULTI_COOP) + rval = find_homing_object_complete( &tracker->pos, tracker, OBJ_ROBOT, -1); + else if (Game_mode & GM_MULTI_ROBOTS) // Not cooperative, if robots, track either robot or player + rval = find_homing_object_complete( &tracker->pos, tracker, OBJ_PLAYER, OBJ_ROBOT); + else // Not cooperative and no robots, track only a player + rval = find_homing_object_complete( &tracker->pos, tracker, OBJ_PLAYER, -1); + } + else + rval = find_homing_object_complete(&tracker->pos, tracker, OBJ_PLAYER, OBJ_ROBOT); + } + else + { + goal_type = Objects[tracker->ctype.laser_info.track_goal].type; + if ((goal_type == OBJ_PLAYER) || (goal_type == OBJ_ROBOT)) + rval = find_homing_object_complete(&tracker->pos, tracker, goal_type, -1); + else + rval = -1; + } + } + else { + int goal_type; + + if (track_goal == -1) + rval = find_homing_object_complete(&tracker->pos, tracker, OBJ_PLAYER, -1); + else { + goal_type = Objects[tracker->ctype.laser_info.track_goal].type; + rval = find_homing_object_complete(&tracker->pos, tracker, goal_type, -1); + } + } + + Assert(rval != -2); // This means it never got set which is bad! Contact Mike. + return rval; + } + + return -1; +} + + +//-------------- Initializes a laser after Fire is pressed ----------------- + +void Laser_player_fire_spread_delay(object *obj, int laser_type, int gun_num, fix spreadr, fix spreadu, fix delay_time, int make_sound, int harmless, vms_vector shot_orientation) +{ + int LaserSeg, Fate; + vms_vector LaserPos, LaserDir; + fvi_query fq; + fvi_info hit_data; + vms_vector gun_point, *pnt; + vms_matrix m; + int objnum; + + // Find the initial position of the laser + pnt = &Player_ship->gun_points[gun_num]; + + // double gx = (double)(pnt->x) / (double)(F1_0); + // double gy = (double)(pnt->y) / (double)(F1_0); + // double gz = (double)(pnt->z) / (double)(F1_0); + // RT_LOGF(RT_LOGSERVERITY_MEDIUM, "Creating weapon at offset %f, %f, %f\n", gx, gy, gz); + + vm_copy_transpose_matrix(&m,&obj->orient); + vm_vec_rotate(&gun_point,pnt,&m); + + vm_vec_add(&LaserPos,&obj->pos,&gun_point); + + // If supposed to fire at a delayed time (delay_time), then move this point backwards. + if (delay_time) + /* CED sniperpackets */ + //vm_vec_scale_add2(&LaserPos, &obj->orient.fvec, -fixmul(delay_time, Weapon_info[laser_type].speed[Difficulty_level])); + vm_vec_scale_add2(&LaserPos, &shot_orientation, -fixmul(delay_time, Weapon_info[laser_type].speed[Difficulty_level])); + +// do_muzzle_stuff(obj, &Pos); + + //--------------- Find LaserPos and LaserSeg ------------------ + fq.p0 = &obj->pos; + fq.startseg = obj->segnum; + fq.p1 = &LaserPos; + fq.rad = 0x10; + fq.thisobjnum = obj-Objects; + fq.ignore_obj_list = NULL; + fq.flags = FQ_CHECK_OBJS; + + Fate = find_vector_intersection(&fq, &hit_data); + + LaserSeg = hit_data.hit_seg; + + if (LaserSeg == -1) //some sort of annoying error + return; + + //SORT OF HACK... IF ABOVE WAS CORRECT THIS WOULDNT BE NECESSARY. + if ( vm_vec_dist_quick(&LaserPos, &obj->pos) > 0x50000 ) + return; + + if (Fate==HIT_WALL) { + return; + } + + if (Fate==HIT_OBJECT) { +// if ( Objects[hit_data.hit_object].type == OBJ_ROBOT ) +// Objects[hit_data.hit_object].flags |= OF_SHOULD_BE_DEAD; +// if ( Objects[hit_data.hit_object].type != OBJ_POWERUP ) +// return; + //as of 12/6/94, we don't care if the laser is stuck in an object. We + //just fire away normally + } + + // Now, make laser spread out. + LaserDir = shot_orientation; /* CED sniperpackets */ //obj->orient.fvec; + if ((spreadr != 0) || (spreadu != 0)) { + vm_vec_scale_add2(&LaserDir, &obj->orient.rvec, spreadr); + vm_vec_scale_add2(&LaserDir, &obj->orient.uvec, spreadu); + } + + objnum = Laser_create_new( &LaserDir, &LaserPos, LaserSeg, obj-Objects, laser_type, make_sound ); + if (objnum == -1) + return; + + // If this weapon is supposed to be silent, set that bit! + if (!make_sound) + Objects[objnum].flags |= OF_SILENT; + + // If this weapon is supposed to be harmless, set that bit! + if (harmless) + Objects[objnum].flags |= OF_HARMLESS; + + // If the object firing the laser is the player, then indicate the laser object so robots can dodge. + if (obj == ConsoleObject) + Player_fired_laser_this_frame = objnum; + + if (Weapon_info[laser_type].homing_flag) { + if (obj == ConsoleObject) + { + Objects[objnum].ctype.laser_info.track_goal = find_homing_object(&LaserPos, &Objects[objnum]); + #ifdef NETWORK + Network_laser_track = Objects[objnum].ctype.laser_info.track_goal; + #endif + } + #ifdef NETWORK + else // Some other player shot the homing thing + { + Assert(Game_mode & GM_MULTI); + Objects[objnum].ctype.laser_info.track_goal = Network_laser_track; + } + #endif + } +} + +// ----------------------------------------------------------------------------------------------------------- +void Laser_player_fire_spread(object *obj, int laser_type, int gun_num, fix spreadr, fix spreadu, int make_sound, int harmless, vms_vector shot_orientation) +{ + Laser_player_fire_spread_delay(obj, laser_type, gun_num, spreadr, spreadu, 0, make_sound, harmless, shot_orientation); /* CED sniperpackets */ +} + + +// ----------------------------------------------------------------------------------------------------------- +void Laser_player_fire(object *obj, int laser_type, int gun_num, int make_sound, int harmless, vms_vector shot_orientation) +{ + Laser_player_fire_spread(obj, laser_type, gun_num, 0, 0, make_sound, harmless, shot_orientation); /* CED sniperpackets */ +} + +// ----------------------------------------------------------------------------------------------------------- +void Flare_create(object *obj) +{ + fix energy_usage; + + energy_usage = Weapon_info[FLARE_ID].energy_usage; + + if (Difficulty_level < 2) + energy_usage = fixmul(energy_usage, i2f(Difficulty_level+2)/4); + + if (Players[Player_num].energy > 0) { + Players[Player_num].energy -= energy_usage; + + if (Players[Player_num].energy <= 0) { + Players[Player_num].energy = 0; + auto_select_weapon(0); + } + + Laser_player_fire( obj, FLARE_ID, 6, 1, 0, Objects[Players[Player_num].objnum].orient.fvec); /* CED sniperpackets */ + + #ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_fire(FLARE_ID+MISSILE_ADJUST, 0, 0, 1, -1); + #endif + } + +} + +#define HOMING_MISSILE_SCALE 8 + +//------------------------------------------------------------------------------------------- +// Set object *objp's orientation to (or towards if I'm ambitious) its velocity. +void homing_missile_turn_towards_velocity(object *objp, vms_vector *norm_vel) +{ + vms_vector new_fvec; + + new_fvec = *norm_vel; + + vm_vec_scale(&new_fvec, FrameTime * HOMING_MISSILE_SCALE); + vm_vec_add2(&new_fvec, &objp->orient.fvec); + vm_vec_normalize_quick(&new_fvec); + +// if ((norm_vel->x == 0) && (norm_vel->y == 0) && (norm_vel->z == 0)) +// return; + + vm_vector_2_matrix(&objp->orient, &new_fvec, NULL, NULL); +} + +#ifdef NEWHOMER +/* + * In the original game homers turned sharper in higher FPS-values. We do not want that so we need to scale vector_to_object to FrameTime. + * For each difficulty setting we have a base value the homers will align to. This we express in a FPS value representing the homers turn radius of the original game (i.e. "The homer will turn like on XXFPS"). + * NOTE: Old homers only get valid track_goal every 8 frames. This does not apply anymore so these values are divided by 4 to compensate this. + */ +fix homing_turn_base[NDL] = { 4, 5, 6, 7, 8 }; +#endif + +//------------------------------------------------------------------------------------------- +//sequence this laser object for this _frame_ (underscores added here to aid MK in his searching!) +void Laser_do_weapon_sequence(object *obj, int doHomerFrame, fix idealHomerFrameTime, unsigned int homerFrameCount) +{ + Assert(obj->control_type == CT_WEAPON); + + if (obj->lifeleft < 0 ) { // We died of old age + obj->flags |= OF_SHOULD_BE_DEAD; + if ( Weapon_info[obj->id].damage_radius ) + explode_badass_weapon(obj); + return; + } + + //delete weapons that are not moving + if ( !((d_tick_count ^ obj->signature) & 3) && + (obj->id != FLARE_ID) && + (Weapon_info[obj->id].speed[Difficulty_level] > 0) && + (vm_vec_mag_quick(&obj->mtype.phys_info.velocity) < F2_0)) { + obj_delete(obj-Objects); + return; + } + + if ( obj->id == FUSION_ID ) { //always set fusion weapon to max vel + + vm_vec_normalize_quick(&obj->mtype.phys_info.velocity); + + vm_vec_scale(&obj->mtype.phys_info.velocity, Weapon_info[obj->id].speed[Difficulty_level]); + } + + // For homing missiles, turn towards target. + if (Weapon_info[obj->id].homing_flag) { + vms_vector vector_to_object, temp_vec; + fix dot=F1_0; + fix speed, max_speed; + + // For first 1/2 second of life, missile flies straight. + if (obj->ctype.laser_info.creation_time + HOMING_MISSILE_STRAIGHT_TIME < GameTime64) { + + int track_goal = obj->ctype.laser_info.track_goal; + + // If it's time to do tracking, then it's time to grow up, stop bouncing and start exploding!. + if ((obj->id == ROBOT_SMART_HOMING_ID) || (obj->id == PLAYER_SMART_HOMING_ID)) { + obj->mtype.phys_info.flags &= ~PF_BOUNCE; + } + + // Make sure the object we are tracking is still trackable. + if(doHomerFrame) { + track_goal = track_track_goal(track_goal, obj, &dot, homerFrameCount); + + + if (track_goal == Players[Player_num].objnum) { + fix dist_to_player; + + dist_to_player = vm_vec_dist_quick(&obj->pos, &Objects[track_goal].pos); + if ((dist_to_player < Players[Player_num].homing_object_dist) || (Players[Player_num].homing_object_dist < 0)) + Players[Player_num].homing_object_dist = dist_to_player; + + } + } + + if ((track_goal != -1) && doHomerFrame) { +// CED -- I'm going to mod the NEWHOMER to keep the diffs clean, even though that's confusing +// This should be refactored if we decide to keep the change. +#ifdef NEWHOMER + vm_vec_sub(&vector_to_object, &Objects[track_goal].pos, &obj->pos); + + vm_vec_normalize_quick(&vector_to_object); + temp_vec = obj->mtype.phys_info.velocity; + speed = vm_vec_normalize(&temp_vec); + max_speed = Weapon_info[obj->id].speed[Difficulty_level]; + if (speed+F1_0 < max_speed) { + speed += fixmul(max_speed, idealHomerFrameTime/2); // CED + if (speed > max_speed) + speed = max_speed; + } + + // Scale vector to object to current FrameTime. + // CED -- Removed + //vm_vec_scale(&vector_to_object, F1_0/((float)(F1_0/homing_turn_base[Difficulty_level])/FrameTime)); + + vm_vec_add2(&temp_vec, &vector_to_object); + // The boss' smart children track better... + if (Weapon_info[obj->id].render_type != WEAPON_RENDER_POLYMODEL) + vm_vec_add2(&temp_vec, &vector_to_object); + vm_vec_normalize(&temp_vec); + vm_vec_scale(&temp_vec, speed); + obj->mtype.phys_info.velocity = temp_vec; + + // Subtract off life proportional to amount turned. + // For hardest turn, it will lose 2 seconds per second. + { + fix lifelost, absdot; + + absdot = abs(F1_0 - dot); + + lifelost = fixmul(absdot*32, idealHomerFrameTime); // CED -- did anyone even know they did this? + obj->lifeleft -= lifelost; + } + + // Only polygon objects have visible orientation, so only they should turn. + if (Weapon_info[obj->id].render_type == WEAPON_RENDER_POLYMODEL) + homing_missile_turn_towards_velocity(obj, &temp_vec); // temp_vec is normalized velocity. +#else // OLD - ORIGINAL - MISSILE TRACKING CODE +/* // CED -- pardon the comment -- I keep looking at the wrong code + vm_vec_sub(&vector_to_object, &Objects[track_goal].pos, &obj->pos); + + vm_vec_normalize_quick(&vector_to_object); + temp_vec = obj->mtype.phys_info.velocity; + speed = vm_vec_normalize_quick(&temp_vec); + max_speed = Weapon_info[obj->id].speed[Difficulty_level]; + if (speed+F1_0 < max_speed) { + speed += fixmul(max_speed, FrameTime/2); + if (speed > max_speed) + speed = max_speed; + } + + dot = vm_vec_dot(&temp_vec, &vector_to_object); + + vm_vec_add2(&temp_vec, &vector_to_object); + // The boss' smart children track better... + if (Weapon_info[obj->id].render_type != WEAPON_RENDER_POLYMODEL) + vm_vec_add2(&temp_vec, &vector_to_object); + vm_vec_normalize_quick(&temp_vec); + vm_vec_scale(&temp_vec, speed); + obj->mtype.phys_info.velocity = temp_vec; + + // Subtract off life proportional to amount turned. + // For hardest turn, it will lose 2 seconds per second. + { + fix lifelost, absdot; + + absdot = abs(F1_0 - dot); + + if (absdot > F1_0/8) { + if (absdot > F1_0/4) + absdot = F1_0/4; + lifelost = fixmul(absdot*16, FrameTime); + obj->lifeleft -= lifelost; + } + //added 8/14/98 by Victor Rachels to make homers lose life while going straight, too + obj->lifeleft -= fixmul(F1_0, FrameTime); + //end addition - Victor Rachels + } + + // Only polygon objects have visible orientation, so only they should turn. + if (Weapon_info[obj->id].render_type == WEAPON_RENDER_POLYMODEL) + homing_missile_turn_towards_velocity(obj, &temp_vec); // temp_vec is normalized velocity. +*/ +#endif + } + } + } + + // Make sure weapon is not moving faster than allowed speed. + if (Weapon_info[obj->id].thrust != 0) { + fix weapon_speed; + + weapon_speed = vm_vec_mag_quick(&obj->mtype.phys_info.velocity); + if (weapon_speed > Weapon_info[obj->id].speed[Difficulty_level]) { + fix scale_factor; + + scale_factor = fixdiv(Weapon_info[obj->id].speed[Difficulty_level], weapon_speed); + vm_vec_scale(&obj->mtype.phys_info.velocity, scale_factor); + } + + } +} + +int Spreadfire_toggle=0; +fix64 Last_laser_fired_time = 0; + +extern int Player_fired_laser_this_frame; + +// -------------------------------------------------------------------------------------------------- +// Assumption: This is only called by the actual console player, not for +// network players + +void do_laser_firing_player(void) +{ + player *plp = &Players[Player_num]; + fix energy_used; + int ammo_used; + int weapon_index; + int rval = 0; + int nfires = 1; + + if (Player_is_dead) + return; + + weapon_index = Primary_weapon_to_weapon_info[Primary_weapon]; + energy_used = Weapon_info[weapon_index].energy_usage; + + if (Difficulty_level < 2) + energy_used = fixmul(energy_used, i2f(Difficulty_level+2)/4); + + ammo_used = Weapon_info[weapon_index].ammo_usage; + + while (Next_laser_fire_time <= GameTime64) { + if ((plp->energy >= energy_used) || ((Primary_weapon == VULCAN_INDEX) && (plp->primary_ammo[Primary_weapon] >= ammo_used)) ) { + int laser_level, flags, fire_frame_overhead = 0; + + if (GameTime64 - Next_laser_fire_time <= FrameTime) // if firing is prolonged by FrameTime overhead, let's try to fix that. + fire_frame_overhead = GameTime64 - Next_laser_fire_time; + + Last_laser_fired_time = GameTime64; + + if (!cheats.rapidfire) + Next_laser_fire_time = GameTime64 + Weapon_info[weapon_index].fire_wait - fire_frame_overhead; + else + Next_laser_fire_time = GameTime64 + (F1_0/25) - fire_frame_overhead; + + laser_level = Players[Player_num].laser_level; + + flags = 0; + + if (Primary_weapon == SPREADFIRE_INDEX) { + if (Spreadfire_toggle) + flags |= LASER_SPREADFIRE_TOGGLED; + Spreadfire_toggle = !Spreadfire_toggle; + } + + if (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS) + flags |= LASER_QUAD; + + /* CED sniperpackets */ + rval += do_laser_firing(Players[Player_num].objnum, Primary_weapon, laser_level, flags, nfires, Objects[Players[Player_num].objnum].orient.fvec); + + int warning_increment = 250/12; + int pre_ammo = plp->primary_ammo[VULCAN_INDEX]; + int post_ammo = plp->primary_ammo[VULCAN_INDEX] - ammo_used; + + //int bump = 1; + if(Primary_weapon == VULCAN_INDEX && PlayerCfg.VulcanAmmoWarnings) { + //if(pre_ammo > warning_increment*4 + bump && post_ammo <= warning_increment*4 + bump) { + // digi_play_sample(SOUND_HUD_MESSAGE, F1_0); + //} + + if(pre_ammo >= warning_increment*4 && post_ammo < warning_increment*4) { + HUD_init_message_literal(HM_MULTI, "Vulcan ammo warning."); + digi_play_sample(SOUND_BAD_SELECTION, F1_0); + } + + //if(pre_ammo > warning_increment*2 + bump && post_ammo <= warning_increment*2 + bump) { + // digi_play_sample(SOUND_HUD_MESSAGE, F1_0); + //} + + + if(pre_ammo >= warning_increment*2 && post_ammo < warning_increment*2) { + HUD_init_message_literal(HM_MULTI, "Vulcan ammo low."); + digi_play_sample(SOUND_BAD_SELECTION, F1_0); + } + + //if(pre_ammo > warning_increment*1 + bump && post_ammo <= warning_increment*1 + bump) { + // digi_play_sample(SOUND_HUD_MESSAGE, F1_0); + //} + + + if(pre_ammo >= warning_increment*1 && post_ammo < warning_increment*1) { + HUD_init_message_literal(HM_MULTI, "Vulcan ammo critical!"); + digi_play_sample(SOUND_BAD_SELECTION, F1_0); + } + } + + pre_ammo = (Players[Player_num].energy)/F1_0; + post_ammo = (Players[Player_num].energy - (energy_used * rval) / Weapon_info[weapon_index].fire_count)/F1_0; + warning_increment = 5; + if(Primary_weapon != VULCAN_INDEX && PlayerCfg.VulcanAmmoWarnings) { + + if(pre_ammo >= warning_increment*4 && post_ammo < warning_increment*4) { + HUD_init_message_literal(HM_MULTI, "Energy warning."); + digi_play_sample(SOUND_BAD_SELECTION, F1_0); + } + + + if(pre_ammo >= warning_increment*2 && post_ammo < warning_increment*2) { + HUD_init_message_literal(HM_MULTI, "Energy low."); + digi_play_sample(SOUND_BAD_SELECTION, F1_0); + } + + + if(pre_ammo >= warning_increment*1 && post_ammo < warning_increment*1) { + HUD_init_message_literal(HM_MULTI, "Energy critical!"); + digi_play_sample(SOUND_BAD_SELECTION, F1_0); + } + } + + plp->energy -= (energy_used * rval) / Weapon_info[weapon_index].fire_count; + if (plp->energy < 0) + plp->energy = 0; + + if (ammo_used > plp->primary_ammo[Primary_weapon]) + plp->primary_ammo[Primary_weapon] = 0; + else + plp->primary_ammo[Primary_weapon] -= ammo_used; + + auto_select_weapon(0); // Make sure the player can fire from this weapon. + + } else + break; // Couldn't fire weapon, so abort. + } + + Global_laser_firing_count = 0; + + return; +} + +// -------------------------------------------------------------------------------------------------- +// Object "objnum" fires weapon "weapon_num" of level "level". (Right now (9/24/94) level is used only for type 0 laser. +// Flags are the player flags. For network mode, set to 0. +// It is assumed that this is a player object (as in multiplayer), and therefore the gun positions are known. +// Returns number of times a weapon was fired. This is typically 1, but might be more for low frame rates. +// More than one shot is fired with a pseudo-delay so that players on slow machines can fire (for themselves +// or other players) often enough for things like the vulcan cannon. +int do_laser_firing(int objnum, int weapon_num, int level, int flags, int nfires, vms_vector shot_orientation) /* CED sniperpackets */ +{ + object *objp = &Objects[objnum]; + + switch (weapon_num) { + case LASER_INDEX: { + Laser_player_fire( objp, level, 0, 1, 0, shot_orientation); + Laser_player_fire( objp, level, 1, 0, 0, shot_orientation); + + if (flags & LASER_QUAD) { + // hideous system to make quad laser 1.5x powerful as normal laser, make every other quad laser bolt harmless + Laser_player_fire( objp, level, 2, 0, 0, shot_orientation); + Laser_player_fire( objp, level, 3, 0, 0, shot_orientation); + } + break; + } + case VULCAN_INDEX: { + // Only make sound for 1/4 of vulcan bullets. + int make_sound = 1; + //if (d_rand() > 24576) + // make_sound = 1; + Laser_player_fire_spread( objp, VULCAN_ID, 6, d_rand()/8 - 32767/16, d_rand()/8 - 32767/16, make_sound, 0, shot_orientation); + if (nfires > 1) { + Laser_player_fire_spread( objp, VULCAN_ID, 6, d_rand()/8 - 32767/16, d_rand()/8 - 32767/16, 0, 0, shot_orientation); + if (nfires > 2) { + Laser_player_fire_spread( objp, VULCAN_ID, 6, d_rand()/8 - 32767/16, d_rand()/8 - 32767/16, 0, 0, shot_orientation); + } + } + break; + } + case SPREADFIRE_INDEX: + if (flags & LASER_SPREADFIRE_TOGGLED) { + Laser_player_fire_spread( objp, SPREADFIRE_ID, 6, F1_0/16, 0, 0, 0, shot_orientation); + Laser_player_fire_spread( objp, SPREADFIRE_ID, 6, -F1_0/16, 0, 0, 0, shot_orientation); + Laser_player_fire_spread( objp, SPREADFIRE_ID, 6, 0, 0, 1, 0, shot_orientation); + } else { + Laser_player_fire_spread( objp, SPREADFIRE_ID, 6, 0, F1_0/16, 0, 0, shot_orientation); + Laser_player_fire_spread( objp, SPREADFIRE_ID, 6, 0, -F1_0/16, 0, 0, shot_orientation); + Laser_player_fire_spread( objp, SPREADFIRE_ID, 6, 0, 0, 1, 0, shot_orientation); + } + break; + +#ifndef SHAREWARE + case PLASMA_INDEX: + Laser_player_fire( objp, PLASMA_ID, 0, 1, 0, shot_orientation); + Laser_player_fire( objp, PLASMA_ID, 1, 0, 0, shot_orientation); + if (nfires > 1) { + Laser_player_fire_spread_delay( objp, PLASMA_ID, 0, 0, 0, FrameTime/2, 1, 0, shot_orientation); + Laser_player_fire_spread_delay( objp, PLASMA_ID, 1, 0, 0, FrameTime/2, 0, 0, shot_orientation); + } + break; + + case FUSION_INDEX: { + vms_vector force_vec; + + Laser_player_fire( objp, FUSION_ID, 0, 1, 0, shot_orientation); + Laser_player_fire( objp, FUSION_ID, 1, 1, 0, shot_orientation); + + flags = (sbyte)(Fusion_charge >> 12); + + Fusion_charge = 0; + + force_vec.x = -(objp->orient.fvec.x << 7); + force_vec.y = -(objp->orient.fvec.y << 7); + force_vec.z = -(objp->orient.fvec.z << 7); + phys_apply_force(objp, &force_vec); + + force_vec.x = (force_vec.x >> 4) + d_rand() - 16384; + force_vec.y = (force_vec.y >> 4) + d_rand() - 16384; + force_vec.z = (force_vec.z >> 4) + d_rand() - 16384; + phys_apply_rot(objp, &force_vec); + + } + break; +#endif + + default: + Int3(); // Contact Mike: Unknown Primary weapon type, setting to 0. + Primary_weapon = 0; + } + + // Set values to be recognized during comunication phase, if we are the + // one shooting +#ifdef NETWORK + if ((Game_mode & GM_MULTI) && (objnum == Players[Player_num].objnum)) + multi_send_fire(weapon_num, level, flags, nfires, -1); +#endif + + return nfires; +} + +#define MAX_SMART_DISTANCE (F1_0*150) +#define MAX_OBJDISTS 30 + +typedef struct { + int objnum; + fix dist; +} objdist; + +// ------------------------------------------------------------------------------------------- +// if goal_obj == -1, then create random vector +int create_homing_missile(object *objp, int goal_obj, int objtype, int make_sound) +{ + int objnum; + vms_vector vector_to_goal; + vms_vector random_vector; + //vms_vector goal_pos; + + if (goal_obj == -1) { + make_random_vector(&vector_to_goal); + } else { + vm_vec_sub(&vector_to_goal, &Objects[goal_obj].pos, &objp->pos); + vm_vec_normalize_quick(&vector_to_goal); + make_random_vector(&random_vector); + vm_vec_scale_add2(&vector_to_goal, &random_vector, F1_0/4); + vm_vec_normalize_quick(&vector_to_goal); + } + + // Create a vector towards the goal, then add some noise to it. + objnum = Laser_create_new(&vector_to_goal, &objp->pos, objp->segnum, objp-Objects, objtype, make_sound); + if (objnum == -1) + return -1; + + // Fixed to make sure the right person gets credit for the kill + +// Objects[objnum].ctype.laser_info.parent_num = objp->ctype.laser_info.parent_num; +// Objects[objnum].ctype.laser_info.parent_type = objp->ctype.laser_info.parent_type; +// Objects[objnum].ctype.laser_info.parent_signature = objp->ctype.laser_info.parent_signature; + + Objects[objnum].ctype.laser_info.track_goal = goal_obj; + + return objnum; +} + +// ------------------------------------------------------------------------------------------- +// Create the children of a smart bomb, which is a bunch of homing missiles. +void create_smart_children(object *objp, int num_smart_children) +{ + int parent_type; + int numobjs=0, objnum = 0, sel_objnum, last_sel_objnum = -1; + int objlist[MAX_OBJDISTS]; + int blob_id; + + parent_type = objp->ctype.laser_info.parent_type; + + if (objp->id == SMART_ID) { + int i; + + if (Game_mode & GM_MULTI) + d_srand(8321L); + + for (objnum=0; objnum<=Highest_object_index; objnum++) { + object *curobjp = &Objects[objnum]; + + if ((((curobjp->type == OBJ_ROBOT) && (!curobjp->ctype.ai_info.CLOAKED)) || (curobjp->type == OBJ_PLAYER)) && (objnum != objp->ctype.laser_info.parent_num)) { + fix dist; + + if (curobjp->type == OBJ_PLAYER) + { + if ((parent_type == OBJ_PLAYER) && (Game_mode & GM_MULTI_COOP)) + continue; + if ((Game_mode & GM_TEAM) && (get_team(curobjp->id) == get_team(Objects[objp->ctype.laser_info.parent_num].id))) + continue; + if (Players[curobjp->id].flags & PLAYER_FLAGS_CLOAKED) + continue; + } + + // Robot blobs can't track robots. + if (curobjp->type == OBJ_ROBOT) + if (parent_type == OBJ_ROBOT) + continue; + + dist = vm_vec_dist_quick(&objp->pos, &curobjp->pos); + if (dist < MAX_SMART_DISTANCE) { + int oovis; + + oovis = object_to_object_visibility(objp, curobjp, FQ_TRANSWALL); + + if (oovis) { //object_to_object_visibility(objp, curobjp, FQ_TRANSWALL)) { + objlist[numobjs] = objnum; + numobjs++; + if (numobjs >= MAX_OBJDISTS) { + numobjs = MAX_OBJDISTS; + break; + } + } + } + } + } + + // Get type of weapon for child from parent. + if (parent_type == OBJ_PLAYER) { + blob_id = PLAYER_SMART_HOMING_ID; + Assert(blob_id != -1); // Hmm, missing data in bitmaps.tbl. Need "children=NN" parameter. + } else { + blob_id = ((N_weapon_types> 15]; + if (numobjs > 1) + while (sel_objnum == last_sel_objnum) + sel_objnum = objlist[(d_rand() * numobjs) >> 15]; + create_homing_missile(objp, sel_objnum, blob_id, (i==0)?1:0); + last_sel_objnum = sel_objnum; + } + } +} + +#define CONCUSSION_GUN 4 +#define HOMING_GUN 4 + +#define PROXIMITY_GUN 7 +#define SMART_GUN 7 +#define MEGA_GUN 7 + + +int Missile_gun=0, Proximity_dropped = 0; + +// ------------------------------------------------------------------------------------------- +//changed on 9/16/98 by adb to distinguish between drop bomb and secondary fire +void do_missile_firing(int drop_bomb) +{ + int bomb = which_bomb(); + int weapon = (drop_bomb) ? bomb : Secondary_weapon; + fix fire_frame_overhead = 0; + + Network_laser_track = -1; + + Assert(weapon < MAX_SECONDARY_WEAPONS); + + if (GameTime64 - Next_missile_fire_time <= FrameTime) // if firing is prolonged by FrameTime overhead, let's try to fix that. + fire_frame_overhead = GameTime64 - Next_missile_fire_time; + + if (!Player_is_dead && (Players[Player_num].secondary_ammo[weapon] > 0)) { + + int weapon_index; + + Players[Player_num].secondary_ammo[weapon]--; + + weapon_index = Secondary_weapon_to_weapon_info[weapon]; + + if (!cheats.rapidfire) + Next_missile_fire_time = GameTime64 + Weapon_info[weapon_index].fire_wait - fire_frame_overhead; + else + Next_missile_fire_time = GameTime64 + (F1_0/25) - fire_frame_overhead; + + vms_vector orient = Objects[Players[Player_num].objnum].orient.fvec; + + switch (weapon) { + case CONCUSSION_INDEX: + Laser_player_fire( ConsoleObject, CONCUSSION_ID, CONCUSSION_GUN+(Missile_gun & 1), 1, 0 , orient); + Missile_gun++; + + #ifdef NETWORK + if(Game_mode & GM_MULTI && Netgame.RespawnConcs && RespawningConcussions[Player_num] > 0 ) { + maybe_drop_net_powerup(POW_MISSILE_1); + RespawningConcussions[Player_num]--; + } + #endif + + break; + + case PROXIMITY_INDEX: + Proximity_dropped ++; + if (Proximity_dropped == 4) + { + Proximity_dropped = 0; +#ifdef NETWORK + maybe_drop_net_powerup(POW_PROXIMITY_WEAPON); +#endif + } + Laser_player_fire( ConsoleObject, PROXIMITY_ID, PROXIMITY_GUN, 1, 0, orient); + break; + + case HOMING_INDEX: + Laser_player_fire( ConsoleObject, HOMING_ID, HOMING_GUN+(Missile_gun & 1), 1, 0, orient ); + Missile_gun++; + #ifdef NETWORK + maybe_drop_net_powerup(POW_HOMING_AMMO_1); + #endif + break; + +#ifndef SHAREWARE + case SMART_INDEX: + Laser_player_fire( ConsoleObject, SMART_ID, SMART_GUN, 1, 0, orient); +#ifdef NETWORK + maybe_drop_net_powerup(POW_SMARTBOMB_WEAPON); +#endif + break; + + case MEGA_INDEX: + Laser_player_fire( ConsoleObject, MEGA_ID, MEGA_GUN, 1, 0, orient); +#ifdef NETWORK + maybe_drop_net_powerup(POW_MEGA_WEAPON); +#endif + + { vms_vector force_vec; + force_vec.x = -(ConsoleObject->orient.fvec.x << 7); + force_vec.y = -(ConsoleObject->orient.fvec.y << 7); + force_vec.z = -(ConsoleObject->orient.fvec.z << 7); + phys_apply_force(ConsoleObject, &force_vec); + + force_vec.x = (force_vec.x >> 4) + d_rand() - 16384; + force_vec.y = (force_vec.y >> 4) + d_rand() - 16384; + force_vec.z = (force_vec.z >> 4) + d_rand() - 16384; + phys_apply_rot(ConsoleObject, &force_vec); + } + break; +#endif + } + +#ifdef NETWORK + if (Game_mode & GM_MULTI) + multi_send_fire(weapon+MISSILE_ADJUST, 0, (Missile_gun-1), 1, Network_laser_track); +#endif + + // don't autoselect if dropping prox and prox not current weapon + if (!drop_bomb || Secondary_weapon == PROXIMITY_INDEX) + auto_select_weapon(1); //select next missile, if this one out of ammo + } +} + +#ifdef NETWORK +void net_missile_firing(int player, int gun, int flags, vms_vector shot_orientation) /* CED sniperpackets */ +{ + /* CED sniperpackets */ + switch (gun-MISSILE_ADJUST) { + case CONCUSSION_INDEX: + Laser_player_fire( Objects+Players[player].objnum, CONCUSSION_ID, CONCUSSION_GUN+(flags & 1), 1, 0, shot_orientation ); + break; + + case PROXIMITY_INDEX: + Laser_player_fire( Objects+Players[player].objnum, PROXIMITY_ID, PROXIMITY_GUN, 1, 0, shot_orientation); + break; + + case HOMING_INDEX: + Laser_player_fire( Objects+Players[player].objnum, HOMING_ID, HOMING_GUN+(flags & 1), 1, 0, shot_orientation); + break; + + case SMART_INDEX: + Laser_player_fire( Objects+Players[player].objnum, SMART_ID, SMART_GUN, 1, 0, shot_orientation); + break; + + case MEGA_INDEX: + Laser_player_fire( Objects+Players[player].objnum, MEGA_ID, MEGA_GUN, 1, 0, shot_orientation); + break; + + case FLARE_ID: + Laser_player_fire( Objects+Players[player].objnum, FLARE_ID, 6, 1, 0, shot_orientation); + break; + + default: + break; + } + +} +#endif + + + diff --git a/d1/main/lighting.c b/d1/main/lighting.c index 9cfa279..99ecce3 100644 --- a/d1/main/lighting.c +++ b/d1/main/lighting.c @@ -1,784 +1,782 @@ -/* -THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX -SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO -END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A -ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS -IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS -SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE -FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE -CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS -AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. -COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. -*/ - -/* - * - * Lighting functions. - * - */ - -#include -#include // for memset() - -#include "fix.h" -#include "vecmat.h" -#include "gr.h" -#include "inferno.h" -#include "segment.h" -#include "dxxerror.h" -#include "render.h" -#include "game.h" -#include "vclip.h" -#include "lighting.h" -#include "3d.h" -#include "laser.h" -#include "timer.h" -#include "player.h" -#include "playsave.h" -#include "weapon.h" -#include "powerup.h" -#include "fvi.h" -#include "robot.h" -#include "multi.h" -#include "palette.h" -#include "bm.h" -#include "rle.h" -#include "wall.h" - -#ifdef RT_DX12 -#include "RTgr.h" -#include "Game/Lights.h" -RT_DynamicLightInfo g_rt_dynamic_light_info = -{ - .explosionLights = true, - .explosionBrightMod = 50.0f, - .explosionRadiusMod = 1.0f, - - .weaponFlareLights = true, - .weaponBrightMod = 30.0f, - .weaponRadiusMod = 1.0f, - .weaponFlareBrightMod = 1000.0f, - - .muzzleLights = true, - .muzzleBrightMod = 250.0f, - .muzzleRadiusMod = 1.0f, -}; - -//weapon_type_t enum size. We are wasting 8 spaces on this array, 8 * 8 unused memory? -#define RT_LIGHT_ADJUST_ARRAY_SUBTRACT_OFFSET (CONCUSSION_ID) -RT_WeaponLightAdjusts rt_light_adjusts[RT_LIGHT_ADJUST_ARRAY_SIZE] = -{ - { "CONCUSSION MISSILE", 1.f, 1.f }, //CONCUSSION_ID - { "FLARE", 10.f, 2.f }, //FLARE_ID - { "LASER", 1.f, 1.f }, //LASER_ID - { "VULCAN GUN", 0.1f, 0.1f }, //VULCAN_ID - { "XSPREADFIRE_NOT_USED", 0.8f, 0.8f }, //XSPREADFIRE_ID - { "PLASMA", 1.5f, 1.5f }, //PLASMA_ID - { "FUSION", 2.f, 2.f }, //FUSION_ID - { "HOMING MISSILE", 1.f, 1.f }, //HOMING_ID - { "PROXIMITY MINE", 1.f, 1.f }, //PROXIMITY_ID - { "SMART MISSILE", 1.f, 1.f }, //SMART_ID - { "MEGA MISSILE", 3.f, 3.f }, //MEGA_ID - { "SMART MISSILE PLASMA", 1.f, 1.f }, //PLAYER_SMART_HOMING_ID - { "SPREADFIRE", 0.8f, 0.8f }, //SPREADFIRE_ID -}; - -//old way that didn't work, compiler thought rt_light_adjusts was an interger. -//rt_light_adjusts[CONCUSSION_ID] = { 3.f, 3.f }; -//rt_light_adjusts[FLARE_ID] = { 10.f, 10.f }; -//rt_light_adjusts[LASER_ID] = { 1.f, 1.f }; -//rt_light_adjusts[VULCAN_ID] = { 0.7f, 0.7f }; -//rt_light_adjusts[XSPREADFIRE_ID] = { 0.8f, 0.8f }; -//rt_light_adjusts[PLASMA_ID] = { 1.5f, 1.5f }; -//rt_light_adjusts[FUSION_ID] = { 2.f, 2.f }; -//rt_light_adjusts[HOMING_ID] = { 3.f, 3.f }; -//rt_light_adjusts[PROXIMITY_ID] = { 3.f, 3.f }; -//rt_light_adjusts[SMART_ID] = { 5.f, 5.f }; -//rt_light_adjusts[MEGA_ID] = { 10.f, 10.f }; - -#endif - -int Do_dynamic_light=1; -int use_fcd_lighting = 0; -g3s_lrgb Dynamic_light[MAX_VERTICES]; - - - -#define HEADLIGHT_CONE_DOT (F1_0*9/10) -#define HEADLIGHT_SCALE (F1_0*10) - -// ---------------------------------------------------------------------------------------------- -void apply_light(g3s_lrgb obj_light_emission, int obj_seg, vms_vector *obj_pos, int n_render_vertices, int *render_vertices, int *vert_segnum_list, int objnum) -{ - int vv; - - if (((obj_light_emission.r+obj_light_emission.g+obj_light_emission.b)/3) > 0) - { - fix obji_64 = ((obj_light_emission.r+obj_light_emission.g+obj_light_emission.b)/3)*64; - - // for pretty dim sources, only process vertices in object's own segment. - // 12/04/95, MK, markers only cast light in own segment. - if (abs(obji_64) <= F1_0*8) { - int *vp = Segments[obj_seg].verts; - - for (vv=0; vv F1_0*32) - { - dist = find_connected_distance(obj_pos, obj_seg, vertpos, vsegnum, n_render_vertices, WID_RENDPAST_FLAG+WID_FLY_FLAG); - if (dist >= 0) - apply_light = 1; - } - else - { - dist = vm_vec_dist_quick(obj_pos, vertpos); - apply_light = 1; - } - - if (apply_light && ((dist >> headlight_shift) < abs(obji_64))) { - - if (dist < MIN_LIGHT_DIST) - dist = MIN_LIGHT_DIST; - - if (headlight_shift && objnum != -1) - { - fix dot; - vms_vector vec_to_point; - - vm_vec_sub(&vec_to_point, vertpos, obj_pos); - vm_vec_normalize_quick(&vec_to_point); // MK, Optimization note: You compute distance about 15 lines up, this is partially redundant - dot = vm_vec_dot(&vec_to_point, &Objects[objnum].orient.fvec); - if (dot < F1_0/2) - { - // Do the normal thing, but darken around headlight. - Dynamic_light[vertnum].r += fixdiv(obj_light_emission.r, fixmul(HEADLIGHT_SCALE, dist)); - Dynamic_light[vertnum].g += fixdiv(obj_light_emission.g, fixmul(HEADLIGHT_SCALE, dist)); - Dynamic_light[vertnum].b += fixdiv(obj_light_emission.b, fixmul(HEADLIGHT_SCALE, dist)); - } - else - { - if (Game_mode & GM_MULTI) - { - if (dist < max_headlight_dist) - { - Dynamic_light[vertnum].r += fixmul(fixmul(dot, dot), obj_light_emission.r)/8; - Dynamic_light[vertnum].g += fixmul(fixmul(dot, dot), obj_light_emission.g)/8; - Dynamic_light[vertnum].b += fixmul(fixmul(dot, dot), obj_light_emission.b)/8; - } - } - else - { - Dynamic_light[vertnum].r += fixmul(fixmul(dot, dot), obj_light_emission.r)/8; - Dynamic_light[vertnum].g += fixmul(fixmul(dot, dot), obj_light_emission.g)/8; - Dynamic_light[vertnum].b += fixmul(fixmul(dot, dot), obj_light_emission.b)/8; - } - } - } - else - { - Dynamic_light[vertnum].r += fixdiv(obj_light_emission.r, dist); - Dynamic_light[vertnum].g += fixdiv(obj_light_emission.g, dist); - Dynamic_light[vertnum].b += fixdiv(obj_light_emission.b, dist); - } - } - } - } - } -} - -#define FLASH_LEN_FIXED_SECONDS (F1_0/3) -#define FLASH_SCALE (3*F1_0/FLASH_LEN_FIXED_SECONDS) - -// ---------------------------------------------------------------------------------------------- -#ifndef RT_DX12 -void cast_muzzle_flash_light(int n_render_vertices, int *render_vertices, int *vert_segnum_list) -#else -void cast_muzzle_flash_light() -#endif -{ - fix64 current_time; - int i; - short time_since_flash; - - current_time = timer_query(); - - for (i=0; itype) - { - case OBJ_PLAYER: - { - vms_vector sthrust = obj->mtype.phys_info.thrust; - fix k = fixmuldiv(obj->mtype.phys_info.mass,obj->mtype.phys_info.drag,(f1_0-obj->mtype.phys_info.drag)); - // smooth thrust value like set_thrust_from_velocity() - vm_vec_copy_scale(&sthrust,&obj->mtype.phys_info.velocity,k); - light_intensity = max(vm_vec_mag_quick(&sthrust)/4, F1_0*2) + F1_0/2; - break; - } - case OBJ_FIREBALL: - if (obj->id != 0xff) - { - if (obj->lifeleft < F1_0*4) - light_intensity = fixmul(fixdiv(obj->lifeleft, Vclip[obj->id].play_time), Vclip[obj->id].light_value); - else - light_intensity = Vclip[obj->id].light_value; - } - else - light_intensity = 0; - break; - case OBJ_ROBOT: - light_intensity = F1_0/2; // F1_0*Robot_info[obj->id].lightcast; - break; - case OBJ_WEAPON: - { - fix tval = Weapon_info[obj->id].light; - - if (obj->id == FLARE_ID ) - light_intensity = 2 * (min(tval, obj->lifeleft) + ((((fix)GameTime64) ^ Obj_light_xlate[objnum & 0x0f]) & 0x3fff)); - else - light_intensity = tval; - break; - } - case OBJ_POWERUP: - light_intensity = Powerup_info[obj->id].light; - break; - case OBJ_DEBRIS: - light_intensity = F1_0/4; - break; - case OBJ_LIGHT: - light_intensity = obj->ctype.light_info.intensity; - break; - default: - light_intensity = 0; - break; - } - - lemission.r = lemission.g = lemission.b = light_intensity; - - //Note (SAM): yes we allow all pretty colors -#ifndef RT_DX12 - - if (!PlayerCfg.DynLightColor) // colored lights not desired so use intensity only OR no intensity (== no light == no color) at all - return lemission; - - if(Game_mode & GM_MULTI && ! Netgame.AllowColoredLighting) - return lemission; - -#endif //RTDX12 - - switch (obj->type) // find out if given object should cast colored light and compute if so - { - case OBJ_FIREBALL: - compute_color = 1; - case OBJ_WEAPON: - compute_color = 1; - case OBJ_FLARE: - compute_color = 1; - break; - case OBJ_POWERUP: - { - switch (obj->id) - { - case POW_EXTRA_LIFE: - case POW_ENERGY: - case POW_SHIELD_BOOST: - case POW_KEY_BLUE: - case POW_KEY_RED: - case POW_KEY_GOLD: - case POW_CLOAK: - case POW_INVULNERABILITY: - compute_color = 1; - break; - default: - break; - } - break; - } - } - - if (compute_color) - { - int i, t_idx_s = -1, t_idx_e = -1; - - if (light_intensity < F1_0) // for every effect we want color, increase light_intensity so the effect becomes barely visible - light_intensity = F1_0; - - obj_color.r = obj_color.g = obj_color.b = 255; - - switch (obj->render_type) - { - case RT_NONE: - break; // no object - no light - case RT_POLYOBJ: - { - polymodel *po = &Polygon_models[obj->rtype.pobj_info.model_num]; - if (po->n_textures <= 0) - { - int color = g3_poly_get_color(po->model_data); - if (color) - { - obj_color.r = gr_current_pal[color*3]; - obj_color.g = gr_current_pal[color*3+1]; - obj_color.b = gr_current_pal[color*3+2]; - } - } - else - { - t_idx_s = ObjBitmaps[ObjBitmapPtrs[po->first_texture]].index; - t_idx_e = t_idx_s + po->n_textures - 1; - } - break; - } - case RT_LASER: - { - t_idx_s = t_idx_e = Weapon_info[obj->id].bitmap.index; - break; - } - case RT_POWERUP: - { - t_idx_s = Vclip[obj->rtype.vclip_info.vclip_num].frames[0].index; - t_idx_e = Vclip[obj->rtype.vclip_info.vclip_num].frames[Vclip[obj->rtype.vclip_info.vclip_num].num_frames-1].index; - break; - } - case RT_WEAPON_VCLIP: - { - t_idx_s = Vclip[Weapon_info[obj->id].weapon_vclip].frames[0].index; - t_idx_e = Vclip[Weapon_info[obj->id].weapon_vclip].frames[Vclip[Weapon_info[obj->id].weapon_vclip].num_frames-1].index; - break; - } - default: - { - t_idx_s = Vclip[obj->id].frames[0].index; - t_idx_e = Vclip[obj->id].frames[Vclip[obj->id].num_frames-1].index; - break; - } - } - - if (t_idx_s != -1 && t_idx_e != -1) - { - obj_color.r = obj_color.g = obj_color.b = 0; - for (i = t_idx_s; i <= t_idx_e; i++) - { - grs_bitmap *bm = &GameBitmaps[i]; - bitmap_index bi; - bi.index = i; - PIGGY_PAGE_IN(bi); - obj_color.r += bm->avg_color_rgb[0]; - obj_color.g += bm->avg_color_rgb[1]; - obj_color.b += bm->avg_color_rgb[2]; - } - } - - // obviously this object did not give us any usable color. so let's do our own but with blackjack and hookers! - if (obj_color.r <= 0 && obj_color.g <= 0 && obj_color.b <= 0) - obj_color.r = obj_color.g = obj_color.b = 255; - - // scale color to light intensity - cscale = ((float)(light_intensity * 3) / (obj_color.r + obj_color.g + obj_color.b)); - lemission.r = obj_color.r * cscale; - lemission.g = obj_color.g * cscale; - lemission.b = obj_color.b * cscale; - } - - //Note (SAM): Intercept! maybe we can do this in a better way, but we do not want all lights. -#ifdef RT_DX12 - - if (obj->type == OBJ_FLARE || - obj->type == OBJ_FIREBALL || - obj->type == OBJ_WEAPON) - //obj->type == OBJ_POWERUP) //Note (SAM): Getting lights for powerups is a great way to crash the renderer on specific levels due to having too many levels. - { - float brightness = 0; - float radius = 0; - switch (obj->type) - { - case OBJ_FIREBALL: - if (!g_rt_dynamic_light_info.explosionLights) - return lemission; - brightness = g_rt_dynamic_light_info.explosionBrightMod; - radius = g_rt_dynamic_light_info.explosionRadiusMod; - break; - case OBJ_WEAPON: - if (!g_rt_dynamic_light_info.weaponFlareLights) - return lemission; - - brightness = g_rt_dynamic_light_info.weaponBrightMod; - radius = g_rt_dynamic_light_info.weaponRadiusMod; - - //LASER_ID is not for lasers, ID 0-7 for weapons is for the level of the laser. - //So make an exception for that. - if (obj->id < CONCUSSION_ID) - { - brightness = brightness * rt_light_adjusts[LASER_ID - RT_LIGHT_ADJUST_ARRAY_SUBTRACT_OFFSET].brightMul; - radius = radius * rt_light_adjusts[LASER_ID - RT_LIGHT_ADJUST_ARRAY_SUBTRACT_OFFSET].radiusMul; - } - - if (obj->id >= CONCUSSION_ID && obj->id <= SPREADFIRE_ID) - { - brightness = brightness * rt_light_adjusts[obj->id - RT_LIGHT_ADJUST_ARRAY_SUBTRACT_OFFSET].brightMul; - radius = radius * rt_light_adjusts[obj->id - RT_LIGHT_ADJUST_ARRAY_SUBTRACT_OFFSET].radiusMul; - } - break; - default: - //Some default values - brightness = 25.f; - radius = 5.f; - break; - } - - // radius = f2fl(light_intensity) * radius; - - RT_Vec3 pos = RT_Vec3Fromvms_vector(&obj->pos); - - - - if (obj->id == FLARE_ID) - { - // And I want to prevent it clipping into the wall too much. - RT_Vec3 forward = RT_Vec3Fromvms_vector(&obj->orient.fvec); - pos = RT_Vec3MulsAdd(pos, forward, -0.75f); - } - - - // NOTE(daniel): I rescaled lighting because the emission is now encoded in RGBE which has limited range compared to float. - brightness /= RT_LIGHT_SCALE; - - //we already scale the emmission on line 399 - RT_Vec3 emission = RT_Vec3Make(brightness * f2fl(lemission.r), brightness * f2fl(lemission.g), brightness * f2fl(lemission.b)); - RT_Light flare = RT_MakeSphericalLight(emission, pos, radius); - RT_RaytraceSubmitLight(flare); - } -#endif - return lemission; -} - -// ---------------------------------------------------------------------------------------------- -void set_dynamic_light(void) -{ - int vv; - int objnum; - int n_render_vertices; - int render_vertices[MAX_VERTICES]; - int vert_segnum_list[MAX_VERTICES]; - sbyte render_vertex_flags[MAX_VERTICES]; - int render_seg,segnum, v; - static fix light_time; - - Num_headlights = 0; - - if (!Do_dynamic_light) - return; - -#ifndef RT_DX12 - light_time += FrameTime; - if (light_time < (F1_0/60)) // it's enough to stress the CPU 60 times per second - return; - light_time = light_time - (F1_0/60); - - memset(render_vertex_flags, 0, Highest_vertex_index+1); - - // Create list of vertices that need to be looked at for setting of ambient light. - n_render_vertices = 0; - for (render_seg=0; render_segHighest_vertex_index) { - Int3(); //invalid vertex number - continue; //ignore it, and go on to next one - } - if (!render_vertex_flags[vnum]) { - render_vertex_flags[vnum] = 1; - render_vertices[n_render_vertices] = vnum; - vert_segnum_list[n_render_vertices] = segnum; - n_render_vertices++; - } - } - } - } - - for (vv=0; vv= 0 && vertnum <= Highest_vertex_index); - Dynamic_light[vertnum].r = Dynamic_light[vertnum].g = Dynamic_light[vertnum].b = 0; - } - - cast_muzzle_flash_light(n_render_vertices, render_vertices, vert_segnum_list); -#else - cast_muzzle_flash_light(); -#endif - - for (objnum=0; objnum<=Highest_object_index; objnum++) - { - object *obj = &Objects[objnum]; - vms_vector *objpos = &obj->pos; - g3s_lrgb obj_light_emission; - - obj_light_emission = compute_light_emission(objnum); - -#ifndef RT_DX12 - if (((obj_light_emission.r+obj_light_emission.g+obj_light_emission.b)/3) > 0) - apply_light(obj_light_emission, obj->segnum, objpos, n_render_vertices, render_vertices, vert_segnum_list, objnum); -#endif - } -} - -// --------------------------------------------------------- - -#define HEADLIGHT_BOOST_SCALE 8 //how much to scale light when have headlight boost - -fix Beam_brightness = (F1_0/2); //global saying how bright the light beam is - -#define MAX_DIST_LOG 6 //log(MAX_DIST-expressed-as-integer) -#define MAX_DIST (f1_0<type != OBJ_ROBOT) && (objp->type != OBJ_PLAYER)) - return 0; - - light = 0; - - for (i=0; ipos, &light_objp->pos); - dist = vm_vec_normalize_quick(&vec_to_obj); - if (dist > 0) { - dot = vm_vec_dot(&light_objp->orient.fvec, &vec_to_obj); - - if (dot < F1_0/2) - light += fixdiv(HEADLIGHT_SCALE, fixmul(HEADLIGHT_SCALE, dist)); // Do the normal thing, but darken around headlight. - else - light += fixmul(fixmul(dot, dot), HEADLIGHT_SCALE)/8; - } - } - - return light; -} - -//compute the average dynamic light in a segment. Takes the segment number -g3s_lrgb compute_seg_dynamic_light(int segnum) -{ - g3s_lrgb sum, seg_lrgb; - segment *seg; - int *verts; - - seg = &Segments[segnum]; - - verts = seg->verts; - sum.r = sum.g = sum.b = 0; - - sum.r += Dynamic_light[*verts].r; - sum.g += Dynamic_light[*verts].g; - sum.b += Dynamic_light[*verts++].b; - sum.r += Dynamic_light[*verts].r; - sum.g += Dynamic_light[*verts].g; - sum.b += Dynamic_light[*verts++].b; - sum.r += Dynamic_light[*verts].r; - sum.g += Dynamic_light[*verts].g; - sum.b += Dynamic_light[*verts++].b; - sum.r += Dynamic_light[*verts].r; - sum.g += Dynamic_light[*verts].g; - sum.b += Dynamic_light[*verts++].b; - sum.r += Dynamic_light[*verts].r; - sum.g += Dynamic_light[*verts].g; - sum.b += Dynamic_light[*verts++].b; - sum.r += Dynamic_light[*verts].r; - sum.g += Dynamic_light[*verts].g; - sum.b += Dynamic_light[*verts++].b; - sum.r += Dynamic_light[*verts].r; - sum.g += Dynamic_light[*verts].g; - sum.b += Dynamic_light[*verts++].b; - sum.r += Dynamic_light[*verts].r; - sum.g += Dynamic_light[*verts].g; - sum.b += Dynamic_light[*verts].b; - - seg_lrgb.r = sum.r >> 3; - seg_lrgb.g = sum.g >> 3; - seg_lrgb.b = sum.b >> 3; - - return seg_lrgb; -} - -g3s_lrgb object_light[MAX_OBJECTS]; -int object_sig[MAX_OBJECTS]; -object *old_viewer; -int reset_lighting_hack; -#define LIGHT_RATE i2f(4) //how fast the light ramps up - -void start_lighting_frame(object *viewer) -{ - reset_lighting_hack = (viewer != old_viewer); - old_viewer = viewer; -} - -//compute the lighting for an object. Takes a pointer to the object, -//and possibly a rotated 3d point. If the point isn't specified, the -//object's center point is rotated. -g3s_lrgb compute_object_light(object *obj,vms_vector *rotated_pnt) -{ - g3s_lrgb light, seg_dl; - fix mlight; - g3s_point objpnt; - int objnum = obj-Objects; - - if (!rotated_pnt) - { - g3_rotate_point(&objpnt,&obj->pos); - rotated_pnt = &objpnt.p3_vec; - } - - //First, get static (mono) light for this segment - light.r = light.g = light.b = Segments[obj->segnum].static_light; - - //Now, maybe return different value to smooth transitions - if (!reset_lighting_hack && object_sig[objnum] == obj->signature) - { - fix frame_delta; - g3s_lrgb delta_light; - - delta_light.r = light.r - object_light[objnum].r; - delta_light.g = light.g - object_light[objnum].g; - delta_light.b = light.b - object_light[objnum].b; - - frame_delta = fixmul(LIGHT_RATE,FrameTime); - - if (abs(((delta_light.r+delta_light.g+delta_light.b)/3)) <= frame_delta) - { - object_light[objnum] = light; //we've hit the goal - } - else - { - if (((delta_light.r+delta_light.g+delta_light.b)/3) < 0) - { - light.r = object_light[objnum].r -= frame_delta; - light.g = object_light[objnum].g -= frame_delta; - light.b = object_light[objnum].b -= frame_delta; - } - else - { - light.r = object_light[objnum].r += frame_delta; - light.g = object_light[objnum].g += frame_delta; - light.b = object_light[objnum].b += frame_delta; - } - } - - } - else //new object, initialize - { - object_sig[objnum] = obj->signature; - object_light[objnum].r = light.r; - object_light[objnum].g = light.g; - object_light[objnum].b = light.b; - } - - //Next, add in (NOTE: WHITE) headlight on this object - mlight = compute_headlight_light_on_object(obj); - light.r += mlight; - light.g += mlight; - light.b += mlight; - - //Finally, add in dynamic light for this segment - seg_dl = compute_seg_dynamic_light(obj->segnum); - light.r += seg_dl.r; - light.g += seg_dl.g; - light.b += seg_dl.b; - - return light; -} +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +/* + * + * Lighting functions. + * + */ + +#include +#include // for memset() + +#include "fix.h" +#include "vecmat.h" +#include "gr.h" +#include "inferno.h" +#include "segment.h" +#include "dxxerror.h" +#include "render.h" +#include "game.h" +#include "vclip.h" +#include "lighting.h" +#include "3d.h" +#include "laser.h" +#include "timer.h" +#include "player.h" +#include "playsave.h" +#include "weapon.h" +#include "powerup.h" +#include "fvi.h" +#include "robot.h" +#include "multi.h" +#include "palette.h" +#include "bm.h" +#include "rle.h" +#include "wall.h" + +#ifdef RT_DX12 +#include "RTgr.h" +#include "Game/Lights.h" +RT_DynamicLightInfo g_rt_dynamic_light_info = +{ + .explosionLights = true, + .explosionBrightMod = 50.0f, + .explosionRadiusMod = 1.0f, + .explosionTypeBias = 1.0f, + + .weaponFlareLights = true, + .weaponBrightMod = 30.0f, + .weaponRadiusMod = 1.0f, + + .muzzleLights = true, + .muzzleBrightMod = 250.0f, + .muzzleRadiusMod = 1.0f, +}; + +//weapon_type_t enum size. We are wasting 8 spaces on this array, 8 * 8 unused memory? +#define RT_LIGHT_ADJUST_ARRAY_SUBTRACT_OFFSET (CONCUSSION_ID) +RT_WeaponLightAdjusts rt_light_adjusts[RT_LIGHT_ADJUST_ARRAY_SIZE] = +{ + { "CONCUSSION MISSILE", 1.f, 1.f }, //CONCUSSION_ID + { "FLARE", 10.f, 2.f }, //FLARE_ID + { "LASER", 1.f, 1.f }, //LASER_ID + { "VULCAN GUN", 0.1f, 0.1f }, //VULCAN_ID + { "XSPREADFIRE_NOT_USED", 0.8f, 0.8f }, //XSPREADFIRE_ID + { "PLASMA", 1.5f, 1.5f }, //PLASMA_ID + { "FUSION", 2.f, 2.f }, //FUSION_ID + { "HOMING MISSILE", 1.f, 1.f }, //HOMING_ID + { "PROXIMITY MINE", 1.f, 1.f }, //PROXIMITY_ID + { "SMART MISSILE", 1.f, 1.f }, //SMART_ID + { "MEGA MISSILE", 3.f, 3.f }, //MEGA_ID + { "SMART MISSILE PLASMA", 1.f, 1.f }, //PLAYER_SMART_HOMING_ID + { "SPREADFIRE", 0.8f, 0.8f }, //SPREADFIRE_ID +}; + +//old way that didn't work, compiler thought rt_light_adjusts was an interger. +//rt_light_adjusts[CONCUSSION_ID] = { 3.f, 3.f }; +//rt_light_adjusts[FLARE_ID] = { 10.f, 10.f }; +//rt_light_adjusts[LASER_ID] = { 1.f, 1.f }; +//rt_light_adjusts[VULCAN_ID] = { 0.7f, 0.7f }; +//rt_light_adjusts[XSPREADFIRE_ID] = { 0.8f, 0.8f }; +//rt_light_adjusts[PLASMA_ID] = { 1.5f, 1.5f }; +//rt_light_adjusts[FUSION_ID] = { 2.f, 2.f }; +//rt_light_adjusts[HOMING_ID] = { 3.f, 3.f }; +//rt_light_adjusts[PROXIMITY_ID] = { 3.f, 3.f }; +//rt_light_adjusts[SMART_ID] = { 5.f, 5.f }; +//rt_light_adjusts[MEGA_ID] = { 10.f, 10.f }; + +#endif + +int Do_dynamic_light=1; +int use_fcd_lighting = 0; +g3s_lrgb Dynamic_light[MAX_VERTICES]; + + + +#define HEADLIGHT_CONE_DOT (F1_0*9/10) +#define HEADLIGHT_SCALE (F1_0*10) + +// ---------------------------------------------------------------------------------------------- +void apply_light(g3s_lrgb obj_light_emission, int obj_seg, vms_vector *obj_pos, int n_render_vertices, int *render_vertices, int *vert_segnum_list, int objnum) +{ + int vv; + + if (((obj_light_emission.r+obj_light_emission.g+obj_light_emission.b)/3) > 0) + { + fix obji_64 = ((obj_light_emission.r+obj_light_emission.g+obj_light_emission.b)/3)*64; + + // for pretty dim sources, only process vertices in object's own segment. + // 12/04/95, MK, markers only cast light in own segment. + if (abs(obji_64) <= F1_0*8) { + int *vp = Segments[obj_seg].verts; + + for (vv=0; vv F1_0*32) + { + dist = find_connected_distance(obj_pos, obj_seg, vertpos, vsegnum, n_render_vertices, WID_RENDPAST_FLAG+WID_FLY_FLAG); + if (dist >= 0) + apply_light = 1; + } + else + { + dist = vm_vec_dist_quick(obj_pos, vertpos); + apply_light = 1; + } + + if (apply_light && ((dist >> headlight_shift) < abs(obji_64))) { + + if (dist < MIN_LIGHT_DIST) + dist = MIN_LIGHT_DIST; + + if (headlight_shift && objnum != -1) + { + fix dot; + vms_vector vec_to_point; + + vm_vec_sub(&vec_to_point, vertpos, obj_pos); + vm_vec_normalize_quick(&vec_to_point); // MK, Optimization note: You compute distance about 15 lines up, this is partially redundant + dot = vm_vec_dot(&vec_to_point, &Objects[objnum].orient.fvec); + if (dot < F1_0/2) + { + // Do the normal thing, but darken around headlight. + Dynamic_light[vertnum].r += fixdiv(obj_light_emission.r, fixmul(HEADLIGHT_SCALE, dist)); + Dynamic_light[vertnum].g += fixdiv(obj_light_emission.g, fixmul(HEADLIGHT_SCALE, dist)); + Dynamic_light[vertnum].b += fixdiv(obj_light_emission.b, fixmul(HEADLIGHT_SCALE, dist)); + } + else + { + if (Game_mode & GM_MULTI) + { + if (dist < max_headlight_dist) + { + Dynamic_light[vertnum].r += fixmul(fixmul(dot, dot), obj_light_emission.r)/8; + Dynamic_light[vertnum].g += fixmul(fixmul(dot, dot), obj_light_emission.g)/8; + Dynamic_light[vertnum].b += fixmul(fixmul(dot, dot), obj_light_emission.b)/8; + } + } + else + { + Dynamic_light[vertnum].r += fixmul(fixmul(dot, dot), obj_light_emission.r)/8; + Dynamic_light[vertnum].g += fixmul(fixmul(dot, dot), obj_light_emission.g)/8; + Dynamic_light[vertnum].b += fixmul(fixmul(dot, dot), obj_light_emission.b)/8; + } + } + } + else + { + Dynamic_light[vertnum].r += fixdiv(obj_light_emission.r, dist); + Dynamic_light[vertnum].g += fixdiv(obj_light_emission.g, dist); + Dynamic_light[vertnum].b += fixdiv(obj_light_emission.b, dist); + } + } + } + } + } +} + +#define FLASH_LEN_FIXED_SECONDS (F1_0/3) +#define FLASH_SCALE (3*F1_0/FLASH_LEN_FIXED_SECONDS) + +// ---------------------------------------------------------------------------------------------- +#ifndef RT_DX12 +void cast_muzzle_flash_light(int n_render_vertices, int *render_vertices, int *vert_segnum_list) +#else +void cast_muzzle_flash_light() +#endif +{ + fix64 current_time; + int i; + short time_since_flash; + + current_time = timer_query(); + + for (i=0; itype) + { + case OBJ_PLAYER: + { + vms_vector sthrust = obj->mtype.phys_info.thrust; + fix k = fixmuldiv(obj->mtype.phys_info.mass,obj->mtype.phys_info.drag,(f1_0-obj->mtype.phys_info.drag)); + // smooth thrust value like set_thrust_from_velocity() + vm_vec_copy_scale(&sthrust,&obj->mtype.phys_info.velocity,k); + light_intensity = max(vm_vec_mag_quick(&sthrust)/4, F1_0*2) + F1_0/2; + break; + } + case OBJ_FIREBALL: + if (obj->id != 0xff) + { + if (obj->lifeleft < F1_0*4) + light_intensity = fixmul(fixdiv(obj->lifeleft, Vclip[obj->id].play_time), Vclip[obj->id].light_value); + else + light_intensity = Vclip[obj->id].light_value; + } + else + light_intensity = 0; + break; + case OBJ_ROBOT: + light_intensity = F1_0/2; // F1_0*Robot_info[obj->id].lightcast; + break; + case OBJ_WEAPON: + { + fix tval = Weapon_info[obj->id].light; + + if (obj->id == FLARE_ID ) + light_intensity = 2 * (min(tval, obj->lifeleft) + ((((fix)GameTime64) ^ Obj_light_xlate[objnum & 0x0f]) & 0x3fff)); + else + light_intensity = tval; + break; + } + case OBJ_POWERUP: + light_intensity = Powerup_info[obj->id].light; + break; + case OBJ_DEBRIS: + light_intensity = F1_0/4; + break; + case OBJ_LIGHT: + light_intensity = obj->ctype.light_info.intensity; + break; + default: + light_intensity = 0; + break; + } + + lemission.r = lemission.g = lemission.b = light_intensity; + + //Note (SAM): yes we allow all pretty colors +#ifndef RT_DX12 + + if (!PlayerCfg.DynLightColor) // colored lights not desired so use intensity only OR no intensity (== no light == no color) at all + return lemission; + + if(Game_mode & GM_MULTI && ! Netgame.AllowColoredLighting) + return lemission; + +#endif //RTDX12 + + switch (obj->type) // find out if given object should cast colored light and compute if so + { + case OBJ_FIREBALL: + compute_color = 1; + case OBJ_WEAPON: + compute_color = 1; + case OBJ_FLARE: + compute_color = 1; + break; + case OBJ_POWERUP: + { + switch (obj->id) + { + case POW_EXTRA_LIFE: + case POW_ENERGY: + case POW_SHIELD_BOOST: + case POW_KEY_BLUE: + case POW_KEY_RED: + case POW_KEY_GOLD: + case POW_CLOAK: + case POW_INVULNERABILITY: + compute_color = 1; + break; + default: + break; + } + break; + } + } + + if (compute_color) + { + int i, t_idx_s = -1, t_idx_e = -1; + + if (light_intensity < F1_0) // for every effect we want color, increase light_intensity so the effect becomes barely visible + light_intensity = F1_0; + + obj_color.r = obj_color.g = obj_color.b = 255; + + switch (obj->render_type) + { + case RT_NONE: + break; // no object - no light + case RT_POLYOBJ: + { + polymodel *po = &Polygon_models[obj->rtype.pobj_info.model_num]; + if (po->n_textures <= 0) + { + int color = g3_poly_get_color(po->model_data); + if (color) + { + obj_color.r = gr_current_pal[color*3]; + obj_color.g = gr_current_pal[color*3+1]; + obj_color.b = gr_current_pal[color*3+2]; + } + } + else + { + t_idx_s = ObjBitmaps[ObjBitmapPtrs[po->first_texture]].index; + t_idx_e = t_idx_s + po->n_textures - 1; + } + break; + } + case RT_LASER: + { + t_idx_s = t_idx_e = Weapon_info[obj->id].bitmap.index; + break; + } + case RT_POWERUP: + { + t_idx_s = Vclip[obj->rtype.vclip_info.vclip_num].frames[0].index; + t_idx_e = Vclip[obj->rtype.vclip_info.vclip_num].frames[Vclip[obj->rtype.vclip_info.vclip_num].num_frames-1].index; + break; + } + case RT_WEAPON_VCLIP: + { + t_idx_s = Vclip[Weapon_info[obj->id].weapon_vclip].frames[0].index; + t_idx_e = Vclip[Weapon_info[obj->id].weapon_vclip].frames[Vclip[Weapon_info[obj->id].weapon_vclip].num_frames-1].index; + break; + } + default: + { + t_idx_s = Vclip[obj->id].frames[0].index; + t_idx_e = Vclip[obj->id].frames[Vclip[obj->id].num_frames-1].index; + break; + } + } + + if (t_idx_s != -1 && t_idx_e != -1) + { + obj_color.r = obj_color.g = obj_color.b = 0; + for (i = t_idx_s; i <= t_idx_e; i++) + { + grs_bitmap *bm = &GameBitmaps[i]; + bitmap_index bi; + bi.index = i; + PIGGY_PAGE_IN(bi); + obj_color.r += bm->avg_color_rgb[0]; + obj_color.g += bm->avg_color_rgb[1]; + obj_color.b += bm->avg_color_rgb[2]; + } + } + + // obviously this object did not give us any usable color. so let's do our own but with blackjack and hookers! + if (obj_color.r <= 0 && obj_color.g <= 0 && obj_color.b <= 0) + obj_color.r = obj_color.g = obj_color.b = 255; + + // scale color to light intensity + cscale = ((float)(light_intensity * 3) / (obj_color.r + obj_color.g + obj_color.b)); + lemission.r = obj_color.r * cscale; + lemission.g = obj_color.g * cscale; + lemission.b = obj_color.b * cscale; + } + + //Note (SAM): Intercept! maybe we can do this in a better way, but we do not want all lights. +#ifdef RT_DX12 + + if (obj->type == OBJ_FLARE || + obj->type == OBJ_FIREBALL || + obj->type == OBJ_WEAPON) + //obj->type == OBJ_POWERUP) //Note (SAM): Getting lights for powerups is a great way to crash the renderer on specific levels due to having too many levels. + { + float brightness = 0; + float radius = 0; + switch (obj->type) + { + case OBJ_FIREBALL: + if (!g_rt_dynamic_light_info.explosionLights) + return lemission; + brightness = g_rt_dynamic_light_info.explosionBrightMod; + radius = g_rt_dynamic_light_info.explosionRadiusMod; + //NOTE (sam) I only do this for explosions since weapons can be adjusted by the player. + float generalBrightMod = (f2fl(light_intensity) * 0.25f) * g_rt_dynamic_light_info.explosionTypeBias; + brightness = brightness * (generalBrightMod * 3); + radius = radius * (generalBrightMod * 0.10f); + break; + case OBJ_WEAPON: + if (!g_rt_dynamic_light_info.weaponFlareLights) + return lemission; + + brightness = g_rt_dynamic_light_info.weaponBrightMod; + radius = g_rt_dynamic_light_info.weaponRadiusMod; + + //LASER_ID is not for lasers, ID 0-7 for weapons is for the level of the laser. + //So make an exception for that. + if (obj->id < CONCUSSION_ID) + { + brightness = brightness * rt_light_adjusts[LASER_ID - RT_LIGHT_ADJUST_ARRAY_SUBTRACT_OFFSET].brightMul; + radius = radius * rt_light_adjusts[LASER_ID - RT_LIGHT_ADJUST_ARRAY_SUBTRACT_OFFSET].radiusMul; + } + + if (obj->id >= CONCUSSION_ID && obj->id <= SPREADFIRE_ID) + { + brightness = brightness * rt_light_adjusts[obj->id - RT_LIGHT_ADJUST_ARRAY_SUBTRACT_OFFSET].brightMul; + radius = radius * rt_light_adjusts[obj->id - RT_LIGHT_ADJUST_ARRAY_SUBTRACT_OFFSET].radiusMul; + } + break; + default: + //Some default values + brightness = 25.f; + radius = 5.f; + break; + } + + // radius = f2fl(light_intensity) * radius; + + RT_Vec3 pos = RT_Vec3Fromvms_vector(&obj->pos); + + // And I want to prevent it clipping into the wall too much. + RT_Vec3 forward = RT_Vec3Fromvms_vector(&obj->orient.fvec); + pos = RT_Vec3MulsAdd(pos, forward, -1.f); + + // NOTE(daniel): I rescaled lighting because the emission is now encoded in RGBE which has limited range compared to float. + brightness /= RT_LIGHT_SCALE; + + //we already scale the emmission on line 399 + RT_Vec3 emission = RT_Vec3Make(brightness * f2fl(lemission.r), brightness * f2fl(lemission.g), brightness * f2fl(lemission.b)); + RT_Light flare = RT_MakeSphericalLight(emission, pos, radius); + RT_RaytraceSubmitLight(flare); + } +#endif + return lemission; +} + +// ---------------------------------------------------------------------------------------------- +void set_dynamic_light(void) +{ + int vv; + int objnum; + int n_render_vertices; + int render_vertices[MAX_VERTICES]; + int vert_segnum_list[MAX_VERTICES]; + sbyte render_vertex_flags[MAX_VERTICES]; + int render_seg,segnum, v; + static fix light_time; + + Num_headlights = 0; + + if (!Do_dynamic_light) + return; + +#ifndef RT_DX12 + light_time += FrameTime; + if (light_time < (F1_0/60)) // it's enough to stress the CPU 60 times per second + return; + light_time = light_time - (F1_0/60); + + memset(render_vertex_flags, 0, Highest_vertex_index+1); + + // Create list of vertices that need to be looked at for setting of ambient light. + n_render_vertices = 0; + for (render_seg=0; render_segHighest_vertex_index) { + Int3(); //invalid vertex number + continue; //ignore it, and go on to next one + } + if (!render_vertex_flags[vnum]) { + render_vertex_flags[vnum] = 1; + render_vertices[n_render_vertices] = vnum; + vert_segnum_list[n_render_vertices] = segnum; + n_render_vertices++; + } + } + } + } + + for (vv=0; vv= 0 && vertnum <= Highest_vertex_index); + Dynamic_light[vertnum].r = Dynamic_light[vertnum].g = Dynamic_light[vertnum].b = 0; + } + + cast_muzzle_flash_light(n_render_vertices, render_vertices, vert_segnum_list); +#else + cast_muzzle_flash_light(); +#endif + + for (objnum=0; objnum<=Highest_object_index; objnum++) + { + object *obj = &Objects[objnum]; + vms_vector *objpos = &obj->pos; + g3s_lrgb obj_light_emission; + + obj_light_emission = compute_light_emission(objnum); + +#ifndef RT_DX12 + if (((obj_light_emission.r+obj_light_emission.g+obj_light_emission.b)/3) > 0) + apply_light(obj_light_emission, obj->segnum, objpos, n_render_vertices, render_vertices, vert_segnum_list, objnum); +#endif + } +} + +// --------------------------------------------------------- + +#define HEADLIGHT_BOOST_SCALE 8 //how much to scale light when have headlight boost + +fix Beam_brightness = (F1_0/2); //global saying how bright the light beam is + +#define MAX_DIST_LOG 6 //log(MAX_DIST-expressed-as-integer) +#define MAX_DIST (f1_0<type != OBJ_ROBOT) && (objp->type != OBJ_PLAYER)) + return 0; + + light = 0; + + for (i=0; ipos, &light_objp->pos); + dist = vm_vec_normalize_quick(&vec_to_obj); + if (dist > 0) { + dot = vm_vec_dot(&light_objp->orient.fvec, &vec_to_obj); + + if (dot < F1_0/2) + light += fixdiv(HEADLIGHT_SCALE, fixmul(HEADLIGHT_SCALE, dist)); // Do the normal thing, but darken around headlight. + else + light += fixmul(fixmul(dot, dot), HEADLIGHT_SCALE)/8; + } + } + + return light; +} + +//compute the average dynamic light in a segment. Takes the segment number +g3s_lrgb compute_seg_dynamic_light(int segnum) +{ + g3s_lrgb sum, seg_lrgb; + segment *seg; + int *verts; + + seg = &Segments[segnum]; + + verts = seg->verts; + sum.r = sum.g = sum.b = 0; + + sum.r += Dynamic_light[*verts].r; + sum.g += Dynamic_light[*verts].g; + sum.b += Dynamic_light[*verts++].b; + sum.r += Dynamic_light[*verts].r; + sum.g += Dynamic_light[*verts].g; + sum.b += Dynamic_light[*verts++].b; + sum.r += Dynamic_light[*verts].r; + sum.g += Dynamic_light[*verts].g; + sum.b += Dynamic_light[*verts++].b; + sum.r += Dynamic_light[*verts].r; + sum.g += Dynamic_light[*verts].g; + sum.b += Dynamic_light[*verts++].b; + sum.r += Dynamic_light[*verts].r; + sum.g += Dynamic_light[*verts].g; + sum.b += Dynamic_light[*verts++].b; + sum.r += Dynamic_light[*verts].r; + sum.g += Dynamic_light[*verts].g; + sum.b += Dynamic_light[*verts++].b; + sum.r += Dynamic_light[*verts].r; + sum.g += Dynamic_light[*verts].g; + sum.b += Dynamic_light[*verts++].b; + sum.r += Dynamic_light[*verts].r; + sum.g += Dynamic_light[*verts].g; + sum.b += Dynamic_light[*verts].b; + + seg_lrgb.r = sum.r >> 3; + seg_lrgb.g = sum.g >> 3; + seg_lrgb.b = sum.b >> 3; + + return seg_lrgb; +} + +g3s_lrgb object_light[MAX_OBJECTS]; +int object_sig[MAX_OBJECTS]; +object *old_viewer; +int reset_lighting_hack; +#define LIGHT_RATE i2f(4) //how fast the light ramps up + +void start_lighting_frame(object *viewer) +{ + reset_lighting_hack = (viewer != old_viewer); + old_viewer = viewer; +} + +//compute the lighting for an object. Takes a pointer to the object, +//and possibly a rotated 3d point. If the point isn't specified, the +//object's center point is rotated. +g3s_lrgb compute_object_light(object *obj,vms_vector *rotated_pnt) +{ + g3s_lrgb light, seg_dl; + fix mlight; + g3s_point objpnt; + int objnum = obj-Objects; + + if (!rotated_pnt) + { + g3_rotate_point(&objpnt,&obj->pos); + rotated_pnt = &objpnt.p3_vec; + } + + //First, get static (mono) light for this segment + light.r = light.g = light.b = Segments[obj->segnum].static_light; + + //Now, maybe return different value to smooth transitions + if (!reset_lighting_hack && object_sig[objnum] == obj->signature) + { + fix frame_delta; + g3s_lrgb delta_light; + + delta_light.r = light.r - object_light[objnum].r; + delta_light.g = light.g - object_light[objnum].g; + delta_light.b = light.b - object_light[objnum].b; + + frame_delta = fixmul(LIGHT_RATE,FrameTime); + + if (abs(((delta_light.r+delta_light.g+delta_light.b)/3)) <= frame_delta) + { + object_light[objnum] = light; //we've hit the goal + } + else + { + if (((delta_light.r+delta_light.g+delta_light.b)/3) < 0) + { + light.r = object_light[objnum].r -= frame_delta; + light.g = object_light[objnum].g -= frame_delta; + light.b = object_light[objnum].b -= frame_delta; + } + else + { + light.r = object_light[objnum].r += frame_delta; + light.g = object_light[objnum].g += frame_delta; + light.b = object_light[objnum].b += frame_delta; + } + } + + } + else //new object, initialize + { + object_sig[objnum] = obj->signature; + object_light[objnum].r = light.r; + object_light[objnum].g = light.g; + object_light[objnum].b = light.b; + } + + //Next, add in (NOTE: WHITE) headlight on this object + mlight = compute_headlight_light_on_object(obj); + light.r += mlight; + light.g += mlight; + light.b += mlight; + + //Finally, add in dynamic light for this segment + seg_dl = compute_seg_dynamic_light(obj->segnum); + light.r += seg_dl.r; + light.g += seg_dl.g; + light.b += seg_dl.b; + + return light; +} diff --git a/d1/main/menu.c b/d1/main/menu.c index b98fe51..8df9fd6 100644 --- a/d1/main/menu.c +++ b/d1/main/menu.c @@ -76,6 +76,11 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #include "ogl_init.h" #endif #include "logger.h" +#ifdef RT_DX12 +#define RT_RENDER_SETTINGS_CONFIG_FILE "render_settings.vars" +#include "Core/String.h" +#include "Core/Config.h" +#endif // Menu IDs... @@ -1219,7 +1224,259 @@ void reticle_config() PlayerCfg.ReticleSize = m[opt_ret_size].value; } +#ifdef RT_DX12 + +int RT_GetIntFromConfig(RT_Config* config, RT_String key) +{ + int temp = 0; + ALWAYS(RT_ConfigReadInt(config, key, &temp)); + return temp; +} + +float RT_GetFloatFromConfig(RT_Config* config, RT_String key) +{ + float temp = 0.0; + ALWAYS(RT_ConfigReadFloat(config, key, &temp)); + return temp; +} + +RT_Vec3 RT_GetVec3FromConfig(RT_Config* config, RT_String key) +{ + RT_Vec3 temp = RT_Vec3FromScalar(0.f); + ALWAYS(RT_ConfigReadVec3(config, key, &temp)); + return temp; +} + +bool preset_changed = false; +void preset_selection() +{ + newmenu_item* m = malloc(sizeof(newmenu_item) * 3); // Enough for text + 2 default presets + int nitems = 0; + int max_items = 3; + int opt_gr_preset_selection = 0; + + m[nitems].type = NM_TYPE_TEXT; m[nitems].text = "Preset:"; nitems++; + opt_gr_preset_selection = nitems; + + char** rc = PHYSFS_enumerateFiles("assets/render_presets/"); + char** file_itterator; + + for (file_itterator = rc; *file_itterator != NULL; file_itterator++){ + + if (nitems + 1 > max_items){ + newmenu_item* np = realloc(m, sizeof(newmenu_item) * ++max_items); + if (np != NULL){ + m = np; + } + } + m[nitems].type = NM_TYPE_RADIO; m[nitems].text = *file_itterator; m[nitems].value = 0; m[nitems].group = 0; nitems++; + } + + newmenu_do1( NULL, "Preset Selection", nitems, m, NULL, NULL, 1 ); + + RT_RendererIO* io = RT_GetRendererIO(); + RT_Config* config = io->config; + + // Apply preset + int index = 0; + for (file_itterator = rc; *file_itterator != NULL; file_itterator++){ + if (m[opt_gr_preset_selection + index].value == 1){ + + // Should be big enough, if not, increase the size; + char buff[255]; + strcpy(buff, "assets/render_presets/"); + strcat(buff, *file_itterator); + + RT_DeserializeConfigFromFile(config, buff); + config->last_modified_time = RT_GetHighResTime().value; + + preset_changed = true; + RT_LOGF(RT_LOGSERVERITY_INFO, "Applied Preset: %s", *file_itterator); + break; + } + index++; + } + + PHYSFS_freeList(rc); + free(m); +} + +int opt_gr_change_preset = 0; +int raytrace_config_menuset(newmenu *menu, d_event *event, void *userdata) +{ + newmenu_item *items = newmenu_get_items(menu); + int citem = newmenu_get_citem(menu); + + userdata = userdata; + + switch (event->type) + { + case EVENT_NEWMENU_SELECTED: + if (citem == opt_gr_change_preset) { + preset_selection(); + return 0; + } + + return 1; // stay in menu + break; + + default: + break; + } + + return 0; +} + +void raytrace_config() +{ + newmenu_item m[28]; + 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; + + // Motion Blur ops + int opt_gr_motion_blur_quality = 0, opt_gr_motion_blur_strength; + + // Bloom ops + int opt_gr_bloom_amount = 0, opt_gr_bloom_threshold; + + // FOV + int opt_gr_fov = 0; + + // Post Processing ops + int opt_gr_sharpen_amount = 0, opt_gr_gamma, opt_gr_vignette_scale, opt_gr_vignette_strength; + + RT_RendererIO* io = RT_GetRendererIO(); + RT_Config* config = io->config; + + // --- PRESETS --- + + preset_changed = false; + opt_gr_change_preset = nitems; + m[nitems].type = NM_TYPE_MENU; m[nitems].text = " Use Preset"; nitems++; + + // --- PATHTRACING --- + m[nitems].type = NM_TYPE_TEXT; m[nitems].text = ""; nitems++; + m[nitems].type = NM_TYPE_TEXT; m[nitems].text = "Pathtracing:"; nitems++; + + opt_gr_enable_pathtracing = nitems; + m[nitems].type = NM_TYPE_CHECK; m[nitems].text = "Enable Pathtracing"; m[nitems].value = RT_GetIntFromConfig(config, RT_StringLiteral("enable_pathtracing")); nitems++; + + 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++; + m[nitems].type = NM_TYPE_RADIO; m[nitems].text = " Medium"; m[nitems].value = 0; m[nitems].group = 0; nitems++; + m[nitems].type = NM_TYPE_RADIO; m[nitems].text = " High"; m[nitems].value = 0; m[nitems].group = 0; nitems++; + int lighting_mode = RT_GetIntFromConfig(config, RT_StringLiteral("ris")); + m[opt_gr_lighting_quality+lighting_mode].value=1; + + // --- MOTION BLUR --- + m[nitems].type = NM_TYPE_TEXT; m[nitems].text = ""; nitems++; + m[nitems].type = NM_TYPE_TEXT; m[nitems].text = "Motion Blur:"; nitems++; + + opt_gr_motion_blur_quality = nitems; + m[nitems].type = NM_TYPE_CHECK; m[nitems].text = "Use motion blur"; m[nitems].value = RT_GetIntFromConfig(config, RT_StringLiteral("motion_blur_quality")); nitems++; + + opt_gr_motion_blur_strength = nitems; + m[nitems].type = NM_TYPE_SLIDER; m[nitems].text = "Motion blur strength"; m[nitems].value = (int)(RT_GetFloatFromConfig(config, RT_StringLiteral("motion_blur_curve")) * 10.0); m[nitems].min_value = 0; m[nitems].max_value = 10; nitems++; + + // --- BLOOM --- + m[nitems].type = NM_TYPE_TEXT; m[nitems].text = ""; nitems++; + m[nitems].type = NM_TYPE_TEXT; m[nitems].text = "Bloom:"; nitems++; + + opt_gr_bloom_amount = nitems; + m[nitems].type = NM_TYPE_SLIDER; m[nitems].text = "Amount"; m[nitems].value = (int)(RT_GetFloatFromConfig(config, RT_StringLiteral("bloom_amount")) * 75.0f); m[nitems].min_value = 0; m[nitems].max_value = 25; nitems++; + + // --- FOV --- + m[nitems].type = NM_TYPE_TEXT; m[nitems].text = ""; nitems++; + m[nitems].type = NM_TYPE_TEXT; m[nitems].text = "FOV:"; nitems++; + + opt_gr_fov = nitems; + m[nitems].type = NM_TYPE_SLIDER; m[nitems].text = "Amount"; m[nitems].value = (int)(RT_GetFloatFromConfig(config, RT_StringLiteral("fov"))) - 60; m[nitems].min_value = 0; m[nitems].max_value = 30; nitems++; + + // --- POST PROCESSING --- + m[nitems].type = NM_TYPE_TEXT; m[nitems].text = ""; nitems++; + m[nitems].type = NM_TYPE_TEXT; m[nitems].text = "Post Processing:"; nitems++; + + opt_gr_sharpen_amount = nitems; + m[nitems].type = NM_TYPE_SLIDER; m[nitems].text = "Sharpen amount:"; m[nitems].value = (int)(RT_GetFloatFromConfig(config, RT_StringLiteral("sharpen_amount")) * 2.f); m[nitems].min_value = 0; m[nitems].max_value = 8; nitems++; + + opt_gr_gamma = nitems; + m[nitems].type = NM_TYPE_SLIDER; m[nitems].text = "Gamma:"; m[nitems].value = (int)((RT_GetFloatFromConfig(config, RT_StringLiteral("gamma")) + 1.0f) * 10.f); m[nitems].min_value = 0; m[nitems].max_value = 20; nitems++; + + opt_gr_vignette_scale = nitems; + m[nitems].type = NM_TYPE_SLIDER; m[nitems].text = "Vignette Scale:"; m[nitems].value = (int)(RT_GetFloatFromConfig(config, RT_StringLiteral("vignette_scale")) * 10.f); m[nitems].min_value = 5; m[nitems].max_value = 15; nitems++; + + 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++; + + newmenu_do1( NULL, "Raytracing Options", nitems, m, raytrace_config_menuset, NULL, 1 ); + + 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; + } + } + + switch(lighting_mode) + { + // LOW + case 0: + RT_ConfigWriteInt(config, RT_StringLiteral("svgf_max_hist_len_diff"), 16); + RT_ConfigWriteInt(config, RT_StringLiteral("svgf_max_hist_len_spec"), 16); + break; + + // Medium + case 1: + RT_ConfigWriteInt(config, RT_StringLiteral("svgf_max_hist_len_diff"), 12); + RT_ConfigWriteInt(config, RT_StringLiteral("svgf_max_hist_len_spec"), 12); + break; + + //High + case 2: + RT_ConfigWriteInt(config, RT_StringLiteral("svgf_max_hist_len_diff"), 4); + RT_ConfigWriteInt(config, RT_StringLiteral("svgf_max_hist_len_spec"), 4); + break; + + default: + break; + } + + RT_ConfigWriteInt(config, RT_StringLiteral("ris"), lighting_mode); + + 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); + + RT_ConfigWriteFloat(config, RT_StringLiteral("bloom_amount"), ((float)m[opt_gr_bloom_amount].value)/75.0f); + + RT_ConfigWriteFloat(config, RT_StringLiteral("fov"), ((float)m[opt_gr_fov].value + 60)); + + RT_ConfigWriteFloat(config, RT_StringLiteral("sharpen_amount"), ((float)m[opt_gr_sharpen_amount].value)/2.0f); + RT_ConfigWriteFloat(config, RT_StringLiteral("gamma"), -1.0 + ((float)m[opt_gr_gamma].value/10.0f)); + RT_ConfigWriteFloat(config, RT_StringLiteral("vignette_scale"), ((float)m[opt_gr_vignette_scale].value)/10.0f); + RT_ConfigWriteFloat(config, RT_StringLiteral("vignette_strength"), ((float)m[opt_gr_vignette_strength].value)/10.0f); + + RT_SerializeConfigToFile(config, RT_RENDER_SETTINGS_CONFIG_FILE); + config->last_modified_time = RT_GetHighResTime().value; + } +} +#endif + int opt_gr_texfilt, opt_gr_brightness, opt_gr_reticlemenu, opt_gr_alphafx, opt_gr_dynlightcolor, opt_gr_vsync, opt_gr_multisample, opt_gr_fpsindi, opt_gr_disablecockpit; +#ifdef RT_DX12 +int opt_gr_raytracemenu; opt_gr_enable_pathtracing; +#endif int graphics_config_menuset(newmenu *menu, d_event *event, void *userdata) { newmenu_item *items = newmenu_get_items(menu); @@ -1233,6 +1490,9 @@ int graphics_config_menuset(newmenu *menu, d_event *event, void *userdata) if ( citem == opt_gr_texfilt + 3 #ifdef OGL && ogl_maxanisotropy <= 1.0 +#endif +#ifdef RT_DX12 + && false #endif ) { @@ -1247,6 +1507,11 @@ int graphics_config_menuset(newmenu *menu, d_event *event, void *userdata) case EVENT_NEWMENU_SELECTED: if (citem == opt_gr_reticlemenu) reticle_config(); +#ifdef RT_DX12 + if (citem == opt_gr_raytracemenu) + raytrace_config(); +#endif + return 1; // stay in menu break; @@ -1262,6 +1527,8 @@ void graphics_config() #ifdef OGL newmenu_item m[16]; int i = 0; +#elif RT_DX12 + newmenu_item m[7]; #else newmenu_item m[6]; #endif @@ -1280,6 +1547,12 @@ void graphics_config() m[nitems].type = NM_TYPE_SLIDER; m[nitems].text = TXT_BRIGHTNESS; m[nitems].value = gr_palette_get_gamma(); m[nitems].min_value = 0; m[nitems].max_value = 16; nitems++; opt_gr_reticlemenu = nitems; m[nitems].type = NM_TYPE_MENU; m[nitems].text = "Reticle Options"; nitems++; + +#ifdef RT_DX12 + opt_gr_raytracemenu = nitems; + m[nitems].type = NM_TYPE_MENU; m[nitems].text = "Raytracing Options"; nitems++; +#endif // RT_DX12 + #ifdef OGL opt_gr_alphafx = nitems; m[nitems].type = NM_TYPE_CHECK; m[nitems].text = "Transparency Effects"; m[nitems].value = PlayerCfg.AlphaEffects; nitems++; @@ -1323,7 +1596,6 @@ void graphics_config() GameCfg.FPSIndicator = m[opt_gr_fpsindi].value; PlayerCfg.DisableCockpit = m[opt_gr_disablecockpit].value; - PlayerCfg.maxFps=atoi(framerate_string); if(PlayerCfg.maxFps < 25) { diff --git a/d1/main/menu.h b/d1/main/menu.h index a6f2cf7..5e5d9f1 100644 --- a/d1/main/menu.h +++ b/d1/main/menu.h @@ -31,7 +31,13 @@ extern int RegisterPlayer(); extern int DoMenu(); extern void do_options_menu(); extern int select_demo(void); +#if RT_DX12 +#define Menu_pcx_name (PHYSFSX_exists("assets/splash-logo/MenuRaytraced.png", 1) ? \ + "assets/splash-logo/MenuRaytraced.png" : \ + (((SWIDTH>=640&&SHEIGHT>=480) && PHYSFSX_exists("menuh.pcx",1))?"menuh.pcx":"menu.pcx")) +#else #define Menu_pcx_name (((SWIDTH>=640&&SHEIGHT>=480) && PHYSFSX_exists("menuh.pcx",1))?"menuh.pcx":"menu.pcx") +#endif #define STARS_BACKGROUND (((SWIDTH>=640&&SHEIGHT>=480) && PHYSFSX_exists("starsb.pcx",1))?"starsb.pcx":"stars.pcx") extern char *menu_difficulty_text[]; diff --git a/d1/main/morph.c b/d1/main/morph.c index 0bebccf..1890aff 100644 --- a/d1/main/morph.c +++ b/d1/main/morph.c @@ -329,7 +329,7 @@ void draw_model(object* obj, int submodel_num, g3s_lrgb light, morph_data* md) polymodel* pm = &Polygon_models[obj->rtype.pobj_info.model_num]; #ifdef RT_DX12 - RT_DrawPolyModelTree(obj->rtype.pobj_info.model_num, obj->objNum, obj->type, &obj->pos, &obj->orient, &obj->rtype.pobj_info.anim_angles); + RT_DrawPolyModelTree(obj->rtype.pobj_info.model_num, obj->signature, obj->type, &obj->pos, &obj->orient, &obj->rtype.pobj_info.anim_angles); return; #endif //RT_DX12 diff --git a/d1/main/object.c b/d1/main/object.c index 999983e..119a513 100644 --- a/d1/main/object.c +++ b/d1/main/object.c @@ -99,10 +99,6 @@ int num_objects=0; int Highest_object_index=0; int Highest_ever_object_index=0; -#ifdef RT_DX12 -RT_SubmodelTransforms g_rt_prev_submodel_transforms[MAX_OBJECTS]; -#endif - // grs_bitmap *robot_bms[MAX_ROBOT_BITMAPS]; //all bitmaps for all robots // int robot_bm_nums[MAX_ROBOT_TYPES]; //starting bitmap num for each robot diff --git a/d1/main/object.h b/d1/main/object.h index d10fbd9..ea75b12 100644 --- a/d1/main/object.h +++ b/d1/main/object.h @@ -371,14 +371,6 @@ extern object Objects[]; extern int Highest_object_index; // highest objnum extern int num_objects; -#ifdef RT_DX12 -typedef struct RT_SubmodelTransforms -{ - RT_Mat4 transforms[MAX_SUBMODELS]; -} RT_SubmodelTransforms; -extern RT_SubmodelTransforms g_rt_prev_submodel_transforms[]; -#endif // ifdef RT_DX12 - extern char *robot_names[]; // name of each robot extern int Num_robot_types; diff --git a/d1/main/physics.c b/d1/main/physics.c index e44610b..ebed102 100644 --- a/d1/main/physics.c +++ b/d1/main/physics.c @@ -32,6 +32,10 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #include "laser.h" #include "logger.h" +#ifdef RT_DX12 +#include "RTgr.h" +#endif + #include //Global variables for physics system @@ -476,15 +480,21 @@ void do_physics_sim(object *obj) #ifdef EXTRA_DEBUG //check for correct object segment - if(!get_seg_masks(&obj->pos, obj->segnum, 0, __FILE__, __LINE__).centermask == 0) + + if (!get_seg_masks(&obj->pos, obj->segnum, 0, __FILE__, __LINE__).centermask == 0 +#ifdef RT_DX12 + && !g_rt_free_cam_info.g_free_cam_enabled && !g_rt_free_cam_info.g_free_cam_clipping_enabled +#endif + ) { if (!update_object_seg(obj)) { if (!(Game_mode & GM_MULTI)) Int3(); - compute_segment_center(&obj->pos,&Segments[obj->segnum]); + compute_segment_center(&obj->pos, &Segments[obj->segnum]); obj->pos.x += objnum; } } + #endif start_pos = obj->pos; @@ -546,6 +556,7 @@ void do_physics_sim(object *obj) total_drag = fixmul(total_drag,f1_0-fixmul(k,drag)); vm_vec_scale(&obj->mtype.phys_info.velocity,total_drag); + } } else if (STRATEGY == GEOMETRIC_DRAG) { if (obj->mtype.phys_info.flags & PF_USES_THRUST) { @@ -602,13 +613,20 @@ void do_physics_sim(object *obj) // The rest of this function is collision stuff // Observers just fly free - if(Game_mode & GM_OBSERVER && ((obj->id == Player_num) || - ((Game_mode & GM_MULTI_COOP) && (obj - Objects == 7))) ) { + ((Game_mode & GM_MULTI_COOP) && (obj - Objects == 7)))) { obj->pos = new_pos; return; } + +#ifdef RT_DX12 + //This needs to be checked seperate for the ifdef + if (g_rt_free_cam_info.g_free_cam_enabled && g_rt_free_cam_info.g_free_cam_clipping_enabled) { + obj->pos = new_pos; + return; + } +#endif ignore_obj_list[n_ignore_objs] = -1; @@ -626,6 +644,7 @@ void do_physics_sim(object *obj) if (obj->type == OBJ_PLAYER) fq.flags |= FQ_GET_SEGLIST; + fate = find_vector_intersection(&fq,&hit_info); // if(fate != HIT_NONE) { // double radius = (double)(fq.rad) / (double)(F1_0); @@ -742,7 +761,6 @@ void do_physics_sim(object *obj) } } - switch( fate ) { case HIT_WALL: { diff --git a/d1/main/polyobj.c b/d1/main/polyobj.c index cfe9674..a462256 100644 --- a/d1/main/polyobj.c +++ b/d1/main/polyobj.c @@ -1,948 +1,833 @@ -/* -THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX -SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO -END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A -ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS -IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS -SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE -FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE -CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS -AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. -COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. -*/ - -/* - * - * Hacked-in polygon objects - * - */ - - -#include -#include -#include - -#ifdef DRIVE -#include "drive.h" -#else -#include "inferno.h" -#endif -#include "polyobj.h" -#include "vecmat.h" -#include "3d.h" -#include "dxxerror.h" -#include "u_mem.h" -#include "args.h" -#ifndef DRIVE -#include "texmap.h" -#include "bm.h" -#include "textures.h" -#include "object.h" -#include "lighting.h" -#include "piggy.h" -#endif -#include "byteswap.h" -#include "render.h" -#ifdef OGL -#include "ogl_init.h" -#endif -#include "logger.h" - -#ifdef RT_DX12 -#include "RTgr.h" -#include "RTmaterials.h" -#include "Core/MiniMath.h" -#endif //RT_DX12 - -polymodel Polygon_models[MAX_POLYGON_MODELS]; // = {&bot11,&bot17,&robot_s2,&robot_b2,&bot11,&bot17,&robot_s2,&robot_b2}; - -int N_polygon_models = 0; - -#define MAX_POLYGON_VECS 1000 -g3s_point robot_points[MAX_POLYGON_VECS]; - -#define PM_COMPATIBLE_VERSION 6 -#define PM_OBJFILE_VERSION 8 - -int Pof_file_end; -int Pof_addr; - -#define MODEL_BUF_SIZE 32768 - -void _pof_cfseek(int len, int type) -{ - switch (type) { - case SEEK_SET: Pof_addr = len; break; - case SEEK_CUR: Pof_addr += len; break; - case SEEK_END: - Assert(len <= 0); // seeking from end, better be moving back. - Pof_addr = Pof_file_end + len; - break; - } - - if (Pof_addr > MODEL_BUF_SIZE) - Int3(); -} - -#define pof_cfseek(_buf,_len,_type) _pof_cfseek((_len),(_type)) - -int pof_read_int(ubyte* bufp) -{ - int i; - - i = *((int*)&bufp[Pof_addr]); - Pof_addr += 4; - return INTEL_INT(i); - - // if (PHYSFS_read(f,&i,sizeof(i),1) != 1) - // RT_LOGF(RT_LOGSERVERITY_HIGH, "Unexpected end-of-file while reading object"); - // - // return i; -} - -size_t pof_cfread(void* dst, size_t elsize, size_t nelem, ubyte* bufp) -{ - if (Pof_addr + nelem * elsize > Pof_file_end) - return 0; - - memcpy(dst, &bufp[Pof_addr], elsize * nelem); - - Pof_addr += elsize * nelem; - - if (Pof_addr > MODEL_BUF_SIZE) - Int3(); - - return nelem; -} - -// #define new_read_int(i,f) PHYSFS_read((f),&(i),sizeof(i),1) -#define new_pof_read_int(i,f) pof_cfread(&(i),sizeof(i),1,(f)) - -short pof_read_short(ubyte* bufp) -{ - short s; - - s = *((short*)&bufp[Pof_addr]); - Pof_addr += 2; - return INTEL_SHORT(s); - // if (PHYSFS_read(f,&s,sizeof(s),1) != 1) - // RT_LOGF(RT_LOGSERVERITY_HIGH, "Unexpected end-of-file while reading object"); - // - // return s; -} - -void pof_read_string(char* buf, int max, ubyte* bufp) -{ - int i; - - for (i = 0; i < max; i++) { - if ((*buf++ = bufp[Pof_addr++]) == 0) - break; - } - - // while (max-- && (*buf=PHYSFSX_fgetc(f)) != 0) buf++; - -} - -void pof_read_vecs(vms_vector* vecs, int n, ubyte* bufp) -{ - int i; - // PHYSFS_read(f,vecs,sizeof(vms_vector),n); - - for (i = 0; i < n; i++) - { - vecs[i].x = pof_read_int(bufp); - vecs[i].y = pof_read_int(bufp); - vecs[i].z = pof_read_int(bufp); - } -} - -void pof_read_angvecs(vms_angvec* vecs, int n, ubyte* bufp) -{ - int i; - // PHYSFS_read(f,vecs,sizeof(vms_vector),n); - - for (i = 0; i < n; i++) - { - vecs[i].p = pof_read_short(bufp); - vecs[i].b = pof_read_short(bufp); - vecs[i].h = pof_read_short(bufp); - } -} - -#define ID_OHDR 0x5244484f // 'RDHO' //Object header -#define ID_SOBJ 0x4a424f53 // 'JBOS' //Subobject header -#define ID_GUNS 0x534e5547 // 'SNUG' //List of guns on this object -#define ID_ANIM 0x4d494e41 // 'MINA' //Animation data -#define ID_IDTA 0x41544449 // 'ATDI' //Interpreter data -#define ID_TXTR 0x52545854 // 'RTXT' //Texture filename list - -#ifdef DRIVE -#define robot_info void -#else -vms_angvec anim_angs[N_ANIM_STATES][MAX_SUBMODELS]; - -//set the animation angles for this robot. Gun fields of robot info must -//be filled in. -void robot_set_angles(robot_info* r, polymodel* pm, vms_angvec angs[N_ANIM_STATES][MAX_SUBMODELS]); -#endif - -#ifdef WORDS_NEED_ALIGNMENT -ubyte* old_dest(chunk o) // return where chunk is (in unaligned struct) -{ - return o.old_base + INTEL_SHORT(*((short*)(o.old_base + o.offset))); -} - -ubyte* new_dest(chunk o) // return where chunk is (in aligned struct) -{ - return o.new_base + INTEL_SHORT(*((short*)(o.old_base + o.offset))) + o.correction; -} - -/* - * find chunk with smallest address - */ -int get_first_chunks_index(chunk* chunk_list, int no_chunks) -{ - int i, first_index = 0; - Assert(no_chunks >= 1); - for (i = 1; i < no_chunks; i++) - if (old_dest(chunk_list[i]) < old_dest(chunk_list[first_index])) - first_index = i; - return first_index; -} -#define SHIFT_SPACE 500 // increase if insufficent - -void align_polygon_model_data(polymodel* pm) -{ - int i, chunk_len; - int total_correction = 0; - ubyte* cur_old, * cur_new; - chunk cur_ch; - chunk ch_list[MAX_CHUNKS]; - int no_chunks = 0; - int tmp_size = pm->model_data_size + SHIFT_SPACE; - ubyte* tmp = d_malloc(tmp_size); // where we build the aligned version of pm->model_data - - Assert(tmp != NULL); - //start with first chunk (is always aligned!) - cur_old = pm->model_data; - cur_new = tmp; - chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks); - memcpy(cur_new, cur_old, chunk_len); - while (no_chunks > 0) { - int first_index = get_first_chunks_index(ch_list, no_chunks); - cur_ch = ch_list[first_index]; - // remove first chunk from array: - no_chunks--; - for (i = first_index; i < no_chunks; i++) - ch_list[i] = ch_list[i + 1]; - // if (new) address unaligned: - if ((u_int32_t)new_dest(cur_ch) % 4L != 0) { - // calculate how much to move to be aligned - short to_shift = 4 - (u_int32_t)new_dest(cur_ch) % 4L; - // correct chunks' addresses - cur_ch.correction += to_shift; - for (i = 0; i < no_chunks; i++) - ch_list[i].correction += to_shift; - total_correction += to_shift; - Assert((u_int32_t)new_dest(cur_ch) % 4L == 0); - Assert(total_correction <= SHIFT_SPACE); // if you get this, increase SHIFT_SPACE - } - //write (corrected) chunk for current chunk: - *((short*)(cur_ch.new_base + cur_ch.offset)) - = INTEL_SHORT(cur_ch.correction - + INTEL_SHORT(*((short*)(cur_ch.old_base + cur_ch.offset)))); - //write (correctly aligned) chunk: - cur_old = old_dest(cur_ch); - cur_new = new_dest(cur_ch); - chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks); - memcpy(cur_new, cur_old, chunk_len); - //correct submodel_ptr's for pm, too - for (i = 0; i < MAX_SUBMODELS; i++) - if (pm->model_data + pm->submodel_ptrs[i] >= cur_old - && pm->model_data + pm->submodel_ptrs[i] < cur_old + chunk_len) - pm->submodel_ptrs[i] += (cur_new - tmp) - (cur_old - pm->model_data); - } - d_free(pm->model_data); - pm->model_data_size += total_correction; - pm->model_data = - d_malloc(pm->model_data_size); - Assert(pm->model_data != NULL); - memcpy(pm->model_data, tmp, pm->model_data_size); - d_free(tmp); -} -#endif //def WORDS_NEED_ALIGNMENT - - -//reads a binary file containing a 3d model -polymodel* read_model_file(polymodel* pm, char* filename, robot_info* r) -{ - PHYSFS_file* ifile; - short version; - int id, len, next_chunk; - ubyte model_buf[MODEL_BUF_SIZE]; - - if ((ifile = PHYSFSX_openReadBuffered(filename)) == NULL) - RT_LOGF(RT_LOGSERVERITY_HIGH, "Can't open file <%s>", filename); - - Assert(PHYSFS_fileLength(ifile) <= MODEL_BUF_SIZE); - - Pof_addr = 0; - Pof_file_end = PHYSFS_read(ifile, model_buf, 1, PHYSFS_fileLength(ifile)); - PHYSFS_close(ifile); - - id = pof_read_int(model_buf); - - if (id != 0x4f505350) /* 'OPSP' */ - RT_LOGF(RT_LOGSERVERITY_HIGH, "Bad ID in model file <%s>", filename); - - version = pof_read_short(model_buf); - - if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION) - RT_LOGF(RT_LOGSERVERITY_HIGH, "Bad version (%d) in model file <%s>", version, filename); - - while (new_pof_read_int(id, model_buf) == 1) { - id = INTEL_INT(id); - //id = pof_read_int(model_buf); - len = pof_read_int(model_buf); - next_chunk = Pof_addr + len; - - switch (id) { - - case ID_OHDR: { //Object header - vms_vector pmmin, pmmax; - - pm->n_models = pof_read_int(model_buf); - pm->rad = pof_read_int(model_buf); - - Assert(pm->n_models <= MAX_SUBMODELS); - - pof_read_vecs(&pmmin, 1, model_buf); - pof_read_vecs(&pmmax, 1, model_buf); - - break; - } - - case ID_SOBJ: { //Subobject header - int n; - - n = pof_read_short(model_buf); - - Assert(n < MAX_SUBMODELS); - - pm->submodel_parents[n] = pof_read_short(model_buf); - - pof_read_vecs(&pm->submodel_norms[n], 1, model_buf); - pof_read_vecs(&pm->submodel_pnts[n], 1, model_buf); - pof_read_vecs(&pm->submodel_offsets[n], 1, model_buf); - - pm->submodel_rads[n] = pof_read_int(model_buf); //radius - - pm->submodel_ptrs[n] = pof_read_int(model_buf); //offset - - break; - - } - -#ifndef DRIVE - case ID_GUNS: { //List of guns on this object - - if (r) { - int i; - vms_vector gun_dir; - - r->n_guns = pof_read_int(model_buf); - - Assert(r->n_guns <= MAX_GUNS); - - for (i = 0; i < r->n_guns; i++) { - int id; - - id = pof_read_short(model_buf); - r->gun_submodels[id] = pof_read_short(model_buf); - Assert(r->gun_submodels[id] != 0xff); - pof_read_vecs(&r->gun_points[id], 1, model_buf); - - if (version >= 7) - pof_read_vecs(&gun_dir, 1, model_buf); - } - } - else - pof_cfseek(model_buf, len, SEEK_CUR); - - break; - } - - case ID_ANIM: //Animation data - if (r) { - int n_frames, f, m; - - n_frames = pof_read_short(model_buf); - - Assert(n_frames == N_ANIM_STATES); - - for (m = 0; m < pm->n_models; m++) - for (f = 0; f < n_frames; f++) - pof_read_angvecs(&anim_angs[f][m], 1, model_buf); - - robot_set_angles(r, pm, anim_angs); - - } - else - pof_cfseek(model_buf, len, SEEK_CUR); - - break; -#endif - - case ID_TXTR: { //Texture filename list - int n; - char name_buf[128]; - - n = pof_read_short(model_buf); - while (n--) { - pof_read_string(name_buf, 128, model_buf); - } - - break; - } - - case ID_IDTA: //Interpreter data - pm->model_data = d_malloc(len); - pm->model_data_size = len; - - pof_cfread(pm->model_data, 1, len, model_buf); - - break; - - default: - pof_cfseek(model_buf, len, SEEK_CUR); - break; - - } - if (version >= 8) // Version 8 needs 4-byte alignment!!! - pof_cfseek(model_buf, next_chunk, SEEK_SET); - } - -#ifdef WORDS_NEED_ALIGNMENT - align_polygon_model_data(pm); -#endif -#ifdef WORDS_BIGENDIAN - swap_polygon_model_data(pm->model_data); -#endif - - return pm; -} - -//reads the gun information for a model -//fills in arrays gun_points & gun_dirs, returns the number of guns read -int read_model_guns(char* filename, vms_vector* gun_points, vms_vector* gun_dirs, int* gun_submodels) -{ - PHYSFS_file* ifile; - short version; - int id, len; - int n_guns = 0; - ubyte model_buf[MODEL_BUF_SIZE]; - - if ((ifile = PHYSFSX_openReadBuffered(filename)) == NULL) - RT_LOGF(RT_LOGSERVERITY_HIGH, "Can't open file <%s>", filename); - - Assert(PHYSFS_fileLength(ifile) <= MODEL_BUF_SIZE); - - Pof_addr = 0; - Pof_file_end = PHYSFS_read(ifile, model_buf, 1, PHYSFS_fileLength(ifile)); - PHYSFS_close(ifile); - - id = pof_read_int(model_buf); - - if (id != 0x4f505350) /* 'OPSP' */ - RT_LOGF(RT_LOGSERVERITY_HIGH, "Bad ID in model file <%s>", filename); - - version = pof_read_short(model_buf); - - Assert(version >= 7); //must be 7 or higher for this data - - if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION) - RT_LOGF(RT_LOGSERVERITY_HIGH, "Bad version (%d) in model file <%s>", version, filename); - - while (new_pof_read_int(id, model_buf) == 1) { - id = INTEL_INT(id); - //id = pof_read_int(model_buf); - len = pof_read_int(model_buf); - - if (id == ID_GUNS) { //List of guns on this object - - int i; - - n_guns = pof_read_int(model_buf); - - for (i = 0; i < n_guns; i++) { - int id, sm; - - id = pof_read_short(model_buf); - sm = pof_read_short(model_buf); - if (gun_submodels) - gun_submodels[id] = sm; - else if (sm != 0) - RT_LOGF(RT_LOGSERVERITY_HIGH, "Invalid gun submodel in file <%s>", filename); - pof_read_vecs(&gun_points[id], 1, model_buf); - - pof_read_vecs(&gun_dirs[id], 1, model_buf); - } - - } - else - pof_cfseek(model_buf, len, SEEK_CUR); - - } - - return n_guns; -} - -//free up a model, getting rid of all its memory -void free_model(polymodel* po) -{ - d_free(po->model_data); -} - -grs_bitmap* texture_list[MAX_POLYOBJ_TEXTURES]; -bitmap_index texture_list_index[MAX_POLYOBJ_TEXTURES]; - -//draw a polygon model - -void draw_polygon_model(_RT_DRAW_POLY vms_vector* pos, vms_matrix* orient, vms_angvec* anim_angles, int model_num, int flags, g3s_lrgb light, fix* glow_values, bitmap_index alt_textures[]) -{ - polymodel* po; - int i; - - if (model_num < 0) - return; - - Assert(model_num < N_polygon_models); - - po = &Polygon_models[model_num]; - - //check if should use simple model - if (po->simpler_model) //must have a simpler model - if (flags == 0) //can't switch if this is debris - //!!if (!alt_textures) { //alternate textures might not match - //alt textures might not match, but in the one case we're using this - //for on 11/14/94, they do match. So we leave it in. - { - int cnt = 1; - fix depth; - - depth = g3_calc_point_depth(pos); //gets 3d depth - - while (po->simpler_model && depth > cnt++ * Simple_model_threshhold_scale * po->rad) - po = &Polygon_models[po->simpler_model - 1]; - } - - if (alt_textures) - // TODO(daniel): When do these alt textures get used? Our renderer doesn't currently support anything like this. - for (i = 0; i < po->n_textures; i++) { - texture_list_index[i] = alt_textures[i]; - texture_list[i] = &GameBitmaps[alt_textures[i].index]; - } - else - for (i = 0; i < po->n_textures; i++) { - texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture + i]]; - texture_list[i] = &GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture + i]].index]; - } - - // Make sure the textures for this object are paged in... - piggy_page_flushed = 0; - for (i = 0; i < po->n_textures; i++) - PIGGY_PAGE_IN(texture_list_index[i]); - // Hmmm... cache got flushed in the middle of paging all these in, - // so we need to reread them all in. - if (piggy_page_flushed) { - piggy_page_flushed = 0; - for (i = 0; i < po->n_textures; i++) - PIGGY_PAGE_IN(texture_list_index[i]); - } - // Make sure that they can all fit in memory. - Assert(piggy_page_flushed == 0); - - g3_start_instance_matrix(pos, orient); - - g3_set_interp_points(robot_points); - - if (flags == 0) //draw entire object - { -#ifndef RT_DX12 - g3_draw_polygon_model(po->model_data, texture_list, anim_angles, light, glow_values); -#else - //RT_DrawPolyModel(model_num, objNum, object_type, pos, orient); - - RT_DrawPolyModelTree(model_num, objNum, object_type, pos, orient, anim_angles); -#endif //RT_DX12 - } - else { - int i; - - for (i = 0; flags; flags >>= 1, i++) - if (flags & 1) { - vms_vector ofs; - - Assert(i < po->n_models); - - //if submodel, rotate around its center point, not pivot point - - vm_vec_avg(&ofs, &po->submodel_mins[i], &po->submodel_maxs[i]); - vm_vec_negate(&ofs); - g3_start_instance_matrix(&ofs, NULL); -#ifndef RT_DX12 - g3_draw_polygon_model(&po->model_data[po->submodel_ptrs[i]], texture_list, anim_angles, light, glow_values); -#else - // Get matrix from local position offset - const vms_vector offset_vms = *pos; - const RT_Vec3 offset_vec3 = RT_Vec3Fromvms_vector(&offset_vms); - RT_Mat4 offset_mat4 = RT_Mat4FromTranslation(offset_vec3); - - // Get matrix from rotation offset - RT_Mat4 rotation_mat4 = RT_Mat4Fromvms_matrix(orient); - - // Combine them into one big matrix - RT_Mat4 combined_matrix = RT_Mat4Mul(offset_mat4, rotation_mat4); - RT_Mat4 prev_transform = g_rt_prev_submodel_transforms[objNum].transforms[i]; - RT_DrawSubPolyModel(po->submodel[i], &combined_matrix, &prev_transform); - g_rt_prev_submodel_transforms[objNum].transforms[i] = combined_matrix; -#endif //RT_DX12 - - g3_done_instance(); - } - } - - g3_done_instance(); - -} - -void free_polygon_models() -{ - int i; - - for (i = 0; i < N_polygon_models; i++) { - free_model(&Polygon_models[i]); - } - -} - -void polyobj_find_min_max(polymodel* pm) -{ - ushort nverts; - vms_vector* vp; - ushort* data, type; - int m; - vms_vector* big_mn, * big_mx; - - big_mn = &pm->mins; - big_mx = &pm->maxs; - - for (m = 0; m < pm->n_models; m++) { - vms_vector* mn, * mx, * ofs; - - mn = &pm->submodel_mins[m]; - mx = &pm->submodel_maxs[m]; - ofs = &pm->submodel_offsets[m]; - - data = (ushort*)&pm->model_data[pm->submodel_ptrs[m]]; - - type = *data++; - - Assert(type == 7 || type == 1); - - nverts = *data++; - - if (type == 7) - data += 2; //skip start & pad - - vp = (vms_vector*)data; - - *mn = *mx = *vp++; nverts--; - - if (m == 0) - *big_mn = *big_mx = *mn; - - while (nverts--) { - if (vp->x > mx->x) mx->x = vp->x; - if (vp->y > mx->y) mx->y = vp->y; - if (vp->z > mx->z) mx->z = vp->z; - - if (vp->x < mn->x) mn->x = vp->x; - if (vp->y < mn->y) mn->y = vp->y; - if (vp->z < mn->z) mn->z = vp->z; - - if (vp->x + ofs->x > big_mx->x) big_mx->x = vp->x + ofs->x; - if (vp->y + ofs->y > big_mx->y) big_mx->y = vp->y + ofs->y; - if (vp->z + ofs->z > big_mx->z) big_mx->z = vp->z + ofs->z; - - if (vp->x + ofs->x < big_mn->x) big_mn->x = vp->x + ofs->x; - if (vp->y + ofs->y < big_mn->y) big_mn->y = vp->y + ofs->y; - if (vp->z + ofs->z < big_mn->z) big_mn->z = vp->z + ofs->z; - - vp++; - } - } -} - -char Pof_names[MAX_POLYGON_MODELS][13]; - -//returns the number of this model -#ifndef DRIVE -int load_polygon_model(char* filename, int n_textures, int first_texture, robot_info* r) -#else -int load_polygon_model(char* filename, int n_textures, grs_bitmap*** textures) -#endif -{ -#ifdef DRIVE -#define r NULL -#endif - - Assert(N_polygon_models < MAX_POLYGON_MODELS); - Assert(n_textures < MAX_POLYOBJ_TEXTURES); - - Assert(strlen(filename) <= 12); - strcpy(Pof_names[N_polygon_models], filename); - - read_model_file(&Polygon_models[N_polygon_models], filename, r); - - polyobj_find_min_max(&Polygon_models[N_polygon_models]); - - g3_init_polygon_model(Polygon_models[N_polygon_models].model_data); - - //Don't need this log, because we don't use highest_texture_num on dx12 - //if (highest_texture_num + 1 != n_textures) - // RT_LOGF(RT_LOGSERVERITY_HIGH, "Model <%s> references %d textures but specifies %d.", filename, highest_texture_num + 1, n_textures); - - Polygon_models[N_polygon_models].n_textures = n_textures; - Polygon_models[N_polygon_models].first_texture = first_texture; - Polygon_models[N_polygon_models].simpler_model = 0; - - //Assert(polygon_models[N_polygon_models]!=NULL); - - N_polygon_models++; - return N_polygon_models - 1; -} - - -void init_polygon_models() -{ - N_polygon_models = 0; -} - -//compare against this size when figuring how far to place eye for picture -#define BASE_MODEL_SIZE 0x28000 - -#define DEFAULT_VIEW_DIST 0x60000 - -//draws the given model in the current canvas. The distance is set to -//more-or-less fill the canvas. Note that this routine actually renders -//into an off-screen canvas that it creates, then copies to the current -//canvas. -void draw_model_picture(int mn, vms_angvec* orient_angles) -{ - vms_vector temp_pos = ZERO_VECTOR; - vms_matrix temp_orient = IDENTITY_MATRIX; - g3s_lrgb lrgb = { f1_0, f1_0, f1_0 }; - - Assert(mn >= 0 && mn < N_polygon_models); - - - gr_clear_canvas(BM_XRGB(0, 0, 0)); - g3_start_frame(); - g3_set_view_matrix(&temp_pos, &temp_orient, 0x9000); - - -#ifndef RT_DX12 - if (Polygon_models[mn].rad != 0) - temp_pos.z = fixmuldiv(DEFAULT_VIEW_DIST, Polygon_models[mn].rad, BASE_MODEL_SIZE); - else - temp_pos.z = DEFAULT_VIEW_DIST; - - vm_angles_2_matrix(&temp_orient, orient_angles); - draw_polygon_model(&temp_pos, &temp_orient, NULL, mn, 0, lrgb, NULL, NULL, OBJ_NONE); -#else - - // TODO(Justin): This needs to be fixed once we got blitting - enemy briefing - //if (Polygon_models[mn].rad != 0) - // temp_pos.z = fixmuldiv(DEFAULT_VIEW_DIST, Polygon_models[mn].rad, BASE_MODEL_SIZE); - //else - // temp_pos.z = DEFAULT_VIEW_DIST; - //vm_angles_2_matrix(&temp_orient, orient_angles); - - //// Alright, let's create a struct that holds a raster triangle + calculated depth, for sorting later - //float tri_avg_depths[2048]; - //RT_RasterTriVertex triangles[2048][3]; - //int new_tri_list_size = 0; - - //// For each triangle of the model - //for (int tri_i = 0; tri_i < meshVerticesRawHack[mn].triangle_count; ++tri_i) { - // // Get the triangle - it should already be in view space - // RT_Triangle* tri = &meshVerticesRawHack[mn].triangles[tri_i]; - - // // Transform to NDC space - static variable so we don't have to recalculate the matrix but I'm too lazy to put it in a more sane spot - // static RT_Mat4 proj_mat; - // static bool proj_mat_inited = false; - // if (!proj_mat_inited) { - // proj_mat = RT_Mat4Perspective(90.f * (3.14159265359f / 180.f), 16.0f / 9.0f, 0.1, 500.f); - // } - - // // Get the position - // RT_Vec4 p0 = { tri->pos0.x, tri->pos0.y, tri->pos0.z, 1.0f }; - // RT_Vec4 p1 = { tri->pos1.x, tri->pos1.y, tri->pos1.z, 1.0f }; - // RT_Vec4 p2 = { tri->pos2.x, tri->pos2.y, tri->pos2.z, 1.0f }; - - // // Apply rotation - // RT_Mat4 rot_mat = RT_Mat4Fromvms_matrix(&temp_orient); - // p0 = RT_Mat4TransformVec4(rot_mat, p0); - // p1 = RT_Mat4TransformVec4(rot_mat, p1); - // p2 = RT_Mat4TransformVec4(rot_mat, p2); - - // // Apply view - // p0.z += f2fl(temp_pos.z); - // p1.z += f2fl(temp_pos.z); - // p2.z += f2fl(temp_pos.z); - - // // Perspective projection - // p0 = RT_Mat4TransformVec4(proj_mat, p0); - // p1 = RT_Mat4TransformVec4(proj_mat, p1); - // p2 = RT_Mat4TransformVec4(proj_mat, p2); - - // // Perspective divide - // p0.x /= p0.w; - // p1.x /= p1.w; - // p2.x /= p2.w; - // p0.y /= p0.w; - // p1.y /= p1.w; - // p2.y /= p2.w; - // p0.z /= p0.w; - // p1.z /= p1.w; - // p2.z /= p2.w; - - // // Move it over scuffedly - // p0.x = p0.x * 2.5f + 0.2f; - // p1.x = p1.x * 2.5f + 0.2f; - // p2.x = p2.x * 2.5f + 0.2f; - // p0.y = p0.y * 2.5f - 0.3f; - // p1.y = p1.y * 2.5f - 0.3f; - // p2.y = p2.y * 2.5f - 0.3f; - - // // Create vertex - // RT_Vertex v0 = { p0.xyz, tri->uv0, tri->normal0, tri->tangent0.xyz, {0, 0, 0} }; - // RT_Vertex v1 = { p2.xyz, tri->uv2, tri->normal2, tri->tangent2.xyz, {0, 0, 0} }; - // RT_Vertex v2 = { p1.xyz, tri->uv1, tri->normal1, tri->tangent1.xyz, {0, 0, 0} }; - - // // Create raster triangle from it - // RT_RasterTriVertex raster_tri_v0 = { p0.xyz, v0.uv, {1,1,1,1}, tri->material_edge_index }; - // RT_RasterTriVertex raster_tri_v1 = { p1.xyz, v1.uv, {1,1,1,1}, tri->material_edge_index }; - // RT_RasterTriVertex raster_tri_v2 = { p2.xyz, v2.uv, {1,1,1,1}, tri->material_edge_index }; - // float avg_depth = v0.pos.z + v1.pos.z + v2.pos.z; // I would divide by 3 here but it's for sorting only, we don't care - - // // Depth culling - // if (avg_depth < 0.0f || avg_depth > 3.0f) { - // continue; - // } - - // // Add it to the list - // triangles[new_tri_list_size][0] = raster_tri_v0; - // triangles[new_tri_list_size][1] = raster_tri_v1; - // triangles[new_tri_list_size][2] = raster_tri_v2; - // tri_avg_depths[new_tri_list_size] = avg_depth; - - // // Move to next entry - // new_tri_list_size++; - //} - - // Sort the triangles - bubble sort - //int curr_max = new_tri_list_size; - //while (--curr_max) { - // // Loop over all unsorted elements - // for (int i = 0; i < curr_max; ++i) { - // // Swap triangles if this one pair's depths are the wrong way around - // if (tri_avg_depths[i] > tri_avg_depths[i + 1]) { - // // Swap depth - // { - // float tmp = tri_avg_depths[i]; - // tri_avg_depths[i] = tri_avg_depths[i + 1]; - // tri_avg_depths[i + 1] = tmp; - // } - // // Swap triangle - // for (int j = 0; j < 3; ++j) - // { - // RT_RasterTriVertex tmp = triangles[i][j]; - // triangles[i][j] = triangles[i + 1][j]; - // triangles[i + 1][j] = tmp; - // } - // } - // } - //} - - // Note(Justin): This could be wrong, but I do not care, since we will replace this with raytraced models anyways - /*RT_RasterTrianglesParams raster_tri_params = { 0 }; - raster_tri_params.texture_handle = g_rt_materials[triangles[0]->texture_index].albedo_texture; - raster_tri_params.num_vertices = new_tri_list_size; - raster_tri_params.vertices = triangles; - - RT_RasterTriangles(&raster_tri_params, 1);*/ - // Draw each triangle of the model - //for (size_t i = 0; i < new_tri_list_size; ++i) { - // // Draw triangles - // RT_RasterTriangle(materials[triangles[i][0].texture_index].albedo_texture, triangles[i]); - //} -#endif //RT_DX12 - - g3_end_frame(); -} - - -/* - * reads n polymodel structs from a PHYSFS_file - */ -extern int polymodel_read_n(polymodel* pm, int n, PHYSFS_file* fp) -{ - int i, j; - - for (i = 0; i < n; i++) { - pm[i].n_models = PHYSFSX_readInt(fp); - pm[i].model_data_size = PHYSFSX_readInt(fp); - pm[i].model_data = (ubyte*)(size_t)PHYSFSX_readInt(fp); - for (j = 0; j < MAX_SUBMODELS; j++) - pm[i].submodel_ptrs[j] = PHYSFSX_readInt(fp); - for (j = 0; j < MAX_SUBMODELS; j++) - PHYSFSX_readVector(&(pm[i].submodel_offsets[j]), fp); - for (j = 0; j < MAX_SUBMODELS; j++) - PHYSFSX_readVector(&(pm[i].submodel_norms[j]), fp); - for (j = 0; j < MAX_SUBMODELS; j++) - PHYSFSX_readVector(&(pm[i].submodel_pnts[j]), fp); - for (j = 0; j < MAX_SUBMODELS; j++) - pm[i].submodel_rads[j] = PHYSFSX_readFix(fp); - PHYSFS_read(fp, pm[i].submodel_parents, MAX_SUBMODELS, 1); - for (j = 0; j < MAX_SUBMODELS; j++) - PHYSFSX_readVector(&(pm[i].submodel_mins[j]), fp); - for (j = 0; j < MAX_SUBMODELS; j++) - PHYSFSX_readVector(&(pm[i].submodel_maxs[j]), fp); - PHYSFSX_readVector(&(pm[i].mins), fp); - PHYSFSX_readVector(&(pm[i].maxs), fp); - pm[i].rad = PHYSFSX_readFix(fp); - pm[i].n_textures = PHYSFSX_readByte(fp); - pm[i].first_texture = PHYSFSX_readShort(fp); - pm[i].simpler_model = PHYSFSX_readByte(fp); - } - return i; -} - -/* - * routine which allocates, reads, and inits a polymodel's model_data - */ -void polygon_model_data_read(polymodel* pm, PHYSFS_file* fp) -{ - pm->model_data = d_malloc(pm->model_data_size); - Assert(pm->model_data != NULL); - PHYSFS_read(fp, pm->model_data, sizeof(ubyte), pm->model_data_size); -#ifdef WORDS_NEED_ALIGNMENT - align_polygon_model_data(pm); -#endif -#ifdef WORDS_BIGENDIAN - swap_polygon_model_data(pm->model_data); -#endif +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +/* + * + * Hacked-in polygon objects + * + */ + + +#include +#include +#include + +#ifdef DRIVE +#include "drive.h" +#else +#include "inferno.h" +#endif +#include "polyobj.h" +#include "vecmat.h" +#include "3d.h" +#include "dxxerror.h" +#include "u_mem.h" +#include "args.h" +#ifndef DRIVE +#include "texmap.h" +#include "bm.h" +#include "textures.h" +#include "object.h" +#include "lighting.h" +#include "piggy.h" +#endif +#include "byteswap.h" +#include "render.h" +#ifdef OGL +#include "ogl_init.h" +#endif +#include "logger.h" + +#ifdef RT_DX12 +#include "RTgr.h" +#include "RTmaterials.h" +#endif //RT_DX12 + +polymodel Polygon_models[MAX_POLYGON_MODELS]; // = {&bot11,&bot17,&robot_s2,&robot_b2,&bot11,&bot17,&robot_s2,&robot_b2}; + +int N_polygon_models = 0; + +#define MAX_POLYGON_VECS 1000 +g3s_point robot_points[MAX_POLYGON_VECS]; + +#define PM_COMPATIBLE_VERSION 6 +#define PM_OBJFILE_VERSION 8 + +int Pof_file_end; +int Pof_addr; + +#define MODEL_BUF_SIZE 32768 + +void _pof_cfseek(int len, int type) +{ + switch (type) { + case SEEK_SET: Pof_addr = len; break; + case SEEK_CUR: Pof_addr += len; break; + case SEEK_END: + Assert(len <= 0); // seeking from end, better be moving back. + Pof_addr = Pof_file_end + len; + break; + } + + if (Pof_addr > MODEL_BUF_SIZE) + Int3(); +} + +#define pof_cfseek(_buf,_len,_type) _pof_cfseek((_len),(_type)) + +int pof_read_int(ubyte* bufp) +{ + int i; + + i = *((int*)&bufp[Pof_addr]); + Pof_addr += 4; + return INTEL_INT(i); + + // if (PHYSFS_read(f,&i,sizeof(i),1) != 1) + // RT_LOGF(RT_LOGSERVERITY_HIGH, "Unexpected end-of-file while reading object"); + // + // return i; +} + +size_t pof_cfread(void* dst, size_t elsize, size_t nelem, ubyte* bufp) +{ + if (Pof_addr + nelem * elsize > Pof_file_end) + return 0; + + memcpy(dst, &bufp[Pof_addr], elsize * nelem); + + Pof_addr += elsize * nelem; + + if (Pof_addr > MODEL_BUF_SIZE) + Int3(); + + return nelem; +} + +// #define new_read_int(i,f) PHYSFS_read((f),&(i),sizeof(i),1) +#define new_pof_read_int(i,f) pof_cfread(&(i),sizeof(i),1,(f)) + +short pof_read_short(ubyte* bufp) +{ + short s; + + s = *((short*)&bufp[Pof_addr]); + Pof_addr += 2; + return INTEL_SHORT(s); + // if (PHYSFS_read(f,&s,sizeof(s),1) != 1) + // RT_LOGF(RT_LOGSERVERITY_HIGH, "Unexpected end-of-file while reading object"); + // + // return s; +} + +void pof_read_string(char* buf, int max, ubyte* bufp) +{ + int i; + + for (i = 0; i < max; i++) { + if ((*buf++ = bufp[Pof_addr++]) == 0) + break; + } + + // while (max-- && (*buf=PHYSFSX_fgetc(f)) != 0) buf++; + +} + +void pof_read_vecs(vms_vector* vecs, int n, ubyte* bufp) +{ + int i; + // PHYSFS_read(f,vecs,sizeof(vms_vector),n); + + for (i = 0; i < n; i++) + { + vecs[i].x = pof_read_int(bufp); + vecs[i].y = pof_read_int(bufp); + vecs[i].z = pof_read_int(bufp); + } +} + +void pof_read_angvecs(vms_angvec* vecs, int n, ubyte* bufp) +{ + int i; + // PHYSFS_read(f,vecs,sizeof(vms_vector),n); + + for (i = 0; i < n; i++) + { + vecs[i].p = pof_read_short(bufp); + vecs[i].b = pof_read_short(bufp); + vecs[i].h = pof_read_short(bufp); + } +} + +#define ID_OHDR 0x5244484f // 'RDHO' //Object header +#define ID_SOBJ 0x4a424f53 // 'JBOS' //Subobject header +#define ID_GUNS 0x534e5547 // 'SNUG' //List of guns on this object +#define ID_ANIM 0x4d494e41 // 'MINA' //Animation data +#define ID_IDTA 0x41544449 // 'ATDI' //Interpreter data +#define ID_TXTR 0x52545854 // 'RTXT' //Texture filename list + +#ifdef DRIVE +#define robot_info void +#else +vms_angvec anim_angs[N_ANIM_STATES][MAX_SUBMODELS]; + +//set the animation angles for this robot. Gun fields of robot info must +//be filled in. +void robot_set_angles(robot_info* r, polymodel* pm, vms_angvec angs[N_ANIM_STATES][MAX_SUBMODELS]); +#endif + +#ifdef WORDS_NEED_ALIGNMENT +ubyte* old_dest(chunk o) // return where chunk is (in unaligned struct) +{ + return o.old_base + INTEL_SHORT(*((short*)(o.old_base + o.offset))); +} + +ubyte* new_dest(chunk o) // return where chunk is (in aligned struct) +{ + return o.new_base + INTEL_SHORT(*((short*)(o.old_base + o.offset))) + o.correction; +} + +/* + * find chunk with smallest address + */ +int get_first_chunks_index(chunk* chunk_list, int no_chunks) +{ + int i, first_index = 0; + Assert(no_chunks >= 1); + for (i = 1; i < no_chunks; i++) + if (old_dest(chunk_list[i]) < old_dest(chunk_list[first_index])) + first_index = i; + return first_index; +} +#define SHIFT_SPACE 500 // increase if insufficent + +void align_polygon_model_data(polymodel* pm) +{ + int i, chunk_len; + int total_correction = 0; + ubyte* cur_old, * cur_new; + chunk cur_ch; + chunk ch_list[MAX_CHUNKS]; + int no_chunks = 0; + int tmp_size = pm->model_data_size + SHIFT_SPACE; + ubyte* tmp = d_malloc(tmp_size); // where we build the aligned version of pm->model_data + + Assert(tmp != NULL); + //start with first chunk (is always aligned!) + cur_old = pm->model_data; + cur_new = tmp; + chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks); + memcpy(cur_new, cur_old, chunk_len); + while (no_chunks > 0) { + int first_index = get_first_chunks_index(ch_list, no_chunks); + cur_ch = ch_list[first_index]; + // remove first chunk from array: + no_chunks--; + for (i = first_index; i < no_chunks; i++) + ch_list[i] = ch_list[i + 1]; + // if (new) address unaligned: + if ((u_int32_t)new_dest(cur_ch) % 4L != 0) { + // calculate how much to move to be aligned + short to_shift = 4 - (u_int32_t)new_dest(cur_ch) % 4L; + // correct chunks' addresses + cur_ch.correction += to_shift; + for (i = 0; i < no_chunks; i++) + ch_list[i].correction += to_shift; + total_correction += to_shift; + Assert((u_int32_t)new_dest(cur_ch) % 4L == 0); + Assert(total_correction <= SHIFT_SPACE); // if you get this, increase SHIFT_SPACE + } + //write (corrected) chunk for current chunk: + *((short*)(cur_ch.new_base + cur_ch.offset)) + = INTEL_SHORT(cur_ch.correction + + INTEL_SHORT(*((short*)(cur_ch.old_base + cur_ch.offset)))); + //write (correctly aligned) chunk: + cur_old = old_dest(cur_ch); + cur_new = new_dest(cur_ch); + chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks); + memcpy(cur_new, cur_old, chunk_len); + //correct submodel_ptr's for pm, too + for (i = 0; i < MAX_SUBMODELS; i++) + if (pm->model_data + pm->submodel_ptrs[i] >= cur_old + && pm->model_data + pm->submodel_ptrs[i] < cur_old + chunk_len) + pm->submodel_ptrs[i] += (cur_new - tmp) - (cur_old - pm->model_data); + } + d_free(pm->model_data); + pm->model_data_size += total_correction; + pm->model_data = + d_malloc(pm->model_data_size); + Assert(pm->model_data != NULL); + memcpy(pm->model_data, tmp, pm->model_data_size); + d_free(tmp); +} +#endif //def WORDS_NEED_ALIGNMENT + + +//reads a binary file containing a 3d model +polymodel* read_model_file(polymodel* pm, char* filename, robot_info* r) +{ + PHYSFS_file* ifile; + short version; + int id, len, next_chunk; + ubyte model_buf[MODEL_BUF_SIZE]; + + if ((ifile = PHYSFSX_openReadBuffered(filename)) == NULL) + RT_LOGF(RT_LOGSERVERITY_HIGH, "Can't open file <%s>", filename); + + Assert(PHYSFS_fileLength(ifile) <= MODEL_BUF_SIZE); + + Pof_addr = 0; + Pof_file_end = PHYSFS_read(ifile, model_buf, 1, PHYSFS_fileLength(ifile)); + PHYSFS_close(ifile); + + id = pof_read_int(model_buf); + + if (id != 0x4f505350) /* 'OPSP' */ + RT_LOGF(RT_LOGSERVERITY_HIGH, "Bad ID in model file <%s>", filename); + + version = pof_read_short(model_buf); + + if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION) + RT_LOGF(RT_LOGSERVERITY_HIGH, "Bad version (%d) in model file <%s>", version, filename); + + while (new_pof_read_int(id, model_buf) == 1) { + id = INTEL_INT(id); + //id = pof_read_int(model_buf); + len = pof_read_int(model_buf); + next_chunk = Pof_addr + len; + + switch (id) { + + case ID_OHDR: { //Object header + vms_vector pmmin, pmmax; + + pm->n_models = pof_read_int(model_buf); + pm->rad = pof_read_int(model_buf); + + Assert(pm->n_models <= MAX_SUBMODELS); + + pof_read_vecs(&pmmin, 1, model_buf); + pof_read_vecs(&pmmax, 1, model_buf); + + break; + } + + case ID_SOBJ: { //Subobject header + int n; + + n = pof_read_short(model_buf); + + Assert(n < MAX_SUBMODELS); + + pm->submodel_parents[n] = pof_read_short(model_buf); + + pof_read_vecs(&pm->submodel_norms[n], 1, model_buf); + pof_read_vecs(&pm->submodel_pnts[n], 1, model_buf); + pof_read_vecs(&pm->submodel_offsets[n], 1, model_buf); + + pm->submodel_rads[n] = pof_read_int(model_buf); //radius + + pm->submodel_ptrs[n] = pof_read_int(model_buf); //offset + + break; + + } + +#ifndef DRIVE + case ID_GUNS: { //List of guns on this object + + if (r) { + int i; + vms_vector gun_dir; + + r->n_guns = pof_read_int(model_buf); + + Assert(r->n_guns <= MAX_GUNS); + + for (i = 0; i < r->n_guns; i++) { + int id; + + id = pof_read_short(model_buf); + r->gun_submodels[id] = pof_read_short(model_buf); + Assert(r->gun_submodels[id] != 0xff); + pof_read_vecs(&r->gun_points[id], 1, model_buf); + + if (version >= 7) + pof_read_vecs(&gun_dir, 1, model_buf); + } + } + else + pof_cfseek(model_buf, len, SEEK_CUR); + + break; + } + + case ID_ANIM: //Animation data + if (r) { + int n_frames, f, m; + + n_frames = pof_read_short(model_buf); + + Assert(n_frames == N_ANIM_STATES); + + for (m = 0; m < pm->n_models; m++) + for (f = 0; f < n_frames; f++) + pof_read_angvecs(&anim_angs[f][m], 1, model_buf); + + robot_set_angles(r, pm, anim_angs); + + } + else + pof_cfseek(model_buf, len, SEEK_CUR); + + break; +#endif + + case ID_TXTR: { //Texture filename list + int n; + char name_buf[128]; + + n = pof_read_short(model_buf); + while (n--) { + pof_read_string(name_buf, 128, model_buf); + } + + break; + } + + case ID_IDTA: //Interpreter data + pm->model_data = d_malloc(len); + pm->model_data_size = len; + + pof_cfread(pm->model_data, 1, len, model_buf); + + break; + + default: + pof_cfseek(model_buf, len, SEEK_CUR); + break; + + } + if (version >= 8) // Version 8 needs 4-byte alignment!!! + pof_cfseek(model_buf, next_chunk, SEEK_SET); + } + +#ifdef WORDS_NEED_ALIGNMENT + align_polygon_model_data(pm); +#endif +#ifdef WORDS_BIGENDIAN + swap_polygon_model_data(pm->model_data); +#endif + + return pm; +} + +//reads the gun information for a model +//fills in arrays gun_points & gun_dirs, returns the number of guns read +int read_model_guns(char* filename, vms_vector* gun_points, vms_vector* gun_dirs, int* gun_submodels) +{ + PHYSFS_file* ifile; + short version; + int id, len; + int n_guns = 0; + ubyte model_buf[MODEL_BUF_SIZE]; + + if ((ifile = PHYSFSX_openReadBuffered(filename)) == NULL) + RT_LOGF(RT_LOGSERVERITY_HIGH, "Can't open file <%s>", filename); + + Assert(PHYSFS_fileLength(ifile) <= MODEL_BUF_SIZE); + + Pof_addr = 0; + Pof_file_end = PHYSFS_read(ifile, model_buf, 1, PHYSFS_fileLength(ifile)); + PHYSFS_close(ifile); + + id = pof_read_int(model_buf); + + if (id != 0x4f505350) /* 'OPSP' */ + RT_LOGF(RT_LOGSERVERITY_HIGH, "Bad ID in model file <%s>", filename); + + version = pof_read_short(model_buf); + + Assert(version >= 7); //must be 7 or higher for this data + + if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION) + RT_LOGF(RT_LOGSERVERITY_HIGH, "Bad version (%d) in model file <%s>", version, filename); + + while (new_pof_read_int(id, model_buf) == 1) { + id = INTEL_INT(id); + //id = pof_read_int(model_buf); + len = pof_read_int(model_buf); + + if (id == ID_GUNS) { //List of guns on this object + + int i; + + n_guns = pof_read_int(model_buf); + + for (i = 0; i < n_guns; i++) { + int id, sm; + + id = pof_read_short(model_buf); + sm = pof_read_short(model_buf); + if (gun_submodels) + gun_submodels[id] = sm; + else if (sm != 0) + RT_LOGF(RT_LOGSERVERITY_HIGH, "Invalid gun submodel in file <%s>", filename); + pof_read_vecs(&gun_points[id], 1, model_buf); + + pof_read_vecs(&gun_dirs[id], 1, model_buf); + } + + } + else + pof_cfseek(model_buf, len, SEEK_CUR); + + } + + return n_guns; +} + +//free up a model, getting rid of all its memory +void free_model(polymodel* po) +{ + d_free(po->model_data); +} + +grs_bitmap* texture_list[MAX_POLYOBJ_TEXTURES]; +bitmap_index texture_list_index[MAX_POLYOBJ_TEXTURES]; + +//draw a polygon model + +void draw_polygon_model(_RT_DRAW_POLY vms_vector* pos, vms_matrix* orient, vms_angvec* anim_angles, int model_num, int flags, g3s_lrgb light, fix* glow_values, bitmap_index alt_textures[]) +{ + polymodel* po; + int i; + + if (model_num < 0) + return; + + Assert(model_num < N_polygon_models); + + po = &Polygon_models[model_num]; + + //check if should use simple model + if (po->simpler_model) //must have a simpler model + if (flags == 0) //can't switch if this is debris + //!!if (!alt_textures) { //alternate textures might not match + //alt textures might not match, but in the one case we're using this + //for on 11/14/94, they do match. So we leave it in. + { + int cnt = 1; + fix depth; + + depth = g3_calc_point_depth(pos); //gets 3d depth + + while (po->simpler_model && depth > cnt++ * Simple_model_threshhold_scale * po->rad) + po = &Polygon_models[po->simpler_model - 1]; + } + + if (alt_textures) + // TODO(daniel): When do these alt textures get used? Our renderer doesn't currently support anything like this. + for (i = 0; i < po->n_textures; i++) { + texture_list_index[i] = alt_textures[i]; + texture_list[i] = &GameBitmaps[alt_textures[i].index]; + } + else + for (i = 0; i < po->n_textures; i++) { + texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture + i]]; + texture_list[i] = &GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture + i]].index]; + } + + // Make sure the textures for this object are paged in... + piggy_page_flushed = 0; + for (i = 0; i < po->n_textures; i++) + PIGGY_PAGE_IN(texture_list_index[i]); + // Hmmm... cache got flushed in the middle of paging all these in, + // so we need to reread them all in. + if (piggy_page_flushed) { + piggy_page_flushed = 0; + for (i = 0; i < po->n_textures; i++) + PIGGY_PAGE_IN(texture_list_index[i]); + } + // Make sure that they can all fit in memory. + Assert(piggy_page_flushed == 0); + + g3_start_instance_matrix(pos, orient); + + g3_set_interp_points(robot_points); + + if (flags == 0) //draw entire object + { +#ifndef RT_DX12 + g3_draw_polygon_model(po->model_data, texture_list, anim_angles, light, glow_values); +#else + //RT_DrawPolyModel(model_num, objNum, object_type, pos, orient); + + RT_DrawPolyModelTree(model_num, signature, object_type, pos, orient, anim_angles); +#endif //RT_DX12 + } + else { + int i; + + for (i = 0; flags; flags >>= 1, i++) + if (flags & 1) { + vms_vector ofs; + + Assert(i < po->n_models); + + //if submodel, rotate around its center point, not pivot point + + vm_vec_avg(&ofs, &po->submodel_mins[i], &po->submodel_maxs[i]); + vm_vec_negate(&ofs); + g3_start_instance_matrix(&ofs, NULL); +#ifndef RT_DX12 + g3_draw_polygon_model(&po->model_data[po->submodel_ptrs[i]], texture_list, anim_angles, light, glow_values); +#else + // Get matrix from local position offset + const vms_vector offset_vms = *pos; + const RT_Vec3 offset_vec3 = RT_Vec3Fromvms_vector(&offset_vms); + RT_Mat4 offset_mat4 = RT_Mat4FromTranslation(offset_vec3); + + // Get matrix from rotation offset + RT_Mat4 rotation_mat4 = RT_Mat4Fromvms_matrix(orient); + + // Combine them into one big matrix + RT_Mat4 combined_matrix = RT_Mat4Mul(offset_mat4, rotation_mat4); + // RT_Mat4 prev_transform = g_rt_prev_submodel_transforms[objNum].transforms[i]; + + RT_RenderKey key = + { + .signature = signature, + .submodel_index = i, + }; + + RT_DrawSubPolyModel(po->submodel[i], &combined_matrix, key); + + // g_rt_prev_submodel_transforms[objNum].transforms[i] = combined_matrix; +#endif //RT_DX12 + + g3_done_instance(); + } + } + + g3_done_instance(); + +} + +void free_polygon_models() +{ + int i; + + for (i = 0; i < N_polygon_models; i++) { + free_model(&Polygon_models[i]); + } + +} + +void polyobj_find_min_max(polymodel* pm) +{ + ushort nverts; + vms_vector* vp; + ushort* data, type; + int m; + vms_vector* big_mn, * big_mx; + + big_mn = &pm->mins; + big_mx = &pm->maxs; + + for (m = 0; m < pm->n_models; m++) { + vms_vector* mn, * mx, * ofs; + + mn = &pm->submodel_mins[m]; + mx = &pm->submodel_maxs[m]; + ofs = &pm->submodel_offsets[m]; + + data = (ushort*)&pm->model_data[pm->submodel_ptrs[m]]; + + type = *data++; + + Assert(type == 7 || type == 1); + + nverts = *data++; + + if (type == 7) + data += 2; //skip start & pad + + vp = (vms_vector*)data; + + *mn = *mx = *vp++; nverts--; + + if (m == 0) + *big_mn = *big_mx = *mn; + + while (nverts--) { + if (vp->x > mx->x) mx->x = vp->x; + if (vp->y > mx->y) mx->y = vp->y; + if (vp->z > mx->z) mx->z = vp->z; + + if (vp->x < mn->x) mn->x = vp->x; + if (vp->y < mn->y) mn->y = vp->y; + if (vp->z < mn->z) mn->z = vp->z; + + if (vp->x + ofs->x > big_mx->x) big_mx->x = vp->x + ofs->x; + if (vp->y + ofs->y > big_mx->y) big_mx->y = vp->y + ofs->y; + if (vp->z + ofs->z > big_mx->z) big_mx->z = vp->z + ofs->z; + + if (vp->x + ofs->x < big_mn->x) big_mn->x = vp->x + ofs->x; + if (vp->y + ofs->y < big_mn->y) big_mn->y = vp->y + ofs->y; + if (vp->z + ofs->z < big_mn->z) big_mn->z = vp->z + ofs->z; + + vp++; + } + } +} + +char Pof_names[MAX_POLYGON_MODELS][13]; + +//returns the number of this model +#ifndef DRIVE +int load_polygon_model(char* filename, int n_textures, int first_texture, robot_info* r) +#else +int load_polygon_model(char* filename, int n_textures, grs_bitmap*** textures) +#endif +{ +#ifdef DRIVE +#define r NULL +#endif + + Assert(N_polygon_models < MAX_POLYGON_MODELS); + Assert(n_textures < MAX_POLYOBJ_TEXTURES); + + Assert(strlen(filename) <= 12); + strcpy(Pof_names[N_polygon_models], filename); + + read_model_file(&Polygon_models[N_polygon_models], filename, r); + + polyobj_find_min_max(&Polygon_models[N_polygon_models]); + + g3_init_polygon_model(Polygon_models[N_polygon_models].model_data); + + //Don't need this log, because we don't use highest_texture_num on dx12 + //if (highest_texture_num + 1 != n_textures) + // RT_LOGF(RT_LOGSERVERITY_HIGH, "Model <%s> references %d textures but specifies %d.", filename, highest_texture_num + 1, n_textures); + + Polygon_models[N_polygon_models].n_textures = n_textures; + Polygon_models[N_polygon_models].first_texture = first_texture; + Polygon_models[N_polygon_models].simpler_model = 0; + + //Assert(polygon_models[N_polygon_models]!=NULL); + + N_polygon_models++; + return N_polygon_models - 1; +} + + +void init_polygon_models() +{ + N_polygon_models = 0; +} + +//compare against this size when figuring how far to place eye for picture +#define BASE_MODEL_SIZE 0x28000 + +#define DEFAULT_VIEW_DIST 0x60000 + +//draws the given model in the current canvas. The distance is set to +//more-or-less fill the canvas. Note that this routine actually renders +//into an off-screen canvas that it creates, then copies to the current +//canvas. +void draw_model_picture(int mn, vms_angvec* orient_angles) +{ + vms_vector temp_pos = ZERO_VECTOR; + vms_matrix temp_orient = IDENTITY_MATRIX; + g3s_lrgb lrgb = { f1_0, f1_0, f1_0 }; + + Assert(mn >= 0 && mn < N_polygon_models); + + gr_clear_canvas(BM_XRGB(0, 0, 0)); + g3_start_frame(); + g3_set_view_matrix(&temp_pos, &temp_orient, 0x9000); + +#ifndef RT_DX12 + if (Polygon_models[mn].rad != 0) + temp_pos.z = fixmuldiv(DEFAULT_VIEW_DIST, Polygon_models[mn].rad, BASE_MODEL_SIZE); + else + temp_pos.z = DEFAULT_VIEW_DIST; + + vm_angles_2_matrix(&temp_orient, orient_angles); + draw_polygon_model(&temp_pos, &temp_orient, NULL, mn, 0, lrgb, NULL, NULL, OBJ_NONE); +#else + + if (Polygon_models[mn].rad != 0) + temp_pos.z = fixmuldiv(DEFAULT_VIEW_DIST, Polygon_models[mn].rad, BASE_MODEL_SIZE); + else + temp_pos.z = DEFAULT_VIEW_DIST; + vm_angles_2_matrix(&temp_orient, orient_angles); + draw_polygon_model(0, 2, &temp_pos, &temp_orient, NULL, mn, 0, lrgb, NULL, NULL, OBJ_NONE); +#endif //RT_DX12 + + g3_end_frame(); +} + + +/* + * reads n polymodel structs from a PHYSFS_file + */ +extern int polymodel_read_n(polymodel* pm, int n, PHYSFS_file* fp) +{ + int i, j; + + for (i = 0; i < n; i++) { + pm[i].n_models = PHYSFSX_readInt(fp); + pm[i].model_data_size = PHYSFSX_readInt(fp); + pm[i].model_data = (ubyte*)(size_t)PHYSFSX_readInt(fp); + for (j = 0; j < MAX_SUBMODELS; j++) + pm[i].submodel_ptrs[j] = PHYSFSX_readInt(fp); + for (j = 0; j < MAX_SUBMODELS; j++) + PHYSFSX_readVector(&(pm[i].submodel_offsets[j]), fp); + for (j = 0; j < MAX_SUBMODELS; j++) + PHYSFSX_readVector(&(pm[i].submodel_norms[j]), fp); + for (j = 0; j < MAX_SUBMODELS; j++) + PHYSFSX_readVector(&(pm[i].submodel_pnts[j]), fp); + for (j = 0; j < MAX_SUBMODELS; j++) + pm[i].submodel_rads[j] = PHYSFSX_readFix(fp); + PHYSFS_read(fp, pm[i].submodel_parents, MAX_SUBMODELS, 1); + for (j = 0; j < MAX_SUBMODELS; j++) + PHYSFSX_readVector(&(pm[i].submodel_mins[j]), fp); + for (j = 0; j < MAX_SUBMODELS; j++) + PHYSFSX_readVector(&(pm[i].submodel_maxs[j]), fp); + PHYSFSX_readVector(&(pm[i].mins), fp); + PHYSFSX_readVector(&(pm[i].maxs), fp); + pm[i].rad = PHYSFSX_readFix(fp); + pm[i].n_textures = PHYSFSX_readByte(fp); + pm[i].first_texture = PHYSFSX_readShort(fp); + pm[i].simpler_model = PHYSFSX_readByte(fp); + } + return i; +} + +/* + * routine which allocates, reads, and inits a polymodel's model_data + */ +void polygon_model_data_read(polymodel* pm, PHYSFS_file* fp) +{ + pm->model_data = d_malloc(pm->model_data_size); + Assert(pm->model_data != NULL); + PHYSFS_read(fp, pm->model_data, sizeof(ubyte), pm->model_data_size); +#ifdef WORDS_NEED_ALIGNMENT + align_polygon_model_data(pm); +#endif +#ifdef WORDS_BIGENDIAN + swap_polygon_model_data(pm->model_data); +#endif } \ No newline at end of file diff --git a/d1/main/render.c b/d1/main/render.c index ac3a9b8..debef48 100644 --- a/d1/main/render.c +++ b/d1/main/render.c @@ -59,6 +59,8 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #ifdef RT_DX12 #include "Core/Arena.h" +#include "Game/Lights.h" +#include "RTmaterials.h" #include "RTgr.h" #include "dx12.h" #endif @@ -171,10 +173,26 @@ void flash_frame() // flash_ang += fixmul(FLASH_CYCLE_RATE,FrameTime); flash_ang += fixmul(flash_rate, FrameTime); - + fix_fastsincos(flash_ang, &flash_scale, NULL); flash_scale = (flash_scale + f1_0) / 2; + +#ifdef RT_DX12 + g_light_multiplier = f2fl(flash_scale); + g_pending_light_update = true; + + //Creating different sincos for emissive + fix flash_scale_em = 0; + fix flash_offset = fl2f(0.90f); + fix_fastsincos(flash_ang + flash_offset, &flash_scale_em, NULL); + flash_scale_em = (flash_scale_em + f1_0) / 2; + + int lightTexture = PCSharePig ? 774 : 997; + RT_Material* material = &g_rt_materials[lightTexture]; + material->emissive_strength = f2fl(flash_scale_em) * 3.5f; + RT_UpdateMaterial(lightTexture, material); +#endif } #ifdef OGL @@ -1549,8 +1567,17 @@ void render_frame(fix eye_offset) Zoom_factor = F1_0; } g3_set_view_matrix(&Viewer_eye, &Viewer->orient, fixdiv(Render_zoom, Zoom_factor)); +#else +#ifdef RT_DX12 + if (!g_rt_free_cam_info.g_free_cam_enabled) { + g3_set_view_matrix(&Viewer_eye, &Viewer->orient, Render_zoom); + } + else { + g3_set_view_matrix(&Viewer_eye, &Objects[g_rt_free_cam_info.g_free_cam_obj].orient, Render_zoom); + } #else g3_set_view_matrix(&Viewer_eye, &Viewer->orient, Render_zoom); +#endif #endif } @@ -1562,19 +1589,38 @@ void render_frame(fix eye_offset) } #ifdef RT_DX12 - g_cam.vfov = 60.0f; - RT_Vec3 player_pos = RT_Vec3FromVmsVector(Viewer->pos); - g_cam.position = player_pos; - //We just take the real view matrix and not the viewer's one. Since the view matrix gets properly used and changed. - g_cam.up = RT_Vec3Normalize(RT_Vec3FromVmsVector(View_matrix.uvec)); - g_cam.forward = RT_Vec3Normalize(RT_Vec3FromVmsVector(View_matrix.fvec)); - g_cam.right = RT_Vec3Normalize(RT_Vec3FromVmsVector(View_matrix.rvec)); - //We still keep this code incase anything breaks due to the camera. - //g_cam.up = RT_Vec3FromVmsVector(Viewer->orient.uvec); - //g_cam.forward = RT_Vec3FromVmsVector(Viewer->orient.fvec); - //g_cam.right = RT_Vec3FromVmsVector(Viewer->orient.rvec); + RT_SceneSettings scene_settings = { 0 }; - scene_settings.camera = &g_cam; + RT_Vec3 object_pos; + + if (!g_rt_free_cam_info.g_free_cam_enabled) { + //Setup main camera + object_pos = RT_Vec3FromVmsVector(Viewer->pos); + g_cam.position = object_pos; + + //We just take the real view matrix and not the viewer's one. Since the view matrix gets properly used and changed. + g_cam.up = RT_Vec3Normalize(RT_Vec3FromVmsVector(View_matrix.uvec)); + g_cam.forward = RT_Vec3Normalize(RT_Vec3FromVmsVector(View_matrix.fvec)); + g_cam.right = RT_Vec3Normalize(RT_Vec3FromVmsVector(View_matrix.rvec)); + + //We still keep this code incase anything breaks due to the camera. + //g_cam.up = RT_Vec3FromVmsVector(Viewer->orient.uvec); + //g_cam.forward = RT_Vec3FromVmsVector(Viewer->orient.fvec); + //g_cam.right = RT_Vec3FromVmsVector(Viewer->orient.rvec); + + scene_settings.camera = &g_cam; + } + else { + //Setup free cam + object_pos = RT_Vec3FromVmsVector(Objects[g_rt_free_cam_info.g_free_cam_obj].pos); + g_free_cam.position = object_pos; + + g_free_cam.up = RT_Vec3Normalize(RT_Vec3FromVmsVector(View_matrix.uvec)); + g_free_cam.forward = RT_Vec3Normalize(RT_Vec3FromVmsVector(View_matrix.fvec)); + g_free_cam.right = RT_Vec3Normalize(RT_Vec3FromVmsVector(View_matrix.rvec)); + scene_settings.camera = &g_free_cam; + } + scene_settings.render_width_override = Screen_3d_window.cv_bitmap.bm_w; scene_settings.render_height_override = Screen_3d_window.cv_bitmap.bm_h; RT_BeginScene(&scene_settings); @@ -1586,8 +1632,8 @@ void render_frame(fix eye_offset) float pos_offset_vert = -2.0f; float skew_horz = 0.12f; float skew_vert = 0.06f; - RT_Vec3 light_pos_left = RT_Vec3Add3(player_pos, RT_Vec3Muls(g_cam.right, -pos_offset_horz), RT_Vec3Muls(g_cam.up, pos_offset_vert)); - RT_Vec3 light_pos_right = RT_Vec3Add3(player_pos, RT_Vec3Muls(g_cam.right, +pos_offset_horz), RT_Vec3Muls(g_cam.up, pos_offset_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); @@ -1600,13 +1646,16 @@ void render_frame(fix eye_offset) light_spot_angle, light_spot_softness, 0.6f)); } - RT_RenderLevel(player_pos); RT_RenderPolyModelViewer(); RT_RenderMaterialViewer(); #endif //RT_DX12 render_mine(start_seg_num, eye_offset); +#ifdef RT_DX12 // Separated because render_mine submits dynamic lights, which impacts how many level lights we want to send + RT_RenderLevel(object_pos); +#endif + g3_end_frame(); #ifdef RT_DX12 @@ -1630,13 +1679,23 @@ void render_frame(fix eye_offset) RT_Mat4 rot = RT_Mat4Fromvms_matrix(&Viewer->orient); mat = RT_Mat4Mul(mat, RT_Mat4Fromvms_matrix(&Viewer->orient)); - // Apply hard-coded offset for the cockpit - it's ok - mat = RT_Mat4Mul(mat, RT_Mat4FromYRotation(3.14159265f)); - RT_Vec3 offset = { 0.0f, -0.5f, -2.25f }; - mat = RT_Mat4Mul(mat, RT_Mat4FromTranslation(offset)); + // Apply offset for the cockpit + if (Rear_view) { + mat = RT_Mat4Mul(mat, RT_Mat4FromXRotation(g_rt_cockpit_settings.back_cockpit_rotation.x)); + mat = RT_Mat4Mul(mat, RT_Mat4FromYRotation(g_rt_cockpit_settings.back_cockpit_rotation.y)); + mat = RT_Mat4Mul(mat, RT_Mat4FromZRotation(g_rt_cockpit_settings.back_cockpit_rotation.z)); + mat = RT_Mat4Mul(mat, RT_Mat4FromTranslation(g_rt_cockpit_settings.back_cockpit_offset)); + mat = RT_Mat4Mul(mat, RT_Mat4FromScale(g_rt_cockpit_settings.back_cockpit_scale)); + } else { + mat = RT_Mat4Mul(mat, RT_Mat4FromXRotation(g_rt_cockpit_settings.front_cockpit_rotation.x)); + mat = RT_Mat4Mul(mat, RT_Mat4FromYRotation(g_rt_cockpit_settings.front_cockpit_rotation.y)); + mat = RT_Mat4Mul(mat, RT_Mat4FromZRotation(g_rt_cockpit_settings.front_cockpit_rotation.z)); + mat = RT_Mat4Mul(mat, RT_Mat4FromTranslation(g_rt_cockpit_settings.front_cockpit_offset)); + mat = RT_Mat4Mul(mat, RT_Mat4FromScale(g_rt_cockpit_settings.front_cockpit_scale)); + } // Render mesh - RT_DrawGLTF(g_rt_cockpit_gltf, mat, prev_matrix); + RT_DrawGLTF(g_rt_cockpit_settings.cockpit_gltf, mat, prev_matrix); prev_matrix = mat; } } diff --git a/d1/main/titles.c b/d1/main/titles.c index 4ed898e..7bb145f 100644 --- a/d1/main/titles.c +++ b/d1/main/titles.c @@ -55,7 +55,12 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #endif #ifdef RT_DX12 +#include "RTgr.h" #include "dx12.h" +#include "globvars.h" +#include "Core/Arena.h" +#include "Core/MiniMath.h" +#include "ImageReadWrite.h" #endif #define MAX_BRIEFING_COLORS 7 @@ -185,10 +190,24 @@ static int show_title_screen( char * filename, int allow_keys, int from_hog_only return 0; } +static int load_the_palette_of_the_title_screen_like_a_fucking_psycho(char * filename) +{ + grs_bitmap bitmap; + gr_init_bitmap_data(&bitmap); + + int pcx_error; + + if ((pcx_error=pcx_read_bitmap( filename, &bitmap, BM_LINEAR, gr_palette ))!=PCX_ERROR_NONE) { + RT_LOGF(RT_LOGSERVERITY_HIGH, "Error loading briefing screen <%s>, PCX load error: %s (%i)\n",filename, pcx_errormsg(pcx_error), pcx_error); + } + + gr_palette_load(gr_palette); + gr_free_bitmap_data(&bitmap); +} + void show_titles(void) { char publisher[PATH_MAX]; - char buasLogo[PATH_MAX]; songs_play_song( SONG_TITLE, 1 ); @@ -201,14 +220,31 @@ void show_titles(void) if (!PHYSFSX_exists(publisher,1)) strcpy(publisher, "iplogo1.pcx"); // PC. Only down here because it's lowres ;-) - if (!PHYSFSX_exists("assets/splash-logo/buas.pcx", 1)) - RT_LOG(RT_LOGSERVERITY_ASSERT, "Cannot find BUAS splash logo"); - strcpy(buasLogo, "assets/splash-logo/buas.pcx"); + show_title_screen(publisher, 1, 0); + show_title_screen((((SWIDTH>=640&&SHEIGHT>=480) && PHYSFSX_exists("logoh.pcx",1))?"logoh.pcx":"logo.pcx"), 1, 0); + + if (PHYSFSX_exists("assets/splash-logo/buas.pcx", 1)) + show_title_screen("assets/splash-logo/buas.pcx", 1, 0); - show_title_screen( publisher, 1, 1 ); - show_title_screen( (((SWIDTH>=640&&SHEIGHT>=480) && PHYSFSX_exists("logoh.pcx",1))?"logoh.pcx":"logo.pcx"), 1, 1 ); - show_title_screen( buasLogo, 1, 0 ); - show_title_screen( (((SWIDTH>=640&&SHEIGHT>=480) && PHYSFSX_exists("descenth.pcx",1))?"descenth.pcx":"descent.pcx"), 1, 1 ); +#if RT_DX12 + if (PHYSFSX_exists("assets/splash-logo/LogoRaytraced.png", 1)) + { + show_title_screen("assets/splash-logo/LogoRaytraced.png", 1, 0); + // FOR SOME REASON BEYOND HUMAN UNDERSTANDING WHEN THE TITLE SCREEN IS LOADED + // THE CODE ALSO READS OUT THE PALETTE FROM THE PCX FILE OF THE TITLE SCREEN + // AND THEN USES THAT AS THE PALETTE TO DECODE ALL THE OTHER GAME TEXTURES. + // YES, LOADING THE TITLE SCREEN IS MISSION CRITICAL TO THE GAME, AND IF YOU + // DON'T DO IT OR DO IT IN THE WRONG ORDER THE GAME TEXTURES GET ALL SCREWED + // UP. ARE YOU MAD. + load_the_palette_of_the_title_screen_like_a_fucking_psycho((((SWIDTH>=640&&SHEIGHT>=480) && PHYSFSX_exists("descenth.pcx", 1)) ? "descenth.pcx" : "descent.pcx"), 1, 0); + } + else + { + show_title_screen((((SWIDTH>=640&&SHEIGHT>=480) && PHYSFSX_exists("descenth.pcx", 1)) ? "descenth.pcx" : "descent.pcx"), 1, 0); + } +#else + show_title_screen( (((SWIDTH>=640&&SHEIGHT>=480) && PHYSFSX_exists("descenth.pcx",1))?"descenth.pcx":"descent.pcx"), 1, 0 ); +#endif } void show_order_form() @@ -1095,6 +1131,36 @@ static int briefing_handler(window *wind, d_event *event, briefing *br) } case EVENT_WINDOW_DRAW: +#ifdef RT_DX12 + RT_Vec2 top_left_blit; + RT_Vec2 bottom_right_blit; + bool raytrace_enemy = br->robot_num != -1; + + if (raytrace_enemy) + { + RT_BeginFrame(); + RT_StartImGuiFrame(); + + top_left_blit = RT_Vec2Make((float)br->robot_canv->cv_bitmap.bm_x, (float)br->robot_canv->cv_bitmap.bm_y); + bottom_right_blit = RT_Vec2Make((float)br->robot_canv->cv_bitmap.bm_x + (float)br->robot_canv->cv_bitmap.bm_w, (float)br->robot_canv->cv_bitmap.bm_y + (float)br->robot_canv->cv_bitmap.bm_h); + + RT_SceneSettings scene_settings = { 0 }; + scene_settings.camera = RT_ArenaAllocStruct(&g_thread_arena, RT_Camera); + scene_settings.camera->position = RT_Vec3Fromvms_vector(&View_position); + scene_settings.camera->right = RT_Vec3Fromvms_vector(&View_matrix.rvec); + scene_settings.camera->up = RT_Vec3Fromvms_vector(&View_matrix.uvec); + scene_settings.camera->forward = RT_Vec3Fromvms_vector(&View_matrix.fvec); + scene_settings.camera->vfov = 60.0f; + scene_settings.camera->near_plane = 0.1f; + scene_settings.camera->far_plane = 10000.0f; + scene_settings.render_blit = true; + + RT_BeginScene(&scene_settings); + RT_Light light = RT_MakeSphericalLight(RT_Vec3Make(100.0f, 100.0f, 100.0f), RT_Vec3Make(70.0f, 70.0f, -5.0f), 20.0f); + RT_RaytraceSubmitLight(light); + } +#endif + gr_set_current_canvas(NULL); timer_delay2(50); @@ -1116,7 +1182,9 @@ static int briefing_handler(window *wind, d_event *event, briefing *br) if (br->bitmap_name[0] != 0) show_animated_bitmap(br); if (br->robot_num != -1) + { show_spinning_robot_frame(br, br->robot_num); + } gr_set_curfont( GAME_FONT ); @@ -1127,6 +1195,20 @@ static int briefing_handler(window *wind, d_event *event, briefing *br) flash_cursor(br, br->flashing_cursor); else if (br->flashing_cursor) gr_printf(br->text_x, br->text_y, "_"); + +#ifdef RT_DX12 + if (raytrace_enemy) + { + RT_UpdateMaterialEdges(); + RT_UpdateMaterialIndices(); + + RT_EndScene(); + RT_RasterBlitScene(&top_left_blit, &bottom_right_blit, true); + + RT_EndImguiFrame(); + RT_EndFrame(); + } +#endif break; case EVENT_WINDOW_CLOSE: diff --git a/physfs-main/out/install/x64-Debug/lib/cmake/PhysFS/PhysFSConfig-debug.cmake b/physfs-main/out/install/x64-Debug/lib/cmake/PhysFS/PhysFSConfig-debug.cmake index 42b15d9..317918c 100644 --- a/physfs-main/out/install/x64-Debug/lib/cmake/PhysFS/PhysFSConfig-debug.cmake +++ b/physfs-main/out/install/x64-Debug/lib/cmake/PhysFS/PhysFSConfig-debug.cmake @@ -1,38 +1,38 @@ -#---------------------------------------------------------------- -# Generated CMake target import file for configuration "Debug". -#---------------------------------------------------------------- - -# Commands may need to know the format version. -set(CMAKE_IMPORT_FILE_VERSION 1) - -# Import target "PhysFS::PhysFS-static" for configuration "Debug" -set_property(TARGET PhysFS::PhysFS-static APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) -set_target_properties(PhysFS::PhysFS-static PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C" - IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/physfs-static.lib" - ) - -list(APPEND _IMPORT_CHECK_TARGETS PhysFS::PhysFS-static ) -list(APPEND _IMPORT_CHECK_FILES_FOR_PhysFS::PhysFS-static "${_IMPORT_PREFIX}/lib/physfs-static.lib" ) - -# Import target "PhysFS::PhysFS" for configuration "Debug" -set_property(TARGET PhysFS::PhysFS APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) -set_target_properties(PhysFS::PhysFS PROPERTIES - IMPORTED_IMPLIB_DEBUG "${_IMPORT_PREFIX}/lib/physfs.lib" - IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/bin/physfs.dll" - ) - -list(APPEND _IMPORT_CHECK_TARGETS PhysFS::PhysFS ) -list(APPEND _IMPORT_CHECK_FILES_FOR_PhysFS::PhysFS "${_IMPORT_PREFIX}/lib/physfs.lib" "${_IMPORT_PREFIX}/bin/physfs.dll" ) - -# Import target "PhysFS::test_physfs" for configuration "Debug" -set_property(TARGET PhysFS::test_physfs APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) -set_target_properties(PhysFS::test_physfs PROPERTIES - IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/bin/test_physfs.exe" - ) - -list(APPEND _IMPORT_CHECK_TARGETS PhysFS::test_physfs ) -list(APPEND _IMPORT_CHECK_FILES_FOR_PhysFS::test_physfs "${_IMPORT_PREFIX}/bin/test_physfs.exe" ) - -# Commands beyond this point should not need to know the version. -set(CMAKE_IMPORT_FILE_VERSION) +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Debug". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "PhysFS::PhysFS-static" for configuration "Debug" +set_property(TARGET PhysFS::PhysFS-static APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) +set_target_properties(PhysFS::PhysFS-static PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C" + IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/physfs-static.lib" + ) + +list(APPEND _IMPORT_CHECK_TARGETS PhysFS::PhysFS-static ) +list(APPEND _IMPORT_CHECK_FILES_FOR_PhysFS::PhysFS-static "${_IMPORT_PREFIX}/lib/physfs-static.lib" ) + +# Import target "PhysFS::PhysFS" for configuration "Debug" +set_property(TARGET PhysFS::PhysFS APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) +set_target_properties(PhysFS::PhysFS PROPERTIES + IMPORTED_IMPLIB_DEBUG "${_IMPORT_PREFIX}/lib/physfs.lib" + IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/bin/physfs.dll" + ) + +list(APPEND _IMPORT_CHECK_TARGETS PhysFS::PhysFS ) +list(APPEND _IMPORT_CHECK_FILES_FOR_PhysFS::PhysFS "${_IMPORT_PREFIX}/lib/physfs.lib" "${_IMPORT_PREFIX}/bin/physfs.dll" ) + +# Import target "PhysFS::test_physfs" for configuration "Debug" +set_property(TARGET PhysFS::test_physfs APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) +set_target_properties(PhysFS::test_physfs PROPERTIES + IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/bin/test_physfs.exe" + ) + +list(APPEND _IMPORT_CHECK_TARGETS PhysFS::test_physfs ) +list(APPEND _IMPORT_CHECK_FILES_FOR_PhysFS::test_physfs "${_IMPORT_PREFIX}/bin/test_physfs.exe" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/physfs-main/out/install/x64-Debug/lib/cmake/PhysFS/PhysFSConfig.cmake b/physfs-main/out/install/x64-Debug/lib/cmake/PhysFS/PhysFSConfig.cmake index 3088b12..bfe57b9 100644 --- a/physfs-main/out/install/x64-Debug/lib/cmake/PhysFS/PhysFSConfig.cmake +++ b/physfs-main/out/install/x64-Debug/lib/cmake/PhysFS/PhysFSConfig.cmake @@ -1,108 +1,108 @@ -# Generated by CMake - -if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.6) - message(FATAL_ERROR "CMake >= 2.6.0 required") -endif() -cmake_policy(PUSH) -cmake_policy(VERSION 2.6...3.21) -#---------------------------------------------------------------- -# Generated CMake target import file. -#---------------------------------------------------------------- - -# Commands may need to know the format version. -set(CMAKE_IMPORT_FILE_VERSION 1) - -# Protect against multiple inclusion, which would fail when already imported targets are added once more. -set(_targetsDefined) -set(_targetsNotDefined) -set(_expectedTargets) -foreach(_expectedTarget PhysFS::PhysFS-static PhysFS::PhysFS PhysFS::test_physfs) - list(APPEND _expectedTargets ${_expectedTarget}) - if(NOT TARGET ${_expectedTarget}) - list(APPEND _targetsNotDefined ${_expectedTarget}) - endif() - if(TARGET ${_expectedTarget}) - list(APPEND _targetsDefined ${_expectedTarget}) - endif() -endforeach() -if("${_targetsDefined}" STREQUAL "${_expectedTargets}") - unset(_targetsDefined) - unset(_targetsNotDefined) - unset(_expectedTargets) - set(CMAKE_IMPORT_FILE_VERSION) - cmake_policy(POP) - return() -endif() -if(NOT "${_targetsDefined}" STREQUAL "") - message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") -endif() -unset(_targetsDefined) -unset(_targetsNotDefined) -unset(_expectedTargets) - - -# Compute the installation prefix relative to this file. -get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) -get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) -get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) -get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) -if(_IMPORT_PREFIX STREQUAL "/") - set(_IMPORT_PREFIX "") -endif() - -# Create imported target PhysFS::PhysFS-static -add_library(PhysFS::PhysFS-static STATIC IMPORTED) - -set_target_properties(PhysFS::PhysFS-static PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" -) - -# Create imported target PhysFS::PhysFS -add_library(PhysFS::PhysFS SHARED IMPORTED) - -set_target_properties(PhysFS::PhysFS PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" -) - -# Create imported target PhysFS::test_physfs -add_executable(PhysFS::test_physfs IMPORTED) - -set_target_properties(PhysFS::test_physfs PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" -) - -# Load information for each installed configuration. -get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) -file(GLOB CONFIG_FILES "${_DIR}/PhysFSConfig-*.cmake") -foreach(f ${CONFIG_FILES}) - include(${f}) -endforeach() - -# Cleanup temporary variables. -set(_IMPORT_PREFIX) - -# Loop over all imported files and verify that they actually exist -foreach(target ${_IMPORT_CHECK_TARGETS} ) - foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} ) - if(NOT EXISTS "${file}" ) - message(FATAL_ERROR "The imported target \"${target}\" references the file - \"${file}\" -but this file does not exist. Possible reasons include: -* The file was deleted, renamed, or moved to another location. -* An install or uninstall procedure did not complete successfully. -* The installation package was faulty and contained - \"${CMAKE_CURRENT_LIST_FILE}\" -but not all the files it references. -") - endif() - endforeach() - unset(_IMPORT_CHECK_FILES_FOR_${target}) -endforeach() -unset(_IMPORT_CHECK_TARGETS) - -# This file does not depend on other imported targets which have -# been exported from the same project but in a separate export set. - -# Commands beyond this point should not need to know the version. -set(CMAKE_IMPORT_FILE_VERSION) -cmake_policy(POP) +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.6) + message(FATAL_ERROR "CMake >= 2.6.0 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.6...3.21) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_targetsDefined) +set(_targetsNotDefined) +set(_expectedTargets) +foreach(_expectedTarget PhysFS::PhysFS-static PhysFS::PhysFS PhysFS::test_physfs) + list(APPEND _expectedTargets ${_expectedTarget}) + if(NOT TARGET ${_expectedTarget}) + list(APPEND _targetsNotDefined ${_expectedTarget}) + endif() + if(TARGET ${_expectedTarget}) + list(APPEND _targetsDefined ${_expectedTarget}) + endif() +endforeach() +if("${_targetsDefined}" STREQUAL "${_expectedTargets}") + unset(_targetsDefined) + unset(_targetsNotDefined) + unset(_expectedTargets) + set(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT "${_targetsDefined}" STREQUAL "") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") +endif() +unset(_targetsDefined) +unset(_targetsNotDefined) +unset(_expectedTargets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target PhysFS::PhysFS-static +add_library(PhysFS::PhysFS-static STATIC IMPORTED) + +set_target_properties(PhysFS::PhysFS-static PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" +) + +# Create imported target PhysFS::PhysFS +add_library(PhysFS::PhysFS SHARED IMPORTED) + +set_target_properties(PhysFS::PhysFS PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" +) + +# Create imported target PhysFS::test_physfs +add_executable(PhysFS::test_physfs IMPORTED) + +set_target_properties(PhysFS::test_physfs PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" +) + +# Load information for each installed configuration. +get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +file(GLOB CONFIG_FILES "${_DIR}/PhysFSConfig-*.cmake") +foreach(f ${CONFIG_FILES}) + include(${f}) +endforeach() + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(target ${_IMPORT_CHECK_TARGETS} ) + foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} ) + if(NOT EXISTS "${file}" ) + message(FATAL_ERROR "The imported target \"${target}\" references the file + \"${file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + unset(_IMPORT_CHECK_FILES_FOR_${target}) +endforeach() +unset(_IMPORT_CHECK_TARGETS) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/sdl-master/CMakeLists.txt b/sdl-master/CMakeLists.txt index 9dc2f4e..c517ce9 100644 --- a/sdl-master/CMakeLists.txt +++ b/sdl-master/CMakeLists.txt @@ -1,79 +1,79 @@ -cmake_minimum_required( VERSION 3.4 ) - -set( SDL ${CMAKE_CURRENT_SOURCE_DIR}/sdl ) - -file( - GLOB SDL_SOURCES - ${SDL}/src/*.c - ${SDL}/src/audio/*.c - ${SDL}/src/audio/disk/*.c - ${SDL}/src/audio/dummy/*.c - ${SDL}/src/cdrom/*.c - ${SDL}/src/cdrom/dummy/*.c - ${SDL}/src/cpuinfo/*.c - ${SDL}/src/events/*.c - ${SDL}/src/file/*.c - ${SDL}/src/joystick/*.c - ${SDL}/src/stdlib/*.c - ${SDL}/src/thread/*.c - ${SDL}/src/thread/generic/*.c - ${SDL}/src/timer/*.c - ${SDL}/src/video/*.c - ${SDL}/src/video/dummy/*.c -) - -file( - GLOB SDL_WIN32_SOURCES - ${SDL}/src/audio/windib/*.c - ${SDL}/src/audio/windx5/*.c - ${SDL}/src/cdrom/win32/*.c - ${SDL}/src/joystick/win32/*.c - ${SDL}/src/loadso/win32/*.c - ${SDL}/src/thread/win32/*.c - ${SDL}/src/timer/win32/*.c - ${SDL}/src/video/wincommon/*.c - ${SDL}/src/video/windib/*.c - ${SDL}/src/video/windx5/*.c -) - -file( - GLOB SDL_MACOS_SOURCES - ${SDL}/src/audio/macosx/*.c - ${SDL}/src/cdrom/macosx/*.c - ${SDL}/src/joystick/darwin/*.c - ${SDL}/src/loadso/dlopen/*.c - ${SDL}/src/loadso/macosx/*.c - # ${SDL}/src/thread/pthread/*.c - ${SDL}/src/timer/unix/*.c - ${SDL}/src/video/quartz/*.m -) - -set( LIBSDL_SOURCES ${SDL_SOURCES} ) - -if (WIN32) - set( LIBSDL_SOURCES ${LIBSDL_SOURCES} ${SDL_WIN32_SOURCES} ) - set( LIBSDLMAIN_SOURCES ${SDL}/src/main/win32/SDL_win32_main.c ) - file( STRINGS ${SDL}/include/SDL_config.h.default SDL_CONFIG_HEADER ) - message( AUTHOR_WARNING "+ Building for Windows.") -elseif( UNIX AND APPLE ) - set( LIBSDL_SOURCES ${LIBSDL_SOURCES} ${SDL_MACOS_SOURCES} ) - set( LIBSDLMAIN_SOURCES ${SDL}/src/main/macosx/SDLMain.m ) - - ## copy over a pre-created macOS config - set( CFLAGS "-Wall -Wextra -O2 -g -fomit-frame-pointer -fPIC" ) - set( CXXFLAGS "${CFLAGS} -fno-exceptions -fno-rtti" ) - - file( STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/SDL_config.h.macOS SDL_CONFIG_HEADER ) - message( AUTHOR_WARNING "+ Building for macOS.") -else() - message( FATAL_ERROR "Unknown operating system-- aborting." ) -endif() - - string(REPLACE ";" "\n" SDL_CONFIG_HEADER "${SDL_CONFIG_HEADER}") -file( WRITE ${SDL}/include/SDL_config.h "${SDL_CONFIG_HEADER}" ) - -add_library( sdl ${LIBSDL_SOURCES} ) -target_include_directories( sdl PUBLIC ${SDL}/include ) - -add_library( sdlmain ${LIBSDLMAIN_SOURCES} ) -target_include_directories( sdlmain PUBLIC ${SDL}/include ) +cmake_minimum_required( VERSION 3.4 ) + +set( SDL ${CMAKE_CURRENT_SOURCE_DIR}/sdl ) + +file( + GLOB SDL_SOURCES + ${SDL}/src/*.c + ${SDL}/src/audio/*.c + ${SDL}/src/audio/disk/*.c + ${SDL}/src/audio/dummy/*.c + ${SDL}/src/cdrom/*.c + ${SDL}/src/cdrom/dummy/*.c + ${SDL}/src/cpuinfo/*.c + ${SDL}/src/events/*.c + ${SDL}/src/file/*.c + ${SDL}/src/joystick/*.c + ${SDL}/src/stdlib/*.c + ${SDL}/src/thread/*.c + ${SDL}/src/thread/generic/*.c + ${SDL}/src/timer/*.c + ${SDL}/src/video/*.c + ${SDL}/src/video/dummy/*.c +) + +file( + GLOB SDL_WIN32_SOURCES + ${SDL}/src/audio/windib/*.c + ${SDL}/src/audio/windx5/*.c + ${SDL}/src/cdrom/win32/*.c + ${SDL}/src/joystick/win32/*.c + ${SDL}/src/loadso/win32/*.c + ${SDL}/src/thread/win32/*.c + ${SDL}/src/timer/win32/*.c + ${SDL}/src/video/wincommon/*.c + ${SDL}/src/video/windib/*.c + ${SDL}/src/video/windx5/*.c +) + +file( + GLOB SDL_MACOS_SOURCES + ${SDL}/src/audio/macosx/*.c + ${SDL}/src/cdrom/macosx/*.c + ${SDL}/src/joystick/darwin/*.c + ${SDL}/src/loadso/dlopen/*.c + ${SDL}/src/loadso/macosx/*.c + # ${SDL}/src/thread/pthread/*.c + ${SDL}/src/timer/unix/*.c + ${SDL}/src/video/quartz/*.m +) + +set( LIBSDL_SOURCES ${SDL_SOURCES} ) + +if (WIN32) + set( LIBSDL_SOURCES ${LIBSDL_SOURCES} ${SDL_WIN32_SOURCES} ) + set( LIBSDLMAIN_SOURCES ${SDL}/src/main/win32/SDL_win32_main.c ) + file( STRINGS ${SDL}/include/SDL_config.h.default SDL_CONFIG_HEADER ) + message( AUTHOR_WARNING "+ Building for Windows.") +elseif( UNIX AND APPLE ) + set( LIBSDL_SOURCES ${LIBSDL_SOURCES} ${SDL_MACOS_SOURCES} ) + set( LIBSDLMAIN_SOURCES ${SDL}/src/main/macosx/SDLMain.m ) + + ## copy over a pre-created macOS config + set( CFLAGS "-Wall -Wextra -O2 -g -fomit-frame-pointer -fPIC" ) + set( CXXFLAGS "${CFLAGS} -fno-exceptions -fno-rtti" ) + + file( STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/SDL_config.h.macOS SDL_CONFIG_HEADER ) + message( AUTHOR_WARNING "+ Building for macOS.") +else() + message( FATAL_ERROR "Unknown operating system-- aborting." ) +endif() + + string(REPLACE ";" "\n" SDL_CONFIG_HEADER "${SDL_CONFIG_HEADER}") +file( WRITE ${SDL}/include/SDL_config.h "${SDL_CONFIG_HEADER}" ) + +add_library( sdl ${LIBSDL_SOURCES} ) +target_include_directories( sdl PUBLIC ${SDL}/include ) + +add_library( sdlmain ${LIBSDLMAIN_SOURCES} ) +target_include_directories( sdlmain PUBLIC ${SDL}/include ) diff --git a/sdl-master/sdl/README.Watcom b/sdl-master/sdl/README.Watcom index 8ed391f..2849a11 100644 --- a/sdl-master/sdl/README.Watcom +++ b/sdl-master/sdl/README.Watcom @@ -1,133 +1,133 @@ - -Using SDL under Windows with the OpenWatcom compiler -==================================================== - -Prerequisites -------------- - -I have done the port under Windows XP Home with SP2 installed. Windows -2000 should also be working. I'm not so sure about ancient Windows NT, -since only DirectX 3 is available there. Building should be possible, -but running the compiled applications will probalbly fail with -SDL_VIDEODRIVER=directx. The windib driver should work, though. - -To compile and use the SDL with Open Watcom you will need the following: -- Open Watcom compiler. I used version 1.5. The environment variables - PATH, WATCOM and INCLUDE need to be set appropriately - please consult - the OpenWatcom documentation and instructions given during the - installation of the compiler. - My setup looks like this in owvars.bat: - set WATCOM=C:\watcom - set INCLUDE=%WATCOM%\h;%WATCOM%\h\nt - set PATH=%PATH%;%WATCOM%\binnt;%WATCOM%\binw -- A fairly recent DirectX SDK. The original unmodified DX8 SDK works, as - well as the minimal DirectX 7 SDK from the Allegro download site - (). -- The SDL sources from Subversion -- The file Watcom-Win32.zip (now available in Subversion) - - -Building the Library --------------------- - -1) In the SDL base directory extract the archive Watcom-Win32.zip. This - creates a subdirectory named 'watcom'. -2) The makefile expects the environment variable DXDIR to be set to the - base directory of a DirectX SDK. I have tried a stock DX8 SDK from - Microsoft as well as the minimal DirectX 7 SDK from the Allegro - download site. - You can also edit the makefile directly and hard code your path to - the SDK on your system. - I have this in my setup: - set DXDIR=D:\devel\DX8_SDK -3) Enter the watcom directory and run - wmake sdl -4) All tests from the test directory are working and can be built by - running - wmake tests - -Notes: - - The makefile offers some options to tweak the way the library is built. - You have at your disposal the option to build a static (default) - library, or a DLL (with tgt=dll). You can also choose whether to build - a Release (default) or a Debug version (with build=debug) of the tests - and library. Please consult the usage comment at the top of the - makefile for usage instructions. - - If you specify a test target (i.e. 'wmake tests' for all tests, or - selected targets like 'wmake testgl testvidinfo testoverlay2'), the - tests are always freshly compiled and linked. This is done to - minimise hassle when switching between library versions (static vs. - DLL), because they require subtly different options. - Also, the test executables are put directly into the test directory, - so they can find their data files. The clean target of the makefile - removes the test executables and the SDL.dll file from the test - directory. - - To use the library in your own projects with Open Watcom, you can use - the way the tests are built as base of your own build environment. - - The library can also be built with the stack calling convention of the - compiler (-6s instead of -6r). - - -Test applications ------------------ - -I've tried to make all tests work. The following table gives an overview -of the current status. - - Testname Status -~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -checkkeys + -graywin + -loopwave + -testalpha + -testbitmap + -testdyngl + -testerror + -testfile + -testgamma + -testgl + -testhread + -testiconv - (all failed) -testkeys + -testlock + -testoverlay + (needs 'set SDL_VIDEODRIVER=directx') -testoverlay2 + (needs 'set SDL_VIDEODRIVER=directx') -testpalette + -testplatform + -testsem + -testsprite + -testtimer + -testver + -testvidinfo + -testwin ? (fading doesn't seem right) -testwm + -torturethread + -testcdrom + -testjoystick not tested -threadwin + -testcursor + - - -TODO ----- - -There is room for further improvement: -- Test joystick functionality. -- Investigate fading issue in 'testwin' test. -- Fix the UTF-8 support. -- Adapt the makefile/object file list to support more target systems -- Use "#pragma aux" syntax for the CPU info functions. - - -Questions and Comments ----------------------- - -Please direct any questions or comments to me: - - Happy Coding! - - Marc Peter + +Using SDL under Windows with the OpenWatcom compiler +==================================================== + +Prerequisites +------------- + +I have done the port under Windows XP Home with SP2 installed. Windows +2000 should also be working. I'm not so sure about ancient Windows NT, +since only DirectX 3 is available there. Building should be possible, +but running the compiled applications will probalbly fail with +SDL_VIDEODRIVER=directx. The windib driver should work, though. + +To compile and use the SDL with Open Watcom you will need the following: +- Open Watcom compiler. I used version 1.5. The environment variables + PATH, WATCOM and INCLUDE need to be set appropriately - please consult + the OpenWatcom documentation and instructions given during the + installation of the compiler. + My setup looks like this in owvars.bat: + set WATCOM=C:\watcom + set INCLUDE=%WATCOM%\h;%WATCOM%\h\nt + set PATH=%PATH%;%WATCOM%\binnt;%WATCOM%\binw +- A fairly recent DirectX SDK. The original unmodified DX8 SDK works, as + well as the minimal DirectX 7 SDK from the Allegro download site + (). +- The SDL sources from Subversion +- The file Watcom-Win32.zip (now available in Subversion) + + +Building the Library +-------------------- + +1) In the SDL base directory extract the archive Watcom-Win32.zip. This + creates a subdirectory named 'watcom'. +2) The makefile expects the environment variable DXDIR to be set to the + base directory of a DirectX SDK. I have tried a stock DX8 SDK from + Microsoft as well as the minimal DirectX 7 SDK from the Allegro + download site. + You can also edit the makefile directly and hard code your path to + the SDK on your system. + I have this in my setup: + set DXDIR=D:\devel\DX8_SDK +3) Enter the watcom directory and run + wmake sdl +4) All tests from the test directory are working and can be built by + running + wmake tests + +Notes: + + The makefile offers some options to tweak the way the library is built. + You have at your disposal the option to build a static (default) + library, or a DLL (with tgt=dll). You can also choose whether to build + a Release (default) or a Debug version (with build=debug) of the tests + and library. Please consult the usage comment at the top of the + makefile for usage instructions. + + If you specify a test target (i.e. 'wmake tests' for all tests, or + selected targets like 'wmake testgl testvidinfo testoverlay2'), the + tests are always freshly compiled and linked. This is done to + minimise hassle when switching between library versions (static vs. + DLL), because they require subtly different options. + Also, the test executables are put directly into the test directory, + so they can find their data files. The clean target of the makefile + removes the test executables and the SDL.dll file from the test + directory. + + To use the library in your own projects with Open Watcom, you can use + the way the tests are built as base of your own build environment. + + The library can also be built with the stack calling convention of the + compiler (-6s instead of -6r). + + +Test applications +----------------- + +I've tried to make all tests work. The following table gives an overview +of the current status. + + Testname Status +~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +checkkeys + +graywin + +loopwave + +testalpha + +testbitmap + +testdyngl + +testerror + +testfile + +testgamma + +testgl + +testhread + +testiconv - (all failed) +testkeys + +testlock + +testoverlay + (needs 'set SDL_VIDEODRIVER=directx') +testoverlay2 + (needs 'set SDL_VIDEODRIVER=directx') +testpalette + +testplatform + +testsem + +testsprite + +testtimer + +testver + +testvidinfo + +testwin ? (fading doesn't seem right) +testwm + +torturethread + +testcdrom + +testjoystick not tested +threadwin + +testcursor + + + +TODO +---- + +There is room for further improvement: +- Test joystick functionality. +- Investigate fading issue in 'testwin' test. +- Fix the UTF-8 support. +- Adapt the makefile/object file list to support more target systems +- Use "#pragma aux" syntax for the CPU info functions. + + +Questions and Comments +---------------------- + +Please direct any questions or comments to me: + + Happy Coding! + + Marc Peter diff --git a/sdl-master/sdl/SDL_config.h b/sdl-master/sdl/SDL_config.h index 4fc8dda..c56a107 100644 --- a/sdl-master/sdl/SDL_config.h +++ b/sdl-master/sdl/SDL_config.h @@ -1,49 +1,49 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2012 Sam Lantinga - - This library is free software\ - you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation\ - either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY\ - without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library\ - if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Sam Lantinga - slouken@libsdl.org -*/ - -#ifndef _SDL_config_h -#define _SDL_config_h - -#include "SDL_platform.h" - -/* Add any platform that doesn't build using the configure system */ -#if defined(__DREAMCAST__) -#include "SDL_config_dreamcast.h" -#elif defined(__MACOS__) -#include "SDL_config_macos.h" -#elif defined(__MACOSX__) -#include "SDL_config_macosx.h" -#elif defined(__SYMBIAN32__) -#include "SDL_config_symbian.h" /* must be before win32! */ -#elif defined(__WIN32__) -#include "SDL_config_win32.h" -#elif defined(__OS2__) -#include "SDL_config_os2.h" -#else -#include "SDL_config_minimal.h" -#endif /* platform config */ - +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software\ + you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation\ + either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY\ + without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library\ + if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifndef _SDL_config_h +#define _SDL_config_h + +#include "SDL_platform.h" + +/* Add any platform that doesn't build using the configure system */ +#if defined(__DREAMCAST__) +#include "SDL_config_dreamcast.h" +#elif defined(__MACOS__) +#include "SDL_config_macos.h" +#elif defined(__MACOSX__) +#include "SDL_config_macosx.h" +#elif defined(__SYMBIAN32__) +#include "SDL_config_symbian.h" /* must be before win32! */ +#elif defined(__WIN32__) +#include "SDL_config_win32.h" +#elif defined(__OS2__) +#include "SDL_config_os2.h" +#else +#include "SDL_config_minimal.h" +#endif /* platform config */ + #endif /* _SDL_config_h */ \ No newline at end of file diff --git a/sdl-master/sdl/include/SDL_config.h b/sdl-master/sdl/include/SDL_config.h index 4fc8dda..c56a107 100644 --- a/sdl-master/sdl/include/SDL_config.h +++ b/sdl-master/sdl/include/SDL_config.h @@ -1,49 +1,49 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2012 Sam Lantinga - - This library is free software\ - you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation\ - either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY\ - without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library\ - if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Sam Lantinga - slouken@libsdl.org -*/ - -#ifndef _SDL_config_h -#define _SDL_config_h - -#include "SDL_platform.h" - -/* Add any platform that doesn't build using the configure system */ -#if defined(__DREAMCAST__) -#include "SDL_config_dreamcast.h" -#elif defined(__MACOS__) -#include "SDL_config_macos.h" -#elif defined(__MACOSX__) -#include "SDL_config_macosx.h" -#elif defined(__SYMBIAN32__) -#include "SDL_config_symbian.h" /* must be before win32! */ -#elif defined(__WIN32__) -#include "SDL_config_win32.h" -#elif defined(__OS2__) -#include "SDL_config_os2.h" -#else -#include "SDL_config_minimal.h" -#endif /* platform config */ - +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software\ + you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation\ + either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY\ + without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library\ + if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifndef _SDL_config_h +#define _SDL_config_h + +#include "SDL_platform.h" + +/* Add any platform that doesn't build using the configure system */ +#if defined(__DREAMCAST__) +#include "SDL_config_dreamcast.h" +#elif defined(__MACOS__) +#include "SDL_config_macos.h" +#elif defined(__MACOSX__) +#include "SDL_config_macosx.h" +#elif defined(__SYMBIAN32__) +#include "SDL_config_symbian.h" /* must be before win32! */ +#elif defined(__WIN32__) +#include "SDL_config_win32.h" +#elif defined(__OS2__) +#include "SDL_config_os2.h" +#else +#include "SDL_config_minimal.h" +#endif /* platform config */ + #endif /* _SDL_config_h */ \ No newline at end of file diff --git a/sdl-master/sdl/src/main/win32/version.rc b/sdl-master/sdl/src/main/win32/version.rc index 38fb642..16921ce 100644 --- a/sdl-master/sdl/src/main/win32/version.rc +++ b/sdl-master/sdl/src/main/win32/version.rc @@ -1,38 +1,38 @@ - -#include "winresrc.h" - -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,2,14,0 - PRODUCTVERSION 1,2,14,0 - FILEFLAGSMASK 0x3fL - FILEFLAGS 0x0L - FILEOS 0x40004L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", "\0" - VALUE "FileDescription", "SDL\0" - VALUE "FileVersion", "1, 2, 14, 0\0" - VALUE "InternalName", "SDL\0" - VALUE "LegalCopyright", "Copyright © 2009 Sam Lantinga\0" - VALUE "OriginalFilename", "SDL.dll\0" - VALUE "ProductName", "Simple DirectMedia Layer\0" - VALUE "ProductVersion", "1, 2, 14, 0\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END + +#include "winresrc.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,2,14,0 + PRODUCTVERSION 1,2,14,0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "SDL\0" + VALUE "FileVersion", "1, 2, 14, 0\0" + VALUE "InternalName", "SDL\0" + VALUE "LegalCopyright", "Copyright © 2009 Sam Lantinga\0" + VALUE "OriginalFilename", "SDL.dll\0" + VALUE "ProductName", "Simple DirectMedia Layer\0" + VALUE "ProductVersion", "1, 2, 14, 0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/sdl-master/sdl/src/video/wincommon/SDL_sysevents.c b/sdl-master/sdl/src/video/wincommon/SDL_sysevents.c index 76c67a1..090f6f1 100644 --- a/sdl-master/sdl/src/video/wincommon/SDL_sysevents.c +++ b/sdl-master/sdl/src/video/wincommon/SDL_sysevents.c @@ -310,8 +310,8 @@ LRESULT CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) if ( WINDIB_FULLSCREEN() ) { appstate |= SDL_APPMOUSEFOCUS; SDL_RestoreDesktopMode(); - /* A fullscreen app gets hidden but will not get a minimize event */ - appstate |= (SDL_APPACTIVE | SDL_APPMOUSEFOCUS); + /* A fullscreen app gets hidden but will not get a minimize event */ + appstate |= (SDL_APPACTIVE | SDL_APPMOUSEFOCUS); #if defined(_WIN32_WCE) LoadAygshell(); if( SHFullScreen )