IBL envprobes initial render interface

This commit is contained in:
Robert Beckebans 2015-12-06 17:03:43 +01:00
parent f18ccd63d6
commit fac1974f1b
10 changed files with 488 additions and 6 deletions

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

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

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;
@ -1180,6 +1233,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

@ -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,23 @@ typedef struct renderLight_s
} renderLight_t;
// RB begin
typedef struct
{
idVec3 origin;
// 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 +333,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").
@ -781,6 +782,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 );