- 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/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(&copyptr[0], parmcnt, 4 * sizeof(float));
memcpy(&copyptr[1], &data.arrays[0][0], 4 * size0*sizeof(float));
memcpy(&copyptr[1 + size0], &data.arrays[1][0], 4 * size1*sizeof(float));
memcpy(&copyptr[1 + size0 + size1], &data.arrays[2][0], 4 * size2*sizeof(float));
buffernum = mBufferNum;
bufferindex = mIndex;
memcpy(&copyptr[4], &data.arrays[0][0], 4 * size0*sizeof(float));
memcpy(&copyptr[4 + 4*size0], &data.arrays[1][0], 4 * size1*sizeof(float));
memcpy(&copyptr[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);
}

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

View file

@ -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=&sectors[frontsector->sectornum];
extsector_t::xfloor &x = sector->e->XFloor;
this->sub=NULL;
dynlightindex = -1;
byte &srf = gl_drawinfo->sectorrenderflags[sector->sectornum];

View file

@ -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;

View file

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

View file

@ -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:

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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,29 +170,33 @@ vec4 getLightColor(float fogdist, float fogfactor)
vec4 dynlight = uDynLightColor;
if (uLightRange.z > uLightRange.x)
if (uLightIndex >= 0)
{
//
// modulated lights
//
for(int i=uLightRange.x; i<uLightRange.y; i+=2)
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
if (lightRange.z > lightRange.x)
{
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
dynlight.rgb += lightcolor.rgb;
}
//
// subtractive lights
//
for(int i=uLightRange.y; i<uLightRange.z; i+=2)
{
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
dynlight.rgb -= lightcolor.rgb;
//
// modulated lights
//
for(int i=lightRange.x; i<lightRange.y; i+=2)
{
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
dynlight.rgb += lightcolor.rgb;
}
//
// subtractive lights
//
for(int i=lightRange.y; i<lightRange.z; i+=2)
{
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
dynlight.rgb -= lightcolor.rgb;
}
}
}
color.rgb = clamp(color.rgb + desaturate(dynlight).rgb, 0.0, 1.4);
@ -254,22 +259,26 @@ void main()
frag *= getLightColor(fogdist, fogfactor);
if (uLightRange.w > uLightRange.z)
if (uLightIndex >= 0)
{
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)
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
if (lightRange.w > lightRange.z)
{
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
addlight.rgb += lightcolor.rgb;
vec4 addlight = vec4(0.0,0.0,0.0,0.0);
//
// additive lights - these can be done after the alpha test.
//
for(int i=lightRange.z; i<lightRange.w; i+=2)
{
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
addlight.rgb += lightcolor.rgb;
}
frag.rgb = clamp(frag.rgb + desaturate(addlight).rgb, 0.0, 1.0);
}
frag.rgb = clamp(frag.rgb + desaturate(addlight).rgb, 0.0, 1.0);
}
//

View file

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