From 3daa40087ea36d44c28cb165f62f0e2fec3bf169 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Fri, 1 Mar 2024 13:04:11 -0800 Subject: [PATCH 1/3] support opaque (and black) particles --- .../RenderableParticleEffectEntityItem.cpp | 63 +++++++++++-------- .../src/RenderableParticleEffectEntityItem.h | 2 +- .../entities-renderer/textured_particle.slp | 1 + .../src/textured_particle.slf | 11 +++- 4 files changed, 49 insertions(+), 28 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index e2a57840d9..ff9ba9fb03 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -21,23 +21,35 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER = 0; static gpu::Stream::FormatPointer _vertexFormat; -static std::weak_ptr _texturedPipeline; +static std::map, gpu::PipelinePointer> _pipelines; static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) { - auto texturedPipeline = _texturedPipeline.lock(); - if (!texturedPipeline) { - auto state = std::make_shared(); - state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - PrepareStencil::testMask(*state); + // FIXME: custom pipelines like this don't handle shadows or renderLayers correctly - auto program = gpu::Shader::createProgram(shader::entities_renderer::program::textured_particle); - _texturedPipeline = texturedPipeline = gpu::Pipeline::create(program, state); + if (_pipelines.empty()) { + for (size_t i = 0; i < 4; i++) { + bool transparent = (i % 2 == 0); + bool wireframe = (i / 2) == 0; + + auto state = std::make_shared(); + state->setCullMode(gpu::State::CULL_BACK); + + if (wireframe) { + state->setFillMode(gpu::State::FILL_LINE); + } + + state->setDepthTest(true, !transparent, gpu::LESS_EQUAL); + state->setBlendFunction(transparent, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + transparent ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state); + + auto program = gpu::Shader::createProgram(transparent ? shader::entities_renderer::program::textured_particle_translucent : + shader::entities_renderer::program::textured_particle); + _pipelines[std::make_tuple(transparent, wireframe)] = gpu::Pipeline::create(program, state); + } } - return std::make_shared(texturedPipeline, nullptr, nullptr, nullptr); + return std::make_shared(_pipelines[std::make_tuple(key.isTranslucent(), key.isWireframe())], nullptr, nullptr, nullptr); } struct GpuParticle { @@ -138,26 +150,25 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn _uniformBuffer.edit() = particleUniforms; } -ItemKey ParticleEffectEntityRenderer::getKey() { - // FIXME: implement isTransparent() for particles and an opaque pipeline - auto builder = ItemKey::Builder::transparentShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); - - if (!_visible) { - builder.withInvisible(); - } - - if (_cullWithParent) { - builder.withSubMetaCulled(); - } - - return builder.build(); +bool ParticleEffectEntityRenderer::isTransparent() const { + bool particleTransparent = _particleProperties.getColorStart().a < 1.0f || _particleProperties.getColorMiddle().a < 1.0f || + _particleProperties.getColorFinish().a < 1.0f || _particleProperties.getColorSpread().a > 0.0f || + _pulseProperties.getAlphaMode() != PulseMode::NONE || (_textureLoaded && _networkTexture && _networkTexture->getGPUTexture() && + _networkTexture->getGPUTexture()->getUsage().isAlpha() && !_networkTexture->getGPUTexture()->getUsage().isAlphaMask()); + return particleTransparent || Parent::isTransparent(); } ShapeKey ParticleEffectEntityRenderer::getShapeKey() { - auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER).withTranslucent(); + auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER); + + if (isTransparent()) { + builder.withTranslucent(); + } + if (_primitiveMode == PrimitiveMode::LINES) { builder.withWireframe(); } + return builder.build(); } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 547d654486..08d8822d2d 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -28,7 +28,7 @@ protected: virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; - virtual ItemKey getKey() override; + bool isTransparent() const override; virtual ShapeKey getShapeKey() override; virtual Item::Bound getBound(RenderArgs* args) override; virtual void doRender(RenderArgs* args) override; diff --git a/libraries/entities-renderer/src/entities-renderer/textured_particle.slp b/libraries/entities-renderer/src/entities-renderer/textured_particle.slp index e69de29bb2..1348d72a8d 100644 --- a/libraries/entities-renderer/src/entities-renderer/textured_particle.slp +++ b/libraries/entities-renderer/src/entities-renderer/textured_particle.slp @@ -0,0 +1 @@ +DEFINES translucent:f \ No newline at end of file diff --git a/libraries/entities-renderer/src/textured_particle.slf b/libraries/entities-renderer/src/textured_particle.slf index 7dadb6fc49..7c26e036e4 100644 --- a/libraries/entities-renderer/src/textured_particle.slf +++ b/libraries/entities-renderer/src/textured_particle.slf @@ -18,5 +18,14 @@ layout(location=1) in vec2 varTexcoord; layout(location=0) out vec4 outFragColor; void main(void) { - outFragColor = texture(colorMap, varTexcoord.xy) * varColor; + vec4 albedo = texture(colorMap, varTexcoord.xy) * varColor; + + <@if not HIFI_USE_TRANSLUCENT@> + // to reduce texel flickering for floating point error we discard when alpha is "almost one" + if (albedo.a < 0.999999) { + discard; + } + <@endif@> + + outFragColor = albedo; } From 903984f427a282034a40b1fb0e4c8f09cc70dbba Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 3 Mar 2024 13:00:15 -0800 Subject: [PATCH 2/3] try to fix amd deferred bug --- .../RenderableParticleEffectEntityItem.cpp | 47 ++++++++++++------- .../entities-renderer/textured_particle.slp | 2 +- .../src/textured_particle.slf | 20 +++++--- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index ff9ba9fb03..f4d729585c 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -21,35 +21,46 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER = 0; static gpu::Stream::FormatPointer _vertexFormat; -static std::map, gpu::PipelinePointer> _pipelines; +static std::map, gpu::PipelinePointer> _pipelines; static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) { // FIXME: custom pipelines like this don't handle shadows or renderLayers correctly if (_pipelines.empty()) { - for (size_t i = 0; i < 4; i++) { - bool transparent = (i % 2 == 0); - bool wireframe = (i / 2) == 0; + using namespace shader::entities_renderer::program; - auto state = std::make_shared(); - state->setCullMode(gpu::State::CULL_BACK); + // forward, translucent + static const std::vector> keys = { + std::make_tuple(false, false, textured_particle), + std::make_tuple(true, false, textured_particle_forward), + std::make_tuple(false, true, textured_particle_translucent), + std::make_tuple(true, true, textured_particle_forward) + }; - if (wireframe) { - state->setFillMode(gpu::State::FILL_LINE); + for (auto& key : keys) { + for (int i = 0; i < 2; ++i) { + bool transparent = std::get<1>(key); + bool wireframe = i == 0; + + auto state = std::make_shared(); + state->setCullMode(gpu::State::CULL_BACK); + + if (wireframe) { + state->setFillMode(gpu::State::FILL_LINE); + } + + state->setDepthTest(true, !transparent, gpu::LESS_EQUAL); + state->setBlendFunction(transparent, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + transparent ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state); + + auto program = gpu::Shader::createProgram(std::get<2>(key)); + _pipelines[std::make_tuple(std::get<0>(key), transparent, wireframe)] = gpu::Pipeline::create(program, state); } - - state->setDepthTest(true, !transparent, gpu::LESS_EQUAL); - state->setBlendFunction(transparent, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - transparent ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state); - - auto program = gpu::Shader::createProgram(transparent ? shader::entities_renderer::program::textured_particle_translucent : - shader::entities_renderer::program::textured_particle); - _pipelines[std::make_tuple(transparent, wireframe)] = gpu::Pipeline::create(program, state); } } - return std::make_shared(_pipelines[std::make_tuple(key.isTranslucent(), key.isWireframe())], nullptr, nullptr, nullptr); + return std::make_shared(_pipelines[std::make_tuple(args->_renderMethod == Args::RenderMethod::FORWARD, key.isTranslucent(), key.isWireframe())], nullptr, nullptr, nullptr); } struct GpuParticle { diff --git a/libraries/entities-renderer/src/entities-renderer/textured_particle.slp b/libraries/entities-renderer/src/entities-renderer/textured_particle.slp index 1348d72a8d..e9942be5cd 100644 --- a/libraries/entities-renderer/src/entities-renderer/textured_particle.slp +++ b/libraries/entities-renderer/src/entities-renderer/textured_particle.slp @@ -1 +1 @@ -DEFINES translucent:f \ No newline at end of file +DEFINES translucent:f/forward:f \ No newline at end of file diff --git a/libraries/entities-renderer/src/textured_particle.slf b/libraries/entities-renderer/src/textured_particle.slf index 7c26e036e4..65d3b112dc 100644 --- a/libraries/entities-renderer/src/textured_particle.slf +++ b/libraries/entities-renderer/src/textured_particle.slf @@ -15,17 +15,23 @@ LAYOUT(binding=0) uniform sampler2D colorMap; layout(location=0) in vec4 varColor; layout(location=1) in vec2 varTexcoord; -layout(location=0) out vec4 outFragColor; +<@if not HIFI_USE_FORWARD@> + <@include DeferredBufferWrite.slh@> +<@else@> + layout(location=0) out vec4 _fragColor0; +<@endif@> void main(void) { vec4 albedo = texture(colorMap, varTexcoord.xy) * varColor; +<@if not HIFI_USE_FORWARD@> + vec3 NORMAL = vec3(1.0, 0.0, 0.0); <@if not HIFI_USE_TRANSLUCENT@> - // to reduce texel flickering for floating point error we discard when alpha is "almost one" - if (albedo.a < 0.999999) { - discard; - } + packDeferredFragmentUnlit(NORMAL, albedo.a, albedo.rgb); + <@else@> + packDeferredFragmentTranslucent(NORMAL, albedo.a, albedo.rgb, DEFAULT_ROUGHNESS); <@endif@> - - outFragColor = albedo; +<@else@> + _fragColor0 = albedo; +<@endif@> } From 7b4c26be845b2084739d3e67c3dcce42390bd36b Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Tue, 5 Mar 2024 14:34:26 -0800 Subject: [PATCH 3/3] fix custom shape key shadows + render layers --- .../RenderableParticleEffectEntityItem.cpp | 26 +++++----- .../src/RenderablePolyVoxEntityItem.cpp | 49 ++++++++----------- .../src/RenderablePolyVoxEntityItem.h | 1 - .../entities-renderer/textured_particle.slp | 2 +- .../src/textured_particle.slf | 23 ++++++--- .../render-utils/src/RenderCommonTask.cpp | 11 +++++ .../render-utils/src/RenderPipelines.cpp | 26 +++++++--- libraries/render/src/render/ShapePipeline.cpp | 4 +- libraries/render/src/render/ShapePipeline.h | 3 +- 9 files changed, 85 insertions(+), 60 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index f4d729585c..8c885094ae 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -21,20 +21,21 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER = 0; static gpu::Stream::FormatPointer _vertexFormat; -static std::map, gpu::PipelinePointer> _pipelines; +// forward, transparent, shadow, wireframe +static std::map, gpu::PipelinePointer> _pipelines; static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) { - // FIXME: custom pipelines like this don't handle shadows or renderLayers correctly - if (_pipelines.empty()) { using namespace shader::entities_renderer::program; - // forward, translucent - static const std::vector> keys = { - std::make_tuple(false, false, textured_particle), - std::make_tuple(true, false, textured_particle_forward), - std::make_tuple(false, true, textured_particle_translucent), - std::make_tuple(true, true, textured_particle_forward) + // forward, translucent, shadow + static const std::vector> keys = { + std::make_tuple(false, false, false, textured_particle), + std::make_tuple(true, false, false, textured_particle_forward), + std::make_tuple(false, true, false, textured_particle_translucent), + std::make_tuple(true, true, false, textured_particle_translucent_forward), + std::make_tuple(false, false, true, textured_particle_shadow), + // no such thing as shadow and forward/translucent }; for (auto& key : keys) { @@ -54,13 +55,14 @@ static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, co gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); transparent ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state); - auto program = gpu::Shader::createProgram(std::get<2>(key)); - _pipelines[std::make_tuple(std::get<0>(key), transparent, wireframe)] = gpu::Pipeline::create(program, state); + auto program = gpu::Shader::createProgram(std::get<3>(key)); + _pipelines[std::make_tuple(std::get<0>(key), transparent, std::get<2>(key), wireframe)] = gpu::Pipeline::create(program, state); } } } - return std::make_shared(_pipelines[std::make_tuple(args->_renderMethod == Args::RenderMethod::FORWARD, key.isTranslucent(), key.isWireframe())], nullptr, nullptr, nullptr); + return std::make_shared(_pipelines[std::make_tuple(args->_renderMethod == Args::RenderMethod::FORWARD, key.isTranslucent(), + args->_renderMode == Args::RenderMode::SHADOW_RENDER_MODE, key.isWireframe())], nullptr, nullptr, nullptr); } struct GpuParticle { diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 8331e016fd..483d1c57ef 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -1719,21 +1719,28 @@ using namespace render; using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER; -static std::map, ShapePipelinePointer> _pipelines; +// forward, shadow, fade, wireframe +static std::map, ShapePipelinePointer> _pipelines; static gpu::Stream::FormatPointer _vertexFormat; ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) { - // FIXME: custom pipelines like this don't handle shadows or renderLayers correctly - if (_pipelines.empty()) { using namespace shader::entities_renderer::program; - static const std::vector> keys = { - std::make_tuple(false, false, polyvox), std::make_tuple(true, false, polyvox_forward) + // forward, shadow, fade + static const std::vector> keys = { + std::make_tuple(false, false, false, polyvox), + std::make_tuple(true, false, false, polyvox_forward), + std::make_tuple(false, true, false, polyvox_shadow), + // no such thing as forward + shadow #ifdef POLYVOX_ENTITY_USE_FADE_EFFECT - , std::make_tuple(false, true, polyvox_fade), std::make_tuple(true, true, polyvox_forward_fade) + std::make_tuple(false, false, true, polyvox_fade), + std::make_tuple(false, true, true, polyvox_shadow_fade), + // no such thing as forward + fade/shadow #else - , std::make_tuple(false, true, polyvox), std::make_tuple(true, true, polyvox_forward) + std::make_tuple(false, false, true, polyvox), + std::make_tuple(false, true, true, polyvox_shadow), + // no such thing as forward + fade/shadow #endif }; for (auto& key : keys) { @@ -1749,19 +1756,19 @@ ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const Sha state->setFillMode(gpu::State::FILL_LINE); } - auto pipeline = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state); - if (std::get<1>(key)) { - _pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), wireframe)] = std::make_shared(pipeline, nullptr, nullptr, nullptr); + auto pipeline = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<3>(key)), state); + if (!std::get<2>(key)) { + _pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), std::get<2>(key), wireframe)] = std::make_shared(pipeline, nullptr, nullptr, nullptr); } else { const auto& fadeEffect = DependencyManager::get(); - _pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), wireframe)] = std::make_shared(pipeline, nullptr, + _pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), std::get<2>(key), wireframe)] = std::make_shared(pipeline, nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); } } } } - return _pipelines[std::make_tuple(args->_renderMethod == Args::RenderMethod::FORWARD, key.isFaded(), key.isWireframe())]; + return _pipelines[std::make_tuple(args->_renderMethod == Args::RenderMethod::FORWARD, args->_renderMode == Args::RenderMode::SHADOW_RENDER_MODE, key.isFaded(), key.isWireframe())]; } PolyVoxEntityRenderer::PolyVoxEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { @@ -1775,16 +1782,6 @@ PolyVoxEntityRenderer::PolyVoxEntityRenderer(const EntityItemPointer& entity) : _params = std::make_shared(sizeof(glm::vec4), nullptr); } -ItemKey PolyVoxEntityRenderer::getKey() { - auto builder = ItemKey::Builder::opaqueShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); - - if (_cullWithParent) { - builder.withSubMetaCulled(); - } - - return builder.build(); -} - ShapeKey PolyVoxEntityRenderer::getShapeKey() { auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER); if (_primitiveMode == PrimitiveMode::LINES) { @@ -1866,13 +1863,7 @@ void PolyVoxEntityRenderer::doRender(RenderArgs* args) { batch.setModelTransform(transform); batch.setInputFormat(_vertexFormat); - batch.setInputBuffer(gpu::Stream::POSITION, _mesh->getVertexBuffer()._buffer, 0, - sizeof(PolyVox::PositionMaterialNormal)); - - // TODO -- should we be setting this? - // batch.setInputBuffer(gpu::Stream::NORMAL, mesh->getVertexBuffer()._buffer, - // 12, - // sizeof(PolyVox::PositionMaterialNormal)); + batch.setInputBuffer(gpu::Stream::POSITION, _mesh->getVertexBuffer()._buffer, 0, sizeof(PolyVox::PositionMaterialNormal)); batch.setIndexBuffer(gpu::UINT32, _mesh->getIndexBuffer()._buffer, 0); for (size_t i = 0; i < _xyzTextures.size(); ++i) { diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index c1c35a21c8..1debeb957c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -203,7 +203,6 @@ public: } protected: - virtual ItemKey getKey() override; virtual ShapeKey getShapeKey() override; virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; diff --git a/libraries/entities-renderer/src/entities-renderer/textured_particle.slp b/libraries/entities-renderer/src/entities-renderer/textured_particle.slp index e9942be5cd..80b57dee25 100644 --- a/libraries/entities-renderer/src/entities-renderer/textured_particle.slp +++ b/libraries/entities-renderer/src/entities-renderer/textured_particle.slp @@ -1 +1 @@ -DEFINES translucent:f/forward:f \ No newline at end of file +DEFINES (translucent:f forward:f)/shadow:f \ No newline at end of file diff --git a/libraries/entities-renderer/src/textured_particle.slf b/libraries/entities-renderer/src/textured_particle.slf index 65d3b112dc..04b74771a0 100644 --- a/libraries/entities-renderer/src/textured_particle.slf +++ b/libraries/entities-renderer/src/textured_particle.slf @@ -15,23 +15,34 @@ LAYOUT(binding=0) uniform sampler2D colorMap; layout(location=0) in vec4 varColor; layout(location=1) in vec2 varTexcoord; -<@if not HIFI_USE_FORWARD@> - <@include DeferredBufferWrite.slh@> -<@else@> +<@if HIFI_USE_FORWARD or HIFI_USE_SHADOW@> layout(location=0) out vec4 _fragColor0; +<@else@> + <@include DeferredBufferWrite.slh@> <@endif@> void main(void) { vec4 albedo = texture(colorMap, varTexcoord.xy) * varColor; -<@if not HIFI_USE_FORWARD@> +<@if HIFI_USE_FORWARD or HIFI_USE_SHADOW@> + <@if not HIFI_USE_TRANSLUCENT@> + // to reduce texel flickering for floating point error we discard when alpha is "almost one" + if (albedo.a < 0.999999) { + discard; + } + <@endif@> + +<@if HIFI_USE_FORWARD@> + _fragColor0 = albedo; +<@else@> + _fragColor0 = vec4(1.0); +<@endif@> +<@else@> vec3 NORMAL = vec3(1.0, 0.0, 0.0); <@if not HIFI_USE_TRANSLUCENT@> packDeferredFragmentUnlit(NORMAL, albedo.a, albedo.rgb); <@else@> packDeferredFragmentTranslucent(NORMAL, albedo.a, albedo.rgb, DEFAULT_ROUGHNESS); <@endif@> -<@else@> - _fragColor0 = albedo; <@endif@> } diff --git a/libraries/render-utils/src/RenderCommonTask.cpp b/libraries/render-utils/src/RenderCommonTask.cpp index 7cf7f1129f..3853d06d31 100644 --- a/libraries/render-utils/src/RenderCommonTask.cpp +++ b/libraries/render-utils/src/RenderCommonTask.cpp @@ -85,6 +85,8 @@ void DrawLayered3D::run(const RenderContextPointer& renderContext, const Inputs& } if (!inItems.empty()) { + auto deferredLightingEffect = DependencyManager::get(); + // Render the items gpu::doInBatch("DrawLayered3D::main", args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -108,11 +110,20 @@ void DrawLayered3D::run(const RenderContextPointer& renderContext, const Inputs& batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, haze->getHazeParametersBuffer()); } + // Set the light + deferredLightingEffect->setupKeyLightBatch(args, batch); + + auto renderMethod = args->_renderMethod; + args->_renderMethod = Args::RenderMethod::FORWARD; if (_opaquePass) { renderStateSortShapes(renderContext, _shapePlumber, inItems, _maxDrawn); } else { renderShapes(renderContext, _shapePlumber, inItems, _maxDrawn); } + + deferredLightingEffect->unsetLocalLightsBatch(batch); + + args->_renderMethod = renderMethod; args->_batch = nullptr; }); } diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 94e235a1c5..879b48ce11 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -403,6 +403,7 @@ void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state, const re void sortAndRenderZPassShapes(const ShapePlumberPointer& shapePlumber, const render::RenderContextPointer& renderContext, const render::ShapeBounds& inShapes, render::ItemBounds &itemBounds) { std::unordered_map, ShapeKey::Hash, ShapeKey::KeyEqual> sortedShapeKeys; + std::unordered_map, ShapeKey::Hash, ShapeKey::KeyEqual>> sortedCustomShapeKeys; std::unordered_map, ShapeKey::Hash, ShapeKey::KeyEqual> sortedOwnPipelineShapeKeys; for (const auto& items : inShapes) { @@ -444,14 +445,25 @@ void sortAndRenderZPassShapes(const ShapePlumberPointer& shapePlumber, const ren if (items.first.hasOwnPipeline()) { sortedOwnPipelineShapeKeys[variantKey.build()].push_back(items.first); + } else if (items.first.isCustom()) { + const uint8_t custom = items.first.getCustom(); + variantKey.withCustom(custom); + sortedCustomShapeKeys[custom][variantKey.build()].push_back(items.first); } else { sortedShapeKeys[variantKey.build()].push_back(items.first); } } - // Render non-withOwnPipeline things - for (auto& variantAndKeys : sortedShapeKeys) { - if (variantAndKeys.second.size() > 0) { + // Render non-withCustom, non-withOwnPipeline things + for (const auto& variantAndKeys : sortedShapeKeys) { + for (const auto& key : variantAndKeys.second) { + renderShapes(renderContext, shapePlumber, inShapes.at(key)); + } + } + + // Render withCustom things + for (const auto& customAndSortedCustomKeys : sortedCustomShapeKeys) { + for (const auto& variantAndKeys : customAndSortedCustomKeys.second) { for (const auto& key : variantAndKeys.second) { renderShapes(renderContext, shapePlumber, inShapes.at(key)); } @@ -459,11 +471,9 @@ void sortAndRenderZPassShapes(const ShapePlumberPointer& shapePlumber, const ren } // Render withOwnPipeline things - for (auto& variantAndKeys : sortedOwnPipelineShapeKeys) { - if (variantAndKeys.second.size() > 0) { - for (const auto& key : variantAndKeys.second) { - renderShapes(renderContext, shapePlumber, inShapes.at(key)); - } + for (const auto& variantAndKeys : sortedOwnPipelineShapeKeys) { + for (const auto& key : variantAndKeys.second) { + renderShapes(renderContext, shapePlumber, inShapes.at(key)); } } diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 048e08e959..4d1682de9a 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -60,8 +60,8 @@ ShapeKey::Filter::Builder::Builder() { } void ShapePlumber::addPipelineHelper(const Filter& filter, ShapeKey key, int bit, const PipelinePointer& pipeline) const { - // Iterate over all keys - if (bit < (int)ShapeKey::FlagBit::NUM_FLAGS) { + // Iterate over all non-custom keys + if (bit < (int)ShapeKey::FlagBit::NUM_NON_CUSTOM - 1) { addPipelineHelper(filter, key, bit + 1, pipeline); if (!filter._mask[bit]) { // Toggle bits set as insignificant in filter._mask diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 525572fc44..fd8b729ffa 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -54,6 +54,7 @@ public: CUSTOM_7, NUM_FLAGS, // Not a valid flag + NUM_NON_CUSTOM = INVALID, CUSTOM_MASK = (0xFF << CUSTOM_0), @@ -112,7 +113,7 @@ public: Builder& withOwnPipeline() { _flags.set(OWN_PIPELINE); return (*this); } Builder& invalidate() { _flags.set(INVALID); return (*this); } - Builder& withCustom(uint8_t custom) { _flags &= (~CUSTOM_MASK); _flags |= (custom << CUSTOM_0); return (*this); } + Builder& withCustom(uint8_t custom) { _flags &= (~CUSTOM_MASK); _flags |= (custom << CUSTOM_0); return (*this); } static const ShapeKey ownPipeline() { return Builder().withOwnPipeline(); } static const ShapeKey invalid() { return Builder().invalidate(); }