Unvanquished 0.56: We deliver

Unvanquished 0.56 is there, 17 months after the last major release (0.55), 6 months after the 0.55.5 release. After 5 point releases, and 2 release candidates. We do deliver!

That’s a big release, with lots of stuff to talk about. Impressive background work has finally been merged and is ready to use. 🚀️

Among all the awesome work that has been contributed by many people who are credited below, it’s important to especially thank Slipher and Illwieckz for the huge amount of work they poured the month preceding that release in reviewing, merging, polishing, testing, debugging, and finally producing the release. That’s commitment, and they made it real.

It’s time to download and play the game! :bsuit:

Linear blend regime

OK, now that is a big topic to start a blog post with… Unvanquished 0.56 makes the official debut of our Linear blend regime.

This is part of a now decades-old effort at improving the lighting and rendering pipeline of the Unvanquished game.. On the Dæmon engine side, the research, and work on designing and plumbing that colorspace-aware pipeline itself started 7 years ago in 2019 on the Dæmon engine side. Xonotic people actually started the work on the Q3map2 map compiler side 15 years ago in 2011. For Unvanquished, this adds up to other efforts we did in the past 10 years (early research being done in 2016), like investigating better build options for better light falloff and bouncing.

So, what’s that linear blend regime about?

Once upon a time, game engines didn’t care about how color and light were blended. They did it the most naive way possible, they didn’t care about your nice textures meticulously crafted in your favorite image editor being stored in a specific colorspace, and the computed light being produced in a specific colorspace, and the final result being presented to the screen in a specific colorspace… and you guessed right, those colorspaces weren’t the same, and computations can only be done in one of those.

Those early engines just took all of this and mixed everything together. The games may have looked fine for unaware players : green, blue and red were still green, blue and red, but their intensities weren’t the right ones, and when blending them together, mistakes were mixed with more mistakes.

Players didn’t know, this was like muddy water for a pond fish, they didn’t know about clear water. Creators struggled with weird results and had to learn esoteric arcane knowledge to deal with them.

You could not expect seeing in game your textures the same way you seen them in editor. They looked similar, not the same. All colors were there, but slightly distorted from what you drawn. Now they will look the same. Also, you could not predict the outcome of a blend operation just based on what your mind expected. Blending 0.5 light  from the [0,1] range would not be perceived as something receiving half the light intensity. All shadows were there, but wrong. Now this is fixed.

We inherited that original sin from our ancestry. Such mistakes were present in many games from the early 2000s like Quake 3, Doom 3 and others… Our Dæmon engine being originally based on Quake 3’s engine (with decades of work above), we inherited from that mitochondrial Eve the genetic disease. That disease was woven not only throughout the whole body, but also throughout every body of the population. Treating this required meticulously unraveling the chromosomes of every individuals one by one, without killing anyone of them.

Our friends from Xonotic already did the job on the map compiler side, Q3map2. We continued the work on the Engine side, Dæmon.

We also did something impressive but time consuming: we actually kept the disease encoded in the genetic code but made it dormant, so it can be activated anytime one of the thousands of accumulated community maps for Unvanquished and Tremulous (or any Quake3 derivative) is played, to keep them rendered as they were before.

Fixing all those mistakes is required for physically based rendering, light computation and texture blending requires it to be correct.

The whole authoring and rendering pipeline is now wired properly to do it right. What’s very interesting is that such physically correct pipeline was perfectly implementable in the early 2000’s, it was just a matter of using proper math equations. If you run the Dæmon engine from today on a compatible devices from that era, that physically correct pipeline will be used and will work. It’s just a matter of math being done properly. Just for fun, the screenshot used as an illustration for this blog post was taken on a Radeon X1950 PRO:

Tyrant in Vega.
Tyrant in Vega (linear pipeline).

That new linear blending regime is only activated by the Dæmon engine when loading maps (game levels) made for it. All previously made maps are rendered the same as before. For building a map for the new  blend regime, the map author has to use explicit map compiler options.  The linear light pipeline spans over the full production pipeline, from mapping, baking, and rendering.

On mapping side, some existing textures meant to be blended may have to be tweaked, since they were likely tested using broken rendering formulæ, and then initially designed to workaround the bugs. We implemented some material keywords to make it easy to port legacy transparent textures by either disabling some color conversion on a per-texture basis, or by making possible to write shader stages targetting specific pipelines.

Us providing this new production and rendering pipeline doesn’t deprecate any of previously released maps, they’re all rendered like before. In fact that new pipeline was already released in the 0.55.5 release, but wasn’t used yet for the simple reason no official map were shipped for it and then no map enabled it.

This 0.56 Unvanquished game release now ships with its official maps ported to the linear blend regime. We focused on fixing the most obvious regressions, but more polishing may come.

Since maps made for the linear blend regime requires to be baked the linear way, a new NetRadiant release will hopefully come soon. The updated build menu will provide entries for building maps for the new linear pipeline, as well as entries for building maps the old way. The linear build option will be usable for anyone wanting to port a map to the new pipeline, while the other compatibility build options will be there for those needing it, for example to quickly fix something in an existing map while postponing the port.

Map ports are usually straightforward, all map sources can be rebuilt the new way without any change, but people may want to tweak some transparent textures or some backlights for better results.

Related to colorspace, we also implemented a trick we learnt from Xonotic: storing lightmaps in sRGB space. They’re still baked in linear space and blended in linear space, but stored in sRGB space. This trick biases the storage to allocate more precision to the low lights, allowing smooth shadows. The visual quality is somewhat similar to what would produce a 12-bit storage, while storing in any 8-bit image format…

War on jaggies

Spacetracks map antialiasing demonstration: no antialiasing
No antialiasing
Spacetracks map antialiasing demonstration: FXAA
FXAA
Spacetracks map antialiasing demonstration: MSAA
MSAA 4

We implemented not one, but two anti-aliasing systems! First, thanks to Reaper, there’s our flagship MSAA (multisample anti-aliasing). This works by internally rendering at higher resolution at the boundaries between objects. It has a high performance cost, especially for high-resolution displays, so it is enabled only for the “Ultra” graphics preset. Now the Ultra preset can bring your GPU to its knees like it should.

As a resource-efficient alternative, we offer FXAA (“fast approximate anti-aliasing”). This is an edge detector + blur filter option which also takes care of jaggies, at the cost of some false positives.

An “FXAA” option was long present in the menu, but it didn’t do anything useful until now. Illwieckz repaired FXAA by
configuring the correct interpolation mode when reading off the pixels. He also tweaked it a bit it’s configuration to make it look better with our maps (to limit as much as possible the blurring). Illwieckz also modified it to work on luma to be more efficient and also integrated it properly with the linear pipeline.

Sound system

POV: hovering over overmind with jetpack and painsaw
Bzzzzzzzzz. But also, whfffffff

Reaper made some enhancements to the audio system. Most prominently, it is now possible to attach more than one looping sound to an entity. You can finally hear the buzz of your Painsaw and the purr of your jetpack at the same time!

Also, sounds produced by your own player will be prioritized in case there are too many active sounds to play them all.

Emancipated skeletons

Reaper did it again! Yet another impressive rework being landed in the 0.56 release is a feat of the Reaper.

Reaper moved model skeleton building and blending into the engine. What’s the deal with it? Well, you probably already know, and if you don’t know I’ll tell you, our game code is virtualized. The engine runs natively on the hardware and operating system of the player, while the game code itself is run virtualized and sandboxed in a virtual machine (currentl, NaCl). To communicate with the engine, the game code uses an IPC, an inter-processus communication channel. But the IPC is slow, so the more things we untie from that IPC, the more performant is the game!

That rework to optimize IPC communication or avoid IPC communication has already been done on many other things of the engine: like particles. Now it’s the turn of model skeleton building and blending to be unchained from that IPC.

He also implemented an entity cache. Those improvements adds-up because, as you guess, models are usually depicted using models who happen to have skeletons.

In another topic, Reaper also worked on implementing PushBuffers, an mechanism to improve performance by avoiding a bunch of driver calls and such. So this other improved communication isn’t between game and engine, but between engine and driver.

Speeding-up models on low-end and lesser-known GPUs… with OpenMP on CPU

As always we do testing on a wide range of hardware to make the game as accessible as possible.

Illwieckz integrated OpenMP into the Daemon engine and used it to accelerate CPU-based rendering of skeletal models. We have to use CPU-based (instead of GPU-based) on lower-end GPUs or ones with poor driver support. For the curious, you can check the log:
if you see a message like  Missing GPU vertex skinning, models are not hardware-accelerated or
Using GPU vertex skinning with max *N* bones in a single pass, some models may not be hardware accelerated, you may benefit from this innovation.

An example of actual GPUs from the market that benefit from this OpenMP work is the Chinese MTT S80 from Moore Threads. Despite having a raw power comparable to a RX 6700XT in some aspects (so, close to an Xbox Series X or PlayStation 5), and supporting OpenGL 4+, for some reasons it exposes some  “max vertex uniforms” limitations similar to some 2.1 GPUs from the early 2000’s, probably a side-effect of its PowerVR-based architecture which is usually found in mobile devices, not in discrete PCIe cards for gaming PCs. Owners of such devices can use the “Ultra” graphics  preset but are recommended to enable the “Low“ model quality option so the engine dispatches more models to the GPU while the processing of remaining models dispatched on CPU will enlist many threads to speed-up the work thanks to OpenMP.

Illwieckz also did some rewriting of this fallback model CPU code for it using cheapest but faster variants of some computations to speed it a bit more.

OpenMP may be used in the future to speed up more things benefiting more people, be it at loading time (decompressing multiple images at the same time, maybe?) or at render time (particles may benefit from it for example, but would require some deeper rewrite first). OpenMP is now enabled by default in Linux and Windows release builds, starting with Dæmon 0.56. Those who build the engine themselves have to set the USE_OPENMP CMake option to ON.

Fixed light grid code when deluxe mapping is disabled

In the process of rewriting the light grid code for better interpolation, slipher fixed the issue of excessively bright models when deluxe mapping is disabled. Deluxe mapping is disabled when selecting the “Low” or “Lowest” graphics presets. So models are illuminated more in line with the rest of the level when using those presets.

Low and lowest graphics preset are only meant to be used with very low end and slow devices. If your hardware is weak, try the medium preset first, then try the low one if not enough, and only resign to the lowest one as a last resort. The lowest the preset, the uglier it looks.

At least with this fix the low preset looks a bit better.

Not trusting OpenGL drivers when they brag about texture barriers

We have continued to improve the handling of depth buffer sampling, which is used for soft particles, SSAO, and now fog. Various systems have long suffered from issues with soft particle rendering, in the past because we didn’t obey the OpenGL dictates correctly, and more recently because the drivers are wrong.  Some OpenGL drivers shamelessly lie about their degree of support for related functionality, so we have to evaluate GPUs on a case-by-case basis and tweak the behavior to avoid bugs.

The OpenGL hardware and driver detection framework and the workaround management framework, both introduced in recent Dæmon versions, prove themselves very handy in this case.

More and more

The overmind look at a battlesuit in Parpax.
The overmind look at a battlesuit in Parpax.

Afontain adjusted the Overmind’s eye to make it spookier: it will look its human enemies right in the eye.

Reaper extended the client/server network protocol to support very large entity baselines. This allows layouts with 700+ buildables to be loaded without bringing down the server.

More renderer goodness

Slipher did a great job at reworking the fog code. It is not only more efficient, the fog looks better. First, when entering a fog volume, that fog is then rendered like a global fog, with a single draw call. Then, the fogs now have softer edges, making them look much better.

The exposure feature is now usable even when tone mapping is disabled. The exposure should be preferred over the gamma option. The gamma option was yet another thing that was part of the broken pipeline. Don’t use it, it breaks colors as soon as you change the default value. If you need to increase brightness, increases exposure. If you used the gamma option before, you’ll better reset it and use exposure instead. The exposure option works with both the new linear blend regime and the old one, and now works when tone mapping is enabled or disabled. The only reason to not use exposure is if the default brightness is fine for you.

Speaking of tone mapping. This is a great feature implemented by Reaper and already released in previous versions of the engine. Illwieckz made sure it integrated properly with the linear pipeline, and also tweaked its default configuration to make it work better with our very large corpus of maps. The tone mapper is now looking great whatever the map you use, such map using the old pipeline or the new one, or featuring very different lighting atmosphere…

The tone mapper is a required component of the upcoming adaptive lighting feature, so we needed to make sure it fitted all our usages, which is now done.

Slipher worked on enabling realtime light on vertex-lit surfaces. The shader language used for describing materials allows to configure a surface to blend a texture with the vertex color (usually carrying light color), meaning the result is a surface that is actually lit, while skipping the lighting code entirely. Since those surfaces are semantically lit, Slipher made sure those surfaces also receives dynamic lights. He also fixed dynamic lights on moving BSP entities, such as doors, which could appear in the wrong location.

UI enhancements

Reaper added a column displaying the server’s version number into the in-game server list. So when you download Unvanquished 0.56 two minutes after it was released, you can see which servers are ready with the new update.

As is customary for a new major release, Unvanquished 0.56 is incompatible with the 0.55.x series. The game will display a warning if you try to connect to a server which is known to be incompatible
with your version of the game.

Detailed changelog

Unvanquished – 0.56.1 branch

  • Fix the ABI mismatch popup check, Unvanquished 0.56.1 – Illwieckz

Unvanquished – 0.56.0 branch

  • EntityCache: add L2 blocks to find non-full blocks quicker – Reaper
  • CG_PlayerWWSmoothing(): Fix acosf() of a value > 1.0f – Reaper
  • NUKE unused refEntity_t fields, improve packing – Reaper
  • Move skeleton building and blending to engine – Reaper
  • Implement a render entity cache – Reaper
  • Fix human buildable under construction shader – Slipher
  • Enable FXAA with the high graphics preset – Illwieckz
  • Fix version data for server list – Slipher
  • Fix non-2d shader registered before colorspace known warnings – Slipher
  • Fix password protection with local servers – Slipher
  • ClientBotConnect: remove useless stuff – Slipher
  • Better document the localClient field – Slipher
  • better detect hosting client in some cases – Slipher
  • Remove usage of no-op SVF_* flags – Slipher
  • Update cvar name r_toneMappingExposure -> r_exposure – Slipher
  • Remove no-op RF_MINLIGHT flag – Slipher
  • Don’t set refEntity_t’s lightingOrigin – Slipher
  • NUKE non-blob shadow code – Slipher
  • Fix lcannon warning sound – Reaper
  • SP_sfx_speakeri: Use SVF_BROADCAST – Reaper
  • Fix looping sounds – Reaper
  • glconfig → WindowConfig – Reaper
  • Update MAX_PARTICLES – Reaper
  • Fix cg_drawClock not using local time (in NaCl) – Reaper
  • Add a deprecation warning for realLight – Reaper
  • Use RSF_FORCE_LIGHTMAP – Reaper
  • Add dynamicLightIntensityCompensate – Reaper
  • Fix missing and extraneous dynamic light color division – Reaper
  • NUKE trap_R_AddAdditiveLightToScene() – Reaper
  • ABI update: Use trap_GetPings not playerstate ping – Slipher
  • Fix chargebar depth – Reaper
  • Fix changemap command not found – Kai
  • Fix dead/powered down barricade is not predicted – Kai

Unvanquished – master branch since 0.55.5

  • Add MSAA to ultra preset – Slipher
  • NUKE rim lighting option from menu – Slipher
  • Disable r_rimLighting in presets – Slipher
  • Fix keynum_t binds in bind menu – Slipher
  • Pre-build shader variants for spawning buildables – Slipher
  • Fix prediction errors if using cg_sprintToggle – Slipher
  • Enable realtime lighting in medium graphics preset – Slipher
  • Improve positioning of “Beta x.y.z.” label – Slipher
  • RML cleanup: remove <blocklink> tag – Slipher
  • Remove CSS directives not used by any element – Slipher
  • Drop some unused CSS classes in menu_ingame.rml – Slipher
  • Add overmind Y axis eye offset – Afontain
  • Use AngleNormalize180 in CG_Buildable – Afontain
  • Make overmind look directly into the eyes of its targets – Afontain
  • Fix spectator 3rd person view YAW limits – Afontain
  • Remove useless AngleNormalize180 – Afontain
  • Fix effectless AngleNormalize360 – Afontain
  • Use AngleNormalize360 instead of AngleMod – Afontain

Daemon Engine – 0.56.0 branch

  • Disable ARB_texture_barrier on GLSL 1.20 (GL 2.1) devices – Illwieckz
  • Fix fog on GLSL 1.20 – Illwieckz
  • BuildSkeleton(): apply boneMod.translation – Reaper
  • NUKE unused refEntity_t fields, improve packing – Reaper
  • Move skeleton building and blending to engine – Reaper
  • Implement a render entity cache – Reaper
  • Cap ompMaxThreads to 4 in MinGW build – Illwieckz
  • Reduce r_FXAAEdgeThreshold to 0.25 – Illwieckz
  • Make FXAA configurable with cvars – Illwieckz
  • Disable FXAA when MSAA is enabled (prefer MSAA) – Illwieckz
  • Fix FXAA sampling by using GL_LINEAR on currentRender – Illwieckz
  • Add r_showFXAA – Illwieckz
  • Implement luma-based FXAA – Illwieckz
  • Run FXAA after the camera shader (after tone mapping and color conversion) – Illwieckz
  • Also set u_SRGB in lightMapping shader for the material system – Illwieckz
  • Add sgame IPC to sync data to Daemon-vulkan – Reaper
  • Add cgame IPC to sync data to Daemon-vulkan – Reaper
  • Adjust dynamic lights in linear blend regime – Slipher
  • Make possible to never compile a shader, do it for “proxy” – Illwieckz
  • Delete unused GLShaderManager::LinkProgram() – Illwieckz
  • Print shader name in link log in GLShaderManager::BuildShaderProgram() – Illwieckz
  • Never build grid deluxe without grid lighting – Slipher
  • Remove GLShader::MissesRequiredMacros – Slipher
  • Only initialize world shaders AFTER all shader storage has been initialized – Ishq
  • Reorder and comment SVF_* flags – Slipher
  • Remove SVF_* flags that do nothing – Slipher
  • Make models brighter with deluxe mapping off – Slipher
  • Rewrite light grid direction interpolation – Slipher
  • NUKE LightForPoint function and trap call – Slipher
  • Rework the non-delayed texture loading, fix loading legacy diffuse stage – Illwieckz
  • Rename r_toneMappingExposure -> r_exposure – Illwieckz
  • Set r_toneMappingContrast to 1.4 – Illwieckz
  • Do the tone mapping operation before the color conversion – Illwieckz
  • Make SVF_BROADCAST_ONCE have a unique SVF_* value – Reaper
  • Clean up RegisterShaderFlags_t ABI interface – Slipher
  • Remove glDriverType_t enum – Slipher
  • Remove unused RF_MINLIGHT – Slipher
  • Remove unused REF_xxx_DLIGHT flags – Slipher
  • Remove unimplemented refEntity_t::lightingOrigin – Slipher
  • NUKE vertex overbright code for generic shader – Slipher
  • Enable realtime lights for vertex-lit surfaces – Slipher
  • Refactor SetLightDeluxeMode arguments – Slipher
  • Implement some sound priorities – Reaper
  • Allow multiple sounds per entity – Reaper
  • Implement SVF_BROADCAST_ONCE – Reaper
  • Destroy dead sounds – Reaper
  • Fix looping sounds – Reaper
  • Update dummygame for glconfig_t -> WindowConfig – Slipher
  • NUKE glconfig_t, use WindowConfig instead – Reaper
  • NUKE the remnants of R_GetEntityToken() – Reaper
  • NUKE server_t.entityParsePoint – Reaper
  • NUKE trap_GetEntityToken – Reaper
  • Update MAX_REF_ENTITIES – Reaper
  • NUKE unused RSF_LIGHT_ATTENUATION – Reaper
  • NUKE unused RDF_SKYBOXPORTAL – Reaper
  • Fix entity baseline overflow – Reaper
  • Check for stage count with RSF_FORCE_LIGHTMAP – Reaper
  • Add RSF_FORCE_LIGHTMAP – Reaper
  • Add VM syscall for getting local time offset – Slipher
  • Add engine + ABI version to server info response – Slipher
  • Multiply with var_Color in generic shader before the u_AlphaThreshold check – Reaper
  • give all server info to cgame, not just selected fields – Slipher
  • Clean up “nettype” from server info for cgame – Slipher ??-?? Fix bad merge with sv_maxClient – Reaper
  • NUKE light intensity/scale – Reaper
  • Remove unused shader from trap_R_AddLightToScene() – Reaper
  • NUKE trap_R_AddAdditiveLightToScene() – Reaper
  • NUKE RE_AddDynamicLightToSceneQ3A(), rename RE_AddDynamicLightToSceneET() to RE_AddDynamicLightToScene() – Reaper
  • NUKE r_lightScale – Reaper
  • NUKE random dynamic light scaling – Reaper
  • NUKE unused RDF_NOSHADOWSRDF_UNDERWATER, and RDF_DRAWINGSKY – Reaper
  • NUKE unused RF_WRAP_FRAMES and RF_FORCENOLOD – Reaper
  • NUKE unsued MAX_DLIGHTS – Reaper
  • Make shared memory player state pointers const – Slipher
  • Add trap_GetPings, remove ping from playerstate – Slipher

Daemon Engine – master branch since 0.55.5

  • Disable rim lighting (r_rimLighting) by default – Slipher
  • r_showLightGrid: access grid values directly – Slipher
  • r_showLightGrid: fix wrong colors displayed – Slipher
  • Fix wrong default light grid (when BSP lacks one) – Slipher
  • R_LoadLightGrid: simplify code for skipping 0 points – Slipher
  • Don’t create lightGrid2 image when deluxe disabled – Slipher
  • Don’t store alpha channel for lightGrid2 image – Slipher
  • Don’t lose precision while linearizing light grid – Slipher
  • R_LoadLightGrid: comment suspicious-looking things – Slipher
  • Frustum cull fogs – Slipher
  • Cleanup: rename GLSL shader fogGlobal -> fog – Slipher
  • Use new depth-based fog shaders in material system – Slipher
  • Use depth-based fog shader for all fogs – Slipher
  • Draw inside of fog with modified global fog shader – Slipher
  • Fix failing to generate depth shader with long name – Slipher
  • NUKE cvar r_wolfFog – Slipher
  • Fix failing to generate depth shader with long name – Slipher
  • NUKE cvar r_wolfFog – Slipher
  • For fogs use a small gradient by default – Slipher
  • Introduce fogGradient shader keyword – Slipher
  • Refactor: save fogparms only on shader, not in fog_t – Slipher
  • Remove some unused fog-related bits – Slipher
  • Reduce the default bloom strength – Illwieckz
  • Recalibrate the default tone mapper preset – Illwieckz
  • Fix lighting for BSP model entities – Slipher
  • Skip visited check for BSP entity surfaces – Slipher
  • Fix missing u_Exposure when high precision rendering is disabled – Illwieckz
  • Disable ARB_texture_barrier on Moore Threads hardware – Illwieckz
  • Report OpenMP support in /gfxinfo – Illwieckz
  • Parallelize Tess_SurfaceMD5() with OpenMP – Illwieckz
  • Prepare Tess_SurfaceMD5() for parallelism – Illwieckz
  • Parallelize Tess_SurfaceIQM() with OpenMP – Illwieckz
  • Prepare Tess_SurfaceIQM() for parallelism – Illwieckz
  • Add OpenMP support – Illwieckz
  • Rename u_TonemapExposure → u_Exposure – Slipher
  • Apply exposure even when tonemapping is off – Slipher
  • Add ifStatic shader keyword – Slipher
  • Add linearBlending/naiveBlending to expression_t – Slipher
  • Warn when loading non-2D shaders before mapa – Slipher
  • Add the linearColorMaplinearSpecularMap and linearRgbGen keywords and raw variants – Illwieckz
  • Delayed animation texture loading – Illwieckz
  • Delayed stage texture loading – Illwieckz
  • Make cvar defaults match Unvanquished “high” gfx preset – Slipher
  • NUKE unused GLUniformSampler::SetValue() – Slipher
  • GLUniform: add bufferSize – Reaper
  • NUKE unused GLUniform.GetSize() – Reaper
  • Only update PushBuffer if any uniform has actually changed – Reaper
  • Fix MSAA with depth-fade and global fog – Reaper
  • Add a GL version check for MSAA – Reaper
  • Clean-up Render_generic3D() MSAA resolve – Reaper
  • MSAA: clean-up FBO bindings – Reaper
  • Fix fog and transparent surfaces with MSAA – Reaper
  • MSAA clean-up and fixes – Reaper
  • R_UploadImage(): early return for MSAA images – Reaper
  • Implement MSAA – Reaper
  • PushBuffer fixes – Reaper
  • Always enable glConfig.usingReadonlyDepth on AMD + bindless textures – Reaper
  • Implement the rest of PushBuffer – Reaper
  • Add PushBuffer – Reaper
  • Don’t use real uniforms in uniform packing test – Slipher
  • Fix console border drawing with negative con_margin – Slipher
  • Fix a crash when console width is less than 1 char – Slipher
  • Migrate remaining in-game console (con_*) cvars – Slipher
  • Migrate many in-game console (con_*) cvars – Slipher
  • Fix cvar changes sometimes not writing autogen – Slipher
  • Cleanup: InternalSetValue flags argument always 0 – Slipher
  • FileSystem: unify open() wording and deduplicate code – Illwieckz
  • Simplify the Saigo arm optimization disablement fix – Illwieckz
  • Disable PIC with NaCl – Illwieckz
  • VMMain: explicitely include unistd on NaCl to please Saigo – Illwieckz
  • Fix screenshots with read-only depth buffer – Slipher
  • Fix tr.numFBOs counter – Slipher
  • Don’t allow loading console font from pak file – Slipher
  • NUKE legacy console font (‘bigchars’) – Slipher
  • Embed Unifont OTF for the default console font – Slipher
  • Properly detect Linux with glibc to detect what’s not – Illwieckz
  • Also make generated source depend on generators to regenerate the target – Illwieckz
  • Do not copy the embedded files in the map – Illwieckz
  • Make possible to chose between TEXT and BINARY formats when embedding files – Illwieckz
  • Make the embedded file generator reusable – Illwieckz
  • Fix /listMaterialSystemStages variant descriptions – Slipher
  • NUKE alphaAddOne bit in color modulate – Slipher
  • Fix broken shader that prevents game start – Afontain
  • Use WARN_UNUSED_RESULT in q_math.cpp – Afontain
  • Deprecate AngleMod – Afontain
  • r_showVertexColors: don’t black out generic shader – Slipher
  • Allow building NaCl dummy gamelogic – Slipher
  • Migrate mouse acceleration cvars cl_mouseAccel* – Slipher
  • Fix mouse accel bug: sensitivity applied twice – Slipher
  • Implement the builtin sound/null.wav file – Illwieckz
  • Remove THIS_IS_NOT_A_DEBUG_BUILD hack (not needed for PCH anymore) – Slipher
  • Use CMake’s target_precompiled_header for PCH – Slipher
  • Bump CMake minimum version to 3.18.4 – Slipher
  • Migrate some input-related cl_* cvars – Slipher
  • NUKE debug cvar cl_showMouseRate – Slipher
  • Migrate cvar sensitivity – Slipher
  • Migrate m_* (mouse) cvars to new style – Slipher
  • Fix WAV file loading – Illwieckz
  • Migrate j_* cvars to new style – Slipher
  • Drop __MACOS__ ifdef in CL_JoystickMove – Slipher
  • Migrate ROM cvar in_gameControllerAvailable – Slipher
  • Rename in_joystickUseAnalog to j_useAnalog – Slipher
  • Move font stuff out of q_shared.h – Slipher
  • NUKE font handle table – Slipher
  • NUKE .dat pre-rasterized font file format – Slipher
  • Remove unused font things – Slipher
  • RE_RegisterFont: fix possibly uninitialized pointer – Slipher
  • Exclude OpenGL tests from Vulkan build – Slipher
  • Fix file:line logging in gamelogic – Slipher
  • Access log suppression cvars less thread-unsafely – Slipher
  • Fix unused Log::(Warn|Notice|Verbose|Debug) decls – Slipher
  • Simplify Logger::Prefix (function that adds prefix) – Slipher
  • Migrate in_* cvars to new style – Slipher
  • Migrate cvar in_joystickNo to new style – Slipher
  • Add game controller logger (logs.level.client.controller) – Slipher
  • Call IN_ShutdownJoystick in non-pedantic shutdown – Slipher
  • Remove “StackTrace unavailable” message – Slipher
  • Start of daemon-vulkan infrastructure – Reaper
  • Faster other R_CalcTangents() with VectorNormalizeFast() – Illwieckz
  • Faster Tess_SurfacePolychain() with VectorNormalizeFast() in R_CalcTangents() – Illwieckz
  • Faster Tess_SurfacePolychain() with R_TBNtoQtangentsFast() – Illwieckz
  • Faster Tess_SurfaceIQM() and Tess_SurfaceMD5() with R_TBNtoQtangentsFast() – Illwieckz
  • Introduce R_TBNtoQtangentsFast() and floatToSnorm16_fast() – Illwieckz

3 thoughts on “Unvanquished 0.56: We deliver”

  1. We’ve realized there is an issue with the server version compatibility check. It always displays a warning when trying to join a server, even if the version is compatible. But don’t worry: you can just click through the warning. The server is compatible as long as the version is not displayed in red in the in-game server list.

  2. The server list patch is now published as 0.56.1. As always, users of the Unvanquished launcher will automatically receive it. No action is required from server owners, since the patch only affects the main menu.

Leave a Reply

Your email address will not be published. Required fields are marked *