HWWall lightmap UV calculation hell
This commit is contained in:
parent
2e6cd8fdda
commit
496b053567
4 changed files with 114 additions and 50 deletions
|
|
@ -54,6 +54,9 @@ struct LightmapTile
|
|||
// True if the tile needs to be rendered into the lightmap texture before it can be used
|
||||
bool NeedsUpdate = true;
|
||||
|
||||
// Lightmap UV coordinates used by HWWall
|
||||
FVector2 WallUV[4];
|
||||
|
||||
FVector2 ToUV(const FVector3& vert) const
|
||||
{
|
||||
FVector3 localPos = vert - Transform.TranslateWorldToLocal;
|
||||
|
|
@ -61,4 +64,12 @@ struct LightmapTile
|
|||
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);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ DoomLevelSubmesh::DoomLevelSubmesh(DoomLevelMesh* mesh, FLevelLocals& doomMap, b
|
|||
SortIndexes();
|
||||
BuildTileSurfaceLists();
|
||||
UpdateCollision();
|
||||
PackLightmapAtlas(0);
|
||||
PackLightmapAtlas(doomMap, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ void DoomLevelSubmesh::Update(FLevelLocals& doomMap, int lightmapStartIndex)
|
|||
UpdateCollision();
|
||||
|
||||
if (doomMap.lightmaps)
|
||||
PackLightmapAtlas(lightmapStartIndex);
|
||||
PackLightmapAtlas(doomMap, lightmapStartIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -246,6 +246,10 @@ void DoomLevelSubmesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, M
|
|||
state.mVertices.Clear();
|
||||
state.mIndexes.Clear();
|
||||
|
||||
FVector2 v1 = FVector2(side->V1()->fPos());
|
||||
FVector2 v2 = FVector2(side->V2()->fPos());
|
||||
FVector2 N = FVector2(v2.Y - v1.Y, v1.X - v2.X).Unit();
|
||||
|
||||
DoomLevelMeshSurface surf;
|
||||
surf.Submesh = this;
|
||||
surf.Type = wallpart.LevelMeshInfo.Type;
|
||||
|
|
@ -259,7 +263,7 @@ void DoomLevelSubmesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, M
|
|||
surf.MeshLocation.StartElementIndex = startElementIndex;
|
||||
surf.MeshLocation.NumVerts = Mesh.Vertices.Size() - startVertIndex;
|
||||
surf.MeshLocation.NumElements = Mesh.Indexes.Size() - startElementIndex;
|
||||
surf.Plane = ToPlane(Mesh.Vertices[startVertIndex + 3].fPos(), Mesh.Vertices[startVertIndex + 2].fPos(), Mesh.Vertices[startVertIndex + 1].fPos(), Mesh.Vertices[startVertIndex].fPos());
|
||||
surf.Plane = FVector4(N.X, N.Y, 0.0f, v1 | N);
|
||||
surf.Texture = wallpart.texture;
|
||||
surf.PipelineID = pipelineID;
|
||||
surf.PortalIndex = isSky ? LevelMesh->linePortals[side->linedef->Index()] : 0;
|
||||
|
|
@ -272,6 +276,9 @@ void DoomLevelSubmesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, M
|
|||
|
||||
int DoomLevelSubmesh::AddSurfaceToTile(const DoomLevelMeshSurface& surf, std::map<LightmapTileBinding, int>& bindings)
|
||||
{
|
||||
if (surf.IsSky)
|
||||
return -1;
|
||||
|
||||
LightmapTileBinding binding;
|
||||
binding.Type = surf.Type;
|
||||
binding.TypeIndex = surf.TypeIndex;
|
||||
|
|
@ -516,6 +523,10 @@ void DoomLevelSubmesh::SortIndexes()
|
|||
for (unsigned int j = 0; j < count; j++)
|
||||
{
|
||||
sortedIndexes.Push(Mesh.Indexes[start + j]);
|
||||
}
|
||||
|
||||
for (unsigned int j = 0; j < count; j += 3)
|
||||
{
|
||||
Mesh.SurfaceIndexes.Push((int)i);
|
||||
}
|
||||
}
|
||||
|
|
@ -617,7 +628,7 @@ bool DoomLevelSubmesh::IsDegenerate(const FVector3 &v0, const FVector3 &v1, cons
|
|||
return crosslengthsqr <= 1.e-6f;
|
||||
}
|
||||
|
||||
void DoomLevelSubmesh::PackLightmapAtlas(int lightmapStartIndex)
|
||||
void DoomLevelSubmesh::PackLightmapAtlas(FLevelLocals& doomMap, int lightmapStartIndex)
|
||||
{
|
||||
std::vector<LightmapTile*> sortedTiles;
|
||||
sortedTiles.reserve(LightmapTiles.Size());
|
||||
|
|
@ -654,28 +665,73 @@ void DoomLevelSubmesh::PackLightmapAtlas(int lightmapStartIndex)
|
|||
const LightmapTile& tile = LightmapTiles[surface.LightmapTileIndex];
|
||||
for (int i = 0; i < surface.MeshLocation.NumVerts; i++)
|
||||
{
|
||||
FVector3 tDelta = Mesh.Vertices[surface.MeshLocation.StartVertIndex + i].fPos() - tile.Transform.TranslateWorldToLocal;
|
||||
auto& vertex = Mesh.Vertices[surface.MeshLocation.StartVertIndex + i];
|
||||
vertex.lu = (tile.AtlasLocation.X + (tDelta | tile.Transform.ProjLocalToU)) / (float)LMTextureSize;
|
||||
vertex.lv = (tile.AtlasLocation.Y + (tDelta | tile.Transform.ProjLocalToV)) / (float)LMTextureSize;
|
||||
FVector2 uv = tile.ToUV(vertex.fPos(), (float)LMTextureSize);
|
||||
vertex.lu = uv.X;
|
||||
vertex.lv = uv.Y;
|
||||
vertex.lindex = (float)tile.AtlasLocation.ArrayIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 // Debug atlas tile locations:
|
||||
uint16_t colors[30] =
|
||||
// Calculate HWWall lightmap UV coordinates for the immediate hwrenderer
|
||||
for (LightmapTile* tile : sortedTiles)
|
||||
{
|
||||
floatToHalf(1.0f), floatToHalf(0.0f), floatToHalf(0.0f),
|
||||
floatToHalf(0.0f), floatToHalf(1.0f), floatToHalf(0.0f),
|
||||
floatToHalf(1.0f), floatToHalf(1.0f), floatToHalf(0.0f),
|
||||
floatToHalf(0.0f), floatToHalf(1.0f), floatToHalf(1.0f),
|
||||
floatToHalf(1.0f), floatToHalf(0.0f), floatToHalf(1.0f),
|
||||
floatToHalf(0.5f), floatToHalf(0.0f), floatToHalf(0.0f),
|
||||
floatToHalf(0.0f), floatToHalf(0.5f), floatToHalf(0.0f),
|
||||
floatToHalf(0.5f), floatToHalf(0.5f), floatToHalf(0.0f),
|
||||
floatToHalf(0.0f), floatToHalf(0.5f), floatToHalf(0.5f),
|
||||
floatToHalf(0.5f), floatToHalf(0.0f), floatToHalf(0.5f)
|
||||
uint32_t type = tile->Binding.Type;
|
||||
if (type != ST_LOWERSIDE && type != ST_MIDDLESIDE && type != ST_UPPERSIDE)
|
||||
continue;
|
||||
|
||||
side_t* frontside = &doomMap.sides[tile->Binding.TypeIndex];
|
||||
side_t* backside = frontside->linedef->sidedef[0] == frontside ? frontside->linedef->sidedef[1] : frontside->linedef->sidedef[0];
|
||||
sector_t* frontsector = frontside->sector;
|
||||
sector_t* backsector = backside ? backside->sector : frontsector;
|
||||
|
||||
FVector2 v1 = FVector2(frontside->V1()->fPos());
|
||||
FVector2 v2 = FVector2(frontside->V2()->fPos());
|
||||
secplane_t* top;
|
||||
secplane_t* bottom;
|
||||
|
||||
if (tile->Binding.ControlSector != 0xffffffff)
|
||||
{
|
||||
sector_t* controlsector = &doomMap.sectors[tile->Binding.ControlSector];
|
||||
top = &controlsector->GetSecPlane(sector_t::ceiling);
|
||||
bottom = &controlsector->GetSecPlane(sector_t::floor);
|
||||
}
|
||||
else if (type == ST_MIDDLESIDE)
|
||||
{
|
||||
top = &frontsector->GetSecPlane(sector_t::ceiling);
|
||||
bottom = &frontsector->GetSecPlane(sector_t::floor);
|
||||
}
|
||||
else if (type == ST_LOWERSIDE)
|
||||
{
|
||||
top = &backsector->GetSecPlane(sector_t::floor);
|
||||
bottom = &frontsector->GetSecPlane(sector_t::floor);
|
||||
}
|
||||
else // if (type == ST_UPPERSIDE)
|
||||
{
|
||||
top = &frontsector->GetSecPlane(sector_t::ceiling);
|
||||
bottom = &backsector->GetSecPlane(sector_t::ceiling);
|
||||
}
|
||||
|
||||
tile->WallUV[0] = tile->ToUV(FVector3(v1, bottom->ZatPoint(v1)), (float)LMTextureSize);
|
||||
tile->WallUV[1] = tile->ToUV(FVector3(v1, top->ZatPoint(v1)), (float)LMTextureSize);
|
||||
tile->WallUV[2] = tile->ToUV(FVector3(v2, top->ZatPoint(v2)), (float)LMTextureSize);
|
||||
tile->WallUV[3] = tile->ToUV(FVector3(v2, bottom->ZatPoint(v2)), (float)LMTextureSize);
|
||||
}
|
||||
|
||||
#if 0 // Debug atlas tile locations:
|
||||
float colors[30] =
|
||||
{
|
||||
1.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f,
|
||||
0.0f, 1.0f, 1.0f,
|
||||
1.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.0f, 0.0f,
|
||||
0.0f, 0.5f, 0.0f,
|
||||
0.5f, 0.5f, 0.0f,
|
||||
0.0f, 0.5f, 0.5f,
|
||||
0.5f, 0.0f, 0.5f
|
||||
};
|
||||
LMTextureData.Resize(LMTextureSize * LMTextureSize * LMTextureCount * 3);
|
||||
uint16_t* pixels = LMTextureData.Data();
|
||||
|
|
@ -684,7 +740,7 @@ void DoomLevelSubmesh::PackLightmapAtlas(int lightmapStartIndex)
|
|||
tile.NeedsUpdate = false;
|
||||
|
||||
int index = tile.Binding.TypeIndex;
|
||||
uint16_t* color = colors + (index % 10) * 3;
|
||||
float* color = colors + (index % 10) * 3;
|
||||
|
||||
int x = tile.AtlasLocation.X;
|
||||
int y = tile.AtlasLocation.Y;
|
||||
|
|
@ -695,9 +751,10 @@ void DoomLevelSubmesh::PackLightmapAtlas(int lightmapStartIndex)
|
|||
uint16_t* line = pixels + tile.AtlasLocation.ArrayIndex * LMTextureSize * LMTextureSize + yy * LMTextureSize * 3;
|
||||
for (int xx = x; xx < x + w; xx++)
|
||||
{
|
||||
line[xx * 3] = color[0];
|
||||
line[xx * 3 + 1] = color[1];
|
||||
line[xx * 3 + 2] = color[2];
|
||||
float gray = (yy - y) / (float)h;
|
||||
line[xx * 3] = floatToHalf(color[0] * gray);
|
||||
line[xx * 3 + 1] = floatToHalf(color[1] * gray);
|
||||
line[xx * 3 + 2] = floatToHalf(color[2] * gray);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -714,17 +771,13 @@ BBox DoomLevelSubmesh::GetBoundsFromSurface(const LevelMeshSurface& surface) con
|
|||
bounds.Clear();
|
||||
for (int i = int(surface.MeshLocation.StartVertIndex); i < int(surface.MeshLocation.StartVertIndex) + surface.MeshLocation.NumVerts; i++)
|
||||
{
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
if (Mesh.Vertices[i].fPos()[j] < bounds.min[j])
|
||||
{
|
||||
bounds.min[j] = Mesh.Vertices[i].fPos()[j];
|
||||
}
|
||||
if (Mesh.Vertices[i].fPos()[j] > bounds.max[j])
|
||||
{
|
||||
bounds.max[j] = Mesh.Vertices[i].fPos()[j];
|
||||
}
|
||||
}
|
||||
FVector3 v = Mesh.Vertices[(int)i].fPos();
|
||||
bounds.min.X = std::min(bounds.min.X, v.X);
|
||||
bounds.min.Y = std::min(bounds.min.Y, v.Y);
|
||||
bounds.min.Z = std::min(bounds.min.Z, v.Z);
|
||||
bounds.max.X = std::max(bounds.max.X, v.X);
|
||||
bounds.max.Y = std::max(bounds.max.Y, v.Y);
|
||||
bounds.max.Z = std::max(bounds.max.Z, v.Z);
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public:
|
|||
|
||||
// Used by Maploader
|
||||
void LinkSurfaces(FLevelLocals& doomMap);
|
||||
void PackLightmapAtlas(int lightmapStartIndex);
|
||||
void PackLightmapAtlas(FLevelLocals& doomMap, int lightmapStartIndex);
|
||||
|
||||
TArray<DoomLevelMeshSurface> Surfaces;
|
||||
|
||||
|
|
|
|||
|
|
@ -910,14 +910,14 @@ bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto
|
|||
}
|
||||
|
||||
texcoord srclightuv[4];
|
||||
if (surface && surface->Type != ST_NONE && surface->MeshLocation.NumVerts >= 4)
|
||||
if (surface && surface->LightmapTileIndex >= 0)
|
||||
{
|
||||
FFlatVertex* vertices = &surface->Submesh->Mesh.Vertices[surface->MeshLocation.StartVertIndex];
|
||||
srclightuv[0] = { vertices[0].lu, vertices[0].lv };
|
||||
srclightuv[1] = { vertices[1].lu, vertices[1].lv };
|
||||
srclightuv[2] = { vertices[2].lu, vertices[2].lv };
|
||||
srclightuv[3] = { vertices[3].lu, vertices[3].lv };
|
||||
lindex = vertices[0].lindex;
|
||||
LightmapTile* tile = &surface->Submesh->LightmapTiles[surface->LightmapTileIndex];
|
||||
srclightuv[0] = { tile->WallUV[0].X, tile->WallUV[0].Y };
|
||||
srclightuv[1] = { tile->WallUV[1].X, tile->WallUV[1].Y };
|
||||
srclightuv[2] = { tile->WallUV[2].X, tile->WallUV[2].Y };
|
||||
srclightuv[3] = { tile->WallUV[3].X, tile->WallUV[3].Y };
|
||||
lindex = (float)tile->AtlasLocation.ArrayIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1672,15 +1672,15 @@ void HWWall::BuildFFBlock(HWWallDispatcher *di, FRenderState& state, seg_t * seg
|
|||
type = RENDERWALL_FFBLOCK;
|
||||
CheckTexturePosition(&tci);
|
||||
|
||||
texcoord srclightuv[4];
|
||||
if (surface && surface->Type != ST_NONE)
|
||||
texcoord srclightuv[4];
|
||||
if (surface && surface->LightmapTileIndex >= 0)
|
||||
{
|
||||
FFlatVertex* vertices = &surface->Submesh->Mesh.Vertices[surface->MeshLocation.StartVertIndex];
|
||||
srclightuv[0] = { vertices[0].lu, vertices[0].lv };
|
||||
srclightuv[1] = { vertices[1].lu, vertices[1].lv };
|
||||
srclightuv[2] = { vertices[2].lu, vertices[2].lv };
|
||||
srclightuv[3] = { vertices[3].lu, vertices[3].lv };
|
||||
lindex = vertices[0].lindex;
|
||||
LightmapTile* tile = &surface->Submesh->LightmapTiles[surface->LightmapTileIndex];
|
||||
srclightuv[0] = { tile->WallUV[0].X, tile->WallUV[0].Y };
|
||||
srclightuv[1] = { tile->WallUV[1].X, tile->WallUV[1].Y };
|
||||
srclightuv[2] = { tile->WallUV[2].X, tile->WallUV[2].Y };
|
||||
srclightuv[3] = { tile->WallUV[3].X, tile->WallUV[3].Y };
|
||||
lindex = (float)tile->AtlasLocation.ArrayIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue