Merge branch '497-envprobe-rendertarget'

This commit is contained in:
Robert Beckebans 2021-03-26 11:20:53 +01:00
commit d9112cd381
34 changed files with 76043 additions and 506 deletions

10
base/def/env_probe.def Normal file
View file

@ -0,0 +1,10 @@
entityDef env_probe
{
"editor_color" "0 0 1"
"editor_mins" "-8 -8 -8"
"editor_maxs" " 8 8 8"
"editor_usage" "Environment probe for Image Based Lighting"
"spawnclass" "EnvironmentProbe"
}

169
base/def/misc.def Normal file
View file

@ -0,0 +1,169 @@
/***********************************************************************
miscellaneous
***********************************************************************/
entityDef worldspawn {
"editor_color" "0 0 0"
"editor_mins" "?"
"editor_maxs" "?"
"editor_usage" "Every map should have exactly one worldspawn."
"editor_var music" "music wav file."
"editor_var gravity" "gravity value for the level."
"editor_var no_stamina" "disables stamina so the player can always run"
"editor_var no_Weapons" "only fists and no melee attacks"
"editor_var def_player" "player def to use when spawning this world"
"spawnclass" "idWorldspawn"
"gravity" "1066"
"name" "world"
}
entityDef light {
"editor_color" "0 1 0"
"editor_mins" "-8 -8 -8"
"editor_maxs" "8 8 8"
"editor_rotatable" "1"
"editor_usage" "Light source. If health is set, light becomes breakable and turns off when shot."
"editor_material texture" "light shader to use."
"editor_color color" "light color"
"editor_var shaderParm3" "shaderParm 3"
"editor_var shaderParm4" "shaderParm 4"
"editor_var shaderParm5" "shaderParm 5"
"editor_var shaderParm6" "shaderParm 6"
"editor_var shaderParm7" "shaderParm 7"
"editor_var count" "how many times light must be triggered to toggle."
"editor_var break" "break when triggered."
"editor_model model" "model to use."
"editor_model broken" "model to use when the light is broken (defaults to model name with '_broken' appended to name)"
"editor_var hideModelOnBreak" "hides the model when broken"
"editor_var health" "amount of damage to recieve before becoming broken. 0 is nonbreakable."
"editor_var target" "entities to trigger if shot."
"editor_var levels" "the number of times a light must be triggered until it turns off. Each time it's triggered, it's dimmed to a lower level."
"editor_var start_off" "causes the light to be off when the level starts."
"editor_var snd_broken" "sound shader to use when broken"
"editor_var mtr_broken" "material to use when broken"
"editor_color color_demonic" "demonic color to use if in demonic mode."
"editor_material mat_demonic" "demonic shader to use if in demonic mode."
"editor_var leave_demonic_mat" "leaves the demonic shader when the effect expires.. color is still reverted back."
"spawnclass" "idLight"
"health" "0"
"levels" "1"
"start_off" "0"
"count" "1"
"break" "0"
// jmarshall: Quake 1 light styles
/*
"style" "-1"
"ls_frametime" "100"
"num_styles" "12"
"light_style0" "m"
"light_style1" "mmnmmommommnonmmonqnmmo"
"light_style2" "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba"
"light_style3" "mmmmmaaaaammmmmaaaaaabcdefgabcdefg"
"light_style4" "mamamamamama"
"light_style5" "jklmnopqrstuvwxyzyxwvutsrqponmlkj"
"light_style6" "nmonqnmomnmomomno"
"light_style7" "mmmaaaabcdefgmmmmaaaammmaamm"
"light_style8" "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa"
"light_style9" "aaaaaaaazzzzzzzz"
"light_style10" "mmamammmmammamamaaamammma"
"light_style11" "abcdefghijklmnopqrrqponmlkjihgfedcba"
*/
// jmarshall end
}
entityDef speaker {
"editor_color" "0 1 0"
"editor_mins" "-8 -8 -8"
"editor_maxs" "8 8 8"
"editor_material" "textures/common/speaker"
"editor_usage" ""
"editor_snd s_shader" "the sound shader or wavefile."
"editor_snd snd_demonic" "demonic sound shader."
"editor_var overlayDemonic" "set to 1 overlays the demonic sound instead of replacing it."
"editor_var s_waitfortrigger" "play on load or play when triggered."
"editor_var s_volume" "override shader volume level."
"editor_var s_minDistance" "override shader minDistance."
"editor_var s_maxDistance" "override shader maxDistance."
"editor_var s_omni" "force omnidirectional"
"editor_var s_looping" "force looping"
"editor_var s_occlusion" "force no portal occlusion"
"editor_var s_global" "force no falloff at all"
"editor_var s_shakes" "this entity can make the screen shake when the sound is loud."
"editor_var wait" "when set > 0, seconds between triggerings. time between sounds is wait + or - random"
"editor_var random" "wait variance."
"spawnclass" "idSound"
}
entityDef info_location {
"editor_color" "1 1 0"
"editor_mins" "-4 -4 -4"
"editor_maxs" "4 4 4"
"editor_usage" "Place one of these in each door-separated area for naming the gameplay sections"
"editor_var name" "location name for HUD. Cannot be the same as any other entity in the game."
"editor_var location" "use this when you have two locations with the same name."
"spawnclass" "idLocationEntity"
}
entityDef info_locationSeparator {
"editor_color" "1 1 0"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Touch a vis-portal with this to break location name flood filling without using a door"
"spawnclass" "idLocationSeparatorEntity"
}
entityDef info_vacuum {
"editor_color" "1 1 0"
"editor_mins" "-4 -4 -4"
"editor_maxs" "4 4 4"
"editor_usage" "Place one of these in an outside area in each map for vacuum flooding"
"spawnclass" "idVacuumEntity"
}
entityDef info_vacuumSeparator {
"editor_color" "1 1 0"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Touch a vis-portal with this to break air/vacuum flood filling at windows. Trigger it to allow vacuum to flood through."
"spawnclass" "idVacuumSeparatorEntity"
}
entityDef text {
"editor_color" "1 1 0"
"editor_mins" "-4 -4 -4"
"editor_maxs" "4 4 4"
"editor_showangle" "1"
"editor_rotatable" "1"
"editor_usage" "Used to display debug text in a level"
"editor_var text" "text to print"
"editor_var force" "if set to 1 prints always otherwise only in developer mode"
"editor_var playerOriented" "if set to 1 text always faces the player"
"spawnclass" "idTextEntity"
}

16
base/devtools.cfg Normal file
View file

@ -0,0 +1,16 @@
bind "I" "toggle r_showSurfaceInfo"
bind "N" "noclip"
bind "M" "spawn moveable_macbethchart"
bind "F1" "toggle r_showViewEnvprobes 1 2 0"
bind "F2" "toggle r_showTris 1 2 3 0"
bind "F3" "toggle r_forceAmbient 0.2 0.3 0.0001"
bind "F4" "toggle r_skipInteractions"
bind "F5" "savegame quick"
bind "F6" "toggle r_hdrDebug"
bind "F7" "toggle r_useSSAO"
bind "F8" "toggle r_useFilmicPostProcessing"
bind "F9" "loadgame quick"
bind "F10" "toggle com_fixedTic"
bind "F11" "toggle r_pbrDebug"

79
base/modelviewer.cfg Normal file
View file

@ -0,0 +1,79 @@
// model viewer
bind kp_5 "toggle pm_thirdPerson;vstr a0;vstr r40;vstr h0"
bind kp_uparrow "vstr closer"
bind kp_downarrow "vstr farther"
bind kp_leftarrow "vstr left"
bind kp_rightarrow "vstr right"
bind kp_pgdn "vstr lower"
bind kp_pgup "vstr higher"
set a0 "pm_thirdPersonAngle 0;set left vstr a10;set right vstr a350"
set a10 "pm_thirdPersonAngle 10;set left vstr a20;set right vstr a0"
set a20 "pm_thirdPersonAngle 20;set left vstr a30;set right vstr a10"
set a30 "pm_thirdPersonAngle 30;set left vstr a40;set right vstr a20"
set a40 "pm_thirdPersonAngle 40;set left vstr a50;set right vstr a30"
set a50 "pm_thirdPersonAngle 50;set left vstr a60;set right vstr a40"
set a60 "pm_thirdPersonAngle 60;set left vstr a70;set right vstr a50"
set a70 "pm_thirdPersonAngle 70;set left vstr a80;set right vstr a60"
set a80 "pm_thirdPersonAngle 80;set left vstr a90;set right vstr a70"
set a90 "pm_thirdPersonAngle 90;set left vstr a100;set right vstr a80"
set a100 "pm_thirdPersonAngle 100;set left vstr a110;set right vstr a90"
set a110 "pm_thirdPersonAngle 110;set left vstr a120;set right vstr a100"
set a120 "pm_thirdPersonAngle 120;set left vstr a130;set right vstr a110"
set a130 "pm_thirdPersonAngle 130;set left vstr a140;set right vstr a120"
set a140 "pm_thirdPersonAngle 140;set left vstr a150;set right vstr a130"
set a150 "pm_thirdPersonAngle 150;set left vstr a160;set right vstr a140"
set a160 "pm_thirdPersonAngle 160;set left vstr a170;set right vstr a150"
set a170 "pm_thirdPersonAngle 170;set left vstr a180;set right vstr a160"
set a180 "pm_thirdPersonAngle 180;set left vstr a190;set right vstr a170"
set a190 "pm_thirdPersonAngle 190;set left vstr a200;set right vstr a180"
set a200 "pm_thirdPersonAngle 200;set left vstr a210;set right vstr a190"
set a210 "pm_thirdPersonAngle 210;set left vstr a220;set right vstr a200"
set a220 "pm_thirdPersonAngle 220;set left vstr a230;set right vstr a210"
set a230 "pm_thirdPersonAngle 230;set left vstr a240;set right vstr a220"
set a240 "pm_thirdPersonAngle 240;set left vstr a250;set right vstr a230"
set a250 "pm_thirdPersonAngle 250;set left vstr a260;set right vstr a240"
set a260 "pm_thirdPersonAngle 260;set left vstr a270;set right vstr a250"
set a270 "pm_thirdPersonAngle 270;set left vstr a280;set right vstr a260"
set a280 "pm_thirdPersonAngle 280;set left vstr a290;set right vstr a270"
set a290 "pm_thirdPersonAngle 290;set left vstr a300;set right vstr a280"
set a300 "pm_thirdPersonAngle 300;set left vstr a310;set right vstr a290"
set a310 "pm_thirdPersonAngle 310;set left vstr a320;set right vstr a300"
set a320 "pm_thirdPersonAngle 320;set left vstr a330;set right vstr a310"
set a330 "pm_thirdPersonAngle 330;set left vstr a340;set right vstr a320"
set a340 "pm_thirdPersonAngle 340;set left vstr a350;set right vstr a330"
set a350 "pm_thirdPersonAngle 350;set left vstr a0;set right vstr a340"
set r5 "pm_thirdPersonRange 5;set farther vstr r10;set closer vstr r500"
set r10 "pm_thirdPersonRange 10;set farther vstr r20;set closer vstr r5"
set r20 "pm_thirdPersonRange 20;set farther vstr r30;set closer vstr r10"
set r30 "pm_thirdPersonRange 30;set farther vstr r40;set closer vstr r20"
set r40 "pm_thirdPersonRange 40;set farther vstr r50;set closer vstr r30"
set r50 "pm_thirdPersonRange 50;set farther vstr r60;set closer vstr r40"
set r60 "pm_thirdPersonRange 60;set farther vstr r70;set closer vstr r50"
set r70 "pm_thirdPersonRange 70;set farther vstr r80;set closer vstr r60"
set r80 "pm_thirdPersonRange 80;set farther vstr r90;set closer vstr r70"
set r90 "pm_thirdPersonRange 90;set farther vstr r100;set closer vstr r80"
set r100 "pm_thirdPersonRange 100;set farther vstr r120;set closer vstr r90"
set r120 "pm_thirdPersonRange 120;set farther vstr r140;set closer vstr r100"
set r140 "pm_thirdPersonRange 140;set farther vstr r160;set closer vstr r120"
set r160 "pm_thirdPersonRange 160;set farther vstr r180;set closer vstr r140"
set r180 "pm_thirdPersonRange 180;set farther vstr r200;set closer vstr r160"
set r200 "pm_thirdPersonRange 200;set farther vstr r220;set closer vstr r180"
set r220 "pm_thirdPersonRange 220;set farther vstr r240;set closer vstr r200"
set r240 "pm_thirdPersonRange 240;set farther vstr r260;set closer vstr r220"
set r260 "pm_thirdPersonRange 260;set farther vstr r280;set closer vstr r240"
set r280 "pm_thirdPersonRange 280;set farther vstr r300;set closer vstr r260"
set r300 "pm_thirdPersonRange 300;set farther vstr r350;set closer vstr r280"
set r350 "pm_thirdPersonRange 350;set farther vstr r400;set closer vstr r300"
set r400 "pm_thirdPersonRange 400;set farther vstr r500;set closer vstr r350"
set r500 "pm_thirdPersonRange 500;set farther vstr r5;set closer vstr r400"
set h0 "pm_thirdPersonHeight 0;set lower vstr h10;set higher vstr h70"
set h10 "pm_thirdPersonHeight -10;set lower vstr h20;set higher vstr h5"
set h20 "pm_thirdPersonHeight -20;set lower vstr h30;set higher vstr h10"
set h30 "pm_thirdPersonHeight -30;set lower vstr h40;set higher vstr h20"
set h40 "pm_thirdPersonHeight -40;set lower vstr h50;set higher vstr h30"
set h50 "pm_thirdPersonHeight -50;set lower vstr h60;set higher vstr h40"
set h60 "pm_thirdPersonHeight -60;set lower vstr h70;set higher vstr h50"
set h70 "pm_thirdPersonHeight -70;set lower vstr h0;set higher vstr h60"

View file

@ -489,6 +489,12 @@ file(GLOB IRRXML_SOURCES libs/irrxml/src/*.cpp)
file(GLOB IMGUI_INCLUDES libs/imgui/*.h)
file(GLOB IMGUI_SOURCES libs/imgui/*.cpp)
file(GLOB STB_INCLUDES libs/stb/*.h)
file(GLOB MESA_INCLUDES libs/mesa/*.h)
file(GLOB TINYEXR_INCLUDES libs/tinyexr/*.h)
file(GLOB MIKKTSPACE_INCLUDES libs/mikktspace/*.h)
file(GLOB MIKKTSPACE_SOURCES libs/mikktspace/*.c)
@ -708,7 +714,6 @@ file(GLOB UI_SOURCES ui/*.cpp)
file(GLOB SWF_INCLUDES swf/*.h)
file(GLOB SWF_SOURCES swf/*.cpp)
set(GAMED3XP_INCLUDES
d3xp/Achievements.h
d3xp/Actor.h
@ -1111,6 +1116,12 @@ source_group("libs\\irrxml" FILES ${IRRXML_SOURCES})
source_group("libs\\imgui" FILES ${IMGUI_INCLUDES})
source_group("libs\\imgui" FILES ${IMGUI_SOURCES})
source_group("libs\\stb" FILES ${STB_INCLUDES})
source_group("libs\\mesa" FILES ${MESA_INCLUDES})
source_group("libs\\tinyexr" FILES ${TINYEXR_INCLUDES})
source_group("libs\\mikktspace" FILES ${MIKKTSPACE_INCLUDES})
source_group("libs\\mikktspace" FILES ${MIKKTSPACE_SOURCES})
@ -1300,6 +1311,9 @@ set(RBDOOM3_INCLUDES
${IRRXML_INCLUDES}
${FRAMEWORK_IMGUI_INCLUDES}
${IMGUI_INCLUDES}
${STB_INCLUDES}
${MESA_INCLUDES}
${TINYEXR_INCLUDES}
${MIKKTSPACE_INCLUDES}
${JPEG_INCLUDES}
${PNG_INCLUDES}

View file

@ -4,6 +4,9 @@ astyle.exe -v --formatted --options=astyle-options.ini --exclude="libs" --exclud
astyle.exe -v --formatted --options=astyle-options.ini --recursive libs/imgui/*.h
astyle.exe -v --formatted --options=astyle-options.ini --recursive libs/imgui/*.cpp
astyle.exe -v --formatted --options=astyle-options.ini --recursive libs/stb/*.h
astyle.exe -v --formatted --options=astyle-options.ini --recursive libs/tinyexr/*.h
astyle.exe -v -Q --options=astyle-options.ini --recursive ../base/renderprogs/*.hlsl
pause

View file

@ -1266,7 +1266,7 @@ extern void Sys_CPUCount( int& logicalNum, int& coreNum, int& packageNum );
// Hyperthreading is not dead yet. Intel's Core i7 Processor is quad-core with HT for 8 logicals.
// DOOM3: We don't have that many jobs, so just set this fairly low so we don't spin up a ton of idle threads
#define MAX_JOB_THREADS 2
#define MAX_JOB_THREADS 32
#define NUM_JOB_THREADS "2"
#define JOB_THREAD_CORES { CORE_ANY, CORE_ANY, CORE_ANY, CORE_ANY, \
CORE_ANY, CORE_ANY, CORE_ANY, CORE_ANY, \

View file

@ -0,0 +1,277 @@
/*
* Copyright (C) 2011 Marek Olšák <maraeo@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/* Based on code from The OpenGL Programming Guide / 7th Edition, Appendix J.
* Available here: http://www.opengl-redbook.com/appendices/
* The algorithm in the book contains a bug though, which is fixed in the code
* below.
*/
#ifndef FORMAT_R11G11B10F_H
#define FORMAT_R11G11B10F_H
#include <stdint.h>
#define UF11(e, m) ((e << 6) | (m))
#define UF11_EXPONENT_BIAS 15
#define UF11_EXPONENT_BITS 0x1F
#define UF11_EXPONENT_SHIFT 6
#define UF11_MANTISSA_BITS 0x3F
#define UF11_MANTISSA_SHIFT (23 - UF11_EXPONENT_SHIFT)
#define UF11_MAX_EXPONENT (UF11_EXPONENT_BITS << UF11_EXPONENT_SHIFT)
#define UF10(e, m) ((e << 5) | (m))
#define UF10_EXPONENT_BIAS 15
#define UF10_EXPONENT_BITS 0x1F
#define UF10_EXPONENT_SHIFT 5
#define UF10_MANTISSA_BITS 0x1F
#define UF10_MANTISSA_SHIFT (23 - UF10_EXPONENT_SHIFT)
#define UF10_MAX_EXPONENT (UF10_EXPONENT_BITS << UF10_EXPONENT_SHIFT)
#define F32_INFINITY 0x7f800000
static inline uint32_t f32_to_uf11( float val )
{
union
{
float f;
uint32_t ui;
} f32 = {val};
uint16_t uf11 = 0;
/* Decode little-endian 32-bit floating-point value */
int sign = ( f32.ui >> 16 ) & 0x8000;
/* Map exponent to the range [-127,128] */
int exponent = ( ( f32.ui >> 23 ) & 0xff ) - 127;
int mantissa = f32.ui & 0x007fffff;
if( exponent == 128 ) /* Infinity or NaN */
{
/* From the GL_EXT_packed_float spec:
*
* "Additionally: negative infinity is converted to zero; positive
* infinity is converted to positive infinity; and both positive and
* negative NaN are converted to positive NaN."
*/
uf11 = UF11_MAX_EXPONENT;
if( mantissa )
{
uf11 |= 1; /* NaN */
}
else
{
if( sign )
{
uf11 = 0; /* 0.0 */
}
}
}
else if( sign )
{
return 0;
}
else if( val > 65024.0f )
{
/* From the GL_EXT_packed_float spec:
*
* "Likewise, finite positive values greater than 65024 (the maximum
* finite representable unsigned 11-bit floating-point value) are
* converted to 65024."
*/
uf11 = UF11( 30, 63 );
}
else if( exponent > -15 ) /* Representable value */
{
exponent += UF11_EXPONENT_BIAS;
mantissa >>= UF11_MANTISSA_SHIFT;
uf11 = exponent << UF11_EXPONENT_SHIFT | mantissa;
}
return uf11;
}
static inline float uf11_to_f32( uint16_t val )
{
union
{
float f;
uint32_t ui;
} f32;
int exponent = ( val & 0x07c0 ) >> UF11_EXPONENT_SHIFT;
int mantissa = ( val & 0x003f );
f32.f = 0.0;
if( exponent == 0 )
{
if( mantissa != 0 )
{
const float scale = 1.0 / ( 1 << 20 );
f32.f = scale * mantissa;
}
}
else if( exponent == 31 )
{
f32.ui = F32_INFINITY | mantissa;
}
else
{
float scale, decimal;
exponent -= 15;
if( exponent < 0 )
{
scale = 1.0f / ( 1 << -exponent );
}
else
{
scale = ( float )( 1 << exponent );
}
decimal = 1.0f + ( float ) mantissa / 64;
f32.f = scale * decimal;
}
return f32.f;
}
static inline uint32_t f32_to_uf10( float val )
{
union
{
float f;
uint32_t ui;
} f32 = {val};
uint16_t uf10 = 0;
/* Decode little-endian 32-bit floating-point value */
int sign = ( f32.ui >> 16 ) & 0x8000;
/* Map exponent to the range [-127,128] */
int exponent = ( ( f32.ui >> 23 ) & 0xff ) - 127;
int mantissa = f32.ui & 0x007fffff;
if( exponent == 128 )
{
/* From the GL_EXT_packed_float spec:
*
* "Additionally: negative infinity is converted to zero; positive
* infinity is converted to positive infinity; and both positive and
* negative NaN are converted to positive NaN."
*/
uf10 = UF10_MAX_EXPONENT;
if( mantissa )
{
uf10 |= 1; /* NaN */
}
else
{
if( sign )
{
uf10 = 0; /* 0.0 */
}
}
}
else if( sign )
{
return 0;
}
else if( val > 64512.0f )
{
/* From the GL_EXT_packed_float spec:
*
* "Likewise, finite positive values greater than 64512 (the maximum
* finite representable unsigned 10-bit floating-point value) are
* converted to 64512."
*/
uf10 = UF10( 30, 31 );
}
else if( exponent > -15 ) /* Representable value */
{
exponent += UF10_EXPONENT_BIAS;
mantissa >>= UF10_MANTISSA_SHIFT;
uf10 = exponent << UF10_EXPONENT_SHIFT | mantissa;
}
return uf10;
}
static inline float uf10_to_f32( uint16_t val )
{
union
{
float f;
uint32_t ui;
} f32;
int exponent = ( val & 0x03e0 ) >> UF10_EXPONENT_SHIFT;
int mantissa = ( val & 0x001f );
f32.f = 0.0;
if( exponent == 0 )
{
if( mantissa != 0 )
{
const float scale = 1.0 / ( 1 << 19 );
f32.f = scale * mantissa;
}
}
else if( exponent == 31 )
{
f32.ui = F32_INFINITY | mantissa;
}
else
{
float scale, decimal;
exponent -= 15;
if( exponent < 0 )
{
scale = 1.0f / ( 1 << -exponent );
}
else
{
scale = ( float )( 1 << exponent );
}
decimal = 1.0f + ( float ) mantissa / 32;
f32.f = scale * decimal;
}
return f32.f;
}
static inline uint32_t float3_to_r11g11b10f( const float rgb[3] )
{
return ( f32_to_uf11( rgb[0] ) & 0x7ff ) |
( ( f32_to_uf11( rgb[1] ) & 0x7ff ) << 11 ) |
( ( f32_to_uf10( rgb[2] ) & 0x3ff ) << 22 );
}
static inline void r11g11b10f_to_float3( uint32_t rgb, float retval[3] )
{
retval[0] = uf11_to_f32( rgb & 0x7ff );
retval[1] = uf11_to_f32( ( rgb >> 11 ) & 0x7ff );
retval[2] = uf10_to_f32( ( rgb >> 22 ) & 0x3ff );
}
#endif /* FORMAT_R11G11B10F_H */

10242
neo/libs/stb/stb_image.h Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

17730
neo/libs/tinyexr/tinyexr.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -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-2016 Robert Beckebans
Copyright (C) 2014-2021 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").
@ -43,6 +43,8 @@ If you have questions concerning this license or the applicable additional terms
#include "DXT/DXTCodec.h"
#include "Color/ColorSpace.h"
#include "../libs/mesa/format_r11g11b10f.h"
idCVar image_highQualityCompression( "image_highQualityCompression", "0", CVAR_BOOL, "Use high quality (slow) compression" );
idCVar r_useHighQualitySky( "r_useHighQualitySky", "1", CVAR_BOOL | CVAR_ARCHIVE, "Use high quality skyboxes" );
@ -249,6 +251,15 @@ void idBinaryImage::Load2DFromMemory( int width, int height, const byte* pic_con
img.data[ i ] = pic[ i ];
}
}
else if( textureFormat == FMT_R11G11B10F )
{
// 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_RGBA16F )
{
img.Alloc( scaledWidth * scaledHeight * 8 );
@ -294,6 +305,319 @@ void idBinaryImage::Load2DFromMemory( int width, int height, const byte* pic_con
Mem_Free( pic );
}
/*
========================
RB idBinaryImage::Load2DAtlasMipchainFromMemory
========================
*/
void idBinaryImage::Load2DAtlasMipchainFromMemory( int width, int height, const byte* pic_const, int numLevels, textureFormat_t& textureFormat, textureColor_t& colorFormat )
{
int sourceWidth = width * ( 2.0f / 3.0f ); // RB
fileData.textureType = TT_2D;
fileData.format = textureFormat;
fileData.colorFormat = CFM_DEFAULT;
fileData.width = sourceWidth;
fileData.height = height;
fileData.numLevels = numLevels;
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d)", width, height ) );
byte* sourcePic = ( byte* )Mem_Alloc( width * height * 4, TAG_TEMP );
memcpy( sourcePic, pic_const, width * height * 4 );
if( colorFormat == CFM_YCOCG_DXT5 )
{
// convert the image data to YCoCg and use the YCoCgDXT5 compressor
idColorSpace::ConvertRGBToCoCg_Y( sourcePic, sourcePic, width, height );
}
else if( colorFormat == CFM_NORMAL_DXT5 )
{
// Blah, HQ swizzles automatically, Fast doesn't
if( !image_highQualityCompression.GetBool() )
{
for( int i = 0; i < width * height; i++ )
{
sourcePic[i * 4 + 3] = sourcePic[i * 4 + 0];
sourcePic[i * 4 + 0] = 0;
sourcePic[i * 4 + 2] = 0;
}
}
}
else if( colorFormat == CFM_GREEN_ALPHA )
{
for( int i = 0; i < width * height; i++ )
{
sourcePic[i * 4 + 1] = sourcePic[i * 4 + 3];
sourcePic[i * 4 + 0] = 0;
sourcePic[i * 4 + 2] = 0;
sourcePic[i * 4 + 3] = 0;
}
}
images.SetNum( numLevels );
const int numColors = 5;
static idVec4 colors[numColors] = { colorBlue, colorCyan, colorGreen, colorYellow, colorRed };
for( int level = 0; level < images.Num(); level++ )
{
idBinaryImageData& img = images[ level ];
// RB: create shrunk image which is a copy of the sub image in the atlas
idVec4 rect = R_CalculateMipRect( sourceWidth, level );
int scaledWidth = rect.z;
int scaledHeight = rect.w;
byte* pic = ( byte* )Mem_Alloc( scaledWidth * scaledHeight * 4, TAG_TEMP );
for( int x = rect.x; x < ( rect.x + rect.z ); x++ )
//for( int x = 0; x < rect.z; x++ )
{
for( int y = rect.y; y < ( rect.y + rect.w ); y++ )
//for( int y = 0; y < rect.w; y++ )
{
int sx = x - rect.x;
int sy = y - rect.y;
#if 1
pic[( sy * scaledWidth + sx ) * 4 + 0] = sourcePic[( y * width + x ) * 4 + 0];
pic[( sy * scaledWidth + sx ) * 4 + 1] = sourcePic[( y * width + x ) * 4 + 1];
pic[( sy * scaledWidth + sx ) * 4 + 2] = sourcePic[( y * width + x ) * 4 + 2];
pic[( sy * scaledWidth + sx ) * 4 + 3] = sourcePic[( y * width + x ) * 4 + 3];
#else
int colorIdx = level % numColors;
float color[3];
color[0] = colors[ colorIdx ].x;
color[0] = colors[ colorIdx ].y;
color[0] = colors[ colorIdx ].z;
uint32_t value = float3_to_r11g11b10f( color );
union
{
uint32 i;
byte b[4];
} tmp;
tmp.i = value;
//*( uint32_t* )pic[( sy * scaledWidth + sx ) * 3] = value;
pic[( sy * scaledWidth + sx ) * 4 + 0] = tmp.b[0];
pic[( sy * scaledWidth + sx ) * 4 + 1] = tmp.b[1];
pic[( sy * scaledWidth + sx ) * 4 + 2] = tmp.b[2];
pic[( sy * scaledWidth + sx ) * 4 + 3] = tmp.b[3];
#endif
}
}
// RB end
commonLocal.LoadPacifierBinarizeMiplevel( level + 1, numLevels );
// Images that are going to be DXT compressed and aren't multiples of 4 need to be
// padded out before compressing.
byte* dxtPic = pic;
int dxtWidth = 0;
int dxtHeight = 0;
if( textureFormat == FMT_DXT5 || textureFormat == FMT_DXT1 )
{
if( ( scaledWidth & 3 ) || ( scaledHeight & 3 ) )
{
dxtWidth = ( scaledWidth + 3 ) & ~3;
dxtHeight = ( scaledHeight + 3 ) & ~3;
dxtPic = ( byte* )Mem_ClearedAlloc( dxtWidth * 4 * dxtHeight, TAG_IMAGE );
for( int i = 0; i < scaledHeight; i++ )
{
memcpy( dxtPic + i * dxtWidth * 4, pic + i * scaledWidth * 4, scaledWidth * 4 );
}
}
else
{
dxtPic = pic;
dxtWidth = scaledWidth;
dxtHeight = scaledHeight;
}
}
img.level = level;
img.destZ = 0;
img.width = scaledWidth;
img.height = scaledHeight;
// compress data or convert floats as necessary
if( textureFormat == FMT_DXT1 )
{
idDxtEncoder dxt;
img.Alloc( dxtWidth * dxtHeight / 2 );
if( image_highQualityCompression.GetBool() )
{
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - DXT1HQ", width, height ) );
dxt.CompressImageDXT1HQ( dxtPic, img.data, dxtWidth, dxtHeight );
}
else
{
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - DXT1Fast", width, height ) );
dxt.CompressImageDXT1Fast( dxtPic, img.data, dxtWidth, dxtHeight );
}
}
else if( textureFormat == FMT_DXT5 )
{
idDxtEncoder dxt;
img.Alloc( dxtWidth * dxtHeight );
if( colorFormat == CFM_NORMAL_DXT5 )
{
if( image_highQualityCompression.GetBool() )
{
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - NormalMapDXT5HQ", width, height ) );
dxt.CompressNormalMapDXT5HQ( dxtPic, img.data, dxtWidth, dxtHeight );
}
else
{
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - NormalMapDXT5Fast", width, height ) );
dxt.CompressNormalMapDXT5Fast( dxtPic, img.data, dxtWidth, dxtHeight );
}
}
else if( colorFormat == CFM_YCOCG_DXT5 )
{
if( image_highQualityCompression.GetBool() )
{
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - YCoCgDXT5HQ", width, height ) );
dxt.CompressYCoCgDXT5HQ( dxtPic, img.data, dxtWidth, dxtHeight );
}
else
{
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - YCoCgDXT5Fast", width, height ) );
dxt.CompressYCoCgDXT5Fast( dxtPic, img.data, dxtWidth, dxtHeight );
}
}
else
{
fileData.colorFormat = colorFormat = CFM_DEFAULT;
if( image_highQualityCompression.GetBool() )
{
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - DXT5HQ", width, height ) );
dxt.CompressImageDXT5HQ( dxtPic, img.data, dxtWidth, dxtHeight );
}
else
{
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - DXT5Fast", width, height ) );
dxt.CompressImageDXT5Fast( dxtPic, img.data, dxtWidth, dxtHeight );
}
}
}
else if( textureFormat == FMT_LUM8 || textureFormat == FMT_INT8 )
{
// LUM8 and INT8 just read the red channel
img.Alloc( scaledWidth * scaledHeight );
for( int i = 0; i < img.dataSize; i++ )
{
img.data[ i ] = pic[ i * 4 ];
}
}
else if( textureFormat == FMT_ALPHA )
{
// ALPHA reads the alpha channel
img.Alloc( scaledWidth * scaledHeight );
for( int i = 0; i < img.dataSize; i++ )
{
img.data[ i ] = pic[ i * 4 + 3 ];
}
}
else if( textureFormat == FMT_L8A8 )
{
// L8A8 reads the alpha and red channels
img.Alloc( scaledWidth * scaledHeight * 2 );
for( int i = 0; i < img.dataSize / 2; i++ )
{
img.data[ i * 2 + 0 ] = pic[ i * 4 + 0 ];
img.data[ i * 2 + 1 ] = pic[ i * 4 + 3 ];
}
}
else if( textureFormat == FMT_RGB565 )
{
img.Alloc( scaledWidth * scaledHeight * 2 );
for( int i = 0; i < img.dataSize / 2; i++ )
{
unsigned short color = ( ( pic[ i * 4 + 0 ] >> 3 ) << 11 ) | ( ( pic[ i * 4 + 1 ] >> 2 ) << 5 ) | ( pic[ i * 4 + 2 ] >> 3 );
img.data[ i * 2 + 0 ] = ( color >> 8 ) & 0xFF;
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
img.Alloc( scaledWidth * scaledHeight * 4 );
for( int i = 0; i < img.dataSize; i++ )
{
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;
img.Alloc( scaledWidth * scaledHeight * 4 );
for( int i = 0; i < img.dataSize; i++ )
{
img.data[ i ] = pic[ i ];
}
}
// if we had to pad to quads, free the padded version
if( pic != dxtPic )
{
Mem_Free( dxtPic );
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 );
}
Mem_Free( sourcePic );
}
/*
========================
PadImageTo4x4

View file

@ -53,6 +53,7 @@ public:
}
void Load2DFromMemory( int width, int height, const byte* pic_const, int numLevels, textureFormat_t& textureFormat, textureColor_t& colorFormat, bool gammaMips );
void Load2DAtlasMipchainFromMemory( int width, int height, const byte* pic_const, int numLevels, textureFormat_t& textureFormat, textureColor_t& colorFormat );
void LoadCubeFromMemory( int width, const byte* pics[6], int numLevels, textureFormat_t& textureFormat, bool gammaMips );
ID_TIME_T LoadFromGeneratedFile( ID_TIME_T sourceFileTime );

View file

@ -35,7 +35,7 @@ static const int MAX_SSAO_BUFFERS = 2;
static const int MAX_HIERARCHICAL_ZBUFFERS = 6; // native resolution + 5 MIP LEVELS
static const int RADIANCE_CUBEMAP_SIZE = 256;
static const int IRRADIANCE_CUBEMAP_SIZE = 32;
static const int IRRADIANCE_CUBEMAP_SIZE = 128;
#if 1
static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 2048, 1024, 512, 512, 256 };
@ -56,13 +56,11 @@ public:
static void CheckFramebuffers();
// deletes OpenGL object but leaves structure intact for reloading
void PurgeFramebuffer();
void Bind();
bool IsBound();
static void Unbind();
static bool IsDefaultFramebufferActive();
static Framebuffer* GetActiveFramebuffer();
void AddColorBuffer( int format, int index, int multiSamples = 0 );
void AddDepthBuffer( int format, int multiSamples = 0 );
@ -132,6 +130,7 @@ struct globalFramebuffers_t
#endif
// Framebuffer* hdrQuarterFBO;
Framebuffer* hdr64FBO;
Framebuffer* envprobeFBO;
Framebuffer* bloomRenderFBO[MAX_BLOOM_BUFFERS];
Framebuffer* ambientOcclusionFBO[MAX_SSAO_BUFFERS];
Framebuffer* csDepthFBO[MAX_HIERARCHICAL_ZBUFFERS];

View file

@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013-2017 Robert Beckebans
Copyright (C) 2013-2021 Robert Beckebans
Copyright (C) 2016-2017 Dustin Land
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -100,6 +100,7 @@ enum textureFormat_t
FMT_RGBA16F, // 64 bpp
FMT_RGBA32F, // 128 bpp
FMT_R32F, // 32 bpp
FMT_R11G11B10F, // 32 bpp
// RB end
};
@ -226,6 +227,7 @@ typedef enum
TD_RGBA16F,
TD_RGBA32F,
TD_R32F,
TD_R11G11B10F, // memory efficient HDR RGB format with only 32bpp
// RB end
} textureUsage_t;
@ -234,14 +236,17 @@ 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_2D_ARRAY // not a cube map but not a single 2d texture either
CF_PANORAMA, // TODO 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
} cubeFiles_t;
enum imageFileType_t
{
TGA,
PNG,
JPG
JPG,
EXR,
};
#include "BinaryImage.h"
@ -395,7 +400,7 @@ public:
textureFilter_t filter,
textureRepeat_t repeat,
textureUsage_t usage,
textureSamples_t samples = SAMPLE_1 );
textureSamples_t samples = SAMPLE_1, cubeFiles_t cubeFiles = CF_2D );
void GenerateCubeImage( const byte* pic[6], int size,
textureFilter_t filter, textureUsage_t usage );
@ -573,6 +578,8 @@ public:
idImage* currentRenderHDRImageQuarter;
idImage* currentRenderHDRImage64;
idImage* bloomRenderImage[2];
idImage* envprobeHDRImage;
idImage* envprobeDepthImage;
idImage* heatmap5Image;
idImage* heatmap7Image;
idImage* smaaInputImage;
@ -635,9 +642,13 @@ byte* R_MipMap( const byte* in, int width, int height );
void R_BlendOverTexture( byte* data, int pixelCount, const byte blend[4] );
void R_HorizontalFlip( byte* data, int width, int height );
void R_VerticalFlip( byte* data, int width, int height );
void R_VerticalFlipRGB16F( byte* data, int width, int height );
void R_RotatePic( byte* data, int width );
void R_ApplyCubeMapTransforms( int i, byte* data, int size );
idVec4 R_CalculateMipRect( uint dimensions, uint mip );
int R_CalculateUsedAtlasPixels( int dimensions );
/*
====================================================================

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012-2020 Robert Beckebans
Copyright (C) 2012-2021 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -30,6 +30,18 @@ If you have questions concerning this license or the applicable additional terms
#pragma hdrstop
#include "precompiled.h"
#undef strncmp
#define STB_IMAGE_IMPLEMENTATION
#include "../libs/stb/stb_image.h"
//#define STB_IMAGE_WRITE_IMPLEMENTATION
//#include "../libs/stb/stb_image_write.h"
#define TINYEXR_IMPLEMENTATION
#include "../libs/tinyexr/tinyexr.h"
#include "../libs/mesa/format_r11g11b10f.h"
#include "RenderCommon.h"
@ -755,7 +767,7 @@ static void LoadPNG( const char* filename, unsigned char** pic, int* width, int*
png_read_update_info( pngPtr, infoPtr );
byte* out = ( byte* )R_StaticAlloc( pngWidth * pngHeight * 4 );
byte* out = ( byte* )R_StaticAlloc( pngWidth * pngHeight * 4, TAG_IMAGE );
*pic = out;
*width = pngWidth;
@ -878,6 +890,103 @@ void R_WritePNG( const char* filename, const byte* data, int bytesPerPixel, int
Mem_Free( buffer );
}
/*
=========================================================
EXR LOADING
Interfaces with tinyexr
=========================================================
*/
/*
=======================
LoadEXR
=======================
*/
static void LoadEXR( const char* filename, unsigned char** pic, int* width, int* height, ID_TIME_T* timestamp )
{
if( !pic )
{
fileSystem->ReadFile( filename, NULL, timestamp );
return; // just getting timestamp
}
*pic = NULL;
// load the file
const byte* fbuffer = NULL;
int fileSize = fileSystem->ReadFile( filename, ( void** )&fbuffer, timestamp );
if( !fbuffer )
{
return;
}
float* rgba;
const char* err;
{
int ret = LoadEXRFromMemory( &rgba, width, height, fbuffer, fileSize, &err );
if( ret != 0 )
{
common->Error( "LoadEXR( %s ): %s\n", filename, err );
return;
}
}
#if 0
// dump file as .hdr for testing - this works
{
idStrStatic< MAX_OSPATH > hdrFileName = "test";
//hdrFileName.AppendPath( filename );
hdrFileName.SetFileExtension( ".hdr" );
int ret = stbi_write_hdr( hdrFileName.c_str(), *width, *height, 4, rgba );
if( ret == 0 )
{
return; // fail
}
}
#endif
if( rgba )
{
int32 pixelCount = *width * *height;
byte* out = ( byte* )R_StaticAlloc( pixelCount * 4, TAG_IMAGE );
*pic = out;
// convert to packed R11G11B10F as uint32 for each pixel
const float* src = rgba;
byte* dst = out;
for( int i = 0; i < pixelCount; i++ )
{
// read 3 floats and ignore the alpha channel
float p[3];
p[0] = src[0];
p[1] = src[1];
p[2] = src[2];
// convert
uint32_t value = float3_to_r11g11b10f( p );
*( uint32_t* )dst = value;
src += 4;
dst += 4;
}
free( rgba );
}
// RB: EXR needs to be flipped to match the .tga behavior
//R_VerticalFlip( *pic, *width, *height );
Mem_Free( ( void* )fbuffer );
}
/*
================
R_WriteEXR
@ -1034,6 +1143,85 @@ void R_WriteEXR( const char* filename, const void* rgba16f, int channelsPerPixel
}
// RB end
/*
=========================================================
HDR LOADING
Interfaces with stb_image
=========================================================
*/
/*
=======================
LoadHDR
RB: load floating point data from memory and convert it into packed R11G11B10F data
=======================
*/
static void LoadHDR( const char* filename, unsigned char** pic, int* width, int* height, ID_TIME_T* timestamp )
{
if( !pic )
{
fileSystem->ReadFile( filename, NULL, timestamp );
return; // just getting timestamp
}
*pic = NULL;
// load the file
const byte* fbuffer = NULL;
int fileSize = fileSystem->ReadFile( filename, ( void** )&fbuffer, timestamp );
if( !fbuffer )
{
return;
}
int32 numChannels;
float* rgba = 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 )
{
int32 pixelCount = *width * *height;
byte* out = ( byte* )R_StaticAlloc( pixelCount * 4, TAG_IMAGE );
*pic = out;
// convert to packed R11G11B10F as uint32 for each pixel
const float* src = rgba;
byte* dst = out;
for( int i = 0; i < pixelCount; i++ )
{
// read 3 floats and ignore the alpha channel
float p[3];
p[0] = src[0];
p[1] = src[1];
p[2] = src[2];
// convert
uint32_t value = float3_to_r11g11b10f( p );
*( uint32_t* )dst = value;
src += 4;
dst += 4;
}
free( rgba );
}
Mem_Free( ( void* )fbuffer );
}
//===================================================================
@ -1048,6 +1236,8 @@ static imageExtToLoader_t imageLoaders[] =
{"png", LoadPNG},
{"tga", LoadTGA},
{"jpg", LoadJPG},
{"exr", LoadEXR},
{"hdr", LoadHDR},
};
static const int numImageLoaders = sizeof( imageLoaders ) / sizeof( imageLoaders[0] );

View file

@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013-2020 Robert Beckebans
Copyright (C) 2013-2021 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -39,6 +39,9 @@ If you have questions concerning this license or the applicable additional terms
//#include "Image_blueNoiseVC_1M.h" // 256^2 R8 data
#include "Image_blueNoiseVC_2.h" // 512^2 RGB8 data
#include "Image_env_UAC_lobby_amb.h"
#include "Image_env_UAC_lobby_spec.h"
#define DEFAULT_SIZE 16
/*
@ -262,6 +265,16 @@ static void R_HDR_RGBA16FImage_Res64( idImage* image )
image->GenerateImage( NULL, 64, 64, TF_NEAREST, TR_CLAMP, TD_RGBA16F );
}
static void R_EnvprobeImage_HDR( idImage* image )
{
image->GenerateImage( NULL, RADIANCE_CUBEMAP_SIZE, RADIANCE_CUBEMAP_SIZE, TF_NEAREST, TR_CLAMP, TD_RGBA16F );
}
static void R_EnvprobeImage_Depth( idImage* image )
{
image->GenerateImage( NULL, RADIANCE_CUBEMAP_SIZE, RADIANCE_CUBEMAP_SIZE, TF_NEAREST, TR_CLAMP, TD_DEPTH );
}
static void R_SMAAImage_ResNative( idImage* image )
{
image->GenerateImage( NULL, renderSystem->GetWidth(), renderSystem->GetHeight(), TF_LINEAR, TR_CLAMP, TD_LOOKUP_TABLE_RGBA );
@ -929,31 +942,19 @@ static void R_CreateImGuiFontImage( idImage* image )
static void R_CreateBrdfLutImage( idImage* image )
{
#if 0
static byte data[BRDFLUT_TEX_HEIGHT][BRDFLUT_TEX_WIDTH][4];
for( int x = 0; x < BRDFLUT_TEX_WIDTH; x++ )
{
for( int y = 0; y < BRDFLUT_TEX_HEIGHT; y++ )
{
#if 0
data[AREATEX_HEIGHT - y][x][0] = areaTexBytes[ y * AREATEX_PITCH + x * 2 + 0 ];
data[AREATEX_HEIGHT - y][x][1] = areaTexBytes[ y * AREATEX_PITCH + x * 2 + 1 ];
data[AREATEX_HEIGHT - y][x][2] = 0;
data[AREATEX_HEIGHT - y][x][3] = 1;
#else
data[y][x][0] = brfLutTexBytes[ y * BRDFLUT_TEX_PITCH + x * 2 + 0 ];
data[y][x][1] = brfLutTexBytes[ y * BRDFLUT_TEX_PITCH + x * 2 + 1 ];
data[y][x][2] = 0;
data[y][x][3] = 1;
#endif
}
}
#endif
image->GenerateImage( ( byte* )brfLutTexBytes, BRDFLUT_TEX_WIDTH, BRDFLUT_TEX_HEIGHT, TF_LINEAR, TR_CLAMP, TD_RG16F );
}
static void R_CreateEnvprobeImage_UAC_lobby_irradiance( idImage* image )
{
image->GenerateImage( ( byte* )IMAGE_ENV_UAC_LOBBY_AMB_H_Bytes, IMAGE_ENV_UAC_LOBBY_AMB_H_TEX_WIDTH, IMAGE_ENV_UAC_LOBBY_AMB_H_TEX_HEIGHT, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, SAMPLE_1, CF_2D_PACKED_MIPCHAIN );
}
static void R_CreateEnvprobeImage_UAC_lobby_radiance( idImage* image )
{
image->GenerateImage( ( byte* )IMAGE_ENV_UAC_LOBBY_SPEC_H_Bytes, IMAGE_ENV_UAC_LOBBY_SPEC_H_TEX_WIDTH, IMAGE_ENV_UAC_LOBBY_SPEC_H_TEX_HEIGHT, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, SAMPLE_1, CF_2D_PACKED_MIPCHAIN );
}
// RB end
@ -997,6 +998,9 @@ void idImageManager::CreateIntrinsicImages()
currentRenderHDRImageQuarter = globalImages->ImageFromFunction( "_currentRenderHDRQuarter", R_HDR_RGBA16FImage_ResQuarter );
currentRenderHDRImage64 = globalImages->ImageFromFunction( "_currentRenderHDR64", R_HDR_RGBA16FImage_Res64 );
envprobeHDRImage = globalImages->ImageFromFunction( "_envprobeHDR", R_EnvprobeImage_HDR );
envprobeDepthImage = ImageFromFunction( "_envprobeDepth", R_EnvprobeImage_Depth );
bloomRenderImage[0] = globalImages->ImageFromFunction( "_bloomRender0", R_HDR_RGBA16FImage_ResQuarter_Linear );
bloomRenderImage[1] = globalImages->ImageFromFunction( "_bloomRender1", R_HDR_RGBA16FImage_ResQuarter_Linear );
@ -1042,8 +1046,13 @@ void idImageManager::CreateIntrinsicImages()
hellLoadingIconImage = ImageFromFile( "textures/loadingicon3", TF_DEFAULT, TR_CLAMP, TD_DEFAULT, CF_2D );
// RB begin
defaultUACIrradianceCube = ImageFromFile( "env/UAC2_amb", TF_DEFAULT, TR_CLAMP, TD_LOOKUP_TABLE_RGB1, CF_2D );
defaultUACRadianceCube = ImageFromFile( "env/UAC2_spec", TF_DEFAULT, TR_CLAMP, TD_LOOKUP_TABLE_RGB1, CF_2D );
#if 0
defaultUACIrradianceCube = ImageFromFile( "env/UAC5_amb", TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
defaultUACRadianceCube = ImageFromFile( "env/UAC5_spec", TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
#else
defaultUACIrradianceCube = ImageFromFunction( "_defaultUACIrradiance", R_CreateEnvprobeImage_UAC_lobby_irradiance );
defaultUACRadianceCube = ImageFromFunction( "_defaultUACRadiance", R_CreateEnvprobeImage_UAC_lobby_radiance );
#endif
// RB end
release_assert( loadingIconImage->referencedOutsideLevelLoad );

View file

@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013-2020 Robert Beckebans
Copyright (C) 2013-2021 Robert Beckebans
Copyright (C) 2014-2016 Kot in Action Creative Artel
Copyright (C) 2016-2017 Dustin Land
@ -77,6 +77,8 @@ int BitsForFormat( textureFormat_t format )
return 128;
case FMT_R32F:
return 32;
case FMT_R11G11B10F:
return 8;
// RB end
case FMT_DEPTH:
return 32;
@ -132,6 +134,10 @@ ID_INLINE void idImage::DeriveOpts()
opts.format = FMT_R32F;
break;
case TD_R11G11B10F:
opts.format = FMT_R11G11B10F;
break;
case TD_DIFFUSE:
// TD_DIFFUSE gets only set to when its a diffuse texture for an interaction
opts.gammaMips = true;
@ -313,7 +319,7 @@ void idImage::ActuallyLoadImage( bool fromBackEnd )
{
opts.textureType = TT_2D_ARRAY;
}
else if( cubeFiles != CF_2D )
else if( cubeFiles == CF_NATIVE || cubeFiles == CF_CAMERA )
{
opts.textureType = TT_CUBIC;
repeat = TR_CLAMP;
@ -433,7 +439,7 @@ void idImage::ActuallyLoadImage( bool fromBackEnd )
//else if( toolUsage )
// binarizeReason = va( "binarize: tool usage '%s'", generatedName.c_str() );
if( cubeFiles != CF_2D )
if( cubeFiles == CF_NATIVE || cubeFiles == CF_CAMERA )
{
int size;
byte* pics[6];
@ -514,6 +520,13 @@ void idImage::ActuallyLoadImage( bool fromBackEnd )
opts.width = width;
opts.height = height;
opts.numLevels = 0;
// RB
if( cubeFiles == CF_2D_PACKED_MIPCHAIN )
{
opts.width = width * ( 2.0f / 3.0f );
}
DeriveOpts();
// foresthale 2014-05-30: give a nice progress display when binarizing
@ -541,7 +554,14 @@ void idImage::ActuallyLoadImage( bool fromBackEnd )
}
// RB: convert to compressed DXT or whatever choosen target format
im.Load2DFromMemory( opts.width, opts.height, pic, opts.numLevels, opts.format, opts.colorFormat, opts.gammaMips );
if( cubeFiles == CF_2D_PACKED_MIPCHAIN )
{
im.Load2DAtlasMipchainFromMemory( width, opts.height, pic, opts.numLevels, opts.format, opts.colorFormat );
}
else
{
im.Load2DFromMemory( opts.width, opts.height, pic, opts.numLevels, opts.format, opts.colorFormat, opts.gammaMips );
}
commonLocal.LoadPacifierBinarizeEnd();
Mem_Free( pic );
@ -644,6 +664,7 @@ void idImage::Print() const
NAME_FORMAT( RGBA16F );
NAME_FORMAT( RGBA32F );
NAME_FORMAT( R32F );
NAME_FORMAT( R11G11B10F );
// RB end
NAME_FORMAT( DEPTH );
NAME_FORMAT( X16 );
@ -743,20 +764,27 @@ void idImage::Reload( bool force )
GenerateImage
================
*/
void idImage::GenerateImage( const byte* pic, int width, int height, textureFilter_t filterParm, textureRepeat_t repeatParm, textureUsage_t usageParm, textureSamples_t samples )
void idImage::GenerateImage( const byte* pic, int width, int height, textureFilter_t filterParm, textureRepeat_t repeatParm, textureUsage_t usageParm, textureSamples_t samples, cubeFiles_t _cubeFiles )
{
PurgeImage();
filter = filterParm;
repeat = repeatParm;
usage = usageParm;
cubeFiles = CF_2D;
cubeFiles = _cubeFiles;
opts.textureType = ( samples > SAMPLE_1 ) ? TT_2D_MULTISAMPLE : TT_2D;
opts.width = width;
opts.height = height;
opts.numLevels = 0;
opts.samples = samples;
// RB
if( cubeFiles == CF_2D_PACKED_MIPCHAIN )
{
opts.width = width * ( 2.0f / 3.0f );
}
DeriveOpts();
// RB: allow pic == NULL for internal framebuffer images
@ -779,7 +807,14 @@ void idImage::GenerateImage( const byte* pic, int width, int height, textureFilt
commonLocal.LoadPacifierBinarizeProgressTotal( opts.width * opts.height );
}
im.Load2DFromMemory( width, height, pic, opts.numLevels, opts.format, opts.colorFormat, opts.gammaMips );
if( cubeFiles == CF_2D_PACKED_MIPCHAIN )
{
im.Load2DAtlasMipchainFromMemory( width, opts.height, pic, opts.numLevels, opts.format, opts.colorFormat );
}
else
{
im.Load2DFromMemory( width, height, pic, opts.numLevels, opts.format, opts.colorFormat, opts.gammaMips );
}
commonLocal.LoadPacifierBinarizeEnd();

View file

@ -3,6 +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
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -527,6 +528,31 @@ void R_VerticalFlip( byte* data, int width, int height )
}
}
// RB: halfFloat_t helper
struct ColorRGB16F
{
uint16 red;
uint16 green;
uint16 blue;
};
void R_VerticalFlipRGB16F( byte* data, int width, int height )
{
int i, j;
ColorRGB16F temp;
for( i = 0; i < width; i++ )
{
for( j = 0; j < height / 2; j++ )
{
temp = *( ( ColorRGB16F* )data + j * width + i );
*( ( ColorRGB16F* )data + j * width + i ) = *( ( ColorRGB16F* )data + ( height - 1 - j ) * width + i );
*( ( ColorRGB16F* )data + ( height - 1 - j ) * width + i ) = temp;
}
}
}
void R_RotatePic( byte* data, int width )
{
int i, j;
@ -570,3 +596,35 @@ void R_ApplyCubeMapTransforms( int iter, byte* data, int size )
}
}
// This is the most efficient way to atlas a mip chain to a 2d texture
// https://twitter.com/SebAaltonen/status/1327188239451611139
idVec4 R_CalculateMipRect( uint dimensions, uint mip )
{
uint pixels_mip = dimensions >> mip;
idVec4 uv_rect = idVec4( 0, 0, pixels_mip, pixels_mip );
if( mip > 0 )
{
uv_rect.x = dimensions;
uv_rect.y = dimensions - pixels_mip * 2;
}
return uv_rect;
}
int R_CalculateUsedAtlasPixels( int dimensions )
{
int numPixels = 0;
const int numMips = idMath::BitsForInteger( dimensions );
for( int mip = 0; mip < numMips; mip++ )
{
idVec4 dstRect = R_CalculateMipRect( dimensions, mip );
numPixels += ( dstRect.z * dstRect.w );
}
return numPixels;
}

View file

@ -133,6 +133,19 @@ void Framebuffer::Init()
globalFramebuffers.hdrNonMSAAFBO->Check();
#endif
// HDR CUBEMAP CAPTURE
globalFramebuffers.envprobeFBO = new Framebuffer( "_envprobeRender", RADIANCE_CUBEMAP_SIZE, RADIANCE_CUBEMAP_SIZE );
globalFramebuffers.envprobeFBO->Bind();
globalFramebuffers.envprobeFBO->AddColorBuffer( GL_RGBA16F, 0 );
globalFramebuffers.envprobeFBO->AddDepthBuffer( GL_DEPTH24_STENCIL8 );
globalFramebuffers.envprobeFBO->AttachImage2D( GL_TEXTURE_2D, globalImages->envprobeHDRImage, 0 );
globalFramebuffers.envprobeFBO->AttachImageDepth( GL_TEXTURE_2D, globalImages->envprobeDepthImage );
globalFramebuffers.envprobeFBO->Check();
// HDR DOWNSCALE
globalFramebuffers.hdr64FBO = new Framebuffer( "_hdr64", 64, 64 );
@ -365,6 +378,7 @@ void Framebuffer::Unbind()
{
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glBindRenderbuffer( GL_RENDERBUFFER, 0 );
tr.backend.currentFramebuffer = NULL;
}
}
@ -374,6 +388,11 @@ bool Framebuffer::IsDefaultFramebufferActive()
return ( tr.backend.currentFramebuffer == NULL );
}
Framebuffer* Framebuffer::GetActiveFramebuffer()
{
return tr.backend.currentFramebuffer;
}
void Framebuffer::AddColorBuffer( int format, int index, int multiSamples )
{
if( index < 0 || index >= glConfig.maxColorAttachments )

View file

@ -725,6 +725,15 @@ void idImage::AllocImage()
dataFormat = GL_LUMINANCE_ALPHA;
dataType = GL_UNSIGNED_SHORT;
break;
// see http://what-when-how.com/Tutorial/topic-615ll9ug/Praise-for-OpenGL-ES-30-Programming-Guide-291.html
case FMT_R11G11B10F:
internalFormat = GL_R11F_G11F_B10F;
dataFormat = GL_RGB;
dataType = GL_UNSIGNED_INT_10F_11F_11F_REV;
//dataType = GL_FLOAT;
break;
default:
idLib::Error( "Unhandled image format %d in %s\n", opts.format, GetName() );
}

View file

@ -1407,6 +1407,7 @@ void idRenderBackend::GL_Clear( bool color, bool depth, bool stencil, byte stenc
glClear( clearFlags );
// RB begin
/*
if( r_useHDR.GetBool() && clearHDR && globalFramebuffers.hdrFBO != NULL )
{
bool isDefaultFramebufferActive = Framebuffer::IsDefaultFramebufferActive();
@ -1419,6 +1420,28 @@ void idRenderBackend::GL_Clear( bool color, bool depth, bool stencil, byte stenc
Framebuffer::Unbind();
}
}
*/
if( r_useHDR.GetBool() && clearHDR )
{
bool isDefaultFramebufferActive = Framebuffer::IsDefaultFramebufferActive();
if( viewDef && viewDef->renderView.rdflags & RDF_IRRADIANCE )
{
globalFramebuffers.envprobeFBO->Bind();
}
else
{
globalFramebuffers.hdrFBO->Bind();
}
glClear( clearFlags );
if( isDefaultFramebufferActive )
{
Framebuffer::Unbind();
}
}
// RB end
}

View file

@ -2078,7 +2078,7 @@ idRenderBackend::AmbientPass
*/
void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDrawSurfs, bool fillGbuffer )
{
const bool hdrIsActive = ( r_useHDR.GetBool() && globalFramebuffers.hdrFBO != NULL && globalFramebuffers.hdrFBO->IsBound() );
Framebuffer* previousFramebuffer = Framebuffer::GetActiveFramebuffer();
if( numDrawSurfs == 0 )
{
@ -2096,6 +2096,11 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr
return;
}
if( viewDef->renderView.rdflags & RDF_NOAMBIENT )
{
return;
}
#if defined( USE_VULKAN )
if( fillGbuffer )
{
@ -2543,9 +2548,9 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr
if( fillGbuffer )
{
// go back to main render target
if( hdrIsActive )
if( previousFramebuffer != NULL )
{
globalFramebuffers.hdrFBO->Bind();
previousFramebuffer->Bind();
}
else
{
@ -2945,6 +2950,11 @@ void idRenderBackend::ShadowMapPass( const drawSurf_t* drawSurfs, const viewLigh
return;
}
if( viewDef->renderView.rdflags & RDF_NOSHADOWS )
{
return;
}
RENDERLOG_PRINTF( "---------- RB_ShadowMapPass( side = %i ) ----------\n", side );
renderProgManager.BindShader_Depth();
@ -3472,21 +3482,6 @@ void idRenderBackend::ShadowMapPass( const drawSurf_t* drawSurfs, const viewLigh
DrawElementsWithCounters( drawSurf );
}
}
// cleanup the shadow specific rendering state
if( r_useHDR.GetBool() ) //&& !backEnd.viewDef->is2Dgui )
{
globalFramebuffers.hdrFBO->Bind();
}
else
{
Framebuffer::Unbind();
}
renderProgManager.Unbind();
GL_State( GLS_DEFAULT );
SetFragmentParm( RENDERPARM_ALPHA_TEST, vec4_zero.ToFloatPtr() );
}
/*
@ -3515,6 +3510,8 @@ void idRenderBackend::DrawInteractions( const viewDef_t* _viewDef )
const bool useLightDepthBounds = r_useLightDepthBounds.GetBool() && !r_useShadowMapping.GetBool();
Framebuffer* previousFramebuffer = Framebuffer::GetActiveFramebuffer();
//
// for each light, perform shadowing and adding
//
@ -3578,6 +3575,21 @@ void idRenderBackend::DrawInteractions( const viewDef_t* _viewDef )
ShadowMapPass( vLight->globalShadows, vLight, side );
}
// go back to main render target
if( previousFramebuffer != NULL )
{
previousFramebuffer->Bind();
}
else
{
Framebuffer::Unbind();
}
renderProgManager.Unbind();
GL_State( GLS_DEFAULT );
SetFragmentParm( RENDERPARM_ALPHA_TEST, vec4_zero.ToFloatPtr() );
// go back from light view to default camera view
ResetViewportAndScissorToDefaultCamera( _viewDef );
@ -4676,7 +4688,7 @@ void idRenderBackend::Tonemap( const viewDef_t* _viewDef )
void idRenderBackend::Bloom( const viewDef_t* _viewDef )
{
if( _viewDef->is2Dgui || !r_useHDR.GetBool() )
if( _viewDef->is2Dgui || !r_useHDR.GetBool() || ( _viewDef->renderView.rdflags & RDF_IRRADIANCE ) )
{
return;
}
@ -4822,13 +4834,18 @@ void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef
return;
}
if( _viewDef->renderView.rdflags & RDF_NOAMBIENT )
{
return;
}
renderLog.OpenMainBlock( MRB_SSAO_PASS );
renderLog.OpenBlock( "Render_SSAO", colorBlue );
currentSpace = &viewDef->worldSpace;
RB_SetMVP( viewDef->worldSpace.mvp );
const bool hdrIsActive = ( r_useHDR.GetBool() && globalFramebuffers.hdrFBO != NULL && globalFramebuffers.hdrFBO->IsBound() );
Framebuffer* previousFramebuffer = Framebuffer::GetActiveFramebuffer();
int screenWidth = renderSystem->GetWidth();
int screenHeight = renderSystem->GetHeight();
@ -4920,9 +4937,9 @@ void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef
GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_ALPHAMASK | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS );
}
if( hdrIsActive )
if( previousFramebuffer != NULL )
{
globalFramebuffers.hdrFBO->Bind();
previousFramebuffer->Bind();
}
else
{
@ -5049,9 +5066,9 @@ void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef
// AO blur Y
if( downModulateScreen )
{
if( hdrIsActive )
if( previousFramebuffer != NULL )
{
globalFramebuffers.hdrFBO->Bind();
previousFramebuffer->Bind();
}
else
{
@ -5086,9 +5103,9 @@ void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef
if( !downModulateScreen )
{
// go back to main scene render target
if( hdrIsActive )
if( previousFramebuffer != NULL )
{
globalFramebuffers.hdrFBO->Bind();
previousFramebuffer->Bind();
}
else
{
@ -5133,12 +5150,17 @@ void idRenderBackend::DrawScreenSpaceGlobalIllumination( const viewDef_t* _viewD
return;
}
if( _viewDef->renderView.rdflags & RDF_NOAMBIENT )
{
return;
}
RENDERLOG_PRINTF( "---------- RB_SSGI() ----------\n" );
currentSpace = &viewDef->worldSpace;
RB_SetMVP( viewDef->worldSpace.mvp );
const bool hdrIsActive = ( r_useHDR.GetBool() && globalFramebuffers.hdrFBO != NULL && globalFramebuffers.hdrFBO->IsBound() );
Framebuffer* previousFramebuffer = Framebuffer::GetActiveFramebuffer();
int screenWidth = renderSystem->GetWidth();
int screenHeight = renderSystem->GetHeight();
@ -5147,7 +5169,8 @@ void idRenderBackend::DrawScreenSpaceGlobalIllumination( const viewDef_t* _viewD
GL_Viewport( 0, 0, screenWidth, screenHeight );
GL_Scissor( 0, 0, screenWidth, screenHeight );
if( !hdrIsActive )
// TODO remove
if( previousFramebuffer == NULL )
{
const idScreenRect& viewport = viewDef->viewport;
globalImages->currentRenderImage->CopyFramebuffer( viewport.x1, viewport.y1, viewport.GetWidth(), viewport.GetHeight() );
@ -5237,9 +5260,9 @@ void idRenderBackend::DrawScreenSpaceGlobalIllumination( const viewDef_t* _viewD
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS );
}
if( hdrIsActive )
if( previousFramebuffer != NULL )
{
globalFramebuffers.hdrFBO->Bind();
previousFramebuffer->Bind();
}
else
{
@ -5301,9 +5324,9 @@ void idRenderBackend::DrawScreenSpaceGlobalIllumination( const viewDef_t* _viewD
}
GL_SelectTexture( 2 );
if( hdrIsActive )
if( previousFramebuffer != NULL )
{
globalImages->currentRenderHDRImage->Bind();
previousFramebuffer->Bind();
}
else
{
@ -5336,9 +5359,9 @@ void idRenderBackend::DrawScreenSpaceGlobalIllumination( const viewDef_t* _viewD
#endif
// AO blur Y
if( hdrIsActive )
if( previousFramebuffer != NULL )
{
globalFramebuffers.hdrFBO->Bind();
previousFramebuffer->Bind();
}
else
{
@ -5539,7 +5562,14 @@ void idRenderBackend::DrawViewInternal( const viewDef_t* _viewDef, const int ste
if( useHDR )
{
globalFramebuffers.hdrFBO->Bind();
if( _viewDef->renderView.rdflags & RDF_IRRADIANCE )
{
globalFramebuffers.envprobeFBO->Bind();
}
else
{
globalFramebuffers.hdrFBO->Bind();
}
}
else
{
@ -5710,8 +5740,9 @@ void idRenderBackend::DrawViewInternal( const viewDef_t* _viewDef, const int ste
DBG_RenderDebugTools( drawSurfs, numDrawSurfs );
#if !defined(USE_VULKAN)
// RB: convert back from HDR to LDR range
if( useHDR )
if( useHDR && !( _viewDef->renderView.rdflags & RDF_IRRADIANCE ) )
{
/*
int x = backEnd.viewDef->viewport.x1;

View file

@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012-2020 Robert Beckebans
Copyright (C) 2012-2021 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").
@ -482,6 +482,22 @@ struct viewEnvprobe_t
idImage* irradianceImage; // cubemap image used for diffuse IBL by backend
idImage* radianceImage; // cubemap image used for specular IBL by backend
};
struct calcEnvprobeParms_t
{
// input
byte* buffers[6]; // HDR R11G11B11F standard OpenGL cubemap sides
int samples;
int outWidth;
int outHeight;
idStr filename;
// output
halfFloat_t* outBuffer; // HDR R11G11B11F packed atlas
int time; // execution time in milliseconds
};
// RB end
const int MAX_CLIP_PLANES = 1; // we may expand this to six for some subview issues
@ -935,6 +951,10 @@ public:
idParallelJobList* frontEndJobList;
// RB irradiance and GGX background jobs
idParallelJobList* envprobeJobList;
idList<calcEnvprobeParms_t*> irradianceJobs;
idRenderBackend backend;
private:

View file

@ -304,7 +304,7 @@ idCVar r_showViewEnvprobes( "r_showViewEnvprobes", "0", CVAR_RENDERER | CVAR_INT
idCVar r_exposure( "r_exposure", "0.5", CVAR_ARCHIVE | CVAR_RENDERER | CVAR_FLOAT, "HDR exposure or LDR brightness [0.0 .. 1.0]", 0.0f, 1.0f );
// RB end
const char* fileExten[3] = { "tga", "png", "jpg" };
const char* fileExten[4] = { "tga", "png", "jpg", "exr" };
const char* envDirection[6] = { "_px", "_nx", "_py", "_ny", "_pz", "_nz" };
const char* skyDirection[6] = { "_forward", "_back", "_left", "_right", "_up", "_down" };
@ -731,7 +731,17 @@ void R_ReadTiledPixels( int width, int height, byte* buffer, renderView_t* ref =
// include extra space for OpenGL padding to word boundaries
int sysWidth = renderSystem->GetWidth();
int sysHeight = renderSystem->GetHeight();
byte* temp = ( byte* )R_StaticAlloc( ( sysWidth + 3 ) * sysHeight * 3 );
byte* temp = NULL;
if( ref && ref->rdflags & RDF_IRRADIANCE )
{
// * 2 = sizeof( half float )
temp = ( byte* )R_StaticAlloc( RADIANCE_CUBEMAP_SIZE * RADIANCE_CUBEMAP_SIZE * 3 * 2 );
}
else
{
temp = ( byte* )R_StaticAlloc( ( sysWidth + 3 ) * sysHeight * 3 );
}
// foresthale 2014-03-01: fixed custom screenshot resolution by doing a more direct render path
#ifdef BUGFIXEDSCREENSHOTRESOLUTION
@ -821,15 +831,29 @@ void R_ReadTiledPixels( int width, int height, byte* buffer, renderView_t* ref =
h = height - yo;
}
glReadBuffer( GL_FRONT );
glReadPixels( 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, temp );
int row = ( w * 3 + 3 ) & ~3; // OpenGL pads to dword boundaries
for( int y = 0 ; y < h ; y++ )
if( ref && ref->rdflags & RDF_IRRADIANCE )
{
memcpy( buffer + ( ( yo + y )* width + xo ) * 3,
temp + y * row, w * 3 );
globalFramebuffers.envprobeFBO->Bind();
glPixelStorei( GL_PACK_ROW_LENGTH, RADIANCE_CUBEMAP_SIZE );
glReadPixels( 0, 0, w, h, GL_RGB, GL_HALF_FLOAT, buffer );
R_VerticalFlipRGB16F( buffer, w, h );
Framebuffer::Unbind();
}
else
{
glReadBuffer( GL_FRONT );
glReadPixels( 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, temp );
int row = ( w * 3 + 3 ) & ~3; // OpenGL pads to dword boundaries
for( int y = 0 ; y < h ; y++ )
{
memcpy( buffer + ( ( yo + y )* width + xo ) * 3,
temp + y * row, w * 3 );
}
}
}
}
@ -874,7 +898,11 @@ void idRenderSystemLocal::TakeScreenshot( int width, int height, const char* fil
int pix = width * height;
const int bufferSize = pix * 3 + 18;
if( exten == PNG )
if( exten == EXR )
{
buffer = ( byte* )R_StaticAlloc( pix * 3 * 2 );
}
else if( exten == PNG )
{
buffer = ( byte* )R_StaticAlloc( pix * 3 );
}
@ -886,7 +914,7 @@ void idRenderSystemLocal::TakeScreenshot( int width, int height, const char* fil
if( blends <= 1 )
{
if( exten == PNG )
if( exten == PNG || exten == EXR )
{
R_ReadTiledPixels( width, height, buffer, ref );
}
@ -944,7 +972,12 @@ void idRenderSystemLocal::TakeScreenshot( int width, int height, const char* fil
r_jitter.SetBool( false );
}
if( exten == PNG )
if( exten == EXR )
{
R_WriteEXR( finalFileName, buffer, 3, width, height, "fs_basepath" );
//R_WritePNG( finalFileName, buffer, 3, width, height, false, "fs_basepath" );
}
else if( exten == PNG )
{
R_WritePNG( finalFileName, buffer, 3, width, height, false, "fs_basepath" );
}
@ -1685,6 +1718,10 @@ void idRenderSystemLocal::Clear()
}
frontEndJobList = NULL;
// RB
envprobeJobList = NULL;
irradianceJobs.Clear();
}
/*
@ -2027,6 +2064,7 @@ void idRenderSystemLocal::Init()
}
frontEndJobList = parallelJobManager->AllocJobList( JOBLIST_RENDERER_FRONTEND, JOBLIST_PRIORITY_MEDIUM, 2048, 0, NULL );
envprobeJobList = parallelJobManager->AllocJobList( JOBLIST_UTILITY, JOBLIST_PRIORITY_MEDIUM, 2048, 0, NULL ); // RB
bInitialized = true;

View file

@ -235,6 +235,13 @@ typedef struct
} renderEnvironmentProbe_t;
// RB end
// RB: added back refdef flags from Quake 3
const int RDF_NOSHADOWS = BIT( 0 ); // force renderer to use faster lighting only path
const int RDF_NOAMBIENT = BIT( 1 ); // don't render indirect lighting
const int RDF_IRRADIANCE = BIT( 2 ); // render into 256^2 HDR render target for irradiance/radiance GGX calculation
const int RDF_UNDERWATER = BIT( 3 ); // TODO enable automatic underwater caustics and fog
typedef struct renderView_s
{
// player views will set this to a non-zero integer for model suppress / allow
@ -258,6 +265,8 @@ typedef struct renderView_s
// the viewEyeBuffer may be of a different polarity than stereoScreenSeparation if the eyes have been swapped
int viewEyeBuffer; // -1 = left eye, 1 = right eye, 0 = monoscopic view or GUI
float stereoScreenSeparation; // projection matrix horizontal offset, positive or negative based on camera eye
int rdflags; // RB: RDF_NOSHADOWS, etc
} renderView_t;

View file

@ -769,10 +769,10 @@ void R_DeriveEnvprobeData( RenderEnvprobeLocal* probe )
// TODO get preconvolved cubemaps
fullname.Format( "env/%s/envprobe%i_amb", basename.c_str(), probeIndex );
probe->irradianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_LOOKUP_TABLE_RGB1, CF_2D );
probe->irradianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
fullname.Format( "env/%s/envprobe%i_spec", basename.c_str(), probeIndex );
probe->radianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_LOOKUP_TABLE_RGB1, CF_2D );
probe->radianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
// ------------------------------------
// compute the light projection matrix

File diff suppressed because it is too large Load diff

View file

@ -113,6 +113,5 @@ struct dynamicShadowVolumeParms_t
void DynamicShadowVolumeJob( const dynamicShadowVolumeParms_t* parms );
void DynamicShadowVolume_SetupSPURSHeader( CellSpursJob128* job, const dynamicShadowVolumeParms_t* parms );
#endif // !__DYNAMICSHADOWVOLUME_H__

View file

@ -80,6 +80,5 @@ struct preLightShadowVolumeParms_t
void PreLightShadowVolumeJob( const preLightShadowVolumeParms_t* parms );
void PreLightShadowVolume_SetupSPURSHeader( CellSpursJob128* job, const preLightShadowVolumeParms_t* parms );
#endif // !__PRELIGHTSHADOWVOLUME_H__

View file

@ -83,6 +83,5 @@ struct staticShadowVolumeParms_t
void StaticShadowVolumeJob( const staticShadowVolumeParms_t* parms );
void StaticShadowVolume_SetupSPURSHeader( CellSpursJob128* job, const staticShadowVolumeParms_t* parms );
#endif // !__STATICSHADOWVOLUME_H__