Merge branch 'IBL-environment-probes2' into vulkan

This commit is contained in:
Robert Beckebans 2019-10-31 21:05:11 +01:00
commit d4576f7cc5
36 changed files with 2666 additions and 46 deletions

View file

@ -78,7 +78,6 @@ _______________________________
- Enhanced Subpixel Morphological Antialiasing
For more information see "Anti-Aliasing Methods in CryENGINE 3" and the docs at http://www.iryoku.com/smaa/
- Filmic post process effects like Technicolor color grading and film grain
- Fixed issues with Mesa drivers and allowed them to use shadow mapping

View file

@ -60,6 +60,11 @@ half3 Fresnel_Schlick( half3 specularColor, half vdotH )
return specularColor + ( 1.0 - specularColor ) * pow( 1.0 - vdotH, 5.0 );
}
half3 Fresnel_Glossy( half3 specularColor, half roughness, half vdotH )
{
return specularColor + ( max( half3( 1.0 - roughness ), specularColor ) - specularColor ) * pow( 1.0 - vdotH, 5.0 );
}
// Visibility term G( l, v, h )
// Very similar to Marmoset Toolbag 2 and gives almost the same results as Smith GGX
float Visibility_Schlick( half vdotN, half ldotN, float alpha )

View file

@ -9,6 +9,8 @@ return
-- shaders
"ambient_lighting.ps.hlsl",
"ambient_lighting.vs.hlsl",
"ambient_lighting_IBL.ps.hlsl",
"ambient_lighting_IBL.vs.hlsl",
"AmbientOcclusion_AO.ps.hlsl",
"AmbientOcclusion_AO.vs.hlsl",
"AmbientOcclusion_blur.ps.hlsl",

View file

@ -0,0 +1,179 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013-2019 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"
#include "BRDF.inc.hlsl"
uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface normal map
uniform sampler2D samp1 : register(s1); // texture 3 is the per-surface specular or roughness/metallic/AO mixer map
uniform sampler2D samp2 : register(s2); // texture 2 is the per-surface baseColor map
uniform sampler2D samp3 : register(s3); // texture 4 is the light falloff texture
uniform sampler2D samp4 : register(s4); // texture 5 is the light projection texture
uniform samplerCUBE samp7 : register(s7); // texture 0 is the cube map
uniform samplerCUBE samp8 : register(s8); // texture 0 is the cube map
struct PS_IN {
half4 position : VPOS;
half4 texcoord0 : TEXCOORD0_centroid;
half4 texcoord1 : TEXCOORD1_centroid;
half4 texcoord2 : TEXCOORD2_centroid;
half4 texcoord3 : TEXCOORD3_centroid;
half4 texcoord4 : TEXCOORD4_centroid;
half4 texcoord5 : TEXCOORD5_centroid;
half4 texcoord6 : TEXCOORD6_centroid;
half4 color : COLOR0;
};
struct PS_OUT {
half4 color : COLOR;
};
void main( PS_IN fragment, out PS_OUT result ) {
half4 bumpMap = tex2D( samp0, fragment.texcoord0.xy );
// half4 lightFalloff = idtex2Dproj( samp1, fragment.texcoord2 );
// half4 lightProj = idtex2Dproj( samp2, fragment.texcoord3 );
half4 YCoCG = tex2D( samp2, fragment.texcoord1.xy );
half4 specMap = tex2D( samp1, fragment.texcoord2.xy );
//half3 lightVector = normalize( fragment.texcoord0.xyz );
half3 diffuseMap = sRGBToLinearRGB( ConvertYCoCgToRGB( YCoCG ) );
half3 localNormal;
#if defined(USE_NORMAL_FMT_RGB8)
localNormal.xy = bumpMap.rg - 0.5;
#else
localNormal.xy = bumpMap.wy - 0.5;
#endif
localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );
localNormal = normalize( localNormal );
//const half specularPower = 10.0f;
//half hDotN = dot3( normalize( fragment.texcoord6.xyz ), localNormal );
// RB: added abs
//half3 specularContribution = _half3( pow( abs( hDotN ), specularPower ) );
//half3 diffuseColor = diffuseMap * ( rpDiffuseModifier.xyz ) * 1.5f;
//half3 specularColor = specMap.xyz * specularContribution * ( rpSpecularModifier.xyz );
// RB: http://developer.valvesoftware.com/wiki/Half_Lambert
//float halfLdotN = dot3( localNormal, lightVector ) * 0.5 + 0.5;
//halfLdotN *= halfLdotN;
// traditional very dark Lambert light model used in Doom 3
//float ldotN = dot3( localNormal, lightVector );
float3 globalNormal;
globalNormal.x = dot3( localNormal, fragment.texcoord4 );
globalNormal.y = dot3( localNormal, fragment.texcoord5 );
globalNormal.z = dot3( localNormal, fragment.texcoord6 );
float3 globalEye = normalize( fragment.texcoord3.xyz );
float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal );
reflectionVector = ( reflectionVector * 2.0f ) - globalEye;
#if defined(USE_PBR)
const half metallic = specMap.g;
const half roughness = specMap.r;
const half glossiness = 1.0 - roughness;
// the vast majority of real-world materials (anything not metal or gems) have F(0°)
// values in a very narrow range (~0.02 - 0.08)
// approximate non-metals with linear RGB 0.04 which is 0.08 * 0.5 (default in UE4)
const half3 dielectricColor = half3( 0.04 );
// derive diffuse and specular from albedo(m) base color
const half3 baseColor = diffuseMap;
half3 diffuseColor = baseColor * ( 1.0 - metallic );
half3 specularColor = lerp( dielectricColor, baseColor, metallic );
//diffuseColor = half3( 1.0 );
float3 diffuseLight = ( texCUBE( samp7, globalNormal ).rgb ) * diffuseColor * ( rpDiffuseModifier.xyz ) * 1.5f;
//specularColor = half3( 0.0 );
float mip = clamp( ( roughness * 7.0 ) + 3.0, 0.0, 10.0 );
float3 envColor = ( textureLod( samp8, reflectionVector, mip ).rgb ) * ( rpSpecularModifier.xyz ) * 1.0f;
float3 specularLight = envColor * specularColor;
#else
half4 specMapSRGB = specMap;
specMap = sRGBAToLinearRGBA( specMap );
//float3 diffuseLight = sRGBToLinearRGB( texCUBE( samp7, globalNormal ).rgb ) * diffuseMap.rgb * ( rpDiffuseModifier.xyz ) * 3.5f;
float3 diffuseLight = ( texCUBE( samp7, globalNormal ).rgb ) * diffuseMap.rgb * ( rpDiffuseModifier.xyz ) * 3.5f;
//float3 diffuseLight = diffuseMap.rgb * ( rpDiffuseModifier.xyz ) * 1.5f;
// HACK calculate roughness from D3 gloss maps
float Y = dot( LUMINANCE_SRGB.rgb, specMapSRGB.rgb );
//const float glossiness = clamp( 1.0 - specMapSRGB.r, 0.0, 0.98 );
const float glossiness = clamp( pow( Y, 1.0 / 2.0 ), 0.0, 0.98 );
const float roughness = 1.0 - glossiness;
float mip = clamp( ( roughness * 7.0 ) + 0.0, 0.0, 10.0 );
float3 envColor = ( textureLod( samp8, reflectionVector, mip ).rgb ) * ( rpSpecularModifier.xyz ) * 0.5f;
float3 specularLight = envColor * specMap.rgb;
#endif
// add glossy fresnel
half hDotN = saturate( dot3( globalEye, globalNormal ) );
half3 specularColor2 = half3( 0.0 );
float3 glossyFresnel = Fresnel_Glossy( specularColor2, roughness, hDotN );
// horizon fade
const half horizonFade = 1.3;
half horiz = saturate( 1.0 + horizonFade * saturate( dot3( reflectionVector, globalNormal ) ) );
horiz *= horiz;
//horiz = clamp( horiz, 0.0, 1.0 );
//specularLight = glossyFresnel * envColor;
specularLight += glossyFresnel * envColor * ( rpSpecularModifier.xyz ) * 0.9 * horiz;
half3 lightColor = sRGBToLinearRGB( rpAmbientColor.rgb );
//result.color.rgb = diffuseLight;
//result.color.rgb = diffuseLight * lightColor;
//result.color.rgb = specularLight;
result.color.rgb = ( diffuseLight + specularLight ) * lightColor * fragment.color.rgb;
//result.color.rgb = localNormal.xyz * 0.5 + 0.5;
//result.color.xyz = ( ( diffuseColor + specularColor ) * halfLdotN * lightColor ) * fragment.color.rgb;
//result.color = ( ( diffuseColor + specularColor ) * halfLdotN * lightColor + rimColor ) * fragment.color.rgba;
result.color.w = fragment.color.a;
}

View file

@ -0,0 +1,186 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013-2015 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"
#if defined( USE_GPU_SKINNING )
uniform matrices_ubo { float4 matrices[408]; };
#endif
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 : POSITION;
float4 texcoord0 : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
float4 texcoord2 : TEXCOORD2;
float4 texcoord3 : TEXCOORD3;
float4 texcoord4 : TEXCOORD4;
float4 texcoord5 : TEXCOORD5;
float4 texcoord6 : TEXCOORD6;
float4 color : COLOR0;
};
void main( VS_IN vertex, out VS_OUT result ) {
float4 vNormal = vertex.normal * 2.0 - 1.0;
float4 vTangent = vertex.tangent * 2.0 - 1.0;
float3 vBitangent = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w;
#if defined( USE_GPU_SKINNING )
//--------------------------------------------------------------
// GPU transformation of the normal / tangent / bitangent
//
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
//--------------------------------------------------------------
const float w0 = vertex.color2.x;
const float w1 = vertex.color2.y;
const float w2 = vertex.color2.z;
const float w3 = vertex.color2.w;
float4 matX, matY, matZ; // must be float4 for vec4
int joint = int(vertex.color.x * 255.1 * 3.0);
matX = matrices[int(joint+0)] * w0;
matY = matrices[int(joint+1)] * w0;
matZ = matrices[int(joint+2)] * w0;
joint = int(vertex.color.y * 255.1 * 3.0);
matX += matrices[int(joint+0)] * w1;
matY += matrices[int(joint+1)] * w1;
matZ += matrices[int(joint+2)] * w1;
joint = int(vertex.color.z * 255.1 * 3.0);
matX += matrices[int(joint+0)] * w2;
matY += matrices[int(joint+1)] * w2;
matZ += matrices[int(joint+2)] * w2;
joint = int(vertex.color.w * 255.1 * 3.0);
matX += matrices[int(joint+0)] * w3;
matY += matrices[int(joint+1)] * w3;
matZ += matrices[int(joint+2)] * w3;
float3 normal;
normal.x = dot3( matX, vNormal );
normal.y = dot3( matY, vNormal );
normal.z = dot3( matZ, vNormal );
normal = normalize( normal );
float3 tangent;
tangent.x = dot3( matX, vTangent );
tangent.y = dot3( matY, vTangent );
tangent.z = dot3( matZ, vTangent );
tangent = normalize( tangent );
float3 bitangent;
bitangent.x = dot3( matX, vBitangent );
bitangent.y = dot3( matY, vBitangent );
bitangent.z = dot3( matZ, vBitangent );
bitangent = normalize( bitangent );
float4 modelPosition;
modelPosition.x = dot4( matX, vertex.position );
modelPosition.y = dot4( matY, vertex.position );
modelPosition.z = dot4( matZ, vertex.position );
modelPosition.w = 1.0;
#else
float4 modelPosition = vertex.position;
float3 normal = vNormal.xyz;
float3 tangent = vTangent.xyz;
float3 bitangent = vBitangent.xyz;
#endif
result.position.x = dot4( modelPosition, rpMVPmatrixX );
result.position.y = dot4( modelPosition, rpMVPmatrixY );
result.position.z = dot4( modelPosition, rpMVPmatrixZ );
result.position.w = dot4( modelPosition, rpMVPmatrixW );
float4 defaultTexCoord = float4( 0.0f, 0.5f, 0.0f, 1.0f );
//calculate vector to light
//float4 toLight = rpLocalLightOrigin;
float4 toLight = normalize( float4( 0.0f, 0.5f, 1.0f, 1.0f ) );
//--------------------------------------------------------------
//# textures 0 takes the base coordinates by the texture matrix
result.texcoord0 = defaultTexCoord;
result.texcoord0.x = dot4( vertex.texcoord.xy, rpBumpMatrixS );
result.texcoord0.y = dot4( vertex.texcoord.xy, rpBumpMatrixT );
//# textures 1 takes the base coordinates by the texture matrix
result.texcoord1 = defaultTexCoord;
result.texcoord1.x = dot4( vertex.texcoord.xy, rpDiffuseMatrixS );
result.texcoord1.y = dot4( vertex.texcoord.xy, rpDiffuseMatrixT );
//# textures 2 takes the base coordinates by the texture matrix
result.texcoord2 = defaultTexCoord;
result.texcoord2.x = dot4( vertex.texcoord.xy, rpSpecularMatrixS );
result.texcoord2.y = dot4( vertex.texcoord.xy, rpSpecularMatrixT );
//# calculate normalized vector to viewer in R1
float4 toEye = normalize( rpLocalViewOrigin - modelPosition );
result.texcoord3.x = dot3( toEye, rpModelMatrixX );
result.texcoord3.y = dot3( toEye, rpModelMatrixY );
result.texcoord3.z = dot3( toEye, rpModelMatrixZ );
result.texcoord4.x = dot3( tangent, rpModelMatrixX );
result.texcoord5.x = dot3( tangent, rpModelMatrixY );
result.texcoord6.x = dot3( tangent, rpModelMatrixZ );
result.texcoord4.y = dot3( bitangent, rpModelMatrixX );
result.texcoord5.y = dot3( bitangent, rpModelMatrixY );
result.texcoord6.y = dot3( bitangent, rpModelMatrixZ );
result.texcoord4.z = dot3( normal, rpModelMatrixX );
result.texcoord5.z = dot3( normal, rpModelMatrixY );
result.texcoord6.z = dot3( normal, rpModelMatrixZ );
#if defined( USE_GPU_SKINNING )
// for joint transformation of the tangent space, we use color and
// color2 for weighting information, so hopefully there aren't any
// effects that need vertex color...
result.color = float4( 1.0f, 1.0f, 1.0f, 1.0f );
#else
//# generate the vertex color, which can be 1.0, color, or 1.0 - color
//# for 1.0 : env[16] = 0, env[17] = 1
//# for color : env[16] = 1, env[17] = 0
//# for 1.0-color : env[16] = -1, env[17] = 1
result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;
#endif
}

View file

@ -115,7 +115,11 @@ void main( PS_IN fragment, out PS_OUT result )
#if OPERATOR == 0
// advanced Reinhard operator, artistically desirable to burn out bright areas
float L = Yr * ( 1.0 + Yr / ( Ymax * Ymax ) ) / ( 1.0 + Yr );
//float L = Yr * ( 1.0 + Yr / ( Ymax * Ymax ) ) / ( 1.0 + Yr );
// exponential tone mapper that is very similar to the Uncharted one
// very good in keeping the colors natural
float L = 1.0 - exp( -Yr );
color.rgb *= L;
#elif OPERATOR == 1

View file

@ -637,6 +637,7 @@ set(GAMED3XP_INCLUDES
d3xp/Camera.h
#d3xp/EndLevel.h
d3xp/Entity.h
d3xp/EnvironmentProbe.h
d3xp/Fx.h
d3xp/Game.h
d3xp/GameEdit.h
@ -674,6 +675,7 @@ set(GAMED3XP_SOURCES
d3xp/Camera.cpp
#d3xp/EndLevel.cpp
d3xp/Entity.cpp
d3xp/EnvironmentProbe.cpp
d3xp/Fx.cpp
d3xp/GameEdit.cpp
d3xp/Game_local.cpp

View file

@ -0,0 +1,940 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2015 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 "precompiled.h"
#pragma hdrstop
#include "Game_local.h"
/*
===============================================================================
idLight
===============================================================================
*/
const idEventDef EV_Envprobe_GetEnvprobeParm( "getEnvprobeParm", "d", 'f' );
const idEventDef EV_Envprobe_SetEnvprobeParm( "setEnvprobeParm", "df" );
const idEventDef EV_Envprobe_SetEnvprobeParms( "setEnvprobeParms", "ffff" );
//const idEventDef EV_Envprobe_SetRadiusXYZ( "setRadiusXYZ", "fff" );
//const idEventDef EV_Envprobe_SetRadius( "setRadius", "f" );
const idEventDef EV_Envprobe_On( "On", NULL );
const idEventDef EV_Envprobe_Off( "Off", NULL );
const idEventDef EV_Envprobe_FadeOut( "fadeOutEnvprobe", "f" );
const idEventDef EV_Envprobe_FadeIn( "fadeInEnvprobe", "f" );
CLASS_DECLARATION( idEntity, EnvironmentProbe )
EVENT( EV_Envprobe_GetEnvprobeParm, EnvironmentProbe::Event_GetEnvprobeParm )
EVENT( EV_Envprobe_SetEnvprobeParm, EnvironmentProbe::Event_SetEnvprobeParm )
EVENT( EV_Envprobe_SetEnvprobeParms, EnvironmentProbe::Event_SetEnvprobeParms )
//EVENT( EV_Envprobe_SetRadiusXYZ, EnvironmentProbe::Event_SetRadiusXYZ )
//EVENT( EV_Envprobe_SetRadius, EnvironmentProbe::Event_SetRadius )
EVENT( EV_Hide, EnvironmentProbe::Event_Hide )
EVENT( EV_Show, EnvironmentProbe::Event_Show )
EVENT( EV_Envprobe_On, EnvironmentProbe::Event_On )
EVENT( EV_Envprobe_Off, EnvironmentProbe::Event_Off )
EVENT( EV_Activate, EnvironmentProbe::Event_ToggleOnOff )
//EVENT( EV_PostSpawn, EnvironmentProbe::Event_SetSoundHandles )
EVENT( EV_Envprobe_FadeOut, EnvironmentProbe::Event_FadeOut )
EVENT( EV_Envprobe_FadeIn, EnvironmentProbe::Event_FadeIn )
END_CLASS
/*
================
idGameEdit::ParseSpawnArgsToRenderLight
parse the light parameters
this is the canonical renderLight parm parsing,
which should be used by dmap and the editor
================
*/
void idGameEdit::ParseSpawnArgsToRenderEnvprobe( const idDict* args, renderEnvironmentProbe_t* renderEnvprobe )
{
idVec3 color;
memset( renderEnvprobe, 0, sizeof( *renderEnvprobe ) );
if( !args->GetVector( "light_origin", "", renderEnvprobe->origin ) )
{
args->GetVector( "origin", "", renderEnvprobe->origin );
}
// check for other attributes
args->GetVector( "_color", "1 1 1", color );
renderEnvprobe->shaderParms[ SHADERPARM_RED ] = color[0];
renderEnvprobe->shaderParms[ SHADERPARM_GREEN ] = color[1];
renderEnvprobe->shaderParms[ SHADERPARM_BLUE ] = color[2];
args->GetFloat( "shaderParm3", "1", renderEnvprobe->shaderParms[ SHADERPARM_TIMESCALE ] );
if( !args->GetFloat( "shaderParm4", "0", renderEnvprobe->shaderParms[ SHADERPARM_TIMEOFFSET ] ) )
{
// offset the start time of the shader to sync it to the game time
renderEnvprobe->shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( gameLocal.time );
}
args->GetFloat( "shaderParm5", "0", renderEnvprobe->shaderParms[5] );
args->GetFloat( "shaderParm6", "0", renderEnvprobe->shaderParms[6] );
args->GetFloat( "shaderParm7", "0", renderEnvprobe->shaderParms[ SHADERPARM_MODE ] );
}
/*
================
EnvironmentProbe::UpdateChangeableSpawnArgs
================
*/
void EnvironmentProbe::UpdateChangeableSpawnArgs( const idDict* source )
{
idEntity::UpdateChangeableSpawnArgs( source );
if( source )
{
source->Print();
}
gameEdit->ParseSpawnArgsToRenderEnvprobe( source ? source : &spawnArgs, &renderEnvprobe );
UpdateVisuals();
}
/*
================
EnvironmentProbe::EnvironmentProbe
================
*/
EnvironmentProbe::EnvironmentProbe():
previousBaseColor( vec3_zero ) ,
nextBaseColor( vec3_zero )
{
memset( &renderEnvprobe, 0, sizeof( renderEnvprobe ) );
localEnvprobeOrigin = vec3_zero;
localEnvprobeAxis = mat3_identity;
envprobeDefHandle = -1;
levels = 0;
currentLevel = 0;
baseColor = vec3_zero;
count = 0;
triggercount = 0;
lightParent = NULL;
fadeFrom.Set( 1, 1, 1, 1 );
fadeTo.Set( 1, 1, 1, 1 );
fadeStart = 0;
fadeEnd = 0;
}
/*
================
EnvironmentProbe::~idLight
================
*/
EnvironmentProbe::~EnvironmentProbe()
{
if( envprobeDefHandle != -1 )
{
gameRenderWorld->FreeEnvprobeDef( envprobeDefHandle );
}
}
/*
================
EnvironmentProbe::Save
archives object for save game file
================
*/
void EnvironmentProbe::Save( idSaveGame* savefile ) const
{
savefile->WriteRenderEnvprobe( renderEnvprobe );
savefile->WriteVec3( localEnvprobeOrigin );
savefile->WriteMat3( localEnvprobeAxis );
savefile->WriteInt( levels );
savefile->WriteInt( currentLevel );
savefile->WriteVec3( baseColor );
savefile->WriteInt( count );
savefile->WriteInt( triggercount );
savefile->WriteObject( lightParent );
savefile->WriteVec4( fadeFrom );
savefile->WriteVec4( fadeTo );
savefile->WriteInt( fadeStart );
savefile->WriteInt( fadeEnd );
}
/*
================
EnvironmentProbe::Restore
unarchives object from save game file
================
*/
void EnvironmentProbe::Restore( idRestoreGame* savefile )
{
savefile->ReadRenderEnvprobe( renderEnvprobe );
savefile->ReadVec3( localEnvprobeOrigin );
savefile->ReadMat3( localEnvprobeAxis );
savefile->ReadInt( levels );
savefile->ReadInt( currentLevel );
savefile->ReadVec3( baseColor );
savefile->ReadInt( count );
savefile->ReadInt( triggercount );
savefile->ReadObject( reinterpret_cast<idClass*&>( lightParent ) );
savefile->ReadVec4( fadeFrom );
savefile->ReadVec4( fadeTo );
savefile->ReadInt( fadeStart );
savefile->ReadInt( fadeEnd );
envprobeDefHandle = -1;
SetLightLevel();
}
/*
================
EnvironmentProbe::Spawn
================
*/
void EnvironmentProbe::Spawn()
{
bool start_off;
// do the parsing the same way dmap and the editor do
gameEdit->ParseSpawnArgsToRenderEnvprobe( &spawnArgs, &renderEnvprobe );
// we need the origin and axis relative to the physics origin/axis
localEnvprobeOrigin = ( renderEnvprobe.origin - GetPhysics()->GetOrigin() ) * GetPhysics()->GetAxis().Transpose();
localEnvprobeAxis = /*renderEnvprobe.axis * */ GetPhysics()->GetAxis().Transpose();
// set the base color from the shader parms
baseColor.Set( renderEnvprobe.shaderParms[ SHADERPARM_RED ], renderEnvprobe.shaderParms[ SHADERPARM_GREEN ], renderEnvprobe.shaderParms[ SHADERPARM_BLUE ] );
previousBaseColor.Set( renderEnvprobe.shaderParms[ SHADERPARM_RED ], renderEnvprobe.shaderParms[ SHADERPARM_GREEN ], renderEnvprobe.shaderParms[ SHADERPARM_BLUE ] );
nextBaseColor.Set( renderEnvprobe.shaderParms[ SHADERPARM_RED ], renderEnvprobe.shaderParms[ SHADERPARM_GREEN ], renderEnvprobe.shaderParms[ SHADERPARM_BLUE ] );
// set the number of light levels
spawnArgs.GetInt( "levels", "1", levels );
currentLevel = levels;
if( levels <= 0 )
{
gameLocal.Error( "Invalid light level set on entity #%d(%s)", entityNumber, name.c_str() );
}
// game specific functionality, not mirrored in
// editor or dmap light parsing
envprobeDefHandle = -1; // no static version yet
spawnArgs.GetBool( "start_off", "0", start_off );
if( start_off )
{
Off();
}
// Midnight CTF
if( gameLocal.mpGame.IsGametypeFlagBased() && gameLocal.serverInfo.GetBool( "si_midnight" ) && !spawnArgs.GetBool( "midnight_override" ) )
{
Off();
}
health = spawnArgs.GetInt( "health", "0" );
spawnArgs.GetInt( "count", "1", count );
triggercount = 0;
fadeFrom.Set( 1, 1, 1, 1 );
fadeTo.Set( 1, 1, 1, 1 );
fadeStart = 0;
fadeEnd = 0;
PostEventMS( &EV_PostSpawn, 0 );
UpdateVisuals();
}
/*
================
EnvironmentProbe::SetLightLevel
================
*/
void EnvironmentProbe::SetLightLevel()
{
idVec3 color;
float intensity;
intensity = ( float )currentLevel / ( float )levels;
color = baseColor * intensity;
renderEnvprobe.shaderParms[ SHADERPARM_RED ] = color[ 0 ];
renderEnvprobe.shaderParms[ SHADERPARM_GREEN ] = color[ 1 ];
renderEnvprobe.shaderParms[ SHADERPARM_BLUE ] = color[ 2 ];
PresentEnvprobeDefChange();
}
/*
================
EnvironmentProbe::GetColor
================
*/
void EnvironmentProbe::GetColor( idVec3& out ) const
{
out[ 0 ] = renderEnvprobe.shaderParms[ SHADERPARM_RED ];
out[ 1 ] = renderEnvprobe.shaderParms[ SHADERPARM_GREEN ];
out[ 2 ] = renderEnvprobe.shaderParms[ SHADERPARM_BLUE ];
}
/*
================
EnvironmentProbe::GetColor
================
*/
void EnvironmentProbe::GetColor( idVec4& out ) const
{
out[ 0 ] = renderEnvprobe.shaderParms[ SHADERPARM_RED ];
out[ 1 ] = renderEnvprobe.shaderParms[ SHADERPARM_GREEN ];
out[ 2 ] = renderEnvprobe.shaderParms[ SHADERPARM_BLUE ];
out[ 3 ] = renderEnvprobe.shaderParms[ SHADERPARM_ALPHA ];
}
/*
================
EnvironmentProbe::SetColor
================
*/
void EnvironmentProbe::SetColor( float red, float green, float blue )
{
baseColor.Set( red, green, blue );
SetLightLevel();
}
/*
================
EnvironmentProbe::SetColor
================
*/
void EnvironmentProbe::SetColor( const idVec4& color )
{
baseColor = color.ToVec3();
renderEnvprobe.shaderParms[ SHADERPARM_ALPHA ] = color[ 3 ];
SetLightLevel();
}
/*
================
EnvironmentProbe::SetColor
================
*/
void EnvironmentProbe::SetColor( const idVec3& color )
{
baseColor = color;
SetLightLevel();
}
/*
================
EnvironmentProbe::SetEnvprobeParm
================
*/
void EnvironmentProbe::SetEnvprobeParm( int parmnum, float value )
{
if( ( parmnum < 0 ) || ( parmnum >= MAX_ENTITY_SHADER_PARMS ) )
{
gameLocal.Error( "shader parm index (%d) out of range", parmnum );
return;
}
renderEnvprobe.shaderParms[ parmnum ] = value;
PresentEnvprobeDefChange();
}
/*
================
EnvironmentProbe::SetEnvprobeParms
================
*/
void EnvironmentProbe::SetEnvprobeParms( float parm0, float parm1, float parm2, float parm3 )
{
renderEnvprobe.shaderParms[ SHADERPARM_RED ] = parm0;
renderEnvprobe.shaderParms[ SHADERPARM_GREEN ] = parm1;
renderEnvprobe.shaderParms[ SHADERPARM_BLUE ] = parm2;
renderEnvprobe.shaderParms[ SHADERPARM_ALPHA ] = parm3;
PresentEnvprobeDefChange();
}
/*
================
EnvironmentProbe::On
================
*/
void EnvironmentProbe::On()
{
currentLevel = levels;
// offset the start time of the shader to sync it to the game time
renderEnvprobe.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( gameLocal.time );
SetLightLevel();
BecomeActive( TH_UPDATEVISUALS );
}
/*
================
EnvironmentProbe::Off
================
*/
void EnvironmentProbe::Off()
{
currentLevel = 0;
SetLightLevel();
BecomeActive( TH_UPDATEVISUALS );
}
/*
================
EnvironmentProbe::Fade
================
*/
void EnvironmentProbe::Fade( const idVec4& to, float fadeTime )
{
GetColor( fadeFrom );
fadeTo = to;
fadeStart = gameLocal.time;
fadeEnd = gameLocal.time + SEC2MS( fadeTime );
BecomeActive( TH_THINK );
}
/*
================
EnvironmentProbe::FadeOut
================
*/
void EnvironmentProbe::FadeOut( float time )
{
Fade( colorBlack, time );
}
/*
================
EnvironmentProbe::FadeIn
================
*/
void EnvironmentProbe::FadeIn( float time )
{
idVec3 color;
idVec4 color4;
currentLevel = levels;
spawnArgs.GetVector( "_color", "1 1 1", color );
color4.Set( color.x, color.y, color.z, 1.0f );
Fade( color4, time );
}
/*
================
EnvironmentProbe::PresentEnvprobeDefChange
================
*/
void EnvironmentProbe::PresentEnvprobeDefChange()
{
// let the renderer apply it to the world
if( ( envprobeDefHandle != -1 ) )
{
gameRenderWorld->UpdateEnvprobeDef( envprobeDefHandle, &renderEnvprobe );
}
else
{
envprobeDefHandle = gameRenderWorld->AddEnvprobeDef( &renderEnvprobe );
}
}
/*
================
EnvironmentProbe::Present
================
*/
void EnvironmentProbe::Present()
{
// don't present to the renderer if the entity hasn't changed
if( !( thinkFlags & TH_UPDATEVISUALS ) )
{
return;
}
// add the model
idEntity::Present();
// current transformation
// renderEnvprobe.axis = localEnvprobeAxis * GetPhysics()->GetAxis();
renderEnvprobe.origin = GetPhysics()->GetOrigin() + GetPhysics()->GetAxis() * localEnvprobeOrigin;
// reference the sound for shader synced effects
// FIXME TODO?
/*
if( lightParent )
{
renderLight.referenceSound = lightParent->GetSoundEmitter();
renderEntity.referenceSound = lightParent->GetSoundEmitter();
}
else
{
renderLight.referenceSound = refSound.referenceSound;
renderEntity.referenceSound = refSound.referenceSound;
}
*/
// update the renderLight and renderEntity to render the light and flare
PresentEnvprobeDefChange();
}
/*
================
EnvironmentProbe::Think
================
*/
void EnvironmentProbe::Think()
{
idVec4 color;
if( thinkFlags & TH_THINK )
{
if( fadeEnd > 0 )
{
if( gameLocal.time < fadeEnd )
{
color.Lerp( fadeFrom, fadeTo, ( float )( gameLocal.time - fadeStart ) / ( float )( fadeEnd - fadeStart ) );
}
else
{
color = fadeTo;
fadeEnd = 0;
BecomeInactive( TH_THINK );
}
SetColor( color );
}
}
RunPhysics();
Present();
}
/*
================
EnvironmentProbe::ClientThink
================
*/
void EnvironmentProbe::ClientThink( const int curTime, const float fraction, const bool predict )
{
InterpolatePhysics( fraction );
if( baseColor != nextBaseColor )
{
baseColor = Lerp( previousBaseColor, nextBaseColor, fraction );
SetColor( baseColor );
BecomeActive( TH_UPDATEVISUALS );
}
Present();
}
/*
================
EnvironmentProbe::GetPhysicsToSoundTransform
================
*/
bool EnvironmentProbe::GetPhysicsToSoundTransform( idVec3& origin, idMat3& axis )
{
//origin = localEnvprobeOrigin + renderEnvprobe.lightCenter;
//axis = localLightAxis * GetPhysics()->GetAxis();
//return true;
return false;
}
/*
================
EnvironmentProbe::FreeEnvprobeDef
================
*/
void EnvironmentProbe::FreeEnvprobeDef()
{
if( envprobeDefHandle != -1 )
{
gameRenderWorld->FreeEnvprobeDef( envprobeDefHandle );
envprobeDefHandle = -1;
}
}
/*
================
EnvironmentProbe::SaveState
================
*/
void EnvironmentProbe::SaveState( idDict* args )
{
int i, c = spawnArgs.GetNumKeyVals();
for( i = 0; i < c; i++ )
{
const idKeyValue* pv = spawnArgs.GetKeyVal( i );
if( pv->GetKey().Find( "editor_", false ) >= 0 || pv->GetKey().Find( "parse_", false ) >= 0 )
{
continue;
}
args->Set( pv->GetKey(), pv->GetValue() );
}
}
/*
===============
EnvironmentProbe::ShowEditingDialog
===============
*/
void EnvironmentProbe::ShowEditingDialog()
{
}
/*
================
EnvironmentProbe::Event_GetEnvprobeParm
================
*/
void EnvironmentProbe::Event_GetEnvprobeParm( int parmnum )
{
if( ( parmnum < 0 ) || ( parmnum >= MAX_ENTITY_SHADER_PARMS ) )
{
gameLocal.Error( "shader parm index (%d) out of range", parmnum );
return;
}
idThread::ReturnFloat( renderEnvprobe.shaderParms[ parmnum ] );
}
/*
================
EnvironmentProbe::Event_SetEnvprobeParm
================
*/
void EnvironmentProbe::Event_SetEnvprobeParm( int parmnum, float value )
{
SetEnvprobeParm( parmnum, value );
}
/*
================
EnvironmentProbe::Event_SetEnvprobetParms
================
*/
void EnvironmentProbe::Event_SetEnvprobeParms( float parm0, float parm1, float parm2, float parm3 )
{
SetEnvprobeParms( parm0, parm1, parm2, parm3 );
}
/*
================
EnvironmentProbe::Event_Hide
================
*/
void EnvironmentProbe::Event_Hide()
{
Hide();
Off();
}
/*
================
EnvironmentProbe::Event_Show
================
*/
void EnvironmentProbe::Event_Show()
{
Show();
On();
}
/*
================
EnvironmentProbe::Event_On
================
*/
void EnvironmentProbe::Event_On()
{
On();
}
/*
================
EnvironmentProbe::Event_Off
================
*/
void EnvironmentProbe::Event_Off()
{
Off();
}
/*
================
EnvironmentProbe::Event_ToggleOnOff
================
*/
void EnvironmentProbe::Event_ToggleOnOff( idEntity* activator )
{
triggercount++;
if( triggercount < count )
{
return;
}
// reset trigger count
triggercount = 0;
if( !currentLevel )
{
On();
}
else
{
currentLevel--;
if( !currentLevel )
{
Off();
}
else
{
SetLightLevel();
}
}
}
/*
================
EnvironmentProbe::Event_SetSoundHandles
set the same sound def handle on all targeted lights
================
*/
/*
void EnvironmentProbe::Event_SetSoundHandles()
{
int i;
idEntity* targetEnt;
if( !refSound.referenceSound )
{
return;
}
for( i = 0; i < targets.Num(); i++ )
{
targetEnt = targets[ i ].GetEntity();
if( targetEnt != NULL && targetEnt->IsType( EnvironmentProbe::Type ) )
{
idLight* light = static_cast<idLight*>( targetEnt );
light->lightParent = this;
// explicitly delete any sounds on the entity
light->FreeSoundEmitter( true );
// manually set the refSound to this light's refSound
light->renderEntity.referenceSound = renderEntity.referenceSound;
// update the renderEntity to the renderer
light->UpdateVisuals();
}
}
}
*/
/*
================
EnvironmentProbe::Event_FadeOut
================
*/
void EnvironmentProbe::Event_FadeOut( float time )
{
FadeOut( time );
}
/*
================
EnvironmentProbe::Event_FadeIn
================
*/
void EnvironmentProbe::Event_FadeIn( float time )
{
FadeIn( time );
}
/*
================
EnvironmentProbe::ClientPredictionThink
================
*/
void EnvironmentProbe::ClientPredictionThink()
{
Think();
}
/*
================
EnvironmentProbe::WriteToSnapshot
================
*/
void EnvironmentProbe::WriteToSnapshot( idBitMsg& msg ) const
{
GetPhysics()->WriteToSnapshot( msg );
WriteBindToSnapshot( msg );
msg.WriteByte( currentLevel );
msg.WriteLong( PackColor( baseColor ) );
// msg.WriteBits( lightParent.GetEntityNum(), GENTITYNUM_BITS );
/* // only helps prediction
msg.WriteLong( PackColor( fadeFrom ) );
msg.WriteLong( PackColor( fadeTo ) );
msg.WriteLong( fadeStart );
msg.WriteLong( fadeEnd );
*/
// FIXME: send renderLight.shader
//msg.WriteFloat( renderEnvprobe.lightRadius[0], 5, 10 );
//msg.WriteFloat( renderEnvprobe.lightRadius[1], 5, 10 );
//msg.WriteFloat( renderEnvprobe.lightRadius[2], 5, 10 );
msg.WriteLong( PackColor( idVec4( renderEnvprobe.shaderParms[SHADERPARM_RED],
renderEnvprobe.shaderParms[SHADERPARM_GREEN],
renderEnvprobe.shaderParms[SHADERPARM_BLUE],
renderEnvprobe.shaderParms[SHADERPARM_ALPHA] ) ) );
msg.WriteFloat( renderEnvprobe.shaderParms[SHADERPARM_TIMESCALE], 5, 10 );
msg.WriteLong( renderEnvprobe.shaderParms[SHADERPARM_TIMEOFFSET] );
msg.WriteShort( renderEnvprobe.shaderParms[SHADERPARM_MODE] );
WriteColorToSnapshot( msg );
}
/*
================
EnvironmentProbe::ReadFromSnapshot
================
*/
void EnvironmentProbe::ReadFromSnapshot( const idBitMsg& msg )
{
idVec4 shaderColor;
int oldCurrentLevel = currentLevel;
idVec3 oldBaseColor = baseColor;
previousBaseColor = nextBaseColor;
GetPhysics()->ReadFromSnapshot( msg );
ReadBindFromSnapshot( msg );
currentLevel = msg.ReadByte();
if( currentLevel != oldCurrentLevel )
{
// need to call On/Off for flickering lights to start/stop the sound
// while doing it this way rather than through events, the flickering is out of sync between clients
// but at least there is no question about saving the event and having them happening globally in the world
if( currentLevel )
{
On();
}
else
{
Off();
}
}
UnpackColor( msg.ReadLong(), nextBaseColor );
// lightParentEntityNum = msg.ReadBits( GENTITYNUM_BITS );
/* // only helps prediction
UnpackColor( msg.ReadLong(), fadeFrom );
UnpackColor( msg.ReadLong(), fadeTo );
fadeStart = msg.ReadLong();
fadeEnd = msg.ReadLong();
*/
// FIXME: read renderLight.shader
//renderLight.lightRadius[0] = msg.ReadFloat( 5, 10 );
//renderLight.lightRadius[1] = msg.ReadFloat( 5, 10 );
//renderLight.lightRadius[2] = msg.ReadFloat( 5, 10 );
UnpackColor( msg.ReadLong(), shaderColor );
renderEnvprobe.shaderParms[SHADERPARM_RED] = shaderColor[0];
renderEnvprobe.shaderParms[SHADERPARM_GREEN] = shaderColor[1];
renderEnvprobe.shaderParms[SHADERPARM_BLUE] = shaderColor[2];
renderEnvprobe.shaderParms[SHADERPARM_ALPHA] = shaderColor[3];
renderEnvprobe.shaderParms[SHADERPARM_TIMESCALE] = msg.ReadFloat( 5, 10 );
renderEnvprobe.shaderParms[SHADERPARM_TIMEOFFSET] = msg.ReadLong();
renderEnvprobe.shaderParms[SHADERPARM_MODE] = msg.ReadShort();
ReadColorFromSnapshot( msg );
if( msg.HasChanged() )
{
if( ( currentLevel != oldCurrentLevel ) || ( previousBaseColor != nextBaseColor ) )
{
SetLightLevel();
}
else
{
PresentEnvprobeDefChange();
}
}
}
/*
================
EnvironmentProbe::ClientReceiveEvent
================
*/
/*
bool EnvironmentProbe::ClientReceiveEvent( int event, int time, const idBitMsg& msg )
{
switch( event )
{
case EVENT_BECOMEBROKEN:
{
BecomeBroken( NULL );
return true;
}
default:
{
return idEntity::ClientReceiveEvent( event, time, msg );
}
}
}
*/

143
neo/d3xp/EnvironmentProbe.h Normal file
View file

@ -0,0 +1,143 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2015 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.
===========================================================================
*/
#ifndef __GAME_ENVIRONMENTPROBE_H__
#define __GAME_ENVIRONMENTPROBE_H__
/*
===============================================================================
Environment probe for Image Based Lighting (part of PBR).
===============================================================================
*/
class EnvironmentProbe : public idEntity
{
public:
CLASS_PROTOTYPE( EnvironmentProbe );
EnvironmentProbe();
~EnvironmentProbe();
void Spawn();
void Save( idSaveGame* savefile ) const; // archives object for save game file
void Restore( idRestoreGame* savefile ); // unarchives object from save game file
virtual void UpdateChangeableSpawnArgs( const idDict* source );
virtual void Think();
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void FreeEnvprobeDef();
virtual bool GetPhysicsToSoundTransform( idVec3& origin, idMat3& axis );
void Present();
void SaveState( idDict* args );
virtual void SetColor( float red, float green, float blue );
virtual void SetColor( const idVec4& color );
void SetColor( const idVec3& color );
virtual void GetColor( idVec3& out ) const;
virtual void GetColor( idVec4& out ) const;
const idVec3& GetBaseColor() const
{
return baseColor;
}
void SetEnvprobeParm( int parmnum, float value );
void SetEnvprobeParms( float parm0, float parm1, float parm2, float parm3 );
void On();
void Off();
void Fade( const idVec4& to, float fadeTime );
void FadeOut( float time );
void FadeIn( float time );
qhandle_t GetEnvprobeDefHandle() const
{
return envprobeDefHandle;
}
void SetEnvprobeParent( idEntity* lparent )
{
lightParent = lparent;
}
void SetLightLevel();
virtual void ShowEditingDialog();
enum
{
EVENT_BECOMEBROKEN = idEntity::EVENT_MAXEVENTS,
EVENT_MAXEVENTS
};
virtual void ClientPredictionThink();
virtual void WriteToSnapshot( idBitMsg& msg ) const;
virtual void ReadFromSnapshot( const idBitMsg& msg );
// virtual bool ClientReceiveEvent( int event, int time, const idBitMsg& msg );
private:
renderEnvironmentProbe_t renderEnvprobe; // envprobe presented to the renderer
idVec3 localEnvprobeOrigin; // light origin relative to the physics origin
idMat3 localEnvprobeAxis; // light axis relative to physics axis
qhandle_t envprobeDefHandle; // handle to renderer light def
int levels;
int currentLevel;
idVec3 baseColor;
// Colors used for client-side interpolation.
idVec3 previousBaseColor;
idVec3 nextBaseColor;
int count;
int triggercount;
idEntity* lightParent;
idVec4 fadeFrom;
idVec4 fadeTo;
int fadeStart;
int fadeEnd;
private:
void PresentEnvprobeDefChange();
void Event_GetEnvprobeParm( int parmnum );
void Event_SetEnvprobeParm( int parmnum, float value );
void Event_SetEnvprobeParms( float parm0, float parm1, float parm2, float parm3 );
void Event_SetRadiusXYZ( float x, float y, float z );
void Event_SetRadius( float radius );
void Event_Hide();
void Event_Show();
void Event_On();
void Event_Off();
void Event_ToggleOnOff( idEntity* activator );
void Event_SetSoundHandles();
void Event_FadeOut( float time );
void Event_FadeIn( float time );
};
#endif /* !__GAME_ENVIRONMENTPROBE_H__ */

View file

@ -240,6 +240,7 @@ public:
// These are the canonical idDict to parameter parsing routines used by both the game and tools.
virtual void ParseSpawnArgsToRenderLight( const idDict* args, renderLight_t* renderLight );
virtual void ParseSpawnArgsToRenderEntity( const idDict* args, renderEntity_t* renderEntity );
virtual void ParseSpawnArgsToRenderEnvprobe( const idDict* args, renderEnvironmentProbe_t* renderEnvprobe ); // RB
virtual void ParseSpawnArgsToRefSound( const idDict* args, refSound_t* refSound );
// Animation system calls for non-game based skeletal rendering.

View file

@ -904,6 +904,7 @@ const int CINEMATIC_SKIP_DELAY = SEC2MS( 2.0f );
#include "Projectile.h"
#include "Weapon.h"
#include "Light.h"
#include "EnvironmentProbe.h"
#include "WorldSpawn.h"
#include "Item.h"
#include "PlayerView.h"

View file

@ -731,6 +731,21 @@ void idSaveGame::WriteRenderLight( const renderLight_t& renderLight )
}
}
// RB begin
void idSaveGame::WriteRenderEnvprobe( const renderEnvironmentProbe_t& renderEnvprobe )
{
WriteVec3( renderEnvprobe.origin );
WriteInt( renderEnvprobe.suppressEnvprobeInViewID );
WriteInt( renderEnvprobe.allowEnvprobeInViewID );
for( int i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ )
{
WriteFloat( renderEnvprobe.shaderParms[ i ] );
}
}
// Rb end
/*
================
idSaveGame::WriteRefSound
@ -1629,6 +1644,21 @@ void idRestoreGame::ReadRenderLight( renderLight_t& renderLight )
renderLight.referenceSound = gameSoundWorld->EmitterForIndex( index );
}
// RB begin
void idRestoreGame::ReadRenderEnvprobe( renderEnvironmentProbe_t& renderEnvprobe )
{
ReadVec3( renderEnvprobe.origin );
ReadInt( renderEnvprobe.suppressEnvprobeInViewID );
ReadInt( renderEnvprobe.allowEnvprobeInViewID );
for( int i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ )
{
ReadFloat( renderEnvprobe.shaderParms[ i ] );
}
}
// RB end
/*
================
idRestoreGame::ReadRefSound

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) 2015 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -82,6 +83,7 @@ public:
void WriteUserInterface( const idUserInterface* ui, bool unique );
void WriteRenderEntity( const renderEntity_t& renderEntity );
void WriteRenderLight( const renderLight_t& renderLight );
void WriteRenderEnvprobe( const renderEnvironmentProbe_t& renderEnvprobe ); // RB
void WriteRefSound( const refSound_t& refSound );
void WriteRenderView( const renderView_t& view );
void WriteUsercmd( const usercmd_t& usercmd );
@ -169,6 +171,7 @@ public:
void ReadUserInterface( idUserInterface*& ui );
void ReadRenderEntity( renderEntity_t& renderEntity );
void ReadRenderLight( renderLight_t& renderLight );
void ReadRenderEnvprobe( renderEnvironmentProbe_t& renderEnvprobe ); // RB
void ReadRefSound( refSound_t& refSound );
void ReadRenderView( renderView_t& view );
void ReadUsercmd( usercmd_t& usercmd );

View file

@ -194,7 +194,8 @@ gameReturn_t idGameThread::RunGameAndDraw( int numGameFrames_, idUserCmdMgr& use
numGameFrames = numGameFrames_;
// start the thread going
if( com_smp.GetInteger() <= 0 )
// foresthale 2014-05-12: also check com_editors as many of them are not particularly thread-safe (editLights for example)
if( com_smp.GetBool() == false || com_editors != 0 )
{
// run it in the main thread so PIX profiling catches everything
Run();
@ -249,8 +250,49 @@ void idCommonLocal::Draw()
Sys_Sleep( com_sleepDraw.GetInteger() );
}
if( loadGUI != NULL )
if( loadPacifierBinarizeActive )
{
// foresthale 2014-05-30: when binarizing an asset we show a special
// overlay indicating progress
renderSystem->SetColor( colorBlack );
renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 1, 1, whiteMaterial );
// render the loading gui (idSWF actually) if it is loaded
// (we want to see progress of the loading gui binarize too)
if( loadGUI != NULL )
loadGUI->Render( renderSystem, Sys_Milliseconds() );
// update our progress estimates
int time = Sys_Milliseconds();
if( loadPacifierBinarizeProgress > 0.0f )
loadPacifierBinarizeTimeLeft = ( 1.0 - loadPacifierBinarizeProgress ) * ( time - loadPacifierBinarizeStartTime ) * 0.001f / loadPacifierBinarizeProgress;
else
loadPacifierBinarizeTimeLeft = -1.0f;
// prepare our strings
const char* text;
if( loadPacifierBinarizeTimeLeft >= 99.5f )
text = va( "Binarizing %3.0f%% ETA %2.0f minutes", loadPacifierBinarizeProgress * 100.0f, loadPacifierBinarizeTimeLeft / 60.0f );
else if( loadPacifierBinarizeTimeLeft )
text = va( "Binarizing %3.0f%% ETA %2.0f seconds", loadPacifierBinarizeProgress * 100.0f, loadPacifierBinarizeTimeLeft );
else
text = va( "Binarizing %3.0f%%", loadPacifierBinarizeProgress * 100.0f );
// draw our basic overlay
renderSystem->SetColor( idVec4( 0.0f, 0.0f, 0.5f, 1.0f ) );
renderSystem->DrawStretchPic( 0, SCREEN_HEIGHT - 48, SCREEN_WIDTH, 48, 0, 0, 1, 1, whiteMaterial );
renderSystem->SetColor( idVec4( 0.0f, 0.5f, 0.8f, 1.0f ) );
renderSystem->DrawStretchPic( 0, SCREEN_HEIGHT - 48, loadPacifierBinarizeProgress * SCREEN_WIDTH, 32, 0, 0, 1, 1, whiteMaterial );
renderSystem->DrawSmallStringExt( 0, SCREEN_HEIGHT - 48, loadPacifierBinarizeFilename.c_str(), idVec4( 1.0f, 1.0f, 1.0f, 1.0f ), true );
renderSystem->DrawSmallStringExt( 0, SCREEN_HEIGHT - 32, va( "%s %d/%d lvls", loadPacifierBinarizeInfo.c_str(), loadPacifierBinarizeMiplevel, loadPacifierBinarizeMiplevelTotal ), idVec4( 1.0f, 1.0f, 1.0f, 1.0f ), true );
renderSystem->DrawSmallStringExt( 0, SCREEN_HEIGHT - 16, text, idVec4( 1.0f, 1.0f, 1.0f, 1.0f ), true );
}
else if( loadGUI != NULL )
{
// foresthale 2014-05-30: showing a black background looks better than flickering in widescreen
renderSystem->SetColor( colorBlack );
renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 1, 1, whiteMaterial );
loadGUI->Render( renderSystem, Sys_Milliseconds() );
}
// RB begin
@ -371,6 +413,7 @@ void idCommonLocal::UpdateScreen( bool captureToImage, bool releaseMouse )
// build all the draw commands without running a new game tic
Draw();
// foresthale 2014-03-01: note: the only place that has captureToImage=true is idAutoRender::StartBackgroundAutoSwaps
if( captureToImage )
{
renderSystem->CaptureRenderToImage( "_currentRender", false );
@ -479,6 +522,8 @@ void idCommonLocal::Frame()
eventLoop->RunEventLoop();
renderSystem->OnFrame();
// DG: prepare new ImGui frame - I guess this is a good place, as all new events should be available?
ImGuiHook::NewFrame();
@ -557,7 +602,9 @@ void idCommonLocal::Frame()
// This may block if the GPU isn't finished renderng the previous frame.
frameTiming.startSyncTime = Sys_Microseconds();
const emptyCommand_t* renderCommands = NULL;
if( com_smp.GetInteger() > 0 )
// foresthale 2014-05-12: also check com_editors as many of them are not particularly thread-safe (editLights for example)
if( com_smp.GetInteger() > 0 && com_editors == 0 )
{
renderCommands = renderSystem->SwapCommandBuffers( &time_frontend, &time_backend, &time_shadows, &time_gpu );
}
@ -786,12 +833,13 @@ void idCommonLocal::Frame()
// start the game / draw command generation thread going in the background
gameReturn_t ret = gameThread.RunGameAndDraw( numGameFrames, userCmdMgr, IsClient(), gameFrame - numGameFrames );
if( com_smp.GetInteger() < 0 )
// foresthale 2014-05-12: also check com_editors as many of them are not particularly thread-safe (editLights for example)
if( !com_smp.GetInteger() < 0 )
{
// RB: this is the same as Doom 3 renderSystem->EndFrame()
renderSystem->SwapCommandBuffers_FinishRendering( &time_frontend, &time_backend, &time_shadows, &time_gpu );
}
else if( com_smp.GetInteger() == 0 )
else if( com_smp.GetInteger() == 0 || com_editors != 0 )
{
// in non-smp mode, run the commands we just generated, instead of
// frame-delayed ones from a background thread

View file

@ -102,9 +102,11 @@ MEM_TAG( RENDER_WINDING )
MEM_TAG( RENDER_STATIC )
MEM_TAG( RENDER_ENTITY )
MEM_TAG( RENDER_LIGHT )
MEM_TAG( RENDER_ENVPROBE ) // RB
MEM_TAG( RENDER_INTERACTION )
MEM_TAG( SURFACE )
MEM_TAG( LIGHT )
MEM_TAG( ENVPROBE ) // RB
MEM_TAG( AI )
MEM_TAG( SCRIPT )
MEM_TAG( EVENTS )

View file

@ -44,7 +44,7 @@ If you have questions concerning this license or the applicable additional terms
#include "Color/ColorSpace.h"
idCVar image_highQualityCompression( "image_highQualityCompression", "0", CVAR_BOOL, "Use high quality (slow) compression" );
idCVar r_useHighQualitySky( "r_useHighQualitySky", "0", CVAR_BOOL | CVAR_ARCHIVE, "Use high quality skyboxes" );
idCVar r_useHighQualitySky( "r_useHighQualitySky", "1", CVAR_BOOL | CVAR_ARCHIVE, "Use high quality skyboxes" );
/*
========================
@ -360,13 +360,37 @@ void idBinaryImage::LoadCubeFromMemory( int width, const byte* pics[6], int numL
{
img.Alloc( padSize * padSize / 2 );
idDxtEncoder dxt;
dxt.CompressImageDXT1Fast( padSrc, img.data, padSize, padSize );
if( image_highQualityCompression.GetBool() )
{
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - DXT1HQ", width, width ) );
dxt.CompressImageDXT1HQ( padSrc, img.data, padSize, padSize );
}
else
{
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - DXT1Fast", width, width ) );
dxt.CompressImageDXT1Fast( padSrc, img.data, padSize, padSize );
}
}
else if( textureFormat == FMT_DXT5 )
{
img.Alloc( padSize * padSize );
idDxtEncoder dxt;
dxt.CompressImageDXT5Fast( padSrc, img.data, padSize, padSize );
if( image_highQualityCompression.GetBool() )
{
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - DXT5HQ", width, width ) );
dxt.CompressImageDXT5HQ( padSrc, img.data, padSize, padSize );
}
else
{
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - DXT5Fast", width, width ) );
dxt.CompressImageDXT5Fast( padSrc, img.data, padSize, padSize );
}
}
else
{

View file

@ -216,6 +216,10 @@ typedef enum
TD_COVERAGE, // coverage map for fill depth pass when YCoCG is used
TD_DEPTH, // depth buffer copy for motion blur
// RB begin
TD_SPECULAR_PBR_RMAO, // may be compressed, and always zeros the alpha channel, linear RGB R = roughness, G = metal, B = ambient occlusion
TD_SPECULAR_PBR_RMAOD, // may be compressed, alpha channel contains displacement map
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_RGBA16F,
TD_RGBA32F,
@ -365,6 +369,11 @@ public:
return ( opts.format == FMT_DXT1 || opts.format == FMT_DXT5 );
}
textureUsage_t GetUsage() const
{
return usage;
}
bool IsLoaded() const;
static void GetGeneratedName( idStr& _name, const textureUsage_t& _usage, const cubeFiles_t& _cube );
@ -564,6 +573,9 @@ public:
idImage* ambientOcclusionImage[2]; // contain AO and bilateral filtering keys
idImage* hierarchicalZbufferImage; // zbuffer with mip maps to accelerate screen space ray tracing
idImage* imguiFontImage;
idImage* defaultUACIrradianceCube;
idImage* defaultUACRadianceCube;
// RB end
idImage* scratchImage;
idImage* scratchImage2;
@ -572,7 +584,7 @@ public:
idImage* currentDepthImage; // for motion blur
idImage* originalCurrentRenderImage; // currentRenderImage before any changes for stereo rendering
idImage* loadingIconImage; // loading icon must exist always
idImage* hellLoadingIconImage; // loading icon must exist always
idImage* hellLoadingIconImage; // loading icon must exist always
//--------------------------------------------------------

View file

@ -920,6 +920,9 @@ void idImageManager::CreateIntrinsicImages()
loadingIconImage = ImageFromFile( "textures/loadingicon2", TF_DEFAULT, TR_CLAMP, TD_DEFAULT, CF_2D );
hellLoadingIconImage = ImageFromFile( "textures/loadingicon3", TF_DEFAULT, TR_CLAMP, TD_DEFAULT, CF_2D );
defaultUACIrradianceCube = ImageFromFile( "env/testmap_1_amb", TF_DEFAULT, TR_CLAMP, TD_HIGHQUALITY_CUBE, CF_NATIVE );
defaultUACRadianceCube = ImageFromFile( "env/testmap_1_spec", TF_DEFAULT, TR_CLAMP, TD_HIGHQUALITY_CUBE, CF_NATIVE );
release_assert( loadingIconImage->referencedOutsideLevelLoad );
release_assert( hellLoadingIconImage->referencedOutsideLevelLoad );
}

View file

@ -137,6 +137,19 @@ ID_INLINE void idImage::DeriveOpts()
opts.format = FMT_DXT1;
opts.colorFormat = CFM_DEFAULT;
break;
case TD_SPECULAR_PBR_RMAO:
opts.gammaMips = false;
opts.format = FMT_DXT1;
opts.colorFormat = CFM_DEFAULT;
break;
case TD_SPECULAR_PBR_RMAOD:
opts.gammaMips = false;
opts.format = FMT_DXT5;
opts.colorFormat = CFM_DEFAULT;
break;
case TD_DEFAULT:
opts.gammaMips = true;
opts.format = FMT_DXT5;
@ -169,6 +182,17 @@ ID_INLINE void idImage::DeriveOpts()
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;
opts.format = FMT_RGBA8;
opts.gammaMips = true;
break;
case TD_LOWQUALITY_CUBE:
opts.colorFormat = CFM_DEFAULT; // CFM_YCOCG_DXT5;
opts.format = FMT_DXT5;
opts.gammaMips = true;
break;
default:
assert( false );
opts.format = FMT_RGBA8;
@ -217,6 +241,35 @@ void idImage::AllocImage( const idImageOpts& imgOpts, textureFilter_t tf, textur
}
/*
// foresthale 2014-05-30: give a nice progress display when binarizing
commonLocal.LoadPacifierBinarizeFilename( GetName() , "generated image" );
if( opts.numLevels > 1 )
{
commonLocal.LoadPacifierBinarizeProgressTotal( opts.width * opts.height * 4 / 3 );
}
else
{
commonLocal.LoadPacifierBinarizeProgressTotal( opts.width * opts.height );
}
commonLocal.LoadPacifierBinarizeEnd();
// foresthale 2014-05-30: give a nice progress display when binarizing
commonLocal.LoadPacifierBinarizeFilename( GetName(), "generated cube image" );
if( opts.numLevels > 1 )
{
commonLocal.LoadPacifierBinarizeProgressTotal( opts.width * opts.width * 6 * 4 / 3 );
}
else
{
commonLocal.LoadPacifierBinarizeProgressTotal( opts.width * opts.width * 6 );
}
commonLocal.LoadPacifierBinarizeEnd();
===============
GetGeneratedName
@ -474,6 +527,19 @@ void idImage::ActuallyLoadImage( bool fromBackEnd )
commonLocal.LoadPacifierBinarizeProgressTotal( opts.width * opts.width * 6 );
}
commonLocal.LoadPacifierBinarizeEnd();
// foresthale 2014-05-30: give a nice progress display when binarizing
commonLocal.LoadPacifierBinarizeFilename( generatedName.c_str(), binarizeReason.c_str() );
if( opts.numLevels > 1 )
{
commonLocal.LoadPacifierBinarizeProgressTotal( opts.width * opts.width * 6 * 4 / 3 );
}
else
{
commonLocal.LoadPacifierBinarizeProgressTotal( opts.width * opts.width * 6 );
}
im.Load2DFromMemory( opts.width, opts.height, pic, opts.numLevels, opts.format, opts.colorFormat, opts.gammaMips );
commonLocal.LoadPacifierBinarizeEnd();

View file

@ -84,6 +84,7 @@ struct surfaceInteraction_t
class idRenderEntityLocal;
class idRenderLightLocal;
class RenderEnvprobeLocal;
class idInteraction
{

View file

@ -72,6 +72,8 @@ typedef struct mtrParsingData_s
bool forceOverlays;
} mtrParsingData_t;
extern idCVar r_useHighQualitySky;
idCVar r_forceSoundOpAmplitude( "r_forceSoundOpAmplitude", "0", CVAR_FLOAT, "Don't call into the sound system for amplitudes" );
/*
@ -1045,17 +1047,17 @@ void idMaterial::ParseBlend( idLexer& src, shaderStage_t* stage )
stage->drawStateBits = GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE;
return;
}
if( !token.Icmp( "bumpmap" ) )
if( !token.Icmp( "bumpmap" ) || !token.Icmp( "normalmap" ) )
{
stage->lighting = SL_BUMP;
return;
}
if( !token.Icmp( "diffusemap" ) )
if( !token.Icmp( "diffusemap" ) || !token.Icmp( "basecolormap" ) )
{
stage->lighting = SL_DIFFUSE;
return;
}
if( !token.Icmp( "specularmap" ) )
if( !token.Icmp( "specularmap" ) || !token.Icmp( "rmaomap" ) )
{
stage->lighting = SL_SPECULAR;
return;
@ -1555,8 +1557,16 @@ void idMaterial::ParseStage( idLexer& src, const textureRepeat_t trpDefault )
{
continue;
}
if( !token.Icmp( "uncompressed" ) )
if( !token.Icmp( "uncompressedCubeMap" ) )
{
if( r_useHighQualitySky.GetBool() )
{
td = TD_HIGHQUALITY_CUBE; // motorsep 05-17-2015; token to mark cubemap/skybox to be uncompressed texture
}
else
{
td = TD_LOWQUALITY_CUBE;
}
continue;
}
if( !token.Icmp( "nopicmip" ) )
@ -1897,7 +1907,18 @@ void idMaterial::ParseStage( idLexer& src, const textureRepeat_t trpDefault )
td = TD_DIFFUSE;
break;
case SL_SPECULAR:
td = TD_SPECULAR;
if( idStr::FindText( imageName, "_rmaod", false ) != -1 )
{
td = TD_SPECULAR_PBR_RMAOD;
}
else if( idStr::FindText( imageName, "_rmao", false ) != -1 )
{
td = TD_SPECULAR_PBR_RMAO;
}
else
{
td = TD_SPECULAR;
}
break;
default:
break;
@ -1910,10 +1931,13 @@ void idMaterial::ParseStage( idLexer& src, const textureRepeat_t trpDefault )
// create new coverage stage
shaderStage_t* newCoverageStage = &pd->parseStages[numStages];
numStages++;
// copy it
*newCoverageStage = *ss;
// toggle alphatest off for the current stage so it doesn't get called during the depth fill pass
ss->hasAlphaTest = false;
// toggle alpha test on for the coverage stage
newCoverageStage->hasAlphaTest = true;
newCoverageStage->lighting = SL_COVERAGE;
@ -2465,7 +2489,7 @@ void idMaterial::ParseMaterial( idLexer& src )
continue;
}
// diffusemap for stage shortcut
else if( !token.Icmp( "diffusemap" ) )
else if( !token.Icmp( "diffusemap" ) || !token.Icmp( "basecolormap" ) )
{
str = R_ParsePastImageProgram( src );
idStr::snPrintf( buffer, sizeof( buffer ), "blend diffusemap\nmap %s\n}\n", str );
@ -2487,7 +2511,7 @@ void idMaterial::ParseMaterial( idLexer& src )
continue;
}
// normalmap for stage shortcut
else if( !token.Icmp( "bumpmap" ) )
else if( !token.Icmp( "bumpmap" ) || !token.Icmp( "normalmap" ) )
{
str = R_ParsePastImageProgram( src );
idStr::snPrintf( buffer, sizeof( buffer ), "blend bumpmap\nmap %s\n}\n", str );

View file

@ -690,9 +690,7 @@ void idRenderBackend::PrepareStageTexturing( const shaderStage_t* pStage, const
}
else if( pStage->texture.texgen == TG_SKYBOX_CUBE )
{
renderProgManager.BindShader_SkyBox();
}
else if( pStage->texture.texgen == TG_WOBBLESKY_CUBE )
{
@ -1205,6 +1203,9 @@ const int INTERACTION_TEXUNIT_PROJECTION = 4;
const int INTERACTION_TEXUNIT_SHADOWMAPS = 5;
const int INTERACTION_TEXUNIT_JITTER = 6;
const int INTERACTION_TEXUNIT_AMBIENT_CUBE1 = 7;
const int INTERACTION_TEXUNIT_SPECULAR_CUBE1 = 8;
/*
==================
idRenderBackend::SetupInteractionStage
@ -1267,7 +1268,7 @@ void idRenderBackend::SetupInteractionStage( const shaderStage_t* surfaceStage,
idRenderBackend::DrawSingleInteraction
=================
*/
void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din )
void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useIBL )
{
if( din->bumpImage == NULL )
{
@ -1300,6 +1301,35 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din )
return;
}
if( useIBL )
{
const textureUsage_t specUsage = din->specularImage->GetUsage();
if( specUsage == TD_SPECULAR_PBR_RMAO || specUsage == TD_SPECULAR_PBR_RMAOD )
{
// PBR path with roughness, metal and AO
if( din->surf->jointCache )
{
renderProgManager.BindShader_ImageBasedLightingSkinned_PBR();
}
else
{
renderProgManager.BindShader_ImageBasedLighting_PBR();
}
}
else
{
if( din->surf->jointCache )
{
renderProgManager.BindShader_ImageBasedLightingSkinned();
}
else
{
renderProgManager.BindShader_ImageBasedLighting();
}
}
}
// bump matrix
SetVertexParm( RENDERPARM_BUMPMATRIX_S, din->bumpMatrix[0].ToFloatPtr() );
SetVertexParm( RENDERPARM_BUMPMATRIX_T, din->bumpMatrix[1].ToFloatPtr() );
@ -1838,7 +1868,7 @@ void idRenderBackend::RenderInteractions( const drawSurf_t* surfList, const view
// draw any previous interaction
if( inter.bumpImage != NULL )
{
DrawSingleInteraction( &inter );
DrawSingleInteraction( &inter, false );
}
inter.bumpImage = surfaceStage->texture.image;
inter.diffuseImage = NULL;
@ -1856,7 +1886,7 @@ void idRenderBackend::RenderInteractions( const drawSurf_t* surfList, const view
// draw any previous interaction
if( inter.diffuseImage != NULL )
{
DrawSingleInteraction( &inter );
DrawSingleInteraction( &inter, false );
}
inter.diffuseImage = surfaceStage->texture.image;
inter.vertexColor = surfaceStage->vertexColor;
@ -1874,7 +1904,7 @@ void idRenderBackend::RenderInteractions( const drawSurf_t* surfList, const view
// draw any previous interaction
if( inter.specularImage != NULL )
{
DrawSingleInteraction( &inter );
DrawSingleInteraction( &inter, false );
}
inter.specularImage = surfaceStage->texture.image;
inter.vertexColor = surfaceStage->vertexColor;
@ -1886,7 +1916,7 @@ void idRenderBackend::RenderInteractions( const drawSurf_t* surfList, const view
}
// draw the final interaction
DrawSingleInteraction( &inter );
DrawSingleInteraction( &inter, false );
renderLog.CloseBlock();
}
@ -2054,6 +2084,23 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr
else
#endif
{
#if 1
// draw Quake 4 style ambient
if( drawSurf->jointCache )
{
renderProgManager.BindShader_ImageBasedLightingSkinned();
}
else
{
renderProgManager.BindShader_ImageBasedLighting();
}
GL_SelectTexture( INTERACTION_TEXUNIT_AMBIENT_CUBE1 );
globalImages->defaultUACIrradianceCube->Bind();
GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE1 );
globalImages->defaultUACRadianceCube->Bind();
#else
// draw Quake 4 style ambient
if( drawSurf->jointCache )
{
@ -2063,6 +2110,7 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr
{
renderProgManager.BindShader_AmbientLighting();
}
#endif
}
}
@ -2118,6 +2166,7 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr
renderProgManager.SetRenderParm( RENDERPARM_COLOR, directedColor.ToFloatPtr() );
renderProgManager.SetRenderParm( RENDERPARM_AMBIENT_COLOR, ambientColor.ToFloatPtr() );
}
float ambientBoost = r_useHDR.GetBool() ? 1.5 : 1.0;
#endif
/*
@ -2226,7 +2275,7 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr
// draw any previous interaction
if( inter.bumpImage != NULL )
{
DrawSingleInteraction( &inter );
DrawSingleInteraction( &inter, !fillGbuffer );
}
inter.bumpImage = surfaceStage->texture.image;
inter.diffuseImage = NULL;
@ -2247,7 +2296,7 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr
// draw any previous interaction
if( inter.diffuseImage != NULL )
{
DrawSingleInteraction( &inter );
DrawSingleInteraction( &inter, !fillGbuffer );
}
inter.diffuseImage = surfaceStage->texture.image;
@ -2267,7 +2316,7 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr
// draw any previous interaction
if( inter.specularImage != NULL )
{
DrawSingleInteraction( &inter );
DrawSingleInteraction( &inter, !fillGbuffer );
}
inter.specularImage = surfaceStage->texture.image;
inter.vertexColor = surfaceStage->vertexColor;
@ -2279,7 +2328,7 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr
}
// draw the final interaction
DrawSingleInteraction( &inter );
DrawSingleInteraction( &inter, !fillGbuffer );
renderLog.CloseBlock();
}

View file

@ -242,12 +242,6 @@ all state modified by the back end is separated from the front end state
===========================================================================
*/
//namespace ImGui
//{
//
//}
//#include "../libs/imgui/imgui.h"
struct ImDrawData;
class idRenderBackend
@ -304,7 +298,7 @@ private:
idVec4 matrix[2], float color[4] );
void DrawInteractions( const viewDef_t* _viewDef );
void DrawSingleInteraction( drawInteraction_t* din );
void DrawSingleInteraction( drawInteraction_t* din, bool useIBL );
int DrawShaderPasses( const drawSurf_t* const* const drawSurfs, const int numDrawSurfs,
const float guiStereoScreenOffset, const int stereoEye );

View file

@ -70,6 +70,8 @@ enum demoCommand_t
DC_SET_PORTAL_STATE,
DC_UPDATE_SOUNDOCCLUSION,
DC_GUI_MODEL,
DC_UPDATE_ENVPROBEDEF,
DC_DELETE_ENVPROBEDEF,
DC_UPDATE_DECAL,
DC_DELETE_DECAL,
DC_UPDATE_OVERLAY,
@ -129,9 +131,12 @@ struct areaReference_t
areaReference_t* areaNext; // chain in the area
areaReference_t* areaPrev;
areaReference_t* ownerNext; // chain on either the entityDef or lightDef
idRenderEntityLocal* entity; // only one of entity / light will be non-NULL
idRenderLightLocal* light; // only one of entity / light will be non-NULL
struct portalArea_s* area; // so owners can find all the areas they are in
idRenderEntityLocal* entity; // only one of entity / light / envprobe will be non-NULL
idRenderLightLocal* light; // only one of entity / light / envprobe will be non-NULL
RenderEnvprobeLocal* envprobe; // only one of entity / light / envprobe will be non-NULL
struct portalArea_s* area; // so owners can find all the areas they are in
};
@ -148,6 +153,19 @@ public:
virtual int GetIndex() = 0;
};
// RB : RennderEnvprobe should become the new public interface replacing the qhandle_t to envprobe defs in the idRenderWorld interface
class RenderEnvprobe
{
public:
virtual ~RenderEnvprobe() {}
virtual void FreeRenderEnvprobe() = 0;
virtual void UpdateRenderEnvprobe( const renderEnvironmentProbe_t* ep, bool forceUpdate = false ) = 0;
virtual void GetRenderEnvprobe( renderEnvironmentProbe_t* ep ) = 0;
virtual void ForceUpdate() = 0;
virtual int GetIndex() = 0;
};
// RB end
// idRenderEntity should become the new public interface replacing the qhandle_t to entity defs in the idRenderWorld interface
class idRenderEntity
@ -221,6 +239,40 @@ public:
};
// RB begin
class RenderEnvprobeLocal : public RenderEnvprobe
{
public:
RenderEnvprobeLocal();
virtual void FreeRenderEnvprobe() override;
virtual void UpdateRenderEnvprobe( const renderEnvironmentProbe_t* ep, bool forceUpdate = false ) override;
virtual void GetRenderEnvprobe( renderEnvironmentProbe_t* ep ) override;
virtual void ForceUpdate() override;
virtual int GetIndex() override;
renderEnvironmentProbe_t parms; // specification
bool envprobeHasMoved; // the light has changed its position since it was
// first added, so the prelight model is not valid
idRenderWorldLocal* world;
int index; // in world envprobeDefs
int areaNum; // if not -1, we may be able to cull all the envprobe's
// interactions if !viewDef->connectedAreas[areaNum]
int lastModifiedFrameNum; // to determine if it is constantly changing,
// and should go in the dynamic frame memory, or kept
// in the cached memory
bool archived; // for demo writing
// derived information
areaReference_t* references; // each area the light is present in will have a lightRef
//idInteraction* firstInteraction; // doubly linked list
//idInteraction* lastInteraction;
};
// RB end
class idRenderEntityLocal : public idRenderEntity
{
public:
@ -666,6 +718,7 @@ struct performanceCounters_t
int c_tangentIndexes; // R_DeriveTangents()
int c_entityUpdates;
int c_lightUpdates;
int c_envprobeUpdates;
int c_entityReferences;
int c_lightReferences;
int c_guiSurfs;
@ -1181,6 +1234,10 @@ void R_DeriveLightData( idRenderLightLocal* light );
void R_RenderLightFrustum( const renderLight_t& renderLight, idPlane lightFrustum[6] );
srfTriangles_t* R_PolytopeSurface( int numPlanes, const idPlane* planes, idWinding** windings );
void R_CreateEnvprobeRefs( RenderEnvprobeLocal* probe );
void R_FreeEnvprobeDefDerivedData( RenderEnvprobeLocal* probe );
// RB end
void R_CreateLightRefs( idRenderLightLocal* light );
void R_FreeLightDefDerivedData( idRenderLightLocal* light );

View file

@ -129,6 +129,38 @@ int idRenderLightLocal::GetIndex()
return index;
}
//======================================================================
RenderEnvprobeLocal::RenderEnvprobeLocal()
{
memset( &parms, 0, sizeof( parms ) );
envprobeHasMoved = false;
world = NULL;
index = 0;
areaNum = 0;
lastModifiedFrameNum = 0;
archived = false;
references = NULL;
}
void RenderEnvprobeLocal::FreeRenderEnvprobe()
{
}
void RenderEnvprobeLocal::UpdateRenderEnvprobe( const renderEnvironmentProbe_t* ep, bool forceUpdate )
{
}
void RenderEnvprobeLocal::GetRenderEnvprobe( renderEnvironmentProbe_t* ep )
{
}
void RenderEnvprobeLocal::ForceUpdate()
{
}
int RenderEnvprobeLocal::GetIndex()
{
return index;
}
void idRenderEntityLocal::ReadFromDemoFile( class idDemoFile* f )
{

View file

@ -109,6 +109,10 @@ void idRenderProgManager::Init()
{ BUILTIN_VERTEX_COLOR, "vertex_color.vfp", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
{ BUILTIN_AMBIENT_LIGHTING, "ambient_lighting", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
{ BUILTIN_AMBIENT_LIGHTING_SKINNED, "ambient_lighting", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
{ BUILTIN_AMBIENT_LIGHTING_IBL, "ambient_lighting_IBL", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
{ BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED, "ambient_lighting_IBL", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
{ BUILTIN_AMBIENT_LIGHTING_IBL_PBR, "ambient_lighting_IBL", "_PBR", BIT( USE_PBR ), false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
{ BUILTIN_AMBIENT_LIGHTING_IBL_PBR_SKINNED, "ambient_lighting_IBL", "_PBR_skinned", BIT( USE_GPU_SKINNING | USE_PBR ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
{ BUILTIN_SMALL_GEOMETRY_BUFFER, "gbuffer", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
{ BUILTIN_SMALL_GEOMETRY_BUFFER_SKINNED, "gbuffer", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
// RB end
@ -242,6 +246,8 @@ void idRenderProgManager::Init()
renderProgs[builtinShaders[BUILTIN_FOG_SKINNED]].usesJoints = true;
// RB begin
renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTING_SKINNED]].usesJoints = true;
renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED]].usesJoints = true;
renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTING_IBL_PBR_SKINNED]].usesJoints = true;
renderProgs[builtinShaders[BUILTIN_SMALL_GEOMETRY_BUFFER_SKINNED]].usesJoints = true;
renderProgs[builtinShaders[BUILTIN_INTERACTION_SHADOW_MAPPING_SPOT_SKINNED]].usesJoints = true;
renderProgs[builtinShaders[BUILTIN_INTERACTION_SHADOW_MAPPING_POINT_SKINNED]].usesJoints = true;
@ -661,4 +667,4 @@ void RpPrintState( uint64 stateBits, uint64* stencilBits )
{
printStencil( STENCIL_FACE_NUM, stateBits, mask, ref );
}
}
}

View file

@ -290,6 +290,26 @@ public:
BindShader_Builtin( BUILTIN_AMBIENT_LIGHTING_SKINNED );
}
void BindShader_ImageBasedLighting()
{
BindShader_Builtin( BUILTIN_AMBIENT_LIGHTING_IBL );
}
void BindShader_ImageBasedLightingSkinned()
{
BindShader_Builtin( BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED );
}
void BindShader_ImageBasedLighting_PBR()
{
BindShader_Builtin( BUILTIN_AMBIENT_LIGHTING_IBL_PBR );
}
void BindShader_ImageBasedLightingSkinned_PBR()
{
BindShader_Builtin( BUILTIN_AMBIENT_LIGHTING_IBL_PBR_SKINNED );
}
void BindShader_SmallGeometryBuffer()
{
BindShader_Builtin( BUILTIN_SMALL_GEOMETRY_BUFFER );
@ -647,6 +667,10 @@ private:
BUILTIN_VERTEX_COLOR,
BUILTIN_AMBIENT_LIGHTING,
BUILTIN_AMBIENT_LIGHTING_SKINNED,
BUILTIN_AMBIENT_LIGHTING_IBL,
BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED,
BUILTIN_AMBIENT_LIGHTING_IBL_PBR,
BUILTIN_AMBIENT_LIGHTING_IBL_PBR_SKINNED,
BUILTIN_SMALL_GEOMETRY_BUFFER,
BUILTIN_SMALL_GEOMETRY_BUFFER_SKINNED,
// RB end
@ -732,6 +756,7 @@ private:
BRIGHTPASS,
HDR_DEBUG,
USE_SRGB,
USE_PBR,
MAX_SHADER_MACRO_NAMES,
};

View file

@ -314,7 +314,8 @@ const char* idRenderProgManager::GLSLMacroNames[MAX_SHADER_MACRO_NAMES] =
"LIGHT_PARALLEL",
"BRIGHTPASS",
"HDR_DEBUG",
"USE_SRGB"
"USE_SRGB",
"USE_PBR"
};
// RB end

View file

@ -1800,6 +1800,11 @@ static const cgShaderDef_t cg_renderprogs[] =
" return specularColor + ( 1.0 - specularColor ) * pow( 1.0 - vdotH, 5.0 );\n"
"}\n"
"\n"
"half3 Fresnel_Glossy( half3 specularColor, half roughness, half vdotH )\n"
"{\n"
" return specularColor + ( max( half3( 1.0 - roughness ), specularColor ) - specularColor ) * pow( 1.0 - vdotH, 5.0 );\n"
"}\n"
"\n"
"// Visibility term G( l, v, h )\n"
"// Very similar to Marmoset Toolbag 2 and gives almost the same results as Smith GGX\n"
"float Visibility_Schlick( half vdotN, half ldotN, float alpha )\n"
@ -2185,6 +2190,382 @@ static const cgShaderDef_t cg_renderprogs[] =
},
{
"renderprogs/ambient_lighting_IBL.ps.hlsl",
"/*\n"
"===========================================================================\n"
"\n"
"Doom 3 BFG Edition GPL Source Code\n"
"Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. \n"
"Copyright (C) 2013-2019 Robert Beckebans\n"
"\n"
"This file is part of the Doom 3 BFG Edition GPL Source Code (\"Doom 3 BFG Edition Source Code\"). \n"
"\n"
"Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License as published by\n"
"the Free Software Foundation, either version 3 of the License, or\n"
"(at your option) any later version.\n"
"\n"
"Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,\n"
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
"GNU General Public License for more details.\n"
"\n"
"You should have received a copy of the GNU General Public License\n"
"along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.\n"
"\n"
"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.\n"
"\n"
"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.\n"
"\n"
"===========================================================================\n"
"*/\n"
"\n"
"#include \"global.inc.hlsl\"\n"
"#include \"BRDF.inc.hlsl\"\n"
"\n"
"uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface normal map\n"
"uniform sampler2D samp1 : register(s1); // texture 3 is the per-surface specular or roughness/metallic/AO mixer map\n"
"uniform sampler2D samp2 : register(s2); // texture 2 is the per-surface baseColor map \n"
"uniform sampler2D samp3 : register(s3); // texture 4 is the light falloff texture\n"
"uniform sampler2D samp4 : register(s4); // texture 5 is the light projection texture\n"
"\n"
"uniform samplerCUBE samp7 : register(s7); // texture 0 is the cube map\n"
"uniform samplerCUBE samp8 : register(s8); // texture 0 is the cube map\n"
"\n"
"struct PS_IN {\n"
" half4 position : VPOS;\n"
" half4 texcoord0 : TEXCOORD0_centroid;\n"
" half4 texcoord1 : TEXCOORD1_centroid;\n"
" half4 texcoord2 : TEXCOORD2_centroid;\n"
" half4 texcoord3 : TEXCOORD3_centroid;\n"
" half4 texcoord4 : TEXCOORD4_centroid;\n"
" half4 texcoord5 : TEXCOORD5_centroid;\n"
" half4 texcoord6 : TEXCOORD6_centroid;\n"
" half4 color : COLOR0;\n"
"};\n"
"\n"
"struct PS_OUT {\n"
" half4 color : COLOR;\n"
"};\n"
"\n"
"void main( PS_IN fragment, out PS_OUT result ) {\n"
" half4 bumpMap = tex2D( samp0, fragment.texcoord0.xy );\n"
"// half4 lightFalloff = idtex2Dproj( samp1, fragment.texcoord2 );\n"
"// half4 lightProj = idtex2Dproj( samp2, fragment.texcoord3 );\n"
" half4 YCoCG = tex2D( samp2, fragment.texcoord1.xy );\n"
" half4 specMap = tex2D( samp1, fragment.texcoord2.xy );\n"
"\n"
" //half3 lightVector = normalize( fragment.texcoord0.xyz );\n"
" half3 diffuseMap = sRGBToLinearRGB( ConvertYCoCgToRGB( YCoCG ) );\n"
"\n"
" half3 localNormal;\n"
"#if defined(USE_NORMAL_FMT_RGB8)\n"
" localNormal.xy = bumpMap.rg - 0.5;\n"
"#else\n"
" localNormal.xy = bumpMap.wy - 0.5;\n"
"#endif\n"
" localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );\n"
" localNormal = normalize( localNormal );\n"
"\n"
" //const half specularPower = 10.0f;\n"
" //half hDotN = dot3( normalize( fragment.texcoord6.xyz ), localNormal );\n"
" // RB: added abs\n"
" //half3 specularContribution = _half3( pow( abs( hDotN ), specularPower ) );\n"
"\n"
" //half3 diffuseColor = diffuseMap * ( rpDiffuseModifier.xyz ) * 1.5f;\n"
" //half3 specularColor = specMap.xyz * specularContribution * ( rpSpecularModifier.xyz ); \n"
" \n"
" // RB: http://developer.valvesoftware.com/wiki/Half_Lambert\n"
" //float halfLdotN = dot3( localNormal, lightVector ) * 0.5 + 0.5;\n"
" //halfLdotN *= halfLdotN;\n"
" \n"
" // traditional very dark Lambert light model used in Doom 3\n"
" //float ldotN = dot3( localNormal, lightVector );\n"
" \n"
" float3 globalNormal;\n"
" globalNormal.x = dot3( localNormal, fragment.texcoord4 );\n"
" globalNormal.y = dot3( localNormal, fragment.texcoord5 );\n"
" globalNormal.z = dot3( localNormal, fragment.texcoord6 );\n"
"\n"
" float3 globalEye = normalize( fragment.texcoord3.xyz );\n"
"\n"
" float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal );\n"
" reflectionVector = ( reflectionVector * 2.0f ) - globalEye;\n"
" \n"
"#if defined(USE_PBR)\n"
" \n"
" const half metallic = specMap.g;\n"
" const half roughness = specMap.r;\n"
" const half glossiness = 1.0 - roughness;\n"
"\n"
" // the vast majority of real-world materials (anything not metal or gems) have F(0°)\n"
" // values in a very narrow range (~0.02 - 0.08)\n"
" \n"
" // approximate non-metals with linear RGB 0.04 which is 0.08 * 0.5 (default in UE4)\n"
" const half3 dielectricColor = half3( 0.04 );\n"
" \n"
" // derive diffuse and specular from albedo(m) base color\n"
" const half3 baseColor = diffuseMap;\n"
" \n"
" half3 diffuseColor = baseColor * ( 1.0 - metallic );\n"
" half3 specularColor = lerp( dielectricColor, baseColor, metallic );\n"
" \n"
" //diffuseColor = half3( 1.0 );\n"
" float3 diffuseLight = ( texCUBE( samp7, globalNormal ).rgb ) * diffuseColor * ( rpDiffuseModifier.xyz ) * 1.5f;\n"
" \n"
" //specularColor = half3( 0.0 );\n"
" \n"
" float mip = clamp( ( roughness * 7.0 ) + 3.0, 0.0, 10.0 );\n"
" float3 envColor = ( textureLod( samp8, reflectionVector, mip ).rgb ) * ( rpSpecularModifier.xyz ) * 1.0f;\n"
" \n"
" float3 specularLight = envColor * specularColor;\n"
" \n"
"#else\n"
" \n"
" half4 specMapSRGB = specMap;\n"
" specMap = sRGBAToLinearRGBA( specMap );\n"
" \n"
" //float3 diffuseLight = sRGBToLinearRGB( texCUBE( samp7, globalNormal ).rgb ) * diffuseMap.rgb * ( rpDiffuseModifier.xyz ) * 3.5f;\n"
" float3 diffuseLight = ( texCUBE( samp7, globalNormal ).rgb ) * diffuseMap.rgb * ( rpDiffuseModifier.xyz ) * 3.5f;\n"
" //float3 diffuseLight = diffuseMap.rgb * ( rpDiffuseModifier.xyz ) * 1.5f;\n"
"\n"
" // HACK calculate roughness from D3 gloss maps\n"
" float Y = dot( LUMINANCE_SRGB.rgb, specMapSRGB.rgb );\n"
" \n"
" //const float glossiness = clamp( 1.0 - specMapSRGB.r, 0.0, 0.98 );\n"
" const float glossiness = clamp( pow( Y, 1.0 / 2.0 ), 0.0, 0.98 );\n"
" \n"
" const float roughness = 1.0 - glossiness;\n"
" \n"
" float mip = clamp( ( roughness * 7.0 ) + 0.0, 0.0, 10.0 );\n"
" float3 envColor = ( textureLod( samp8, reflectionVector, mip ).rgb ) * ( rpSpecularModifier.xyz ) * 0.5f;\n"
" \n"
" float3 specularLight = envColor * specMap.rgb;\n"
" \n"
"#endif\n"
"\n"
" // add glossy fresnel\n"
" half hDotN = saturate( dot3( globalEye, globalNormal ) );\n"
" \n"
" half3 specularColor2 = half3( 0.0 );\n"
" float3 glossyFresnel = Fresnel_Glossy( specularColor2, roughness, hDotN );\n"
" \n"
" // horizon fade\n"
" const half horizonFade = 1.3;\n"
" half horiz = saturate( 1.0 + horizonFade * saturate( dot3( reflectionVector, globalNormal ) ) );\n"
" horiz *= horiz;\n"
" //horiz = clamp( horiz, 0.0, 1.0 );\n"
" \n"
" //specularLight = glossyFresnel * envColor;\n"
" specularLight += glossyFresnel * envColor * ( rpSpecularModifier.xyz ) * 0.9 * horiz;\n"
"\n"
" half3 lightColor = sRGBToLinearRGB( rpAmbientColor.rgb );\n"
" \n"
" //result.color.rgb = diffuseLight;\n"
" //result.color.rgb = diffuseLight * lightColor;\n"
" //result.color.rgb = specularLight;\n"
" result.color.rgb = ( diffuseLight + specularLight ) * lightColor * fragment.color.rgb;\n"
" //result.color.rgb = localNormal.xyz * 0.5 + 0.5;\n"
" //result.color.xyz = ( ( diffuseColor + specularColor ) * halfLdotN * lightColor ) * fragment.color.rgb;\n"
" //result.color = ( ( diffuseColor + specularColor ) * halfLdotN * lightColor + rimColor ) * fragment.color.rgba;\n"
" result.color.w = fragment.color.a;\n"
"}\n"
"\n"
},
{
"renderprogs/ambient_lighting_IBL.vs.hlsl",
"/*\n"
"===========================================================================\n"
"\n"
"Doom 3 BFG Edition GPL Source Code\n"
"Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. \n"
"Copyright (C) 2013-2015 Robert Beckebans\n"
"\n"
"This file is part of the Doom 3 BFG Edition GPL Source Code (\"Doom 3 BFG Edition Source Code\"). \n"
"\n"
"Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License as published by\n"
"the Free Software Foundation, either version 3 of the License, or\n"
"(at your option) any later version.\n"
"\n"
"Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,\n"
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
"GNU General Public License for more details.\n"
"\n"
"You should have received a copy of the GNU General Public License\n"
"along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.\n"
"\n"
"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.\n"
"\n"
"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.\n"
"\n"
"===========================================================================\n"
"*/\n"
"\n"
"#include \"global.inc.hlsl\"\n"
"\n"
"#if defined( USE_GPU_SKINNING )\n"
"uniform matrices_ubo { float4 matrices[408]; };\n"
"#endif\n"
"\n"
"struct VS_IN {\n"
" float4 position : POSITION;\n"
" float2 texcoord : TEXCOORD0;\n"
" float4 normal : NORMAL;\n"
" float4 tangent : TANGENT;\n"
" float4 color : COLOR0;\n"
" float4 color2 : COLOR1;\n"
"};\n"
"\n"
"struct VS_OUT {\n"
" float4 position : POSITION;\n"
" float4 texcoord0 : TEXCOORD0;\n"
" float4 texcoord1 : TEXCOORD1;\n"
" float4 texcoord2 : TEXCOORD2;\n"
" float4 texcoord3 : TEXCOORD3;\n"
" float4 texcoord4 : TEXCOORD4;\n"
" float4 texcoord5 : TEXCOORD5;\n"
" float4 texcoord6 : TEXCOORD6;\n"
" float4 color : COLOR0;\n"
"};\n"
"\n"
"void main( VS_IN vertex, out VS_OUT result ) {\n"
"\n"
" float4 vNormal = vertex.normal * 2.0 - 1.0;\n"
" float4 vTangent = vertex.tangent * 2.0 - 1.0;\n"
" float3 vBitangent = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w;\n"
"\n"
"#if defined( USE_GPU_SKINNING )\n"
" //--------------------------------------------------------------\n"
" // GPU transformation of the normal / tangent / bitangent\n"
" //\n"
" // multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )\n"
" //--------------------------------------------------------------\n"
" const float w0 = vertex.color2.x;\n"
" const float w1 = vertex.color2.y;\n"
" const float w2 = vertex.color2.z;\n"
" const float w3 = vertex.color2.w;\n"
"\n"
" float4 matX, matY, matZ; // must be float4 for vec4\n"
" int joint = int(vertex.color.x * 255.1 * 3.0);\n"
" matX = matrices[int(joint+0)] * w0;\n"
" matY = matrices[int(joint+1)] * w0;\n"
" matZ = matrices[int(joint+2)] * w0;\n"
"\n"
" joint = int(vertex.color.y * 255.1 * 3.0);\n"
" matX += matrices[int(joint+0)] * w1;\n"
" matY += matrices[int(joint+1)] * w1;\n"
" matZ += matrices[int(joint+2)] * w1;\n"
"\n"
" joint = int(vertex.color.z * 255.1 * 3.0);\n"
" matX += matrices[int(joint+0)] * w2;\n"
" matY += matrices[int(joint+1)] * w2;\n"
" matZ += matrices[int(joint+2)] * w2;\n"
"\n"
" joint = int(vertex.color.w * 255.1 * 3.0);\n"
" matX += matrices[int(joint+0)] * w3;\n"
" matY += matrices[int(joint+1)] * w3;\n"
" matZ += matrices[int(joint+2)] * w3;\n"
"\n"
" float3 normal;\n"
" normal.x = dot3( matX, vNormal );\n"
" normal.y = dot3( matY, vNormal );\n"
" normal.z = dot3( matZ, vNormal );\n"
" normal = normalize( normal );\n"
"\n"
" float3 tangent;\n"
" tangent.x = dot3( matX, vTangent );\n"
" tangent.y = dot3( matY, vTangent );\n"
" tangent.z = dot3( matZ, vTangent );\n"
" tangent = normalize( tangent );\n"
"\n"
" float3 bitangent;\n"
" bitangent.x = dot3( matX, vBitangent );\n"
" bitangent.y = dot3( matY, vBitangent );\n"
" bitangent.z = dot3( matZ, vBitangent );\n"
" bitangent = normalize( bitangent );\n"
"\n"
" float4 modelPosition;\n"
" modelPosition.x = dot4( matX, vertex.position );\n"
" modelPosition.y = dot4( matY, vertex.position );\n"
" modelPosition.z = dot4( matZ, vertex.position );\n"
" modelPosition.w = 1.0;\n"
"\n"
"#else\n"
" float4 modelPosition = vertex.position;\n"
" float3 normal = vNormal.xyz;\n"
" float3 tangent = vTangent.xyz;\n"
" float3 bitangent = vBitangent.xyz;\n"
"#endif\n"
"\n"
" result.position.x = dot4( modelPosition, rpMVPmatrixX );\n"
" result.position.y = dot4( modelPosition, rpMVPmatrixY );\n"
" result.position.z = dot4( modelPosition, rpMVPmatrixZ );\n"
" result.position.w = dot4( modelPosition, rpMVPmatrixW );\n"
"\n"
" float4 defaultTexCoord = float4( 0.0f, 0.5f, 0.0f, 1.0f );\n"
"\n"
" //calculate vector to light\n"
" //float4 toLight = rpLocalLightOrigin;\n"
" float4 toLight = normalize( float4( 0.0f, 0.5f, 1.0f, 1.0f ) );\n"
"\n"
" //--------------------------------------------------------------\n"
"\n"
"\n"
" //# textures 0 takes the base coordinates by the texture matrix\n"
" result.texcoord0 = defaultTexCoord;\n"
" result.texcoord0.x = dot4( vertex.texcoord.xy, rpBumpMatrixS );\n"
" result.texcoord0.y = dot4( vertex.texcoord.xy, rpBumpMatrixT );\n"
"\n"
" //# textures 1 takes the base coordinates by the texture matrix\n"
" result.texcoord1 = defaultTexCoord;\n"
" result.texcoord1.x = dot4( vertex.texcoord.xy, rpDiffuseMatrixS );\n"
" result.texcoord1.y = dot4( vertex.texcoord.xy, rpDiffuseMatrixT );\n"
"\n"
" //# textures 2 takes the base coordinates by the texture matrix\n"
" result.texcoord2 = defaultTexCoord;\n"
" result.texcoord2.x = dot4( vertex.texcoord.xy, rpSpecularMatrixS );\n"
" result.texcoord2.y = dot4( vertex.texcoord.xy, rpSpecularMatrixT );\n"
"\n"
" //# calculate normalized vector to viewer in R1\n"
" float4 toEye = normalize( rpLocalViewOrigin - modelPosition );\n"
"\n"
" result.texcoord3.x = dot3( toEye, rpModelMatrixX );\n"
" result.texcoord3.y = dot3( toEye, rpModelMatrixY );\n"
" result.texcoord3.z = dot3( toEye, rpModelMatrixZ );\n"
" \n"
" result.texcoord4.x = dot3( tangent, rpModelMatrixX );\n"
" result.texcoord5.x = dot3( tangent, rpModelMatrixY );\n"
" result.texcoord6.x = dot3( tangent, rpModelMatrixZ );\n"
"\n"
" result.texcoord4.y = dot3( bitangent, rpModelMatrixX );\n"
" result.texcoord5.y = dot3( bitangent, rpModelMatrixY );\n"
" result.texcoord6.y = dot3( bitangent, rpModelMatrixZ );\n"
"\n"
" result.texcoord4.z = dot3( normal, rpModelMatrixX );\n"
" result.texcoord5.z = dot3( normal, rpModelMatrixY );\n"
" result.texcoord6.z = dot3( normal, rpModelMatrixZ );\n"
"\n"
"#if defined( USE_GPU_SKINNING )\n"
" // for joint transformation of the tangent space, we use color and\n"
" // color2 for weighting information, so hopefully there aren't any\n"
" // effects that need vertex color...\n"
" result.color = float4( 1.0f, 1.0f, 1.0f, 1.0f );\n"
"#else\n"
" //# generate the vertex color, which can be 1.0, color, or 1.0 - color\n"
" //# for 1.0 : env[16] = 0, env[17] = 1\n"
" //# for color : env[16] = 1, env[17] = 0\n"
" //# for 1.0-color : env[16] = -1, env[17] = 1 \n"
" result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n"
"#endif\n"
"}\n"
},
{
"renderprogs/AmbientOcclusion_AO.ps.hlsl",
"/**\n"
@ -12313,7 +12694,11 @@ static const cgShaderDef_t cg_renderprogs[] =
" \n"
"#if OPERATOR == 0\n"
" // advanced Reinhard operator, artistically desirable to burn out bright areas\n"
" float L = Yr * ( 1.0 + Yr / ( Ymax * Ymax ) ) / ( 1.0 + Yr );\n"
" //float L = Yr * ( 1.0 + Yr / ( Ymax * Ymax ) ) / ( 1.0 + Yr );\n"
" \n"
" // exponential tone mapper that is very similar to the Uncharted one\n"
" // very good in keeping the colors natural\n"
" float L = 1.0 - exp( -Yr );\n"
" color.rgb *= L;\n"
"\n"
"#elif OPERATOR == 1\n"

View file

@ -267,7 +267,7 @@ idCVar r_ldrContrastThreshold( "r_ldrContrastThreshold", "1.1", CVAR_RENDERER |
idCVar r_ldrContrastOffset( "r_ldrContrastOffset", "3", CVAR_RENDERER | CVAR_FLOAT, "" );
idCVar r_useFilmicPostProcessEffects( "r_useFilmicPostProcessEffects", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "apply several post process effects to mimic a filmic look" );
idCVar r_forceAmbient( "r_forceAmbient", "0.2", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_FLOAT, "render additional ambient pass to make the game less dark", 0.0f, 0.4f );
idCVar r_forceAmbient( "r_forceAmbient", "0.3", CVAR_RENDERER | CVAR_FLOAT, "render additional ambient pass to make the game less dark", 0.0f, 0.4f );
idCVar r_useSSGI( "r_useSSGI", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "use screen space global illumination and reflections" );
idCVar r_ssgiDebug( "r_ssgiDebug", "0", CVAR_RENDERER | CVAR_INTEGER, "" );

View file

@ -611,6 +611,155 @@ const renderLight_t* idRenderWorldLocal::GetRenderLight( qhandle_t lightHandle )
return &def->parms;
}
// RB begin
qhandle_t idRenderWorldLocal::AddEnvprobeDef( const renderEnvironmentProbe_t* ep )
{
// try and reuse a free spot
int envprobeHandle = envprobeDefs.FindNull();
if( envprobeHandle == -1 )
{
envprobeHandle = envprobeDefs.Append( NULL );
// TODO
//if( interactionTable && envprobeDefs.Num() > interactionTableHeight )
//{
// ResizeEnvprobeInteractionTable();
//}
}
UpdateEnvprobeDef( envprobeHandle, ep );
return envprobeHandle;
}
/*
=================
UpdateEnvprobeDef
The generation of all the derived interaction data will
usually be deferred until it is visible in a scene
Does not write to the demo file, which will only be done for visible lights
=================
*/
void idRenderWorldLocal::UpdateEnvprobeDef( qhandle_t envprobeHandle, const renderEnvironmentProbe_t* ep )
{
if( r_skipUpdates.GetBool() )
{
return;
}
tr.pc.c_envprobeUpdates++;
// create new slots if needed
if( envprobeHandle < 0 || envprobeHandle > LUDICROUS_INDEX )
{
common->Error( "idRenderWorld::UpdateEnvprobeDef: index = %i", envprobeHandle );
}
while( envprobeHandle >= envprobeDefs.Num() )
{
envprobeDefs.Append( NULL );
}
bool justUpdate = false;
RenderEnvprobeLocal* probe = envprobeDefs[envprobeHandle];
if( probe )
{
// if the shape of the envprobe stays the same, we don't need to dump
// any of our derived data, because shader parms are calculated every frame
if( ep->origin == probe->parms.origin )
{
justUpdate = true;
}
else
{
probe->envprobeHasMoved = true;
R_FreeEnvprobeDefDerivedData( probe );
}
}
else
{
// create a new one
probe = new( TAG_RENDER_LIGHT ) RenderEnvprobeLocal;
envprobeDefs[envprobeHandle] = probe;
probe->world = this;
probe->index = envprobeHandle;
}
probe->parms = *ep;
probe->lastModifiedFrameNum = tr.frameCount;
if( common->WriteDemo() && probe->archived )
{
WriteFreeEnvprobe( envprobeHandle );
probe->archived = false;
}
if( !justUpdate )
{
R_CreateEnvprobeRefs( probe );
}
}
/*
====================
FreeEnvprobeDef
Frees all references and lit surfaces from the light, and
NULL's out it's entry in the world list
====================
*/
void idRenderWorldLocal::FreeEnvprobeDef( qhandle_t envprobeHandle )
{
RenderEnvprobeLocal* probe;
if( envprobeHandle < 0 || envprobeHandle >= envprobeDefs.Num() )
{
common->Printf( "idRenderWorld::FreeEnvprobeDef: invalid handle %i [0, %i]\n", envprobeHandle, envprobeDefs.Num() );
return;
}
probe = envprobeDefs[envprobeHandle];
if( !probe )
{
common->Printf( "idRenderWorld::FreeEnvprobeDef: handle %i is NULL\n", envprobeHandle );
return;
}
R_FreeEnvprobeDefDerivedData( probe );
if( common->WriteDemo() && probe->archived )
{
WriteFreeEnvprobe( envprobeHandle );
}
delete probe;
envprobeDefs[envprobeHandle] = NULL;
}
const renderEnvironmentProbe_t* idRenderWorldLocal::GetRenderEnvprobe( qhandle_t envprobeHandle ) const
{
RenderEnvprobeLocal* def;
if( envprobeHandle < 0 || envprobeHandle >= envprobeDefs.Num() )
{
common->Printf( "idRenderWorld::GetRenderEnvprobe: handle %i > %i\n", envprobeHandle, envprobeDefs.Num() );
return NULL;
}
def = envprobeDefs[envprobeHandle];
if( !def )
{
common->Printf( "idRenderWorld::GetRenderEnvprobe: handle %i is NULL\n", envprobeHandle );
return NULL;
}
return &def->parms;
}
// RB end
/*
================
idRenderWorldLocal::ProjectDecalOntoWorld
@ -1739,6 +1888,35 @@ void idRenderWorldLocal::AddLightRefToArea( idRenderLightLocal* light, portalAre
area->lightRefs.areaNext = lref;
}
// RB begin
void idRenderWorldLocal::AddEnvprobeRefToArea( RenderEnvprobeLocal* probe, portalArea_t* area )
{
areaReference_t* lref;
for( lref = probe->references; lref != NULL; lref = lref->ownerNext )
{
if( lref->area == area )
{
return;
}
}
// add a envproberef to this area
lref = areaReferenceAllocator.Alloc();
lref->envprobe = probe;
lref->area = area;
lref->ownerNext = probe->references;
probe->references = lref;
tr.pc.c_lightReferences++;
// doubly linked list so we can free them easily later
area->envprobeRefs.areaNext->areaPrev = lref;
lref->areaNext = area->envprobeRefs.areaNext;
lref->areaPrev = &area->envprobeRefs;
area->envprobeRefs.areaNext = lref;
}
// RB end
/*
===================
idRenderWorldLocal::GenerateAllInteractions
@ -1955,6 +2133,67 @@ void idRenderWorldLocal::PushFrustumIntoTree( idRenderEntityLocal* def, idRender
PushFrustumIntoTree_r( def, light, corners, 0 );
}
// RB begin
void idRenderWorldLocal::PushEnvprobeIntoTree_r( RenderEnvprobeLocal* probe, int nodeNum )
{
if( nodeNum < 0 )
{
int areaNum = -1 - nodeNum;
portalArea_t* area = &portalAreas[ areaNum ];
if( area->viewCount == tr.viewCount )
{
return; // already added a reference here
}
area->viewCount = tr.viewCount;
if( probe != NULL )
{
AddEnvprobeRefToArea( probe, area );
}
return;
}
areaNode_t* node = areaNodes + nodeNum;
// if we know that all possible children nodes only touch an area
// we have already marked, we can early out
if( node->commonChildrenArea != CHILDREN_HAVE_MULTIPLE_AREAS && r_useNodeCommonChildren.GetBool() )
{
// note that we do NOT try to set a reference in this area
// yet, because the test volume may yet wind up being in the
// solid part, which would cause bounds slightly poked into
// a wall to show up in the next room
if( portalAreas[ node->commonChildrenArea ].viewCount == tr.viewCount )
{
return;
}
}
int cull = node->plane.Side( probe->parms.origin );
if( cull != PLANESIDE_BACK )
{
nodeNum = node->children[0];
if( nodeNum != 0 ) // 0 = solid
{
PushEnvprobeIntoTree_r( probe, nodeNum );
}
}
if( cull != PLANESIDE_FRONT )
{
nodeNum = node->children[1];
if( nodeNum != 0 ) // 0 = solid
{
PushEnvprobeIntoTree_r( probe, nodeNum );
}
}
}
// RB end
//===================================================================
/*

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) 2015 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -216,6 +217,24 @@ typedef struct renderLight_s
} renderLight_t;
// RB begin
typedef struct
{
idVec3 origin;
float shaderParms[MAX_ENTITY_SHADER_PARMS];
// if non-zero, the environment probe will not show up in the specific view,
// which may be used if we want to have slightly different muzzle
// flash lights for the player and other views
int suppressEnvprobeInViewID;
// if non-zero, the environment probe will only show up in the specific view
// which can allow player gun gui lights and such to not effect everyone
int allowEnvprobeInViewID;
} renderEnvironmentProbe_t;
// RB end
typedef struct renderView_s
{
// player views will set this to a non-zero integer for model suppress / allow
@ -315,6 +334,13 @@ public:
virtual void FreeLightDef( qhandle_t lightHandle ) = 0;
virtual const renderLight_t* GetRenderLight( qhandle_t lightHandle ) const = 0;
// RB: environment probes for IBL
virtual qhandle_t AddEnvprobeDef( const renderEnvironmentProbe_t* ep ) = 0;
virtual void UpdateEnvprobeDef( qhandle_t envprobeHandle, const renderEnvironmentProbe_t* ep ) = 0;
virtual void FreeEnvprobeDef( qhandle_t envprobeHandle ) = 0;
virtual const renderEnvironmentProbe_t* GetRenderEnvprobe( qhandle_t envprobeHandle ) const = 0;
// RB end
// Force the generation of all light / surface interactions at the start of a level
// If this isn't called, they will all be dynamically generated
virtual void GenerateAllInteractions() = 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-2014 Robert Beckebans
Copyright (C) 2013-2015 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -753,6 +753,55 @@ void R_CreateLightRefs( idRenderLightLocal* light )
/*
=================================================================================
ENVPROBE DEFS
=================================================================================
*/
void R_CreateEnvprobeRefs( RenderEnvprobeLocal* probe )
{
// TODO ? derive envprobe data
//R_DeriveEnvprobeData( probe );
// determine the areaNum for the envprobe origin, which may let us
// cull the envprobe if it is behind a closed door
probe->areaNum = probe->world->PointInArea( probe->parms.origin );
// bump the view count so we can tell if an
// area already has a reference
tr.viewCount++;
// push the probe down the BSP tree into areas
probe->world->PushEnvprobeIntoTree_r( probe, 0 );
}
void R_FreeEnvprobeDefDerivedData( RenderEnvprobeLocal* probe )
{
// TODO free all the interactions
//while( ldef->firstInteraction != NULL )
//{
// ldef->firstInteraction->UnlinkAndFree();
//}
// free all the references to the envprobe
areaReference_t* nextRef = NULL;
for( areaReference_t* lref = probe->references; lref != NULL; lref = nextRef )
{
nextRef = lref->ownerNext;
// unlink from the area
lref->areaNext->areaPrev = lref->areaPrev;
lref->areaPrev->areaNext = lref->areaNext;
// put it back on the free list for reuse
probe->world->areaReferenceAllocator.Free( lref );
}
probe->references = NULL;
}
/*
=================================================================================
WORLD MODEL & LIGHT DEFS
=================================================================================
@ -790,6 +839,18 @@ void R_FreeDerivedData()
}
R_FreeLightDefDerivedData( light );
}
// RB begin
for( int i = 0; i < rw->envprobeDefs.Num(); i++ )
{
RenderEnvprobeLocal* probe = rw->envprobeDefs[i];
if( probe == NULL )
{
continue;
}
R_FreeEnvprobeDefDerivedData( probe );
}
// RB end
}
}
@ -869,6 +930,21 @@ void R_ReCreateWorldReferences()
light->world->FreeLightDef( i );
rw->UpdateLightDef( i, &parms );
}
// RB begin
for( int i = 0; i < rw->envprobeDefs.Num(); i++ )
{
RenderEnvprobeLocal* probe = rw->envprobeDefs[i];
if( probe == NULL )
{
continue;
}
renderEnvironmentProbe_t parms = probe->parms;
probe->world->FreeLightDef( i );
rw->UpdateEnvprobeDef( i, &parms );
}
// RB end
}
}

View file

@ -970,3 +970,26 @@ void idRenderWorldLocal::WriteFreeOverlay( idDemoFile* f, qhandle_t handle )
common->Printf( "write DC_DELETE_OVERLAY: %i\n", handle );
}
}
// RB begin
void idRenderWorldLocal::WriteFreeEnvprobe( qhandle_t handle )
{
// only the main renderWorld writes stuff to demos, not the wipes or
// menu renders
if( this != common->RW() )
{
return;
}
common->WriteDemo()->WriteInt( DS_RENDER );
common->WriteDemo()->WriteInt( DC_DELETE_ENVPROBEDEF );
common->WriteDemo()->WriteInt( handle );
if( r_showDemo.GetBool() )
{
common->Printf( "write DC_DELETE_ENVPROBEDEF: %i\n", handle );
}
}
// RB end

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) 2015 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -417,10 +418,15 @@ void idRenderWorldLocal::SetupAreaRefs()
for( int i = 0; i < numPortalAreas; i++ )
{
portalAreas[i].areaNum = i;
portalAreas[i].lightRefs.areaNext =
portalAreas[i].lightRefs.areaPrev = &portalAreas[i].lightRefs;
portalAreas[i].entityRefs.areaNext =
portalAreas[i].entityRefs.areaPrev = &portalAreas[i].entityRefs;
portalAreas[i].envprobeRefs.areaNext =
portalAreas[i].envprobeRefs.areaPrev = &portalAreas[i].envprobeRefs;
}
}
@ -781,6 +787,18 @@ void idRenderWorldLocal::FreeDefs()
}
}
// RB: free all envprobeDefs
for( int i = 0; i < envprobeDefs.Num(); i++ )
{
RenderEnvprobeLocal* ep = envprobeDefs[i];
if( ep != NULL && ep->world == this )
{
FreeEnvprobeDef( i );
envprobeDefs[i] = NULL;
}
}
// RB end
// Reset decals and overlays
for( int i = 0; i < decals.Num(); i++ )
{

View file

@ -69,6 +69,7 @@ typedef struct portalArea_s
portal_t* portals; // never changes after load
areaReference_t entityRefs; // head/tail of doubly linked list, may change
areaReference_t lightRefs; // head/tail of doubly linked list, may change
areaReference_t envprobeRefs; // head/tail of doubly linked list, may change
} portalArea_t;
@ -117,6 +118,13 @@ public:
virtual void FreeLightDef( qhandle_t lightHandle );
virtual const renderLight_t* GetRenderLight( qhandle_t lightHandle ) const;
// RB: environment probes for IBL
virtual qhandle_t AddEnvprobeDef( const renderEnvironmentProbe_t* ep );
virtual void UpdateEnvprobeDef( qhandle_t envprobeHandle, const renderEnvironmentProbe_t* ep );
virtual void FreeEnvprobeDef( qhandle_t envprobeHandle );
virtual const renderEnvironmentProbe_t* GetRenderEnvprobe( qhandle_t envprobeHandle ) const;
// RB end
virtual bool CheckAreaForPortalSky( int areaNum );
virtual void GenerateAllInteractions();
@ -177,8 +185,9 @@ public:
idList<idRenderModel*, TAG_MODEL> localModels;
idList<idRenderEntityLocal*, TAG_ENTITY> entityDefs;
idList<idRenderLightLocal*, TAG_LIGHT> lightDefs;
idList<idRenderEntityLocal*, TAG_ENTITY> entityDefs;
idList<idRenderLightLocal*, TAG_LIGHT> lightDefs;
idList<RenderEnvprobeLocal*, TAG_ENVPROBE> envprobeDefs; // RB
idBlockAlloc<areaReference_t, 1024> areaReferenceAllocator;
idBlockAlloc<idInteraction, 256> interactionAllocator;
@ -266,12 +275,15 @@ public:
void WriteFreeOverlay( idDemoFile* f, qhandle_t handle );
void WriteFreeLight( qhandle_t handle );
void WriteFreeEntity( qhandle_t handle );
void WriteFreeEnvprobe( qhandle_t handle ); // RB
void WriteRenderDecal( idDemoFile* f, qhandle_t handle );
void WriteRenderOverlay( idDemoFile* f, qhandle_t handle );
void WriteRenderLight( idDemoFile* f, qhandle_t handle, const renderLight_t* light );
void WriteRenderEntity( idDemoFile* f, idRenderEntityLocal* entity );
void WriteRenderEnvprobe( qhandle_t handle, const renderEnvironmentProbe_t* probe ); // RB
void ReadRenderEntity();
void ReadRenderLight();
void ReadRenderEnvprobe(); // RB
//--------------------------
@ -281,6 +293,7 @@ public:
void AddEntityRefToArea( idRenderEntityLocal* def, portalArea_t* area );
void AddLightRefToArea( idRenderLightLocal* light, portalArea_t* area );
void AddEnvprobeRefToArea( RenderEnvprobeLocal* probe, portalArea_t* area ); // RB
void RecurseProcBSP_r( modelTrace_t* results, int parentNodeNum, int nodeNum, float p1f, float p2f, const idVec3& p1, const idVec3& p2 ) const;
void BoundsInAreas_r( int nodeNum, const idBounds& bounds, int* areas, int* numAreas, int maxAreas ) const;
@ -291,6 +304,7 @@ public:
void PushFrustumIntoTree_r( idRenderEntityLocal* def, idRenderLightLocal* light, const frustumCorners_t& corners, int nodeNum );
void PushFrustumIntoTree( idRenderEntityLocal* def, idRenderLightLocal* light, const idRenderMatrix& frustumTransform, const idBounds& frustumBounds );
void PushEnvprobeIntoTree_r( RenderEnvprobeLocal* probe, int nodeNum ); // RB
idRenderModelDecal* AllocDecal( qhandle_t newEntityHandle, int startTime );
idRenderModelOverlay* AllocOverlay( qhandle_t newEntityHandle, int startTime );