Developping the Light Clusters, adding visualization

This commit is contained in:
samcake 2016-09-08 18:02:35 -07:00
parent 25616be7c1
commit 61de063b29
15 changed files with 412 additions and 69 deletions

View file

@ -380,6 +380,23 @@ public:
}
};
template <class T> class StructBuffer : public gpu::BufferView {
public:
static BufferPointer makeBuffer() {
T t;
return std::make_shared<gpu::Buffer>(sizeof(T), (const gpu::Byte*) &t);
}
~StructBuffer<T>() {};
StructBuffer<T>() : gpu::BufferView(makeBuffer()) {}
const T* operator ->() const { return &get<T>(); }
T& edit() {
return BufferView::edit<T>(0);
}
};
};
#endif

View file

@ -184,46 +184,46 @@ void AmbientOcclusionEffect::configure(const Config& config) {
const double RADIUS_POWER = 6.0;
const auto& radius = config.radius;
if (radius != _parametersBuffer->getRadius()) {
auto& current = _parametersBuffer->radiusInfo;
auto& current = _parametersBuffer.edit().radiusInfo;
current.x = radius;
current.y = radius * radius;
current.z = (float)(1.0 / pow((double)radius, RADIUS_POWER));
}
if (config.obscuranceLevel != _parametersBuffer->getObscuranceLevel()) {
auto& current = _parametersBuffer->radiusInfo;
auto& current = _parametersBuffer.edit().radiusInfo;
current.w = config.obscuranceLevel;
}
if (config.falloffBias != _parametersBuffer->getFalloffBias()) {
auto& current = _parametersBuffer->ditheringInfo;
auto& current = _parametersBuffer.edit().ditheringInfo;
current.z = config.falloffBias;
}
if (config.edgeSharpness != _parametersBuffer->getEdgeSharpness()) {
auto& current = _parametersBuffer->blurInfo;
auto& current = _parametersBuffer.edit().blurInfo;
current.x = config.edgeSharpness;
}
if (config.blurDeviation != _parametersBuffer->getBlurDeviation()) {
auto& current = _parametersBuffer->blurInfo;
auto& current = _parametersBuffer.edit().blurInfo;
current.z = config.blurDeviation;
shouldUpdateGaussian = true;
}
if (config.numSpiralTurns != _parametersBuffer->getNumSpiralTurns()) {
auto& current = _parametersBuffer->sampleInfo;
auto& current = _parametersBuffer.edit().sampleInfo;
current.z = config.numSpiralTurns;
}
if (config.numSamples != _parametersBuffer->getNumSamples()) {
auto& current = _parametersBuffer->sampleInfo;
auto& current = _parametersBuffer.edit().sampleInfo;
current.x = config.numSamples;
current.y = 1.0f / config.numSamples;
}
if (config.fetchMipsEnabled != _parametersBuffer->isFetchMipsEnabled()) {
auto& current = _parametersBuffer->sampleInfo;
auto& current = _parametersBuffer.edit().sampleInfo;
current.w = (float)config.fetchMipsEnabled;
}
@ -232,26 +232,26 @@ void AmbientOcclusionEffect::configure(const Config& config) {
}
if (config.perspectiveScale != _parametersBuffer->getPerspectiveScale()) {
_parametersBuffer->resolutionInfo.z = config.perspectiveScale;
_parametersBuffer.edit().resolutionInfo.z = config.perspectiveScale;
}
if (config.resolutionLevel != _parametersBuffer->getResolutionLevel()) {
auto& current = _parametersBuffer->resolutionInfo;
auto& current = _parametersBuffer.edit().resolutionInfo;
current.x = (float) config.resolutionLevel;
}
if (config.blurRadius != _parametersBuffer->getBlurRadius()) {
auto& current = _parametersBuffer->blurInfo;
auto& current = _parametersBuffer.edit().blurInfo;
current.y = (float)config.blurRadius;
shouldUpdateGaussian = true;
}
if (config.ditheringEnabled != _parametersBuffer->isDitheringEnabled()) {
auto& current = _parametersBuffer->ditheringInfo;
auto& current = _parametersBuffer.edit().ditheringInfo;
current.x = (float)config.ditheringEnabled;
}
if (config.borderingEnabled != _parametersBuffer->isBorderingEnabled()) {
auto& current = _parametersBuffer->ditheringInfo;
auto& current = _parametersBuffer.edit().ditheringInfo;
current.w = (float)config.borderingEnabled;
}
@ -334,7 +334,7 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getVBlurPipeline() {
}
void AmbientOcclusionEffect::updateGaussianDistribution() {
auto coefs = _parametersBuffer->_gaussianCoefs;
auto coefs = _parametersBuffer.edit()._gaussianCoefs;
GaussianDistribution::evalSampling(coefs, Parameters::GAUSSIAN_COEFS_LENGTH, _parametersBuffer->getBlurRadius(), _parametersBuffer->getBlurDeviation());
}
@ -451,7 +451,7 @@ void DebugAmbientOcclusion::configure(const Config& config) {
auto cursorPos = glm::vec2(_parametersBuffer->pixelInfo);
if (cursorPos != config.debugCursorTexcoord) {
_parametersBuffer->pixelInfo = glm::vec4(config.debugCursorTexcoord, 0.0f, 0.0f);
_parametersBuffer.edit().pixelInfo = glm::vec4(config.debugCursorTexcoord, 0.0f, 0.0f);
}
}

View file

@ -104,26 +104,6 @@ signals:
void dirty();
};
namespace gpu {
template <class T> class UniformBuffer : public gpu::BufferView {
public:
static BufferPointer makeBuffer() {
T t;
return std::make_shared<gpu::Buffer>(sizeof(T), (const gpu::Byte*) &t);
}
~UniformBuffer<T>() {};
UniformBuffer<T>() : gpu::BufferView(makeBuffer()) {}
const T* operator ->() const { return &get<T>(); }
T* operator ->() {
return &edit<T>(0);
}
};
}
class AmbientOcclusionEffect {
public:
using Inputs = render::VaryingSet3<DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer>;
@ -172,7 +152,7 @@ public:
bool isDitheringEnabled() const { return ditheringInfo.x; }
bool isBorderingEnabled() const { return ditheringInfo.w; }
};
using ParametersBuffer = gpu::UniformBuffer<Parameters>;
using ParametersBuffer = gpu::StructBuffer<Parameters>;
private:
void updateGaussianDistribution();
@ -232,7 +212,7 @@ private:
Parameters() {}
};
gpu::UniformBuffer<Parameters> _parametersBuffer;
gpu::StructBuffer<Parameters> _parametersBuffer;
const gpu::PipelinePointer& getDebugPipeline();

View file

@ -116,6 +116,11 @@ void DeferredLightingEffect::init() {
loadLightVolumeProgram(deferred_light_spot_vert, no_light_frag, false, _spotLightBack, _spotLightLocations);
loadLightVolumeProgram(deferred_light_spot_vert, no_light_frag, true, _spotLightFront, _spotLightLocations);
// Light Stage and clusters
_lightStage = std::make_shared<LightStage>();
_lightClusters = std::make_shared<LightClusters>();
_lightClusters->updateLightStage(_lightStage);
// Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light
_allocatedLights.push_back(std::make_shared<model::Light>());
model::LightPointer lp = _allocatedLights[0];
@ -127,13 +132,13 @@ void DeferredLightingEffect::init() {
lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset::OLD_TOWN_SQUARE);
// Add the global light to the light stage (for later shadow rendering)
_globalLights.push_back(_lightStage.addLight(lp));
_globalLights.push_back(_lightStage->addLight(lp));
}
void DeferredLightingEffect::addLight(const model::LightPointer& light) {
assert(light);
auto lightID = _lightStage.addLight(light);
auto lightID = _lightStage->addLight(light);
if (light->getType() == model::Light::POINT) {
_pointLights.push_back(lightID);
} else {
@ -239,10 +244,8 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo
auto state = std::make_shared<gpu::State>();
state->setColorWriteMask(true, true, true, false);
// state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
if (lightVolume) {
state->setStencilTest(true, 0x00, gpu::State::StencilTest(1, 0xFF, gpu::GREATER_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
state->setStencilTest(true, 0x00, gpu::State::StencilTest(1, 0xFF, gpu::LESS_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
state->setCullMode(gpu::State::CULL_BACK);
// state->setCullMode(gpu::State::CULL_FRONT);
@ -270,27 +273,29 @@ static void loadLightVolumeProgram(const char* vertSource, const char* fragSourc
gpu::ShaderPointer program = makeLightProgram(vertSource, fragSource, locations);
auto state = std::make_shared<gpu::State>();
// state->setColorWriteMask(true, true, true, false);
state->setColorWriteMask(false, false, false, false);
// Stencil test all the light passes for objects pixels only, not the background
if (front) {
state->setCullMode(gpu::State::CULL_BACK);
state->setDepthTest(true, false, gpu::LESS_EQUAL);
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_DECR));
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_DECR, gpu::State::STENCIL_OP_KEEP));
// state->setDepthClampEnable(true);
// TODO: We should use DepthClamp and avoid changing geometry for inside /outside cases
// additive blending
// state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
//state->setColorWriteMask(true, true, true, false);
state->setColorWriteMask(false, false, false, false);
} else {
state->setCullMode(gpu::State::CULL_FRONT);
state->setDepthTest(true, false, gpu::LESS_EQUAL);
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_INCR));
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_INCR, gpu::State::STENCIL_OP_KEEP));
// additive blending
// state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
// state->setColorWriteMask(true, true, true, false);
state->setColorWriteMask(false, false, false, false);
}
pipeline = gpu::Pipeline::create(program, state);
@ -568,8 +573,8 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c
// Global directional light and ambient pass
assert(deferredLightingEffect->getLightStage().getNumLights() > 0);
auto lightAndShadow = deferredLightingEffect->getLightStage().getLightAndShadow(0);
assert(deferredLightingEffect->getLightStage()->getNumLights() > 0);
auto lightAndShadow = deferredLightingEffect->getLightStage()->getLightAndShadow(0);
const auto& globalShadow = lightAndShadow.second;
// Bind the shadow buffer
@ -682,6 +687,8 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext,
int numSpotLights = (int) srcSpotLights.size();
int offsetSpotLights = numPointLights;
auto lightClusters = deferredLightingEffect->_lightClusters;
std::vector<int> lightIndices(numPointLights + numSpotLights + 1);
lightIndices[0] = 0;
@ -695,11 +702,20 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext,
}
if (lightIndices[0] > 0) {
static int frame = 0;
frame++;
if (frame % 1000 == 0) {
lightClusters->updateFrustum(viewFrustum);
lightClusters->updateVisibleLights(lightIndices);
}
_localLightsBuffer._buffer->setData(lightIndices.size() * sizeof(int), (const gpu::Byte*) lightIndices.data());
_localLightsBuffer._size = lightIndices.size() * sizeof(int);
// Bind the global list of lights and the visible lights this frame
batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer);
batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()->_lightArrayBuffer);
batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightIndexBufferUnit, _localLightsBuffer);

View file

@ -28,6 +28,8 @@
#include "LightingModel.h"
#include "LightStage.h"
#include "LightClusters.h"
#include "SurfaceGeometryPass.h"
#include "SubsurfaceScattering.h"
#include "AmbientOcclusionEffect.h"
@ -59,7 +61,8 @@ public:
// update global lighting
void setGlobalLight(const model::LightPointer& light);
const LightStage& getLightStage() { return _lightStage; }
const LightStagePointer getLightStage() { return _lightStage; }
const LightClustersPointer getLightClusters() { return _lightClusters; }
void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; };
void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; }
@ -68,7 +71,9 @@ public:
private:
DeferredLightingEffect() = default;
LightStage _lightStage;
LightStagePointer _lightStage;
LightClustersPointer _lightClusters;
bool _shadowMapEnabled{ false };
bool _ambientOcclusionEnabled{ false };
@ -200,4 +205,6 @@ protected:
gpu::RangeTimerPointer _gpuTimer;
};
#endif // hifi_DeferredLightingEffect_h

View file

@ -10,3 +10,114 @@
#include "LightClusters.h"
#include <gpu/Context.h>
#include "lightClusters_drawGrid_vert.h"
#include "lightClusters_drawGrid_frag.h"
enum LightClusterGridShader_BufferSlot {
LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT = 0,
};
#include "DeferredLightingEffect.h"
LightClusters::LightClusters() {
}
void LightClusters::updateFrustum(const ViewFrustum& frustum) {
_frustum = frustum;
_frustrumGridBuffer.edit().updateFrustrum(frustum);
}
void LightClusters::updateLightStage(const LightStagePointer& lightStage) {
_lightStage = lightStage;
}
void LightClusters::updateVisibleLights(const LightStage::LightIndices& visibleLights) {
}
DebugLightClusters::DebugLightClusters() {
}
void DebugLightClusters::configure(const Config& config) {
}
const gpu::PipelinePointer DebugLightClusters::getDrawClusterGridPipeline() {
if (!_drawClusterGrid) {
auto vs = gpu::Shader::createVertex(std::string(lightClusters_drawGrid_vert));
auto ps = gpu::Shader::createPixel(std::string(lightClusters_drawGrid_frag));
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("frustrumGridBuffer"), LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT));
gpu::Shader::makeProgram(*program, slotBindings);
auto state = std::make_shared<gpu::State>();
state->setDepthTest(true, false, gpu::LESS_EQUAL);
// Blend on transparent
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
// Good to go add the brand new pipeline
_drawClusterGrid = gpu::Pipeline::create(program, state);
}
return _drawClusterGrid;
}
void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
auto lightClusters = deferredLightingEffect->getLightClusters();
/* auto deferredTransform = inputs.get0();
auto deferredFramebuffer = inputs.get1();
auto lightingModel = inputs.get2();
auto surfaceGeometryFramebuffer = inputs.get3();
auto ssaoFramebuffer = inputs.get4();
auto subsurfaceScatteringResource = inputs.get5();
*/
auto args = renderContext->args;
auto drawPipeline = getDrawClusterGridPipeline();
gpu::Batch batch;
// Assign the camera transform
batch.setViewportTransform(args->_viewport);
glm::mat4 projMat;
Transform viewMat;
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat, true);
// Then the actual ClusterGrid attributes
batch.setModelTransform(Transform());
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustrumGridBuffer);
// bind the one gpu::Pipeline we need
batch.setPipeline(drawPipeline);
if (true) {
batch.draw(gpu::LINES, 24, 0);
}
args->_context->appendFrameBatch(batch);
}

View file

@ -11,12 +11,12 @@
#ifndef hifi_render_utils_LightClusters_h
#define hifi_render_utils_LightClusters_h
#include "gpu/Framebuffer.h"
#include <gpu/Buffer.h>
#include <render/Engine.h>
#include "LightStage.h"
#include <ViewFrustum.h>
/*
class FrustumGrid {
public:
float _near { 0.1f };
@ -25,6 +25,12 @@ public:
float _far { 10000.0f };
glm::uvec3 _dims { 16, 16, 16 };
float spare;
glm::mat4 _eyeToGridProj;
glm::mat4 _eyeToGridProjInv;
glm::mat4 _worldToEyeMat;
glm::mat4 _eyeToWorldMat;
float viewToLinearDepth(float depth) const {
float nDepth = -depth;
@ -43,36 +49,104 @@ public:
return depth / (float) _dims.z;
}
glm::vec2 linearToGridXY(const glm::vec3& cpos) const {
return glm::vec2(cpos.x / (float) _dims.x, cpos.y / (float) _dims.y);
}
int gridDepthToLayer(float gridDepth) const {
return (int) gridDepth;
}
glm::vec2 ndcToGridXY(const glm::vec3& ncpos) const {
return 0.5f * glm::vec2((ncpos.x + 1.0f) / (float)_dims.x, (ncpos.y + 1.0f) / (float)_dims.y);
}
glm::ivec3 viewToGridPos(const glm::vec3& pos) const {
return glm::ivec3(0);
float z = linearToGridDepth(viewToLinearDepth(pos.z));
auto cpos = _eyeToGridProj * glm::vec4(pos, 1.0f);
glm::vec3 ncpos(cpos);
ncpos /= cpos.w;
return glm::ivec3(ndcToGridXY(ncpos), (int) linearToGridDepth(z));
}
void updateFrustrum(const ViewFrustum& frustum) {
_eyeToGridProj = frustum.evalProjectionMatrixRange(_nearPrime, _farPrime);
_eyeToGridProjInv = glm::inverse(_eyeToGridProj);
Transform view;
frustum.evalViewTransform(view);
_eyeToWorldMat = view.getMatrix();
_worldToEyeMat = view.getInverseMatrix();
}
};
*/
class LightClusters {
public:
LightClusters();
void updateFrustum(const ViewFrustum& frustum);
void updateLightStage(const LightStagePointer& lightStage);
void updateVisibleLights(const LightStage::LightIndices& visibleLights);
// FrustumGrid _grid;
ViewFrustum _frustum;
LightStagePointer _lightStage;
gpu::StructBuffer<FrustumGrid> _frustrumGridBuffer;
gpu::BufferPointer _lightIndicesBuffer;
};
using LightClustersPointer = std::shared_ptr<LightClusters>;
class DebugLightClustersConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged)
Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty)
public:
DebugLightClustersConfig() : render::Job::Config(true){}
int getNumDrawn() { return numDrawn; }
void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); }
int maxDrawn { -1 };
signals:
void numDrawnChanged();
void dirty();
protected:
int numDrawn { 0 };
};
class DebugLightClusters {
public:
// using Inputs = render::VaryingSet6 < DeferredFrameTransformPointer, DeferredFramebufferPointer, LightingModelPointer, SurfaceGeometryFramebufferPointer, AmbientOcclusionFramebufferPointer, SubsurfaceScatteringResourcePointer>;
using Config = DebugLightClustersConfig;
using JobModel = render::Job::Model<DebugLightClusters, Config>;
DebugLightClusters();
void configure(const Config& config);
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
protected:
gpu::BufferPointer _gridBuffer;
gpu::PipelinePointer _drawClusterGrid;
const gpu::PipelinePointer getDrawClusterGridPipeline();
};
#endif

View file

@ -32,6 +32,8 @@ public:
using Lights = render::indexed_container::IndexedPointerVector<model::Light>;
using LightMap = std::unordered_map<LightPointer, Index>;
using LightIndices = std::vector<Index>;
class Shadow {
public:
using UniformBufferView = gpu::BufferView;

View file

@ -190,6 +190,11 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
addJob<DrawItemSelection>("DrawItemSelection", spatialSelection);
}
// LIght Cluster Grid Debuging job
{
addJob<DebugLightClusters>("DebugLightClusters");
}
// Status icon rendering job
{
// Grab a texture map representing the different status icons and assign that to the drawStatsuJob

View file

@ -36,12 +36,12 @@ void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const
assert(renderContext->args);
assert(renderContext->args->hasViewFrustum());
const auto& lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
auto lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
LightStage::Index globalLightIndex { 0 };
const auto globalLight = lightStage.getLight(globalLightIndex);
const auto shadow = lightStage.getShadow(globalLightIndex);
const auto globalLight = lightStage->getLight(globalLightIndex);
const auto shadow = lightStage->getShadow(globalLightIndex);
if (!shadow) return;
const auto& fbo = shadow->framebuffer;
@ -144,8 +144,8 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render
return;
}
const auto& lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
const auto globalShadow = lightStage.getShadow(0);
auto lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
const auto globalShadow = lightStage->getShadow(0);
// If the global light is not set, bail
if (!globalShadow) {

View file

@ -530,7 +530,7 @@ void DebugSubsurfaceScattering::run(const render::SceneContextPointer& sceneCont
const auto light = DependencyManager::get<DeferredLightingEffect>()->getLightStage().getLight(0);
const auto light = DependencyManager::get<DeferredLightingEffect>()->getLightStage()->getLight(0);
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
batch.enableStereo(false);

View file

@ -0,0 +1,19 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// lightClusters_drawGrid.slf
//
// Created by Sam Gateau on 9/8/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
//
in vec4 varColor;
out vec4 outFragColor;
void main(void) {
outFragColor = varColor;
}

View file

@ -0,0 +1,89 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// lightClusters_drawGrid.slv
// Vertex shader
//
// Created by Sam Gateau on 9/8/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
//
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
<@include gpu/Color.slh@>
<$declareColorWheel()$>
struct FrustrumGrid {
vec4 nearFarRange;
ivec4 dims;
mat4 eyeToGridProj;
mat4 eyeToGridProjInv;
mat4 worldToEyeMat;
mat4 eyeToWorldMat;
};
uniform frustrumGridBuffer {
FrustrumGrid frustrumGrid;
};
//uniform ivec4 inClusterLocation;
out vec4 varColor;
void main(void) {
const vec4 UNIT_BOX[8] = vec4[8](
vec4(0.0, 0.0, 0.0, 1.0),
vec4(1.0, 0.0, 0.0, 1.0),
vec4(0.0, 1.0, 0.0, 1.0),
vec4(1.0, 1.0, 0.0, 1.0),
vec4(0.0, 0.0, 1.0, 1.0),
vec4(1.0, 0.0, 1.0, 1.0),
vec4(0.0, 1.0, 1.0, 1.0),
vec4(1.0, 1.0, 1.0, 1.0)
);
const int UNIT_BOX_LINE_INDICES[24] = int[24](
0, 1,
1, 3,
3, 2,
2, 0,
4, 5,
5, 7,
7, 6,
6, 4,
2, 6,
3, 7,
0, 4,
1, 5
);
vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]];
// pos.z -= 10.0f;
vec4 eyePos = frustrumGrid.eyeToGridProjInv * (pos);
eyePos.xyz *= eyePos.w;
vec4 worldPos = frustrumGrid.eyeToWorldMat * vec4(eyePos.xyz, 1.0);
/*
int cellIsEmpty = sign(inClusterLocation.w);
ivec4 cellLocation = ivec4(inClusterLocation.xyz, (inClusterLocation.w < 0 ? -inClusterLocation.w : inClusterLocation.w));
vec4 cellBound = evalBound(cellLocation);
pos.xyz = cellBound.xyz + vec3(cellBound.w) * pos.xyz;
*/
// standard transform
TransformCamera cam = getTransformCamera();
<$transformWorldToClipPos(cam, worldPos, gl_Position)$>
varColor = vec4(colorWheel(fract(float(gl_VertexID) / 24.0)), 0.9);
}

View file

@ -657,6 +657,26 @@ void ViewFrustum::evalProjectionMatrix(glm::mat4& proj) const {
proj = _projection;
}
glm::mat4 ViewFrustum::evalProjectionMatrixRange(float rangeNear, float rangeFar) const {
// make sure range near far make sense
assert(rangeNear > 0.0);
assert(rangeFar > rangeNear);
// recreate a projection matrix for only a range of depth of this frustum.
// take the current projection
glm::mat4 rangeProj = _projection;
float A = -(rangeFar + rangeNear) / (rangeFar - rangeNear);
float B = -2 * rangeFar*rangeNear / ((rangeFar - rangeNear));
rangeProj[2][2] = A;
rangeProj[3][2] = B;
return rangeProj;
}
void ViewFrustum::evalViewTransform(Transform& view) const {
view.setTranslation(getPosition());
view.setRotation(getOrientation());

View file

@ -129,6 +129,9 @@ public:
float distanceToCamera(const glm::vec3& point) const;
void evalProjectionMatrix(glm::mat4& proj) const;
glm::mat4 evalProjectionMatrixRange(float rangeNear, float rangeFar) const;
void evalViewTransform(Transform& view) const;
enum PlaneIndex { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE, NUM_PLANES };