mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
Move all GPU handling to gl_shadowmap and rename gl_lightbsp to gl_aabbtree
This commit is contained in:
parent
8687a9868a
commit
d09c3ad305
5 changed files with 74 additions and 147 deletions
|
@ -939,7 +939,7 @@ set( FASTMATH_SOURCES
|
||||||
gl/dynlights/gl_glow.cpp
|
gl/dynlights/gl_glow.cpp
|
||||||
gl/dynlights/gl_dynlight1.cpp
|
gl/dynlights/gl_dynlight1.cpp
|
||||||
gl/dynlights/gl_lightbuffer.cpp
|
gl/dynlights/gl_lightbuffer.cpp
|
||||||
gl/dynlights/gl_lightbsp.cpp
|
gl/dynlights/gl_aabbtree.cpp
|
||||||
gl/dynlights/gl_shadowmap.cpp
|
gl/dynlights/gl_shadowmap.cpp
|
||||||
gl/shaders/gl_shader.cpp
|
gl/shaders/gl_shader.cpp
|
||||||
gl/shaders/gl_texshader.cpp
|
gl/shaders/gl_texshader.cpp
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// 2D collision tree for 1D shadowmap lights
|
// AABB-tree used for ray testing
|
||||||
// Copyright(C) 2017 Magnus Norddahl
|
// Copyright(C) 2017 Magnus Norddahl
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
|
@ -22,106 +22,11 @@
|
||||||
|
|
||||||
#include "gl/system/gl_system.h"
|
#include "gl/system/gl_system.h"
|
||||||
#include "gl/shaders/gl_shader.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 "gl/system/gl_interface.h"
|
||||||
#include "r_state.h"
|
#include "r_state.h"
|
||||||
#include "g_levellocals.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()
|
LevelAABBTree::LevelAABBTree()
|
||||||
{
|
{
|
||||||
// Calculate the center of all lines
|
// Calculate the center of all lines
|
|
@ -2,7 +2,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "vectors.h"
|
#include "vectors.h"
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
// Node in a binary AABB tree
|
// Node in a binary AABB tree
|
||||||
struct AABBTreeNode
|
struct AABBTreeNode
|
||||||
|
@ -14,7 +13,7 @@ struct AABBTreeNode
|
||||||
float aabb_left, aabb_top;
|
float aabb_left, aabb_top;
|
||||||
float aabb_right, aabb_bottom;
|
float aabb_right, aabb_bottom;
|
||||||
|
|
||||||
// Children node indices
|
// Child node indices
|
||||||
int left_node;
|
int left_node;
|
||||||
int right_node;
|
int right_node;
|
||||||
|
|
||||||
|
@ -45,7 +44,7 @@ public:
|
||||||
// Line segments for the leaf nodes in the tree.
|
// Line segments for the leaf nodes in the tree.
|
||||||
TArray<AABBTreeLine> lines;
|
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);
|
double RayTest(const DVector3 &ray_start, const DVector3 &ray_end);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -58,32 +57,3 @@ private:
|
||||||
// Generate a tree node and its children recursively
|
// Generate a tree node and its children recursively
|
||||||
int GenerateTreeNode(int *lines, int num_lines, const FVector2 *centroids, int *work_buffer);
|
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;
|
|
||||||
};
|
|
|
@ -32,19 +32,9 @@
|
||||||
#include "gl/shaders/gl_shadowmapshader.h"
|
#include "gl/shaders/gl_shadowmapshader.h"
|
||||||
#include "r_state.h"
|
#include "r_state.h"
|
||||||
|
|
||||||
void FShadowMap::Clear()
|
|
||||||
{
|
|
||||||
if (mLightList != 0)
|
|
||||||
{
|
|
||||||
glDeleteBuffers(1, (GLuint*)&mLightList);
|
|
||||||
mLightList = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mLightBSP.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FShadowMap::Update()
|
void FShadowMap::Update()
|
||||||
{
|
{
|
||||||
|
UploadAABBTree();
|
||||||
UploadLights();
|
UploadLights();
|
||||||
|
|
||||||
FGLDebug::PushGroup("ShadowMap");
|
FGLDebug::PushGroup("ShadowMap");
|
||||||
|
@ -54,8 +44,8 @@ void FShadowMap::Update()
|
||||||
|
|
||||||
GLRenderer->mShadowMapShader->Bind();
|
GLRenderer->mShadowMapShader->Bind();
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, mLightList);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, mLightList);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, mLightBSP.GetNodesBuffer());
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, mNodesBuffer);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, mLightBSP.GetLinesBuffer());
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, mLinesBuffer);
|
||||||
|
|
||||||
glViewport(0, 0, 1024, 1024);
|
glViewport(0, 0, 1024, 1024);
|
||||||
GLRenderer->RenderScreenQuad();
|
GLRenderer->RenderScreenQuad();
|
||||||
|
@ -72,6 +62,14 @@ void FShadowMap::Update()
|
||||||
FGLDebug::PopGroup();
|
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()
|
void FShadowMap::UploadLights()
|
||||||
{
|
{
|
||||||
mLights.Clear();
|
mLights.Clear();
|
||||||
|
@ -107,7 +105,52 @@ void FShadowMap::UploadLights()
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, oldBinding);
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "gl/dynlights/gl_lightbsp.h"
|
#include "gl/dynlights/gl_aabbtree.h"
|
||||||
#include "tarray.h"
|
#include "tarray.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class ADynamicLight;
|
class ADynamicLight;
|
||||||
|
|
||||||
|
@ -20,13 +21,21 @@ public:
|
||||||
bool ShadowTest(ADynamicLight *light, const DVector3 &pos);
|
bool ShadowTest(ADynamicLight *light, const DVector3 &pos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void UploadAABBTree();
|
||||||
void UploadLights();
|
void UploadLights();
|
||||||
|
|
||||||
FLightBSP mLightBSP;
|
|
||||||
int mLightList = 0;
|
int mLightList = 0;
|
||||||
TArray<float> mLights;
|
TArray<float> mLights;
|
||||||
TMap<ADynamicLight*, int> mLightToShadowmap;
|
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(const FShadowMap &) = delete;
|
||||||
FShadowMap &operator=(FShadowMap &) = delete;
|
FShadowMap &operator=(FShadowMap &) = delete;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue