diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2f3a94d49..6d39692e5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -115,7 +115,8 @@ if( WIN32 ) comdlg32 ws2_32 setupapi - oleaut32 ) + oleaut32 + dbghelp ) if( NOT ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) set( ZDOOM_LIBS ${ZDOOM_LIBS} DelayImp ) diff --git a/src/actor.h b/src/actor.h index 4f37dcf98..d3a6d94aa 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1259,7 +1259,6 @@ public: void LinkToWorld (FLinkContext *ctx, bool spawningmapthing=false, sector_t *sector = NULL); void UnlinkFromWorld(FLinkContext *ctx); void AdjustFloorClip (); - bool InStateSequence(FState * newstate, FState * basestate); bool IsMapActor(); int GetTics(FState * newstate); bool SetState (FState *newstate, bool nofunction=false); diff --git a/src/d_main.cpp b/src/d_main.cpp index a7a0ef46a..e6c0f6ca8 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1853,6 +1853,16 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char sc.MustGetString(); DoomStartupInfo.Song = sc.String; } + else if (!nextKey.CompareNoCase("LOADLIGHTS")) + { + sc.MustGetNumber(); + DoomStartupInfo.LoadLights = !!sc.Number; + } + else if (!nextKey.CompareNoCase("LOADBRIGHTMAPS")) + { + sc.MustGetNumber(); + DoomStartupInfo.LoadBrightmaps = !!sc.Number; + } else { // Silently ignore unknown properties @@ -2022,13 +2032,13 @@ static void AddAutoloadFiles(const char *autoname) // [SP] Dialog reaction - load lights.pk3 and brightmaps.pk3 based on user choices if (!(gameinfo.flags & GI_SHAREWARE)) { - if (autoloadlights) + if (DoomStartupInfo.LoadLights == 1 || (DoomStartupInfo.LoadLights != 0 && autoloadlights)) { const char *lightswad = BaseFileSearch ("lights.pk3", NULL); if (lightswad) D_AddFile (allwads, lightswad); } - if (autoloadbrightmaps) + if (DoomStartupInfo.LoadBrightmaps == 1 || (DoomStartupInfo.LoadBrightmaps != 0 && autoloadbrightmaps)) { const char *bmwad = BaseFileSearch ("brightmaps.pk3", NULL); if (bmwad) @@ -2712,8 +2722,9 @@ void D_DoomMain (void) LightDefaults.DeleteAndClear(); // this can leak heap memory if it isn't cleared. // delete DoomStartupInfo data - DoomStartupInfo.Name = (const char*)0; + DoomStartupInfo.Name = ""; DoomStartupInfo.BkColor = DoomStartupInfo.FgColor = DoomStartupInfo.Type = 0; + DoomStartupInfo.LoadLights = DoomStartupInfo.LoadBrightmaps = -1; GC::FullGC(); // clean up before taking down the object list. diff --git a/src/d_main.h b/src/d_main.h index f48521f8c..05d818f14 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -81,6 +81,8 @@ struct FStartupInfo uint32_t BkColor; // Background color for title banner FString Song; int Type; + int LoadLights = -1; + int LoadBrightmaps = -1; enum { DefaultStartup, diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index ea05706d5..254aafb65 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -425,7 +425,7 @@ AActor &AActor::operator= (const AActor &other) // //========================================================================== -bool AActor::InStateSequence(FState * newstate, FState * basestate) +static int InStateSequence(FState * newstate, FState * basestate) { if (basestate == NULL) return false; @@ -440,12 +440,19 @@ bool AActor::InStateSequence(FState * newstate, FState * basestate) return false; } -DEFINE_ACTION_FUNCTION(AActor, InStateSequence) +DEFINE_ACTION_FUNCTION_NATIVE(AActor, InStateSequence, InStateSequence) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_PROLOGUE; PARAM_POINTER(newstate, FState); PARAM_POINTER(basestate, FState); - ACTION_RETURN_BOOL(self->InStateSequence(newstate, basestate)); + ACTION_RETURN_BOOL(InStateSequence(newstate, basestate)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FState, InStateSequence, InStateSequence) +{ + PARAM_SELF_STRUCT_PROLOGUE(FState); + PARAM_POINTER(basestate, FState); + ACTION_RETURN_BOOL(InStateSequence(self, basestate)); } diff --git a/src/polyrenderer/drawers/poly_triangle.cpp b/src/polyrenderer/drawers/poly_triangle.cpp index 0e834dee5..1949b06e3 100644 --- a/src/polyrenderer/drawers/poly_triangle.cpp +++ b/src/polyrenderer/drawers/poly_triangle.cpp @@ -151,8 +151,8 @@ void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, ui dest_height = new_dest_height; dest_pitch = new_dest_pitch; dest_bgra = new_dest_bgra; - numa_start_y = numa_node * dest_height / num_numa_nodes; - numa_end_y = (numa_node + 1) * dest_height / num_numa_nodes; + numa_start_y = numa_node * screen->GetHeight() / num_numa_nodes; + numa_end_y = (numa_node + 1) * screen->GetHeight() / num_numa_nodes; ccw = true; weaponScene = false; } diff --git a/src/polyrenderer/scene/poly_sky.cpp b/src/polyrenderer/scene/poly_sky.cpp index 3e7cd072c..4e3e2fbfd 100644 --- a/src/polyrenderer/scene/poly_sky.cpp +++ b/src/polyrenderer/scene/poly_sky.cpp @@ -31,12 +31,7 @@ #include "polyrenderer/scene/poly_light.h" EXTERN_CVAR(Float, skyoffset) - -extern double skytexturemid; -extern float skyiscale; -extern double skyscale; -extern fixed_t sky1cyl, sky2cyl; - +EXTERN_CVAR(Int, r_skymode) PolySkyDome::PolySkyDome() { @@ -292,6 +287,53 @@ static FSoftwareTexture *GetSWTex(FTextureID texid, bool allownull = true) void PolySkySetup::Update() { + double skytexturemid = 0.0; + double skyscale = 0.0; + float skyiscale = 0.0f; + fixed_t sky1cyl = 0, sky2cyl = 0; + + auto skytex1 = TexMan.GetPalettedTexture(sky1texture, true); + auto skytex2 = TexMan.GetPalettedTexture(sky2texture, true); + + if (skytex1) + { + FSoftwareTexture *sskytex1 = skytex1->GetSoftwareTexture(); + FSoftwareTexture *sskytex2 = skytex2->GetSoftwareTexture(); + skytexturemid = 0; + int skyheight = skytex1->GetDisplayHeight(); + if (skyheight >= 128 && skyheight < 200) + { + skytexturemid = -28; + } + else if (skyheight > 200) + { + skytexturemid = (200 - skyheight) * sskytex1->GetScale().Y + ((r_skymode == 2 && !(level.flags & LEVEL_FORCETILEDSKY)) ? skytex1->GetSkyOffset() : 0); + } + + if (viewwidth != 0 && viewheight != 0) + { + skyiscale = float(r_Yaspect / freelookviewheight); + skyscale = freelookviewheight / r_Yaspect; + + skyiscale *= float(r_viewpoint.FieldOfView.Degrees / 90.); + skyscale *= float(90. / r_viewpoint.FieldOfView.Degrees); + } + + if (skystretch) + { + skyscale *= (double)SKYSTRETCH_HEIGHT / skyheight; + skyiscale *= skyheight / (float)SKYSTRETCH_HEIGHT; + skytexturemid *= skyheight / (double)SKYSTRETCH_HEIGHT; + } + + // The standard Doom sky texture is 256 pixels wide, repeated 4 times over 360 degrees, + // giving a total sky width of 1024 pixels. So if the sky texture is no wider than 1024, + // we map it to a cylinder with circumfrence 1024. For larger ones, we use the width of + // the texture as the cylinder's circumfrence. + sky1cyl = MAX(sskytex1->GetWidth(), fixed_t(sskytex1->GetScale().X * 1024)); + sky2cyl = MAX(sskytex2->GetWidth(), fixed_t(sskytex2->GetScale().Y * 1024)); + } + FTextureID sky1tex, sky2tex; double frontdpos = 0, backdpos = 0; diff --git a/src/r_data/gldefs.cpp b/src/r_data/gldefs.cpp index 8552ad77d..84ace2798 100644 --- a/src/r_data/gldefs.cpp +++ b/src/r_data/gldefs.cpp @@ -871,6 +871,7 @@ class GLDefsParser sc.ScriptError("Name longer than 8 characters: %s\n", sc.String); } frameName = sc.String; + frameName.ToUpper(); startDepth = ScriptDepth; diff --git a/src/scripting/vm/jit.cpp b/src/scripting/vm/jit.cpp index 319130aa4..1e94e3ada 100644 --- a/src/scripting/vm/jit.cpp +++ b/src/scripting/vm/jit.cpp @@ -26,9 +26,7 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc) code.setLogger(&logger); JitCompiler compiler(&code, sfunc); - CCFunc *func = compiler.Codegen(); - - return reinterpret_cast(AddJitFunction(&code, func)); + return reinterpret_cast(AddJitFunction(&code, &compiler)); } catch (const CRecoverableError &e) { @@ -100,6 +98,8 @@ asmjit::CCFunc *JitCompiler::Codegen() { Setup(); + int lastLine = -1; + pc = sfunc->Code; auto end = pc + sfunc->CodeSize; while (pc != end) @@ -107,10 +107,24 @@ asmjit::CCFunc *JitCompiler::Codegen() int i = (int)(ptrdiff_t)(pc - sfunc->Code); op = pc->op; + int curLine = sfunc->PCToLine(pc); + if (curLine != lastLine) + { + lastLine = curLine; + + auto label = cc.newLabel(); + cc.bind(label); + + JitLineInfo info; + info.Label = label; + info.LineNumber = curLine; + LineInfo.Push(info); + } + if (op != OP_PARAM && op != OP_PARAMI && op != OP_VTBL) { FString lineinfo; - lineinfo.Format("; line %d: %02x%02x%02x%02x %s", sfunc->PCToLine(pc), pc->op, pc->a, pc->b, pc->c, OpNames[op]); + lineinfo.Format("; line %d: %02x%02x%02x%02x %s", curLine, pc->op, pc->a, pc->b, pc->c, OpNames[op]); cc.comment("", 0); cc.comment(lineinfo.GetChars(), lineinfo.Len()); } @@ -127,6 +141,21 @@ asmjit::CCFunc *JitCompiler::Codegen() cc.endFunc(); cc.finalize(); + auto code = cc.getCode (); + for (unsigned int j = 0; j < LineInfo.Size (); j++) + { + auto info = LineInfo[j]; + + if (!code->isLabelValid (info.Label)) + { + continue; + } + + info.InstructionIndex = code->getLabelOffset (info.Label); + + LineInfo[j] = info; + } + return func; } diff --git a/src/scripting/vm/jit.h b/src/scripting/vm/jit.h index 618f37d4b..faaf65112 100644 --- a/src/scripting/vm/jit.h +++ b/src/scripting/vm/jit.h @@ -5,3 +5,4 @@ JitFuncPtr JitCompile(VMScriptFunction *func); void JitDumpLog(FILE *file, VMScriptFunction *func); +FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames); diff --git a/src/scripting/vm/jit_runtime.cpp b/src/scripting/vm/jit_runtime.cpp index 68b7988a0..5ef0760d6 100644 --- a/src/scripting/vm/jit_runtime.cpp +++ b/src/scripting/vm/jit_runtime.cpp @@ -2,6 +2,25 @@ #include "jit.h" #include "jitintern.h" +#ifdef WIN32 +#include +#else +#include +#include +#include +#include +#endif + +struct JitFuncInfo +{ + FString name; + FString filename; + TArray LineInfo; + void *start; + void *end; +}; + +static TArray JitDebugInfo; static TArray JitBlocks; static TArray JitFrames; static size_t JitBlockPos = 0; @@ -230,10 +249,12 @@ static TArray CreateUnwindInfoWindows(asmjit::CCFunc *func) return info; } -void *AddJitFunction(asmjit::CodeHolder* code, asmjit::CCFunc *func) +void *AddJitFunction(asmjit::CodeHolder* code, JitCompiler *compiler) { using namespace asmjit; + CCFunc *func = compiler->Codegen(); + size_t codeSize = code->getCodeSize(); if (codeSize == 0) return nullptr; @@ -271,11 +292,17 @@ void *AddJitFunction(asmjit::CodeHolder* code, asmjit::CCFunc *func) RUNTIME_FUNCTION *table = (RUNTIME_FUNCTION*)(unwindptr + unwindInfoSize); table[0].BeginAddress = (DWORD)(ptrdiff_t)(startaddr - baseaddr); table[0].EndAddress = (DWORD)(ptrdiff_t)(endaddr - baseaddr); +#ifndef __MINGW64__ table[0].UnwindInfoAddress = (DWORD)(ptrdiff_t)(unwindptr - baseaddr); +#else + table[0].UnwindData = (DWORD)(ptrdiff_t)(unwindptr - baseaddr); +#endif BOOLEAN result = RtlAddFunctionTable(table, 1, (DWORD64)baseaddr); JitFrames.Push((uint8_t*)table); if (result == 0) I_Error("RtlAddFunctionTable failed"); + + JitDebugInfo.Push({ compiler->GetScriptFunction()->PrintableName, compiler->GetScriptFunction()->SourceFileName, compiler->LineInfo, startaddr, endaddr }); #endif return p; @@ -287,52 +314,6 @@ extern "C" { void __register_frame(const void*); void __deregister_frame(const void*); - -#if 0 // Someone needs to implement this if GDB/LLDB should produce correct call stacks - - // GDB JIT interface (GG guys! Thank you SO MUCH for not hooking into the above functions. Really appreciate it!) - - // To register code with GDB, the JIT should follow this protocol: - // - // * Generate an object file in memory with symbols and other desired debug information. - // The file must include the virtual addresses of the sections. - // * Create a code entry for the file, which gives the start and size of the symbol file. - // * Add it to the linked list in the JIT descriptor. - // * Point the relevant_entry field of the descriptor at the entry. - // * Set action_flag to JIT_REGISTER and call __jit_debug_register_code. - - // Pure beauty! Now a JIT also has to create a full ELF object file. And is it a MACH-O on macOS? You guys ROCK! - - typedef enum - { - JIT_NOACTION = 0, - JIT_REGISTER_FN, - JIT_UNREGISTER_FN - } jit_actions_t; - - struct jit_code_entry - { - struct jit_code_entry *next_entry; - struct jit_code_entry *prev_entry; - const char *symfile_addr; - uint64_t symfile_size; - }; - - struct jit_descriptor - { - uint32_t version; - // This type should be jit_actions_t, but we use uint32_t to be explicit about the bitwidth. - uint32_t action_flag; - struct jit_code_entry *relevant_entry; - struct jit_code_entry *first_entry; - }; - - // GDB puts a breakpoint in this function. - void __attribute__((noinline)) __jit_debug_register_code() { }; - - // Make sure to specify the version statically, because the debugger may check the version before we can set it. - struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; -#endif } static void WriteLength(TArray &stream, unsigned int pos, unsigned int v) @@ -664,10 +645,12 @@ static TArray CreateUnwindInfoUnix(asmjit::CCFunc *func, unsigned int & return stream; } -void *AddJitFunction(asmjit::CodeHolder* code, asmjit::CCFunc *func) +void *AddJitFunction(asmjit::CodeHolder* code, JitCompiler *compiler) { using namespace asmjit; + CCFunc *func = compiler->Codegen(); + size_t codeSize = code->getCodeSize(); if (codeSize == 0) return nullptr; @@ -743,6 +726,8 @@ void *AddJitFunction(asmjit::CodeHolder* code, asmjit::CCFunc *func) #endif } + JitDebugInfo.Push({ compiler->GetScriptFunction()->PrintableName, compiler->GetScriptFunction()->SourceFileName, compiler->LineInfo, startaddr, endaddr }); + return p; } #endif @@ -764,8 +749,219 @@ void JitRelease() { asmjit::OSUtils::releaseVirtualMemory(p, 1024 * 1024); } + JitDebugInfo.Clear(); JitFrames.Clear(); JitBlocks.Clear(); JitBlockPos = 0; JitBlockSize = 0; } + +static int CaptureStackTrace(int max_frames, void **out_frames) +{ + memset(out_frames, 0, sizeof(void *) * max_frames); + +#ifdef _WIN64 + // RtlCaptureStackBackTrace doesn't support RtlAddFunctionTable.. + + CONTEXT context; + RtlCaptureContext(&context); + + UNWIND_HISTORY_TABLE history; + memset(&history, 0, sizeof(UNWIND_HISTORY_TABLE)); + + ULONG64 establisherframe = 0; + PVOID handlerdata = nullptr; + + int frame; + for (frame = 0; frame < max_frames; frame++) + { + ULONG64 imagebase; + PRUNTIME_FUNCTION rtfunc = RtlLookupFunctionEntry(context.Rip, &imagebase, &history); + + KNONVOLATILE_CONTEXT_POINTERS nvcontext; + memset(&nvcontext, 0, sizeof(KNONVOLATILE_CONTEXT_POINTERS)); + if (!rtfunc) + { + // Leaf function + context.Rip = (ULONG64)(*(PULONG64)context.Rsp); + context.Rsp += 8; + } + else + { + RtlVirtualUnwind(UNW_FLAG_NHANDLER, imagebase, context.Rip, rtfunc, &context, &handlerdata, &establisherframe, &nvcontext); + } + + if (!context.Rip) + break; + + out_frames[frame] = (void*)context.Rip; + } + return frame; + +#elif defined(WIN32) + // JIT isn't supported here, so just do nothing. + return 0;//return RtlCaptureStackBackTrace(0, MIN(max_frames, 32), out_frames, nullptr); +#else + return backtrace(out_frames, max_frames); +#endif +} + +#ifdef WIN32 +class NativeSymbolResolver +{ +public: + NativeSymbolResolver() { SymInitialize(GetCurrentProcess(), nullptr, TRUE); } + ~NativeSymbolResolver() { SymCleanup(GetCurrentProcess()); } + + FString GetName(void *frame) + { + FString s; + + unsigned char buffer[sizeof(IMAGEHLP_SYMBOL64) + 128]; + IMAGEHLP_SYMBOL64 *symbol64 = reinterpret_cast(buffer); + memset(symbol64, 0, sizeof(IMAGEHLP_SYMBOL64) + 128); + symbol64->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + symbol64->MaxNameLength = 128; + + DWORD64 displacement = 0; + BOOL result = SymGetSymFromAddr64(GetCurrentProcess(), (DWORD64)frame, &displacement, symbol64); + if (result) + { + IMAGEHLP_LINE64 line64; + DWORD displacement = 0; + memset(&line64, 0, sizeof(IMAGEHLP_LINE64)); + line64.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + result = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)frame, &displacement, &line64); + if (result) + { + s.Format("Called from %s at %s, line %d\n", symbol64->Name, line64.FileName, (int)line64.LineNumber); + } + else + { + s.Format("Called from %s\n", symbol64->Name); + } + } + + return s; + } +}; +#else +class NativeSymbolResolver +{ +public: + FString GetName(void *frame) + { + FString s; + char **strings; + void *frames[1] = { frame }; + strings = backtrace_symbols(frames, 1); + + // Decode the strings + char *ptr = strings[0]; + char *filename = ptr; + const char *function = ""; + + // Find function name + while (*ptr) + { + if (*ptr == '(') // Found function name + { + *(ptr++) = 0; + function = ptr; + break; + } + ptr++; + } + + // Find offset + if (function[0]) // Only if function was found + { + while (*ptr) + { + if (*ptr == '+') // Found function offset + { + *(ptr++) = 0; + break; + } + if (*ptr == ')') // Not found function offset, but found, end of function + { + *(ptr++) = 0; + break; + } + ptr++; + } + } + + int status; + char *new_function = abi::__cxa_demangle(function, nullptr, nullptr, &status); + if (new_function) // Was correctly decoded + { + function = new_function; + } + + s.Format("Called from %s at %s\n", function, filename); + + if (new_function) + { + free(new_function); + } + + free(strings); + return s; + } +}; +#endif + +int JITPCToLine(uint8_t *pc, const JitFuncInfo *info) +{ + int PCIndex = int(pc - ((uint8_t *) (info->start))); + if (info->LineInfo.Size () == 1) return info->LineInfo[0].LineNumber; + for (unsigned i = 1; i < info->LineInfo.Size (); i++) + { + if (info->LineInfo[i].InstructionIndex >= PCIndex) + { + return info->LineInfo[i - 1].LineNumber; + } + } + return -1; +} + +FString JitGetStackFrameName(NativeSymbolResolver *nativeSymbols, void *pc) +{ + for (unsigned int i = 0; i < JitDebugInfo.Size(); i++) + { + const auto &info = JitDebugInfo[i]; + if (pc >= info.start && pc < info.end) + { + int line = JITPCToLine ((uint8_t *)pc, &info); + + FString s; + + if (line == -1) + s.Format("Called from %s at %s\n", info.name.GetChars(), info.filename.GetChars()); + else + s.Format("Called from %s at %s, line %d\n", info.name.GetChars(), info.filename.GetChars(), line); + + return s; + } + } + + return nativeSymbols ? nativeSymbols->GetName(pc) : FString(); +} + +FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames) +{ + void *frames[32]; + int numframes = CaptureStackTrace(32, frames); + + std::unique_ptr nativeSymbols; + if (includeNativeFrames) + nativeSymbols.reset(new NativeSymbolResolver()); + + FString s; + for (int i = framesToSkip + 1; i < numframes; i++) + { + s += JitGetStackFrameName(nativeSymbols.get(), frames[i]); + } + return s; +} diff --git a/src/scripting/vm/jitintern.h b/src/scripting/vm/jitintern.h index 2f67e6ed3..deb0378f0 100644 --- a/src/scripting/vm/jitintern.h +++ b/src/scripting/vm/jitintern.h @@ -25,12 +25,22 @@ extern int VMCalls[10]; #define ABCs (pc[0].i24) #define JMPOFS(x) ((x)->i24) +struct JitLineInfo +{ + ptrdiff_t InstructionIndex = 0; + int32_t LineNumber = -1; + asmjit::Label Label; +}; + class JitCompiler { public: JitCompiler(asmjit::CodeHolder *code, VMScriptFunction *sfunc) : cc(code), sfunc(sfunc) { } asmjit::CCFunc *Codegen(); + VMScriptFunction *GetScriptFunction() { return sfunc; } + + TArray LineInfo; private: // Declare EmitXX functions for the opcodes: @@ -308,5 +318,5 @@ public: } }; -void *AddJitFunction(asmjit::CodeHolder* code, asmjit::CCFunc *func); +void *AddJitFunction(asmjit::CodeHolder* code, JitCompiler *compiler); asmjit::CodeInfo GetHostCodeInfo(); diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 66af710f2..3a08eb450 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -658,7 +658,11 @@ CVMAbortException::CVMAbortException(EVMAbortException reason, const char *morei size_t len = strlen(m_Message); myvsnprintf(m_Message + len, MAX_ERRORTEXT - len, moreinfo, ap); } - stacktrace = ""; + + if (vm_jit) + stacktrace = JitCaptureStackTrace(1, false); + else + stacktrace = ""; } // Print this only once on the first catch block. diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index a067a296e..74a2c5d3b 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -1427,6 +1427,35 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, LookForPlayers, P_LookForPlayers) ACTION_RETURN_BOOL(P_LookForPlayers(self, allaround, params)); } +static int CheckMonsterUseSpecials(AActor *self) +{ + spechit_t spec; + int good = 0; + + if (!(self->flags6 & MF6_NOTRIGGER)) + { + while (spechit.Pop (spec)) + { + // [RH] let monsters push lines, as well as use them + if (((self->flags4 & MF4_CANUSEWALLS) && P_ActivateLine (spec.line, self, 0, SPAC_Use)) || + ((self->flags2 & MF2_PUSHWALL) && P_ActivateLine (spec.line, self, 0, SPAC_Push))) + { + good |= spec.line == self->BlockingLine ? 1 : 2; + } + } + } + else spechit.Clear(); + + return good; +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckMonsterUseSpecials, CheckMonsterUseSpecials) +{ + PARAM_SELF_PROLOGUE(AActor); + + ACTION_RETURN_INT(CheckMonsterUseSpecials(self)); +} + DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_Wander, A_Wander) { PARAM_SELF_PROLOGUE(AActor); @@ -1587,6 +1616,37 @@ DEFINE_ACTION_FUNCTION_NATIVE(AKey, GetKeyType, P_GetKeyType) ACTION_RETURN_POINTER(P_GetKeyType(num)); } +//===================================================================================== +// +// 3D Floor exports +// +//===================================================================================== +int CheckFor3DFloorHit(AActor *self, double z, bool trigger) +{ + return P_CheckFor3DFloorHit(self, z, trigger); +} +DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckFor3DFloorHit, CheckFor3DFloorHit) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(z); + PARAM_BOOL(trigger); + + ACTION_RETURN_BOOL(P_CheckFor3DFloorHit(self, z, trigger)); +} + +int CheckFor3DCeilingHit(AActor *self, double z, bool trigger) +{ + return P_CheckFor3DCeilingHit(self, z, trigger); +} +DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckFor3DCeilingHit, CheckFor3DCeilingHit) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(z); + PARAM_BOOL(trigger); + + ACTION_RETURN_BOOL(P_CheckFor3DCeilingHit(self, z, trigger)); +} + DEFINE_FIELD(AActor, snext) diff --git a/src/sound/i_music.cpp b/src/sound/i_music.cpp index ead98b35e..f69116a15 100644 --- a/src/sound/i_music.cpp +++ b/src/sound/i_music.cpp @@ -73,6 +73,7 @@ enum EMIDIType extern int MUSHeaderSearch(const uint8_t *head, int len); void I_InitSoundFonts(); +extern "C" void dumb_exit(); EXTERN_CVAR (Int, snd_samplerate) EXTERN_CVAR (Int, snd_mididevice) @@ -127,8 +128,6 @@ CUSTOM_CVAR (Float, snd_musicvolume, 0.5f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) void I_InitMusic (void) { - static bool setatterm = false; - I_InitSoundFonts(); snd_musicvolume.Callback (); @@ -139,12 +138,6 @@ void I_InitMusic (void) I_InitMusicWin32 (); #endif // _WIN32 - if (!setatterm) - { - setatterm = true; - atterm (I_ShutdownMusicExit); - - } MusicDown = false; } @@ -170,15 +163,10 @@ void I_ShutdownMusic(bool onexit) { WildMidi_Shutdown(); TimidityPP_Shutdown(); + dumb_exit(); } } -void I_ShutdownMusicExit() -{ - I_ShutdownMusic(true); -} - - //========================================================================== // // diff --git a/src/sound/i_music.h b/src/sound/i_music.h index be910bf9b..421bf1355 100644 --- a/src/sound/i_music.h +++ b/src/sound/i_music.h @@ -45,7 +45,6 @@ struct FOptionValues; // void I_InitMusic (); void I_ShutdownMusic (bool onexit = false); -void I_ShutdownMusicExit (); void I_BuildMIDIMenuList (FOptionValues *); void I_UpdateMusic (); diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index 1772d0c0d..a3587e3a5 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -287,6 +287,7 @@ void I_CloseSound () void I_ShutdownSound() { + I_ShutdownMusic(true); if (GSnd != NULL) { S_StopAllChannels(); diff --git a/src/sound/musicformats/music_dumb.cpp b/src/sound/musicformats/music_dumb.cpp index 99974a106..94c7199c6 100644 --- a/src/sound/musicformats/music_dumb.cpp +++ b/src/sound/musicformats/music_dumb.cpp @@ -774,8 +774,6 @@ MusInfo *MOD_OpenSong(FileReader &reader) bool is_it = false; bool is_dos = true; - atterm(dumb_exit); - int size = (int)reader.GetLength(); auto fpos = reader.Tell(); diff --git a/src/sound/timiditypp/resample.cpp b/src/sound/timiditypp/resample.cpp index 3c6f96867..06b531fc9 100644 --- a/src/sound/timiditypp/resample.cpp +++ b/src/sound/timiditypp/resample.cpp @@ -247,7 +247,6 @@ void initialize_resampler_coeffs(void) static bool done = false; if (done) return; done = true; - // atterm(free_gauss_table); initialize_newton_coeffs(); initialize_gauss_table(gauss_n); diff --git a/src/swrenderer/drawers/r_draw_pal.cpp b/src/swrenderer/drawers/r_draw_pal.cpp index 9af01cffb..daf5713fd 100644 --- a/src/swrenderer/drawers/r_draw_pal.cpp +++ b/src/swrenderer/drawers/r_draw_pal.cpp @@ -558,21 +558,6 @@ namespace swrenderer int32_t frac = args.TextureVPos(); int32_t fracstep = args.TextureVStep(); - if (!args.FadeSky()) - { - int count = thread->count_for_thread(args.DestY(), args.Count()); - - for (int index = 0; index < count; index++) - { - uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; - *dest = source0[sample_index]; - dest += pitch; - frac += fracstep; - } - - return; - } - int num_cores = thread->num_cores; int skipped = thread->skipped_by_thread(args.DestY()); int count = skipped + thread->count_for_thread(args.DestY(), args.Count()) * num_cores; @@ -594,6 +579,21 @@ namespace swrenderer fracstep *= num_cores; pitch *= num_cores; + if (!args.FadeSky()) + { + count = thread->count_for_thread(args.DestY(), args.Count()); + + for (int index = 0; index < count; index++) + { + uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; + *dest = source0[sample_index]; + dest += pitch; + frac += fracstep; + } + + return; + } + uint32_t solid_top = args.SolidTopColor(); uint32_t solid_bottom = args.SolidBottomColor(); @@ -686,7 +686,6 @@ namespace swrenderer void DrawDoubleSky1PalCommand::Execute(DrawerThread *thread) { uint8_t *dest = args.Dest(); - int count = args.Count(); int pitch = args.Viewport()->RenderTarget->GetPitch(); const uint8_t *source0 = args.FrontTexturePixels(); const uint8_t *source1 = args.BackTexturePixels(); @@ -696,6 +695,10 @@ namespace swrenderer int32_t frac = args.TextureVPos(); int32_t fracstep = args.TextureVStep(); + int num_cores = thread->num_cores; + int skipped = thread->skipped_by_thread(args.DestY()); + int count = skipped + thread->count_for_thread(args.DestY(), args.Count()) * num_cores; + // Find bands for top solid color, top fade, center textured, bottom fade, bottom solid color: int start_fade = 2; // How fast it should fade out int fade_length = (1 << (24 - start_fade)); @@ -708,8 +711,6 @@ namespace swrenderer start_fadebottom_y = clamp(start_fadebottom_y, 0, count); end_fadebottom_y = clamp(end_fadebottom_y, 0, count); - int num_cores = thread->num_cores; - int skipped = thread->skipped_by_thread(args.DestY()); dest = thread->dest_for_thread(args.DestY(), pitch, dest); frac += fracstep * skipped; fracstep *= num_cores; diff --git a/src/swrenderer/drawers/r_draw_sky32.h b/src/swrenderer/drawers/r_draw_sky32.h index 864002446..bc65e41e2 100644 --- a/src/swrenderer/drawers/r_draw_sky32.h +++ b/src/swrenderer/drawers/r_draw_sky32.h @@ -50,21 +50,6 @@ namespace swrenderer uint32_t solid_bottom = args.SolidBottomColor(); bool fadeSky = args.FadeSky(); - if (!fadeSky) - { - int count = thread->count_for_thread(args.DestY(), args.Count()); - - for (int index = 0; index < count; index++) - { - uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; - *dest = source0[sample_index]; - dest += pitch; - frac += fracstep; - } - - return; - } - int num_cores = thread->num_cores; int skipped = thread->skipped_by_thread(args.DestY()); int count = skipped + thread->count_for_thread(args.DestY(), args.Count()) * num_cores; @@ -86,6 +71,21 @@ namespace swrenderer fracstep *= num_cores; pitch *= num_cores; + if (!fadeSky) + { + int count = thread->count_for_thread(args.DestY(), args.Count()); + + for (int index = 0; index < count; index++) + { + uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; + *dest = source0[sample_index]; + dest += pitch; + frac += fracstep; + } + + return; + } + BgraColor solid_top_fill = solid_top; BgraColor solid_bottom_fill = solid_bottom; @@ -172,7 +172,6 @@ namespace swrenderer void Execute(DrawerThread *thread) override { uint32_t *dest = (uint32_t *)args.Dest(); - int count = args.Count(); int pitch = args.Viewport()->RenderTarget->GetPitch(); const uint32_t *source0 = (const uint32_t *)args.FrontTexturePixels(); const uint32_t *source1 = (const uint32_t *)args.BackTexturePixels(); @@ -181,7 +180,11 @@ namespace swrenderer int32_t frac = args.TextureVPos(); int32_t fracstep = args.TextureVStep(); - + + int num_cores = thread->num_cores; + int skipped = thread->skipped_by_thread(args.DestY()); + int count = skipped + thread->count_for_thread(args.DestY(), args.Count()) * num_cores; + uint32_t solid_top = args.SolidTopColor(); uint32_t solid_bottom = args.SolidBottomColor(); bool fadeSky = args.FadeSky(); @@ -198,8 +201,6 @@ namespace swrenderer start_fadebottom_y = clamp(start_fadebottom_y, 0, count); end_fadebottom_y = clamp(end_fadebottom_y, 0, count); - int num_cores = thread->num_cores; - int skipped = thread->skipped_by_thread(args.DestY()); dest = thread->dest_for_thread(args.DestY(), pitch, dest); frac += fracstep * skipped; fracstep *= num_cores; diff --git a/src/swrenderer/drawers/r_draw_sky32_sse2.h b/src/swrenderer/drawers/r_draw_sky32_sse2.h index 56fd50300..64afca87a 100644 --- a/src/swrenderer/drawers/r_draw_sky32_sse2.h +++ b/src/swrenderer/drawers/r_draw_sky32_sse2.h @@ -49,21 +49,6 @@ namespace swrenderer uint32_t solid_bottom = args.SolidBottomColor(); bool fadeSky = args.FadeSky(); - if (!fadeSky) - { - int count = thread->count_for_thread(args.DestY(), args.Count()); - - for (int index = 0; index < count; index++) - { - uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; - *dest = source0[sample_index]; - dest += pitch; - frac += fracstep; - } - - return; - } - int num_cores = thread->num_cores; int skipped = thread->skipped_by_thread(args.DestY()); int count = skipped + thread->count_for_thread(args.DestY(), args.Count()) * num_cores; @@ -85,6 +70,21 @@ namespace swrenderer fracstep *= num_cores; pitch *= num_cores; + if (!fadeSky) + { + int count = thread->count_for_thread(args.DestY(), args.Count()); + + for (int index = 0; index < count; index++) + { + uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; + *dest = source0[sample_index]; + dest += pitch; + frac += fracstep; + } + + return; + } + __m128i solid_top_fill = _mm_unpacklo_epi8(_mm_cvtsi32_si128(solid_top), _mm_setzero_si128()); __m128i solid_bottom_fill = _mm_unpacklo_epi8(_mm_cvtsi32_si128(solid_bottom), _mm_setzero_si128()); @@ -167,7 +167,6 @@ namespace swrenderer void Execute(DrawerThread *thread) override { uint32_t *dest = (uint32_t *)args.Dest(); - int count = args.Count(); int pitch = args.Viewport()->RenderTarget->GetPitch(); const uint32_t *source0 = (const uint32_t *)args.FrontTexturePixels(); const uint32_t *source1 = (const uint32_t *)args.BackTexturePixels(); @@ -176,7 +175,11 @@ namespace swrenderer int32_t frac = args.TextureVPos(); int32_t fracstep = args.TextureVStep(); - + + int num_cores = thread->num_cores; + int skipped = thread->skipped_by_thread(args.DestY()); + int count = skipped + thread->count_for_thread(args.DestY(), args.Count()) * num_cores; + uint32_t solid_top = args.SolidTopColor(); uint32_t solid_bottom = args.SolidBottomColor(); bool fadeSky = args.FadeSky(); @@ -193,8 +196,6 @@ namespace swrenderer start_fadebottom_y = clamp(start_fadebottom_y, 0, count); end_fadebottom_y = clamp(end_fadebottom_y, 0, count); - int num_cores = thread->num_cores; - int skipped = thread->skipped_by_thread(args.DestY()); dest = thread->dest_for_thread(args.DestY(), pitch, dest); frac += fracstep * skipped; fracstep *= num_cores; diff --git a/src/swrenderer/drawers/r_thread.cpp b/src/swrenderer/drawers/r_thread.cpp index 5aa157f27..5055e259b 100644 --- a/src/swrenderer/drawers/r_thread.cpp +++ b/src/swrenderer/drawers/r_thread.cpp @@ -140,8 +140,8 @@ void DrawerThreads::WorkerMain(DrawerThread *thread) // Grab the commands DrawerCommandQueuePtr list = active_commands[thread->current_queue]; thread->current_queue++; - thread->numa_start_y = thread->numa_node * viewheight / thread->num_numa_nodes; - thread->numa_end_y = (thread->numa_node + 1) * viewheight / thread->num_numa_nodes; + thread->numa_start_y = thread->numa_node * screen->GetHeight() / thread->num_numa_nodes; + thread->numa_end_y = (thread->numa_node + 1) * screen->GetHeight() / thread->num_numa_nodes; start_lock.unlock(); // Do the work: diff --git a/src/swrenderer/drawers/r_thread.h b/src/swrenderer/drawers/r_thread.h index f2d1d4d0e..f12193a49 100644 --- a/src/swrenderer/drawers/r_thread.h +++ b/src/swrenderer/drawers/r_thread.h @@ -55,7 +55,7 @@ public: // Active range for the numa block the cores are part of int numa_start_y = 0; - int numa_end_y = 0; + int numa_end_y = MAXHEIGHT; // Working buffer used by the tilted (sloped) span drawer const uint8_t *tiltlighting[MAXWIDTH]; diff --git a/src/swrenderer/line/r_fogboundary.cpp b/src/swrenderer/line/r_fogboundary.cpp index ae222200c..ab970d8e0 100644 --- a/src/swrenderer/line/r_fogboundary.cpp +++ b/src/swrenderer/line/r_fogboundary.cpp @@ -74,7 +74,8 @@ namespace swrenderer fillshort(spanend + t2, b2 - t2, x); } - drawerargs.SetLight(basecolormap, (float)light, lightlevel, foggy, thread->Viewport.get()); + drawerargs.SetBaseColormap(basecolormap); + drawerargs.SetLight(light, lightlevel, foggy, thread->Viewport.get()); uint8_t *fake_dc_colormap = basecolormap->Maps + (GETPALOOKUP(light, wallshade) << COLORMAPSHIFT); @@ -101,7 +102,7 @@ namespace swrenderer fillshort(spanend + t2, b2 - t2, x); } rcolormap = lcolormap; - drawerargs.SetLight(basecolormap, (float)light, wallshade); + drawerargs.SetLight(light, wallshade); fake_dc_colormap = basecolormap->Maps + (GETPALOOKUP(light, wallshade) << COLORMAPSHIFT); } else diff --git a/src/swrenderer/line/r_line.cpp b/src/swrenderer/line/r_line.cpp index a3af39bb6..ab2f6a96a 100644 --- a/src/swrenderer/line/r_line.cpp +++ b/src/swrenderer/line/r_line.cpp @@ -1164,24 +1164,10 @@ namespace swrenderer offset = -offset; } - WallDrawerArgs drawerargs; - drawerargs.SetStyle(false, false, OPAQUE); - - CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedLightLevel() >= 0) - drawerargs.SetLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap, 0, cameraLight->FixedLightLevelShade()); - else if (cameraLight->FixedColormap() != nullptr) - drawerargs.SetLight(cameraLight->FixedColormap(), 0, 0); - float rw_light = rw_lightleft + rw_lightstep * (x1 - WallC.sx1); - FLightNode *light_list = (mLineSegment && mLineSegment->sidedef) ? mLineSegment->sidedef->lighthead : nullptr; - - if ((cameraLight->FixedLightLevel() >= 0) || (cameraLight->FixedColormap() != nullptr)) - light_list = nullptr; // [SP] Don't draw dynlights if invul/lightamp active - RenderWallPart renderWallpart(Thread); - renderWallpart.Render(drawerargs, mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallupper.ScreenY, mTopPart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mBackCeilingZ1, mBackCeilingZ2), false, lightlevel, offset, rw_light, rw_lightstep, light_list, foggy, basecolormap); + renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallupper.ScreenY, mTopPart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mBackCeilingZ1, mBackCeilingZ2), false, false, OPAQUE, lightlevel, offset, rw_light, rw_lightstep, GetLightList(), foggy, basecolormap); } void SWRenderLine::RenderMiddleTexture(int x1, int x2) @@ -1211,24 +1197,10 @@ namespace swrenderer offset = -offset; } - WallDrawerArgs drawerargs; - drawerargs.SetStyle(false, false, OPAQUE); - - CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedLightLevel() >= 0) - drawerargs.SetLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap, 0, cameraLight->FixedLightLevelShade()); - else if (cameraLight->FixedColormap() != nullptr) - drawerargs.SetLight(cameraLight->FixedColormap(), 0, 0); - float rw_light = rw_lightleft + rw_lightstep * (x1 - WallC.sx1); - FLightNode *light_list = (mLineSegment && mLineSegment->sidedef) ? mLineSegment->sidedef->lighthead : nullptr; - - if ((cameraLight->FixedLightLevel() >= 0) || (cameraLight->FixedColormap() != nullptr)) - light_list = nullptr; // [SP] Don't draw dynlights if invul/lightamp active - RenderWallPart renderWallpart(Thread); - renderWallpart.Render(drawerargs, mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallbottom.ScreenY, mMiddlePart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, lightlevel, offset, rw_light, rw_lightstep, light_list, foggy, basecolormap); + renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallbottom.ScreenY, mMiddlePart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, lightlevel, offset, rw_light, rw_lightstep, GetLightList(), foggy, basecolormap); } void SWRenderLine::RenderBottomTexture(int x1, int x2) @@ -1259,24 +1231,21 @@ namespace swrenderer offset = -offset; } - WallDrawerArgs drawerargs; - drawerargs.SetStyle(false, false, OPAQUE); - - CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedLightLevel() >= 0) - drawerargs.SetLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap, 0, cameraLight->FixedLightLevelShade()); - else if (cameraLight->FixedColormap() != nullptr) - drawerargs.SetLight(cameraLight->FixedColormap(), 0, 0); - float rw_light = rw_lightleft + rw_lightstep * (x1 - WallC.sx1); - FLightNode *light_list = (mLineSegment && mLineSegment->sidedef) ? mLineSegment->sidedef->lighthead : nullptr; - - if ((cameraLight->FixedLightLevel() >= 0) || (cameraLight->FixedColormap() != nullptr)) - light_list = nullptr; // [SP] Don't draw dynlights if invul/lightamp active - RenderWallPart renderWallpart(Thread); - renderWallpart.Render(drawerargs, mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walllower.ScreenY, wallbottom.ScreenY, mBottomPart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mBackFloorZ1, mBackFloorZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, lightlevel, offset, rw_light, rw_lightstep, light_list, foggy, basecolormap); + renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walllower.ScreenY, wallbottom.ScreenY, mBottomPart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mBackFloorZ1, mBackFloorZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, lightlevel, offset, rw_light, rw_lightstep, GetLightList(), foggy, basecolormap); + } + + FLightNode *SWRenderLine::GetLightList() + { + CameraLight *cameraLight = CameraLight::Instance(); + if ((cameraLight->FixedLightLevel() >= 0) || cameraLight->FixedColormap()) + return nullptr; // [SP] Don't draw dynlights if invul/lightamp active + else if (mLineSegment && mLineSegment->sidedef) + return mLineSegment->sidedef->lighthead; + else + return nullptr; } //////////////////////////////////////////////////////////////////////////// diff --git a/src/swrenderer/line/r_line.h b/src/swrenderer/line/r_line.h index 0b7283fc0..d06adf35a 100644 --- a/src/swrenderer/line/r_line.h +++ b/src/swrenderer/line/r_line.h @@ -91,6 +91,8 @@ namespace swrenderer void RenderMiddleTexture(int x1, int x2); void RenderBottomTexture(int x1, int x2); + FLightNode *GetLightList(); + bool IsFogBoundary(sector_t *front, sector_t *back) const; bool SkyboxCompare(sector_t *frontsector, sector_t *backsector) const; diff --git a/src/swrenderer/line/r_renderdrawsegment.cpp b/src/swrenderer/line/r_renderdrawsegment.cpp index f1a11c454..e62e51bb4 100644 --- a/src/swrenderer/line/r_renderdrawsegment.cpp +++ b/src/swrenderer/line/r_renderdrawsegment.cpp @@ -70,21 +70,6 @@ namespace swrenderer curline = ds->curline; m3DFloor = clip3DFloor; - float alpha = (float)MIN(curline->linedef->alpha, 1.); - bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0; - - WallDrawerArgs walldrawerargs; - walldrawerargs.SetStyle(true, additive, FLOAT2FIXED(alpha)); - - SpriteDrawerArgs columndrawerargs; - FDynamicColormap *patchstylecolormap = nullptr; - bool visible = columndrawerargs.SetStyle(viewport, LegacyRenderStyles[additive ? STYLE_Add : STYLE_Translucent], alpha, 0, 0, patchstylecolormap); - - if (!visible && !ds->bFogBoundary && !ds->Has3DFloorWalls()) - { - return; - } - if (Thread->MainThread) NetUpdate(); @@ -97,29 +82,38 @@ namespace swrenderer FDynamicColormap *basecolormap = GetColorTable(sec->Colormap, sec->SpecialColors[sector_t::walltop]); // [RH] Set basecolormap + bool foggy = ds->foggy; int lightlevel = ds->lightlevel; rw_lightstep = ds->lightstep; rw_light = ds->light + (x1 - ds->x1) * rw_lightstep; Clip3DFloors *clip3d = Thread->Clip3D.get(); - CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedLightLevel() < 0) + double clipTop = m3DFloor.clipTop ? m3DFloor.sclipTop : sec->ceilingplane.ZatPoint(Thread->Viewport->viewpoint.Pos); + for (int i = frontsector->e->XFloor.lightlist.Size() - 1; i >= 0; i--) { - double clipTop = m3DFloor.clipTop ? m3DFloor.sclipTop : sec->ceilingplane.ZatPoint(Thread->Viewport->viewpoint.Pos); - for (int i = frontsector->e->XFloor.lightlist.Size() - 1; i >= 0; i--) + if (clipTop <= frontsector->e->XFloor.lightlist[i].plane.Zat0()) { - if (clipTop <= frontsector->e->XFloor.lightlist[i].plane.Zat0()) - { - lightlist_t *lit = &frontsector->e->XFloor.lightlist[i]; - basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]); - //bool foggy = (level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE)); // [RH] set foggy flag - lightlevel = curline->sidedef->GetLightLevel(ds->foggy, *lit->p_lightlevel, lit->lightsource != nullptr); - break; - } + lightlist_t *lit = &frontsector->e->XFloor.lightlist[i]; + basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]); + foggy = (level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE)); // [RH] set foggy flag + lightlevel = curline->sidedef->GetLightLevel(ds->foggy, *lit->p_lightlevel, lit->lightsource != nullptr); + break; } } + float alpha = (float)MIN(curline->linedef->alpha, 1.); + bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0; + + SpriteDrawerArgs columndrawerargs; + ColormapLight cmlight; + cmlight.SetColormap(Thread, MINZ, lightlevel, foggy, basecolormap, false, false, false, false, false); + bool visible = columndrawerargs.SetStyle(viewport, LegacyRenderStyles[additive ? STYLE_Add : STYLE_Translucent], alpha, 0, 0, cmlight); + if (!visible && !ds->bFogBoundary && !ds->Has3DFloorWalls()) + { + return; + } + // [RH] Draw fog partition bool renderwall = true; bool notrelevant = false; @@ -140,7 +134,7 @@ namespace swrenderer } if (renderwall) - notrelevant = RenderWall(ds, x1, x2, walldrawerargs, columndrawerargs, visible, basecolormap, lightlevel); + notrelevant = RenderWall(ds, x1, x2, basecolormap, columndrawerargs, visible, lightlevel, foggy); if (ds->Has3DFloorFrontSectorWalls() || ds->Has3DFloorBackSectorWalls()) { @@ -153,7 +147,7 @@ namespace swrenderer } } - bool RenderDrawSegment::RenderWall(DrawSegment *ds, int x1, int x2, WallDrawerArgs &walldrawerargs, SpriteDrawerArgs &columndrawerargs, bool visible, FDynamicColormap *basecolormap, int lightlevel) + bool RenderDrawSegment::RenderWall(DrawSegment *ds, int x1, int x2, FDynamicColormap *basecolormap, SpriteDrawerArgs &columndrawerargs, bool visible, int lightlevel, bool foggy) { auto renderstyle = DefaultRenderStyle(); auto viewport = Thread->Viewport.get(); @@ -178,18 +172,6 @@ namespace swrenderer double spryscale = ds->iscale + ds->iscalestep * (x1 - ds->x1); float rw_scalestep = ds->iscalestep; - CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedLightLevel() >= 0) - { - walldrawerargs.SetLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap, 0, cameraLight->FixedLightLevelShade()); - columndrawerargs.SetLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap, 0, cameraLight->FixedLightLevelShade()); - } - else if (cameraLight->FixedColormap() != nullptr) - { - walldrawerargs.SetLight(cameraLight->FixedColormap(), 0, 0); - columndrawerargs.SetLight(cameraLight->FixedColormap(), 0, 0); - } - // find positioning double texheight = tex->GetScaledHeightDouble(); double texheightscale = fabs(curline->sidedef->GetTextureYScale(side_t::mid)); @@ -328,16 +310,17 @@ namespace swrenderer mfloorclip = walllower.ScreenY; mceilingclip = wallupper.ScreenY; + auto cameraLight = CameraLight::Instance(); + bool needslight = (cameraLight->FixedColormap() == nullptr && cameraLight->FixedLightLevel() < 0); + // draw the columns one at a time if (visible) { Thread->PrepareTexture(tex, renderstyle); for (int x = x1; x < x2; ++x) { - if (cameraLight->FixedColormap() == nullptr && cameraLight->FixedLightLevel() < 0) - { - columndrawerargs.SetLight(basecolormap, rw_light, lightlevel, ds->foggy, Thread->Viewport.get()); - } + if (needslight) + columndrawerargs.SetLight(rw_light, lightlevel, foggy, Thread->Viewport.get()); fixed_t iscale = xs_Fix<16>::ToFix(MaskedSWall[x] * MaskedScaleY); double sprtopscreen; @@ -412,8 +395,11 @@ namespace swrenderer double top, bot; GetMaskedWallTopBottom(ds, top, bot); + float alpha = FLOAT2FIXED((float)MIN(curline->linedef->alpha, 1.)); + bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0; + RenderWallPart renderWallpart(Thread); - renderWallpart.Render(walldrawerargs, frontsector, curline, WallC, rw_pic, x1, x2, mceilingclip, mfloorclip, texturemid, MaskedSWall, maskedtexturecol, ds->yscale, top, bot, true, lightlevel, rw_offset, rw_light, rw_lightstep, nullptr, ds->foggy, basecolormap); + renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, mceilingclip, mfloorclip, texturemid, MaskedSWall, maskedtexturecol, ds->yscale, top, bot, true, additive, alpha, lightlevel, rw_offset, rw_light, rw_lightstep, nullptr, ds->foggy, basecolormap); } return false; @@ -430,9 +416,6 @@ namespace swrenderer if (Alpha <= 0) return; - WallDrawerArgs drawerargs; - drawerargs.SetStyle(true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha); - rw_lightstep = ds->lightstep; rw_light = ds->light + (x1 - ds->x1) * rw_lightstep; @@ -486,12 +469,6 @@ namespace swrenderer texturemid += rowoffset; } - CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedLightLevel() >= 0) - drawerargs.SetLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap, 0, cameraLight->FixedLightLevelShade()); - else if (cameraLight->FixedColormap() != nullptr) - drawerargs.SetLight(cameraLight->FixedColormap(), 0, 0); - WallC.sz1 = ds->sz1; WallC.sz2 = ds->sz2; WallC.sx1 = ds->sx1; @@ -524,7 +501,7 @@ namespace swrenderer GetMaskedWallTopBottom(ds, top, bot); RenderWallPart renderWallpart(Thread); - renderWallpart.Render(drawerargs, frontsector, curline, WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, texturemid, MaskedSWall, walltexcoords.UPos, yscale, top, bot, true, lightlevel, rw_offset, rw_light, rw_lightstep, nullptr, ds->foggy, basecolormap); + renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, texturemid, MaskedSWall, walltexcoords.UPos, yscale, top, bot, true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha, lightlevel, rw_offset, rw_light, rw_lightstep, nullptr, ds->foggy, basecolormap); RenderDecal::RenderDecals(Thread, curline->sidedef, ds, lightlevel, rw_light, rw_lightstep, curline, WallC, ds->foggy, basecolormap, wallupper.ScreenY, walllower.ScreenY, true); } diff --git a/src/swrenderer/line/r_renderdrawsegment.h b/src/swrenderer/line/r_renderdrawsegment.h index 229e8705d..3f857a45c 100644 --- a/src/swrenderer/line/r_renderdrawsegment.h +++ b/src/swrenderer/line/r_renderdrawsegment.h @@ -37,7 +37,7 @@ namespace swrenderer RenderThread *Thread = nullptr; private: - bool RenderWall(DrawSegment *ds, int x1, int x2, WallDrawerArgs &walldrawerargs, SpriteDrawerArgs &columndrawerargs, bool visible, FDynamicColormap *basecolormap, int lightlevel); + bool RenderWall(DrawSegment *ds, int x1, int x2, FDynamicColormap *basecolormap, SpriteDrawerArgs &columndrawerargs, bool visible, int lightlevel, bool foggy); void ClipMidtex(int x1, int x2); void RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, int lightlevel, FDynamicColormap *basecolormap, double clipTop, double clipBottom); void RenderFakeWallRange(DrawSegment *ds, int x1, int x2); diff --git a/src/swrenderer/line/r_walldraw.cpp b/src/swrenderer/line/r_walldraw.cpp index 4eb940413..92247671b 100644 --- a/src/swrenderer/line/r_walldraw.cpp +++ b/src/swrenderer/line/r_walldraw.cpp @@ -341,16 +341,19 @@ namespace swrenderer drawerargs.SetTextureFracBits(Thread->Viewport->RenderTarget->IsBgra() ? FRACBITS : fracbits); + // Textures that aren't masked can use the faster opaque drawer + if (!rw_pic->GetTexture()->isMasked() && mask && alpha >= OPAQUE && !additive) + { + drawerargs.SetStyle(true, false, OPAQUE, basecolormap); + } + else + { + drawerargs.SetStyle(mask, additive, alpha, basecolormap); + } + CameraLight *cameraLight = CameraLight::Instance(); bool fixed = (cameraLight->FixedColormap() != NULL || cameraLight->FixedLightLevel() >= 0); - if (cameraLight->FixedLightLevel() >= 0) - drawerargs.SetLight(cameraLight->FixedColormap(), 0, cameraLight->FixedLightLevelShade()); - else if (cameraLight->FixedColormap()) - drawerargs.SetLight(cameraLight->FixedColormap(), 0, 0); - else - drawerargs.SetLight(basecolormap, 0, 0); - float dx = WallC.tright.X - WallC.tleft.X; float dy = WallC.tright.Y - WallC.tleft.Y; float length = sqrt(dx * dx + dy * dy); @@ -369,7 +372,7 @@ namespace swrenderer continue; if (!fixed) - drawerargs.SetLight(basecolormap, curlight, lightlevel, foggy, Thread->Viewport.get()); + drawerargs.SetLight(curlight, lightlevel, foggy, Thread->Viewport.get()); if (x + 1 < x2) xmagnitude = fabs(FIXED2DBL(lwal[x + 1]) - FIXED2DBL(lwal[x])); @@ -425,12 +428,6 @@ namespace swrenderer void RenderWallPart::ProcessWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal) { - // Textures that aren't masked can use the faster ProcessNormalWall. - if (!rw_pic->GetTexture()->isMasked() && drawerargs.IsMaskedDrawer()) - { - drawerargs.SetStyle(true, false, OPAQUE); - } - CameraLight *cameraLight = CameraLight::Instance(); if (cameraLight->FixedColormap() != NULL || cameraLight->FixedLightLevel() >= 0 || !(frontsector->e && frontsector->e->XFloor.lightlist.Size())) { @@ -514,9 +511,8 @@ namespace swrenderer } } - void RenderWallPart::Render(const WallDrawerArgs &drawerargs, sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, FSoftwareTexture *pic, int x1, int x2, const short *walltop, const short *wallbottom, double texturemid, float *swall, fixed_t *lwall, double yscale, double top, double bottom, bool mask, int lightlevel, fixed_t xoffset, float light, float lightstep, FLightNode *light_list, bool foggy, FDynamicColormap *basecolormap) + void RenderWallPart::Render(sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, FSoftwareTexture *pic, int x1, int x2, const short *walltop, const short *wallbottom, double texturemid, float *swall, fixed_t *lwall, double yscale, double top, double bottom, bool mask, bool additive, fixed_t alpha, int lightlevel, fixed_t xoffset, float light, float lightstep, FLightNode *light_list, bool foggy, FDynamicColormap *basecolormap) { - this->drawerargs = drawerargs; this->x1 = x1; this->x2 = x2; this->frontsector = frontsector; @@ -532,6 +528,8 @@ namespace swrenderer this->light_list = light_list; this->rw_pic = pic; this->mask = mask; + this->additive = additive; + this->alpha = alpha; Thread->PrepareTexture(pic, DefaultRenderStyle()); // Get correct render style? Shaded won't get here. diff --git a/src/swrenderer/line/r_walldraw.h b/src/swrenderer/line/r_walldraw.h index b44484b15..fa6074b8e 100644 --- a/src/swrenderer/line/r_walldraw.h +++ b/src/swrenderer/line/r_walldraw.h @@ -46,7 +46,6 @@ namespace swrenderer RenderWallPart(RenderThread *thread); void Render( - const WallDrawerArgs &drawerargs, sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, @@ -62,6 +61,8 @@ namespace swrenderer double top, double bottom, bool mask, + bool additive, + fixed_t alpha, int lightlevel, fixed_t xoffset, float light, @@ -96,6 +97,8 @@ namespace swrenderer FDynamicColormap *basecolormap = nullptr; FLightNode *light_list = nullptr; bool mask = false; + bool additive = false; + fixed_t alpha = 0; WallDrawerArgs drawerargs; }; diff --git a/src/swrenderer/plane/r_flatplane.cpp b/src/swrenderer/plane/r_flatplane.cpp index 3ddf3a1b6..7350d6983 100644 --- a/src/swrenderer/plane/r_flatplane.cpp +++ b/src/swrenderer/plane/r_flatplane.cpp @@ -134,29 +134,14 @@ namespace swrenderer planeheight = fabs(pl->height.Zat0() - Thread->Viewport->viewpoint.Pos.Z); - basecolormap = colormap; - // [RH] set foggy flag - foggy = (level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE)); + foggy = (level.fadeto || colormap->Fade || (level.flags & LEVEL_HASFADETABLE)); + lightlevel = pl->lightlevel; CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedLightLevel() >= 0) - { - drawerargs.SetLight(basecolormap, 0, cameraLight->FixedLightLevelShade()); - plane_shade = false; - } - else if (cameraLight->FixedColormap()) - { - drawerargs.SetLight(cameraLight->FixedColormap(), 0, 0); - plane_shade = false; - } - else - { - plane_shade = true; - lightlevel = pl->lightlevel; - } + plane_shade = cameraLight->FixedLightLevel() < 0 && !cameraLight->FixedColormap(); - drawerargs.SetStyle(masked, additive, alpha); + drawerargs.SetStyle(masked, additive, alpha, colormap); light_list = pl->lights; @@ -200,7 +185,7 @@ namespace swrenderer if (plane_shade) { // Determine lighting based on the span's distance from the viewer. - drawerargs.SetLight(basecolormap, (float)Thread->Light->FlatPlaneVis(y, planeheight, foggy, viewport), lightlevel, foggy, viewport); + drawerargs.SetLight((float)Thread->Light->FlatPlaneVis(y, planeheight, foggy, viewport), lightlevel, foggy, viewport); } if (r_dynlights) diff --git a/src/swrenderer/plane/r_flatplane.h b/src/swrenderer/plane/r_flatplane.h index fa12101d7..10fa0379a 100644 --- a/src/swrenderer/plane/r_flatplane.h +++ b/src/swrenderer/plane/r_flatplane.h @@ -46,7 +46,6 @@ namespace swrenderer bool plane_shade; int lightlevel; bool foggy; - FDynamicColormap *basecolormap; double pviewx, pviewy; double xstepscale, ystepscale; double basexfrac, baseyfrac; diff --git a/src/swrenderer/plane/r_skyplane.cpp b/src/swrenderer/plane/r_skyplane.cpp index 5b5c4894a..24653860d 100644 --- a/src/swrenderer/plane/r_skyplane.cpp +++ b/src/swrenderer/plane/r_skyplane.cpp @@ -57,65 +57,8 @@ CVAR(Bool, r_linearsky, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); EXTERN_CVAR(Int, r_skymode) - -double skytexturemid; -double skyscale; -float skyiscale; -fixed_t sky1cyl, sky2cyl; - -void InitSoftwareSky() -{ - auto skytex1 = TexMan.GetPalettedTexture(sky1texture, true); - auto skytex2 = TexMan.GetPalettedTexture(sky2texture, true); - - if (skytex1 == nullptr) - return; - - // Note: I don't think it is good that this stuff gets cached globally. - // For something that only needs to be once per frame it is rather pointless and makes it hard to swap out the underlying textures based on user settings. - FSoftwareTexture *sskytex1 = skytex1->GetSoftwareTexture(); - FSoftwareTexture *sskytex2 = skytex2->GetSoftwareTexture(); - skytexturemid = 0; - int skyheight = skytex1->GetDisplayHeight(); - if (skyheight >= 128 && skyheight < 200) - { - skytexturemid = -28; - } - else if (skyheight > 200) - { - skytexturemid = (200 - skyheight) * sskytex1->GetScale().Y + ((r_skymode == 2 && !(level.flags & LEVEL_FORCETILEDSKY)) ? skytex1->GetSkyOffset() : 0); - } - - if (viewwidth != 0 && viewheight != 0) - { - skyiscale = float(r_Yaspect / freelookviewheight); - skyscale = freelookviewheight / r_Yaspect; - - skyiscale *= float(r_viewpoint.FieldOfView.Degrees / 90.); - skyscale *= float(90. / r_viewpoint.FieldOfView.Degrees); - } - - if (skystretch) - { - skyscale *= (double)SKYSTRETCH_HEIGHT / skyheight; - skyiscale *= skyheight / (float)SKYSTRETCH_HEIGHT; - skytexturemid *= skyheight / (double)SKYSTRETCH_HEIGHT; - } - - // The standard Doom sky texture is 256 pixels wide, repeated 4 times over 360 degrees, - // giving a total sky width of 1024 pixels. So if the sky texture is no wider than 1024, - // we map it to a cylinder with circumfrence 1024. For larger ones, we use the width of - // the texture as the cylinder's circumfrence. - sky1cyl = MAX(sskytex1->GetWidth(), fixed_t(sskytex1->GetScale().X * 1024)); - sky2cyl = MAX(sskytex2->GetWidth(), fixed_t(sskytex2->GetScale().Y * 1024)); -} - - - - namespace swrenderer { - static FSoftwareTexture *GetSWTex(FTextureID texid, bool allownull = true) { auto tex = TexMan.GetPalettedTexture(texid, true); @@ -127,6 +70,48 @@ namespace swrenderer RenderSkyPlane::RenderSkyPlane(RenderThread *thread) { Thread = thread; + + auto skytex1 = TexMan.GetPalettedTexture(sky1texture, true); + auto skytex2 = TexMan.GetPalettedTexture(sky2texture, true); + + if (skytex1 == nullptr) + return; + + FSoftwareTexture *sskytex1 = skytex1->GetSoftwareTexture(); + FSoftwareTexture *sskytex2 = skytex2->GetSoftwareTexture(); + skytexturemid = 0; + int skyheight = skytex1->GetDisplayHeight(); + if (skyheight >= 128 && skyheight < 200) + { + skytexturemid = -28; + } + else if (skyheight > 200) + { + skytexturemid = (200 - skyheight) * sskytex1->GetScale().Y + ((r_skymode == 2 && !(level.flags & LEVEL_FORCETILEDSKY)) ? skytex1->GetSkyOffset() : 0); + } + + if (viewwidth != 0 && viewheight != 0) + { + skyiscale = float(r_Yaspect / freelookviewheight); + skyscale = freelookviewheight / r_Yaspect; + + skyiscale *= float(r_viewpoint.FieldOfView.Degrees / 90.); + skyscale *= float(90. / r_viewpoint.FieldOfView.Degrees); + } + + if (skystretch) + { + skyscale *= (double)SKYSTRETCH_HEIGHT / skyheight; + skyiscale *= skyheight / (float)SKYSTRETCH_HEIGHT; + skytexturemid *= skyheight / (double)SKYSTRETCH_HEIGHT; + } + + // The standard Doom sky texture is 256 pixels wide, repeated 4 times over 360 degrees, + // giving a total sky width of 1024 pixels. So if the sky texture is no wider than 1024, + // we map it to a cylinder with circumfrence 1024. For larger ones, we use the width of + // the texture as the cylinder's circumfrence. + sky1cyl = MAX(sskytex1->GetWidth(), fixed_t(sskytex1->GetScale().X * 1024)); + sky2cyl = MAX(sskytex2->GetWidth(), fixed_t(sskytex2->GetScale().Y * 1024)); } void RenderSkyPlane::Render(VisiblePlane *pl) @@ -227,15 +212,7 @@ namespace swrenderer backpos = int(fmod(backdpos, sky2cyl * 65536.0)); } - CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedColormap()) - { - drawerargs.SetLight(cameraLight->FixedColormap(), 0, 0); - } - else - { - drawerargs.SetLight(&NormalLight, 0, 0); - } + drawerargs.SetStyle(); Thread->PrepareTexture(frontskytex, DefaultRenderStyle()); Thread->PrepareTexture(backskytex, DefaultRenderStyle()); diff --git a/src/swrenderer/plane/r_skyplane.h b/src/swrenderer/plane/r_skyplane.h index ac5e07d25..a0fd268ed 100644 --- a/src/swrenderer/plane/r_skyplane.h +++ b/src/swrenderer/plane/r_skyplane.h @@ -41,6 +41,11 @@ namespace swrenderer void DrawSkyColumnStripe(int start_x, int y1, int y2, double scale, double texturemid, double yrepeat); void DrawSkyColumn(int start_x, int y1, int y2); + double skytexturemid; + double skyscale; + float skyiscale; + fixed_t sky1cyl, sky2cyl; + FSoftwareTexture *frontskytex = nullptr; FSoftwareTexture *backskytex = nullptr; angle_t skyflip = 0; diff --git a/src/swrenderer/plane/r_slopeplane.cpp b/src/swrenderer/plane/r_slopeplane.cpp index 0f4ac159a..3c7dcb72d 100644 --- a/src/swrenderer/plane/r_slopeplane.cpp +++ b/src/swrenderer/plane/r_slopeplane.cpp @@ -174,31 +174,19 @@ namespace swrenderer // [RH] set foggy flag basecolormap = colormap; - foggy = level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE);; + foggy = level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE); planelightfloat = (Thread->Light->SlopePlaneGlobVis(foggy) * lxscale * lyscale) / (fabs(pl->height.ZatPoint(Thread->Viewport->viewpoint.Pos) - Thread->Viewport->viewpoint.Pos.Z)) / 65536.f; if (pl->height.fC() > 0) planelightfloat = -planelightfloat; + drawerargs.SetStyle(false, false, OPAQUE, basecolormap); CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedLightLevel() >= 0) - { - drawerargs.SetLight(basecolormap, 0, cameraLight->FixedLightLevelShade()); - plane_shade = false; - } - else if (cameraLight->FixedColormap()) - { - drawerargs.SetLight(cameraLight->FixedColormap(), 0, 0); - plane_shade = false; - } - else - { - drawerargs.SetLight(basecolormap, 0, 0); - plane_shade = true; - lightlevel = pl->lightlevel; - } + plane_shade = cameraLight->FixedLightLevel() < 0 && !cameraLight->FixedColormap(); + + lightlevel = pl->lightlevel; // Hack in support for 1 x Z and Z x 1 texture sizes if (drawerargs.TextureHeightBits() == 0) diff --git a/src/swrenderer/r_swscene.cpp b/src/swrenderer/r_swscene.cpp index 807a3126e..013308bbf 100644 --- a/src/swrenderer/r_swscene.cpp +++ b/src/swrenderer/r_swscene.cpp @@ -38,7 +38,6 @@ // [RH] Base blending values (for e.g. underwater) int BaseBlendR, BaseBlendG, BaseBlendB; float BaseBlendA; -void InitSoftwareSky(); @@ -87,7 +86,6 @@ SWSceneDrawer::~SWSceneDrawer() sector_t *SWSceneDrawer::RenderView(player_t *player) { // Avoid using the pixel buffer from the last frame - InitSoftwareSky(); // do this here to avoid problems when texture modes are changed on the fly. FBTextureIndex = (FBTextureIndex + 1) % 2; auto &fbtex = FBTexture[FBTextureIndex]; diff --git a/src/swrenderer/things/r_decal.cpp b/src/swrenderer/things/r_decal.cpp index f5393ce0b..db42a0a2e 100644 --- a/src/swrenderer/things/r_decal.cpp +++ b/src/swrenderer/things/r_decal.cpp @@ -74,8 +74,6 @@ namespace swrenderer double zpos; int needrepeat = 0; sector_t *back; - bool calclighting; - bool rereadcolormap; FDynamicColormap *usecolormap; float light = 0; const short *mfloorclip; @@ -259,15 +257,12 @@ namespace swrenderer } // Prepare lighting - calclighting = false; usecolormap = basecolormap; - rereadcolormap = true; // Decals that are added to the scene must fade to black. if (decal->RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0) { usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate); - rereadcolormap = false; } light = lightleft + (x1 - savecoord.sx1) * lightstep; @@ -292,24 +287,12 @@ namespace swrenderer { int x = x1; + ColormapLight cmlight; + cmlight.SetColormap(thread, MINZ, lightlevel, foggy, usecolormap, decal->RenderFlags & RF_FULLBRIGHT, false, false, false, false); + SpriteDrawerArgs drawerargs; - - if (cameraLight->FixedLightLevel() >= 0) - drawerargs.SetLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, cameraLight->FixedLightLevelShade()); - else if (cameraLight->FixedColormap() != NULL) - drawerargs.SetLight(cameraLight->FixedColormap(), 0, 0); - else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT)) - drawerargs.SetLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, 0); - else - calclighting = true; - - bool visible = drawerargs.SetStyle(thread->Viewport.get(), decal->RenderStyle, (float)decal->Alpha, decal->Translation, decal->AlphaColor, basecolormap); - - // R_SetPatchStyle can modify basecolormap. - if (rereadcolormap) - { - usecolormap = basecolormap; - } + bool visible = drawerargs.SetStyle(thread->Viewport.get(), decal->RenderStyle, (float)decal->Alpha, decal->Translation, decal->AlphaColor, cmlight); + bool calclighting = cameraLight->FixedLightLevel() < 0 && !cameraLight->FixedColormap(); if (visible) { @@ -318,7 +301,7 @@ namespace swrenderer { if (calclighting) { // calculate lighting - drawerargs.SetLight(usecolormap, light, lightlevel, foggy, thread->Viewport.get()); + drawerargs.SetLight(light, lightlevel, foggy, thread->Viewport.get()); } DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, decal->RenderStyle); light += lightstep; diff --git a/src/swrenderer/things/r_playersprite.cpp b/src/swrenderer/things/r_playersprite.cpp index c206c4863..fd1b8adf8 100644 --- a/src/swrenderer/things/r_playersprite.cpp +++ b/src/swrenderer/things/r_playersprite.cpp @@ -492,11 +492,7 @@ namespace swrenderer } SpriteDrawerArgs drawerargs; - drawerargs.SetLight(Light.BaseColormap, 0, Light.ColormapNum << FRACBITS); - - FDynamicColormap *basecolormap = static_cast(Light.BaseColormap); - - bool visible = drawerargs.SetStyle(thread->Viewport.get(), RenderStyle, Alpha, Translation, FillColor, basecolormap, Light.ColormapNum << FRACBITS); + bool visible = drawerargs.SetStyle(thread->Viewport.get(), RenderStyle, Alpha, Translation, FillColor, Light); if (!visible) return; diff --git a/src/swrenderer/things/r_sprite.cpp b/src/swrenderer/things/r_sprite.cpp index 1daa0b62a..bc44bcebe 100644 --- a/src/swrenderer/things/r_sprite.cpp +++ b/src/swrenderer/things/r_sprite.cpp @@ -323,12 +323,8 @@ namespace swrenderer } SpriteDrawerArgs drawerargs; - drawerargs.SetLight(vis->Light.BaseColormap, 0, vis->Light.ColormapNum << FRACBITS); drawerargs.SetDynamicLight(dynlightcolor); - - FDynamicColormap *basecolormap = static_cast(vis->Light.BaseColormap); - - bool visible = drawerargs.SetStyle(thread->Viewport.get(), vis->RenderStyle, vis->Alpha, vis->Translation, vis->FillColor, basecolormap, vis->Light.ColormapNum << FRACBITS); + bool visible = drawerargs.SetStyle(thread->Viewport.get(), vis->RenderStyle, vis->Alpha, vis->Translation, vis->FillColor, vis->Light); if (visible) { diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index 30b8dc259..662fd1bc3 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -162,7 +162,6 @@ namespace swrenderer vis->Alpha = float(thing->Alpha); vis->fakefloor = fakefloor; vis->fakeceiling = fakeceiling; - vis->Light.ColormapNum = 0; vis->bInMirror = renderportal->MirrorFlags & RF_XFLIP; //vis->bSplitSprite = false; @@ -192,9 +191,7 @@ namespace swrenderer // Fake a voxel drawing to find its extents.. SpriteDrawerArgs drawerargs; - drawerargs.SetLight(vis->Light.BaseColormap, 0, vis->Light.ColormapNum << FRACBITS); - basecolormap = (FDynamicColormap*)vis->Light.BaseColormap; - bool visible = drawerargs.SetStyle(thread->Viewport.get(), vis->RenderStyle, vis->Alpha, vis->Translation, vis->FillColor, basecolormap); + bool visible = drawerargs.SetStyle(thread->Viewport.get(), vis->RenderStyle, vis->Alpha, vis->Translation, vis->FillColor, vis->Light); if (!visible) return; int flags = vis->bInMirror ? (DVF_MIRRORED | DVF_FIND_X1X2) : DVF_FIND_X1X2; @@ -211,10 +208,7 @@ namespace swrenderer auto viewport = thread->Viewport.get(); SpriteDrawerArgs drawerargs; - drawerargs.SetLight(spr->Light.BaseColormap, 0, spr->Light.ColormapNum << FRACBITS); - - FDynamicColormap *basecolormap = (FDynamicColormap*)spr->Light.BaseColormap; - bool visible = drawerargs.SetStyle(viewport, spr->RenderStyle, spr->Alpha, spr->Translation, spr->FillColor, basecolormap); + bool visible = drawerargs.SetStyle(viewport, spr->RenderStyle, spr->Alpha, spr->Translation, spr->FillColor, spr->Light); if (!visible) return; @@ -908,12 +902,8 @@ namespace swrenderer auto sprite = this; auto viewport = RenderViewport::Instance(); - FDynamicColormap *basecolormap = static_cast(sprite->Light.BaseColormap); - SpriteDrawerArgs drawerargs; - drawerargs.SetLight(sprite->Light.BaseColormap, 0, sprite->Light.ColormapNum << FRACBITS); - - bool visible = drawerargs.SetStyle(sprite->RenderStyle, sprite->Alpha, sprite->Translation, sprite->FillColor, basecolormap); + bool visible = drawerargs.SetStyle(sprite->RenderStyle, sprite->Alpha, sprite->Translation, sprite->FillColor, sprite->Light); if (!visible) return; diff --git a/src/swrenderer/things/r_wallsprite.cpp b/src/swrenderer/things/r_wallsprite.cpp index 2046fe2f3..15d600b5f 100644 --- a/src/swrenderer/things/r_wallsprite.cpp +++ b/src/swrenderer/things/r_wallsprite.cpp @@ -176,32 +176,27 @@ namespace swrenderer walltexcoords.UPos[i] = right - walltexcoords.UPos[i]; } } + // Prepare lighting - bool calclighting = false; - FSWColormap *usecolormap = spr->Light.BaseColormap; - bool rereadcolormap = true; // Decals that are added to the scene must fade to black. - if (spr->RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0) + ColormapLight cmlight; + if (spr->RenderStyle == LegacyRenderStyles[STYLE_Add] && cmlight.BaseColormap->Fade != 0) { - usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate); - rereadcolormap = false; + cmlight.BaseColormap = GetSpecialLights(cmlight.BaseColormap->Color, 0, cmlight.BaseColormap->Desaturate); } SpriteDrawerArgs drawerargs; + bool visible = drawerargs.SetStyle(thread->Viewport.get(), spr->RenderStyle, spr->Alpha, spr->Translation, spr->FillColor, cmlight); + if (!visible) + return; + float lightleft = float(thread->Light->WallVis(spr->wallc.sz1, foggy)); float lightstep = float((thread->Light->WallVis(spr->wallc.sz2, foggy) - lightleft) / (spr->wallc.sx2 - spr->wallc.sx1)); float light = lightleft + (x1 - spr->wallc.sx1) * lightstep; CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedLightLevel() >= 0) - drawerargs.SetLight(usecolormap, 0, cameraLight->FixedLightLevelShade()); - else if (cameraLight->FixedColormap() != NULL) - drawerargs.SetLight(cameraLight->FixedColormap(), 0, 0); - else if (!spr->foggy && (spr->renderflags & RF_FULLBRIGHT)) - drawerargs.SetLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, 0); - else - calclighting = true; + bool calclighting = cameraLight->FixedLightLevel() < 0 && !cameraLight->FixedColormap(); // Draw it auto WallSpriteTile = spr->pic; @@ -220,36 +215,19 @@ namespace swrenderer int x = x1; - FDynamicColormap *basecolormap = static_cast(spr->Light.BaseColormap); + RenderTranslucentPass *translucentPass = thread->TranslucentPass.get(); - bool visible = drawerargs.SetStyle(thread->Viewport.get(), spr->RenderStyle, spr->Alpha, spr->Translation, spr->FillColor, basecolormap); - - // R_SetPatchStyle can modify basecolormap. - if (rereadcolormap) + thread->PrepareTexture(WallSpriteTile, spr->RenderStyle); + while (x < x2) { - usecolormap = spr->Light.BaseColormap; - } - - if (!visible) - { - return; - } - else - { - RenderTranslucentPass *translucentPass = thread->TranslucentPass.get(); - - thread->PrepareTexture(WallSpriteTile, spr->RenderStyle); - while (x < x2) + if (calclighting) { - if (calclighting) - { // calculate lighting - drawerargs.SetLight(usecolormap, light, spr->sector->lightlevel, spr->foggy, thread->Viewport.get()); - } - if (!translucentPass->ClipSpriteColumnWithPortals(x, spr)) - DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, spr->RenderStyle); - light += lightstep; - x++; + drawerargs.SetLight(light, spr->sector->lightlevel, spr->foggy, thread->Viewport.get()); } + if (!translucentPass->ClipSpriteColumnWithPortals(x, spr)) + DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, spr->RenderStyle); + light += lightstep; + x++; } } diff --git a/src/swrenderer/viewport/r_drawerargs.cpp b/src/swrenderer/viewport/r_drawerargs.cpp index 3306381a4..cf12dc41f 100644 --- a/src/swrenderer/viewport/r_drawerargs.cpp +++ b/src/swrenderer/viewport/r_drawerargs.cpp @@ -24,15 +24,26 @@ namespace swrenderer { - void DrawerArgs::SetLight(FSWColormap *base_colormap, float light, int lightlevel, bool foggy, RenderViewport *viewport) - { - SetLight(base_colormap, light, LightVisibility::LightLevelToShade(lightlevel, foggy, viewport)); - } - - void DrawerArgs::SetLight(FSWColormap *base_colormap, float light, int shade) + void DrawerArgs::SetBaseColormap(FSWColormap *base_colormap) { mBaseColormap = base_colormap; assert(mBaseColormap->Maps != nullptr); + } + + void DrawerArgs::SetLight(float light, int lightlevel, bool foggy, RenderViewport *viewport) + { + mLight = light; + mShade = LightVisibility::LightLevelToShade(lightlevel, foggy, viewport); + } + + void DrawerArgs::SetLight(const ColormapLight &light) + { + SetBaseColormap(light.BaseColormap); + SetLight(0.0f, light.ColormapNum << FRACBITS); + } + + void DrawerArgs::SetLight(float light, int shade) + { mLight = light; mShade = shade; } diff --git a/src/swrenderer/viewport/r_drawerargs.h b/src/swrenderer/viewport/r_drawerargs.h index 1ba8d5e61..8fcb812b4 100644 --- a/src/swrenderer/viewport/r_drawerargs.h +++ b/src/swrenderer/viewport/r_drawerargs.h @@ -16,6 +16,7 @@ struct FLightNode; namespace swrenderer { + class ColormapLight; class SWPixelFormatDrawers; class DrawerArgs; struct ShadeConstants; @@ -30,8 +31,9 @@ namespace swrenderer class DrawerArgs { public: - void SetLight(FSWColormap *base_colormap, float light, int shade); - void SetLight(FSWColormap *base_colormap, float light, int lightlevel, bool foggy, RenderViewport *viewport); + void SetBaseColormap(FSWColormap *base_colormap); + void SetLight(float light, int shade); + void SetLight(float light, int lightlevel, bool foggy, RenderViewport *viewport); void SetTranslationMap(lighttable_t *translation); uint8_t *Colormap(RenderViewport *viewport) const; @@ -40,6 +42,9 @@ namespace swrenderer ShadeConstants ColormapConstants() const; fixed_t Light() const { return LIGHTSCALE(mLight, mShade); } + protected: + void SetLight(const ColormapLight &light); + private: FSWColormap *mBaseColormap = nullptr; float mLight = 0.0f; diff --git a/src/swrenderer/viewport/r_skydrawer.cpp b/src/swrenderer/viewport/r_skydrawer.cpp index 2f75e30e2..008903498 100644 --- a/src/swrenderer/viewport/r_skydrawer.cpp +++ b/src/swrenderer/viewport/r_skydrawer.cpp @@ -40,6 +40,21 @@ namespace swrenderer thread->Drawers(dc_viewport)->DrawDoubleSkyColumn(*this); } + void SkyDrawerArgs::SetStyle() + { + CameraLight *cameraLight = CameraLight::Instance(); + if (cameraLight->FixedColormap()) + { + SetBaseColormap(cameraLight->FixedColormap()); + SetLight(0, 0); + } + else + { + SetBaseColormap(&NormalLight); + SetLight(0, 0); + } + } + void SkyDrawerArgs::SetDest(RenderViewport *viewport, int x, int y) { dc_dest = viewport->GetDest(x, y); diff --git a/src/swrenderer/viewport/r_skydrawer.h b/src/swrenderer/viewport/r_skydrawer.h index 2634c514f..4603a0b20 100644 --- a/src/swrenderer/viewport/r_skydrawer.h +++ b/src/swrenderer/viewport/r_skydrawer.h @@ -13,6 +13,7 @@ namespace swrenderer class SkyDrawerArgs : public DrawerArgs { public: + void SetStyle(); void SetDest(RenderViewport *viewport, int x, int y); void SetCount(int count) { dc_count = count; } void SetFrontTexture(RenderThread *thread, FSoftwareTexture *texture, fixed_t column); diff --git a/src/swrenderer/viewport/r_spandrawer.cpp b/src/swrenderer/viewport/r_spandrawer.cpp index 69c6ead64..51da4fb46 100644 --- a/src/swrenderer/viewport/r_spandrawer.cpp +++ b/src/swrenderer/viewport/r_spandrawer.cpp @@ -51,7 +51,7 @@ namespace swrenderer ds_source_mipmapped = tex->Mipmapped() && tex->GetPhysicalWidth() > 1 && tex->GetPhysicalHeight() > 1; } - void SpanDrawerArgs::SetStyle(bool masked, bool additive, fixed_t alpha) + void SpanDrawerArgs::SetStyle(bool masked, bool additive, fixed_t alpha, FDynamicColormap *basecolormap) { if (masked) { @@ -105,6 +105,22 @@ namespace swrenderer spanfunc = &SWPixelFormatDrawers::DrawSpan; } } + + CameraLight *cameraLight = CameraLight::Instance(); + if (cameraLight->FixedLightLevel() >= 0) + { + SetBaseColormap((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap); + SetLight(0, cameraLight->FixedLightLevelShade()); + } + else if (cameraLight->FixedColormap()) + { + SetBaseColormap(cameraLight->FixedColormap()); + SetLight(0, 0); + } + else + { + SetBaseColormap(basecolormap); + } } void SpanDrawerArgs::DrawDepthSpan(RenderThread *thread, float idepth1, float idepth2) diff --git a/src/swrenderer/viewport/r_spandrawer.h b/src/swrenderer/viewport/r_spandrawer.h index 8bd2aeb10..b0c194553 100644 --- a/src/swrenderer/viewport/r_spandrawer.h +++ b/src/swrenderer/viewport/r_spandrawer.h @@ -15,7 +15,7 @@ namespace swrenderer public: SpanDrawerArgs(); - void SetStyle(bool masked, bool additive, fixed_t alpha); + void SetStyle(bool masked, bool additive, fixed_t alpha, FDynamicColormap *basecolormap); void SetDestY(RenderViewport *viewport, int y) { ds_viewport = viewport; ds_y = y; } void SetDestX1(int x) { ds_x1 = x; } void SetDestX2(int x) { ds_x2 = x; } diff --git a/src/swrenderer/viewport/r_spritedrawer.cpp b/src/swrenderer/viewport/r_spritedrawer.cpp index f6d870912..dd0c7b1b4 100644 --- a/src/swrenderer/viewport/r_spritedrawer.cpp +++ b/src/swrenderer/viewport/r_spritedrawer.cpp @@ -382,8 +382,14 @@ namespace swrenderer } } - bool SpriteDrawerArgs::SetStyle(RenderViewport *viewport, FRenderStyle style, fixed_t alpha, int translation, uint32_t color, FDynamicColormap *&basecolormap, fixed_t shadedlightshade) + bool SpriteDrawerArgs::SetStyle(RenderViewport *viewport, FRenderStyle style, fixed_t alpha, int translation, uint32_t color, const ColormapLight &light) { + if (light.BaseColormap) + SetLight(light); + + FDynamicColormap *basecolormap = light.BaseColormap ? static_cast(light.BaseColormap) : nullptr; + fixed_t shadedlightshade = light.ColormapNum << FRACBITS; + fixed_t fglevel, bglevel; drawer_needs_pal_input = false; @@ -450,11 +456,13 @@ namespace swrenderer { fixed_t shade = shadedlightshade; if (shade == 0) shade = cameraLight->FixedLightLevelShade(); - SetLight(basecolormap, 0, shade); + SetBaseColormap(basecolormap); + SetLight(0, shade); } else { - SetLight(basecolormap, 0, shadedlightshade); + SetBaseColormap(basecolormap); + SetLight(0, shadedlightshade); } return true; } @@ -482,15 +490,16 @@ namespace swrenderer // dc_srccolor is used by the R_Fill* routines. It is premultiplied // with the alpha. dc_srccolor = ((((r*x) >> 4) << 20) | ((g*x) >> 4) | ((((b)*x) >> 4) << 10)) & 0x3feffbff; - SetLight(&identitycolormap, 0, 0); + SetBaseColormap(&identitycolormap); + SetLight(0, 0); } return SpriteDrawerArgs::SetBlendFunc(style.BlendOp, fglevel, bglevel, style.Flags); } - bool SpriteDrawerArgs::SetStyle(RenderViewport *viewport, FRenderStyle style, float alpha, int translation, uint32_t color, FDynamicColormap *&basecolormap, fixed_t shadedlightshade) + bool SpriteDrawerArgs::SetStyle(RenderViewport *viewport, FRenderStyle style, float alpha, int translation, uint32_t color, const ColormapLight &light) { - return SetStyle(viewport, style, FLOAT2FIXED(alpha), translation, color, basecolormap, shadedlightshade); + return SetStyle(viewport, style, FLOAT2FIXED(alpha), translation, color, light); } void SpriteDrawerArgs::FillColumn(RenderThread *thread) diff --git a/src/swrenderer/viewport/r_spritedrawer.h b/src/swrenderer/viewport/r_spritedrawer.h index e025d5c9e..186618991 100644 --- a/src/swrenderer/viewport/r_spritedrawer.h +++ b/src/swrenderer/viewport/r_spritedrawer.h @@ -26,8 +26,8 @@ namespace swrenderer public: SpriteDrawerArgs(); - bool SetStyle(RenderViewport *viewport, FRenderStyle style, fixed_t alpha, int translation, uint32_t color, FDynamicColormap *&basecolormap, fixed_t shadedlightshade = 0); - bool SetStyle(RenderViewport *viewport, FRenderStyle style, float alpha, int translation, uint32_t color, FDynamicColormap *&basecolormap, fixed_t shadedlightshade = 0); + bool SetStyle(RenderViewport *viewport, FRenderStyle style, fixed_t alpha, int translation, uint32_t color, const ColormapLight &light); + bool SetStyle(RenderViewport *viewport, FRenderStyle style, float alpha, int translation, uint32_t color, const ColormapLight &light); void SetDest(RenderViewport *viewport, int x, int y); void SetCount(int count) { dc_count = count; } void SetSolidColor(int color) { dc_color = color; dc_color_bgra = GPalette.BaseColors[color]; } diff --git a/src/swrenderer/viewport/r_walldrawer.cpp b/src/swrenderer/viewport/r_walldrawer.cpp index 50530eec5..ae9077f4e 100644 --- a/src/swrenderer/viewport/r_walldrawer.cpp +++ b/src/swrenderer/viewport/r_walldrawer.cpp @@ -42,7 +42,7 @@ namespace swrenderer (thread->Drawers(dc_viewport)->*wallfunc)(*this); } - void WallDrawerArgs::SetStyle(bool masked, bool additive, fixed_t alpha) + void WallDrawerArgs::SetStyle(bool masked, bool additive, fixed_t alpha, FDynamicColormap *basecolormap) { if (alpha < OPAQUE || additive) { @@ -71,10 +71,21 @@ namespace swrenderer { wallfunc = &SWPixelFormatDrawers::DrawWallColumn; } - } - bool WallDrawerArgs::IsMaskedDrawer() const - { - return wallfunc == &SWPixelFormatDrawers::DrawWallMaskedColumn; + CameraLight *cameraLight = CameraLight::Instance(); + if (cameraLight->FixedLightLevel() >= 0) + { + SetBaseColormap((r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap); + SetLight(0.0f, cameraLight->FixedLightLevelShade()); + } + else if (cameraLight->FixedColormap() != nullptr) + { + SetBaseColormap(cameraLight->FixedColormap()); + SetLight(0.0f, 0); + } + else + { + SetBaseColormap(basecolormap); + } } } diff --git a/src/swrenderer/viewport/r_walldrawer.h b/src/swrenderer/viewport/r_walldrawer.h index 54bec778d..a657865c2 100644 --- a/src/swrenderer/viewport/r_walldrawer.h +++ b/src/swrenderer/viewport/r_walldrawer.h @@ -14,7 +14,7 @@ namespace swrenderer class WallDrawerArgs : public DrawerArgs { public: - void SetStyle(bool masked, bool additive, fixed_t alpha); + void SetStyle(bool masked, bool additive, fixed_t alpha, FDynamicColormap *basecolormap); void SetDest(RenderViewport *viewport, int x, int y); void SetCount(int count) { dc_count = count; } void SetTexture(const uint8_t *pixels, const uint8_t *pixels2, int height) @@ -28,8 +28,6 @@ namespace swrenderer void SetTextureVPos(fixed_t pos) { dc_texturefrac = pos; } void SetTextureVStep(fixed_t step) { dc_iscale = step; } - bool IsMaskedDrawer() const; - void DrawDepthColumn(RenderThread *thread, float idepth); void DrawColumn(RenderThread *thread); diff --git a/src/textures/multipatchtexturebuilder.cpp b/src/textures/multipatchtexturebuilder.cpp index 2ec06d0e9..7be8a69e5 100644 --- a/src/textures/multipatchtexturebuilder.cpp +++ b/src/textures/multipatchtexturebuilder.cpp @@ -797,6 +797,7 @@ void FMultipatchTextureBuilder::CheckForHacks(BuildInfo &buildinfo) buildinfo.Height == 128) { buildinfo.Height = 200; + buildinfo.tex->SetSize(buildinfo.tex->Width, 200); return; } @@ -924,6 +925,7 @@ void FMultipatchTextureBuilder::ResolveAllPatches() while (BuiltTextures.Size() > 0) { bool donesomething = false; + for (unsigned i = 0; i < BuiltTextures.Size(); i++) { auto &buildinfo = BuiltTextures[i]; diff --git a/src/textures/textures.h b/src/textures/textures.h index 934fb122f..a91be051b 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -298,7 +298,8 @@ class FTexture friend class FMultiPatchTexture; friend class FSkyBox; friend class FBrightmapTexture; - friend class FFontChar1; + friend class FFont; + friend class FSpecialFont; friend void RecordTextureColors (FTexture *pic, uint8_t *usedcolors); @@ -431,14 +432,11 @@ protected: float shaderspeed = 1.f; int shaderindex = 0; - // This is only legal for the null texture! + // This is only used for the null texture and for Heretic's skies. void SetSize(int w, int h) { - if (UseType == ETextureType::Null) - { - Width = w; - Height = h; - } + Width = w; + Height = h; } void SetSpeed(float fac) { shaderspeed = fac; } @@ -492,15 +490,6 @@ protected: FTexture (const char *name = NULL, int lumpnum = -1); - void CopyInfo(FTexture *other) - { - CopySize(other); - bNoDecals = other->bNoDecals; - Rotations = other->Rotations; - } - - - public: FTextureBuffer CreateTexBuffer(int translation, int flags = 0); bool GetTranslucency(); diff --git a/src/v_font.cpp b/src/v_font.cpp index da3335236..a7b5f74f0 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -385,6 +385,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count, { Chars[i].OriginalPic = charLumps[i]; Chars[i].TranslatedPic = new FImageTexture(new FFontChar1 (charLumps[i]->GetImage()), ""); + Chars[i].TranslatedPic->Scale = charLumps[i]->Scale; TexMan.AddTexture(Chars[i].TranslatedPic); } else Chars[i].TranslatedPic = charLumps[i]; @@ -1546,6 +1547,7 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l if (!noTranslate) { Chars[i].TranslatedPic = new FImageTexture(new FFontChar1 (charlumps[i]->GetImage()), ""); + Chars[i].TranslatedPic->Scale = charlumps[i]->Scale; TexMan.AddTexture(Chars[i].TranslatedPic); } else Chars[i].TranslatedPic = charlumps[i]; diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index e6ec4c63f..f033ac2f0 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -122,12 +122,12 @@ vec4 getTexel(vec2 st) // Vanilla Doom wall colormap equation // //=========================================================================== -float R_WallColormap(float lightnum, float z) +float R_WallColormap(float lightnum, float z, vec3 normal) { // R_ScaleFromGlobalAngle calculation float projection = 160.0; // projection depends on SCREENBLOCKS!! 160 is the fullscreen value vec2 line_v1 = pixelpos.xz; // in vanilla this is the first curline vertex - vec2 line_normal = vWorldNormal.xz; + vec2 line_normal = normal.xz; float texscale = projection * clamp(dot(normalize(uCameraPos.xz - line_v1), line_normal), 0.0, 1.0) / z; float lightz = clamp(16.0 * texscale, 0.0, 47.0); @@ -174,7 +174,8 @@ float R_DoomColormap(float light, float z) if (dot(vWorldNormal.xyz, vWorldNormal.xyz) > 0.5) { - return mix(R_WallColormap(lightnum, z), R_PlaneColormap(lightnum, z), abs(vWorldNormal.y)); + vec3 normal = normalize(vWorldNormal.xyz); + return mix(R_WallColormap(lightnum, z, normal), R_PlaneColormap(lightnum, z), abs(normal.y)); } else // vWorldNormal is not set on sprites { diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index eed1118f4..31f855258 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -625,6 +625,9 @@ class Actor : Thinker native native clearscope Actor GetPointer(int aaptr); native double BulletSlope(out FTranslatedLineTarget pLineTarget = null, int aimflags = 0); native void CheckFakeFloorTriggers (double oldz, bool oldz_has_viewheight = false); + native bool CheckFor3DFloorHit(double z, bool trigger); + native bool CheckFor3DCeilingHit(double z, bool trigger); + native int CheckMonsterUseSpecials(); native bool CheckMissileSpawn(double maxdist); native bool CheckPosition(Vector2 pos, bool actorsonly = false, FCheckPosition tm = null); @@ -680,7 +683,7 @@ class Actor : Thinker native native void FindFloorCeiling(int flags = 0); native double, double GetFriction(); native bool, Actor TestMobjZ(bool quick = false); - native bool InStateSequence(State newstate, State basestate); + native static bool InStateSequence(State newstate, State basestate); bool TryWalk () { diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 449e8aa09..466529aea 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -747,6 +747,7 @@ struct State native native int DistanceTo(state other); native bool ValidateSpriteFrame(); native TextureID, bool, Vector2 GetSpriteTexture(int rotation, int skin = 0, Vector2 scale = (0,0)); + native bool InStateSequence(State base); } struct F3DFloor native diff --git a/wadsrc/static/zscript/inventory/weapons.txt b/wadsrc/static/zscript/inventory/weapons.txt index 1c2d1d2e9..7eebdf3dc 100644 --- a/wadsrc/static/zscript/inventory/weapons.txt +++ b/wadsrc/static/zscript/inventory/weapons.txt @@ -811,24 +811,32 @@ class Weapon : StateProvider let player = Owner.player; if (SisterWeapon != NULL && bPowered_Up) { - if (GetReadyState() != SisterWeapon.GetReadyState()) + let ready = GetReadyState(); + if (ready != SisterWeapon.GetReadyState()) { if (player.PendingWeapon == NULL || player.PendingWeapon == WP_NOCHANGE) + { player.PendingWeapon = SisterWeapon; + } + player.WeaponState |= WF_REFIRESWITCHOK; } else { let psp = player.FindPSprite(PSP_WEAPON); - if (psp != null && psp.Caller == player.ReadyWeapon) + if (psp != null && psp.Caller == player.ReadyWeapon && psp.CurState.InStateSequence(ready)) { // If the weapon changes but the state does not, we have to manually change the PSprite's caller here. psp.Caller = SisterWeapon; player.ReadyWeapon = SisterWeapon; } - else + else { - // Something went wrong. Initiate a regular weapon change. - player.PendingWeapon = SisterWeapon; + if (player.PendingWeapon == NULL || player.PendingWeapon == WP_NOCHANGE) + { + // Something went wrong. Initiate a regular weapon change. + player.PendingWeapon = SisterWeapon; + } + player.WeaponState |= WF_REFIRESWITCHOK; } } }