From fac1974f1b8ef32717f78f036efebd868cd892a1 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sun, 6 Dec 2015 17:03:43 +0100 Subject: [PATCH 01/11] IBL envprobes initial render interface --- neo/idlib/sys/sys_alloc_tags.h | 2 + neo/renderer/Interaction.h | 1 + neo/renderer/RenderCommon.h | 63 +++++++- neo/renderer/RenderEntity.cpp | 32 ++++ neo/renderer/RenderWorld.cpp | 239 ++++++++++++++++++++++++++++++ neo/renderer/RenderWorld.h | 25 ++++ neo/renderer/RenderWorld_defs.cpp | 78 +++++++++- neo/renderer/RenderWorld_demo.cpp | 23 +++ neo/renderer/RenderWorld_load.cpp | 13 ++ neo/renderer/RenderWorld_local.h | 18 ++- 10 files changed, 488 insertions(+), 6 deletions(-) diff --git a/neo/idlib/sys/sys_alloc_tags.h b/neo/idlib/sys/sys_alloc_tags.h index 2ad906da..fbec0c68 100644 --- a/neo/idlib/sys/sys_alloc_tags.h +++ b/neo/idlib/sys/sys_alloc_tags.h @@ -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 ) diff --git a/neo/renderer/Interaction.h b/neo/renderer/Interaction.h index 51600895..dbfa7cd3 100644 --- a/neo/renderer/Interaction.h +++ b/neo/renderer/Interaction.h @@ -84,6 +84,7 @@ struct surfaceInteraction_t class idRenderEntityLocal; class idRenderLightLocal; +class RenderEnvprobeLocal; class idInteraction { diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index f009c0ad..3fdbc96b 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -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 ); diff --git a/neo/renderer/RenderEntity.cpp b/neo/renderer/RenderEntity.cpp index d7d72cf2..d4c4e75c 100644 --- a/neo/renderer/RenderEntity.cpp +++ b/neo/renderer/RenderEntity.cpp @@ -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 ) { diff --git a/neo/renderer/RenderWorld.cpp b/neo/renderer/RenderWorld.cpp index b46e077f..562392ef 100644 --- a/neo/renderer/RenderWorld.cpp +++ b/neo/renderer/RenderWorld.cpp @@ -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 + //=================================================================== /* diff --git a/neo/renderer/RenderWorld.h b/neo/renderer/RenderWorld.h index 435706ff..3eaefd63 100644 --- a/neo/renderer/RenderWorld.h +++ b/neo/renderer/RenderWorld.h @@ -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; diff --git a/neo/renderer/RenderWorld_defs.cpp b/neo/renderer/RenderWorld_defs.cpp index c0871c84..1f190dbc 100644 --- a/neo/renderer/RenderWorld_defs.cpp +++ b/neo/renderer/RenderWorld_defs.cpp @@ -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 } } diff --git a/neo/renderer/RenderWorld_demo.cpp b/neo/renderer/RenderWorld_demo.cpp index b6000b69..0213a671 100644 --- a/neo/renderer/RenderWorld_demo.cpp +++ b/neo/renderer/RenderWorld_demo.cpp @@ -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 \ No newline at end of file diff --git a/neo/renderer/RenderWorld_load.cpp b/neo/renderer/RenderWorld_load.cpp index 87bbd234..0d80c853 100644 --- a/neo/renderer/RenderWorld_load.cpp +++ b/neo/renderer/RenderWorld_load.cpp @@ -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++ ) { diff --git a/neo/renderer/RenderWorld_local.h b/neo/renderer/RenderWorld_local.h index d7430f31..44623d4e 100644 --- a/neo/renderer/RenderWorld_local.h +++ b/neo/renderer/RenderWorld_local.h @@ -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 localModels; - idList entityDefs; - idList lightDefs; + idList entityDefs; + idList lightDefs; + idList envprobeDefs; // RB idBlockAlloc areaReferenceAllocator; idBlockAlloc 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 ); From 85532b96222d2afbeb54057c77f5b865d4c67b94 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sat, 19 Dec 2015 13:59:07 +0100 Subject: [PATCH 02/11] IBL envprobes game entity --- neo/d3xp/EnvironmentProbe.cpp | 940 ++++++++++++++++++++++++++++++ neo/d3xp/EnvironmentProbe.h | 143 +++++ neo/d3xp/Game.h | 1 + neo/d3xp/Game_local.h | 1 + neo/d3xp/gamesys/SaveGame.cpp | 30 + neo/d3xp/gamesys/SaveGame.h | 3 + neo/renderer/RenderWorld.h | 1 + neo/renderer/RenderWorld_load.cpp | 5 + 8 files changed, 1124 insertions(+) create mode 100644 neo/d3xp/EnvironmentProbe.cpp create mode 100644 neo/d3xp/EnvironmentProbe.h diff --git a/neo/d3xp/EnvironmentProbe.cpp b/neo/d3xp/EnvironmentProbe.cpp new file mode 100644 index 00000000..c524a608 --- /dev/null +++ b/neo/d3xp/EnvironmentProbe.cpp @@ -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 . + +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( 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( 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 ); + } + } +} +*/ \ No newline at end of file diff --git a/neo/d3xp/EnvironmentProbe.h b/neo/d3xp/EnvironmentProbe.h new file mode 100644 index 00000000..ab412edd --- /dev/null +++ b/neo/d3xp/EnvironmentProbe.h @@ -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 . + +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__ */ diff --git a/neo/d3xp/Game.h b/neo/d3xp/Game.h index d222d901..d3701d14 100644 --- a/neo/d3xp/Game.h +++ b/neo/d3xp/Game.h @@ -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. diff --git a/neo/d3xp/Game_local.h b/neo/d3xp/Game_local.h index f04cb1f0..e8d61eef 100644 --- a/neo/d3xp/Game_local.h +++ b/neo/d3xp/Game_local.h @@ -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" diff --git a/neo/d3xp/gamesys/SaveGame.cpp b/neo/d3xp/gamesys/SaveGame.cpp index a2519110..c5536cd7 100644 --- a/neo/d3xp/gamesys/SaveGame.cpp +++ b/neo/d3xp/gamesys/SaveGame.cpp @@ -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 diff --git a/neo/d3xp/gamesys/SaveGame.h b/neo/d3xp/gamesys/SaveGame.h index 1d872766..fc8e7493 100644 --- a/neo/d3xp/gamesys/SaveGame.h +++ b/neo/d3xp/gamesys/SaveGame.h @@ -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 ); diff --git a/neo/renderer/RenderWorld.h b/neo/renderer/RenderWorld.h index 3eaefd63..b4ffd324 100644 --- a/neo/renderer/RenderWorld.h +++ b/neo/renderer/RenderWorld.h @@ -221,6 +221,7 @@ typedef struct renderLight_s 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 diff --git a/neo/renderer/RenderWorld_load.cpp b/neo/renderer/RenderWorld_load.cpp index 0d80c853..05bed311 100644 --- a/neo/renderer/RenderWorld_load.cpp +++ b/neo/renderer/RenderWorld_load.cpp @@ -418,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; } } From bd8dedca16a893c9d84eba984506753800e5276e Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Thu, 24 Dec 2015 16:43:02 +0100 Subject: [PATCH 03/11] Added ambient pass to make game less dark --- base/renderprogs/ambient_lighting.pixel | 97 +++++++++++ base/renderprogs/ambient_lighting.vertex | 199 +++++++++++++++++++++++ neo/renderer/RenderBackend.cpp | 4 +- neo/renderer/RenderProgs_embedded.h | 10 +- 4 files changed, 303 insertions(+), 7 deletions(-) create mode 100644 base/renderprogs/ambient_lighting.pixel create mode 100644 base/renderprogs/ambient_lighting.vertex diff --git a/base/renderprogs/ambient_lighting.pixel b/base/renderprogs/ambient_lighting.pixel new file mode 100644 index 00000000..46ac16b3 --- /dev/null +++ b/base/renderprogs/ambient_lighting.pixel @@ -0,0 +1,97 @@ +/* +=========================================================================== + +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 . + +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 "renderprogs/global.inc" + +uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface bump map +uniform sampler2D samp1 : register(s1); // texture 2 is the light falloff texture +uniform sampler2D samp2 : register(s2); // texture 3 is the light projection texture +uniform sampler2D samp3 : register(s3); // texture 4 is the per-surface diffuse map +uniform sampler2D samp4 : register(s4); // texture 5 is the per-surface specular 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.texcoord1.xy ); +// half4 lightFalloff = idtex2Dproj( samp1, fragment.texcoord2 ); +// half4 lightProj = idtex2Dproj( samp2, fragment.texcoord3 ); + half4 YCoCG = tex2D( samp3, fragment.texcoord4.xy ); + half4 specMap = tex2D( samp4, fragment.texcoord5.xy ); + + half3 lightVector = normalize( fragment.texcoord0.xyz ); + half3 diffuseMap = 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 ); + + half3 lightColor = rpAmbientColor.rgb; + + half rim = 1.0f - saturate( hDotN ); + half rimPower = 8.0; + half3 rimColor = half3( 0.125 ) * 1.2 * lightColor * pow( rim, rimPower ); + + //result.color.rgb = localNormal.xyz * 0.5 + 0.5; + result.color.xyz = ( diffuseColor + specularColor ) * halfLdotN * lightColor + rimColor; + result.color.w = 1.0; +} diff --git a/base/renderprogs/ambient_lighting.vertex b/base/renderprogs/ambient_lighting.vertex new file mode 100644 index 00000000..c6473cd7 --- /dev/null +++ b/base/renderprogs/ambient_lighting.vertex @@ -0,0 +1,199 @@ +/* +=========================================================================== + +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 . + +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 "renderprogs/global.inc" + +#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 ) ); + + //-------------------------------------------------------------- + + //result.texcoord0 is the direction to the light in tangent space + result.texcoord0.x = dot3( tangent, toLight ); + result.texcoord0.y = dot3( bitangent, toLight ); + result.texcoord0.z = dot3( normal, toLight ); + result.texcoord0.w = 1.0f; + + //textures 1 takes the base coordinates by the texture matrix + result.texcoord1 = defaultTexCoord; + result.texcoord1.x = dot4( vertex.texcoord.xy, rpBumpMatrixS ); + result.texcoord1.y = dot4( vertex.texcoord.xy, rpBumpMatrixT ); + + //# texture 2 has one texgen + //result.texcoord2 = defaultTexCoord; + //result.texcoord2.x = dot4( vertex.position, rpLightFalloffS ); + + //# texture 3 has three texgens + //result.texcoord3.x = dot4( vertex.position, rpLightProjectionS ); + //result.texcoord3.y = dot4( vertex.position, rpLightProjectionT ); + //result.texcoord3.z = 0.0f; + //result.texcoord3.w = dot4( vertex.position, rpLightProjectionQ ); + + //# textures 4 takes the base coordinates by the texture matrix + result.texcoord4 = defaultTexCoord; + result.texcoord4.x = dot4( vertex.texcoord.xy, rpDiffuseMatrixS ); + result.texcoord4.y = dot4( vertex.texcoord.xy, rpDiffuseMatrixT ); + + //# textures 5 takes the base coordinates by the texture matrix + result.texcoord5 = defaultTexCoord; + result.texcoord5.x = dot4( vertex.texcoord.xy, rpSpecularMatrixS ); + result.texcoord5.y = dot4( vertex.texcoord.xy, rpSpecularMatrixT ); + + //# texture 6's texcoords will be the halfangle in texture space + + //# calculate normalized vector to light in R0 + toLight = normalize( toLight ); + + //# calculate normalized vector to viewer in R1 + float4 toView = normalize( rpLocalViewOrigin - modelPosition ); + + //# add together to become the half angle vector in object space (non-normalized) + float4 halfAngleVector = toLight + toView; + + //# put into texture space + result.texcoord6.x = dot3( tangent, halfAngleVector ); + result.texcoord6.y = dot3( bitangent, halfAngleVector ); + result.texcoord6.z = dot3( normal, halfAngleVector ); + result.texcoord6.w = 1.0f; + +#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 +} \ No newline at end of file diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 9370b798..21fea207 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -5836,7 +5836,7 @@ void idRenderBackend::PostProcess( const void* data ) /* * The shader has three passes, chained together as follows: * - * |input|------------------· + * |input|------------------� * v | * [ SMAA*EdgeDetection ] | * v | @@ -5846,7 +5846,7 @@ void idRenderBackend::PostProcess( const void* data ) * v | * |blendTex| | * v | - * [ SMAANeighborhoodBlending ] <------· + * [ SMAANeighborhoodBlending ] <------� * v * |output| */ diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index 110faced..457dc176 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -396,7 +396,7 @@ static const cgShaderDef_t cg_renderprogs[] = " *\n" " * The shader has three passes, chained together as follows:\n" " *\n" - " * |input|------------------·\n" + " * |input|------------------�\n" " * v |\n" " * [ SMAA*EdgeDetection ] |\n" " * v |\n" @@ -406,7 +406,7 @@ static const cgShaderDef_t cg_renderprogs[] = " * v |\n" " * |blendTex| |\n" " * v |\n" - " * [ SMAANeighborhoodBlending ] <------·\n" + " * [ SMAANeighborhoodBlending ] <------�\n" " * v\n" " * |output|\n" " *\n" @@ -1794,7 +1794,7 @@ static const cgShaderDef_t cg_renderprogs[] = "}\n" "\n" "// Fresnel term F( v, h )\n" - "// Fnone( v, h ) = F(0°) = specularColor\n" + "// Fnone( v, h ) = F(0�) = specularColor\n" "half3 Fresnel_Schlick( half3 specularColor, half vdotH )\n" "{\n" " return specularColor + ( 1.0 - specularColor ) * pow( 1.0 - vdotH, 5.0 );\n" @@ -8279,7 +8279,7 @@ static const cgShaderDef_t cg_renderprogs[] = " const half roughness = specMapSRGB.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" + " // 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" @@ -9364,7 +9364,7 @@ static const cgShaderDef_t cg_renderprogs[] = " const half roughness = specMapSRGB.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" + " // 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" From 76555219d4f3da6fe1020a928dcee1eb5b8fccef Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Thu, 24 Dec 2015 18:01:23 +0100 Subject: [PATCH 04/11] Tweaked HDR parameters --- base/renderprogs/ambient_lighting.pixel | 2 +- neo/renderer/RenderBackend.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/base/renderprogs/ambient_lighting.pixel b/base/renderprogs/ambient_lighting.pixel index 46ac16b3..38db99e3 100644 --- a/base/renderprogs/ambient_lighting.pixel +++ b/base/renderprogs/ambient_lighting.pixel @@ -92,6 +92,6 @@ void main( PS_IN fragment, out PS_OUT result ) { half3 rimColor = half3( 0.125 ) * 1.2 * lightColor * pow( rim, rimPower ); //result.color.rgb = localNormal.xyz * 0.5 + 0.5; - result.color.xyz = ( diffuseColor + specularColor ) * halfLdotN * lightColor + rimColor; + result.color.xyz = ( ( diffuseColor + specularColor ) * halfLdotN * lightColor + rimColor ) * fragment.color.rgb;; result.color.w = 1.0; } diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 21fea207..502e3c1b 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -2115,6 +2115,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 /* From e6498e297539f0e5e8695b9974c8f080ac373452 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Thu, 24 Dec 2015 18:46:28 +0100 Subject: [PATCH 05/11] Tweaked HDR/ambient --- RELEASE-NOTES.txt | 1 - base/renderprogs/postprocess.ps.hlsl | 2 +- base/renderprogs/tonemap.ps.hlsl | 6 +++++- neo/renderer/RenderSystem_init.cpp | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 1446ffa3..d5a3ba97 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -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 diff --git a/base/renderprogs/postprocess.ps.hlsl b/base/renderprogs/postprocess.ps.hlsl index 9dbfcc31..969079e5 100644 --- a/base/renderprogs/postprocess.ps.hlsl +++ b/base/renderprogs/postprocess.ps.hlsl @@ -47,7 +47,7 @@ struct PS_OUT #define USE_TECHNICOLOR 1 // [0 or 1] -#define Technicolor_Amount 0.5 // [0.00 to 1.00] +#define Technicolor_Amount 0.6 // [0.00 to 1.00] #define Technicolor_Power 4.0 // [0.00 to 8.00] #define Technicolor_RedNegativeAmount 0.88 // [0.00 to 1.00] #define Technicolor_GreenNegativeAmount 0.88 // [0.00 to 1.00] diff --git a/base/renderprogs/tonemap.ps.hlsl b/base/renderprogs/tonemap.ps.hlsl index 2d42d0d5..9b53ef3e 100644 --- a/base/renderprogs/tonemap.ps.hlsl +++ b/base/renderprogs/tonemap.ps.hlsl @@ -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 diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index ce6b2c8b..8c06c1b5 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -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, "" ); From 1e4292e52a9d6b9510b49b5208b2e6be89060610 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Thu, 7 Jul 2016 00:32:44 +0200 Subject: [PATCH 06/11] Merged LordHavoc's image compression progress bar --- neo/framework/common_frame.cpp | 61 ++++++++++++++++++++++++++++++---- neo/renderer/Image_load.cpp | 42 +++++++++++++++++++++++ 2 files changed, 96 insertions(+), 7 deletions(-) diff --git a/neo/framework/common_frame.cpp b/neo/framework/common_frame.cpp index c9b11c8e..52d198bf 100644 --- a/neo/framework/common_frame.cpp +++ b/neo/framework/common_frame.cpp @@ -32,7 +32,7 @@ If you have questions concerning this license or the applicable additional terms #pragma hdrstop #include "Common_local.h" -#include "../renderer/Image.h" // now I did it! +#include "../renderer/Image.h" // RB begin #if defined(USE_DOOMCLASSIC) @@ -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(); + // Activate the shell if it's been requested if( showShellRequested && game ) { @@ -554,7 +599,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 ); } @@ -783,12 +830,12 @@ 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 diff --git a/neo/renderer/Image_load.cpp b/neo/renderer/Image_load.cpp index 5a5e0164..49e1b705 100644 --- a/neo/renderer/Image_load.cpp +++ b/neo/renderer/Image_load.cpp @@ -217,6 +217,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 +503,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(); From 21bdc82d135372e45dcf0ced37f2345fa5ae7a13 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Thu, 7 Jul 2016 03:17:33 +0200 Subject: [PATCH 07/11] IBL indirect lighting test --- base/renderprogs/_manifest.lua | 2 + base/renderprogs/ambient_lighting_IBL.pixel | 127 +++++++++++++ base/renderprogs/ambient_lighting_IBL.vertex | 186 +++++++++++++++++++ neo/renderer/BinaryImage.cpp | 30 ++- neo/renderer/Image.h | 7 +- neo/renderer/Image_intrinsic.cpp | 3 + neo/renderer/Image_load.cpp | 11 ++ neo/renderer/Material.cpp | 12 +- neo/renderer/RenderBackend.cpp | 23 ++- neo/renderer/RenderProgs.cpp | 3 + neo/renderer/RenderProgs.h | 12 ++ 11 files changed, 409 insertions(+), 7 deletions(-) create mode 100644 base/renderprogs/ambient_lighting_IBL.pixel create mode 100644 base/renderprogs/ambient_lighting_IBL.vertex diff --git a/base/renderprogs/_manifest.lua b/base/renderprogs/_manifest.lua index 58f18bfc..e4213eea 100644 --- a/base/renderprogs/_manifest.lua +++ b/base/renderprogs/_manifest.lua @@ -9,6 +9,8 @@ return -- shaders "ambient_lighting.ps.hlsl", "ambient_lighting.vs.hlsl", + "ambient_lighting_IBL.pixel", + "ambient_lighting_IBL.vertex", "AmbientOcclusion_AO.ps.hlsl", "AmbientOcclusion_AO.vs.hlsl", "AmbientOcclusion_blur.ps.hlsl", diff --git a/base/renderprogs/ambient_lighting_IBL.pixel b/base/renderprogs/ambient_lighting_IBL.pixel new file mode 100644 index 00000000..8de07c84 --- /dev/null +++ b/base/renderprogs/ambient_lighting_IBL.pixel @@ -0,0 +1,127 @@ +/* +=========================================================================== + +Doom 3 BFG Edition GPL Source Code +Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. +Copyright (C) 2013-2016 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 . + +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 "renderprogs/global.inc" + +uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface bump map +uniform sampler2D samp1 : register(s1); // texture 2 is the light falloff texture +uniform sampler2D samp2 : register(s2); // texture 3 is the light projection texture +uniform sampler2D samp3 : register(s3); // texture 4 is the per-surface diffuse map +uniform sampler2D samp4 : register(s4); // texture 5 is the per-surface specular map + +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( samp3, fragment.texcoord1.xy ); + half4 specMapSRGB = tex2D( samp4, fragment.texcoord2.xy ); + half4 specMap = sRGBAToLinearRGBA( specMapSRGB ); + + //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; + + //half rim = 1.0f - saturate( hDotN ); + //half rimPower = 8.0; + //half3 rimColor = sRGBToLinearRGB( half3( 0.125 ) * 1.2 ) * lightColor * pow( rim, rimPower ); + + float3 diffuseLight = sRGBToLinearRGB( texCUBE( samp7, globalNormal ).rgb ) * diffuseMap.rgb * ( rpDiffuseModifier.xyz ) * 1.0f; + + // 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 = roughness * 7.0; + float3 specularLight = sRGBToLinearRGB( texCUBEbias( samp8, float4( reflectionVector, mip ) ).rgb ) * specMap.rgb * ( rpSpecularModifier.xyz ) * 1.0f; + + half3 lightColor = sRGBToLinearRGB( rpAmbientColor.rgb ); + + //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; +} diff --git a/base/renderprogs/ambient_lighting_IBL.vertex b/base/renderprogs/ambient_lighting_IBL.vertex new file mode 100644 index 00000000..8d2007fa --- /dev/null +++ b/base/renderprogs/ambient_lighting_IBL.vertex @@ -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 . + +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 "renderprogs/global.inc" + +#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 +} \ No newline at end of file diff --git a/neo/renderer/BinaryImage.cpp b/neo/renderer/BinaryImage.cpp index 0c7b1516..70a92fb0 100644 --- a/neo/renderer/BinaryImage.cpp +++ b/neo/renderer/BinaryImage.cpp @@ -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 { diff --git a/neo/renderer/Image.h b/neo/renderer/Image.h index 0ea1827b..a4879de7 100644 --- a/neo/renderer/Image.h +++ b/neo/renderer/Image.h @@ -216,6 +216,8 @@ 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_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, @@ -545,6 +547,9 @@ public: idImage* currentNormalsImage; // cheap G-Buffer replacement, holds normals and surface roughness idImage* ambientOcclusionImage[2]; // contain AO and bilateral filtering keys idImage* hierarchicalZbufferImage; // zbuffer with mip maps to accelerate screen space ray tracing + + idImage* defaultUACIrradianceCube; + idImage* defaultUACRadianceCube; // RB end idImage* scratchImage; idImage* scratchImage2; @@ -553,7 +558,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 //-------------------------------------------------------- diff --git a/neo/renderer/Image_intrinsic.cpp b/neo/renderer/Image_intrinsic.cpp index c2456b6c..8978c9b5 100644 --- a/neo/renderer/Image_intrinsic.cpp +++ b/neo/renderer/Image_intrinsic.cpp @@ -891,6 +891,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 ); } diff --git a/neo/renderer/Image_load.cpp b/neo/renderer/Image_load.cpp index 49e1b705..2f518a4e 100644 --- a/neo/renderer/Image_load.cpp +++ b/neo/renderer/Image_load.cpp @@ -169,6 +169,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; diff --git a/neo/renderer/Material.cpp b/neo/renderer/Material.cpp index 4d75c2c2..c55f7615 100644 --- a/neo/renderer/Material.cpp +++ b/neo/renderer/Material.cpp @@ -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" ); /* @@ -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" ) ) diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 502e3c1b..3a270d2c 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -687,9 +687,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 ) { @@ -1202,6 +1200,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 @@ -2051,6 +2052,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 ) { @@ -2060,6 +2078,7 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr { renderProgManager.BindShader_AmbientLighting(); } +#endif } } diff --git a/neo/renderer/RenderProgs.cpp b/neo/renderer/RenderProgs.cpp index cc63a2a4..c32a69e0 100644 --- a/neo/renderer/RenderProgs.cpp +++ b/neo/renderer/RenderProgs.cpp @@ -109,6 +109,8 @@ 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 false, SHADER_STAGE_DEFAULT, LAYOUT_DRA }, + { BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED, "ambient_lighting_IBL", "_skinned", BIT( USE_GPU_SKINNING ), true false, SHADER_STAGE_DEFAULT, LAYOUT_DRA }, { 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 +244,7 @@ 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_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; diff --git a/neo/renderer/RenderProgs.h b/neo/renderer/RenderProgs.h index b64938aa..680bc0a5 100644 --- a/neo/renderer/RenderProgs.h +++ b/neo/renderer/RenderProgs.h @@ -290,6 +290,16 @@ 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_SmallGeometryBuffer() { BindShader_Builtin( BUILTIN_SMALL_GEOMETRY_BUFFER ); @@ -647,6 +657,8 @@ private: BUILTIN_VERTEX_COLOR, BUILTIN_AMBIENT_LIGHTING, BUILTIN_AMBIENT_LIGHTING_SKINNED, + BUILTIN_AMBIENT_LIGHTING_IBL, + BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED, BUILTIN_SMALL_GEOMETRY_BUFFER, BUILTIN_SMALL_GEOMETRY_BUFFER_SKINNED, // RB end From 60f330874d8a8e42dcb79f2dffac0d6bb9c73484 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sun, 10 Jul 2016 23:46:24 +0200 Subject: [PATCH 08/11] PBR metal workflow texture support for IBL --- base/renderprogs/BRDF.inc.hlsl | 5 ++ base/renderprogs/ambient_lighting_IBL.pixel | 67 ++++++++++++++++++--- neo/renderer/Image.h | 7 +++ neo/renderer/Image_load.cpp | 13 ++++ neo/renderer/Material.cpp | 26 ++++++-- neo/renderer/RenderBackend.cpp | 47 ++++++++++++--- neo/renderer/RenderProgs.cpp | 5 +- neo/renderer/RenderProgs.h | 13 ++++ neo/renderer/RenderProgs_GLSL.cpp | 3 +- 9 files changed, 160 insertions(+), 26 deletions(-) diff --git a/base/renderprogs/BRDF.inc.hlsl b/base/renderprogs/BRDF.inc.hlsl index f4b15b3d..a87f9e71 100644 --- a/base/renderprogs/BRDF.inc.hlsl +++ b/base/renderprogs/BRDF.inc.hlsl @@ -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 ) diff --git a/base/renderprogs/ambient_lighting_IBL.pixel b/base/renderprogs/ambient_lighting_IBL.pixel index 8de07c84..ad314c7b 100644 --- a/base/renderprogs/ambient_lighting_IBL.pixel +++ b/base/renderprogs/ambient_lighting_IBL.pixel @@ -28,6 +28,7 @@ If you have questions concerning this license or the applicable additional terms */ #include "renderprogs/global.inc" +#include "renderprogs/BRDF.inc" uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface bump map uniform sampler2D samp1 : register(s1); // texture 2 is the light falloff texture @@ -59,8 +60,7 @@ void main( PS_IN fragment, out PS_OUT result ) { // half4 lightFalloff = idtex2Dproj( samp1, fragment.texcoord2 ); // half4 lightProj = idtex2Dproj( samp2, fragment.texcoord3 ); half4 YCoCG = tex2D( samp3, fragment.texcoord1.xy ); - half4 specMapSRGB = tex2D( samp4, fragment.texcoord2.xy ); - half4 specMap = sRGBAToLinearRGBA( specMapSRGB ); + half4 specMap = tex2D( samp4, fragment.texcoord2.xy ); //half3 lightVector = normalize( fragment.texcoord0.xyz ); half3 diffuseMap = sRGBToLinearRGB( ConvertYCoCgToRGB( YCoCG ) ); @@ -99,11 +99,41 @@ void main( PS_IN fragment, out PS_OUT result ) { float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal ); reflectionVector = ( reflectionVector * 2.0f ) - globalEye; - //half rim = 1.0f - saturate( hDotN ); - //half rimPower = 8.0; - //half3 rimColor = sRGBToLinearRGB( half3( 0.125 ) * 1.2 ) * lightColor * pow( rim, rimPower ); +#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) - float3 diffuseLight = sRGBToLinearRGB( texCUBE( samp7, globalNormal ).rgb ) * diffuseMap.rgb * ( rpDiffuseModifier.xyz ) * 1.0f; + // 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 = sRGBToLinearRGB( 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 = sRGBToLinearRGB( texCUBElod( samp8, float4( 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 ) * 1.5f; + float3 diffuseLight = diffuseMap.rgb * ( rpDiffuseModifier.xyz ) * 1.5f; // HACK calculate roughness from D3 gloss maps float Y = dot( LUMINANCE_SRGB.rgb, specMapSRGB.rgb ); @@ -113,11 +143,32 @@ void main( PS_IN fragment, out PS_OUT result ) { const float roughness = 1.0 - glossiness; - float mip = roughness * 7.0; - float3 specularLight = sRGBToLinearRGB( texCUBEbias( samp8, float4( reflectionVector, mip ) ).rgb ) * specMap.rgb * ( rpSpecularModifier.xyz ) * 1.0f; + float mip = clamp( ( roughness * 7.0 ) + 0.0, 0.0, 10.0 ); + float3 envColor = sRGBToLinearRGB( texCUBElod( samp8, float4( reflectionVector, mip ) ).rgb ) * ( rpSpecularModifier.xyz ) * 1.0f; + 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; diff --git a/neo/renderer/Image.h b/neo/renderer/Image.h index a4879de7..eed7eabb 100644 --- a/neo/renderer/Image.h +++ b/neo/renderer/Image.h @@ -216,6 +216,8 @@ 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 @@ -367,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 ); diff --git a/neo/renderer/Image_load.cpp b/neo/renderer/Image_load.cpp index 2f518a4e..94778b78 100644 --- a/neo/renderer/Image_load.cpp +++ b/neo/renderer/Image_load.cpp @@ -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; diff --git a/neo/renderer/Material.cpp b/neo/renderer/Material.cpp index c55f7615..3029df45 100644 --- a/neo/renderer/Material.cpp +++ b/neo/renderer/Material.cpp @@ -1047,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; @@ -1907,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; @@ -1920,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; @@ -2475,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 ); @@ -2497,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 ); diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 3a270d2c..53243a08 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -1265,7 +1265,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 ) { @@ -1298,6 +1298,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() ); @@ -1836,7 +1865,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; @@ -1854,7 +1883,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; @@ -1872,7 +1901,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; @@ -1884,7 +1913,7 @@ void idRenderBackend::RenderInteractions( const drawSurf_t* surfList, const view } // draw the final interaction - DrawSingleInteraction( &inter ); + DrawSingleInteraction( &inter, false ); renderLog.CloseBlock(); } @@ -2243,7 +2272,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; @@ -2264,7 +2293,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; @@ -2284,7 +2313,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; @@ -2296,7 +2325,7 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr } // draw the final interaction - DrawSingleInteraction( &inter ); + DrawSingleInteraction( &inter,!fillGbuffer ); renderLog.CloseBlock(); } diff --git a/neo/renderer/RenderProgs.cpp b/neo/renderer/RenderProgs.cpp index c32a69e0..a754f0a8 100644 --- a/neo/renderer/RenderProgs.cpp +++ b/neo/renderer/RenderProgs.cpp @@ -109,8 +109,8 @@ 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 false, SHADER_STAGE_DEFAULT, LAYOUT_DRA }, - { BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED, "ambient_lighting_IBL", "_skinned", BIT( USE_GPU_SKINNING ), true false, SHADER_STAGE_DEFAULT, LAYOUT_DRA }, + { BUILTIN_AMBIENT_LIGHTING_IBL, "ambient_lighting_IBL", "", 0, false false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, + { BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED, "ambient_lighting_IBL", "_skinned", BIT( USE_GPU_SKINNING ), true false, 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 @@ -245,6 +245,7 @@ void idRenderProgManager::Init() // 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; diff --git a/neo/renderer/RenderProgs.h b/neo/renderer/RenderProgs.h index 680bc0a5..8e5b7e2e 100644 --- a/neo/renderer/RenderProgs.h +++ b/neo/renderer/RenderProgs.h @@ -300,6 +300,16 @@ public: 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 ); @@ -659,6 +669,8 @@ private: 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 @@ -744,6 +756,7 @@ private: BRIGHTPASS, HDR_DEBUG, USE_SRGB, + USE_PBR, MAX_SHADER_MACRO_NAMES, }; diff --git a/neo/renderer/RenderProgs_GLSL.cpp b/neo/renderer/RenderProgs_GLSL.cpp index 6e73c18f..149d6786 100644 --- a/neo/renderer/RenderProgs_GLSL.cpp +++ b/neo/renderer/RenderProgs_GLSL.cpp @@ -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 From a0dfca7596c3055644cf6659618501399c492810 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sun, 17 Jul 2016 11:46:14 +0200 Subject: [PATCH 09/11] Fixed CMakeLists missing EnvironmentProbe file --- neo/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/neo/CMakeLists.txt b/neo/CMakeLists.txt index a5db8a03..b375b60e 100644 --- a/neo/CMakeLists.txt +++ b/neo/CMakeLists.txt @@ -619,6 +619,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 @@ -656,6 +657,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 From 3709713d79d570d83ccf3c1477bcb9a480cd73ad Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sat, 19 Oct 2019 22:51:14 +0200 Subject: [PATCH 10/11] Solved IBL branch conflicts --- neo/framework/common_frame.cpp | 1 + neo/renderer/Image_load.cpp | 14 +++++++------- neo/renderer/RenderBackend.cpp | 2 +- neo/renderer/RenderBackend.h | 2 +- neo/renderer/RenderProgs.cpp | 8 +++++--- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/neo/framework/common_frame.cpp b/neo/framework/common_frame.cpp index 52d198bf..fe55d8d0 100644 --- a/neo/framework/common_frame.cpp +++ b/neo/framework/common_frame.cpp @@ -832,6 +832,7 @@ void idCommonLocal::Frame() // 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 ); } diff --git a/neo/renderer/Image_load.cpp b/neo/renderer/Image_load.cpp index 94778b78..ad6eb727 100644 --- a/neo/renderer/Image_load.cpp +++ b/neo/renderer/Image_load.cpp @@ -241,8 +241,8 @@ 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 ) @@ -253,10 +253,10 @@ void idImage::AllocImage( const idImageOpts& imgOpts, textureFilter_t tf, textur { 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 ) @@ -267,9 +267,9 @@ void idImage::AllocImage( const idImageOpts& imgOpts, textureFilter_t tf, textur { commonLocal.LoadPacifierBinarizeProgressTotal( opts.width * opts.width * 6 ); } - + commonLocal.LoadPacifierBinarizeEnd(); - + =============== GetGeneratedName diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 53243a08..0ec163c5 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -2325,7 +2325,7 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr } // draw the final interaction - DrawSingleInteraction( &inter,!fillGbuffer ); + DrawSingleInteraction( &inter, !fillGbuffer ); renderLog.CloseBlock(); } diff --git a/neo/renderer/RenderBackend.h b/neo/renderer/RenderBackend.h index bdfa27dd..4a8a055c 100644 --- a/neo/renderer/RenderBackend.h +++ b/neo/renderer/RenderBackend.h @@ -292,7 +292,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 ); diff --git a/neo/renderer/RenderProgs.cpp b/neo/renderer/RenderProgs.cpp index a754f0a8..b4cf3853 100644 --- a/neo/renderer/RenderProgs.cpp +++ b/neo/renderer/RenderProgs.cpp @@ -109,8 +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 false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, - { BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED, "ambient_lighting_IBL", "_skinned", BIT( USE_GPU_SKINNING ), true false, 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 @@ -665,4 +667,4 @@ void RpPrintState( uint64 stateBits, uint64* stencilBits ) { printStencil( STENCIL_FACE_NUM, stateBits, mask, ref ); } -} \ No newline at end of file +} From b8d28c426c3dd0d91471aa1f33c5a6a2ea6ec5a6 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Wed, 30 Oct 2019 18:08:37 +0100 Subject: [PATCH 11/11] Fixed shader loading problems --- base/renderprogs/_manifest.lua | 4 +- base/renderprogs/ambient_lighting.pixel | 97 ----- base/renderprogs/ambient_lighting.vertex | 199 --------- ...IBL.pixel => ambient_lighting_IBL.ps.hlsl} | 31 +- ...BL.vertex => ambient_lighting_IBL.vs.hlsl} | 2 +- base/renderprogs/postprocess.ps.hlsl | 2 +- neo/renderer/RenderBackend.cpp | 4 +- neo/renderer/RenderBackend.h | 6 - neo/renderer/RenderProgs.cpp | 4 +- neo/renderer/RenderProgs_embedded.h | 397 +++++++++++++++++- 10 files changed, 415 insertions(+), 331 deletions(-) delete mode 100644 base/renderprogs/ambient_lighting.pixel delete mode 100644 base/renderprogs/ambient_lighting.vertex rename base/renderprogs/{ambient_lighting_IBL.pixel => ambient_lighting_IBL.ps.hlsl} (83%) rename base/renderprogs/{ambient_lighting_IBL.vertex => ambient_lighting_IBL.vs.hlsl} (99%) diff --git a/base/renderprogs/_manifest.lua b/base/renderprogs/_manifest.lua index e4213eea..649b8590 100644 --- a/base/renderprogs/_manifest.lua +++ b/base/renderprogs/_manifest.lua @@ -9,8 +9,8 @@ return -- shaders "ambient_lighting.ps.hlsl", "ambient_lighting.vs.hlsl", - "ambient_lighting_IBL.pixel", - "ambient_lighting_IBL.vertex", + "ambient_lighting_IBL.ps.hlsl", + "ambient_lighting_IBL.vs.hlsl", "AmbientOcclusion_AO.ps.hlsl", "AmbientOcclusion_AO.vs.hlsl", "AmbientOcclusion_blur.ps.hlsl", diff --git a/base/renderprogs/ambient_lighting.pixel b/base/renderprogs/ambient_lighting.pixel deleted file mode 100644 index 38db99e3..00000000 --- a/base/renderprogs/ambient_lighting.pixel +++ /dev/null @@ -1,97 +0,0 @@ -/* -=========================================================================== - -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 . - -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 "renderprogs/global.inc" - -uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface bump map -uniform sampler2D samp1 : register(s1); // texture 2 is the light falloff texture -uniform sampler2D samp2 : register(s2); // texture 3 is the light projection texture -uniform sampler2D samp3 : register(s3); // texture 4 is the per-surface diffuse map -uniform sampler2D samp4 : register(s4); // texture 5 is the per-surface specular 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.texcoord1.xy ); -// half4 lightFalloff = idtex2Dproj( samp1, fragment.texcoord2 ); -// half4 lightProj = idtex2Dproj( samp2, fragment.texcoord3 ); - half4 YCoCG = tex2D( samp3, fragment.texcoord4.xy ); - half4 specMap = tex2D( samp4, fragment.texcoord5.xy ); - - half3 lightVector = normalize( fragment.texcoord0.xyz ); - half3 diffuseMap = 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 ); - - half3 lightColor = rpAmbientColor.rgb; - - half rim = 1.0f - saturate( hDotN ); - half rimPower = 8.0; - half3 rimColor = half3( 0.125 ) * 1.2 * lightColor * pow( rim, rimPower ); - - //result.color.rgb = localNormal.xyz * 0.5 + 0.5; - result.color.xyz = ( ( diffuseColor + specularColor ) * halfLdotN * lightColor + rimColor ) * fragment.color.rgb;; - result.color.w = 1.0; -} diff --git a/base/renderprogs/ambient_lighting.vertex b/base/renderprogs/ambient_lighting.vertex deleted file mode 100644 index c6473cd7..00000000 --- a/base/renderprogs/ambient_lighting.vertex +++ /dev/null @@ -1,199 +0,0 @@ -/* -=========================================================================== - -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 . - -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 "renderprogs/global.inc" - -#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 ) ); - - //-------------------------------------------------------------- - - //result.texcoord0 is the direction to the light in tangent space - result.texcoord0.x = dot3( tangent, toLight ); - result.texcoord0.y = dot3( bitangent, toLight ); - result.texcoord0.z = dot3( normal, toLight ); - result.texcoord0.w = 1.0f; - - //textures 1 takes the base coordinates by the texture matrix - result.texcoord1 = defaultTexCoord; - result.texcoord1.x = dot4( vertex.texcoord.xy, rpBumpMatrixS ); - result.texcoord1.y = dot4( vertex.texcoord.xy, rpBumpMatrixT ); - - //# texture 2 has one texgen - //result.texcoord2 = defaultTexCoord; - //result.texcoord2.x = dot4( vertex.position, rpLightFalloffS ); - - //# texture 3 has three texgens - //result.texcoord3.x = dot4( vertex.position, rpLightProjectionS ); - //result.texcoord3.y = dot4( vertex.position, rpLightProjectionT ); - //result.texcoord3.z = 0.0f; - //result.texcoord3.w = dot4( vertex.position, rpLightProjectionQ ); - - //# textures 4 takes the base coordinates by the texture matrix - result.texcoord4 = defaultTexCoord; - result.texcoord4.x = dot4( vertex.texcoord.xy, rpDiffuseMatrixS ); - result.texcoord4.y = dot4( vertex.texcoord.xy, rpDiffuseMatrixT ); - - //# textures 5 takes the base coordinates by the texture matrix - result.texcoord5 = defaultTexCoord; - result.texcoord5.x = dot4( vertex.texcoord.xy, rpSpecularMatrixS ); - result.texcoord5.y = dot4( vertex.texcoord.xy, rpSpecularMatrixT ); - - //# texture 6's texcoords will be the halfangle in texture space - - //# calculate normalized vector to light in R0 - toLight = normalize( toLight ); - - //# calculate normalized vector to viewer in R1 - float4 toView = normalize( rpLocalViewOrigin - modelPosition ); - - //# add together to become the half angle vector in object space (non-normalized) - float4 halfAngleVector = toLight + toView; - - //# put into texture space - result.texcoord6.x = dot3( tangent, halfAngleVector ); - result.texcoord6.y = dot3( bitangent, halfAngleVector ); - result.texcoord6.z = dot3( normal, halfAngleVector ); - result.texcoord6.w = 1.0f; - -#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 -} \ No newline at end of file diff --git a/base/renderprogs/ambient_lighting_IBL.pixel b/base/renderprogs/ambient_lighting_IBL.ps.hlsl similarity index 83% rename from base/renderprogs/ambient_lighting_IBL.pixel rename to base/renderprogs/ambient_lighting_IBL.ps.hlsl index ad314c7b..ccd8a849 100644 --- a/base/renderprogs/ambient_lighting_IBL.pixel +++ b/base/renderprogs/ambient_lighting_IBL.ps.hlsl @@ -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-2016 Robert Beckebans +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"). @@ -27,14 +27,14 @@ If you have questions concerning this license or the applicable additional terms =========================================================================== */ -#include "renderprogs/global.inc" -#include "renderprogs/BRDF.inc" +#include "global.inc.hlsl" +#include "BRDF.inc.hlsl" -uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface bump map -uniform sampler2D samp1 : register(s1); // texture 2 is the light falloff texture -uniform sampler2D samp2 : register(s2); // texture 3 is the light projection texture -uniform sampler2D samp3 : register(s3); // texture 4 is the per-surface diffuse map -uniform sampler2D samp4 : register(s4); // texture 5 is the per-surface specular map +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 @@ -59,8 +59,8 @@ 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( samp3, fragment.texcoord1.xy ); - half4 specMap = tex2D( samp4, fragment.texcoord2.xy ); + 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 ) ); @@ -118,12 +118,12 @@ void main( PS_IN fragment, out PS_OUT result ) { half3 specularColor = lerp( dielectricColor, baseColor, metallic ); //diffuseColor = half3( 1.0 ); - float3 diffuseLight = sRGBToLinearRGB( texCUBE( samp7, globalNormal ).rgb ) * diffuseColor * ( rpDiffuseModifier.xyz ) * 1.5f; + 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 = sRGBToLinearRGB( texCUBElod( samp8, float4( reflectionVector, mip ) ).rgb ) * ( rpSpecularModifier.xyz ) * 1.0f; + float3 envColor = ( textureLod( samp8, reflectionVector, mip ).rgb ) * ( rpSpecularModifier.xyz ) * 1.0f; float3 specularLight = envColor * specularColor; @@ -132,8 +132,9 @@ void main( PS_IN fragment, out PS_OUT result ) { half4 specMapSRGB = specMap; specMap = sRGBAToLinearRGBA( specMap ); - //float3 diffuseLight = sRGBToLinearRGB( texCUBE( samp7, globalNormal ).rgb ) * diffuseMap.rgb * ( rpDiffuseModifier.xyz ) * 1.5f; - float3 diffuseLight = diffuseMap.rgb * ( rpDiffuseModifier.xyz ) * 1.5f; + //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 ); @@ -144,7 +145,7 @@ void main( PS_IN fragment, out PS_OUT result ) { const float roughness = 1.0 - glossiness; float mip = clamp( ( roughness * 7.0 ) + 0.0, 0.0, 10.0 ); - float3 envColor = sRGBToLinearRGB( texCUBElod( samp8, float4( reflectionVector, mip ) ).rgb ) * ( rpSpecularModifier.xyz ) * 1.0f; + float3 envColor = ( textureLod( samp8, reflectionVector, mip ).rgb ) * ( rpSpecularModifier.xyz ) * 0.5f; float3 specularLight = envColor * specMap.rgb; diff --git a/base/renderprogs/ambient_lighting_IBL.vertex b/base/renderprogs/ambient_lighting_IBL.vs.hlsl similarity index 99% rename from base/renderprogs/ambient_lighting_IBL.vertex rename to base/renderprogs/ambient_lighting_IBL.vs.hlsl index 8d2007fa..e44f360f 100644 --- a/base/renderprogs/ambient_lighting_IBL.vertex +++ b/base/renderprogs/ambient_lighting_IBL.vs.hlsl @@ -27,7 +27,7 @@ If you have questions concerning this license or the applicable additional terms =========================================================================== */ -#include "renderprogs/global.inc" +#include "global.inc.hlsl" #if defined( USE_GPU_SKINNING ) uniform matrices_ubo { float4 matrices[408]; }; diff --git a/base/renderprogs/postprocess.ps.hlsl b/base/renderprogs/postprocess.ps.hlsl index 969079e5..9dbfcc31 100644 --- a/base/renderprogs/postprocess.ps.hlsl +++ b/base/renderprogs/postprocess.ps.hlsl @@ -47,7 +47,7 @@ struct PS_OUT #define USE_TECHNICOLOR 1 // [0 or 1] -#define Technicolor_Amount 0.6 // [0.00 to 1.00] +#define Technicolor_Amount 0.5 // [0.00 to 1.00] #define Technicolor_Power 4.0 // [0.00 to 8.00] #define Technicolor_RedNegativeAmount 0.88 // [0.00 to 1.00] #define Technicolor_GreenNegativeAmount 0.88 // [0.00 to 1.00] diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 64f21fce..041c4bf0 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -5890,7 +5890,7 @@ void idRenderBackend::PostProcess( const void* data ) /* * The shader has three passes, chained together as follows: * - * |input|------------------� + * |input|------------------· * v | * [ SMAA*EdgeDetection ] | * v | @@ -5900,7 +5900,7 @@ void idRenderBackend::PostProcess( const void* data ) * v | * |blendTex| | * v | - * [ SMAANeighborhoodBlending ] <------� + * [ SMAANeighborhoodBlending ] <------· * v * |output| */ diff --git a/neo/renderer/RenderBackend.h b/neo/renderer/RenderBackend.h index 7119b7a1..1f9484e1 100644 --- a/neo/renderer/RenderBackend.h +++ b/neo/renderer/RenderBackend.h @@ -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 diff --git a/neo/renderer/RenderProgs.cpp b/neo/renderer/RenderProgs.cpp index b4cf3853..8dbd7579 100644 --- a/neo/renderer/RenderProgs.cpp +++ b/neo/renderer/RenderProgs.cpp @@ -111,8 +111,8 @@ void idRenderProgManager::Init() { 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_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 diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index 457dc176..d0450507 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -396,7 +396,7 @@ static const cgShaderDef_t cg_renderprogs[] = " *\n" " * The shader has three passes, chained together as follows:\n" " *\n" - " * |input|------------------�\n" + " * |input|------------------·\n" " * v |\n" " * [ SMAA*EdgeDetection ] |\n" " * v |\n" @@ -406,7 +406,7 @@ static const cgShaderDef_t cg_renderprogs[] = " * v |\n" " * |blendTex| |\n" " * v |\n" - " * [ SMAANeighborhoodBlending ] <------�\n" + " * [ SMAANeighborhoodBlending ] <------·\n" " * v\n" " * |output|\n" " *\n" @@ -1794,12 +1794,17 @@ static const cgShaderDef_t cg_renderprogs[] = "}\n" "\n" "// Fresnel term F( v, h )\n" - "// Fnone( v, h ) = F(0�) = specularColor\n" + "// Fnone( v, h ) = F(0°) = specularColor\n" "half3 Fresnel_Schlick( half3 specularColor, half vdotH )\n" "{\n" " 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 .\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 .\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" @@ -8279,7 +8660,7 @@ static const cgShaderDef_t cg_renderprogs[] = " const half roughness = specMapSRGB.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" + " // 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" @@ -9364,7 +9745,7 @@ static const cgShaderDef_t cg_renderprogs[] = " const half roughness = specMapSRGB.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" + " // 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" @@ -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"