- Add lightmaps to the main shader (currently only OpenGL)

- Create a version of CreateIndexedSectorVertices that works with lightmap sectors
This commit is contained in:
nashmuhandes 2021-09-24 16:56:15 +08:00
parent 39481f0d07
commit 2f8cff90b6
12 changed files with 168 additions and 13 deletions

View file

@ -364,6 +364,29 @@ void OpenGLFrameBuffer::BlurScene(float amount)
GLRenderer->BlurScene(amount);
}
void OpenGLFrameBuffer::InitLightmap(FLevelLocals *Level)
{
if (Level->LMTextureData.Size() > 0)
{
GLint activeTex = 0;
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex);
glActiveTexture(GL_TEXTURE0 + 17);
if (GLRenderer->mLightMapID == 0)
glGenTextures(1, (GLuint*)&GLRenderer->mLightMapID);
glBindTexture(GL_TEXTURE_2D_ARRAY, GLRenderer->mLightMapID);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB16F, Level->LMTextureSize, Level->LMTextureSize, Level->LMTextureCount, 0, GL_RGB, GL_HALF_FLOAT, &Level->LMTextureData[0]);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
glActiveTexture(activeTex);
Level->LMTextureData.Reset(); // We no longer need this, release the memory
}
}
void OpenGLFrameBuffer::SetViewportRects(IntRect *bounds)
{
Super::SetViewportRects(bounds);

View file

@ -50,6 +50,8 @@ public:
IIndexBuffer *CreateIndexBuffer() override;
IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override;
void InitLightmap(FLevelLocals* Level) override;
// Retrieves a buffer containing image data for a screenshot.
// Hint: Pitch can be negative for upside-down images, in which case buffer
// points to the last row in the buffer, which will be the first row output.

View file

@ -61,6 +61,8 @@ public:
FPresent3DRowShader *mPresent3dRowShader = nullptr;
FShadowMapShader *mShadowMapShader = nullptr;
int mLightMapID = 0;
//FRotator mAngles;
FGLRenderer(OpenGLFrameBuffer *fb);

View file

@ -298,6 +298,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
// textures
uniform sampler2D tex;
uniform sampler2D ShadowMap;
uniform sampler2DArray LightMap;
uniform sampler2D texture2;
uniform sampler2D texture3;
uniform sampler2D texture4;

View file

@ -24,6 +24,7 @@ enum
VATTR_VERTEX2,
VATTR_NORMAL,
VATTR_NORMAL2,
VATTR_LIGHTMAP,
VATTR_MAX
};

View file

@ -93,10 +93,11 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height, int pipelineNbr):
static const FVertexBufferAttribute format[] = {
{ 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FFlatVertex, x) },
{ 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) }
{ 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) },
{ 0, VATTR_LIGHTMAP, VFmt_Float3, (int)myoffsetof(FFlatVertex, lu) },
};
mVertexBufferPipeline[n]->SetFormat(1, 2, sizeof(FFlatVertex), format);
mVertexBufferPipeline[n]->SetFormat(1, 3, sizeof(FFlatVertex), format);
}
mVertexBuffer = mVertexBufferPipeline[mPipelinePos];

View file

@ -14,6 +14,8 @@ struct FFlatVertex
{
float x, z, y; // world position
float u, v; // texture coordinates
float lu, lv; // lightmap texture coordinates
float lindex; // lightmap texture index
void Set(float xx, float zz, float yy, float uu, float vv)
{
@ -22,6 +24,19 @@ struct FFlatVertex
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;
u = uu;
v = vv;
lu = llu;
lv = llv;
lindex = llindex;
}
void SetVertex(float _x, float _y, float _z = 0)

View file

@ -44,6 +44,7 @@
#include "intrect.h"
#include "hw_shadowmap.h"
#include "buffers.h"
#include "g_levellocals.h"
struct FPortalSceneState;
@ -220,7 +221,7 @@ public:
virtual int GetClientHeight() = 0;
virtual void BlurScene(float amount) {}
virtual void InitLightmap() {}
virtual void InitLightmap(FLevelLocals *Level) {}
// Interface to hardware rendering resources
virtual IVertexBuffer *CreateVertexBuffer() { return nullptr; }

View file

@ -3247,7 +3247,7 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
Level->ClearDynamic3DFloorData(); // CreateVBO must be run on the plain 3D floor data.
CreateVBO(screen->mVertexData, Level->sectors);
screen->InitLightmap();
screen->InitLightmap(Level);
for (auto &sec : Level->sectors)
{

View file

@ -160,13 +160,18 @@ TArray<VertexContainer> BuildVertices(TArray<sector_t> &sectors)
//
//==========================================================================
static F3DFloor* Find3DFloor(sector_t* target, sector_t* model)
static F3DFloor *Find3DFloor(sector_t* target, sector_t* model, int &ffloorIndex)
{
for (unsigned i = 0; i < target->e->XFloor.ffloors.Size(); i++)
{
F3DFloor* ffloor = target->e->XFloor.ffloors[i];
if (ffloor->model == model && !(ffloor->flags & FF_THISINSIDE)) return ffloor;
if (ffloor->model == model && !(ffloor->flags & FF_THISINSIDE))
{
ffloorIndex = i;
return ffloor;
}
}
ffloorIndex = -1;
return NULL;
}
@ -183,12 +188,99 @@ static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plan
ffv.z = (float)plane.ZatPoint(vt);
ffv.u = (float)vt->fX() / 64.f;
ffv.v = -(float)vt->fY() / 64.f;
ffv.lindex = -1.0f;
}
static int CreateIndexedSectorVertices(FFlatVertexBuffer* fvb, sector_t* sec, const secplane_t& plane, int floor, VertexContainer& verts)
static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plane, float llu, float llv, float llindex)
{
ffv.x = (float)vt->fX();
ffv.y = (float)vt->fY();
ffv.z = (float)plane.ZatPoint(vt);
ffv.u = (float)vt->fX() / 64.f;
ffv.v = -(float)vt->fY() / 64.f;
ffv.lu = llu;
ffv.lv = llv;
ffv.lindex = llindex;
}
//==========================================================================
//
// Creates the vertices for one plane in one subsector w/lightmap support.
// Sectors with lightmaps cannot share subsector vertices.
//
//==========================================================================
static int CreateIndexedSectorVerticesLM(FFlatVertexBuffer* fvb, sector_t* sec, const secplane_t& plane, int floor, int h, int lightmapIndex)
{
int i, pos;
float diff;
auto& ibo_data = fvb->ibo_data;
int rt = ibo_data.Size();
if (sec->transdoor && floor) diff = -1.f;
else diff = 0.f;
// Allocate space
for (i = 0, pos = 0; i < sec->subsectorcount; i++)
{
pos += sec->subsectors[i]->numlines;
}
auto& vbo_shadowdata = fvb->vbo_shadowdata;
int vi = vbo_shadowdata.Reserve(pos);
int idx = ibo_data.Reserve((pos - 2 * sec->subsectorcount) * 3);
// Create the actual vertices.
for (i = 0, pos = 0; i < sec->subsectorcount; i++)
{
subsector_t* sub = sec->subsectors[i];
LightmapSurface* lightmap = &sub->lightmap[h][lightmapIndex];
if (lightmap->Type != ST_NULL)
{
float* luvs = lightmap->TexCoords;
int lindex = lightmap->LightmapNum;
for (unsigned int j = 0; j < sub->numlines; j++)
{
SetFlatVertex(vbo_shadowdata[vi + pos], sub->firstline->v1, plane, luvs[j * 2], luvs[j * 2 + 1], lindex);
vbo_shadowdata[vi + pos].z += diff;
pos++;
}
}
else
{
for (unsigned int j = 0; j < sub->numlines; j++)
{
SetFlatVertex(vbo_shadowdata[vi + pos], sub->firstline->v1, plane);
vbo_shadowdata[vi + pos].z += diff;
pos++;
}
}
}
// Create the indices for the subsectors
for (int i = 0; i < sec->subsectorcount; i++)
{
subsector_t* sub = sec->subsectors[i];
int firstndx = vi + pos;
for (unsigned int k = 2; k < sub->numlines; k++)
{
ibo_data[idx++] = firstndx;
ibo_data[idx++] = firstndx + k - 1;
ibo_data[idx++] = firstndx + k;
}
pos += sec->subsectors[i]->numlines;
}
sec->ibocount = ibo_data.Size() - rt;
return rt;
}
static int CreateIndexedSectorVertices(FFlatVertexBuffer* fvb, sector_t* sec, const secplane_t& plane, int floor, VertexContainer& verts, int h, int lightmapIndex)
{
if (sec->HasLightmaps && lightmapIndex != -1)
return CreateIndexedSectorVerticesLM(fvb, sec, plane, floor, h, lightmapIndex);
auto& vbo_shadowdata = fvb->vbo_shadowdata;
unsigned vi = vbo_shadowdata.Reserve(verts.vertices.Size());
float diff;
@ -225,14 +317,14 @@ static int CreateIndexedVertices(FFlatVertexBuffer* fvb, int h, sector_t* sec, c
for (int n = 0; n < screen->mPipelineNbr; n++)
sec->vboheight[n][h] = sec->GetPlaneTexZ(h);
sec->ibocount = verts[sec->Index()].indices.Size();
sec->iboindex[h] = CreateIndexedSectorVertices(fvb, sec, plane, floor, verts[sec->Index()]);
sec->iboindex[h] = CreateIndexedSectorVertices(fvb, sec, plane, floor, verts[sec->Index()], h, 0);
// Next are all sectors using this one as heightsec
TArray<sector_t*>& fakes = sec->e->FakeFloor.Sectors;
for (unsigned g = 0; g < fakes.Size(); g++)
{
sector_t* fsec = fakes[g];
fsec->iboindex[2 + h] = CreateIndexedSectorVertices(fvb, fsec, plane, false, verts[fsec->Index()]);
fsec->iboindex[2 + h] = CreateIndexedSectorVertices(fvb, fsec, plane, false, verts[fsec->Index()], h, -1);
}
// and finally all attached 3D floors
@ -240,7 +332,8 @@ static int CreateIndexedVertices(FFlatVertexBuffer* fvb, int h, sector_t* sec, c
for (unsigned g = 0; g < xf.Size(); g++)
{
sector_t* fsec = xf[g];
F3DFloor* ffloor = Find3DFloor(fsec, sec);
int ffloorIndex;
F3DFloor* ffloor = Find3DFloor(fsec, sec, ffloorIndex);
if (ffloor != NULL && ffloor->flags & FF_RENDERPLANES)
{
@ -249,7 +342,7 @@ static int CreateIndexedVertices(FFlatVertexBuffer* fvb, int h, sector_t* sec, c
if (dotop || dobottom)
{
auto ndx = CreateIndexedSectorVertices(fvb, fsec, plane, false, verts[fsec->Index()]);
auto ndx = CreateIndexedSectorVertices(fvb, fsec, plane, false, verts[fsec->Index()], h, ffloorIndex + 1);
if (dotop) ffloor->top.vindex = ndx;
if (dobottom) ffloor->bottom.vindex = ndx;
}

View file

@ -7,10 +7,12 @@ layout(location = 3) in vec3 glowdist;
layout(location = 4) in vec3 gradientdist;
layout(location = 5) in vec4 vWorldNormal;
layout(location = 6) in vec4 vEyeNormal;
layout(location = 7) in vec3 vLightmap;
#ifdef NO_CLIPDISTANCE_SUPPORT
layout(location = 7) in vec4 ClipDistanceA;
layout(location = 8) in vec4 ClipDistanceB;
layout(location = 9) in vec3 vLightmap;
#endif
layout(location=0) out vec4 FragColor;
@ -655,6 +657,14 @@ vec4 getLightColor(Material material, float fogdist, float fogfactor)
//
color = ProcessLight(material, color);
//
// apply lightmaps
//
if (vLightmap.z >= 0.0)
{
color.rgb += texture(LightMap, vLightmap).rgb;
}
//
// apply dynamic lights
//

View file

@ -5,6 +5,7 @@ layout(location = 2) in vec4 aColor;
layout(location = 0) out vec4 vTexCoord;
layout(location = 1) out vec4 vColor;
layout(location = 2) out vec3 vLightmap;
#ifndef SIMPLE // we do not need these for simple shaders
layout(location = 3) in vec4 aVertex2;
@ -16,11 +17,14 @@ layout(location = 3) out vec3 glowdist;
layout(location = 4) out vec3 gradientdist;
layout(location = 5) out vec4 vWorldNormal;
layout(location = 6) out vec4 vEyeNormal;
layout(location = 7) in vec3 aLightmap;
#endif
#ifdef NO_CLIPDISTANCE_SUPPORT
layout(location = 7) out vec4 ClipDistanceA;
layout(location = 8) out vec4 ClipDistanceB;
layout(location = 9) in vec3 aLightmap;
#endif
void main()
@ -51,6 +55,8 @@ void main()
#endif
#ifndef SIMPLE
vLightmap = aLightmap;
pixelpos.xyz = worldcoord.xyz;
pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w;