mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
Upload BSP tree to the GPU
This commit is contained in:
parent
e64f1e645d
commit
58c7c3c902
4 changed files with 213 additions and 0 deletions
|
@ -939,6 +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/shaders/gl_shader.cpp
|
||||
gl/shaders/gl_texshader.cpp
|
||||
gl/shaders/gl_shaderprogram.cpp
|
||||
|
|
167
src/gl/dynlights/gl_lightbsp.cpp
Normal file
167
src/gl/dynlights/gl_lightbsp.cpp
Normal file
|
@ -0,0 +1,167 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
// Doom BSP tree on the GPU
|
||||
// Copyright(C) 2017 Magnus Norddahl
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
#include "gl/dynlights/gl_lightbsp.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "r_state.h"
|
||||
|
||||
int FLightBSP::GetNodesBuffer()
|
||||
{
|
||||
UpdateBuffers();
|
||||
return NodesBuffer;
|
||||
}
|
||||
|
||||
int FLightBSP::GetSegsBuffer()
|
||||
{
|
||||
UpdateBuffers();
|
||||
return SegsBuffer;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
UploadNodes();
|
||||
UploadSegs();
|
||||
}
|
||||
|
||||
void FLightBSP::UploadNodes()
|
||||
{
|
||||
TArray<GPUNode> gpunodes;
|
||||
gpunodes.Resize(numnodes);
|
||||
for (int i = 0; i < numnodes; i++)
|
||||
{
|
||||
const auto &node = nodes[i];
|
||||
auto &gpunode = gpunodes[i];
|
||||
|
||||
float a = -FIXED2FLOAT(node.dy);
|
||||
float b = FIXED2FLOAT(node.dx);
|
||||
float c = 0.0f;
|
||||
float d = -(a * FIXED2FLOAT(node.x) + b * FIXED2FLOAT(node.y));
|
||||
|
||||
gpunode.plane[0] = a;
|
||||
gpunode.plane[1] = b;
|
||||
gpunode.plane[2] = c;
|
||||
gpunode.plane[3] = d;
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
bool isNode = (!((size_t)node.children[j] & 1));
|
||||
if (isNode)
|
||||
{
|
||||
node_t *bsp = (node_t *)node.children[j];
|
||||
gpunode.children[j] = (int)(ptrdiff_t)(bsp - nodes);
|
||||
gpunode.linecount[j] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
subsector_t *sub = (subsector_t *)((BYTE *)node.children[j] - 1);
|
||||
if (sub->numlines > 0)
|
||||
gpunode.children[j] = (int)(ptrdiff_t)(sub->firstline - segs);
|
||||
else
|
||||
gpunode.children[j] = 0;
|
||||
gpunode.linecount[j] = sub->numlines;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (gpunodes.Size() > 0)
|
||||
{
|
||||
FILE *file = fopen("nodes.txt", "wb");
|
||||
fwrite(&gpunodes[0], sizeof(GPUNode) * gpunodes.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(GPUNode) * gpunodes.Size(), &gpunodes[0], GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, oldBinding);
|
||||
|
||||
NumNodes = numnodes;
|
||||
}
|
||||
|
||||
void FLightBSP::UploadSegs()
|
||||
{
|
||||
TArray<GPUSeg> gpusegs;
|
||||
gpusegs.Resize(numsegs);
|
||||
for (int i = 0; i < numsegs; i++)
|
||||
{
|
||||
const auto &seg = segs[i];
|
||||
auto &gpuseg = gpusegs[i];
|
||||
|
||||
gpuseg.x = (float)seg.v1->fX();
|
||||
gpuseg.y = (float)seg.v1->fY();
|
||||
gpuseg.dx = (float)seg.v2->fX() - gpuseg.x;
|
||||
gpuseg.dy = (float)seg.v2->fY() - gpuseg.y;
|
||||
gpuseg.bSolid = (seg.backsector == nullptr) ? 1.0f : 0.0f;
|
||||
gpuseg.padding1 = 0.0f;
|
||||
gpuseg.padding2 = 0.0f;
|
||||
gpuseg.padding3 = 0.0f;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (gpusegs.Size() > 0)
|
||||
{
|
||||
FILE *file = fopen("segs.txt", "wb");
|
||||
fwrite(&gpusegs[0], sizeof(GPUSeg) * gpusegs.Size(), 1, file);
|
||||
fclose(file);
|
||||
}
|
||||
#endif
|
||||
|
||||
int oldBinding = 0;
|
||||
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &oldBinding);
|
||||
|
||||
glGenBuffers(1, (GLuint*)&SegsBuffer);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, SegsBuffer);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GPUSeg) * gpusegs.Size(), &gpusegs[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 (SegsBuffer != 0)
|
||||
{
|
||||
glDeleteBuffers(1, (GLuint*)&SegsBuffer);
|
||||
SegsBuffer = 0;
|
||||
}
|
||||
}
|
42
src/gl/dynlights/gl_lightbsp.h
Normal file
42
src/gl/dynlights/gl_lightbsp.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
struct GPUNode
|
||||
{
|
||||
float plane[4];
|
||||
int children[2];
|
||||
int linecount[2];
|
||||
};
|
||||
|
||||
struct GPUSeg
|
||||
{
|
||||
float x, y;
|
||||
float dx, dy;
|
||||
float bSolid;
|
||||
float padding1, padding2, padding3;
|
||||
};
|
||||
|
||||
class FLightBSP
|
||||
{
|
||||
public:
|
||||
FLightBSP() { }
|
||||
~FLightBSP() { Clear(); }
|
||||
|
||||
int GetNodesBuffer();
|
||||
int GetSegsBuffer();
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
void UpdateBuffers();
|
||||
void GenerateBuffers();
|
||||
void UploadNodes();
|
||||
void UploadSegs();
|
||||
|
||||
FLightBSP(const FLightBSP &) = delete;
|
||||
FLightBSP &operator=(FLightBSP &) = delete;
|
||||
|
||||
int NodesBuffer = 0;
|
||||
int SegsBuffer = 0;
|
||||
int NumNodes = 0;
|
||||
int NumSegs = 0;
|
||||
};
|
|
@ -6,6 +6,7 @@
|
|||
#include "vectors.h"
|
||||
#include "r_renderer.h"
|
||||
#include "gl/data/gl_matrix.h"
|
||||
#include "gl/dynlights/gl_lightbsp.h"
|
||||
|
||||
struct particle_t;
|
||||
class FCanvasTexture;
|
||||
|
@ -123,6 +124,8 @@ public:
|
|||
FPresent3DColumnShader *mPresent3dColumnShader;
|
||||
FPresent3DRowShader *mPresent3dRowShader;
|
||||
|
||||
FLightBSP mLightBSP;
|
||||
|
||||
FTexture *gllight;
|
||||
FTexture *glpart2;
|
||||
FTexture *glpart;
|
||||
|
|
Loading…
Reference in a new issue