mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-12 08:11:10 +02:00
221 lines
7.8 KiB
C++
221 lines
7.8 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Radiant masked occlusion culling bridge
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "gl_radiant_moc.h"
|
|
|
|
#define USE_D3D 0
|
|
#define USE_AVX512 0
|
|
#include "thirdparty/MaskedOcclusionCulling/MaskedOcclusionCulling.h"
|
|
|
|
#include <algorithm>
|
|
|
|
namespace {
|
|
|
|
struct radiantMOCState_t {
|
|
MaskedOcclusionCulling* moc;
|
|
unsigned int width;
|
|
unsigned int height;
|
|
bool active;
|
|
qglRadiantMOCStats_t stats;
|
|
};
|
|
|
|
radiantMOCState_t s_radiantMOC = {};
|
|
|
|
static unsigned int RadiantMOC_RoundUp(unsigned int value, unsigned int alignment) {
|
|
return (value + alignment - 1) & ~(alignment - 1);
|
|
}
|
|
|
|
static radiantMOCState_t* RadiantMOC_FromContext(qglMOCContext_t context) {
|
|
return reinterpret_cast<radiantMOCState_t*>(context);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
qglMOCContext_t QGL_MOC_Create() {
|
|
radiantMOCState_t* context = new radiantMOCState_t;
|
|
context->moc = NULL;
|
|
context->width = 0;
|
|
context->height = 0;
|
|
context->active = false;
|
|
context->stats.occluderTriangles = 0;
|
|
context->stats.testedRects = 0;
|
|
context->stats.occludedRects = 0;
|
|
return context;
|
|
}
|
|
|
|
void QGL_MOC_Destroy(qglMOCContext_t context) {
|
|
radiantMOCState_t* state = RadiantMOC_FromContext(context);
|
|
if (state == NULL) {
|
|
return;
|
|
}
|
|
if (state->moc != NULL) {
|
|
MaskedOcclusionCulling::Destroy(state->moc);
|
|
state->moc = NULL;
|
|
}
|
|
delete state;
|
|
}
|
|
|
|
bool QGL_MOC_BeginFrame(qglMOCContext_t context, int width, int height, float nearClip) {
|
|
radiantMOCState_t* state = RadiantMOC_FromContext(context);
|
|
if (state == NULL) {
|
|
return false;
|
|
}
|
|
|
|
const unsigned int mocWidth = RadiantMOC_RoundUp(std::max(width, 64), 8);
|
|
const unsigned int mocHeight = RadiantMOC_RoundUp(std::max(height, 64), 4);
|
|
|
|
if (state->moc == NULL) {
|
|
state->moc = MaskedOcclusionCulling::Create(MaskedOcclusionCulling::AVX2);
|
|
}
|
|
|
|
if (state->moc == NULL) {
|
|
state->active = false;
|
|
return false;
|
|
}
|
|
|
|
if (state->width != mocWidth || state->height != mocHeight) {
|
|
state->moc->SetResolution(mocWidth, mocHeight);
|
|
state->width = mocWidth;
|
|
state->height = mocHeight;
|
|
}
|
|
|
|
state->moc->SetNearClipPlane(nearClip);
|
|
state->moc->ClearBuffer();
|
|
state->active = true;
|
|
state->stats.occluderTriangles = 0;
|
|
state->stats.testedRects = 0;
|
|
state->stats.occludedRects = 0;
|
|
return true;
|
|
}
|
|
|
|
void QGL_MOC_EndFrame(qglMOCContext_t context) {
|
|
radiantMOCState_t* state = RadiantMOC_FromContext(context);
|
|
if (state != NULL) {
|
|
state->active = false;
|
|
}
|
|
}
|
|
|
|
bool QGL_MOC_IsActive(qglMOCContext_t context) {
|
|
radiantMOCState_t* state = RadiantMOC_FromContext(context);
|
|
return state != NULL && state->active && state->moc != NULL;
|
|
}
|
|
|
|
void QGL_MOC_RenderTriangles(qglMOCContext_t context, const qglRadiantMOCClipVertex_t* verts, const unsigned int* indices, int numTriangles) {
|
|
radiantMOCState_t* state = RadiantMOC_FromContext(context);
|
|
if (!QGL_MOC_IsActive(context) || verts == NULL || indices == NULL || numTriangles <= 0) {
|
|
return;
|
|
}
|
|
|
|
MaskedOcclusionCulling::VertexLayout layout(sizeof(qglRadiantMOCClipVertex_t), 4, 8);
|
|
state->moc->RenderTriangles(&verts[0].x, indices, numTriangles, NULL, MaskedOcclusionCulling::BACKFACE_NONE, MaskedOcclusionCulling::CLIP_PLANE_ALL, layout);
|
|
state->stats.occluderTriangles += numTriangles;
|
|
}
|
|
|
|
bool QGL_MOC_TestTriangles(qglMOCContext_t context, const qglRadiantMOCClipVertex_t* verts, const unsigned int* indices, int numTriangles) {
|
|
radiantMOCState_t* state = RadiantMOC_FromContext(context);
|
|
if (!QGL_MOC_IsActive(context) || verts == NULL || indices == NULL || numTriangles <= 0) {
|
|
return true;
|
|
}
|
|
|
|
MaskedOcclusionCulling::VertexLayout layout(sizeof(qglRadiantMOCClipVertex_t), 4, 8);
|
|
state->stats.testedRects++;
|
|
const MaskedOcclusionCulling::CullingResult result = state->moc->TestTriangles(&verts[0].x, indices, numTriangles, NULL, MaskedOcclusionCulling::BACKFACE_NONE, MaskedOcclusionCulling::CLIP_PLANE_ALL, layout);
|
|
if (result == MaskedOcclusionCulling::OCCLUDED || result == MaskedOcclusionCulling::VIEW_CULLED) {
|
|
state->stats.occludedRects++;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void QGL_MOC_RenderIndexedTriangles(qglMOCContext_t context, const float* verts, const unsigned int* indices, int numTriangles, const float* modelToClipMatrix, int vertexStride, int yOffset, int zOffset) {
|
|
radiantMOCState_t* state = RadiantMOC_FromContext(context);
|
|
if (!QGL_MOC_IsActive(context) || verts == NULL || indices == NULL || numTriangles <= 0 || modelToClipMatrix == NULL) {
|
|
return;
|
|
}
|
|
|
|
MaskedOcclusionCulling::VertexLayout layout(vertexStride, yOffset, zOffset);
|
|
state->moc->RenderTriangles(verts, indices, numTriangles, modelToClipMatrix, MaskedOcclusionCulling::BACKFACE_NONE, MaskedOcclusionCulling::CLIP_PLANE_ALL, layout);
|
|
state->stats.occluderTriangles += numTriangles;
|
|
}
|
|
|
|
bool QGL_MOC_TestIndexedTriangles(qglMOCContext_t context, const float* verts, const unsigned int* indices, int numTriangles, const float* modelToClipMatrix, int vertexStride, int yOffset, int zOffset) {
|
|
radiantMOCState_t* state = RadiantMOC_FromContext(context);
|
|
if (!QGL_MOC_IsActive(context) || verts == NULL || indices == NULL || numTriangles <= 0 || modelToClipMatrix == NULL) {
|
|
return true;
|
|
}
|
|
|
|
MaskedOcclusionCulling::VertexLayout layout(vertexStride, yOffset, zOffset);
|
|
state->stats.testedRects++;
|
|
const MaskedOcclusionCulling::CullingResult result = state->moc->TestTriangles(verts, indices, numTriangles, modelToClipMatrix, MaskedOcclusionCulling::BACKFACE_NONE, MaskedOcclusionCulling::CLIP_PLANE_ALL, layout);
|
|
if (result == MaskedOcclusionCulling::OCCLUDED || result == MaskedOcclusionCulling::VIEW_CULLED) {
|
|
state->stats.occludedRects++;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool QGL_MOC_TestRect(qglMOCContext_t context, float xmin, float ymin, float xmax, float ymax, float wmin) {
|
|
radiantMOCState_t* state = RadiantMOC_FromContext(context);
|
|
if (!QGL_MOC_IsActive(context)) {
|
|
return true;
|
|
}
|
|
|
|
state->stats.testedRects++;
|
|
const MaskedOcclusionCulling::CullingResult result = state->moc->TestRect(xmin, ymin, xmax, ymax, wmin);
|
|
if (result == MaskedOcclusionCulling::OCCLUDED || result == MaskedOcclusionCulling::VIEW_CULLED) {
|
|
state->stats.occludedRects++;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
qglRadiantMOCStats_t QGL_MOC_GetStats(qglMOCContext_t context) {
|
|
radiantMOCState_t* state = RadiantMOC_FromContext(context);
|
|
if (state == NULL) {
|
|
qglRadiantMOCStats_t emptyStats = {};
|
|
return emptyStats;
|
|
}
|
|
return state->stats;
|
|
}
|
|
|
|
bool QGL_RadiantMOC_BeginFrame(int width, int height, float nearClip) {
|
|
return QGL_MOC_BeginFrame(&s_radiantMOC, width, height, nearClip);
|
|
}
|
|
|
|
void QGL_RadiantMOC_EndFrame() {
|
|
QGL_MOC_EndFrame(&s_radiantMOC);
|
|
}
|
|
|
|
bool QGL_RadiantMOC_IsActive() {
|
|
return QGL_MOC_IsActive(&s_radiantMOC);
|
|
}
|
|
|
|
void QGL_RadiantMOC_RenderTriangles(const qglRadiantMOCClipVertex_t* verts, const unsigned int* indices, int numTriangles) {
|
|
QGL_MOC_RenderTriangles(&s_radiantMOC, verts, indices, numTriangles);
|
|
}
|
|
|
|
bool QGL_RadiantMOC_TestTriangles(const qglRadiantMOCClipVertex_t* verts, const unsigned int* indices, int numTriangles) {
|
|
return QGL_MOC_TestTriangles(&s_radiantMOC, verts, indices, numTriangles);
|
|
}
|
|
|
|
void QGL_RadiantMOC_RenderIndexedTriangles(const float* verts, const unsigned int* indices, int numTriangles, const float* modelToClipMatrix, int vertexStride, int yOffset, int zOffset) {
|
|
QGL_MOC_RenderIndexedTriangles(&s_radiantMOC, verts, indices, numTriangles, modelToClipMatrix, vertexStride, yOffset, zOffset);
|
|
}
|
|
|
|
bool QGL_RadiantMOC_TestIndexedTriangles(const float* verts, const unsigned int* indices, int numTriangles, const float* modelToClipMatrix, int vertexStride, int yOffset, int zOffset) {
|
|
return QGL_MOC_TestIndexedTriangles(&s_radiantMOC, verts, indices, numTriangles, modelToClipMatrix, vertexStride, yOffset, zOffset);
|
|
}
|
|
|
|
bool QGL_RadiantMOC_TestRect(float xmin, float ymin, float xmax, float ymax, float wmin) {
|
|
return QGL_MOC_TestRect(&s_radiantMOC, xmin, ymin, xmax, ymax, wmin);
|
|
}
|
|
|
|
qglRadiantMOCStats_t QGL_RadiantMOC_GetStats() {
|
|
return s_radiantMOC.stats;
|
|
}
|