- use the light buffer to handle dynamic lighting.

This commit is contained in:
Christoph Oelckers 2014-08-01 20:59:39 +02:00
parent 01a1e10084
commit 7967082e60
17 changed files with 194 additions and 197 deletions

View file

@ -144,36 +144,3 @@ bool gl_GetLight(Plane & p, ADynamicLight * light, bool checkside, bool forceadd
} }
//==========================================================================
//
//
//
//==========================================================================
#if 0
void gl_UploadLights(FDynLightData &data)
{
ParameterBufferElement *pptr;
int size0 = data.arrays[0].Size()/4;
int size1 = data.arrays[1].Size()/4;
int size2 = data.arrays[2].Size()/4;
if (size0 + size1 + size2 > 0)
{
int sizetotal = size0 + size1 + size2 + 1;
int index = GLRenderer->mParmBuffer->Reserve(sizetotal, &pptr);
float parmcnt[] = { index + 1, index + 1 + size0, index + 1 + size0 + size1, index + 1 + size0 + size1 + size2 };
memcpy(&pptr[0], parmcnt, 4 * sizeof(float));
memcpy(&pptr[1], &data.arrays[0][0], 4 * size0*sizeof(float));
memcpy(&pptr[1 + size0], &data.arrays[1][0], 4 * size1*sizeof(float));
memcpy(&pptr[1 + size0 + size1], &data.arrays[2][0], 4 * size2*sizeof(float));
gl_RenderState.SetDynLightIndex(index);
}
else
{
gl_RenderState.SetDynLightIndex(-1);
}
}
#endif

View file

@ -39,93 +39,79 @@
*/ */
#include "gl/system/gl_system.h" #include "gl/system/gl_system.h"
#include "gl/shaders/gl_shader.h"
#include "gl/dynlights/gl_lightbuffer.h" #include "gl/dynlights/gl_lightbuffer.h"
#include "gl/dynlights/gl_dynlight.h" #include "gl/dynlights/gl_dynlight.h"
#include "gl/system/gl_interface.h" #include "gl/system/gl_interface.h"
#include "gl/utility//gl_clock.h"
static const int LIGHTBUF_BINDINGPOINT = 1; static const int BUFFER_SIZE = 160000; // This means 80000 lights per frame and 160000*16 bytes == 2.56 MB.
FLightBuffer::FLightBuffer() FLightBuffer::FLightBuffer()
{ {
if (gl.flags & RFL_SHADER_STORAGE_BUFFER) if (gl.flags & RFL_SHADER_STORAGE_BUFFER)
{ {
mBufferType = GL_SHADER_STORAGE_BUFFER; mBufferType = GL_SHADER_STORAGE_BUFFER;
mBufferSize = 80000; // 40000 lights per scene should be plenty. The largest I've ever seen was around 5000. mBlockAlign = 0;
} }
else else
{ {
mBufferType = GL_UNIFORM_BUFFER; mBufferType = GL_UNIFORM_BUFFER;
mBufferSize = gl.maxuniformblock / 4 - 100; // we need to be a bit careful here so don't use the full buffer size mBlockSize = 2048;// gl.maxuniformblock / 4 - 100;
mBlockAlign = 1024;// ((mBlockSize * 2) & ~(gl.uniformblockalignment - 1)) / 4; // count in vec4's
} }
AddBuffer();
glGenBuffers(1, &mBufferId);
glBindBuffer(mBufferType, mBufferId);
unsigned int bytesize = BUFFER_SIZE * 4 * sizeof(float);
if (gl.flags & RFL_BUFFER_STORAGE)
{
glBufferStorage(mBufferType, bytesize, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
void *map = glMapBufferRange(mBufferType, 0, bytesize, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
mBufferPointer = (float*)map;
glBindBufferBase(mBufferType, LIGHTBUF_BINDINGPOINT, mBufferId);
}
else
{
glBufferData(mBufferType, bytesize, NULL, GL_STREAM_DRAW);
mBufferPointer = NULL;
}
Clear(); Clear();
mLastMappedIndex = UINT_MAX;
} }
FLightBuffer::~FLightBuffer() FLightBuffer::~FLightBuffer()
{ {
glBindBuffer(mBufferType, 0); glBindBuffer(mBufferType, 0);
for (unsigned int i = 0; i < mBufferIds.Size(); i++) glDeleteBuffers(1, &mBufferId);
{
glDeleteBuffers(1, &mBufferIds[i]);
}
}
void FLightBuffer::AddBuffer()
{
unsigned int id;
glGenBuffers(1, &id);
mBufferIds.Push(id);
glBindBuffer(mBufferType, id);
unsigned int bytesize = mBufferSize * 8 * sizeof(float);
if (gl.flags & RFL_BUFFER_STORAGE)
{
glBufferStorage(mBufferType, bytesize, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
void *map = glMapBufferRange(mBufferType, 0, bytesize, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
mBufferPointers.Push((float*)map);
}
else
{
glBufferData(mBufferType, bytesize, NULL, GL_STREAM_DRAW);
}
} }
void FLightBuffer::Clear() void FLightBuffer::Clear()
{ {
mBufferNum = 0;
mIndex = 0; mIndex = 0;
mBufferArray.Clear(); mBufferArray.Clear();
mBufferStart.Clear();
} }
void FLightBuffer::UploadLights(FDynLightData &data, unsigned int &buffernum, unsigned int &bufferindex) int FLightBuffer::UploadLights(FDynLightData &data)
{ {
int size0 = data.arrays[0].Size()/4; int size0 = data.arrays[0].Size()/4;
int size1 = data.arrays[1].Size()/4; int size1 = data.arrays[1].Size()/4;
int size2 = data.arrays[2].Size()/4; int size2 = data.arrays[2].Size()/4;
int totalsize = size0 + size1 + size2 + 1; int totalsize = size0 + size1 + size2 + 1;
if (totalsize == 0) return; if (totalsize <= 1) return -1;
if (mIndex + totalsize > mBufferSize) if (mIndex + totalsize > BUFFER_SIZE)
{ {
if (gl.flags & RFL_SHADER_STORAGE_BUFFER) return -1; // we ran out of space. All following lights will be ignored
{
return; // we do not want multiple shader storage blocks. 40000 lights is too much already
}
else
{
mBufferNum++;
mBufferStart.Push(mIndex);
mIndex = 0;
if (mBufferIds.Size() <= mBufferNum) AddBuffer();
}
} }
float *copyptr; float *copyptr;
if (gl.flags & RFL_BUFFER_STORAGE) if (mBufferPointer != NULL)
{ {
copyptr = mBufferPointers[mBufferNum] + mIndex * 4; copyptr = mBufferPointer + mIndex * 4;
} }
else else
{ {
@ -133,20 +119,48 @@ void FLightBuffer::UploadLights(FDynLightData &data, unsigned int &buffernum, un
copyptr = &mBufferArray[pos]; copyptr = &mBufferArray[pos];
} }
float parmcnt[] = { mIndex + 1, mIndex + 1 + size0, mIndex + 1 + size0 + size1, mIndex + totalsize }; float parmcnt[] = { 0, size0, size0 + size1, size0 + size1 + size2 };
memcpy(&copyptr[0], parmcnt, 4 * sizeof(float)); memcpy(&copyptr[0], parmcnt, 4 * sizeof(float));
memcpy(&copyptr[1], &data.arrays[0][0], 4 * size0*sizeof(float)); memcpy(&copyptr[4], &data.arrays[0][0], 4 * size0*sizeof(float));
memcpy(&copyptr[1 + size0], &data.arrays[1][0], 4 * size1*sizeof(float)); memcpy(&copyptr[4 + 4*size0], &data.arrays[1][0], 4 * size1*sizeof(float));
memcpy(&copyptr[1 + size0 + size1], &data.arrays[2][0], 4 * size2*sizeof(float)); memcpy(&copyptr[4 + 4*(size0 + size1)], &data.arrays[2][0], 4 * size2*sizeof(float));
buffernum = mBufferNum;
bufferindex = mIndex; if (mBufferPointer == NULL) // if we can't persistently map the buffer we need to upload it after all lights have been added.
{
glBindBuffer(mBufferType, mBufferId);
glBufferSubData(mBufferType, mIndex, totalsize * 4 * sizeof(float), copyptr);
}
unsigned int bufferindex = mIndex;
mIndex += totalsize; mIndex += totalsize;
draw_dlight += (totalsize-1) / 2;
return bufferindex;
} }
void FLightBuffer::Finish() void FLightBuffer::Finish()
{ {
//glBindBufferBase(mBufferType, LIGHTBUF_BINDINGPOINT, mBufferIds[0]); /*
if (!(gl.flags & RFL_BUFFER_STORAGE)) // if we can't persistently map the buffer we need to upload it after all lights have been added.
{
glBindBuffer(mBufferType, mBufferId);
glBufferSubData(mBufferType, 0, mBufferArray.Size() * sizeof(float), &mBufferArray[0]);
}
*/
Clear();
}
int FLightBuffer::BindUBO(unsigned int index)
{
unsigned int offset = (index / mBlockAlign) * mBlockAlign;
if (offset != mLastMappedIndex)
{
// this will only get called if a uniform buffer is used. For a shader storage buffer we only need to bind the buffer once at the start to all shader programs
mLastMappedIndex = offset;
glBindBufferRange(GL_UNIFORM_BUFFER, LIGHTBUF_BINDINGPOINT, mBufferId, offset*16, mBlockSize*16); // we go from counting vec4's to counting bytes here.
}
return (index - offset);
} }

View file

@ -7,23 +7,25 @@ struct FDynLightData;
class FLightBuffer class FLightBuffer
{ {
TArray<float> mBufferArray; TArray<float> mBufferArray;
TArray<unsigned int> mBufferIds; unsigned int mBufferId;
TArray<unsigned int> mBufferStart; float * mBufferPointer;
TArray<float *> mBufferPointers;
unsigned int mBufferType;
unsigned int mBufferSize;
unsigned int mIndex;
unsigned int mBufferNum;
void AddBuffer(); unsigned int mBufferType;
unsigned int mIndex;
unsigned int mLastMappedIndex;
unsigned int mBlockAlign;
unsigned int mBlockSize;
public: public:
FLightBuffer(); FLightBuffer();
~FLightBuffer(); ~FLightBuffer();
void Clear(); void Clear();
void UploadLights(FDynLightData &data, unsigned int &buffernum, unsigned int &bufferindex); int UploadLights(FDynLightData &data);
void Finish(); void Finish();
int BindUBO(unsigned int index);
unsigned int GetBlockSize() const { return mBlockSize; }
unsigned int GetBufferType() const { return mBufferType; }
}; };
#endif #endif

View file

@ -67,6 +67,7 @@
#include "gl/utility/gl_clock.h" #include "gl/utility/gl_clock.h"
#include "gl/utility/gl_templates.h" #include "gl/utility/gl_templates.h"
#include "gl/models/gl_models.h" #include "gl/models/gl_models.h"
#include "gl/dynlights/gl_lightbuffer.h"
//=========================================================================== //===========================================================================
// //
@ -97,6 +98,7 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
gl_spriteindex = 0; gl_spriteindex = 0;
mShaderManager = NULL; mShaderManager = NULL;
glpart2 = glpart = mirrortexture = NULL; glpart2 = glpart = mirrortexture = NULL;
mLights = NULL;
} }
void FGLRenderer::Initialize() void FGLRenderer::Initialize()
@ -108,6 +110,7 @@ void FGLRenderer::Initialize()
mVBO = new FFlatVertexBuffer; mVBO = new FFlatVertexBuffer;
mSkyVBO = new FSkyVertexBuffer; mSkyVBO = new FSkyVertexBuffer;
mModelVBO = new FModelVertexBuffer; mModelVBO = new FModelVertexBuffer;
mLights = new FLightBuffer;
gl_RenderState.SetVertexBuffer(mVBO); gl_RenderState.SetVertexBuffer(mVBO);
mFBID = 0; mFBID = 0;
SetupLevel(); SetupLevel();
@ -124,6 +127,7 @@ FGLRenderer::~FGLRenderer()
if (mVBO != NULL) delete mVBO; if (mVBO != NULL) delete mVBO;
if (mModelVBO) delete mModelVBO; if (mModelVBO) delete mModelVBO;
if (mSkyVBO != NULL) delete mSkyVBO; if (mSkyVBO != NULL) delete mSkyVBO;
if (mLights != NULL) delete mLights;
if (glpart2) delete glpart2; if (glpart2) delete glpart2;
if (glpart) delete glpart; if (glpart) delete glpart;
if (mirrortexture) delete mirrortexture; if (mirrortexture) delete mirrortexture;

View file

@ -17,6 +17,7 @@ struct pspdef_t;
class FShaderManager; class FShaderManager;
class GLPortal; class GLPortal;
class FGLThreadManager; class FGLThreadManager;
class FLightBuffer;
enum SectorRenderFlags enum SectorRenderFlags
{ {
@ -72,6 +73,7 @@ public:
FFlatVertexBuffer *mVBO; FFlatVertexBuffer *mVBO;
FSkyVertexBuffer *mSkyVBO; FSkyVertexBuffer *mSkyVBO;
FModelVertexBuffer *mModelVBO; FModelVertexBuffer *mModelVBO;
FLightBuffer *mLights;
FGLRenderer(OpenGLFrameBuffer *fb); FGLRenderer(OpenGLFrameBuffer *fb);

View file

@ -48,6 +48,7 @@
#include "gl/renderer/gl_renderer.h" #include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderstate.h" #include "gl/renderer/gl_renderstate.h"
#include "gl/renderer/gl_colormap.h" #include "gl/renderer/gl_colormap.h"
#include "gl/dynlights//gl_lightbuffer.h"
void gl_SetTextureMode(int type); void gl_SetTextureMode(int type);
@ -68,9 +69,10 @@ TArray<VSMatrix> gl_MatrixStack;
void FRenderState::Reset() void FRenderState::Reset()
{ {
mTextureEnabled = true; mTextureEnabled = true;
mBrightmapEnabled = mFogEnabled = mGlowEnabled = mLightEnabled = false; mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
mFogColor.d = -1; mFogColor.d = -1;
mTextureMode = -1; mTextureMode = -1;
mLightIndex = -1;
mDesaturation = 0; mDesaturation = 0;
mSrcBlend = GL_SRC_ALPHA; mSrcBlend = GL_SRC_ALPHA;
mDstBlend = GL_ONE_MINUS_SRC_ALPHA; mDstBlend = GL_ONE_MINUS_SRC_ALPHA;
@ -98,7 +100,6 @@ void FRenderState::Reset()
bool FRenderState::ApplyShader() bool FRenderState::ApplyShader()
{ {
FShader *activeShader;
if (mSpecialEffect > EFF_NONE) if (mSpecialEffect > EFF_NONE)
{ {
activeShader = GLRenderer->mShaderManager->BindEffect(mSpecialEffect); activeShader = GLRenderer->mShaderManager->BindEffect(mSpecialEffect);
@ -139,6 +140,7 @@ bool FRenderState::ApplyShader()
activeShader->muClipHeightBottom.Set(mClipHeightBottom); activeShader->muClipHeightBottom.Set(mClipHeightBottom);
activeShader->muTimer.Set(gl_frameMS * mShaderTimer / 1000.f); activeShader->muTimer.Set(gl_frameMS * mShaderTimer / 1000.f);
activeShader->muAlphaThreshold.Set(mAlphaThreshold); activeShader->muAlphaThreshold.Set(mAlphaThreshold);
activeShader->muLightIndex.Set(mLightIndex); // will always be -1 for now
if (mGlowEnabled) if (mGlowEnabled)
{ {
@ -159,17 +161,6 @@ bool FRenderState::ApplyShader()
activeShader->currentglowstate = 0; activeShader->currentglowstate = 0;
} }
if (mLightEnabled)
{
activeShader->muLightRange.Set(mNumLights);
glUniform4fv(activeShader->lights_index, mNumLights[3], mLightData);
}
else
{
static const int nulint[] = { 0, 0, 0, 0 };
activeShader->muLightRange.Set(nulint);
}
if (mColormapState != activeShader->currentfixedcolormap) if (mColormapState != activeShader->currentfixedcolormap)
{ {
float r, g, b; float r, g, b;
@ -282,3 +273,12 @@ void FRenderState::ApplyMatrices()
GLRenderer->mShaderManager->ApplyMatrices(&mProjectionMatrix, &mViewMatrix); GLRenderer->mShaderManager->ApplyMatrices(&mProjectionMatrix, &mViewMatrix);
} }
} }
void FRenderState::ApplyLightIndex(int index)
{
if (GLRenderer->mLights->GetBufferType() == GL_UNIFORM_BUFFER && index > -1)
{
index = GLRenderer->mLights->BindUBO(index);
}
activeShader->muLightIndex.Set(index);
}

View file

@ -9,6 +9,7 @@
#include "r_defs.h" #include "r_defs.h"
class FVertexBuffer; class FVertexBuffer;
class FShader;
extern TArray<VSMatrix> gl_MatrixStack; extern TArray<VSMatrix> gl_MatrixStack;
EXTERN_CVAR(Bool, gl_direct_state_change) EXTERN_CVAR(Bool, gl_direct_state_change)
@ -43,24 +44,22 @@ class FRenderState
bool mTextureEnabled; bool mTextureEnabled;
bool mFogEnabled; bool mFogEnabled;
bool mGlowEnabled; bool mGlowEnabled;
bool mLightEnabled;
bool mBrightmapEnabled; bool mBrightmapEnabled;
int mLightIndex;
int mSpecialEffect; int mSpecialEffect;
int mTextureMode; int mTextureMode;
int mDesaturation; int mDesaturation;
int mSoftLight; int mSoftLight;
float mLightParms[4]; float mLightParms[4];
int mNumLights[4];
float *mLightData;
int mSrcBlend, mDstBlend; int mSrcBlend, mDstBlend;
float mAlphaThreshold; float mAlphaThreshold;
bool mAlphaTest;
int mBlendEquation; int mBlendEquation;
bool mAlphaTest;
bool m2D; bool m2D;
float mInterpolationFactor;
float mClipHeightTop, mClipHeightBottom;
bool mModelMatrixEnabled; bool mModelMatrixEnabled;
bool mTextureMatrixEnabled; bool mTextureMatrixEnabled;
float mInterpolationFactor;
float mClipHeightTop, mClipHeightBottom;
float mShaderTimer; float mShaderTimer;
FVertexBuffer *mVertexBuffer, *mCurrentVertexBuffer; FVertexBuffer *mVertexBuffer, *mCurrentVertexBuffer;
@ -80,6 +79,8 @@ class FRenderState
bool stAlphaTest; bool stAlphaTest;
int stBlendEquation; int stBlendEquation;
FShader *activeShader;
bool ApplyShader(); bool ApplyShader();
public: public:
@ -104,6 +105,7 @@ public:
void Apply(); void Apply();
void ApplyMatrices(); void ApplyMatrices();
void ApplyLightIndex(int index);
void SetVertexBuffer(FVertexBuffer *vb) void SetVertexBuffer(FVertexBuffer *vb)
{ {
@ -185,9 +187,9 @@ public:
mGlowEnabled = on; mGlowEnabled = on;
} }
void EnableLight(bool on) void SetLightIndex(int n)
{ {
mLightEnabled = on; mLightIndex = n;
} }
void EnableBrightmap(bool on) void EnableBrightmap(bool on)
@ -251,15 +253,6 @@ public:
mLightParms[0] = d; mLightParms[0] = d;
} }
void SetLights(int *numlights, float *lightdata)
{
mNumLights[0] = 0;
mNumLights[1] = numlights[0];
mNumLights[2] = numlights[1];
mNumLights[3] = numlights[2];
mLightData = lightdata; // caution: the data must be preserved by the caller until the 'apply' call!
}
void SetFixedColormap(int cm) void SetFixedColormap(int cm)
{ {
mColormapState = cm; mColormapState = cm;

View file

@ -56,6 +56,7 @@
#include "gl/data/gl_vertexbuffer.h" #include "gl/data/gl_vertexbuffer.h"
#include "gl/dynlights/gl_dynlight.h" #include "gl/dynlights/gl_dynlight.h"
#include "gl/dynlights/gl_glow.h" #include "gl/dynlights/gl_glow.h"
#include "gl/dynlights/gl_lightbuffer.h"
#include "gl/scene/gl_drawinfo.h" #include "gl/scene/gl_drawinfo.h"
#include "gl/shaders/gl_shader.h" #include "gl/shaders/gl_shader.h"
#include "gl/textures/gl_material.h" #include "gl/textures/gl_material.h"
@ -142,22 +143,8 @@ bool GLFlat::SetupSubsectorLights(bool lightsapplied, subsector_t * sub)
node = node->nextLight; node = node->nextLight;
} }
int numlights[3]; dynlightindex = GLRenderer->mLights->UploadLights(lightdata);
gl_RenderState.ApplyLightIndex(dynlightindex);
lightdata.Combine(numlights, gl.MaxLights());
if (numlights[2] > 0)
{
draw_dlightf+=numlights[2]/2;
gl_RenderState.EnableLight(true);
gl_RenderState.SetLights(numlights, &lightdata.arrays[0][0]);
gl_RenderState.Apply();
return true;
}
if (lightsapplied)
{
gl_RenderState.EnableLight(false);
gl_RenderState.Apply();
}
return false; return false;
} }
@ -271,7 +258,6 @@ void GLFlat::DrawSubsectors(int pass, bool istrans)
} }
} }
} }
gl_RenderState.EnableLight(false);
} }
@ -450,6 +436,7 @@ void GLFlat::ProcessSector(sector_t * frontsector)
sector=&sectors[frontsector->sectornum]; sector=&sectors[frontsector->sectornum];
extsector_t::xfloor &x = sector->e->XFloor; extsector_t::xfloor &x = sector->e->XFloor;
this->sub=NULL; this->sub=NULL;
dynlightindex = -1;
byte &srf = gl_drawinfo->sectorrenderflags[sector->sectornum]; byte &srf = gl_drawinfo->sectorrenderflags[sector->sectornum];

View file

@ -57,6 +57,7 @@
#include "p_local.h" #include "p_local.h"
#include "gl/gl_functions.h" #include "gl/gl_functions.h"
#include "gl/dynlights/gl_lightbuffer.h"
#include "gl/system/gl_interface.h" #include "gl/system/gl_interface.h"
#include "gl/system/gl_framebuffer.h" #include "gl/system/gl_framebuffer.h"
#include "gl/system/gl_cvars.h" #include "gl/system/gl_cvars.h"
@ -348,6 +349,7 @@ void FGLRenderer::RenderScene(int recursion)
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
glDisable(GL_POLYGON_OFFSET_FILL); // just in case glDisable(GL_POLYGON_OFFSET_FILL); // just in case
GLRenderer->mLights->Finish();
int pass; int pass;

View file

@ -135,7 +135,7 @@ public:
float topglowcolor[4]; float topglowcolor[4];
float bottomglowcolor[4]; float bottomglowcolor[4];
unsigned int dynlightindex, dynlightbuffer; int dynlightindex;
int firstwall, numwalls; // splitting info. int firstwall, numwalls; // splitting info.
union union

View file

@ -53,6 +53,7 @@
#include "gl/data/gl_vertexbuffer.h" #include "gl/data/gl_vertexbuffer.h"
#include "gl/dynlights/gl_dynlight.h" #include "gl/dynlights/gl_dynlight.h"
#include "gl/dynlights/gl_glow.h" #include "gl/dynlights/gl_glow.h"
#include "gl/dynlights/gl_lightbuffer.h"
#include "gl/scene/gl_drawinfo.h" #include "gl/scene/gl_drawinfo.h"
#include "gl/scene/gl_portal.h" #include "gl/scene/gl_portal.h"
#include "gl/shaders/gl_shader.h" #include "gl/shaders/gl_shader.h"
@ -150,15 +151,8 @@ void GLWall::SetupLights()
} }
node = node->nextLight; node = node->nextLight;
} }
int numlights[3];
lightdata.Combine(numlights, gl.MaxLights()); dynlightindex = GLRenderer->mLights->UploadLights(lightdata);
if (numlights[2] > 0)
{
draw_dlight+=numlights[2]/2;
gl_RenderState.EnableLight(true);
gl_RenderState.SetLights(numlights, &lightdata.arrays[0][0]);
}
} }
@ -187,6 +181,7 @@ void GLWall::RenderWall(int textured, unsigned int *store)
if (!(textured & RWF_NORENDER)) if (!(textured & RWF_NORENDER))
{ {
gl_RenderState.Apply(); gl_RenderState.Apply();
gl_RenderState.ApplyLightIndex(dynlightindex);
} }
// the rest of the code is identical for textured rendering and lights // the rest of the code is identical for textured rendering and lights
@ -383,7 +378,6 @@ void GLWall::Draw(int pass)
gltexture->Bind(flags, 0); gltexture->Bind(flags, 0);
RenderWall(RWF_TEXTURED|RWF_GLOW); RenderWall(RWF_TEXTURED|RWF_GLOW);
gl_RenderState.EnableGlow(false); gl_RenderState.EnableGlow(false);
gl_RenderState.EnableLight(false);
break; break;
case GLPASS_DECALS: case GLPASS_DECALS:

View file

@ -57,6 +57,7 @@
#include "gl/system/gl_cvars.h" #include "gl/system/gl_cvars.h"
#include "gl/shaders/gl_shader.h" #include "gl/shaders/gl_shader.h"
#include "gl/textures/gl_material.h" #include "gl/textures/gl_material.h"
#include "gl/dynlights/gl_lightbuffer.h"
//========================================================================== //==========================================================================
// //
@ -86,10 +87,19 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
// //
// The following code uses GetChars on the strings to get rid of terminating 0 characters. Do not remove or the code may break! // The following code uses GetChars on the strings to get rid of terminating 0 characters. Do not remove or the code may break!
// //
unsigned int lightbuffertype = GLRenderer->mLights->GetBufferType();
unsigned int lightbuffersize = GLRenderer->mLights->GetBlockSize();
FString vp_comb = "#version 130\n"; FString vp_comb;
// todo when using shader storage buffers, add
// "#version 400 compatibility\n#extension GL_ARB_shader_storage_buffer_object : require\n" instead. if (lightbuffertype == GL_UNIFORM_BUFFER)
{
vp_comb.Format("#version 130\n#extension GL_ARB_uniform_buffer_object : require\n#define NUM_UBO_LIGHTS %d\n", lightbuffersize);
}
else
{
vp_comb = "#version 400 compatibility\n#extension GL_ARB_shader_storage_buffer_object : require\n#define SHADER_STORAGE_LIGHTS\n";
}
if (!(gl.flags & RFL_BUFFER_STORAGE)) if (!(gl.flags & RFL_BUFFER_STORAGE))
{ {
@ -196,7 +206,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
muLightParms.Init(hShader, "uLightAttr"); muLightParms.Init(hShader, "uLightAttr");
muColormapStart.Init(hShader, "uFixedColormapStart"); muColormapStart.Init(hShader, "uFixedColormapStart");
muColormapRange.Init(hShader, "uFixedColormapRange"); muColormapRange.Init(hShader, "uFixedColormapRange");
muLightRange.Init(hShader, "uLightRange"); muLightIndex.Init(hShader, "uLightIndex");
muFogColor.Init(hShader, "uFogColor"); muFogColor.Init(hShader, "uFogColor");
muDynLightColor.Init(hShader, "uDynLightColor"); muDynLightColor.Init(hShader, "uDynLightColor");
muObjectColor.Init(hShader, "uObjectColor"); muObjectColor.Init(hShader, "uObjectColor");
@ -218,10 +228,13 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
modelmatrix_index = glGetUniformLocation(hShader, "ModelMatrix"); modelmatrix_index = glGetUniformLocation(hShader, "ModelMatrix");
texturematrix_index = glGetUniformLocation(hShader, "TextureMatrix"); texturematrix_index = glGetUniformLocation(hShader, "TextureMatrix");
int tempindex = glGetUniformBlockIndex(hShader, "LightBufferUBO");
if (tempindex != -1) glUniformBlockBinding(hShader, tempindex, LIGHTBUF_BINDINGPOINT);
glUseProgram(hShader); glUseProgram(hShader);
int texture_index = glGetUniformLocation(hShader, "texture2"); tempindex = glGetUniformLocation(hShader, "texture2");
if (texture_index > 0) glUniform1i(texture_index, 1); if (tempindex > 0) glUniform1i(tempindex, 1);
glUseProgram(0); glUseProgram(0);
return !!linked; return !!linked;

View file

@ -187,7 +187,7 @@ class FShader
FUniform1i muFixedColormap; FUniform1i muFixedColormap;
FUniform4f muColormapStart; FUniform4f muColormapStart;
FUniform4f muColormapRange; FUniform4f muColormapRange;
FBufferedUniform4i muLightRange; FBufferedUniform1i muLightIndex;
FBufferedUniformPE muFogColor; FBufferedUniformPE muFogColor;
FBufferedUniform4f muDynLightColor; FBufferedUniform4f muDynLightColor;
FBufferedUniformPE muObjectColor; FBufferedUniformPE muObjectColor;
@ -281,6 +281,10 @@ public:
#define FIRST_USER_SHADER 12 #define FIRST_USER_SHADER 12
enum
{
LIGHTBUF_BINDINGPOINT = 1
};
#endif #endif

View file

@ -133,6 +133,7 @@ void gl_LoadExtensions()
if (CheckExtension("GL_ARB_texture_compression")) gl.flags|=RFL_TEXTURE_COMPRESSION; if (CheckExtension("GL_ARB_texture_compression")) gl.flags|=RFL_TEXTURE_COMPRESSION;
if (CheckExtension("GL_EXT_texture_compression_s3tc")) gl.flags|=RFL_TEXTURE_COMPRESSION_S3TC; if (CheckExtension("GL_EXT_texture_compression_s3tc")) gl.flags|=RFL_TEXTURE_COMPRESSION_S3TC;
if (CheckExtension("GL_ARB_shader_storage_buffer_object")) gl.flags |= RFL_SHADER_STORAGE_BUFFER;
if (CheckExtension("GL_ARB_buffer_storage") && !Args->CheckParm("-nopersistentbuffers")) if (CheckExtension("GL_ARB_buffer_storage") && !Args->CheckParm("-nopersistentbuffers"))
{ {
gl.flags |= RFL_BUFFER_STORAGE; // the cmdline option is for testing the fallback implementation on newer hardware. gl.flags |= RFL_BUFFER_STORAGE; // the cmdline option is for testing the fallback implementation on newer hardware.
@ -178,6 +179,10 @@ void gl_PrintStartupLog()
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &v); glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &v);
Printf ("Max. uniform block size: %d\n", v); Printf ("Max. uniform block size: %d\n", v);
gl.maxuniformblock = v; gl.maxuniformblock = v;
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &v);
Printf ("Uniform block alignment: %d\n", v);
gl.uniformblockalignment = v;
glGetIntegerv(GL_MAX_VARYING_FLOATS, &v); glGetIntegerv(GL_MAX_VARYING_FLOATS, &v);
Printf ("Max. varying: %d\n", v); Printf ("Max. varying: %d\n", v);
glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &v); glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &v);

View file

@ -30,6 +30,7 @@ struct RenderContext
unsigned int flags; unsigned int flags;
unsigned int maxuniforms; unsigned int maxuniforms;
unsigned int maxuniformblock; unsigned int maxuniformblock;
unsigned int uniformblockalignment;
float version; float version;
float glslversion; float glslversion;
int max_texturesize; int max_texturesize;

View file

@ -7,14 +7,15 @@ in vec4 vColor;
out vec4 FragColor; out vec4 FragColor;
#ifdef SHADER_STORAGE_LIGHTS #ifdef SHADER_STORAGE_LIGHTS
layout(std430, binding = 3) buffer ParameterBuffer layout(std430, binding = 1) buffer LightBufferSSO
{ {
vec4 lights[]; vec4 lights[];
}; };
#elif defined MAXLIGHTS128
uniform vec4 lights[256];
#else #else
uniform vec4 lights[128]; layout(std140) uniform LightBufferUBO
{
vec4 lights[NUM_UBO_LIGHTS];
};
#endif #endif
@ -169,12 +170,15 @@ vec4 getLightColor(float fogdist, float fogfactor)
vec4 dynlight = uDynLightColor; vec4 dynlight = uDynLightColor;
if (uLightRange.z > uLightRange.x) if (uLightIndex >= 0)
{
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
if (lightRange.z > lightRange.x)
{ {
// //
// modulated lights // modulated lights
// //
for(int i=uLightRange.x; i<uLightRange.y; i+=2) for(int i=lightRange.x; i<lightRange.y; i+=2)
{ {
vec4 lightpos = lights[i]; vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1]; vec4 lightcolor = lights[i+1];
@ -185,7 +189,7 @@ vec4 getLightColor(float fogdist, float fogfactor)
// //
// subtractive lights // subtractive lights
// //
for(int i=uLightRange.y; i<uLightRange.z; i+=2) for(int i=lightRange.y; i<lightRange.z; i+=2)
{ {
vec4 lightpos = lights[i]; vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1]; vec4 lightcolor = lights[i+1];
@ -194,6 +198,7 @@ vec4 getLightColor(float fogdist, float fogfactor)
dynlight.rgb -= lightcolor.rgb; dynlight.rgb -= lightcolor.rgb;
} }
} }
}
color.rgb = clamp(color.rgb + desaturate(dynlight).rgb, 0.0, 1.4); color.rgb = clamp(color.rgb + desaturate(dynlight).rgb, 0.0, 1.4);
// prevent any unintentional messing around with the alpha. // prevent any unintentional messing around with the alpha.
@ -254,14 +259,17 @@ void main()
frag *= getLightColor(fogdist, fogfactor); frag *= getLightColor(fogdist, fogfactor);
if (uLightRange.w > uLightRange.z) if (uLightIndex >= 0)
{
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
if (lightRange.w > lightRange.z)
{ {
vec4 addlight = vec4(0.0,0.0,0.0,0.0); vec4 addlight = vec4(0.0,0.0,0.0,0.0);
// //
// additive lights - these can be done after the alpha test. // additive lights - these can be done after the alpha test.
// //
for(int i=uLightRange.z; i<uLightRange.w; i+=2) for(int i=lightRange.z; i<lightRange.w; i+=2)
{ {
vec4 lightpos = lights[i]; vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1]; vec4 lightcolor = lights[i+1];
@ -271,6 +279,7 @@ void main()
} }
frag.rgb = clamp(frag.rgb + desaturate(addlight).rgb, 0.0, 1.0); frag.rgb = clamp(frag.rgb + desaturate(addlight).rgb, 0.0, 1.0);
} }
}
// //
// colored fog // colored fog

View file

@ -38,7 +38,7 @@ uniform vec4 uLightAttr;
uniform int uFogEnabled; uniform int uFogEnabled;
// dynamic lights // dynamic lights
uniform ivec4 uLightRange; uniform int uLightIndex;
// matrices // matrices
uniform mat4 ProjectionMatrix; uniform mat4 ProjectionMatrix;