diff --git a/interface/resources/images/fadeMask.png b/interface/resources/images/fadeMask.png new file mode 100644 index 0000000000..9c342ba788 Binary files /dev/null and b/interface/resources/images/fadeMask.png differ diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh new file mode 100644 index 0000000000..a40f1048a8 --- /dev/null +++ b/libraries/render-utils/src/Fade.slh @@ -0,0 +1,59 @@ +// Generated on <$_SCRIBE_DATE$> +// +// Created by Olivier Prat on 04/12/17. +// 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 +// +<@if not FADE_SLH@> +<@def FADE_SLH@> + +<@func declareFade()@> + +struct Fade { + vec3 _Offset; + float _Percent; +}; + +uniform fadeBuffer { + Fade fade; +}; + +uniform sampler2D fadeMaskMap; + +vec2 hash2D(vec3 position) { + return position.xy* vec2(0.1677, 0.221765) + position.z*0.561; +} + +float evalFadeMask(vec3 position, vec3 normal) { + const float FADE_MASK_INV_SCALE = 3.0; + + // Do tri-linear interpolation + vec3 noisePosition = position * FADE_MASK_INV_SCALE; + vec3 noisePositionFloored = floor(noisePosition) + fade._Offset; + vec3 noisePositionFraction = fract(noisePosition); + float noiseLowXLowYLowZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored), 0).r; + float noiseLowXHighYLowZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(0,1,0)), 0).r; + float noiseHighXLowYLowZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(1,0,0)), 0).r; + float noiseHighXHighYLowZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(1,1,0)), 0).r; + float noiseLowXLowYHighZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(0,0,1)), 0).r; + float noiseLowXHighYHighZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(0,1,1)), 0).r; + float noiseHighXLowYHighZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(1,0,1)), 0).r; + float noiseHighXHighYHighZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(1,1,1)), 0).r; + vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ); + vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ); + vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z); + vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x); + + return mix(maskY.x, maskY.y, noisePositionFraction.y); +} + +void applyFade(vec3 position, vec3 normal) { + if (evalFadeMask(position, normal) < fade._Percent) { + discard; + } +} +<@endfunc@> + +<@endif@> \ No newline at end of file diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 51ce0fffa7..57070479b6 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -321,11 +321,20 @@ template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, Ren } } +struct ModelMeshPartPayload::Fade +{ + glm::vec3 _offset; // The noise offset + float _percent; // The fade percent +}; + ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : _model(model), _meshIndex(_meshIndex), _shapeID(shapeIndex) { + Fade fade; + _fadeBuffer = gpu::BufferView(std::make_shared(sizeof(Fade), (const gpu::Byte*) &fade)); + assert(_model && _model->isLoaded()); auto& modelMesh = _model->getGeometry()->getMeshes().at(_meshIndex); updateMeshPart(modelMesh, partIndex); @@ -461,7 +470,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { ShapeKey::Builder builder; builder.withMaterial(); - if (isTranslucent || _fadeState != FADE_COMPLETE) { + if (isTranslucent) { builder.withTranslucent(); } if (hasTangents) { @@ -482,6 +491,9 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { if (wireframe) { builder.withWireframe(); } + if (_fadeState != FADE_COMPLETE) { + builder.withFade(); + } return builder.build(); } @@ -501,12 +513,6 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { batch.setInputBuffer(1, _model->_blendedVertexBuffers[_meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3)); batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2)); } - - if (_fadeState != FADE_COMPLETE) { - batch._glColor4f(1.0f, 1.0f, 1.0f, computeFadeAlpha()); - } else if (!_hasColorAttrib) { - batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - } } void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { @@ -517,23 +523,40 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline: batch.setModelTransform(_transform); } -float ModelMeshPartPayload::computeFadeAlpha() const { - if (_fadeState == FADE_WAITING_TO_START) { - return 0.0f; +float ModelMeshPartPayload::computeFadePercent(bool isDebugEnabled) const { + if (!isDebugEnabled) { + if (_fadeState == FADE_WAITING_TO_START) { + return 0.0f; + } + float fadeAlpha = 1.0f; + const float INV_FADE_PERIOD = 1.0f / (float)(1 * USECS_PER_SECOND); + float fraction = (float)(usecTimestampNow() - _fadeStartTime) * INV_FADE_PERIOD; + if (fraction < 1.0f) { + fadeAlpha = Interpolate::simpleNonLinearBlend(fraction); + } + if (fadeAlpha >= 1.0f) { + _fadeState = FADE_COMPLETE; + // when fade-in completes we flag model for one last "render item update" + _model->setRenderItemsNeedUpdate(); + return 1.0f; + } + return Interpolate::simpleNonLinearBlend(fadeAlpha); } - float fadeAlpha = 1.0f; - const float INV_FADE_PERIOD = 1.0f / (float)(1 * USECS_PER_SECOND); - float fraction = (float)(usecTimestampNow() - _fadeStartTime) * INV_FADE_PERIOD; - if (fraction < 1.0f) { - fadeAlpha = Interpolate::simpleNonLinearBlend(fraction); + else { + // Animate fade for debugging purposes during repeated 3 second cycles + return (usecTimestampNow() % (3 * USECS_PER_SECOND)) / (float)(3 * USECS_PER_SECOND); } - if (fadeAlpha >= 1.0f) { - _fadeState = FADE_COMPLETE; - // when fade-in completes we flag model for one last "render item update" - _model->setRenderItemsNeedUpdate(); - return 1.0f; +} + +void ModelMeshPartPayload::bindFade(gpu::Batch& batch, bool isDebugEnabled) const { + if (_fadeState != FADE_COMPLETE || isDebugEnabled) { + auto& fade = _fadeBuffer.edit(); + glm::vec3 offset = _transform.getTranslation(); + + fade._percent = computeFadePercent(isDebugEnabled); + fade._offset = offset; + batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::FADE, _fadeBuffer); } - return Interpolate::simpleNonLinearBlend(fadeAlpha); } void ModelMeshPartPayload::render(RenderArgs* args) const { @@ -576,6 +599,9 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { // apply material properties bindMaterial(batch, locations, args->_enableTexturing); + // Apply fade effect + bindFade(batch, (args->_debugFlags & RenderArgs::RENDER_DEBUG_FADE) != 0); + args->_details._materialSwitches++; // Draw! diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index ef74011c40..ffffb9ec88 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -93,7 +93,7 @@ public: const Transform& boundTransform, const gpu::BufferPointer& buffer); - float computeFadeAlpha() const; + float computeFadePercent(bool isDebugEnabled) const; // Render Item interface render::ItemKey getKey() const override; @@ -104,6 +104,7 @@ public: // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) const override; void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override; + void bindFade(gpu::Batch& batch, bool isDebugEnabled) const; void initCache(); @@ -119,6 +120,10 @@ public: bool _isBlendShaped{ false }; private: + + struct Fade; + + mutable gpu::BufferView _fadeBuffer; mutable quint64 _fadeStartTime { 0 }; mutable uint8_t _fadeState { FADE_WAITING_TO_START }; }; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 313b176f19..1dd212fea3 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -86,9 +86,13 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto deferredFramebuffer = prepareDeferredOutputs.getN(0); const auto lightingFramebuffer = prepareDeferredOutputs.getN(1); + // Fade texture mask + auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png"; + auto fadeMaskMap = DependencyManager::get()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE); + // Render opaque objects in DeferredBuffer const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying(); - task.addJob("DrawOpaqueDeferred", opaqueInputs, shapePlumber); + task.addJob("DrawOpaqueDeferred", opaqueInputs, shapePlumber, fadeMaskMap); // Once opaque is all rendered create stencil background task.addJob("DrawOpaqueStencil", deferredFramebuffer); @@ -310,11 +314,21 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const // Setup lighting model for all items; batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); - // From the lighting model define a global shapKey ORED with individiual keys + // From the lighting model define a global shapeKey ORED with individiual keys ShapeKey::Builder keyBuilder; if (lightingModel->isWireframeEnabled()) { keyBuilder.withWireframe(); } + + // Prepare fade effect + batch.setResourceTexture(ShapePipeline::Slot::MAP::FADE_MASK, _fadeMaskMap); + if (_debugFade) { + args->_debugFlags = static_cast(args->_debugFlags | + static_cast(RenderArgs::RENDER_DEBUG_FADE)); + // Force fade for everyone + keyBuilder.withFade(); + } + ShapeKey globalKey = keyBuilder.build(); args->_globalShapeKey = globalKey._flags.to_ulong(); @@ -325,6 +339,13 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const } args->_batch = nullptr; args->_globalShapeKey = 0; + + // Not sure this is really needed... + if (_debugFade) { + // Turn off fade debug + args->_debugFlags = static_cast(args->_debugFlags & + ~static_cast(RenderArgs::RENDER_DEBUG_FADE)); + } }); config->setNumDrawn((int)inItems.size()); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 12ecd5ecaf..c8f3326486 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -86,6 +86,7 @@ class DrawStateSortConfig : public render::Job::Config { Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) Q_PROPERTY(bool stateSort MEMBER stateSort NOTIFY dirty) + Q_PROPERTY(bool debugFade MEMBER debugFade NOTIFY dirty) public: int getNumDrawn() { return numDrawn; } @@ -93,6 +94,7 @@ public: int maxDrawn{ -1 }; bool stateSort{ true }; + bool debugFade{ false }; signals: void numDrawnChanged(); @@ -109,15 +111,17 @@ public: using Config = DrawStateSortConfig; using JobModel = render::Job::ModelI; - DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber, gpu::TexturePointer fadeMaskMap) : _shapePlumber{ shapePlumber }, _fadeMaskMap{ fadeMaskMap } {} - void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; } + void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; _debugFade = config.debugFade; } void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); protected: render::ShapePlumberPointer _shapePlumber; + gpu::TexturePointer _fadeMaskMap; int _maxDrawn; // initialized by Config bool _stateSort; + bool _debugFade; }; class DeferredFramebuffer; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index da264cbf7d..763fca04ed 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -41,6 +41,12 @@ #include "model_normal_specular_map_frag.h" #include "model_specular_map_frag.h" +#include "model_fade_vert.h" +#include "model_normal_map_fade_vert.h" + +#include "model_fade_frag.h" +#include "model_normal_map_fade_frag.h" + #include "forward_model_frag.h" #include "forward_model_unlit_frag.h" #include "forward_model_normal_map_frag.h" @@ -151,6 +157,10 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert)); auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); + // Only models can have fade applied to them (?) + auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_fade_vert)); + auto modelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_normal_map_fade_vert)); + // Pixel shaders auto simplePixel = gpu::Shader::createPixel(std::string(simple_textured_frag)); auto simpleUnlitPixel = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag)); @@ -169,6 +179,10 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag)); auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag)); + // Only models can have fade applied to them (?) + auto modelFadePixel = gpu::Shader::createPixel(std::string(model_fade_frag)); + auto modelNormalMapFadePixel = gpu::Shader::createPixel(std::string(model_normal_map_fade_frag)); + using Key = render::ShapeKey; auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3); // TODO: Refactor this to use a filter @@ -194,6 +208,14 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withMaterial().withTangents().withSpecular(), modelNormalMapVertex, modelNormalSpecularMapPixel); + // Same thing but with Fade on + addPipeline( + Key::Builder().withMaterial().withFade(), + modelFadeVertex, modelFadePixel); + addPipeline( + Key::Builder().withMaterial().withTangents().withFade(), + modelNormalMapFadeVertex, modelNormalMapFadePixel); + // Translucents addPipeline( Key::Builder().withMaterial().withTranslucent(), diff --git a/libraries/render-utils/src/model_fade.slf b/libraries/render-utils/src/model_fade.slf new file mode 100644 index 0000000000..06b2695d2b --- /dev/null +++ b/libraries/render-utils/src/model_fade.slf @@ -0,0 +1,65 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// model_fade.frag +// fragment shader +// +// Created by Olivier Prat on 04/19/17. +// 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 DeferredBufferWrite.slh@> + +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> + +<@include Fade.slh@> +<$declareFade()$> + +in vec4 _position; +in vec4 _worldPosition; +in vec3 _normal; +in vec3 _color; +in vec2 _texCoord0; +in vec2 _texCoord1; + + +void main(void) { + applyFade(_worldPosition.xyz, _normal); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + float scattering = getMaterialScattering(mat); + + packDeferredFragment( + normalize(_normal.xyz), + opacity, + albedo, + roughness, + getMaterialMetallic(mat), + emissive, + occlusionTex, + scattering); +} diff --git a/libraries/render-utils/src/model_fade.slv b/libraries/render-utils/src/model_fade.slv new file mode 100644 index 0000000000..4e6e02c1ad --- /dev/null +++ b/libraries/render-utils/src/model_fade.slv @@ -0,0 +1,44 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// model_fade.slv +// vertex shader +// +// Created by Olivier Prat on 04/24/17. +// 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +out vec3 _color; +out float _alpha; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec4 _position; +out vec4 _worldPosition; +out vec3 _normal; + +void main(void) { + _color = colorToLinearRGB(inColor.xyz); + _alpha = inColor.w; + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> +} diff --git a/libraries/render-utils/src/model_normal_map_fade.slf b/libraries/render-utils/src/model_normal_map_fade.slf new file mode 100644 index 0000000000..4586fe555a --- /dev/null +++ b/libraries/render-utils/src/model_normal_map_fade.slf @@ -0,0 +1,70 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_normal_map_fade.frag +// fragment shader +// +// Created by Olivier Prat on 04/19/17. +// 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 DeferredBufferWrite.slh@> + +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION, SCATTERING)$> + +<@include Fade.slh@> +<$declareFade()$> + +in vec4 _position; +in vec4 _worldPosition; +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec3 _normal; +in vec3 _tangent; +in vec3 _color; + +void main(void) { + applyFade(_worldPosition.xyz, _normal); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, scatteringTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + vec3 viewNormal; + <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$> + + float scattering = getMaterialScattering(mat); + <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; + + packDeferredFragment( + viewNormal, + opacity, + albedo, + roughness, + getMaterialMetallic(mat), + emissive, + occlusionTex, + scattering); +} diff --git a/libraries/render-utils/src/model_normal_map_fade.slv b/libraries/render-utils/src/model_normal_map_fade.slv new file mode 100644 index 0000000000..a71900d5c3 --- /dev/null +++ b/libraries/render-utils/src/model_normal_map_fade.slv @@ -0,0 +1,48 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_normal_map_fade.vert +// vertex shader +// +// Created by Olivier Prat on 04/24/17. +// 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +out vec4 _position; +out vec4 _worldPosition; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec3 _normal; +out vec3 _tangent; +out vec3 _color; +out float _alpha; + +void main(void) { + // pass along the color + _color = colorToLinearRGB(inColor.rgb); + _alpha = inColor.a; + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$> +} diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index d51d7f8cb6..77f7f61801 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -69,6 +69,8 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::BUFFER::LIGHT)); 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); @@ -87,6 +89,8 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p locations->lightBufferUnit = program->getUniformBuffers().findLocation("lightBuffer"); 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 73e8f82f24..b8045dfbcc 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -33,6 +33,7 @@ public: DEPTH_BIAS, WIREFRAME, NO_CULL_FACE, + FADE, OWN_PIPELINE, INVALID, @@ -68,6 +69,7 @@ public: Builder& withDepthBias() { _flags.set(DEPTH_BIAS); return (*this); } Builder& withWireframe() { _flags.set(WIREFRAME); return (*this); } Builder& withoutCullFace() { _flags.set(NO_CULL_FACE); return (*this); } + Builder& withFade() { _flags.set(FADE); return (*this); } Builder& withOwnPipeline() { _flags.set(OWN_PIPELINE); return (*this); } Builder& invalidate() { _flags.set(INVALID); return (*this); } @@ -126,6 +128,9 @@ public: Builder& withCullFace() { _flags.reset(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); } Builder& withoutCullFace() { _flags.set(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); } + Builder& withFade() { _flags.reset(FADE); _mask.set(FADE); return (*this); } + Builder& withoutFade() { _flags.set(FADE); _mask.set(FADE); return (*this); } + protected: friend class Filter; Flags _flags{0}; @@ -150,6 +155,7 @@ public: bool isDepthBiased() const { return _flags[DEPTH_BIAS]; } bool isWireframe() const { return _flags[WIREFRAME]; } bool isCullFace() const { return !_flags[NO_CULL_FACE]; } + bool isFaded() const { return _flags[FADE]; } bool hasOwnPipeline() const { return _flags[OWN_PIPELINE]; } bool isValid() const { return !_flags[INVALID]; } @@ -186,6 +192,7 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& key) { << "isDepthBiased:" << key.isDepthBiased() << "isWireframe:" << key.isWireframe() << "isCullFace:" << key.isCullFace() + << "isFaded:" << key.isFaded() << "]"; } } else { @@ -207,6 +214,7 @@ public: LIGHTING_MODEL, LIGHT, LIGHT_AMBIENT_BUFFER, + FADE, }; enum MAP { @@ -218,6 +226,7 @@ public: OCCLUSION, SCATTERING, LIGHT_AMBIENT, + FADE_MASK, }; }; @@ -236,6 +245,8 @@ public: int lightBufferUnit; int lightAmbientBufferUnit; int lightAmbientMapUnit; + int fadeBufferUnit; + int fadeMaskTextureUnit; }; using LocationsPointer = std::shared_ptr; diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 10a9a20287..8fe65fb5a6 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -79,7 +79,8 @@ public: enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT }; enum DebugFlags { RENDER_DEBUG_NONE = 0, - RENDER_DEBUG_HULLS = 1 + RENDER_DEBUG_HULLS = 1, + RENDER_DEBUG_FADE = 2, }; RenderArgs(std::shared_ptr context = nullptr,