mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-13 22:22:05 +00:00
Merge branch 'master' into sdl-joykeys
This commit is contained in:
commit
201485eb37
59 changed files with 1756 additions and 1079 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -41,6 +41,8 @@ base/renderprogs2/
|
|||
base/generated/
|
||||
base/env/
|
||||
base/screenshots/
|
||||
base/_tb/*.obj
|
||||
base/_tb/*.mtl
|
||||
|
||||
GPATH
|
||||
GRTAGS
|
||||
|
@ -52,3 +54,4 @@ neo/neo.kdev4
|
|||
neo/.idea/
|
||||
neo/cmake-build-*/
|
||||
neo/bin/
|
||||
tools/
|
||||
|
|
64
README.md
64
README.md
|
@ -24,20 +24,19 @@ This file contains the following sections:
|
|||
|
||||
1. [About the Port](#about)
|
||||
2. [".plan"](#plan)
|
||||
3. [May or may not ".plan"](#plan2)
|
||||
4. [Renderer Features Explained](#render)
|
||||
5. [TrenchBroom Mapping Support](#trenchbroom)
|
||||
6. [General Notes](#notes)
|
||||
7. [License](#license)
|
||||
8. [Getting the Source Code ](#source)
|
||||
9. [Compiling on Windows](#compile_windows)
|
||||
10. [Compiling on Linux](#compile_linux)
|
||||
11. [Compiling on macOS](#compile_macos)
|
||||
12. [Installation](#installation)
|
||||
13. [New Console Variables](#console)
|
||||
14. [Known Issues](#issues)
|
||||
15. [Bug Reports](#reports)
|
||||
16. [FAQ](#faq)
|
||||
3. [Renderer Features Explained](#render)
|
||||
4. [TrenchBroom Mapping Support](#trenchbroom)
|
||||
5. [General Notes](#notes)
|
||||
6. [License](#license)
|
||||
7. [Getting the Source Code ](#source)
|
||||
8. [Compiling on Windows](#compile_windows)
|
||||
9. [Compiling on Linux](#compile_linux)
|
||||
10. [Compiling on macOS](#compile_macos)
|
||||
11. [Installation](#installation)
|
||||
12. [New Console Variables](#console)
|
||||
13. [Known Issues](#issues)
|
||||
14. [Bug Reports](#reports)
|
||||
15. [FAQ](#faq)
|
||||
|
||||
|
||||
|
||||
|
@ -47,7 +46,7 @@ This file contains the following sections:
|
|||
|
||||
`RBDOOM-3-BFG is a modernization effort of DOOM-3-BFG.`
|
||||
|
||||
RBDOOM-3-BFG is based on DOOM-3-BFG and the goal of this port is to bring DOOM-3-BFG up to latest technology in 2024 making it closer to Doom 2016 while still remaining a DOOM 3 port regarding the gameplay.
|
||||
RBDOOM-3-BFG is based on DOOM-3-BFG and the goal of this port is to bring DOOM-3-BFG up to latest technology in 2025 making it closer to Doom 2016 while still remaining a DOOM 3 port regarding the gameplay.
|
||||
|
||||
I started this project in 2012 and focused on making this code being future proof so other cool projects can build interesting things on top of it without the need to fix a lot of stuff first. Over 40 people all over the world contributed cool patches. Some results are:
|
||||
|
||||
|
@ -59,7 +58,7 @@ I started this project in 2012 and focused on making this code being future proo
|
|||
* All 3 light types (point, spot, parallel/sun) are supported which means parallel lights (sun) use
|
||||
scene independent cascaded shadow mapping.
|
||||
* True internal 64 bit HDR lighting with filmic ACES tone mapping and gamma-correct rendering in linear RGB space
|
||||
* Temporal Antialiasing (TAA) as a cheap alternative for MSAA and that works well with HDR and also improves PBR lighting
|
||||
* SMAA and Temporal Antialiasing (TAA) as cheap alternatives for MSAA
|
||||
* Filmic post process effects like Chromatic Aberration and Dithering
|
||||
* Retro Rendering modes for the nostalgia of the 8-bit and 16-bit eras including the Commodore 64, Amstrad CPC 6128, Sega Genesis and Sony PSX
|
||||
* Screen Space Ambient Occlusion used to only dim down the Global Illumination contribution like in the Frostbite engine
|
||||
|
@ -115,18 +114,6 @@ You can fork RBDOOM-3-BFG and create a new renamed binary that includes all requ
|
|||
|
||||
If you want to see what is planned or in progress in a Trello/Kanban style manner look here: [RBDOOM-3-BFG projects](https://github.com/RobertBeckebans/RBDOOM-3-BFG/projects)
|
||||
|
||||
Short term goals:
|
||||
* Node based Imgui particle editor
|
||||
* Flash support through Adobe Animate or Blender
|
||||
* Raytracing for accelerating the probe baking and optionally adding realtime global illumination
|
||||
|
||||
---
|
||||
# May or may not ".plan" <a name="plan2"></a>
|
||||
* Replace traditional multipass forward shading with a faster forward+ solution
|
||||
* [Volumetric Lighting](http://www.alexandre-pestana.com/volumetric-lights/)
|
||||
* ReSTIR or some other realtime path tracing
|
||||
* Optional alternative collision detection and physics with PhysX 5 or Jolt
|
||||
|
||||
---
|
||||
# Renderer Features Explained <a name="render"></a>
|
||||
|
||||
|
@ -328,7 +315,7 @@ r_useSSAO 1 darkens the corners of the scene and also removes too much ambient a
|
|||
"""
|
||||
-->
|
||||
## Filmic Post Processing
|
||||
If you enable it with r_useFilmicPostProcessing 1 then you play DOOM 3 BFG the optics of a Zack Snyder movie.
|
||||
If you enable it with r_useFilmicPostFX 1 then you play DOOM 3 BFG the optics of a Zack Snyder movie.
|
||||
|
||||
It adds chromatic abberation and filmic dithering using Blue Noise.
|
||||
The effect is heavy and is usually aimed in Film production to mix real camera footage with CG generated content.
|
||||
|
@ -375,11 +362,11 @@ Directory | Description
|
|||
RBDOOM-3-BFG/base/ | Doom 3 BFG media directory ( models, textures, sounds, maps, etc. )
|
||||
RBDOOM-3-BFG/neo/ | RBDOOM-3-BFG source code ( renderer, game code for multiple games, OS layer, etc. )
|
||||
RBDOOM-3-BFG/build/ | Build folder for CMake
|
||||
RBDOOM-3-BFG/tools/runtimedeps | Visual Studio C++ Redistributables if you have problems to start the engine or the tools
|
||||
RBDOOM-3-BFG/tools/trenchbroom | TrenchBroomBFG level editor customized for DOOM 3 and RBDOOM-3-BFG
|
||||
RBDOOM-3-BFG/tools/darkradiant | DarkRadiant level editor with an additional config for RBDOOM-3-BFG
|
||||
RBDOOM-3-BFG/tools/bfgpakexlorer | BFG Resource File Manager by George Kalampokis aka Mr.GK
|
||||
RBDOOM-3-BFG/tools/optick-profiler | Optick is a super-lightweight C++ profiler for Games
|
||||
RBDOOM-3-BFG/tools/runtimedeps | Visual Studio C++ Redistributables if you have problems to start the engine or the tools
|
||||
|
||||
The GPL release does not contain any game data, the game data is still
|
||||
covered by the original EULA and must be obeyed as usual.
|
||||
|
@ -629,15 +616,16 @@ Name | Description
|
|||
r_graphicsAPI | Default DX12, can be either DX12 or Vulkan on Windows
|
||||
r_antiAliasing | Different Anti-Aliasing modes
|
||||
r_exposure [0 .. 1] | Default 0.5, controls brightness and affects HDR -> sRGB Rec. 709 exposure key. This is what you change in the video brightness options
|
||||
r_useSSAO [0 .. 1] | Use Screen Space Ambient Occlusion to darken the corners in the scene and give it more depth
|
||||
r_useSSAO [0, 1] | Use Screen Space Ambient Occlusion to darken the corners in the scene and give it more depth
|
||||
r_forceAmbient | Default 0.5, controls additional brightness by Global Illumination
|
||||
r_useFilmicPostFX [0, 1] | Apply several post process effects to mimic a filmic look
|
||||
r_useCRTPostFX [0 .. 2] | CRT monitor/TV filter
|
||||
r_renderMode [0 .. 7] | Default 0 = Doom, 1 = CGA, 2 = CGA Highres, 3 = Commodore 64, 4 = Commodore 64 Highres, 5 = Amstrad CPC 6128, 6 = Amstrad CPC 6128 Highres, 7 = NES, 8 = NES Highres, 9 = Sega Genesis, 10 = Sega Genesis Highres, 11 = Sony PSX
|
||||
r_renderMode [0 .. 9] | Default 0 = Doom, 1 = CGA, 2 = CGA Highres, 3 = Commodore 64, 4 = Commodore 64 Highres, 5 = Amstrad CPC 6128, 6 = Amstrad CPC 6128 Highres, 7 = Sega Genesis, 8 = Sega Genesis Highres, 9 = Sony PSX
|
||||
|
||||
## Modding Support
|
||||
Name | Description
|
||||
:--------------------------------------| :------------------------------------------------
|
||||
listCvars `[new]` | Option that lists all cvars that have been added to this sourceport
|
||||
dmap mapfile | Command: Compiles a .map to its corresponding BSP .proc, Collision .cm files and Area Awareness System (AI navigation) .aas files. Just type dmap to list all options
|
||||
dmap `[glview]` mapfile | DMap option that exports the BSP areas and portals to .obj for debugging purposes
|
||||
bakeEnvironmentProbes | Command after loading a map. Captures all env_probe entities and stores them to disc
|
||||
|
@ -648,11 +636,11 @@ exportImagesToTrenchBroom | Command: Decompresses and saves all TB
|
|||
exportModelsToTrenchBroom | Command: Saves all binarized models to base/_tb/*.obj files
|
||||
convertMapToValve220 `<map>` | Command: Saves *_valve220.map version of the given map. This makes it editable with TrenchBroomBFG.
|
||||
convertMapQuakeToDoom `<map>` | Command: Expects a Quake 1 .map in the Valve220 format and does some Doom 3 specific fixes
|
||||
makeZooMapForModels | Command: Makes a Source engine style zoo map with mapobject/models like .blwo, .base et cetera and saves it to maps/zoomaps/zoo_models.map. This helps mappers to get a good overview of the trememdous amount of custom models available in Doom 3 BFG by sorting them into categories and arranging them in 3D. It also filters models so that only modular models are picked that can be reused in new maps.
|
||||
exportEntityDefsToBlender | Command: Exports all entity and model defs to base/_bl/entities.json for usage in Blender before loading a map.
|
||||
exportMapToOBJ | Command: Convert .map file to .obj/.mtl
|
||||
swf_show | Cvar: Draws the bounding box of instanced Flash sprites in red and their names
|
||||
makeMaterials `<folder>` | Command: Make a .mtr file based on PBR naming conventions
|
||||
makeZooMapForModels | Command: Makes a Source engine style zoo map with mapobject/models like .blwo, .base et cetera and saves it to maps/zoomaps/zoo_models.map. This helps mappers to get a good overview of the trememdous amount of custom models available in Doom 3 BFG by sorting them into categories and arranging them in 3D. It also filters models so that only modular models are picked that can be reused in new maps.
|
||||
|
||||
|
||||
---
|
||||
|
@ -682,14 +670,18 @@ You can find your qconsole.log on Windows in C:\Users\<your user name>\Saved Gam
|
|||
---
|
||||
# FAQ <a name="faq"></a>
|
||||
|
||||
**Q**: Why bother with DOOM-3-BFG in 2021?
|
||||
**Q**: Why bother with DOOM-3-BFG in 2025?
|
||||
**A**: It is fun, period. Doom 3 is from 2004 but it is still an impressive and entertaining game. In 2011 id Software added many results from the development of Rage like its own Flash SWF and ActionScript 2 interpreter, proper support for gamepads and widescreens. It also combines the gamecode for Doom 3 and its missionpacks and runs it in a seperate thread and it has many multithreaded rendering optimizations.
|
||||
DOOM-3 and DOOM-3-BFG are some of the most transparent games available where you can open all files and inspect how the game was built.
|
||||
Unlike Quake 1-3, DOOM-3-BFG shipped with all level .map sources for 47 single player maps.
|
||||
There is plenty of stuff you can learn from it like solid run & gun core gameplay, AI, animations, client/server multiplayer, level design or simple and elegant engine design.
|
||||
|
||||
**Q**: Why bother with DOOM-3-BFG in 2023?
|
||||
**A**: The engine compiles faster than opening a project in Unity. Maybe you just appreciate that it doesn't require more than 300 MB of RAM and 1024 MB of VRAM while running a complex game like Doom 3.
|
||||
**Q**: Why bother with the DOOM-3-BFG engine in 2025?
|
||||
**A**: The engine compiles faster than opening a project in Unity or Unreal. Maybe you just appreciate that it doesn't require more than 300 MB of RAM and 3072 MB of VRAM while running a complex game like Doom 3. Maybe it is just nice that it can run Epic's Sun Temple demo with over 230 fps @ 1080p on a Geforce 2070 Super unlike UE4.
|
||||
|
||||
<!--
|
||||
<img src="https://i.imgur.com/cwwr4z5.png" width="800">
|
||||
-->
|
||||
|
||||
**Q**: Can I use this engine to make a commercial game?
|
||||
**A**: You can but don't bother me to give you free support and you probably should use Unreal Engine 4/5. I am a full time game developer and usually don't have time for any free support. I recommend that you have moderate C++ skills even if you are an artist. Technical designers (coders who became artists) might benefit most from this engine. Keep in mind that the GPL license will lock you out of the console markets because you can't use proprietary APIs covered by NDAs. However you can sell your game on Steam without problems.
|
||||
|
|
|
@ -18,6 +18,74 @@ _______________________________________
|
|||
TBD - RBDOOM-3-BFG 1.6.0
|
||||
_______________________________
|
||||
|
||||
## .plan - January 16, 2025
|
||||
|
||||
This test build comes with HDRI support and a few critical bugfixes that save video memory and avoid unnessessary duplicated .bimage files.
|
||||
|
||||
Changelog:
|
||||
|
||||
* Fixed bad lightgrid lookups if models span multiple areas. close #965
|
||||
|
||||
* Fixed several bugs in the .bimage lookup logic
|
||||
|
||||
* Added HDRI extension to the material system
|
||||
|
||||
* Added default loading screen for custom maps
|
||||
|
||||
* Simplified image loading code
|
||||
|
||||
* Fixed potential memleaks in R_LoadEXR and R_WriteEXR
|
||||
|
||||
* Added cacheGlobalIlluminationData cmd to turn env/maps/*.exr into .bimage files
|
||||
|
||||
* Apply invertGreen( normalmap ) with DX normalmaps and makeMaterials
|
||||
|
||||
* Added some docs by Mr.Elusive about the BFG architecture
|
||||
|
||||
|
||||
|
||||
## .plan - January 02, 2025
|
||||
|
||||
This test build comes with a new TrenchBroomBFG build that drastically reduces the load time of maps that use custom models with higher polycounts than the typical Doom 3 models. This reduces the load time to seconds instead of minutes and makes the editor feasible to work with more modern models like Epic's Sun Temple demo or Crytek's Sponza level.
|
||||
|
||||
Besides that RBDoom has a new binary model format that was necessary to avoid crashes when reloading custom maps.
|
||||
This will also regenerate all models like .glb -> .bglb, .obj -> .bobj and so on.
|
||||
|
||||
Changelog:
|
||||
|
||||
* Reduced peter panning effect and shadow acne with Nvidia cards
|
||||
|
||||
* Added new .bproc format to avoid crashes with custom maps
|
||||
|
||||
* Replaced in the ingame light editor 'Save as .map' button with 'Apply' button. Use Ctrl+S instead to save the map.
|
||||
|
||||
* Optimized retro shaders by precomputing deviation
|
||||
|
||||
* Deleted NES shader
|
||||
|
||||
* Disabled scrolling scanlines in Newpixie CRT shader
|
||||
|
||||
* Replaced Sega retro shader quant with a fixed 64 color palette
|
||||
|
||||
* Don't quit rbdmap quietly if running in imtui mode
|
||||
|
||||
* Quadruppled vertex cache limits like before in RBDoom 1.4
|
||||
|
||||
* Extended makeMaterials to handle UE4 specular maps
|
||||
|
||||
* Added textures/common/black material to block light behind walls
|
||||
|
||||
* glTF culling bugfix caused by uninitialized variable
|
||||
|
||||
* Fixed menu button controller mappings with SDL
|
||||
|
||||
* Use correct controller button->joystick event mapping for SDL joystick polling
|
||||
|
||||
Changelog TrenchBroomBFG:
|
||||
|
||||
* Replaced ray traced model picker code using TinyBVH which allows to load bigger glTF 2 maps almost instantly instead of minutes
|
||||
|
||||
|
||||
## .plan - December 6, 2024
|
||||
|
||||
This is a first test build for the new blood effects.
|
||||
|
@ -124,7 +192,7 @@ Immerse yourself in the authentic Commodore 64 mode, faithfully replicating the
|
|||
|
||||
The retro rendering modes transport you back to the golden age of gaming, with a resolution that mimics the beloved 320x240 display, now extended to a widescreen 480x270 format. To enhance the arcade feel, two new CRT filters are included that overlay the entire game, including Doom 1 & 2.
|
||||
|
||||
To access these retro rendering modes, simply navigate to the menu options and select your desired mode. Alternatively, you can control the rendering mode by modifying the `r_renderMode` variable. The available values for `r_renderMode` are as follows: Default (0) for Doom 3, 2-bit CGA (1), 2-bit CGA Highres(2), Commodore 64 (3), Commodore 64 Highres (4), Amstrad CPC (5), Amstrad CPC Highres (6), NES (7), NES Highres (8), Sega Genesis (9), Sega Genesis Highres (10) and Sony PSX (11).
|
||||
To access these retro rendering modes, simply navigate to the menu options and select your desired mode. Alternatively, you can control the rendering mode by modifying the `r_renderMode` variable. The available values for `r_renderMode` are as follows: Default (0) for Doom 3, 2-bit CGA (1), 2-bit CGA Highres(2), Commodore 64 (3), Commodore 64 Highres (4), Amstrad CPC (5), Amstrad CPC Highres (6), Sega Genesis (7), Sega Genesis Highres (8) and Sony PSX (9).
|
||||
|
||||
<img src="https://i.imgur.com/W8umJ3a.png" width="800">
|
||||
|
||||
|
|
|
@ -72,5 +72,4 @@ bind y "clientMessageMode 1"
|
|||
//
|
||||
|
||||
bind MOUSE1 _attack
|
||||
bind MOUSE2 _moveup
|
||||
|
||||
|
|
|
@ -12,9 +12,9 @@ bind "F2" "toggle r_showTris 1 2 0"
|
|||
bind "F3" "toggle r_forceAmbient 0.3 0.5 1.0 0"
|
||||
bind "F4" "toggle r_skipInteractions"
|
||||
bind "F5" "savegame quick"
|
||||
// bind "F6" "toggle r_showLightGrid 1 3 4 0"
|
||||
bind "F6" "toggle r_renderMode 0 1 3 5 7 9 11"
|
||||
bind "F7" "toggle r_renderMode 0 1 2 3 4 5 6 7 8 9 10 11"
|
||||
bind "F6" "toggle r_showLightGrid 1 3 4 0"
|
||||
//bind "F6" "toggle r_renderMode 0 1 3 5 7 9 11"
|
||||
bind "F7" "toggle r_renderMode 0 1 2 3 4 5 6 7 8 9"
|
||||
bind "F8" "toggle r_useCRTPostFX 0 1 2 3"
|
||||
bind "F9" "loadgame quick"
|
||||
// bind "F10" "toggle com_fixedTic"
|
||||
|
|
BIN
base/guis/assets/loadscreens/default.jpg
Normal file
BIN
base/guis/assets/loadscreens/default.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 300 KiB |
|
@ -442,4 +442,17 @@ textures/common/occlusion
|
|||
noshadows
|
||||
occlusion
|
||||
}
|
||||
|
||||
// this one is not invisible and like textures/sfx/black but will also cast shadows
|
||||
// so it works as a blocker for the lightgrid
|
||||
textures/common/black
|
||||
{
|
||||
qer_editorimage textures/common/black.tga
|
||||
nonsolid
|
||||
forceshadows
|
||||
forceOpaque
|
||||
noselfshadow
|
||||
|
||||
basecolormap _blackDiffuse
|
||||
}
|
||||
// RB end
|
|
@ -295,7 +295,7 @@ scriptEvent entity getEntity( string name );
|
|||
scriptEvent entity spawn( string classname );
|
||||
|
||||
// Respawn
|
||||
scriptEvent void respawn();
|
||||
scriptEvent void respawn( );
|
||||
|
||||
// copies the spawn args from an entity
|
||||
scriptEvent void copySpawnArgs( entity ent );
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
|
||||
Alternate Quake Tracks
|
||||
----------------------
|
||||
This is a compilation of alternate tracks.
|
||||
They are to be used for streamers/YouTubers
|
||||
as well as for those who lack the OST.
|
||||
|
||||
02. Often not Their Right Time Verbum Mentis
|
||||
03. EoE intermission Markie Music
|
||||
04. Yss Éskiuth Immorpher
|
||||
05. Gwam Swolíst Immorpher
|
||||
06. Feedback AlekswithaK
|
||||
07. Thia Whythdyi Immorpher
|
||||
08. Deeper Outside, pt 1 Verbum Mentis
|
||||
09. Lingering Repetitive Agony Verbum Mentis
|
||||
10. Architects of Enmity AlekswithaK
|
||||
11. Scratch my surface Verbum Mentis
|
||||
|
||||
|
||||
All music is either open source or permitted
|
||||
to be used, when playing the game, by the
|
||||
composer. Enjoy!
|
||||
|
||||
- Greenwood
|
||||
*/
|
||||
|
||||
music/aqm/track02
|
||||
{
|
||||
description "Often not Their Right Time Verbum Mentis"
|
||||
|
||||
volume -5
|
||||
global
|
||||
looping
|
||||
music/aqm/track02.ogg
|
||||
}
|
||||
|
||||
music/aqm/track03
|
||||
{
|
||||
description "EoE intermission"
|
||||
|
||||
volume -5
|
||||
global
|
||||
looping
|
||||
music/aqm/track03.ogg
|
||||
}
|
||||
|
||||
music/aqm/track04
|
||||
{
|
||||
description "Yss Éskiuth"
|
||||
|
||||
volume -2
|
||||
global
|
||||
looping
|
||||
music/aqm/track04.ogg
|
||||
}
|
||||
|
||||
music/aqm/track05
|
||||
{
|
||||
description "Gwam Swolíst"
|
||||
|
||||
volume -2
|
||||
global
|
||||
looping
|
||||
music/aqm/track05.ogg
|
||||
}
|
||||
|
||||
music/aqm/track06
|
||||
{
|
||||
description "Feedback"
|
||||
|
||||
volume -3
|
||||
global
|
||||
looping
|
||||
music/aqm/track06.ogg
|
||||
}
|
||||
|
||||
music/aqm/track07
|
||||
{
|
||||
description "Thia Whythdyi"
|
||||
|
||||
volume -2
|
||||
global
|
||||
looping
|
||||
music/aqm/track07.ogg
|
||||
}
|
||||
|
||||
music/aqm/track08
|
||||
{
|
||||
description "Deeper Outside, pt 1"
|
||||
|
||||
volume -4
|
||||
global
|
||||
looping
|
||||
music/aqm/track08.ogg
|
||||
}
|
||||
|
||||
music/aqm/track09
|
||||
{
|
||||
description "Lingering Repetitive Agony"
|
||||
|
||||
volume -5
|
||||
global
|
||||
looping
|
||||
music/aqm/track09.ogg
|
||||
}
|
||||
|
||||
music/aqm/track10
|
||||
{
|
||||
description "Architects of Enmity"
|
||||
|
||||
volume -2
|
||||
global
|
||||
looping
|
||||
music/aqm/track10.ogg
|
||||
}
|
||||
|
||||
music/aqm/track11
|
||||
{
|
||||
description "Scratch my surface"
|
||||
|
||||
volume -2
|
||||
global
|
||||
looping
|
||||
music/aqm/track11.ogg
|
||||
}
|
BIN
base/textures/common/black.png
Normal file
BIN
base/textures/common/black.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
BIN
docs/DOOM-3-BFG-Technical-Note.pdf
Normal file
BIN
docs/DOOM-3-BFG-Technical-Note.pdf
Normal file
Binary file not shown.
BIN
docs/flash/avm2overview.pdf
Normal file
BIN
docs/flash/avm2overview.pdf
Normal file
Binary file not shown.
BIN
docs/flash/swf-file-format-spec.pdf
Normal file
BIN
docs/flash/swf-file-format-spec.pdf
Normal file
Binary file not shown.
BIN
docs/multiplayer/The-DOOM-III-Network-Architecture.pdf
Normal file
BIN
docs/multiplayer/The-DOOM-III-Network-Architecture.pdf
Normal file
Binary file not shown.
BIN
docs/physics/Robust-Continuous-Collision-Detection.pdf
Normal file
BIN
docs/physics/Robust-Continuous-Collision-Detection.pdf
Normal file
Binary file not shown.
|
@ -1715,6 +1715,18 @@ void idGameLocal::MapShutdown()
|
|||
gameRenderWorld->DebugClearPolygons( 0 );
|
||||
}
|
||||
|
||||
// RB: kill ingame editors to prevent crashes during shutdown
|
||||
if( com_editors != 0 )
|
||||
{
|
||||
com_editors = 0;
|
||||
g_editEntityMode.SetInteger( 0 );
|
||||
|
||||
// turn off light debug drawing in the render backend
|
||||
r_singleLight.SetInteger( -1 );
|
||||
r_showLights.SetInteger( 0 );
|
||||
}
|
||||
// RB end
|
||||
|
||||
// clear out camera if we're in a cinematic
|
||||
if( inCinematic )
|
||||
{
|
||||
|
|
|
@ -2747,6 +2747,9 @@ void Cmd_EditLights_f( const idCmdArgs& args )
|
|||
r_singleLight.SetInteger( -1 );
|
||||
r_showLights.SetInteger( 0 );
|
||||
}
|
||||
|
||||
// put player into fly mode
|
||||
Cmd_Noclip_f( args );
|
||||
}
|
||||
// RB end
|
||||
|
||||
|
|
|
@ -614,8 +614,8 @@ void idMenuScreen_Shell_SystemOptions::idMenuDataSource_SystemSettings::AdjustFi
|
|||
// RB begin
|
||||
case SYSTEM_FIELD_RENDERMODE:
|
||||
{
|
||||
static const int numValues = 12;
|
||||
static const int values[numValues] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
|
||||
static const int numValues = 10;
|
||||
static const int values[numValues] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
r_renderMode.SetInteger( AdjustOption( r_renderMode.GetInteger(), values, numValues, adjustAmount ) );
|
||||
break;
|
||||
}
|
||||
|
@ -795,7 +795,7 @@ idSWFScriptVar idMenuScreen_Shell_SystemOptions::idMenuDataSource_SystemSettings
|
|||
}
|
||||
case SYSTEM_FIELD_RENDERMODE:
|
||||
{
|
||||
static const int numValues = 12;
|
||||
static const int numValues = 10;
|
||||
static const char* values[numValues] =
|
||||
{
|
||||
"Doom 3",
|
||||
|
@ -805,8 +805,6 @@ idSWFScriptVar idMenuScreen_Shell_SystemOptions::idMenuDataSource_SystemSettings
|
|||
"Commodore 64 Hi",
|
||||
"Amstrad CPC 6128",
|
||||
"Amstrad CPC 6128 Hi",
|
||||
"NES",
|
||||
"NES Hi",
|
||||
"Sega Genesis",
|
||||
"Sega Genesis Highres",
|
||||
"Sony PSX",
|
||||
|
|
|
@ -444,7 +444,7 @@ float idConsoleLocal::DrawFPS( float y )
|
|||
aaMode = aaValues[ r_antiAliasing.GetInteger() ];
|
||||
}
|
||||
|
||||
static const int rrNumValues = 12;
|
||||
static const int rrNumValues = 10;
|
||||
static const char* rrValues[rrNumValues] =
|
||||
{
|
||||
"Doom",
|
||||
|
@ -454,10 +454,8 @@ float idConsoleLocal::DrawFPS( float y )
|
|||
"C64 Hi",
|
||||
"CPC",
|
||||
"CPC Hi",
|
||||
"NES",
|
||||
"NES Hi",
|
||||
"Sega MD",
|
||||
"Sega MD Hi",
|
||||
"Sega",
|
||||
"Sega Hi",
|
||||
"Sony PSX",
|
||||
};
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 2022 Harrie van Ginneken
|
||||
Copyright (C) 2022 Robert Beckebans
|
||||
Copyright (C) 2022-2025 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
@ -32,7 +32,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
// files import as y-up. Use this transform to change the model to z-up.
|
||||
static const idMat4 blenderToDoomTransform( idAngles( 0.0f, 0.0f, 90 ).ToMat3(), vec3_origin );
|
||||
//static const idMat4 blenderToDoomTransform = mat4_identity;
|
||||
|
||||
MapPolygonMesh* MapPolygonMesh::ConvertFromMeshGltf( const gltfMesh_Primitive* prim, gltfData* _data , const idMat4& transform )
|
||||
{
|
||||
|
@ -409,7 +408,7 @@ static void AddMeshesToWorldspawn_r( idMapEntity* entity, gltfNode* node, const
|
|||
}
|
||||
};
|
||||
|
||||
void ResolveLight( gltfData* data, idMapEntity* newEntity, gltfNode* node )
|
||||
static void ResolveLight( gltfData* data, idMapEntity* newEntity, gltfNode* node )
|
||||
{
|
||||
assert( node && node->extensions.KHR_lights_punctual );
|
||||
|
||||
|
@ -493,7 +492,7 @@ void ResolveLight( gltfData* data, idMapEntity* newEntity, gltfNode* node )
|
|||
|
||||
}
|
||||
|
||||
void ResolveEntity( gltfData* data, idMapEntity* newEntity, gltfNode* node )
|
||||
static void ResolveEntity( gltfData* data, idMapEntity* newEntity, gltfNode* node )
|
||||
{
|
||||
const char* classname = node->extras.strPairs.GetString( "classname" );
|
||||
|
||||
|
@ -533,9 +532,11 @@ void ResolveEntity( gltfData* data, idMapEntity* newEntity, gltfNode* node )
|
|||
if( node->extensions.KHR_lights_punctual != nullptr )
|
||||
{
|
||||
ResolveLight( data, newEntity, node );
|
||||
return;
|
||||
}
|
||||
|
||||
// HarrievG: TODO cleanup this was done by try & error until it worked
|
||||
#if 0
|
||||
if( node->camera >= 0 && !newEntity->epairs.FindKey( "rotation" ) )
|
||||
{
|
||||
idQuat q = entityToWorldTransform.ToMat3().ToQuat();
|
||||
|
@ -545,7 +546,7 @@ void ResolveEntity( gltfData* data, idMapEntity* newEntity, gltfNode* node )
|
|||
else if( idStr::Icmp( classname, "info_player_start" ) == 0 && !newEntity->epairs.FindKey( "rotation" ) )
|
||||
{
|
||||
idQuat q = entityToWorldTransform.ToMat3().ToQuat();
|
||||
q = idAngles( -90.0f, 0.0, -90.0f ).ToQuat() * q * blenderToDoomTransform.ToMat3().ToQuat();
|
||||
q = idAngles( 90.0f, 0.0, -90.0f ).ToQuat() * q * blenderToDoomTransform.ToMat3().ToQuat();
|
||||
newEntity->epairs.SetMatrix( "rotation", q.ToMat3() );
|
||||
}
|
||||
else if( node->extras.strPairs.GetBool( "useNodeOrientation", false ) )
|
||||
|
@ -561,6 +562,24 @@ void ResolveEntity( gltfData* data, idMapEntity* newEntity, gltfNode* node )
|
|||
//idMat3 rot = ( blenderToDoomTransform * entityToWorldTransform ).ToMat3();
|
||||
newEntity->epairs.SetMatrix( "rotation", rot );
|
||||
}
|
||||
#else
|
||||
if( node->camera >= 0 && !newEntity->epairs.FindKey( "rotation" ) )
|
||||
{
|
||||
idQuat q = entityToWorldTransform.ToMat3().ToQuat();
|
||||
q = idAngles( 90.0f, 0.0, -90.0f ).ToQuat() * q * blenderToDoomTransform.ToMat3().ToQuat();
|
||||
newEntity->epairs.SetMatrix( "rotation", q.ToMat3() );
|
||||
}
|
||||
else
|
||||
{
|
||||
idQuat q = entityToWorldTransform.ToMat3().ToQuat();
|
||||
q = idAngles( 0.0f, 0.0f, -90.0f ).ToQuat() * q * blenderToDoomTransform.ToMat3().ToQuat();
|
||||
newEntity->epairs.SetMatrix( "rotation", q.ToMat3() );
|
||||
|
||||
// FIXME this should be
|
||||
//idMat3 rot = ( blenderToDoomTransform * entityToWorldTransform ).ToMat3();
|
||||
//newEntity->epairs.SetMatrix( "rotation", rot );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
for( int i = 0; i < newEntity->epairs.GetNumKeyVals(); i++ )
|
||||
|
@ -572,20 +591,23 @@ void ResolveEntity( gltfData* data, idMapEntity* newEntity, gltfNode* node )
|
|||
#endif
|
||||
}
|
||||
|
||||
int FindEntities( gltfData* data, idMapEntity::EntityListRef entities, gltfNode* node , idDict epairs , idMapEntity* worldspawn )
|
||||
static int FindEntities_r( gltfData* data, idMapEntity::EntityListRef entities, gltfNode* node , idDict epairs , idMapEntity* worldspawn )
|
||||
{
|
||||
int entityCount = 0;
|
||||
|
||||
const char* classname = node->extras.strPairs.GetString( "classname" );
|
||||
|
||||
// skip all nodes with "worldspawn." or "BSP" in the name
|
||||
if( idStr::Icmpn( node->name, "BSP", 3 ) != 0
|
||||
&& idStr::Icmpn( node->name, "worldspawn.", 11 ) != 0 )
|
||||
if( idStr::Icmpn( node->name, "BSP", 3 ) == 0 || idStr::Icmpn( node->name, "worldspawn.", 11 ) == 0 )
|
||||
{
|
||||
AddMeshesToWorldspawn_r( worldspawn, node, mat4_identity, data );
|
||||
}
|
||||
else
|
||||
{
|
||||
idStr classnameStr = node->extras.strPairs.GetString( "classname" );
|
||||
|
||||
// skip everything that is not an entity
|
||||
if( !classnameStr.IsEmpty() )
|
||||
// skip everything that is not an entity except lights
|
||||
if( !classnameStr.IsEmpty() || node->extensions.KHR_lights_punctual )
|
||||
{
|
||||
auto* newEntity = new( TAG_IDLIB_GLTF ) idMapEntity();
|
||||
entities.Append( newEntity );
|
||||
|
@ -604,14 +626,10 @@ int FindEntities( gltfData* data, idMapEntity::EntityListRef entities, gltfNode*
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddMeshesToWorldspawn_r( worldspawn, node, mat4_identity, data );
|
||||
}
|
||||
|
||||
for( auto& child : node->children )
|
||||
{
|
||||
entityCount += FindEntities( data, entities, data->NodeList()[child], epairs , worldspawn );
|
||||
entityCount += FindEntities_r( data, entities, data->NodeList()[child], epairs , worldspawn );
|
||||
}
|
||||
|
||||
return entityCount;
|
||||
|
@ -648,7 +666,14 @@ int idMapEntity::GetEntities( gltfData* data, EntityListRef entities, int sceneI
|
|||
else
|
||||
{
|
||||
idStr classnameStr = node->extras.strPairs.GetString( "classname" );
|
||||
bool skipInline = !node->extras.strPairs.GetBool( "inline", true );
|
||||
idStr model = node->extras.strPairs.GetString( "model" );
|
||||
|
||||
// inline should be false by default because drag n drop in the asset browser in Blender is Append by default
|
||||
// however it would break previous maps
|
||||
|
||||
// in Doom 3 maps inline entities have as model key the same name as the entity name
|
||||
const bool defaultInline = ( idStr::Icmp( model.c_str(), node->name.c_str() ) == 0 );
|
||||
bool skipInline = !node->extras.strPairs.GetBool( "inline", defaultInline );
|
||||
idDict epairs;
|
||||
|
||||
// skip everything that is not an entity except lights
|
||||
|
@ -678,10 +703,11 @@ int idMapEntity::GetEntities( gltfData* data, EntityListRef entities, int sceneI
|
|||
epairs.Copy( node->extras.strPairs );
|
||||
}
|
||||
}
|
||||
|
||||
// add entities from all subnodes
|
||||
for( auto& child : node->children )
|
||||
{
|
||||
entityCount += FindEntities( data, entities, data->NodeList()[child] , epairs, worldspawn );
|
||||
entityCount += FindEntities_r( data, entities, data->NodeList()[child] , epairs, worldspawn );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,6 +117,26 @@ bool HandleKeyEvent( const sysEvent_t& keyEvent )
|
|||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
if( keyNum == K_MOUSE2 )
|
||||
{
|
||||
// RB: allow navigation like in a level editor
|
||||
g_MousePressed[1] = pressed;
|
||||
|
||||
if( ImGuiTools::AreEditorsActive() )
|
||||
{
|
||||
ImGuiTools::SetReleaseToolMouse( !pressed );
|
||||
}
|
||||
//common->Printf( "mouse2 pressed %d\n", int( pressed ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( g_MousePressed[1] )
|
||||
{
|
||||
// RB: ignore everything as long right mouse button is pressed
|
||||
return false;
|
||||
}
|
||||
|
||||
if( keyNum < K_JOY1 )
|
||||
{
|
||||
// keyboard input as direct input scancodes
|
||||
|
@ -230,7 +250,7 @@ bool ShowWindows()
|
|||
|
||||
bool UseInput()
|
||||
{
|
||||
return ImGuiTools::ReleaseMouseForTools() || imgui_showDemoWindow.GetBool();
|
||||
return ( ImGuiTools::ReleaseMouseForTools() || imgui_showDemoWindow.GetBool() );
|
||||
}
|
||||
|
||||
void StyleGruvboxDark()
|
||||
|
@ -752,7 +772,7 @@ void NotifyDisplaySizeChanged( int width, int height )
|
|||
// inject a sys event
|
||||
bool InjectSysEvent( const sysEvent_t* event )
|
||||
{
|
||||
if( IsInitialized() && UseInput() )
|
||||
if( IsInitialized() && ( UseInput() || RightMouseActive() ) )
|
||||
{
|
||||
if( event == NULL )
|
||||
{
|
||||
|
@ -795,6 +815,11 @@ bool InjectSysEvent( const sysEvent_t* event )
|
|||
return false;
|
||||
}
|
||||
|
||||
bool RightMouseActive()
|
||||
{
|
||||
return g_MousePressed[1];
|
||||
}
|
||||
|
||||
bool InjectMouseWheel( int delta )
|
||||
{
|
||||
if( IsInitialized() && UseInput() && delta != 0 )
|
||||
|
|
|
@ -61,6 +61,8 @@ void Render();
|
|||
|
||||
void Destroy();
|
||||
|
||||
bool RightMouseActive();
|
||||
|
||||
} //namespace ImGuiHook
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2014-2024 Robert Beckebans
|
||||
Copyright (C) 2014-2025 Robert Beckebans
|
||||
Copyright (C) 2014-2016 Kot in Action Creative Artel
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
@ -260,14 +260,6 @@ void idBinaryImage::Load2DFromMemory( int width, int height, const byte* pic_con
|
|||
img.data[ i ] = pic[ i ];
|
||||
}
|
||||
}
|
||||
else if( textureFormat == FMT_RGBA16F )
|
||||
{
|
||||
img.Alloc( scaledWidth * scaledHeight * 8 );
|
||||
for( int i = 0; i < img.dataSize; i++ )
|
||||
{
|
||||
img.data[ i ] = pic[ i ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fileData.format = textureFormat = FMT_RGBA8;
|
||||
|
@ -287,7 +279,11 @@ void idBinaryImage::Load2DFromMemory( int width, int height, const byte* pic_con
|
|||
|
||||
// downsample for the next level
|
||||
byte* shrunk = NULL;
|
||||
if( gammaMips )
|
||||
if( textureFormat == FMT_R11G11B10F )
|
||||
{
|
||||
shrunk = R_MipMapR11G11B10F( pic, scaledWidth, scaledHeight );
|
||||
}
|
||||
else if( gammaMips )
|
||||
{
|
||||
shrunk = R_MipMapWithGamma( pic, scaledWidth, scaledHeight );
|
||||
}
|
||||
|
@ -556,15 +552,6 @@ void idBinaryImage::Load2DAtlasMipchainFromMemory( int width, int height, const
|
|||
img.data[ i * 2 + 1 ] = color & 0xFF;
|
||||
}
|
||||
}
|
||||
else if( textureFormat == FMT_RG16F )
|
||||
{
|
||||
// RB: copy it as it was a RGBA8 because of the same size
|
||||
img.Alloc( scaledWidth * scaledHeight * 4 );
|
||||
for( int i = 0; i < img.dataSize; i++ )
|
||||
{
|
||||
img.data[ i ] = pic[ i ];
|
||||
}
|
||||
}
|
||||
else if( textureFormat == FMT_R11G11B10F )
|
||||
{
|
||||
// RB: copy it as it was a RGBA8 because of the same size
|
||||
|
@ -574,14 +561,6 @@ void idBinaryImage::Load2DAtlasMipchainFromMemory( int width, int height, const
|
|||
img.data[ i ] = pic[ i ];
|
||||
}
|
||||
}
|
||||
else if( textureFormat == FMT_RGBA16F )
|
||||
{
|
||||
img.Alloc( scaledWidth * scaledHeight * 8 );
|
||||
for( int i = 0; i < img.dataSize; i++ )
|
||||
{
|
||||
img.data[ i ] = pic[ i ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fileData.format = textureFormat = FMT_RGBA8;
|
||||
|
@ -599,21 +578,6 @@ void idBinaryImage::Load2DAtlasMipchainFromMemory( int width, int height, const
|
|||
dxtPic = NULL;
|
||||
}
|
||||
|
||||
// downsample for the next level
|
||||
/*
|
||||
byte* shrunk = NULL;
|
||||
if( gammaMips )
|
||||
{
|
||||
shrunk = R_MipMapWithGamma( pic, scaledWidth, scaledHeight );
|
||||
}
|
||||
else
|
||||
{
|
||||
shrunk = R_MipMap( pic, scaledWidth, scaledHeight );
|
||||
}
|
||||
Mem_Free( pic );
|
||||
pic = shrunk;
|
||||
*/
|
||||
|
||||
Mem_Free( pic );
|
||||
}
|
||||
|
||||
|
@ -735,6 +699,15 @@ void idBinaryImage::LoadCubeFromMemory( int width, const byte* pics[6], int numL
|
|||
dxt.CompressImageDXT5Fast( padSrc, img.data, padSize, padSize );
|
||||
}
|
||||
}
|
||||
else if( textureFormat == FMT_R11G11B10F )
|
||||
{
|
||||
// RB: copy it as it was a RGBA8 because of the same size
|
||||
img.Alloc( padSize * padSize * 4 );
|
||||
for( int i = 0; i < img.dataSize; i++ )
|
||||
{
|
||||
img.data[ i ] = pic[ i ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fileData.format = textureFormat = FMT_RGBA8;
|
||||
|
@ -744,7 +717,11 @@ void idBinaryImage::LoadCubeFromMemory( int width, const byte* pics[6], int numL
|
|||
|
||||
// downsample for the next level
|
||||
byte* shrunk = NULL;
|
||||
if( gammaMips )
|
||||
if( textureFormat == FMT_R11G11B10F )
|
||||
{
|
||||
shrunk = R_MipMapR11G11B10F( pic, scaledWidth, scaledWidth );
|
||||
}
|
||||
else if( gammaMips )
|
||||
{
|
||||
shrunk = R_MipMapWithGamma( pic, scaledWidth, scaledWidth );
|
||||
}
|
||||
|
@ -785,7 +762,7 @@ ID_TIME_T idBinaryImage::WriteGeneratedFile( ID_TIME_T sourceFileTime )
|
|||
idLib::Warning( "idBinaryImage: Could not open file '%s'", binaryFileName.c_str() );
|
||||
return FILE_NOT_FOUND_TIMESTAMP;
|
||||
}
|
||||
idLib::Printf( "Writing %s: %ix%i\n", binaryFileName.c_str(), fileData.width, fileData.height );
|
||||
//idLib::Printf( "Writing %s: %ix%i\n", binaryFileName.c_str(), fileData.width, fileData.height );
|
||||
|
||||
fileData.headerMagic = BIMAGE_MAGIC;
|
||||
fileData.sourceFileTime = sourceFileTime;
|
||||
|
|
|
@ -97,7 +97,7 @@ enum textureFormat_t
|
|||
FMT_Y16_X16, // 32 bpp
|
||||
FMT_RGB565, // 16 bpp
|
||||
|
||||
// RB: don't change above for .bimage compatibility up until RBDOOM-3-BFG 1.1
|
||||
// ^-- used in BFG edition, don't change above for .bimage compatibility
|
||||
FMT_ETC1_RGB8_OES, // 4 bpp
|
||||
FMT_SHADOW_ARRAY, // 32 bpp * 6
|
||||
FMT_RG16F, // 32 bpp
|
||||
|
@ -127,10 +127,6 @@ enum textureColor_t
|
|||
CFM_NORMAL_DXT5, // XY format and use the fast DXT5 compressor
|
||||
CFM_YCOCG_DXT5, // convert RGBA to CoCg_Y format
|
||||
CFM_GREEN_ALPHA, // Copy the alpha channel to green
|
||||
|
||||
// RB: don't change above for legacy .bimage compatibility
|
||||
CFM_YCOCG_RGBA8,
|
||||
// RB end
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -207,6 +203,8 @@ No texture is ever used that does not have a corresponding idImage.
|
|||
static const int MAX_TEXTURE_LEVELS = 14;
|
||||
|
||||
// How is this texture used? Determines the storage and color format
|
||||
// NOTE: be very careful when editing these because it might break older .bimage files or the lookup name
|
||||
// Only add new entries at the bottom
|
||||
typedef enum
|
||||
{
|
||||
TD_SPECULAR, // may be compressed, and always zeros the alpha channel
|
||||
|
@ -227,28 +225,33 @@ typedef enum
|
|||
TD_HIGHQUALITY_CUBE, // motorsep - Uncompressed cubemap texture (RGB colorspace)
|
||||
TD_LOWQUALITY_CUBE, // motorsep - Compressed cubemap texture (RGB colorspace DXT5)
|
||||
TD_SHADOW_ARRAY, // 2D depth buffer array for shadow mapping
|
||||
TD_RG16F,
|
||||
TD_RGBA16F,
|
||||
TD_RGBA16S,
|
||||
TD_RGBA32F,
|
||||
TD_R32F,
|
||||
TD_RG16F, // BRDF lookup table
|
||||
TD_RGBA16F, // RT = render target format only, not written to disk
|
||||
TD_RGBA16S, // RT only
|
||||
TD_RGBA32F, // RT only
|
||||
TD_R11G11B10F, // memory efficient HDR RGB format with only 32bpp
|
||||
// ^-- used up until RBDOOM-3-BFG 1.3
|
||||
TD_HDRI, // RB: R11G11B10F or BC6
|
||||
// RB end
|
||||
TD_R8F, // Stephen: Added for ambient occlusion render target.
|
||||
TD_LDR, // Stephen: Added for SRGB render target when tonemapping.
|
||||
TD_DEPTH_STENCIL, // depth buffer and stencil buffer
|
||||
TD_R32F, // RT only
|
||||
TD_R8F, // SP: RT only, added for ambient occlusion
|
||||
TD_LDR, // SP: RT only, added for SRGB render target when tonemapping
|
||||
TD_DEPTH_STENCIL, // SP: RT only, depth buffer and stencil buffer
|
||||
} textureUsage_t;
|
||||
|
||||
// NOTE: be very careful when editing these because it might break older .bimage files or the lookup name
|
||||
// Only add new entries at the bottom
|
||||
typedef enum
|
||||
{
|
||||
CF_2D, // not a cube map
|
||||
CF_NATIVE, // _px, _nx, _py, etc, directly sent to GL
|
||||
CF_CAMERA, // _forward, _back, etc, rotated and flipped as needed before sending to GL
|
||||
CF_QUAKE1, // _ft, _bk, etc, rotated and flipped as needed before sending to GL
|
||||
CF_PANORAMA, // TODO latlong encoded HDRI panorama typically used by Substance or Blender
|
||||
CF_PANORAMA, // RB: latlong encoded HDRI panorama typically used by Substance or Blender
|
||||
CF_2D_ARRAY, // not a cube map but not a single 2d texture either
|
||||
CF_2D_PACKED_MIPCHAIN, // usually 2d but can be an octahedron, packed mipmaps into single 2d texture atlas and limited to dim^2
|
||||
// ^-- used up until RBDOOM-3-BFG 1.3
|
||||
CF_SINGLE, // SP: A single texture cubemap. All six sides in one image.
|
||||
CF_QUAKE1, // RB: _ft, _bk, etc, rotated and flipped as needed before sending to GL
|
||||
} cubeFiles_t;
|
||||
|
||||
typedef void ( *ImageGeneratorFunction )( idImage* image, nvrhi::ICommandList* commandList );
|
||||
|
@ -505,12 +508,15 @@ void R_WriteEXR( const char* filename, const void* data, int channelsPerPixel, i
|
|||
|
||||
class idImageManager
|
||||
{
|
||||
friend class idImage;
|
||||
|
||||
public:
|
||||
|
||||
idImageManager()
|
||||
{
|
||||
insideLevelLoad = false;
|
||||
preloadingMapImages = false;
|
||||
cacheImages = false;
|
||||
commandList = nullptr;
|
||||
}
|
||||
|
||||
|
@ -593,10 +599,6 @@ public:
|
|||
idImage* taaFeedback1Image;
|
||||
idImage* taaFeedback2Image;
|
||||
idImage* bloomRenderImage[2];
|
||||
//idImage* glowImage[2]; // contains any glowable surface information.
|
||||
//idImage* glowDepthImage[2];
|
||||
//idImage* accumTransparencyImage;
|
||||
//idImage* revealTransparencyImage;
|
||||
idImage* envprobeHDRImage;
|
||||
idImage* envprobeDepthImage;
|
||||
idImage* heatmap5Image;
|
||||
|
@ -636,13 +638,18 @@ public:
|
|||
bool ExcludePreloadImage( const char* name );
|
||||
|
||||
idList<idImage*, TAG_IDLIB_LIST_IMAGE> images;
|
||||
private:
|
||||
idHashIndex imageHash;
|
||||
|
||||
static void CacheGlobalIlluminationData_f( const idCmdArgs& args ); // RB
|
||||
static void R_ListImages_f( const idCmdArgs& args );
|
||||
|
||||
// Transient list of images to load on the main thread to the gpu. Freed after images are loaded.
|
||||
idList<idImage*, TAG_IDLIB_LIST_IMAGE> imagesToLoad;
|
||||
|
||||
bool insideLevelLoad; // don't actually load images now
|
||||
bool preloadingMapImages; // unless this is set
|
||||
bool cacheImages; // similar to preload but surpresses prints
|
||||
|
||||
nvrhi::CommandListHandle commandList;
|
||||
};
|
||||
|
@ -663,6 +670,7 @@ byte* R_ResampleTexture( const byte* in, int inwidth, int inheight, int outwidth
|
|||
byte* R_MipMapWithAlphaSpecularity( const byte* in, int width, int height );
|
||||
byte* R_MipMapWithGamma( const byte* in, int width, int height );
|
||||
byte* R_MipMap( const byte* in, int width, int height );
|
||||
byte* R_MipMapR11G11B10F( const byte* in, int width, int height );
|
||||
|
||||
// these operate in-place on the provided pixels
|
||||
void R_BlendOverTexture( byte* data, int pixelCount, const byte blend[4] );
|
||||
|
@ -674,8 +682,10 @@ void R_ApplyCubeMapTransforms( int i, byte* data, int size );
|
|||
// SP begin
|
||||
// This method takes in a cubemap from a single image. Depending on the side (0-5),
|
||||
// the image will be extracted from data and returned. The dimensions will be size x size.
|
||||
byte* R_GenerateCubeMapSideFromSingleImage( byte* data, int srcWidth, int srcHeight, int size, int side );
|
||||
byte* R_GenerateCubeMapSideFromSingleImage( const byte* in, int srcWidth, int srcHeight, int size, int side );
|
||||
// SP end
|
||||
// RB
|
||||
byte* R_GenerateCubeMapSideFromPanoramaImage( const byte* in, int srcWidth, int srcHeight, int size, int side );
|
||||
|
||||
idVec4 R_CalculateMipRect( uint dimensions, uint mip );
|
||||
int R_CalculateUsedAtlasPixels( int dimensions );
|
||||
|
|
|
@ -137,7 +137,7 @@ static int R_QsortImageName( const void* a, const void* b )
|
|||
R_ListImages_f
|
||||
===============
|
||||
*/
|
||||
void R_ListImages_f( const idCmdArgs& args )
|
||||
void idImageManager::R_ListImages_f( const idCmdArgs& args )
|
||||
{
|
||||
int i, partialSize;
|
||||
idImage* image;
|
||||
|
@ -356,7 +356,11 @@ idImage* idImageManager::ImageFromFunction( const char* _name, ImageGeneratorFun
|
|||
{
|
||||
// strip any .tga file extensions from anywhere in the _name
|
||||
idStr name = _name;
|
||||
name.Replace( ".tga", "" );
|
||||
idStrList imageFormats = { ".tga", ".jpg", ".png", ".exr", ".hdr" };
|
||||
for( auto& ext : imageFormats )
|
||||
{
|
||||
name.Replace( ext, "" );
|
||||
}
|
||||
name.BackSlashesToSlashes();
|
||||
|
||||
// see if the image already exists
|
||||
|
@ -413,7 +417,11 @@ idImage* idImageManager::ImageFromFile( const char* _name, textureFilter_t filte
|
|||
|
||||
// strip any .tga file extensions from anywhere in the _name, including image program parameters
|
||||
idStrStatic< MAX_OSPATH > name = _name;
|
||||
name.Replace( ".tga", "" );
|
||||
idStrList imageFormats = { ".tga", ".jpg", ".png", ".exr", ".hdr" };
|
||||
for( auto& ext : imageFormats )
|
||||
{
|
||||
name.Replace( ext, "" );
|
||||
}
|
||||
name.BackSlashesToSlashes();
|
||||
|
||||
//
|
||||
|
@ -598,7 +606,6 @@ idImageManager::GetImage
|
|||
*/
|
||||
idImage* idImageManager::GetImage( const char* _name ) const
|
||||
{
|
||||
|
||||
if( !_name || !_name[0] || idStr::Icmp( _name, "default" ) == 0 || idStr::Icmp( _name, "_default" ) == 0 )
|
||||
{
|
||||
declManager->MediaPrint( "DEFAULTED\n" );
|
||||
|
@ -607,7 +614,11 @@ idImage* idImageManager::GetImage( const char* _name ) const
|
|||
|
||||
// strip any .tga file extensions from anywhere in the _name, including image program parameters
|
||||
idStr name = _name;
|
||||
name.Replace( ".tga", "" );
|
||||
idStrList imageFormats = { ".tga", ".jpg", ".png", ".exr", ".hdr" };
|
||||
for( auto& ext : imageFormats )
|
||||
{
|
||||
name.Replace( ext, "" );
|
||||
}
|
||||
name.BackSlashesToSlashes();
|
||||
|
||||
//
|
||||
|
@ -759,6 +770,7 @@ void idImageManager::Init()
|
|||
CreateIntrinsicImages();
|
||||
|
||||
cmdSystem->AddCommand( "reloadImages", R_ReloadImages_f, CMD_FL_RENDERER, "reloads images" );
|
||||
cmdSystem->AddCommand( "cacheGlobalIlluminationData", CacheGlobalIlluminationData_f, CMD_FL_RENDERER, "turn env/maps/*.exr files into .bimage files" );
|
||||
#endif
|
||||
cmdSystem->AddCommand( "listImages", R_ListImages_f, CMD_FL_RENDERER, "lists images" );
|
||||
cmdSystem->AddCommand( "combineCubeImages", R_CombineCubeImages_f, CMD_FL_RENDERER, "combines six images for roq compression" );
|
||||
|
@ -1097,3 +1109,52 @@ void idImageManager::LoadDeferredImages( nvrhi::ICommandList* _commandList )
|
|||
|
||||
globalImages->imagesToLoad.Clear();
|
||||
}
|
||||
|
||||
#include "CmdlineProgressbar.h"
|
||||
|
||||
#if !defined( DMAP )
|
||||
void idImageManager::CacheGlobalIlluminationData_f( const idCmdArgs& args )
|
||||
{
|
||||
common->Printf( "Caching images to bimage files...\n" );
|
||||
|
||||
int start = Sys_Milliseconds();
|
||||
globalImages->preloadingMapImages = true;
|
||||
globalImages->cacheImages = true;
|
||||
|
||||
idFileList* files = fileSystem->ListFilesTree( "env/maps", "*.exr", true );
|
||||
int numFiles = files->GetNumFiles();
|
||||
|
||||
CommandlineProgressBar progressBar( numFiles, renderSystem->GetWidth(), renderSystem->GetHeight() );
|
||||
progressBar.Start();
|
||||
|
||||
for( int i = 0; i < files->GetNumFiles(); i++ )
|
||||
{
|
||||
const char* filename = files->GetFile( i );
|
||||
|
||||
if( idStr::FindText( filename, "envprobe" ) != -1 )
|
||||
{
|
||||
if( idStr::FindText( filename, "_spec" ) != -1 )
|
||||
{
|
||||
globalImages->ImageFromFile( filename, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||
}
|
||||
else
|
||||
{
|
||||
globalImages->ImageFromFile( filename, TF_LINEAR, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||
}
|
||||
}
|
||||
else if( idStr::FindText( filename, "lightgrid" ) != -1 )
|
||||
{
|
||||
globalImages->ImageFromFile( filename, TF_LINEAR, TR_CLAMP, TD_R11G11B10F, CF_2D );
|
||||
}
|
||||
|
||||
progressBar.Increment( true );
|
||||
}
|
||||
fileSystem->FreeFileList( files );
|
||||
|
||||
int end = Sys_Milliseconds();
|
||||
common->Printf( "%05d images cached in %5.1f seconds\n", numFiles, ( end - start ) * 0.001 );
|
||||
common->Printf( "----------------------------------------\n" );
|
||||
globalImages->preloadingMapImages = false;
|
||||
globalImages->cacheImages = false;
|
||||
}
|
||||
#endif
|
|
@ -573,6 +573,7 @@ static void LoadEXR( const char* filename, unsigned char** pic, int* width, int*
|
|||
if( ret != 0 )
|
||||
{
|
||||
common->Error( "LoadEXR( %s ): %s\n", filename, err );
|
||||
FreeEXRErrorMessage( err );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -852,7 +853,7 @@ void R_WriteEXR( const char* filename, const void* rgba16f, int channelsPerPixel
|
|||
if( size == 0 )
|
||||
{
|
||||
common->Error( "R_WriteEXR( %s ): Save EXR err: %s\n", filename, err );
|
||||
|
||||
FreeEXRErrorMessage( err );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@ -905,14 +906,14 @@ static void LoadHDR( const char* filename, unsigned char** pic, int* width, int*
|
|||
|
||||
int32 numChannels;
|
||||
|
||||
float* rgba = stbi_loadf_from_memory( ( stbi_uc const* ) fbuffer, fileSize, width, height, &numChannels, 0 );
|
||||
float* rgb = stbi_loadf_from_memory( ( stbi_uc const* ) fbuffer, fileSize, width, height, &numChannels, 0 );
|
||||
|
||||
if( numChannels != 3 )
|
||||
{
|
||||
common->Error( "LoadHDR( %s ): HDR has not 3 channels\n", filename );
|
||||
}
|
||||
|
||||
if( rgba )
|
||||
if( rgb )
|
||||
{
|
||||
int32 pixelCount = *width * *height;
|
||||
byte* out = ( byte* )R_StaticAlloc( pixelCount * 4, TAG_IMAGE );
|
||||
|
@ -921,7 +922,7 @@ static void LoadHDR( const char* filename, unsigned char** pic, int* width, int*
|
|||
|
||||
// convert to packed R11G11B10F as uint32 for each pixel
|
||||
|
||||
const float* src = rgba;
|
||||
const float* src = rgb;
|
||||
byte* dst = out;
|
||||
for( int i = 0; i < pixelCount; i++ )
|
||||
{
|
||||
|
@ -936,11 +937,11 @@ static void LoadHDR( const char* filename, unsigned char** pic, int* width, int*
|
|||
uint32_t value = float3_to_r11g11b10f( p );
|
||||
*( uint32_t* )dst = value;
|
||||
|
||||
src += 4;
|
||||
src += 3;
|
||||
dst += 4;
|
||||
}
|
||||
|
||||
free( rgba );
|
||||
free( rgb );
|
||||
}
|
||||
|
||||
Mem_Free( ( void* )fbuffer );
|
||||
|
@ -1268,6 +1269,52 @@ bool R_LoadCubeImages( const char* imgName, cubeFiles_t extensions, byte* pics[6
|
|||
return true;
|
||||
}
|
||||
|
||||
if( extensions == CF_PANORAMA )
|
||||
{
|
||||
ID_TIME_T thisTime;
|
||||
byte* thisPic[1];
|
||||
thisPic[0] = nullptr;
|
||||
|
||||
if( pics )
|
||||
{
|
||||
R_LoadImageProgram( imgName, thisPic, &width, &height, &thisTime );
|
||||
}
|
||||
else
|
||||
{
|
||||
// load just the timestamps
|
||||
R_LoadImageProgram( imgName, nullptr, &width, &height, &thisTime );
|
||||
}
|
||||
|
||||
|
||||
if( thisTime == FILE_NOT_FOUND_TIMESTAMP )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( timestamp )
|
||||
{
|
||||
if( thisTime > *timestamp )
|
||||
{
|
||||
*timestamp = thisTime;
|
||||
}
|
||||
}
|
||||
|
||||
if( pics )
|
||||
{
|
||||
cubeMapSize = 1024;
|
||||
*outSize = cubeMapSize;
|
||||
|
||||
for( int i = 0; i < 6; i++ )
|
||||
{
|
||||
pics[i] = R_GenerateCubeMapSideFromPanoramaImage( thisPic[0], width, height, cubeMapSize, i );
|
||||
}
|
||||
|
||||
R_StaticFree( thisPic[0] );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
for( i = 0 ; i < 6 ; i++ )
|
||||
{
|
||||
idStr::snPrintf( fullName, sizeof( fullName ), "%s%s", imgName, sides[i] );
|
||||
|
|
|
@ -1248,6 +1248,41 @@ CONSOLE_COMMAND( makeImageHeader, "load an image and turn it into a .h file", NU
|
|||
Mem_Free( buffer );
|
||||
}
|
||||
|
||||
class idSortColors : public idSort_Quick< idVec3, idSortColors >
|
||||
{
|
||||
public:
|
||||
int SizeMetric( const idVec3& v ) const
|
||||
{
|
||||
return v.x * v.x + v.y * v.y + v.z * v.z;
|
||||
}
|
||||
int Compare( const idVec3& a, const idVec3& b ) const
|
||||
{
|
||||
//idVec3 diff = b - a;
|
||||
//return SizeMetric( diff );
|
||||
|
||||
return SizeMetric( a ) - SizeMetric( b );
|
||||
}
|
||||
};
|
||||
|
||||
idVec3 Average( const idList<idVec3>& colors )
|
||||
{
|
||||
idVec3 avg = vec3_zero;
|
||||
|
||||
int numColors = colors.Num();
|
||||
for( int i = 0; i < numColors; i++ )
|
||||
{
|
||||
avg += colors[i];
|
||||
}
|
||||
avg *= ( 1.0f / numColors );
|
||||
|
||||
return avg;
|
||||
}
|
||||
|
||||
idVec3 Median( const idList<idVec3>& sortedPal )
|
||||
{
|
||||
return sortedPal[sortedPal.Num() / 2];
|
||||
}
|
||||
|
||||
CONSOLE_COMMAND( makePaletteHeader, "load a .pal palette, build an image from it and turn it into a .h file", NULL )
|
||||
{
|
||||
if( args.Argc() < 2 )
|
||||
|
@ -1280,17 +1315,66 @@ CONSOLE_COMMAND( makePaletteHeader, "load a .pal palette, build an image from it
|
|||
|
||||
int numColors = src.ParseInt();
|
||||
|
||||
//idList<id
|
||||
byte rgb[3];
|
||||
idList<idVec3> colors;
|
||||
colors.AssureSize( numColors );
|
||||
|
||||
idVec3 rgb;
|
||||
for( int i = 0; i < numColors; i++ )
|
||||
{
|
||||
rgb[0] = src.ParseInt();
|
||||
rgb[1] = src.ParseInt();
|
||||
rgb[2] = src.ParseInt();
|
||||
|
||||
idLib::Printf( "RGB( %d, %d, %d ),\n", rgb[0], rgb[1], rgb[2] );
|
||||
colors[ i ] = rgb;
|
||||
|
||||
//idLib::Printf( "RGB( %d, %d, %d ),\n", (int)rgb[0], (int)rgb[1], (int)rgb[2] );
|
||||
}
|
||||
|
||||
idLib::Printf( "// SORTED ============\n" );
|
||||
colors.SortWithTemplate( idSortColors() );
|
||||
|
||||
idLib::Printf( "const float3 palette[NUM_COLORS] = // %d\n{\n", numColors );
|
||||
for( int i = 0; i < numColors; i++ )
|
||||
{
|
||||
rgb = colors[ i ];
|
||||
idLib::Printf( "\tRGB( %d, %d, %d ),\n", ( int )rgb[0], ( int )rgb[1], ( int )rgb[2] );
|
||||
}
|
||||
idLib::Printf( "};\n\n" );
|
||||
|
||||
// calc the median absolute deviation
|
||||
idVec3 median = Median( colors );
|
||||
idList<idVec3> deviations;
|
||||
deviations.AssureSize( numColors );
|
||||
|
||||
for( int i = 0; i < numColors; i++ )
|
||||
{
|
||||
idVec3 diff = colors[i] - median;
|
||||
deviations[i].x = idMath::Fabs( diff.x );
|
||||
deviations[i].y = idMath::Fabs( diff.y );
|
||||
deviations[i].z = idMath::Fabs( diff.z );
|
||||
}
|
||||
|
||||
deviations.SortWithTemplate( idSortColors() );
|
||||
rgb = Median( deviations );
|
||||
|
||||
idLib::Printf( "const float3 medianAbsoluteDeviation = RGB( %d, %d, %d );\n", ( int )rgb[0], ( int )rgb[1], ( int )rgb[2] );
|
||||
|
||||
// calc the standard deviation
|
||||
idVec3 avg = Average( colors );
|
||||
|
||||
idVec3 deviation = vec3_zero;
|
||||
for( int i = 0; i < numColors; i++ )
|
||||
{
|
||||
idVec3 diff = colors[i] - avg;
|
||||
deviation.x += idMath::Fabs( diff.x );
|
||||
deviation.y += idMath::Fabs( diff.y );
|
||||
deviation.z += idMath::Fabs( diff.z );
|
||||
}
|
||||
deviation *= ( 1.0f / numColors );
|
||||
|
||||
rgb = deviation;
|
||||
idLib::Printf( "const float3 deviation = RGB( %d, %d, %d );\n", ( int )rgb[0], ( int )rgb[1], ( int )rgb[2] );
|
||||
|
||||
fileSystem->FreeFile( palBuffer );
|
||||
|
||||
filename.StripFileExtension();
|
||||
|
@ -1364,4 +1448,4 @@ CONSOLE_COMMAND( makePaletteHeader, "load a .pal palette, build an image from it
|
|||
|
||||
Mem_Free( buffer );
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,11 +156,11 @@ ID_INLINE void idImage::DeriveOpts()
|
|||
opts.format = FMT_DEPTH;
|
||||
break;
|
||||
|
||||
// sp begin
|
||||
// SP begin
|
||||
case TD_DEPTH_STENCIL:
|
||||
opts.format = FMT_DEPTH_STENCIL;
|
||||
break;
|
||||
// sp end
|
||||
// SP end
|
||||
|
||||
case TD_SHADOW_ARRAY:
|
||||
opts.format = FMT_SHADOW_ARRAY;
|
||||
|
@ -200,6 +200,7 @@ ID_INLINE void idImage::DeriveOpts()
|
|||
opts.format = FMT_DXT5;
|
||||
opts.colorFormat = CFM_YCOCG_DXT5;
|
||||
break;
|
||||
|
||||
case TD_SPECULAR:
|
||||
opts.gammaMips = true;
|
||||
opts.format = FMT_DXT1;
|
||||
|
@ -223,16 +224,19 @@ ID_INLINE void idImage::DeriveOpts()
|
|||
opts.format = FMT_DXT5;
|
||||
opts.colorFormat = CFM_DEFAULT;
|
||||
break;
|
||||
|
||||
case TD_BUMP:
|
||||
opts.format = FMT_DXT5;
|
||||
opts.colorFormat = CFM_NORMAL_DXT5;
|
||||
break;
|
||||
|
||||
case TD_FONT:
|
||||
opts.format = FMT_DXT1;
|
||||
opts.colorFormat = CFM_GREEN_ALPHA;
|
||||
opts.numLevels = 4; // We only support 4 levels because we align to 16 in the exporter
|
||||
opts.gammaMips = true;
|
||||
break;
|
||||
|
||||
case TD_LIGHT:
|
||||
// RB: TODO check binary format version
|
||||
// D3 BFG assets require RGB565 but it introduces color banding
|
||||
|
@ -240,16 +244,20 @@ ID_INLINE void idImage::DeriveOpts()
|
|||
opts.format = FMT_RGB565; //FMT_RGBA8;
|
||||
opts.gammaMips = true;
|
||||
break;
|
||||
|
||||
case TD_LOOKUP_TABLE_MONO:
|
||||
opts.format = FMT_INT8;
|
||||
break;
|
||||
|
||||
case TD_LOOKUP_TABLE_ALPHA:
|
||||
opts.format = FMT_ALPHA;
|
||||
break;
|
||||
|
||||
case TD_LOOKUP_TABLE_RGB1:
|
||||
case TD_LOOKUP_TABLE_RGBA:
|
||||
opts.format = FMT_RGBA8;
|
||||
break;
|
||||
|
||||
// motorsep 05-17-2015; added this for uncompressed cubemap/skybox textures
|
||||
case TD_HIGHQUALITY_CUBE:
|
||||
opts.colorFormat = CFM_DEFAULT;
|
||||
|
@ -261,6 +269,13 @@ ID_INLINE void idImage::DeriveOpts()
|
|||
opts.format = FMT_DXT5;
|
||||
opts.gammaMips = true;
|
||||
break;
|
||||
// motorsep end
|
||||
|
||||
case TD_HDRI:
|
||||
opts.format = FMT_R11G11B10F;
|
||||
//opts.numLevels = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( false );
|
||||
opts.format = FMT_RGBA8;
|
||||
|
@ -364,9 +379,6 @@ void idImage::GenerateImage( const byte* pic, int width, int height, textureFilt
|
|||
#if defined( USE_NVRHI ) && !defined( DMAP )
|
||||
if( commandList )
|
||||
{
|
||||
const nvrhi::FormatInfo& info = nvrhi::getFormatInfo( texture->getDesc().format );
|
||||
const int bytesPerBlock = info.bytesPerBlock;
|
||||
|
||||
commandList->beginTrackingTextureState( texture, nvrhi::AllSubresources, nvrhi::ResourceStates::Common );
|
||||
|
||||
for( int i = 0; i < im.NumImages(); i++ )
|
||||
|
@ -439,15 +451,8 @@ void idImage::GenerateCubeImage( const byte* pic[6], int size, textureFilter_t f
|
|||
AllocImage();
|
||||
|
||||
#if defined( USE_NVRHI ) && !defined( DMAP )
|
||||
int numChannels = 4;
|
||||
int bytesPerPixel = numChannels;
|
||||
if( opts.format == FMT_ALPHA || opts.format == FMT_DXT1 || opts.format == FMT_INT8 || opts.format == FMT_R8 )
|
||||
{
|
||||
bytesPerPixel = 1;
|
||||
}
|
||||
|
||||
const nvrhi::FormatInfo& info = nvrhi::getFormatInfo( texture->getDesc().format );
|
||||
bytesPerPixel = info.bytesPerBlock;
|
||||
//const nvrhi::FormatInfo& info = nvrhi::getFormatInfo( texture->getDesc().format );
|
||||
//bytesPerPixel = info.bytesPerBlock;
|
||||
|
||||
commandList->beginTrackingTextureState( texture, nvrhi::AllSubresources, nvrhi::ResourceStates::Common );
|
||||
|
||||
|
@ -555,9 +560,6 @@ void idImage::ActuallyLoadImage( bool fromBackEnd, nvrhi::ICommandList* commandL
|
|||
// RB: the following does not load the source images from disk because pic is NULL
|
||||
// but it tries to get the timestamp to see if we have a newer file than the one in the compressed .bimage
|
||||
|
||||
// TODO also check for alternative names like .png suffices or _rmao.png or even _rmaod.png files
|
||||
// to support the PBR code path
|
||||
|
||||
if( com_productionMode.GetInteger() != 0 )
|
||||
{
|
||||
sourceFileTime = FILE_NOT_FOUND_TIMESTAMP;
|
||||
|
@ -574,7 +576,7 @@ void idImage::ActuallyLoadImage( bool fromBackEnd, nvrhi::ICommandList* commandL
|
|||
{
|
||||
opts.textureType = TT_2D_ARRAY;
|
||||
}
|
||||
else if( cubeFiles == CF_NATIVE || cubeFiles == CF_CAMERA || cubeFiles == CF_QUAKE1 || cubeFiles == CF_SINGLE )
|
||||
else if( cubeFiles == CF_NATIVE || cubeFiles == CF_CAMERA || cubeFiles == CF_QUAKE1 || cubeFiles == CF_SINGLE || cubeFiles == CF_PANORAMA )
|
||||
{
|
||||
opts.textureType = TT_CUBIC;
|
||||
repeat = TR_CLAMP;
|
||||
|
@ -606,6 +608,12 @@ void idImage::ActuallyLoadImage( bool fromBackEnd, nvrhi::ICommandList* commandL
|
|||
idStrStatic< MAX_OSPATH > generatedName = GetName();
|
||||
GetGeneratedName( generatedName, usage, cubeFiles );
|
||||
|
||||
//if( generatedName.Find( "textures/base_floor/a_stairs_d02", false ) >= 0 )
|
||||
//{
|
||||
// #924
|
||||
//int c = 1;
|
||||
//}
|
||||
|
||||
// RB: try to load the .bimage and skip if sourceFileTime is newer
|
||||
idBinaryImage im( generatedName );
|
||||
binaryFileTime = im.LoadFromGeneratedFile( sourceFileTime );
|
||||
|
@ -700,10 +708,6 @@ void idImage::ActuallyLoadImage( bool fromBackEnd, nvrhi::ICommandList* commandL
|
|||
binarizeReason = va( "binarize: binary file not found '%s'", generatedName.c_str() );
|
||||
}
|
||||
else if( header.colorFormat != opts.colorFormat )
|
||||
{
|
||||
binarizeReason = va( "binarize: mismatch color format '%s'", generatedName.c_str() );
|
||||
}
|
||||
else if( header.colorFormat != opts.colorFormat )
|
||||
{
|
||||
binarizeReason = va( "binarize: mismatched color format '%s'", generatedName.c_str() );
|
||||
}
|
||||
|
@ -714,7 +718,7 @@ void idImage::ActuallyLoadImage( bool fromBackEnd, nvrhi::ICommandList* commandL
|
|||
//else if( toolUsage )
|
||||
// binarizeReason = va( "binarize: tool usage '%s'", generatedName.c_str() );
|
||||
|
||||
if( cubeFiles == CF_NATIVE || cubeFiles == CF_CAMERA || cubeFiles == CF_QUAKE1 || cubeFiles == CF_SINGLE )
|
||||
if( cubeFiles == CF_NATIVE || cubeFiles == CF_CAMERA || cubeFiles == CF_QUAKE1 || cubeFiles == CF_SINGLE || cubeFiles == CF_PANORAMA )
|
||||
{
|
||||
int size;
|
||||
byte* pics[6];
|
||||
|
@ -737,7 +741,11 @@ void idImage::ActuallyLoadImage( bool fromBackEnd, nvrhi::ICommandList* commandL
|
|||
DeriveOpts();
|
||||
|
||||
// foresthale 2014-05-30: give a nice progress display when binarizing
|
||||
commonLocal.LoadPacifierBinarizeFilename( generatedName.c_str(), binarizeReason.c_str() );
|
||||
if( !globalImages->cacheImages )
|
||||
{
|
||||
commonLocal.LoadPacifierBinarizeFilename( generatedName.c_str(), binarizeReason.c_str() );
|
||||
}
|
||||
|
||||
if( opts.numLevels > 1 )
|
||||
{
|
||||
commonLocal.LoadPacifierBinarizeProgressTotal( opts.width * opts.width * 6 * 4 / 3 );
|
||||
|
@ -796,8 +804,6 @@ void idImage::ActuallyLoadImage( bool fromBackEnd, nvrhi::ICommandList* commandL
|
|||
memset( clear.Ptr(), 0, clear.Size() );
|
||||
|
||||
#if defined( USE_NVRHI ) && !defined( DMAP )
|
||||
const nvrhi::FormatInfo& info = nvrhi::getFormatInfo( texture->getDesc().format );
|
||||
|
||||
commandList->beginTrackingTextureState( texture, nvrhi::AllSubresources, nvrhi::ResourceStates::Common );
|
||||
for( int level = 0; level < opts.numLevels; level++ )
|
||||
{
|
||||
|
@ -832,14 +838,21 @@ void idImage::ActuallyLoadImage( bool fromBackEnd, nvrhi::ICommandList* commandL
|
|||
// RB: convert to compressed DXT or whatever choosen target format
|
||||
if( cubeFiles == CF_2D_PACKED_MIPCHAIN )
|
||||
{
|
||||
commonLocal.LoadPacifierBinarizeFilename( generatedName.c_str(), binarizeReason.c_str() );
|
||||
if( !globalImages->cacheImages )
|
||||
{
|
||||
commonLocal.LoadPacifierBinarizeFilename( generatedName.c_str(), binarizeReason.c_str() );
|
||||
}
|
||||
commonLocal.LoadPacifierBinarizeProgressTotal( width * opts.height );
|
||||
|
||||
im.Load2DAtlasMipchainFromMemory( width, opts.height, pic, opts.numLevels, opts.format, opts.colorFormat );
|
||||
}
|
||||
else
|
||||
{
|
||||
commonLocal.LoadPacifierBinarizeFilename( generatedName.c_str(), binarizeReason.c_str() );
|
||||
if( !globalImages->cacheImages )
|
||||
{
|
||||
commonLocal.LoadPacifierBinarizeFilename( generatedName.c_str(), binarizeReason.c_str() );
|
||||
}
|
||||
|
||||
if( opts.numLevels > 1 )
|
||||
{
|
||||
commonLocal.LoadPacifierBinarizeProgressTotal( opts.width * opts.height * 4 / 3 );
|
||||
|
@ -870,9 +883,6 @@ void idImage::ActuallyLoadImage( bool fromBackEnd, nvrhi::ICommandList* commandL
|
|||
AllocImage();
|
||||
|
||||
#if defined( USE_NVRHI ) && !defined( DMAP )
|
||||
const nvrhi::FormatInfo& info = nvrhi::getFormatInfo( texture->getDesc().format );
|
||||
const int bytesPerPixel = info.bytesPerBlock / info.blockSize;
|
||||
|
||||
commandList->beginTrackingTextureState( texture, nvrhi::AllSubresources, nvrhi::ResourceStates::Common );
|
||||
|
||||
for( int i = 0; i < im.NumImages(); i++ )
|
||||
|
@ -880,45 +890,7 @@ void idImage::ActuallyLoadImage( bool fromBackEnd, nvrhi::ICommandList* commandL
|
|||
const bimageImage_t& img = im.GetImageHeader( i );
|
||||
const byte* pic = im.GetImageData( i );
|
||||
|
||||
#if 0
|
||||
if( opts.format == FMT_RGB565 )
|
||||
{
|
||||
int bufferW = img.width;
|
||||
int bufferH = img.height;
|
||||
|
||||
if( IsCompressed() )
|
||||
{
|
||||
bufferW = ( img.width + 3 ) & ~3;
|
||||
bufferH = ( img.height + 3 ) & ~3;
|
||||
}
|
||||
|
||||
int size = bufferW * bufferH * BitsForFormat( opts.format ) / 8;
|
||||
|
||||
byte* data = ( byte* )Mem_Alloc16( size, TAG_IMAGE );
|
||||
memcpy( data, pic, size );
|
||||
|
||||
byte* imgData = ( byte* )pic;
|
||||
for( int j = 0; j < size; j += 2 )
|
||||
{
|
||||
data[i] = imgData[i + 1];
|
||||
data[i + 1] = imgData[i];
|
||||
}
|
||||
|
||||
commandList->writeTexture( texture, img.destZ, img.level, data, GetRowPitch( opts.format, img.width ) );
|
||||
|
||||
Mem_Free16( data );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
int bufferW = img.width;
|
||||
if( IsCompressed() )
|
||||
{
|
||||
bufferW = ( img.width + 3 ) & ~3;
|
||||
}
|
||||
|
||||
commandList->writeTexture( texture, img.destZ, img.level, pic, GetRowPitch( opts.format, img.width ) );
|
||||
}
|
||||
commandList->writeTexture( texture, img.destZ, img.level, pic, GetRowPitch( opts.format, img.width ) );
|
||||
}
|
||||
commandList->setPermanentTextureState( texture, nvrhi::ResourceStates::ShaderResource );
|
||||
commandList->commitBarriers();
|
||||
|
@ -983,26 +955,10 @@ void idImage::UploadScratch( const byte* data, int cols, int rows, nvrhi::IComma
|
|||
}
|
||||
|
||||
#if defined( USE_NVRHI )
|
||||
int numChannels = 4;
|
||||
int bytesPerPixel = numChannels;
|
||||
if( opts.format == FMT_ALPHA || opts.format == FMT_DXT1 || opts.format == FMT_INT8 || opts.format == FMT_R8 )
|
||||
{
|
||||
bytesPerPixel = 1;
|
||||
}
|
||||
|
||||
const nvrhi::FormatInfo& info = nvrhi::getFormatInfo( texture->getDesc().format );
|
||||
bytesPerPixel = info.bytesPerBlock;
|
||||
|
||||
SetSamplerState( TF_LINEAR, TR_CLAMP );
|
||||
|
||||
commandList->beginTrackingTextureState( texture, nvrhi::AllSubresources, nvrhi::ResourceStates::Common );
|
||||
|
||||
int bufferW = opts.width;
|
||||
if( IsCompressed() )
|
||||
{
|
||||
bufferW = ( opts.width + 3 ) & ~3;
|
||||
}
|
||||
|
||||
for( int i = 0; i < 6; i++ )
|
||||
{
|
||||
commandList->writeTexture( texture, i, 0, pic[i], GetRowPitch( opts.format, opts.width ) );
|
||||
|
@ -1032,24 +988,8 @@ void idImage::UploadScratch( const byte* data, int cols, int rows, nvrhi::IComma
|
|||
|
||||
if( data != NULL && commandList != NULL )
|
||||
{
|
||||
int numChannels = 4;
|
||||
int bytesPerPixel = numChannels;
|
||||
if( opts.format == FMT_ALPHA || opts.format == FMT_DXT1 || opts.format == FMT_INT8 || opts.format == FMT_R8 || opts.format == FMT_LUM8 )
|
||||
{
|
||||
bytesPerPixel = 1;
|
||||
}
|
||||
|
||||
const nvrhi::FormatInfo& info = nvrhi::getFormatInfo( texture->getDesc().format );
|
||||
bytesPerPixel = info.bytesPerBlock;
|
||||
|
||||
SetSamplerState( TF_LINEAR, TR_REPEAT );
|
||||
|
||||
int bufferW = opts.width;
|
||||
if( IsCompressed() )
|
||||
{
|
||||
bufferW = ( opts.width + 3 ) & ~3;
|
||||
}
|
||||
|
||||
commandList->beginTrackingTextureState( texture, nvrhi::AllSubresources, nvrhi::ResourceStates::Common );
|
||||
|
||||
commandList->writeTexture( texture, 0, 0, data, GetRowPitch( opts.format, opts.width ) );
|
||||
|
@ -1242,7 +1182,7 @@ void idImage::Reload( bool force, nvrhi::ICommandList* commandList )
|
|||
if( !force )
|
||||
{
|
||||
ID_TIME_T current;
|
||||
if( cubeFiles == CF_NATIVE || cubeFiles == CF_CAMERA || cubeFiles == CF_QUAKE1 || cubeFiles == CF_SINGLE )
|
||||
if( cubeFiles == CF_NATIVE || cubeFiles == CF_CAMERA || cubeFiles == CF_QUAKE1 || cubeFiles == CF_SINGLE || cubeFiles == CF_PANORAMA )
|
||||
{
|
||||
R_LoadCubeImages( imgName, cubeFiles, NULL, NULL, ¤t );
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2021 Robert Beckebans
|
||||
Copyright (C) 2021-2025 Robert Beckebans
|
||||
Copyright (C) 2021 Stephen Pridham
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
@ -33,6 +33,8 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "RenderCommon.h"
|
||||
|
||||
#include "../libs/mesa/format_r11g11b10f.h"
|
||||
|
||||
/*
|
||||
================
|
||||
R_ResampleTexture
|
||||
|
@ -463,6 +465,152 @@ byte* R_MipMap( const byte* in, int width, int height )
|
|||
return out;
|
||||
}
|
||||
|
||||
// RB begin
|
||||
byte* R_MipMapR11G11B10F( const byte* in, int width, int height )
|
||||
{
|
||||
int i, j;
|
||||
const byte* in_p;
|
||||
byte* out, *out_p;
|
||||
int row;
|
||||
int newWidth, newHeight;
|
||||
|
||||
if( width < 1 || height < 1 || ( width + height == 2 ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
row = width * 4;
|
||||
|
||||
newWidth = width >> 1;
|
||||
newHeight = height >> 1;
|
||||
if( !newWidth )
|
||||
{
|
||||
newWidth = 1;
|
||||
}
|
||||
if( !newHeight )
|
||||
{
|
||||
newHeight = 1;
|
||||
}
|
||||
out = ( byte* )R_StaticAlloc( newWidth * newHeight * 4, TAG_IMAGE );
|
||||
out_p = out;
|
||||
|
||||
in_p = in;
|
||||
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint32 i;
|
||||
byte b[4];
|
||||
} convert_t;
|
||||
|
||||
if( width == 0 || height == 0 )
|
||||
{
|
||||
width += height; // get largest
|
||||
for( i = 0 ; i < width ; i++, out_p += 4, in_p += 8 )
|
||||
{
|
||||
convert_t p1;
|
||||
p1.b[0] = in_p[0];
|
||||
p1.b[1] = in_p[1];
|
||||
p1.b[2] = in_p[2];
|
||||
p1.b[3] = in_p[3];
|
||||
|
||||
convert_t p2;
|
||||
p2.b[0] = in_p[4];
|
||||
p2.b[1] = in_p[5];
|
||||
p2.b[2] = in_p[6];
|
||||
p2.b[3] = in_p[7];
|
||||
|
||||
float c1[3];
|
||||
r11g11b10f_to_float3( p1.i, c1 );
|
||||
|
||||
float c2[3];
|
||||
r11g11b10f_to_float3( p2.i, c2 );
|
||||
|
||||
float rgb[3];
|
||||
rgb[0] = ( c1[0] + c2[0] ) * 0.5f;
|
||||
rgb[1] = ( c1[1] + c2[1] ) * 0.5f;
|
||||
rgb[2] = ( c1[2] + c2[2] ) * 0.5f;
|
||||
|
||||
p1.i = float3_to_r11g11b10f( rgb );
|
||||
|
||||
out_p[0] = p1.b[0];
|
||||
out_p[1] = p1.b[1];
|
||||
out_p[2] = p1.b[2];
|
||||
out_p[3] = p1.b[3];
|
||||
|
||||
//out_p[0] = ( in_p[0] + in_p[4] ) >> 1;
|
||||
//out_p[1] = ( in_p[1] + in_p[5] ) >> 1;
|
||||
//out_p[2] = ( in_p[2] + in_p[6] ) >> 1;
|
||||
//out_p[3] = ( in_p[3] + in_p[7] ) >> 1;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
for( i = 0 ; i < height ; i++, in_p += row )
|
||||
{
|
||||
for( j = 0 ; j < width ; j++, out_p += 4, in_p += 8 )
|
||||
{
|
||||
convert_t p1;
|
||||
p1.b[0] = in_p[0];
|
||||
p1.b[1] = in_p[1];
|
||||
p1.b[2] = in_p[2];
|
||||
p1.b[3] = in_p[3];
|
||||
|
||||
convert_t p2;
|
||||
p2.b[0] = in_p[4];
|
||||
p2.b[1] = in_p[5];
|
||||
p2.b[2] = in_p[6];
|
||||
p2.b[3] = in_p[7];
|
||||
|
||||
convert_t p3;
|
||||
p3.b[0] = in_p[row + 0];
|
||||
p3.b[1] = in_p[row + 1];
|
||||
p3.b[2] = in_p[row + 2];
|
||||
p3.b[3] = in_p[row + 3];
|
||||
|
||||
convert_t p4;
|
||||
p4.b[0] = in_p[row + 4];
|
||||
p4.b[1] = in_p[row + 5];
|
||||
p4.b[2] = in_p[row + 6];
|
||||
p4.b[3] = in_p[row + 7];
|
||||
|
||||
float c1[3];
|
||||
r11g11b10f_to_float3( p1.i, c1 );
|
||||
|
||||
float c2[3];
|
||||
r11g11b10f_to_float3( p2.i, c2 );
|
||||
|
||||
float c3[3];
|
||||
r11g11b10f_to_float3( p3.i, c3 );
|
||||
|
||||
float c4[3];
|
||||
r11g11b10f_to_float3( p4.i, c4 );
|
||||
|
||||
float rgb[3];
|
||||
rgb[0] = ( c1[0] + c2[0] + c3[0] + c4[0] ) * 0.25f;
|
||||
rgb[1] = ( c1[1] + c2[1] + c3[1] + c4[1] ) * 0.25f;
|
||||
rgb[2] = ( c1[2] + c2[2] + c3[2] + c4[2] ) * 0.25f;
|
||||
|
||||
p1.i = float3_to_r11g11b10f( rgb );
|
||||
|
||||
out_p[0] = p1.b[0];
|
||||
out_p[1] = p1.b[1];
|
||||
out_p[2] = p1.b[2];
|
||||
out_p[3] = p1.b[3];
|
||||
|
||||
//out_p[0] = ( in_p[0] + in_p[4] + in_p[row + 0] + in_p[row + 4] ) >> 2;
|
||||
//out_p[1] = ( in_p[1] + in_p[5] + in_p[row + 1] + in_p[row + 5] ) >> 2;
|
||||
//out_p[2] = ( in_p[2] + in_p[6] + in_p[row + 2] + in_p[row + 6] ) >> 2;
|
||||
//out_p[3] = ( in_p[3] + in_p[7] + in_p[row + 3] + in_p[row + 7] ) >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
// RB end
|
||||
|
||||
/*
|
||||
==================
|
||||
R_BlendOverTexture
|
||||
|
@ -631,8 +779,7 @@ int R_CalculateUsedAtlasPixels( int dimensions )
|
|||
}
|
||||
|
||||
// SP begin
|
||||
|
||||
byte* R_GenerateCubeMapSideFromSingleImage( byte* data, int srcWidth, int srcHeight, int size, int side )
|
||||
byte* R_GenerateCubeMapSideFromSingleImage( const byte* in, int srcWidth, int srcHeight, int size, int side )
|
||||
{
|
||||
size_t x = 0, y = 0;
|
||||
switch( side )
|
||||
|
@ -689,7 +836,7 @@ byte* R_GenerateCubeMapSideFromSingleImage( byte* data, int srcWidth, int srcHei
|
|||
const size_t copySize = ( size_t )size * ( size_t )size * 4;
|
||||
byte* out = ( byte* )R_StaticAlloc( copySize, TAG_IMAGE );
|
||||
uint32_t* out_p = ( uint32_t* )out;
|
||||
const uint32_t* in_p = ( uint32_t* )data + x + y * srcWidth;
|
||||
const uint32_t* in_p = ( uint32_t* )in + x + y * srcWidth;
|
||||
|
||||
for( int j = 0; j < size; j++ )
|
||||
{
|
||||
|
@ -701,5 +848,321 @@ byte* R_GenerateCubeMapSideFromSingleImage( byte* data, int srcWidth, int srcHei
|
|||
|
||||
return out;
|
||||
}
|
||||
|
||||
// SP end
|
||||
|
||||
|
||||
// RB: ripped from cmft utils by Dario Manesku
|
||||
/*
|
||||
* Copyright 2014-2015 Dario Manesku. All rights reserved.
|
||||
* License: http://www.opensource.org/licenses/BSD-2-Clause
|
||||
*/
|
||||
///
|
||||
///
|
||||
/// +----------+
|
||||
/// | +---->+x |
|
||||
/// | | |
|
||||
/// | | +y |
|
||||
/// |+z 2 |
|
||||
/// +----------+----------+----------+----------+
|
||||
/// | +---->+z | +---->+x | +---->-z | +---->-x |
|
||||
/// | | | | | | | | |
|
||||
/// | | -x | | +z | | +x | | -z |
|
||||
/// |-y 1 |-y 4 |-y 0 |-y 5 |
|
||||
/// +----------+----------+----------+----------+
|
||||
/// | +---->+x |
|
||||
/// | | |
|
||||
/// | | -y |
|
||||
/// |-z 3 |
|
||||
/// +----------+
|
||||
///
|
||||
static const float s_faceUvVectors[6][3][3] =
|
||||
{
|
||||
{
|
||||
// +x face
|
||||
{ 0.0f, 0.0f, -1.0f }, // u -> -z
|
||||
{ 0.0f, -1.0f, 0.0f }, // v -> -y
|
||||
{ 1.0f, 0.0f, 0.0f }, // +x face
|
||||
},
|
||||
{
|
||||
// -x face
|
||||
{ 0.0f, 0.0f, 1.0f }, // u -> +z
|
||||
{ 0.0f, -1.0f, 0.0f }, // v -> -y
|
||||
{ -1.0f, 0.0f, 0.0f }, // -x face
|
||||
},
|
||||
{
|
||||
// +y face
|
||||
{ 1.0f, 0.0f, 0.0f }, // u -> +x
|
||||
{ 0.0f, 0.0f, 1.0f }, // v -> +z
|
||||
{ 0.0f, 1.0f, 0.0f }, // +y face
|
||||
},
|
||||
{
|
||||
// -y face
|
||||
{ 1.0f, 0.0f, 0.0f }, // u -> +x
|
||||
{ 0.0f, 0.0f, -1.0f }, // v -> -z
|
||||
{ 0.0f, -1.0f, 0.0f }, // -y face
|
||||
},
|
||||
{
|
||||
// +z face
|
||||
{ 1.0f, 0.0f, 0.0f }, // u -> +x
|
||||
{ 0.0f, -1.0f, 0.0f }, // v -> -y
|
||||
{ 0.0f, 0.0f, 1.0f }, // +z face
|
||||
},
|
||||
{
|
||||
// -z face
|
||||
{ -1.0f, 0.0f, 0.0f }, // u -> -x
|
||||
{ 0.0f, -1.0f, 0.0f }, // v -> -y
|
||||
{ 0.0f, 0.0f, -1.0f }, // -z face
|
||||
}
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CMFT_FACE_POS_X = 0,
|
||||
CMFT_FACE_NEG_X = 1,
|
||||
CMFT_FACE_POS_Y = 2,
|
||||
CMFT_FACE_NEG_Y = 3,
|
||||
CMFT_FACE_POS_Z = 4,
|
||||
CMFT_FACE_NEG_Z = 5,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CMFT_EDGE_LEFT = 0,
|
||||
CMFT_EDGE_RIGHT = 1,
|
||||
CMFT_EDGE_TOP = 2,
|
||||
CMFT_EDGE_BOTTOM = 3,
|
||||
};
|
||||
|
||||
///
|
||||
/// --> U _____
|
||||
/// | | |
|
||||
/// v | +Y |
|
||||
/// V _____|_____|_____ _____
|
||||
/// | | | | |
|
||||
/// | -X | +Z | +X | -Z |
|
||||
/// |_____|_____|_____|_____|
|
||||
/// | |
|
||||
/// | -Y |
|
||||
/// |_____|
|
||||
///
|
||||
/// Neighbour faces in order: left, right, top, bottom.
|
||||
/// FaceEdge is the edge that belongs to the neighbour face.
|
||||
static const struct CubeFaceNeighbour
|
||||
{
|
||||
uint8_t m_faceIdx;
|
||||
uint8_t m_faceEdge;
|
||||
} s_cubeFaceNeighbours[6][4] =
|
||||
{
|
||||
{
|
||||
//POS_X
|
||||
{ CMFT_FACE_POS_Z, CMFT_EDGE_RIGHT },
|
||||
{ CMFT_FACE_NEG_Z, CMFT_EDGE_LEFT },
|
||||
{ CMFT_FACE_POS_Y, CMFT_EDGE_RIGHT },
|
||||
{ CMFT_FACE_NEG_Y, CMFT_EDGE_RIGHT },
|
||||
},
|
||||
{
|
||||
//NEG_X
|
||||
{ CMFT_FACE_NEG_Z, CMFT_EDGE_RIGHT },
|
||||
{ CMFT_FACE_POS_Z, CMFT_EDGE_LEFT },
|
||||
{ CMFT_FACE_POS_Y, CMFT_EDGE_LEFT },
|
||||
{ CMFT_FACE_NEG_Y, CMFT_EDGE_LEFT },
|
||||
},
|
||||
{
|
||||
//POS_Y
|
||||
{ CMFT_FACE_NEG_X, CMFT_EDGE_TOP },
|
||||
{ CMFT_FACE_POS_X, CMFT_EDGE_TOP },
|
||||
{ CMFT_FACE_NEG_Z, CMFT_EDGE_TOP },
|
||||
{ CMFT_FACE_POS_Z, CMFT_EDGE_TOP },
|
||||
},
|
||||
{
|
||||
//NEG_Y
|
||||
{ CMFT_FACE_NEG_X, CMFT_EDGE_BOTTOM },
|
||||
{ CMFT_FACE_POS_X, CMFT_EDGE_BOTTOM },
|
||||
{ CMFT_FACE_POS_Z, CMFT_EDGE_BOTTOM },
|
||||
{ CMFT_FACE_NEG_Z, CMFT_EDGE_BOTTOM },
|
||||
},
|
||||
{
|
||||
//POS_Z
|
||||
{ CMFT_FACE_NEG_X, CMFT_EDGE_RIGHT },
|
||||
{ CMFT_FACE_POS_X, CMFT_EDGE_LEFT },
|
||||
{ CMFT_FACE_POS_Y, CMFT_EDGE_BOTTOM },
|
||||
{ CMFT_FACE_NEG_Y, CMFT_EDGE_TOP },
|
||||
},
|
||||
{
|
||||
//NEG_Z
|
||||
{ CMFT_FACE_POS_X, CMFT_EDGE_RIGHT },
|
||||
{ CMFT_FACE_NEG_X, CMFT_EDGE_LEFT },
|
||||
{ CMFT_FACE_POS_Y, CMFT_EDGE_TOP },
|
||||
{ CMFT_FACE_NEG_Y, CMFT_EDGE_BOTTOM },
|
||||
}
|
||||
};
|
||||
|
||||
/// _u and _v should be center adressing and in [-1.0+invSize..1.0-invSize] range.
|
||||
static inline void TexelCoordToVec( float* _out3f, float _u, float _v, uint8_t _faceId )
|
||||
{
|
||||
// out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
|
||||
_out3f[0] = s_faceUvVectors[_faceId][0][0] * _u + s_faceUvVectors[_faceId][1][0] * _v + s_faceUvVectors[_faceId][2][0];
|
||||
_out3f[1] = s_faceUvVectors[_faceId][0][1] * _u + s_faceUvVectors[_faceId][1][1] * _v + s_faceUvVectors[_faceId][2][1];
|
||||
_out3f[2] = s_faceUvVectors[_faceId][0][2] * _u + s_faceUvVectors[_faceId][1][2] * _v + s_faceUvVectors[_faceId][2][2];
|
||||
|
||||
// Normalize.
|
||||
const float invLen = 1.0f / sqrtf( _out3f[0] * _out3f[0] + _out3f[1] * _out3f[1] + _out3f[2] * _out3f[2] );
|
||||
_out3f[0] *= invLen;
|
||||
_out3f[1] *= invLen;
|
||||
_out3f[2] *= invLen;
|
||||
}
|
||||
|
||||
/// Notice: _faceSize should not be equal to one!
|
||||
static inline float WarpFixupFactor( float _faceSize )
|
||||
{
|
||||
// Edge fixup.
|
||||
// Based on Nvtt : http://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvtt/CubeSurface.cpp
|
||||
if( _faceSize == 1.0f )
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
const float fs = _faceSize;
|
||||
const float fsmo = fs - 1.0f;
|
||||
return ( fs * fs ) / ( fsmo * fsmo * fsmo );
|
||||
}
|
||||
|
||||
/// _u and _v should be center adressing and in [-1.0+invSize..1.0-invSize] range.
|
||||
static inline void TexelCoordToVecWarp( float* _out3f, float _u, float _v, uint8_t _faceId, float _warpFixup )
|
||||
{
|
||||
_u = ( _warpFixup * _u * _u * _u ) + _u;
|
||||
_v = ( _warpFixup * _v * _v * _v ) + _v;
|
||||
|
||||
TexelCoordToVec( _out3f, _u, _v, _faceId );
|
||||
}
|
||||
|
||||
inline void vec3Mul( float* __restrict _result, const float* __restrict _a, float _b )
|
||||
{
|
||||
_result[0] = _a[0] * _b;
|
||||
_result[1] = _a[1] * _b;
|
||||
_result[2] = _a[2] * _b;
|
||||
}
|
||||
|
||||
inline float vec3Dot( const float* __restrict _a, const float* __restrict _b )
|
||||
{
|
||||
return _a[0] * _b[0] + _a[1] * _b[1] + _a[2] * _b[2];
|
||||
}
|
||||
|
||||
/// _u and _v are in [0.0 .. 1.0] range.
|
||||
static inline void VecToTexelCoord( float& _u, float& _v, uint8_t& _faceIdx, const float* _vec )
|
||||
{
|
||||
const float absVec[3] =
|
||||
{
|
||||
fabsf( _vec[0] ),
|
||||
fabsf( _vec[1] ),
|
||||
fabsf( _vec[2] ),
|
||||
};
|
||||
const float max = fmaxf( fmaxf( absVec[0], absVec[1] ), absVec[2] );
|
||||
|
||||
// Get face id (max component == face vector).
|
||||
if( max == absVec[0] )
|
||||
{
|
||||
_faceIdx = ( _vec[0] >= 0.0f ) ? uint8_t( CMFT_FACE_POS_X ) : uint8_t( CMFT_FACE_NEG_X );
|
||||
}
|
||||
else if( max == absVec[1] )
|
||||
{
|
||||
_faceIdx = ( _vec[1] >= 0.0f ) ? uint8_t( CMFT_FACE_POS_Y ) : uint8_t( CMFT_FACE_NEG_Y );
|
||||
}
|
||||
else //if (max == absVec[2])
|
||||
{
|
||||
_faceIdx = ( _vec[2] >= 0.0f ) ? uint8_t( CMFT_FACE_POS_Z ) : uint8_t( CMFT_FACE_NEG_Z );
|
||||
}
|
||||
|
||||
// Divide by max component.
|
||||
float faceVec[3];
|
||||
vec3Mul( faceVec, _vec, 1.0f / max );
|
||||
|
||||
// Project other two components to face uv basis.
|
||||
_u = ( vec3Dot( s_faceUvVectors[_faceIdx][0], faceVec ) + 1.0f ) * 0.5f;
|
||||
_v = ( vec3Dot( s_faceUvVectors[_faceIdx][1], faceVec ) + 1.0f ) * 0.5f;
|
||||
}
|
||||
|
||||
#define CMFT_RPI 0.31830988618379067153f
|
||||
|
||||
static inline void LatLongFromVec( float& _u, float& _v, const float _vec[3] )
|
||||
{
|
||||
const float phi = atan2f( _vec[0], _vec[2] );
|
||||
const float theta = acosf( _vec[1] );
|
||||
|
||||
_u = ( idMath::PI + phi ) * ( 0.5f / idMath::PI );
|
||||
_v = theta * CMFT_RPI;
|
||||
}
|
||||
|
||||
static inline void VecFromLatLong( float _vec[3], float _u, float _v )
|
||||
{
|
||||
const float phi = _u * idMath::TWO_PI;
|
||||
const float theta = _v * idMath::PI;
|
||||
|
||||
_vec[0] = -sinf( theta ) * sinf( phi );
|
||||
_vec[1] = cosf( theta );
|
||||
_vec[2] = -sinf( theta ) * cosf( phi );
|
||||
}
|
||||
|
||||
byte* R_GenerateCubeMapSideFromPanoramaImage( const byte* in, int srcWidth, int srcHeight, int cubeWidth, int side )
|
||||
{
|
||||
size_t x = 0, y = 0;
|
||||
|
||||
const uint32 bytesPerPixel = 4;
|
||||
|
||||
const int copySize = cubeWidth * cubeWidth * bytesPerPixel;
|
||||
|
||||
byte* out = ( byte* )R_StaticAlloc( copySize, TAG_IMAGE );
|
||||
uint32_t* out_p = ( uint32_t* )out;
|
||||
|
||||
const uint32 dstFaceSize = cubeWidth;
|
||||
const uint32 dstPitch = dstFaceSize * bytesPerPixel;
|
||||
//const uint32 dstFaceDataSize = dstPitch * dstFaceSize;
|
||||
//const uint32 dstDataSize = dstFaceDataSize * 6;
|
||||
|
||||
const float srcWidthMinusOne = float( int32( srcWidth - 1 ) );
|
||||
const float srcHeightMinusOne = float( int32( srcHeight - 1 ) );
|
||||
const uint32 srcPitch = srcWidth * bytesPerPixel;
|
||||
const float invDstFaceSizef = 1.0f / float( dstFaceSize );
|
||||
|
||||
// maybe wrong, done by observation
|
||||
const idMat4 toDoomTransform( idAngles( -90, 0, -90 ).ToMat3(), vec3_origin );
|
||||
|
||||
byte* dstFaceData = ( byte* )out;// + face * dstFaceDataSize;
|
||||
for( int y = 0; y < dstFaceSize; y++ )
|
||||
{
|
||||
byte* dstRowData = ( byte* )dstFaceData + y * dstPitch;
|
||||
for( int x = 0; x < dstFaceSize; x++ )
|
||||
{
|
||||
// Cubemap (u,v) on current face.
|
||||
const float uu = 2.0f * x * invDstFaceSizef - 1.0f;
|
||||
const float vv = 2.0f * y * invDstFaceSizef - 1.0f;
|
||||
|
||||
// Get cubemap vector (x,y,z) from (u,v,faceIdx).
|
||||
idVec3 vec;
|
||||
TexelCoordToVec( &vec[0], uu, vv, side );
|
||||
vec = toDoomTransform * vec;
|
||||
|
||||
// Convert cubemap vector (x,y,z) to latlong (u,v).
|
||||
float xSrcf;
|
||||
float ySrcf;
|
||||
LatLongFromVec( xSrcf, ySrcf, &vec[0] );
|
||||
|
||||
// Convert from [0..1] to [0..(size-1)] range.
|
||||
xSrcf *= srcWidthMinusOne;
|
||||
ySrcf *= srcHeightMinusOne;
|
||||
|
||||
const int32 xSrc = int32( idMath::Fabs( idMath::Rint( xSrcf ) ) );
|
||||
const int32 ySrc = int32( idMath::Fabs( idMath::Rint( ySrcf ) ) );
|
||||
const byte* src = ( const byte* )in + ySrc * srcPitch + xSrc * bytesPerPixel ;
|
||||
|
||||
byte* dstColumnData = ( uint8_t* )dstRowData + x * bytesPerPixel;
|
||||
dstColumnData[0] = src[0];
|
||||
dstColumnData[1] = src[1];
|
||||
dstColumnData[2] = src[2];
|
||||
dstColumnData[3] = src[3];
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
// RB end
|
|
@ -509,6 +509,7 @@ void idInteraction::UnlinkAndFree()
|
|||
{
|
||||
// clear the table pointer
|
||||
idRenderWorldLocal* renderWorld = this->lightDef->world;
|
||||
|
||||
// RB: added check for NULL
|
||||
if( renderWorld->interactionTable != NULL )
|
||||
{
|
||||
|
|
|
@ -1285,6 +1285,17 @@ void idMaterial::ParseFragmentMap( idLexer& src, newShaderStage_t* newStage )
|
|||
cubeMap = CF_SINGLE;
|
||||
continue;
|
||||
}
|
||||
if( !token.Icmp( "panoramaMap" ) )
|
||||
{
|
||||
cubeMap = CF_PANORAMA;
|
||||
continue;
|
||||
}
|
||||
if( !token.Icmp( "hdriMap" ) )
|
||||
{
|
||||
cubeMap = CF_PANORAMA;
|
||||
td = TD_HDRI;
|
||||
continue;
|
||||
}
|
||||
if( !token.Icmp( "nearest" ) )
|
||||
{
|
||||
tf = TF_NEAREST;
|
||||
|
@ -1807,6 +1818,24 @@ void idMaterial::ParseStage( idLexer& src, const textureRepeat_t trpDefault )
|
|||
continue;
|
||||
}
|
||||
|
||||
if( !token.Icmp( "panoramaMap" ) )
|
||||
{
|
||||
str = R_ParsePastImageProgram( src );
|
||||
idStr::Copynz( imageName, str, sizeof( imageName ) );
|
||||
cubeMap = CF_PANORAMA;
|
||||
td = TD_HIGHQUALITY_CUBE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !token.Icmp( "hdriMap" ) )
|
||||
{
|
||||
str = R_ParsePastImageProgram( src );
|
||||
idStr::Copynz( imageName, str, sizeof( imageName ) );
|
||||
cubeMap = CF_PANORAMA;
|
||||
td = TD_HDRI;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !token.Icmp( "cubeMapSize" ) )
|
||||
{
|
||||
cubeMapSize = src.ParseInt();
|
||||
|
@ -3960,7 +3989,7 @@ CONSOLE_COMMAND_SHIP( makeMaterials, "Make .mtr file from a models or textures f
|
|||
return;
|
||||
}
|
||||
|
||||
bool stripFolderFromMaterial = false;
|
||||
bool ueMode = false;
|
||||
|
||||
idStr option;
|
||||
for( int i = 1; i < args.Argc(); i++ )
|
||||
|
@ -3970,7 +3999,7 @@ CONSOLE_COMMAND_SHIP( makeMaterials, "Make .mtr file from a models or textures f
|
|||
|
||||
if( option.IcmpPrefix( "Unreal" ) == 0 )
|
||||
{
|
||||
stripFolderFromMaterial = true;
|
||||
ueMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4043,8 +4072,9 @@ CONSOLE_COMMAND_SHIP( makeMaterials, "Make .mtr file from a models or textures f
|
|||
materialName.CopyRange( baseName.c_str(), 0, baseName.Length() - 2 );
|
||||
}
|
||||
|
||||
if( stripFolderFromMaterial )
|
||||
if( ueMode )
|
||||
{
|
||||
// strip folder from material name
|
||||
idStr matName;
|
||||
materialName.ExtractFileName( matName );
|
||||
materialName = matName;
|
||||
|
@ -4143,7 +4173,7 @@ CONSOLE_COMMAND_SHIP( makeMaterials, "Make .mtr file from a models or textures f
|
|||
|
||||
if( testStamp != FILE_NOT_FOUND_TIMESTAMP )
|
||||
{
|
||||
if( name.Cmp( "_normal_opengl" ) == 0 )
|
||||
if( name.Cmp( "_nor_dx" ) == 0 || name.Cmp( "_normal_directx" ) == 0 || ueMode )
|
||||
{
|
||||
mtrBuffer += va( "\tnormalmap invertGreen( %s )\n", testName.c_str() );
|
||||
}
|
||||
|
@ -4255,6 +4285,52 @@ CONSOLE_COMMAND_SHIP( makeMaterials, "Make .mtr file from a models or textures f
|
|||
}
|
||||
}
|
||||
|
||||
if( ueMode )
|
||||
{
|
||||
// ===============================
|
||||
// test UE4 specular map
|
||||
idStrList specNames = { "_specular" };
|
||||
byte* specPic = NULL;
|
||||
int specWidth = 0;
|
||||
int specHeight = 0;
|
||||
|
||||
for( auto& name : specNames )
|
||||
{
|
||||
ID_TIME_T testStamp;
|
||||
idStr testName = baseName + name + resName;
|
||||
|
||||
R_LoadImage( testName, &specPic, &specWidth, &specHeight, &testStamp, true, NULL );
|
||||
if( testStamp != FILE_NOT_FOUND_TIMESTAMP )
|
||||
{
|
||||
// swap bytes to RMAO order
|
||||
int c = specWidth * specHeight * 4;
|
||||
|
||||
for( int j = 0 ; j < c ; j += 4 )
|
||||
{
|
||||
byte ao = specPic[j + 0];
|
||||
byte roughness = specPic[j + 1];
|
||||
byte metal = specPic[j + 2];
|
||||
|
||||
specPic[j + 0] = roughness;
|
||||
specPic[j + 1] = metal;
|
||||
specPic[j + 2] = ao;
|
||||
|
||||
// put middle 0.5 value into alpha channel for the case we want to add displacement later
|
||||
specPic[j + 3] = 128;
|
||||
}
|
||||
|
||||
idStr mergedName = baseName + "_rmao.png";
|
||||
R_WritePNG( mergedName, static_cast<byte*>( specPic ), 4, specWidth, specHeight, "fs_basepath" );
|
||||
|
||||
mergedName.StripFileExtension();
|
||||
mtrBuffer += va( "\trmaomap %s\n", mergedName.c_str() );
|
||||
|
||||
R_StaticFree( specPic );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( roughPic )
|
||||
{
|
||||
R_StaticFree( roughPic );
|
||||
|
|
|
@ -75,7 +75,7 @@ private:
|
|||
bool fileExclusive;
|
||||
bool hasAnimations;
|
||||
|
||||
float maxJointVertDist; // maximum distance a vertex is separated from a joint
|
||||
float maxJointVertDist = 10.0f; // maximum distance a vertex is separated from a joint
|
||||
idList<int, TAG_MODEL> animIds;
|
||||
idList<int, TAG_MODEL> bones;
|
||||
idList<int, TAG_MODEL> MeshNodeIds;
|
||||
|
|
|
@ -1177,7 +1177,7 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas
|
|||
const textureUsage_t specUsage = din->specularImage->GetUsage();
|
||||
|
||||
// RB begin
|
||||
if( useIBL && currentSpace->useLightGrid && r_useLightGrid.GetBool() )
|
||||
if( useIBL && din->surf->area != NULL && r_useLightGrid.GetBool() )
|
||||
{
|
||||
idVec4 probeMins, probeMaxs, probeCenter;
|
||||
|
||||
|
@ -1199,9 +1199,11 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas
|
|||
SetVertexParm( RENDERPARM_WOBBLESKY_Z, probeCenter.ToFloatPtr() );
|
||||
|
||||
// use rpGlobalLightOrigin for lightGrid center
|
||||
idVec4 lightGridOrigin( currentSpace->lightGridOrigin.x, currentSpace->lightGridOrigin.y, currentSpace->lightGridOrigin.z, 1.0f );
|
||||
idVec4 lightGridSize( currentSpace->lightGridSize.x, currentSpace->lightGridSize.y, currentSpace->lightGridSize.z, 1.0f );
|
||||
idVec4 lightGridBounds( currentSpace->lightGridBounds[0], currentSpace->lightGridBounds[1], currentSpace->lightGridBounds[2], 1.0f );
|
||||
const LightGrid& lightGrid = din->surf->area->lightGrid;
|
||||
|
||||
idVec4 lightGridOrigin( lightGrid.lightGridOrigin.x, lightGrid.lightGridOrigin.y, lightGrid.lightGridOrigin.z, 1.0f );
|
||||
idVec4 lightGridSize( lightGrid.lightGridSize.x, lightGrid.lightGridSize.y, lightGrid.lightGridSize.z, 1.0f );
|
||||
idVec4 lightGridBounds( lightGrid.lightGridBounds[0], lightGrid.lightGridBounds[1], lightGrid.lightGridBounds[2], 1.0f );
|
||||
|
||||
renderProgManager.SetUniformValue( RENDERPARM_GLOBALLIGHTORIGIN, lightGridOrigin.ToFloatPtr() );
|
||||
renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXSCALE, lightGridSize.ToFloatPtr() );
|
||||
|
@ -1209,10 +1211,10 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas
|
|||
|
||||
// individual probe sizes on the atlas image
|
||||
idVec4 probeSize;
|
||||
probeSize[0] = currentSpace->lightGridAtlasSingleProbeSize - currentSpace->lightGridAtlasBorderSize;
|
||||
probeSize[1] = currentSpace->lightGridAtlasSingleProbeSize;
|
||||
probeSize[2] = currentSpace->lightGridAtlasBorderSize;
|
||||
probeSize[3] = float( currentSpace->lightGridAtlasSingleProbeSize - currentSpace->lightGridAtlasBorderSize ) / currentSpace->lightGridAtlasSingleProbeSize;
|
||||
probeSize[0] = lightGrid.imageSingleProbeSize - lightGrid.imageBorderSize;
|
||||
probeSize[1] = lightGrid.imageSingleProbeSize;
|
||||
probeSize[2] = lightGrid.imageBorderSize;
|
||||
probeSize[3] = float( lightGrid.imageSingleProbeSize - lightGrid.imageBorderSize ) / lightGrid.imageSingleProbeSize;
|
||||
renderProgManager.SetUniformValue( RENDERPARM_SCREENCORRECTIONFACTOR, probeSize.ToFloatPtr() ); // rpScreenCorrectionFactor
|
||||
|
||||
// specular cubemap blend weights
|
||||
|
@ -1256,9 +1258,9 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas
|
|||
}
|
||||
|
||||
GL_SelectTexture( INTERACTION_TEXUNIT_AMBIENT_CUBE1 );
|
||||
currentSpace->lightGridAtlasImage->Bind();
|
||||
lightGrid.GetIrradianceImage()->Bind();
|
||||
|
||||
idVec2i res = currentSpace->lightGridAtlasImage->GetUploadResolution();
|
||||
idVec2i res = lightGrid.GetIrradianceImage()->GetUploadResolution();
|
||||
idVec4 textureSize( res.x, res.y, 1.0f / res.x, 1.0f / res.y );
|
||||
|
||||
renderProgManager.SetUniformValue( RENDERPARM_CASCADEDISTANCES, textureSize.ToFloatPtr() );
|
||||
|
@ -1710,7 +1712,7 @@ void idRenderBackend::RenderInteractions( const drawSurf_t* surfList, const view
|
|||
// are added single-threaded, and there is only a negligable amount
|
||||
// of benefit to trying to sort by materials.
|
||||
//---------------------------------
|
||||
static const int MAX_INTERACTIONS_PER_LIGHT = 1024;
|
||||
static const int MAX_INTERACTIONS_PER_LIGHT = 2048; // 1024 in BFG
|
||||
static const int MAX_COMPLEX_INTERACTIONS_PER_LIGHT = 256;
|
||||
idStaticList< const drawSurf_t*, MAX_INTERACTIONS_PER_LIGHT > allSurfaces;
|
||||
idStaticList< const drawSurf_t*, MAX_COMPLEX_INTERACTIONS_PER_LIGHT > complexSurfaces;
|
||||
|
@ -3012,12 +3014,9 @@ void idRenderBackend::SetupShadowMapMatrices( viewLight_t* vLight, int side, idR
|
|||
lightProjectionMatrix[1 * 4 + 2] = 0.0f;
|
||||
lightProjectionMatrix[2 * 4 + 2] = -0.999f; // adjust value to prevent imprecision issues
|
||||
|
||||
#if 0 //defined( USE_NVRHI )
|
||||
// the D3D clip space Z is in range [0,1] instead of [-1,1]
|
||||
lightProjectionMatrix[3 * 4 + 2] = -zNear;
|
||||
#else
|
||||
// FIXME -1.0f * zNear kills shadow depth
|
||||
lightProjectionMatrix[3 * 4 + 2] = -2.0f * zNear;
|
||||
#endif
|
||||
|
||||
lightProjectionMatrix[0 * 4 + 3] = 0.0f;
|
||||
lightProjectionMatrix[1 * 4 + 3] = 0.0f;
|
||||
|
@ -3096,21 +3095,28 @@ void idRenderBackend::ShadowMapPassPerforated( const drawSurf_t** drawSurfs, int
|
|||
// like a no-change-required
|
||||
GL_State( glState | GLS_POLYGON_OFFSET );
|
||||
|
||||
const float polygonFactor = r_shadowMapPolygonFactor.GetFloat();
|
||||
float polygonOffset = r_dxShadowMapPolygonOffset.GetFloat();
|
||||
if( deviceManager->GetGraphicsAPI() == nvrhi::GraphicsAPI::VULKAN )
|
||||
{
|
||||
polygonOffset = r_vkShadowMapPolygonOffset.GetFloat();
|
||||
}
|
||||
|
||||
switch( r_shadowMapOccluderFacing.GetInteger() )
|
||||
{
|
||||
case 0:
|
||||
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_FRONTSIDED );
|
||||
GL_PolygonOffset( r_shadowMapPolygonFactor.GetFloat(), r_shadowMapPolygonOffset.GetFloat() );
|
||||
GL_PolygonOffset( polygonFactor, polygonOffset );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_BACKSIDED );
|
||||
GL_PolygonOffset( -r_shadowMapPolygonFactor.GetFloat(), -r_shadowMapPolygonOffset.GetFloat() );
|
||||
GL_PolygonOffset( -polygonFactor, -polygonOffset );
|
||||
break;
|
||||
|
||||
default:
|
||||
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_TWOSIDED );
|
||||
GL_PolygonOffset( r_shadowMapPolygonFactor.GetFloat(), r_shadowMapPolygonOffset.GetFloat() );
|
||||
GL_PolygonOffset( polygonFactor, polygonOffset );
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3318,21 +3324,28 @@ void idRenderBackend::ShadowMapPassFast( const drawSurf_t* drawSurfs, viewLight_
|
|||
// like a no-change-required
|
||||
GL_State( glState | GLS_POLYGON_OFFSET );
|
||||
|
||||
const float polygonFactor = r_shadowMapPolygonFactor.GetFloat();
|
||||
float polygonOffset = r_dxShadowMapPolygonOffset.GetFloat();
|
||||
if( deviceManager->GetGraphicsAPI() == nvrhi::GraphicsAPI::VULKAN )
|
||||
{
|
||||
polygonOffset = r_vkShadowMapPolygonOffset.GetFloat();
|
||||
}
|
||||
|
||||
switch( r_shadowMapOccluderFacing.GetInteger() )
|
||||
{
|
||||
case 0:
|
||||
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_FRONTSIDED );
|
||||
GL_PolygonOffset( r_shadowMapPolygonFactor.GetFloat(), r_shadowMapPolygonOffset.GetFloat() );
|
||||
GL_PolygonOffset( polygonFactor, polygonOffset );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_BACKSIDED );
|
||||
GL_PolygonOffset( -r_shadowMapPolygonFactor.GetFloat(), -r_shadowMapPolygonOffset.GetFloat() );
|
||||
GL_PolygonOffset( -polygonFactor, -polygonOffset );
|
||||
break;
|
||||
|
||||
default:
|
||||
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_TWOSIDED );
|
||||
GL_PolygonOffset( r_shadowMapPolygonFactor.GetFloat(), r_shadowMapPolygonOffset.GetFloat() );
|
||||
GL_PolygonOffset( polygonFactor, polygonOffset );
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5789,6 +5802,7 @@ void idRenderBackend::DrawViewInternal( const viewDef_t* _viewDef, const int ste
|
|||
//-------------------------------------------------
|
||||
// resolve the screen for SSR
|
||||
//-------------------------------------------------
|
||||
if( is3D && r_useSSR.GetBool() )
|
||||
{
|
||||
if( R_GetMSAASamples() > 1 )
|
||||
{
|
||||
|
@ -6575,12 +6589,6 @@ void idRenderBackend::PostProcess( const void* data )
|
|||
|
||||
renderProgManager.BindShader_PostProcess_RetroCPC();
|
||||
}
|
||||
else if( r_renderMode.GetInteger() == RENDERMODE_NES || r_renderMode.GetInteger() == RENDERMODE_NES_HIGHRES )
|
||||
{
|
||||
jitterTexScale[0] = r_renderMode.GetInteger() == RENDERMODE_NES_HIGHRES ? 2.0 : 1.0;
|
||||
|
||||
renderProgManager.BindShader_PostProcess_RetroNES();
|
||||
}
|
||||
else if( r_renderMode.GetInteger() == RENDERMODE_GENESIS || r_renderMode.GetInteger() == RENDERMODE_GENESIS_HIGHRES )
|
||||
{
|
||||
jitterTexScale[0] = r_renderMode.GetInteger() == RENDERMODE_GENESIS_HIGHRES ? 2.0 : 1.0;
|
||||
|
|
|
@ -98,10 +98,11 @@ struct drawSurf_t
|
|||
const idMaterial* material; // may be NULL for shadow volumes
|
||||
uint64 extraGLState; // Extra GL state |'d with material->stage[].drawStateBits
|
||||
float sort; // material->sort, modified by gui / entity sort offsets
|
||||
const float* shaderRegisters; // evaluated and adjusted for referenceShaders
|
||||
const float* shaderRegisters; // evaluated and adjusted for referenceShaders
|
||||
drawSurf_t* nextOnLight; // viewLight chains
|
||||
drawSurf_t** linkChain; // defer linking to lights to a serial section to avoid a mutex
|
||||
idScreenRect scissorRect; // for scissor clipping, local inside renderView viewport
|
||||
const struct portalArea_s* area; // RB: if != NULL then the area provides valid lightgrid
|
||||
};
|
||||
|
||||
// areas have references to hold all the lights and entities in them
|
||||
|
@ -422,17 +423,6 @@ struct viewEntity_t
|
|||
// parallelAddModels will build a chain of surfaces here that will need to
|
||||
// be linked to the lights or added to the drawsurf list in a serial code section
|
||||
drawSurf_t* drawSurfs;
|
||||
|
||||
// RB: use light grid of the best area this entity is in
|
||||
bool useLightGrid;
|
||||
idImage* lightGridAtlasImage;
|
||||
int lightGridAtlasSingleProbeSize; // including border
|
||||
int lightGridAtlasBorderSize;
|
||||
|
||||
idVec3 lightGridOrigin;
|
||||
idVec3 lightGridSize;
|
||||
int lightGridBounds[3];
|
||||
// RB end
|
||||
};
|
||||
|
||||
// RB: viewEnvprobes are allocated on the frame temporary stack memory
|
||||
|
@ -1200,8 +1190,6 @@ extern idCVar r_singleEntity; // suppress all but one entity
|
|||
extern idCVar r_singleEnvprobe; // suppress all but one envprobe
|
||||
extern idCVar r_singleArea; // only draw the portal area the view is actually in
|
||||
extern idCVar r_singleSurface; // suppress all but one surface on each entity
|
||||
extern idCVar r_shadowPolygonOffset; // bias value added to depth test for stencil shadow drawing
|
||||
extern idCVar r_shadowPolygonFactor; // scale value for stencil shadow drawing
|
||||
|
||||
extern idCVar r_orderIndexes; // perform index reorganization to optimize vertex use
|
||||
|
||||
|
@ -1233,7 +1221,8 @@ extern idCVar r_shadowMapSplitWeight;
|
|||
extern idCVar r_shadowMapLodScale;
|
||||
extern idCVar r_shadowMapLodBias;
|
||||
extern idCVar r_shadowMapPolygonFactor;
|
||||
extern idCVar r_shadowMapPolygonOffset;
|
||||
extern idCVar r_dxShadowMapPolygonOffset;
|
||||
extern idCVar r_vkShadowMapPolygonOffset;
|
||||
extern idCVar r_shadowMapOccluderFacing;
|
||||
extern idCVar r_shadowMapRegularDepthBiasScale;
|
||||
extern idCVar r_shadowMapSunDepthBiasScale;
|
||||
|
@ -1298,8 +1287,6 @@ enum RenderMode
|
|||
RENDERMODE_C64_HIGHRES,
|
||||
RENDERMODE_CPC,
|
||||
RENDERMODE_CPC_HIGHRES,
|
||||
RENDERMODE_NES,
|
||||
RENDERMODE_NES_HIGHRES,
|
||||
RENDERMODE_GENESIS,
|
||||
RENDERMODE_GENESIS_HIGHRES,
|
||||
RENDERMODE_PSX,
|
||||
|
|
|
@ -345,9 +345,9 @@ void idRenderProgManager::Init( nvrhi::IDevice* device )
|
|||
auto ppFxBindingLayout2 = nvrhi::BindingLayoutDesc()
|
||||
.setVisibility( nvrhi::ShaderType::All )
|
||||
.addItem( renderParmLayoutItem )
|
||||
.addItem( nvrhi::BindingLayoutItem::Texture_SRV( 0 ) ) // LDR _currentRender
|
||||
.addItem( nvrhi::BindingLayoutItem::Texture_SRV( 1 ) ) // _blueNoise
|
||||
.addItem( nvrhi::BindingLayoutItem::Texture_SRV( 2 ) ) // _currentNormals
|
||||
.addItem( nvrhi::BindingLayoutItem::Texture_SRV( 0 ) ) // LDR _currentRender
|
||||
.addItem( nvrhi::BindingLayoutItem::Texture_SRV( 1 ) ) // _blueNoise
|
||||
.addItem( nvrhi::BindingLayoutItem::Texture_SRV( 2 ) ) // _currentNormals
|
||||
.addItem( nvrhi::BindingLayoutItem::Texture_SRV( 3 ) ); // _currentDepth
|
||||
|
||||
bindingLayouts[BINDING_LAYOUT_POST_PROCESS_FINAL2] = { device->createBindingLayout( ppFxBindingLayout2 ), samplerTwoBindingLayout };
|
||||
|
@ -575,7 +575,6 @@ void idRenderProgManager::Init( nvrhi::IDevice* device )
|
|||
{ BUILTIN_POSTPROCESS_RETRO_2BIT, "builtin/post/retro_2bit", "", {}, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_POST_PROCESS_FINAL },
|
||||
{ BUILTIN_POSTPROCESS_RETRO_C64, "builtin/post/retro_c64", "", {}, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_POST_PROCESS_FINAL },
|
||||
{ BUILTIN_POSTPROCESS_RETRO_CPC, "builtin/post/retro_cpc", "", {}, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_POST_PROCESS_FINAL2 },
|
||||
{ BUILTIN_POSTPROCESS_RETRO_NES, "builtin/post/retro_nes", "", {}, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_POST_PROCESS_FINAL },
|
||||
{ BUILTIN_POSTPROCESS_RETRO_GENESIS, "builtin/post/retro_genesis", "", {}, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_POST_PROCESS_FINAL },
|
||||
{ BUILTIN_POSTPROCESS_RETRO_PSX, "builtin/post/retro_ps1", "", {}, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_POST_PROCESS_FINAL },
|
||||
{ BUILTIN_CRT_MATTIAS, "builtin/post/crt_mattias", "", {}, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT, BINDING_LAYOUT_POST_PROCESS_CRT },
|
||||
|
|
|
@ -375,7 +375,6 @@ enum
|
|||
BUILTIN_POSTPROCESS_RETRO_2BIT, // CGA, Gameboy, cool for Gamejams
|
||||
BUILTIN_POSTPROCESS_RETRO_C64, // Commodore 64
|
||||
BUILTIN_POSTPROCESS_RETRO_CPC, // Amstrad 6128
|
||||
BUILTIN_POSTPROCESS_RETRO_NES, // NES
|
||||
BUILTIN_POSTPROCESS_RETRO_GENESIS, // Sega Genesis / Megadrive
|
||||
BUILTIN_POSTPROCESS_RETRO_PSX, // Sony Playstation 1
|
||||
BUILTIN_CRT_MATTIAS,
|
||||
|
@ -857,11 +856,6 @@ public:
|
|||
BindShader_Builtin( BUILTIN_POSTPROCESS_RETRO_2BIT );
|
||||
}
|
||||
|
||||
void BindShader_PostProcess_RetroNES()
|
||||
{
|
||||
BindShader_Builtin( BUILTIN_POSTPROCESS_RETRO_NES );
|
||||
}
|
||||
|
||||
void BindShader_PostProcess_RetroGenesis()
|
||||
{
|
||||
BindShader_Builtin( BUILTIN_POSTPROCESS_RETRO_GENESIS );
|
||||
|
|
|
@ -165,8 +165,6 @@ idCVar r_offsetFactor( "r_offsetfactor", "0", CVAR_RENDERER | CVAR_FLOAT, "polyg
|
|||
#endif
|
||||
// RB end
|
||||
|
||||
idCVar r_shadowPolygonOffset( "r_shadowPolygonOffset", "-1", CVAR_RENDERER | CVAR_FLOAT, "bias value added to depth test for stencil shadow drawing" );
|
||||
idCVar r_shadowPolygonFactor( "r_shadowPolygonFactor", "0", CVAR_RENDERER | CVAR_FLOAT, "scale value for stencil shadow drawing" );
|
||||
idCVar r_subviewOnly( "r_subviewOnly", "0", CVAR_RENDERER | CVAR_BOOL, "1 = don't render main view, allowing subviews to be debugged" );
|
||||
idCVar r_testGamma( "r_testGamma", "0", CVAR_RENDERER | CVAR_FLOAT, "if > 0 draw a grid pattern to test gamma levels", 0, 195 );
|
||||
idCVar r_testGammaBias( "r_testGammaBias", "0", CVAR_RENDERER | CVAR_FLOAT, "if > 0 draw a grid pattern to test gamma levels" );
|
||||
|
@ -257,10 +255,11 @@ idCVar r_shadowMapSplitWeight( "r_shadowMapSplitWeight", "0.9", CVAR_RENDERER |
|
|||
idCVar r_shadowMapLodScale( "r_shadowMapLodScale", "1.4", CVAR_RENDERER | CVAR_FLOAT | CVAR_NEW, "" );
|
||||
idCVar r_shadowMapLodBias( "r_shadowMapLodBias", "0", CVAR_RENDERER | CVAR_INTEGER | CVAR_NEW, "" );
|
||||
idCVar r_shadowMapPolygonFactor( "r_shadowMapPolygonFactor", "2", CVAR_RENDERER | CVAR_FLOAT | CVAR_NEW, "polygonOffset factor for drawing shadow buffer" );
|
||||
idCVar r_shadowMapPolygonOffset( "r_shadowMapPolygonOffset", "3000", CVAR_RENDERER | CVAR_FLOAT | CVAR_NEW, "polygonOffset units for drawing shadow buffer" );
|
||||
idCVar r_dxShadowMapPolygonOffset( "r_dxShadowMapPolygonOffset", "0.1", CVAR_RENDERER | CVAR_FLOAT | CVAR_NEW, "polygonOffset units for drawing shadow buffer" );
|
||||
idCVar r_vkShadowMapPolygonOffset( "r_vkShadowMapPolygonOffset", "1", CVAR_RENDERER | CVAR_FLOAT | CVAR_NEW, "polygonOffset units for drawing shadow buffer" );
|
||||
idCVar r_shadowMapOccluderFacing( "r_shadowMapOccluderFacing", "2", CVAR_RENDERER | CVAR_INTEGER | CVAR_NEW, "0 = front faces, 1 = back faces, 2 = twosided" );
|
||||
idCVar r_shadowMapRegularDepthBiasScale( "r_shadowMapRegularDepthBiasScale", "0.999", CVAR_RENDERER | CVAR_FLOAT | CVAR_NEW, "shadowmap bias to fight shadow acne for point and spot lights" );
|
||||
idCVar r_shadowMapSunDepthBiasScale( "r_shadowMapSunDepthBiasScale", "0.999991", CVAR_RENDERER | CVAR_FLOAT | CVAR_NEW, "shadowmap bias to fight shadow acne for cascaded shadow mapping with parallel lights" );
|
||||
idCVar r_shadowMapSunDepthBiasScale( "r_shadowMapSunDepthBiasScale", "0.999", CVAR_RENDERER | CVAR_FLOAT | CVAR_NEW, "shadowmap bias to fight shadow acne for cascaded shadow mapping with parallel lights" );
|
||||
|
||||
// RB: HDR parameters
|
||||
idCVar r_hdrAutoExposure( "r_hdrAutoExposure", "0", CVAR_RENDERER | CVAR_BOOL | CVAR_NEW, "EXPENSIVE: enables adapative HDR tone mapping otherwise the exposure is derived by r_exposure" );
|
||||
|
@ -315,7 +314,7 @@ idCVar r_crtVignette( "r_crtVignette", "0.8", CVAR_RENDERER | CVAR_FLOAT | CVAR_
|
|||
|
||||
idCVar r_retroDitherScale( "r_retroDitherScale", "0.3", CVAR_RENDERER | CVAR_FLOAT | CVAR_NEW, "" );
|
||||
|
||||
idCVar r_renderMode( "r_renderMode", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER | CVAR_NEW, "0 = Doom, 1 = CGA, 2 = CGA Highres, 3 = Commodore 64, 4 = Commodore 64 Highres, 5 = Amstrad CPC 6128, 6 = Amstrad CPC 6128 Highres, 7 = NES, 8 = NES Highres, 9 = Sega Genesis, 10 = Sega Genesis Highres, 11 = Sony PSX", 0, 11 );
|
||||
idCVar r_renderMode( "r_renderMode", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER | CVAR_NEW, "0 = Doom, 1 = CGA, 2 = CGA Highres, 3 = Commodore 64, 4 = Commodore 64 Highres, 5 = Amstrad CPC 6128, 6 = Amstrad CPC 6128 Highres, 7 = Sega Genesis, 8 = Sega Genesis Highres, 9 = Sony PSX", 0, 9 );
|
||||
|
||||
idCVar r_psxVertexJitter( "r_psxVertexJitter", "0.5", CVAR_RENDERER | CVAR_FLOAT | CVAR_NEW, "", 0.0f, 0.75f );
|
||||
idCVar r_psxAffineTextures( "r_psxAffineTextures", "1", CVAR_RENDERER | CVAR_FLOAT | CVAR_NEW, "" );
|
||||
|
|
|
@ -1133,7 +1133,14 @@ CONSOLE_COMMAND_SHIP( bakeEnvironmentProbes, "Bake environment probes", NULL )
|
|||
}
|
||||
|
||||
// generate .bimage file
|
||||
globalImages->ImageFromFile( job->filename, TF_LINEAR, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||
if( job->outHeight == RADIANCE_OCTAHEDRON_SIZE )
|
||||
{
|
||||
globalImages->ImageFromFile( job->filename, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||
}
|
||||
else
|
||||
{
|
||||
globalImages->ImageFromFile( job->filename, TF_LINEAR, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||
}
|
||||
|
||||
Mem_Free( job->outBuffer );
|
||||
|
||||
|
|
|
@ -497,7 +497,8 @@ void idRenderWorldLocal::WriteLightGrid( idFile* fp, const LightGrid& lightGrid
|
|||
{
|
||||
const lightGridPoint_t* gridPoint = &lightGrid.lightGridPoints[i];
|
||||
|
||||
fp->WriteFloatString( "/* lgp %i */ %d ( %f %f %f )", i, ( int )gridPoint->valid, gridPoint->origin[0], gridPoint->origin[1], gridPoint->origin[2] );
|
||||
//fp->WriteFloatString( "/* lgp %i */ %d ( %f %f %f )", i, ( int )gridPoint->valid, gridPoint->origin[0], gridPoint->origin[1], gridPoint->origin[2] );
|
||||
fp->WriteFloatString( " %d ( %f %f %f )", ( int )gridPoint->valid, gridPoint->origin[0], gridPoint->origin[1], gridPoint->origin[2] );
|
||||
|
||||
#if STORE_LIGHTGRID_SHDATA
|
||||
// spherical harmonic
|
||||
|
|
|
@ -249,7 +249,7 @@ public:
|
|||
idBlockAlloc<areaReference_t, 1024> areaReferenceAllocator;
|
||||
idBlockAlloc<idInteraction, 256> interactionAllocator;
|
||||
|
||||
#ifdef ID_PC
|
||||
#if 1 //def ID_PC
|
||||
static const int MAX_DECAL_SURFACES = 32;
|
||||
#else
|
||||
static const int MAX_DECAL_SURFACES = 16;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2016-2017 Dustin Land
|
||||
Copyright (C) 2020 Robert Beckebans
|
||||
Copyright (C) 2022 Stephen Pridham
|
||||
Copyright (C) 2024 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
@ -33,7 +33,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#if 1
|
||||
|
||||
// RB: increased some static memory limits for custom modder content
|
||||
// RB: quadruppled static memory limits for custom content
|
||||
|
||||
const int VERTCACHE_INDEX_MEMORY_PER_FRAME = 31 * 1024 * 1024;
|
||||
const int VERTCACHE_VERTEX_MEMORY_PER_FRAME = 31 * 1024 * 1024;
|
||||
|
@ -42,7 +42,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
// there are a lot more static indexes than vertexes, because interactions are just new
|
||||
// index lists that reference existing vertexes
|
||||
const int STATIC_INDEX_MEMORY = 4 * 31 * 1024 * 1024;
|
||||
const int STATIC_VERTEX_MEMORY = 2 * 31 * 1024 * 1024; // make sure it fits in VERTCACHE_OFFSET_MASK!
|
||||
const int STATIC_VERTEX_MEMORY = 4 * 31 * 1024 * 1024; // make sure it fits in VERTCACHE_OFFSET_MASK!
|
||||
|
||||
// vertCacheHandle_t packs size, offset, and frame number into 64 bits
|
||||
typedef uint64 vertCacheHandle_t;
|
||||
|
@ -52,10 +52,10 @@ If you have questions concerning this license or the applicable additional terms
|
|||
const int VERTCACHE_SIZE_MASK = 0x7fffff; // 23 bits = 8 megs
|
||||
|
||||
const int VERTCACHE_OFFSET_SHIFT = 24;
|
||||
const int VERTCACHE_OFFSET_MASK = 0x3ffffff; // 26 bits = 64 megs
|
||||
const int VERTCACHE_OFFSET_MASK = 0x7ffffff; // 27 bits = 128 megs
|
||||
|
||||
const int VERTCACHE_FRAME_SHIFT = 50;
|
||||
const int VERTCACHE_FRAME_MASK = 0x3fff; // 14 bits = 16382 frames to wrap around
|
||||
const int VERTCACHE_FRAME_SHIFT = 51;
|
||||
const int VERTCACHE_FRAME_MASK = 0x1fff; // 13 bits = 8191 frames to wrap around
|
||||
|
||||
|
||||
#else
|
||||
|
|
|
@ -177,7 +177,6 @@ idRenderModel* R_EntityDefDynamicModel( idRenderEntityLocal* def )
|
|||
// if we don't have a snapshot of the dynamic model, generate it now
|
||||
if( def->dynamicModel == NULL )
|
||||
{
|
||||
|
||||
SCOPED_PROFILE_EVENT( "InstantiateDynamicModel" );
|
||||
|
||||
// instantiate the snapshot of the dynamic model, possibly reusing memory from the cached snapshot
|
||||
|
@ -316,9 +315,6 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
// we will add all interaction surfs here, to be chained to the lights in later serial code
|
||||
vEntity->drawSurfs = NULL;
|
||||
|
||||
// RB
|
||||
vEntity->useLightGrid = false;
|
||||
|
||||
// globals we really should pass in...
|
||||
const viewDef_t* viewDef = tr.viewDef;
|
||||
|
||||
|
@ -495,32 +491,6 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
}
|
||||
}
|
||||
|
||||
// RB: use first valid lightgrid
|
||||
for( areaReference_t* ref = entityDef->entityRefs; ref != NULL; ref = ref->ownerNext )
|
||||
{
|
||||
idImage* lightGridImage = ref->area->lightGrid.GetIrradianceImage();
|
||||
|
||||
if( ref->area->lightGrid.lightGridPoints.Num() && lightGridImage && !lightGridImage->IsDefaulted() )
|
||||
{
|
||||
vEntity->useLightGrid = true;
|
||||
vEntity->lightGridAtlasImage = lightGridImage;
|
||||
vEntity->lightGridAtlasSingleProbeSize = ref->area->lightGrid.imageSingleProbeSize;
|
||||
vEntity->lightGridAtlasBorderSize = ref->area->lightGrid.imageBorderSize;
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
vEntity->lightGridOrigin[i] = ref->area->lightGrid.lightGridOrigin[i];
|
||||
vEntity->lightGridSize[i] = ref->area->lightGrid.lightGridSize[i];
|
||||
vEntity->lightGridBounds[i] = ref->area->lightGrid.lightGridBounds[i];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// RB end
|
||||
|
||||
//---------------------------
|
||||
// copy matrix related stuff for back-end use
|
||||
// and setup a render matrix for faster culling
|
||||
|
@ -709,26 +679,23 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
tr.pc.c_mocIndexes += 36;
|
||||
tr.pc.c_mocVerts += 8;
|
||||
|
||||
const float size = 16.0f;
|
||||
idBounds debugBounds( idVec3( -size ), idVec3( size ) );
|
||||
//debugBounds = vEntity->entityDef->localReferenceBounds;
|
||||
#if 0
|
||||
idBounds surfaceBounds;
|
||||
#if 1
|
||||
if( gpuSkinned )
|
||||
{
|
||||
//debugBounds = vEntity->entityDef->localReferenceBounds;
|
||||
debugBounds = model->Bounds();
|
||||
surfaceBounds = vEntity->entityDef->localReferenceBounds;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
debugBounds = tri->bounds;
|
||||
surfaceBounds = tri->bounds;
|
||||
}
|
||||
|
||||
idRenderMatrix modelRenderMatrix;
|
||||
idRenderMatrix::CreateFromOriginAxis( renderEntity->origin, renderEntity->axis, modelRenderMatrix );
|
||||
|
||||
idRenderMatrix inverseBaseModelProject;
|
||||
idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject );
|
||||
idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, surfaceBounds, inverseBaseModelProject );
|
||||
|
||||
idRenderMatrix invProjectMVPMatrix;
|
||||
idRenderMatrix::Multiply( viewDef->worldSpace.unjitteredMVP, inverseBaseModelProject, invProjectMVPMatrix );
|
||||
|
@ -760,8 +727,6 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
}
|
||||
#endif // #if defined(USE_INTRINSICS_SSE)
|
||||
|
||||
|
||||
|
||||
//--------------------------
|
||||
// base drawing surface
|
||||
//--------------------------
|
||||
|
@ -845,6 +810,99 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
baseDrawSurf->nextOnLight = vEntity->drawSurfs;
|
||||
vEntity->drawSurfs = baseDrawSurf;
|
||||
}
|
||||
|
||||
// RB: use area the surface is in because a model can span multiple areas #965
|
||||
baseDrawSurf->area = NULL;
|
||||
|
||||
if( shader->ReceivesLighting() )
|
||||
{
|
||||
idVec3 surfaceCenter;
|
||||
idVec3 triCenter = tri->bounds.GetCenter();
|
||||
|
||||
idRenderMatrix modelRenderMatrix;
|
||||
idRenderMatrix::CreateFromOriginAxis( renderEntity->origin, renderEntity->axis, modelRenderMatrix );
|
||||
modelRenderMatrix.TransformPoint( triCenter, surfaceCenter );
|
||||
|
||||
int surfaceArea = tr.primaryWorld->PointInArea( surfaceCenter );
|
||||
|
||||
for( areaReference_t* ref = entityDef->entityRefs; ref != NULL; ref = ref->ownerNext )
|
||||
{
|
||||
idImage* lightGridImage = ref->area->lightGrid.GetIrradianceImage();
|
||||
|
||||
if( surfaceArea == ref->area->areaNum && ref->area->lightGrid.lightGridPoints.Num() && lightGridImage != NULL && !lightGridImage->IsDefaulted() )
|
||||
{
|
||||
baseDrawSurf->area = ref->area;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// RB: use first valid lightgrid
|
||||
// this would be wrong but less wrong than a flickering env_probe fallback
|
||||
if( baseDrawSurf->area == NULL )
|
||||
{
|
||||
for( areaReference_t* ref = entityDef->entityRefs; ref != NULL; ref = ref->ownerNext )
|
||||
{
|
||||
idImage* lightGridImage = ref->area->lightGrid.GetIrradianceImage();
|
||||
|
||||
if( ref->area->lightGrid.lightGridPoints.Num() && lightGridImage != NULL && !lightGridImage->IsDefaulted() )
|
||||
{
|
||||
baseDrawSurf->area = ref->area;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// show which area the surface is coming from
|
||||
//if( baseDrawSurf->area == NULL )
|
||||
{
|
||||
idBounds surfaceBounds;
|
||||
if( gpuSkinned )
|
||||
{
|
||||
surfaceBounds = vEntity->entityDef->localReferenceBounds;
|
||||
}
|
||||
else
|
||||
{
|
||||
surfaceBounds = tri->bounds;
|
||||
}
|
||||
|
||||
idRenderMatrix modelRenderMatrix;
|
||||
idRenderMatrix::CreateFromOriginAxis( renderEntity->origin, renderEntity->axis, modelRenderMatrix );
|
||||
|
||||
idRenderMatrix inverseBaseModelProject;
|
||||
idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, surfaceBounds, inverseBaseModelProject );
|
||||
|
||||
// NOTE: unit cube instead of zeroToOne cube
|
||||
idVec4* verts = tr.maskedUnitCubeVerts;
|
||||
idVec4 triVerts[8];
|
||||
|
||||
for( int i = 0; i < 8; i++ )
|
||||
{
|
||||
// transform to clip space
|
||||
inverseBaseModelProject.TransformPoint( verts[i], triVerts[i] );
|
||||
}
|
||||
|
||||
static idVec4 colors[] = { colorBrown, colorBlue, colorCyan, colorGreen, colorYellow, colorRed, colorWhite };
|
||||
idVec4 color = colors[surfaceArea & 7];
|
||||
|
||||
if( baseDrawSurf->area == NULL )
|
||||
{
|
||||
color = colorPurple;
|
||||
}
|
||||
|
||||
// same as idRenderWorldLocal::DebugBox
|
||||
const int lifetime = 0;
|
||||
for( int i = 0; i < 4; i++ )
|
||||
{
|
||||
tr.viewDef->renderWorld->DebugLine( color, triVerts[i].ToVec3(), triVerts[( i + 1 ) & 3].ToVec3(), lifetime );
|
||||
tr.viewDef->renderWorld->DebugLine( color, triVerts[4 + i].ToVec3(), triVerts[4 + ( ( i + 1 ) & 3 )].ToVec3(), lifetime );
|
||||
tr.viewDef->renderWorld->DebugLine( color, triVerts[i].ToVec3(), triVerts[4 + i].ToVec3(), lifetime );
|
||||
}
|
||||
|
||||
tr.viewDef->renderWorld->DebugAxis( surfaceCenter, renderEntity->axis );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
|
|
@ -382,51 +382,80 @@ void R_RenderSingleModel( viewEntity_t* vEntity )
|
|||
#if 0
|
||||
else
|
||||
{
|
||||
idVec4 triVerts[3];
|
||||
unsigned int triIndices[] = { 0, 1, 2 };
|
||||
|
||||
tr.pc.c_mocIndexes += 36;
|
||||
tr.pc.c_mocVerts += 8;
|
||||
|
||||
idBounds surfaceBounds;
|
||||
if( gpuSkinned )
|
||||
{
|
||||
surfaceBounds = vEntity->entityDef->localReferenceBounds;
|
||||
}
|
||||
else
|
||||
{
|
||||
surfaceBounds = tri->bounds;
|
||||
}
|
||||
|
||||
idRenderMatrix modelRenderMatrix;
|
||||
idRenderMatrix::CreateFromOriginAxis( renderEntity->origin, renderEntity->axis, modelRenderMatrix );
|
||||
|
||||
//const float size = 16.0f;
|
||||
//idBounds debugBounds( idVec3( -size ), idVec3( size ) );
|
||||
idBounds debugBounds;
|
||||
#if 0
|
||||
if( gpuSkinned )
|
||||
{
|
||||
//debugBounds = vEntity->entityDef->localReferenceBounds;
|
||||
debugBounds = model->Bounds();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
debugBounds = tri->bounds;
|
||||
}
|
||||
|
||||
idRenderMatrix inverseBaseModelProject;
|
||||
idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject );
|
||||
idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, surfaceBounds, inverseBaseModelProject );
|
||||
|
||||
idRenderMatrix invProjectMVPMatrix;
|
||||
idRenderMatrix::Multiply( viewDef->worldSpace.unjitteredMVP, inverseBaseModelProject, invProjectMVPMatrix );
|
||||
|
||||
// NOTE: unit cube instead of zeroToOne cube
|
||||
idVec4* verts = tr.maskedUnitCubeVerts;
|
||||
unsigned int* indexes = tr.maskedZeroOneCubeIndexes;
|
||||
for( int i = 0, face = 0; i < 36; i += 3, face++ )
|
||||
idVec4 triVerts[8];
|
||||
|
||||
for( int i = 0; i < 8; i++ )
|
||||
{
|
||||
const idVec4& v0 = verts[indexes[i + 0]];
|
||||
const idVec4& v1 = verts[indexes[i + 1]];
|
||||
const idVec4& v2 = verts[indexes[i + 2]];
|
||||
|
||||
// transform to clip space
|
||||
invProjectMVPMatrix.TransformPoint( v0, triVerts[0] );
|
||||
invProjectMVPMatrix.TransformPoint( v1, triVerts[1] );
|
||||
invProjectMVPMatrix.TransformPoint( v2, triVerts[2] );
|
||||
invProjectMVPMatrix.TransformPoint( verts[i], triVerts[i] );
|
||||
}
|
||||
|
||||
tr.maskedOcclusionCulling->RenderTriangles( ( float* )triVerts, triIndices, 1, NULL, MaskedOcclusionCulling::BACKFACE_CCW );
|
||||
tr.maskedOcclusionCulling->RenderTriangles( ( float* )triVerts, tr.maskedZeroOneCubeIndexes, 12, NULL, MaskedOcclusionCulling::BACKFACE_CCW );
|
||||
}
|
||||
|
||||
#elif 0
|
||||
else
|
||||
{
|
||||
idBounds surfaceBounds;
|
||||
if( gpuSkinned )
|
||||
{
|
||||
surfaceBounds = vEntity->entityDef->localReferenceBounds;
|
||||
}
|
||||
else
|
||||
{
|
||||
surfaceBounds = tri->bounds;
|
||||
}
|
||||
|
||||
idRenderMatrix modelRenderMatrix;
|
||||
idRenderMatrix::CreateFromOriginAxis( renderEntity->origin, renderEntity->axis, modelRenderMatrix );
|
||||
|
||||
idRenderMatrix inverseBaseModelProject;
|
||||
idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, surfaceBounds, inverseBaseModelProject );
|
||||
|
||||
// NOTE: unit cube instead of zeroToOne cube
|
||||
idVec4* verts = tr.maskedUnitCubeVerts;
|
||||
idVec4 triVerts[8];
|
||||
|
||||
for( int i = 0; i < 8; i++ )
|
||||
{
|
||||
// transform to clip space
|
||||
inverseBaseModelProject.TransformPoint( verts[i], triVerts[i] );
|
||||
}
|
||||
|
||||
static idVec4 colors[] = { colorRed, colorGreen, colorBlue, colorYellow, colorMagenta, colorCyan, colorWhite, colorPurple };
|
||||
idVec4 color = colors[surfaceNum & 7];
|
||||
|
||||
// same as idRenderWorldLocal::DebugBox
|
||||
const int lifetime = 0;
|
||||
for( int i = 0; i < 4; i++ )
|
||||
{
|
||||
tr.viewDef->renderWorld->DebugLine( color, triVerts[i].ToVec3(), triVerts[( i + 1 ) & 3].ToVec3(), lifetime );
|
||||
tr.viewDef->renderWorld->DebugLine( color, triVerts[4 + i].ToVec3(), triVerts[4 + ( ( i + 1 ) & 3 )].ToVec3(), lifetime );
|
||||
tr.viewDef->renderWorld->DebugLine( color, triVerts[i].ToVec3(), triVerts[4 + i].ToVec3(), lifetime );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -58,5 +58,7 @@ void main( VS_IN vertex, out VS_OUT result )
|
|||
|
||||
result.texcoord0 = vertex.position.xyz - rpLocalViewOrigin.xyz;
|
||||
|
||||
result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;
|
||||
// RB: pass rpColor as intensity scaling factor for HDRI skies because the vertex color logic isn't used on skyboxes afaik
|
||||
//result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;
|
||||
result.color = rpColor;
|
||||
}
|
||||
|
|
|
@ -242,14 +242,11 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
gridCoord[j] = int( floor( v ) );
|
||||
frac[ j ] = v - gridCoord[ j ];
|
||||
|
||||
/*
|
||||
if( gridCoord[i] < 0 )
|
||||
if( gridCoord[j] < 0 )
|
||||
{
|
||||
gridCoord[i] = 0;
|
||||
gridCoord[j] = 0;
|
||||
}
|
||||
else
|
||||
*/
|
||||
if( gridCoord[j] >= lightGridBounds[j] - 1 )
|
||||
else if( gridCoord[j] >= lightGridBounds[j] - 1 )
|
||||
{
|
||||
gridCoord[j] = lightGridBounds[j] - 1;
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
Params params;
|
||||
params.curvature = rpWindowCoord.x;
|
||||
params.ghosting = 0.0;
|
||||
params.scanroll = 1.0;
|
||||
params.scanroll = 0.0;
|
||||
params.wiggle_toggle = 0.0;
|
||||
params.vignette = rpWindowCoord.y;
|
||||
params.FrameCount = int( rpJitterTexOffset.w );
|
||||
|
|
|
@ -106,73 +106,6 @@ float3 LinearSearch( float3 c, float3 pal[NUM_COLORS] )
|
|||
return pal[index];
|
||||
}
|
||||
|
||||
/*
|
||||
float3 GetClosest( float3 val1, float3 val2, float3 target )
|
||||
{
|
||||
if( distance( target, val1 ) >= distance( val2, target ) )
|
||||
{
|
||||
return val2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return val1;
|
||||
}
|
||||
}
|
||||
|
||||
// find nearest palette color using Euclidean disntance and binary search
|
||||
// this requires an already sorted palette as input
|
||||
float3 BinarySearch( float3 target, float3 pal[NUM_COLORS] )
|
||||
{
|
||||
float targetY = PhotoLuma( target );
|
||||
|
||||
// left-side case
|
||||
if( targetY <= PhotoLuma( pal[0] ) )
|
||||
{
|
||||
return pal[0];
|
||||
}
|
||||
|
||||
// right-side case
|
||||
if( targetY >= PhotoLuma( pal[NUM_COLORS - 1] ) )
|
||||
{
|
||||
return pal[NUM_COLORS - 1];
|
||||
}
|
||||
|
||||
int i = 0, j = NUM_COLORS, mid = 0;
|
||||
while( i < j )
|
||||
{
|
||||
mid = ( i + j ) / 2;
|
||||
|
||||
if( distance( pal[mid], target ) < 0.01 )
|
||||
{
|
||||
return pal[mid];
|
||||
}
|
||||
|
||||
// if target is less than array element, then search in left
|
||||
if( targetY < PhotoLuma( pal[mid] ) )
|
||||
{
|
||||
// if target is greater than previous
|
||||
// to mid, return closest of two
|
||||
if( mid > 0 && targetY > PhotoLuma( pal[mid - 1] ) )
|
||||
{
|
||||
return GetClosest( pal[mid - 1], pal[mid], target );
|
||||
}
|
||||
j = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mid < ( NUM_COLORS - 1 ) && targetY < PhotoLuma( pal[mid + 1] ) )
|
||||
{
|
||||
return GetClosest( pal[mid], pal[mid + 1], target );
|
||||
}
|
||||
i = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// only single element left after search
|
||||
return pal[mid];
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
#define RGB(r, g, b) float3(float(r)/255.0, float(g)/255.0, float(b)/255.0)
|
||||
|
||||
|
@ -283,7 +216,6 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
|
||||
// find closest color match from C64 color palette
|
||||
color = LinearSearch( color.rgb, palette );
|
||||
//color = float4( BinarySearch( color.rgb, palette ), 1.0 );
|
||||
|
||||
result.color = float4( color, 1.0 );
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ struct PS_OUT
|
|||
|
||||
|
||||
#define RESOLUTION_DIVISOR 4.0
|
||||
#define NUM_COLORS 32 // original 27
|
||||
#define NUM_COLORS 31 // original 27
|
||||
|
||||
|
||||
float3 Average( float3 pal[NUM_COLORS] )
|
||||
|
@ -233,46 +233,131 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
#endif
|
||||
};
|
||||
|
||||
#elif 1
|
||||
#elif 0
|
||||
// Tweaked LOSPEC CPC BOY PALETTE which is less saturated by Arne Niklas Jansson
|
||||
// https://lospec.com/palette-list/cpc-boy
|
||||
|
||||
const float3 palette[NUM_COLORS] = // 32
|
||||
{
|
||||
RGB( 0, 0, 0 ),
|
||||
RGB( 36, 49, 55 ),
|
||||
RGB( 27, 27, 101 ),
|
||||
RGB( 53, 53, 201 ),
|
||||
RGB( 102, 30, 37 ),
|
||||
RGB( 85, 51, 97 ),
|
||||
RGB( 127, 53, 201 ),
|
||||
RGB( 188, 53, 53 ),
|
||||
RGB( 192, 70, 110 ),
|
||||
RGB( 223, 109, 155 ),
|
||||
RGB( 27, 101, 27 ),
|
||||
RGB( 27, 110, 131 ),
|
||||
RGB( 30, 121, 229 ),
|
||||
RGB( 102, 30, 37 ),
|
||||
RGB( 63, 80, 63 ),
|
||||
RGB( 85, 51, 97 ),
|
||||
RGB( 121, 95, 27 ),
|
||||
RGB( 128, 128, 128 ),
|
||||
RGB( 145, 148, 223 ),
|
||||
RGB( 201, 127, 53 ),
|
||||
RGB( 227, 155, 141 ),
|
||||
RGB( 248, 120, 248 ),
|
||||
RGB( 27, 110, 131 ),
|
||||
RGB( 53, 175, 53 ),
|
||||
RGB( 118, 132, 72 ),
|
||||
RGB( 188, 53, 53 ),
|
||||
RGB( 53, 53, 201 ),
|
||||
RGB( 128, 128, 128 ),
|
||||
RGB( 192, 70, 110 ),
|
||||
RGB( 53, 183, 143 ),
|
||||
RGB( 53, 193, 215 ),
|
||||
RGB( 127, 201, 53 ),
|
||||
RGB( 127, 53, 201 ),
|
||||
RGB( 201, 127, 53 ),
|
||||
RGB( 30, 121, 229 ),
|
||||
RGB( 172, 181, 107 ),
|
||||
RGB( 223, 109, 155 ),
|
||||
RGB( 53, 193, 215 ),
|
||||
RGB( 145, 148, 223 ),
|
||||
RGB( 225, 198, 67 ),
|
||||
RGB( 227, 155, 141 ),
|
||||
RGB( 173, 200, 170 ),
|
||||
RGB( 141, 225, 199 ),
|
||||
RGB( 225, 198, 67 ),
|
||||
RGB( 228, 221, 154 ),
|
||||
RGB( 255, 255, 255 ),
|
||||
RGB( 248, 120, 248 ),
|
||||
RGB( 238, 234, 224 ),
|
||||
RGB( 172, 181, 107 ),
|
||||
RGB( 118, 132, 72 ),
|
||||
RGB( 63, 80, 63 ),
|
||||
RGB( 36, 49, 55 ),
|
||||
RGB( 255, 255, 255 ),
|
||||
};
|
||||
|
||||
const float3 medianAbsoluteDeviation = RGB( 65, 131, 57 );
|
||||
const float3 deviation = RGB( 66, 57, 63 );
|
||||
|
||||
#elif 1
|
||||
|
||||
// https://lospec.com/palette-list/ruzzi-cpc
|
||||
const float3 palette[NUM_COLORS] = // 31
|
||||
{
|
||||
RGB( 0, 0, 28 ), // dark blue
|
||||
RGB( 28, 0, 28 ), // dark magenta
|
||||
RGB( 33, 30, 32 ),
|
||||
RGB( 85, 85, 104 ),
|
||||
|
||||
RGB( 36, 14, 11 ),
|
||||
RGB( 26, 34, 114 ),
|
||||
RGB( 68, 118, 16 ),
|
||||
RGB( 129, 16, 51 ),
|
||||
RGB( 50, 131, 113 ),
|
||||
RGB( 124, 36, 136 ),
|
||||
RGB( 151, 122, 44 ),
|
||||
RGB( 16, 55, 218 ),
|
||||
RGB( 143, 136, 132 ),
|
||||
RGB( 222, 18, 92 ),
|
||||
RGB( 100, 222, 21 ),
|
||||
RGB( 32, 144, 210 ),
|
||||
RGB( 120, 58, 220 ),
|
||||
RGB( 74, 228, 112 ),
|
||||
RGB( 223, 39, 158 ),
|
||||
RGB( 236, 126, 74 ),
|
||||
RGB( 174, 228, 38 ),
|
||||
RGB( 136, 151, 219 ),
|
||||
RGB( 49, 234, 203 ),
|
||||
RGB( 163, 236, 128 ),
|
||||
RGB( 238, 142, 151 ),
|
||||
RGB( 224, 60, 223 ),
|
||||
RGB( 249, 234, 56 ),
|
||||
RGB( 152, 244, 218 ),
|
||||
RGB( 239, 157, 228 ),
|
||||
RGB( 252, 244, 144 ),
|
||||
RGB( 255, 255, 233 ),
|
||||
};
|
||||
|
||||
const float3 medianAbsoluteDeviation = RGB( 175, 6, 56 );
|
||||
const float3 deviation = RGB( 67, 70, 62 );
|
||||
|
||||
#elif 0
|
||||
|
||||
// https://lospec.com/palette-list/ancientheritage30
|
||||
const float3 palette[NUM_COLORS] = // 30
|
||||
{
|
||||
RGB( 2, 4, 5 ),
|
||||
RGB( 21, 33, 43 ),
|
||||
RGB( 51, 38, 20 ),
|
||||
RGB( 30, 56, 56 ),
|
||||
RGB( 32, 50, 66 ),
|
||||
RGB( 77, 59, 34 ),
|
||||
RGB( 95, 26, 41 ),
|
||||
RGB( 41, 77, 70 ),
|
||||
RGB( 97, 31, 73 ),
|
||||
RGB( 45, 71, 94 ),
|
||||
RGB( 51, 99, 83 ),
|
||||
RGB( 125, 69, 52 ),
|
||||
RGB( 83, 88, 94 ),
|
||||
RGB( 113, 89, 72 ),
|
||||
RGB( 146, 40, 62 ),
|
||||
RGB( 67, 104, 121 ),
|
||||
RGB( 140, 76, 128 ),
|
||||
RGB( 175, 107, 66 ),
|
||||
RGB( 109, 153, 106 ),
|
||||
RGB( 199, 78, 51 ),
|
||||
RGB( 122, 129, 140 ),
|
||||
RGB( 154, 116, 181 ),
|
||||
RGB( 100, 166, 194 ),
|
||||
RGB( 240, 120, 62 ),
|
||||
RGB( 176, 178, 181 ),
|
||||
RGB( 255, 168, 97 ),
|
||||
RGB( 171, 157, 227 ),
|
||||
RGB( 119, 217, 213 ),
|
||||
RGB( 255, 240, 156 ),
|
||||
RGB( 233, 241, 242 ),
|
||||
};
|
||||
|
||||
const float3 medianAbsoluteDeviation = RGB( 87, 12, 60 );
|
||||
const float3 deviation = RGB( 57, 50, 51 );
|
||||
|
||||
#elif 0
|
||||
|
||||
// Atari STE
|
||||
|
@ -354,29 +439,6 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
RGB( 46, 43, 18 ),
|
||||
};
|
||||
|
||||
#elif 0
|
||||
|
||||
// Hollow
|
||||
// https://lospec.com/palette-list/hollow
|
||||
const float3 palette[NUM_COLORS] = // 4
|
||||
{
|
||||
RGB( 15, 15, 27 ),
|
||||
RGB( 86, 90, 117 ),
|
||||
RGB( 198, 183, 190 ),
|
||||
RGB( 250, 251, 246 ),
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
// https://lospec.com/palette-list/2bit-demichrome
|
||||
const float3 palette[NUM_COLORS] = // 4
|
||||
{
|
||||
RGB( 33, 30, 32 ),
|
||||
RGB( 85, 85, 104 ),
|
||||
RGB( 160, 160, 139 ),
|
||||
RGB( 233, 239, 236 ),
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
float2 uv = ( fragment.texcoord0 );
|
||||
|
@ -384,6 +446,7 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
|
||||
float3 quantizationPeriod = _float3( 1.0 / NUM_COLORS );
|
||||
float3 quantDeviation = Deviation( palette );
|
||||
//quantDeviation = medianAbsoluteDeviation;
|
||||
|
||||
// get pixellated base color
|
||||
float4 color = t_BaseColor.Sample( s_LinearClamp, uvPixelated * rpWindowCoord.xy );
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2023 Robert Beckebans
|
||||
Copyright (C) 2024 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
@ -34,8 +34,8 @@ If you have questions concerning this license or the applicable additional terms
|
|||
Texture2D t_BaseColor : register( t0 VK_DESCRIPTOR_SET( 0 ) );
|
||||
Texture2D t_BlueNoise : register( t1 VK_DESCRIPTOR_SET( 0 ) );
|
||||
|
||||
SamplerState samp0 : register(s0 VK_DESCRIPTOR_SET( 1 ) );
|
||||
SamplerState samp1 : register(s1 VK_DESCRIPTOR_SET( 1 ) ); // blue noise 256
|
||||
SamplerState s_LinearClamp : register(s0 VK_DESCRIPTOR_SET( 1 ) );
|
||||
SamplerState s_LinearWrap : register(s1 VK_DESCRIPTOR_SET( 1 ) ); // blue noise 256
|
||||
|
||||
struct PS_IN
|
||||
{
|
||||
|
@ -50,52 +50,345 @@ struct PS_OUT
|
|||
// *INDENT-ON*
|
||||
|
||||
|
||||
#define RESOLUTION_DIVISOR 4.0
|
||||
#define Dithering_QuantizationSteps 8.0 // 8.0 = 2 ^ 3 quantization bits
|
||||
#define RESOLUTION_DIVISOR 4.0
|
||||
#define NUM_COLORS 64 // original 61
|
||||
|
||||
float3 Quantize( float3 color, float3 period )
|
||||
|
||||
// squared distance to avoid the sqrt of distance function
|
||||
float ColorCompare( float3 a, float3 b )
|
||||
{
|
||||
return floor( color * Dithering_QuantizationSteps ) * ( 1.0 / ( Dithering_QuantizationSteps - 1.0 ) );
|
||||
|
||||
//return floor( ( color + period / 2.0 ) / period ) * period;
|
||||
float3 diff = b - a;
|
||||
return dot( diff, diff );
|
||||
}
|
||||
|
||||
|
||||
float3 BlueNoise3( float2 n, float x )
|
||||
// find nearest palette color using Euclidean distance
|
||||
float3 LinearSearch( float3 c, float3 pal[NUM_COLORS] )
|
||||
{
|
||||
float2 uv = n.xy * rpJitterTexOffset.xy;
|
||||
int index = 0;
|
||||
float minDist = ColorCompare( c, pal[0] );
|
||||
|
||||
float3 noise = t_BlueNoise.Sample( samp1, uv ).rgb;
|
||||
for( int i = 1; i < NUM_COLORS; i++ )
|
||||
{
|
||||
float dist = ColorCompare( c, pal[i] );
|
||||
|
||||
noise = frac( noise + c_goldenRatioConjugate * rpJitterTexOffset.w * x );
|
||||
if( dist < minDist )
|
||||
{
|
||||
minDist = dist;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
noise.x = RemapNoiseTriErp( noise.x );
|
||||
noise.y = RemapNoiseTriErp( noise.y );
|
||||
noise.z = RemapNoiseTriErp( noise.z );
|
||||
|
||||
noise = noise * 2.0 - 1.0;
|
||||
|
||||
return noise;
|
||||
return pal[index];
|
||||
}
|
||||
|
||||
#define RGB(r, g, b) float3(float(r)/255.0, float(g)/255.0, float(b)/255.0)
|
||||
|
||||
void main( PS_IN fragment, out PS_OUT result )
|
||||
{
|
||||
#if 0
|
||||
|
||||
// + very colorful
|
||||
// - no blacks
|
||||
// - looks more 8 bit than 16 bit
|
||||
// https://lospec.com/palette-list/meld-plus
|
||||
|
||||
const float3 palette[NUM_COLORS] = // 45
|
||||
{
|
||||
RGB( 0, 0, 55 ),
|
||||
RGB( 30, 13, 78 ),
|
||||
RGB( 0, 60, 69 ),
|
||||
RGB( 81, 6, 44 ),
|
||||
RGB( 82, 48, 55 ),
|
||||
RGB( 76, 2, 91 ),
|
||||
RGB( 64, 47, 93 ),
|
||||
RGB( 0, 89, 86 ),
|
||||
RGB( 19, 33, 120 ),
|
||||
RGB( 64, 60, 105 ),
|
||||
RGB( 79, 10, 138 ),
|
||||
RGB( 149, 18, 58 ),
|
||||
RGB( 135, 14, 87 ),
|
||||
RGB( 33, 165, 63 ),
|
||||
RGB( 95, 92, 128 ),
|
||||
RGB( 29, 84, 177 ),
|
||||
RGB( 131, 97, 144 ),
|
||||
RGB( 189, 101, 55 ),
|
||||
RGB( 205, 80, 24 ),
|
||||
RGB( 4, 182, 146 ),
|
||||
RGB( 156, 130, 119 ),
|
||||
RGB( 209, 57, 103 ),
|
||||
RGB( 53, 135, 210 ),
|
||||
RGB( 133, 223, 83 ),
|
||||
RGB( 13, 233, 142 ),
|
||||
RGB( 255, 94, 67 ),
|
||||
RGB( 149, 154, 187 ),
|
||||
RGB( 194, 42, 218 ),
|
||||
RGB( 230, 167, 88 ),
|
||||
RGB( 255, 130, 87 ),
|
||||
RGB( 255, 153, 51 ),
|
||||
RGB( 197, 180, 161 ),
|
||||
RGB( 210, 154, 173 ),
|
||||
RGB( 97, 212, 255 ),
|
||||
RGB( 152, 255, 192 ),
|
||||
RGB( 231, 255, 125 ),
|
||||
RGB( 249, 132, 237 ),
|
||||
RGB( 251, 227, 163 ),
|
||||
RGB( 242, 230, 179 ),
|
||||
RGB( 255, 231, 160 ),
|
||||
RGB( 255, 211, 200 ),
|
||||
RGB( 247, 236, 206 ),
|
||||
RGB( 209, 234, 251 ),
|
||||
RGB( 255, 205, 243 ),
|
||||
RGB( 255, 255, 255 ),
|
||||
};
|
||||
|
||||
const float3 medianAbsoluteDeviation = RGB( 29, 87, 155 );
|
||||
const float3 deviation = RGB( 80, 72, 55 );
|
||||
|
||||
#elif 1
|
||||
|
||||
// + very good dithering variety at dark grey values
|
||||
// + does not leak too much color into grey values
|
||||
// + good saturation when colors are really needed
|
||||
// - a bit too strong visible dithering pattern
|
||||
// https://lospec.com/palette-list/famicube
|
||||
const float3 palette[NUM_COLORS] = // 64
|
||||
{
|
||||
RGB( 0, 0, 0 ),
|
||||
RGB( 21, 21, 21 ),
|
||||
RGB( 35, 23, 18 ),
|
||||
RGB( 23, 40, 8 ),
|
||||
RGB( 13, 32, 48 ),
|
||||
RGB( 33, 22, 64 ),
|
||||
RGB( 0, 78, 0 ),
|
||||
RGB( 79, 21, 7 ),
|
||||
RGB( 52, 52, 52 ),
|
||||
RGB( 92, 60, 13 ),
|
||||
RGB( 0, 96, 75 ),
|
||||
RGB( 55, 109, 3 ),
|
||||
RGB( 0, 23, 125 ),
|
||||
RGB( 0, 82, 128 ),
|
||||
RGB( 65, 93, 102 ),
|
||||
RGB( 135, 22, 70 ),
|
||||
RGB( 130, 60, 61 ),
|
||||
RGB( 19, 157, 8 ),
|
||||
RGB( 90, 25, 145 ),
|
||||
RGB( 61, 52, 165 ),
|
||||
RGB( 173, 78, 26 ),
|
||||
RGB( 32, 181, 98 ),
|
||||
RGB( 106, 180, 23 ),
|
||||
RGB( 147, 151, 23 ),
|
||||
RGB( 174, 108, 55 ),
|
||||
RGB( 123, 123, 123 ),
|
||||
RGB( 2, 74, 202 ),
|
||||
RGB( 10, 152, 172 ),
|
||||
RGB( 106, 49, 202 ),
|
||||
RGB( 88, 211, 50 ),
|
||||
RGB( 224, 60, 40 ),
|
||||
RGB( 207, 60, 113 ),
|
||||
RGB( 163, 40, 179 ),
|
||||
RGB( 204, 143, 21 ),
|
||||
RGB( 140, 214, 18 ),
|
||||
RGB( 113, 166, 161 ),
|
||||
RGB( 218, 101, 94 ),
|
||||
RGB( 98, 100, 220 ),
|
||||
RGB( 182, 193, 33 ),
|
||||
RGB( 197, 151, 130 ),
|
||||
RGB( 10, 137, 255 ),
|
||||
RGB( 246, 143, 55 ),
|
||||
RGB( 168, 168, 168 ),
|
||||
RGB( 225, 130, 137 ),
|
||||
RGB( 37, 226, 205 ),
|
||||
RGB( 91, 168, 255 ),
|
||||
RGB( 255, 187, 49 ),
|
||||
RGB( 190, 235, 113 ),
|
||||
RGB( 204, 105, 228 ),
|
||||
RGB( 166, 117, 254 ),
|
||||
RGB( 155, 160, 239 ),
|
||||
RGB( 245, 183, 132 ),
|
||||
RGB( 255, 231, 55 ),
|
||||
RGB( 255, 130, 206 ),
|
||||
RGB( 226, 215, 181 ),
|
||||
RGB( 213, 156, 252 ),
|
||||
RGB( 152, 220, 255 ),
|
||||
RGB( 215, 215, 215 ),
|
||||
RGB( 189, 255, 202 ),
|
||||
RGB( 238, 255, 169 ),
|
||||
RGB( 226, 201, 255 ),
|
||||
RGB( 255, 233, 197 ),
|
||||
RGB( 254, 201, 237 ),
|
||||
RGB( 255, 255, 255 ),
|
||||
};
|
||||
|
||||
const float3 medianAbsoluteDeviation = RGB( 63, 175, 2 );
|
||||
const float3 deviation = RGB( 76, 62, 75 );
|
||||
|
||||
#elif 0
|
||||
|
||||
// Resurrect 64 - Most popular 64 colors palette
|
||||
// - leaks too much color into grey scale bar
|
||||
// - dark greys are just dark purple
|
||||
// https://lospec.com/palette-list/resurrect-64
|
||||
|
||||
const float3 palette[NUM_COLORS] = // 64
|
||||
{
|
||||
RGB( 46, 34, 47 ),
|
||||
RGB( 49, 54, 56 ),
|
||||
RGB( 69, 41, 63 ),
|
||||
RGB( 76, 62, 36 ),
|
||||
RGB( 62, 53, 70 ),
|
||||
RGB( 50, 51, 83 ),
|
||||
RGB( 22, 90, 76 ),
|
||||
RGB( 55, 78, 74 ),
|
||||
RGB( 110, 39, 39 ),
|
||||
RGB( 11, 94, 101 ),
|
||||
RGB( 122, 48, 69 ),
|
||||
RGB( 103, 102, 51 ),
|
||||
RGB( 117, 60, 84 ),
|
||||
RGB( 72, 74, 119 ),
|
||||
RGB( 131, 28, 93 ),
|
||||
RGB( 105, 79, 98 ),
|
||||
RGB( 98, 85, 101 ),
|
||||
RGB( 107, 62, 117 ),
|
||||
RGB( 35, 144, 99 ),
|
||||
RGB( 84, 126, 100 ),
|
||||
RGB( 158, 69, 57 ),
|
||||
RGB( 174, 35, 52 ),
|
||||
RGB( 179, 56, 49 ),
|
||||
RGB( 11, 138, 143 ),
|
||||
RGB( 162, 75, 111 ),
|
||||
RGB( 150, 108, 108 ),
|
||||
RGB( 195, 36, 84 ),
|
||||
RGB( 127, 112, 138 ),
|
||||
RGB( 77, 101, 180 ),
|
||||
RGB( 30, 188, 115 ),
|
||||
RGB( 14, 175, 155 ),
|
||||
RGB( 205, 104, 61 ),
|
||||
RGB( 144, 94, 169 ),
|
||||
RGB( 162, 169, 71 ),
|
||||
RGB( 232, 59, 59 ),
|
||||
RGB( 234, 79, 54 ),
|
||||
RGB( 171, 148, 122 ),
|
||||
RGB( 146, 169, 132 ),
|
||||
RGB( 207, 101, 127 ),
|
||||
RGB( 251, 107, 29 ),
|
||||
RGB( 240, 79, 120 ),
|
||||
RGB( 230, 144, 78 ),
|
||||
RGB( 145, 219, 105 ),
|
||||
RGB( 245, 125, 74 ),
|
||||
RGB( 77, 155, 230 ),
|
||||
RGB( 247, 150, 23 ),
|
||||
RGB( 155, 171, 178 ),
|
||||
RGB( 178, 186, 144 ),
|
||||
RGB( 48, 225, 185 ),
|
||||
RGB( 246, 129, 129 ),
|
||||
RGB( 237, 128, 153 ),
|
||||
RGB( 213, 224, 75 ),
|
||||
RGB( 249, 194, 43 ),
|
||||
RGB( 205, 223, 108 ),
|
||||
RGB( 251, 185, 84 ),
|
||||
RGB( 168, 132, 243 ),
|
||||
RGB( 252, 167, 144 ),
|
||||
RGB( 143, 211, 255 ),
|
||||
RGB( 199, 220, 208 ),
|
||||
RGB( 143, 248, 226 ),
|
||||
RGB( 253, 203, 176 ),
|
||||
RGB( 234, 173, 237 ),
|
||||
RGB( 251, 255, 134 ),
|
||||
RGB( 255, 255, 255 ),
|
||||
};
|
||||
|
||||
const float3 medianAbsoluteDeviation = RGB( 94, 43, 86 );
|
||||
const float3 deviation = RGB( 64, 54, 46 );
|
||||
|
||||
#elif 0
|
||||
|
||||
// Endesga 64
|
||||
// + great dithering in the grey scale bar
|
||||
// - makes the game look too grey
|
||||
// https://lospec.com/palette-list/endesga-64
|
||||
|
||||
const float3 palette[NUM_COLORS] = // 64
|
||||
{
|
||||
RGB( 14, 7, 27 ),
|
||||
RGB( 19, 19, 19 ),
|
||||
RGB( 28, 18, 28 ),
|
||||
RGB( 27, 27, 27 ),
|
||||
RGB( 26, 25, 50 ),
|
||||
RGB( 39, 39, 39 ),
|
||||
RGB( 3, 25, 63 ),
|
||||
RGB( 57, 31, 33 ),
|
||||
RGB( 12, 46, 68 ),
|
||||
RGB( 59, 20, 67 ),
|
||||
RGB( 87, 28, 39 ),
|
||||
RGB( 42, 47, 78 ),
|
||||
RGB( 61, 61, 61 ),
|
||||
RGB( 19, 76, 76 ),
|
||||
RGB( 93, 44, 40 ),
|
||||
RGB( 0, 57, 109 ),
|
||||
RGB( 30, 111, 80 ),
|
||||
RGB( 98, 36, 97 ),
|
||||
RGB( 137, 30, 43 ),
|
||||
RGB( 12, 2, 147 ),
|
||||
RGB( 66, 76, 110 ),
|
||||
RGB( 142, 37, 29 ),
|
||||
RGB( 93, 93, 93 ),
|
||||
RGB( 138, 72, 54 ),
|
||||
RGB( 51, 152, 75 ),
|
||||
RGB( 0, 105, 170 ),
|
||||
RGB( 196, 36, 48 ),
|
||||
RGB( 101, 115, 146 ),
|
||||
RGB( 147, 56, 143 ),
|
||||
RGB( 198, 69, 36 ),
|
||||
RGB( 48, 3, 217 ),
|
||||
RGB( 133, 133, 133 ),
|
||||
RGB( 90, 197, 79 ),
|
||||
RGB( 191, 111, 74 ),
|
||||
RGB( 234, 50, 60 ),
|
||||
RGB( 200, 80, 134 ),
|
||||
RGB( 224, 116, 56 ),
|
||||
RGB( 255, 0, 64 ),
|
||||
RGB( 237, 118, 20 ),
|
||||
RGB( 255, 80, 0 ),
|
||||
RGB( 0, 152, 220 ),
|
||||
RGB( 245, 85, 93 ),
|
||||
RGB( 122, 9, 250 ),
|
||||
RGB( 146, 161, 185 ),
|
||||
RGB( 153, 230, 95 ),
|
||||
RGB( 202, 82, 201 ),
|
||||
RGB( 230, 156, 105 ),
|
||||
RGB( 255, 162, 20 ),
|
||||
RGB( 237, 171, 80 ),
|
||||
RGB( 246, 129, 135 ),
|
||||
RGB( 180, 180, 180 ),
|
||||
RGB( 0, 205, 249 ),
|
||||
RGB( 255, 200, 37 ),
|
||||
RGB( 219, 63, 253 ),
|
||||
RGB( 12, 241, 255 ),
|
||||
RGB( 211, 252, 126 ),
|
||||
RGB( 246, 202, 159 ),
|
||||
RGB( 255, 235, 87 ),
|
||||
RGB( 199, 207, 221 ),
|
||||
RGB( 243, 137, 245 ),
|
||||
RGB( 148, 253, 255 ),
|
||||
RGB( 249, 230, 207 ),
|
||||
RGB( 253, 210, 237 ),
|
||||
RGB( 255, 255, 255 ),
|
||||
};
|
||||
|
||||
const float3 medianAbsoluteDeviation = RGB( 33, 166, 46 );
|
||||
const float3 deviation = RGB( 82, 65, 64 );
|
||||
|
||||
#endif
|
||||
|
||||
float2 uv = ( fragment.texcoord0 );
|
||||
float2 uvPixelated = floor( fragment.position.xy / RESOLUTION_DIVISOR ) * RESOLUTION_DIVISOR;
|
||||
|
||||
// the Sega Mega Drive has a 9 bit HW palette making a total of 512 available colors
|
||||
// that is 3 bit per RGB channel
|
||||
// 2^3 = 8
|
||||
// 8 * 8 * 8 = 512 colors
|
||||
// although only 61 colors were available on the screen at the same time but we ignore this for now
|
||||
|
||||
const int quantizationSteps = Dithering_QuantizationSteps;
|
||||
float3 quantizationPeriod = _float3( 1.0 / ( quantizationSteps - 1 ) );
|
||||
float3 quantizationPeriod = _float3( 1.0 / NUM_COLORS );
|
||||
float3 quantDeviation = deviation;
|
||||
//quantDeviation = medianAbsoluteDeviation;
|
||||
|
||||
// get pixellated base color
|
||||
float3 color = t_BaseColor.Sample( samp0, uvPixelated * rpWindowCoord.xy ).rgb;
|
||||
float3 color = t_BaseColor.Sample( s_LinearClamp, uvPixelated * rpWindowCoord.xy ).rgb;
|
||||
|
||||
float2 uvDither = uvPixelated;
|
||||
//if( rpJitterTexScale.x > 1.0 )
|
||||
|
@ -116,7 +409,7 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
{
|
||||
// quantized
|
||||
color = HSVToRGB( float3( uv.x, 1.0, ( uv.y - 0.0625 ) * 16.0 ) );
|
||||
color = Quantize( color, quantizationPeriod );
|
||||
color = LinearSearch( color, palette );
|
||||
|
||||
result.color = float4( color, 1.0 );
|
||||
return;
|
||||
|
@ -126,8 +419,8 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
// dithered quantized
|
||||
color = HSVToRGB( float3( uv.x, 1.0, ( uv.y - 0.125 ) * 16.0 ) );
|
||||
|
||||
color.rgb += float3( dither, dither, dither ) * quantizationPeriod;
|
||||
color = Quantize( color, quantizationPeriod );
|
||||
color.rgb += float3( dither, dither, dither ) * quantDeviation * rpJitterTexScale.y;
|
||||
color = LinearSearch( color, palette );
|
||||
|
||||
result.color = float4( color, 1.0 );
|
||||
return;
|
||||
|
@ -135,14 +428,19 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
else if( uv.y < 0.25 )
|
||||
{
|
||||
color = _float3( uv.x );
|
||||
color = Quantize( color, quantizationPeriod );
|
||||
color = floor( color * NUM_COLORS ) * ( 1.0 / ( NUM_COLORS - 1.0 ) );
|
||||
color += float3( dither, dither, dither ) * quantDeviation * rpJitterTexScale.y;
|
||||
color = LinearSearch( color.rgb, palette );
|
||||
|
||||
result.color = float4( color, 1.0 );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
color.rgb += float3( dither, dither, dither ) * quantizationPeriod;// * rpJitterTexScale.y;
|
||||
color.rgb += float3( dither, dither, dither ) * quantDeviation * rpJitterTexScale.y;
|
||||
|
||||
// find closest color match from Sega Mega Drive color palette
|
||||
color = Quantize( color, quantizationPeriod );
|
||||
// find closest color match from C64 color palette
|
||||
color = LinearSearch( color.rgb, palette );
|
||||
|
||||
result.color = float4( color, 1.0 );
|
||||
}
|
||||
|
|
|
@ -1,306 +0,0 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2024 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "global_inc.hlsl"
|
||||
|
||||
|
||||
// *INDENT-OFF*
|
||||
Texture2D t_BaseColor : register( t0 VK_DESCRIPTOR_SET( 0 ) );
|
||||
Texture2D t_BlueNoise : register( t1 VK_DESCRIPTOR_SET( 0 ) );
|
||||
|
||||
SamplerState s_LinearClamp : register(s0 VK_DESCRIPTOR_SET( 1 ) );
|
||||
SamplerState s_LinearWrap : register(s1 VK_DESCRIPTOR_SET( 1 ) ); // blue noise 256
|
||||
|
||||
struct PS_IN
|
||||
{
|
||||
float4 position : SV_Position;
|
||||
float2 texcoord0 : TEXCOORD0_centroid;
|
||||
};
|
||||
|
||||
struct PS_OUT
|
||||
{
|
||||
float4 color : SV_Target0;
|
||||
};
|
||||
// *INDENT-ON*
|
||||
|
||||
|
||||
#define RESOLUTION_DIVISOR 4.0
|
||||
#define NUM_COLORS 55
|
||||
|
||||
|
||||
float3 Average( float3 pal[NUM_COLORS] )
|
||||
{
|
||||
float3 sum = _float3( 0 );
|
||||
|
||||
for( int i = 0; i < NUM_COLORS; i++ )
|
||||
{
|
||||
sum += pal[i];
|
||||
}
|
||||
|
||||
return sum / float( NUM_COLORS );
|
||||
}
|
||||
|
||||
float3 Deviation( float3 pal[NUM_COLORS] )
|
||||
{
|
||||
float3 sum = _float3( 0 );
|
||||
float3 avg = Average( pal );
|
||||
|
||||
for( int i = 0; i < NUM_COLORS; i++ )
|
||||
{
|
||||
sum += abs( pal[i] - avg );
|
||||
}
|
||||
|
||||
return sum / float( NUM_COLORS );
|
||||
}
|
||||
|
||||
// squared distance to avoid the sqrt of distance function
|
||||
float ColorCompare( float3 a, float3 b )
|
||||
{
|
||||
float3 diff = b - a;
|
||||
return dot( diff, diff );
|
||||
}
|
||||
|
||||
// find nearest palette color using Euclidean distance
|
||||
float3 LinearSearch( float3 c, float3 pal[NUM_COLORS] )
|
||||
{
|
||||
int index = 0;
|
||||
float minDist = ColorCompare( c, pal[0] );
|
||||
|
||||
for( int i = 1; i < NUM_COLORS; i++ )
|
||||
{
|
||||
float dist = ColorCompare( c, pal[i] );
|
||||
|
||||
if( dist < minDist )
|
||||
{
|
||||
minDist = dist;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
return pal[index];
|
||||
}
|
||||
|
||||
|
||||
#define RGB(r, g, b) float3(float(r)/255.0, float(g)/255.0, float(b)/255.0)
|
||||
|
||||
void main( PS_IN fragment, out PS_OUT result )
|
||||
{
|
||||
#if 0
|
||||
|
||||
// NES 1
|
||||
// https://lospec.com/palette-list/nintendo-entertainment-system
|
||||
|
||||
const float3 palette[NUM_COLORS] = // 55
|
||||
{
|
||||
RGB( 0, 0, 0 ),
|
||||
RGB( 252, 252, 252 ),
|
||||
RGB( 248, 248, 248 ),
|
||||
RGB( 188, 188, 188 ),
|
||||
RGB( 124, 124, 124 ),
|
||||
RGB( 164, 228, 252 ),
|
||||
RGB( 60, 188, 252 ),
|
||||
RGB( 0, 120, 248 ),
|
||||
RGB( 0, 0, 252 ),
|
||||
RGB( 184, 184, 248 ),
|
||||
RGB( 104, 136, 252 ),
|
||||
RGB( 0, 88, 248 ),
|
||||
RGB( 0, 0, 188 ),
|
||||
RGB( 216, 184, 248 ),
|
||||
RGB( 152, 120, 248 ),
|
||||
RGB( 104, 68, 252 ),
|
||||
RGB( 68, 40, 188 ),
|
||||
RGB( 248, 184, 248 ),
|
||||
RGB( 248, 120, 248 ),
|
||||
RGB( 216, 0, 204 ),
|
||||
RGB( 148, 0, 132 ),
|
||||
RGB( 248, 164, 192 ),
|
||||
RGB( 248, 88, 152 ),
|
||||
RGB( 228, 0, 88 ),
|
||||
RGB( 168, 0, 32 ),
|
||||
RGB( 240, 208, 176 ),
|
||||
RGB( 248, 120, 88 ),
|
||||
RGB( 248, 56, 0 ),
|
||||
RGB( 168, 16, 0 ),
|
||||
RGB( 252, 224, 168 ),
|
||||
RGB( 252, 160, 68 ),
|
||||
RGB( 228, 92, 16 ),
|
||||
RGB( 136, 20, 0 ),
|
||||
RGB( 248, 216, 120 ),
|
||||
RGB( 248, 184, 0 ),
|
||||
RGB( 172, 124, 0 ),
|
||||
RGB( 80, 48, 0 ),
|
||||
RGB( 216, 248, 120 ),
|
||||
RGB( 184, 248, 24 ),
|
||||
RGB( 0, 184, 0 ),
|
||||
RGB( 0, 120, 0 ),
|
||||
RGB( 184, 248, 184 ),
|
||||
RGB( 88, 216, 84 ),
|
||||
RGB( 0, 168, 0 ),
|
||||
RGB( 0, 104, 0 ),
|
||||
RGB( 184, 248, 216 ),
|
||||
RGB( 88, 248, 152 ),
|
||||
RGB( 0, 168, 68 ),
|
||||
RGB( 0, 88, 0 ),
|
||||
RGB( 0, 252, 252 ),
|
||||
RGB( 0, 232, 216 ),
|
||||
RGB( 0, 136, 136 ),
|
||||
RGB( 0, 64, 88 ),
|
||||
RGB( 248, 216, 248 ),
|
||||
RGB( 120, 120, 120 ),
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
// NES Advanced
|
||||
// https://lospec.com/palette-list/nes-advanced
|
||||
|
||||
const float3 palette[NUM_COLORS] = // 55
|
||||
{
|
||||
RGB( 0, 0, 0 ),
|
||||
RGB( 38, 35, 47 ),
|
||||
RGB( 49, 64, 71 ),
|
||||
RGB( 89, 109, 98 ),
|
||||
RGB( 146, 156, 116 ),
|
||||
RGB( 200, 197, 163 ),
|
||||
RGB( 252, 252, 252 ),
|
||||
RGB( 27, 55, 127 ),
|
||||
RGB( 20, 122, 191 ),
|
||||
RGB( 64, 175, 221 ),
|
||||
RGB( 178, 219, 244 ),
|
||||
RGB( 24, 22, 103 ),
|
||||
RGB( 59, 44, 150 ),
|
||||
RGB( 112, 106, 225 ),
|
||||
RGB( 143, 149, 238 ),
|
||||
RGB( 68, 10, 65 ),
|
||||
RGB( 129, 37, 147 ),
|
||||
RGB( 204, 75, 185 ),
|
||||
RGB( 236, 153, 219 ),
|
||||
RGB( 63, 0, 17 ),
|
||||
RGB( 179, 28, 53 ),
|
||||
RGB( 239, 32, 100 ),
|
||||
RGB( 242, 98, 130 ),
|
||||
RGB( 150, 8, 17 ),
|
||||
RGB( 232, 24, 19 ),
|
||||
RGB( 167, 93, 105 ),
|
||||
RGB( 236, 158, 164 ),
|
||||
RGB( 86, 13, 4 ),
|
||||
RGB( 196, 54, 17 ),
|
||||
RGB( 226, 106, 18 ),
|
||||
RGB( 240, 175, 102 ),
|
||||
RGB( 42, 26, 20 ),
|
||||
RGB( 93, 52, 42 ),
|
||||
RGB( 166, 110, 70 ),
|
||||
RGB( 223, 156, 110 ),
|
||||
RGB( 142, 78, 17 ),
|
||||
RGB( 216, 149, 17 ),
|
||||
RGB( 234, 209, 30 ),
|
||||
RGB( 245, 235, 107 ),
|
||||
RGB( 47, 84, 28 ),
|
||||
RGB( 90, 131, 27 ),
|
||||
RGB( 162, 187, 30 ),
|
||||
RGB( 198, 223, 107 ),
|
||||
RGB( 15, 69, 15 ),
|
||||
RGB( 0, 139, 18 ),
|
||||
RGB( 11, 203, 18 ),
|
||||
RGB( 62, 243, 63 ),
|
||||
RGB( 17, 81, 83 ),
|
||||
RGB( 12, 133, 99 ),
|
||||
RGB( 4, 191, 121 ),
|
||||
RGB( 106, 230, 170 ),
|
||||
RGB( 38, 39, 38 ),
|
||||
RGB( 81, 79, 76 ),
|
||||
RGB( 136, 126, 131 ),
|
||||
RGB( 179, 170, 192 ),
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
float2 uv = ( fragment.texcoord0 );
|
||||
float2 uvPixelated = floor( fragment.position.xy / RESOLUTION_DIVISOR ) * RESOLUTION_DIVISOR;
|
||||
|
||||
float3 quantizationPeriod = _float3( 1.0 / NUM_COLORS );
|
||||
float3 quantDeviation = Deviation( palette );
|
||||
|
||||
// get pixellated base color
|
||||
float3 color = t_BaseColor.Sample( s_LinearClamp, uvPixelated * rpWindowCoord.xy ).rgb;
|
||||
|
||||
float2 uvDither = uvPixelated;
|
||||
//if( rpJitterTexScale.x > 1.0 )
|
||||
{
|
||||
uvDither = fragment.position.xy / ( RESOLUTION_DIVISOR / rpJitterTexScale.x );
|
||||
}
|
||||
float dither = DitherArray8x8( uvDither ) - 0.5;
|
||||
|
||||
#if 0
|
||||
if( uv.y < 0.0625 )
|
||||
{
|
||||
color = HSVToRGB( float3( uv.x, 1.0, uv.y * 16.0 ) );
|
||||
|
||||
result.color = float4( color, 1.0 );
|
||||
return;
|
||||
}
|
||||
else if( uv.y < 0.125 )
|
||||
{
|
||||
// quantized
|
||||
color = HSVToRGB( float3( uv.x, 1.0, ( uv.y - 0.0625 ) * 16.0 ) );
|
||||
color = LinearSearch( color, palette );
|
||||
|
||||
result.color = float4( color, 1.0 );
|
||||
return;
|
||||
}
|
||||
else if( uv.y < 0.1875 )
|
||||
{
|
||||
// dithered quantized
|
||||
color = HSVToRGB( float3( uv.x, 1.0, ( uv.y - 0.125 ) * 16.0 ) );
|
||||
|
||||
color.rgb += float3( dither, dither, dither ) * quantDeviation * rpJitterTexScale.y;
|
||||
color = LinearSearch( color, palette );
|
||||
|
||||
result.color = float4( color, 1.0 );
|
||||
return;
|
||||
}
|
||||
else if( uv.y < 0.25 )
|
||||
{
|
||||
color = _float3( uv.x );
|
||||
color = floor( color * NUM_COLORS ) * ( 1.0 / ( NUM_COLORS - 1.0 ) );
|
||||
color += float3( dither, dither, dither ) * quantDeviation * rpJitterTexScale.y;
|
||||
color = LinearSearch( color.rgb, palette );
|
||||
|
||||
result.color = float4( color, 1.0 );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
color.rgb += float3( dither, dither, dither ) * quantDeviation * rpJitterTexScale.y;
|
||||
|
||||
// find closest color match from C64 color palette
|
||||
color = LinearSearch( color.rgb, palette );
|
||||
|
||||
result.color = float4( color, 1.0 );
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "global_inc.hlsl"
|
||||
|
||||
|
||||
// *INDENT-OFF*
|
||||
struct VS_IN
|
||||
{
|
||||
float4 position : POSITION;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
float4 normal : NORMAL;
|
||||
float4 tangent : TANGENT;
|
||||
float4 color : COLOR0;
|
||||
float4 color2 : COLOR1;
|
||||
};
|
||||
|
||||
struct VS_OUT {
|
||||
float4 position : SV_Position;
|
||||
float2 texcoord0 : TEXCOORD0_centroid;
|
||||
};
|
||||
// *INDENT-ON*
|
||||
|
||||
void main( VS_IN vertex, out VS_OUT result )
|
||||
{
|
||||
result.position = vertex.position;
|
||||
result.position.y = -result.position.y;
|
||||
|
||||
result.texcoord0 = vertex.texcoord;
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2023 Robert Beckebans
|
||||
Copyright (C) 2024 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
|
|
@ -60,8 +60,6 @@ builtin/post/retro_cpc.vs.hlsl -T vs
|
|||
builtin/post/retro_cpc.ps.hlsl -T ps
|
||||
builtin/post/retro_2bit.vs.hlsl -T vs
|
||||
builtin/post/retro_2bit.ps.hlsl -T ps
|
||||
builtin/post/retro_nes.vs.hlsl -T vs
|
||||
builtin/post/retro_nes.ps.hlsl -T ps
|
||||
builtin/post/retro_genesis.vs.hlsl -T vs
|
||||
builtin/post/retro_genesis.ps.hlsl -T ps
|
||||
builtin/post/retro_ps1.vs.hlsl -T vs
|
||||
|
|
|
@ -488,9 +488,14 @@ void Dmap( const idCmdArgs& args )
|
|||
// create AAS files
|
||||
RunAAS_f( args );
|
||||
}
|
||||
|
||||
common->DmapPacifierFilename( passedName, "Done" );
|
||||
}
|
||||
else
|
||||
{
|
||||
common->DmapPacifierFilename( passedName, "Failed due to errors. Quit program." );
|
||||
}
|
||||
|
||||
common->DmapPacifierFilename( passedName, "Done" );
|
||||
|
||||
// free the common .map representation
|
||||
delete dmapGlobals.dmapFile;
|
||||
|
|
|
@ -1234,11 +1234,11 @@ int main( int argc, char** argv )
|
|||
|
||||
Dmap_f( args );
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
// maybe only do this if dmap has a leaked BSP
|
||||
while( true )
|
||||
{
|
||||
bool captureToImage = false;
|
||||
common->UpdateScreen( captureToImage );
|
||||
common->UpdateScreen( false );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -41,14 +41,8 @@ If you have questions concerning this license or the applicable additional terms
|
|||
namespace ImGuiTools
|
||||
{
|
||||
|
||||
// things in impl need to be used in at least one other file, but should generally not be touched
|
||||
namespace impl
|
||||
{
|
||||
|
||||
void SetReleaseToolMouse( bool doRelease );
|
||||
|
||||
} //namespace impl
|
||||
|
||||
bool ReleaseMouseForTools();
|
||||
|
||||
bool AreEditorsActive();
|
||||
|
|
|
@ -40,27 +40,16 @@ If you have questions concerning this license or the applicable additional terms
|
|||
extern idCVar g_editEntityMode;
|
||||
|
||||
static bool releaseMouse = false;
|
||||
#if 0 // currently this doesn't make too much sense
|
||||
void ShowEditors_f( const idCmdArgs& args )
|
||||
{
|
||||
showToolWindows = true;
|
||||
}
|
||||
#endif // 0
|
||||
|
||||
|
||||
namespace ImGuiTools
|
||||
{
|
||||
|
||||
// things in impl need to be used in at least one other file, but should generally not be touched
|
||||
namespace impl
|
||||
{
|
||||
|
||||
void SetReleaseToolMouse( bool doRelease )
|
||||
{
|
||||
releaseMouse = doRelease;
|
||||
}
|
||||
|
||||
} //namespace impl
|
||||
|
||||
bool AreEditorsActive()
|
||||
{
|
||||
// FIXME: this is not exactly clean and must be changed if we ever support game dlls
|
||||
|
@ -69,11 +58,17 @@ bool AreEditorsActive()
|
|||
|
||||
bool ReleaseMouseForTools()
|
||||
{
|
||||
return AreEditorsActive() && releaseMouse;
|
||||
// RB: ignore everything as long right mouse button is pressed
|
||||
return AreEditorsActive() && releaseMouse && !ImGuiHook::RightMouseActive();
|
||||
}
|
||||
|
||||
void DrawToolWindows()
|
||||
{
|
||||
if( !AreEditorsActive() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( LightEditor::Instance().IsShown() )
|
||||
{
|
||||
LightEditor::Instance().Draw();
|
||||
|
@ -98,7 +93,7 @@ void LightEditorInit( const idDict* dict, idEntity* ent )
|
|||
|
||||
|
||||
LightEditor::Instance().ShowIt( true );
|
||||
impl::SetReleaseToolMouse( true );
|
||||
SetReleaseToolMouse( true );
|
||||
|
||||
LightEditor::ReInit( dict, ent );
|
||||
}
|
||||
|
@ -106,7 +101,7 @@ void LightEditorInit( const idDict* dict, idEntity* ent )
|
|||
void AfEditorInit()
|
||||
{
|
||||
AfEditor::Instance().ShowIt( true );
|
||||
impl::SetReleaseToolMouse( true );
|
||||
SetReleaseToolMouse( true );
|
||||
}
|
||||
|
||||
} //namespace ImGuiTools
|
||||
|
|
|
@ -196,7 +196,7 @@ void AfEditor::Draw()
|
|||
|
||||
if( ImGui::Begin( "AF Editor", &showTool, ImGuiWindowFlags_MenuBar ) )
|
||||
{
|
||||
impl::SetReleaseToolMouse( true );
|
||||
SetReleaseToolMouse( true );
|
||||
|
||||
bool changedAf = false;
|
||||
bool openedAfBrowser = false;
|
||||
|
@ -571,7 +571,7 @@ void AfEditor::Draw()
|
|||
{
|
||||
// TODO: do the same as when pressing cancel?
|
||||
isShown = showTool;
|
||||
impl::SetReleaseToolMouse( false );
|
||||
SetReleaseToolMouse( false );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1017,9 +1017,9 @@ void LightEditor::Draw()
|
|||
|
||||
ImGui::Spacing();
|
||||
|
||||
if( ImGui::Button( "Save to .map" ) )
|
||||
if( ImGui::Button( "Apply" ) )
|
||||
{
|
||||
SaveChanges( true );
|
||||
SaveChanges( false );
|
||||
showTool = false;
|
||||
}
|
||||
else if( ImGui::SameLine(), ImGui::Button( "Cancel" ) )
|
||||
|
@ -1229,7 +1229,7 @@ void LightEditor::Draw()
|
|||
if( isShown && !showTool )
|
||||
{
|
||||
isShown = showTool;
|
||||
impl::SetReleaseToolMouse( false );
|
||||
SetReleaseToolMouse( false );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue