From cba70e6be0e8728410edb3d40c4479401838f864 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 8 Jun 2017 14:57:09 +0200 Subject: [PATCH] Fade working on voxel objects --- .../src/RenderablePolyVoxEntityItem.cpp | 40 +++++++++---- .../src/RenderablePolyVoxEntityItem.h | 7 ++- .../entities-renderer/src/polyvox_fade.slf | 60 +++++++++++++++++++ .../entities-renderer/src/polyvox_fade.slv | 35 +++++++++++ libraries/render-utils/src/FadeEffect.cpp | 20 ++++--- libraries/render-utils/src/FadeEffect.h | 13 ++-- .../render-utils/src/MeshPartPayload.cpp | 10 ++-- libraries/render-utils/src/MeshPartPayload.h | 8 ++- libraries/render/src/render/ShapePipeline.cpp | 2 - libraries/render/src/render/ShapePipeline.h | 2 - 10 files changed, 155 insertions(+), 42 deletions(-) create mode 100644 libraries/entities-renderer/src/polyvox_fade.slf create mode 100644 libraries/entities-renderer/src/polyvox_fade.slv diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index fd5346093b..e5eecfd66c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -48,13 +48,17 @@ #include "model/Geometry.h" #include "EntityTreeRenderer.h" #include "polyvox_vert.h" +#include "polyvox_fade_vert.h" #include "polyvox_frag.h" +#include "polyvox_fade_frag.h" #include "RenderablePolyVoxEntityItem.h" #include "EntityEditPacketSender.h" #include "PhysicalEntitySimulation.h" -gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipeline = nullptr; -gpu::PipelinePointer RenderablePolyVoxEntityItem::_wireframePipeline = nullptr; +#include "FadeEffect.h" + +gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipelines[2] = { nullptr, nullptr }; +gpu::PipelinePointer RenderablePolyVoxEntityItem::_wireframePipelines[2] = { nullptr, nullptr }; const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5; @@ -727,31 +731,34 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { return; } - if (!_pipeline) { - gpu::ShaderPointer vertexShader = gpu::Shader::createVertex(std::string(polyvox_vert)); - gpu::ShaderPointer pixelShader = gpu::Shader::createPixel(std::string(polyvox_frag)); + if (!_pipelines[0]) { + gpu::ShaderPointer vertexShaders[2] = { gpu::Shader::createVertex(std::string(polyvox_vert)), gpu::Shader::createVertex(std::string(polyvox_fade_vert)) }; + gpu::ShaderPointer pixelShaders[2] = { gpu::Shader::createPixel(std::string(polyvox_frag)), gpu::Shader::createPixel(std::string(polyvox_fade_frag)) }; gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("xMap"), 0)); slotBindings.insert(gpu::Shader::Binding(std::string("yMap"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("zMap"), 2)); - - gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader); - gpu::Shader::makeProgram(*program, slotBindings); + slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), 3)); auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); state->setDepthTest(true, true, gpu::LESS_EQUAL); - _pipeline = gpu::Pipeline::create(program, state); - auto wireframeState = std::make_shared(); wireframeState->setCullMode(gpu::State::CULL_BACK); wireframeState->setDepthTest(true, true, gpu::LESS_EQUAL); wireframeState->setFillMode(gpu::State::FILL_LINE); - _wireframePipeline = gpu::Pipeline::create(program, wireframeState); + // Two sets of pipelines: normal and fading + for (auto i = 0; i < 2; i++) { + gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShaders[i], pixelShaders[i]); + gpu::Shader::makeProgram(*program, slotBindings); + + _pipelines[i] = gpu::Pipeline::create(program, state); + _wireframePipelines[i] = gpu::Pipeline::create(program, wireframeState); + } } if (!_vertexFormat) { @@ -765,7 +772,8 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { // Pick correct Pipeline bool wireframe = (render::ShapeKey(args->_globalShapeKey).isWireframe()); - auto pipeline = (wireframe ? _wireframePipeline : _pipeline); + auto pipelineVariation = isFading() & 1; + auto pipeline = (wireframe ? _wireframePipelines[pipelineVariation]: _pipelines[pipelineVariation]); batch.setPipeline(pipeline); Transform transform(voxelToWorldMatrix()); @@ -809,6 +817,12 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { batch.setResourceTexture(2, DependencyManager::get()->getWhiteTexture()); } + // Apply fade effect + auto fadeEffect = DependencyManager::get(); + if (fadeEffect->bindPerItem(batch, pipeline.get(), glm::vec3(0, 0, 0), _fadeStartTime, isFading())) { + fadeEffect->bindPerBatch(batch, 3); + } + int voxelVolumeSizeLocation = pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize"); batch._glUniform3f(voxelVolumeSizeLocation, voxelVolumeSize.x, voxelVolumeSize.y, voxelVolumeSize.z); @@ -1611,7 +1625,7 @@ void RenderablePolyVoxEntityItem::bonkNeighbors() { void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) { EntityItem::locationChanged(tellPhysics); - if (!_pipeline || !render::Item::isValidID(_myItem)) { + if (!_pipelines[0] || !render::Item::isValidID(_myItem)) { return; } render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index ff97f09ee1..d6216f3eff 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -143,7 +143,7 @@ public: void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; _meshReady = false; }); } - // Transparent polyvox didn't seem to be working so disable for now + // Transparent polyvox didn't seem to be working so disable for now. bool isTransparent() override { return false; } bool getMeshes(MeshProxyList& result) override; @@ -166,8 +166,9 @@ private: const int MATERIAL_GPU_SLOT = 3; render::ItemID _myItem{ render::Item::INVALID_ITEM_ID }; - static gpu::PipelinePointer _pipeline; - static gpu::PipelinePointer _wireframePipeline; + + static gpu::PipelinePointer _pipelines[2]; + static gpu::PipelinePointer _wireframePipelines[2]; ShapeInfo _shapeInfo; diff --git a/libraries/entities-renderer/src/polyvox_fade.slf b/libraries/entities-renderer/src/polyvox_fade.slf new file mode 100644 index 0000000000..ac2d77564b --- /dev/null +++ b/libraries/entities-renderer/src/polyvox_fade.slf @@ -0,0 +1,60 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// polyvox_fade.frag +// fragment shader +// +// Created by Olivier Prat on 2017-06-08 +// Copyright 2017 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 model/Material.slh@> +<@include DeferredBufferWrite.slh@> + +<@include Fade.slh@> + +in vec3 _normal; +in vec4 _position; +in vec4 _worldPosition; +in vec4 _worldFadePosition; + +uniform sampler2D xMap; +uniform sampler2D yMap; +uniform sampler2D zMap; +uniform vec3 voxelVolumeSize; + +// Declare after all samplers to prevent sampler location mix up with voxel shading (sampler locations are hardcoded in RenderablePolyVoxEntityItem) +<$declareFadeFragment()$> + +void main(void) { + applyFade(_worldFadePosition.xyz); + + vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); + worldNormal = normalize(worldNormal); + + float inPositionX = (_worldPosition.x - 0.5) / voxelVolumeSize.x; + float inPositionY = (_worldPosition.y - 0.5) / voxelVolumeSize.y; + float inPositionZ = (_worldPosition.z - 0.5) / voxelVolumeSize.z; + + vec4 xyDiffuse = texture(xMap, vec2(-inPositionX, -inPositionY)); + vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ)); + vec4 yzDiffuse = texture(zMap, vec2(inPositionZ, -inPositionY)); + + vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(worldNormal.z); + vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(worldNormal.y); + vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x); + vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0); + + packDeferredFragment( + _normal, + 1.0, + vec3(diffuse), + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); +} diff --git a/libraries/entities-renderer/src/polyvox_fade.slv b/libraries/entities-renderer/src/polyvox_fade.slv new file mode 100644 index 0000000000..f024957677 --- /dev/null +++ b/libraries/entities-renderer/src/polyvox_fade.slv @@ -0,0 +1,35 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// polyvox_fade.vert +// vertex shader +// +// Created by Seth Alves on 2015-8-3 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include gpu/Inputs.slh@> + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +<@include Fade.slh@> + +out vec4 _position; +out vec4 _worldPosition; +out vec3 _normal; +out vec4 _worldFadePosition; + +void main(void) { + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToWorldPos(obj, inPosition, _worldFadePosition)$> + _worldPosition = inPosition; +} diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index ceec55c448..f2a799dbc6 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -22,9 +22,13 @@ render::ShapeKey::Builder FadeEffect::getKeyBuilder(render::ShapeKey::Builder bu return builder; } -void FadeEffect::bindPerBatch(gpu::Batch& batch) const -{ - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::FADE_MASK, _fadeMaskMap); +void FadeEffect::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation) const { + batch.setResourceTexture(fadeMaskMapLocation, _fadeMaskMap); +} + +void FadeEffect::bindPerBatch(gpu::Batch& batch, const gpu::PipelinePointer& pipeline) const { + auto slot = pipeline->getProgram()->getTextures().findLocation("fadeMaskMap"); + batch.setResourceTexture(slot, _fadeMaskMap); } float FadeEffect::computeFadePercent(quint64 startTime) const { @@ -37,12 +41,12 @@ float FadeEffect::computeFadePercent(quint64 startTime) const { return fadeAlpha; } -void FadeEffect::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, State state) const { - bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime, state); +bool FadeEffect::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, bool isFading) const { + return bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime, isFading); } -void FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, State state) const { - if (state != Complete || _isDebugEnabled) { +bool FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, bool isFading) const { + if (isFading || _isDebugEnabled) { auto& program = pipeline->getProgram(); auto fadeOffsetLoc = program->getUniforms().findLocation("fadeOffset"); auto fadePercentLoc = program->getUniforms().findLocation("fadePercent"); @@ -60,5 +64,7 @@ void FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, g batch._glUniform1f(fadePercentLoc, percent); batch._glUniform3f(fadeOffsetLoc, offset.x, offset.y, offset.z); } + return true; } + return false; } diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index dea14e5678..5be1288120 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -20,12 +20,6 @@ class FadeEffect : public Dependency { SINGLETON_DEPENDENCY public: - enum State : uint8_t { - WaitingToStart = 0, - InProgress = 1, - Complete = 2, - }; - FadeEffect(); const gpu::TexturePointer getFadeMaskMap() const { return _fadeMaskMap; } @@ -38,9 +32,10 @@ public: render::ShapeKey::Builder getKeyBuilder(render::ShapeKey::Builder builder = render::ShapeKey::Builder()) const; - void bindPerBatch(gpu::Batch& batch) const; - void bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, State state = InProgress) const; - void bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, State state = InProgress) const; + void bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation = render::ShapePipeline::Slot::MAP::FADE_MASK) const; + void bindPerBatch(gpu::Batch& batch, const gpu::PipelinePointer& pipeline) const; + bool bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, bool isFading) const; + bool bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, bool isFading) const; float computeFadePercent(quint64 startTime) const; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index a44974cc92..46989eaba7 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -484,7 +484,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { if (wireframe) { builder.withWireframe(); } - if (_fadeState != FadeEffect::Complete) { + if (_fadeState != STATE_COMPLETE) { builder.withFade(); } return builder.build(); @@ -528,13 +528,13 @@ void ModelMeshPartPayload::render(RenderArgs* args) { return; // bail asap } - if (_fadeState == FadeEffect::WaitingToStart) { + if (_fadeState == STATE_WAITING_TO_START) { if (model->isLoaded()) { if (EntityItem::getEntitiesShouldFadeFunction()()) { _fadeStartTime = usecTimestampNow(); - _fadeState = FadeEffect::InProgress; + _fadeState = STATE_IN_PROGRESS; } else { - _fadeState = FadeEffect::Complete; + _fadeState = STATE_COMPLETE; } model->setRenderItemsNeedUpdate(); } else { @@ -567,7 +567,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { bindMaterial(batch, locations, args->_enableTexturing); // Apply fade effect - DependencyManager::get()->bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime, _fadeState); + DependencyManager::get()->bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime, _fadeState!=STATE_COMPLETE); args->_details._materialSwitches++; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 6762601738..b68a542bce 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -118,8 +118,14 @@ public: private: + enum State : uint8_t { + STATE_WAITING_TO_START = 0, + STATE_IN_PROGRESS = 1, + STATE_COMPLETE = 2, + }; + mutable quint64 _fadeStartTime { 0 }; - mutable FadeEffect::State _fadeState { FadeEffect::WaitingToStart } ; + mutable State _fadeState { STATE_WAITING_TO_START } ; }; diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 77f7f61801..b521ff12ee 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -70,7 +70,6 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT)); slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), Slot::MAP::FADE_MASK)); - slotBindings.insert(gpu::Shader::Binding(std::string("fadeBuffer"), Slot::BUFFER::FADE)); gpu::Shader::makeProgram(*program, slotBindings); @@ -90,7 +89,6 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p locations->lightAmbientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer"); locations->lightAmbientMapUnit = program->getTextures().findLocation("skyboxMap"); locations->fadeMaskTextureUnit = program->getTextures().findLocation("fadeMaskMap"); - locations->fadeBufferUnit = program->getUniformBuffers().findLocation("fadeBuffer"); ShapeKey key{filter._flags}; auto gpuPipeline = gpu::Pipeline::create(program, state); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index b8045dfbcc..1c18f2a26e 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -214,7 +214,6 @@ public: LIGHTING_MODEL, LIGHT, LIGHT_AMBIENT_BUFFER, - FADE, }; enum MAP { @@ -245,7 +244,6 @@ public: int lightBufferUnit; int lightAmbientBufferUnit; int lightAmbientMapUnit; - int fadeBufferUnit; int fadeMaskTextureUnit; }; using LocationsPointer = std::shared_ptr;