mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
Merge pull request #15469 from SamGondelman/switch
Case 22379: Run-time switch for deferred/forward rendering
This commit is contained in:
commit
4c4589271c
45 changed files with 532 additions and 259 deletions
|
@ -245,11 +245,8 @@
|
|||
#include "webbrowser/WebBrowserSuggestionsEngine.h"
|
||||
#include <DesktopPreviewProvider.h>
|
||||
|
||||
|
||||
#include "AboutUtil.h"
|
||||
|
||||
#include <DisableDeferred.h>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
|
@ -3030,7 +3027,7 @@ void Application::initializeDisplayPlugins() {
|
|||
void Application::initializeRenderEngine() {
|
||||
// FIXME: on low end systems os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread.
|
||||
DeadlockWatchdogThread::withPause([&] {
|
||||
_graphicsEngine.initializeRender(DISABLE_DEFERRED);
|
||||
_graphicsEngine.initializeRender();
|
||||
DependencyManager::get<Keyboard>()->registerKeyboardHighlighting();
|
||||
});
|
||||
}
|
||||
|
@ -6707,7 +6704,7 @@ void Application::updateRenderArgs(float deltaTime) {
|
|||
}
|
||||
appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getOctreeSizeScale(),
|
||||
lodManager->getBoundaryLevelAdjust(), lodManager->getLODAngleHalfTan(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
||||
RenderArgs::MONO, RenderArgs::DEFERRED, RenderArgs::RENDER_DEBUG_NONE);
|
||||
appRenderArgs._renderArgs._scene = getMain3DScene();
|
||||
|
||||
{
|
||||
|
|
|
@ -272,10 +272,10 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
void SecondaryCameraRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) {
|
||||
void SecondaryCameraRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor) {
|
||||
const auto cachedArg = task.addJob<SecondaryCameraJob>("SecondaryCamera");
|
||||
|
||||
task.addJob<RenderViewTask>("RenderSecondView", cullFunctor, isDeferred, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1);
|
||||
task.addJob<RenderViewTask>("RenderSecondView", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1);
|
||||
|
||||
task.addJob<EndSecondaryCameraFrame>("EndSecondaryCamera", cachedArg);
|
||||
}
|
|
@ -65,7 +65,7 @@ public:
|
|||
using JobModel = render::Task::Model<SecondaryCameraRenderTask, Config>;
|
||||
SecondaryCameraRenderTask() {}
|
||||
void configure(const Config& config) {}
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred = true);
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -65,15 +65,15 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) {
|
|||
DependencyManager::get<TextureCache>()->setGPUContext(_gpuContext);
|
||||
}
|
||||
|
||||
void GraphicsEngine::initializeRender(bool disableDeferred) {
|
||||
void GraphicsEngine::initializeRender() {
|
||||
|
||||
// Set up the render engine
|
||||
render::CullFunctor cullFunctor = LODManager::shouldRender;
|
||||
_renderEngine->addJob<UpdateSceneTask>("UpdateScene");
|
||||
#ifndef Q_OS_ANDROID
|
||||
_renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraJob", cullFunctor, !disableDeferred);
|
||||
_renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraJob", cullFunctor);
|
||||
#endif
|
||||
_renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, !disableDeferred, render::ItemKey::TAG_BITS_0, render::ItemKey::TAG_BITS_0);
|
||||
_renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, render::ItemKey::TAG_BITS_0, render::ItemKey::TAG_BITS_0);
|
||||
_renderEngine->load();
|
||||
_renderEngine->registerScene(_renderScene);
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
~GraphicsEngine();
|
||||
|
||||
void initializeGPU(GLWidget*);
|
||||
void initializeRender(bool disableDeferred);
|
||||
void initializeRender();
|
||||
void startup();
|
||||
void shutdown();
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace render {
|
|||
PerformanceTimer perfTimer("worldBox");
|
||||
|
||||
auto& batch = *args->_batch;
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, false, false, true, args->_renderMethod == Args::RenderMethod::FORWARD);
|
||||
WorldBoxRenderData::renderWorldBox(args, batch);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,7 @@ const float ParabolaPointer::RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_W
|
|||
const bool ParabolaPointer::RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_ISVISIBLEINSECONDARYCAMERA { false };
|
||||
const bool ParabolaPointer::RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_DRAWINFRONT { false };
|
||||
|
||||
gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::_parabolaPipeline { nullptr };
|
||||
gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::_transparentParabolaPipeline { nullptr };
|
||||
std::map<std::pair<bool, bool>, gpu::PipelinePointer> ParabolaPointer::RenderState::ParabolaRenderItem::_parabolaPipelines;
|
||||
|
||||
ParabolaPointer::ParabolaPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, bool hover,
|
||||
const PointerTriggers& triggers, bool faceAvatar, bool followNormal, float followNormalStrength, bool centerEndY, bool lockEnd, bool distanceScaleEnd,
|
||||
|
@ -401,33 +400,34 @@ void ParabolaPointer::RenderState::ParabolaRenderItem::updateBounds() {
|
|||
_bound = AABox(min, max - min);
|
||||
}
|
||||
|
||||
const gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabolaPipeline() {
|
||||
if (!_parabolaPipeline || !_transparentParabolaPipeline) {
|
||||
{
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::parabola);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabolaPipeline(bool forward) const {
|
||||
if (_parabolaPipelines.empty()) {
|
||||
using namespace shader::render_utils::program;
|
||||
|
||||
static const std::vector<std::tuple<bool, bool, uint32_t>> keys = {
|
||||
std::make_tuple(false, false, parabola), std::make_tuple(false, true, forward_parabola), std::make_tuple(true, false, parabola_translucent)/*, std::make_tuple(true, true, forward_parabola_translucent)*/
|
||||
};
|
||||
|
||||
for (auto& key : keys) {
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(false,
|
||||
if (std::get<0>(key)) {
|
||||
PrepareStencil::testMask(*state);
|
||||
} else {
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
}
|
||||
state->setBlendFunction(std::get<0>(key),
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
state->setCullMode(gpu::State::CULL_NONE);
|
||||
_parabolaPipeline = gpu::Pipeline::create(program, state);
|
||||
|
||||
_parabolaPipelines[{std::get<0>(key), std::get<1>(key)}] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state);
|
||||
}
|
||||
|
||||
{
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::parabola_translucent);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
PrepareStencil::testMask(*state);
|
||||
state->setCullMode(gpu::State::CULL_NONE);
|
||||
_transparentParabolaPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
// The forward opaque/translucent pipelines are the same for now
|
||||
_parabolaPipelines[{ true, true }] = _parabolaPipelines[{ false, true}];
|
||||
}
|
||||
return (_parabolaData.color.a < 1.0f ? _transparentParabolaPipeline : _parabolaPipeline);
|
||||
return _parabolaPipelines[{ _parabolaData.color.a < 1.0f, forward }];
|
||||
}
|
||||
|
||||
void ParabolaPointer::RenderState::ParabolaRenderItem::render(RenderArgs* args) {
|
||||
|
@ -441,7 +441,7 @@ void ParabolaPointer::RenderState::ParabolaRenderItem::render(RenderArgs* args)
|
|||
transform.setTranslation(_origin);
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
batch.setPipeline(getParabolaPipeline());
|
||||
batch.setPipeline(getParabolaPipeline(args->_renderMethod == render::Args::RenderMethod::FORWARD));
|
||||
|
||||
const int MAX_SECTIONS = 100;
|
||||
if (glm::length2(_parabolaData.acceleration) < EPSILON) {
|
||||
|
|
|
@ -26,9 +26,8 @@ public:
|
|||
bool isVisibleInSecondaryCamera, bool drawInFront, bool enabled);
|
||||
~ParabolaRenderItem() {}
|
||||
|
||||
static gpu::PipelinePointer _parabolaPipeline;
|
||||
static gpu::PipelinePointer _transparentParabolaPipeline;
|
||||
const gpu::PipelinePointer getParabolaPipeline();
|
||||
static std::map<std::pair<bool, bool>, gpu::PipelinePointer> _parabolaPipelines;
|
||||
gpu::PipelinePointer getParabolaPipeline(bool forward) const;
|
||||
|
||||
void render(RenderArgs* args);
|
||||
render::Item::Bound& editBound() { return _bound; }
|
||||
|
|
|
@ -145,6 +145,7 @@ void GameWorkloadRenderItem::setAllViews(const workload::Views& views) {
|
|||
}
|
||||
|
||||
const gpu::PipelinePointer GameWorkloadRenderItem::getProxiesPipeline() {
|
||||
// FIXME: this needs a forward pipeline, or to only write to one output
|
||||
if (!_drawAllProxiesPipeline) {
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::drawWorkloadProxy);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
|
@ -162,6 +163,7 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getProxiesPipeline() {
|
|||
|
||||
|
||||
const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() {
|
||||
// FIXME: this needs a forward pipeline, or to only write to one output
|
||||
if (!_drawAllViewsPipeline) {
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::drawWorkloadView);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
|
|
|
@ -779,7 +779,7 @@ void Avatar::render(RenderArgs* renderArgs) {
|
|||
pointerTransform.setTranslation(position);
|
||||
pointerTransform.setRotation(rotation);
|
||||
batch.setModelTransform(pointerTransform);
|
||||
geometryCache->bindSimpleProgram(batch);
|
||||
geometryCache->bindSimpleProgram(batch, false, false, true, false, false, true, renderArgs->_renderMethod == render::Args::FORWARD);
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, laserLength, 0.0f), laserColor, _leftPointerGeometryID);
|
||||
}
|
||||
}
|
||||
|
@ -803,7 +803,7 @@ void Avatar::render(RenderArgs* renderArgs) {
|
|||
pointerTransform.setTranslation(position);
|
||||
pointerTransform.setRotation(rotation);
|
||||
batch.setModelTransform(pointerTransform);
|
||||
geometryCache->bindSimpleProgram(batch);
|
||||
geometryCache->bindSimpleProgram(batch, false, false, true, false, false, true, renderArgs->_renderMethod == render::Args::FORWARD);
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, laserLength, 0.0f), laserColor, _rightPointerGeometryID);
|
||||
}
|
||||
}
|
||||
|
@ -829,7 +829,7 @@ void Avatar::render(RenderArgs* renderArgs) {
|
|||
auto& frustum = renderArgs->getViewFrustum();
|
||||
auto textPosition = getDisplayNamePosition();
|
||||
if (frustum.pointIntersectsFrustum(textPosition)) {
|
||||
renderDisplayName(batch, frustum, textPosition);
|
||||
renderDisplayName(batch, frustum, textPosition, renderArgs->_renderMethod == render::Args::FORWARD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1034,7 +1034,7 @@ Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& view, const g
|
|||
return result;
|
||||
}
|
||||
|
||||
void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition) const {
|
||||
void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition, bool forward) const {
|
||||
PROFILE_RANGE_BATCH(batch, __FUNCTION__);
|
||||
|
||||
bool shouldShowReceiveStats = showReceiveStats && !isMyAvatar();
|
||||
|
@ -1090,7 +1090,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const
|
|||
|
||||
{
|
||||
PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderBevelCornersRect");
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, true);
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, true, true, forward);
|
||||
DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height,
|
||||
bevelDistance, backgroundColor, _nameRectGeometryID);
|
||||
}
|
||||
|
@ -1103,7 +1103,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const
|
|||
batch.setModelTransform(textTransform);
|
||||
{
|
||||
PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderText");
|
||||
renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor);
|
||||
renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor, glm::vec2(-1.0f), forward);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -694,7 +694,7 @@ protected:
|
|||
glm::vec3 getDisplayNamePosition() const;
|
||||
|
||||
Transform calculateDisplayNameTransform(const ViewFrustum& view, const glm::vec3& textPosition) const;
|
||||
void renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition) const;
|
||||
void renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition, bool forward) const;
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const;
|
||||
virtual void fixupModelsInScene(const render::ScenePointer& scene);
|
||||
|
||||
|
|
|
@ -261,15 +261,17 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) {
|
|||
Transform transform;
|
||||
bool hasTickMarks;
|
||||
glm::vec4 tickProperties;
|
||||
bool forward;
|
||||
withReadLock([&] {
|
||||
transform = _renderTransform;
|
||||
hasTickMarks = _ringProperties.getHasTickMarks();
|
||||
tickProperties = glm::vec4(_ringProperties.getMajorTickMarksAngle(), _ringProperties.getMajorTickMarksLength(),
|
||||
_ringProperties.getMinorTickMarksAngle(), _ringProperties.getMinorTickMarksLength());
|
||||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||
});
|
||||
|
||||
bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
|
||||
geometryCache->bindSimpleProgram(batch, false, isTransparent(), false, wireframe, true, true, _renderLayer != RenderLayer::WORLD);
|
||||
geometryCache->bindSimpleProgram(batch, false, isTransparent(), false, wireframe, true, true, forward);
|
||||
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
|
|
|
@ -113,11 +113,13 @@ void GridEntityRenderer::doRender(RenderArgs* args) {
|
|||
glm::vec4 color;
|
||||
glm::vec3 dimensions;
|
||||
Transform renderTransform;
|
||||
bool forward;
|
||||
withReadLock([&] {
|
||||
color = glm::vec4(toGlm(_color), _alpha);
|
||||
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
||||
dimensions = _dimensions;
|
||||
renderTransform = _renderTransform;
|
||||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||
});
|
||||
|
||||
if (!_visible) {
|
||||
|
@ -153,5 +155,5 @@ void GridEntityRenderer::doRender(RenderArgs* args) {
|
|||
DependencyManager::get<GeometryCache>()->renderGrid(*batch, minCorner, maxCorner,
|
||||
minorGridRowDivisions, minorGridColDivisions, MINOR_GRID_EDGE,
|
||||
majorGridRowDivisions, majorGridColDivisions, MAJOR_GRID_EDGE,
|
||||
color, _geometryId);
|
||||
color, forward, _geometryId);
|
||||
}
|
|
@ -55,7 +55,8 @@ void LineEntityRenderer::doRender(RenderArgs* args) {
|
|||
transform.setRotation(modelTransform.getRotation());
|
||||
batch.setModelTransform(transform);
|
||||
if (_linePoints.size() > 1) {
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, false, false, true,
|
||||
_renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD);
|
||||
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1522,7 +1522,7 @@ void ModelEntityRenderer::doRender(RenderArgs* args) {
|
|||
model = _model;
|
||||
});
|
||||
if (model) {
|
||||
model->renderDebugMeshBoxes(batch);
|
||||
model->renderDebugMeshBoxes(batch, args->_renderMethod == Args::RenderMethod::FORWARD);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -19,15 +19,12 @@
|
|||
#include <PerfStat.h>
|
||||
#include <shaders/Shaders.h>
|
||||
|
||||
#include <DisableDeferred.h>
|
||||
|
||||
#include "paintStroke_Shared.slh"
|
||||
|
||||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
gpu::PipelinePointer PolyLineEntityRenderer::_pipeline = nullptr;
|
||||
gpu::PipelinePointer PolyLineEntityRenderer::_glowPipeline = nullptr;
|
||||
std::map<std::pair<render::Args::RenderMethod, bool>, gpu::PipelinePointer> PolyLineEntityRenderer::_pipelines;
|
||||
|
||||
static const QUrl DEFAULT_POLYLINE_TEXTURE = PathUtils::resourcesUrl("images/paintStroke.png");
|
||||
|
||||
|
@ -44,29 +41,24 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity)
|
|||
}
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::buildPipeline() {
|
||||
// FIXME: opaque pipeline
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(DISABLE_DEFERRED ? shader::entities_renderer::program::paintStroke_forward : shader::entities_renderer::program::paintStroke);
|
||||
void PolyLineEntityRenderer::buildPipelines() {
|
||||
// FIXME: opaque pipelines
|
||||
|
||||
static const std::vector<std::pair<render::Args::RenderMethod, bool>> keys = {
|
||||
{ render::Args::DEFERRED, false }, { render::Args::DEFERRED, true }, { render::Args::FORWARD, false }, { render::Args::FORWARD, true },
|
||||
};
|
||||
|
||||
for (auto& key : keys) {
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(key.first == render::Args::DEFERRED ? shader::entities_renderer::program::paintStroke : shader::entities_renderer::program::paintStroke_forward);
|
||||
|
||||
{
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setCullMode(gpu::State::CullMode::CULL_NONE);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setDepthTest(true, !key.second, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMask(*state);
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
_pipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
{
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setCullMode(gpu::State::CullMode::CULL_NONE);
|
||||
state->setDepthTest(true, false, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMask(*state);
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
_glowPipeline = gpu::Pipeline::create(program, state);
|
||||
_pipelines[key] = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,11 +291,11 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!_pipeline) {
|
||||
buildPipeline();
|
||||
if (_pipelines.empty()) {
|
||||
buildPipelines();
|
||||
}
|
||||
|
||||
batch.setPipeline(_glow ? _glowPipeline : _pipeline);
|
||||
batch.setPipeline(_pipelines[{args->_renderMethod, _glow}]);
|
||||
batch.setModelTransform(transform);
|
||||
batch.setResourceTexture(0, texture);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, (gpu::uint32)(2 * numVertices), 0);
|
||||
|
|
|
@ -37,7 +37,7 @@ protected:
|
|||
virtual ShapeKey getShapeKey() override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
||||
void buildPipeline();
|
||||
static void buildPipelines();
|
||||
void updateGeometry();
|
||||
void updateData();
|
||||
|
||||
|
@ -58,8 +58,7 @@ protected:
|
|||
size_t _numVertices;
|
||||
gpu::BufferPointer _polylineDataBuffer;
|
||||
gpu::BufferPointer _polylineGeometryBuffer;
|
||||
static gpu::PipelinePointer _pipeline;
|
||||
static gpu::PipelinePointer _glowPipeline;
|
||||
static std::map<std::pair<render::Args::RenderMethod, bool>, gpu::PipelinePointer> _pipelines;
|
||||
};
|
||||
|
||||
} } // namespace
|
||||
|
|
|
@ -280,7 +280,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
||||
outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
render::ShapePipelinePointer pipeline;
|
||||
if (renderLayer == RenderLayer::WORLD) {
|
||||
if (renderLayer == RenderLayer::WORLD && args->_renderMethod != Args::RenderMethod::FORWARD) {
|
||||
pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
|
||||
} else {
|
||||
pipeline = outColor.a < 1.0f ? geometryCache->getForwardTransparentShapePipeline() : geometryCache->getForwardOpaqueShapePipeline();
|
||||
|
|
|
@ -163,7 +163,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
|||
Transform modelTransform;
|
||||
glm::vec3 dimensions;
|
||||
BillboardMode billboardMode;
|
||||
bool layered;
|
||||
bool forward;
|
||||
withReadLock([&] {
|
||||
modelTransform = _renderTransform;
|
||||
dimensions = _dimensions;
|
||||
|
@ -174,7 +174,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
|||
textColor = EntityRenderer::calculatePulseColor(textColor, _pulseProperties, _created);
|
||||
backgroundColor = glm::vec4(_backgroundColor, fadeRatio * _backgroundAlpha);
|
||||
backgroundColor = EntityRenderer::calculatePulseColor(backgroundColor, _pulseProperties, _created);
|
||||
layered = _renderLayer != RenderLayer::WORLD;
|
||||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD;
|
||||
});
|
||||
|
||||
// Render background
|
||||
|
@ -187,7 +187,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
|||
gpu::Batch& batch = *args->_batch;
|
||||
|
||||
// FIXME: we need to find a better way of rendering text so we don't have to do this
|
||||
if (layered) {
|
||||
if (forward) {
|
||||
DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch);
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
|||
if (backgroundColor.a > 0.0f) {
|
||||
batch.setModelTransform(transformToTopLeft);
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
geometryCache->bindSimpleProgram(batch, false, backgroundColor.a < 1.0f, false, false, false, true, layered);
|
||||
geometryCache->bindSimpleProgram(batch, false, backgroundColor.a < 1.0f, false, false, false, true, forward);
|
||||
geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID);
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
|||
batch.setModelTransform(transformToTopLeft);
|
||||
|
||||
glm::vec2 bounds = glm::vec2(dimensions.x - (_leftMargin + _rightMargin), dimensions.y - (_topMargin + _bottomMargin));
|
||||
_textRenderer->draw(batch, _leftMargin / scale, -_topMargin / scale, _text, textColor, bounds / scale, layered);
|
||||
_textRenderer->draw(batch, _leftMargin / scale, -_topMargin / scale, _text, textColor, bounds / scale, forward);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -288,6 +288,7 @@ void Procedural::prepare(gpu::Batch& batch,
|
|||
recompiledShader = true;
|
||||
}
|
||||
|
||||
// FIXME: need to handle forward rendering
|
||||
batch.setPipeline(recompiledShader ? _proceduralPipelines[key] : pipeline->second);
|
||||
|
||||
if (_shaderDirty || _uniformsDirty) {
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
|
||||
#include "DeferredLightingEffect.h"
|
||||
|
||||
#include <DisableDeferred.h>
|
||||
|
||||
namespace gr {
|
||||
using graphics::slot::texture::Texture;
|
||||
using graphics::slot::buffer::Buffer;
|
||||
|
@ -115,6 +113,8 @@ static const uint SHAPE_NORMALS_OFFSET = offsetof(GeometryCache::ShapeVertex, no
|
|||
static const uint SHAPE_TEXCOORD0_OFFSET = offsetof(GeometryCache::ShapeVertex, uv);
|
||||
static const uint SHAPE_TANGENT_OFFSET = offsetof(GeometryCache::ShapeVertex, tangent);
|
||||
|
||||
std::map<std::pair<bool, bool>, gpu::PipelinePointer> GeometryCache::_gridPipelines;
|
||||
|
||||
void GeometryCache::computeSimpleHullPointListForShape(const int entityShape, const glm::vec3 &entityExtents, QVector<glm::vec3> &outPointList) {
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
@ -714,11 +714,13 @@ QHash<SimpleProgramKey, gpu::PipelinePointer> GeometryCache::_simplePrograms;
|
|||
gpu::ShaderPointer GeometryCache::_simpleShader;
|
||||
gpu::ShaderPointer GeometryCache::_transparentShader;
|
||||
gpu::ShaderPointer GeometryCache::_unlitShader;
|
||||
gpu::ShaderPointer GeometryCache::_simpleFadeShader;
|
||||
gpu::ShaderPointer GeometryCache::_unlitFadeShader;
|
||||
gpu::ShaderPointer GeometryCache::_forwardSimpleShader;
|
||||
gpu::ShaderPointer GeometryCache::_forwardTransparentShader;
|
||||
gpu::ShaderPointer GeometryCache::_forwardUnlitShader;
|
||||
gpu::ShaderPointer GeometryCache::_simpleFadeShader;
|
||||
gpu::ShaderPointer GeometryCache::_unlitFadeShader;
|
||||
gpu::ShaderPointer GeometryCache::_forwardSimpleFadeShader;
|
||||
gpu::ShaderPointer GeometryCache::_forwardUnlitFadeShader;
|
||||
|
||||
render::ShapePipelinePointer GeometryCache::_simpleOpaquePipeline;
|
||||
render::ShapePipelinePointer GeometryCache::_simpleTransparentPipeline;
|
||||
|
@ -740,16 +742,13 @@ render::ShapePipelinePointer GeometryCache::shapePipelineFactory(const render::S
|
|||
if (key.isFaded()) {
|
||||
if (key.isTranslucent()) {
|
||||
return _simpleTransparentFadePipeline;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return _simpleOpaqueFadePipeline;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (key.isTranslucent()) {
|
||||
return _simpleTransparentPipeline;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return _simpleOpaquePipeline;
|
||||
}
|
||||
}
|
||||
|
@ -805,6 +804,8 @@ void GeometryCache::initializeShapePipelines() {
|
|||
_simpleTransparentPipeline = getShapePipeline(false, true, true, false);
|
||||
_forwardSimpleOpaquePipeline = getShapePipeline(false, false, true, false, false, true);
|
||||
_forwardSimpleTransparentPipeline = getShapePipeline(false, true, true, false, false, true);
|
||||
|
||||
// FIXME: these need forward pipelines
|
||||
_simpleOpaqueFadePipeline = getFadingShapePipeline(false, false, false, false, false);
|
||||
_simpleTransparentFadePipeline = getFadingShapePipeline(false, true, false, false, false);
|
||||
_simpleWirePipeline = getShapePipeline(false, false, true, true);
|
||||
|
@ -823,11 +824,11 @@ render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool
|
|||
}
|
||||
|
||||
render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured, bool transparent, bool culled,
|
||||
bool unlit, bool depthBias) {
|
||||
bool unlit, bool depthBias, bool forward) {
|
||||
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
auto fadeBatchSetter = fadeEffect->getBatchSetter();
|
||||
auto fadeItemSetter = fadeEffect->getItemUniformSetter();
|
||||
return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, true), nullptr,
|
||||
return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, true, true, forward), nullptr,
|
||||
[fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args* args) {
|
||||
batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
fadeBatchSetter(shapePipeline, batch, args);
|
||||
|
@ -937,7 +938,7 @@ void GeometryCache::renderWireSphere(gpu::Batch& batch, const glm::vec4& color)
|
|||
|
||||
void GeometryCache::renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
|
||||
int majorRows, int majorCols, float majorEdge, int minorRows, int minorCols, float minorEdge,
|
||||
const glm::vec4& color, int id) {
|
||||
const glm::vec4& color, bool forward, int id) {
|
||||
Vec2FloatPair majorKey(glm::vec2(majorRows, majorCols), majorEdge);
|
||||
Vec2FloatPair minorKey(glm::vec2(minorRows, minorCols), minorEdge);
|
||||
Vec2FloatPairPair key(majorKey, minorKey);
|
||||
|
@ -970,7 +971,7 @@ void GeometryCache::renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, co
|
|||
}
|
||||
|
||||
// Set the grid pipeline
|
||||
useGridPipeline(batch, gridBuffer, color.a < 1.0f);
|
||||
useGridPipeline(batch, gridBuffer, color.a < 1.0f, forward);
|
||||
|
||||
static const glm::vec2 MIN_TEX_COORD(0.0f, 0.0f);
|
||||
static const glm::vec2 MAX_TEX_COORD(1.0f, 1.0f);
|
||||
|
@ -2038,39 +2039,34 @@ void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) {
|
|||
}
|
||||
}
|
||||
|
||||
void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bool transparent) {
|
||||
if (!_gridPipelineOpaque || !_gridPipelineTransparent) {
|
||||
void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bool transparent, bool forward) {
|
||||
if (_gridPipelines.empty()) {
|
||||
using namespace shader::render_utils::program;
|
||||
const float DEPTH_BIAS = 0.001f;
|
||||
|
||||
// FIXME: need forward pipelines
|
||||
{
|
||||
auto program = gpu::Shader::createProgram(shader::render_utils::program::grid);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
state->setCullMode(gpu::State::CULL_NONE);
|
||||
state->setDepthBias(DEPTH_BIAS);
|
||||
_gridPipelineOpaque = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
static const std::vector<std::tuple<bool, bool, uint32_t>> keys = {
|
||||
std::make_tuple(false, false, grid), std::make_tuple(false, true, forward_grid), std::make_tuple(true, false, grid_translucent), std::make_tuple(true, true, forward_grid_translucent)
|
||||
};
|
||||
|
||||
{
|
||||
auto program = gpu::Shader::createProgram(shader::render_utils::program::grid_translucent);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
for (auto& key : keys) {
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(true,
|
||||
if (std::get<0>(key)) {
|
||||
PrepareStencil::testMask(*state);
|
||||
} else {
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
}
|
||||
state->setBlendFunction(std::get<0>(key),
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
PrepareStencil::testMask(*state);
|
||||
state->setCullMode(gpu::State::CULL_NONE);
|
||||
state->setDepthBias(DEPTH_BIAS);
|
||||
_gridPipelineTransparent = gpu::Pipeline::create(program, state);
|
||||
|
||||
_gridPipelines[{std::get<0>(key), std::get<1>(key)}] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state);
|
||||
}
|
||||
}
|
||||
|
||||
batch.setPipeline(transparent ? _gridPipelineTransparent : _gridPipelineOpaque);
|
||||
batch.setPipeline(_gridPipelines[{ transparent, forward }]);
|
||||
batch.setUniformBuffer(0, gridBuffer);
|
||||
}
|
||||
|
||||
|
@ -2162,6 +2158,7 @@ void GeometryCache::bindWebBrowserProgram(gpu::Batch& batch, bool transparent) {
|
|||
gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent) {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&]() {
|
||||
// FIXME: need a forward pipeline for this
|
||||
buildWebShader(shader::render_utils::program::simple_opaque_web_browser, false, _simpleOpaqueWebBrowserShader, _simpleOpaqueWebBrowserPipeline);
|
||||
buildWebShader(shader::render_utils::program::simple_transparent_web_browser, true, _simpleTransparentWebBrowserShader, _simpleTransparentWebBrowserPipeline);
|
||||
});
|
||||
|
@ -2197,22 +2194,21 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
|
|||
_forwardSimpleShader = gpu::Shader::createProgram(forward_simple_textured);
|
||||
_forwardTransparentShader = gpu::Shader::createProgram(forward_simple_textured_transparent);
|
||||
_forwardUnlitShader = gpu::Shader::createProgram(forward_simple_textured_unlit);
|
||||
if (DISABLE_DEFERRED) {
|
||||
_simpleShader = _forwardSimpleShader;
|
||||
_transparentShader = _forwardTransparentShader;
|
||||
_unlitShader = _forwardUnlitShader;
|
||||
} else {
|
||||
_simpleShader = gpu::Shader::createProgram(simple_textured);
|
||||
_transparentShader = gpu::Shader::createProgram(simple_transparent_textured);
|
||||
_unlitShader = gpu::Shader::createProgram(simple_textured_unlit);
|
||||
}
|
||||
|
||||
_simpleShader = gpu::Shader::createProgram(simple_textured);
|
||||
_transparentShader = gpu::Shader::createProgram(simple_transparent_textured);
|
||||
_unlitShader = gpu::Shader::createProgram(simple_textured_unlit);
|
||||
});
|
||||
} else {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&]() {
|
||||
using namespace shader::render_utils::program;
|
||||
_simpleFadeShader = gpu::Shader::createProgram(DISABLE_DEFERRED ? forward_simple_textured : simple_textured_fade);
|
||||
_unlitFadeShader = gpu::Shader::createProgram(DISABLE_DEFERRED ? forward_simple_textured_unlit : simple_textured_unlit_fade);
|
||||
// FIXME: these aren't right...
|
||||
_forwardSimpleFadeShader = gpu::Shader::createProgram(forward_simple_textured);
|
||||
_forwardUnlitFadeShader = gpu::Shader::createProgram(forward_simple_textured_unlit);
|
||||
|
||||
_simpleFadeShader = gpu::Shader::createProgram(simple_textured_fade);
|
||||
_unlitFadeShader = gpu::Shader::createProgram(simple_textured_unlit_fade);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2240,8 +2236,8 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
|
|||
|
||||
gpu::ShaderPointer program;
|
||||
if (config.isForward()) {
|
||||
program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _forwardUnlitShader) :
|
||||
(config.isFading() ? _simpleFadeShader : (config.isTransparent() ? _forwardTransparentShader : _forwardSimpleShader));
|
||||
program = (config.isUnlit()) ? (config.isFading() ? _forwardUnlitFadeShader : _forwardUnlitShader) :
|
||||
(config.isFading() ? _forwardSimpleFadeShader : (config.isTransparent() ? _forwardTransparentShader : _forwardSimpleShader));
|
||||
} else {
|
||||
program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) :
|
||||
(config.isFading() ? _simpleFadeShader : (config.isTransparent() ? _transparentShader : _simpleShader));
|
||||
|
|
|
@ -266,7 +266,7 @@ public:
|
|||
void renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
|
||||
int majorRows, int majorCols, float majorEdge,
|
||||
int minorRows, int minorCols, float minorEdge,
|
||||
const glm::vec4& color, int id);
|
||||
const glm::vec4& color, bool forward, int id);
|
||||
|
||||
void renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id);
|
||||
|
||||
|
@ -400,9 +400,8 @@ private:
|
|||
glm::vec4 edge;
|
||||
};
|
||||
using GridBuffer = gpu::BufferView;
|
||||
void useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bool isLayered);
|
||||
gpu::PipelinePointer _gridPipelineOpaque;
|
||||
gpu::PipelinePointer _gridPipelineTransparent;
|
||||
void useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bool transparent, bool forward);
|
||||
static std::map<std::pair<bool, bool>, gpu::PipelinePointer> _gridPipelines;
|
||||
|
||||
class BatchItemDetails {
|
||||
public:
|
||||
|
@ -460,11 +459,14 @@ private:
|
|||
static gpu::ShaderPointer _simpleShader;
|
||||
static gpu::ShaderPointer _transparentShader;
|
||||
static gpu::ShaderPointer _unlitShader;
|
||||
static gpu::ShaderPointer _simpleFadeShader;
|
||||
static gpu::ShaderPointer _unlitFadeShader;
|
||||
static gpu::ShaderPointer _forwardSimpleShader;
|
||||
static gpu::ShaderPointer _forwardTransparentShader;
|
||||
static gpu::ShaderPointer _forwardUnlitShader;
|
||||
static gpu::ShaderPointer _simpleFadeShader;
|
||||
static gpu::ShaderPointer _unlitFadeShader;
|
||||
static gpu::ShaderPointer _forwardSimpleFadeShader;
|
||||
static gpu::ShaderPointer _forwardUnlitFadeShader;
|
||||
|
||||
static render::ShapePipelinePointer _simpleOpaquePipeline;
|
||||
static render::ShapePipelinePointer _simpleTransparentPipeline;
|
||||
static render::ShapePipelinePointer _forwardSimpleOpaquePipeline;
|
||||
|
@ -483,7 +485,7 @@ private:
|
|||
static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true,
|
||||
bool unlit = false, bool depthBias = false, bool forward = false);
|
||||
static render::ShapePipelinePointer getFadingShapePipeline(bool textured = false, bool transparent = false, bool culled = true,
|
||||
bool unlit = false, bool depthBias = false);
|
||||
bool unlit = false, bool depthBias = false, bool forward = false);
|
||||
};
|
||||
|
||||
#endif // hifi_GeometryCache_h
|
||||
|
|
|
@ -1033,7 +1033,7 @@ void Model::removeFromScene(const render::ScenePointer& scene, render::Transacti
|
|||
_renderInfoHasTransparent = false;
|
||||
}
|
||||
|
||||
void Model::renderDebugMeshBoxes(gpu::Batch& batch) {
|
||||
void Model::renderDebugMeshBoxes(gpu::Batch& batch, bool forward) {
|
||||
int colorNdx = 0;
|
||||
_mutex.lock();
|
||||
|
||||
|
@ -1042,7 +1042,7 @@ void Model::renderDebugMeshBoxes(gpu::Batch& batch) {
|
|||
Transform meshToWorld(meshToWorldMatrix);
|
||||
batch.setModelTransform(meshToWorld);
|
||||
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, true, true);
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, true, true, forward);
|
||||
|
||||
for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
|
||||
for (auto &partTriangleSet : meshTriangleSets) {
|
||||
|
|
|
@ -347,7 +347,7 @@ public:
|
|||
const QMap<render::ItemID, render::PayloadPointer>& getRenderItems() const { return _modelMeshRenderItemsMap; }
|
||||
BlendShapeOperator getModelBlendshapeOperator() const { return _modelBlendshapeOperator; }
|
||||
|
||||
void renderDebugMeshBoxes(gpu::Batch& batch);
|
||||
void renderDebugMeshBoxes(gpu::Batch& batch, bool forward);
|
||||
|
||||
int getResourceDownloadAttempts() { return _renderWatcher.getResourceDownloadAttempts(); }
|
||||
int getResourceDownloadAttemptsRemaining() { return _renderWatcher.getResourceDownloadAttemptsRemaining(); }
|
||||
|
|
|
@ -137,4 +137,16 @@ public:
|
|||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output);
|
||||
};
|
||||
|
||||
class SetRenderMethod {
|
||||
public:
|
||||
using JobModel = render::Job::Model<SetRenderMethod>;
|
||||
|
||||
SetRenderMethod(render::Args::RenderMethod method) : _method(method) {}
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext) { renderContext->args->_renderMethod = _method; }
|
||||
|
||||
protected:
|
||||
render::Args::RenderMethod _method;
|
||||
};
|
||||
|
||||
#endif // hifi_RenderDeferredTask_h
|
||||
|
|
|
@ -48,6 +48,8 @@ using namespace render;
|
|||
extern void initForwardPipelines(ShapePlumber& plumber);
|
||||
|
||||
void RenderForwardTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
|
||||
task.addJob<SetRenderMethod>("SetRenderMethodTask", render::Args::FORWARD);
|
||||
|
||||
// Prepare the ShapePipelines
|
||||
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
|
||||
|
|
|
@ -10,14 +10,37 @@
|
|||
//
|
||||
#include "RenderViewTask.h"
|
||||
|
||||
#include "AssembleLightingStageTask.h"
|
||||
#include "RenderShadowTask.h"
|
||||
#include "RenderCommonTask.h"
|
||||
#include "RenderDeferredTask.h"
|
||||
#include "RenderForwardTask.h"
|
||||
|
||||
void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred, uint8_t tagBits, uint8_t tagMask) {
|
||||
#include <RenderForward.h>
|
||||
|
||||
void RenderShadowsAndDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask) {
|
||||
task.addJob<SetRenderMethod>("SetRenderMethodTask", render::Args::DEFERRED);
|
||||
|
||||
const auto items = input.getN<DeferredForwardSwitchJob::Input>(0);
|
||||
const auto lightingModel = input.getN<DeferredForwardSwitchJob::Input>(1);
|
||||
const auto lightingStageFramesAndZones = input.getN<DeferredForwardSwitchJob::Input>(2);
|
||||
|
||||
// Warning : the cull functor passed to the shadow pass should only be testing for LOD culling. If frustum culling
|
||||
// is performed, then casters not in the view frustum will be removed, which is not what we wish.
|
||||
const auto shadowTaskIn = RenderShadowTask::Input(lightingStageFramesAndZones.get<AssembleLightingStageTask::Output>().get0()[0], lightingModel).asVarying();
|
||||
const auto shadowTaskOut = task.addJob<RenderShadowTask>("RenderShadowTask", shadowTaskIn, cullFunctor, tagBits, tagMask);
|
||||
|
||||
const auto renderDeferredInput = RenderDeferredTask::Input(items, lightingModel, lightingStageFramesAndZones, shadowTaskOut).asVarying();
|
||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", renderDeferredInput);
|
||||
}
|
||||
|
||||
void DeferredForwardSwitchJob::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask) {
|
||||
task.addBranch<RenderShadowsAndDeferredTask>("RenderShadowsAndDeferredTask", RENDER_FORWARD ? 1 : 0, input, cullFunctor, tagBits, tagMask);
|
||||
|
||||
task.addBranch<RenderForwardTask>("RenderForwardTask", RENDER_FORWARD ? 0 : 1, input);
|
||||
}
|
||||
|
||||
void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask) {
|
||||
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor, tagBits, tagMask);
|
||||
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
||||
|
||||
// Issue the lighting model, aka the big global settings for the view
|
||||
const auto lightingModel = task.addJob<MakeLightingModel>("LightingModel");
|
||||
|
@ -25,17 +48,11 @@ void RenderViewTask::build(JobModel& task, const render::Varying& input, render:
|
|||
// Assemble the lighting stages current frames
|
||||
const auto lightingStageFramesAndZones = task.addJob<AssembleLightingStageTask>("AssembleStages", items);
|
||||
|
||||
if (isDeferred) {
|
||||
// Warning : the cull functor passed to the shadow pass should only be testing for LOD culling. If frustum culling
|
||||
// is performed, then casters not in the view frustum will be removed, which is not what we wish.
|
||||
const auto shadowTaskIn = RenderShadowTask::Input(lightingStageFramesAndZones.get<AssembleLightingStageTask::Output>().get0()[0], lightingModel).asVarying();
|
||||
const auto shadowTaskOut = task.addJob<RenderShadowTask>("RenderShadowTask", shadowTaskIn, cullFunctor, tagBits, tagMask);
|
||||
|
||||
const auto renderInput = RenderDeferredTask::Input(items, lightingModel, lightingStageFramesAndZones, shadowTaskOut).asVarying();
|
||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", renderInput);
|
||||
} else {
|
||||
#ifndef Q_OS_ANDROID
|
||||
const auto deferredForwardIn = DeferredForwardSwitchJob::Input(items, lightingModel, lightingStageFramesAndZones).asVarying();
|
||||
task.addJob<DeferredForwardSwitchJob>("DeferredForwardSwitch", deferredForwardIn, cullFunctor, tagBits, tagMask);
|
||||
#else
|
||||
const auto renderInput = RenderForwardTask::Input(items, lightingModel, lightingStageFramesAndZones).asVarying();
|
||||
task.addJob<RenderForwardTask>("Forward", renderInput);
|
||||
}
|
||||
task.addJob<RenderForwardTask>("RenderForwardTask", renderInput);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,30 @@
|
|||
#include <render/Engine.h>
|
||||
#include <render/RenderFetchCullSortTask.h>
|
||||
|
||||
#include "AssembleLightingStageTask.h"
|
||||
|
||||
class RenderShadowsAndDeferredTask {
|
||||
public:
|
||||
using Input = render::VaryingSet3<RenderFetchCullSortTask::Output, LightingModelPointer, AssembleLightingStageTask::Output>;
|
||||
using JobModel = render::Task::ModelI<RenderShadowsAndDeferredTask, Input>;
|
||||
|
||||
RenderShadowsAndDeferredTask() {}
|
||||
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask);
|
||||
|
||||
};
|
||||
|
||||
class DeferredForwardSwitchJob {
|
||||
public:
|
||||
using Input = render::VaryingSet3<RenderFetchCullSortTask::Output, LightingModelPointer, AssembleLightingStageTask::Output>;
|
||||
using JobModel = render::Switch::ModelI<DeferredForwardSwitchJob, Input>;
|
||||
|
||||
DeferredForwardSwitchJob() {}
|
||||
|
||||
void configure(const render::SwitchConfig& config) {}
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask);
|
||||
|
||||
};
|
||||
|
||||
class RenderViewTask {
|
||||
public:
|
||||
|
@ -23,7 +47,7 @@ public:
|
|||
|
||||
RenderViewTask() {}
|
||||
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00);
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -67,11 +67,11 @@ float TextRenderer3D::getFontSize() const {
|
|||
}
|
||||
|
||||
void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color,
|
||||
const glm::vec2& bounds, bool layered) {
|
||||
const glm::vec2& bounds, bool forward) {
|
||||
// The font does all the OpenGL work
|
||||
if (_font) {
|
||||
_color = color;
|
||||
_font->drawString(batch, _drawInfo, str, _color, _effectType, { x, y }, bounds, layered);
|
||||
_font->drawString(batch, _drawInfo, str, _color, _effectType, { x, y }, bounds, forward);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ public:
|
|||
glm::vec2 computeExtent(const QString& str) const;
|
||||
float getFontSize() const; // Pixel size
|
||||
|
||||
void draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color = glm::vec4(1.0f),
|
||||
const glm::vec2& bounds = glm::vec2(-1.0f), bool layered = false);
|
||||
void draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color,
|
||||
const glm::vec2& bounds, bool forward);
|
||||
|
||||
private:
|
||||
TextRenderer3D(const char* family, float pointSize, int weight = -1, bool italic = false,
|
||||
|
|
40
libraries/render-utils/src/forward_grid.slf
Normal file
40
libraries/render-utils/src/forward_grid.slf
Normal file
|
@ -0,0 +1,40 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// Created by Sam Gondelman on 5/9/19
|
||||
// Copyright 2019 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/ShaderConstants.h@>
|
||||
<@include gpu/Paint.slh@>
|
||||
|
||||
struct Grid {
|
||||
vec4 period;
|
||||
vec4 offset;
|
||||
vec4 edge;
|
||||
};
|
||||
|
||||
LAYOUT(binding=0) uniform gridBuffer {
|
||||
Grid grid;
|
||||
};
|
||||
|
||||
layout(location=GPU_ATTR_TEXCOORD0) in vec2 varTexCoord0;
|
||||
layout(location=GPU_ATTR_COLOR) in vec4 varColor;
|
||||
|
||||
layout(location=0) out vec4 _fragColor0;
|
||||
|
||||
void main(void) {
|
||||
float alpha = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge),
|
||||
paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy),
|
||||
float(grid.edge.z == 0.0));
|
||||
|
||||
if (alpha < 0.0001) {
|
||||
discard;
|
||||
}
|
||||
|
||||
_fragColor0 = vec4(varColor.xyz, 1.0);
|
||||
}
|
41
libraries/render-utils/src/forward_grid_translucent.slf
Normal file
41
libraries/render-utils/src/forward_grid_translucent.slf
Normal file
|
@ -0,0 +1,41 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// Created by Sam Gondelman on 5/9/19
|
||||
// Copyright 2019 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/ShaderConstants.h@>
|
||||
<@include gpu/Paint.slh@>
|
||||
|
||||
struct Grid {
|
||||
vec4 period;
|
||||
vec4 offset;
|
||||
vec4 edge;
|
||||
};
|
||||
|
||||
LAYOUT(binding=0) uniform gridBuffer {
|
||||
Grid grid;
|
||||
};
|
||||
|
||||
layout(location=GPU_ATTR_TEXCOORD0) in vec2 varTexCoord0;
|
||||
layout(location=GPU_ATTR_COLOR) in vec4 varColor;
|
||||
|
||||
layout(location=0) out vec4 _fragColor0;
|
||||
|
||||
void main(void) {
|
||||
float alpha = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge),
|
||||
paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy),
|
||||
float(grid.edge.z == 0.0));
|
||||
alpha *= varColor.w;
|
||||
|
||||
if (alpha < 0.0001) {
|
||||
discard;
|
||||
}
|
||||
|
||||
_fragColor0 = vec4(varColor.xyz, alpha);
|
||||
}
|
18
libraries/render-utils/src/forward_parabola.slf
Normal file
18
libraries/render-utils/src/forward_parabola.slf
Normal file
|
@ -0,0 +1,18 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// Created by Sam Gondelman on 5/9/19
|
||||
// Copyright 2019 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
|
||||
//
|
||||
|
||||
layout(location=0) in vec4 _color;
|
||||
|
||||
layout(location=0) out vec4 _fragColor0;
|
||||
|
||||
void main(void) {
|
||||
_fragColor0 = _color;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
layout(location=0) in vec4 _color;
|
||||
|
||||
layout(location=0) out vec4 _fragColor0;
|
||||
|
||||
void main(void) {
|
||||
_fragColor0 = _color;
|
||||
}
|
1
libraries/render-utils/src/render-utils/forward_grid.slp
Normal file
1
libraries/render-utils/src/render-utils/forward_grid.slp
Normal file
|
@ -0,0 +1 @@
|
|||
VERTEX standardTransformPNTC
|
|
@ -0,0 +1 @@
|
|||
VERTEX standardTransformPNTC
|
|
@ -0,0 +1 @@
|
|||
VERTEX parabola
|
|
@ -13,10 +13,13 @@
|
|||
#include "FontFamilies.h"
|
||||
#include "../StencilMaskPass.h"
|
||||
|
||||
#include "DisableDeferred.h"
|
||||
|
||||
static std::mutex fontMutex;
|
||||
|
||||
gpu::PipelinePointer Font::_deferredPipeline;
|
||||
gpu::PipelinePointer Font::_forwardPipeline;
|
||||
gpu::PipelinePointer Font::_transparentPipeline;
|
||||
gpu::Stream::FormatPointer Font::_format;
|
||||
|
||||
struct TextureVertex {
|
||||
glm::vec2 pos;
|
||||
glm::vec2 tex;
|
||||
|
@ -218,13 +221,10 @@ void Font::read(QIODevice& in) {
|
|||
}
|
||||
|
||||
void Font::setupGPU() {
|
||||
if (!_initialized) {
|
||||
_initialized = true;
|
||||
|
||||
if (!_deferredPipeline) {
|
||||
// Setup render pipeline
|
||||
{
|
||||
{
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::forward_sdf_text3D);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
|
@ -232,25 +232,11 @@ void Font::setupGPU() {
|
|||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
_layeredPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
if (DISABLE_DEFERRED) {
|
||||
_pipeline = _layeredPipeline;
|
||||
} else {
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
_pipeline = gpu::Pipeline::create(program, state);
|
||||
_deferredPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D), state);
|
||||
_forwardPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::forward_sdf_text3D), state);
|
||||
}
|
||||
|
||||
{
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D_transparent);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
|
@ -258,7 +244,7 @@ void Font::setupGPU() {
|
|||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
PrepareStencil::testMask(*state);
|
||||
_transparentPipeline = gpu::Pipeline::create(program, state);
|
||||
_transparentPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D_transparent), state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,7 +349,7 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm
|
|||
}
|
||||
|
||||
void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString& str, const glm::vec4& color,
|
||||
EffectType effectType, const glm::vec2& origin, const glm::vec2& bounds, bool layered) {
|
||||
EffectType effectType, const glm::vec2& origin, const glm::vec2& bounds, bool forward) {
|
||||
if (str == "") {
|
||||
return;
|
||||
}
|
||||
|
@ -390,7 +376,7 @@ void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString
|
|||
}
|
||||
// need the gamma corrected color here
|
||||
|
||||
batch.setPipeline(color.a < 1.0f ? _transparentPipeline : (layered ? _layeredPipeline : _pipeline));
|
||||
batch.setPipeline(color.a < 1.0f ? _transparentPipeline : (forward ? _forwardPipeline : _deferredPipeline));
|
||||
batch.setInputFormat(_format);
|
||||
batch.setInputBuffer(0, drawInfo.verticesBuffer, 0, _format->getChannels().at(0)._stride);
|
||||
batch.setResourceTexture(render_utils::slot::texture::TextFont, _texture);
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
// Render string to batch
|
||||
void drawString(gpu::Batch& batch, DrawInfo& drawInfo, const QString& str,
|
||||
const glm::vec4& color, EffectType effectType,
|
||||
const glm::vec2& origin, const glm::vec2& bound, bool layered);
|
||||
const glm::vec2& origin, const glm::vec2& bound, bool forward);
|
||||
|
||||
static Pointer load(const QString& family);
|
||||
|
||||
|
@ -77,15 +77,13 @@ private:
|
|||
float _descent = 0.0f;
|
||||
float _spaceWidth = 0.0f;
|
||||
|
||||
bool _initialized = false;
|
||||
|
||||
// gpu structures
|
||||
gpu::PipelinePointer _pipeline;
|
||||
gpu::PipelinePointer _layeredPipeline;
|
||||
gpu::PipelinePointer _transparentPipeline;
|
||||
gpu::TexturePointer _texture;
|
||||
gpu::Stream::FormatPointer _format;
|
||||
gpu::BufferStreamPointer _stream;
|
||||
|
||||
static gpu::PipelinePointer _deferredPipeline;
|
||||
static gpu::PipelinePointer _forwardPipeline;
|
||||
static gpu::PipelinePointer _transparentPipeline;
|
||||
static gpu::Stream::FormatPointer _format;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -64,6 +64,7 @@ namespace render {
|
|||
public:
|
||||
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, MIRROR_RENDER_MODE, SECONDARY_CAMERA_RENDER_MODE };
|
||||
enum DisplayMode { MONO, STEREO_MONITOR, STEREO_HMD };
|
||||
enum RenderMethod { DEFERRED, FORWARD };
|
||||
enum DebugFlags {
|
||||
RENDER_DEBUG_NONE = 0,
|
||||
RENDER_DEBUG_HULLS = 1
|
||||
|
@ -77,6 +78,7 @@ namespace render {
|
|||
float lodAngleHalfTan = 0.1f,
|
||||
RenderMode renderMode = DEFAULT_RENDER_MODE,
|
||||
DisplayMode displayMode = MONO,
|
||||
RenderMethod renderMethod = DEFERRED,
|
||||
DebugFlags debugFlags = RENDER_DEBUG_NONE,
|
||||
gpu::Batch* batch = nullptr) :
|
||||
_context(context),
|
||||
|
@ -86,6 +88,7 @@ namespace render {
|
|||
_lodAngleHalfTanSq(lodAngleHalfTan * lodAngleHalfTan),
|
||||
_renderMode(renderMode),
|
||||
_displayMode(displayMode),
|
||||
_renderMethod(renderMethod),
|
||||
_debugFlags(debugFlags),
|
||||
_batch(batch) {
|
||||
}
|
||||
|
@ -117,6 +120,7 @@ namespace render {
|
|||
|
||||
RenderMode _renderMode { DEFAULT_RENDER_MODE };
|
||||
DisplayMode _displayMode { MONO };
|
||||
RenderMethod _renderMethod { DEFERRED };
|
||||
DebugFlags _debugFlags { RENDER_DEBUG_NONE };
|
||||
gpu::Batch* _batch = nullptr;
|
||||
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
//
|
||||
// Created by Sam Gondelman on 3/7/19.
|
||||
// Copyright 2019 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_DisableDeferred_h
|
||||
#define hifi_DisableDeferred_h
|
||||
|
||||
#include <QString>
|
||||
#include <QProcess>
|
||||
|
||||
#if defined(USE_GLES)
|
||||
static bool DISABLE_DEFERRED = true;
|
||||
#else
|
||||
static const QString RENDER_FORWARD{ "HIFI_RENDER_FORWARD" };
|
||||
static bool DISABLE_DEFERRED = QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD);
|
||||
#endif
|
||||
|
||||
|
||||
#endif // hifi_DisableDeferred_h
|
||||
|
24
libraries/shared/src/RenderForward.h
Normal file
24
libraries/shared/src/RenderForward.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// Created by Sam Gondelman on 3/7/19.
|
||||
// Copyright 2019 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_RenderForward_h
|
||||
#define hifi_RenderForward_h
|
||||
|
||||
#include <QString>
|
||||
#include <QProcess>
|
||||
|
||||
#if defined(USE_GLES)
|
||||
// This isn't necessary since android forces the forward renderer, but just in case
|
||||
static bool RENDER_FORWARD = true;
|
||||
#else
|
||||
static const QString RENDER_FORWARD_STRING { "HIFI_RENDER_FORWARD" };
|
||||
static bool RENDER_FORWARD = QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD_STRING);
|
||||
#endif
|
||||
|
||||
|
||||
#endif // hifi_RenderForward_h
|
|
@ -38,7 +38,7 @@ void JobConfig::setPresetList(const QJsonObject& object) {
|
|||
}
|
||||
}
|
||||
|
||||
void TaskConfig::connectChildConfig(QConfigPointer childConfig, const std::string& name) {
|
||||
void JobConfig::connectChildConfig(std::shared_ptr<JobConfig> childConfig, const std::string& name) {
|
||||
childConfig->setParent(this);
|
||||
childConfig->setObjectName(name.c_str());
|
||||
|
||||
|
@ -52,7 +52,7 @@ void TaskConfig::connectChildConfig(QConfigPointer childConfig, const std::strin
|
|||
}
|
||||
}
|
||||
|
||||
void TaskConfig::transferChildrenConfigs(QConfigPointer source) {
|
||||
void JobConfig::transferChildrenConfigs(std::shared_ptr<JobConfig> source) {
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
|
@ -70,13 +70,13 @@ void TaskConfig::transferChildrenConfigs(QConfigPointer source) {
|
|||
}
|
||||
}
|
||||
|
||||
void TaskConfig::refresh() {
|
||||
void JobConfig::refresh() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
BLOCKING_INVOKE_METHOD(this, "refresh");
|
||||
return;
|
||||
}
|
||||
|
||||
_task->applyConfiguration();
|
||||
_jobConcept->applyConfiguration();
|
||||
}
|
||||
|
||||
TaskConfig* TaskConfig::getRootConfig(const std::string& jobPath, std::string& jobName) const {
|
||||
|
@ -133,3 +133,11 @@ JobConfig* TaskConfig::getJobConfig(const std::string& jobPath) const {
|
|||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
void SwitchConfig::setBranch(uint8_t branch) {
|
||||
if (_branch != branch) {
|
||||
_branch = branch;
|
||||
// We can re-use this signal here
|
||||
emit dirtyEnabled();
|
||||
}
|
||||
}
|
|
@ -154,6 +154,11 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE virtual QObject* getSubConfig(int i) const { return nullptr; }
|
||||
|
||||
void connectChildConfig(std::shared_ptr<JobConfig> childConfig, const std::string& name);
|
||||
void transferChildrenConfigs(std::shared_ptr<JobConfig> source);
|
||||
|
||||
JobConcept* _jobConcept;
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
|
@ -162,6 +167,11 @@ public slots:
|
|||
*/
|
||||
void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); emit loaded(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Render.refresh
|
||||
*/
|
||||
void refresh();
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
|
@ -248,18 +258,18 @@ public:
|
|||
auto subs = getSubConfigs();
|
||||
return ((i < 0 || i >= subs.size()) ? nullptr : subs[i]);
|
||||
}
|
||||
};
|
||||
|
||||
void connectChildConfig(QConfigPointer childConfig, const std::string& name);
|
||||
void transferChildrenConfigs(QConfigPointer source);
|
||||
class SwitchConfig : public JobConfig {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool branch READ getBranch WRITE setBranch NOTIFY dirtyEnabled)
|
||||
|
||||
JobConcept* _task;
|
||||
public:
|
||||
uint8_t getBranch() const { return _branch; }
|
||||
void setBranch(uint8_t index);
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function Render.refresh
|
||||
*/
|
||||
void refresh();
|
||||
protected:
|
||||
uint8_t _branch { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "Config.h"
|
||||
#include "Varying.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace task {
|
||||
|
||||
class JobConcept;
|
||||
|
@ -175,6 +177,7 @@ public:
|
|||
template <class T, class O, class C = Config> using ModelO = Model<T, C, None, O>;
|
||||
template <class T, class I, class O, class C = Config> using ModelIO = Model<T, C, I, O>;
|
||||
|
||||
Job() {}
|
||||
Job(const ConceptPointer& concept) : _concept(concept) {}
|
||||
virtual ~Job() = default;
|
||||
|
||||
|
@ -244,25 +247,6 @@ public:
|
|||
const Varying getOutput() const override { return _output; }
|
||||
Varying& editInput() override { return _input; }
|
||||
|
||||
typename Jobs::iterator editJob(std::string name) {
|
||||
typename Jobs::iterator jobIt;
|
||||
for (jobIt = _jobs.begin(); jobIt != _jobs.end(); ++jobIt) {
|
||||
if (jobIt->getName() == name) {
|
||||
return jobIt;
|
||||
}
|
||||
}
|
||||
return jobIt;
|
||||
}
|
||||
typename Jobs::const_iterator getJob(std::string name) const {
|
||||
typename Jobs::const_iterator jobIt;
|
||||
for (jobIt = _jobs.begin(); jobIt != _jobs.end(); ++jobIt) {
|
||||
if (jobIt->getName() == name) {
|
||||
return jobIt;
|
||||
}
|
||||
}
|
||||
return jobIt;
|
||||
}
|
||||
|
||||
TaskConcept(const std::string& name, const Varying& input, QConfigPointer config) : Concept(name, config), _input(input) {}
|
||||
|
||||
// Create a new job in the container's queue; returns the job's output
|
||||
|
@ -321,7 +305,7 @@ public:
|
|||
// swap
|
||||
Concept::_config = config;
|
||||
// Capture this
|
||||
std::static_pointer_cast<C>(Concept::_config)->_task = this;
|
||||
Concept::_config->_jobConcept = this;
|
||||
}
|
||||
|
||||
QConfigPointer& getConfiguration() override {
|
||||
|
@ -369,8 +353,146 @@ public:
|
|||
std::shared_ptr<Config> getConfiguration() {
|
||||
return std::static_pointer_cast<Config>(JobType::_concept->getConfiguration());
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
// A Switch is a specialized job to run a collection of other jobs and switch between different branches at run time
|
||||
// It can be created on any type T by aliasing the type JobModel in the class T
|
||||
// using JobModel = Switch::Model<T>
|
||||
// The class T is expected to have a "build" method acting as a constructor.
|
||||
// The build method is where child Jobs can be added internally to the branches of the switch
|
||||
// where the input of the switch can be setup to feed the child jobs
|
||||
// and where the output of the switch is defined
|
||||
template <class JC, class TP>
|
||||
class Switch : public Job<JC, TP> {
|
||||
public:
|
||||
using Context = JC;
|
||||
using TimeProfiler = TP;
|
||||
using ContextPointer = std::shared_ptr<Context>;
|
||||
using Config = SwitchConfig;
|
||||
using JobType = Job<JC, TP>;
|
||||
using None = typename JobType::None;
|
||||
using Concept = typename JobType::Concept;
|
||||
using ConceptPointer = typename JobType::ConceptPointer;
|
||||
using Branches = std::unordered_map<uint8_t, JobType>;
|
||||
|
||||
Switch(ConceptPointer concept) : JobType(concept) {}
|
||||
|
||||
class SwitchConcept : public Concept {
|
||||
public:
|
||||
Varying _input;
|
||||
Varying _output;
|
||||
Branches _branches;
|
||||
|
||||
const Varying getInput() const override { return _input; }
|
||||
const Varying getOutput() const override { return _output; }
|
||||
Varying& editInput() override { return _input; }
|
||||
|
||||
SwitchConcept(const std::string& name, const Varying& input, QConfigPointer config) : Concept(name, config), _input(input) {}
|
||||
|
||||
template <class NT, class... NA> const Varying addBranch(std::string name, uint8_t index, const Varying& input, NA&&... args) {
|
||||
auto& branch = _branches[index];
|
||||
branch = JobType(NT::JobModel::create(name, input, std::forward<NA>(args)...));
|
||||
|
||||
// Conect the child config to this task's config
|
||||
std::static_pointer_cast<SwitchConfig>(Concept::getConfiguration())->connectChildConfig(branch.getConfiguration(), name);
|
||||
|
||||
return branch.getOutput();
|
||||
}
|
||||
template <class NT, class... NA> const Varying addBranch(std::string name, uint8_t index, NA&&... args) {
|
||||
const auto input = Varying(typename NT::JobModel::Input());
|
||||
return addBranch<NT>(name, index, input, std::forward<NA>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class C = SwitchConfig, class I = None, class O = None> class SwitchModel : public SwitchConcept {
|
||||
public:
|
||||
using Data = T;
|
||||
using Input = I;
|
||||
using Output = O;
|
||||
|
||||
Data _data;
|
||||
|
||||
SwitchModel(const std::string& name, const Varying& input, QConfigPointer config) :
|
||||
SwitchConcept(name, input, config),
|
||||
_data(Data()) {
|
||||
}
|
||||
|
||||
template <class... A>
|
||||
static std::shared_ptr<SwitchModel> create(const std::string& name, const Varying& input, A&&... args) {
|
||||
auto model = std::make_shared<SwitchModel>(name, input, std::make_shared<C>());
|
||||
|
||||
{
|
||||
TimeProfiler probe("build::" + model->getName());
|
||||
model->_data.build(*(model), model->_input, model->_output, std::forward<A>(args)...);
|
||||
}
|
||||
// Recreate the Config to use the templated type
|
||||
model->createConfiguration();
|
||||
model->applyConfiguration();
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
template <class... A>
|
||||
static std::shared_ptr<SwitchModel> create(const std::string& name, A&&... args) {
|
||||
const auto input = Varying(Input());
|
||||
return create(name, input, std::forward<A>(args)...);
|
||||
}
|
||||
|
||||
void createConfiguration() {
|
||||
// A brand new config
|
||||
auto config = std::make_shared<C>();
|
||||
// Make sure we transfer the former children configs to the new config
|
||||
config->transferChildrenConfigs(Concept::_config);
|
||||
// swap
|
||||
Concept::_config = config;
|
||||
// Capture this
|
||||
Concept::_config->_jobConcept = this;
|
||||
}
|
||||
|
||||
QConfigPointer& getConfiguration() override {
|
||||
if (!Concept::_config) {
|
||||
createConfiguration();
|
||||
}
|
||||
return Concept::_config;
|
||||
}
|
||||
|
||||
void applyConfiguration() override {
|
||||
TimeProfiler probe("configure::" + JobConcept::getName());
|
||||
jobConfigure(_data, *std::static_pointer_cast<C>(Concept::_config));
|
||||
for (auto& branch : SwitchConcept::_branches) {
|
||||
branch.second.applyConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
void run(const ContextPointer& jobContext) override {
|
||||
auto config = std::static_pointer_cast<C>(Concept::_config);
|
||||
if (config->isEnabled()) {
|
||||
auto jobsIt = SwitchConcept::_branches.find(config->getBranch());
|
||||
if (jobsIt != SwitchConcept::_branches.end()) {
|
||||
jobsIt->second.run(jobContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
template <class T, class C = SwitchConfig> using Model = SwitchModel<T, C, None, None>;
|
||||
template <class T, class I, class C = SwitchConfig> using ModelI = SwitchModel<T, C, I, None>;
|
||||
// TODO: Switches don't support Outputs yet
|
||||
//template <class T, class O, class C = SwitchConfig> using ModelO = SwitchModel<T, C, None, O>;
|
||||
//template <class T, class I, class O, class C = SwitchConfig> using ModelIO = SwitchModel<T, C, I, O>;
|
||||
|
||||
// Create a new job in the Switches' branches; returns the job's output
|
||||
template <class T, class... A> const Varying addBranch(std::string name, uint8_t index, const Varying& input, A&&... args) {
|
||||
return std::static_pointer_cast<SwitchConcept>(JobType::_concept)->template addBranch<T>(name, index, input, std::forward<A>(args)...);
|
||||
}
|
||||
template <class T, class... A> const Varying addBranch(std::string name, uint8_t index, A&&... args) {
|
||||
const auto input = Varying(typename T::JobModel::Input());
|
||||
return std::static_pointer_cast<SwitchConcept>(JobType::_concept)->template addBranch<T>(name, index, input, std::forward<A>(args)...);
|
||||
}
|
||||
|
||||
std::shared_ptr<Config> getConfiguration() {
|
||||
return std::static_pointer_cast<Config>(JobType::_concept->getConfiguration());
|
||||
}
|
||||
};
|
||||
|
||||
template <class JC, class TP>
|
||||
|
@ -407,8 +529,10 @@ protected:
|
|||
#define Task_DeclareTypeAliases(ContextType, TimeProfiler) \
|
||||
using JobConfig = task::JobConfig; \
|
||||
using TaskConfig = task::TaskConfig; \
|
||||
using SwitchConfig = task::SwitchConfig; \
|
||||
template <class T> using PersistentConfig = task::PersistentConfig<T>; \
|
||||
using Job = task::Job<ContextType, TimeProfiler>; \
|
||||
using Switch = task::Switch<ContextType, TimeProfiler>; \
|
||||
using Task = task::Task<ContextType, TimeProfiler>; \
|
||||
using Engine = task::Engine<ContextType, TimeProfiler>; \
|
||||
using Varying = task::Varying; \
|
||||
|
|
Loading…
Reference in a new issue