diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp index 008eca503..727c693de 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp @@ -574,10 +574,10 @@ void PPColormap::Render(PPRenderState *renderstate, int fixedcm, float flash) ///////////////////////////////////////////////////////////////////////////// -void PPTonemap::UpdateTextures() +void PPTonemap::UpdateTextures(bool palettePostprocess) { // level.info->tonemap cannot be ETonemapMode::Palette, so it's fine to only check gl_tonemap here - if (ETonemapMode((int)gl_tonemap) == ETonemapMode::Palette && !PaletteTexture.Data) + if ((palettePostprocess || ETonemapMode((int)gl_tonemap) == ETonemapMode::Palette) && !PaletteTexture.Data) { std::shared_ptr data(new uint32_t[512 * 512], [](void *p) { delete[](uint32_t*)p; }); @@ -588,8 +588,13 @@ void PPTonemap::UpdateTextures() { for (int b = 0; b < 64; b++) { + // Use the exact math from the software renderer. + // Hardware renderer palette emulation needs a post process pass to fix up translucent stuff. + PalEntry color = GPalette.BaseColors[ColorMatcher.Pick((r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4))]; +/* PalEntry color = GPalette.BaseColors[(uint8_t)PTM_BestColor((uint32_t *)GPalette.BaseColors, (r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4), gl_paltonemap_reverselookup, gl_paltonemap_powtable, 0, 256)]; +*/ int index = ((r * 64 + g) * 64 + b) * 4; lut[index] = color.r; lut[index + 1] = color.g; @@ -603,16 +608,19 @@ void PPTonemap::UpdateTextures() } } -void PPTonemap::Render(PPRenderState *renderstate) +void PPTonemap::Render(PPRenderState *renderstate, bool palettePostprocess) { ETonemapMode current_tonemap = (level_tonemap != ETonemapMode::None) ? level_tonemap : ETonemapMode((int)gl_tonemap); + if (palettePostprocess) + current_tonemap = ETonemapMode::Palette; + if (current_tonemap == ETonemapMode::None) { return; } - UpdateTextures(); + UpdateTextures(palettePostprocess); PPShader *shader = nullptr; switch (current_tonemap) @@ -1167,9 +1175,9 @@ void Postprocess::Pass1(PPRenderState* state, int fixedcm, int sceneWidth, int s bloom.RenderBloom(state, sceneWidth, sceneHeight, fixedcm); } -void Postprocess::Pass2(PPRenderState* state, int fixedcm, float flash, int sceneWidth, int sceneHeight) +void Postprocess::Pass2(PPRenderState* state, int fixedcm, float flash, bool palettePostprocess, int sceneWidth, int sceneHeight) { - tonemap.Render(state); + tonemap.Render(state, palettePostprocess); colormap.Render(state, fixedcm, flash); lens.Render(state); fxaa.Render(state); diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.h b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.h index 191bdc7be..05b4ec1d0 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.h +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.h @@ -531,11 +531,11 @@ class PPTonemap { public: void SetTonemapMode(ETonemapMode tm) { level_tonemap = tm; } - void Render(PPRenderState *renderstate); + void Render(PPRenderState *renderstate, bool palettePostprocess); void ClearTonemapPalette() { PaletteTexture = {}; } private: - void UpdateTextures(); + void UpdateTextures(bool palettePostprocess); PPTexture PaletteTexture; @@ -827,7 +827,7 @@ public: void SetTonemapMode(ETonemapMode tm) { tonemap.SetTonemapMode(tm); } void Pass1(PPRenderState *state, int fixedcm, int sceneWidth, int sceneHeight); - void Pass2(PPRenderState* state, int fixedcm, float flash, int sceneWidth, int sceneHeight); + void Pass2(PPRenderState* state, int fixedcm, float flash, bool palettePostprocess, int sceneWidth, int sceneHeight); }; diff --git a/src/common/rendering/v_video.h b/src/common/rendering/v_video.h index c8e55a5ce..68bb8fa35 100644 --- a/src/common/rendering/v_video.h +++ b/src/common/rendering/v_video.h @@ -236,7 +236,7 @@ public: virtual FTexture *WipeStartScreen(); virtual FTexture *WipeEndScreen(); - virtual void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) { if (afterBloomDrawEndScene2D) afterBloomDrawEndScene2D(); } + virtual void PostProcessScene(bool swscene, int fixedcm, float flash, bool palettePostprocess, const std::function &afterBloomDrawEndScene2D) { if (afterBloomDrawEndScene2D) afterBloomDrawEndScene2D(); } virtual int GetLevelMeshPipelineID(const MeshApplyData& applyData, const SurfaceUniforms& surfaceUniforms, const FMaterialState& material) { return 0; } virtual void DownloadLightmap(int arrayIndex, uint16_t* buffer) { } diff --git a/src/common/rendering/vulkan/vk_postprocess.cpp b/src/common/rendering/vulkan/vk_postprocess.cpp index 162a901fa..428113f33 100644 --- a/src/common/rendering/vulkan/vk_postprocess.cpp +++ b/src/common/rendering/vulkan/vk_postprocess.cpp @@ -64,7 +64,7 @@ void VkPostprocess::SetActiveRenderTarget() fb->GetRenderState()->SetRenderTarget(&buffers->PipelineImage[mCurrentPipelineImage], buffers->PipelineDepthStencil.View.get(), buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT); } -void VkPostprocess::PostProcessScene(int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) +void VkPostprocess::PostProcessScene(int fixedcm, float flash, bool palettePostprocess, const std::function &afterBloomDrawEndScene2D) { fb->GetRenderState()->EndRenderPass(); fb->GetCommands()->FlushCommands(false); @@ -77,7 +77,7 @@ void VkPostprocess::PostProcessScene(int fixedcm, float flash, const std::functi hw_postprocess.Pass1(&renderstate, fixedcm, sceneWidth, sceneHeight); SetActiveRenderTarget(); afterBloomDrawEndScene2D(); - hw_postprocess.Pass2(&renderstate, fixedcm, flash, sceneWidth, sceneHeight); + hw_postprocess.Pass2(&renderstate, fixedcm, flash, palettePostprocess, sceneWidth, sceneHeight); } void VkPostprocess::BlitSceneToPostprocess() diff --git a/src/common/rendering/vulkan/vk_postprocess.h b/src/common/rendering/vulkan/vk_postprocess.h index 8eab87c11..ddd9bdf05 100644 --- a/src/common/rendering/vulkan/vk_postprocess.h +++ b/src/common/rendering/vulkan/vk_postprocess.h @@ -24,7 +24,7 @@ public: ~VkPostprocess(); void SetActiveRenderTarget(); - void PostProcessScene(int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D); + void PostProcessScene(int fixedcm, float flash, bool palettePostprocess, const std::function &afterBloomDrawEndScene2D); void UpdateLinearDepthTexture(); void AmbientOccludeScene(float m5); diff --git a/src/common/rendering/vulkan/vk_renderdevice.cpp b/src/common/rendering/vulkan/vk_renderdevice.cpp index cd3fb7167..34e72169a 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.cpp +++ b/src/common/rendering/vulkan/vk_renderdevice.cpp @@ -403,10 +403,10 @@ void VulkanRenderDevice::UploadEnvironmentMaps(int cubemapCount, const TArrayCreatePrefiltermap(128, 6 * cubemapCount, prefilterMaps); } -void VulkanRenderDevice::PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) +void VulkanRenderDevice::PostProcessScene(bool swscene, int fixedcm, float flash, bool palettePostprocess, const std::function &afterBloomDrawEndScene2D) { if (!swscene) mPostprocess->BlitSceneToPostprocess(); // Copy the resulting scene to the current post process texture - mPostprocess->PostProcessScene(fixedcm, flash, afterBloomDrawEndScene2D); + mPostprocess->PostProcessScene(fixedcm, flash, palettePostprocess, afterBloomDrawEndScene2D); } const char* VulkanRenderDevice::DeviceName() const diff --git a/src/common/rendering/vulkan/vk_renderdevice.h b/src/common/rendering/vulkan/vk_renderdevice.h index c56ef5b10..c1b13922b 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.h +++ b/src/common/rendering/vulkan/vk_renderdevice.h @@ -66,7 +66,7 @@ public: void StartPrecaching() override; void BeginFrame() override; void BlurScene(float amount) override; - void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) override; + void PostProcessScene(bool swscene, int fixedcm, float flash, bool palettePostprocess, const std::function &afterBloomDrawEndScene2D) override; void UpdateLinearDepthTexture() override; void AmbientOccludeScene(float m5) override; void SetSceneRenderTarget(bool useSSAO) override; diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index 9bc14771a..130a5b6c1 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -207,7 +207,7 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou RenderState.EnableDrawBuffers(1); } - screen->PostProcessScene(false, cm, flash, [&]() { di->DrawEndScene2D(mainvp.sector, RenderState); }); + screen->PostProcessScene(false, cm, flash, !V_IsTrueColor(), [&]() { di->DrawEndScene2D(mainvp.sector, RenderState); }); PostProcess.Unclock(); } // Reset colormap so 2D drawing isn't affected diff --git a/src/rendering/swrenderer/r_swscene.cpp b/src/rendering/swrenderer/r_swscene.cpp index 2b29d6f70..5ca661720 100644 --- a/src/rendering/swrenderer/r_swscene.cpp +++ b/src/rendering/swrenderer/r_swscene.cpp @@ -118,7 +118,7 @@ sector_t *SWSceneDrawer::RenderView(player_t *player) DrawTexture(twod, fbtex.get(), 0, 0, DTA_SpecialColormap, map, TAG_DONE); screen->Draw2D(); twod->Clear(); - screen->PostProcessScene(true, CM_DEFAULT, 1.f, [&]() { + screen->PostProcessScene(true, CM_DEFAULT, 1.f, false, [&]() { SWRenderer->DrawRemainingPlayerSprites(); screen->Draw2D(); twod->Clear(); @@ -134,7 +134,7 @@ sector_t *SWSceneDrawer::RenderView(player_t *player) int cm = CM_DEFAULT; auto map = swrenderer::CameraLight::Instance()->ShaderColormap(); if (map) cm = (int)(ptrdiff_t)(map - SpecialColormaps.Data()) + CM_FIRSTSPECIALCOLORMAP; - screen->PostProcessScene(true, cm, 1.f, [&]() { }); + screen->PostProcessScene(true, cm, 1.f, false, [&]() { }); SWRenderer->DrawRemainingPlayerSprites(); screen->Draw2D();