mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 14:51:40 +00:00
- Add lightmaps to the main shader (currently only OpenGL)
- Create a version of CreateIndexedSectorVertices that works with lightmap sectors
This commit is contained in:
parent
39481f0d07
commit
2f8cff90b6
12 changed files with 168 additions and 13 deletions
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -61,6 +61,8 @@ public:
|
|||
FPresent3DRowShader *mPresent3dRowShader = nullptr;
|
||||
FShadowMapShader *mShadowMapShader = nullptr;
|
||||
|
||||
int mLightMapID = 0;
|
||||
|
||||
//FRotator mAngles;
|
||||
|
||||
FGLRenderer(OpenGLFrameBuffer *fb);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -24,6 +24,7 @@ enum
|
|||
VATTR_VERTEX2,
|
||||
VATTR_NORMAL,
|
||||
VATTR_NORMAL2,
|
||||
VATTR_LIGHTMAP,
|
||||
|
||||
VATTR_MAX
|
||||
};
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -160,13 +160,18 @@ TArray<VertexContainer> BuildVertices(TArray<sector_t> §ors)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue