Move all GPU handling to gl_shadowmap and rename gl_lightbsp to gl_aabbtree

This commit is contained in:
Magnus Norddahl 2017-03-08 13:31:19 +01:00
parent 8687a9868a
commit d09c3ad305
5 changed files with 74 additions and 147 deletions

View File

@ -939,7 +939,7 @@ set( FASTMATH_SOURCES
gl/dynlights/gl_glow.cpp
gl/dynlights/gl_dynlight1.cpp
gl/dynlights/gl_lightbuffer.cpp
gl/dynlights/gl_lightbsp.cpp
gl/dynlights/gl_aabbtree.cpp
gl/dynlights/gl_shadowmap.cpp
gl/shaders/gl_shader.cpp
gl/shaders/gl_texshader.cpp

View File

@ -1,6 +1,6 @@
//
//---------------------------------------------------------------------------
// 2D collision tree for 1D shadowmap lights
// AABB-tree used for ray testing
// Copyright(C) 2017 Magnus Norddahl
// All rights reserved.
//
@ -22,106 +22,11 @@
#include "gl/system/gl_system.h"
#include "gl/shaders/gl_shader.h"
#include "gl/dynlights/gl_lightbsp.h"
#include "gl/dynlights/gl_aabbtree.h"
#include "gl/system/gl_interface.h"
#include "r_state.h"
#include "g_levellocals.h"
int FLightBSP::GetNodesBuffer()
{
UpdateBuffers();
return NodesBuffer;
}
int FLightBSP::GetLinesBuffer()
{
UpdateBuffers();
return LinesBuffer;
}
void FLightBSP::UpdateBuffers()
{
if (numnodes != NumNodes || numsegs != NumSegs) // To do: there is probably a better way to detect a map change than this..
Clear();
if (NodesBuffer == 0)
GenerateBuffers();
}
void FLightBSP::GenerateBuffers()
{
if (!Shape)
Shape.reset(new LevelAABBTree());
UploadNodes();
UploadSegs();
}
void FLightBSP::UploadNodes()
{
#if 0
if (Shape->nodes.Size() > 0)
{
FILE *file = fopen("nodes.txt", "wb");
fwrite(&Shape->nodes[0], sizeof(AABBTreeNode) * Shape->nodes.Size(), 1, file);
fclose(file);
}
#endif
int oldBinding = 0;
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &oldBinding);
glGenBuffers(1, (GLuint*)&NodesBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, NodesBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(AABBTreeNode) * Shape->nodes.Size(), &Shape->nodes[0], GL_STATIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, oldBinding);
NumNodes = numnodes;
}
void FLightBSP::UploadSegs()
{
#if 0
if (Shape->lines.Size() > 0)
{
FILE *file = fopen("lines.txt", "wb");
fwrite(&Shape->lines[0], sizeof(AABBTreeLine) * Shape->lines.Size(), 1, file);
fclose(file);
}
#endif
int oldBinding = 0;
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &oldBinding);
glGenBuffers(1, (GLuint*)&LinesBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, LinesBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(AABBTreeLine) * Shape->lines.Size(), &Shape->lines[0], GL_STATIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, oldBinding);
NumSegs = numsegs;
}
void FLightBSP::Clear()
{
if (NodesBuffer != 0)
{
glDeleteBuffers(1, (GLuint*)&NodesBuffer);
NodesBuffer = 0;
}
if (LinesBuffer != 0)
{
glDeleteBuffers(1, (GLuint*)&LinesBuffer);
LinesBuffer = 0;
}
Shape.reset();
}
bool FLightBSP::ShadowTest(const DVector3 &light, const DVector3 &pos)
{
return Shape->RayTest(light, pos) >= 1.0f;
}
/////////////////////////////////////////////////////////////////////////////
LevelAABBTree::LevelAABBTree()
{
// Calculate the center of all lines

View File

@ -2,7 +2,6 @@
#pragma once
#include "vectors.h"
#include <memory>
// Node in a binary AABB tree
struct AABBTreeNode
@ -14,7 +13,7 @@ struct AABBTreeNode
float aabb_left, aabb_top;
float aabb_right, aabb_bottom;
// Children node indices
// Child node indices
int left_node;
int right_node;
@ -45,7 +44,7 @@ public:
// Line segments for the leaf nodes in the tree.
TArray<AABBTreeLine> lines;
// Shoot a ray from ray_start to ray_end and return the first hit as a fractional value between 0 and 1. Returns 1 if no line was hit.
// Shoot a ray from ray_start to ray_end and return the closest hit as a fractional value between 0 and 1. Returns 1 if no line was hit.
double RayTest(const DVector3 &ray_start, const DVector3 &ray_end);
private:
@ -58,32 +57,3 @@ private:
// Generate a tree node and its children recursively
int GenerateTreeNode(int *lines, int num_lines, const FVector2 *centroids, int *work_buffer);
};
class FLightBSP
{
public:
FLightBSP() { }
~FLightBSP() { Clear(); }
int GetNodesBuffer();
int GetLinesBuffer();
void Clear();
bool ShadowTest(const DVector3 &light, const DVector3 &pos);
private:
void UpdateBuffers();
void GenerateBuffers();
void UploadNodes();
void UploadSegs();
FLightBSP(const FLightBSP &) = delete;
FLightBSP &operator=(FLightBSP &) = delete;
int NodesBuffer = 0;
int LinesBuffer = 0;
int NumNodes = 0;
int NumSegs = 0;
std::unique_ptr<LevelAABBTree> Shape;
};

View File

@ -32,19 +32,9 @@
#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()
{
UploadAABBTree();
UploadLights();
FGLDebug::PushGroup("ShadowMap");
@ -54,8 +44,8 @@ void FShadowMap::Update()
GLRenderer->mShadowMapShader->Bind();
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, mLightList);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, mLightBSP.GetNodesBuffer());
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, mLightBSP.GetLinesBuffer());
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, mNodesBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, mLinesBuffer);
glViewport(0, 0, 1024, 1024);
GLRenderer->RenderScreenQuad();
@ -72,6 +62,14 @@ void FShadowMap::Update()
FGLDebug::PopGroup();
}
bool FShadowMap::ShadowTest(ADynamicLight *light, const DVector3 &pos)
{
if (mAABBTree)
return mAABBTree->RayTest(light->Pos(), pos) >= 1.0f;
else
return true;
}
void FShadowMap::UploadLights()
{
mLights.Clear();
@ -107,7 +105,52 @@ void FShadowMap::UploadLights()
glBindBuffer(GL_SHADER_STORAGE_BUFFER, oldBinding);
}
bool FShadowMap::ShadowTest(ADynamicLight *light, const DVector3 &pos)
void FShadowMap::UploadAABBTree()
{
return mLightBSP.ShadowTest(light->Pos(), pos);
if (numnodes != mLastNumNodes || numsegs != mLastNumSegs) // To do: there is probably a better way to detect a map change than this..
Clear();
if (mAABBTree)
return;
mAABBTree.reset(new LevelAABBTree());
int oldBinding = 0;
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &oldBinding);
glGenBuffers(1, (GLuint*)&mNodesBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mNodesBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(AABBTreeNode) * mAABBTree->nodes.Size(), &mAABBTree->nodes[0], GL_STATIC_DRAW);
glGenBuffers(1, (GLuint*)&mLinesBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mLinesBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(AABBTreeLine) * mAABBTree->lines.Size(), &mAABBTree->lines[0], GL_STATIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, oldBinding);
}
void FShadowMap::Clear()
{
if (mLightList != 0)
{
glDeleteBuffers(1, (GLuint*)&mLightList);
mLightList = 0;
}
if (mNodesBuffer != 0)
{
glDeleteBuffers(1, (GLuint*)&mNodesBuffer);
mNodesBuffer = 0;
}
if (mLinesBuffer != 0)
{
glDeleteBuffers(1, (GLuint*)&mLinesBuffer);
mLinesBuffer = 0;
}
mAABBTree.reset();
mLastNumNodes = numnodes;
mLastNumSegs = numsegs;
}

View File

@ -1,8 +1,9 @@
#pragma once
#include "gl/dynlights/gl_lightbsp.h"
#include "gl/dynlights/gl_aabbtree.h"
#include "tarray.h"
#include <memory>
class ADynamicLight;
@ -20,13 +21,21 @@ public:
bool ShadowTest(ADynamicLight *light, const DVector3 &pos);
private:
void UploadAABBTree();
void UploadLights();
FLightBSP mLightBSP;
int mLightList = 0;
TArray<float> mLights;
TMap<ADynamicLight*, int> mLightToShadowmap;
int mNodesBuffer = 0;
int mLinesBuffer = 0;
int mLastNumNodes = 0;
int mLastNumSegs = 0;
std::unique_ptr<LevelAABBTree> mAABBTree;
FShadowMap(const FShadowMap &) = delete;
FShadowMap &operator=(FShadowMap &) = delete;
};