mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-22 03:51:26 +00:00
Upgrade lightmapper to latest vkdoom code
This commit is contained in:
parent
08f280b54a
commit
f689ea3640
28 changed files with 2716 additions and 2120 deletions
|
@ -52,16 +52,25 @@ set(ZDRAY_SOURCES
|
||||||
src/nodebuilder/nodebuild.h
|
src/nodebuilder/nodebuild.h
|
||||||
src/lightmapper/hw_levelmesh.cpp
|
src/lightmapper/hw_levelmesh.cpp
|
||||||
src/lightmapper/hw_levelmesh.h
|
src/lightmapper/hw_levelmesh.h
|
||||||
|
src/lightmapper/hw_levelmeshlight.h
|
||||||
|
src/lightmapper/hw_levelmeshportal.h
|
||||||
|
src/lightmapper/hw_levelmeshsurface.h
|
||||||
|
src/lightmapper/hw_lightmaptile.h
|
||||||
|
src/lightmapper/flatvertices.h
|
||||||
|
src/lightmapper/hw_materialstate.h
|
||||||
|
src/lightmapper/hw_surfaceuniforms.h
|
||||||
src/lightmapper/hw_collision.cpp
|
src/lightmapper/hw_collision.cpp
|
||||||
src/lightmapper/hw_collision.h
|
src/lightmapper/hw_collision.h
|
||||||
src/lightmapper/vk_renderdevice.cpp
|
src/lightmapper/vk_renderdevice.cpp
|
||||||
src/lightmapper/vk_renderdevice.h
|
src/lightmapper/vk_renderdevice.h
|
||||||
src/lightmapper/vk_lightmap.cpp
|
src/lightmapper/vk_levelmesh.cpp
|
||||||
src/lightmapper/vk_lightmap.h
|
src/lightmapper/vk_levelmesh.h
|
||||||
src/lightmapper/vk_raytrace.cpp
|
src/lightmapper/vk_lightmapper.cpp
|
||||||
src/lightmapper/vk_raytrace.h
|
src/lightmapper/vk_lightmapper.h
|
||||||
src/lightmapper/doom_levelmesh.cpp
|
src/lightmapper/doom_levelmesh.cpp
|
||||||
src/lightmapper/doom_levelmesh.h
|
src/lightmapper/doom_levelmesh.h
|
||||||
|
src/lightmapper/doom_levelsubmesh.cpp
|
||||||
|
src/lightmapper/doom_levelsubmesh.h
|
||||||
src/lightmapper/gpuraytracer.cpp
|
src/lightmapper/gpuraytracer.cpp
|
||||||
src/lightmapper/gpuraytracer.h
|
src/lightmapper/gpuraytracer.h
|
||||||
src/lightmapper/stacktrace.cpp
|
src/lightmapper/stacktrace.cpp
|
||||||
|
|
|
@ -839,7 +839,10 @@ void FProcessor::BuildLightmaps()
|
||||||
|
|
||||||
Level.SetupLights();
|
Level.SetupLights();
|
||||||
|
|
||||||
LightmapMesh = std::make_unique<DoomLevelMesh>(Level, Level.DefaultSamples, LMDims);
|
printf(" Creating level mesh\n");
|
||||||
|
LightmapMesh = std::make_unique<DoomLevelMesh>(Level);
|
||||||
|
printf(" Surfaces: %d\n", LightmapMesh->StaticMesh->GetSurfaceCount());
|
||||||
|
printf(" Tiles: %d\n", (int)LightmapMesh->StaticMesh->LightmapTiles.Size());
|
||||||
|
|
||||||
std::unique_ptr<GPURaytracer> gpuraytracer = std::make_unique<GPURaytracer>();
|
std::unique_ptr<GPURaytracer> gpuraytracer = std::make_unique<GPURaytracer>();
|
||||||
gpuraytracer->Raytrace(LightmapMesh.get());
|
gpuraytracer->Raytrace(LightmapMesh.get());
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,6 +7,32 @@
|
||||||
struct FLevel;
|
struct FLevel;
|
||||||
class FWadWriter;
|
class FWadWriter;
|
||||||
|
|
||||||
|
class DoomLevelMesh : public LevelMesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DoomLevelMesh(FLevel& doomMap);
|
||||||
|
|
||||||
|
int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) override;
|
||||||
|
|
||||||
|
void BeginFrame(FLevel& doomMap);
|
||||||
|
bool TraceSky(const FVector3& start, FVector3 direction, float dist);
|
||||||
|
void DumpMesh(const FString& objFilename, const FString& mtlFilename) const;
|
||||||
|
void AddLightmapLump(FLevel& doomMap, FWadWriter& out);
|
||||||
|
|
||||||
|
void BuildSectorGroups(const FLevel& 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(FLevel& doomMap);
|
||||||
|
void BuildLightLists(FLevel& doomMap);
|
||||||
|
void PropagateLight(FLevel& doomMap, ThingLight* light, int recursiveDepth = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
class DoomLevelMesh : public LevelMesh
|
class DoomLevelMesh : public LevelMesh
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -140,3 +166,5 @@ private:
|
||||||
static FVector3 ToFVector3(const DVector3& v) { return FVector3((float)v.X, (float)v.Y, (float)v.Z); }
|
static FVector3 ToFVector3(const DVector3& v) { return FVector3((float)v.X, (float)v.Y, (float)v.Z); }
|
||||||
static FVector4 ToFVector4(const DVector4& v) { return FVector4((float)v.X, (float)v.Y, (float)v.Z, (float)v.W); }
|
static FVector4 ToFVector4(const DVector4& v) { return FVector4((float)v.X, (float)v.Y, (float)v.Z, (float)v.W); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
1009
src/lightmapper/doom_levelsubmesh.cpp
Normal file
1009
src/lightmapper/doom_levelsubmesh.cpp
Normal file
File diff suppressed because it is too large
Load diff
136
src/lightmapper/doom_levelsubmesh.h
Normal file
136
src/lightmapper/doom_levelsubmesh.h
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "hw_levelmesh.h"
|
||||||
|
#include "framework/tarray.h"
|
||||||
|
#include "framework/vectors.h"
|
||||||
|
#include "framework/bounds.h"
|
||||||
|
#include "level/level.h"
|
||||||
|
#include <dp_rect_pack/dp_rect_pack.h>
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
typedef dp::rect_pack::RectPacker<int> RectPacker;
|
||||||
|
|
||||||
|
struct FLevel;
|
||||||
|
struct FPolyObj;
|
||||||
|
struct HWWallDispatcher;
|
||||||
|
class DoomLevelMesh;
|
||||||
|
class MeshBuilder;
|
||||||
|
|
||||||
|
enum DoomLevelMeshSurfaceType
|
||||||
|
{
|
||||||
|
ST_NONE,
|
||||||
|
ST_MIDDLESIDE,
|
||||||
|
ST_UPPERSIDE,
|
||||||
|
ST_LOWERSIDE,
|
||||||
|
ST_CEILING,
|
||||||
|
ST_FLOOR
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DoomLevelMeshSurface : public LevelMeshSurface
|
||||||
|
{
|
||||||
|
DoomLevelMeshSurfaceType Type = ST_NONE;
|
||||||
|
int TypeIndex = 0;
|
||||||
|
|
||||||
|
MapSubsectorEx* Subsector = nullptr;
|
||||||
|
IntSideDef* Side = nullptr;
|
||||||
|
IntSector* ControlSector = nullptr;
|
||||||
|
|
||||||
|
int PipelineID = 0;
|
||||||
|
|
||||||
|
std::vector<ThingLight*> LightList;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DoomLevelSubmesh : public LevelSubmesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DoomLevelSubmesh(DoomLevelMesh* mesh, FLevel& doomMap, bool staticMesh);
|
||||||
|
|
||||||
|
void Update(FLevel& doomMap, int lightmapStartIndex);
|
||||||
|
|
||||||
|
LevelMeshSurface* GetSurface(int index) override { return &Surfaces[index]; }
|
||||||
|
unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const override { return (unsigned int)(ptrdiff_t)(static_cast<const DoomLevelMeshSurface*>(surface) - Surfaces.Data()); }
|
||||||
|
int GetSurfaceCount() override { return Surfaces.Size(); }
|
||||||
|
|
||||||
|
TArray<DoomLevelMeshSurface> Surfaces;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
void CreateStaticSurfaces(FLevel& doomMap);
|
||||||
|
void CreateDynamicSurfaces(FLevel& doomMap);
|
||||||
|
|
||||||
|
void CreateSideSurfaces(std::map<LightmapTileBinding, int>& bindings, FLevel& doomMap, IntSideDef* side);
|
||||||
|
void CreateLineHorizonSurface(std::map<LightmapTileBinding, int>& bindings, FLevel& doomMap, IntSideDef* side);
|
||||||
|
void CreateFrontWallSurface(std::map<LightmapTileBinding, int>& bindings, FLevel& doomMap, IntSideDef* side);
|
||||||
|
void CreateMidWallSurface(std::map<LightmapTileBinding, int>& bindings, FLevel& doomMap, IntSideDef* side);
|
||||||
|
void Create3DFloorWallSurfaces(std::map<LightmapTileBinding, int>& bindings, FLevel& doomMap, IntSideDef* side);
|
||||||
|
void CreateTopWallSurface(std::map<LightmapTileBinding, int>& bindings, FLevel& doomMap, IntSideDef* side);
|
||||||
|
void CreateBottomWallSurface(std::map<LightmapTileBinding, int>& bindings, FLevel& doomMap, IntSideDef* side);
|
||||||
|
void SetSideTextureUVs(DoomLevelMeshSurface& surface, IntSideDef* side, WallPart texpart, float v1TopZ, float v1BottomZ, float v2TopZ, float v2BottomZ);
|
||||||
|
void CreateFloorSurface(std::map<LightmapTileBinding, int>& bindings, FLevel& doomMap, MapSubsectorEx* sub, IntSector* sector, IntSector* controlSector, int typeIndex);
|
||||||
|
void CreateCeilingSurface(std::map<LightmapTileBinding, int>& bindings, FLevel& doomMap, MapSubsectorEx* sub, IntSector* sector, IntSector* controlSector, int typeIndex);
|
||||||
|
|
||||||
|
void AddWallVertices(DoomLevelMeshSurface& surf, FFlatVertex* verts);
|
||||||
|
|
||||||
|
static bool IsTopSideSky(IntSector* frontsector, IntSector* backsector, IntSideDef* side);
|
||||||
|
static bool IsTopSideVisible(IntSideDef* side);
|
||||||
|
static bool IsBottomSideVisible(IntSideDef* side);
|
||||||
|
static bool IsSkySector(IntSector* sector, SecPlaneType plane);
|
||||||
|
static bool IsDegenerate(const FVector3& v0, const FVector3& v1, const FVector3& v2);
|
||||||
|
|
||||||
|
static FVector4 ToPlane(const FFlatVertex& pt1, const FFlatVertex& pt2, const FFlatVertex& pt3)
|
||||||
|
{
|
||||||
|
return ToPlane(FVector3(pt1.x, pt1.y, pt1.z), FVector3(pt2.x, pt2.y, pt2.z), FVector3(pt3.x, pt3.y, pt3.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
static FVector4 ToPlane(const FFlatVertex& pt1, const FFlatVertex& pt2, const FFlatVertex& pt3, const FFlatVertex& pt4)
|
||||||
|
{
|
||||||
|
return ToPlane(FVector3(pt1.x, pt1.y, pt1.z), FVector3(pt2.x, pt2.y, pt2.z), FVector3(pt3.x, pt3.y, pt3.z), FVector3(pt4.x, pt4.y, pt4.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
static FVector4 ToPlane(const FVector3& pt1, const FVector3& pt2, const FVector3& pt3)
|
||||||
|
{
|
||||||
|
FVector3 n = ((pt2 - pt1) ^ (pt3 - pt2)).Unit();
|
||||||
|
float d = pt1 | n;
|
||||||
|
return FVector4(n.X, n.Y, n.Z, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FVector4 ToPlane(const FVector3& pt1, const FVector3& pt2, const FVector3& pt3, const FVector3& pt4)
|
||||||
|
{
|
||||||
|
if (pt1.ApproximatelyEquals(pt3))
|
||||||
|
{
|
||||||
|
return ToPlane(pt1, pt2, pt4);
|
||||||
|
}
|
||||||
|
else if (pt1.ApproximatelyEquals(pt2) || pt2.ApproximatelyEquals(pt3))
|
||||||
|
{
|
||||||
|
return ToPlane(pt1, pt3, pt4);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ToPlane(pt1, pt2, pt3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SortIndexes();
|
||||||
|
|
||||||
|
void PackLightmapAtlas(FLevel& doomMap, int lightmapStartIndex);
|
||||||
|
|
||||||
|
enum PlaneAxis
|
||||||
|
{
|
||||||
|
AXIS_YZ = 0,
|
||||||
|
AXIS_XZ,
|
||||||
|
AXIS_XY
|
||||||
|
};
|
||||||
|
|
||||||
|
static PlaneAxis BestAxis(const FVector4& p);
|
||||||
|
BBox GetBoundsFromSurface(const LevelMeshSurface& surface) const;
|
||||||
|
|
||||||
|
void SetupTileTransform(int lightMapTextureWidth, int lightMapTextureHeight, LightmapTile& tile);
|
||||||
|
void AddSurfaceToTile(DoomLevelMeshSurface& surf, std::map<LightmapTileBinding, int>& bindings, FLevel& doomMap, uint16_t sampleDimension);
|
||||||
|
int GetSampleDimension(const DoomLevelMeshSurface& surf, uint16_t sampleDimension);
|
||||||
|
|
||||||
|
DoomLevelMesh* LevelMesh = nullptr;
|
||||||
|
bool StaticMesh = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(alignof(FVector2) == alignof(float[2]) && sizeof(FVector2) == sizeof(float) * 2);
|
46
src/lightmapper/flatvertices.h
Normal file
46
src/lightmapper/flatvertices.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct FFlatVertex // Note: this must always match the SurfaceVertex struct in shaders (std430 layout rules apply)
|
||||||
|
{
|
||||||
|
float x, z, y; // world position
|
||||||
|
float lindex; // lightmap texture index
|
||||||
|
float u, v; // texture coordinates
|
||||||
|
float lu, lv; // lightmap texture coordinates
|
||||||
|
|
||||||
|
void Set(float xx, float zz, float yy, float uu, float vv)
|
||||||
|
{
|
||||||
|
x = xx;
|
||||||
|
z = zz;
|
||||||
|
y = yy;
|
||||||
|
u = uu;
|
||||||
|
v = vv;
|
||||||
|
lindex = -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Set(float xx, float zz, float yy, float uu, float vv, float llu, float llv, float llindex)
|
||||||
|
{
|
||||||
|
x = xx;
|
||||||
|
z = zz;
|
||||||
|
y = yy;
|
||||||
|
lindex = llindex;
|
||||||
|
u = uu;
|
||||||
|
v = vv;
|
||||||
|
lu = llu;
|
||||||
|
lv = llv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetVertex(float _x, float _y, float _z = 0)
|
||||||
|
{
|
||||||
|
x = _x;
|
||||||
|
z = _y;
|
||||||
|
y = _z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTexCoord(float _u = 0, float _v = 0)
|
||||||
|
{
|
||||||
|
u = _u;
|
||||||
|
v = _v;
|
||||||
|
}
|
||||||
|
|
||||||
|
FVector3 fPos() const { return FVector3(x, y, z); }
|
||||||
|
};
|
|
@ -12,10 +12,10 @@ struct SurfaceInfo
|
||||||
{
|
{
|
||||||
vec3 Normal;
|
vec3 Normal;
|
||||||
float Sky;
|
float Sky;
|
||||||
float SamplingDistance;
|
|
||||||
uint PortalIndex;
|
uint PortalIndex;
|
||||||
int TextureIndex;
|
int TextureIndex;
|
||||||
float Alpha;
|
float Alpha;
|
||||||
|
float Padding;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PortalInfo
|
struct PortalInfo
|
||||||
|
|
|
@ -29,11 +29,12 @@ layout(std430, set = 1, binding = 0) buffer NodeBuffer
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct SurfaceVertex
|
struct SurfaceVertex // Note: this must always match the FFlatVertex struct
|
||||||
{
|
{
|
||||||
vec4 pos;
|
vec3 pos;
|
||||||
|
float lindex;
|
||||||
vec2 uv;
|
vec2 uv;
|
||||||
float Padding1, Padding2;
|
vec2 luv;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, set = 1, binding = 1) buffer VertexBuffer { SurfaceVertex vertices[]; };
|
layout(std430, set = 1, binding = 1) buffer VertexBuffer { SurfaceVertex vertices[]; };
|
||||||
|
|
|
@ -26,7 +26,7 @@ int TraceFirstHitTriangleT(vec3 origin, float tmin, vec3 dir, float tmax, out fl
|
||||||
int index = primitiveID * 3;
|
int index = primitiveID * 3;
|
||||||
vec2 uv = vertices[elements[index + 1]].uv * primitiveWeights.x + vertices[elements[index + 2]].uv * primitiveWeights.y + vertices[elements[index + 0]].uv * primitiveWeights.z;
|
vec2 uv = vertices[elements[index + 1]].uv * primitiveWeights.x + vertices[elements[index + 2]].uv * primitiveWeights.y + vertices[elements[index + 0]].uv * primitiveWeights.z;
|
||||||
|
|
||||||
if (surface.TextureIndex < 0)
|
if (surface.TextureIndex == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ bool TracePoint(vec3 origin, vec3 target, float tmin, vec3 dir, float tmax)
|
||||||
int index = primitiveID * 3;
|
int index = primitiveID * 3;
|
||||||
vec2 uv = vertices[elements[index + 1]].uv * primitiveWeights.x + vertices[elements[index + 2]].uv * primitiveWeights.y + vertices[elements[index + 0]].uv * primitiveWeights.z;
|
vec2 uv = vertices[elements[index + 1]].uv * primitiveWeights.x + vertices[elements[index + 2]].uv * primitiveWeights.y + vertices[elements[index + 0]].uv * primitiveWeights.z;
|
||||||
|
|
||||||
if (surface.TextureIndex < 0)
|
if (surface.TextureIndex == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ vec3 TraceSunLight(vec3 origin, vec3 normal, int surfaceIndex)
|
||||||
|
|
||||||
const float minDistance = 0.01;
|
const float minDistance = 0.01;
|
||||||
vec3 incoming = vec3(0.0);
|
vec3 incoming = vec3(0.0);
|
||||||
const float dist = 32768.0;
|
const float dist = 65536.0;
|
||||||
|
|
||||||
#if defined(USE_SOFTSHADOWS)
|
#if defined(USE_SOFTSHADOWS)
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
#include "gpuraytracer.h"
|
#include "gpuraytracer.h"
|
||||||
#include "vk_renderdevice.h"
|
#include "vk_renderdevice.h"
|
||||||
#include "vk_raytrace.h"
|
#include "vk_levelmesh.h"
|
||||||
#include "vk_lightmap.h"
|
#include "vk_lightmapper.h"
|
||||||
#include "renderdoc_app.h"
|
#include "renderdoc_app.h"
|
||||||
#include "doom_levelmesh.h"
|
#include "doom_levelmesh.h"
|
||||||
|
|
||||||
|
@ -34,44 +34,44 @@ void GPURaytracer::Raytrace(DoomLevelMesh* mesh)
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto raytrace = mDevice->GetRaytrace();
|
auto levelmesh = mDevice->GetLevelMesh();
|
||||||
auto lightmap = mDevice->GetLightmap();
|
auto lightmapper = mDevice->GetLightmapper();
|
||||||
auto submesh = mesh->StaticMesh.get();
|
auto submesh = mesh->StaticMesh.get();
|
||||||
|
|
||||||
printf(" Map uses %u lightmap textures\n", submesh->LMTextureCount);
|
printf(" Map uses %u lightmap textures\n", submesh->LMTextureCount);
|
||||||
|
|
||||||
mDevice->GetTextureManager()->CreateLightmap(submesh->LMTextureSize, submesh->LMTextureCount);
|
mDevice->GetTextureManager()->CreateLightmap(submesh->LMTextureSize, submesh->LMTextureCount);
|
||||||
|
|
||||||
raytrace->SetLevelMesh(mesh);
|
levelmesh->SetLevelMesh(mesh);
|
||||||
lightmap->SetLevelMesh(mesh);
|
lightmapper->SetLevelMesh(mesh);
|
||||||
|
|
||||||
// Keep baking until all surfaces have been processed
|
// Keep baking until all surfaces have been processed
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
raytrace->BeginFrame();
|
levelmesh->BeginFrame();
|
||||||
lightmap->BeginFrame();
|
lightmapper->BeginFrame();
|
||||||
|
|
||||||
TArray<LevelMeshSurface*> surfaces;
|
TArray<LightmapTile*> tiles;
|
||||||
for (int i = 0, count = submesh->GetSurfaceCount(); i < count; i++)
|
for (unsigned int i = 0, count = submesh->LightmapTiles.Size(); i < count; i++)
|
||||||
{
|
{
|
||||||
LevelMeshSurface* surface = submesh->GetSurface(i);
|
LightmapTile* tile = &submesh->LightmapTiles[i];
|
||||||
if (surface->needsUpdate)
|
if (tile->NeedsUpdate)
|
||||||
{
|
{
|
||||||
surfaces.Push(surface);
|
tiles.Push(tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surfaces.Size() == 0)
|
if (tiles.Size() == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
printf(" Ray tracing surfaces: %u / %u\r", submesh->GetSurfaceCount() - surfaces.Size(), submesh->GetSurfaceCount());
|
printf(" Ray tracing tiles: %u / %u\r", submesh->LightmapTiles.Size() - tiles.Size(), submesh->LightmapTiles.Size());
|
||||||
|
|
||||||
lightmap->Raytrace(surfaces);
|
lightmapper->Raytrace(tiles);
|
||||||
|
|
||||||
mDevice->GetCommands()->SubmitAndWait();
|
mDevice->GetCommands()->SubmitAndWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" Ray tracing surfaces: %u / %u\n", submesh->GetSurfaceCount(), submesh->GetSurfaceCount());
|
printf(" Ray tracing tiles: %u / %u\n", submesh->LightmapTiles.Size(), submesh->LightmapTiles.Size());
|
||||||
|
|
||||||
submesh->LMTextureData.Resize(submesh->LMTextureSize * submesh->LMTextureSize * submesh->LMTextureCount * 4);
|
submesh->LMTextureData.Resize(submesh->LMTextureSize * submesh->LMTextureSize * submesh->LMTextureCount * 4);
|
||||||
for (int arrayIndex = 0; arrayIndex < submesh->LMTextureCount; arrayIndex++)
|
for (int arrayIndex = 0; arrayIndex < submesh->LMTextureCount; arrayIndex++)
|
||||||
|
|
|
@ -24,12 +24,11 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <cstdint>
|
#ifndef NO_SSE
|
||||||
#ifndef DISABLE_SSE
|
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TriangleMeshShape::TriangleMeshShape(const FVector3 *vertices, int num_vertices, const unsigned int *elements, int num_elements)
|
TriangleMeshShape::TriangleMeshShape(const FFlatVertex *vertices, int num_vertices, const unsigned int *elements, int num_elements)
|
||||||
: vertices(vertices), num_vertices(num_vertices), elements(elements), num_elements(num_elements)
|
: vertices(vertices), num_vertices(num_vertices), elements(elements), num_elements(num_elements)
|
||||||
{
|
{
|
||||||
int num_triangles = num_elements / 3;
|
int num_triangles = num_elements / 3;
|
||||||
|
@ -45,7 +44,7 @@ TriangleMeshShape::TriangleMeshShape(const FVector3 *vertices, int num_vertices,
|
||||||
triangles.push_back(i);
|
triangles.push_back(i);
|
||||||
|
|
||||||
int element_index = i * 3;
|
int element_index = i * 3;
|
||||||
FVector3 centroid = (vertices[elements[element_index + 0]] + vertices[elements[element_index + 1]] + vertices[elements[element_index + 2]]) * (1.0f / 3.0f);
|
FVector3 centroid = (vertices[elements[element_index + 0]].fPos() + vertices[elements[element_index + 1]].fPos() + vertices[elements[element_index + 2]].fPos()) * (1.0f / 3.0f);
|
||||||
centroids.push_back(centroid);
|
centroids.push_back(centroid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,12 +280,12 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
|
||||||
|
|
||||||
FVector3 p[3] =
|
FVector3 p[3] =
|
||||||
{
|
{
|
||||||
shape->vertices[shape->elements[start_element]],
|
shape->vertices[shape->elements[start_element]].fPos(),
|
||||||
shape->vertices[shape->elements[start_element + 1]],
|
shape->vertices[shape->elements[start_element + 1]].fPos(),
|
||||||
shape->vertices[shape->elements[start_element + 2]]
|
shape->vertices[shape->elements[start_element + 2]].fPos()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Moeller<EFBFBD>Trumbore ray-triangle intersection algorithm:
|
// Moeller–Trumbore ray-triangle intersection algorithm:
|
||||||
|
|
||||||
FVector3 D = ray.end - ray.start;
|
FVector3 D = ray.end - ray.start;
|
||||||
|
|
||||||
|
@ -357,9 +356,9 @@ float TriangleMeshShape::sweep_intersect_triangle_sphere(TriangleMeshShape *shap
|
||||||
|
|
||||||
FVector3 p[3] =
|
FVector3 p[3] =
|
||||||
{
|
{
|
||||||
shape1->vertices[shape1->elements[start_element]],
|
shape1->vertices[shape1->elements[start_element]].fPos(),
|
||||||
shape1->vertices[shape1->elements[start_element + 1]],
|
shape1->vertices[shape1->elements[start_element + 1]].fPos(),
|
||||||
shape1->vertices[shape1->elements[start_element + 2]]
|
shape1->vertices[shape1->elements[start_element + 2]].fPos()
|
||||||
};
|
};
|
||||||
|
|
||||||
FVector3 c = shape2->center;
|
FVector3 c = shape2->center;
|
||||||
|
@ -529,9 +528,9 @@ bool TriangleMeshShape::overlap_triangle_sphere(TriangleMeshShape *shape1, Spher
|
||||||
int element_index = shape1->nodes[shape1_node_index].element_index;
|
int element_index = shape1->nodes[shape1_node_index].element_index;
|
||||||
|
|
||||||
FVector3 P = shape2->center;
|
FVector3 P = shape2->center;
|
||||||
FVector3 A = shape1->vertices[shape1->elements[element_index]] - P;
|
FVector3 A = shape1->vertices[shape1->elements[element_index]].fPos() - P;
|
||||||
FVector3 B = shape1->vertices[shape1->elements[element_index + 1]] - P;
|
FVector3 B = shape1->vertices[shape1->elements[element_index + 1]].fPos() - P;
|
||||||
FVector3 C = shape1->vertices[shape1->elements[element_index + 2]] - P;
|
FVector3 C = shape1->vertices[shape1->elements[element_index + 2]].fPos() - P;
|
||||||
float r = shape2->radius;
|
float r = shape2->radius;
|
||||||
float rr = r * r;
|
float rr = r * r;
|
||||||
|
|
||||||
|
@ -641,14 +640,14 @@ int TriangleMeshShape::subdivide(int *triangles, int num_triangles, const FVecto
|
||||||
// Find bounding box and median of the triangle centroids
|
// Find bounding box and median of the triangle centroids
|
||||||
FVector3 median;
|
FVector3 median;
|
||||||
FVector3 min, max;
|
FVector3 min, max;
|
||||||
min = vertices[elements[triangles[0] * 3]];
|
min = vertices[elements[triangles[0] * 3]].fPos();
|
||||||
max = min;
|
max = min;
|
||||||
for (int i = 0; i < num_triangles; i++)
|
for (int i = 0; i < num_triangles; i++)
|
||||||
{
|
{
|
||||||
int element_index = triangles[i] * 3;
|
int element_index = triangles[i] * 3;
|
||||||
for (int j = 0; j < 3; j++)
|
for (int j = 0; j < 3; j++)
|
||||||
{
|
{
|
||||||
const FVector3 &vertex = vertices[elements[element_index + j]];
|
const FVector3 &vertex = vertices[elements[element_index + j]].fPos();
|
||||||
|
|
||||||
min.X = std::min(min.X, vertex.X);
|
min.X = std::min(min.X, vertex.X);
|
||||||
min.Y = std::min(min.Y, vertex.Y);
|
min.Y = std::min(min.Y, vertex.Y);
|
||||||
|
@ -785,7 +784,7 @@ static const uint32_t clearsignbitmask[] = { 0x7fffffff, 0x7fffffff, 0x7fffffff,
|
||||||
|
|
||||||
IntersectionTest::OverlapResult IntersectionTest::ray_aabb(const RayBBox &ray, const CollisionBBox &aabb)
|
IntersectionTest::OverlapResult IntersectionTest::ray_aabb(const RayBBox &ray, const CollisionBBox &aabb)
|
||||||
{
|
{
|
||||||
#ifndef DISABLE_SSE
|
#ifndef NO_SSE
|
||||||
|
|
||||||
__m128 v = _mm_loadu_ps(&ray.v.X);
|
__m128 v = _mm_loadu_ps(&ray.v.X);
|
||||||
__m128 w = _mm_loadu_ps(&ray.w.X);
|
__m128 w = _mm_loadu_ps(&ray.w.X);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "framework/vectors.h"
|
#include "framework/vectors.h"
|
||||||
|
#include "flatvertices.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
@ -86,7 +87,7 @@ public:
|
||||||
class TriangleMeshShape
|
class TriangleMeshShape
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TriangleMeshShape(const FVector3 *vertices, int num_vertices, const unsigned int *elements, int num_elements);
|
TriangleMeshShape(const FFlatVertex *vertices, int num_vertices, const unsigned int *elements, int num_elements);
|
||||||
|
|
||||||
int get_min_depth() const;
|
int get_min_depth() const;
|
||||||
int get_max_depth() const;
|
int get_max_depth() const;
|
||||||
|
@ -121,7 +122,7 @@ public:
|
||||||
int get_root() const { return root; }
|
int get_root() const { return root; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const FVector3 *vertices = nullptr;
|
const FFlatVertex* vertices = nullptr;
|
||||||
const int num_vertices = 0;
|
const int num_vertices = 0;
|
||||||
const unsigned int *elements = nullptr;
|
const unsigned int *elements = nullptr;
|
||||||
int num_elements = 0;
|
int num_elements = 0;
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
|
|
||||||
#include "hw_levelmesh.h"
|
#include "hw_levelmesh.h"
|
||||||
|
|
||||||
|
LevelMesh::LevelMesh()
|
||||||
|
{
|
||||||
|
// Default portal
|
||||||
|
LevelMeshPortal portal;
|
||||||
|
Portals.Push(portal);
|
||||||
|
}
|
||||||
|
|
||||||
LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, float maxDist)
|
LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, float maxDist)
|
||||||
{
|
{
|
||||||
maxDist = std::max(maxDist - 10.0f, 0.0f);
|
maxDist = std::max(maxDist - 10.0f, 0.0f);
|
||||||
|
@ -24,15 +31,15 @@ LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, fl
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
hitSurface = hitmesh->GetSurface(hitmesh->MeshSurfaceIndexes[hit.triangle]);
|
hitSurface = hitmesh->GetSurface(hitmesh->Mesh.SurfaceIndexes[hit.triangle]);
|
||||||
auto portal = hitSurface->portalIndex;
|
|
||||||
|
|
||||||
|
int portal = hitSurface->PortalIndex;
|
||||||
if (!portal)
|
if (!portal)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& transformation = hitmesh->Portals[portal];
|
auto& transformation = Portals[portal];
|
||||||
|
|
||||||
auto travelDist = hit.fraction * maxDist + 2.0f;
|
auto travelDist = hit.fraction * maxDist + 2.0f;
|
||||||
if (travelDist >= maxDist)
|
if (travelDist >= maxDist)
|
||||||
|
@ -48,11 +55,11 @@ LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, fl
|
||||||
return hitSurface; // I hit something
|
return hitSurface; // I hit something
|
||||||
}
|
}
|
||||||
|
|
||||||
LevelMeshSurfaceStats LevelMesh::GatherSurfacePixelStats()
|
LevelMeshTileStats LevelMesh::GatherTilePixelStats()
|
||||||
{
|
{
|
||||||
LevelMeshSurfaceStats stats;
|
LevelMeshTileStats stats;
|
||||||
StaticMesh->GatherSurfacePixelStats(stats);
|
StaticMesh->GatherTilePixelStats(stats);
|
||||||
DynamicMesh->GatherSurfacePixelStats(stats);
|
DynamicMesh->GatherTilePixelStats(stats);
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,131 +67,123 @@ LevelMeshSurfaceStats LevelMesh::GatherSurfacePixelStats()
|
||||||
|
|
||||||
LevelSubmesh::LevelSubmesh()
|
LevelSubmesh::LevelSubmesh()
|
||||||
{
|
{
|
||||||
// Default portal
|
|
||||||
LevelMeshPortal portal;
|
|
||||||
Portals.Push(portal);
|
|
||||||
|
|
||||||
// Default empty mesh (we can't make it completely empty since vulkan doesn't like that)
|
// Default empty mesh (we can't make it completely empty since vulkan doesn't like that)
|
||||||
float minval = -100001.0f;
|
float minval = -100001.0f;
|
||||||
float maxval = -100000.0f;
|
float maxval = -100000.0f;
|
||||||
MeshVertices.Push({ minval, minval, minval });
|
Mesh.Vertices.Push({ minval, minval, minval });
|
||||||
MeshVertices.Push({ maxval, minval, minval });
|
Mesh.Vertices.Push({ maxval, minval, minval });
|
||||||
MeshVertices.Push({ maxval, maxval, minval });
|
Mesh.Vertices.Push({ maxval, maxval, minval });
|
||||||
MeshVertices.Push({ minval, minval, minval });
|
Mesh.Vertices.Push({ minval, minval, minval });
|
||||||
MeshVertices.Push({ minval, maxval, minval });
|
Mesh.Vertices.Push({ minval, maxval, minval });
|
||||||
MeshVertices.Push({ maxval, maxval, minval });
|
Mesh.Vertices.Push({ maxval, maxval, minval });
|
||||||
MeshVertices.Push({ minval, minval, maxval });
|
Mesh.Vertices.Push({ minval, minval, maxval });
|
||||||
MeshVertices.Push({ maxval, minval, maxval });
|
Mesh.Vertices.Push({ maxval, minval, maxval });
|
||||||
MeshVertices.Push({ maxval, maxval, maxval });
|
Mesh.Vertices.Push({ maxval, maxval, maxval });
|
||||||
MeshVertices.Push({ minval, minval, maxval });
|
Mesh.Vertices.Push({ minval, minval, maxval });
|
||||||
MeshVertices.Push({ minval, maxval, maxval });
|
Mesh.Vertices.Push({ minval, maxval, maxval });
|
||||||
MeshVertices.Push({ maxval, maxval, maxval });
|
Mesh.Vertices.Push({ maxval, maxval, maxval });
|
||||||
|
|
||||||
MeshVertexUVs.Resize(MeshVertices.Size());
|
|
||||||
|
|
||||||
for (int i = 0; i < 3 * 4; i++)
|
for (int i = 0; i < 3 * 4; i++)
|
||||||
MeshElements.Push(i);
|
Mesh.Indexes.Push(i);
|
||||||
|
|
||||||
UpdateCollision();
|
UpdateCollision();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelSubmesh::UpdateCollision()
|
void LevelSubmesh::UpdateCollision()
|
||||||
{
|
{
|
||||||
Collision = std::make_unique<TriangleMeshShape>(MeshVertices.Data(), MeshVertices.Size(), MeshElements.Data(), MeshElements.Size());
|
Collision = std::make_unique<TriangleMeshShape>(Mesh.Vertices.Data(), Mesh.Vertices.Size(), Mesh.Indexes.Data(), Mesh.Indexes.Size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelSubmesh::GatherSurfacePixelStats(LevelMeshSurfaceStats& stats)
|
void LevelSubmesh::GatherTilePixelStats(LevelMeshTileStats& stats)
|
||||||
{
|
{
|
||||||
int count = GetSurfaceCount();
|
int count = GetSurfaceCount();
|
||||||
for (int i = 0; i < count; ++i)
|
for (const LightmapTile& tile : LightmapTiles)
|
||||||
{
|
{
|
||||||
const auto* surface = GetSurface(i);
|
auto area = tile.AtlasLocation.Area();
|
||||||
auto area = surface->Area();
|
|
||||||
|
|
||||||
stats.pixels.total += area;
|
stats.pixels.total += area;
|
||||||
|
|
||||||
if (surface->needsUpdate)
|
if (tile.NeedsUpdate)
|
||||||
{
|
{
|
||||||
stats.surfaces.dirty++;
|
stats.tiles.dirty++;
|
||||||
stats.pixels.dirty += area;
|
stats.pixels.dirty += area;
|
||||||
}
|
}
|
||||||
if (surface->bSky)
|
|
||||||
{
|
|
||||||
stats.surfaces.sky++;
|
|
||||||
stats.pixels.sky += area;
|
|
||||||
}
|
}
|
||||||
}
|
stats.tiles.total += LightmapTiles.Size();
|
||||||
stats.surfaces.total += count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct LevelMeshPlaneGroup
|
||||||
|
{
|
||||||
|
FVector4 plane = FVector4(0, 0, 1, 0);
|
||||||
|
int sectorGroup = 0;
|
||||||
|
std::vector<LevelMeshSurface*> surfaces;
|
||||||
|
};
|
||||||
|
|
||||||
void LevelSubmesh::BuildTileSurfaceLists()
|
void LevelSubmesh::BuildTileSurfaceLists()
|
||||||
{
|
{
|
||||||
// Smoothing group surface is to be rendered with
|
// Plane group surface is to be rendered with
|
||||||
TArray<LevelMeshSmoothingGroup> SmoothingGroups;
|
TArray<LevelMeshPlaneGroup> PlaneGroups;
|
||||||
TArray<int> SmoothingGroupIndexes(GetSurfaceCount());
|
TArray<int> PlaneGroupIndexes(GetSurfaceCount());
|
||||||
|
|
||||||
for (int i = 0, count = GetSurfaceCount(); i < count; i++)
|
for (int i = 0, count = GetSurfaceCount(); i < count; i++)
|
||||||
{
|
{
|
||||||
auto surface = GetSurface(i);
|
auto surface = GetSurface(i);
|
||||||
|
|
||||||
// Is this surface in the same plane as an existing smoothing group?
|
// Is this surface in the same plane as an existing plane group?
|
||||||
int smoothingGroupIndex = -1;
|
int planeGroupIndex = -1;
|
||||||
|
|
||||||
for (size_t j = 0; j < SmoothingGroups.Size(); j++)
|
for (size_t j = 0; j < PlaneGroups.Size(); j++)
|
||||||
{
|
{
|
||||||
if (surface->sectorGroup == SmoothingGroups[j].sectorGroup)
|
if (surface->SectorGroup == PlaneGroups[j].sectorGroup)
|
||||||
{
|
{
|
||||||
float direction = SmoothingGroups[j].plane.XYZ() | surface->plane.XYZ();
|
float direction = PlaneGroups[j].plane.XYZ() | surface->Plane.XYZ();
|
||||||
if (direction >= 0.9999f && direction <= 1.001f)
|
if (direction >= 0.9999f && direction <= 1.001f)
|
||||||
{
|
{
|
||||||
auto point = (surface->plane.XYZ() * surface->plane.W);
|
auto point = (surface->Plane.XYZ() * surface->Plane.W);
|
||||||
auto planeDistance = (SmoothingGroups[j].plane.XYZ() | point) - SmoothingGroups[j].plane.W;
|
auto planeDistance = (PlaneGroups[j].plane.XYZ() | point) - PlaneGroups[j].plane.W;
|
||||||
|
|
||||||
float dist = std::abs(planeDistance);
|
float dist = std::abs(planeDistance);
|
||||||
if (dist <= 0.01f)
|
if (dist <= 0.01f)
|
||||||
{
|
{
|
||||||
smoothingGroupIndex = (int)j;
|
planeGroupIndex = (int)j;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Surface is in a new plane. Create a smoothing group for it
|
// Surface is in a new plane. Create a plane group for it
|
||||||
if (smoothingGroupIndex == -1)
|
if (planeGroupIndex == -1)
|
||||||
{
|
{
|
||||||
smoothingGroupIndex = SmoothingGroups.Size();
|
planeGroupIndex = PlaneGroups.Size();
|
||||||
|
|
||||||
LevelMeshSmoothingGroup group;
|
LevelMeshPlaneGroup group;
|
||||||
group.plane = surface->plane;
|
group.plane = surface->Plane;
|
||||||
group.sectorGroup = surface->sectorGroup;
|
group.sectorGroup = surface->SectorGroup;
|
||||||
SmoothingGroups.Push(group);
|
PlaneGroups.Push(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
SmoothingGroups[smoothingGroupIndex].surfaces.push_back(surface);
|
PlaneGroups[planeGroupIndex].surfaces.push_back(surface);
|
||||||
SmoothingGroupIndexes.Push(smoothingGroupIndex);
|
PlaneGroupIndexes.Push(planeGroupIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& tile : LightmapTiles)
|
||||||
|
tile.Surfaces.Clear();
|
||||||
|
|
||||||
for (int i = 0, count = GetSurfaceCount(); i < count; i++)
|
for (int i = 0, count = GetSurfaceCount(); i < count; i++)
|
||||||
{
|
{
|
||||||
auto targetSurface = GetSurface(i);
|
LevelMeshSurface* targetSurface = GetSurface(i);
|
||||||
targetSurface->tileSurfaces.Clear();
|
if (targetSurface->LightmapTileIndex < 0)
|
||||||
for (LevelMeshSurface* surface : SmoothingGroups[SmoothingGroupIndexes[i]].surfaces)
|
continue;
|
||||||
|
LightmapTile* tile = &LightmapTiles[targetSurface->LightmapTileIndex];
|
||||||
|
for (LevelMeshSurface* surface : PlaneGroups[PlaneGroupIndexes[i]].surfaces)
|
||||||
{
|
{
|
||||||
FVector2 minUV = ToUV(surface->bounds.min, targetSurface);
|
FVector2 minUV = tile->ToUV(surface->Bounds.min);
|
||||||
FVector2 maxUV = ToUV(surface->bounds.max, targetSurface);
|
FVector2 maxUV = tile->ToUV(surface->Bounds.max);
|
||||||
if (surface != targetSurface && (maxUV.X < 0.0f || maxUV.Y < 0.0f || minUV.X > 1.0f || minUV.Y > 1.0f))
|
if (surface != targetSurface && (maxUV.X < 0.0f || maxUV.Y < 0.0f || minUV.X > 1.0f || minUV.Y > 1.0f))
|
||||||
continue; // Bounding box not visible
|
continue; // Bounding box not visible
|
||||||
|
|
||||||
targetSurface->tileSurfaces.Push(surface);
|
tile->Surfaces.Push(surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FVector2 LevelSubmesh::ToUV(const FVector3& vert, const LevelMeshSurface* targetSurface)
|
|
||||||
{
|
|
||||||
FVector3 localPos = vert - targetSurface->translateWorldToLocal;
|
|
||||||
float u = (1.0f + (localPos | targetSurface->projLocalToU)) / (targetSurface->AtlasTile.Width + 2);
|
|
||||||
float v = (1.0f + (localPos | targetSurface->projLocalToV)) / (targetSurface->AtlasTile.Height + 2);
|
|
||||||
return FVector2(u, v);
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,214 +3,73 @@
|
||||||
|
|
||||||
#include "framework/tarray.h"
|
#include "framework/tarray.h"
|
||||||
#include "framework/vectors.h"
|
#include "framework/vectors.h"
|
||||||
#include "framework/matrix.h"
|
|
||||||
#include "framework/bounds.h"
|
|
||||||
#include "framework/textureid.h"
|
|
||||||
#include "hw_collision.h"
|
#include "hw_collision.h"
|
||||||
|
#include "flatvertices.h"
|
||||||
|
#include "hw_levelmeshlight.h"
|
||||||
|
#include "hw_levelmeshportal.h"
|
||||||
|
#include "hw_lightmaptile.h"
|
||||||
|
#include "hw_levelmeshsurface.h"
|
||||||
|
#include "hw_materialstate.h"
|
||||||
|
#include "hw_surfaceuniforms.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include <dp_rect_pack/dp_rect_pack.h>
|
struct LevelMeshTileStats;
|
||||||
|
|
||||||
typedef dp::rect_pack::RectPacker<int> RectPacker;
|
struct LevelSubmeshDrawRange
|
||||||
|
|
||||||
class LevelSubmesh;
|
|
||||||
|
|
||||||
class LevelMeshLight
|
|
||||||
{
|
{
|
||||||
public:
|
int PipelineID;
|
||||||
FVector3 Origin;
|
int Start;
|
||||||
FVector3 RelativeOrigin;
|
int Count;
|
||||||
float Radius;
|
|
||||||
float Intensity;
|
|
||||||
float InnerAngleCos;
|
|
||||||
float OuterAngleCos;
|
|
||||||
FVector3 SpotDir;
|
|
||||||
FVector3 Color;
|
|
||||||
int SectorGroup;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LevelMeshSurface
|
|
||||||
{
|
|
||||||
LevelSubmesh* Submesh = nullptr;
|
|
||||||
|
|
||||||
int numVerts = 0;
|
|
||||||
unsigned int startVertIndex = 0;
|
|
||||||
unsigned int startUvIndex = 0;
|
|
||||||
unsigned int startElementIndex = 0;
|
|
||||||
unsigned int numElements = 0;
|
|
||||||
FVector4 plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f);
|
|
||||||
bool bSky = false;
|
|
||||||
|
|
||||||
// Surface location in lightmap texture
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
int X = 0;
|
|
||||||
int Y = 0;
|
|
||||||
int Width = 0;
|
|
||||||
int Height = 0;
|
|
||||||
int ArrayIndex = 0;
|
|
||||||
} AtlasTile;
|
|
||||||
|
|
||||||
// True if the surface needs to be rendered into the lightmap texture before it can be used
|
|
||||||
bool needsUpdate = true;
|
|
||||||
|
|
||||||
FTextureID texture = FNullTextureID();
|
|
||||||
float alpha = 1.0;
|
|
||||||
|
|
||||||
int portalIndex = 0;
|
|
||||||
int sectorGroup = 0;
|
|
||||||
|
|
||||||
BBox bounds;
|
|
||||||
uint16_t sampleDimension = 0;
|
|
||||||
|
|
||||||
// Calculate world coordinates to UV coordinates
|
|
||||||
FVector3 translateWorldToLocal = { 0.f, 0.f, 0.f };
|
|
||||||
FVector3 projLocalToU = { 0.f, 0.f, 0.f };
|
|
||||||
FVector3 projLocalToV = { 0.f, 0.f, 0.f };
|
|
||||||
|
|
||||||
// Surfaces that are visible within the lightmap tile
|
|
||||||
TArray<LevelMeshSurface*> tileSurfaces;
|
|
||||||
|
|
||||||
uint32_t Area() const { return AtlasTile.Width * AtlasTile.Height; }
|
|
||||||
|
|
||||||
// Light list location in the lightmapper GPU buffers
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
int Pos = -1;
|
|
||||||
int Count = 0;
|
|
||||||
int ResetCounter = -1;
|
|
||||||
} LightList;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline float IsInFrontOfPlane(const FVector4& plane, const FVector3& point)
|
|
||||||
{
|
|
||||||
return (plane.X * point.X + plane.Y * point.Y + plane.Z * point.Z) >= plane.W;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LevelMeshSmoothingGroup
|
|
||||||
{
|
|
||||||
FVector4 plane = FVector4(0, 0, 1, 0);
|
|
||||||
int sectorGroup = 0;
|
|
||||||
std::vector<LevelMeshSurface*> surfaces;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LevelMeshPortal
|
|
||||||
{
|
|
||||||
LevelMeshPortal() { transformation.loadIdentity(); }
|
|
||||||
|
|
||||||
VSMatrix transformation;
|
|
||||||
|
|
||||||
int sourceSectorGroup = 0;
|
|
||||||
int targetSectorGroup = 0;
|
|
||||||
|
|
||||||
inline FVector3 TransformPosition(const FVector3& pos) const
|
|
||||||
{
|
|
||||||
auto v = transformation * FVector4(pos, 1.0);
|
|
||||||
return FVector3(v.X, v.Y, v.Z);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FVector3 TransformRotation(const FVector3& dir) const
|
|
||||||
{
|
|
||||||
auto v = transformation * FVector4(dir, 0.0);
|
|
||||||
return FVector3(v.X, v.Y, v.Z);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks only transformation
|
|
||||||
inline bool IsInverseTransformationPortal(const LevelMeshPortal& portal) const
|
|
||||||
{
|
|
||||||
auto diff = portal.TransformPosition(TransformPosition(FVector3(0, 0, 0)));
|
|
||||||
return abs(diff.X) < 0.001 && abs(diff.Y) < 0.001 && abs(diff.Z) < 0.001;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks only transformation
|
|
||||||
inline bool IsEqualTransformationPortal(const LevelMeshPortal& portal) const
|
|
||||||
{
|
|
||||||
auto diff = portal.TransformPosition(FVector3(0, 0, 0)) - TransformPosition(FVector3(0, 0, 0));
|
|
||||||
return (abs(diff.X) < 0.001 && abs(diff.Y) < 0.001 && abs(diff.Z) < 0.001);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks transformation, source and destiantion sector groups
|
|
||||||
inline bool IsEqualPortal(const LevelMeshPortal& portal) const
|
|
||||||
{
|
|
||||||
return sourceSectorGroup == portal.sourceSectorGroup && targetSectorGroup == portal.targetSectorGroup && IsEqualTransformationPortal(portal);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks transformation, source and destiantion sector groups
|
|
||||||
inline bool IsInversePortal(const LevelMeshPortal& portal) const
|
|
||||||
{
|
|
||||||
return sourceSectorGroup == portal.targetSectorGroup && targetSectorGroup == portal.sourceSectorGroup && IsInverseTransformationPortal(portal);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// for use with std::set to recursively go through portals and skip returning portals
|
|
||||||
struct RecursivePortalComparator
|
|
||||||
{
|
|
||||||
bool operator()(const LevelMeshPortal& a, const LevelMeshPortal& b) const
|
|
||||||
{
|
|
||||||
return !a.IsInversePortal(b) && std::memcmp(&a.transformation, &b.transformation, sizeof(VSMatrix)) < 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// for use with std::map to reject portals which have the same effect for light rays
|
|
||||||
struct IdenticalPortalComparator
|
|
||||||
{
|
|
||||||
bool operator()(const LevelMeshPortal& a, const LevelMeshPortal& b) const
|
|
||||||
{
|
|
||||||
return !a.IsEqualPortal(b) && std::memcmp(&a.transformation, &b.transformation, sizeof(VSMatrix)) < 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LevelMeshSurfaceStats
|
|
||||||
{
|
|
||||||
struct Stats
|
|
||||||
{
|
|
||||||
uint32_t total = 0, dirty = 0, sky = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
Stats surfaces, pixels;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class LevelSubmesh
|
class LevelSubmesh
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LevelSubmesh();
|
LevelSubmesh();
|
||||||
|
|
||||||
virtual ~LevelSubmesh() = default;
|
virtual ~LevelSubmesh() = default;
|
||||||
|
|
||||||
virtual LevelMeshSurface* GetSurface(int index) { return nullptr; }
|
virtual LevelMeshSurface* GetSurface(int index) { return nullptr; }
|
||||||
virtual unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const { return 0xffffffff; }
|
virtual unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const { return 0xffffffff; }
|
||||||
virtual int GetSurfaceCount() { return 0; }
|
virtual int GetSurfaceCount() { return 0; }
|
||||||
|
|
||||||
TArray<FVector3> MeshVertices;
|
struct
|
||||||
TArray<FVector2> MeshVertexUVs;
|
{
|
||||||
TArray<uint32_t> MeshElements;
|
TArray<FFlatVertex> Vertices;
|
||||||
TArray<int> MeshSurfaceIndexes;
|
TArray<uint32_t> Indexes;
|
||||||
|
TArray<int> SurfaceIndexes;
|
||||||
TArray<LevelMeshPortal> Portals;
|
TArray<int> UniformIndexes;
|
||||||
|
TArray<SurfaceUniforms> Uniforms;
|
||||||
|
TArray<FMaterialState> Materials;
|
||||||
|
} Mesh;
|
||||||
|
|
||||||
std::unique_ptr<TriangleMeshShape> Collision;
|
std::unique_ptr<TriangleMeshShape> Collision;
|
||||||
|
|
||||||
|
TArray<LevelSubmeshDrawRange> DrawList;
|
||||||
|
TArray<LevelSubmeshDrawRange> PortalList;
|
||||||
|
|
||||||
// Lightmap atlas
|
// Lightmap atlas
|
||||||
int LMTextureCount = 0;
|
int LMTextureCount = 0;
|
||||||
int LMTextureSize = 0;
|
int LMTextureSize = 1024;
|
||||||
TArray<uint16_t> LMTextureData;
|
TArray<uint16_t> LMTextureData;
|
||||||
|
|
||||||
uint16_t LightmapSampleDistance = 16;
|
uint16_t LightmapSampleDistance = 16;
|
||||||
|
|
||||||
|
TArray<LightmapTile> LightmapTiles;
|
||||||
|
|
||||||
uint32_t AtlasPixelCount() const { return uint32_t(LMTextureCount * LMTextureSize * LMTextureSize); }
|
uint32_t AtlasPixelCount() const { return uint32_t(LMTextureCount * LMTextureSize * LMTextureSize); }
|
||||||
|
|
||||||
void UpdateCollision();
|
void UpdateCollision();
|
||||||
void GatherSurfacePixelStats(LevelMeshSurfaceStats& stats);
|
void GatherTilePixelStats(LevelMeshTileStats& stats);
|
||||||
void BuildTileSurfaceLists();
|
void BuildTileSurfaceLists();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FVector2 ToUV(const FVector3& vert, const LevelMeshSurface* targetSurface);
|
FVector2 ToUV(const FVector3& vert, const LightmapTile* tile);
|
||||||
};
|
};
|
||||||
|
|
||||||
class LevelMesh
|
class LevelMesh
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
LevelMesh();
|
||||||
virtual ~LevelMesh() = default;
|
virtual ~LevelMesh() = default;
|
||||||
|
|
||||||
std::unique_ptr<LevelSubmesh> StaticMesh = std::make_unique<LevelSubmesh>();
|
std::unique_ptr<LevelSubmesh> StaticMesh = std::make_unique<LevelSubmesh>();
|
||||||
|
@ -220,9 +79,21 @@ public:
|
||||||
|
|
||||||
LevelMeshSurface* Trace(const FVector3& start, FVector3 direction, float maxDist);
|
LevelMeshSurface* Trace(const FVector3& start, FVector3 direction, float maxDist);
|
||||||
|
|
||||||
LevelMeshSurfaceStats GatherSurfacePixelStats();
|
LevelMeshTileStats GatherTilePixelStats();
|
||||||
|
|
||||||
// Map defaults
|
// Map defaults
|
||||||
FVector3 SunDirection = FVector3(0.0f, 0.0f, -1.0f);
|
FVector3 SunDirection = FVector3(0.0f, 0.0f, -1.0f);
|
||||||
FVector3 SunColor = FVector3(0.0f, 0.0f, 0.0f);
|
FVector3 SunColor = FVector3(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
TArray<LevelMeshPortal> Portals;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LevelMeshTileStats
|
||||||
|
{
|
||||||
|
struct Stats
|
||||||
|
{
|
||||||
|
uint32_t total = 0, dirty = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Stats tiles, pixels;
|
||||||
};
|
};
|
||||||
|
|
18
src/lightmapper/hw_levelmeshlight.h
Normal file
18
src/lightmapper/hw_levelmeshlight.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "framework/vectors.h"
|
||||||
|
|
||||||
|
class LevelMeshLight
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FVector3 Origin;
|
||||||
|
FVector3 RelativeOrigin;
|
||||||
|
float Radius;
|
||||||
|
float Intensity;
|
||||||
|
float InnerAngleCos;
|
||||||
|
float OuterAngleCos;
|
||||||
|
FVector3 SpotDir;
|
||||||
|
FVector3 Color;
|
||||||
|
int SectorGroup;
|
||||||
|
};
|
72
src/lightmapper/hw_levelmeshportal.h
Normal file
72
src/lightmapper/hw_levelmeshportal.h
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include "framework/vectors.h"
|
||||||
|
#include "framework/matrix.h"
|
||||||
|
|
||||||
|
struct LevelMeshPortal
|
||||||
|
{
|
||||||
|
LevelMeshPortal() { transformation.loadIdentity(); }
|
||||||
|
|
||||||
|
VSMatrix transformation;
|
||||||
|
|
||||||
|
int sourceSectorGroup = 0;
|
||||||
|
int targetSectorGroup = 0;
|
||||||
|
|
||||||
|
inline FVector3 TransformPosition(const FVector3& pos) const
|
||||||
|
{
|
||||||
|
auto v = transformation * FVector4(pos, 1.0);
|
||||||
|
return FVector3(v.X, v.Y, v.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FVector3 TransformRotation(const FVector3& dir) const
|
||||||
|
{
|
||||||
|
auto v = transformation * FVector4(dir, 0.0);
|
||||||
|
return FVector3(v.X, v.Y, v.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks only transformation
|
||||||
|
inline bool IsInverseTransformationPortal(const LevelMeshPortal& portal) const
|
||||||
|
{
|
||||||
|
auto diff = portal.TransformPosition(TransformPosition(FVector3(0, 0, 0)));
|
||||||
|
return abs(diff.X) < 0.001 && abs(diff.Y) < 0.001 && abs(diff.Z) < 0.001;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks only transformation
|
||||||
|
inline bool IsEqualTransformationPortal(const LevelMeshPortal& portal) const
|
||||||
|
{
|
||||||
|
auto diff = portal.TransformPosition(FVector3(0, 0, 0)) - TransformPosition(FVector3(0, 0, 0));
|
||||||
|
return (abs(diff.X) < 0.001 && abs(diff.Y) < 0.001 && abs(diff.Z) < 0.001);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks transformation, source and destiantion sector groups
|
||||||
|
inline bool IsEqualPortal(const LevelMeshPortal& portal) const
|
||||||
|
{
|
||||||
|
return sourceSectorGroup == portal.sourceSectorGroup && targetSectorGroup == portal.targetSectorGroup && IsEqualTransformationPortal(portal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks transformation, source and destiantion sector groups
|
||||||
|
inline bool IsInversePortal(const LevelMeshPortal& portal) const
|
||||||
|
{
|
||||||
|
return sourceSectorGroup == portal.targetSectorGroup && targetSectorGroup == portal.sourceSectorGroup && IsInverseTransformationPortal(portal);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// for use with std::set to recursively go through portals and skip returning portals
|
||||||
|
struct RecursivePortalComparator
|
||||||
|
{
|
||||||
|
bool operator()(const LevelMeshPortal& a, const LevelMeshPortal& b) const
|
||||||
|
{
|
||||||
|
return !a.IsInversePortal(b) && std::memcmp(&a.transformation, &b.transformation, sizeof(VSMatrix)) < 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// for use with std::map to reject portals which have the same effect for light rays
|
||||||
|
struct IdenticalPortalComparator
|
||||||
|
{
|
||||||
|
bool operator()(const LevelMeshPortal& a, const LevelMeshPortal& b) const
|
||||||
|
{
|
||||||
|
return !a.IsEqualPortal(b) && std::memcmp(&a.transformation, &b.transformation, sizeof(VSMatrix)) < 0;
|
||||||
|
}
|
||||||
|
};
|
45
src/lightmapper/hw_levelmeshsurface.h
Normal file
45
src/lightmapper/hw_levelmeshsurface.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "framework/tarray.h"
|
||||||
|
#include "framework/vectors.h"
|
||||||
|
#include "framework/matrix.h"
|
||||||
|
#include "framework/bounds.h"
|
||||||
|
#include "framework/textureid.h"
|
||||||
|
|
||||||
|
class LevelSubmesh;
|
||||||
|
struct LevelMeshSurface;
|
||||||
|
|
||||||
|
struct LevelMeshSurface
|
||||||
|
{
|
||||||
|
LevelSubmesh* Submesh = nullptr;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned int StartVertIndex = 0;
|
||||||
|
int NumVerts = 0;
|
||||||
|
unsigned int StartElementIndex = 0;
|
||||||
|
unsigned int NumElements = 0;
|
||||||
|
} MeshLocation;
|
||||||
|
|
||||||
|
BBox Bounds;
|
||||||
|
FVector4 Plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
int LightmapTileIndex = -1;
|
||||||
|
|
||||||
|
bool AlwaysUpdate = false;
|
||||||
|
|
||||||
|
FTextureID Texture = FNullTextureID();
|
||||||
|
float Alpha = 1.0;
|
||||||
|
|
||||||
|
bool IsSky = false;
|
||||||
|
int PortalIndex = 0;
|
||||||
|
int SectorGroup = 0;
|
||||||
|
|
||||||
|
// Light list location in the lightmapper GPU buffers
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int Pos = -1;
|
||||||
|
int Count = 0;
|
||||||
|
int ResetCounter = -1;
|
||||||
|
} LightList;
|
||||||
|
};
|
72
src/lightmapper/hw_lightmaptile.h
Normal file
72
src/lightmapper/hw_lightmaptile.h
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "framework/tarray.h"
|
||||||
|
#include "framework/vectors.h"
|
||||||
|
#include "framework/bounds.h"
|
||||||
|
|
||||||
|
struct LevelMeshSurface;
|
||||||
|
|
||||||
|
struct LightmapTileBinding
|
||||||
|
{
|
||||||
|
uint32_t Type = 0;
|
||||||
|
uint32_t TypeIndex = 0;
|
||||||
|
uint32_t ControlSector = 0xffffffff;
|
||||||
|
|
||||||
|
bool operator<(const LightmapTileBinding& other) const
|
||||||
|
{
|
||||||
|
if (TypeIndex != other.TypeIndex) return TypeIndex < other.TypeIndex;
|
||||||
|
if (ControlSector != other.ControlSector) return ControlSector < other.ControlSector;
|
||||||
|
return Type < other.Type;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LightmapTile
|
||||||
|
{
|
||||||
|
// Surface location in lightmap texture
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int X = 0;
|
||||||
|
int Y = 0;
|
||||||
|
int Width = 0;
|
||||||
|
int Height = 0;
|
||||||
|
int ArrayIndex = 0;
|
||||||
|
uint32_t Area() const { return Width * Height; }
|
||||||
|
} AtlasLocation;
|
||||||
|
|
||||||
|
// Calculate world coordinates to UV coordinates
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
FVector3 TranslateWorldToLocal = { 0.0f, 0.0f, 0.0f };
|
||||||
|
FVector3 ProjLocalToU = { 0.0f, 0.0f, 0.0f };
|
||||||
|
FVector3 ProjLocalToV = { 0.0f, 0.0f, 0.0f };
|
||||||
|
} Transform;
|
||||||
|
|
||||||
|
LightmapTileBinding Binding;
|
||||||
|
|
||||||
|
// Surfaces that are visible within the lightmap tile
|
||||||
|
TArray<LevelMeshSurface*> Surfaces;
|
||||||
|
|
||||||
|
BBox Bounds;
|
||||||
|
uint16_t SampleDimension = 0;
|
||||||
|
FVector4 Plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
// True if the tile needs to be rendered into the lightmap texture before it can be used
|
||||||
|
bool NeedsUpdate = true;
|
||||||
|
|
||||||
|
FVector2 ToUV(const FVector3& vert) const
|
||||||
|
{
|
||||||
|
FVector3 localPos = vert - Transform.TranslateWorldToLocal;
|
||||||
|
float u = (1.0f + (localPos | Transform.ProjLocalToU)) / (AtlasLocation.Width + 2);
|
||||||
|
float v = (1.0f + (localPos | Transform.ProjLocalToV)) / (AtlasLocation.Height + 2);
|
||||||
|
return FVector2(u, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
FVector2 ToUV(const FVector3& vert, float textureSize) const
|
||||||
|
{
|
||||||
|
FVector3 localPos = vert - Transform.TranslateWorldToLocal;
|
||||||
|
float u = (AtlasLocation.X + (localPos | Transform.ProjLocalToU)) / textureSize;
|
||||||
|
float v = (AtlasLocation.Y + (localPos | Transform.ProjLocalToV)) / textureSize;
|
||||||
|
return FVector2(u, v);
|
||||||
|
}
|
||||||
|
};
|
37
src/lightmapper/hw_materialstate.h
Normal file
37
src/lightmapper/hw_materialstate.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CLAMP_NONE = 0,
|
||||||
|
CLAMP_X,
|
||||||
|
CLAMP_Y,
|
||||||
|
CLAMP_XY,
|
||||||
|
CLAMP_XY_NOMIP,
|
||||||
|
CLAMP_NOFILTER,
|
||||||
|
CLAMP_NOFILTER_X,
|
||||||
|
CLAMP_NOFILTER_Y,
|
||||||
|
CLAMP_NOFILTER_XY,
|
||||||
|
CLAMP_CAMTEX,
|
||||||
|
NUMSAMPLERS
|
||||||
|
};
|
||||||
|
|
||||||
|
class FMaterial;
|
||||||
|
|
||||||
|
struct FMaterialState
|
||||||
|
{
|
||||||
|
FMaterial* mMaterial = nullptr;
|
||||||
|
int mClampMode;
|
||||||
|
int mTranslation;
|
||||||
|
int mOverrideShader;
|
||||||
|
bool mChanged;
|
||||||
|
|
||||||
|
void Reset()
|
||||||
|
{
|
||||||
|
mMaterial = nullptr;
|
||||||
|
mTranslation = 0;
|
||||||
|
mClampMode = CLAMP_NONE;
|
||||||
|
mOverrideShader = -1;
|
||||||
|
mChanged = false;
|
||||||
|
}
|
||||||
|
};
|
49
src/lightmapper/hw_surfaceuniforms.h
Normal file
49
src/lightmapper/hw_surfaceuniforms.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "framework/vectors.h"
|
||||||
|
|
||||||
|
struct SurfaceUniforms
|
||||||
|
{
|
||||||
|
FVector4 uObjectColor;
|
||||||
|
FVector4 uObjectColor2;
|
||||||
|
FVector4 uDynLightColor;
|
||||||
|
FVector4 uAddColor;
|
||||||
|
FVector4 uTextureAddColor;
|
||||||
|
FVector4 uTextureModulateColor;
|
||||||
|
FVector4 uTextureBlendColor;
|
||||||
|
FVector4 uFogColor;
|
||||||
|
float uDesaturationFactor; // HWDrawInfo::SetColor
|
||||||
|
float uInterpolationFactor;
|
||||||
|
float timer;
|
||||||
|
int useVertexData;
|
||||||
|
FVector4 uVertexColor; // HWDrawInfo::SetColor
|
||||||
|
FVector4 uVertexNormal;
|
||||||
|
|
||||||
|
FVector4 uGlowTopPlane;
|
||||||
|
FVector4 uGlowTopColor;
|
||||||
|
FVector4 uGlowBottomPlane;
|
||||||
|
FVector4 uGlowBottomColor;
|
||||||
|
|
||||||
|
FVector4 uGradientTopPlane;
|
||||||
|
FVector4 uGradientBottomPlane;
|
||||||
|
|
||||||
|
FVector4 uSplitTopPlane;
|
||||||
|
FVector4 uSplitBottomPlane;
|
||||||
|
|
||||||
|
FVector4 uDetailParms;
|
||||||
|
FVector4 uNpotEmulation;
|
||||||
|
|
||||||
|
FVector2 uClipSplit;
|
||||||
|
FVector2 uSpecularMaterial;
|
||||||
|
|
||||||
|
float uLightLevel; // HWDrawInfo::SetColor
|
||||||
|
float uFogDensity;
|
||||||
|
float uLightFactor;
|
||||||
|
float uLightDist;
|
||||||
|
|
||||||
|
float uAlphaThreshold;
|
||||||
|
int uTextureIndex;
|
||||||
|
float padding2;
|
||||||
|
float padding3;
|
||||||
|
};
|
File diff suppressed because it is too large
Load diff
|
@ -31,17 +31,10 @@ struct SurfaceInfo
|
||||||
{
|
{
|
||||||
FVector3 Normal;
|
FVector3 Normal;
|
||||||
float Sky;
|
float Sky;
|
||||||
float SamplingDistance;
|
|
||||||
uint32_t PortalIndex;
|
uint32_t PortalIndex;
|
||||||
int32_t TextureIndex;
|
int32_t TextureIndex;
|
||||||
float Alpha;
|
float Alpha;
|
||||||
};
|
float Padding;
|
||||||
|
|
||||||
struct SurfaceVertex
|
|
||||||
{
|
|
||||||
FVector4 pos;
|
|
||||||
FVector2 uv;
|
|
||||||
float Padding1, Padding2;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PortalInfo
|
struct PortalInfo
|
||||||
|
@ -49,37 +42,44 @@ struct PortalInfo
|
||||||
VSMatrix transformation;
|
VSMatrix transformation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SubmeshBufferRange
|
||||||
|
{
|
||||||
|
int Offset = 0;
|
||||||
|
int Size = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct SubmeshBufferLocation
|
struct SubmeshBufferLocation
|
||||||
{
|
{
|
||||||
LevelSubmesh* Submesh = nullptr;
|
LevelSubmesh* Submesh = nullptr;
|
||||||
int VertexOffset = 0;
|
SubmeshBufferRange Vertex;
|
||||||
int VertexSize = 0;
|
SubmeshBufferRange Index;
|
||||||
int IndexOffset = 0;
|
SubmeshBufferRange Node;
|
||||||
int IndexSize = 0;
|
SubmeshBufferRange SurfaceIndex;
|
||||||
int NodeOffset = 0;
|
SubmeshBufferRange Surface;
|
||||||
int NodeSize = 0;
|
SubmeshBufferRange UniformIndexes;
|
||||||
int SurfaceIndexOffset = 0;
|
SubmeshBufferRange Uniforms;
|
||||||
int SurfaceIndexSize = 0;
|
|
||||||
int SurfaceOffset = 0;
|
|
||||||
int SurfaceSize = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class VkRaytrace
|
class VkLevelMesh
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VkRaytrace(VulkanRenderDevice* fb);
|
VkLevelMesh(VulkanRenderDevice* fb);
|
||||||
|
|
||||||
void SetLevelMesh(LevelMesh* mesh);
|
void SetLevelMesh(LevelMesh* mesh);
|
||||||
void BeginFrame();
|
void BeginFrame();
|
||||||
|
|
||||||
VulkanAccelerationStructure* GetAccelStruct() { return TopLevelAS.AccelStruct.get(); }
|
VulkanAccelerationStructure* GetAccelStruct() { return TopLevelAS.AccelStruct.get(); }
|
||||||
VulkanBuffer* GetVertexBuffer() { return VertexBuffer.get(); }
|
VulkanBuffer* GetVertexBuffer() { return VertexBuffer.get(); }
|
||||||
|
VulkanBuffer* GetUniformIndexBuffer() { return UniformIndexBuffer.get(); }
|
||||||
VulkanBuffer* GetIndexBuffer() { return IndexBuffer.get(); }
|
VulkanBuffer* GetIndexBuffer() { return IndexBuffer.get(); }
|
||||||
VulkanBuffer* GetNodeBuffer() { return NodeBuffer.get(); }
|
VulkanBuffer* GetNodeBuffer() { return NodeBuffer.get(); }
|
||||||
VulkanBuffer* GetSurfaceIndexBuffer() { return SurfaceIndexBuffer.get(); }
|
VulkanBuffer* GetSurfaceIndexBuffer() { return SurfaceIndexBuffer.get(); }
|
||||||
VulkanBuffer* GetSurfaceBuffer() { return SurfaceBuffer.get(); }
|
VulkanBuffer* GetSurfaceBuffer() { return SurfaceBuffer.get(); }
|
||||||
|
VulkanBuffer* GetUniformsBuffer() { return UniformsBuffer.get(); }
|
||||||
VulkanBuffer* GetPortalBuffer() { return PortalBuffer.get(); }
|
VulkanBuffer* GetPortalBuffer() { return PortalBuffer.get(); }
|
||||||
|
|
||||||
|
LevelMesh* GetMesh() { return Mesh; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct BLAS
|
struct BLAS
|
||||||
{
|
{
|
||||||
|
@ -93,9 +93,11 @@ private:
|
||||||
void CreateBuffers();
|
void CreateBuffers();
|
||||||
void CreateStaticBLAS();
|
void CreateStaticBLAS();
|
||||||
void CreateDynamicBLAS();
|
void CreateDynamicBLAS();
|
||||||
|
void CreateTLASInstanceBuffer();
|
||||||
void CreateTopLevelAS();
|
void CreateTopLevelAS();
|
||||||
|
|
||||||
void UploadMeshes(bool dynamicOnly);
|
void UploadMeshes(bool dynamicOnly);
|
||||||
void UpdateDynamicBLAS();
|
void UploadTLASInstanceBuffer();
|
||||||
void UpdateTopLevelAS();
|
void UpdateTopLevelAS();
|
||||||
|
|
||||||
BLAS CreateBLAS(LevelSubmesh *submesh, bool preferFastBuild, int vertexOffset, int indexOffset);
|
BLAS CreateBLAS(LevelSubmesh *submesh, bool preferFastBuild, int vertexOffset, int indexOffset);
|
||||||
|
@ -104,6 +106,7 @@ private:
|
||||||
int GetMaxIndexBufferSize();
|
int GetMaxIndexBufferSize();
|
||||||
int GetMaxNodeBufferSize();
|
int GetMaxNodeBufferSize();
|
||||||
int GetMaxSurfaceBufferSize();
|
int GetMaxSurfaceBufferSize();
|
||||||
|
int GetMaxUniformsBufferSize();
|
||||||
int GetMaxSurfaceIndexBufferSize();
|
int GetMaxSurfaceIndexBufferSize();
|
||||||
|
|
||||||
VulkanRenderDevice* fb = nullptr;
|
VulkanRenderDevice* fb = nullptr;
|
||||||
|
@ -114,17 +117,20 @@ private:
|
||||||
LevelMesh* Mesh = nullptr;
|
LevelMesh* Mesh = nullptr;
|
||||||
|
|
||||||
std::unique_ptr<VulkanBuffer> VertexBuffer;
|
std::unique_ptr<VulkanBuffer> VertexBuffer;
|
||||||
|
std::unique_ptr<VulkanBuffer> UniformIndexBuffer;
|
||||||
std::unique_ptr<VulkanBuffer> IndexBuffer;
|
std::unique_ptr<VulkanBuffer> IndexBuffer;
|
||||||
std::unique_ptr<VulkanBuffer> SurfaceIndexBuffer;
|
std::unique_ptr<VulkanBuffer> SurfaceIndexBuffer;
|
||||||
std::unique_ptr<VulkanBuffer> SurfaceBuffer;
|
std::unique_ptr<VulkanBuffer> SurfaceBuffer;
|
||||||
|
std::unique_ptr<VulkanBuffer> UniformsBuffer;
|
||||||
std::unique_ptr<VulkanBuffer> PortalBuffer;
|
std::unique_ptr<VulkanBuffer> PortalBuffer;
|
||||||
|
|
||||||
std::unique_ptr<VulkanBuffer> NodeBuffer;
|
std::unique_ptr<VulkanBuffer> NodeBuffer;
|
||||||
|
|
||||||
TArray<SurfaceVertex> Vertices;
|
TArray<FFlatVertex> Vertices;
|
||||||
static const int MaxDynamicVertices = 100'000;
|
static const int MaxDynamicVertices = 100'000;
|
||||||
static const int MaxDynamicIndexes = 100'000;
|
static const int MaxDynamicIndexes = 100'000;
|
||||||
static const int MaxDynamicSurfaces = 100'000;
|
static const int MaxDynamicSurfaces = 100'000;
|
||||||
|
static const int MaxDynamicUniforms = 100'000;
|
||||||
static const int MaxDynamicSurfaceIndexes = 25'000;
|
static const int MaxDynamicSurfaceIndexes = 25'000;
|
||||||
static const int MaxDynamicNodes = 10'000;
|
static const int MaxDynamicNodes = 10'000;
|
||||||
|
|
||||||
|
@ -139,4 +145,38 @@ private:
|
||||||
std::unique_ptr<VulkanBuffer> AccelStructBuffer;
|
std::unique_ptr<VulkanBuffer> AccelStructBuffer;
|
||||||
std::unique_ptr<VulkanAccelerationStructure> AccelStruct;
|
std::unique_ptr<VulkanAccelerationStructure> AccelStruct;
|
||||||
} TopLevelAS;
|
} TopLevelAS;
|
||||||
|
|
||||||
|
friend class VkLevelMeshUploader;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VkLevelMeshUploader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VkLevelMeshUploader(VkLevelMesh* mesh);
|
||||||
|
|
||||||
|
void Upload(bool dynamicOnly);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void BeginTransfer(size_t transferBufferSize);
|
||||||
|
void EndTransfer(size_t transferBufferSize);
|
||||||
|
void UploadNodes();
|
||||||
|
void UploadVertices();
|
||||||
|
void UploadUniformIndexes();
|
||||||
|
void UploadIndexes();
|
||||||
|
void UploadSurfaceIndexes();
|
||||||
|
void UploadSurfaces();
|
||||||
|
void UploadUniforms();
|
||||||
|
void UploadPortals();
|
||||||
|
void UpdateSizes();
|
||||||
|
void UpdateLocations();
|
||||||
|
size_t GetTransferSize();
|
||||||
|
|
||||||
|
VkLevelMesh* Mesh;
|
||||||
|
TArray<SubmeshBufferLocation> locations;
|
||||||
|
unsigned int start = 0;
|
||||||
|
unsigned int end = 0;
|
||||||
|
uint8_t* data = nullptr;
|
||||||
|
size_t datapos = 0;
|
||||||
|
VulkanCommandBuffer* cmdbuffer = nullptr;
|
||||||
|
std::unique_ptr<VulkanBuffer> transferBuffer;
|
||||||
};
|
};
|
|
@ -1,10 +1,8 @@
|
||||||
|
|
||||||
#include "vk_lightmap.h"
|
#include "vk_lightmapper.h"
|
||||||
#include "vk_renderdevice.h"
|
#include "vk_renderdevice.h"
|
||||||
#include "vk_raytrace.h"
|
#include "vk_levelmesh.h"
|
||||||
#include "zvulkan/vulkanbuilders.h"
|
#include "zvulkan/vulkanbuilders.h"
|
||||||
#include "framework/halffloat.h"
|
|
||||||
#include "framework/zstring.h"
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "glsl/binding_lightmapper.glsl.h"
|
#include "glsl/binding_lightmapper.glsl.h"
|
||||||
|
@ -22,7 +20,6 @@
|
||||||
#include "glsl/vert_copy.glsl.h"
|
#include "glsl/vert_copy.glsl.h"
|
||||||
#include "glsl/vert_raytrace.glsl.h"
|
#include "glsl/vert_raytrace.glsl.h"
|
||||||
#include "glsl/vert_screenquad.glsl.h"
|
#include "glsl/vert_screenquad.glsl.h"
|
||||||
|
|
||||||
#define USE_DRAWINDIRECT
|
#define USE_DRAWINDIRECT
|
||||||
|
|
||||||
int lm_background_updates = 8;
|
int lm_background_updates = 8;
|
||||||
|
@ -33,7 +30,7 @@ bool lm_softshadows = true;
|
||||||
bool lm_sunlight = true;
|
bool lm_sunlight = true;
|
||||||
bool lm_blur = true;
|
bool lm_blur = true;
|
||||||
|
|
||||||
VkLightmap::VkLightmap(VulkanRenderDevice* fb) : fb(fb)
|
VkLightmapper::VkLightmapper(VulkanRenderDevice* fb) : fb(fb)
|
||||||
{
|
{
|
||||||
useRayQuery = fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME) && fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery;
|
useRayQuery = fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME) && fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery;
|
||||||
|
|
||||||
|
@ -60,12 +57,12 @@ VkLightmap::VkLightmap(VulkanRenderDevice* fb) : fb(fb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkLightmap::~VkLightmap()
|
VkLightmapper::~VkLightmapper()
|
||||||
{
|
{
|
||||||
ReleaseResources();
|
ReleaseResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::ReleaseResources()
|
void VkLightmapper::ReleaseResources()
|
||||||
{
|
{
|
||||||
if (lights.Buffer)
|
if (lights.Buffer)
|
||||||
lights.Buffer->Unmap();
|
lights.Buffer->Unmap();
|
||||||
|
@ -77,25 +74,25 @@ void VkLightmap::ReleaseResources()
|
||||||
drawindexed.ConstantsBuffer->Unmap();
|
drawindexed.ConstantsBuffer->Unmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::SetLevelMesh(LevelMesh* level)
|
void VkLightmapper::SetLevelMesh(LevelMesh* level)
|
||||||
{
|
{
|
||||||
mesh = level;
|
mesh = level;
|
||||||
UpdateAccelStructDescriptors();
|
UpdateAccelStructDescriptors();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::BeginFrame()
|
void VkLightmapper::BeginFrame()
|
||||||
{
|
{
|
||||||
lights.Pos = 0;
|
lights.Pos = 0;
|
||||||
lights.ResetCounter++;
|
lights.ResetCounter++;
|
||||||
drawindexed.Pos = 0;
|
drawindexed.Pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::Raytrace(const TArray<LevelMeshSurface*>& surfaces)
|
void VkLightmapper::Raytrace(const TArray<LightmapTile*>& tiles)
|
||||||
{
|
{
|
||||||
if (surfaces.Size())
|
if (mesh && tiles.Size() > 0)
|
||||||
{
|
{
|
||||||
SelectSurfaces(surfaces);
|
SelectTiles(tiles);
|
||||||
if (selectedSurfaces.Size() > 0)
|
if (selectedTiles.Size() > 0)
|
||||||
{
|
{
|
||||||
fb->GetCommands()->PushGroup(fb->GetCommands()->GetTransferCommands(), "lightmap.total");
|
fb->GetCommands()->PushGroup(fb->GetCommands()->GetTransferCommands(), "lightmap.total");
|
||||||
|
|
||||||
|
@ -111,41 +108,41 @@ void VkLightmap::Raytrace(const TArray<LevelMeshSurface*>& surfaces)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::SelectSurfaces(const TArray<LevelMeshSurface*>& surfaces)
|
void VkLightmapper::SelectTiles(const TArray<LightmapTile*>& tiles)
|
||||||
{
|
{
|
||||||
bakeImage.maxX = 0;
|
bakeImage.maxX = 0;
|
||||||
bakeImage.maxY = 0;
|
bakeImage.maxY = 0;
|
||||||
selectedSurfaces.Clear();
|
selectedTiles.Clear();
|
||||||
|
|
||||||
const int spacing = 5; // Note: the spacing is here to avoid that the resolve sampler finds data from other surface tiles
|
const int spacing = 5; // Note: the spacing is here to avoid that the resolve sampler finds data from other surface tiles
|
||||||
RectPacker packer(bakeImageSize - spacing, bakeImageSize - spacing, RectPacker::Spacing(spacing));
|
RectPacker packer(bakeImageSize - spacing, bakeImageSize - spacing, RectPacker::Spacing(spacing));
|
||||||
|
|
||||||
for (int i = 0, count = surfaces.Size(); i < count; i++)
|
for (int i = 0, count = tiles.Size(); i < count; i++)
|
||||||
{
|
{
|
||||||
LevelMeshSurface* surface = surfaces[i];
|
LightmapTile* tile = tiles[i];
|
||||||
|
|
||||||
if (!surface->needsUpdate)
|
if (!tile->NeedsUpdate)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Only grab surfaces until our bake texture is full
|
// Only grab surfaces until our bake texture is full
|
||||||
auto result = packer.insert(surface->AtlasTile.Width + 2, surface->AtlasTile.Height + 2);
|
auto result = packer.insert(tile->AtlasLocation.Width + 2, tile->AtlasLocation.Height + 2);
|
||||||
if (result.pageIndex == 0)
|
if (result.pageIndex == 0)
|
||||||
{
|
{
|
||||||
SelectedSurface selected;
|
SelectedTile selected;
|
||||||
selected.Surface = surface;
|
selected.Tile = tile;
|
||||||
selected.X = result.pos.x + 1;
|
selected.X = result.pos.x + 1;
|
||||||
selected.Y = result.pos.y + 1;
|
selected.Y = result.pos.y + 1;
|
||||||
selectedSurfaces.Push(selected);
|
selectedTiles.Push(selected);
|
||||||
|
|
||||||
bakeImage.maxX = std::max<uint16_t>(bakeImage.maxX, uint16_t(selected.X + surface->AtlasTile.Width + spacing));
|
bakeImage.maxX = std::max<uint16_t>(bakeImage.maxX, uint16_t(selected.X + tile->AtlasLocation.Width + spacing));
|
||||||
bakeImage.maxY = std::max<uint16_t>(bakeImage.maxY, uint16_t(selected.Y + surface->AtlasTile.Height + spacing));
|
bakeImage.maxY = std::max<uint16_t>(bakeImage.maxY, uint16_t(selected.Y + tile->AtlasLocation.Height + spacing));
|
||||||
|
|
||||||
surface->needsUpdate = false;
|
tile->NeedsUpdate = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::Render()
|
void VkLightmapper::Render()
|
||||||
{
|
{
|
||||||
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||||
|
|
||||||
|
@ -159,12 +156,12 @@ void VkLightmap::Render()
|
||||||
.Execute(cmdbuffer);
|
.Execute(cmdbuffer);
|
||||||
|
|
||||||
VkDeviceSize offset = 0;
|
VkDeviceSize offset = 0;
|
||||||
cmdbuffer->bindVertexBuffers(0, 1, &fb->GetRaytrace()->GetVertexBuffer()->buffer, &offset);
|
cmdbuffer->bindVertexBuffers(0, 1, &fb->GetLevelMesh()->GetVertexBuffer()->buffer, &offset);
|
||||||
cmdbuffer->bindIndexBuffer(fb->GetRaytrace()->GetIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32);
|
cmdbuffer->bindIndexBuffer(fb->GetLevelMesh()->GetIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||||
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipeline[GetRaytracePipelineIndex()].get());
|
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipeline[GetRaytracePipelineIndex()].get());
|
||||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 0, raytrace.descriptorSet0.get());
|
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 0, raytrace.descriptorSet0.get());
|
||||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 1, raytrace.descriptorSet1.get());
|
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 1, raytrace.descriptorSet1.get());
|
||||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 2, fb->GetDescriptorSetManager()->GetBindlessDescriptorSet());
|
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 2, fb->GetDescriptorSetManager()->GetBindlessSet());
|
||||||
|
|
||||||
VkViewport viewport = {};
|
VkViewport viewport = {};
|
||||||
viewport.maxDepth = 1;
|
viewport.maxDepth = 1;
|
||||||
|
@ -172,35 +169,40 @@ void VkLightmap::Render()
|
||||||
viewport.height = (float)bakeImageSize;
|
viewport.height = (float)bakeImageSize;
|
||||||
cmdbuffer->setViewport(0, 1, &viewport);
|
cmdbuffer->setViewport(0, 1, &viewport);
|
||||||
|
|
||||||
for (int i = 0, count = selectedSurfaces.Size(); i < count; i++)
|
int dynamicSurfaceIndexOffset = mesh->StaticMesh->GetSurfaceCount();
|
||||||
{
|
int dynamicFirstIndexOffset = mesh->StaticMesh->Mesh.Indexes.Size();
|
||||||
auto& selectedSurface = selectedSurfaces[i];
|
LevelSubmesh* staticMesh = mesh->StaticMesh.get();
|
||||||
LevelMeshSurface* targetSurface = selectedSurface.Surface;
|
|
||||||
|
|
||||||
int surfaceIndexOffset = 0;
|
for (int i = 0, count = selectedTiles.Size(); i < count; i++)
|
||||||
int firstIndexOffset = 0;
|
|
||||||
if (targetSurface->Submesh != mesh->StaticMesh.get())
|
|
||||||
{
|
{
|
||||||
surfaceIndexOffset = mesh->StaticMesh->GetSurfaceCount();
|
auto& selectedTile = selectedTiles[i];
|
||||||
firstIndexOffset = mesh->StaticMesh->MeshElements.Size();
|
LightmapTile* targetTile = selectedTile.Tile;
|
||||||
}
|
|
||||||
|
|
||||||
LightmapRaytracePC pc;
|
LightmapRaytracePC pc;
|
||||||
pc.TileX = (float)selectedSurface.X;
|
pc.TileX = (float)selectedTile.X;
|
||||||
pc.TileY = (float)selectedSurface.Y;
|
pc.TileY = (float)selectedTile.Y;
|
||||||
pc.SurfaceIndex = surfaceIndexOffset + targetSurface->Submesh->GetSurfaceIndex(targetSurface);
|
|
||||||
pc.TextureSize = (float)bakeImageSize;
|
pc.TextureSize = (float)bakeImageSize;
|
||||||
pc.TileWidth = (float)targetSurface->AtlasTile.Width;
|
pc.TileWidth = (float)targetTile->AtlasLocation.Width;
|
||||||
pc.TileHeight = (float)targetSurface->AtlasTile.Height;
|
pc.TileHeight = (float)targetTile->AtlasLocation.Height;
|
||||||
pc.WorldToLocal = targetSurface->translateWorldToLocal;
|
pc.WorldToLocal = SwapYZ(targetTile->Transform.TranslateWorldToLocal);
|
||||||
pc.ProjLocalToU = targetSurface->projLocalToU;
|
pc.ProjLocalToU = SwapYZ(targetTile->Transform.ProjLocalToU);
|
||||||
pc.ProjLocalToV = targetSurface->projLocalToV;
|
pc.ProjLocalToV = SwapYZ(targetTile->Transform.ProjLocalToV);
|
||||||
|
|
||||||
bool buffersFull = false;
|
bool buffersFull = false;
|
||||||
|
|
||||||
// Paint all surfaces visible in the tile
|
// Paint all surfaces visible in the tile
|
||||||
for (LevelMeshSurface* surface : targetSurface->tileSurfaces)
|
for (LevelMeshSurface* surface : targetTile->Surfaces)
|
||||||
{
|
{
|
||||||
|
int surfaceIndexOffset = 0;
|
||||||
|
int firstIndexOffset = 0;
|
||||||
|
if (surface->Submesh != staticMesh)
|
||||||
|
{
|
||||||
|
surfaceIndexOffset = dynamicSurfaceIndexOffset;
|
||||||
|
firstIndexOffset = dynamicFirstIndexOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
pc.SurfaceIndex = surfaceIndexOffset + surface->Submesh->GetSurfaceIndex(surface);
|
||||||
|
|
||||||
if (surface->LightList.ResetCounter != lights.ResetCounter)
|
if (surface->LightList.ResetCounter != lights.ResetCounter)
|
||||||
{
|
{
|
||||||
int lightCount = mesh->AddSurfaceLights(surface, templightlist.Data(), (int)templightlist.Size());
|
int lightCount = mesh->AddSurfaceLights(surface, templightlist.Data(), (int)templightlist.Size());
|
||||||
|
@ -220,13 +222,13 @@ void VkLightmap::Render()
|
||||||
for (int i = 0; i < lightCount; i++)
|
for (int i = 0; i < lightCount; i++)
|
||||||
{
|
{
|
||||||
const LevelMeshLight* light = &templightlist[i];
|
const LevelMeshLight* light = &templightlist[i];
|
||||||
lightinfo->Origin = light->Origin;
|
lightinfo->Origin = SwapYZ(light->Origin);
|
||||||
lightinfo->RelativeOrigin = light->RelativeOrigin;
|
lightinfo->RelativeOrigin = SwapYZ(light->RelativeOrigin);
|
||||||
lightinfo->Radius = light->Radius;
|
lightinfo->Radius = light->Radius;
|
||||||
lightinfo->Intensity = light->Intensity;
|
lightinfo->Intensity = light->Intensity;
|
||||||
lightinfo->InnerAngleCos = light->InnerAngleCos;
|
lightinfo->InnerAngleCos = light->InnerAngleCos;
|
||||||
lightinfo->OuterAngleCos = light->OuterAngleCos;
|
lightinfo->OuterAngleCos = light->OuterAngleCos;
|
||||||
lightinfo->SpotDir = light->SpotDir;
|
lightinfo->SpotDir = SwapYZ(light->SpotDir);
|
||||||
lightinfo->Color = light->Color;
|
lightinfo->Color = light->Color;
|
||||||
lightinfo++;
|
lightinfo++;
|
||||||
}
|
}
|
||||||
|
@ -239,9 +241,9 @@ void VkLightmap::Render()
|
||||||
|
|
||||||
#ifdef USE_DRAWINDIRECT
|
#ifdef USE_DRAWINDIRECT
|
||||||
VkDrawIndexedIndirectCommand cmd;
|
VkDrawIndexedIndirectCommand cmd;
|
||||||
cmd.indexCount = surface->numElements;
|
cmd.indexCount = surface->MeshLocation.NumElements;
|
||||||
cmd.instanceCount = 1;
|
cmd.instanceCount = 1;
|
||||||
cmd.firstIndex = firstIndexOffset + surface->startElementIndex;
|
cmd.firstIndex = firstIndexOffset + surface->MeshLocation.StartElementIndex;
|
||||||
cmd.vertexOffset = 0;
|
cmd.vertexOffset = 0;
|
||||||
cmd.firstInstance = drawindexed.Pos;
|
cmd.firstInstance = drawindexed.Pos;
|
||||||
drawindexed.Constants[drawindexed.Pos] = pc;
|
drawindexed.Constants[drawindexed.Pos] = pc;
|
||||||
|
@ -264,13 +266,13 @@ void VkLightmap::Render()
|
||||||
{
|
{
|
||||||
while (i < count)
|
while (i < count)
|
||||||
{
|
{
|
||||||
selectedSurfaces[i].Surface->needsUpdate = true;
|
selectedTiles[i].Tile->NeedsUpdate = true;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedSurface.Rendered = true;
|
selectedTile.Rendered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_DRAWINDIRECT
|
#ifdef USE_DRAWINDIRECT
|
||||||
|
@ -282,10 +284,10 @@ void VkLightmap::Render()
|
||||||
fb->GetCommands()->PopGroup(cmdbuffer);
|
fb->GetCommands()->PopGroup(cmdbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::UploadUniforms()
|
void VkLightmapper::UploadUniforms()
|
||||||
{
|
{
|
||||||
Uniforms values = {};
|
Uniforms values = {};
|
||||||
values.SunDir = mesh->SunDirection;
|
values.SunDir = SwapYZ(mesh->SunDirection);
|
||||||
values.SunColor = mesh->SunColor;
|
values.SunColor = mesh->SunColor;
|
||||||
values.SunIntensity = 1.0f;
|
values.SunIntensity = 1.0f;
|
||||||
|
|
||||||
|
@ -300,7 +302,7 @@ void VkLightmap::UploadUniforms()
|
||||||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
.Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::Resolve()
|
void VkLightmapper::Resolve()
|
||||||
{
|
{
|
||||||
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||||
|
|
||||||
|
@ -332,7 +334,7 @@ void VkLightmap::Resolve()
|
||||||
fb->GetCommands()->PopGroup(cmdbuffer);
|
fb->GetCommands()->PopGroup(cmdbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::Blur()
|
void VkLightmapper::Blur()
|
||||||
{
|
{
|
||||||
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||||
|
|
||||||
|
@ -393,24 +395,24 @@ void VkLightmap::Blur()
|
||||||
fb->GetCommands()->PopGroup(cmdbuffer);
|
fb->GetCommands()->PopGroup(cmdbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::CopyResult()
|
void VkLightmapper::CopyResult()
|
||||||
{
|
{
|
||||||
// Sort by destination
|
// Sort by destination
|
||||||
uint32_t pixels = 0;
|
uint32_t pixels = 0;
|
||||||
for (auto& list : copylists) list.Clear();
|
for (auto& list : copylists) list.Clear();
|
||||||
for (int i = 0, count = selectedSurfaces.Size(); i < count; i++)
|
for (int i = 0, count = selectedTiles.Size(); i < count; i++)
|
||||||
{
|
{
|
||||||
auto& selected = selectedSurfaces[i];
|
auto& selected = selectedTiles[i];
|
||||||
if (selected.Rendered)
|
if (selected.Rendered)
|
||||||
{
|
{
|
||||||
unsigned int pageIndex = (unsigned int)selected.Surface->AtlasTile.ArrayIndex;
|
unsigned int pageIndex = (unsigned int)selected.Tile->AtlasLocation.ArrayIndex;
|
||||||
if (pageIndex >= copylists.Size())
|
if (pageIndex >= copylists.Size())
|
||||||
{
|
{
|
||||||
copylists.Resize(pageIndex + 1);
|
copylists.Resize(pageIndex + 1);
|
||||||
}
|
}
|
||||||
copylists[pageIndex].Push(&selected);
|
copylists[pageIndex].Push(&selected);
|
||||||
|
|
||||||
pixels += selected.Surface->Area();
|
pixels += selected.Tile->AtlasLocation.Area();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,17 +475,17 @@ void VkLightmap::CopyResult()
|
||||||
|
|
||||||
// Copy the tile positions into a storage buffer for the vertex shader to read
|
// Copy the tile positions into a storage buffer for the vertex shader to read
|
||||||
start = pos;
|
start = pos;
|
||||||
for (SelectedSurface* selected : list)
|
for (SelectedTile* selected : list)
|
||||||
{
|
{
|
||||||
LevelMeshSurface* surface = selected->Surface;
|
LightmapTile* tile = selected->Tile;
|
||||||
|
|
||||||
CopyTileInfo* copyinfo = ©tiles.Tiles[pos++];
|
CopyTileInfo* copyinfo = ©tiles.Tiles[pos++];
|
||||||
copyinfo->SrcPosX = selected->X;
|
copyinfo->SrcPosX = selected->X;
|
||||||
copyinfo->SrcPosY = selected->Y;
|
copyinfo->SrcPosY = selected->Y;
|
||||||
copyinfo->DestPosX = surface->AtlasTile.X;
|
copyinfo->DestPosX = tile->AtlasLocation.X;
|
||||||
copyinfo->DestPosY = surface->AtlasTile.Y;
|
copyinfo->DestPosY = tile->AtlasLocation.Y;
|
||||||
copyinfo->TileWidth = surface->AtlasTile.Width;
|
copyinfo->TileWidth = tile->AtlasLocation.Width;
|
||||||
copyinfo->TileHeight = surface->AtlasTile.Height;
|
copyinfo->TileHeight = tile->AtlasLocation.Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the tiles. One instance per tile.
|
// Draw the tiles. One instance per tile.
|
||||||
|
@ -524,7 +526,7 @@ void VkLightmap::CopyResult()
|
||||||
fb->GetCommands()->PopGroup(cmdbuffer);
|
fb->GetCommands()->PopGroup(cmdbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::CreateShaders()
|
void VkLightmapper::CreateShaders()
|
||||||
{
|
{
|
||||||
std::string prefix = "#version 460\r\n";
|
std::string prefix = "#version 460\r\n";
|
||||||
std::string traceprefix = "#version 460\r\n";
|
std::string traceprefix = "#version 460\r\n";
|
||||||
|
@ -551,8 +553,8 @@ void VkLightmap::CreateShaders()
|
||||||
.AddSource("vert_raytrace.glsl", LoadPrivateShaderLump("shaders/lightmap/vert_raytrace.glsl").GetChars())
|
.AddSource("vert_raytrace.glsl", LoadPrivateShaderLump("shaders/lightmap/vert_raytrace.glsl").GetChars())
|
||||||
.OnIncludeLocal(onIncludeLocal)
|
.OnIncludeLocal(onIncludeLocal)
|
||||||
.OnIncludeSystem(onIncludeSystem)
|
.OnIncludeSystem(onIncludeSystem)
|
||||||
.DebugName("VkLightmap.VertRaytrace")
|
.DebugName("VkLightmapper.VertRaytrace")
|
||||||
.Create("VkLightmap.VertRaytrace", fb->GetDevice());
|
.Create("VkLightmapper.VertRaytrace", fb->GetDevice());
|
||||||
|
|
||||||
shaders.vertScreenquad = ShaderBuilder()
|
shaders.vertScreenquad = ShaderBuilder()
|
||||||
.Type(ShaderType::Vertex)
|
.Type(ShaderType::Vertex)
|
||||||
|
@ -560,8 +562,8 @@ void VkLightmap::CreateShaders()
|
||||||
.AddSource("vert_screenquad.glsl", LoadPrivateShaderLump("shaders/lightmap/vert_screenquad.glsl").GetChars())
|
.AddSource("vert_screenquad.glsl", LoadPrivateShaderLump("shaders/lightmap/vert_screenquad.glsl").GetChars())
|
||||||
.OnIncludeLocal(onIncludeLocal)
|
.OnIncludeLocal(onIncludeLocal)
|
||||||
.OnIncludeSystem(onIncludeSystem)
|
.OnIncludeSystem(onIncludeSystem)
|
||||||
.DebugName("VkLightmap.VertScreenquad")
|
.DebugName("VkLightmapper.VertScreenquad")
|
||||||
.Create("VkLightmap.VertScreenquad", fb->GetDevice());
|
.Create("VkLightmapper.VertScreenquad", fb->GetDevice());
|
||||||
|
|
||||||
shaders.vertCopy = ShaderBuilder()
|
shaders.vertCopy = ShaderBuilder()
|
||||||
.Type(ShaderType::Vertex)
|
.Type(ShaderType::Vertex)
|
||||||
|
@ -569,8 +571,8 @@ void VkLightmap::CreateShaders()
|
||||||
.AddSource("vert_copy.glsl", LoadPrivateShaderLump("shaders/lightmap/vert_copy.glsl").GetChars())
|
.AddSource("vert_copy.glsl", LoadPrivateShaderLump("shaders/lightmap/vert_copy.glsl").GetChars())
|
||||||
.OnIncludeLocal(onIncludeLocal)
|
.OnIncludeLocal(onIncludeLocal)
|
||||||
.OnIncludeSystem(onIncludeSystem)
|
.OnIncludeSystem(onIncludeSystem)
|
||||||
.DebugName("VkLightmap.VertCopy")
|
.DebugName("VkLightmapper.VertCopy")
|
||||||
.Create("VkLightmap.VertCopy", fb->GetDevice());
|
.Create("VkLightmapper.VertCopy", fb->GetDevice());
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
|
@ -588,8 +590,8 @@ void VkLightmap::CreateShaders()
|
||||||
.AddSource("frag_raytrace.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_raytrace.glsl").GetChars())
|
.AddSource("frag_raytrace.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_raytrace.glsl").GetChars())
|
||||||
.OnIncludeLocal(onIncludeLocal)
|
.OnIncludeLocal(onIncludeLocal)
|
||||||
.OnIncludeSystem(onIncludeSystem)
|
.OnIncludeSystem(onIncludeSystem)
|
||||||
.DebugName("VkLightmap.FragRaytrace")
|
.DebugName("VkLightmapper.FragRaytrace")
|
||||||
.Create("VkLightmap.FragRaytrace", fb->GetDevice());
|
.Create("VkLightmapper.FragRaytrace", fb->GetDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
shaders.fragResolve = ShaderBuilder()
|
shaders.fragResolve = ShaderBuilder()
|
||||||
|
@ -598,8 +600,8 @@ void VkLightmap::CreateShaders()
|
||||||
.AddSource("frag_resolve.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_resolve.glsl").GetChars())
|
.AddSource("frag_resolve.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_resolve.glsl").GetChars())
|
||||||
.OnIncludeLocal(onIncludeLocal)
|
.OnIncludeLocal(onIncludeLocal)
|
||||||
.OnIncludeSystem(onIncludeSystem)
|
.OnIncludeSystem(onIncludeSystem)
|
||||||
.DebugName("VkLightmap.FragResolve")
|
.DebugName("VkLightmapper.FragResolve")
|
||||||
.Create("VkLightmap.FragResolve", fb->GetDevice());
|
.Create("VkLightmapper.FragResolve", fb->GetDevice());
|
||||||
|
|
||||||
shaders.fragBlur[0] = ShaderBuilder()
|
shaders.fragBlur[0] = ShaderBuilder()
|
||||||
.Type(ShaderType::Fragment)
|
.Type(ShaderType::Fragment)
|
||||||
|
@ -607,8 +609,8 @@ void VkLightmap::CreateShaders()
|
||||||
.AddSource("frag_blur.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_blur.glsl").GetChars())
|
.AddSource("frag_blur.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_blur.glsl").GetChars())
|
||||||
.OnIncludeLocal(onIncludeLocal)
|
.OnIncludeLocal(onIncludeLocal)
|
||||||
.OnIncludeSystem(onIncludeSystem)
|
.OnIncludeSystem(onIncludeSystem)
|
||||||
.DebugName("VkLightmap.FragBlur")
|
.DebugName("VkLightmapper.FragBlur")
|
||||||
.Create("VkLightmap.FragBlur", fb->GetDevice());
|
.Create("VkLightmapper.FragBlur", fb->GetDevice());
|
||||||
|
|
||||||
shaders.fragBlur[1] = ShaderBuilder()
|
shaders.fragBlur[1] = ShaderBuilder()
|
||||||
.Type(ShaderType::Fragment)
|
.Type(ShaderType::Fragment)
|
||||||
|
@ -616,8 +618,8 @@ void VkLightmap::CreateShaders()
|
||||||
.AddSource("frag_blur.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_blur.glsl").GetChars())
|
.AddSource("frag_blur.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_blur.glsl").GetChars())
|
||||||
.OnIncludeLocal(onIncludeLocal)
|
.OnIncludeLocal(onIncludeLocal)
|
||||||
.OnIncludeSystem(onIncludeSystem)
|
.OnIncludeSystem(onIncludeSystem)
|
||||||
.DebugName("VkLightmap.FragBlur")
|
.DebugName("VkLightmapper.FragBlur")
|
||||||
.Create("VkLightmap.FragBlur", fb->GetDevice());
|
.Create("VkLightmapper.FragBlur", fb->GetDevice());
|
||||||
|
|
||||||
shaders.fragCopy = ShaderBuilder()
|
shaders.fragCopy = ShaderBuilder()
|
||||||
.Type(ShaderType::Fragment)
|
.Type(ShaderType::Fragment)
|
||||||
|
@ -625,11 +627,11 @@ void VkLightmap::CreateShaders()
|
||||||
.AddSource("frag_copy.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_copy.glsl").GetChars())
|
.AddSource("frag_copy.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_copy.glsl").GetChars())
|
||||||
.OnIncludeLocal(onIncludeLocal)
|
.OnIncludeLocal(onIncludeLocal)
|
||||||
.OnIncludeSystem(onIncludeSystem)
|
.OnIncludeSystem(onIncludeSystem)
|
||||||
.DebugName("VkLightmap.FragCopy")
|
.DebugName("VkLightmapper.FragCopy")
|
||||||
.Create("VkLightmap.FragCopy", fb->GetDevice());
|
.Create("VkLightmapper.FragCopy", fb->GetDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
int VkLightmap::GetRaytracePipelineIndex()
|
int VkLightmapper::GetRaytracePipelineIndex()
|
||||||
{
|
{
|
||||||
int index = 0;
|
int index = 0;
|
||||||
if (lm_softshadows && useRayQuery)
|
if (lm_softshadows && useRayQuery)
|
||||||
|
@ -641,7 +643,7 @@ int VkLightmap::GetRaytracePipelineIndex()
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
FString VkLightmap::LoadPrivateShaderLump(const char* lumpname)
|
FString VkLightmapper::LoadPrivateShaderLump(const char* lumpname)
|
||||||
{
|
{
|
||||||
static std::map<FString, FString> sources =
|
static std::map<FString, FString> sources =
|
||||||
{
|
{
|
||||||
|
@ -669,7 +671,12 @@ FString VkLightmap::LoadPrivateShaderLump(const char* lumpname)
|
||||||
return FString();
|
return FString();
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderIncludeResult VkLightmap::OnInclude(FString headerName, FString includerName, size_t depth, bool system)
|
FString VkLightmapper::LoadPublicShaderLump(const char* lumpname)
|
||||||
|
{
|
||||||
|
return LoadPrivateShaderLump(lumpname);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderIncludeResult VkLightmapper::OnInclude(FString headerName, FString includerName, size_t depth, bool system)
|
||||||
{
|
{
|
||||||
if (depth > 8)
|
if (depth > 8)
|
||||||
{
|
{
|
||||||
|
@ -695,7 +702,7 @@ ShaderIncludeResult VkLightmap::OnInclude(FString headerName, FString includerNa
|
||||||
return ShaderIncludeResult(headerName.GetChars(), code.GetChars());
|
return ShaderIncludeResult(headerName.GetChars(), code.GetChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::CreateRaytracePipeline()
|
void VkLightmapper::CreateRaytracePipeline()
|
||||||
{
|
{
|
||||||
raytrace.descriptorSetLayout0 = DescriptorSetLayoutBuilder()
|
raytrace.descriptorSetLayout0 = DescriptorSetLayoutBuilder()
|
||||||
.AddBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
|
.AddBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||||
|
@ -731,7 +738,7 @@ void VkLightmap::CreateRaytracePipeline()
|
||||||
raytrace.pipelineLayout = PipelineLayoutBuilder()
|
raytrace.pipelineLayout = PipelineLayoutBuilder()
|
||||||
.AddSetLayout(raytrace.descriptorSetLayout0.get())
|
.AddSetLayout(raytrace.descriptorSetLayout0.get())
|
||||||
.AddSetLayout(raytrace.descriptorSetLayout1.get())
|
.AddSetLayout(raytrace.descriptorSetLayout1.get())
|
||||||
.AddSetLayout(fb->GetDescriptorSetManager()->GetBindlessSetLayout())
|
.AddSetLayout(fb->GetDescriptorSetManager()->GetBindlessLayout())
|
||||||
#ifndef USE_DRAWINDIRECT
|
#ifndef USE_DRAWINDIRECT
|
||||||
.AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(LightmapRaytracePC))
|
.AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(LightmapRaytracePC))
|
||||||
#endif
|
#endif
|
||||||
|
@ -763,7 +770,7 @@ void VkLightmap::CreateRaytracePipeline()
|
||||||
.RenderPass(raytrace.renderPass.get())
|
.RenderPass(raytrace.renderPass.get())
|
||||||
.AddVertexShader(shaders.vertRaytrace.get())
|
.AddVertexShader(shaders.vertRaytrace.get())
|
||||||
.AddFragmentShader(shaders.fragRaytrace[i].get())
|
.AddFragmentShader(shaders.fragRaytrace[i].get())
|
||||||
.AddVertexBufferBinding(0, sizeof(SurfaceVertex))
|
.AddVertexBufferBinding(0, sizeof(FFlatVertex))
|
||||||
.AddVertexAttribute(0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, 0)
|
.AddVertexAttribute(0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, 0)
|
||||||
.Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
.Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
||||||
.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT)
|
.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT)
|
||||||
|
@ -806,38 +813,38 @@ void VkLightmap::CreateRaytracePipeline()
|
||||||
raytrace.descriptorSet1->SetDebugName("raytrace.descriptorSet1");
|
raytrace.descriptorSet1->SetDebugName("raytrace.descriptorSet1");
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::UpdateAccelStructDescriptors()
|
void VkLightmapper::UpdateAccelStructDescriptors()
|
||||||
{
|
{
|
||||||
if (useRayQuery)
|
if (useRayQuery)
|
||||||
{
|
{
|
||||||
WriteDescriptors()
|
WriteDescriptors()
|
||||||
.AddAccelerationStructure(raytrace.descriptorSet1.get(), 0, fb->GetRaytrace()->GetAccelStruct())
|
.AddAccelerationStructure(raytrace.descriptorSet1.get(), 0, fb->GetLevelMesh()->GetAccelStruct())
|
||||||
.AddBuffer(raytrace.descriptorSet1.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetVertexBuffer())
|
.AddBuffer(raytrace.descriptorSet1.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetVertexBuffer())
|
||||||
.AddBuffer(raytrace.descriptorSet1.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetIndexBuffer())
|
.AddBuffer(raytrace.descriptorSet1.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetIndexBuffer())
|
||||||
.Execute(fb->GetDevice());
|
.Execute(fb->GetDevice());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WriteDescriptors()
|
WriteDescriptors()
|
||||||
.AddBuffer(raytrace.descriptorSet1.get(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetNodeBuffer())
|
.AddBuffer(raytrace.descriptorSet1.get(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetNodeBuffer())
|
||||||
.AddBuffer(raytrace.descriptorSet1.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetVertexBuffer())
|
.AddBuffer(raytrace.descriptorSet1.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetVertexBuffer())
|
||||||
.AddBuffer(raytrace.descriptorSet1.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetIndexBuffer())
|
.AddBuffer(raytrace.descriptorSet1.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetIndexBuffer())
|
||||||
.Execute(fb->GetDevice());
|
.Execute(fb->GetDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteDescriptors()
|
WriteDescriptors()
|
||||||
.AddBuffer(raytrace.descriptorSet0.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniforms.Buffer.get(), 0, sizeof(Uniforms))
|
.AddBuffer(raytrace.descriptorSet0.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniforms.Buffer.get(), 0, sizeof(Uniforms))
|
||||||
.AddBuffer(raytrace.descriptorSet0.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetSurfaceIndexBuffer())
|
.AddBuffer(raytrace.descriptorSet0.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceIndexBuffer())
|
||||||
.AddBuffer(raytrace.descriptorSet0.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetSurfaceBuffer())
|
.AddBuffer(raytrace.descriptorSet0.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceBuffer())
|
||||||
.AddBuffer(raytrace.descriptorSet0.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, lights.Buffer.get())
|
.AddBuffer(raytrace.descriptorSet0.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, lights.Buffer.get())
|
||||||
.AddBuffer(raytrace.descriptorSet0.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetRaytrace()->GetPortalBuffer())
|
.AddBuffer(raytrace.descriptorSet0.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetPortalBuffer())
|
||||||
#ifdef USE_DRAWINDIRECT
|
#ifdef USE_DRAWINDIRECT
|
||||||
.AddBuffer(raytrace.descriptorSet0.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, drawindexed.ConstantsBuffer.get(), 0, drawindexed.BufferSize * sizeof(LightmapRaytracePC))
|
.AddBuffer(raytrace.descriptorSet0.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, drawindexed.ConstantsBuffer.get(), 0, drawindexed.BufferSize * sizeof(LightmapRaytracePC))
|
||||||
#endif
|
#endif
|
||||||
.Execute(fb->GetDevice());
|
.Execute(fb->GetDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::CreateResolvePipeline()
|
void VkLightmapper::CreateResolvePipeline()
|
||||||
{
|
{
|
||||||
resolve.descriptorSetLayout = DescriptorSetLayoutBuilder()
|
resolve.descriptorSetLayout = DescriptorSetLayoutBuilder()
|
||||||
.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||||
|
@ -890,7 +897,7 @@ void VkLightmap::CreateResolvePipeline()
|
||||||
.Create(fb->GetDevice());
|
.Create(fb->GetDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::CreateBlurPipeline()
|
void VkLightmapper::CreateBlurPipeline()
|
||||||
{
|
{
|
||||||
blur.descriptorSetLayout = DescriptorSetLayoutBuilder()
|
blur.descriptorSetLayout = DescriptorSetLayoutBuilder()
|
||||||
.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||||
|
@ -946,7 +953,7 @@ void VkLightmap::CreateBlurPipeline()
|
||||||
.Create(fb->GetDevice());
|
.Create(fb->GetDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::CreateCopyPipeline()
|
void VkLightmapper::CreateCopyPipeline()
|
||||||
{
|
{
|
||||||
copy.descriptorSetLayout = DescriptorSetLayoutBuilder()
|
copy.descriptorSetLayout = DescriptorSetLayoutBuilder()
|
||||||
.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||||
|
@ -1002,7 +1009,7 @@ void VkLightmap::CreateCopyPipeline()
|
||||||
.Create(fb->GetDevice());
|
.Create(fb->GetDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::CreateBakeImage()
|
void VkLightmapper::CreateBakeImage()
|
||||||
{
|
{
|
||||||
int width = bakeImageSize;
|
int width = bakeImageSize;
|
||||||
int height = bakeImageSize;
|
int height = bakeImageSize;
|
||||||
|
@ -1087,7 +1094,7 @@ void VkLightmap::CreateBakeImage()
|
||||||
.Execute(fb->GetDevice());
|
.Execute(fb->GetDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::CreateUniformBuffer()
|
void VkLightmapper::CreateUniformBuffer()
|
||||||
{
|
{
|
||||||
VkDeviceSize align = fb->GetDevice()->PhysicalDevice.Properties.Properties.limits.minUniformBufferOffsetAlignment;
|
VkDeviceSize align = fb->GetDevice()->PhysicalDevice.Properties.Properties.limits.minUniformBufferOffsetAlignment;
|
||||||
uniforms.StructStride = (sizeof(Uniforms) + align - 1) / align * align;
|
uniforms.StructStride = (sizeof(Uniforms) + align - 1) / align * align;
|
||||||
|
@ -1105,7 +1112,7 @@ void VkLightmap::CreateUniformBuffer()
|
||||||
.Create(fb->GetDevice());
|
.Create(fb->GetDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::CreateLightBuffer()
|
void VkLightmapper::CreateLightBuffer()
|
||||||
{
|
{
|
||||||
size_t size = sizeof(LightInfo) * lights.BufferSize;
|
size_t size = sizeof(LightInfo) * lights.BufferSize;
|
||||||
|
|
||||||
|
@ -1124,7 +1131,7 @@ void VkLightmap::CreateLightBuffer()
|
||||||
lights.Pos = 0;
|
lights.Pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::CreateTileBuffer()
|
void VkLightmapper::CreateTileBuffer()
|
||||||
{
|
{
|
||||||
size_t size = sizeof(CopyTileInfo) * copytiles.BufferSize;
|
size_t size = sizeof(CopyTileInfo) * copytiles.BufferSize;
|
||||||
|
|
||||||
|
@ -1142,7 +1149,7 @@ void VkLightmap::CreateTileBuffer()
|
||||||
copytiles.Tiles = (CopyTileInfo*)copytiles.Buffer->Map(0, size);
|
copytiles.Tiles = (CopyTileInfo*)copytiles.Buffer->Map(0, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkLightmap::CreateDrawIndexedBuffer()
|
void VkLightmapper::CreateDrawIndexedBuffer()
|
||||||
{
|
{
|
||||||
size_t size1 = sizeof(VkDrawIndexedIndirectCommand) * drawindexed.BufferSize;
|
size_t size1 = sizeof(VkDrawIndexedIndirectCommand) * drawindexed.BufferSize;
|
||||||
size_t size2 = sizeof(LightmapRaytracePC) * drawindexed.BufferSize;
|
size_t size2 = sizeof(LightmapRaytracePC) * drawindexed.BufferSize;
|
|
@ -2,8 +2,7 @@
|
||||||
|
|
||||||
#include "hw_levelmesh.h"
|
#include "hw_levelmesh.h"
|
||||||
#include "zvulkan/vulkanobjects.h"
|
#include "zvulkan/vulkanobjects.h"
|
||||||
#include "dp_rect_pack/dp_rect_pack.h"
|
#include <dp_rect_pack/dp_rect_pack.h>
|
||||||
#include "framework/zstring.h"
|
|
||||||
|
|
||||||
typedef dp::rect_pack::RectPacker<int> RectPacker;
|
typedef dp::rect_pack::RectPacker<int> RectPacker;
|
||||||
|
|
||||||
|
@ -96,9 +95,9 @@ struct LightInfo
|
||||||
float Padding3;
|
float Padding3;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SelectedSurface
|
struct SelectedTile
|
||||||
{
|
{
|
||||||
LevelMeshSurface* Surface = nullptr;
|
LightmapTile* Tile = nullptr;
|
||||||
int X = -1;
|
int X = -1;
|
||||||
int Y = -1;
|
int Y = -1;
|
||||||
bool Rendered = false;
|
bool Rendered = false;
|
||||||
|
@ -120,20 +119,20 @@ struct CopyTileInfo
|
||||||
|
|
||||||
static_assert(sizeof(CopyTileInfo) == sizeof(int32_t) * 8);
|
static_assert(sizeof(CopyTileInfo) == sizeof(int32_t) * 8);
|
||||||
|
|
||||||
class VkLightmap
|
class VkLightmapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VkLightmap(VulkanRenderDevice* fb);
|
VkLightmapper(VulkanRenderDevice* fb);
|
||||||
~VkLightmap();
|
~VkLightmapper();
|
||||||
|
|
||||||
void BeginFrame();
|
void BeginFrame();
|
||||||
void Raytrace(const TArray<LevelMeshSurface*>& surfaces);
|
void Raytrace(const TArray<LightmapTile*>& surfaces);
|
||||||
void SetLevelMesh(LevelMesh* level);
|
void SetLevelMesh(LevelMesh* level);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ReleaseResources();
|
void ReleaseResources();
|
||||||
|
|
||||||
void SelectSurfaces(const TArray<LevelMeshSurface*>& surfaces);
|
void SelectTiles(const TArray<LightmapTile*>& surfaces);
|
||||||
void UploadUniforms();
|
void UploadUniforms();
|
||||||
void Render();
|
void Render();
|
||||||
void Resolve();
|
void Resolve();
|
||||||
|
@ -156,16 +155,18 @@ private:
|
||||||
int GetRaytracePipelineIndex();
|
int GetRaytracePipelineIndex();
|
||||||
|
|
||||||
static FString LoadPrivateShaderLump(const char* lumpname);
|
static FString LoadPrivateShaderLump(const char* lumpname);
|
||||||
static FString LoadPublicShaderLump(const char* lumpname) { return LoadPrivateShaderLump(lumpname); }
|
static FString LoadPublicShaderLump(const char* lumpname);
|
||||||
static ShaderIncludeResult OnInclude(FString headerName, FString includerName, size_t depth, bool system);
|
static ShaderIncludeResult OnInclude(FString headerName, FString includerName, size_t depth, bool system);
|
||||||
|
|
||||||
|
FVector3 SwapYZ(const FVector3& v) { return FVector3(v.X, v.Z, v.Y); }
|
||||||
|
|
||||||
VulkanRenderDevice* fb = nullptr;
|
VulkanRenderDevice* fb = nullptr;
|
||||||
LevelMesh* mesh = nullptr;
|
LevelMesh* mesh = nullptr;
|
||||||
|
|
||||||
bool useRayQuery = true;
|
bool useRayQuery = true;
|
||||||
|
|
||||||
TArray<SelectedSurface> selectedSurfaces;
|
TArray<SelectedTile> selectedTiles;
|
||||||
TArray<TArray<SelectedSurface*>> copylists;
|
TArray<TArray<SelectedTile*>> copylists;
|
||||||
TArray<LevelMeshLight> templightlist;
|
TArray<LevelMeshLight> templightlist;
|
||||||
|
|
||||||
struct
|
struct
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
#include "vk_renderdevice.h"
|
#include "vk_renderdevice.h"
|
||||||
#include "vk_raytrace.h"
|
#include "vk_levelmesh.h"
|
||||||
#include "vk_lightmap.h"
|
#include "vk_lightmapper.h"
|
||||||
#include "stacktrace.h"
|
#include "stacktrace.h"
|
||||||
#include <zvulkan/vulkanbuilders.h>
|
#include <zvulkan/vulkanbuilders.h>
|
||||||
#include <zvulkan/vulkancompatibledevice.h>
|
#include <zvulkan/vulkancompatibledevice.h>
|
||||||
|
@ -37,8 +37,8 @@ VulkanRenderDevice::VulkanRenderDevice()
|
||||||
commands = std::make_unique<VkCommandBufferManager>(this);
|
commands = std::make_unique<VkCommandBufferManager>(this);
|
||||||
descriptors = std::make_unique<VkDescriptorSetManager>(this);
|
descriptors = std::make_unique<VkDescriptorSetManager>(this);
|
||||||
textures = std::make_unique<VkTextureManager>(this);
|
textures = std::make_unique<VkTextureManager>(this);
|
||||||
raytrace = std::make_unique<VkRaytrace>(this);
|
levelmesh = std::make_unique<VkLevelMesh>(this);
|
||||||
lightmap = std::make_unique<VkLightmap>(this);
|
lightmapper = std::make_unique<VkLightmapper>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanRenderDevice::~VulkanRenderDevice()
|
VulkanRenderDevice::~VulkanRenderDevice()
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
#include "zvulkan/vulkanbuilders.h"
|
#include "zvulkan/vulkanbuilders.h"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
class VkRaytrace;
|
class VkLevelMesh;
|
||||||
class VkLightmap;
|
class VkLightmapper;
|
||||||
class VkCommandBufferManager;
|
class VkCommandBufferManager;
|
||||||
class VkDescriptorSetManager;
|
class VkDescriptorSetManager;
|
||||||
class VkTextureManager;
|
class VkTextureManager;
|
||||||
|
@ -22,8 +22,8 @@ public:
|
||||||
VkCommandBufferManager* GetCommands() { return commands.get(); }
|
VkCommandBufferManager* GetCommands() { return commands.get(); }
|
||||||
VkDescriptorSetManager* GetDescriptorSetManager() { return descriptors.get(); }
|
VkDescriptorSetManager* GetDescriptorSetManager() { return descriptors.get(); }
|
||||||
VkTextureManager* GetTextureManager() { return textures.get(); }
|
VkTextureManager* GetTextureManager() { return textures.get(); }
|
||||||
VkRaytrace* GetRaytrace() { return raytrace.get(); }
|
VkLevelMesh* GetLevelMesh() { return levelmesh.get(); }
|
||||||
VkLightmap* GetLightmap() { return lightmap.get(); }
|
VkLightmapper* GetLightmapper() { return lightmapper.get(); }
|
||||||
|
|
||||||
int GetBindlessTextureIndex(FTextureID texture) { return -1; }
|
int GetBindlessTextureIndex(FTextureID texture) { return -1; }
|
||||||
|
|
||||||
|
@ -34,8 +34,8 @@ private:
|
||||||
std::unique_ptr<VkCommandBufferManager> commands;
|
std::unique_ptr<VkCommandBufferManager> commands;
|
||||||
std::unique_ptr<VkDescriptorSetManager> descriptors;
|
std::unique_ptr<VkDescriptorSetManager> descriptors;
|
||||||
std::unique_ptr<VkTextureManager> textures;
|
std::unique_ptr<VkTextureManager> textures;
|
||||||
std::unique_ptr<VkRaytrace> raytrace;
|
std::unique_ptr<VkLevelMesh> levelmesh;
|
||||||
std::unique_ptr<VkLightmap> lightmap;
|
std::unique_ptr<VkLightmapper> lightmapper;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VkCommandBufferManager
|
class VkCommandBufferManager
|
||||||
|
@ -128,8 +128,8 @@ class VkDescriptorSetManager
|
||||||
public:
|
public:
|
||||||
VkDescriptorSetManager(VulkanRenderDevice* fb);
|
VkDescriptorSetManager(VulkanRenderDevice* fb);
|
||||||
|
|
||||||
VulkanDescriptorSetLayout* GetBindlessSetLayout() { return BindlessDescriptorSetLayout.get(); }
|
VulkanDescriptorSetLayout* GetBindlessLayout() { return BindlessDescriptorSetLayout.get(); }
|
||||||
VulkanDescriptorSet* GetBindlessDescriptorSet() { return BindlessDescriptorSet.get(); }
|
VulkanDescriptorSet* GetBindlessSet() { return BindlessDescriptorSet.get(); }
|
||||||
|
|
||||||
void UpdateBindlessDescriptorSet();
|
void UpdateBindlessDescriptorSet();
|
||||||
int AddBindlessTextureIndex(VulkanImageView* imageview, VulkanSampler* sampler);
|
int AddBindlessTextureIndex(VulkanImageView* imageview, VulkanSampler* sampler);
|
||||||
|
|
Loading…
Reference in a new issue