mirror of
https://github.com/overte-org/overte.git
synced 2025-04-06 00:52:37 +02:00
242 lines
6.7 KiB
C++
242 lines
6.7 KiB
C++
//
|
|
// LightClusters.h
|
|
//
|
|
// Created by Sam Gateau on 9/7/2016.
|
|
// Copyright 2015 High Fidelity, Inc.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
#ifndef hifi_render_utils_LightClusters_h
|
|
#define hifi_render_utils_LightClusters_h
|
|
|
|
#include <ViewFrustum.h>
|
|
#include <gpu/Buffer.h>
|
|
#include <render/Engine.h>
|
|
#include "LightStage.h"
|
|
#include "DeferredFrameTransform.h"
|
|
#include "LightingModel.h"
|
|
#include "SurfaceGeometryPass.h"
|
|
|
|
class FrustumGrid {
|
|
public:
|
|
float frustumNear { 0.1f };
|
|
float rangeNear { 0.1f };
|
|
float rangeFar { 200.0f };
|
|
float frustumFar { 10000.0f };
|
|
|
|
glm::ivec3 dims { 1, 1, 1 };
|
|
float spare;
|
|
|
|
glm::mat4 eyeToGridProj;
|
|
glm::mat4 worldToEyeMat;
|
|
glm::mat4 eyeToWorldMat;
|
|
|
|
FrustumGrid() = default;
|
|
FrustumGrid(const FrustumGrid& source);
|
|
|
|
void updateFrustum(const ViewFrustum& frustum) {
|
|
frustumNear = frustum.getNearClip();
|
|
frustumFar = frustum.getFarClip();
|
|
|
|
eyeToGridProj = frustum.evalProjectionMatrixRange(rangeNear, rangeFar);
|
|
|
|
Transform view;
|
|
frustum.evalViewTransform(view);
|
|
eyeToWorldMat = view.getMatrix();
|
|
worldToEyeMat = view.getInverseMatrix();
|
|
}
|
|
|
|
// Copy paste of the slh functions
|
|
using vec3 = glm::vec3;
|
|
using ivec3 = glm::ivec3;
|
|
using mat4 = glm::mat4;
|
|
#define frustumGrid (*this)
|
|
#include "LightClusterGrid_shared.slh"
|
|
|
|
|
|
using Planes = std::vector < glm::vec4 >;
|
|
void generateGridPlanes(Planes& xPlanes, Planes& yPlanes, Planes& zPlanes);
|
|
};
|
|
|
|
|
|
|
|
class LightClusters {
|
|
public:
|
|
using LightID = LightStage::Index;
|
|
|
|
static const glm::uvec4 MAX_GRID_DIMENSIONS;
|
|
|
|
LightClusters();
|
|
|
|
void setDimensions(glm::uvec3 gridDims, uint32_t listBudget = MAX_GRID_DIMENSIONS.w);
|
|
void setRangeNearFar(float rangeNear, float rangeFar);
|
|
|
|
uint32_t getNumClusters() const;
|
|
|
|
void updateFrustum(const ViewFrustum& frustum);
|
|
|
|
void updateLightStage(const LightStagePointer& lightStage);
|
|
|
|
void updateLightFrame(const LightStage::FramePointer& lightFrame, bool points = true, bool spots = true);
|
|
|
|
glm::ivec3 updateClusters();
|
|
|
|
|
|
ViewFrustum _frustum;
|
|
|
|
|
|
LightStagePointer _lightStage;
|
|
|
|
|
|
|
|
gpu::StructBuffer<FrustumGrid> _frustumGridBuffer;
|
|
|
|
FrustumGrid::Planes _gridPlanes[3];
|
|
|
|
render::ElementIndices _visibleLightIndices;
|
|
gpu::BufferView _lightIndicesBuffer;
|
|
|
|
const uint32_t EMPTY_CLUSTER { 0x0000FFFF };
|
|
const LightID INVALID_LIGHT { LightStage::INVALID_INDEX };
|
|
|
|
using LightIndex = uint16_t;
|
|
|
|
std::vector<uint32_t> _clusterGrid;
|
|
std::vector<LightIndex> _clusterContent;
|
|
gpu::BufferView _clusterGridBuffer;
|
|
gpu::BufferView _clusterContentBuffer;
|
|
uint32_t _clusterContentBudget { 0 };
|
|
|
|
bool _clusterResourcesInvalid { true };
|
|
void updateClusterResource();
|
|
};
|
|
|
|
using LightClustersPointer = std::shared_ptr<LightClusters>;
|
|
|
|
|
|
|
|
class LightClusteringPassConfig : public render::Job::Config {
|
|
Q_OBJECT
|
|
Q_PROPERTY(float rangeNear MEMBER rangeNear NOTIFY dirty)
|
|
Q_PROPERTY(float rangeFar MEMBER rangeFar NOTIFY dirty)
|
|
|
|
Q_PROPERTY(int dimX MEMBER dimX NOTIFY dirty)
|
|
Q_PROPERTY(int dimY MEMBER dimY NOTIFY dirty)
|
|
Q_PROPERTY(int dimZ MEMBER dimZ NOTIFY dirty)
|
|
|
|
Q_PROPERTY(bool freeze MEMBER freeze NOTIFY dirty)
|
|
|
|
Q_PROPERTY(int numClusteredLightReferences MEMBER numClusteredLightReferences NOTIFY dirty)
|
|
Q_PROPERTY(int numInputLights MEMBER numInputLights NOTIFY dirty)
|
|
Q_PROPERTY(int numClusteredLights MEMBER numClusteredLights NOTIFY dirty)
|
|
|
|
Q_PROPERTY(int numSceneLights MEMBER numSceneLights NOTIFY dirty)
|
|
Q_PROPERTY(int numFreeSceneLights MEMBER numFreeSceneLights NOTIFY dirty)
|
|
Q_PROPERTY(int numAllocatedSceneLights MEMBER numAllocatedSceneLights NOTIFY dirty)
|
|
|
|
public:
|
|
LightClusteringPassConfig() : render::Job::Config(true){}
|
|
float rangeNear{ 0.1f };
|
|
float rangeFar{ 200.0f };
|
|
|
|
int dimX { 14 };
|
|
int dimY { 14 };
|
|
int dimZ { 14 };
|
|
|
|
|
|
bool freeze{ false };
|
|
|
|
int numClusteredLightReferences { 0 };
|
|
int numInputLights { 0 };
|
|
int numClusteredLights { 0 };
|
|
|
|
void setNumClusteredLightReferences(int numRefs) { numClusteredLightReferences = numRefs; }
|
|
void setNumInputLights(int numLights) { numInputLights = numLights; }
|
|
void setNumClusteredLights(int numLights) { numClusteredLights = numLights; }
|
|
|
|
int numSceneLights { 0 };
|
|
int numFreeSceneLights { 0 };
|
|
int numAllocatedSceneLights { 0 };
|
|
signals:
|
|
void dirty();
|
|
|
|
protected:
|
|
};
|
|
|
|
class LightClusteringPass {
|
|
public:
|
|
using Input = render::VaryingSet4<DeferredFrameTransformPointer, LightingModelPointer, LightStage::FramePointer, LinearDepthFramebufferPointer>;
|
|
using Output = LightClustersPointer;
|
|
using Config = LightClusteringPassConfig;
|
|
using JobModel = render::Job::ModelIO<LightClusteringPass, Input, Output, Config>;
|
|
|
|
LightClusteringPass();
|
|
|
|
void configure(const Config& config);
|
|
|
|
void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output);
|
|
|
|
protected:
|
|
LightClustersPointer _lightClusters;
|
|
bool _freeze;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DebugLightClustersConfig : public render::Job::Config {
|
|
Q_OBJECT
|
|
Q_PROPERTY(bool doDrawGrid MEMBER doDrawGrid NOTIFY dirty)
|
|
Q_PROPERTY(bool doDrawClusterFromDepth MEMBER doDrawClusterFromDepth NOTIFY dirty)
|
|
Q_PROPERTY(bool doDrawContent MEMBER doDrawContent NOTIFY dirty)
|
|
public:
|
|
DebugLightClustersConfig() : render::Job::Config(false){}
|
|
|
|
|
|
bool doDrawGrid{ false };
|
|
bool doDrawClusterFromDepth { false };
|
|
bool doDrawContent { false };
|
|
|
|
signals:
|
|
void dirty();
|
|
|
|
protected:
|
|
};
|
|
|
|
|
|
#include "DeferredFramebuffer.h"
|
|
|
|
class DebugLightClusters {
|
|
public:
|
|
using Inputs = render::VaryingSet4 < DeferredFrameTransformPointer, LightingModelPointer, LinearDepthFramebufferPointer, LightClustersPointer>;
|
|
using Config = DebugLightClustersConfig;
|
|
using JobModel = render::Job::ModelI<DebugLightClusters, Inputs, Config>;
|
|
|
|
DebugLightClusters(uint transformSlot) : _transformSlot(transformSlot) {}
|
|
|
|
void configure(const Config& config);
|
|
|
|
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
|
|
|
|
protected:
|
|
static gpu::PipelinePointer _drawClusterGrid;
|
|
static gpu::PipelinePointer _drawClusterFromDepth;
|
|
static gpu::PipelinePointer _drawClusterContent;
|
|
gpu::BufferPointer _gridBuffer;
|
|
uint _transformSlot;
|
|
|
|
bool doDrawGrid { false };
|
|
bool doDrawClusterFromDepth { false };
|
|
bool doDrawContent { false };
|
|
|
|
static gpu::PipelinePointer getDrawClusterGridPipeline();
|
|
static gpu::PipelinePointer getDrawClusterFromDepthPipeline();
|
|
static gpu::PipelinePointer getDrawClusterContentPipeline();
|
|
};
|
|
|
|
#endif
|