Create a shadowmap texture and upload light list

This commit is contained in:
Magnus Norddahl 2017-03-01 17:17:33 +01:00
parent 7a4b01471d
commit 62c285f7b3
5 changed files with 111 additions and 7 deletions

View file

@ -28,27 +28,32 @@
#include "gl/system/gl_debug.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_postprocessstate.h"
#include "gl/renderer/gl_renderbuffers.h"
#include "gl/shaders/gl_shadowmapshader.h"
#include "r_state.h"
void FShadowMap::Clear()
{
if (mLightList != 0)
{
glDeleteBuffers(1, (GLuint*)&mLightList);
mLightList = 0;
}
mLightBSP.Clear();
}
void FShadowMap::Update()
{
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
while (true)
{
ADynamicLight *light = it.Next();
if (!light) break;
}
UploadLights();
FGLDebug::PushGroup("ShadowMap");
FGLPostProcessState savedState;
GLRenderer->mBuffers->BindShadowMapFB();
GLRenderer->mShadowMapShader->Bind();
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mLightList);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, mLightBSP.GetNodesBuffer());
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, mLightBSP.GetSegsBuffer());
@ -58,8 +63,41 @@ void FShadowMap::Update()
const auto &viewport = GLRenderer->mScreenViewport;
glViewport(viewport.left, viewport.top, viewport.width, viewport.height);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, 0);
FGLDebug::PopGroup();
}
void FShadowMap::UploadLights()
{
lights.Clear();
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
while (true)
{
ADynamicLight *light = it.Next();
if (!light) break;
lights.Push(light->X());
lights.Push(light->Y());
lights.Push(light->Z());
lights.Push(light->GetRadius());
if (lights.Size() == 1024) // Only 1024 lights for now
break;
}
while (lights.Size() < 1024 * 4)
lights.Push(0.0f);
if (mLightList == 0)
glGenBuffers(1, (GLuint*)&mLightList);
int oldBinding = 0;
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &oldBinding);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mLightList);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float) * lights.Size(), &lights[0], GL_STATIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, oldBinding);
}

View file

@ -13,7 +13,11 @@ public:
void Update();
private:
void UploadLights();
FLightBSP mLightBSP;
int mLightList = 0;
TArray<float> lights;
FShadowMap(const FShadowMap &) = delete;
FShadowMap &operator=(FShadowMap &) = delete;

View file

@ -741,6 +741,44 @@ void FGLRenderBuffers::BindEyeFB(int eye, bool readBuffer)
glBindFramebuffer(readBuffer ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER, mEyeFBs[eye]);
}
//==========================================================================
//
// Shadow map texture and frame buffers
//
//==========================================================================
void FGLRenderBuffers::BindShadowMapFB()
{
CreateShadowMap();
glBindFramebuffer(GL_FRAMEBUFFER, mShadowMapFB);
}
void FGLRenderBuffers::BindShadowMapTexture(int texunit)
{
CreateShadowMap();
glActiveTexture(GL_TEXTURE0 + texunit);
glBindTexture(GL_TEXTURE_2D, mShadowMapTexture);
}
void FGLRenderBuffers::CreateShadowMap()
{
if (mShadowMapTexture != 0)
return;
GLint activeTex, textureBinding, frameBufferBinding;
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex);
glActiveTexture(GL_TEXTURE0);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBufferBinding);
mShadowMapTexture = Create2DTexture("ShadowMap", GL_R32F, 1024, 1024);
mShadowMapFB = CreateFrameBuffer("ShadowMapFB", mShadowMapTexture);
glBindTexture(GL_TEXTURE_2D, textureBinding);
glActiveTexture(activeTex);
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferBinding);
}
//==========================================================================
//
// Makes the scene frame buffer active (multisample, depth, stecil, etc.)

View file

@ -49,6 +49,9 @@ public:
void BindEyeTexture(int eye, int texunit);
void BindEyeFB(int eye, bool readBuffer = false);
void BindShadowMapFB();
void BindShadowMapTexture(int index);
enum { NumBloomLevels = 4 };
FGLBloomTextureLevel BloomLevels[NumBloomLevels];
@ -89,6 +92,7 @@ private:
void CreateBloom(int width, int height);
void CreateExposureLevels(int width, int height);
void CreateEyeBuffers(int eye);
void CreateShadowMap();
void CreateAmbientOcclusion(int width, int height);
GLuint Create2DTexture(const FString &name, GLuint format, int width, int height, const void *data = nullptr);
GLuint Create2DMultisampleTexture(const FString &name, GLuint format, int width, int height, int samples, bool fixedSampleLocations);
@ -133,6 +137,10 @@ private:
TArray<GLuint> mEyeTextures;
TArray<GLuint> mEyeFBs;
// Shadow map texture
GLuint mShadowMapTexture = 0;
GLuint mShadowMapFB = 0;
static bool FailedCreate;
static bool BuffersActive;
};

View file

@ -16,6 +16,11 @@ struct GPUSeg
vec4 bSolid;
};
layout(std430, binding = 1) buffer LightList
{
vec4 lights[];
};
layout(std430, binding = 2) buffer LightNodes
{
GPUNode bspNodes[];
@ -112,5 +117,16 @@ float rayTest(vec2 from, vec2 to)
void main()
{
FragColor = vec4(rayTest(vec2(0.0, 0.0), vec2(1.0, 1.0)));
int lightIndex = int(gl_FragCoord.y);
int x = int(gl_FragCoord.x);
vec4 light = lights[lightIndex];
float radius = light.w;
vec2 lightpos = light.xy;
vec2 pixelpos = lightpos + vec2(10.0);
if (radius > 0.0)
FragColor = vec4(rayTest(lightpos, pixelpos), 0.0, 0.0, 1.0);
else
FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}