Implement line portals and improve sky handling
This commit is contained in:
parent
4633029a74
commit
4ca2ffd58e
10 changed files with 121 additions and 56 deletions
|
|
@ -31,6 +31,7 @@ enum ERenderEffect
|
|||
EFF_SPHEREMAP,
|
||||
EFF_BURN,
|
||||
EFF_STENCIL,
|
||||
EFF_PORTAL,
|
||||
|
||||
MAX_EFFECTS
|
||||
};
|
||||
|
|
@ -689,8 +690,8 @@ public:
|
|||
}
|
||||
|
||||
// Draw level mesh
|
||||
virtual void DrawLevelMeshDepthPass() { }
|
||||
virtual void DrawLevelMeshOpaquePass() { }
|
||||
virtual void DrawLevelMeshSurfaces(bool noFragmentShader) { }
|
||||
virtual void DrawLevelMeshPortals(bool noFragmentShader) { }
|
||||
virtual int GetNextQueryIndex() { return 0; }
|
||||
virtual void BeginQuery() { }
|
||||
virtual void EndQuery() { }
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ VkShaderProgram* VkShaderManager::Get(const VkShaderKey& key)
|
|||
{ "spheremap", "shaders/scene/frag_main.glsl", "shaders/scene/material_default.glsl", "shaders/scene/mateffect_default.glsl", "shaders/scene/lightmodel_normal.glsl", "#define SPHEREMAP\n#define NO_ALPHATEST\n" },
|
||||
{ "burn", "shaders/scene/frag_burn.glsl", nullptr, nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||
{ "stencil", "shaders/scene/frag_stencil.glsl", nullptr, nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||
{ "portal", "shaders/scene/frag_portal.glsl", nullptr, nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||
};
|
||||
|
||||
const auto& desc = effectshaders[key.SpecialEffect];
|
||||
|
|
|
|||
|
|
@ -851,31 +851,31 @@ void VkRenderState::ApplyLevelMesh()
|
|||
mCommandBuffer->bindIndexBuffer(fb->GetLevelMesh()->GetIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
}
|
||||
|
||||
void VkRenderState::DrawLevelMeshDepthPass()
|
||||
void VkRenderState::DrawLevelMeshSurfaces(bool noFragmentShader)
|
||||
{
|
||||
ApplyLevelMesh();
|
||||
|
||||
auto submesh = fb->GetLevelMesh()->GetMesh()->StaticMesh.get();
|
||||
for (LevelSubmeshDrawRange& range : submesh->DrawList)
|
||||
auto mesh = fb->GetLevelMesh()->GetMesh();
|
||||
for (LevelSubmesh* submesh : { mesh->StaticMesh.get(), mesh->DynamicMesh.get() })
|
||||
{
|
||||
DrawLevelMeshRange(mCommandBuffer, fb->GetLevelMeshPipelineKey(range.PipelineID), range.Start, range.Count, true);
|
||||
for (LevelSubmeshDrawRange& range : submesh->DrawList)
|
||||
{
|
||||
DrawLevelMeshRange(mCommandBuffer, fb->GetLevelMeshPipelineKey(range.PipelineID), range.Start, range.Count, noFragmentShader);
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (LevelSubmeshDrawRange& range : submesh->PortalList)
|
||||
{
|
||||
DrawLevelMeshRange(mCommandBuffer, fb->GetLevelMeshPipelineKey(range.PipelineID), range.Start, range.Count, true);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void VkRenderState::DrawLevelMeshOpaquePass()
|
||||
void VkRenderState::DrawLevelMeshPortals(bool noFragmentShader)
|
||||
{
|
||||
ApplyLevelMesh();
|
||||
|
||||
auto submesh = fb->GetLevelMesh()->GetMesh()->StaticMesh.get();
|
||||
for (LevelSubmeshDrawRange& range : submesh->DrawList)
|
||||
auto mesh = fb->GetLevelMesh()->GetMesh();
|
||||
for (LevelSubmesh* submesh : { mesh->StaticMesh.get(), mesh->DynamicMesh.get() })
|
||||
{
|
||||
DrawLevelMeshRange(mCommandBuffer, fb->GetLevelMeshPipelineKey(range.PipelineID), range.Start, range.Count, false);
|
||||
for (LevelSubmeshDrawRange& range : submesh->PortalList)
|
||||
{
|
||||
DrawLevelMeshRange(mCommandBuffer, fb->GetLevelMeshPipelineKey(range.PipelineID), range.Start, range.Count, noFragmentShader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -925,6 +925,8 @@ void VkRenderState::DrawLevelMeshRange(VulkanCommandBuffer* cmdbuffer, VkPipelin
|
|||
pipelineKey.StencilPassOp = mStencilOp;
|
||||
pipelineKey.ColorMask = mColorMask;
|
||||
pipelineKey.CullMode = mCullMode;
|
||||
if (!mTextureEnabled)
|
||||
pipelineKey.ShaderKey.EffectState = SHADER_NoTexture;
|
||||
mPipelineKey = pipelineKey;
|
||||
|
||||
PushConstants pushConstants = {};
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ public:
|
|||
void ResetVertices() override;
|
||||
|
||||
// Draw level mesh
|
||||
void DrawLevelMeshDepthPass() override;
|
||||
void DrawLevelMeshOpaquePass() override;
|
||||
void DrawLevelMeshSurfaces(bool noFragmentShader) override;
|
||||
void DrawLevelMeshPortals(bool noFragmentShader) override;
|
||||
int GetNextQueryIndex() override;
|
||||
void BeginQuery() override;
|
||||
void EndQuery() override;
|
||||
|
|
|
|||
|
|
@ -3693,7 +3693,7 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
|
|||
// set up world state
|
||||
SpawnSpecials();
|
||||
|
||||
InitLevelMesh(map);
|
||||
//InitLevelMesh(map);
|
||||
|
||||
// disable reflective planes on sloped sectors.
|
||||
for (auto &sec : Level->sectors)
|
||||
|
|
@ -3728,7 +3728,7 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
|
|||
if (!Level->IsReentering())
|
||||
Level->FinalizePortals(); // finalize line portals after polyobjects have been initialized. This info is needed for properly flagging them.
|
||||
|
||||
Level->levelMesh->CreatePortals(*Level); // [RaveYard]: needs portal data, but at the same time intializing the level mesh here breaks floor/ceiling planes!
|
||||
InitLevelMesh(map);
|
||||
|
||||
Level->aabbTree = new DoomLevelAABBTree(Level);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ public:
|
|||
void DumpMesh(const FString& objFilename, const FString& mtlFilename) const;
|
||||
|
||||
void BuildSectorGroups(const FLevelLocals& doomMap);
|
||||
void CreatePortals(FLevelLocals& doomMap);
|
||||
|
||||
TArray<int> sectorGroup; // index is sector, value is sectorGroup
|
||||
TArray<int> sectorPortals[2]; // index is sector+plane, value is index into the portal list
|
||||
TArray<int> linePortals; // index is linedef, value is index into the portal list
|
||||
|
||||
private:
|
||||
void CreatePortals(FLevelLocals& doomMap);
|
||||
FLightNode* GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
VSMatrix GetPlaneTextureRotationMatrix(FGameTexture* gltexture, const sector_t* sector, int plane);
|
||||
void GetTexCoordInfo(FGameTexture* tex, FTexCoordInfo* tci, side_t* side, int texpos);
|
||||
|
||||
EXTERN_CVAR(Bool, gl_texture)
|
||||
EXTERN_CVAR(Float, lm_scale);
|
||||
|
||||
DoomLevelSubmesh::DoomLevelSubmesh(DoomLevelMesh* mesh, FLevelLocals& doomMap, bool staticMesh) : LevelMesh(mesh), StaticMesh(staticMesh)
|
||||
|
|
@ -61,7 +60,7 @@ void DoomLevelSubmesh::Update(FLevelLocals& doomMap, int lightmapStartIndex)
|
|||
void DoomLevelSubmesh::Reset()
|
||||
{
|
||||
Surfaces.Clear();
|
||||
WallPortals.Clear();
|
||||
Portals.Clear();
|
||||
Mesh.Vertices.Clear();
|
||||
Mesh.Indexes.Clear();
|
||||
Mesh.SurfaceIndexes.Clear();
|
||||
|
|
@ -113,22 +112,24 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap)
|
|||
// Part 1: solid geometry. This is set up so that there are no transparent parts
|
||||
state.SetDepthFunc(DF_LEqual);
|
||||
state.ClearDepthBias();
|
||||
state.EnableTexture(gl_texture);
|
||||
state.EnableTexture(true);
|
||||
state.EnableBrightmap(true);
|
||||
state.AlphaFunc(Alpha_GEqual, 0.f);
|
||||
CreateWallSurface(side, disp, state, result.list);
|
||||
|
||||
for (HWWall& portal : result.portals)
|
||||
{
|
||||
Portals.Push(portal);
|
||||
}
|
||||
|
||||
CreateWallSurface(side, disp, state, result.portals, true);
|
||||
|
||||
// final pass: translucent stuff
|
||||
state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold);
|
||||
state.SetRenderStyle(STYLE_Translucent);
|
||||
CreateWallSurface(side, disp, state, result.translucent);
|
||||
state.AlphaFunc(Alpha_GEqual, 0.f);
|
||||
state.SetRenderStyle(STYLE_Normal);
|
||||
|
||||
for (const HWWall& portal : result.portals)
|
||||
{
|
||||
WallPortals.Push(portal);
|
||||
}
|
||||
}
|
||||
|
||||
// Create surfaces for all flats
|
||||
|
|
@ -149,7 +150,7 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap)
|
|||
// Part 1: solid geometry. This is set up so that there are no transparent parts
|
||||
state.SetDepthFunc(DF_LEqual);
|
||||
state.ClearDepthBias();
|
||||
state.EnableTexture(gl_texture);
|
||||
state.EnableTexture(true);
|
||||
state.EnableBrightmap(true);
|
||||
CreateFlatSurface(disp, state, result.list);
|
||||
|
||||
|
|
@ -168,20 +169,39 @@ void DoomLevelSubmesh::CreateStaticSurfaces(FLevelLocals& doomMap)
|
|||
}
|
||||
}
|
||||
|
||||
void DoomLevelSubmesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray<HWWall>& list)
|
||||
void DoomLevelSubmesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray<HWWall>& list, bool isSky)
|
||||
{
|
||||
for (HWWall& wallpart : list)
|
||||
{
|
||||
if (wallpart.texture && wallpart.texture->isMasked())
|
||||
if (isSky)
|
||||
{
|
||||
state.AlphaFunc(Alpha_GEqual, gl_mask_threshold);
|
||||
state.SetEffect(EFF_PORTAL);
|
||||
state.EnableTexture(false);
|
||||
state.SetRenderStyle(STYLE_Normal);
|
||||
|
||||
wallpart.MakeVertices(state, false);
|
||||
wallpart.RenderWall(state, HWWall::RWF_BLANK);
|
||||
wallpart.vertcount = 0;
|
||||
|
||||
wallpart.LevelMeshInfo.Type = ST_UPPERSIDE;
|
||||
wallpart.LevelMeshInfo.ControlSector = nullptr;
|
||||
|
||||
state.SetEffect(EFF_NONE);
|
||||
state.EnableTexture(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
state.AlphaFunc(Alpha_GEqual, 0.f);
|
||||
}
|
||||
if (wallpart.texture && wallpart.texture->isMasked())
|
||||
{
|
||||
state.AlphaFunc(Alpha_GEqual, gl_mask_threshold);
|
||||
}
|
||||
else
|
||||
{
|
||||
state.AlphaFunc(Alpha_GEqual, 0.f);
|
||||
}
|
||||
|
||||
wallpart.DrawWall(&disp, state, false);
|
||||
wallpart.DrawWall(&disp, state, false);
|
||||
}
|
||||
|
||||
int pipelineID = 0;
|
||||
int startVertIndex = Mesh.Vertices.Size();
|
||||
|
|
@ -230,7 +250,8 @@ void DoomLevelSubmesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, M
|
|||
surf.Plane = ToPlane(Mesh.Vertices[startVertIndex + 3].fPos(), Mesh.Vertices[startVertIndex + 2].fPos(), Mesh.Vertices[startVertIndex + 1].fPos(), Mesh.Vertices[startVertIndex].fPos());
|
||||
surf.Texture = wallpart.texture;
|
||||
surf.PipelineID = pipelineID;
|
||||
surf.PortalIndex = (surf.Type == ST_MIDDLESIDE) ? LevelMesh->linePortals[side->linedef->Index()] : 0;
|
||||
surf.PortalIndex = isSky ? LevelMesh->linePortals[side->linedef->Index()] : 0;
|
||||
surf.IsSky = isSky;
|
||||
Surfaces.Push(surf);
|
||||
}
|
||||
}
|
||||
|
|
@ -239,16 +260,30 @@ void DoomLevelSubmesh::CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& st
|
|||
{
|
||||
for (HWFlat& flatpart : list)
|
||||
{
|
||||
if (flatpart.texture && flatpart.texture->isMasked())
|
||||
if (isSky)
|
||||
{
|
||||
state.AlphaFunc(Alpha_GEqual, gl_mask_threshold);
|
||||
state.SetEffect(EFF_PORTAL);
|
||||
state.EnableTexture(false);
|
||||
state.SetRenderStyle(STYLE_Normal);
|
||||
|
||||
flatpart.DrawSubsectors(&disp, state);
|
||||
|
||||
state.SetEffect(EFF_NONE);
|
||||
state.EnableTexture(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
state.AlphaFunc(Alpha_GEqual, 0.f);
|
||||
}
|
||||
if (flatpart.texture && flatpart.texture->isMasked())
|
||||
{
|
||||
state.AlphaFunc(Alpha_GEqual, gl_mask_threshold);
|
||||
}
|
||||
else
|
||||
{
|
||||
state.AlphaFunc(Alpha_GEqual, 0.f);
|
||||
}
|
||||
|
||||
flatpart.DrawFlat(&disp, state, false);
|
||||
flatpart.DrawFlat(&disp, state, false);
|
||||
}
|
||||
|
||||
int pipelineID = 0;
|
||||
int uniformsIndex = 0;
|
||||
|
|
@ -290,6 +325,8 @@ void DoomLevelSubmesh::CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& st
|
|||
if (surf.ControlSector)
|
||||
surf.Plane = -surf.Plane;
|
||||
|
||||
float skyZ = flatpart.ceiling ? 32768.0f : -32768.0f;
|
||||
|
||||
for (subsector_t* sub : flatpart.section->subsectors)
|
||||
{
|
||||
int startVertIndex = Mesh.Vertices.Size();
|
||||
|
|
@ -301,7 +338,7 @@ void DoomLevelSubmesh::CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& st
|
|||
FFlatVertex ffv;
|
||||
ffv.x = (float)vt->fX();
|
||||
ffv.y = (float)vt->fY();
|
||||
ffv.z = (float)plane.ZatPoint(vt);
|
||||
ffv.z = isSky ? skyZ : (float)plane.ZatPoint(vt);
|
||||
ffv.u = (float)vt->fX() / 64.f;
|
||||
ffv.v = -(float)vt->fY() / 64.f;
|
||||
ffv.lu = 0.0f;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ public:
|
|||
|
||||
TArray<std::unique_ptr<DoomLevelMeshSurface*[]>> PolyLMSurfaces;
|
||||
|
||||
TArray<HWWall> WallPortals;
|
||||
TArray<HWWall> Portals;
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
|
|
@ -64,7 +64,7 @@ private:
|
|||
|
||||
void CreateIndexes();
|
||||
|
||||
void CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray<HWWall>& list);
|
||||
void CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray<HWWall>& list, bool isSky = false);
|
||||
void CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& state, TArray<HWFlat>& list, bool isSky = false);
|
||||
|
||||
static FVector4 ToPlane(const FVector3& pt1, const FVector3& pt2, const FVector3& pt3)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
EXTERN_CVAR(Float, r_visibility)
|
||||
EXTERN_CVAR(Int, lm_background_updates);
|
||||
EXTERN_CVAR(Float, r_actorspriteshadowdist)
|
||||
EXTERN_CVAR(Bool, gl_portals)
|
||||
|
||||
CVAR(Bool, lm_always_update, false, 0)
|
||||
|
||||
|
|
@ -410,20 +411,25 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state)
|
|||
|
||||
validcount++; // used for processing sidedefs only once by the renderer.
|
||||
|
||||
auto& wallPortals = static_cast<DoomLevelSubmesh*>(level.levelMesh->StaticMesh.get())->WallPortals;
|
||||
auto& portals = static_cast<DoomLevelSubmesh*>(level.levelMesh->StaticMesh.get())->Portals;
|
||||
|
||||
// draw level into depth buffer
|
||||
state.SetColorMask(false);
|
||||
state.SetCulling(Cull_CW);
|
||||
state.DrawLevelMeshDepthPass();
|
||||
state.DrawLevelMeshSurfaces(true);
|
||||
if (gl_portals)
|
||||
{
|
||||
state.SetDepthBias(1, 128);
|
||||
state.DrawLevelMeshPortals(true);
|
||||
state.SetDepthBias(0, 0);
|
||||
}
|
||||
|
||||
// use occlusion queries on all portals in level to decide which are visible
|
||||
int queryStart = state.GetNextQueryIndex();
|
||||
state.SetDepthMask(false);
|
||||
state.EnableTexture(false);
|
||||
state.SetEffect(EFF_FOGBOUNDARY);
|
||||
state.AlphaFunc(Alpha_GEqual, 0.f);
|
||||
for (HWWall& wall : wallPortals)
|
||||
state.SetEffect(EFF_PORTAL);
|
||||
for (HWWall& wall : portals)
|
||||
{
|
||||
state.BeginQuery();
|
||||
|
||||
|
|
@ -434,13 +440,19 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state)
|
|||
state.EndQuery();
|
||||
}
|
||||
state.SetEffect(EFF_NONE);
|
||||
state.EnableTexture(true);
|
||||
state.EnableTexture(gl_texture);
|
||||
state.SetColorMask(true);
|
||||
state.SetDepthMask(true);
|
||||
int queryEnd = state.GetNextQueryIndex();
|
||||
|
||||
// draw opaque level so the GPU has something to do while we examine the query results
|
||||
state.DrawLevelMeshOpaquePass();
|
||||
state.DrawLevelMeshSurfaces(false);
|
||||
if (!gl_portals)
|
||||
{
|
||||
state.SetDepthBias(1, 128);
|
||||
state.DrawLevelMeshPortals(false);
|
||||
state.SetDepthBias(0, 0);
|
||||
}
|
||||
state.SetCulling(Cull_None);
|
||||
|
||||
// retrieve the query results and use them to fill the portal manager with portals
|
||||
|
|
@ -450,7 +462,7 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state)
|
|||
bool portalVisible = QueryResultsBuffer[i];
|
||||
if (portalVisible)
|
||||
{
|
||||
PutWallPortal(wallPortals[i], state);
|
||||
PutWallPortal(portals[i], state);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -524,9 +536,11 @@ void HWDrawInfo::PutWallPortal(HWWall wall, FRenderState& state)
|
|||
}
|
||||
else if (portaltype == PORTALTYPE_SECTORSTACK)
|
||||
{
|
||||
if (screen->instack[1 - portalplane])
|
||||
return;
|
||||
wall.PutPortal(&ddi, state, portaltype, portalplane);
|
||||
// To do: this seems to need AddSubsectorToPortal?
|
||||
|
||||
//if (screen->instack[1 - portalplane])
|
||||
// return;
|
||||
//wall.PutPortal(&ddi, state, portaltype, portalplane);
|
||||
}
|
||||
else if (portaltype == PORTALTYPE_PLANEMIRROR)
|
||||
{
|
||||
|
|
|
|||
10
wadsrc/static/shaders/scene/frag_portal.glsl
Normal file
10
wadsrc/static/shaders/scene/frag_portal.glsl
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
void main()
|
||||
{
|
||||
FragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
#ifdef GBUFFER_PASS
|
||||
FragFog = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
FragNormal = vec4(0.5, 0.5, 0.5, 1.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue