mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-31 05:40:44 +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/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(©ptr[0], parmcnt, 4 * sizeof(float));
|
memcpy(©ptr[0], parmcnt, 4 * sizeof(float));
|
||||||
memcpy(©ptr[1], &data.arrays[0][0], 4 * size0*sizeof(float));
|
memcpy(©ptr[4], &data.arrays[0][0], 4 * size0*sizeof(float));
|
||||||
memcpy(©ptr[1 + size0], &data.arrays[1][0], 4 * size1*sizeof(float));
|
memcpy(©ptr[4 + 4*size0], &data.arrays[1][0], 4 * size1*sizeof(float));
|
||||||
memcpy(©ptr[1 + size0 + size1], &data.arrays[2][0], 4 * size2*sizeof(float));
|
memcpy(©ptr[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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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=§ors[frontsector->sectornum];
|
sector=§ors[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];
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue