mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 06:53:58 +00:00
- use the light buffer to handle dynamic lighting.
This commit is contained in:
parent
01a1e10084
commit
7967082e60
17 changed files with 194 additions and 197 deletions
|
@ -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
|
||||
|
|
|
@ -39,93 +39,79 @@
|
|||
*/
|
||||
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
#include "gl/dynlights/gl_dynlight.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()
|
||||
{
|
||||
if (gl.flags & RFL_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
|
||||
{
|
||||
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();
|
||||
mLastMappedIndex = UINT_MAX;
|
||||
}
|
||||
|
||||
FLightBuffer::~FLightBuffer()
|
||||
{
|
||||
glBindBuffer(mBufferType, 0);
|
||||
for (unsigned int i = 0; i < mBufferIds.Size(); i++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
glDeleteBuffers(1, &mBufferId);
|
||||
}
|
||||
|
||||
void FLightBuffer::Clear()
|
||||
{
|
||||
mBufferNum = 0;
|
||||
mIndex = 0;
|
||||
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 size1 = data.arrays[1].Size()/4;
|
||||
int size2 = data.arrays[2].Size()/4;
|
||||
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; // 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();
|
||||
}
|
||||
return -1; // we ran out of space. All following lights will be ignored
|
||||
}
|
||||
|
||||
float *copyptr;
|
||||
|
||||
if (gl.flags & RFL_BUFFER_STORAGE)
|
||||
if (mBufferPointer != NULL)
|
||||
{
|
||||
copyptr = mBufferPointers[mBufferNum] + mIndex * 4;
|
||||
copyptr = mBufferPointer + mIndex * 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -133,20 +119,48 @@ void FLightBuffer::UploadLights(FDynLightData &data, unsigned int &buffernum, un
|
|||
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(©ptr[0], parmcnt, 4 * sizeof(float));
|
||||
memcpy(©ptr[1], &data.arrays[0][0], 4 * size0*sizeof(float));
|
||||
memcpy(©ptr[1 + size0], &data.arrays[1][0], 4 * size1*sizeof(float));
|
||||
memcpy(©ptr[1 + size0 + size1], &data.arrays[2][0], 4 * size2*sizeof(float));
|
||||
buffernum = mBufferNum;
|
||||
bufferindex = mIndex;
|
||||
memcpy(©ptr[4], &data.arrays[0][0], 4 * size0*sizeof(float));
|
||||
memcpy(©ptr[4 + 4*size0], &data.arrays[1][0], 4 * size1*sizeof(float));
|
||||
memcpy(©ptr[4 + 4*(size0 + size1)], &data.arrays[2][0], 4 * size2*sizeof(float));
|
||||
|
||||
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;
|
||||
draw_dlight += (totalsize-1) / 2;
|
||||
return bufferindex;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,23 +7,25 @@ struct FDynLightData;
|
|||
class FLightBuffer
|
||||
{
|
||||
TArray<float> mBufferArray;
|
||||
TArray<unsigned int> mBufferIds;
|
||||
TArray<unsigned int> mBufferStart;
|
||||
TArray<float *> mBufferPointers;
|
||||
unsigned int mBufferType;
|
||||
unsigned int mBufferSize;
|
||||
unsigned int mIndex;
|
||||
unsigned int mBufferNum;
|
||||
unsigned int mBufferId;
|
||||
float * mBufferPointer;
|
||||
|
||||
void AddBuffer();
|
||||
unsigned int mBufferType;
|
||||
unsigned int mIndex;
|
||||
unsigned int mLastMappedIndex;
|
||||
unsigned int mBlockAlign;
|
||||
unsigned int mBlockSize;
|
||||
|
||||
public:
|
||||
|
||||
FLightBuffer();
|
||||
~FLightBuffer();
|
||||
void Clear();
|
||||
void UploadLights(FDynLightData &data, unsigned int &buffernum, unsigned int &bufferindex);
|
||||
int UploadLights(FDynLightData &data);
|
||||
void Finish();
|
||||
int BindUBO(unsigned int index);
|
||||
unsigned int GetBlockSize() const { return mBlockSize; }
|
||||
unsigned int GetBufferType() const { return mBufferType; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#include "gl/utility/gl_clock.h"
|
||||
#include "gl/utility/gl_templates.h"
|
||||
#include "gl/models/gl_models.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -97,6 +98,7 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
|
|||
gl_spriteindex = 0;
|
||||
mShaderManager = NULL;
|
||||
glpart2 = glpart = mirrortexture = NULL;
|
||||
mLights = NULL;
|
||||
}
|
||||
|
||||
void FGLRenderer::Initialize()
|
||||
|
@ -108,6 +110,7 @@ void FGLRenderer::Initialize()
|
|||
mVBO = new FFlatVertexBuffer;
|
||||
mSkyVBO = new FSkyVertexBuffer;
|
||||
mModelVBO = new FModelVertexBuffer;
|
||||
mLights = new FLightBuffer;
|
||||
gl_RenderState.SetVertexBuffer(mVBO);
|
||||
mFBID = 0;
|
||||
SetupLevel();
|
||||
|
@ -124,6 +127,7 @@ FGLRenderer::~FGLRenderer()
|
|||
if (mVBO != NULL) delete mVBO;
|
||||
if (mModelVBO) delete mModelVBO;
|
||||
if (mSkyVBO != NULL) delete mSkyVBO;
|
||||
if (mLights != NULL) delete mLights;
|
||||
if (glpart2) delete glpart2;
|
||||
if (glpart) delete glpart;
|
||||
if (mirrortexture) delete mirrortexture;
|
||||
|
|
|
@ -17,6 +17,7 @@ struct pspdef_t;
|
|||
class FShaderManager;
|
||||
class GLPortal;
|
||||
class FGLThreadManager;
|
||||
class FLightBuffer;
|
||||
|
||||
enum SectorRenderFlags
|
||||
{
|
||||
|
@ -72,6 +73,7 @@ public:
|
|||
FFlatVertexBuffer *mVBO;
|
||||
FSkyVertexBuffer *mSkyVBO;
|
||||
FModelVertexBuffer *mModelVBO;
|
||||
FLightBuffer *mLights;
|
||||
|
||||
|
||||
FGLRenderer(OpenGLFrameBuffer *fb);
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/renderer/gl_colormap.h"
|
||||
#include "gl/dynlights//gl_lightbuffer.h"
|
||||
|
||||
void gl_SetTextureMode(int type);
|
||||
|
||||
|
@ -68,9 +69,10 @@ TArray<VSMatrix> gl_MatrixStack;
|
|||
void FRenderState::Reset()
|
||||
{
|
||||
mTextureEnabled = true;
|
||||
mBrightmapEnabled = mFogEnabled = mGlowEnabled = mLightEnabled = false;
|
||||
mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
|
||||
mFogColor.d = -1;
|
||||
mTextureMode = -1;
|
||||
mLightIndex = -1;
|
||||
mDesaturation = 0;
|
||||
mSrcBlend = GL_SRC_ALPHA;
|
||||
mDstBlend = GL_ONE_MINUS_SRC_ALPHA;
|
||||
|
@ -98,7 +100,6 @@ void FRenderState::Reset()
|
|||
|
||||
bool FRenderState::ApplyShader()
|
||||
{
|
||||
FShader *activeShader;
|
||||
if (mSpecialEffect > EFF_NONE)
|
||||
{
|
||||
activeShader = GLRenderer->mShaderManager->BindEffect(mSpecialEffect);
|
||||
|
@ -139,6 +140,7 @@ bool FRenderState::ApplyShader()
|
|||
activeShader->muClipHeightBottom.Set(mClipHeightBottom);
|
||||
activeShader->muTimer.Set(gl_frameMS * mShaderTimer / 1000.f);
|
||||
activeShader->muAlphaThreshold.Set(mAlphaThreshold);
|
||||
activeShader->muLightIndex.Set(mLightIndex); // will always be -1 for now
|
||||
|
||||
if (mGlowEnabled)
|
||||
{
|
||||
|
@ -159,17 +161,6 @@ bool FRenderState::ApplyShader()
|
|||
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)
|
||||
{
|
||||
float r, g, b;
|
||||
|
@ -282,3 +273,12 @@ void FRenderState::ApplyMatrices()
|
|||
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);
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
#include "r_defs.h"
|
||||
|
||||
class FVertexBuffer;
|
||||
class FShader;
|
||||
extern TArray<VSMatrix> gl_MatrixStack;
|
||||
|
||||
EXTERN_CVAR(Bool, gl_direct_state_change)
|
||||
|
@ -43,24 +44,22 @@ class FRenderState
|
|||
bool mTextureEnabled;
|
||||
bool mFogEnabled;
|
||||
bool mGlowEnabled;
|
||||
bool mLightEnabled;
|
||||
bool mBrightmapEnabled;
|
||||
int mLightIndex;
|
||||
int mSpecialEffect;
|
||||
int mTextureMode;
|
||||
int mDesaturation;
|
||||
int mSoftLight;
|
||||
float mLightParms[4];
|
||||
int mNumLights[4];
|
||||
float *mLightData;
|
||||
int mSrcBlend, mDstBlend;
|
||||
float mAlphaThreshold;
|
||||
bool mAlphaTest;
|
||||
int mBlendEquation;
|
||||
bool mAlphaTest;
|
||||
bool m2D;
|
||||
float mInterpolationFactor;
|
||||
float mClipHeightTop, mClipHeightBottom;
|
||||
bool mModelMatrixEnabled;
|
||||
bool mTextureMatrixEnabled;
|
||||
float mInterpolationFactor;
|
||||
float mClipHeightTop, mClipHeightBottom;
|
||||
float mShaderTimer;
|
||||
|
||||
FVertexBuffer *mVertexBuffer, *mCurrentVertexBuffer;
|
||||
|
@ -80,6 +79,8 @@ class FRenderState
|
|||
bool stAlphaTest;
|
||||
int stBlendEquation;
|
||||
|
||||
FShader *activeShader;
|
||||
|
||||
bool ApplyShader();
|
||||
|
||||
public:
|
||||
|
@ -104,6 +105,7 @@ public:
|
|||
|
||||
void Apply();
|
||||
void ApplyMatrices();
|
||||
void ApplyLightIndex(int index);
|
||||
|
||||
void SetVertexBuffer(FVertexBuffer *vb)
|
||||
{
|
||||
|
@ -185,9 +187,9 @@ public:
|
|||
mGlowEnabled = on;
|
||||
}
|
||||
|
||||
void EnableLight(bool on)
|
||||
void SetLightIndex(int n)
|
||||
{
|
||||
mLightEnabled = on;
|
||||
mLightIndex = n;
|
||||
}
|
||||
|
||||
void EnableBrightmap(bool on)
|
||||
|
@ -251,15 +253,6 @@ public:
|
|||
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)
|
||||
{
|
||||
mColormapState = cm;
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/dynlights/gl_dynlight.h"
|
||||
#include "gl/dynlights/gl_glow.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
#include "gl/textures/gl_material.h"
|
||||
|
@ -142,22 +143,8 @@ bool GLFlat::SetupSubsectorLights(bool lightsapplied, subsector_t * sub)
|
|||
node = node->nextLight;
|
||||
}
|
||||
|
||||
int numlights[3];
|
||||
|
||||
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();
|
||||
}
|
||||
dynlightindex = GLRenderer->mLights->UploadLights(lightdata);
|
||||
gl_RenderState.ApplyLightIndex(dynlightindex);
|
||||
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=§ors[frontsector->sectornum];
|
||||
extsector_t::xfloor &x = sector->e->XFloor;
|
||||
this->sub=NULL;
|
||||
dynlightindex = -1;
|
||||
|
||||
byte &srf = gl_drawinfo->sectorrenderflags[sector->sectornum];
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "p_local.h"
|
||||
#include "gl/gl_functions.h"
|
||||
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/system/gl_framebuffer.h"
|
||||
#include "gl/system/gl_cvars.h"
|
||||
|
@ -348,6 +349,7 @@ void FGLRenderer::RenderScene(int recursion)
|
|||
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
|
||||
|
||||
glDisable(GL_POLYGON_OFFSET_FILL); // just in case
|
||||
GLRenderer->mLights->Finish();
|
||||
|
||||
int pass;
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ public:
|
|||
float topglowcolor[4];
|
||||
float bottomglowcolor[4];
|
||||
|
||||
unsigned int dynlightindex, dynlightbuffer;
|
||||
int dynlightindex;
|
||||
int firstwall, numwalls; // splitting info.
|
||||
|
||||
union
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/dynlights/gl_dynlight.h"
|
||||
#include "gl/dynlights/gl_glow.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
|
@ -150,15 +151,8 @@ void GLWall::SetupLights()
|
|||
}
|
||||
node = node->nextLight;
|
||||
}
|
||||
int numlights[3];
|
||||
|
||||
lightdata.Combine(numlights, gl.MaxLights());
|
||||
if (numlights[2] > 0)
|
||||
{
|
||||
draw_dlight+=numlights[2]/2;
|
||||
gl_RenderState.EnableLight(true);
|
||||
gl_RenderState.SetLights(numlights, &lightdata.arrays[0][0]);
|
||||
}
|
||||
dynlightindex = GLRenderer->mLights->UploadLights(lightdata);
|
||||
}
|
||||
|
||||
|
||||
|
@ -187,6 +181,7 @@ void GLWall::RenderWall(int textured, unsigned int *store)
|
|||
if (!(textured & RWF_NORENDER))
|
||||
{
|
||||
gl_RenderState.Apply();
|
||||
gl_RenderState.ApplyLightIndex(dynlightindex);
|
||||
}
|
||||
|
||||
// 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);
|
||||
RenderWall(RWF_TEXTURED|RWF_GLOW);
|
||||
gl_RenderState.EnableGlow(false);
|
||||
gl_RenderState.EnableLight(false);
|
||||
break;
|
||||
|
||||
case GLPASS_DECALS:
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "gl/system/gl_cvars.h"
|
||||
#include "gl/shaders/gl_shader.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!
|
||||
//
|
||||
unsigned int lightbuffertype = GLRenderer->mLights->GetBufferType();
|
||||
unsigned int lightbuffersize = GLRenderer->mLights->GetBlockSize();
|
||||
|
||||
FString vp_comb = "#version 130\n";
|
||||
// todo when using shader storage buffers, add
|
||||
// "#version 400 compatibility\n#extension GL_ARB_shader_storage_buffer_object : require\n" instead.
|
||||
FString vp_comb;
|
||||
|
||||
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))
|
||||
{
|
||||
|
@ -196,7 +206,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
|||
muLightParms.Init(hShader, "uLightAttr");
|
||||
muColormapStart.Init(hShader, "uFixedColormapStart");
|
||||
muColormapRange.Init(hShader, "uFixedColormapRange");
|
||||
muLightRange.Init(hShader, "uLightRange");
|
||||
muLightIndex.Init(hShader, "uLightIndex");
|
||||
muFogColor.Init(hShader, "uFogColor");
|
||||
muDynLightColor.Init(hShader, "uDynLightColor");
|
||||
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");
|
||||
texturematrix_index = glGetUniformLocation(hShader, "TextureMatrix");
|
||||
|
||||
int tempindex = glGetUniformBlockIndex(hShader, "LightBufferUBO");
|
||||
if (tempindex != -1) glUniformBlockBinding(hShader, tempindex, LIGHTBUF_BINDINGPOINT);
|
||||
|
||||
glUseProgram(hShader);
|
||||
|
||||
int texture_index = glGetUniformLocation(hShader, "texture2");
|
||||
if (texture_index > 0) glUniform1i(texture_index, 1);
|
||||
tempindex = glGetUniformLocation(hShader, "texture2");
|
||||
if (tempindex > 0) glUniform1i(tempindex, 1);
|
||||
|
||||
glUseProgram(0);
|
||||
return !!linked;
|
||||
|
|
|
@ -187,7 +187,7 @@ class FShader
|
|||
FUniform1i muFixedColormap;
|
||||
FUniform4f muColormapStart;
|
||||
FUniform4f muColormapRange;
|
||||
FBufferedUniform4i muLightRange;
|
||||
FBufferedUniform1i muLightIndex;
|
||||
FBufferedUniformPE muFogColor;
|
||||
FBufferedUniform4f muDynLightColor;
|
||||
FBufferedUniformPE muObjectColor;
|
||||
|
@ -281,6 +281,10 @@ public:
|
|||
|
||||
#define FIRST_USER_SHADER 12
|
||||
|
||||
enum
|
||||
{
|
||||
LIGHTBUF_BINDINGPOINT = 1
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -133,6 +133,7 @@ void gl_LoadExtensions()
|
|||
|
||||
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_ARB_shader_storage_buffer_object")) gl.flags |= RFL_SHADER_STORAGE_BUFFER;
|
||||
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.
|
||||
|
@ -178,6 +179,10 @@ void gl_PrintStartupLog()
|
|||
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &v);
|
||||
Printf ("Max. uniform block size: %d\n", 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);
|
||||
Printf ("Max. varying: %d\n", v);
|
||||
glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &v);
|
||||
|
|
|
@ -30,6 +30,7 @@ struct RenderContext
|
|||
unsigned int flags;
|
||||
unsigned int maxuniforms;
|
||||
unsigned int maxuniformblock;
|
||||
unsigned int uniformblockalignment;
|
||||
float version;
|
||||
float glslversion;
|
||||
int max_texturesize;
|
||||
|
|
|
@ -7,14 +7,15 @@ in vec4 vColor;
|
|||
out vec4 FragColor;
|
||||
|
||||
#ifdef SHADER_STORAGE_LIGHTS
|
||||
layout(std430, binding = 3) buffer ParameterBuffer
|
||||
layout(std430, binding = 1) buffer LightBufferSSO
|
||||
{
|
||||
vec4 lights[];
|
||||
};
|
||||
#elif defined MAXLIGHTS128
|
||||
uniform vec4 lights[256];
|
||||
#else
|
||||
uniform vec4 lights[128];
|
||||
layout(std140) uniform LightBufferUBO
|
||||
{
|
||||
vec4 lights[NUM_UBO_LIGHTS];
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -169,12 +170,15 @@ vec4 getLightColor(float fogdist, float fogfactor)
|
|||
|
||||
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
|
||||
//
|
||||
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 lightcolor = lights[i+1];
|
||||
|
@ -185,7 +189,7 @@ vec4 getLightColor(float fogdist, float fogfactor)
|
|||
//
|
||||
// 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 lightcolor = lights[i+1];
|
||||
|
@ -194,6 +198,7 @@ vec4 getLightColor(float fogdist, float fogfactor)
|
|||
dynlight.rgb -= lightcolor.rgb;
|
||||
}
|
||||
}
|
||||
}
|
||||
color.rgb = clamp(color.rgb + desaturate(dynlight).rgb, 0.0, 1.4);
|
||||
|
||||
// prevent any unintentional messing around with the alpha.
|
||||
|
@ -254,14 +259,17 @@ void main()
|
|||
|
||||
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);
|
||||
|
||||
//
|
||||
// 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 lightcolor = lights[i+1];
|
||||
|
@ -271,6 +279,7 @@ void main()
|
|||
}
|
||||
frag.rgb = clamp(frag.rgb + desaturate(addlight).rgb, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// colored fog
|
||||
|
|
|
@ -38,7 +38,7 @@ uniform vec4 uLightAttr;
|
|||
uniform int uFogEnabled;
|
||||
|
||||
// dynamic lights
|
||||
uniform ivec4 uLightRange;
|
||||
uniform int uLightIndex;
|
||||
|
||||
// matrices
|
||||
uniform mat4 ProjectionMatrix;
|
||||
|
|
Loading…
Reference in a new issue