From 96fb96617f606f5218e880a0ce609b542fa85de5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 16:32:45 +0200 Subject: [PATCH 01/70] - backend update from GZDoom. --- source/common/audio/music/music_config.cpp | 10 +- source/common/platform/posix/sdl/i_system.cpp | 5 +- .../polyrenderer/backend/poly_framebuffer.cpp | 82 ++++++++++++- .../polyrenderer/backend/poly_framebuffer.h | 116 ++++++++++++++++++ .../polyrenderer/drawers/screen_shader.cpp | 34 +++-- .../vulkan/renderer/vk_renderbuffers.cpp | 9 +- .../vulkan/renderer/vk_renderbuffers.h | 1 + .../vulkan/renderer/vk_renderpass.cpp | 5 +- .../rendering/vulkan/system/vk_builders.h | 11 +- .../rendering/vulkan/system/vk_device.cpp | 3 +- 10 files changed, 244 insertions(+), 32 deletions(-) diff --git a/source/common/audio/music/music_config.cpp b/source/common/audio/music/music_config.cpp index 12573b781..86eef267e 100644 --- a/source/common/audio/music/music_config.cpp +++ b/source/common/audio/music/music_config.cpp @@ -85,17 +85,17 @@ CUSTOM_CVAR(Bool, adl_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUA FORWARD_BOOL_CVAR(adl_fullpan); } -CUSTOM_CVAR(Int, adl_bank, 14, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Int, adl_bank, 14, CVAR_ARCHIVE | CVAR_VIRTUAL) { FORWARD_CVAR(adl_bank); } -CUSTOM_CVAR(Bool, adl_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Bool, adl_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_VIRTUAL) { FORWARD_BOOL_CVAR(adl_use_custom_bank); } -CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_VIRTUAL) { FORWARD_STRING_CVAR(adl_custom_bank); } @@ -261,12 +261,12 @@ CUSTOM_CVAR(Bool, opn_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUA FORWARD_BOOL_CVAR(opn_fullpan); } -CUSTOM_CVAR(Bool, opn_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Bool, opn_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_VIRTUAL) { FORWARD_BOOL_CVAR(opn_use_custom_bank); } -CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_VIRTUAL) { FORWARD_STRING_CVAR(opn_custom_bank); } diff --git a/source/common/platform/posix/sdl/i_system.cpp b/source/common/platform/posix/sdl/i_system.cpp index 1dc656a69..b2f0d8436 100644 --- a/source/common/platform/posix/sdl/i_system.cpp +++ b/source/common/platform/posix/sdl/i_system.cpp @@ -175,10 +175,11 @@ void I_PrintStr(const char *cp) { const char * srcp = cp; FString printData = ""; + bool terminal = isatty(STDOUT_FILENO); while (*srcp != 0) { - if (*srcp == 0x1c && con_printansi) + if (*srcp == 0x1c && con_printansi && terminal) { srcp += 1; EColorRange range = V_ParseFontColor((const uint8_t*&)srcp, CR_UNTRANSLATED, CR_YELLOW); @@ -224,7 +225,7 @@ void I_PrintStr(const char *cp) if (StartScreen) CleanProgressBar(); fputs(printData.GetChars(),stdout); - fputs("\033[0m",stdout); + if (terminal) fputs("\033[0m",stdout); if (StartScreen) RedrawProgressBar(ProgressBarCurPos,ProgressBarMaxPos); } diff --git a/source/common/rendering/polyrenderer/backend/poly_framebuffer.cpp b/source/common/rendering/polyrenderer/backend/poly_framebuffer.cpp index 7ce16369b..a71523a46 100644 --- a/source/common/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/source/common/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -152,6 +152,10 @@ void PolyFrameBuffer::FlushDrawCommands() } } +EXTERN_CVAR(Float, vid_brightness) +EXTERN_CVAR(Float, vid_contrast) +EXTERN_CVAR(Float, vid_saturation) + void PolyFrameBuffer::Update() { twoD.Reset(); @@ -177,8 +181,9 @@ void PolyFrameBuffer::Update() if (dst) { #if 1 + // [GEC] with the help of dpJudas a new system of copying and applying gamma in the video buffer auto copyqueue = std::make_shared(&mFrameMemory); - copyqueue->Push(dst, pitch / pixelsize, src, w, h, w, pixelsize); + copyqueue->Push(dst, pitch / pixelsize, src, w, h, w, vid_gamma, vid_contrast, vid_brightness, vid_saturation); DrawerThreads::Execute(copyqueue); #else for (int y = 0; y < h; y++) @@ -366,6 +371,40 @@ FTexture *PolyFrameBuffer::WipeEndScreen() TArray PolyFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) { + // [GEC] Really necessary to apply gamma, brightness, contrast and saturation for screenshot + + std::vector gammatablebuf(256); + uint8_t* gammatable = gammatablebuf.data(); + + float InvGamma = 1.0f / clamp(vid_gamma, 0.1f, 4.f); + float Brightness = clamp(vid_brightness, -0.8f, 0.8f); + float Contrast = clamp(vid_contrast, 0.1f, 3.f); + float Saturation = clamp(vid_saturation, -15.0f, 15.f); + + for (int x = 0; x < 256; x++) + { + float ramp = (float)(x / 255.f); + // Apply Contrast + // vec4 finalColor = vec4((((originalColor.rgb - vec3(0.5)) * Contrast) + vec3(0.5)), 1.0); + if(vid_contrast != 1.0f) + ramp = (((ramp - 0.5f) * Contrast) + 0.5f); + + // Apply Brightness + // vec4 finalColor = vec4(originalColor.rgb + Brightness, 1.0); + if (vid_brightness != 0.0f) + ramp += (Brightness / 2.0f); + + // Apply Gamma + // FragColor.rgb = pow(fragColor.rgb, vec3(1.0/gamma)); + if (vid_gamma != 1.0f) + ramp = pow(ramp, InvGamma); + + // Clamp ramp + ramp = clamp(ramp, 0.0f, 1.f); + + gammatable[x] = (uint8_t)(ramp * 255); + } + int w = SCREENWIDTH; int h = SCREENHEIGHT; @@ -380,9 +419,44 @@ TArray PolyFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &color_ for (int x = 0; x < w; x++) { - ScreenshotBuffer[dindex ] = pixels[sindex + 2]; - ScreenshotBuffer[dindex + 1] = pixels[sindex + 1]; - ScreenshotBuffer[dindex + 2] = pixels[sindex ]; + uint32_t red = pixels[sindex + 2]; + uint32_t green = pixels[sindex + 1]; + uint32_t blue = pixels[sindex]; + + if (vid_saturation != 1.0f) + { + float NewR = (float)(red / 255.f); + float NewG = (float)(green / 255.f); + float NewB = (float)(blue / 255.f); + + // Apply Saturation + // float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750)); + // Out = luma.xxx + Saturation.xxx * (In - luma.xxx); + //float luma = (NewR * 0.2126729f) + (NewG * 0.7151522f) + (NewB * 0.0721750f); // Rec. 709 + float luma = (NewR * 0.299f) + (NewG * 0.587f) + (NewB * 0.114f); //Rec. 601 + NewR = luma + (Saturation * (NewR - luma)); + NewG = luma + (Saturation * (NewG - luma)); + NewB = luma + (Saturation * (NewB - luma)); + + // Clamp All + NewR = clamp(NewR, 0.0f, 1.f); + NewG = clamp(NewG, 0.0f, 1.f); + NewB = clamp(NewB, 0.0f, 1.f); + + red = (uint32_t)(NewR * 255.f); + green = (uint32_t)(NewG * 255.f); + blue = (uint32_t)(NewB * 255.f); + } + + // Apply Contrast / Brightness / Gamma + red = gammatable[red]; + green = gammatable[green]; + blue = gammatable[blue]; + + ScreenshotBuffer[dindex ] = red; + ScreenshotBuffer[dindex + 1] = green; + ScreenshotBuffer[dindex + 2] = blue; + dindex += 3; sindex += 4; } diff --git a/source/common/rendering/polyrenderer/backend/poly_framebuffer.h b/source/common/rendering/polyrenderer/backend/poly_framebuffer.h index a3c4eee29..76eae0ced 100644 --- a/source/common/rendering/polyrenderer/backend/poly_framebuffer.h +++ b/source/common/rendering/polyrenderer/backend/poly_framebuffer.h @@ -96,3 +96,119 @@ private: }; inline PolyFrameBuffer *GetPolyFrameBuffer() { return static_cast(screen); } + +// [GEC] Original code of dpJudas, I add the formulas of gamma, brightness, contrast and saturation. +class CopyAndApplyGammaCommand : public DrawerCommand +{ +public: + CopyAndApplyGammaCommand(void* dest, int destpitch, const void* src, int width, int height, int srcpitch, + float gamma, float contrast, float brightness, float saturation) : dest(dest), src(src), destpitch(destpitch), width(width), height(height), srcpitch(srcpitch), + gamma(gamma), contrast(contrast), brightness(brightness), saturation(saturation) + { + } + + void Execute(DrawerThread* thread) + { + float Saturation = clamp(saturation, -15.0f, 15.f); + + std::vector gammatablebuf(256); + uint8_t* gammatable = gammatablebuf.data(); + InitGammaTable(gammatable); + + int w = width; + int start = thread->skipped_by_thread(0); + int count = thread->count_for_thread(0, height); + int sstep = thread->num_cores * srcpitch; + int dstep = thread->num_cores * destpitch; + uint32_t* d = (uint32_t*)dest + start * destpitch; + const uint32_t* s = (const uint32_t*)src + start * srcpitch; + for (int y = 0; y < count; y++) + { + for (int x = 0; x < w; x++) + { + uint32_t red = RPART(s[x]); + uint32_t green = GPART(s[x]); + uint32_t blue = BPART(s[x]); + uint32_t alpha = APART(s[x]); + + if (saturation != 1.0f) + { + float NewR = (float)(red / 255.f); + float NewG = (float)(green / 255.f); + float NewB = (float)(blue / 255.f); + + // Apply Saturation + // float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750)); + // Out = luma.xxx + Saturation.xxx * (In - luma.xxx); + //float luma = (NewR * 0.2126729f) + (NewG * 0.7151522f) + (NewB * 0.0721750f); // Rec. 709 + float luma = (NewR * 0.299f) + (NewG * 0.587f) + (NewB * 0.114f); //Rec. 601 + NewR = luma + (Saturation * (NewR - luma)); + NewG = luma + (Saturation * (NewG - luma)); + NewB = luma + (Saturation * (NewB - luma)); + + // Clamp All + NewR = clamp(NewR, 0.0f, 1.f); + NewG = clamp(NewG, 0.0f, 1.f); + NewB = clamp(NewB, 0.0f, 1.f); + + red = (uint32_t)(NewR * 255.f); + green = (uint32_t)(NewG * 255.f); + blue = (uint32_t)(NewB * 255.f); + } + + // Apply Contrast / Brightness / Gamma + red = gammatable[red]; + green = gammatable[green]; + blue = gammatable[blue]; + + d[x] = MAKEARGB(alpha, (uint8_t)red, (uint8_t)green, (uint8_t)blue); + } + d += dstep; + s += sstep; + } + } + +private: + void InitGammaTable(uint8_t *gammatable) + { + float InvGamma = 1.0f / clamp(gamma, 0.1f, 4.f); + float Brightness = clamp(brightness, -0.8f, 0.8f); + float Contrast = clamp(contrast, 0.1f, 3.f); + + for (int x = 0; x < 256; x++) + { + float ramp = (float)(x / 255.f); + + // Apply Contrast + // vec4 finalColor = vec4((((originalColor.rgb - vec3(0.5)) * Contrast) + vec3(0.5)), 1.0); + if (contrast != 1.0f) + ramp = (((ramp - 0.5f) * Contrast) + 0.5f); + + // Apply Brightness + // vec4 finalColor = vec4(originalColor.rgb + Brightness, 1.0); + if (brightness != 0.0f) + ramp += (Brightness / 2.0f); + + // Apply Gamma + // FragColor.rgb = pow(fragColor.rgb, vec3(1.0/gamma)); + if (gamma != 1.0f) + ramp = pow(ramp, InvGamma); + + // Clamp ramp + ramp = clamp(ramp, 0.0f, 1.f); + + gammatable[x] = (uint8_t)(ramp * 255); + } + } + + void* dest; + const void* src; + int destpitch; + int width; + int height; + int srcpitch; + float gamma; + float contrast; + float brightness; + float saturation; +}; diff --git a/source/common/rendering/polyrenderer/drawers/screen_shader.cpp b/source/common/rendering/polyrenderer/drawers/screen_shader.cpp index 285c97670..7e225bef1 100644 --- a/source/common/rendering/polyrenderer/drawers/screen_shader.cpp +++ b/source/common/rendering/polyrenderer/drawers/screen_shader.cpp @@ -538,12 +538,13 @@ static void MainFP(int x0, int x1, PolyTriangleThreadData* thread) // frag = frag * vColor; // frag.rgb = frag.rgb + uFogColor.rgb; - uint32_t startR = (int)((thread->mainVertexShader.Data.uObjectColor.r) * 255.0f); - uint32_t startG = (int)((thread->mainVertexShader.Data.uObjectColor.g) * 255.0f); - uint32_t startB = (int)((thread->mainVertexShader.Data.uObjectColor.b) * 255.0f); - uint32_t rangeR = (int)((thread->mainVertexShader.Data.uAddColor.r) * 255.0f) - startR; - uint32_t rangeG = (int)((thread->mainVertexShader.Data.uAddColor.g) * 255.0f) - startG; - uint32_t rangeB = (int)((thread->mainVertexShader.Data.uAddColor.b) * 255.0f) - startB; + // [GEC] I leave the default floating values. + float startR = thread->mainVertexShader.Data.uObjectColor.r; + float startG = thread->mainVertexShader.Data.uObjectColor.g; + float startB = thread->mainVertexShader.Data.uObjectColor.b; + float rangeR = thread->mainVertexShader.Data.uAddColor.r - startR; + float rangeG = thread->mainVertexShader.Data.uAddColor.g - startG; + float rangeB = thread->mainVertexShader.Data.uAddColor.b - startB; for (int x = x0; x < x1; x++) { @@ -555,15 +556,22 @@ static void MainFP(int x0, int x1, PolyTriangleThreadData* thread) uint32_t gray = (r * 77 + g * 143 + b * 37) >> 8; gray += (gray >> 7); // gray*=256/255 - r = (startR + ((gray * rangeR) >> 8)) << 1; - g = (startG + ((gray * rangeG) >> 8)) << 1; - b = (startB + ((gray * rangeB) >> 8)) << 1; + // [GEC] I use the same method as in shaders using floating values. + // This avoids errors in the invulneravility colormap in Doom and Heretic. + float fgray = (float)(gray / 255.f); + float fr = (startR + (fgray * rangeR)) * 2; + float fg = (startG + (fgray * rangeG)) * 2; + float fb = (startB + (fgray * rangeB)) * 2; - r = MIN(r, (uint32_t)255); - g = MIN(g, (uint32_t)255); - b = MIN(b, (uint32_t)255); + fr = clamp(fr, 0.0f, 1.0f); + fg = clamp(fg, 0.0f, 1.0f); + fb = clamp(fb, 0.0f, 1.0f); - fragcolor[x] = MAKEARGB(a, r, g, b); + r = (uint32_t)(fr * 255.f); + g = (uint32_t)(fg * 255.f); + b = (uint32_t)(fb * 255.f); + + fragcolor[x] = MAKEARGB(a, (uint8_t)r, (uint8_t)g, (uint8_t)b); } } else diff --git a/source/common/rendering/vulkan/renderer/vk_renderbuffers.cpp b/source/common/rendering/vulkan/renderer/vk_renderbuffers.cpp index e3217076d..34e44096d 100644 --- a/source/common/rendering/vulkan/renderer/vk_renderbuffers.cpp +++ b/source/common/rendering/vulkan/renderer/vk_renderbuffers.cpp @@ -212,13 +212,18 @@ void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlag ImageBuilder builder; builder.setSize(width, height); builder.setSamples(samples); - builder.setFormat(VK_FORMAT_A2R10G10B10_UNORM_PACK32); + builder.setFormat(SceneNormalFormat); builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + if (!builder.isFormatSupported(fb->device, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) + { + SceneNormalFormat = VK_FORMAT_R8G8B8A8_UNORM; + builder.setFormat(SceneNormalFormat); + } SceneNormal.Image = builder.create(fb->device); SceneNormal.Image->SetDebugName("VkRenderBuffers.SceneNormal"); ImageViewBuilder viewbuilder; - viewbuilder.setImage(SceneNormal.Image.get(), VK_FORMAT_A2R10G10B10_UNORM_PACK32); + viewbuilder.setImage(SceneNormal.Image.get(), SceneNormalFormat); SceneNormal.View = viewbuilder.create(fb->device); SceneNormal.View->SetDebugName("VkRenderBuffers.SceneNormalView"); } diff --git a/source/common/rendering/vulkan/renderer/vk_renderbuffers.h b/source/common/rendering/vulkan/renderer/vk_renderbuffers.h index b1df96b02..92ad9c5be 100644 --- a/source/common/rendering/vulkan/renderer/vk_renderbuffers.h +++ b/source/common/rendering/vulkan/renderer/vk_renderbuffers.h @@ -24,6 +24,7 @@ public: VkTextureImage SceneFog; VkFormat SceneDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT; + VkFormat SceneNormalFormat = VK_FORMAT_A2R10G10B10_UNORM_PACK32; static const int NumPipelineImages = 2; VkTextureImage PipelineImage[NumPipelineImages]; diff --git a/source/common/rendering/vulkan/renderer/vk_renderpass.cpp b/source/common/rendering/vulkan/renderer/vk_renderpass.cpp index 2e0973c08..44c325ecf 100644 --- a/source/common/rendering/vulkan/renderer/vk_renderpass.cpp +++ b/source/common/rendering/vulkan/renderer/vk_renderpass.cpp @@ -281,7 +281,7 @@ std::unique_ptr VkRenderPassSetup::CreateRenderPass(int clearT { auto buffers = GetVulkanFrameBuffer()->GetBuffers(); - VkFormat drawBufferFormats[] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_A2R10G10B10_UNORM_PACK32 }; + VkFormat drawBufferFormats[] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, buffers->SceneNormalFormat }; RenderPassBuilder builder; @@ -420,7 +420,8 @@ std::unique_ptr VkRenderPassSetup::CreatePipeline(const VkPipeli builder.setTopology(vktopology[key.DrawType]); builder.setDepthStencilEnable(key.DepthTest, key.DepthWrite, key.StencilTest); builder.setDepthFunc(depthfunc2vk[key.DepthFunc]); - builder.setDepthClampEnable(key.DepthClamp); + if (fb->device->UsedDeviceFeatures.depthClamp) + builder.setDepthClampEnable(key.DepthClamp); builder.setDepthBias(key.DepthBias, 0.0f, 0.0f, 0.0f); // Note: CCW and CW is intentionally swapped here because the vulkan and opengl coordinate systems differ. diff --git a/source/common/rendering/vulkan/system/vk_builders.h b/source/common/rendering/vulkan/system/vk_builders.h index 5f0e3c0fc..343313bbd 100644 --- a/source/common/rendering/vulkan/system/vk_builders.h +++ b/source/common/rendering/vulkan/system/vk_builders.h @@ -45,7 +45,7 @@ public: void setMemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits = 0); void setLinearTiling(); - bool isFormatSupported(VulkanDevice *device); + bool isFormatSupported(VulkanDevice *device, VkFormatFeatureFlags bufferFeatures = 0); std::unique_ptr create(VulkanDevice *device, VkDeviceSize* allocatedBytes = nullptr); std::unique_ptr tryCreate(VulkanDevice *device); @@ -410,7 +410,7 @@ inline void ImageBuilder::setMemoryType(VkMemoryPropertyFlags requiredFlags, VkM allocInfo.memoryTypeBits = memoryTypeBits; } -inline bool ImageBuilder::isFormatSupported(VulkanDevice *device) +inline bool ImageBuilder::isFormatSupported(VulkanDevice *device, VkFormatFeatureFlags bufferFeatures) { VkImageFormatProperties properties = { }; VkResult result = vkGetPhysicalDeviceImageFormatProperties(device->PhysicalDevice.Device, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &properties); @@ -421,6 +421,13 @@ inline bool ImageBuilder::isFormatSupported(VulkanDevice *device) if (imageInfo.mipLevels > properties.maxMipLevels) return false; if (imageInfo.arrayLayers > properties.maxArrayLayers) return false; if ((imageInfo.samples & properties.sampleCounts) != imageInfo.samples) return false; + if (bufferFeatures != 0) + { + VkFormatProperties formatProperties = { }; + vkGetPhysicalDeviceFormatProperties(device->PhysicalDevice.Device, imageInfo.format, &formatProperties); + if ((formatProperties.bufferFeatures & bufferFeatures) != bufferFeatures) + return false; + } return true; } diff --git a/source/common/rendering/vulkan/system/vk_device.cpp b/source/common/rendering/vulkan/system/vk_device.cpp index 8fc6e8949..2e7ca9aad 100644 --- a/source/common/rendering/vulkan/system/vk_device.cpp +++ b/source/common/rendering/vulkan/system/vk_device.cpp @@ -108,8 +108,7 @@ bool VulkanDevice::CheckRequiredFeatures(const VkPhysicalDeviceFeatures &f) { return f.samplerAnisotropy == VK_TRUE && - f.fragmentStoresAndAtomics == VK_TRUE && - f.depthClamp == VK_TRUE; + f.fragmentStoresAndAtomics == VK_TRUE; } void VulkanDevice::SelectPhysicalDevice() From f2dd4ceaabd65df5a823a0bde76095ad08c47143 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 16:17:13 +0200 Subject: [PATCH 02/70] - always ensure that the global index buffer is not empty. This needs to be valid for Vulkan, even if it isn't used. --- source/common/rendering/hwrenderer/data/flatvertices.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/common/rendering/hwrenderer/data/flatvertices.cpp b/source/common/rendering/hwrenderer/data/flatvertices.cpp index 47ae19ec3..5bc37bcb7 100644 --- a/source/common/rendering/hwrenderer/data/flatvertices.cpp +++ b/source/common/rendering/hwrenderer/data/flatvertices.cpp @@ -80,6 +80,8 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height) mVertexBuffer = screen->CreateVertexBuffer(); mIndexBuffer = screen->CreateIndexBuffer(); + int data[4] = {}; + mIndexBuffer->SetData(4, data); // On Vulkan this may not be empty, so set some dummy defaults to avoid crashes. unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex); mVertexBuffer->SetData(bytesize, nullptr, false); From 0017b5d9c5d00f4546017e829250251ff2194a25 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 17:58:59 +0200 Subject: [PATCH 03/70] - pad out the StreamData buffer to 16 bytes and avoid any form of conditional compilation here. Vulkan does not manage to get the shader properly compiled without this. --- source/common/rendering/hwrenderer/data/hw_renderstate.h | 9 ++++----- source/common/rendering/vulkan/shaders/vk_shader.cpp | 5 ++--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/source/common/rendering/hwrenderer/data/hw_renderstate.h b/source/common/rendering/hwrenderer/data/hw_renderstate.h index 9cf1015d2..54aab25f8 100644 --- a/source/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/source/common/rendering/hwrenderer/data/hw_renderstate.h @@ -200,9 +200,8 @@ struct StreamData FVector4 uSplitBottomPlane; FVector4 uDetailParms; -#ifdef NPOT_EMULATION - FVector2 uNpotEmulation; -#endif + FVector4 uNpotEmulation; + FVector4 padding1, padding2, padding3; }; class FRenderState @@ -295,7 +294,7 @@ public: mStreamData.uDynLightColor = { 0.0f, 0.0f, 0.0f, 1.0f }; mStreamData.uDetailParms = { 0.0f, 0.0f, 0.0f, 0.0f }; #ifdef NPOT_EMULATION - mStreamData.uNpotEmulation = { 0,0 }; + mStreamData.uNpotEmulation = { 0,0,0,0 }; #endif mModelMatrix.loadIdentity(); mTextureMatrix.loadIdentity(); @@ -490,7 +489,7 @@ public: void SetNpotEmulation(float factor, float offset) { #ifdef NPOT_EMULATION - mStreamData.uNpotEmulation = { offset, factor }; + mStreamData.uNpotEmulation = { offset, factor, 0, 0 }; #endif } diff --git a/source/common/rendering/vulkan/shaders/vk_shader.cpp b/source/common/rendering/vulkan/shaders/vk_shader.cpp index 0456061fb..acb15dd47 100644 --- a/source/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/source/common/rendering/vulkan/shaders/vk_shader.cpp @@ -163,9 +163,8 @@ static const char *shaderBindings = R"( vec4 uSplitBottomPlane; vec4 uDetailParms; - #ifdef NPOT_EMULATION - vec2 uNpotEmulation; - #endif + vec4 uNpotEmulation; + vec4 padding1, padding2, padding3; }; layout(set = 0, binding = 3, std140) uniform StreamUBO { From e30dc82676159d66c18317436ed14915e2a852fb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 13:55:36 +0200 Subject: [PATCH 04/70] - Cleanup of the voxel code. * moving polymost_voxdraw into polymost.cpp. * consolidated all remaining voxel code in hw_voxels.cpp. All original Build voxel code is completely gone now, except for polymost_voxdraw, so this got moved out of the build/ folder. * integrate Blood's voxel init code into the main function. * some further cleanup was allowed as a result of this, so engineInit is gone now because these parts can now be done outside the games' app_init functions. --- source/CMakeLists.txt | 2 +- source/build/include/build.h | 24 +- source/build/include/mdsprite.h | 24 -- source/build/include/polymost.h | 1 - source/build/src/defs.cpp | 9 +- source/build/src/engine.cpp | 115 +-------- source/build/src/mdsprite.cpp | 7 + source/build/src/polymost.cpp | 171 ++++++++++++- source/build/src/voxmodel.cpp | 230 ------------------ source/core/gamecontrol.cpp | 40 ++- source/core/gamecontrol.h | 1 - source/core/gamefuncs.cpp | 22 -- source/core/gamefuncs.h | 1 - source/core/rendering/hw_voxels.cpp | 114 +++++++++ source/core/rendering/hw_voxels.h | 24 ++ .../core/rendering/scene/hw_bunchdrawer.cpp | 1 + source/core/rendering/scene/hw_drawinfo.cpp | 5 +- source/core/rendering/scene/hw_drawstructs.h | 1 + source/core/rendering/scene/hw_sprites.cpp | 3 +- source/core/savegamehelp.cpp | 1 - source/core/textures/buildtiles.cpp | 3 +- source/games/blood/src/animatesprite.cpp | 1 + source/games/blood/src/blood.cpp | 3 - source/games/blood/src/misc.h | 1 - source/games/blood/src/tile.cpp | 26 -- source/games/duke/src/game.cpp | 6 - source/games/exhumed/src/exhumed.cpp | 6 - source/games/sw/src/game.cpp | 3 - source/games/sw/src/scrip2.cpp | 3 +- 29 files changed, 362 insertions(+), 486 deletions(-) delete mode 100644 source/build/src/voxmodel.cpp create mode 100644 source/core/rendering/hw_voxels.cpp create mode 100644 source/core/rendering/hw_voxels.h diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index f5149b96e..6ca5e7e13 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1033,7 +1033,6 @@ set (PCH_SOURCES build/src/engine.cpp build/src/mdsprite.cpp build/src/polymost.cpp - build/src/voxmodel.cpp core/movie/playmve.cpp core/automap.cpp @@ -1081,6 +1080,7 @@ set (PCH_SOURCES core/rendering/hw_entrypoint.cpp core/rendering/hw_models.cpp + core/rendering/hw_voxels.cpp core/rendering/scene/hw_clipper.cpp core/rendering/scene/hw_walls.cpp core/rendering/scene/hw_flats.cpp diff --git a/source/build/include/build.h b/source/build/include/build.h index 192b1346d..9421b59bd 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -198,7 +198,7 @@ enum { PALETTE_TRANSLUC = 1<<2, }; -EXTERN int32_t g_visibility, parallaxvisibility; +EXTERN int32_t g_visibility; // blendtable[1] to blendtable[numalphatabs] are considered to be // alpha-blending tables: @@ -267,12 +267,6 @@ extern FixedBitArray gotsector; extern uint32_t drawlinepat; -extern int32_t novoxmips; - -extern int16_t tiletovox[MAXTILES]; -extern int32_t voxscale[MAXVOXELS]; -extern char g_haveVoxels; - extern uint8_t globalr, globalg, globalb; enum { @@ -360,10 +354,6 @@ void engineLoadBoard(const char *filename, int flags, vec3_t *dapos, int16_t *da void loadMapBackup(const char* filename); void G_LoadMapHack(const char* filename, const unsigned char*); -int32_t qloadkvx(int32_t voxindex, const char *filename); -void vox_undefine(int32_t const); -void vox_deinit(); - void videoSetCorrectedAspect(); void videoSetViewableArea(int32_t x1, int32_t y1, int32_t x2, int32_t y2); void renderSetAspect(int32_t daxrange, int32_t daaspect); @@ -596,7 +586,6 @@ int32_t md_setmisc(int32_t modelid, float scale, int32_t shadeoff, float zadd, f EXTERN int32_t nextvoxid; EXTERN int8_t voxreserve[(MAXVOXELS+7)>>3]; -EXTERN int8_t voxrotate[(MAXVOXELS+7)>>3]; #ifdef USE_OPENGL // TODO: dynamically allocate this @@ -626,13 +615,7 @@ inline int32_t md_tilehasmodel(int32_t const tilenume, int32_t const pal) } #endif // defined USE_OPENGL -inline int tilehasmodelorvoxel(int const tilenume, int pal) -{ - UNREFERENCED_PARAMETER(pal); - return - (mdinited && hw_models && tile2model[Ptile2tile(tilenume, pal)].modelid != -1) || - (r_voxels && tiletovox[tilenume] != -1); -} +int tilehasmodelorvoxel(int const tilenume, int pal); int32_t md_defineframe(int32_t modelid, const char *framename, int32_t tilenume, int32_t skinnum, float smoothduration, int32_t pal); @@ -733,9 +716,6 @@ extern int32_t(*insertsprite_replace)(int16_t sectnum, int16_t statnum); extern int32_t(*deletesprite_replace)(int16_t spritenum); extern int32_t(*changespritesect_replace)(int16_t spritenum, int16_t newsectnum); extern int32_t(*changespritestat_replace)(int16_t spritenum, int16_t newstatnum); -#ifdef USE_OPENGL -extern void(*PolymostProcessVoxels_Callback)(void); -#endif // Masking these into the object index to keep it in 16 bit was probably the single most dumbest and pointless thing Build ever did. // Gonna be fun to globally replace these to finally lift the limit this imposes on map size. diff --git a/source/build/include/mdsprite.h b/source/build/include/mdsprite.h index fd27cf90d..f2cfa4415 100644 --- a/source/build/include/mdsprite.h +++ b/source/build/include/mdsprite.h @@ -177,25 +177,6 @@ struct md3model_t : public idmodel_t */ }; -#define VOXBORDWIDTH 1 //use 0 to save memory, but has texture artifacts; 1 looks better... -#define VOXUSECHAR 0 - -#if (VOXUSECHAR != 0) -typedef struct { uint8_t x, y, z, u, v; } vert_t; -#else -typedef struct { uint16_t x, y, z, u, v; } vert_t; -#endif - -typedef struct { vert_t v[4]; } voxrect_t; - -struct voxmodel_t : public mdmodel_t -{ - FVoxelModel* model = nullptr; - vec3_t siz; - vec3f_t piv; - int32_t is8bit; -}; - EXTERN mdmodel_t **models; FGameTexture* mdloadskin(idmodel_t* m, int32_t number, int32_t pal, int32_t surf, bool* exact); @@ -206,11 +187,6 @@ EXTERN void md3_vox_calcmat_common(tspriteptr_t tspr, const vec3f_t *a0, float f EXTERN int32_t mdpause; EXTERN int32_t nextmodelid; -EXTERN voxmodel_t *voxmodels[MAXVOXELS]; - -void voxfree(voxmodel_t *m); -voxmodel_t *voxload(int lumpnum); -int32_t polymost_voxdraw(voxmodel_t *m, tspriteptr_t const tspr, bool rotate); #endif // defined USE_OPENGL diff --git a/source/build/include/polymost.h b/source/build/include/polymost.h index 2bbdbb637..e1e9a15f3 100644 --- a/source/build/include/polymost.h +++ b/source/build/include/polymost.h @@ -32,7 +32,6 @@ void polymost_deletesprite(int num); int32_t polymost_maskWallHasTranslucency(walltype const * const wall); int32_t polymost_spriteHasTranslucency(spritetype const * const tspr); -int32_t polymost_spriteIsModelOrVoxel(spritetype const * const tspr); void polymost_glreset(void); void polymost_scansector(int32_t sectnum); diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 0ce87e508..cf253152e 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -17,6 +17,7 @@ #include "gamecontrol.h" #include "palettecontainer.h" #include "mapinfo.h" +#include "hw_voxels.h" int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor, uint8_t flags); int tileSetSkybox(int picnum, int palnum, const char** facenames, int flags); @@ -1117,7 +1118,7 @@ static int32_t defsparser(scriptfile *script) break; } - if (qloadkvx(nextvoxid, fn)) + if (voxDefine(nextvoxid, fn)) { Printf("Failure loading voxel file \"%s\"\n",fn.GetChars()); break; @@ -1588,7 +1589,7 @@ static int32_t defsparser(scriptfile *script) break; } - if (qloadkvx(nextvoxid, fn)) + if (voxDefine(nextvoxid, fn)) { voxelpos.Message(MSG_ERROR, "Failure loading voxel file \"%s\"",fn.GetChars()); break; @@ -1629,14 +1630,14 @@ static int32_t defsparser(scriptfile *script) { double scale=1.0; scriptfile_getdouble(script,&scale); - voxscale[lastvoxid] = (int32_t)(65536*scale); + voxscale[lastvoxid] = (float)scale; if (voxmodels[lastvoxid]) voxmodels[lastvoxid]->scale = scale; break; } case T_ROTATE: - voxrotate[lastvoxid>>3] |= (1 << (lastvoxid&7)); + voxrotate.Set(lastvoxid); break; } } diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index c0a221a04..a74aa8737 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -32,6 +32,7 @@ #include "gamecontrol.h" #include "render.h" #include "gamefuncs.h" +#include "hw_voxels.h" #ifdef USE_OPENGL # include "mdsprite.h" @@ -53,18 +54,6 @@ uint8_t globalr = 255, globalg = 255, globalb = 255; int16_t pskybits_override = -1; -// This was on the cache but is permanently allocated, so put it into something static. This needs some rethinking anyway -static TArray> voxelmemory; - -int16_t tiletovox[MAXTILES]; -int voxlumps[MAXVOXELS]; -char g_haveVoxels; -//#define kloadvoxel loadvoxel - -int32_t novoxmips = 1; - -int32_t voxscale[MAXVOXELS]; - static int32_t beforedrawrooms = 1; int32_t globalflags; @@ -151,7 +140,6 @@ fixed_t qglobalang; int32_t globalpal, globalfloorpal, cosglobalang, singlobalang; int32_t cosviewingrangeglobalang, sinviewingrangeglobalang; -int32_t xyaspect; int32_t viewingrangerecip; static int32_t globalxpanning, globalypanning; @@ -671,26 +659,8 @@ int32_t enginePreInit(void) // int32_t engineInit(void) { - if (engineLoadTables()) - return 1; - - xyaspect = -1; - - voxelmemory.Reset(); - - for (int i=0; iloadPalette(); - if (!mdinited) mdinit(); return 0; } @@ -750,80 +720,6 @@ void initspritelists(void) Numsprites = 0; } - - -// -// qloadkvx -// - - - -int32_t qloadkvx(int32_t voxindex, const char *filename) -{ - if ((unsigned)voxindex >= MAXVOXELS) - return -1; - - auto fil = fileSystem.OpenFileReader(filename); - if (!fil.isOpen()) - return -1; - - int32_t lengcnt = 0; - const int32_t lengtot = fil.GetLength(); - - for (bssize_t i=0; i= lengtot-768) - break; - } - - - if (voxmodels[voxindex]) - { - voxfree(voxmodels[voxindex]); - voxmodels[voxindex] = NULL; - } - - voxlumps[voxindex] = fileSystem.FindFile(filename); - - g_haveVoxels = 1; - - return 0; -} - -void vox_undefine(int32_t const tile) -{ - int voxindex = tiletovox[tile]; - if (voxindex < 0) - return; - - if (voxmodels[voxindex]) - { - voxfree(voxmodels[voxindex]); - voxmodels[voxindex] = NULL; - } - - voxscale[voxindex] = 65536; - voxrotate[voxindex>>3] &= ~(1 << (voxindex&7)); - tiletovox[tile] = -1; - - // TODO: nextvoxid -} - -void vox_deinit() -{ - for (auto &vox : voxmodels) - { - voxfree(vox); - vox = nullptr; - } -} - // // inside // @@ -1865,3 +1761,10 @@ void alignflorslope(int16_t dasect, int32_t x, int32_t y, int32_t z) } +int tilehasmodelorvoxel(int const tilenume, int pal) +{ + UNREFERENCED_PARAMETER(pal); + return + (mdinited && hw_models && tile2model[Ptile2tile(tilenume, pal)].modelid != -1) || + (r_voxels && tiletovox[tilenume] != -1); +} diff --git a/source/build/src/mdsprite.cpp b/source/build/src/mdsprite.cpp index a637674f9..422e40605 100644 --- a/source/build/src/mdsprite.cpp +++ b/source/build/src/mdsprite.cpp @@ -16,6 +16,7 @@ #include "texturemanager.h" #include "hw_renderstate.h" #include "printf.h" +#include "hw_voxels.h" #include "../../glbackend/glbackend.h" static int32_t curextra=MAXTILES; @@ -23,6 +24,7 @@ static int32_t curextra=MAXTILES; #define MIN_CACHETIME_PRINT 10 using namespace Polymost; +int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr, bool rotate); static int32_t addtileP(int32_t model,int32_t tile,int32_t pallet) { @@ -1538,6 +1540,11 @@ int32_t polymost_mddraw(tspriteptr_t tspr) return 0; } +void voxfree(voxmodel_t* m) +{ + if (m) delete m; +} + static void mdfree(mdmodel_t *vm) { if (vm->mdnum == 1) { voxfree((voxmodel_t *)vm); return; } diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index f6f75b98c..31a4198e4 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -26,6 +26,7 @@ Ken Silverman's official web site: http://www.advsys.net/ken #include "hw_drawinfo.h" #include "gamestruct.h" #include "gamestruct.h" +#include "hw_voxels.h" typedef struct { @@ -35,11 +36,13 @@ typedef struct { } vec3d_t; static_assert(sizeof(vec3d_t) == sizeof(double) * 3); +int32_t xyaspect = -1; int skiptile = -1; FGameTexture* GetSkyTexture(int basetile, int lognumtiles, const int16_t* tilemap, int remap = 0); +int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr, bool rotate); int checkTranslucentReplacement(FTextureID picnum, int pal); @@ -2750,14 +2753,14 @@ void polymost_drawsprite(int32_t snum) if ((tspr->cstat & 48) != 48 && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]]) { int num = tiletovox[tspr->picnum]; - if (polymost_voxdraw(voxmodels[num], tspr, voxrotate[num>>3] & (1<<(num&7)))) return; + if (polymost_voxdraw(voxmodels[num], tspr, voxrotate[num])) return; break; // else, render as flat sprite } if ((tspr->cstat & 48) == 48 && tspr->picnum < MAXVOXELS && voxmodels[tspr->picnum]) { int num = tspr->picnum; - polymost_voxdraw(voxmodels[tspr->picnum], tspr, voxrotate[num >> 3] & (1 << (num & 7))); + polymost_voxdraw(voxmodels[tspr->picnum], tspr, voxrotate[num]); return; } } @@ -3494,6 +3497,23 @@ static void sortsprites(int const start, int const end) } } +static bool spriteIsModelOrVoxel(const spritetype* tspr) +{ + if ((unsigned)tspr->owner < MAXSPRITES && spriteext[tspr->owner].flags & SPREXT_NOTMD) + return false; + + if (hw_models) + { + auto& mdinfo = tile2model[Ptile2tile(tspr->picnum, tspr->pal)]; + if (mdinfo.modelid >= 0 && mdinfo.framenum >= 0) return true; + } + + auto slabalign = (tspr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_SLAB; + if (r_voxels && !slabalign && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]]) return true; + return (slabalign && voxmodels[tspr->picnum]); +} + + // // drawmasks // @@ -3817,4 +3837,151 @@ void renderSetAspect(int32_t daxrange, int32_t daaspect) xdimscale = Scale(320, xyaspect, xdimen); } +//Draw voxel model as perfect cubes +int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr, bool rotate) +{ + float f, g, k0, zoff; + + if ((intptr_t)m == (intptr_t)(-1)) // hackhackhack + return 0; + + if ((tspr->cstat & 48) == 32) + return 0; + + if ((tspr->cstat & CSTAT_SPRITE_MDLROTATE) || rotate) + { + int myclock = (PlayClock << 3) + MulScale(4 << 3, pm_smoothratio, 16); + tspr->ang = (tspr->ang + myclock) & 2047; // will be applied in md3_vox_calcmat_common. + } + + + vec3f_t m0 = { m->scale, m->scale, m->scale }; + vec3f_t a0 = { 0, 0, m->zadd * m->scale }; + + k0 = m->bscale / 64.f; + f = (float)tspr->xrepeat * (256.f / 320.f) * k0; + if ((sprite[tspr->owner].cstat & 48) == 16) + { + f *= 1.25f; + a0.y -= tspr->xoffset * bcosf(spriteext[tspr->owner].angoff, -20); + a0.x += tspr->xoffset * bsinf(spriteext[tspr->owner].angoff, -20); + } + + if (globalorientation & 8) { m0.z = -m0.z; a0.z = -a0.z; } //y-flipping + if (globalorientation & 4) { m0.x = -m0.x; a0.x = -a0.x; a0.y = -a0.y; } //x-flipping + + m0.x *= f; a0.x *= f; f = -f; + m0.y *= f; a0.y *= f; + f = (float)tspr->yrepeat * k0; + m0.z *= f; a0.z *= f; + + k0 = (float)(tspr->z + spriteext[tspr->owner].position_offset.z); + f = ((globalorientation & 8) && (sprite[tspr->owner].cstat & 48) != 0) ? -4.f : 4.f; + k0 -= (tspr->yoffset * tspr->yrepeat) * f * m->bscale; + zoff = m->siz.z * .5f; + if (!(tspr->cstat & 128)) + zoff += m->piv.z; + else if ((tspr->cstat & 48) != 48) + { + zoff += m->piv.z; + zoff -= m->siz.z * .5f; + } + if (globalorientation & 8) zoff = m->siz.z - zoff; + + f = (65536.f * 512.f) / ((float)xdimen * viewingrange); + g = 32.f / ((float)xdimen * Polymost::gxyaspect); + + int const shadowHack = !!(tspr->clipdist & TSPR_FLAGS_MDHACK); + + m0.y *= f; a0.y = (((float)(tspr->x + spriteext[tspr->owner].position_offset.x - globalposx)) * (1.f / 1024.f) + a0.y) * f; + m0.x *= -f; a0.x = (((float)(tspr->y + spriteext[tspr->owner].position_offset.y - globalposy)) * -(1.f / 1024.f) + a0.x) * -f; + m0.z *= g; a0.z = (((float)(k0 - globalposz - shadowHack)) * -(1.f / 16384.f) + a0.z) * g; + + float mat[16]; + md3_vox_calcmat_common(tspr, &a0, f, mat); + + //Mirrors + if (Polymost::grhalfxdown10x < 0) + { + mat[0] = -mat[0]; + mat[4] = -mat[4]; + mat[8] = -mat[8]; + mat[12] = -mat[12]; + } + + if (shadowHack) + { + GLInterface.SetDepthFunc(DF_LEqual); + } + + + int winding = ((Polymost::grhalfxdown10x >= 0) ^ ((globalorientation & 8) != 0) ^ ((globalorientation & 4) != 0)) ? Winding_CW : Winding_CCW; + GLInterface.SetCull(Cull_Back, winding); + + float pc[4]; + + pc[0] = pc[1] = pc[2] = 1.f; + + + if (!shadowHack) + { + pc[3] = (tspr->cstat & 2) ? glblend[tspr->blend].def[!!(tspr->cstat & 512)].alpha : 1.0f; + pc[3] *= 1.0f - spriteext[tspr->owner].alpha; + + SetRenderStyleFromBlend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512)); + + if (!(tspr->cstat & 2) || spriteext[tspr->owner].alpha > 0.f || pc[3] < 1.0f) + GLInterface.EnableBlend(true); // else GLInterface.EnableBlend(false); + } + else pc[3] = 1.f; + GLInterface.SetShade(std::max(0, globalshade), numshades); + //------------ + + //transform to Build coords + float omat[16]; + memcpy(omat, mat, sizeof(omat)); + + f = 1.f / 64.f; + g = m0.x * f; mat[0] *= g; mat[1] *= g; mat[2] *= g; + g = m0.y * f; mat[4] = omat[8] * g; mat[5] = omat[9] * g; mat[6] = omat[10] * g; + g = -m0.z * f; mat[8] = omat[4] * g; mat[9] = omat[5] * g; mat[10] = omat[6] * g; + // + mat[12] -= (m->piv.x * mat[0] + m->piv.y * mat[4] + zoff * mat[8]); + mat[13] -= (m->piv.x * mat[1] + m->piv.y * mat[5] + zoff * mat[9]); + mat[14] -= (m->piv.x * mat[2] + m->piv.y * mat[6] + zoff * mat[10]); + // + //Let OpenGL (and perhaps hardware :) handle the matrix rotation + mat[3] = mat[7] = mat[11] = 0.f; mat[15] = 1.f; + + for (int i = 0; i < 15; i++) mat[i] *= 1024.f; + + // Adjust to backend coordinate system being used by the vertex buffer. + for (int i = 4; i < 8; i++) + { + float f = mat[i]; + mat[i] = -mat[i + 4]; + mat[i + 4] = -f; + } + + GLInterface.SetMatrix(Matrix_Model, mat); + + int palId = TRANSLATION(Translation_Remap + curbasepal, globalpal); + GLInterface.SetPalswap(globalpal); + GLInterface.SetFade(sector[tspr->sectnum].floorpal); + + auto tex = TexMan.GetGameTexture(m->model->GetPaletteTexture()); + GLInterface.SetTexture(tex, TRANSLATION(Translation_Remap + curbasepal, globalpal), CLAMP_NOFILTER_XY, true); + GLInterface.SetModel(m->model, 0, 0, 0); + GLInterface.Draw(DT_Triangles, 0, 0); + GLInterface.SetModel(nullptr, 0, 0, 0); + GLInterface.SetCull(Cull_None); + + if (shadowHack) + { + GLInterface.SetDepthFunc(DF_Less); + } + GLInterface.SetIdentityMatrix(Matrix_Model); + return 1; +} + diff --git a/source/build/src/voxmodel.cpp b/source/build/src/voxmodel.cpp deleted file mode 100644 index 6a6e8d134..000000000 --- a/source/build/src/voxmodel.cpp +++ /dev/null @@ -1,230 +0,0 @@ -//--------------------------------------- VOX LIBRARY BEGINS --------------------------------------- - -#ifdef USE_OPENGL - -#include "compat.h" -#include "build.h" -#include "engine_priv.h" -#include "polymost.h" -#include "mdsprite.h" -#include "v_video.h" -#include "flatvertices.h" -#include "hw_renderstate.h" -#include "texturemanager.h" -#include "voxels.h" -#include "gamecontrol.h" -#include "hw_models.h" -#include "printf.h" - -#include "palette.h" -#include "../../glbackend/glbackend.h" - -using namespace Polymost; - -void voxfree(voxmodel_t *m) -{ - if (m) delete m; -} - -voxmodel_t *voxload(int lumpnum) -{ - FVoxel* voxel = R_LoadKVX(lumpnum); - if (voxel != nullptr) - { - voxmodel_t* vm = new voxmodel_t; - *vm = {}; - auto pivot = voxel->Mips[0].Pivot; - vm->mdnum = 1; //VOXel model id - vm->scale = vm->bscale = 1.f; - vm->piv.x = float(pivot.X); - vm->piv.y = float(pivot.Y); - vm->piv.z = float(pivot.Z); - vm->siz.x = voxel->Mips[0].SizeX; - vm->siz.y = voxel->Mips[0].SizeY; - vm->siz.z = voxel->Mips[0].SizeZ; - vm->is8bit = true; - voxel->Mips[0].Pivot.Zero(); // Needs to be taken out of the voxel data because it gets baked into the vertex buffer which we cannot use here. - vm->model = new FVoxelModel(voxel, true); - return vm; - } - return nullptr; -} - -//Draw voxel model as perfect cubes -int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr, bool rotate) -{ - float f, g, k0, zoff; - - if ((intptr_t)m == (intptr_t)(-1)) // hackhackhack - return 0; - - if ((tspr->cstat & 48) == 32) - return 0; - - if ((tspr->cstat & CSTAT_SPRITE_MDLROTATE) || rotate) - { - int myclock = (PlayClock << 3) + MulScale(4 << 3, pm_smoothratio, 16); - tspr->ang = (tspr->ang + myclock) & 2047; // will be applied in md3_vox_calcmat_common. - } - - - vec3f_t m0 = { m->scale, m->scale, m->scale }; - vec3f_t a0 = { 0, 0, m->zadd*m->scale }; - - k0 = m->bscale / 64.f; - f = (float) tspr->xrepeat * (256.f/320.f) * k0; - if ((sprite[tspr->owner].cstat&48)==16) - { - f *= 1.25f; - a0.y -= tspr->xoffset * bcosf(spriteext[tspr->owner].angoff, -20); - a0.x += tspr->xoffset * bsinf(spriteext[tspr->owner].angoff, -20); - } - - if (globalorientation&8) { m0.z = -m0.z; a0.z = -a0.z; } //y-flipping - if (globalorientation&4) { m0.x = -m0.x; a0.x = -a0.x; a0.y = -a0.y; } //x-flipping - - m0.x *= f; a0.x *= f; f = -f; - m0.y *= f; a0.y *= f; - f = (float) tspr->yrepeat * k0; - m0.z *= f; a0.z *= f; - - k0 = (float) (tspr->z+spriteext[tspr->owner].position_offset.z); - f = ((globalorientation&8) && (sprite[tspr->owner].cstat&48)!=0) ? -4.f : 4.f; - k0 -= (tspr->yoffset*tspr->yrepeat)*f*m->bscale; - zoff = m->siz.z*.5f; - if (!(tspr->cstat&128)) - zoff += m->piv.z; - else if ((tspr->cstat&48) != 48) - { - zoff += m->piv.z; - zoff -= m->siz.z*.5f; - } - if (globalorientation&8) zoff = m->siz.z-zoff; - - f = (65536.f*512.f) / ((float)xdimen*viewingrange); - g = 32.f / ((float)xdimen*gxyaspect); - - int const shadowHack = !!(tspr->clipdist & TSPR_FLAGS_MDHACK); - - m0.y *= f; a0.y = (((float)(tspr->x+spriteext[tspr->owner].position_offset.x-globalposx)) * (1.f/1024.f) + a0.y) * f; - m0.x *=-f; a0.x = (((float)(tspr->y+spriteext[tspr->owner].position_offset.y-globalposy)) * -(1.f/1024.f) + a0.x) * -f; - m0.z *= g; a0.z = (((float)(k0 -globalposz - shadowHack)) * -(1.f/16384.f) + a0.z) * g; - - float mat[16]; - md3_vox_calcmat_common(tspr, &a0, f, mat); - - //Mirrors - if (grhalfxdown10x < 0) - { - mat[0] = -mat[0]; - mat[4] = -mat[4]; - mat[8] = -mat[8]; - mat[12] = -mat[12]; - } - - if (shadowHack) - { - GLInterface.SetDepthFunc(DF_LEqual); - } - - - int winding = ((grhalfxdown10x >= 0) ^ ((globalorientation & 8) != 0) ^ ((globalorientation & 4) != 0)) ? Winding_CW : Winding_CCW; - GLInterface.SetCull(Cull_Back, winding); - - float pc[4]; - - pc[0] = pc[1] = pc[2] = 1.f; - - - if (!shadowHack) - { - pc[3] = (tspr->cstat & 2) ? glblend[tspr->blend].def[!!(tspr->cstat & 512)].alpha : 1.0f; - pc[3] *= 1.0f - spriteext[tspr->owner].alpha; - - SetRenderStyleFromBlend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512)); - - if (!(tspr->cstat & 2) || spriteext[tspr->owner].alpha > 0.f || pc[3] < 1.0f) - GLInterface.EnableBlend(true); // else GLInterface.EnableBlend(false); - } - else pc[3] = 1.f; - GLInterface.SetShade(std::max(0, globalshade), numshades); - //------------ - - //transform to Build coords - float omat[16]; - memcpy(omat, mat, sizeof(omat)); - - f = 1.f/64.f; - g = m0.x*f; mat[0] *= g; mat[1] *= g; mat[2] *= g; - g = m0.y*f; mat[4] = omat[8]*g; mat[5] = omat[9]*g; mat[6] = omat[10]*g; - g =-m0.z*f; mat[8] = omat[4]*g; mat[9] = omat[5]*g; mat[10] = omat[6]*g; - // - mat[12] -= (m->piv.x*mat[0] + m->piv.y*mat[4] + zoff*mat[8]); - mat[13] -= (m->piv.x*mat[1] + m->piv.y*mat[5] + zoff*mat[9]); - mat[14] -= (m->piv.x*mat[2] + m->piv.y*mat[6] + zoff*mat[10]); - // - //Let OpenGL (and perhaps hardware :) handle the matrix rotation - mat[3] = mat[7] = mat[11] = 0.f; mat[15] = 1.f; - - for (int i = 0; i < 15; i++) mat[i] *= 1024.f; - - // Adjust to backend coordinate system being used by the vertex buffer. - for (int i = 4; i < 8; i++) - { - float f = mat[i]; - mat[i] = -mat[i + 4]; - mat[i + 4] = -f; - } - - GLInterface.SetMatrix(Matrix_Model, mat); - - int palId = TRANSLATION(Translation_Remap + curbasepal, globalpal); - GLInterface.SetPalswap(globalpal); - GLInterface.SetFade(sector[tspr->sectnum].floorpal); - - auto tex = TexMan.GetGameTexture(m->model->GetPaletteTexture()); - GLInterface.SetTexture(tex, TRANSLATION(Translation_Remap + curbasepal, globalpal), CLAMP_NOFILTER_XY, true); - GLInterface.SetModel(m->model, 0, 0, 0); - GLInterface.Draw(DT_Triangles, 0, 0); - GLInterface.SetModel(nullptr, 0, 0, 0); - GLInterface.SetCull(Cull_None); - - if (shadowHack) - { - GLInterface.SetDepthFunc(DF_Less); - } - GLInterface.SetIdentityMatrix(Matrix_Model); - return 1; -} - -extern int voxlumps[MAXVOXELS]; -void (*PolymostProcessVoxels_Callback)(void) = NULL; -void PolymostProcessVoxels(void) -{ - if (PolymostProcessVoxels_Callback) - PolymostProcessVoxels_Callback(); - - if (g_haveVoxels != 1) - return; - - g_haveVoxels = 2; - - Printf(PRINT_NONOTIFY, "Generating voxel models for Polymost. This may take a while...\n"); - - for (int i = 0; i < MAXVOXELS; i++) - { - int lumpnum = voxlumps[i]; - if (lumpnum > 0) - { - voxmodels[i] = voxload(lumpnum); - if (voxmodels[i]) - voxmodels[i]->scale = voxscale[i] * (1.f / 65536.f); - else - Printf("Unable to load voxel from %s\n", fileSystem.GetFileFullPath(lumpnum)); - } - } -} - -#endif - -//---------------------------------------- VOX LIBRARY ENDS ---------------------------------------- diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index 29c214841..2337f10e3 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -74,6 +74,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "v_draw.h" #include "gi.h" #include "gamefuncs.h" +#include "hw_voxels.h" CVAR(Bool, autoloadlights, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Bool, autoloadbrightmaps, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -135,6 +136,7 @@ void SetConsoleNotifyBuffer(); bool PreBindTexture(FRenderState* state, FGameTexture*& tex, EUpscaleFlags& flags, int& scaleflags, int& clampmode, int& translation, int& overrideshader); void PostLoadSetup(); void FontCharCreated(FGameTexture* base, FGameTexture* untranslated, FGameTexture* translated); +void LoadVoxelModels(); DBaseStatusBar* StatusBar; @@ -573,7 +575,7 @@ int GameMain() G_SaveConfig(); C_DeinitConsole(); V_ClearFonts(); - vox_deinit(); + voxClear(); TexMan.DeleteAll(); TileFiles.CloseAll(); // delete the texture data before shutting down graphics. GLInterface.Deinit(); @@ -923,6 +925,12 @@ int RunGame() enginePreInit(); SetupGameButtons(); gameinfo.mBackButton = "engine/graphics/m_back.png"; + + GPalette.Init(MAXPALOOKUPS + 1); // one slot for each translation, plus a separate one for the base palettes. + gi->loadPalette(); + voxInit(); + TileFiles.LoadArtSet("tiles%03d.art"); // it's the same for all games. + engineInit(); gi->app_init(); CreateStatusBar(); SetDefaultMenuColors(); @@ -934,7 +942,15 @@ int RunGame() V_LoadTranslations(); // loading the translations must be delayed until the palettes have been fully set up. lookups.postLoadTables(); PostLoadSetup(); - videoInit(); + lookups.postLoadLookups(); + V_Init2(); + setVideoMode(); + + LoadVoxelModels(); + GLInterface.Init(screen->GetWidth()); + screen->BeginFrame(); + screen->SetTextureFilterMode(); + setViewport(hud_size); D_CheckNetGame(); UpdateGenericUI(ui_generic); @@ -1002,7 +1018,7 @@ void updatePauseStatus() // //========================================================================== -void PolymostProcessVoxels(void); +void LoadVoxelModels(void); void setVideoMode() { @@ -1013,24 +1029,6 @@ void setVideoMode() videoClearScreen(0); } -void videoInit() -{ - lookups.postLoadLookups(); - V_Init2(); - setVideoMode(); - - PolymostProcessVoxels(); - GLInterface.Init(screen->GetWidth()); - screen->BeginFrame(); - screen->SetTextureFilterMode(); - setViewport(hud_size); -} - -void G_FatalEngineError(void) -{ - I_FatalError("There was a problem initializing the engine: %s\n\nThe application will now close.", engineerrstr); -} - //========================================================================== // // diff --git a/source/core/gamecontrol.h b/source/core/gamecontrol.h index 85242b2f7..4a3d684b2 100644 --- a/source/core/gamecontrol.h +++ b/source/core/gamecontrol.h @@ -213,7 +213,6 @@ void S_PauseSound(bool notmusic, bool notsfx); void S_ResumeSound(bool notsfx); void S_SetSoundPaused(int state); -void G_FatalEngineError(void); enum { MaxSmoothRatio = FRACUNIT diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index 61038ee88..c8bd0d41b 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -148,28 +148,6 @@ bool calcChaseCamPos(int* px, int* py, int* pz, spritetype* pspr, short *psectnu return true; } -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -bool spriteIsModelOrVoxel(const spritetype * tspr) -{ - if ((unsigned)tspr->owner < MAXSPRITES && spriteext[tspr->owner].flags & SPREXT_NOTMD) - return false; - - if (hw_models) - { - auto& mdinfo = tile2model[Ptile2tile(tspr->picnum, tspr->pal)]; - if (mdinfo.modelid >= 0 && mdinfo.framenum >= 0) return true; - } - - auto slabalign = (tspr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_SLAB; - if (r_voxels && !slabalign && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]]) return true; - return (slabalign && voxmodels[tspr->picnum]); -} - //========================================================================== // // note that this returns values in renderer coordinate space with inverted sign! diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index 5435325e6..f9f2432d9 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -7,7 +7,6 @@ extern int cameradist, cameraclock; bool calcChaseCamPos(int* px, int* py, int* pz, spritetype* pspr, short *psectnum, binangle ang, fixedhoriz horiz, double const smoothratio); -bool spriteIsModelOrVoxel(const spritetype* tspr); void PlanesAtPoint(const sectortype* sec, float dax, float day, float* ceilz, float* florz); void setWallSectors(); void GetWallSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out, bool render = false); diff --git a/source/core/rendering/hw_voxels.cpp b/source/core/rendering/hw_voxels.cpp new file mode 100644 index 000000000..7ee3cbc6a --- /dev/null +++ b/source/core/rendering/hw_voxels.cpp @@ -0,0 +1,114 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2021 Christoph Oelckers +// All rights reserved. +// +// This program 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 of the License, or +// (at your option) any later version. +// +// This program 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 program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// +/* +** hw_voxels.cpp +** +** voxel handling. +** +**/ + +#include "build.h" +#include "voxels.h" +#include "hw_voxels.h" +#include "gamecontrol.h" + +int16_t tiletovox[MAXTILES]; +static int voxlumps[MAXVOXELS]; +float voxscale[MAXVOXELS]; +voxmodel_t* voxmodels[MAXVOXELS]; +FixedBitArray voxrotate; + + +void voxInit() +{ + for (auto& v : tiletovox) v = -1; + for (auto& v : voxscale) v = 1.f; + voxrotate.Zero(); +} + +void voxClear() +{ + for (auto& vox : voxmodels) + { + if (vox) delete vox; + vox = nullptr; + } +} + +int voxDefine(int voxindex, const char* filename) +{ + if ((unsigned)voxindex >= MAXVOXELS) + return -1; + + int i = fileSystem.FindFile(filename); + voxlumps[voxindex] = i; + return i < 0 ? -1 : 0; +} + +static voxmodel_t* voxload(int lumpnum) +{ + FVoxel* voxel = R_LoadKVX(lumpnum); + if (voxel != nullptr) + { + voxmodel_t* vm = new voxmodel_t; + *vm = {}; + auto pivot = voxel->Mips[0].Pivot; + vm->mdnum = 1; //VOXel model id + vm->scale = vm->bscale = 1.f; + vm->piv.x = float(pivot.X); + vm->piv.y = float(pivot.Y); + vm->piv.z = float(pivot.Z); + vm->siz.x = voxel->Mips[0].SizeX; + vm->siz.y = voxel->Mips[0].SizeY; + vm->siz.z = voxel->Mips[0].SizeZ; + vm->is8bit = true; + voxel->Mips[0].Pivot.Zero(); // Needs to be taken out of the voxel data because it gets baked into the vertex buffer which we cannot use here. + vm->model = new FVoxelModel(voxel, true); + return vm; + } + return nullptr; +} + +void LoadVoxelModels() +{ + for (int i = 0; i < MAXVOXELS; i++) + { + int lumpnum = voxlumps[i]; + if (lumpnum > 0) + { + voxmodels[i] = voxload(lumpnum); + if (voxmodels[i]) + voxmodels[i]->scale = voxscale[i]; + else + Printf("Unable to load voxel from %s\n", fileSystem.GetFileFullPath(lumpnum)); + } + else + { + auto index = fileSystem.FindResource(i, "KVX"); + if (index >= 0) + { + voxmodels[i] = voxload(index); + } + } + } +} + diff --git a/source/core/rendering/hw_voxels.h b/source/core/rendering/hw_voxels.h new file mode 100644 index 000000000..1633d1808 --- /dev/null +++ b/source/core/rendering/hw_voxels.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include "mdsprite.h" + +// We still need the relation to mdmodel_t as long as the model code hasn't been redone. +struct voxmodel_t : public mdmodel_t +{ + FVoxelModel* model = nullptr; + vec3_t siz; + vec3f_t piv; + int32_t is8bit; +}; + + + +extern int16_t tiletovox[]; +extern float voxscale[]; +extern voxmodel_t* voxmodels[MAXVOXELS]; +extern FixedBitArray voxrotate; + +void voxInit(); +void voxClear(); +int voxDefine(int voxindex, const char* filename); diff --git a/source/core/rendering/scene/hw_bunchdrawer.cpp b/source/core/rendering/scene/hw_bunchdrawer.cpp index 86f2985d2..5f2572849 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.cpp +++ b/source/core/rendering/scene/hw_bunchdrawer.cpp @@ -40,6 +40,7 @@ #include "gamefuncs.h" #include "hw_portal.h" #include "gamestruct.h" +#include "hw_voxels.h" //========================================================================== diff --git a/source/core/rendering/scene/hw_drawinfo.cpp b/source/core/rendering/scene/hw_drawinfo.cpp index 74905bcd3..7f4a8d328 100644 --- a/source/core/rendering/scene/hw_drawinfo.cpp +++ b/source/core/rendering/scene/hw_drawinfo.cpp @@ -41,6 +41,7 @@ #include "gamecvars.h" #include "gamestruct.h" #include "automap.h" +#include "hw_voxels.h" EXTERN_CVAR(Float, r_visibility) CVAR(Bool, gl_no_skyclear, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -300,14 +301,14 @@ void HWDrawInfo::DispatchSprites() { HWSprite hwsprite; int num = tiletovox[tspr->picnum]; - if (hwsprite.ProcessVoxel(this, voxmodels[tiletovox[tspr->picnum]], tspr, §or[tspr->sectnum], voxrotate[num >> 3] & (1 << (num & 7)))) + if (hwsprite.ProcessVoxel(this, voxmodels[tiletovox[tspr->picnum]], tspr, §or[tspr->sectnum], voxrotate[num])) continue; } else if ((tspr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_SLAB && tspr->picnum < MAXVOXELS && voxmodels[tspr->picnum]) { HWSprite hwsprite; int num = tspr->picnum; - hwsprite.ProcessVoxel(this, voxmodels[tspr->picnum], tspr, §or[tspr->sectnum], voxrotate[num >> 3] & (1 << (num & 7))); + hwsprite.ProcessVoxel(this, voxmodels[tspr->picnum], tspr, §or[tspr->sectnum], voxrotate[num]); continue; } } diff --git a/source/core/rendering/scene/hw_drawstructs.h b/source/core/rendering/scene/hw_drawstructs.h index e987adbc7..68869f8ea 100644 --- a/source/core/rendering/scene/hw_drawstructs.h +++ b/source/core/rendering/scene/hw_drawstructs.h @@ -26,6 +26,7 @@ struct FDynLightData; class VSMatrix; struct FSpriteModelFrame; class FRenderState; +struct voxmodel_t; struct HWSectorPlane { diff --git a/source/core/rendering/scene/hw_sprites.cpp b/source/core/rendering/scene/hw_sprites.cpp index 4fe85f31f..b555fdd92 100644 --- a/source/core/rendering/scene/hw_sprites.cpp +++ b/source/core/rendering/scene/hw_sprites.cpp @@ -44,6 +44,7 @@ #include "hw_renderstate.h" #include "hw_models.h" #include "hw_viewpointbuffer.h" +#include "hw_voxels.h" extern PalEntry GlobalMapFog; extern float GlobalFogDensity; @@ -487,7 +488,7 @@ bool HWSprite::ProcessVoxel(HWDrawInfo* di, voxmodel_t* vox, spritetype* spr, se if ((spr->cstat & CSTAT_SPRITE_MDLROTATE) || rotate) { int myclock = (PlayClock << 3) + MulScale(4 << 3, (int)di->Viewpoint.TicFrac, 16); - ang = (ang + myclock) & 2047; // will be applied in md3_vox_calcmat_common. + ang = (ang + myclock) & 2047; } diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp index 030e9234a..74de2d8af 100644 --- a/source/core/savegamehelp.cpp +++ b/source/core/savegamehelp.cpp @@ -646,7 +646,6 @@ void SerializeMap(FSerializer& arc) ("numshades", numshades) // is this really needed? ("visibility", g_visibility) ("parallaxtype", parallaxtype) - ("parallaxvisibility", parallaxvisibility) ("parallaxyo", parallaxyoffs_override) ("parallaxys", parallaxyscale_override) ("pskybits", pskybits_override) diff --git a/source/core/textures/buildtiles.cpp b/source/core/textures/buildtiles.cpp index 95f5751b7..987736ea4 100644 --- a/source/core/textures/buildtiles.cpp +++ b/source/core/textures/buildtiles.cpp @@ -47,6 +47,7 @@ #include "c_dispatch.h" #include "sc_man.h" #include "gamestruct.h" +#include "hw_voxels.h" #include "hw_renderstate.h" @@ -648,7 +649,7 @@ void artSetupMapArt(const char* filename) void tileDelete(int tile) { TileFiles.tiledata[tile].texture = TileFiles.tiledata[tile].backup = TexMan.GameByIndex(0); - vox_undefine(tile); + tiletovox[tile] = -1; // clear the link but don't clear the voxel. It may be in use for another tile. md_undefinetile(tile); } diff --git a/source/games/blood/src/animatesprite.cpp b/source/games/blood/src/animatesprite.cpp index 0f21c89e7..949052ceb 100644 --- a/source/games/blood/src/animatesprite.cpp +++ b/source/games/blood/src/animatesprite.cpp @@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "v_2ddrawer.h" #include "v_video.h" #include "v_font.h" +#include "hw_voxels.h" #include "glbackend/glbackend.h" BEGIN_BLD_NS diff --git a/source/games/blood/src/blood.cpp b/source/games/blood/src/blood.cpp index 55399119e..f9ac09273 100644 --- a/source/games/blood/src/blood.cpp +++ b/source/games/blood/src/blood.cpp @@ -465,9 +465,6 @@ void GameInterface::app_init() HookReplaceFunctions(); - Printf(PRINT_NONOTIFY, "Initializing Build 3D engine\n"); - engineInit(); - Printf(PRINT_NONOTIFY, "Loading tiles\n"); if (!tileInit(0, NULL)) I_FatalError("TILES###.ART files not found"); diff --git a/source/games/blood/src/misc.h b/source/games/blood/src/misc.h index cea185bf6..33d2d7704 100644 --- a/source/games/blood/src/misc.h +++ b/source/games/blood/src/misc.h @@ -122,7 +122,6 @@ extern short voxelIndex[MAXTILES]; extern int nPrecacheCount; int tileInit(char a1, const char *a2); -void tileProcessGLVoxels(void); void tilePreloadTile(int nTile); void tilePrecacheTile(int nTile, int nType, HitList& hits); diff --git a/source/games/blood/src/tile.cpp b/source/games/blood/src/tile.cpp index ac46809d1..3d81013e0 100644 --- a/source/games/blood/src/tile.cpp +++ b/source/games/blood/src/tile.cpp @@ -44,14 +44,11 @@ char surfType[kMaxTiles]; signed char tileShade[kMaxTiles]; short voxelIndex[kMaxTiles]; -const char *pzBaseFileName = "TILES%03i.ART"; //"TILES%03i.ART"; - int tileInit(char a1, const char *a2) { UNREFERENCED_PARAMETER(a1); if (artLoaded) return 1; - TileFiles.artLoadFiles(a2 ? a2 : pzBaseFileName); for (int i = 0; i < kMaxTiles; i++) voxelIndex[i] = 0; @@ -81,32 +78,9 @@ int tileInit(char a1, const char *a2) } artLoaded = 1; - - #ifdef USE_OPENGL - PolymostProcessVoxels_Callback = tileProcessGLVoxels; - #endif - return 1; } -#ifdef USE_OPENGL -void tileProcessGLVoxels(void) -{ - static bool voxInit = false; - if (voxInit) - return; - voxInit = true; - for (int i = 0; i < kMaxVoxels; i++) - { - auto index = fileSystem.FindResource(i, "KVX"); - if (index >= 0) - { - voxmodels[i] = voxload(index); - } - } -} -#endif - char tileGetSurfType(int hit) { int n = hit & 0x3fff; diff --git a/source/games/duke/src/game.cpp b/source/games/duke/src/game.cpp index 181997346..8325fd7da 100644 --- a/source/games/duke/src/game.cpp +++ b/source/games/duke/src/game.cpp @@ -230,9 +230,6 @@ static void setupbackdrop() static void initTiles() { - if (TileFiles.artLoadFiles("tiles%03i.art") < 0) - I_FatalError("Failed loading art."); - tileDelete(TILE_MIRROR); skiptile = TILE_W_FORCEFIELD + 1; @@ -310,9 +307,6 @@ void GameInterface::app_init() OnEvent(EVENT_INIT); - if (engineInit()) - G_FatalEngineError(); - //Net_SendClientInfo(); initTiles(); diff --git a/source/games/exhumed/src/exhumed.cpp b/source/games/exhumed/src/exhumed.cpp index 462c2923f..b2988a45d 100644 --- a/source/games/exhumed/src/exhumed.cpp +++ b/source/games/exhumed/src/exhumed.cpp @@ -75,12 +75,6 @@ void ResetEngine() void InstallEngine() { - TileFiles.LoadArtSet("tiles%03d.art"); - - if (engineInit()) - { - G_FatalEngineError(); - } uploadCinemaPalettes(); LoadPaletteLookups(); } diff --git a/source/games/sw/src/game.cpp b/source/games/sw/src/game.cpp index fedd97681..a63d32ccb 100644 --- a/source/games/sw/src/game.cpp +++ b/source/games/sw/src/game.cpp @@ -199,7 +199,6 @@ void GameInterface::app_init() registerosdcommands(); - engineInit(); auto pal = fileSystem.LoadFile("3drealms.pal", 0); if (pal.Size() >= 768) { @@ -220,8 +219,6 @@ void GameInterface::app_init() "the full version. Read the Ordering Info screens for details."); } - TileFiles.LoadArtSet("tiles%03d.art"); - //Connect(); SortBreakInfo(); parallaxtype = 1; diff --git a/source/games/sw/src/scrip2.cpp b/source/games/sw/src/scrip2.cpp index d008ea556..ac36e7607 100644 --- a/source/games/sw/src/scrip2.cpp +++ b/source/games/sw/src/scrip2.cpp @@ -40,6 +40,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "razemenu.h" #include "quotemgr.h" #include "mapinfo.h" +#include "hw_voxels.h" BEGIN_SW_NS @@ -231,7 +232,7 @@ void LoadKVXFromScript(const char* filename) GetToken(false); // Load the voxel file into memory - if (!qloadkvx(lNumber,token)) + if (!voxDefine(lNumber,token)) { // Store the sprite and voxel numbers for later use aVoxelArray[lTile].Voxel = lNumber; // Voxel num From 7a9e58c31e1f7e8ea3580b5469725329ea9fa812 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 15:14:28 +0200 Subject: [PATCH 05/70] - removed redundant cstat.h file. Constants are already defined in buildtypes.h --- source/build/include/cstat.h | 43 ------------------------------------ source/core/automap.cpp | 1 - 2 files changed, 44 deletions(-) delete mode 100644 source/build/include/cstat.h diff --git a/source/build/include/cstat.h b/source/build/include/cstat.h deleted file mode 100644 index 17824c3c2..000000000 --- a/source/build/include/cstat.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -// nobody uses these. What's so cool about naked numbers? :( -#if 0 -// system defines for status bits -#define CEILING_STAT_PLAX BIT(0) -#define CEILING_STAT_SLOPE BIT(1) -#define CEILING_STAT_SWAPXY BIT(2) -#define CEILING_STAT_SMOOSH BIT(3) -#define CEILING_STAT_XFLIP BIT(4) -#define CEILING_STAT_YFLIP BIT(5) -#define CEILING_STAT_RELATIVE BIT(6) -#define CEILING_STAT_TYPE_MASK (BIT(7)|BIT(8)) -#define CEILING_STAT_MASKED BIT(7) -#define CEILING_STAT_TRANS BIT(8) -#define CEILING_STAT_TRANS_FLIP (BIT(7)|BIT(8)) -#define CEILING_STAT_FAF_BLOCK_HITSCAN BIT(15) - -#define FLOOR_STAT_PLAX BIT(0) -#define FLOOR_STAT_SLOPE BIT(1) -#define FLOOR_STAT_SWAPXY BIT(2) -#define FLOOR_STAT_SMOOSH BIT(3) -#define FLOOR_STAT_XFLIP BIT(4) -#define FLOOR_STAT_YFLIP BIT(5) -#define FLOOR_STAT_RELATIVE BIT(6) -#define FLOOR_STAT_TYPE_MASK (BIT(7)|BIT(8)) -#define FLOOR_STAT_MASKED BIT(7) -#define FLOOR_STAT_TRANS BIT(8) -#define FLOOR_STAT_TRANS_FLIP (BIT(7)|BIT(8)) -#define FLOOR_STAT_FAF_BLOCK_HITSCAN BIT(15) - -#define CSTAT_WALL_BLOCK BIT(0) -#define CSTAT_WALL_BOTTOM_SWAP BIT(1) -#define CSTAT_WALL_ALIGN_BOTTOM BIT(2) -#define CSTAT_WALL_XFLIP BIT(3) -#define CSTAT_WALL_MASKED BIT(4) -#define CSTAT_WALL_1WAY BIT(5) -#define CSTAT_WALL_BLOCK_HITSCAN BIT(6) -#define CSTAT_WALL_TRANSLUCENT BIT(7) -#define CSTAT_WALL_YFLIP BIT(8) -#define CSTAT_WALL_TRANS_FLIP BIT(9) -#define CSTAT_WALL_BLOCK_ACTOR (BIT(14)) // my def -#define CSTAT_WALL_WARP_HITSCAN (BIT(15)) // my def -#endif diff --git a/source/core/automap.cpp b/source/core/automap.cpp index 902ab46a3..258ad9089 100644 --- a/source/core/automap.cpp +++ b/source/core/automap.cpp @@ -27,7 +27,6 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) //------------------------------------------------------------------------- #include "automap.h" -#include "cstat.h" #include "c_dispatch.h" #include "c_cvars.h" #include "gstrings.h" From f6b46e9f6335840efe33a4896a277e27e6787f55 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 15:41:57 +0200 Subject: [PATCH 06/70] - added a few missing init calls. --- source/core/gamecontrol.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index 2337f10e3..6bf494e9f 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -944,6 +944,11 @@ int RunGame() PostLoadSetup(); lookups.postLoadLookups(); V_Init2(); + twod->Begin(screen->GetWidth(), screen->GetHeight()); + twod->End(); + UpdateJoystickMenu(NULL); + UpdateVRModes(); + setVideoMode(); LoadVoxelModels(); From ec460df2c007329f2445f73e64f38df3d68ffd1a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 16:17:13 +0200 Subject: [PATCH 07/70] - always ensure that the global index buffer is not empty. This needs to be valid for Vulkan, even if it isn't used. --- source/common/rendering/hwrenderer/data/flatvertices.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/common/rendering/hwrenderer/data/flatvertices.cpp b/source/common/rendering/hwrenderer/data/flatvertices.cpp index 47ae19ec3..5bc37bcb7 100644 --- a/source/common/rendering/hwrenderer/data/flatvertices.cpp +++ b/source/common/rendering/hwrenderer/data/flatvertices.cpp @@ -80,6 +80,8 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height) mVertexBuffer = screen->CreateVertexBuffer(); mIndexBuffer = screen->CreateIndexBuffer(); + int data[4] = {}; + mIndexBuffer->SetData(4, data); // On Vulkan this may not be empty, so set some dummy defaults to avoid crashes. unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex); mVertexBuffer->SetData(bytesize, nullptr, false); From c0f1949fb95f6767ddf750d3e8dd3dd853d72071 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 19:07:59 +0200 Subject: [PATCH 08/70] - fixed some swapped parameters in status bar code. --- source/common/statusbar/base_sbar.cpp | 4 ++-- source/common/statusbar/base_sbar.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/common/statusbar/base_sbar.cpp b/source/common/statusbar/base_sbar.cpp index b0e917872..ae1a375c3 100644 --- a/source/common/statusbar/base_sbar.cpp +++ b/source/common/statusbar/base_sbar.cpp @@ -605,13 +605,13 @@ void DStatusBarCore::DrawGraphic(FGameTexture* tex, double x, double y, int flag // //============================================================================ -void DStatusBarCore::DrawRotated(FTextureID texture, double x, double y, double angle, int flags, double Alpha, double scaleX, double scaleY, PalEntry color, int translation, ERenderStyle style) +void DStatusBarCore::DrawRotated(FTextureID texture, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color, int translation, ERenderStyle style) { if (!texture.isValid()) return; FGameTexture* tex = TexMan.GetGameTexture(texture, !(flags & DI_DONTANIMATE)); - DrawRotated(tex, x, y, angle, flags, Alpha, scaleX, scaleY, color, translation, style); + DrawRotated(tex, x, y, flags, angle, Alpha, scaleX, scaleY, color, translation, style); } void DStatusBarCore::DrawRotated(FGameTexture* tex, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color, int translation, ERenderStyle style) diff --git a/source/common/statusbar/base_sbar.h b/source/common/statusbar/base_sbar.h index 02c66ba26..7f892b4e4 100644 --- a/source/common/statusbar/base_sbar.h +++ b/source/common/statusbar/base_sbar.h @@ -186,7 +186,7 @@ public: void StatusbarToRealCoords(double& x, double& y, double& w, double& h) const; void DrawGraphic(FGameTexture* texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent, double clipwidth = -1.0); void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent, double clipwidth = -1.0); - void DrawRotated(FTextureID texture, double x, double y, double angle, int flags, double Alpha, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent); + void DrawRotated(FTextureID texture, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent); void DrawRotated(FGameTexture* tex, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent); void DrawString(FFont* font, const FString& cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY, int pt); void TransformRect(double& x, double& y, double& w, double& h, int flags = 0); From 869433ee2e81caeb9fcc2e26bebae6d9019d84a2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 19:18:57 +0200 Subject: [PATCH 09/70] - fixed invalidation of programmatic textures. This is only relevant for Vulkan because it stores the descriptor sets with the material, not the hardware texture. --- source/common/textures/animtexture.cpp | 5 +++-- source/core/textures/buildtiles.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source/common/textures/animtexture.cpp b/source/common/textures/animtexture.cpp index 6a96365a8..8f8add3f7 100644 --- a/source/common/textures/animtexture.cpp +++ b/source/common/textures/animtexture.cpp @@ -48,7 +48,6 @@ void AnimTexture::SetFrameSize(int format, int width, int height) FTexture::SetSize(width, height); Image.Resize(width * height * (format == Paletted ? 1 : 3)); memset(Image.Data(), 0, Image.Size()); - CleanHardwareTextures(); } void AnimTexture::SetFrame(const uint8_t* palette, const void* data_) @@ -81,7 +80,6 @@ void AnimTexture::SetFrame(const uint8_t* palette, const void* data_) } else memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3)); } - CleanHardwareTextures(); } //=========================================================================== @@ -156,10 +154,13 @@ void AnimTextures::SetSize(int format, int width, int height) static_cast(tex[1]->GetTexture())->SetFrameSize(format, width, height); tex[0]->SetSize(width, height); tex[1]->SetSize(width, height); + tex[0]->CleanHardwareData(); + tex[1]->CleanHardwareData(); } void AnimTextures::SetFrame(const uint8_t* palette, const void* data) { active ^= 1; static_cast(tex[active]->GetTexture())->SetFrame(palette, data); + tex[active]->CleanHardwareData(); } diff --git a/source/core/textures/buildtiles.cpp b/source/core/textures/buildtiles.cpp index 07efd696f..b08a70b0d 100644 --- a/source/core/textures/buildtiles.cpp +++ b/source/core/textures/buildtiles.cpp @@ -256,7 +256,7 @@ void BuildTiles::InvalidateTile(int num) if ((unsigned) num < MAXTILES) { auto tex = tiledata[num].texture; - tex->GetTexture()->SystemTextures.Clean(); + tex->CleanHardwareData(); tiledata[num].rawCache.data.Clear(); } } From 41072eb020ee728572a0c5174448c756ac8c034e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 19:20:41 +0200 Subject: [PATCH 10/70] - fixed uninitialized scale variable in sky code. --- source/common/rendering/hwrenderer/data/hw_renderstate.h | 2 +- source/common/rendering/hwrenderer/data/hw_skydome.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/source/common/rendering/hwrenderer/data/hw_renderstate.h b/source/common/rendering/hwrenderer/data/hw_renderstate.h index 07cc8819f..54aab25f8 100644 --- a/source/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/source/common/rendering/hwrenderer/data/hw_renderstate.h @@ -273,7 +273,7 @@ public: mSpecialEffect = EFF_NONE; mLightIndex = -1; mStreamData.uInterpolationFactor = 0; - mRenderStyle = LegacyRenderStyles[STYLE_Translucent]; + mRenderStyle = DefaultRenderStyle(); mMaterial.Reset(); mBias.Reset(); mPassType = NORMAL_PASS; diff --git a/source/common/rendering/hwrenderer/data/hw_skydome.cpp b/source/common/rendering/hwrenderer/data/hw_skydome.cpp index 2a16ccbf3..5d5ee8000 100644 --- a/source/common/rendering/hwrenderer/data/hw_skydome.cpp +++ b/source/common/rendering/hwrenderer/data/hw_skydome.cpp @@ -202,7 +202,7 @@ void FSkyVertexBuffer::SkyVertexBuild(int r, int c, bool zflip) // And the texture coordinates. if (zflip) r = mRows * 2 - r; - vert.u = 0.5 + (-c / (float)mColumns); + vert.u = 0.5f + (-c / (float)mColumns); vert.v = (r / (float)(2*mRows)); // And finally the vertex. @@ -413,11 +413,13 @@ void FSkyVertexBuffer::SetupMatrices(FGameTexture *tex, float x_offset, float y_ { modelMatrix.translate(0.f, -1250.f, 0.f); modelMatrix.scale(1.f, texh / 230.f, 1.f); + yscale = 1.f; } else if (texh <= 240) { modelMatrix.translate(0.f, (200 - texh + texskyoffset) * skyoffsetfactor, 0.f); modelMatrix.scale(1.f, 1.f + ((texh - 200.f) / 200.f) * 1.17f, 1.f); + yscale = 1.f; } else { From 7c4e9ea87e42beabb2458b3b7e8b1e416dbf87f3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 20:00:21 +0200 Subject: [PATCH 11/70] - moved palette manager for indexed textures out of glbackend --- source/CMakeLists.txt | 2 +- source/core/gamecontrol.cpp | 5 +++- .../rendering/hw_palmanager.cpp} | 24 +++++++++++++++++- source/core/rendering/hw_palmanager.h | 24 ++++++++++++++++++ source/glbackend/glbackend.cpp | 17 ------------- source/glbackend/glbackend.h | 25 +------------------ 6 files changed, 53 insertions(+), 44 deletions(-) rename source/{glbackend/gl_palmanager.cpp => core/rendering/hw_palmanager.cpp} (87%) create mode 100644 source/core/rendering/hw_palmanager.h diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 6ca5e7e13..78735bc91 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1022,7 +1022,6 @@ set (FASTMATH_SOURCES ${FASTMATH_SOURCES}) set (PCH_SOURCES glbackend/glbackend.cpp - glbackend/gl_palmanager.cpp glbackend/gl_texture.cpp thirdparty/src/md4.cpp @@ -1081,6 +1080,7 @@ set (PCH_SOURCES core/rendering/hw_entrypoint.cpp core/rendering/hw_models.cpp core/rendering/hw_voxels.cpp + core/rendering/hw_palmanager.cpp core/rendering/scene/hw_clipper.cpp core/rendering/scene/hw_walls.cpp core/rendering/scene/hw_flats.cpp diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index 6bf494e9f..e395ece8a 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -75,6 +75,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "gi.h" #include "gamefuncs.h" #include "hw_voxels.h" +#include "hw_palmanager.h" CVAR(Bool, autoloadlights, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Bool, autoloadbrightmaps, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -576,9 +577,9 @@ int GameMain() C_DeinitConsole(); V_ClearFonts(); voxClear(); + ClearPalManager(); TexMan.DeleteAll(); TileFiles.CloseAll(); // delete the texture data before shutting down graphics. - GLInterface.Deinit(); I_ShutdownGraphics(); freeallmodels(); if (gi) @@ -943,6 +944,8 @@ int RunGame() lookups.postLoadTables(); PostLoadSetup(); lookups.postLoadLookups(); + FMaterial::SetLayerCallback(setpalettelayer); + V_Init2(); twod->Begin(screen->GetWidth(), screen->GetHeight()); twod->End(); diff --git a/source/glbackend/gl_palmanager.cpp b/source/core/rendering/hw_palmanager.cpp similarity index 87% rename from source/glbackend/gl_palmanager.cpp rename to source/core/rendering/hw_palmanager.cpp index aee5dade4..0298aa657 100644 --- a/source/glbackend/gl_palmanager.cpp +++ b/source/core/rendering/hw_palmanager.cpp @@ -35,7 +35,7 @@ #include #include "m_crc32.h" -#include "glbackend.h" +#include "hw_palmanager.h" #include "resourcefile.h" #include "imagehelpers.h" @@ -44,6 +44,8 @@ #include "build.h" #include "v_video.h" +static PaletteManager* palmanager; + //=========================================================================== // // This class manages the hardware data for the indexed render mode. @@ -138,4 +140,24 @@ IHardwareTexture* PaletteManager::GetLookup(int index) return nullptr; } +//=========================================================================== +// +// +// +//=========================================================================== +IHardwareTexture *setpalettelayer(int layer, int translation) +{ + if (!palmanager) palmanager = new PaletteManager; + if (layer == 1) + return palmanager->GetPalette(GetTranslationType(translation) - Translation_Remap); + else if (layer == 2) + return palmanager->GetLookup(GetTranslationIndex(translation)); + else return nullptr; +} + +void ClearPalManager() +{ + if (palmanager) delete palmanager; + palmanager = nullptr; +} \ No newline at end of file diff --git a/source/core/rendering/hw_palmanager.h b/source/core/rendering/hw_palmanager.h new file mode 100644 index 000000000..e308f79ab --- /dev/null +++ b/source/core/rendering/hw_palmanager.h @@ -0,0 +1,24 @@ +#pragma once + +#include "gl_hwtexture.h" + +struct palette_t; + +class PaletteManager +{ + IHardwareTexture* palettetextures[256] = {}; + IHardwareTexture* lookuptextures[256] = {}; + + unsigned FindPalswap(const uint8_t* paldata, palette_t& fadecolor); + +public: + ~PaletteManager(); + void DeleteAll(); + IHardwareTexture *GetPalette(int index); + IHardwareTexture* GetLookup(int index); +}; + + +IHardwareTexture* setpalettelayer(int layer, int translation); +void ClearPalManager(); + diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp index dc44c5e37..a31f8aa70 100644 --- a/source/glbackend/glbackend.cpp +++ b/source/glbackend/glbackend.cpp @@ -70,33 +70,16 @@ void Draw2D(F2DDrawer* drawer, FRenderState& state); GLInstance GLInterface; GLInstance::GLInstance() - :palmanager(this) { VSMatrix mat(0); matrixArray.Push(mat); } -IHardwareTexture *setpalettelayer(int layer, int translation) -{ - if (layer == 1) - return GLInterface.palmanager.GetPalette(GetTranslationType(translation) - Translation_Remap); - else if (layer == 2) - return GLInterface.palmanager.GetLookup(GetTranslationIndex(translation)); - else return nullptr; -} - void GLInstance::Init(int ydim) { - FMaterial::SetLayerCallback(setpalettelayer); new(&renderState) PolymostRenderState; // reset to defaults. } -void GLInstance::Deinit() -{ - palmanager.DeleteAll(); - lastPalswapIndex = -1; -} - void GLInstance::Draw(EDrawType type, size_t start, size_t count) { assert (BufferLock > 0); diff --git a/source/glbackend/glbackend.h b/source/glbackend/glbackend.h index a21ccb2a3..90512258d 100644 --- a/source/glbackend/glbackend.h +++ b/source/glbackend/glbackend.h @@ -21,25 +21,6 @@ class F2DDrawer; struct palette_t; extern int xdim, ydim; -class PaletteManager -{ - IHardwareTexture* palettetextures[256] = {}; - IHardwareTexture* lookuptextures[256] = {}; - - GLInstance* const inst; - - unsigned FindPalswap(const uint8_t* paldata, palette_t& fadecolor); - -public: - PaletteManager(GLInstance *inst_) : inst(inst_) - {} - ~PaletteManager(); - void DeleteAll(); - IHardwareTexture *GetPalette(int index); - IHardwareTexture* GetLookup(int index); -}; - - struct glinfo_t { float maxanisotropy; }; @@ -75,9 +56,7 @@ class GLInstance friend IHardwareTexture* setpalettelayer(int layer, int translation); public: - TArray rendercommands; - PaletteManager palmanager; - int lastPalswapIndex = -1; + TArray rendercommands; FGameTexture* currentTexture = nullptr; int MatrixChange = 0; @@ -90,8 +69,6 @@ public: void Init(int y); - void Deinit(); - static int GetTexDimension(int value) { //if (value > gl.max_texturesize) return gl.max_texturesize; From e098e0ca2ee5060cdf632c2941de77ef92f79dba Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 20:12:11 +0200 Subject: [PATCH 12/70] - added VR mode init code as this is actually functional with the new renderer. Also moved a few things out of gl_texture.cpp as this file is scheduled to go away with Polymost. --- source/common/textures/hw_material.cpp | 1 + source/core/gamecontrol.cpp | 7 +++++++ source/core/menu/razemenu.cpp | 26 ++++++++++++++++++++++++++ source/glbackend/gl_texture.cpp | 17 ----------------- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/source/common/textures/hw_material.cpp b/source/common/textures/hw_material.cpp index f8d379cd4..a157cbc07 100644 --- a/source/common/textures/hw_material.cpp +++ b/source/common/textures/hw_material.cpp @@ -30,6 +30,7 @@ #include "v_video.h" static IHardwareTexture* (*layercallback)(int layer, int translation); +TArray usershaders; void FMaterial::SetLayerCallback(IHardwareTexture* (*cb)(int layer, int translation)) { diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index e395ece8a..e5e5410f5 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -1412,3 +1412,10 @@ DEFINE_GLOBAL(gameaction) DEFINE_GLOBAL(gamestate) DEFINE_GLOBAL(demoplayback) DEFINE_GLOBAL(consoleplayer) + + +void InitBuildTiles() +{ + // need to find a better way to handle this thing. +} + diff --git a/source/core/menu/razemenu.cpp b/source/core/menu/razemenu.cpp index 08b5c84be..528a9175b 100644 --- a/source/core/menu/razemenu.cpp +++ b/source/core/menu/razemenu.cpp @@ -731,3 +731,29 @@ DEFINE_ACTION_FUNCTION(_PlayerMenu, DrawPlayerSprite) return 0; } +#ifdef _WIN32 +EXTERN_CVAR(Bool, vr_enable_quadbuffered) +#endif + +void UpdateVRModes(bool considerQuadBuffered) +{ + FOptionValues** pVRModes = OptionValues.CheckKey("VRMode"); + if (pVRModes == nullptr) return; + + TArray& vals = (*pVRModes)->mValues; + TArray filteredValues; + int cnt = vals.Size(); + for (int i = 0; i < cnt; ++i) { + auto const& mode = vals[i]; + if (mode.Value == 7) { // Quad-buffered stereo +#ifdef _WIN32 + if (!vr_enable_quadbuffered) continue; +#else + continue; // Remove quad-buffered option on Mac and Linux +#endif + if (!considerQuadBuffered) continue; // Probably no compatible screen mode was found + } + filteredValues.Push(mode); + } + vals = filteredValues; +} diff --git a/source/glbackend/gl_texture.cpp b/source/glbackend/gl_texture.cpp index 023c9475d..783e02d83 100644 --- a/source/glbackend/gl_texture.cpp +++ b/source/glbackend/gl_texture.cpp @@ -86,20 +86,3 @@ bool GLInstance::SetTexture(FGameTexture* tex, int paletteid, int sampler, bool return true; } -//=========================================================================== -// -// stand-ins for the texture system. Nothing of this is used right now, but needs to be present to satisfy the linker -// -//=========================================================================== - -void InitBuildTiles() -{ - -} - -TArray usershaders; - -void UpdateVRModes(bool considerQuadBuffered = true) -{ - // should update the menu. -} From 8ea13f7c65f452cfb4f8b0e6d7cd93a7f4097f75 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 21:24:29 +0200 Subject: [PATCH 13/70] - implemented support for paletted textures to Vulkan backend. --- .../vulkan/system/vk_framebuffer.cpp | 2 +- .../vulkan/textures/vk_hwtexture.cpp | 36 ++++++++++++------- .../rendering/vulkan/textures/vk_hwtexture.h | 4 +-- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/source/common/rendering/vulkan/system/vk_framebuffer.cpp b/source/common/rendering/vulkan/system/vk_framebuffer.cpp index 32d36447f..9b83b6e26 100644 --- a/source/common/rendering/vulkan/system/vk_framebuffer.cpp +++ b/source/common/rendering/vulkan/system/vk_framebuffer.cpp @@ -390,7 +390,7 @@ void VulkanFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) IHardwareTexture *VulkanFrameBuffer::CreateHardwareTexture(int numchannels) { - return new VkHardwareTexture(); + return new VkHardwareTexture(numchannels); } FMaterial* VulkanFrameBuffer::CreateMaterial(FGameTexture* tex, int scaleflags) diff --git a/source/common/rendering/vulkan/textures/vk_hwtexture.cpp b/source/common/rendering/vulkan/textures/vk_hwtexture.cpp index 25bd66d71..6178549ab 100644 --- a/source/common/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/source/common/rendering/vulkan/textures/vk_hwtexture.cpp @@ -37,8 +37,9 @@ VkHardwareTexture *VkHardwareTexture::First = nullptr; -VkHardwareTexture::VkHardwareTexture() +VkHardwareTexture::VkHardwareTexture(int numchannels) { + mTexelsize = numchannels; Next = First; First = this; if (Next) Next->Prev = this; @@ -126,7 +127,8 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) if (!tex->isHardwareCanvas()) { FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData); - CreateTexture(texbuffer.mWidth, texbuffer.mHeight, 4, VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer); + bool indexed = flags & CTF_Indexed; + CreateTexture(texbuffer.mWidth, texbuffer.mHeight,indexed? 1 : 4, indexed? VK_FORMAT_R8_UNORM : VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer, !indexed); } else { @@ -156,7 +158,7 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) } } -void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels) +void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap) { if (w <= 0 || h <= 0) throw CVulkanError("Trying to create zero size texture"); @@ -177,7 +179,7 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form ImageBuilder imgbuilder; imgbuilder.setFormat(format); - imgbuilder.setSize(w, h, GetMipLevels(w, h)); + imgbuilder.setSize(w, h, !mipmap ? 1 : GetMipLevels(w, h)); imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); mImage.Image = imgbuilder.create(fb->device); mImage.Image->SetDebugName("VkHardwareTexture.mImage"); @@ -203,7 +205,7 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form fb->FrameDeleteList.Buffers.push_back(std::move(stagingBuffer)); - mImage.GenerateMipmaps(cmdbuffer); + if (mipmap) mImage.GenerateMipmaps(cmdbuffer); } int VkHardwareTexture::GetMipLevels(int w, int h) @@ -268,6 +270,7 @@ uint8_t *VkHardwareTexture::MapBuffer() unsigned int VkHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, const char *name) { + CreateTexture(w, h, mTexelsize, mTexelsize == 4 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R8_UNORM, buffer, mipmap); return 0; } @@ -371,10 +374,6 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) int clampmode = state.mClampMode; int translation = state.mTranslation; - auto remap = translation <= 0 ? nullptr : GPalette.TranslationToTable(translation); - if (remap) - translation = remap->Index; - clampmode = base->GetClampMode(clampmode); for (auto& set : mDescriptorSets) @@ -395,10 +394,23 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) MaterialLayerInfo *layer; auto systex = static_cast(GetLayer(0, state.mTranslation, &layer)); update.addCombinedImageSampler(descriptor.get(), 0, systex->GetImage(layer->layerTexture, state.mTranslation, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout); - for (int i = 1; i < numLayers; i++) + + if (!(layer->scaleFlags & CTF_Indexed)) { - auto systex = static_cast(GetLayer(i, 0, &layer)); - update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout); + for (int i = 1; i < numLayers; i++) + { + auto systex = static_cast(GetLayer(i, 0, &layer)); + update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout); + } + } + else + { + for (int i = 1; i < 3; i++) + { + auto systex = static_cast(GetLayer(i, translation, &layer)); + update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout); + } + numLayers = 3; } auto dummyImage = fb->GetRenderPassManager()->GetNullTextureView(); diff --git a/source/common/rendering/vulkan/textures/vk_hwtexture.h b/source/common/rendering/vulkan/textures/vk_hwtexture.h index 872f58aef..22958c494 100644 --- a/source/common/rendering/vulkan/textures/vk_hwtexture.h +++ b/source/common/rendering/vulkan/textures/vk_hwtexture.h @@ -24,7 +24,7 @@ class VkHardwareTexture : public IHardwareTexture { friend class VkMaterial; public: - VkHardwareTexture(); + VkHardwareTexture(int numchannels); ~VkHardwareTexture(); static void ResetAll(); @@ -45,7 +45,7 @@ public: private: void CreateImage(FTexture *tex, int translation, int flags); - void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels); + void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap); static int GetMipLevels(int w, int h); static VkHardwareTexture *First; From 16ad5f0cc870510fcf62221b15cae1accd4a0fb6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 Apr 2021 21:53:19 +0200 Subject: [PATCH 14/70] - fixed sky rendering in palette emulation mode. The sky dome drawer cannot work with indexed textures, but since they are fullbright anyway we can just temporarily disable it. --- source/core/rendering/scene/hw_skyportal.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/core/rendering/scene/hw_skyportal.cpp b/source/core/rendering/scene/hw_skyportal.cpp index 22865de75..0d0e7260b 100644 --- a/source/core/rendering/scene/hw_skyportal.cpp +++ b/source/core/rendering/scene/hw_skyportal.cpp @@ -34,6 +34,8 @@ //----------------------------------------------------------------------------- void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state) { + int indexed = hw_int_useindexedcolortextures; + hw_int_useindexedcolortextures = false; // this code does not work with indexed textures. bool drawBoth = false; auto &vp = di->Viewpoint; @@ -101,6 +103,7 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state) //di->lightmode = oldlightmode; state.SetDepthClamp(oldClamp); -} + hw_int_useindexedcolortextures = indexed; + } const char *HWSkyPortal::GetName() { return "Sky"; } From 5984fda8a1c5739e205abb02544d60468e65a81a Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Mon, 5 Apr 2021 21:41:11 +1000 Subject: [PATCH 15/70] - PlayerAngle: Repair issues with `addadjustment()` method following changes in 4ffe0044832410f8c8650001f344abe1cc637cec that were affecting negative input. --- source/core/binaryangle.h | 4 +++- source/core/gameinput.h | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/source/core/binaryangle.h b/source/core/binaryangle.h index bec19e891..3cdc8dc49 100644 --- a/source/core/binaryangle.h +++ b/source/core/binaryangle.h @@ -122,6 +122,7 @@ class lookangle friend constexpr lookangle bamlook(int32_t v); friend constexpr lookangle q16look(int32_t v); friend constexpr lookangle buildlook(int32_t v); + friend lookangle buildflook(double v); friend lookangle radlook(double v); friend lookangle deglook(double v); @@ -224,7 +225,8 @@ public: inline constexpr lookangle bamlook(int32_t v) { return lookangle(v); } inline constexpr lookangle q16look(int32_t v) { return lookangle(v << 5); } inline constexpr lookangle buildlook(int32_t v) { return lookangle(v << BAMBITS); } -inline lookangle radlook(double v) { return lookangle(xs_CRoundToUInt(v * (0x80000000u / pi::pi()))); } +inline lookangle buildflook(double v) { return lookangle(xs_CRoundToInt(v * BAMUNIT)); } +inline lookangle radlook(double v) { return lookangle(xs_CRoundToInt(v * (0x80000000u / pi::pi()))); } inline lookangle deglook(double v) { return lookangle(FloatToAngle(v)); } inline FSerializer &Serialize(FSerializer &arc, const char *key, lookangle &obj, lookangle *defval) diff --git a/source/core/gameinput.h b/source/core/gameinput.h index 2fdc94b9a..39f9a12ff 100644 --- a/source/core/gameinput.h +++ b/source/core/gameinput.h @@ -149,22 +149,22 @@ struct PlayerAngle void addadjustment(int value) { - __addadjustment(buildang(value)); + __addadjustment(buildlook(value)); } void addadjustment(double value) { - __addadjustment(buildfang(value)); + __addadjustment(buildflook(value)); } void addadjustment(lookangle value) { - __addadjustment(bamang(value.asbam())); + __addadjustment(value); } void addadjustment(binangle value) { - __addadjustment(value); + __addadjustment(bamlook(value.asbam())); } void resetadjustment() @@ -254,7 +254,7 @@ private: binangle target; double adjustment; - void __addadjustment(binangle value) + void __addadjustment(lookangle value) { if (!SyncInput()) { From bfcedc2177ccb1b65d27d40f49adab18414f3b85 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Apr 2021 00:56:34 +0200 Subject: [PATCH 16/70] - autodetect .inis when loading Blood mods. This works as long as the loaded mods have one single .ini file in them - in that case it is assumed that it is supposed to replace blood.ini, which will allow dragging & dropping such archives without further user intervention. --- source/games/blood/src/levels.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/source/games/blood/src/levels.cpp b/source/games/blood/src/levels.cpp index ad1cd6ad9..462fbe316 100644 --- a/source/games/blood/src/levels.cpp +++ b/source/games/blood/src/levels.cpp @@ -115,6 +115,28 @@ void levelLoadMapInfo(IniFile *pIni, MapRecord *pLevelInfo, const char *pzSectio static const char* DefFile(void) { + int found = -1; + if (userConfig.DefaultCon.IsEmpty() || userConfig.DefaultCon.CompareNoCase("blood.ini") == 0) + { + int numlumps = fileSystem.GetNumEntries(); + for (int i = numlumps - 1; i >= 0; i--) + { + if (fileSystem.GetFileContainer(i) <= fileSystem.GetMaxIwadNum()) break; + FString fn = fileSystem.GetFileFullName(i, false); + FString ext = fn.Right(4); + if (ext.CompareNoCase(".ini") == 0) + { + if (fileSystem.CheckNumForFullName(fn) != i) continue; + if (found == -1) found = i; + else + { + found = -1; + break; + } + } + } + } + if (found >= 0) return fileSystem.GetFileFullName(found); // The command line parser stores this in the CON field. return userConfig.DefaultCon.IsNotEmpty() ? userConfig.DefaultCon.GetChars() : "blood.ini"; } From fc314b6616e14b83a40e8dca9cbe94caa2e4f08c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Apr 2021 01:06:03 +0200 Subject: [PATCH 17/70] - allow loading Zips where all content is in a subdirectory. The same logic as in GZDoom applies: The root must not have any other content and the subdirectory must contain identifiable game content. Some handling was also added to strip out macOS resource fork folders because they can contain data that can confuse file detection. --- source/common/filesystem/file_zip.cpp | 16 ++++++++++++---- source/core/initfs.cpp | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/source/common/filesystem/file_zip.cpp b/source/common/filesystem/file_zip.cpp index 00de98cdc..2adca1160 100644 --- a/source/common/filesystem/file_zip.cpp +++ b/source/common/filesystem/file_zip.cpp @@ -233,12 +233,14 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) } name.ToLower(); + if (name.IndexOf("__macosx") == 0) + continue; // skip Apple garbage. At this stage only the root folder matters, if (i == 0) { // check for special names, if one of these gets found this must be treated as a normal zip. bool isspecial = name.IndexOf("/") < 0 || (filter && filter->reservedFolders.Find(name) < filter->reservedFolders.Size()); if (isspecial) break; - name0 = name; + name0 = name.Left(name.LastIndexOf("/")+1); } else { @@ -252,7 +254,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) // at least one of the more common definition lumps must be present. for (auto &p : filter->requiredPrefixes) { - if (name.IndexOf(name0 + p) == 0) + if (name.IndexOf(name0 + p) == 0 || name.LastIndexOf(p) == name.Len() - strlen(p)) { foundspeciallump = true; break; @@ -272,7 +274,6 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) int len = LittleShort(zip_fh->NameLength); FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len); - if (name0.IsNotEmpty()) name = name.Mid(name0.Len()); dirptr += sizeof(FZipCentralDirectoryInfo) + LittleShort(zip_fh->NameLength) + LittleShort(zip_fh->ExtraLength) + @@ -284,7 +285,14 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars()); return false; } - + + if (name.IndexOf("__macosx") == 0 || name.IndexOf("__MACOSX") == 0) + { + skipped++; + continue; // Weed out Apple's resource fork garbage right here because it interferes with safe operation. + } + if (name0.IsNotEmpty()) name = name.Mid(name0.Len()); + // skip Directories if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize) == 0)) { diff --git a/source/core/initfs.cpp b/source/core/initfs.cpp index f18fd50d3..6910d2cdf 100644 --- a/source/core/initfs.cpp +++ b/source/core/initfs.cpp @@ -274,6 +274,18 @@ static void DeleteStuff(FileSystem &fileSystem, const TArray& deletelum // // //========================================================================== +const char* iwad_folders[13] = { "textures/", "hires/", "sounds/", "music/", "maps/" }; +const char* iwad_reserved_duke[12] = { ".map", ".con", "menudef", "gldefs", "zscript", "maps/", nullptr }; +const char* iwad_reserved_blood[12] = { ".map", ".ini", "menudef", "gldefs", "zscript", "maps/", nullptr }; +const char* iwad_reserved_sw[12] = { ".map", "swcustom.txt", "menudef", "gldefs", "zscript", "maps/", nullptr }; +const char* iwad_reserved_ex[12] = { ".map", "menudef", "gldefs", "zscript", "maps/", nullptr }; + +const char** iwad_reserved() +{ + return (g_gameType & GAMEFLAG_PSEXHUMED) ? iwad_reserved_ex : + (g_gameType & GAMEFLAG_SW) ? iwad_reserved_sw : + (g_gameType & GAMEFLAG_BLOOD) ? iwad_reserved_blood : iwad_reserved_duke; +} void InitFileSystem(TArray& groups) { @@ -374,6 +386,8 @@ void InitFileSystem(TArray& groups) } todelete.Append(userConfig.toBeDeleted); LumpFilterInfo lfi; + for (auto p : iwad_folders) lfi.reservedFolders.Push(p); + for (auto p = iwad_reserved(); *p; p++) lfi.requiredPrefixes.Push(*p); lfi.dotFilter = LumpFilter; From cbe25d9d6bc9b3b1acde13a7466df556ae87226d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Apr 2021 12:06:03 +0200 Subject: [PATCH 18/70] - Blood: disable look left and look right in the classic key configuration. --- source/common/console/c_bind.cpp | 6 ++++++ wadsrc/static/filter/blood/engine/origbinds.txt | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/source/common/console/c_bind.cpp b/source/common/console/c_bind.cpp index 1aad2d255..fa94d1e72 100644 --- a/source/common/console/c_bind.cpp +++ b/source/common/console/c_bind.cpp @@ -696,6 +696,12 @@ void ReadBindings(int lump, bool override) dest = &AutomapBindings; sc.MustGetString(); } + else if (sc.Compare("unbind")) + { + sc.MustGetString(); + dest->UnbindKey(sc.String); + continue; + } key = GetConfigKeyFromName(sc.String); sc.MustGetString(); dest->SetBind(key, sc.String, override); diff --git a/wadsrc/static/filter/blood/engine/origbinds.txt b/wadsrc/static/filter/blood/engine/origbinds.txt index 85f93e3dc..e13f235d1 100644 --- a/wadsrc/static/filter/blood/engine/origbinds.txt +++ b/wadsrc/static/filter/blood/engine/origbinds.txt @@ -8,3 +8,8 @@ X "+Alt_Fire" J "useitem 4" M "useitem 1" Mouse2 "+Alt_Fire" + +unbind KP0 +unbind KP. +unbind DEL +unbind INS From 424c0ce3f49e188c3fc2bd4adb834e97a559453e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Apr 2021 15:07:12 +0200 Subject: [PATCH 19/70] - testing some script parser improvements. --- source/build/src/defs.cpp | 11 +++----- source/common/engine/sc_man.h | 7 +++++ source/core/parsefuncs.h | 48 +++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 source/core/parsefuncs.h diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 0ed7faeb5..99beccbb3 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -17,6 +17,7 @@ #include "gamecontrol.h" #include "palettecontainer.h" #include "mapinfo.h" +#include "parsefuncs.h" int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor, uint8_t flags); int tileSetSkybox(int picnum, int palnum, const char** facenames, int flags); @@ -655,15 +656,9 @@ static int32_t defsparser(scriptfile *script) break; } case T_ANIMTILERANGE: - { - SetAnim set; - if (scriptfile_getsymbol(script,&set.tile1)) break; - if (scriptfile_getsymbol(script,&set.tile2)) break; - if (scriptfile_getsymbol(script,&set.speed)) break; - if (scriptfile_getsymbol(script,&set.type)) break; - processSetAnim("animtilerange", pos, set); + parseAnimTileRange(*script, pos); break; - } + case T_TILEFROMTEXTURE: { auto texturepos = scriptfile_getposition(script); diff --git a/source/common/engine/sc_man.h b/source/common/engine/sc_man.h index 6c37806a8..3a894fcb3 100644 --- a/source/common/engine/sc_man.h +++ b/source/common/engine/sc_man.h @@ -113,6 +113,13 @@ public: void MustGetNumber(bool evaluate = false); bool CheckNumber(bool evaluate = false); + bool GetNumber(int& var, bool evaluate = false) + { + if (!GetNumber(evaluate)) return false; + var = Number; + return true; + } + bool GetFloat(bool evaluate = false); void MustGetFloat(bool evaluate = false); bool CheckFloat(bool evaluate = false); diff --git a/source/core/parsefuncs.h b/source/core/parsefuncs.h new file mode 100644 index 000000000..05b3aa87b --- /dev/null +++ b/source/core/parsefuncs.h @@ -0,0 +1,48 @@ + +/* +** parsefuncs.h +** handlers for .def parser +** only to be included by the actual parser +** +**--------------------------------------------------------------------------- +** Copyright 2021 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +*/ + + +void parseAnimTileRange(FScanner& sc, FScriptPosition& pos) +{ + SetAnim set; + if (!sc.GetNumber(set.tile1, true)) return; + if (!sc.GetNumber(set.tile2, true)) return; + if (!sc.GetNumber(set.speed, true)) return; + if (!sc.GetNumber(set.type, true)) return; + processSetAnim("animtilerange", pos, set); +} + From d193e199f1c678983f5b97e2a4936613128335bb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Apr 2021 15:55:33 +0200 Subject: [PATCH 20/70] - reorganized hightile offset storage. --- source/build/src/defs.cpp | 32 ++++++++-------------- source/build/src/polymost.cpp | 10 +++---- source/core/gamefuncs.cpp | 16 +++++------ source/core/rendering/scene/hw_sprites.cpp | 10 +++---- source/core/rendering/scene/hw_walls.cpp | 6 ++-- source/core/textures/buildtiles.cpp | 2 +- source/core/textures/buildtiles.h | 8 ++++-- 7 files changed, 40 insertions(+), 44 deletions(-) diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index cf253152e..f11d366a3 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -617,38 +617,30 @@ static int32_t defsparser(scriptfile *script) if (check_tile("setuptile", tile, script, pos)) break; auto& tiled = TileFiles.tiledata[tile]; - if (scriptfile_getsymbol(script,&tmp)) break; // XXX - tiled.h_xsize = tmp; - if (scriptfile_getsymbol(script,&tmp)) break; - tiled.h_ysize = tmp; - if (scriptfile_getsymbol(script,&tmp)) break; - tiled.h_xoffs = tmp; - if (scriptfile_getsymbol(script,&tmp)) break; - tiled.h_yoffs = tmp; + if (scriptfile_getsymbol(script,&tiled.hiofs.xsize)) break; // XXX + if (scriptfile_getsymbol(script, &tiled.hiofs.ysize)) break; + if (scriptfile_getsymbol(script, &tiled.hiofs.xoffs)) break; + if (scriptfile_getsymbol(script, &tiled.hiofs.yoffs)) break; break; } case T_SETUPTILERANGE: { - int tile1,tile2,xsiz,ysiz,xoffs,yoffs,i; + int tile1,tile2; + TileOffs t; if (scriptfile_getsymbol(script,&tile1)) break; if (scriptfile_getsymbol(script,&tile2)) break; - if (scriptfile_getnumber(script,&xsiz)) break; - if (scriptfile_getnumber(script,&ysiz)) break; - if (scriptfile_getsymbol(script,&xoffs)) break; - if (scriptfile_getsymbol(script,&yoffs)) break; + if (scriptfile_getnumber(script,&t.xsize)) break; + if (scriptfile_getnumber(script,&t.ysize)) break; + if (scriptfile_getsymbol(script,&t.xoffs)) break; + if (scriptfile_getsymbol(script,&t.yoffs)) break; if (check_tile_range("setuptilerange", &tile1, &tile2, script, pos)) break; - for (i=tile1; i<=tile2; i++) + for (int i=tile1; i<=tile2; i++) { - auto& tiled = TileFiles.tiledata[i]; - - tiled.h_xsize = xsiz; - tiled.h_ysize = ysiz; - tiled.h_xoffs = xoffs; - tiled.h_yoffs = yoffs; + TileFiles.tiledata[i].hiofs = t; } break; diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index 31a4198e4..44423429a 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -2722,9 +2722,9 @@ void polymost_drawsprite(int32_t snum) if ((globalorientation & 48) != 48) // only non-voxel sprites should do this { - int const flag = hw_hightile && TileFiles.tiledata[globalpicnum].h_xsize; - off = { (int32_t)tspr->xoffset + (flag ? TileFiles.tiledata[globalpicnum].h_xoffs : tileLeftOffset(globalpicnum)), - (int32_t)tspr->yoffset + (flag ? TileFiles.tiledata[globalpicnum].h_yoffs : tileTopOffset(globalpicnum)) }; + int const flag = hw_hightile && TileFiles.tiledata[globalpicnum].hiofs.xsize; + off = { (int32_t)tspr->xoffset + (flag ? TileFiles.tiledata[globalpicnum].hiofs.xoffs : tileLeftOffset(globalpicnum)), + (int32_t)tspr->yoffset + (flag ? TileFiles.tiledata[globalpicnum].hiofs.yoffs : tileTopOffset(globalpicnum)) }; } int32_t method = DAMETH_MASK | DAMETH_CLAMPED; @@ -2784,8 +2784,8 @@ void polymost_drawsprite(int32_t snum) vec2_t tsiz; - if (hw_hightile && TileFiles.tiledata[globalpicnum].h_xsize) - tsiz = { TileFiles.tiledata[globalpicnum].h_xsize, TileFiles.tiledata[globalpicnum].h_ysize }; + if (hw_hightile && TileFiles.tiledata[globalpicnum].hiofs.xsize) + tsiz = { TileFiles.tiledata[globalpicnum].hiofs.xsize, TileFiles.tiledata[globalpicnum].hiofs.ysize }; else tsiz = { tileWidth(globalpicnum), tileHeight(globalpicnum) }; diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index c8bd0d41b..23191157e 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -191,10 +191,10 @@ void GetWallSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out, bool auto tex = tileGetTexture(spr->picnum); int width, leftofs; - if (render && hw_hightile && TileFiles.tiledata[spr->picnum].h_xsize) + if (render && hw_hightile && TileFiles.tiledata[spr->picnum].hiofs.xsize) { - width = TileFiles.tiledata[spr->picnum].h_xsize; - leftofs = (TileFiles.tiledata[spr->picnum].h_xoffs + spr->xoffset); + width = TileFiles.tiledata[spr->picnum].hiofs.xsize; + leftofs = (TileFiles.tiledata[spr->picnum].hiofs.xoffs + spr->xoffset); } else { @@ -227,12 +227,12 @@ void GetFlatSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out, bool auto tex = tileGetTexture(spr->picnum); int width, height, leftofs, topofs; - if (render && hw_hightile && TileFiles.tiledata[spr->picnum].h_xsize) + if (render && hw_hightile && TileFiles.tiledata[spr->picnum].hiofs.xsize) { - width = TileFiles.tiledata[spr->picnum].h_xsize * spr->xrepeat; - height = TileFiles.tiledata[spr->picnum].h_ysize * spr->yrepeat; - leftofs = (TileFiles.tiledata[spr->picnum].h_xoffs + spr->xoffset) * spr->xrepeat; - topofs = (TileFiles.tiledata[spr->picnum].h_yoffs + spr->yoffset) * spr->yrepeat; + width = TileFiles.tiledata[spr->picnum].hiofs.xsize * spr->xrepeat; + height = TileFiles.tiledata[spr->picnum].hiofs.ysize * spr->yrepeat; + leftofs = (TileFiles.tiledata[spr->picnum].hiofs.xoffs + spr->xoffset) * spr->xrepeat; + topofs = (TileFiles.tiledata[spr->picnum].hiofs.yoffs + spr->yoffset) * spr->yrepeat; } else { diff --git a/source/core/rendering/scene/hw_sprites.cpp b/source/core/rendering/scene/hw_sprites.cpp index b555fdd92..1637c1854 100644 --- a/source/core/rendering/scene/hw_sprites.cpp +++ b/source/core/rendering/scene/hw_sprites.cpp @@ -376,12 +376,12 @@ void HWSprite::Process(HWDrawInfo* di, spritetype* spr, sectortype* sector, int int tilenum = spr->picnum; int xsize, ysize, tilexoff, tileyoff; - if (hw_hightile && TileFiles.tiledata[tilenum].h_xsize) + if (hw_hightile && TileFiles.tiledata[tilenum].hiofs.xsize) { - xsize = TileFiles.tiledata[tilenum].h_xsize; - ysize = TileFiles.tiledata[tilenum].h_ysize; - tilexoff = TileFiles.tiledata[tilenum].h_xoffs; - tileyoff = TileFiles.tiledata[tilenum].h_yoffs; + xsize = TileFiles.tiledata[tilenum].hiofs.xsize; + ysize = TileFiles.tiledata[tilenum].hiofs.ysize; + tilexoff = TileFiles.tiledata[tilenum].hiofs.xoffs; + tileyoff = TileFiles.tiledata[tilenum].hiofs.yoffs; } else { diff --git a/source/core/rendering/scene/hw_walls.cpp b/source/core/rendering/scene/hw_walls.cpp index d21e7d911..673c2c726 100644 --- a/source/core/rendering/scene/hw_walls.cpp +++ b/source/core/rendering/scene/hw_walls.cpp @@ -1104,10 +1104,10 @@ void HWWall::ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* sect int height, topofs; - if (hw_hightile && TileFiles.tiledata[spr->picnum].h_xsize) + if (hw_hightile && TileFiles.tiledata[spr->picnum].hiofs.xsize) { - height = TileFiles.tiledata[spr->picnum].h_ysize; - topofs = (TileFiles.tiledata[spr->picnum].h_yoffs + spr->yoffset); + height = TileFiles.tiledata[spr->picnum].hiofs.ysize; + topofs = (TileFiles.tiledata[spr->picnum].hiofs.yoffs + spr->yoffset); } else { diff --git a/source/core/textures/buildtiles.cpp b/source/core/textures/buildtiles.cpp index cbddedbdb..2148b27a7 100644 --- a/source/core/textures/buildtiles.cpp +++ b/source/core/textures/buildtiles.cpp @@ -145,7 +145,7 @@ void BuildTiles::Init() tile.RotTile = { -1,-1 }; tile.replacement = ReplacementType::Art; tile.alphaThreshold = 0.5; - tile.h_xsize = 0; + tile.hiofs = {}; } } diff --git a/source/core/textures/buildtiles.h b/source/core/textures/buildtiles.h index c875f7084..d0d9d9cc8 100644 --- a/source/core/textures/buildtiles.h +++ b/source/core/textures/buildtiles.h @@ -256,6 +256,11 @@ struct RawCacheNode uint64_t lastUseTime; }; +struct TileOffs +{ + int xsize, ysize, xoffs, yoffs; +}; + struct TileDesc { FGameTexture* texture; // the currently active tile @@ -268,8 +273,7 @@ struct TileDesc float alphaThreshold; // Sprite offset hackery for hires replacements. This only gets used for sprites in the 3D view, nothing else. - uint16_t h_xsize, h_ysize; - int8_t h_xoffs, h_yoffs; + TileOffs hiofs; }; From 5c2335bbeba532e2d5e4e6030c5e9aadb9578148 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Apr 2021 16:22:24 +0200 Subject: [PATCH 21/70] - encapsulate setuptile(range) parsing in separate functions. --- source/build/src/defs.cpp | 36 ++++-------------------------------- source/core/parsefuncs.h | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index ab94457b0..55f382431 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -611,41 +611,13 @@ static int32_t defsparser(scriptfile *script) } break; case T_SETUPTILE: - { - int tile, tmp; - - if (scriptfile_getsymbol(script,&tile)) break; - if (check_tile("setuptile", tile, script, pos)) - break; - auto& tiled = TileFiles.tiledata[tile]; - if (scriptfile_getsymbol(script,&tiled.hiofs.xsize)) break; // XXX - if (scriptfile_getsymbol(script, &tiled.hiofs.ysize)) break; - if (scriptfile_getsymbol(script, &tiled.hiofs.xoffs)) break; - if (scriptfile_getsymbol(script, &tiled.hiofs.yoffs)) break; + parseSetupTile(*script, pos); break; - } + case T_SETUPTILERANGE: - { - int tile1,tile2; - TileOffs t; - - if (scriptfile_getsymbol(script,&tile1)) break; - if (scriptfile_getsymbol(script,&tile2)) break; - if (scriptfile_getnumber(script,&t.xsize)) break; - if (scriptfile_getnumber(script,&t.ysize)) break; - if (scriptfile_getsymbol(script,&t.xoffs)) break; - if (scriptfile_getsymbol(script,&t.yoffs)) break; - - if (check_tile_range("setuptilerange", &tile1, &tile2, script, pos)) - break; - - for (int i=tile1; i<=tile2; i++) - { - TileFiles.tiledata[i].hiofs = t; - } - + parseSetupTileRange(*script, pos); break; - } + case T_ANIMTILERANGE: parseAnimTileRange(*script, pos); break; diff --git a/source/core/parsefuncs.h b/source/core/parsefuncs.h index 05b3aa87b..498f3cdb7 100644 --- a/source/core/parsefuncs.h +++ b/source/core/parsefuncs.h @@ -35,6 +35,33 @@ ** */ +void parseSetupTile(FScanner& sc, FScriptPosition& pos) +{ + int tile; + if (!sc.GetNumber(tile, true)) return; + if (!ValidateTilenum("setuptile", tile, pos)) return; + auto& tiled = TileFiles.tiledata[tile]; + if (!sc.GetNumber(tiled.hiofs.xsize, true)) return; + if (!sc.GetNumber(tiled.hiofs.ysize, true)) return; + if (!sc.GetNumber(tiled.hiofs.xoffs, true)) return; + if (!sc.GetNumber(tiled.hiofs.yoffs, true)) return; +} + +void parseSetupTileRange(FScanner& sc, FScriptPosition& pos) +{ + int tilestart, tileend; + if (!sc.GetNumber(tilestart, true)) return; + if (!sc.GetNumber(tileend, true)) return; + if (!ValidateTileRange("setuptilerange", tilestart, tileend, pos)) return; + + TileOffs hiofs; + if (!sc.GetNumber(hiofs.xsize, true)) return; + if (!sc.GetNumber(hiofs.ysize, true)) return; + if (!sc.GetNumber(hiofs.xoffs, true)) return; + if (!sc.GetNumber(hiofs.yoffs, true)) return; + + for (int i = tilestart; i <= tileend; i++) TileFiles.tiledata[i].hiofs = hiofs; +} void parseAnimTileRange(FScanner& sc, FScriptPosition& pos) { From d823ae255e90d266aefe0f0e948b332d41db233f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Apr 2021 19:25:40 +0200 Subject: [PATCH 22/70] - fixed view clipping for portal sectors. All lines within the portal must neither be added to the clipper nor checked for obstruction by other parts of the map. --- .../core/rendering/scene/hw_bunchdrawer.cpp | 21 ++++++++++--------- source/core/rendering/scene/hw_bunchdrawer.h | 9 ++++---- source/core/rendering/scene/hw_drawinfo.cpp | 16 +++++++------- source/core/rendering/scene/hw_drawinfo.h | 4 ++-- source/core/rendering/scene/hw_portal.cpp | 7 ++++--- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/source/core/rendering/scene/hw_bunchdrawer.cpp b/source/core/rendering/scene/hw_bunchdrawer.cpp index 5f2572849..6c84a911c 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.cpp +++ b/source/core/rendering/scene/hw_bunchdrawer.cpp @@ -91,7 +91,7 @@ void BunchDrawer::StartScene() // //========================================================================== -void BunchDrawer::StartBunch(int sectnum, int linenum, binangle startan, binangle endan) +void BunchDrawer::StartBunch(int sectnum, int linenum, binangle startan, binangle endan, bool portal) { FBunch* bunch = &Bunches[LastBunch = Bunches.Reserve(1)]; @@ -99,6 +99,7 @@ void BunchDrawer::StartBunch(int sectnum, int linenum, binangle startan, binangl bunch->startline = bunch->endline = linenum; bunch->startangle = startan; bunch->endangle = endan; + bunch->portal = portal; } //========================================================================== @@ -182,7 +183,7 @@ bool BunchDrawer::CheckClip(walltype* wal) // //========================================================================== -int BunchDrawer::ClipLine(int line) +int BunchDrawer::ClipLine(int line, bool portal) { auto wal = &wall[line]; @@ -195,7 +196,7 @@ int BunchDrawer::ClipLine(int line) return CL_Skip; } - if (!clipper->SafeCheckRange(startAngle, endAngle)) + if (!portal && !clipper->SafeCheckRange(startAngle, endAngle)) { return CL_Skip; } @@ -203,7 +204,7 @@ int BunchDrawer::ClipLine(int line) if (wal->nextwall == -1 || (wal->cstat & CSTAT_WALL_1WAY) || CheckClip(wal)) { // one-sided - clipper->SafeAddClipRange(startAngle, endAngle); + if (!portal) clipper->SafeAddClipRange(startAngle, endAngle); return CL_Draw; } else @@ -225,7 +226,7 @@ void BunchDrawer::ProcessBunch(int bnch) ClipWall.Clock(); for (int i = bunch->startline; i <= bunch->endline; i++) { - int clipped = ClipLine(i); + int clipped = ClipLine(i, bunch->portal); if (clipped & CL_Draw) { @@ -250,7 +251,7 @@ void BunchDrawer::ProcessBunch(int bnch) if (clipped & CL_Pass) { ClipWall.Unclock(); - ProcessSector(wall[i].nextsector); + ProcessSector(wall[i].nextsector, false); ClipWall.Clock(); } } @@ -425,7 +426,7 @@ int BunchDrawer::FindClosestBunch() // //========================================================================== -void BunchDrawer::ProcessSector(int sectnum) +void BunchDrawer::ProcessSector(int sectnum, bool portal) { if (gotsector[sectnum]) return; gotsector.Set(sectnum); @@ -503,7 +504,7 @@ void BunchDrawer::ProcessSector(int sectnum) // situation where 2 bunches may overlap at both ends. startangle = ang1; - StartBunch(sectnum, sect->wallptr + i, ang1, ang2); + StartBunch(sectnum, sect->wallptr + i, ang1, ang2, portal); inbunch = true; } else @@ -520,11 +521,11 @@ void BunchDrawer::ProcessSector(int sectnum) // //========================================================================== -void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount) +void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount, bool portal) { Bsp.Clock(); for(unsigned i=0;i 0) { int closest = FindClosestBunch(); diff --git a/source/core/rendering/scene/hw_bunchdrawer.h b/source/core/rendering/scene/hw_bunchdrawer.h index dbf5329eb..ae030bf3a 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.h +++ b/source/core/rendering/scene/hw_bunchdrawer.h @@ -11,6 +11,7 @@ struct FBunch int sectnum; int startline; int endline; + bool portal; binangle startangle; // in pseudo angles for the clipper binangle endangle; }; @@ -38,19 +39,19 @@ private: }; void StartScene(); - void StartBunch(int sectnum, int linenum, binangle startan, binangle endan); + void StartBunch(int sectnum, int linenum, binangle startan, binangle endan, bool portal); void AddLineToBunch(int line, binangle newan); void DeleteBunch(int index); bool CheckClip(walltype* wal); - int ClipLine(int line); + int ClipLine(int line, bool portal); void ProcessBunch(int bnch); int WallInFront(int wall1, int wall2); int BunchInFront(FBunch* b1, FBunch* b2); int FindClosestBunch(); - void ProcessSector(int sectnum); + void ProcessSector(int sectnum, bool portal); public: void Init(HWDrawInfo* _di, Clipper* c, vec2_t& view); - void RenderScene(const int* viewsectors, unsigned sectcount); + void RenderScene(const int* viewsectors, unsigned sectcount, bool portal); const FixedBitArray& GotSector() const { return gotsector; } }; diff --git a/source/core/rendering/scene/hw_drawinfo.cpp b/source/core/rendering/scene/hw_drawinfo.cpp index 7f4a8d328..be7841bc0 100644 --- a/source/core/rendering/scene/hw_drawinfo.cpp +++ b/source/core/rendering/scene/hw_drawinfo.cpp @@ -364,7 +364,7 @@ void HWDrawInfo::DispatchSprites() // //----------------------------------------------------------------------------- -void HWDrawInfo::CreateScene() +void HWDrawInfo::CreateScene(bool portal) { const auto& vp = Viewpoint; @@ -387,9 +387,9 @@ void HWDrawInfo::CreateScene() vec2_t view = { int(vp.Pos.X * 16), int(vp.Pos.Y * -16) }; mDrawer.Init(this, mClipper, view); if (vp.SectNums) - mDrawer.RenderScene(vp.SectNums, vp.SectCount); + mDrawer.RenderScene(vp.SectNums, vp.SectCount, portal); else - mDrawer.RenderScene(&vp.SectCount, 1); + mDrawer.RenderScene(&vp.SectCount, 1, portal); SetupSprite.Clock(); gi->processSprites(tsprite, spritesortcnt, view.x, view.y, vp.Pos.Z * -256, bamang(vp.RotAngle), vp.TicFrac * 65536); @@ -422,7 +422,7 @@ void HWDrawInfo::CreateScene() mClipper->Clear(); mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1)); mDrawer.Init(this, mClipper, view); - mDrawer.RenderScene(&drawsect, 1); + mDrawer.RenderScene(&drawsect, 1, false); for (int i = 0; i < eff.geocnt; i++) { @@ -453,7 +453,7 @@ void HWDrawInfo::CreateScene() mClipper->Clear(); mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1)); mDrawer.Init(this, mClipper, view); - mDrawer.RenderScene(&drawsect, 1); + mDrawer.RenderScene(&drawsect, 1, false); for (int i = 0; i < eff.geocnt; i++) { @@ -670,7 +670,7 @@ void HWDrawInfo::Set3DViewport(FRenderState &state) // //----------------------------------------------------------------------------- -void HWDrawInfo::DrawScene(int drawmode) +void HWDrawInfo::DrawScene(int drawmode, bool portal) { static int recursion = 0; static int ssao_portals_available = 0; @@ -692,7 +692,7 @@ void HWDrawInfo::DrawScene(int drawmode) ssao_portals_available--; } - CreateScene(); + CreateScene(portal); auto& RenderState = *screen->RenderState(); RenderState.SetDepthMask(true); @@ -725,7 +725,7 @@ void HWDrawInfo::DrawScene(int drawmode) void HWDrawInfo::ProcessScene(bool toscreen) { portalState.BeginScene(); - DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN); + DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN, false); if (toscreen && isBlood()) { gotsector = mDrawer.GotSector(); // Blood needs this to implement some lighting effect hacks. Needs to be refactored to use better info. diff --git a/source/core/rendering/scene/hw_drawinfo.h b/source/core/rendering/scene/hw_drawinfo.h index dc223ed21..9e7995f0a 100644 --- a/source/core/rendering/scene/hw_drawinfo.h +++ b/source/core/rendering/scene/hw_drawinfo.h @@ -158,8 +158,8 @@ public: void ClearBuffers(); HWDrawInfo *EndDrawInfo(); - void DrawScene(int drawmode); - void CreateScene(); + void DrawScene(int drawmode, bool portal); + void CreateScene(bool portal); void DispatchSprites(); void RenderScene(FRenderState &state); void RenderTranslucent(FRenderState &state); diff --git a/source/core/rendering/scene/hw_portal.cpp b/source/core/rendering/scene/hw_portal.cpp index 5d97679ba..016725636 100644 --- a/source/core/rendering/scene/hw_portal.cpp +++ b/source/core/rendering/scene/hw_portal.cpp @@ -400,9 +400,10 @@ void HWScenePortalBase::DrawContents(HWDrawInfo* di, FRenderState& state) { if (Setup(di, state, di->mClipper)) { - gi->EnterPortal(di->Viewpoint.CameraSprite, GetType()); - di->DrawScene(DM_PORTAL); - gi->LeavePortal(di->Viewpoint.CameraSprite, GetType()); + auto type = GetType(); + gi->EnterPortal(di->Viewpoint.CameraSprite, type); + di->DrawScene(DM_PORTAL, type == PORTAL_SECTOR_CEILING); + gi->LeavePortal(di->Viewpoint.CameraSprite, type); Shutdown(di, state); } else state.ClearScreen(); From 3d846f341a21f27002a716b90fac5529cb17954a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 Apr 2021 00:02:36 +0200 Subject: [PATCH 23/70] - fixed a major clipping issue with the new renderer. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * the bunch drawer can at most process an angular range of 180°. If this gets exceeded it can run into wraparound issues that may cause holes in the geometry. * there was no clipping to the current field of view so it always checked the full 360°. --- .../core/rendering/scene/hw_bunchdrawer.cpp | 74 +++++++++++-------- source/core/rendering/scene/hw_bunchdrawer.h | 4 +- source/core/rendering/scene/hw_drawinfo.cpp | 13 ++-- 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/source/core/rendering/scene/hw_bunchdrawer.cpp b/source/core/rendering/scene/hw_bunchdrawer.cpp index 6c84a911c..95a520f36 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.cpp +++ b/source/core/rendering/scene/hw_bunchdrawer.cpp @@ -49,8 +49,10 @@ // //========================================================================== -void BunchDrawer::Init(HWDrawInfo *_di, Clipper* c, vec2_t& view) +void BunchDrawer::Init(HWDrawInfo *_di, Clipper* c, vec2_t& view, binangle a1, binangle a2) { + ang1 = a1; + ang2 = a2; di = _di; clipper = c; viewx = view.x * (1/ 16.f); @@ -83,6 +85,7 @@ void BunchDrawer::StartScene() Bunches.Clear(); CompareData.Clear(); gotsector.Zero(); + gotwall.Zero(); } //========================================================================== @@ -232,8 +235,9 @@ void BunchDrawer::ProcessBunch(int bnch) { show2dwall.Set(i); - //if (gl_render_walls) + if (!gotwall[i]) { + gotwall.Set(i); ClipWall.Unclock(); Bsp.Unclock(); SetupWall.Clock(); @@ -480,36 +484,25 @@ void BunchDrawer::ProcessSector(int sectnum, bool portal) DVector2 start = { WallStartX(thiswall), WallStartY(thiswall) }; DVector2 end = { WallStartX(thiswall->point2), WallStartY(thiswall->point2) }; #endif - binangle ang1 = thiswall->clipangle; - binangle ang2 = wall[thiswall->point2].clipangle; + binangle walang1 = thiswall->clipangle; + binangle walang2 = wall[thiswall->point2].clipangle; - if (ang1.asbam() - ang2.asbam() < ANGLE_180) + // outside the visible area or seen from the backside. + if ((walang1.asbam() - ang1.asbam() > ANGLE_180 && walang2.asbam() - ang1.asbam() > ANGLE_180) || + (walang1.asbam() - ang2.asbam() < ANGLE_180 && walang2.asbam() - ang2.asbam() < ANGLE_180) || + (walang1.asbam() - walang2.asbam() < ANGLE_180)) { - // Backside inbunch = false; } - /* disabled because it only fragments the bunches without any performance gain. - else if (!clipper->SafeCheckRange(ang1, ang2)) + else if (!inbunch) { - // is it visible? - inbunch = false; - } - */ - else if (!inbunch || ang2.asbam() - startangle.asbam() >= ANGLE_180) - { - // don't let a bunch span more than 180° to avoid problems. - // This limitation ensures that the combined range of 2 - // bunches will always be less than 360° which simplifies - // the distance comparison code because it prevents a - // situation where 2 bunches may overlap at both ends. - - startangle = ang1; - StartBunch(sectnum, sect->wallptr + i, ang1, ang2, portal); + startangle = walang1; + StartBunch(sectnum, sect->wallptr + i, walang1, walang2, portal); inbunch = true; } else { - AddLineToBunch(sect->wallptr + i, ang2); + AddLineToBunch(sect->wallptr + i, walang2); } if (thiswall->point2 != sect->wallptr + i + 1) inbunch = false; } @@ -523,14 +516,35 @@ void BunchDrawer::ProcessSector(int sectnum, bool portal) void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount, bool portal) { - Bsp.Clock(); - for(unsigned i=0;i 0) + auto process = [&]() { - int closest = FindClosestBunch(); - ProcessBunch(closest); - DeleteBunch(closest); + for (unsigned i = 0; i < sectcount; i++) + ProcessSector(viewsectors[i], portal); + while (Bunches.Size() > 0) + { + int closest = FindClosestBunch(); + ProcessBunch(closest); + DeleteBunch(closest); + } + }; + + Bsp.Clock(); + if (ang1.asbam() != 0 || ang2.asbam() != 0) + { + process(); + } + else + { + // with a 360° field of view we need to split the scene into two halves. + // The BunchInFront check can fail with angles that may wrap around. + auto rotang = di->Viewpoint.RotAngle; + ang1 = bamang(rotang - ANGLE_90); + ang2 = bamang(rotang + ANGLE_90); + process(); + clipper->Clear(); + ang1 = bamang(rotang + ANGLE_90); + ang2 = bamang(rotang - ANGLE_90); + process(); } Bsp.Unclock(); } diff --git a/source/core/rendering/scene/hw_bunchdrawer.h b/source/core/rendering/scene/hw_bunchdrawer.h index ae030bf3a..d72454cd5 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.h +++ b/source/core/rendering/scene/hw_bunchdrawer.h @@ -28,6 +28,8 @@ class BunchDrawer vec2_t iview; float gcosang, gsinang; FixedBitArray gotsector; + FixedBitArray gotwall; + binangle ang1, ang2; private: @@ -51,7 +53,7 @@ private: void ProcessSector(int sectnum, bool portal); public: - void Init(HWDrawInfo* _di, Clipper* c, vec2_t& view); + void Init(HWDrawInfo* _di, Clipper* c, vec2_t& view, binangle a1, binangle a2); void RenderScene(const int* viewsectors, unsigned sectcount, bool portal); const FixedBitArray& GotSector() const { return gotsector; } }; diff --git a/source/core/rendering/scene/hw_drawinfo.cpp b/source/core/rendering/scene/hw_drawinfo.cpp index be7841bc0..196734a83 100644 --- a/source/core/rendering/scene/hw_drawinfo.cpp +++ b/source/core/rendering/scene/hw_drawinfo.cpp @@ -211,7 +211,7 @@ angle_t HWDrawInfo::FrustumAngle() // but at least it doesn't overestimate too much... double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*Viewpoint.FieldOfView.Degrees*48.0 / AspectMultiplier(WidescreenRatio) / 90.0; angle_t a1 = DAngle(floatangle).BAMs(); - if (a1 >= ANGLE_180) return 0xffffffff; + if (a1 >= ANGLE_90) return 0xffffffff; // it's either below 90 or bust. return a1; } @@ -369,7 +369,7 @@ void HWDrawInfo::CreateScene(bool portal) const auto& vp = Viewpoint; angle_t a1 = FrustumAngle(); - mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1)); + if (a1 != 0xffffffff) mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1)); // reset the portal manager portalState.StartFrame(); @@ -385,7 +385,8 @@ void HWDrawInfo::CreateScene(bool portal) geoofs = { 0,0 }; vec2_t view = { int(vp.Pos.X * 16), int(vp.Pos.Y * -16) }; - mDrawer.Init(this, mClipper, view); + if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1)); + else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0)); if (vp.SectNums) mDrawer.RenderScene(vp.SectNums, vp.SectCount, portal); else @@ -421,7 +422,8 @@ void HWDrawInfo::CreateScene(bool portal) mClipper->Clear(); mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1)); - mDrawer.Init(this, mClipper, view); + if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1)); + else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0)); mDrawer.RenderScene(&drawsect, 1, false); for (int i = 0; i < eff.geocnt; i++) @@ -452,7 +454,8 @@ void HWDrawInfo::CreateScene(bool portal) mClipper->Clear(); mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1)); - mDrawer.Init(this, mClipper, view); + if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1)); + else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0)); mDrawer.RenderScene(&drawsect, 1, false); for (int i = 0; i < eff.geocnt; i++) From f9f1d591b3e19c67090d78533ea1edc4b6bcb6db Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 Apr 2021 10:30:49 +0200 Subject: [PATCH 24/70] - must set up fog before textures. Otherwise the PickTexture callback won't get all needed info. --- source/core/rendering/scene/hw_walls.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/source/core/rendering/scene/hw_walls.cpp b/source/core/rendering/scene/hw_walls.cpp index 673c2c726..8d74b0437 100644 --- a/source/core/rendering/scene/hw_walls.cpp +++ b/source/core/rendering/scene/hw_walls.cpp @@ -190,11 +190,8 @@ void HWWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) { - //int tmode = state.GetTextureMode(); - - state.SetMaterial(texture, UF_Texture, 0, sprite == nullptr? (flags & (HWF_CLAMPX | HWF_CLAMPY)) : CLAMP_XY, TRANSLATION(Translation_Remap + curbasepal, palette), -1); - SetLightAndFog(state); + state.SetMaterial(texture, UF_Texture, 0, sprite == nullptr ? (flags & (HWF_CLAMPX | HWF_CLAMPY)) : CLAMP_XY, TRANSLATION(Translation_Remap + curbasepal, palette), -1); int h = (int)texture->GetDisplayHeight(); int h2 = 1 << sizeToBits(h); From 59f18f5fa791f005e19d21b008f3a08bd9961bfa Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 Apr 2021 12:31:47 +0200 Subject: [PATCH 25/70] - ensure that all HWSprites are oriented with z1 > z2. This is required by the sorting code to work as intended. --- source/core/rendering/scene/hw_sprites.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/core/rendering/scene/hw_sprites.cpp b/source/core/rendering/scene/hw_sprites.cpp index 1637c1854..888a8b429 100644 --- a/source/core/rendering/scene/hw_sprites.cpp +++ b/source/core/rendering/scene/hw_sprites.cpp @@ -437,6 +437,12 @@ void HWSprite::Process(HWDrawInfo* di, spritetype* spr, sectortype* sector, int z1 = z + yoff; z2 = z + height + yoff; + if (z1 < z2) + { + // Make sure that z1 is the higher one. Some utilities expect it to be oriented this way. + std::swap(z1, z2); + std::swap(vt, vb); + } } else { From 6ad0089524eea9afa159309911360304265bbb28 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 Apr 2021 12:39:12 +0200 Subject: [PATCH 26/70] - fixed flat sprites using the sector bit names for checking for being flipped. Thank you, autocompletion... :( --- source/core/rendering/scene/hw_flats.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/core/rendering/scene/hw_flats.cpp b/source/core/rendering/scene/hw_flats.cpp index a964e9aaa..2be5262c7 100644 --- a/source/core/rendering/scene/hw_flats.cpp +++ b/source/core/rendering/scene/hw_flats.cpp @@ -124,8 +124,8 @@ void HWFlat::MakeVertices() auto ret = screen->mVertexData->AllocVertices(6); auto vp = ret.first; - float x = !(sprite->cstat & CSTAT_SECTOR_XFLIP) ? 0.f : 1.f; - float y = !(sprite->cstat & CSTAT_SECTOR_YFLIP) ? 0.f : 1.f; + float x = !(sprite->cstat & CSTAT_SPRITE_XFLIP) ? 0.f : 1.f; + float y = !(sprite->cstat & CSTAT_SPRITE_YFLIP) ? 0.f : 1.f; for (unsigned i = 0; i < 6; i++) { const static unsigned indices[] = { 0, 1, 2, 0, 2, 3 }; From 4bd44f9d6275f6c9fc0098a598987d7f85d8f221 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 Apr 2021 12:58:45 +0200 Subject: [PATCH 27/70] - flat sprites use different visibility rules. Hooray, Build engine, yet another totally nonsensical magic factor with absolutely no reason why... --- source/core/rendering/scene/hw_flats.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/core/rendering/scene/hw_flats.cpp b/source/core/rendering/scene/hw_flats.cpp index 2be5262c7..f7d61fd0e 100644 --- a/source/core/rendering/scene/hw_flats.cpp +++ b/source/core/rendering/scene/hw_flats.cpp @@ -366,7 +366,7 @@ void HWFlat::ProcessFlatSprite(HWDrawInfo* di, spritetype* sprite, sectortype* s z = sprite->z * (1 / -256.f); if (z == di->Viewpoint.Pos.Z) return; // looking right at the edge. - visibility = sectorVisibility(§or[sprite->sectnum]);// *(4.f / 5.f); // The factor comes directly from Polymost. No idea why this uses a different visibility setting. Bad projection math? + visibility = sectorVisibility(§or[sprite->sectnum]) *(4.f / 5.f); // The factor comes directly from Polymost. What is it with Build and these magic factors? // Weird Build logic that really makes no sense. if ((sprite->cstat & CSTAT_SPRITE_ONE_SIDED) != 0 && (di->Viewpoint.Pos.Z < z) == ((sprite->cstat & CSTAT_SPRITE_YFLIP) == 0)) From 4a6a999f89f418d1a7e276b2905a74f98d84deb8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 Apr 2021 15:03:00 +0200 Subject: [PATCH 28/70] - SW: fixed interpolation for sector object sprites. When checking for an existing interpolation it needs to check the actual sprite, not just the interpolation type. --- source/games/sw/src/interpso.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/source/games/sw/src/interpso.cpp b/source/games/sw/src/interpso.cpp index cb5ef9e1c..bcb2c9612 100644 --- a/source/games/sw/src/interpso.cpp +++ b/source/games/sw/src/interpso.cpp @@ -108,8 +108,10 @@ static void so_setpointinterpolation(so_interp *interp, int element) return; for (i = 0; i < interp->numinterpolations; i++) + { if (interp->data[i].curelement == element) return; + } so_interp::interp_data *data = &interp->data[interp->numinterpolations++]; @@ -127,7 +129,7 @@ static void so_setspriteanginterpolation(so_interp *interp, int32_t spritenum) return; for (i = 0; i < interp->numinterpolations; i++) - if (interp->data[i].curelement == -1) + if (interp->data[i].curelement == -1 && interp->data[i].spriteofang == spritenum) return; so_interp::interp_data *data = &interp->data[interp->numinterpolations++]; @@ -146,9 +148,16 @@ static void so_stopdatainterpolation(so_interp *interp, int element) int32_t i; for (i = 0; i < interp->numinterpolations; i++) - if (interp->data[i].curelement == element) + { + if (interp->data[i].curelement == -1) + { + if (interp->data[i].spriteofang == element) break; + } + else if (interp->data[i].curelement == element) break; + } + if (i == interp->numinterpolations) return; @@ -217,7 +226,7 @@ void so_setspriteinterpolation(SECTOR_OBJECTp sop, spritetype *sp) so_setpointinterpolation(interp, snum | soi_spry); if (!interp->hasvator) so_setpointinterpolation(interp, snum | soi_sprz); - so_setspriteanginterpolation(interp, int(sp - sprite)); + so_setspriteanginterpolation(interp, snum); } void so_stopspriteinterpolation(SECTOR_OBJECTp sop, spritetype *sp) From caa8efd3d53b1a71b9d5d7162ec17e27581c1325 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 Apr 2021 16:09:25 +0200 Subject: [PATCH 29/70] - fixed renderer to avoid bunches of walls that wrap around behind the camera's back. --- .../core/rendering/scene/hw_bunchdrawer.cpp | 21 ++++++++++++------- source/core/rendering/scene/hw_bunchdrawer.h | 6 +++--- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/source/core/rendering/scene/hw_bunchdrawer.cpp b/source/core/rendering/scene/hw_bunchdrawer.cpp index 95a520f36..955aa7f3d 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.cpp +++ b/source/core/rendering/scene/hw_bunchdrawer.cpp @@ -94,15 +94,16 @@ void BunchDrawer::StartScene() // //========================================================================== -void BunchDrawer::StartBunch(int sectnum, int linenum, binangle startan, binangle endan, bool portal) +bool BunchDrawer::StartBunch(int sectnum, int linenum, binangle startan, binangle endan, bool portal) { FBunch* bunch = &Bunches[LastBunch = Bunches.Reserve(1)]; bunch->sectnum = sectnum; bunch->startline = bunch->endline = linenum; - bunch->startangle = startan; - bunch->endangle = endan; + bunch->startangle = (startan.asbam() - ang1.asbam()) > ANGLE_180? ang1 :startan; + bunch->endangle = (endan.asbam() - ang2.asbam()) < ANGLE_180 ? ang2 : endan; bunch->portal = portal; + return bunch->endangle != ang2; } //========================================================================== @@ -111,10 +112,11 @@ void BunchDrawer::StartBunch(int sectnum, int linenum, binangle startan, binangl // //========================================================================== -void BunchDrawer::AddLineToBunch(int line, binangle newan) +bool BunchDrawer::AddLineToBunch(int line, binangle newan) { Bunches[LastBunch].endline++; - Bunches[LastBunch].endangle = newan; + Bunches[LastBunch].endangle = (newan.asbam() - ang2.asbam()) < ANGLE_180 ? ang2 : newan; + return Bunches[LastBunch].endangle != ang2; } //========================================================================== @@ -421,6 +423,7 @@ int BunchDrawer::FindClosestBunch() } } + //Printf("picked bunch starting at %d\n", Bunches[closest].startline); return closest; } @@ -497,12 +500,13 @@ void BunchDrawer::ProcessSector(int sectnum, bool portal) else if (!inbunch) { startangle = walang1; - StartBunch(sectnum, sect->wallptr + i, walang1, walang2, portal); - inbunch = true; + //Printf("Starting bunch:\n\tWall %d\n", sect->wallptr + i); + inbunch = StartBunch(sectnum, sect->wallptr + i, walang1, walang2, portal); } else { - AddLineToBunch(sect->wallptr + i, walang2); + //Printf("\tWall %d\n", sect->wallptr + i); + inbunch = AddLineToBunch(sect->wallptr + i, walang2); } if (thiswall->point2 != sect->wallptr + i + 1) inbunch = false; } @@ -516,6 +520,7 @@ void BunchDrawer::ProcessSector(int sectnum, bool portal) void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount, bool portal) { + //Printf("----------------------------------------- \n"); auto process = [&]() { for (unsigned i = 0; i < sectcount; i++) diff --git a/source/core/rendering/scene/hw_bunchdrawer.h b/source/core/rendering/scene/hw_bunchdrawer.h index d72454cd5..9182ef76a 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.h +++ b/source/core/rendering/scene/hw_bunchdrawer.h @@ -12,7 +12,7 @@ struct FBunch int startline; int endline; bool portal; - binangle startangle; // in pseudo angles for the clipper + binangle startangle; binangle endangle; }; @@ -41,8 +41,8 @@ private: }; void StartScene(); - void StartBunch(int sectnum, int linenum, binangle startan, binangle endan, bool portal); - void AddLineToBunch(int line, binangle newan); + bool StartBunch(int sectnum, int linenum, binangle startan, binangle endan, bool portal); + bool AddLineToBunch(int line, binangle newan); void DeleteBunch(int index); bool CheckClip(walltype* wal); int ClipLine(int line, bool portal); From 7a03967ceb3f00e59e4c179cd9b762affabdfec8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 Apr 2021 16:52:17 +0200 Subject: [PATCH 30/70] - fixed clipping info not properly reset when rendering the scene in two passes. We need to reset the gotsector array for that, but since we also need the accumulate result of both passes there's now two such arrays. --- .../core/rendering/scene/hw_bunchdrawer.cpp | 46 +++++++++++-------- source/core/rendering/scene/hw_bunchdrawer.h | 1 + source/core/rendering/scene/hw_walls.cpp | 1 - 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/source/core/rendering/scene/hw_bunchdrawer.cpp b/source/core/rendering/scene/hw_bunchdrawer.cpp index 955aa7f3d..23168b8da 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.cpp +++ b/source/core/rendering/scene/hw_bunchdrawer.cpp @@ -85,6 +85,7 @@ void BunchDrawer::StartScene() Bunches.Clear(); CompareData.Clear(); gotsector.Zero(); + gotsector2.Zero(); gotwall.Zero(); } @@ -435,8 +436,8 @@ int BunchDrawer::FindClosestBunch() void BunchDrawer::ProcessSector(int sectnum, bool portal) { - if (gotsector[sectnum]) return; - gotsector.Set(sectnum); + if (gotsector2[sectnum]) return; + gotsector2.Set(sectnum); auto sect = §or[sectnum]; bool inbunch; @@ -445,28 +446,32 @@ void BunchDrawer::ProcessSector(int sectnum, bool portal) SetupSprite.Clock(); int z; - SectIterator it(sectnum); - while ((z = it.NextIndex()) >= 0) + if (!gotsector[sectnum]) { - auto const spr = (uspriteptr_t)&sprite[z]; - - if ((spr->cstat & CSTAT_SPRITE_INVISIBLE) || spr->xrepeat == 0 || spr->yrepeat == 0) // skip invisible sprites - continue; - - int sx = spr->x - iview.x, sy = spr->y - int(iview.y); - - // this checks if the sprite is it behind the camera, which will not work if the pitch is high enough to necessitate a FOV of more than 180°. - //if ((spr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) || (hw_models && tile2model[spr->picnum].modelid >= 0) || ((sx * gcosang) + (sy * gsinang) > 0)) + gotsector.Set(sectnum); + SectIterator it(sectnum); + while ((z = it.NextIndex()) >= 0) { - if ((spr->cstat & (CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_ALIGNMENT_MASK)) != (CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_ALIGNMENT_WALL) || - (r_voxels && tiletovox[spr->picnum] >= 0 && voxmodels[tiletovox[spr->picnum]]) || - (r_voxels && gi->Voxelize(spr->picnum)) || - DMulScale(bcos(spr->ang), -sx, bsin(spr->ang), -sy, 6) > 0) - if (renderAddTsprite(di->tsprite, di->spritesortcnt, z, sectnum)) - break; + auto const spr = (uspriteptr_t)&sprite[z]; + + if ((spr->cstat & CSTAT_SPRITE_INVISIBLE) || spr->xrepeat == 0 || spr->yrepeat == 0) // skip invisible sprites + continue; + + int sx = spr->x - iview.x, sy = spr->y - int(iview.y); + + // this checks if the sprite is it behind the camera, which will not work if the pitch is high enough to necessitate a FOV of more than 180°. + //if ((spr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) || (hw_models && tile2model[spr->picnum].modelid >= 0) || ((sx * gcosang) + (sy * gsinang) > 0)) + { + if ((spr->cstat & (CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_ALIGNMENT_MASK)) != (CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_ALIGNMENT_WALL) || + (r_voxels && tiletovox[spr->picnum] >= 0 && voxmodels[tiletovox[spr->picnum]]) || + (r_voxels && gi->Voxelize(spr->picnum)) || + DMulScale(bcos(spr->ang), -sx, bsin(spr->ang), -sy, 6) > 0) + if (renderAddTsprite(di->tsprite, di->spritesortcnt, z, sectnum)) + break; + } } + SetupSprite.Unclock(); } - SetupSprite.Unclock(); if (automapping) show2dsector.Set(sectnum); @@ -547,6 +552,7 @@ void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount, bool p ang2 = bamang(rotang + ANGLE_90); process(); clipper->Clear(); + gotsector2.Zero(); ang1 = bamang(rotang + ANGLE_90); ang2 = bamang(rotang - ANGLE_90); process(); diff --git a/source/core/rendering/scene/hw_bunchdrawer.h b/source/core/rendering/scene/hw_bunchdrawer.h index 9182ef76a..d8906c6c8 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.h +++ b/source/core/rendering/scene/hw_bunchdrawer.h @@ -28,6 +28,7 @@ class BunchDrawer vec2_t iview; float gcosang, gsinang; FixedBitArray gotsector; + FixedBitArray gotsector2; FixedBitArray gotwall; binangle ang1, ang2; diff --git a/source/core/rendering/scene/hw_walls.cpp b/source/core/rendering/scene/hw_walls.cpp index 8d74b0437..7117bbac1 100644 --- a/source/core/rendering/scene/hw_walls.cpp +++ b/source/core/rendering/scene/hw_walls.cpp @@ -1046,7 +1046,6 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec } } } - globalr = globalg = globalb = 255; } void HWWall::ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* sector) From 68b7628f56c85a89d2bf0210d29c318fa439faad Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 Apr 2021 18:12:25 +0200 Subject: [PATCH 31/70] - RRRA: Sector effector type 156 is not supposed to scroll the floor texture. --- source/games/duke/src/actors.cpp | 4 ++-- source/games/duke/src/actors_d.cpp | 2 +- source/games/duke/src/actors_r.cpp | 2 +- source/games/duke/src/funct.h | 2 +- source/games/duke/src/spawn.cpp | 3 ++- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index 04d9e311e..ccce5da8c 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -4505,7 +4505,7 @@ void handle_se27(DDukeActor* actor) // //--------------------------------------------------------------------------- -void handle_se24(DDukeActor *actor, int16_t *list1, int16_t *list2, int TRIPBOMB, int LASERLINE, int CRANE, int shift) +void handle_se24(DDukeActor *actor, int16_t *list1, int16_t *list2, bool scroll, int TRIPBOMB, int LASERLINE, int CRANE, int shift) { int* t = &actor->temp_data[0]; @@ -4575,7 +4575,7 @@ void handle_se24(DDukeActor *actor, int16_t *list1, int16_t *list2, int TRIPBOMB } } } - sector[actor->s.sectnum].addfloorxpan(actor->s.yvel / 128.f); + if (scroll) sector[actor->s.sectnum].addfloorxpan(actor->s.yvel / 128.f); } //--------------------------------------------------------------------------- diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index 3ceaf8ed2..308866bd8 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -3697,7 +3697,7 @@ void moveeffectors_d(void) //STATNUM 3 { static int16_t list1[] = { BLOODPOOL, PUKE, FOOTPRINTS, FOOTPRINTS2, FOOTPRINTS3, FOOTPRINTS4, BULLETHOLE, BLOODSPLAT1, BLOODSPLAT2, BLOODSPLAT3, BLOODSPLAT4, -1 }; static int16_t list2[] = { BOLT1, BOLT1 + 1,BOLT1 + 2, BOLT1 + 3, SIDEBOLT1, SIDEBOLT1 + 1, SIDEBOLT1 + 2, SIDEBOLT1 + 3, -1 }; - handle_se24(act, list1, list2, TRIPBOMB, LASERLINE, CRANE, 2); + handle_se24(act, list1, list2, false, TRIPBOMB, LASERLINE, CRANE, 2); break; } case SE_35: diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index a6935be5a..f4988af0d 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -3576,7 +3576,7 @@ void moveeffectors_r(void) //STATNUM 3 { static int16_t list1[] = { BLOODPOOL, PUKE, FOOTPRINTS, FOOTPRINTS2, FOOTPRINTS3, -1 }; static int16_t list2[] = { BOLT1, BOLT1 + 1,BOLT1 + 2, BOLT1 + 3, -1 }; - handle_se24(act, list1, list2, BULLETHOLE, -1, CRANE, 1); + handle_se24(act, list1, list2, st != 156, BULLETHOLE, -1, CRANE, 1); break; } diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index 29a56af54..1785fabce 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -84,7 +84,7 @@ void handle_se19(DDukeActor* i, int BIGFORCE); void handle_se20(DDukeActor* i); void handle_se21(DDukeActor* i); void handle_se22(DDukeActor* i); -void handle_se24(DDukeActor* actor, int16_t* list1, int16_t* list2, int TRIPBOMB, int LASERLINE, int CRANE, int shift); +void handle_se24(DDukeActor* actor, int16_t* list1, int16_t* list2, bool scroll, int TRIPBOMB, int LASERLINE, int CRANE, int shift); void handle_se25(DDukeActor* a, int t_index, int snd1, int snd2); void handle_se26(DDukeActor* i); void handle_se27(DDukeActor* i); diff --git a/source/games/duke/src/spawn.cpp b/source/games/duke/src/spawn.cpp index 1a85073a5..11f64ca7d 100644 --- a/source/games/duke/src/spawn.cpp +++ b/source/games/duke/src/spawn.cpp @@ -785,7 +785,8 @@ void spawneffector(DDukeActor* actor) break; } case 156: - if (!isRRRA()) break; + break; + case 34: StartInterpolation(sect, Interp_Sect_FloorPanX); break; From 58fb938aa7c3617d1efc2653c23b2c86d008e7f6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 Apr 2021 19:39:48 +0200 Subject: [PATCH 32/70] - block opening of the menu in the fade out phase of a screenjob and in Exhumed's map/intermission screens. At these places there's some inteference that can bring the engine into an unstable state. This is not a real fix, just a quick workaround. The actual problem requires closer examination why these are the only places where this happens. --- source/core/mainloop.cpp | 1 + source/core/screenjob.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/source/core/mainloop.cpp b/source/core/mainloop.cpp index 286f016cb..efdd496d4 100644 --- a/source/core/mainloop.cpp +++ b/source/core/mainloop.cpp @@ -189,6 +189,7 @@ static void GameTicker() case ga_newgame: FX_StopAllSounds(); case ga_newgamenostopsound: + DeleteScreenJob(); newGameStarted = true; FX_SetReverb(0); gi->FreeLevelData(); diff --git a/source/core/screenjob.cpp b/source/core/screenjob.cpp index 886ade1c1..97413104e 100644 --- a/source/core/screenjob.cpp +++ b/source/core/screenjob.cpp @@ -915,6 +915,7 @@ public: startTime = -1; clock = 0; jobs[index].job->fadestate = DScreenJob::fadeout; + gamestate = GS_INTRO; // block menu and console during fadeout - this can cause timing problems. actionState = State_Fadeout; } else @@ -959,6 +960,7 @@ void DeleteScreenJob() delete runner; runner = nullptr; } + twod->SetScreenFade(1); } void RunScreenJobFrame() From a80c5db02b597f367125ef989503abe674179744 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 Apr 2021 21:37:01 +0200 Subject: [PATCH 33/70] - forgot to save the Exhumed part of the last commit --- source/games/exhumed/src/gameloop.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/games/exhumed/src/gameloop.cpp b/source/games/exhumed/src/gameloop.cpp index 4307b1325..949670c75 100644 --- a/source/games/exhumed/src/gameloop.cpp +++ b/source/games/exhumed/src/gameloop.cpp @@ -193,7 +193,7 @@ static void Intermission(MapRecord *from_map, MapRecord *to_map) gameaction = ga_nextlevel; } - }); + }, true, true); } } From 8cc3a81c3bc28cb8623d2053c71ecb89e55311e7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 Apr 2021 23:56:01 +0200 Subject: [PATCH 34/70] - enable the render backend switch in the menu. Vulkan is working now so this can be reactivated. --- wadsrc/static/menudef.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 35e2a9cb1..675a6b08b 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1494,9 +1494,8 @@ OptionMenu VideoModeMenu protected { Title "$VIDMNU_TITLE" - // does not work yet. - //Option "$VIDMNU_PREFERBACKEND", "vid_preferbackend", "PreferBackend" - //StaticText " " + Option "$VIDMNU_PREFERBACKEND", "vid_preferbackend", "PreferBackend" + StaticText " " Option "$VIDMNU_FULLSCREEN", "vid_fullscreen", "YesNo" IfOption(Mac) From e0ee3a67017e0ca3e19203fc32fb26418c17c84f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 09:29:08 +0200 Subject: [PATCH 35/70] - fixed: Vulkan did not define NPOT_EMULATION for its fragment shader. --- source/common/rendering/vulkan/shaders/vk_shader.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/common/rendering/vulkan/shaders/vk_shader.cpp b/source/common/rendering/vulkan/shaders/vk_shader.cpp index acb15dd47..84f7d3d5e 100644 --- a/source/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/source/common/rendering/vulkan/shaders/vk_shader.cpp @@ -296,6 +296,9 @@ std::unique_ptr VkShaderManager::LoadFragShader(FString shadername code << defines; code << "\n$placeholder$"; // here the code can later add more needed #defines. code << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n"; +#ifdef NPOT_EMULATION + code << "#define NPOT_EMULATION\n"; +#endif code << shaderBindings; FString placeholder = "\n"; From d348377bd823a63b47fdc42ce451a89910229d24 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 09:45:17 +0200 Subject: [PATCH 36/70] - when drawing skies on walls where both sides are sky, use the backside's texture. This fixes a sky anomaly in RR's E1L1. --- source/core/rendering/scene/hw_sky.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/core/rendering/scene/hw_sky.cpp b/source/core/rendering/scene/hw_sky.cpp index c5ba9a144..be63f3ca2 100644 --- a/source/core/rendering/scene/hw_sky.cpp +++ b/source/core/rendering/scene/hw_sky.cpp @@ -185,6 +185,7 @@ void HWWall::SkyTop(HWDrawInfo *di, walltype * seg,sectortype * fs,sectortype * // if the back sector is closed the sky must be drawn! if (c1 > f1 || c2 > f2) return; + fs = bs; // draw sky from the backsector. } flags |= HWF_SKYHACK; // mid textures on such lines need special treatment! @@ -241,6 +242,7 @@ void HWWall::SkyBottom(HWDrawInfo *di, walltype * seg,sectortype * fs,sectortype if (c1 > f1 || c2 > f2) return; } flags |= HWF_SKYHACK; // mid textures on such lines need special treatment! + fs = bs; // draw sky from the backsector. } else return; From b68512ef889befb22238ff851d3c74fea04d749d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 10:10:15 +0200 Subject: [PATCH 37/70] - on closer inspection, do not draw skies on intra-sky lines ever - the renderer already takes care of this elsewhere. --- source/core/rendering/scene/hw_sky.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/source/core/rendering/scene/hw_sky.cpp b/source/core/rendering/scene/hw_sky.cpp index be63f3ca2..fead13983 100644 --- a/source/core/rendering/scene/hw_sky.cpp +++ b/source/core/rendering/scene/hw_sky.cpp @@ -179,13 +179,7 @@ void HWWall::SkyTop(HWDrawInfo *di, walltype * seg,sectortype * fs,sectortype * { if (bs->ceilingstat & CSTAT_SECTOR_SKY) { - float c1, c2, f1, f2; - PlanesAtPoint(bs, v1.X * 16.f, v1.Y * -16.f, &c1, &f1); - PlanesAtPoint(bs, v2.X * 16.f, v2.Y * -16.f, &c2, &f2); - - // if the back sector is closed the sky must be drawn! - if (c1 > f1 || c2 > f2) return; - fs = bs; // draw sky from the backsector. + return; } flags |= HWF_SKYHACK; // mid textures on such lines need special treatment! @@ -232,17 +226,12 @@ void HWWall::SkyBottom(HWDrawInfo *di, walltype * seg,sectortype * fs,sectortype } else if (fs->floorstat & CSTAT_SECTOR_SKY) { - float c1, c2, f1, f2; - PlanesAtPoint(bs, v1.X * 16.f, v1.Y * -16.f, &c1, &f1); - PlanesAtPoint(bs, v2.X * 16.f, v2.Y * -16.f, &c2, &f2); if (bs->floorstat & CSTAT_SECTOR_SKY) { - // if the back sector is closed the sky must be drawn! - if (c1 > f1 || c2 > f2) return; + return; } flags |= HWF_SKYHACK; // mid textures on such lines need special treatment! - fs = bs; // draw sky from the backsector. } else return; From 38ecfc8fa55cdc7dffbd20c83d8c3a47d4d985fd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 00:47:07 +0200 Subject: [PATCH 38/70] - added handling for cubemapped skyboxes. --- source/build/src/defs.cpp | 56 ++-------------- source/core/parsefuncs.h | 35 ++++++++++ source/core/rendering/scene/hw_drawstructs.h | 18 +++++ source/core/rendering/scene/hw_sky.cpp | 5 +- source/core/rendering/scene/hw_skyportal.cpp | 3 +- source/core/textures/buildtiles.cpp | 4 +- source/core/textures/hightile.cpp | 69 ++++++++++++-------- 7 files changed, 110 insertions(+), 80 deletions(-) diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 55f382431..bf9d48197 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -20,11 +20,6 @@ #include "hw_voxels.h" #include "parsefuncs.h" -int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor, uint8_t flags); -int tileSetSkybox(int picnum, int palnum, const char** facenames, int flags); -void tileRemoveReplacement(int num); - - int32_t getatoken(scriptfile *sf, const tokenlist *tl, int32_t ntokens) { int32_t i; @@ -409,44 +404,11 @@ static int32_t defsparser(scriptfile *script) // OLD (DEPRECATED) DEFINITION SYNTAX case T_DEFINETEXTURE: - { - int32_t tile,pal,fnoo; - FString fn; - - if (scriptfile_getsymbol(script,&tile)) break; - if (scriptfile_getsymbol(script,&pal)) break; - if (scriptfile_getnumber(script,&fnoo)) break; //x-center - if (scriptfile_getnumber(script,&fnoo)) break; //y-center - if (scriptfile_getnumber(script,&fnoo)) break; //x-size - if (scriptfile_getnumber(script,&fnoo)) break; //y-size - if (scriptfile_getstring(script,&fn)) break; - - if (!fileSystem.FileExists(fn)) - break; - - tileSetHightileReplacement(tile,pal,fn,-1.0,1.0,1.0,1.0,1.0,0); - } - break; + parseDefineTexture(*script, pos); + break; case T_DEFINESKYBOX: - { - int32_t tile,pal,i; - FString fn[6]; - int happy = 1; - - if (scriptfile_getsymbol(script,&tile)) break; - if (scriptfile_getsymbol(script,&pal)) break; - if (scriptfile_getsymbol(script,&i)) break; //future expansion - for (i=0; i<6; i++) - { - if (scriptfile_getstring(script,&fn[i])) break; //grab the 6 faces - - if (!fileSystem.FileExists(fn[i])) - happy = 0; - } - if (i < 6 || !happy) break; - tileSetSkybox(tile, pal, (const char **)fn, 0); - } - break; + parseDefineSkybox(*script, pos); + break; case T_DEFINETINT: { int32_t pal, r,g,b,f; @@ -1609,7 +1571,6 @@ static int32_t defsparser(scriptfile *script) FString fn[6]; FScanner::SavedPos modelend; int32_t i, tile = -1, pal = 0, happy = 1; - int flags = 0; static const tokenlist skyboxtokens[] = { @@ -1663,8 +1624,7 @@ static int32_t defsparser(scriptfile *script) } if (!happy) break; - const char* fns[] = { fn[0].GetChars(), fn[1].GetChars(), fn[2].GetChars(), fn[3].GetChars(), fn[4].GetChars(), fn[5].GetChars() }; - tileSetSkybox(tile, pal, fns, flags); + tileSetSkybox(tile, pal, fn); } break; case T_HIGHPALOOKUP: @@ -1901,7 +1861,6 @@ static int32_t defsparser(scriptfile *script) int32_t pal=-1, xsiz = 0, ysiz = 0; FString fn; double alphacut = -1.0, xscale = 1.0, yscale = 1.0, specpower = 1.0, specfactor = 1.0; - uint8_t flags = 0; static const tokenlist texturetokens_pal[] = { @@ -1972,7 +1931,7 @@ static int32_t defsparser(scriptfile *script) xscale = 1.0f / xscale; yscale = 1.0f / yscale; - tileSetHightileReplacement(tile,pal,fn,alphacut,xscale,yscale, specpower, specfactor,flags); + tileSetHightileReplacement(tile,pal,fn,alphacut,xscale,yscale, specpower, specfactor); } break; case T_DETAIL: case T_GLOW: case T_SPECULAR: case T_NORMAL: @@ -1980,7 +1939,6 @@ static int32_t defsparser(scriptfile *script) auto detailpos = scriptfile_getposition(script); FScanner::SavedPos detailend; int32_t pal = 0; - char flags = 0; FString fn; double xscale = 1.0, yscale = 1.0, specpower = 1.0, specfactor = 1.0; @@ -2045,7 +2003,7 @@ static int32_t defsparser(scriptfile *script) pal = NORMALPAL; break; } - tileSetHightileReplacement(tile,pal,fn,-1.0f,xscale,yscale, specpower, specfactor,flags); + tileSetHightileReplacement(tile,pal,fn,-1.0f,xscale,yscale, specpower, specfactor); } break; default: diff --git a/source/core/parsefuncs.h b/source/core/parsefuncs.h index 498f3cdb7..6096bdd2d 100644 --- a/source/core/parsefuncs.h +++ b/source/core/parsefuncs.h @@ -35,6 +35,41 @@ ** */ +int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor); +int tileSetSkybox(int picnum, int palnum, FString* facenames); +void tileRemoveReplacement(int num); + +void parseDefineTexture(FScanner& sc, FScriptPosition& pos) +{ + int tile, palette; + + if (!sc.GetNumber(tile, true)) return; + if (!sc.GetNumber(palette, true)) return; + if (!sc.GetNumber(true)) return; //formerly x-center, unused + if (!sc.GetNumber(true)) return; //formerly y-center, unused + if (!sc.GetNumber(true)) return; //formerly x-size, unused + if (!sc.GetNumber(true)) return; //formerly y-size, unused + if (!sc.GetString()) return; + + tileSetHightileReplacement(tile, palette, sc.String, -1.0, 1.0, 1.0, 1.0, 1.0); +} + +void parseDefineSkybox(FScanner& sc, FScriptPosition& pos) +{ + int tile, palette; + FString fn[6]; + + if (!sc.GetNumber(tile, true)) return; + if (!sc.GetNumber(palette, true)) return; + if (!sc.GetNumber(true)) return; //'future extension' (for what?) + for (int i = 0; i < 6; i++) + { + if (!sc.GetString()) return; + fn[i] = sc.String; + } + tileSetSkybox(tile, palette, fn); +} + void parseSetupTile(FScanner& sc, FScriptPosition& pos) { int tile; diff --git a/source/core/rendering/scene/hw_drawstructs.h b/source/core/rendering/scene/hw_drawstructs.h index 68869f8ea..1c7416553 100644 --- a/source/core/rendering/scene/hw_drawstructs.h +++ b/source/core/rendering/scene/hw_drawstructs.h @@ -11,6 +11,7 @@ #include "gamefuncs.h" #include "render.h" #include "matrix.h" +#include "gamecontrol.h" #ifdef _MSC_VER #pragma warning(disable:4244) @@ -357,3 +358,20 @@ inline float sectorVisibility(sectortype* sec) } inline const float hw_density = 0.35f; + +int checkTranslucentReplacement(FTextureID picnum, int pal); + +inline bool maskWallHasTranslucency(const walltype* wall) +{ + return (wall->cstat & CSTAT_WALL_TRANSLUCENT) || checkTranslucentReplacement(tileGetTexture(wall->picnum)->GetID(), wall->pal); +} + +inline bool spriteHasTranslucency(const spritetype* tspr) +{ + if ((tspr->cstat & CSTAT_SPRITE_TRANSLUCENT) || //(tspr->clipdist & TSPR_FLAGS_DRAW_LAST) || + ((unsigned)tspr->owner < MAXSPRITES && spriteext[tspr->owner].alpha)) + return true; + + return checkTranslucentReplacement(tileGetTexture(tspr->picnum)->GetID(), tspr->pal); +} + diff --git a/source/core/rendering/scene/hw_sky.cpp b/source/core/rendering/scene/hw_sky.cpp index fead13983..4577ed0b8 100644 --- a/source/core/rendering/scene/hw_sky.cpp +++ b/source/core/rendering/scene/hw_sky.cpp @@ -32,6 +32,7 @@ CVAR(Bool,gl_noskyboxes, false, 0) FGameTexture* GetSkyTexture(int basetile, int lognumtiles, const int16_t* tilemap, int remap); +FGameTexture* SkyboxReplacement(FTextureID picnum, int palnum); //========================================================================== // @@ -42,14 +43,14 @@ FGameTexture* GetSkyTexture(int basetile, int lognumtiles, const int16_t* tilema void initSkyInfo(HWDrawInfo *di, HWSkyInfo* sky, sectortype* sector, int plane, PalEntry FadeColor) { int picnum = plane == plane_ceiling ? sector->ceilingpicnum : sector->floorpicnum; + int palette = plane == plane_ceiling ? sector->ceilingpal : sector->floorpal; int32_t dapyscale = 0, dapskybits = 0, dapyoffs = 0, daptileyscale = 0; - FGameTexture* skytex = nullptr; + FGameTexture* skytex = SkyboxReplacement(tileGetTexture(picnum)->GetID(), palette); int realskybits = 0; // todo: check for skybox replacement. if (!skytex) { - int palette = plane == plane_ceiling ? sector->ceilingpal : sector->floorpal; int remap = TRANSLATION(Translation_Remap + curbasepal, palette); int16_t const* dapskyoff = getpsky(picnum, &dapyscale, &dapskybits, &dapyoffs, &daptileyscale); diff --git a/source/core/rendering/scene/hw_skyportal.cpp b/source/core/rendering/scene/hw_skyportal.cpp index 0d0e7260b..457b97fe1 100644 --- a/source/core/rendering/scene/hw_skyportal.cpp +++ b/source/core/rendering/scene/hw_skyportal.cpp @@ -26,7 +26,8 @@ #include "hw_renderstate.h" #include "skyboxtexture.h" - CVAR(Float, skyoffsettest, 0, 0) +CVAR(Float, skyoffsettest, 0, 0) + //----------------------------------------------------------------------------- // // diff --git a/source/core/textures/buildtiles.cpp b/source/core/textures/buildtiles.cpp index 2148b27a7..a515647d6 100644 --- a/source/core/textures/buildtiles.cpp +++ b/source/core/textures/buildtiles.cpp @@ -60,7 +60,7 @@ enum BuildTiles TileFiles; -int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor, uint8_t flags); +int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor); //========================================================================== // @@ -514,7 +514,7 @@ int tileImportFromTexture(const char* fn, int tilenum, int alphacut, int istextu TexMan.AddGameTexture(tex); TileFiles.tiledata[tilenum].backup = TileFiles.tiledata[tilenum].texture = tex; if (istexture) - tileSetHightileReplacement(tilenum, 0, fn, (float)(255 - alphacut) * (1.f / 255.f), 1.0f, 1.0f, 1.0, 1.0, 0); + tileSetHightileReplacement(tilenum, 0, fn, (float)(255 - alphacut) * (1.f / 255.f), 1.0f, 1.0f, 1.0, 1.0); return 0; } diff --git a/source/core/textures/hightile.cpp b/source/core/textures/hightile.cpp index f5d240233..e73e72686 100644 --- a/source/core/textures/hightile.cpp +++ b/source/core/textures/hightile.cpp @@ -48,15 +48,17 @@ #include "sc_man.h" #include "gamestruct.h" #include "hw_renderstate.h" +#include "skyboxtexture.h" CVARD(Bool, hw_shadeinterpolate, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "enable/disable shade interpolation") struct HightileReplacement { - FGameTexture* faces[6]; // only one gets used by a texture, the other 5 are for skyboxes only + FGameTexture* image; FVector2 scale; float alphacut, specpower, specfactor; - uint16_t palnum, flags; + uint16_t palnum; + bool issky; }; static TMap> tileReplacements; @@ -91,7 +93,7 @@ static void AddReplacement(int picnum, const HightileReplacement& replace) auto& Hightiles = tileReplacements[picnum]; for (auto& ht : Hightiles) { - if (replace.palnum == ht.palnum && (replace.faces[1] == nullptr) == (ht.faces[1] == nullptr)) + if (replace.palnum == ht.palnum && replace.issky == ht.issky) { ht = replace; return; @@ -125,7 +127,7 @@ static HightileReplacement* FindReplacement(FTextureID picnum, int palnum, bool { for (auto& rep : *Hightiles) { - if (rep.palnum == palnum && (rep.faces[1] != nullptr) == skybox) return &rep; + if (rep.palnum == palnum && rep.issky == skybox) return &rep; } if (!palnum || palnum >= MAXPALOOKUPS - RESERVEDPALS) break; palnum = 0; @@ -137,11 +139,19 @@ int checkTranslucentReplacement(FTextureID picnum, int pal) { FGameTexture* tex = nullptr; auto si = FindReplacement(picnum, pal, 0); - if (si && hw_hightile) tex = si->faces[0]; + if (si && hw_hightile) tex = si->image; if (!tex || tex->GetTexelWidth() == 0 || tex->GetTexelHeight() == 0) return false; return tex && tex->GetTranslucency(); } +FGameTexture* SkyboxReplacement(FTextureID picnum, int palnum) +{ + auto hr = FindReplacement(picnum, palnum, true); + if (!hr) return nullptr; + return hr->image; +} + + //========================================================================== // // Processes data from .def files into the textures @@ -163,19 +173,19 @@ void PostLoadSetup() { if (rep.palnum == GLOWPAL) { - glowTex = rep.faces[0]; + glowTex = rep.image; } if (rep.palnum == NORMALPAL) { - normalTex = rep.faces[0]; + normalTex = rep.image; } if (rep.palnum == SPECULARPAL) { - specTex = rep.faces[0]; + specTex = rep.image; } if (rep.palnum == DETAILPAL) { - detailTex = rep.faces[0]; + detailTex = rep.image; scalex = rep.scale.X; scaley = rep.scale.Y; } @@ -185,10 +195,10 @@ void PostLoadSetup() { for (auto& rep : *Hightile) { - if (rep.faces[1]) continue; // do not muck around with skyboxes (yet) + if (rep.issky) continue; // do not muck around with skyboxes (yet) if (rep.palnum < NORMALPAL) { - auto tex = rep.faces[0]; + auto tex = rep.image; // Make a copy so that multiple appearances of the same texture with different layers can be handled. They will all refer to the same internal texture anyway. tex = MakeGameTexture(tex->GetTexture(), "", ETextureType::Any); if (glowTex) tex->SetGlowmap(glowTex->GetTexture()); @@ -196,7 +206,7 @@ void PostLoadSetup() if (normalTex) tex->SetNormalmap(normalTex->GetTexture()); if (specTex) tex->SetSpecularmap(specTex->GetTexture()); tex->SetDetailScale(scalex, scaley); - rep.faces[0] = tex; + rep.image = tex; } } } @@ -237,7 +247,7 @@ void PostLoadSetup() // //========================================================================== -int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor, uint8_t flags) +int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor) { if ((uint32_t)picnum >= (uint32_t)MAXTILES) return -1; if ((uint32_t)palnum >= (uint32_t)MAXPALOOKUPS) return -1; @@ -257,13 +267,12 @@ int tileSetHightileReplacement(int picnum, int palnum, const char* filename, flo return -1; } - replace.faces[0] = TexMan.GetGameTexture(texid); - if (replace.faces[0] == nullptr) + replace.image = TexMan.GetGameTexture(texid); replace.alphacut = min(alphacut,1.f); replace.scale = { xscale, yscale }; replace.specpower = specpower; // currently unused replace.specfactor = specfactor; // currently unused - replace.flags = flags; + replace.issky = 0; replace.palnum = (uint16_t)palnum; AddReplacement(picnum, replace); return 0; @@ -276,10 +285,10 @@ int tileSetHightileReplacement(int picnum, int palnum, const char* filename, flo // //========================================================================== -int tileSetSkybox(int picnum, int palnum, const char **facenames, int flags ) +int tileSetSkybox(int picnum, int palnum, FString* facenames) { - if ((uint32_t)picnum >= (uint32_t)MAXTILES) return -1; - if ((uint32_t)palnum >= (uint32_t)MAXPALOOKUPS) return -1; + if ((uint32_t)picnum >= (uint32_t)MAXTILES) return -1; + if ((uint32_t)palnum >= (uint32_t)MAXPALOOKUPS) return -1; auto tex = tileGetTexture(picnum); if (tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) @@ -288,18 +297,26 @@ int tileSetSkybox(int picnum, int palnum, const char **facenames, int flags ) return -1; // cannot add replacements to empty tiles, must create one beforehand } HightileReplacement replace = {}; - - for (auto &face : replace.faces) + + FGameTexture *faces[6]; + const static uint8_t map[] = { 2, 1, 0, 3, 4, 5 }; + for (int i = 0; i < 6; i++) { - FTextureID texid = TexMan.CheckForTexture(*facenames, ETextureType::Any); + FTextureID texid = TexMan.CheckForTexture(facenames[i], ETextureType::Any); if (!texid.isValid()) { - Printf("%s: Skybox image for tile %d does not exist or is invalid\n", *facenames, picnum); + Printf("%s: Skybox image for tile %d does not exist or is invalid\n", facenames[i].GetChars(), picnum); return -1; } - face = TexMan.GetGameTexture(texid); + faces[map[i]] = TexMan.GetGameTexture(texid); } - replace.flags = flags; + FSkyBox* sbtex = new FSkyBox(""); + memcpy(sbtex->faces, faces, sizeof(faces)); + sbtex->previous = faces[0]; // won't ever be used, just to be safe. + sbtex->fliptop = true; + replace.image = MakeGameTexture(sbtex, "", ETextureType::Override); + TexMan.AddGameTexture(replace.image, false); + replace.issky = 1; replace.palnum = (uint16_t)palnum; AddReplacement(picnum, replace); return 0; @@ -341,7 +358,7 @@ bool PickTexture(FRenderState *state, FGameTexture* tex, int paletteid, TextureP if (rep) { - tex = rep->faces[0]; + tex = rep->image; } if (!rep || rep->palnum != hipalswap || (h.tintFlags & TINTF_APPLYOVERALTPAL)) applytint = true; From 4d29cd2df23ca20f809afff16c3e721a6cabf1ff Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 13:54:58 +0200 Subject: [PATCH 39/70] - I shouldn't have used WT's skies as reference - they got front and back faces swapped. --- source/core/textures/hightile.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/core/textures/hightile.cpp b/source/core/textures/hightile.cpp index e73e72686..36f8e6315 100644 --- a/source/core/textures/hightile.cpp +++ b/source/core/textures/hightile.cpp @@ -299,7 +299,6 @@ int tileSetSkybox(int picnum, int palnum, FString* facenames) HightileReplacement replace = {}; FGameTexture *faces[6]; - const static uint8_t map[] = { 2, 1, 0, 3, 4, 5 }; for (int i = 0; i < 6; i++) { FTextureID texid = TexMan.CheckForTexture(facenames[i], ETextureType::Any); @@ -308,7 +307,7 @@ int tileSetSkybox(int picnum, int palnum, FString* facenames) Printf("%s: Skybox image for tile %d does not exist or is invalid\n", facenames[i].GetChars(), picnum); return -1; } - faces[map[i]] = TexMan.GetGameTexture(texid); + faces[i] = TexMan.GetGameTexture(texid); } FSkyBox* sbtex = new FSkyBox(""); memcpy(sbtex->faces, faces, sizeof(faces)); From cecd34efc7c7cc62c99dee8a470e67e0d655344f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 Apr 2021 21:59:47 +0200 Subject: [PATCH 40/70] - moved a bit more script parsing functionality into the backend and tried it out on the 'skybox' command. --- source/build/src/defs.cpp | 63 ++------------------------------ source/common/engine/sc_man.cpp | 36 +++++++++++++++++++ source/common/engine/sc_man.h | 9 +++++ source/core/parsefuncs.h | 64 +++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 61 deletions(-) diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index bf9d48197..7726d9bf2 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -1566,67 +1566,8 @@ static int32_t defsparser(scriptfile *script) } break; case T_SKYBOX: - { - auto skyboxpos = scriptfile_getposition(script); - FString fn[6]; - FScanner::SavedPos modelend; - int32_t i, tile = -1, pal = 0, happy = 1; - - static const tokenlist skyboxtokens[] = - { - { "tile" ,T_TILE }, - { "pal" ,T_PAL }, - { "ft" ,T_FRONT },{ "front" ,T_FRONT },{ "forward",T_FRONT }, - { "rt" ,T_RIGHT },{ "right" ,T_RIGHT }, - { "bk" ,T_BACK },{ "back" ,T_BACK }, - { "lf" ,T_LEFT },{ "left" ,T_LEFT },{ "lt" ,T_LEFT }, - { "up" ,T_TOP },{ "top" ,T_TOP },{ "ceiling",T_TOP },{ "ceil" ,T_TOP }, - { "dn" ,T_BOTTOM },{ "bottom" ,T_BOTTOM },{ "floor" ,T_BOTTOM },{ "down" ,T_BOTTOM }, - { "nocompress", T_NOCOMPRESS }, - { "nodownsize", T_NODOWNSIZE }, - { "forcefilter", T_FORCEFILTER }, - { "artquality", T_ARTQUALITY }, - }; - - if (scriptfile_getbraces(script,&modelend)) break; - while (!scriptfile_endofblock(script, modelend)) - { - switch (getatoken(script,skyboxtokens,countof(skyboxtokens))) - { - //case T_ERROR: Printf("Error on line %s:%d in skybox tokens\n",script->filename,linenum); break; - case T_TILE: - scriptfile_getsymbol(script,&tile); break; - case T_PAL: - scriptfile_getsymbol(script,&pal); break; - case T_FRONT: - scriptfile_getstring(script,&fn[0]); break; - case T_RIGHT: - scriptfile_getstring(script,&fn[1]); break; - case T_BACK: - scriptfile_getstring(script,&fn[2]); break; - case T_LEFT: - scriptfile_getstring(script,&fn[3]); break; - case T_TOP: - scriptfile_getstring(script,&fn[4]); break; - case T_BOTTOM: - scriptfile_getstring(script,&fn[5]); break; - - } - } - - if (tile < 0) skyboxpos.Message(MSG_ERROR, "skybox: missing 'tile number'"), happy=0; - for (i=0; i<6; i++) - { - if (fn[i].IsEmpty()) skyboxpos.Message(MSG_ERROR, "skybox: missing '%s filename'", skyfaces[i]), happy = 0; - // FIXME? - if (!fileSystem.FileExists(fn[i])) - happy = 0; - } - if (!happy) break; - - tileSetSkybox(tile, pal, fn); - } - break; + parseSkybox(*script, pos); + break; case T_HIGHPALOOKUP: { int32_t basepal=-1, pal=-1; diff --git a/source/common/engine/sc_man.cpp b/source/common/engine/sc_man.cpp index fa9a2f6c4..f24f25d92 100644 --- a/source/common/engine/sc_man.cpp +++ b/source/common/engine/sc_man.cpp @@ -1287,6 +1287,42 @@ void FScanner::AddSymbol(const char* name, double value) symbols.Insert(name, sym); } +//========================================================================== +// +// +// +//========================================================================== + +int FScanner::StartBraces(FScanner::SavedPos* braceend) +{ + if (CheckString("{")) + { + auto here = SavePos(); + SkipToEndOfBlock(); + *braceend = SavePos(); + RestorePos(here); + return 0; + } + else + { + ScriptError("'{' expected"); + return -1; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +bool FScanner::FoundEndBrace(FScanner::SavedPos& braceend) +{ + auto here = SavePos(); + return here.SavedScriptPtr >= braceend.SavedScriptPtr; +} + + //========================================================================== // // a class that remembers a parser position diff --git a/source/common/engine/sc_man.h b/source/common/engine/sc_man.h index 3a894fcb3..6874eb186 100644 --- a/source/common/engine/sc_man.h +++ b/source/common/engine/sc_man.h @@ -94,6 +94,8 @@ public: inline void AddSymbol(const char* name, uint32_t value) { return AddSymbol(name, uint64_t(value)); } void AddSymbol(const char* name, double value); void SkipToEndOfBlock(); + int StartBraces(FScanner::SavedPos* braceend); + bool FoundEndBrace(FScanner::SavedPos& braceend); static FString TokenName(int token, const char *string=NULL); @@ -120,6 +122,13 @@ public: return true; } + bool GetString(FString& var) + { + if (!GetString()) return false; + var = String; + return true; + } + bool GetFloat(bool evaluate = false); void MustGetFloat(bool evaluate = false); bool CheckFloat(bool evaluate = false); diff --git a/source/core/parsefuncs.h b/source/core/parsefuncs.h index 6096bdd2d..c26746dff 100644 --- a/source/core/parsefuncs.h +++ b/source/core/parsefuncs.h @@ -39,6 +39,12 @@ int tileSetHightileReplacement(int picnum, int palnum, const char* filename, flo int tileSetSkybox(int picnum, int palnum, FString* facenames); void tileRemoveReplacement(int num); +//=========================================================================== +// +// +// +//=========================================================================== + void parseDefineTexture(FScanner& sc, FScriptPosition& pos) { int tile, palette; @@ -54,6 +60,12 @@ void parseDefineTexture(FScanner& sc, FScriptPosition& pos) tileSetHightileReplacement(tile, palette, sc.String, -1.0, 1.0, 1.0, 1.0, 1.0); } +//=========================================================================== +// +// +// +//=========================================================================== + void parseDefineSkybox(FScanner& sc, FScriptPosition& pos) { int tile, palette; @@ -70,6 +82,46 @@ void parseDefineSkybox(FScanner& sc, FScriptPosition& pos) tileSetSkybox(tile, palette, fn); } +//=========================================================================== +// +// +// +//=========================================================================== + +void parseSkybox(FScanner& sc, FScriptPosition& pos) +{ + FString faces[6]; + FScanner::SavedPos blockend; + int32_t tile = -1, pal = 0; + + if (sc.StartBraces(&blockend)) return; + while (!sc.FoundEndBrace(blockend)) + { + sc.GetString(); + if (sc.Compare("tile")) sc.GetNumber(tile, true); + else if (sc.Compare("pal")) sc.GetNumber(pal, true); + else if (sc.Compare({ "ft", "front", "forward" })) sc.GetString(faces[0]); + else if (sc.Compare({ "rt", "right" })) sc.GetString(faces[1]); + else if (sc.Compare({ "bk", "back" })) sc.GetString(faces[2]); + else if (sc.Compare({ "lt", "lf", "left" })) sc.GetString(faces[3]); + else if (sc.Compare({ "up", "ceiling", "top", "ceil" })) sc.GetString(faces[4]); + else if (sc.Compare({ "dn", "floor", "bottom", "down" })) sc.GetString(faces[5]); + // skip over everything else. + } + if (tile < 0) + { + pos.Message(MSG_ERROR, "skybox: missing tile number"); + return; + } + tileSetSkybox(tile, pal, faces); +} + +//=========================================================================== +// +// +// +//=========================================================================== + void parseSetupTile(FScanner& sc, FScriptPosition& pos) { int tile; @@ -82,6 +134,12 @@ void parseSetupTile(FScanner& sc, FScriptPosition& pos) if (!sc.GetNumber(tiled.hiofs.yoffs, true)) return; } +//=========================================================================== +// +// +// +//=========================================================================== + void parseSetupTileRange(FScanner& sc, FScriptPosition& pos) { int tilestart, tileend; @@ -98,6 +156,12 @@ void parseSetupTileRange(FScanner& sc, FScriptPosition& pos) for (int i = tilestart; i <= tileend; i++) TileFiles.tiledata[i].hiofs = hiofs; } +//=========================================================================== +// +// +// +//=========================================================================== + void parseAnimTileRange(FScanner& sc, FScriptPosition& pos) { SetAnim set; From 1439897b65f9083f9d76954842561d7770555aeb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 15:55:37 +0200 Subject: [PATCH 41/70] - fixed extended music lookup. The logic was inverted for extended lookup which always resulted in failure to find the song. --- source/core/raze_music.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/core/raze_music.cpp b/source/core/raze_music.cpp index 9ee2d1c72..69cc5dbba 100644 --- a/source/core/raze_music.cpp +++ b/source/core/raze_music.cpp @@ -132,7 +132,7 @@ FileReader OpenMusic(const char* musicname) if (!reader.isOpen()) { int lumpnum = LookupMusic(musicname); - if (mus_extendedlookup && lumpnum >= 0) + if (mus_extendedlookup && lumpnum < 0) { // EDuke also looks in a subfolder named after the main game resource. Do this as well if extended lookup is active. auto rfn = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(lumpnum)); From e2f570a70afcf6e8cff983ca0e94aa2fba0630d5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 16:05:32 +0200 Subject: [PATCH 42/70] - fixed: extended sound lookup must check the sound/ folder. --- source/core/raze_sound.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/core/raze_sound.cpp b/source/core/raze_sound.cpp index 4020f1b0a..463fece92 100644 --- a/source/core/raze_sound.cpp +++ b/source/core/raze_sound.cpp @@ -142,7 +142,11 @@ int S_LookupSound(const char* fn) static const char * const sndformats[] = { "OGG", "FLAC", "WAV" }; if (snd_extendedlookup) { - int lump = fileSystem.FindFileWithExtensions(StripExtension(fn), sndformats, countof(sndformats)); + auto newfn = StripExtension(fn); + int lump = fileSystem.FindFileWithExtensions(newfn, sndformats, countof(sndformats)); + if (lump >= 0) return lump; + newfn = "sound/" + newfn; + lump = fileSystem.FindFileWithExtensions(newfn, sndformats, countof(sndformats)); if (lump >= 0) return lump; } return fileSystem.FindFile(fn); From fc1fbfe8b351884e5ca5ef2b04d9b23869793c56 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 16:35:26 +0200 Subject: [PATCH 43/70] - fixed .def 'music' parsing. This was incomplete and just ignored Duke's special music, and the levelnum generation used an outdated formula so that it never managed to assign any music to the maps. --- source/core/mapinfo.cpp | 6 ++++-- source/core/raze_music.cpp | 1 + source/core/raze_music.h | 1 + source/games/duke/src/sounds.cpp | 1 - source/games/duke/src/sounds.h | 2 -- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/source/core/mapinfo.cpp b/source/core/mapinfo.cpp index 506cae54c..609081f7f 100644 --- a/source/core/mapinfo.cpp +++ b/source/core/mapinfo.cpp @@ -38,6 +38,7 @@ #include "raze_music.h" #include "filesystem.h" #include "printf.h" +#include "raze_sound.h" FString gSkillNames[MAXSKILLS]; FString gVolumeNames[MAXVOLUMES]; @@ -109,7 +110,8 @@ bool SetMusicForMap(const char* mapname, const char* music, bool namehack) { if (!stricmp(mapname, specials[i])) { - // todo: store this properly. + if (specialmusic.Size() <= i) specialmusic.Resize(i + 1); + specialmusic[i] = music; return true; } } @@ -127,7 +129,7 @@ bool SetMusicForMap(const char* mapname, const char* music, bool namehack) if (numMatches != 4 || toupper(b1) != 'E' || toupper(b2) != 'L') return false; - index = FindMapByLevelNum(ep*100 + lev); + index = FindMapByLevelNum(levelnum(ep - 1, lev - 1)); } if (index != nullptr) diff --git a/source/core/raze_music.cpp b/source/core/raze_music.cpp index 69cc5dbba..8586dbc00 100644 --- a/source/core/raze_music.cpp +++ b/source/core/raze_music.cpp @@ -46,6 +46,7 @@ static bool mus_blocked; static FString lastStartedMusic; +TArray specialmusic; MusicAliasMap MusicAliases; MusicAliasMap LevelMusicAliases; diff --git a/source/core/raze_music.h b/source/core/raze_music.h index a9051d650..a87644406 100644 --- a/source/core/raze_music.h +++ b/source/core/raze_music.h @@ -6,6 +6,7 @@ typedef TMap MusicAliasMap; extern MusicAliasMap MusicAliases; +extern TArray specialmusic; // Totally minimalistic interface - should be all the game modules need. void Mus_InitMusic(); diff --git a/source/games/duke/src/sounds.cpp b/source/games/duke/src/sounds.cpp index 79970b348..aefc53400 100644 --- a/source/games/duke/src/sounds.cpp +++ b/source/games/duke/src/sounds.cpp @@ -65,7 +65,6 @@ inline DDukeActor* getSndActor(const void* source) return source ? &hittype[((spritetype*)source) - sprite] : nullptr; } -TArray specialmusic; static FSoundID currentCommentarySound; static DDukeActor* currentCommentarySprite; // todo: GC this once actors become objects diff --git a/source/games/duke/src/sounds.h b/source/games/duke/src/sounds.h index 883496606..415af4406 100644 --- a/source/games/duke/src/sounds.h +++ b/source/games/duke/src/sounds.h @@ -74,8 +74,6 @@ void S_ParseDeveloperCommentary(); void StopCommentary(); bool StartCommentary(int tag, DDukeActor* sprnum); -extern TArray specialmusic; - END_DUKE_NS From a53ed46baeac0b5f556c44be65a6ec9af11f65b2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 17:43:56 +0200 Subject: [PATCH 44/70] - fixed item placement on SW minihud. Fixes #295 --- source/games/sw/src/sbar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/games/sw/src/sbar.cpp b/source/games/sw/src/sbar.cpp index c9cd50ba8..51a380646 100644 --- a/source/games/sw/src/sbar.cpp +++ b/source/games/sw/src/sbar.cpp @@ -695,7 +695,7 @@ private: void DisplayMinibarInventory(PLAYERp pp) { int InventoryBoxX = MINI_BAR_INVENTORY_BOX_X; - int InventoryBoxY = MINI_BAR_INVENTORY_BOX_Y; + int InventoryBoxY = MINI_BAR_INVENTORY_BOX_Y - 200; int InventoryXoff = 0; int InventoryYoff = 1; From 793d2d99ef14329fe5313b4d8ccd22310cfe952b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 17:46:53 +0200 Subject: [PATCH 45/70] - re-fixed the music lookup. --- source/core/raze_music.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/core/raze_music.cpp b/source/core/raze_music.cpp index 8586dbc00..b2c3f0aed 100644 --- a/source/core/raze_music.cpp +++ b/source/core/raze_music.cpp @@ -133,13 +133,14 @@ FileReader OpenMusic(const char* musicname) if (!reader.isOpen()) { int lumpnum = LookupMusic(musicname); - if (mus_extendedlookup && lumpnum < 0) + if (mus_extendedlookup && lumpnum >= 0) { // EDuke also looks in a subfolder named after the main game resource. Do this as well if extended lookup is active. auto rfn = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(lumpnum)); auto rfbase = ExtractFileBase(rfn); FStringf aliasMusicname("music/%s/%s", rfbase.GetChars(), musicname); - lumpnum = LookupMusic(aliasMusicname); + int newlumpnum = LookupMusic(aliasMusicname); + if (newlumpnum >= 0) lumpnum = newlumpnum; } if (lumpnum == -1) { @@ -149,7 +150,7 @@ FileReader OpenMusic(const char* musicname) } if (lumpnum == -1 && (g_gameType & GAMEFLAG_SW)) { - // Some Shadow Warrioe distributions have the music in a subfolder named 'classic'. Check that, too. + // Some Shadow Warrior distributions have the music in a subfolder named 'classic'. Check that, too. FStringf aliasMusicname("classic/music/%s", musicname); lumpnum = fileSystem.FindFile(aliasMusicname); } From 51c4c47183350d5c7abd96b4ae19340739fdb265 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 18:01:42 +0200 Subject: [PATCH 46/70] - block manual advancing of intermission screens when already fading out. This seems to cause some serious stability issues with how they handle the 2D drawer. --- source/core/screenjob.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/core/screenjob.cpp b/source/core/screenjob.cpp index 97413104e..943178a68 100644 --- a/source/core/screenjob.cpp +++ b/source/core/screenjob.cpp @@ -840,7 +840,7 @@ public: clock += now - lastTime; if (clock == 0) clock = 1; } - bool skiprequest = clock > 100'000'000 && inputState.CheckAllInput() && !processed; + bool skiprequest = clock > 100'000'000 && inputState.CheckAllInput() && !processed && job.job->fadestate != DScreenJob::fadeout; lastTime = now; if (screenfade < 1.f && !M_Active()) @@ -848,7 +848,8 @@ public: float ms = (clock / 1'000'000) / job.job->fadetime; screenfade = clamp(ms, 0.f, 1.f); twod->SetScreenFade(screenfade); - job.job->fadestate = DScreenJob::fadein; + if (job.job->fadestate != DScreenJob::fadeout) + job.job->fadestate = DScreenJob::fadein; } else { From 794cab2d545f6ae8dc9fca13a0dc775644f7d30c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 18:54:39 +0200 Subject: [PATCH 47/70] - removed some dead code. --- source/build/src/defs.cpp | 62 --------------------------------------- 1 file changed, 62 deletions(-) diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 7726d9bf2..38e658ed6 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -36,68 +36,6 @@ int32_t getatoken(scriptfile *sf, const tokenlist *tl, int32_t ntokens) } void AddUserMapHack(usermaphack_t&); -#if 0 -// For later -{ -if (sc.Compare("music")) -{ - FString id, mus; - sc.MustGetToken('{'); - while (!sc.CheckToken('}')) - { - sc.MustGetToken(TK_Identifier); - if (sc.Compare("id")) - { - sc.MustGetString(); - id = sc.String; - } - else if (sc.Compare("file")) - { - sc.MustGetString(); - mus = sc.String; - } - } - - if (!SetMusicForMap(id, mus, true)) - { - sc.ScriptError("Map %s not found in music definition", id.GetChars()); - } - - char* tokenPtr = pScript->ltextptr; - char* musicID = NULL; - char* fileName = NULL; - char* musicEnd; - - if (scriptfile_getbraces(pScript, &musicEnd)) - break; - - while (pScript->textptr < musicEnd) - { - switch (getatoken(pScript, soundTokens, countof(soundTokens))) - { - case T_ID: scriptfile_getstring(pScript, &musicID); break; - case T_FILE: scriptfile_getstring(pScript, &fileName); break; - } - } - - if (!firstPass) - { - if (musicID == NULL) - { - pos.Message(MSG_ERROR, "missing ID for music definition\n"); - break; - } - - if (fileName == NULL || fileSystem.FileExists(fileName)) - break; - - if (S_DefineMusic(musicID, fileName) == -1) - pos.Message(MSG_ERROR, "invalid music ID"); - } - -} -} -#endif enum scripttoken_t { From 1362a7ebc57a7b9da089b741d9f3492b4d3e3c25 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 19:45:18 +0200 Subject: [PATCH 48/70] - added extended translucency support and did a bit of code consolidation. --- .../core/rendering/scene/hw_drawlistadd.cpp | 2 +- source/core/rendering/scene/hw_drawstructs.h | 15 ++++++++++ source/core/rendering/scene/hw_flats.cpp | 13 ++------- source/core/rendering/scene/hw_sprites.cpp | 28 +++---------------- source/core/rendering/scene/hw_walls.cpp | 17 ++--------- 5 files changed, 25 insertions(+), 50 deletions(-) diff --git a/source/core/rendering/scene/hw_drawlistadd.cpp b/source/core/rendering/scene/hw_drawlistadd.cpp index 26ef3da57..69fb35222 100644 --- a/source/core/rendering/scene/hw_drawlistadd.cpp +++ b/source/core/rendering/scene/hw_drawlistadd.cpp @@ -95,7 +95,7 @@ void HWDrawInfo::AddFlat(HWFlat *flat) { int list;; - if (flat->RenderStyle != LegacyRenderStyles[STYLE_Translucent] || flat->alpha < 1.f - FLT_EPSILON) // flat->texture->GetTranslucency() - fixme + if (flat->RenderStyle != LegacyRenderStyles[STYLE_Translucent] || flat->alpha < 1.f - FLT_EPSILON || checkTranslucentReplacement(flat->texture->GetID(), flat->palette)) { // translucent portals go into the translucent border list. list = flat->sprite? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER; diff --git a/source/core/rendering/scene/hw_drawstructs.h b/source/core/rendering/scene/hw_drawstructs.h index 1c7416553..252a15b16 100644 --- a/source/core/rendering/scene/hw_drawstructs.h +++ b/source/core/rendering/scene/hw_drawstructs.h @@ -375,3 +375,18 @@ inline bool spriteHasTranslucency(const spritetype* tspr) return checkTranslucentReplacement(tileGetTexture(tspr->picnum)->GetID(), tspr->pal); } +inline void SetSpriteTranslucency(const spritetype* sprite, float& alpha, FRenderStyle& RenderStyle) +{ + bool trans = (sprite->cstat & CSTAT_SPRITE_TRANSLUCENT); + if (trans) + { + RenderStyle = GetRenderStyle(0, !!(sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT)); + alpha = GetAlphaFromBlend((sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0); + } + else + { + RenderStyle = LegacyRenderStyles[STYLE_Translucent]; + alpha = 1.f; + } + alpha *= 1.f - spriteext[sprite->owner].alpha; +} diff --git a/source/core/rendering/scene/hw_flats.cpp b/source/core/rendering/scene/hw_flats.cpp index f7d61fd0e..a99d9b13e 100644 --- a/source/core/rendering/scene/hw_flats.cpp +++ b/source/core/rendering/scene/hw_flats.cpp @@ -380,17 +380,8 @@ void HWFlat::ProcessFlatSprite(HWDrawInfo* di, spritetype* sprite, sectortype* s palette = sprite->pal; fade = lookups.getFade(sector[sprite->sectnum].floorpal); // fog is per sector. - bool trans = (sprite->cstat & CSTAT_SPRITE_TRANSLUCENT); - if (trans) - { - RenderStyle = GetRenderStyle(0, !!(sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT)); - alpha = GetAlphaFromBlend((sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0); - } - else - { - RenderStyle = LegacyRenderStyles[STYLE_Translucent]; - alpha = 1.f; - } + SetSpriteTranslucency(sprite, alpha, RenderStyle); + PutFlat(di, 0); } } diff --git a/source/core/rendering/scene/hw_sprites.cpp b/source/core/rendering/scene/hw_sprites.cpp index 888a8b429..66f96865f 100644 --- a/source/core/rendering/scene/hw_sprites.cpp +++ b/source/core/rendering/scene/hw_sprites.cpp @@ -353,17 +353,7 @@ void HWSprite::Process(HWDrawInfo* di, spritetype* spr, sectortype* sector, int fade = lookups.getFade(sector->floorpal); // fog is per sector. visibility = sectorVisibility(sector); - bool trans = (spr->cstat & CSTAT_SPRITE_TRANSLUCENT); - if (trans) - { - RenderStyle = GetRenderStyle(0, !!(spr->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT)); - alpha = GetAlphaFromBlend((spr->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0); - } - else - { - RenderStyle = LegacyRenderStyles[STYLE_Translucent]; - alpha = 1.f; - } + SetSpriteTranslucency(spr, alpha, RenderStyle); x = spr->x * (1 / 16.f); z = spr->z * (1 / -256.f); @@ -466,7 +456,7 @@ void HWSprite::Process(HWDrawInfo* di, spritetype* spr, sectortype* sector, int } #endif - PutSprite(di, alpha < 1.f-FLT_EPSILON || modelframe == 0); + PutSprite(di, true); rendered_sprites++; } @@ -500,17 +490,7 @@ bool HWSprite::ProcessVoxel(HWDrawInfo* di, voxmodel_t* vox, spritetype* spr, se if (!vox || (spr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_FLOOR) return false; - bool trans = (spr->cstat & CSTAT_SPRITE_TRANSLUCENT); - if (trans) - { - RenderStyle = GetRenderStyle(0, !!(spr->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT)); - alpha = GetAlphaFromBlend((spr->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0); - } - else - { - RenderStyle = LegacyRenderStyles[STYLE_Translucent]; - alpha = 1.f; - } + SetSpriteTranslucency(spr, alpha, RenderStyle); auto sprext = &spriteext[spr->owner]; @@ -575,7 +555,7 @@ bool HWSprite::ProcessVoxel(HWDrawInfo* di, voxmodel_t* vox, spritetype* spr, se auto vp = di->Viewpoint; depth = (float)((x - vp.Pos.X) * vp.TanCos + (y - vp.Pos.Y) * vp.TanSin); - PutSprite(di, alpha < 1.f - FLT_EPSILON); + PutSprite(di, spriteHasTranslucency(sprite)); rendered_sprites++; return true; } diff --git a/source/core/rendering/scene/hw_walls.cpp b/source/core/rendering/scene/hw_walls.cpp index 7117bbac1..466979155 100644 --- a/source/core/rendering/scene/hw_walls.cpp +++ b/source/core/rendering/scene/hw_walls.cpp @@ -749,7 +749,7 @@ void HWWall::DoTexture(HWDrawInfo* di, walltype* wal, walltype* refwall, float r tcs[UPRGT].v = setv(topleft, topright, glseg.fracright); tcs[LORGT].v = setv(bottomleft, bottomright, glseg.fracright); if (th == pow2size) CheckTexturePosition(); // for NPOT textures this adjustment can break things. - bool trans = type == RENDERWALL_M2S && (wal->cstat & CSTAT_WALL_TRANSLUCENT); + bool trans = type == RENDERWALL_M2S && maskWallHasTranslucency(wal); if (trans) { RenderStyle = GetRenderStyle(0, !!(wal->cstat & CSTAT_WALL_TRANS_FLIP)); @@ -1086,18 +1086,7 @@ void HWWall::ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* sect fade = lookups.getFade(sector->floorpal); // fog is per sector. visibility = sectorVisibility(sector); - bool trans = (sprite->cstat & CSTAT_SPRITE_TRANSLUCENT); - if (trans) - { - RenderStyle = GetRenderStyle(0, !!(sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT)); - alpha = GetAlphaFromBlend((sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0); - } - else - { - RenderStyle = LegacyRenderStyles[STYLE_Translucent]; - alpha = 1.f; - } - + SetSpriteTranslucency(sprite, alpha, RenderStyle); int height, topofs; if (hw_hightile && TileFiles.tiledata[spr->picnum].hiofs.xsize) @@ -1156,5 +1145,5 @@ void HWWall::ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* sect zbottom[0] = zbottom[1] = floorz; } } - PutWall(di, trans); + PutWall(di, spriteHasTranslucency(sprite)); } \ No newline at end of file From c9483353ff4058ecd7e68b84921c663aee1322d9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 19:56:18 +0200 Subject: [PATCH 49/70] - some more translucency checks. --- source/core/rendering/scene/hw_flats.cpp | 3 ++- source/core/rendering/scene/hw_sprites.cpp | 2 +- source/core/rendering/scene/hw_walls.cpp | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/source/core/rendering/scene/hw_flats.cpp b/source/core/rendering/scene/hw_flats.cpp index a99d9b13e..1f08a86e2 100644 --- a/source/core/rendering/scene/hw_flats.cpp +++ b/source/core/rendering/scene/hw_flats.cpp @@ -202,7 +202,8 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) state.SetRenderStyle(RenderStyle); state.SetTextureMode(RenderStyle); - if (!texture->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); + + if (!texture || !checkTranslucentReplacement(texture->GetID(), palette)) state.AlphaFunc(Alpha_GEqual, texture->alphaThreshold); else state.AlphaFunc(Alpha_GEqual, 0.f); } state.SetMaterial(texture, UF_Texture, 0, sprite == nullptr? CLAMP_NONE : CLAMP_XY, TRANSLATION(Translation_Remap + curbasepal, palette), -1); diff --git a/source/core/rendering/scene/hw_sprites.cpp b/source/core/rendering/scene/hw_sprites.cpp index 66f96865f..d32bf3514 100644 --- a/source/core/rendering/scene/hw_sprites.cpp +++ b/source/core/rendering/scene/hw_sprites.cpp @@ -75,7 +75,7 @@ void HWSprite::DrawSprite(HWDrawInfo* di, FRenderState& state, bool translucent) state.SetRenderStyle(RenderStyle); state.SetTextureMode(RenderStyle); - if (!texture || !texture->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); + if (!texture || !checkTranslucentReplacement(texture->GetID(), palette)) state.AlphaFunc(Alpha_GEqual, texture->alphaThreshold); else state.AlphaFunc(Alpha_Greater, 0.f); if (RenderStyle.BlendOp == STYLEOP_Add && RenderStyle.DestAlpha == STYLEALPHA_One) diff --git a/source/core/rendering/scene/hw_walls.cpp b/source/core/rendering/scene/hw_walls.cpp index 466979155..a1826af63 100644 --- a/source/core/rendering/scene/hw_walls.cpp +++ b/source/core/rendering/scene/hw_walls.cpp @@ -176,7 +176,7 @@ void HWWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) state.EnableTextureMatrix(false); state.SetEffect(EFF_NONE); - state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); + state.AlphaFunc(Alpha_GEqual, 0.5f); state.SetDepthFunc(DF_Less); state.SetRenderStyle(STYLE_Translucent); @@ -235,7 +235,7 @@ void HWWall::RenderTranslucentWall(HWDrawInfo *di, FRenderState &state) state.SetRenderStyle(RenderStyle); state.SetTextureMode(RenderStyle); - if (!texture->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); + if (!texture || !checkTranslucentReplacement(texture->GetID(), palette)) state.AlphaFunc(Alpha_GEqual, texture->alphaThreshold); else state.AlphaFunc(Alpha_GEqual, 0.f); RenderTexturedWall(di, state, HWWall::RWF_TEXTURED); state.SetRenderStyle(STYLE_Translucent); From 9f08f9786a65b933cc2ac07e5c550c1c1055276b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 20:03:50 +0200 Subject: [PATCH 50/70] - consolidated a bit of dead content in .def parser. --- source/build/src/defs.cpp | 53 ++++++--------------------------------- source/core/parsefuncs.h | 6 +++++ 2 files changed, 13 insertions(+), 46 deletions(-) diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 38e658ed6..9b7993666 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -387,38 +387,12 @@ static int32_t defsparser(scriptfile *script) } break; case T_SPRITECOL: - { - int32_t tile,col,col2; - - if (scriptfile_getsymbol(script,&tile)) break; - if (scriptfile_getnumber(script,&col)) break; - if (scriptfile_getnumber(script,&col2)) break; - } - break; - case T_2DCOL: - { - int32_t col,b,g,r; - - if (scriptfile_getnumber(script,&col)) break; - if (scriptfile_getnumber(script,&r)) break; - if (scriptfile_getnumber(script,&g)) break; - if (scriptfile_getnumber(script,&b)) break; - - if ((unsigned)col < 256) - { - } - } - break; case T_2DCOLIDXRANGE: // NOTE: takes precedence over 2dcol, see InitCustomColors() - { - int32_t col, idx, idxend; - - if (scriptfile_getnumber(script,&col)) break; - if (scriptfile_getnumber(script,&idx)) break; - if (scriptfile_getnumber(script,&idxend)) break; - - } - break; + parseSkip<3>(*script, pos); + break; + case T_2DCOL: + parseSkip<4>(*script, pos); + break; case T_FOGPAL: { int32_t p,r,g,b; @@ -461,15 +435,9 @@ static int32_t defsparser(scriptfile *script) } break; case T_CACHESIZE: - { - int32_t j; - - if (scriptfile_getnumber(script,&j)) break; - } - break; case T_SHADEFACTOR: - //scriptfile_getnumber(script, &realmaxshade); - //frealmaxshade = (float)realmaxshade; + case T_GLOBALGAMEFLAGS: + parseSkip<1>(*script, pos); break; case T_ARTFILE: { @@ -2087,13 +2055,6 @@ static int32_t defsparser(scriptfile *script) } break; - case T_GLOBALGAMEFLAGS: - { - int32_t dummy; - if (scriptfile_getnumber(script,&dummy)) break; - } - break; - case T_MULTIPSKY: { FScanner::SavedPos blockend; diff --git a/source/core/parsefuncs.h b/source/core/parsefuncs.h index c26746dff..b6f71f8f1 100644 --- a/source/core/parsefuncs.h +++ b/source/core/parsefuncs.h @@ -45,6 +45,12 @@ void tileRemoveReplacement(int num); // //=========================================================================== +template +void parseSkip(FScanner& sc, FScriptPosition& pos) +{ + for (int i = 0; i < cnt; i++) if (!sc.GetNumber(true)) return; +} + void parseDefineTexture(FScanner& sc, FScriptPosition& pos) { int tile, palette; From 778a75c097c9d93568abb4eb9c93973e22518e02 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 21:36:52 +0200 Subject: [PATCH 51/70] - fixed rffdefineid handler passing a bad file name to the backend. --- source/build/src/defs.cpp | 2 +- source/core/gamecontrol.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 99beccbb3..c03f6fe29 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -3156,7 +3156,7 @@ static int32_t defsparser(scriptfile *script) break; FStringf name("%s.%s", resName.GetChars(), resType.GetChars()); - fileSystem.CreatePathlessCopy(resName, resID, 0); + fileSystem.CreatePathlessCopy(name, resID, 0); } break; diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index 0b6da9865..e3f7d6926 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -1328,7 +1328,7 @@ void LoadDefinitions() { loaddefinitionsfile("engine/widescreen.def"); } - + fileSystem.InitHashChains(); } From f20acca49868a5b151de86831844bd777bbb093b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Apr 2021 22:03:25 +0200 Subject: [PATCH 52/70] - always default the resource ID to -1, even for dummy entries. Better be safe than sorry, this should never happen in Blood but we never know what people may load... --- source/common/filesystem/filesystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/common/filesystem/filesystem.cpp b/source/common/filesystem/filesystem.cpp index 0ea4ac7a6..dae98edf5 100644 --- a/source/common/filesystem/filesystem.cpp +++ b/source/common/filesystem/filesystem.cpp @@ -76,14 +76,14 @@ struct FileSystem::LumpRecord shortName.String[8] = 0; longName = ""; Namespace = lump->GetNamespace(); - resourceId = 0; + resourceId = -1; } else if ((lump->Flags & LUMPF_EMBEDDED) || !lump->getName() || !*lump->getName()) { shortName.qword = 0; longName = ""; Namespace = ns_hidden; - resourceId = 0; + resourceId = -1; } else { From c8c8635b4c18bd92c6f2376c2f1f0a9f9b5d69ff Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 9 Apr 2021 10:47:00 +0300 Subject: [PATCH 53/70] - fixed render backend switch menu option --- wadsrc/static/menudef.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 675a6b08b..907b26f2d 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1490,6 +1490,14 @@ OptionValue GPUSwitch 2.0, "$OPTVAL_INTEGRATED" } +OptionValue PreferBackend +{ + 0, "$OPTVAL_OPENGL" + 1, "$OPTVAL_VULKAN" + // Enable when HAVE_SOFTPOLY will be defined + //2, "$OPTVAL_SOFTPOLY" +} + OptionMenu VideoModeMenu protected { Title "$VIDMNU_TITLE" From 03c19a0cade0d1baf8852c7b572d4089cf156e9d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 9 Apr 2021 14:15:47 +0200 Subject: [PATCH 54/70] - removed the no longer used 'options' menu item graphic for Exhumed. --- wadsrc/static/filter/exhumed/engine/engine.def | 1 - wadsrc/static/filter/exhumed/tiles/options.png | Bin 1366 -> 0 bytes 2 files changed, 1 deletion(-) delete mode 100644 wadsrc/static/filter/exhumed/engine/engine.def delete mode 100644 wadsrc/static/filter/exhumed/tiles/options.png diff --git a/wadsrc/static/filter/exhumed/engine/engine.def b/wadsrc/static/filter/exhumed/engine/engine.def deleted file mode 100644 index eaa696b26..000000000 --- a/wadsrc/static/filter/exhumed/engine/engine.def +++ /dev/null @@ -1 +0,0 @@ -tilefromtexture 3463 { file "tiles/options.png" } \ No newline at end of file diff --git a/wadsrc/static/filter/exhumed/tiles/options.png b/wadsrc/static/filter/exhumed/tiles/options.png deleted file mode 100644 index a035cbae28d83ac531dd745548187721249c3b80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1366 zcmV-c1*!UpP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw0001K zP)t-sL?T^fT&w^9010qNS#tmYE+YT{E+YYWr9XB600ZbrL_t(Y z$IVuMmzy{YbaLn1u54^*#TEn2wcr0s-i%~Ya@)Sw|GIjFAGSc_(MV1R;qpHVzh&36 z{q+-ja`?S(zDM$R{J3@t|GeC8FCWluudlZkL-#5oDP^;CoN){T4o(!GO}UgRQfuXJ z97n++HNgrjmCBRf(orUvMw(31_({fTtQeA!Cp<~PwPF;<1lLLU1^av{pHJv8ib4C~ z%gNv*{v7FmOH^90(W1)7pta8WMuWDr6g(7us`~;xqT^=5BKSN`!QKl>Y~%E4q7g45 zr}Tvj1T-*`K0k5S8Sx7sCZbFS$Q1Rmw6(Pj_;S+7hiwBq-S@9|*tT7h>UISeXWv5K zO+}(^fe^Q4S@B|zL=L4#uflj~V1`7_=-kD8E9vHYAX$nbOgaAB+BXW7A#>KHebWeh zL3D<-I~aMBdEc%wJ^5DAwyea}mLOwnD<)K_g=9*=FBusmj0`gJb7sx0U=mqRLh>pS zimNz*+FDZ+BtnLewXJxJ>#7AJC_p!JJ$k=iNAty-Qp`62P+Pz;&?PKu)9BhBOv#=c z5|&-DrsC(!f+cYsA2ty`-!`#x$%9u-T(^+<9F$Ql!rXS{OUUw7I5)B&q|z7Y76pq~ z5J_+Aa=B;eBk~{> zjNp#Glvg)x~`VyTQe_TuQHruGghtw(hN(8wK*{Ts)JE3!ZI>ZC1 z@#pnHK2~KZivcZ+rbopT>dsi4?>pyKijrx2a0i^*Li)*41v*p+8m5p1=?nl7naf?1 zXLLjE(#+mk4VpLJ5p{&rG*uD`8loYHzMjM{5gk9OK-YaaWxfE`E`@Y0)>n9nRyQVe zHuTYZ7@Iv=;}$Rs=ge}c$#g%k*%s~uC=^Rj_2nWYlY)+rj63TI*>)1@jzu@`_Zj(o z=NrjBxJz;Q&VI5kQ9V<=rA^HloL7|OJC9t<6A{+_b?5T5mW+_7Bl6J3l>6A zrvX)=Ghdo_%lFBbN`vfrVUfpWT^4d%x-d|t6p$^nbZE@s6S~I^Ta07tjARY0TP>45 zGbNe0)}t|D68-qNdTssiMK?lrNs>mKd>FU+u%5E6seE*qGdhaLMxAeTWZUicjN@9<7)F-cR}&T~38D0i?u%KDdw_Kn-~dHi9p&)b=o2hs<+*YE-VeTD Date: Wed, 7 Apr 2021 21:46:44 +0200 Subject: [PATCH 55/70] - better .def loading logic. To allow cumulative loading without interfering with other ports, Raze will now look for files called xxxx-raze.def, where xxxx is the default .def name (e.g. duke3d-raze.def for Duke3D.) and if that is found, cumulatively load all same-named files - it will fall back on the default name if no such thing is found. -def still overrides both and will not cumulatively load. --- source/build/include/build.h | 2 +- source/build/src/defs.cpp | 59 +++++++++++++++++++----------------- source/core/gamecontrol.cpp | 43 ++++++++++++++++++++------ source/core/gamecontrol.h | 1 + 4 files changed, 67 insertions(+), 38 deletions(-) diff --git a/source/build/include/build.h b/source/build/include/build.h index 9ffd26e04..5accd465f 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -759,7 +759,7 @@ int32_t md_definehud (int32_t modelid, int32_t tilex, vec3f_t add, int32_t md_undefinetile(int32_t tile); int32_t md_undefinemodel(int32_t modelid); -int32_t loaddefinitionsfile(const char *fn, bool loadadds = false); +int32_t loaddefinitionsfile(const char *fn, bool loadadds = false, bool cumulative = false); // if loadboard() fails with -2 return, try loadoldboard(). if it fails with // -2, board is dodgy diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index c03f6fe29..3c35ff162 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -211,8 +211,6 @@ enum scripttoken_t }; static int32_t lastmodelid = -1, lastvoxid = -1, modelskin = -1, lastmodelskin = -1, seenframe = 0; -static char *faketilebuffer = NULL; -static int32_t faketilebuffersiz = 0; static const char *skyfaces[6] = { @@ -3169,37 +3167,44 @@ static int32_t defsparser(scriptfile *script) return 0; } - -int32_t loaddefinitionsfile(const char *fn, bool loadadds) +int32_t loaddefinitionsfile(const char *fn, bool loadadds, bool cumulative) { - scriptfile *script; - - script = scriptfile_fromfile(fn); - - if (script) + bool done = false; + auto parseit = [&](int lump) { - Printf(PRINT_NONOTIFY, "Loading \"%s\"\n",fn); + FScanner sc; + sc.OpenLumpNum(lump); + sc.SetNoOctals(true); + sc.SetNoFatalErrors(true); + defsparser(&sc); + done = true; + Printf(PRINT_NONOTIFY, "\n"); + }; - defsparser(script); + if (!cumulative) + { + int lump = fileSystem.FindFile(fn); + if (lump >= 0) + { + Printf(PRINT_NONOTIFY, "Loading \"%s\"\n", fn); + parseit(lump); + } + } + else + { + int lump, lastlump = 0; + while ((lump = fileSystem.FindLumpFullName(fn, &lastlump)) >= 0) + { + Printf(PRINT_NONOTIFY, "Loading \"%s\"\n", fileSystem.GetFileFullPath(lump)); + parseit(lump); + } } if (userConfig.AddDefs && loadadds) for (auto& m : *userConfig.AddDefs) { Printf("Loading module \"%s\"\n",m.GetChars()); - defsparser_include(m, NULL, NULL); // Q: should we let the external script see our symbol table? - } - - if (script) - scriptfile_close(script); - - DO_FREE_AND_NULL(faketilebuffer); - faketilebuffersiz = 0; - - if (!script) return -1; - - Printf(PRINT_NONOTIFY, "\n"); - - return 0; + defsparser_include(m, nullptr, nullptr); // Q: should we let the external script see our symbol table? + Printf(PRINT_NONOTIFY, "\n"); + } + return done ? 0 : -1; } - -// vim:ts=4: diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index e3f7d6926..c9d0f4dfb 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -350,7 +350,7 @@ void UserConfig::ProcessOptions() static const char* defs[] = { "-def", "-h", nullptr }; Args->CollectFiles("-def", defs, ".def"); - DefaultDef = Args->CheckValue("-def"); + UserDef = Args->CheckValue("-def"); if (DefaultCon.IsEmpty()) { @@ -1309,27 +1309,50 @@ void DrawCrosshair(int deftile, int health, double xdelta, double ydelta, double void LoadDefinitions() { - loaddefinitionsfile("engine/engine.def"); // Internal stuff that is required. - - const char* defsfile = G_DefFile(); - cycle_t deftimer; deftimer.Reset(); deftimer.Clock(); - if (!loaddefinitionsfile(defsfile, true)) + const char* loaded = nullptr; + + const char* defsfile = G_DefFile(); + FString razedefsfile = defsfile; + razedefsfile.Substitute(".def", "-raze.def"); + + loaddefinitionsfile("engine/engine.def", false); // Internal stuff that is required. + + // check what we have. + // user .defs override the default ones and are not cumulative. + // if we fine even one Raze-specific file, all of those will be loaded cumulatively. + // otherwise the default rules inherited from older ports apply. + if (userConfig.UserDef.IsNotEmpty()) + { + if (!loaddefinitionsfile(userConfig.UserDef, true, false)) loaded = userConfig.UserDef; + } + else + { + if (fileSystem.FileExists(razedefsfile)) + { + if (!loaddefinitionsfile(razedefsfile, true, true)) loaded = razedefsfile; + } + else + { + if (!loaddefinitionsfile(defsfile, true, false)) loaded = defsfile; + } + } + + if (loaded) { deftimer.Unclock(); - Printf(PRINT_NONOTIFY, "Definitions file \"%s\" loaded in %.3f ms.\n", defsfile, deftimer.TimeMS()); + DPrintf(DMSG_SPAMMY, "Definitions file \"%s\" loaded, %f ms.\n", loaded, deftimer.TimeMS()); } userConfig.AddDefs.reset(); - // load the widescreen replacements last so that they do not clobber the CRC for the original items so that mod-side replacement are picked up. + // load the widescreen replacements last. This ensures that mods still get the correct CRCs for their own tile replacements. if (fileSystem.FindFile("engine/widescreen.def") >= 0 && !Args->CheckParm("-nowidescreen")) { loaddefinitionsfile("engine/widescreen.def"); } - fileSystem.InitHashChains(); - + fileSystem.InitHashChains(); // make sure that any resources that got added can be found again. } bool M_Active() diff --git a/source/core/gamecontrol.h b/source/core/gamecontrol.h index 85242b2f7..8a1cd1685 100644 --- a/source/core/gamecontrol.h +++ b/source/core/gamecontrol.h @@ -65,6 +65,7 @@ struct UserConfig { FString gamegrp; FString CommandMap; + FString UserDef; FString DefaultDef; FString DefaultCon; FString CommandDemo; From 57c7a85d9f1c9acdf986c16065ba8d087fd38143 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 9 Apr 2021 15:55:30 +0300 Subject: [PATCH 56/70] - fixed compilation with Clang source/build/src/defs.cpp:3198:56: error: cannot pass non-trivial object of type 'FString' to variadic function; expected type from format string was 'char *' [-Wnon-pod-varargs] --- source/build/src/defs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 3c35ff162..d141f2219 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -3195,7 +3195,7 @@ int32_t loaddefinitionsfile(const char *fn, bool loadadds, bool cumulative) int lump, lastlump = 0; while ((lump = fileSystem.FindLumpFullName(fn, &lastlump)) >= 0) { - Printf(PRINT_NONOTIFY, "Loading \"%s\"\n", fileSystem.GetFileFullPath(lump)); + Printf(PRINT_NONOTIFY, "Loading \"%s\"\n", fileSystem.GetFileFullPath(lump).GetChars()); parseit(lump); } } From 2820c50f3e0f2aabbb820116c78cb70d62c7502a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 9 Apr 2021 18:25:32 +0200 Subject: [PATCH 57/70] - Blood: let the RFS parser handle forward slashes when cutting out the base directory of a given file name. --- source/games/blood/src/barf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/games/blood/src/barf.cpp b/source/games/blood/src/barf.cpp index f5f6f6381..ad218159c 100644 --- a/source/games/blood/src/barf.cpp +++ b/source/games/blood/src/barf.cpp @@ -656,7 +656,7 @@ void ParseScript(int lumpnum) if (dword_44CE0[gParseLevel] == 0) { // In the RFS files I have seen the outermost directory is not part of what goes into the file system. - auto inp1 = strchr(inp, '\\'); + auto inp1 = strpbrk(inp, "/\\"); if (!inp1 || !fileSystem.CreatePathlessCopy(inp1 + 1, ID, nFlags)) { // I'll activate this when I find evidence that it is needed. Otherwise the risk of picking up unwanted data is too high. From 92697686cbf7d772ba3303c39223154d0b807d0a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 9 Apr 2021 19:59:03 +0200 Subject: [PATCH 58/70] - migrated a few more .def commands. --- source/build/src/defs.cpp | 57 +++++---------------------------------- 1 file changed, 7 insertions(+), 50 deletions(-) diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 91c2eac86..8cbb7844a 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -323,24 +323,11 @@ static int32_t defsparser(scriptfile *script) break; } case T_INCLUDEDEFAULT: - { defsparser_include(G_DefaultDefFile(), script, &pos); break; - } case T_DEFINE: - { - FString name; - int32_t number; - - if (scriptfile_getstring(script,&name)) break; - if (scriptfile_getsymbol(script,&number)) break; - - if (scriptfile_addsymbolvalue(script, name,number) < 0) - pos.Message(MSG_WARNING, "Warning: Symbol %s was NOT redefined to %d", name.GetChars(),number); + parseDefine(*script, pos); break; - } - - // OLD (DEPRECATED) DEFINITION SYNTAX case T_DEFINETEXTURE: parseDefineTexture(*script, pos); break; @@ -348,44 +335,14 @@ static int32_t defsparser(scriptfile *script) parseDefineSkybox(*script, pos); break; case T_DEFINETINT: - { - int32_t pal, r,g,b,f; - - if (scriptfile_getsymbol(script,&pal)) break; - if (scriptfile_getnumber(script,&r)) break; - if (scriptfile_getnumber(script,&g)) break; - if (scriptfile_getnumber(script,&b)) break; - if (scriptfile_getnumber(script,&f)) break; //effects - lookups.setPaletteTint(pal,r,g,b,0,0,0,f); - } - break; + parseDefineTint(*script, pos); + break; case T_ALPHAHACK: - { - int32_t tile; - double alpha; - - if (scriptfile_getsymbol(script,&tile)) break; - if (scriptfile_getdouble(script,&alpha)) break; - if ((uint32_t)tile < MAXTILES) - TileFiles.tiledata[tile].texture->alphaThreshold = (float)alpha; - } - break; + parseAlphahack(*script, pos); + break; case T_ALPHAHACKRANGE: - { - int32_t tilenume1,tilenume2; - double alpha; - - if (scriptfile_getsymbol(script,&tilenume1)) break; - if (scriptfile_getsymbol(script,&tilenume2)) break; - if (scriptfile_getdouble(script,&alpha)) break; - - if (check_tile_range("alphahackrange", &tilenume1, &tilenume2, script, pos)) - break; - - for (int i=tilenume1; i<=tilenume2; i++) - TileFiles.tiledata[i].texture->alphaThreshold = (float)alpha; - } - break; + parseAlphahackRange(*script, pos); + break; case T_SPRITECOL: case T_2DCOLIDXRANGE: // NOTE: takes precedence over 2dcol, see InitCustomColors() parseSkip<3>(*script, pos); From 2084c5353831af850d70742322cceca7aa5ec58e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 9 Apr 2021 21:21:53 +0200 Subject: [PATCH 59/70] - fixed extended music lookup again. --- source/core/parsefuncs.h | 1 + source/core/raze_music.cpp | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/source/core/parsefuncs.h b/source/core/parsefuncs.h index 61459d10a..5f2d18026 100644 --- a/source/core/parsefuncs.h +++ b/source/core/parsefuncs.h @@ -243,3 +243,4 @@ void parseDefineTint(FScanner& sc, FScriptPosition& pos) if (!sc.GetNumber(f)) return; lookups.setPaletteTint(pal, r, g, b, 0, 0, 0, f); } + \ No newline at end of file diff --git a/source/core/raze_music.cpp b/source/core/raze_music.cpp index b2c3f0aed..c23f0b0ff 100644 --- a/source/core/raze_music.cpp +++ b/source/core/raze_music.cpp @@ -133,21 +133,24 @@ FileReader OpenMusic(const char* musicname) if (!reader.isOpen()) { int lumpnum = LookupMusic(musicname); - if (mus_extendedlookup && lumpnum >= 0) - { - // EDuke also looks in a subfolder named after the main game resource. Do this as well if extended lookup is active. - auto rfn = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(lumpnum)); - auto rfbase = ExtractFileBase(rfn); - FStringf aliasMusicname("music/%s/%s", rfbase.GetChars(), musicname); - int newlumpnum = LookupMusic(aliasMusicname); - if (newlumpnum >= 0) lumpnum = newlumpnum; - } - if (lumpnum == -1) + if (mus_extendedlookup || lumpnum < 0) { + if (lumpnum >= 0) + { + // EDuke also looks in a subfolder named after the main game resource. Do this as well if extended lookup is active. + auto rfn = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(lumpnum)); + auto rfbase = ExtractFileBase(rfn); + FStringf aliasMusicname("music/%s/%s", rfbase.GetChars(), musicname); + int newlumpnum = LookupMusic(aliasMusicname); + if (newlumpnum >= 0) lumpnum = newlumpnum; + } + // Always look in the 'music' subfolder as well. This gets used by multiple setups to store ripped CD tracks. FStringf aliasMusicname("music/%s", musicname); - lumpnum = LookupMusic(aliasMusicname); + int newlumpnum = LookupMusic(aliasMusicname, lumpnum >= 0); + if (newlumpnum >= 0) lumpnum = newlumpnum; } + if (lumpnum == -1 && (g_gameType & GAMEFLAG_SW)) { // Some Shadow Warrior distributions have the music in a subfolder named 'classic'. Check that, too. From 19a4c12e6abbd36a5c4a1a330c1e8de82268c576 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 9 Apr 2021 22:11:16 +0200 Subject: [PATCH 60/70] - Blood: undid restriction for original QAV for Guns Akimbo shotgun fix. --- source/games/blood/src/weapon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/games/blood/src/weapon.cpp b/source/games/blood/src/weapon.cpp index 3dd797e90..130074dd5 100644 --- a/source/games/blood/src/weapon.cpp +++ b/source/games/blood/src/weapon.cpp @@ -266,7 +266,7 @@ void WeaponDraw(PLAYER *pPlayer, int shade, double xpos, double ypos, int palnum if (pPlayer->weaponTimer == 0) // playing idle QAV? { // Double shotgun fix from BloodGDX. - if (/*!IsOriginalDemo() &&*/ (pPlayer->weaponState == -1 || (pPlayer->curWeapon == 3 && pPlayer->weaponState == 7)) && isOriginalQAV()) + if (/*!IsOriginalDemo() &&*/ (pPlayer->weaponState == -1 || (pPlayer->curWeapon == 3 && pPlayer->weaponState == 7))/* && isOriginalQAV()*/) duration = pQAV->duration - 1; else duration = (PlayClock + MulScale(4, smoothratio, 16)) % pQAV->duration; } From 345275db5d32b2b33d49a06a6e82b38de945731c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 9 Apr 2021 22:48:16 +0200 Subject: [PATCH 61/70] - better handling for portal lines having sloped back sectors. This is a very ugly special case that probably needs a bit more work to get right, for now this should be enough as this combination is rather rare. --- source/core/rendering/scene/hw_walls.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/source/core/rendering/scene/hw_walls.cpp b/source/core/rendering/scene/hw_walls.cpp index a1826af63..b4a234023 100644 --- a/source/core/rendering/scene/hw_walls.cpp +++ b/source/core/rendering/scene/hw_walls.cpp @@ -893,7 +893,7 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec #ifdef _DEBUG - if (wal - wall == 843) + if (wal - wall == 788) { int a = 0; } @@ -990,11 +990,14 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec { float bch1a = bch1; float bch2a = bch2; - if (ffh1 > bch1 && ffh2 > bch2) + if (ffh1 > bch1 || ffh2 > bch2) { - // the back sector's floor obstructs part of this wall - bch2a = ffh2; - bch1a = ffh1; + // the back sector's floor obstructs part of this wall. Todo: Handle the portal case better. + if ((ffh1 > bch1 && ffh2 > bch2) || frontsector->portalflags == PORTAL_SECTOR_FLOOR) + { + bch2a = ffh2; + bch1a = ffh1; + } } if (bch1a < fch1 || bch2a < fch2) @@ -1025,11 +1028,14 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec // lower texture if (!(frontsector->floorstat & backsector->floorstat & CSTAT_SECTOR_SKY)) { - if (fch1 < bfh1 && fch2 < bfh2) + if (fch1 < bfh1 || fch2 < bfh2) { - // the back sector's ceiling obstructs part of this wall. - bfh1 = fch1; - bfh2 = fch2; + // the back sector's ceiling obstructs part of this wall. Todo: Handle the portal case better. + if ((fch1 < bfh1 && fch2 < bfh2) || frontsector->portalflags == PORTAL_SECTOR_CEILING) + { + bfh1 = fch1; + bfh2 = fch2; + } } if (bfh1 > ffh1 || bfh2 > ffh2) From e0dc261dfd31d35e5f47beee919d1f9fbf1d24ee Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 10 Apr 2021 00:05:29 +0200 Subject: [PATCH 62/70] - fixed edge case in wall sorter when the camera is exactly on a line that's being checked. --- source/core/rendering/scene/hw_bunchdrawer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/core/rendering/scene/hw_bunchdrawer.cpp b/source/core/rendering/scene/hw_bunchdrawer.cpp index 23168b8da..4f66ef393 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.cpp +++ b/source/core/rendering/scene/hw_bunchdrawer.cpp @@ -297,7 +297,7 @@ int BunchDrawer::WallInFront(int wall1, int wall2) if ((t1 * t2) >= 0) { t2 = PointOnLineSide(viewx, viewy, x1s, y1s, dx, dy); - return((t2 * t1) < 0); + return((t2 * t1) <= 0); } dx = x2e - x2s; @@ -313,7 +313,7 @@ int BunchDrawer::WallInFront(int wall1, int wall2) if ((t1 * t2) >= 0) { t2 = PointOnLineSide(viewx, viewy, x2s, y2s, dx, dy); - return((t2 * t1) >= 0); + return((t2 * t1) > 0); } return(-2); } @@ -525,7 +525,7 @@ void BunchDrawer::ProcessSector(int sectnum, bool portal) void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount, bool portal) { - //Printf("----------------------------------------- \n"); + //Printf("----------------------------------------- \nstart at sector %d\n", viewsectors[0]); auto process = [&]() { for (unsigned i = 0; i < sectcount; i++) From 28fb752446066538af5bf4c79d5a9717807788e8 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Sat, 10 Apr 2021 08:59:40 +1000 Subject: [PATCH 63/70] - Replace `gethiq16angle()` with `bvectangbam()` in renderer code. This addresses some observed clipping issues in the new renderer. --- source/core/rendering/scene/hw_clipper.cpp | 2 +- source/core/rendering/scene/hw_portal.cpp | 34 +++++++++++----------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/source/core/rendering/scene/hw_clipper.cpp b/source/core/rendering/scene/hw_clipper.cpp index 13476a747..81b3c08da 100644 --- a/source/core/rendering/scene/hw_clipper.cpp +++ b/source/core/rendering/scene/hw_clipper.cpp @@ -377,7 +377,7 @@ binangle Clipper::PointToAngle(const vec2_t& pos) return bamang(xs_Fix<30>::ToFix(result)); } #else - return q16ang(gethiq16angle(vec.x, vec.y)); + return bvectangbam(vec.x, vec.y); #endif } diff --git a/source/core/rendering/scene/hw_portal.cpp b/source/core/rendering/scene/hw_portal.cpp index 016725636..db37b870f 100644 --- a/source/core/rendering/scene/hw_portal.cpp +++ b/source/core/rendering/scene/hw_portal.cpp @@ -431,8 +431,8 @@ void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper) clipper->SafeAddClipRange(bamang(0), bamang(0xffffffff)); for (unsigned int i = 0; i < lines.Size(); i++) { - binangle startang = q16ang(gethiq16angle(lines[i].seg->x - view.x, lines[i].seg->y - view.y)); - binangle endang = q16ang(gethiq16angle(wall[lines[i].seg->point2].x - view.x, wall[lines[i].seg->point2].y - view.y)); + binangle startang = bvectangbam(lines[i].seg->x - view.x, lines[i].seg->y - view.y); + binangle endang = bvectangbam(wall[lines[i].seg->point2].x - view.x, wall[lines[i].seg->point2].y - view.y); if (endang.asbam() - startang.asbam() >= ANGLE_180) { @@ -574,14 +574,14 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe int newx = int((x << 1) + Scale(dx, i, j) - view.x); int newy = int((y << 1) + Scale(dy, i, j) - view.y); - int newan = ((gethiq16angle(dx, dy) << 1) - bamang(vp.RotAngle).asq16()) & 0x7FFFFFF; - vp.RotAngle = q16ang(newan).asbam(); + auto newan = bamang(int64_t((bvectangf(dx, dy) * (BAMUNIT << 1)) - vp.RotAngle) & 0xFFFFFFFF); + vp.RotAngle = newan.asbam(); vp.SectNums = nullptr; vp.SectCount = line->sector; vp.Pos.X = newx / 16.f; vp.Pos.Y = newy / -16.f; - vp.HWAngles.Yaw = -90.f + q16ang(newan).asdeg(); + vp.HWAngles.Yaw = -90.f + newan.asdeg(); double FocalTangent = tan(vp.FieldOfView.Radians() / 2); DAngle an = 270. - vp.HWAngles.Yaw.Degrees; @@ -598,9 +598,9 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe angle_t af = di->FrustumAngle(); if (af < ANGLE_180) clipper->SafeAddClipRange(bamang(vp.RotAngle + af), bamang(vp.RotAngle - af)); - auto startan = gethiq16angle(line->x - newx, line->y - newy); - auto endan = gethiq16angle(wall[line->point2].x - newx, wall[line->point2].y - newy); - clipper->SafeAddClipRange(q16ang(startan), q16ang(endan)); // we check the line from the backside so angles are reversed. + auto startan = bvectangbam(line->x - newx, line->y - newy); + auto endan = bvectangbam(wall[line->point2].x - newx, wall[line->point2].y - newy); + clipper->SafeAddClipRange(startan, endan); // we check the line from the backside so angles are reversed. return true; } @@ -647,10 +647,10 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl int dx2 = wall[line->point2].x - line->x; int dy2 = wall[line->point2].y - line->y; - int srcang = gethiq16angle(dx, dy); - int destang = gethiq16angle(-dx, -dy); + auto srcang = bvectangbam(dx, dy); + auto destang = bvectangbam(-dx, -dy); - vp.RotAngle += q16ang(destang - srcang).asbam(); + vp.RotAngle += (destang - srcang).asbam(); #endif // Nothing in the entire setup mandates that both lines have the same length. @@ -670,9 +670,9 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl angle_t af = di->FrustumAngle(); if (af < ANGLE_180) clipper->SafeAddClipRange(bamang(vp.RotAngle + af), bamang(vp.RotAngle - af)); - auto startan = gethiq16angle(origin->x - origx, origin->y - origy); - auto endan = gethiq16angle(wall[origin->point2].x - origx, wall[origin->point2].y - origy); - clipper->SafeAddClipRange(q16ang(endan), q16ang(startan)); + auto startan = bvectangbam(origin->x - origx, origin->y - origy); + auto endan = bvectangbam(wall[origin->point2].x - origx, wall[origin->point2].y - origy); + clipper->SafeAddClipRange(endan, startan); return true; } @@ -724,9 +724,9 @@ bool HWLineToSpritePortal::Setup(HWDrawInfo* di, FRenderState& rstate, Clipper* angle_t af = di->FrustumAngle(); if (af < ANGLE_180) clipper->SafeAddClipRange(bamang(vp.RotAngle + af), bamang(vp.RotAngle - af)); - auto startan = gethiq16angle(origin->x - origx, origin->y - origy); - auto endan = gethiq16angle(wall[origin->point2].x - origx, wall[origin->point2].y - origy); - clipper->SafeAddClipRange(q16ang(endan), q16ang(startan)); + auto startan = bvectangbam(origin->x - origx, origin->y - origy); + auto endan = bvectangbam(wall[origin->point2].x - origx, wall[origin->point2].y - origy); + clipper->SafeAddClipRange(endan, startan); return true; } From 8ebd1a9ebce17b79445cda8a617b837e9509a5ae Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Sat, 10 Apr 2021 10:06:30 +1000 Subject: [PATCH 64/70] - binaryangle.h: Clean up `HorizToPitch()` since we're on the new renderer. --- source/core/binaryangle.h | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/source/core/binaryangle.h b/source/core/binaryangle.h index 6d827a2d8..e4d86116a 100644 --- a/source/core/binaryangle.h +++ b/source/core/binaryangle.h @@ -366,24 +366,14 @@ inline FSerializer &Serialize(FSerializer &arc, const char *key, binangle &obj, //--------------------------------------------------------------------------- // -// Constants and functions for use with fixedhoriz and friendly functions. +// Functions for use with fixedhoriz and friendly functions. // //--------------------------------------------------------------------------- -// 280039127 is the maximum horizon in Q16.16 the engine will handle before wrapping around. -constexpr double horizDiff = 280039127 * 3. / 100.; - -// Degrees needed to convert horizAngle into pitch degrees. -constexpr double horizDegrees = 183.503609961216825; - -// Ratio to convert inverse tangent to -90/90 degrees of pitch. -constexpr double horizRatio = horizDegrees / pi::pi(); - -// Horizon conversion functions. -inline double HorizToPitch(double horiz) { return atan2(horiz, horizDiff / 65536.) * horizRatio; } -inline double HorizToPitch(fixed_t q16horiz) { return atan2(q16horiz, horizDiff) * horizRatio; } -inline fixed_t PitchToHoriz(double horizAngle) { return xs_CRoundToInt(horizDiff * tan(horizAngle * (pi::pi() / horizDegrees))); } -inline int32_t PitchToBAM(double horizAngle) { return xs_CRoundToInt(clamp(horizAngle * (1073741823.5 / 45.), -INT32_MAX, INT32_MAX)); } +inline double HorizToPitch(double horiz) { return atan2(horiz, 128) * (180. / pi::pi()); } +inline double HorizToPitch(fixed_t q16horiz) { return atan2(q16horiz, IntToFixed(128)) * (180. / pi::pi()); } +inline fixed_t PitchToHoriz(double pitch) { return xs_CRoundToInt(IntToFixed(128) * tan(pitch * (pi::pi() / 180.))); } +inline int32_t PitchToBAM(double pitch) { return xs_CRoundToInt(clamp(pitch * (1073741823.5 / 45.), -INT32_MAX, INT32_MAX)); } inline constexpr double BAMToPitch(int32_t bam) { return bam * (45. / 1073741823.5); } From 2e191f2742daf3c0c190ccea93730ba289e0437e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 10 Apr 2021 09:57:03 +0200 Subject: [PATCH 65/70] - consolidated the SetLightAndFog code fragments. --- source/core/rendering/scene/hw_drawstructs.h | 39 ++++++++++++++- source/core/rendering/scene/hw_flats.cpp | 26 +--------- source/core/rendering/scene/hw_sprites.cpp | 50 ++++++-------------- source/core/rendering/scene/hw_walls.cpp | 41 ++-------------- 4 files changed, 57 insertions(+), 99 deletions(-) diff --git a/source/core/rendering/scene/hw_drawstructs.h b/source/core/rendering/scene/hw_drawstructs.h index 252a15b16..8b051fac7 100644 --- a/source/core/rendering/scene/hw_drawstructs.h +++ b/source/core/rendering/scene/hw_drawstructs.h @@ -12,6 +12,8 @@ #include "render.h" #include "matrix.h" #include "gamecontrol.h" +#include "hw_renderstate.h" +#include "hw_cvars.h" #ifdef _MSC_VER #pragma warning(disable:4244) @@ -194,7 +196,6 @@ public: void SetupLights(HWDrawInfo *di, FDynLightData &lightdata); void MakeVertices(HWDrawInfo *di, bool nosplit); - void SetLightAndFog(FRenderState& state); void SkyPlane(HWDrawInfo *di, sectortype *sector, int plane, bool allowmirror); void SkyLine(HWDrawInfo *di, sectortype *sec, walltype *line); @@ -390,3 +391,39 @@ inline void SetSpriteTranslucency(const spritetype* sprite, float& alpha, FRende } alpha *= 1.f - spriteext[sprite->owner].alpha; } + +//========================================================================== +// +// +// +//========================================================================== +extern PalEntry GlobalMapFog; +extern float GlobalFogDensity; + +__forceinline void SetLightAndFog(FRenderState& state, PalEntry fade, int palette, int shade, int visibility, float alpha, bool setcolor = true) +{ + // Fog must be done before the texture so that the texture selector can override it. + bool foggy = (GlobalMapFog || (fade & 0xffffff)); + auto ShadeDiv = lookups.tables[palette].ShadeFactor; + shade = clamp(shade, 0, numshades - 1); + // Disable brightmaps if non-black fog is used. + if (ShadeDiv >= 1 / 1000.f && foggy) + { + state.EnableFog(1); + float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); + state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); + state.SetSoftLightLevel(255); + state.SetLightParms(128.f, 1 / 1000.f); + } + else + { + state.EnableFog(0); + state.SetFog(0, 0); + state.SetSoftLightLevel(gl_fogmode != 0 && ShadeDiv >= 1 / 1000.f ? 255 - Scale(shade, 255, numshades) : 255); + state.SetLightParms(visibility, ShadeDiv / (numshades - 2)); + } + + // The shade rgb from the tint is ignored here. + state.SetColor(globalr * (1 / 255.f), globalg * (1 / 255.f), globalb * (1 / 255.f), alpha); +} + diff --git a/source/core/rendering/scene/hw_flats.cpp b/source/core/rendering/scene/hw_flats.cpp index 1f08a86e2..71a1f50e7 100644 --- a/source/core/rendering/scene/hw_flats.cpp +++ b/source/core/rendering/scene/hw_flats.cpp @@ -41,9 +41,6 @@ CVAR(Int, gl_breaksec, -1, 0) #endif -extern PalEntry GlobalMapFog; -extern float GlobalFogDensity; - //========================================================================== // // @@ -170,28 +167,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) else state.SetNormal({ 0, -1, 0 }); } - // Fog must be done before the texture so that the texture selector can override it. - bool foggy = (GlobalMapFog || (fade & 0xffffff)); - auto ShadeDiv = lookups.tables[palette].ShadeFactor; - // Disable brightmaps if non-black fog is used. - if (ShadeDiv >= 1 / 1000.f && foggy) - { - state.EnableFog(1); - float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); - state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); - state.SetSoftLightLevel(255); - state.SetLightParms(128.f, 1 / 1000.f); - } - else - { - state.EnableFog(0); - state.SetFog(0, 0); - state.SetSoftLightLevel(ShadeDiv >= 1 / 1000.f ? 255 - Scale(shade, 255, numshades) : 255); - state.SetLightParms(visibility, ShadeDiv / (numshades - 2)); - } - - // The shade rgb from the tint is ignored here. - state.SetColorAlpha(PalEntry(255, globalr, globalg, globalb), alpha); + SetLightAndFog(state, fade, palette, shade, visibility, alpha); if (translucent) { diff --git a/source/core/rendering/scene/hw_sprites.cpp b/source/core/rendering/scene/hw_sprites.cpp index d32bf3514..17934fac3 100644 --- a/source/core/rendering/scene/hw_sprites.cpp +++ b/source/core/rendering/scene/hw_sprites.cpp @@ -46,10 +46,6 @@ #include "hw_viewpointbuffer.h" #include "hw_voxels.h" -extern PalEntry GlobalMapFog; -extern float GlobalFogDensity; - - //========================================================================== // // @@ -114,36 +110,15 @@ void HWSprite::DrawSprite(HWDrawInfo* di, FRenderState& state, bool translucent) } // Fog must be done before the texture so that the texture selector can override it. - bool foggy = (GlobalMapFog || (fade & 0xffffff)); - auto ShadeDiv = lookups.tables[palette].ShadeFactor; // Disable brightmaps if non-black fog is used. int shade = this->shade; - PalEntry color(255, globalr, globalg, globalb); if (this->shade > numshades) // handling of SW's shadow hack using a shade of 127. { shade = sector[sprite->sectnum].floorshade; - color = 0xff000000; - } - shade = clamp(shade, 0, numshades - 1); - - if (ShadeDiv >= 1 / 1000.f && foggy && !foglayer) - { - state.EnableFog(1); - float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); - state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); - state.SetSoftLightLevel(255); - state.SetLightParms(128.f, 1 / 1000.f); - } - else - { - state.EnableFog(0); - state.SetFog(0, 0); - state.SetSoftLightLevel(ShadeDiv >= 1 / 1000.f ? 255 - Scale(shade, 255, numshades) : 255); - state.SetLightParms(visibility, ShadeDiv / (numshades - 2)); + state.SetColor(0, 0, 0, alpha); } - // The shade rgb from the tint is ignored here. - state.SetColorAlpha(color, alpha); + SetLightAndFog(state, fade, palette, shade, visibility, alpha, this->shade <= numshades); if (modelframe == 0) { @@ -158,15 +133,20 @@ void HWSprite::DrawSprite(HWDrawInfo* di, FRenderState& state, bool translucent) state.SetLightIndex(-1); state.Draw(DT_TriangleStrip, vertexindex, 4); - if (ShadeDiv >= 1 / 1000.f && foggy && foglayer) + if (foglayer) { - // If we get here we know that we have colored fog and no fixed colormap. - float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); - state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); - state.SetTextureMode(TM_FOGLAYER); - state.SetRenderStyle(STYLE_Translucent); - state.Draw(DT_TriangleStrip, vertexindex, 4); - state.SetTextureMode(TM_NORMAL); + bool foggy = (GlobalMapFog || (fade & 0xffffff)); + auto ShadeDiv = lookups.tables[palette].ShadeFactor; + if (ShadeDiv >= 1 / 1000.f && foggy) + { + // If we get here we know that we have colored fog and no fixed colormap. + float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); + state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); + state.SetTextureMode(TM_FOGLAYER); + state.SetRenderStyle(STYLE_Translucent); + state.Draw(DT_TriangleStrip, vertexindex, 4); + state.SetTextureMode(TM_NORMAL); + } } } else diff --git a/source/core/rendering/scene/hw_walls.cpp b/source/core/rendering/scene/hw_walls.cpp index b4a234023..b41ae6f2a 100644 --- a/source/core/rendering/scene/hw_walls.cpp +++ b/source/core/rendering/scene/hw_walls.cpp @@ -39,9 +39,6 @@ #include "flatvertices.h" #include "glbackend/glbackend.h" -extern PalEntry GlobalMapFog; -extern float GlobalFogDensity; - //========================================================================== // // Create vertices for one wall @@ -104,7 +101,7 @@ void HWWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state) if (gl_fogmode)// && !di->isFullbrightScene()) { state.EnableDrawBufferAttachments(false); - SetLightAndFog(state); + SetLightAndFog(state, fade, palette, shade, visibility, alpha); state.SetEffect(EFF_FOGBOUNDARY); state.AlphaFunc(Alpha_GEqual, 0.f); state.SetDepthBias(-1, -128); @@ -115,38 +112,6 @@ void HWWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state) } } -//========================================================================== -// -// -// -//========================================================================== - -void HWWall::SetLightAndFog(FRenderState& state) -{ - // Fog must be done before the texture so that the texture selector can override it. - bool foggy = (GlobalMapFog || (fade & 0xffffff)); - auto ShadeDiv = lookups.tables[palette].ShadeFactor; - // Disable brightmaps if non-black fog is used. - if (ShadeDiv >= 1 / 1000.f && foggy) - { - state.EnableFog(1); - float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); - state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); - state.SetSoftLightLevel(255); - state.SetLightParms(128.f, 1 / 1000.f); - } - else - { - state.EnableFog(0); - state.SetFog(0, 0); - state.SetSoftLightLevel(ShadeDiv >= 1 / 1000.f ? 255 - Scale(shade, 255, numshades) : 255); - state.SetLightParms(visibility, ShadeDiv / (numshades - 2)); - } - - // The shade rgb from the tint is ignored here. - state.SetColorAlpha(PalEntry(255, globalr, globalg, globalb), alpha); -} - //========================================================================== // // @@ -163,7 +128,7 @@ void HWWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) // Use sphere mapping for this state.SetEffect(EFF_SPHEREMAP); - SetLightAndFog(state); + SetLightAndFog(state, fade, palette, shade, visibility, alpha, false); state.SetColor(PalEntry(25, globalr >> 1, globalg >> 1, globalb >> 1)); state.SetRenderStyle(STYLE_Add); @@ -190,7 +155,7 @@ void HWWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) { - SetLightAndFog(state); + SetLightAndFog(state, fade, palette, shade, visibility, alpha); state.SetMaterial(texture, UF_Texture, 0, sprite == nullptr ? (flags & (HWF_CLAMPX | HWF_CLAMPY)) : CLAMP_XY, TRANSLATION(Translation_Remap + curbasepal, palette), -1); int h = (int)texture->GetDisplayHeight(); From 35221188dbba00dc1bd7717ba707c2ee4a6daa13 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 10 Apr 2021 10:56:11 +0200 Subject: [PATCH 66/70] - inlined Clipper::PointToAngle --- source/core/rendering/scene/hw_clipper.cpp | 23 --------------------- source/core/rendering/scene/hw_clipper.h | 24 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/source/core/rendering/scene/hw_clipper.cpp b/source/core/rendering/scene/hw_clipper.cpp index 81b3c08da..124bea91c 100644 --- a/source/core/rendering/scene/hw_clipper.cpp +++ b/source/core/rendering/scene/hw_clipper.cpp @@ -358,29 +358,6 @@ void Clipper::DoRemoveClipRange(angle_t start, angle_t end) // //----------------------------------------------------------------------------- -binangle Clipper::PointToAngle(const vec2_t& pos) -{ - vec2_t vec = pos - viewpoint; -#if 0 - - if (vec.x == 0 && vec.y == 0) - { - return 0; - } - else - { - double result = vec.y / double(abs(vec.x) + fabs(vec.y)); - if (vec.x < 0) - { - result = 2. - result; - } - return bamang(xs_Fix<30>::ToFix(result)); - } -#else - return bvectangbam(vec.x, vec.y); -#endif -} - void Clipper::DumpClipper() { for (auto node = cliphead; node; node = node->next) diff --git a/source/core/rendering/scene/hw_clipper.h b/source/core/rendering/scene/hw_clipper.h index e19a01136..5c1280d5b 100644 --- a/source/core/rendering/scene/hw_clipper.h +++ b/source/core/rendering/scene/hw_clipper.h @@ -144,7 +144,29 @@ public: void DumpClipper(); - binangle PointToAngle(const vec2_t& point); + binangle PointToAngle(const vec2_t& pos) + { + vec2_t vec = pos - viewpoint; +#if 0 + + if (vec.x == 0 && vec.y == 0) + { + return bamang(0); + } + else + { + double result = vec.y / double(abs(vec.x) + fabs(vec.y)); + if (vec.x < 0) + { + result = 2. - result; + } + return bamang(xs_Fix<30>::ToFix(result)); + } +#else + return bvectangbam(vec.x, vec.y); +#endif + } + }; From b4d89cbac391080c12455d6e8793b8217ab62d3a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 10 Apr 2021 12:10:28 +0200 Subject: [PATCH 67/70] - got rid of the remaining occurences of gethiq16angle and all related tables. --- source/build/include/build.h | 1 - source/build/src/engine.cpp | 26 -------------------------- source/build/src/polymost.cpp | 2 +- source/games/sw/src/draw.cpp | 4 ++-- source/games/sw/src/player.cpp | 2 +- 5 files changed, 4 insertions(+), 31 deletions(-) diff --git a/source/build/include/build.h b/source/build/include/build.h index e523bde57..92da9f8c4 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -436,7 +436,6 @@ inline int32_t ksqrt(uint32_t num) } int32_t getangle(int32_t xvect, int32_t yvect); -fixed_t gethiq16angle(int32_t xvect, int32_t yvect); inline constexpr uint32_t uhypsq(int32_t const dx, int32_t const dy) { diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index a74aa8737..bbbfa8948 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -62,7 +62,6 @@ static int8_t tempbuf[MAXWALLS]; static int32_t no_radarang2 = 0; static int16_t radarang[1280]; -static int32_t qradarang[10240]; const char *engineerrstr = "No error"; @@ -215,11 +214,6 @@ static int32_t engineLoadTables(void) for (i=0; i<640; i++) radarang[1279-i] = -radarang[i]; - for (i=0; i<5120; i++) - qradarang[i] = FloatToFixed(atan((5119.5 - i) / 1280.) * (-64. / BAngRadian)); - for (i=0; i<5120; i++) - qradarang[10239-i] = -qradarang[i]; - tablesloaded = 1; } @@ -873,26 +867,6 @@ int32_t getangle(int32_t xvect, int32_t yvect) return rv; } -fixed_t gethiq16angle(int32_t xvect, int32_t yvect) -{ - fixed_t rv; - - if ((xvect | yvect) == 0) - rv = 0; - else if (xvect == 0) - rv = IntToFixed(512 + ((yvect < 0) << 10)); - else if (yvect == 0) - rv = IntToFixed(((xvect < 0) << 10)); - else if (xvect == yvect) - rv = IntToFixed(256 + ((xvect < 0) << 10)); - else if (xvect == -yvect) - rv = IntToFixed(768 + ((xvect > 0) << 10)); - else if (abs(xvect) > abs(yvect)) - rv = ((qradarang[5120 + Scale(1280, yvect, xvect)] >> 6) + IntToFixed(((xvect < 0) << 10))) & 0x7FFFFFF; - else rv = ((qradarang[5120 - Scale(1280, xvect, yvect)] >> 6) + IntToFixed(512 + ((yvect < 0) << 10))) & 0x7FFFFFF; - - return rv; -} // Gets the BUILD unit height and z offset of a sprite. // Returns the z offset, 'height' may be NULL. diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index 44423429a..307111c3c 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -3315,7 +3315,7 @@ void renderPrepareMirror(int32_t dax, int32_t day, int32_t daz, fixed_t daang, f *tposx = (x << 1) + Scale(dx, i, j) - dax; *tposy = (y << 1) + Scale(dy, i, j) - day; - *tang = ((gethiq16angle(dx, dy) << 1) - daang) & 0x7FFFFFF; + *tang = ((bvectangq16(dx, dy) << 1) - daang) & 0x7FFFFFF; inpreparemirror = 1; diff --git a/source/games/sw/src/draw.cpp b/source/games/sw/src/draw.cpp index e100ee4a5..1b8e8b2e0 100644 --- a/source/games/sw/src/draw.cpp +++ b/source/games/sw/src/draw.cpp @@ -1123,7 +1123,7 @@ void CameraView(PLAYERp pp, int *tx, int *ty, int *tz, short *tsectnum, binangle { sp = &sprite[i]; - ang = q16ang(gethiq16angle(*tx - sp->x, *ty - sp->y)); + ang = bvectangbam(*tx - sp->x, *ty - sp->y); ang_test = getincangle(ang.asbuild(), sp->ang) < sp->lotag; FAFcansee_test = @@ -1568,7 +1568,7 @@ drawscreen(PLAYERp pp, double smoothratio) if (TEST_BOOL1(pp->remote_sprite)) tang = buildang(pp->remote_sprite->ang); else - tang = q16ang(gethiq16angle(pp->sop_remote->xmid - tx, pp->sop_remote->ymid - ty)); + tang = bvectangbam(pp->sop_remote->xmid - tx, pp->sop_remote->ymid - ty); } if (TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE)) diff --git a/source/games/sw/src/player.cpp b/source/games/sw/src/player.cpp index 351df2422..766b511f0 100644 --- a/source/games/sw/src/player.cpp +++ b/source/games/sw/src/player.cpp @@ -5471,7 +5471,7 @@ DoPlayerStopOperate(PLAYERp pp) if (TEST_BOOL1(pp->remote_sprite)) pp->angle.ang = pp->angle.oang = buildang(pp->remote_sprite->ang); else - pp->angle.ang = pp->angle.oang = q16ang(gethiq16angle(pp->sop_remote->xmid - pp->posx, pp->sop_remote->ymid - pp->posy)); + pp->angle.ang = pp->angle.oang = bvectangbam(pp->sop_remote->xmid - pp->posx, pp->sop_remote->ymid - pp->posy); } if (pp->sop_control) From 057b8a73546446a30fd7948a771f48d35ec2eda0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 10 Apr 2021 12:54:29 +0200 Subject: [PATCH 68/70] - cleanup of bvectan family of functions. This can be greatly simplified to a single bvectangbam function using atan2 directly. --- source/build/src/polymost.cpp | 2 +- source/core/binaryangle.h | 47 +---------------------- source/core/rendering/scene/hw_portal.cpp | 5 ++- source/games/sw/src/player.cpp | 4 +- 4 files changed, 10 insertions(+), 48 deletions(-) diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index 307111c3c..118212656 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -3315,7 +3315,7 @@ void renderPrepareMirror(int32_t dax, int32_t day, int32_t daz, fixed_t daang, f *tposx = (x << 1) + Scale(dx, i, j) - dax; *tposy = (y << 1) + Scale(dy, i, j) - day; - *tang = ((bvectangq16(dx, dy) << 1) - daang) & 0x7FFFFFF; + *tang = ((bvectangbam(dx, dy).asq16() << 1) - daang) & 0x7FFFFFF; inpreparemirror = 1; diff --git a/source/core/binaryangle.h b/source/core/binaryangle.h index e4d86116a..a0690d734 100644 --- a/source/core/binaryangle.h +++ b/source/core/binaryangle.h @@ -502,54 +502,11 @@ inline FSerializer &Serialize(FSerializer &arc, const char *key, fixedhoriz &obj //--------------------------------------------------------------------------- // -// Double-precision implementation of `getangle()` with associated wrappers and helper functions. +// High precision vector angle function, mainly for the renderer. // //--------------------------------------------------------------------------- -inline double bradarangf(double vect) -{ - return atan(vect) * BRadAngScale; -} -inline double bvectangf(int32_t x, int32_t y) -{ - if ((x | y) == 0) - { - return 0; - } - else if (x == 0) - { - return 512 + ((y < 0) << 10); - } - else if (y == 0) - { - return ((x < 0) << 10); - } - else if (x == y) - { - return 256 + ((x < 0) << 10); - } - else if (x == -y) - { - return 768 + ((x > 0) << 10); - } - else if (abs(x) > abs(y)) - { - return fmod(bradarangf(double(y) / x) + ((x < 0) << 10), 2048.); - } - else - { - return fmod(bradarangf(double(x) / -y) + 512 + ((y < 0) << 10), 2048.); - } -} -inline int32_t bvectang(int32_t x, int32_t y) -{ - return xs_CRoundToInt(bvectangf(x, y)); -} -inline fixed_t bvectangq16(int32_t x, int32_t y) -{ - return FloatToFixed(bvectangf(x, y)); -} inline binangle bvectangbam(int32_t x, int32_t y) { - return bamang(xs_CRoundToUInt(bvectangf(x, y) * BAMUNIT)); + return radang(atan2(y, x)); } diff --git a/source/core/rendering/scene/hw_portal.cpp b/source/core/rendering/scene/hw_portal.cpp index db37b870f..cf35cc320 100644 --- a/source/core/rendering/scene/hw_portal.cpp +++ b/source/core/rendering/scene/hw_portal.cpp @@ -574,7 +574,10 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe int newx = int((x << 1) + Scale(dx, i, j) - view.x); int newy = int((y << 1) + Scale(dy, i, j) - view.y); - auto newan = bamang(int64_t((bvectangf(dx, dy) * (BAMUNIT << 1)) - vp.RotAngle) & 0xFFFFFFFF); + + auto myan = bvectangbam(dx, dy); + auto newan = myan + myan - bamang(vp.RotAngle); + vp.RotAngle = newan.asbam(); vp.SectNums = nullptr; vp.SectCount = line->sector; diff --git a/source/games/sw/src/player.cpp b/source/games/sw/src/player.cpp index 766b511f0..a8ab12403 100644 --- a/source/games/sw/src/player.cpp +++ b/source/games/sw/src/player.cpp @@ -7148,7 +7148,9 @@ domovethings(void) // auto tracking mode for single player multi-game if (numplayers <= 1 && PlayerTrackingMode && pnum == screenpeek && screenpeek != myconnectindex) { - Player[screenpeek].angle.settarget(bvectangf(Player[myconnectindex].posx - Player[screenpeek].posx, Player[myconnectindex].posy - Player[screenpeek].posy)); + int deltax = Player[myconnectindex].posx - Player[screenpeek].posx; + int deltay = Player[myconnectindex].posy - Player[screenpeek].posy; + Player[screenpeek].angle.settarget(bvectangbam(deltax, deltay)); } if (!TEST(pp->Flags, PF_DEAD)) From 6b684e74bae233dccd977362591a4466142597f0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 10 Apr 2021 14:09:08 +0200 Subject: [PATCH 69/70] - migrated 'texture' .def command. --- source/build/src/defs.cpp | 185 +--------------------------------- source/common/engine/sc_man.h | 9 ++ source/core/parsefuncs.h | 156 ++++++++++++++++++++++++---- 3 files changed, 150 insertions(+), 200 deletions(-) diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 8cbb7844a..be38f8bdd 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -1638,189 +1638,8 @@ static int32_t defsparser(scriptfile *script) } break; case T_TEXTURE: - { - FScanner::SavedPos textureend; - int32_t tile=-1, token; - - static const tokenlist texturetokens[] = - { - { "pal", T_PAL }, - { "detail", T_DETAIL }, - { "glow", T_GLOW }, - { "specular",T_SPECULAR }, - { "normal", T_NORMAL }, - }; - - if (scriptfile_getsymbol(script,&tile)) break; - if (scriptfile_getbraces(script,&textureend)) break; - while (!scriptfile_endofblock(script, textureend)) - { - token = getatoken(script,texturetokens,countof(texturetokens)); - switch (token) - { - case T_PAL: - { - auto palpos = scriptfile_getposition(script); - FScanner::SavedPos palend; - int32_t pal=-1, xsiz = 0, ysiz = 0; - FString fn; - double alphacut = -1.0, xscale = 1.0, yscale = 1.0, specpower = 1.0, specfactor = 1.0; - - static const tokenlist texturetokens_pal[] = - { - { "file", T_FILE },{ "name", T_FILE }, - { "alphacut", T_ALPHACUT }, - { "detailscale", T_XSCALE }, { "scale", T_XSCALE }, { "xscale", T_XSCALE }, { "intensity", T_XSCALE }, - { "yscale", T_YSCALE }, - { "specpower", T_SPECPOWER }, { "specularpower", T_SPECPOWER }, { "parallaxscale", T_SPECPOWER }, - { "specfactor", T_SPECFACTOR }, { "specularfactor", T_SPECFACTOR }, { "parallaxbias", T_SPECFACTOR }, - { "nocompress", T_NOCOMPRESS }, - { "nodownsize", T_NODOWNSIZE }, - { "forcefilter", T_FORCEFILTER }, - { "artquality", T_ARTQUALITY }, - { "orig_sizex", T_ORIGSIZEX }, { "orig_sizey", T_ORIGSIZEY } - }; - - if (scriptfile_getsymbol(script,&pal)) break; - if (scriptfile_getbraces(script,&palend)) break; - while (!scriptfile_endofblock(script, palend)) - { - switch (getatoken(script,texturetokens_pal,countof(texturetokens_pal))) - { - case T_FILE: - scriptfile_getstring(script,&fn); break; - case T_ALPHACUT: - scriptfile_getdouble(script,&alphacut); break; - case T_XSCALE: - scriptfile_getdouble(script,&xscale); break; - case T_YSCALE: - scriptfile_getdouble(script,&yscale); break; - case T_SPECPOWER: - scriptfile_getdouble(script,&specpower); break; - case T_SPECFACTOR: - scriptfile_getdouble(script,&specfactor); break; - case T_ORIGSIZEX: - scriptfile_getnumber(script, &xsiz); - break; - case T_ORIGSIZEY: - scriptfile_getnumber(script, &ysiz); - break; - default: - break; - } - } - - if ((unsigned)tile >= MAXUSERTILES) break; // message is printed later - if ((unsigned)pal >= MAXPALOOKUPS - RESERVEDPALS) - { - palpos.Message(MSG_ERROR, "missing or invalid 'palette number' for texture definition"); - break; - } - if (fn.IsEmpty()) - { - palpos.Message(MSG_ERROR, "missing 'file name' for texture definition"); - break; - } - - if (!fileSystem.FileExists(fn)) - { - palpos.Message(MSG_ERROR, "%s not found in replacement for tile %d", fn.GetChars(), tile); - break; - } - - if (xsiz > 0 && ysiz > 0) - { - tileSetDummy(tile, xsiz, ysiz); - } - xscale = 1.0f / xscale; - yscale = 1.0f / yscale; - - tileSetHightileReplacement(tile,pal,fn,alphacut,xscale,yscale, specpower, specfactor); - } - break; - case T_DETAIL: case T_GLOW: case T_SPECULAR: case T_NORMAL: - { - auto detailpos = scriptfile_getposition(script); - FScanner::SavedPos detailend; - int32_t pal = 0; - FString fn; - double xscale = 1.0, yscale = 1.0, specpower = 1.0, specfactor = 1.0; - - static const tokenlist texturetokens_pal[] = - { - { "file", T_FILE },{ "name", T_FILE }, - { "alphacut", T_ALPHACUT }, - { "detailscale", T_XSCALE }, { "scale", T_XSCALE }, { "xscale", T_XSCALE }, { "intensity", T_XSCALE }, - { "yscale", T_YSCALE }, - { "specpower", T_SPECPOWER }, { "specularpower", T_SPECPOWER }, { "parallaxscale", T_SPECPOWER }, - { "specfactor", T_SPECFACTOR }, { "specularfactor", T_SPECFACTOR }, { "parallaxbias", T_SPECFACTOR }, - { "nocompress", T_NOCOMPRESS }, - { "nodownsize", T_NODOWNSIZE }, - { "forcefilter", T_FORCEFILTER }, - { "artquality", T_ARTQUALITY }, - }; - - if (scriptfile_getbraces(script,&detailend)) break; - while (!scriptfile_endofblock(script, detailend)) - { - switch (getatoken(script,texturetokens_pal,countof(texturetokens_pal))) - { - case T_FILE: - scriptfile_getstring(script,&fn); break; - case T_XSCALE: - scriptfile_getdouble(script,&xscale); break; - case T_YSCALE: - scriptfile_getdouble(script,&yscale); break; - case T_SPECPOWER: - scriptfile_getdouble(script,&specpower); break; - case T_SPECFACTOR: - scriptfile_getdouble(script,&specfactor); break; - default: - break; - } - } - - if ((unsigned)tile >= MAXUSERTILES) break; // message is printed later - if (fn.IsEmpty()) - { - detailpos.Message(MSG_ERROR, "missing 'file name' for texture definition"); - break; - } - - if (!fileSystem.FileExists(fn)) - break; - - switch (token) - { - case T_DETAIL: - pal = DETAILPAL; - xscale = 1.0f / xscale; - yscale = 1.0f / yscale; - break; - case T_GLOW: - pal = GLOWPAL; - break; - case T_SPECULAR: - pal = SPECULARPAL; - break; - case T_NORMAL: - pal = NORMALPAL; - break; - } - tileSetHightileReplacement(tile,pal,fn,-1.0f,xscale,yscale, specpower, specfactor); - } - break; - default: - break; - } - } - if ((unsigned)tile >= MAXUSERTILES) - { - pos.Message(MSG_ERROR, "missing or invalid 'tile number' for texture definition"); - break; - } - } - break; + parseTexture(*script, pos); + break; case T_UNDEFMODEL: case T_UNDEFMODELRANGE: diff --git a/source/common/engine/sc_man.h b/source/common/engine/sc_man.h index 6874eb186..64690d24b 100644 --- a/source/common/engine/sc_man.h +++ b/source/common/engine/sc_man.h @@ -130,6 +130,15 @@ public: } bool GetFloat(bool evaluate = false); + + bool GetFloat(double& var, bool evaluate = false) + { + if (!GetFloat(evaluate)) return false; + var = Float; + return true; + } + + void MustGetFloat(bool evaluate = false); bool CheckFloat(bool evaluate = false); diff --git a/source/core/parsefuncs.h b/source/core/parsefuncs.h index 5f2d18026..f36893671 100644 --- a/source/core/parsefuncs.h +++ b/source/core/parsefuncs.h @@ -86,6 +86,128 @@ void parseDefineTexture(FScanner& sc, FScriptPosition& pos) // //=========================================================================== +static void parseTexturePaletteBlock(FScanner& sc, FScriptPosition& pos, int tile) +{ + FScanner::SavedPos blockend; + + int pal = -1, xsiz = 0, ysiz = 0; + FString fn; + double alphacut = -1.0, xscale = 1.0, yscale = 1.0, specpower = 1.0, specfactor = 1.0; + + if (!sc.GetNumber(pal, true)) return; + + if (sc.StartBraces(&blockend)) return; + while (!sc.FoundEndBrace(blockend)) + { + sc.GetString(); + if (sc.Compare("file")) sc.GetString(fn); + else if (sc.Compare("alphacut")) sc.GetFloat(alphacut, true); + else if (sc.Compare({ "xscale", "scale", "intensity", "detailscale" })) sc.GetFloat(xscale, true); // what's the point of all of these names? + else if (sc.Compare("yscale")) sc.GetFloat(yscale, true); + else if (sc.Compare({ "specpower", "specularpower", "parallaxscale" })) sc.GetFloat(specpower, true); + else if (sc.Compare({ "specfactor", "specularfactor", "parallaxbias" })) sc.GetFloat(specfactor, true); + else if (sc.Compare("orig_sizex")) sc.GetNumber(xsiz, true); + else if (sc.Compare("orig_sizey")) sc.GetNumber(ysiz, true); + }; + + if ((unsigned)tile < MAXUSERTILES) + { + if ((unsigned)pal >= MAXPALOOKUPS - RESERVEDPALS) + { + pos.Message(MSG_ERROR, "missing or invalid 'palette number' for texture definition"); + } + else if (fn.IsEmpty()) + { + pos.Message(MSG_ERROR, "missing 'file name' for texture definition"); + } + else if (!fileSystem.FileExists(fn)) + { + pos.Message(MSG_ERROR, "%s not found in replacement for tile %d", fn.GetChars(), tile); + } + else + { + if (xsiz > 0 && ysiz > 0) + { + tileSetDummy(tile, xsiz, ysiz); + } + xscale = 1.0f / xscale; + yscale = 1.0f / yscale; + + tileSetHightileReplacement(tile, pal, fn, alphacut, xscale, yscale, specpower, specfactor); + } + } +} + +static void parseTextureSpecialBlock(FScanner& sc, FScriptPosition& pos, int tile, int specialpal) +{ + FScanner::SavedPos blockend; + + int pal = -1; + FString fn; + double xscale = 1.0, yscale = 1.0, specpower = 1.0, specfactor = 1.0; + + if (!sc.GetNumber(pal, true)) return; + + if (sc.StartBraces(&blockend)) return; + while (!sc.FoundEndBrace(blockend)) + { + sc.GetString(); + if (sc.Compare("file")) sc.GetString(fn); + else if (sc.Compare({ "xscale", "scale", "intensity", "detailscale" })) sc.GetFloat(xscale, true); // what's the point of all of these names? + else if (sc.Compare("yscale")) sc.GetFloat(yscale, true); + else if (sc.Compare({ "specpower", "specularpower", "parallaxscale" })) sc.GetFloat(specpower, true); + else if (sc.Compare({ "specfactor", "specularfactor", "parallaxbias" })) sc.GetFloat(specfactor, true); + }; + + if ((unsigned)tile < MAXUSERTILES) + { + if (fn.IsEmpty()) + { + pos.Message(MSG_ERROR, "missing 'file name' for texture definition"); + } + else if (!fileSystem.FileExists(fn)) + { + pos.Message(MSG_ERROR, "%s not found in replacement for tile %d", fn.GetChars(), tile); + } + else + { + if (pal == DETAILPAL) + { + xscale = 1.0f / xscale; + yscale = 1.0f / yscale; + } + + tileSetHightileReplacement(tile, pal, fn, -1.f, xscale, yscale, specpower, specfactor); + } + } +} + +void parseTexture(FScanner& sc, FScriptPosition& pos) +{ + FScanner::SavedPos blockend; + int tile = -1; + + if (!sc.GetNumber(tile, true)) return; + ValidateTilenum("texture", tile, pos); // do not abort, we still need to parse over the data. + + if (sc.StartBraces(&blockend)) return; + while (!sc.FoundEndBrace(blockend)) + { + sc.MustGetString(); + if (sc.Compare("pal")) parseTexturePaletteBlock(sc, pos, tile); + else if (sc.Compare("detail")) parseTextureSpecialBlock(sc, pos, tile, DETAILPAL); + else if (sc.Compare("glow")) parseTextureSpecialBlock(sc, pos, tile, GLOWPAL); + else if (sc.Compare("specular")) parseTextureSpecialBlock(sc, pos, tile, SPECULARPAL); + else if (sc.Compare("normal")) parseTextureSpecialBlock(sc, pos, tile, NORMALPAL); + } +} + +//=========================================================================== +// +// +// +//=========================================================================== + void parseDefineSkybox(FScanner& sc, FScriptPosition& pos) { int tile, palette; @@ -110,30 +232,30 @@ void parseDefineSkybox(FScanner& sc, FScriptPosition& pos) void parseSkybox(FScanner& sc, FScriptPosition& pos) { - FString faces[6]; - FScanner::SavedPos blockend; - int32_t tile = -1, pal = 0; + FString faces[6]; + FScanner::SavedPos blockend; + int tile = -1, pal = 0; - if (sc.StartBraces(&blockend)) return; - while (!sc.FoundEndBrace(blockend)) - { - sc.GetString(); - if (sc.Compare("tile")) sc.GetNumber(tile, true); - else if (sc.Compare("pal")) sc.GetNumber(pal, true); - else if (sc.Compare({ "ft", "front", "forward" })) sc.GetString(faces[0]); - else if (sc.Compare({ "rt", "right" })) sc.GetString(faces[1]); - else if (sc.Compare({ "bk", "back" })) sc.GetString(faces[2]); - else if (sc.Compare({ "lt", "lf", "left" })) sc.GetString(faces[3]); - else if (sc.Compare({ "up", "ceiling", "top", "ceil" })) sc.GetString(faces[4]); - else if (sc.Compare({ "dn", "floor", "bottom", "down" })) sc.GetString(faces[5]); + if (sc.StartBraces(&blockend)) return; + while (!sc.FoundEndBrace(blockend)) + { + sc.MustGetString(); + if (sc.Compare("tile")) sc.GetNumber(tile, true); + else if (sc.Compare("pal")) sc.GetNumber(pal, true); + else if (sc.Compare({ "ft", "front", "forward" })) sc.GetString(faces[0]); + else if (sc.Compare({ "rt", "right" })) sc.GetString(faces[1]); + else if (sc.Compare({ "bk", "back" })) sc.GetString(faces[2]); + else if (sc.Compare({ "lt", "lf", "left" })) sc.GetString(faces[3]); + else if (sc.Compare({ "up", "ceiling", "top", "ceil" })) sc.GetString(faces[4]); + else if (sc.Compare({ "dn", "floor", "bottom", "down" })) sc.GetString(faces[5]); // skip over everything else. - } + } if (tile < 0) { pos.Message(MSG_ERROR, "skybox: missing tile number"); return; } - tileSetSkybox(tile, pal, faces); + tileSetSkybox(tile, pal, faces); } //=========================================================================== From a5ed7ba8a3eb26d3e3aa46bc87044608eacba57f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 10 Apr 2021 16:35:29 +0200 Subject: [PATCH 70/70] - two more simple .def commands. --- source/build/src/defs.cpp | 66 ++++++++++----------------------------- source/core/parsefuncs.h | 42 +++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 52 deletions(-) diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index be38f8bdd..dc8300d2e 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -325,6 +325,19 @@ static int32_t defsparser(scriptfile *script) case T_INCLUDEDEFAULT: defsparser_include(G_DefaultDefFile(), script, &pos); break; + case T_LOADGRP: + case T_CACHESIZE: + case T_SHADEFACTOR: + case T_GLOBALGAMEFLAGS: + parseSkip<1>(*script, pos); + break; + case T_SPRITECOL: + case T_2DCOLIDXRANGE: // NOTE: takes precedence over 2dcol, see InitCustomColors() + parseSkip<3>(*script, pos); + break; + case T_2DCOL: + parseSkip<4>(*script, pos); + break; case T_DEFINE: parseDefine(*script, pos); break; @@ -343,58 +356,11 @@ static int32_t defsparser(scriptfile *script) case T_ALPHAHACKRANGE: parseAlphahackRange(*script, pos); break; - case T_SPRITECOL: - case T_2DCOLIDXRANGE: // NOTE: takes precedence over 2dcol, see InitCustomColors() - parseSkip<3>(*script, pos); - break; - case T_2DCOL: - parseSkip<4>(*script, pos); - break; case T_FOGPAL: - { - int32_t p,r,g,b; - - if (scriptfile_getsymbol(script,&p)) break; - if (scriptfile_getnumber(script,&r)) break; - if (scriptfile_getnumber(script,&g)) break; - if (scriptfile_getnumber(script,&b)) break; - - r = clamp(r, 0, 63); - g = clamp(g, 0, 63); - b = clamp(b, 0, 63); - - lookups.makeTable(p, NULL, r<<2, g<<2, b<<2, 1); - } - break; + parseFogpal(*script, pos); + break; case T_NOFLOORPALRANGE: - { - int32_t b,e,i; - - if (scriptfile_getsymbol(script,&b)) break; - if (scriptfile_getsymbol(script,&e)) break; - - b = max(b, 1); - e = min(e, MAXPALOOKUPS-1); - - for (i = b; i <= e; i++) - lookups.tables[i].noFloorPal = true; - } - break; - case T_LOADGRP: - { - scriptfile_getstring(script,nullptr); -#if 0 - if (!scriptfile_getstring(pScript, &fileName) && firstPass) - { - fileSystem.AddAdditionalFile(fileName); - } -#endif - } - break; - case T_CACHESIZE: - case T_SHADEFACTOR: - case T_GLOBALGAMEFLAGS: - parseSkip<1>(*script, pos); + parseNoFloorpalRange(*script, pos); break; case T_ARTFILE: { diff --git a/source/core/parsefuncs.h b/source/core/parsefuncs.h index f36893671..4704988e8 100644 --- a/source/core/parsefuncs.h +++ b/source/core/parsefuncs.h @@ -48,7 +48,7 @@ void tileRemoveReplacement(int num); template void parseSkip(FScanner& sc, FScriptPosition& pos) { - for (int i = 0; i < cnt; i++) if (!sc.GetNumber(true)) return; + for (int i = 0; i < cnt; i++) if (!sc.GetString()) return; } void parseDefine(FScanner& sc, FScriptPosition& pos) @@ -365,4 +365,42 @@ void parseDefineTint(FScanner& sc, FScriptPosition& pos) if (!sc.GetNumber(f)) return; lookups.setPaletteTint(pal, r, g, b, 0, 0, 0, f); } - \ No newline at end of file + +//=========================================================================== +// +// +// +//=========================================================================== + +void parseFogpal(FScanner& sc, FScriptPosition& pos) +{ + int pal, r, g, b; + + if (!sc.GetNumber(pal, true)) return; + if (!sc.GetNumber(r)) return; + if (!sc.GetNumber(g)) return; + if (!sc.GetNumber(b)) return; + + r = clamp(r, 0, 63); + g = clamp(g, 0, 63); + b = clamp(b, 0, 63); + + lookups.makeTable(pal, nullptr, r << 2, g << 2, b << 2, 1); +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void parseNoFloorpalRange(FScanner& sc, FScriptPosition& pos) +{ + int start, end; + if (!sc.GetNumber(start, true)) return; + if (!sc.GetNumber(end, true)) return; + if (start > 1) start = 1; + if (end > MAXPALOOKUPS - 1) end = MAXPALOOKUPS - 1; + for (int i = start; i <= end; i++) + lookups.tables[i].noFloorPal = true; +}