- 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); 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) void OpenGLFrameBuffer::SetViewportRects(IntRect *bounds)
{ {
Super::SetViewportRects(bounds); Super::SetViewportRects(bounds);

View file

@ -50,6 +50,8 @@ public:
IIndexBuffer *CreateIndexBuffer() override; IIndexBuffer *CreateIndexBuffer() override;
IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override; IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override;
void InitLightmap(FLevelLocals* Level) override;
// Retrieves a buffer containing image data for a screenshot. // Retrieves a buffer containing image data for a screenshot.
// Hint: Pitch can be negative for upside-down images, in which case buffer // 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. // 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; FPresent3DRowShader *mPresent3dRowShader = nullptr;
FShadowMapShader *mShadowMapShader = nullptr; FShadowMapShader *mShadowMapShader = nullptr;
int mLightMapID = 0;
//FRotator mAngles; //FRotator mAngles;
FGLRenderer(OpenGLFrameBuffer *fb); FGLRenderer(OpenGLFrameBuffer *fb);

View file

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

View file

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

View file

@ -93,10 +93,11 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height, int pipelineNbr):
static const FVertexBufferAttribute format[] = { static const FVertexBufferAttribute format[] = {
{ 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FFlatVertex, x) }, { 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]; mVertexBuffer = mVertexBufferPipeline[mPipelinePos];

View file

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

View file

@ -44,6 +44,7 @@
#include "intrect.h" #include "intrect.h"
#include "hw_shadowmap.h" #include "hw_shadowmap.h"
#include "buffers.h" #include "buffers.h"
#include "g_levellocals.h"
struct FPortalSceneState; struct FPortalSceneState;
@ -220,7 +221,7 @@ public:
virtual int GetClientHeight() = 0; virtual int GetClientHeight() = 0;
virtual void BlurScene(float amount) {} virtual void BlurScene(float amount) {}
virtual void InitLightmap() {} virtual void InitLightmap(FLevelLocals *Level) {}
// Interface to hardware rendering resources // Interface to hardware rendering resources
virtual IVertexBuffer *CreateVertexBuffer() { return nullptr; } 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. Level->ClearDynamic3DFloorData(); // CreateVBO must be run on the plain 3D floor data.
CreateVBO(screen->mVertexData, Level->sectors); CreateVBO(screen->mVertexData, Level->sectors);
screen->InitLightmap(); screen->InitLightmap(Level);
for (auto &sec : Level->sectors) 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++) for (unsigned i = 0; i < target->e->XFloor.ffloors.Size(); i++)
{ {
F3DFloor* ffloor = target->e->XFloor.ffloors[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; 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.z = (float)plane.ZatPoint(vt);
ffv.u = (float)vt->fX() / 64.f; ffv.u = (float)vt->fX() / 64.f;
ffv.v = -(float)vt->fY() / 64.f; ffv.v = -(float)vt->fY() / 64.f;
ffv.lindex = -1.0f;
} }
static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plane, float llu, float llv, float llindex)
static int CreateIndexedSectorVertices(FFlatVertexBuffer* fvb, sector_t* sec, const secplane_t& plane, int floor, VertexContainer& verts)
{ {
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; auto& vbo_shadowdata = fvb->vbo_shadowdata;
unsigned vi = vbo_shadowdata.Reserve(verts.vertices.Size()); unsigned vi = vbo_shadowdata.Reserve(verts.vertices.Size());
float diff; 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++) for (int n = 0; n < screen->mPipelineNbr; n++)
sec->vboheight[n][h] = sec->GetPlaneTexZ(h); sec->vboheight[n][h] = sec->GetPlaneTexZ(h);
sec->ibocount = verts[sec->Index()].indices.Size(); 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 // Next are all sectors using this one as heightsec
TArray<sector_t*>& fakes = sec->e->FakeFloor.Sectors; TArray<sector_t*>& fakes = sec->e->FakeFloor.Sectors;
for (unsigned g = 0; g < fakes.Size(); g++) for (unsigned g = 0; g < fakes.Size(); g++)
{ {
sector_t* fsec = fakes[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 // 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++) for (unsigned g = 0; g < xf.Size(); g++)
{ {
sector_t* fsec = xf[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) 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) 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 (dotop) ffloor->top.vindex = ndx;
if (dobottom) ffloor->bottom.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 = 4) in vec3 gradientdist;
layout(location = 5) in vec4 vWorldNormal; layout(location = 5) in vec4 vWorldNormal;
layout(location = 6) in vec4 vEyeNormal; layout(location = 6) in vec4 vEyeNormal;
layout(location = 7) in vec3 vLightmap;
#ifdef NO_CLIPDISTANCE_SUPPORT #ifdef NO_CLIPDISTANCE_SUPPORT
layout(location = 7) in vec4 ClipDistanceA; layout(location = 7) in vec4 ClipDistanceA;
layout(location = 8) in vec4 ClipDistanceB; layout(location = 8) in vec4 ClipDistanceB;
layout(location = 9) in vec3 vLightmap;
#endif #endif
layout(location=0) out vec4 FragColor; layout(location=0) out vec4 FragColor;
@ -655,6 +657,14 @@ vec4 getLightColor(Material material, float fogdist, float fogfactor)
// //
color = ProcessLight(material, color); color = ProcessLight(material, color);
//
// apply lightmaps
//
if (vLightmap.z >= 0.0)
{
color.rgb += texture(LightMap, vLightmap).rgb;
}
// //
// apply dynamic lights // apply dynamic lights
// //

View file

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