From c6f7c058bc1140027e10e3941e25114215e663ce Mon Sep 17 00:00:00 2001 From: milad Date: Tue, 5 Nov 2019 17:30:09 -0800 Subject: [PATCH] merging master --- assignment-client/CMakeLists.txt | 1 + assignment-client/src/avatars/AvatarMixer.cpp | 4 +- interface/src/Application.cpp | 15 +- interface/src/Menu.cpp | 6 + interface/src/Menu.h | 1 + interface/src/ui/PreferencesDialog.cpp | 10 + libraries/avatars-renderer/CMakeLists.txt | 4 +- .../src/avatars-renderer/Avatar.h | 4 +- libraries/avatars/CMakeLists.txt | 3 +- libraries/avatars/src/AvatarData.h | 4 - libraries/avatars/src/AvatarHashMap.h | 1 + libraries/baking/CMakeLists.txt | 3 +- libraries/baking/src/MaterialBaker.h | 2 +- libraries/baking/src/TextureBaker.h | 2 +- libraries/display-plugins/CMakeLists.txt | 1 + .../src/RenderableMaterialEntityItem.cpp | 68 ++++-- .../src/RenderableMaterialEntityItem.h | 2 +- .../src/RenderableModelEntityItem.cpp | 2 +- .../src/RenderableShapeEntityItem.cpp | 181 +++++++-------- .../src/RenderableShapeEntityItem.h | 8 +- libraries/entities/CMakeLists.txt | 4 +- libraries/gpu/src/gpu/Shader.h | 3 - libraries/gpu/src/gpu/ShaderConstants.h | 1 - .../src/graphics-scripting/Forward.h | 3 + .../GraphicsScriptingInterface.cpp | 218 +++++++++--------- .../graphics-scripting/ScriptableModel.cpp | 182 ++++++++------- libraries/graphics/src/graphics/Material.cpp | 4 +- libraries/graphics/src/graphics/Material.h | 11 +- libraries/model-baker/CMakeLists.txt | 3 +- .../model-baker/ParseMaterialMappingTask.h | 2 +- libraries/model-networking/CMakeLists.txt | 5 +- .../src/model-networking/ModelCache.h | 2 +- libraries/physics/CMakeLists.txt | 7 +- libraries/procedural/CMakeLists.txt | 2 +- .../procedural/src/procedural/Procedural.cpp | 112 +++++---- .../procedural/src/procedural/Procedural.h | 81 ++++++- .../src/procedural/ProceduralCommon.slh | 2 +- .../src/procedural/ProceduralSkybox.cpp | 6 +- .../src/procedural/ShaderConstants.h | 15 +- .../src/CauterizedMeshPartPayload.cpp | 5 +- .../src/CauterizedMeshPartPayload.h | 2 +- .../render-utils/src/CauterizedModel.cpp | 2 +- .../render-utils/src/MeshPartPayload.cpp | 139 +++++++---- libraries/render-utils/src/MeshPartPayload.h | 7 +- libraries/render-utils/src/Model.cpp | 7 +- libraries/render-utils/src/Model.h | 4 +- .../render-utils/src/RenderPipelines.cpp | 1 + .../src/render-utils/simple_procedural.slp | 2 +- .../render-utils/src/simple_procedural.slv | 32 ++- libraries/script-engine/CMakeLists.txt | 10 +- libraries/script-engine/src/Quat.cpp | 2 - .../src/SceneScriptingInterface.cpp | 129 +---------- .../src/SceneScriptingInterface.h | 197 +--------------- libraries/ui/src/MainWindow.cpp | 3 +- tests-manual/render-perf/src/main.cpp | 62 ----- tools/oven/CMakeLists.txt | 2 +- tools/oven/src/Oven.cpp | 2 +- tools/oven/src/OvenCLIApplication.cpp | 2 + 58 files changed, 724 insertions(+), 871 deletions(-) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index b7afc3ed9e..b4042cf294 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -16,6 +16,7 @@ link_hifi_libraries( controllers physics plugins midi image material-networking model-networking ktx shaders ) +include_hifi_library_headers(procedural) add_dependencies(${TARGET_NAME} oven) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 36fd04681a..c7ab810c9a 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -512,10 +512,10 @@ void AvatarMixer::handleAvatarKilled(SharedNodePointer avatarNode) { // we relay avatar kill packets to agents that are not upstream // and downstream avatar mixers, if the node that was just killed was being replicatedConnectedAgent return node->getActiveSocket() && - ((node->getType() == NodeType::Agent && !node->isUpstream()) || + (((node->getType() == NodeType::Agent || node->getType() == NodeType::EntityScriptServer) && !node->isUpstream()) || (avatarNode->isReplicated() && shouldReplicateTo(*avatarNode, *node))); }, [&](const SharedNodePointer& node) { - if (node->getType() == NodeType::Agent) { + if (node->getType() == NodeType::Agent || node->getType() == NodeType::EntityScriptServer) { if (!killPacket) { killPacket = NLPacket::create(PacketType::KillAvatar, NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason), true); killPacket->write(avatarNode->getUUID().toRfc4122()); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 156f2d564b..f7ba8beb26 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -106,7 +106,7 @@ #include #include #include -#include +#include #include #include #include @@ -159,7 +159,8 @@ #include #include #include -#include +#include +#include #include "recording/ClipCache.h" #include "AudioClient.h" @@ -2096,7 +2097,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo EntityTreeRenderer::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) { auto avatarManager = DependencyManager::get(); - auto avatar = avatarManager->getAvatarBySessionID(avatarID); + auto avatar = static_pointer_cast(avatarManager->getAvatarBySessionID(avatarID)); if (avatar) { avatar->addMaterial(material, parentMaterialName); return true; @@ -2105,13 +2106,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo }); EntityTreeRenderer::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) { auto avatarManager = DependencyManager::get(); - auto avatar = avatarManager->getAvatarBySessionID(avatarID); + auto avatar = static_pointer_cast(avatarManager->getAvatarBySessionID(avatarID)); if (avatar) { avatar->removeMaterial(material, parentMaterialName); return true; } return false; }); + Procedural::opaqueStencil = [](gpu::StatePointer state) { PrepareStencil::testMaskDrawShape(*state); }; + Procedural::transparentStencil = [](gpu::StatePointer state) { PrepareStencil::testMask(*state); }; EntityTree::setGetEntityObjectOperator([this](const QUuid& id) -> QObject* { auto entities = getEntities(); @@ -7092,10 +7095,6 @@ void Application::clearDomainOctreeDetails(bool clearAll) { // reset the model renderer clearAll ? getEntities()->clear() : getEntities()->clearDomainAndNonOwnedEntities(); - auto skyStage = DependencyManager::get()->getSkyStage(); - - skyStage->setBackgroundMode(graphics::SunSkyStage::SKY_DEFAULT); - DependencyManager::get()->clearUnusedResources(); DependencyManager::get()->clearUnusedResources(); DependencyManager::get()->clearUnusedResources(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index fe269a6a64..9700ff6336 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -53,6 +53,7 @@ #include "SpeechRecognizer.h" #endif +#include "MeshPartPayload.h" #include "scripting/RenderScriptingInterface.h" extern bool DEV_DECIMATE_TEXTURES; @@ -470,6 +471,11 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ComputeBlendshapes, 0, true, DependencyManager::get().data(), SLOT(setComputeBlendshapes(bool))); + action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::MeshShaders, 0, false); + connect(action, &QAction::triggered, [action] { + MeshPartPayload::enableMeshShaders = action->isChecked(); + }); + { auto drawStatusConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.DrawStatus"); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::HighlightTransitions, 0, false, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 4a2a97b168..4c6a6c48dc 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -228,6 +228,7 @@ namespace MenuOption { const QString ForceCoarsePicking = "Force Coarse Picking"; const QString ComputeBlendshapes = "Compute Blendshapes"; const QString HighlightTransitions = "Highlight Transitions"; + const QString MeshShaders = "Enable Procedural Materials on Meshes"; } #endif // hifi_Menu_h diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 9e98b84edc..4e4fd965a8 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -102,6 +102,16 @@ void setupPreferences() { preference->setItems(refreshRateProfiles); preferences->addPreference(preference); + + auto getterMeshShaders = []() -> bool { + auto menu = Menu::getInstance(); + return menu->isOptionChecked(MenuOption::MeshShaders); + }; + auto setterMeshShaders = [](bool value) { + auto menu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::MeshShaders, value); + }; + preferences->addPreference(new CheckPreference(GRAPHICS_QUALITY, "Enable Procedural Materials on Meshes", getterMeshShaders, setterMeshShaders)); } { // Expose the Viewport Resolution Scale diff --git a/libraries/avatars-renderer/CMakeLists.txt b/libraries/avatars-renderer/CMakeLists.txt index 7929be8b04..deba2913c1 100644 --- a/libraries/avatars-renderer/CMakeLists.txt +++ b/libraries/avatars-renderer/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME avatars-renderer) setup_hifi_library(Network Script) -link_hifi_libraries(shared shaders gpu graphics animation material-networking model-networking script-engine render render-utils image entities-renderer) +link_hifi_libraries(shared shaders gpu graphics animation material-networking model-networking script-engine render render-utils image entities-renderer physics) include_hifi_library_headers(avatars) include_hifi_library_headers(networking) include_hifi_library_headers(hfm) @@ -8,8 +8,6 @@ include_hifi_library_headers(fbx) include_hifi_library_headers(recording) include_hifi_library_headers(ktx) include_hifi_library_headers(procedural) -include_hifi_library_headers(physics) -include_hifi_library_headers(entities-renderer) include_hifi_library_headers(audio) include_hifi_library_headers(entities) include_hifi_library_headers(octree) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 610f34ed45..031b2f1309 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -547,8 +547,8 @@ public: virtual void setEnableMeshVisible(bool isEnabled); virtual bool getEnableMeshVisible() const; - void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) override; - void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) override; + void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName); + void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName); virtual scriptable::ScriptableModelBase getScriptableModel() override; diff --git a/libraries/avatars/CMakeLists.txt b/libraries/avatars/CMakeLists.txt index 13fda28f40..fc6d15cced 100644 --- a/libraries/avatars/CMakeLists.txt +++ b/libraries/avatars/CMakeLists.txt @@ -1,4 +1,3 @@ set(TARGET_NAME avatars) setup_hifi_library(Network Script) -include_hifi_library_headers(gpu) -link_hifi_libraries(shared networking graphics) +link_hifi_libraries(shared networking) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 16fe4d82d4..e8aee1f3d2 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -55,8 +55,6 @@ #include "HeadData.h" #include "PathUtils.h" -#include - using AvatarSharedPointer = std::shared_ptr; using AvatarWeakPointer = std::weak_ptr; using AvatarHash = QHash; @@ -1493,8 +1491,6 @@ public: bool getIsReplicated() const { return _isReplicated; } - virtual void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) {} - virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {} void setReplicaIndex(int replicaIndex) { _replicaIndex = replicaIndex; } int getReplicaIndex() { return _replicaIndex; } diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 17a3d28eb0..c474353451 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -44,6 +44,7 @@ const quint64 MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS = USECS_PER_SECOND / CLIENT_ * @namespace AvatarList * * @hifi-assignment-client + * @hifi-server-entity */ class AvatarReplicas { diff --git a/libraries/baking/CMakeLists.txt b/libraries/baking/CMakeLists.txt index 73618427f6..4350f386ab 100644 --- a/libraries/baking/CMakeLists.txt +++ b/libraries/baking/CMakeLists.txt @@ -1,6 +1,7 @@ set(TARGET_NAME baking) setup_hifi_library(Concurrent) -link_hifi_libraries(shared shaders graphics networking material-networking graphics-scripting ktx image fbx model-baker task) +link_hifi_libraries(shared shaders graphics networking procedural graphics-scripting ktx image fbx model-baker task) include_hifi_library_headers(gpu) include_hifi_library_headers(hfm) +include_hifi_library_headers(material-networking) \ No newline at end of file diff --git a/libraries/baking/src/MaterialBaker.h b/libraries/baking/src/MaterialBaker.h index 04782443f0..33123cfc73 100644 --- a/libraries/baking/src/MaterialBaker.h +++ b/libraries/baking/src/MaterialBaker.h @@ -17,7 +17,7 @@ #include "TextureBaker.h" #include "baking/TextureFileNamer.h" -#include +#include static const QString BAKED_MATERIAL_EXTENSION = ".baked.json"; diff --git a/libraries/baking/src/TextureBaker.h b/libraries/baking/src/TextureBaker.h index 5fda05e9b4..5c6c85ea16 100644 --- a/libraries/baking/src/TextureBaker.h +++ b/libraries/baking/src/TextureBaker.h @@ -22,7 +22,7 @@ #include "Baker.h" -#include +#include extern const QString BAKED_TEXTURE_KTX_EXT; extern const QString BAKED_META_TEXTURE_SUFFIX; diff --git a/libraries/display-plugins/CMakeLists.txt b/libraries/display-plugins/CMakeLists.txt index ad6503b22d..bfe88f2eb8 100644 --- a/libraries/display-plugins/CMakeLists.txt +++ b/libraries/display-plugins/CMakeLists.txt @@ -11,6 +11,7 @@ include_hifi_library_headers(fbx) include_hifi_library_headers(image) include_hifi_library_headers(ktx) include_hifi_library_headers(render) +include_hifi_library_headers(procedural) target_opengl() diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index eae0561343..a013ff75b7 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -11,6 +11,8 @@ #include "RenderPipelines.h" #include "GeometryCache.h" +#include + using namespace render; using namespace render::entities; @@ -227,31 +229,31 @@ ItemKey MaterialEntityRenderer::getKey() { } ShapeKey MaterialEntityRenderer::getShapeKey() { + ShapeKey::Builder builder; graphics::MaterialKey drawMaterialKey; const auto drawMaterial = getMaterial(); if (drawMaterial) { drawMaterialKey = drawMaterial->getKey(); } - bool isTranslucent = drawMaterialKey.isTranslucent(); - bool hasTangents = drawMaterialKey.isNormalMap(); - bool hasLightmap = drawMaterialKey.isLightMap(); - bool isUnlit = drawMaterialKey.isUnlit(); - - ShapeKey::Builder builder; - builder.withMaterial(); - - if (isTranslucent) { + if (drawMaterialKey.isTranslucent()) { builder.withTranslucent(); } - if (hasTangents) { - builder.withTangents(); - } - if (hasLightmap) { - builder.withLightMap(); - } - if (isUnlit) { - builder.withUnlit(); + + if (drawMaterial && drawMaterial->isProcedural() && drawMaterial->isReady()) { + builder.withOwnPipeline(); + } else { + builder.withMaterial(); + + if (drawMaterialKey.isNormalMap()) { + builder.withTangents(); + } + if (drawMaterialKey.isLightMap()) { + builder.withLightMap(); + } + if (drawMaterialKey.isUnlit()) { + builder.withUnlit(); + } } if (_primitiveMode == PrimitiveMode::LINES) { @@ -277,6 +279,7 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { Transform renderTransform; graphics::MaterialPointer drawMaterial; + bool proceduralRender = false; Transform textureTransform; withReadLock([&] { renderTransform = _renderTransform; @@ -284,6 +287,10 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0)); textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialMappingRot))); textureTransform.setScale(glm::vec3(_materialMappingScale, 1)); + + if (drawMaterial && drawMaterial->isProcedural() && drawMaterial->isReady()) { + proceduralRender = true; + } }); if (!drawMaterial) { return; @@ -291,14 +298,27 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { batch.setModelTransform(renderTransform); - drawMaterial->setTextureTransforms(textureTransform, MaterialMappingMode::UV, true); - // bind the material - if (RenderPipelines::bindMaterial(drawMaterial, batch, args->_renderMode, args->_enableTexturing)) { - args->_details._materialSwitches++; - } + if (!proceduralRender) { + drawMaterial->setTextureTransforms(textureTransform, MaterialMappingMode::UV, true); + // bind the material + if (RenderPipelines::bindMaterial(drawMaterial, batch, args->_renderMode, args->_enableTexturing)) { + args->_details._materialSwitches++; + } - // Draw! - DependencyManager::get()->renderSphere(batch); + // Draw! + DependencyManager::get()->renderSphere(batch); + } else { + auto proceduralDrawMaterial = std::static_pointer_cast(drawMaterial); + glm::vec4 outColor = glm::vec4(drawMaterial->getAlbedo(), drawMaterial->getOpacity()); + outColor = proceduralDrawMaterial->getColor(outColor); + proceduralDrawMaterial->prepare(batch, renderTransform.getTranslation(), renderTransform.getScale(), + renderTransform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f)); + if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { + DependencyManager::get()->renderWireSphere(batch, outColor); + } else { + DependencyManager::get()->renderSphere(batch, outColor); + } + } args->_details._trianglesRendered += (int)DependencyManager::get()->getSphereTriangleCount(); } diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h index 0c347155e0..ff7367a44e 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h @@ -13,7 +13,7 @@ #include -#include +#include class NetworkMaterial; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 6314cc8ce4..1f2be0c488 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1316,7 +1316,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce // Check for addition if (_hasModel && !model) { - model = std::make_shared(nullptr, entity.get()); + model = std::make_shared(nullptr, entity.get(), _created); connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate); connect(model.get(), &Model::setURLFinished, this, [&](bool didVisualGeometryRequestSucceed) { setKey(didVisualGeometryRequestSucceed); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 4f1ebaecb9..88cc78b6b6 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -12,17 +12,11 @@ #include #include -#include #include #include -#include #include "RenderPipelines.h" -//#define SHAPE_ENTITY_USE_FADE_EFFECT -#ifdef SHAPE_ENTITY_USE_FADE_EFFECT -#include -#endif using namespace render; using namespace render::entities; @@ -31,25 +25,20 @@ using namespace render::entities; static const float SPHERE_ENTITY_SCALE = 0.5f; ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { - _procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural); - // FIXME: Setup proper uniform slots and use correct pipelines for forward rendering - _procedural._opaqueFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_procedural); - _procedural._transparentFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_procedural_translucent); - - // TODO: move into Procedural.cpp - PrepareStencil::testMaskDrawShape(*_procedural._opaqueState); - PrepareStencil::testMask(*_procedural._transparentState); - addMaterial(graphics::MaterialLayer(_material, 0), "0"); } bool ShapeEntityRenderer::needsRenderUpdate() const { if (resultWithReadLock([&] { - if (_procedural.isEnabled() && _procedural.isFading()) { - return true; + auto mat = _materials.find("0"); + if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() && + mat->second.top().material->isEnabled()) { + auto procedural = std::static_pointer_cast(mat->second.top().material); + if (procedural->isFading()) { + return true; + } } - auto mat = _materials.find("0"); if (mat != _materials.end() && mat->second.shouldUpdate()) { return true; } @@ -67,7 +56,7 @@ bool ShapeEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin return true; } - if (_lastUserData != entity->getUserData()) { + if (_proceduralData != entity->getUserData()) { return true; } @@ -76,12 +65,6 @@ bool ShapeEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { withWriteLock([&] { - auto userData = entity->getUserData(); - if (_lastUserData != userData) { - _lastUserData = userData; - _procedural.setProceduralData(ProceduralData::parse(_lastUserData)); - } - _shape = entity->getShape(); _pulseProperties = entity->getPulseProperties(); }); @@ -106,25 +89,45 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { withReadLock([&] { - if (_procedural.isEnabled() && _procedural.isFading()) { - float isFading = Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f; - _procedural.setIsFading(isFading); + auto mat = _materials.find("0"); + if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() && mat->second.top().material->isEnabled()) { + auto procedural = std::static_pointer_cast(mat->second.top().material); + if (procedural->isFading()) { + procedural->setIsFading(Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) < 1.0f); + } } }); - glm::vec3 color = toGlm(entity->getColor()); - float alpha = entity->getAlpha(); - if (_color != color || _alpha != alpha) { - _color = color; - _alpha = alpha; - _material->setAlbedo(color); - _material->setOpacity(_alpha); - - auto materials = _materials.find("0"); - if (materials != _materials.end()) { - materials->second.setNeedsUpdate(true); + withWriteLock([&] { + bool materialChanged = false; + glm::vec3 color = toGlm(entity->getColor()); + if (_color != color) { + _color = color; + _material->setAlbedo(color); + materialChanged = true; } - } + + float alpha = entity->getAlpha(); + if (_alpha != alpha) { + _alpha = alpha; + _material->setOpacity(alpha); + materialChanged = true; + } + + auto userData = entity->getUserData(); + if (_proceduralData != userData) { + _proceduralData = userData; + _material->setProceduralData(_proceduralData); + materialChanged = true; + } + + if (materialChanged) { + auto materials = _materials.find("0"); + if (materials != _materials.end()) { + materials->second.setNeedsUpdate(true); + } + } + }); } bool ShapeEntityRenderer::isTransparent() const { @@ -132,12 +135,15 @@ bool ShapeEntityRenderer::isTransparent() const { return true; } - if (_procedural.isEnabled() && _procedural.isFading()) { - return Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f; - } - auto mat = _materials.find("0"); - if (mat != _materials.end()) { + if (mat != _materials.end() && mat->second.top().material) { + if (mat->second.top().material->isProcedural() && mat->second.top().material->isEnabled()) { + auto procedural = std::static_pointer_cast(mat->second.top().material); + if (procedural->isFading()) { + return true; + } + } + if (mat->second.getMaterialKey().isTranslucent()) { return true; } @@ -146,80 +152,59 @@ bool ShapeEntityRenderer::isTransparent() const { return Parent::isTransparent(); } -bool ShapeEntityRenderer::useMaterialPipeline(const graphics::MultiMaterial& materials) const { - bool proceduralReady = resultWithReadLock([&] { - return _procedural.isReady(); - }); - if (proceduralReady) { - return false; +ShapeEntityRenderer::Pipeline ShapeEntityRenderer::getPipelineType(const graphics::MultiMaterial& materials) const { + if (materials.top().material && materials.top().material->isProcedural() && materials.top().material->isReady()) { + return Pipeline::PROCEDURAL; } graphics::MaterialKey drawMaterialKey = materials.getMaterialKey(); if (drawMaterialKey.isEmissive() || drawMaterialKey.isUnlit() || drawMaterialKey.isMetallic() || drawMaterialKey.isScattering()) { - return true; + return Pipeline::MATERIAL; } // If the material is using any map, we need to use a material ShapeKey for (int i = 0; i < graphics::Material::MapChannel::NUM_MAP_CHANNELS; i++) { if (drawMaterialKey.isMapChannel(graphics::Material::MapChannel(i))) { - return true; + return Pipeline::MATERIAL; } } - return false; + return Pipeline::SIMPLE; } ShapeKey ShapeEntityRenderer::getShapeKey() { + ShapeKey::Builder builder; auto mat = _materials.find("0"); if (mat != _materials.end() && mat->second.shouldUpdate()) { RenderPipelines::updateMultiMaterial(mat->second); } - if (mat != _materials.end() && useMaterialPipeline(mat->second)) { - graphics::MaterialKey drawMaterialKey = mat->second.getMaterialKey(); + if (isTransparent()) { + builder.withTranslucent(); + } - bool isTranslucent = drawMaterialKey.isTranslucent(); - bool hasTangents = drawMaterialKey.isNormalMap(); - bool hasLightmap = drawMaterialKey.isLightMap(); - bool isUnlit = drawMaterialKey.isUnlit(); + if (_primitiveMode == PrimitiveMode::LINES) { + builder.withWireframe(); + } - ShapeKey::Builder builder; + auto pipelineType = getPipelineType(mat->second); + if (pipelineType == Pipeline::MATERIAL) { builder.withMaterial(); - if (isTranslucent) { - builder.withTranslucent(); - } - if (hasTangents) { + graphics::MaterialKey drawMaterialKey = mat->second.getMaterialKey(); + if (drawMaterialKey.isNormalMap()) { builder.withTangents(); } - if (hasLightmap) { + if (drawMaterialKey.isLightMap()) { builder.withLightMap(); } - if (isUnlit) { + if (drawMaterialKey.isUnlit()) { builder.withUnlit(); } - - if (_primitiveMode == PrimitiveMode::LINES) { - builder.withWireframe(); - } - - return builder.build(); - } else { - ShapeKey::Builder builder; - bool proceduralReady = resultWithReadLock([&] { - return _procedural.isReady(); - }); - if (proceduralReady) { - builder.withOwnPipeline(); - } - if (isTransparent()) { - builder.withTranslucent(); - } - - if (_primitiveMode == PrimitiveMode::LINES) { - builder.withWireframe(); - } - return builder.build(); + } else if (pipelineType == Pipeline::PROCEDURAL) { + builder.withOwnPipeline(); } + + return builder.build(); } void ShapeEntityRenderer::doRender(RenderArgs* args) { @@ -233,36 +218,36 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { GeometryCache::Shape geometryShape; PrimitiveMode primitiveMode; RenderLayer renderLayer; - bool proceduralRender = false; glm::vec4 outColor; + Pipeline pipelineType; withReadLock([&] { geometryShape = geometryCache->getShapeForEntityShape(_shape); primitiveMode = _primitiveMode; renderLayer = _renderLayer; batch.setModelTransform(_renderTransform); // use a transform with scale, rotation, registration point and translation materials = _materials["0"]; + pipelineType = getPipelineType(materials); auto& schema = materials.getSchemaBuffer().get(); outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); outColor = EntityRenderer::calculatePulseColor(outColor, _pulseProperties, _created); - if (_procedural.isReady()) { - outColor = _procedural.getColor(outColor); - outColor.a *= _procedural.isFading() ? Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) : 1.0f; - _procedural.prepare(batch, _position, _dimensions, _orientation, _created, ProceduralProgramKey(outColor.a < 1.0f)); - proceduralRender = true; - } }); if (outColor.a == 0.0f) { return; } - if (proceduralRender) { + if (pipelineType == Pipeline::PROCEDURAL) { + auto procedural = std::static_pointer_cast(materials.top().material); + outColor = procedural->getColor(outColor); + outColor.a *= procedural->isFading() ? Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) : 1.0f; + procedural->prepare(batch, _position, _dimensions, _orientation, _created, ProceduralProgramKey(outColor.a < 1.0f)); + if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) { geometryCache->renderWireShape(batch, geometryShape, outColor); } else { geometryCache->renderShape(batch, geometryShape, outColor); } - } else if (!useMaterialPipeline(materials)) { + } else if (pipelineType == Pipeline::SIMPLE) { // FIXME, support instanced multi-shape rendering using multidraw indirect outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(outColor.a < 1.0f, false, diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 6e4b05f716..6061526f75 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -35,14 +35,14 @@ private: virtual void doRender(RenderArgs* args) override; virtual bool isTransparent() const override; - bool useMaterialPipeline(const graphics::MultiMaterial& materials) const; + enum Pipeline { SIMPLE, MATERIAL, PROCEDURAL }; + Pipeline getPipelineType(const graphics::MultiMaterial& materials) const; - Procedural _procedural; - QString _lastUserData; + QString _proceduralData; entity::Shape _shape { entity::Sphere }; PulsePropertyGroup _pulseProperties; - std::shared_ptr _material { std::make_shared() }; + std::shared_ptr _material { std::make_shared() }; glm::vec3 _color { NAN }; float _alpha; diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index 56adb59914..3157a6552b 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -6,4 +6,6 @@ include_hifi_library_headers(fbx) include_hifi_library_headers(gpu) include_hifi_library_headers(image) include_hifi_library_headers(ktx) -link_hifi_libraries(shared shaders networking octree avatars graphics material-networking model-networking) +include_hifi_library_headers(material-networking) +include_hifi_library_headers(procedural) +link_hifi_libraries(shared shaders networking octree avatars graphics model-networking) diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index f4f37b1815..9220f301d6 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -119,9 +119,6 @@ protected: Shader(Type type, const Source& source, bool dynamic); Shader(Type type, const Pointer& vertex, const Pointer& geometry, const Pointer& pixel); - Shader(const Shader& shader); // deep copy of the sysmem shader - Shader& operator=(const Shader& shader); // deep copy of the sysmem texture - // Source contains the actual source code or nothing if the shader is a program const Source _source; diff --git a/libraries/gpu/src/gpu/ShaderConstants.h b/libraries/gpu/src/gpu/ShaderConstants.h index 1a37c69784..c2637e2dfb 100644 --- a/libraries/gpu/src/gpu/ShaderConstants.h +++ b/libraries/gpu/src/gpu/ShaderConstants.h @@ -21,7 +21,6 @@ #define GPU_TEXTURE_TRANSFORM_OBJECT 31 - #define GPU_RESOURCE_BUFFER_SLOT0_TEXTURE 35 #define GPU_RESOURCE_BUFFER_SLOT1_TEXTURE 36 #define GPU_RESOURCE_BUFFER_SLOT0_STORAGE 0 diff --git a/libraries/graphics-scripting/src/graphics-scripting/Forward.h b/libraries/graphics-scripting/src/graphics-scripting/Forward.h index 1295fc5722..9efaa0a90d 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/Forward.h +++ b/libraries/graphics-scripting/src/graphics-scripting/Forward.h @@ -66,6 +66,7 @@ namespace scriptable { * @property {string} lightmapParams * @property {string} materialParams * @property {boolean} defaultFallthrough + * @property {string} procedural */ class ScriptableMaterial { public: @@ -101,6 +102,8 @@ namespace scriptable { bool defaultFallthrough; std::unordered_map propertyFallthroughs; // not actually exposed to script + QString procedural; + graphics::MaterialKey key { 0 }; }; diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp index ca9634e365..d76c1fcbd2 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp @@ -368,129 +368,135 @@ namespace scriptable { obj.setProperty("opacity", material.opacity); } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::GLOSSY_VAL_BIT)) { - obj.setProperty("roughness", FALLTHROUGH); - } else if (material.key.isGlossy()) { - obj.setProperty("roughness", material.roughness); - } - - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::METALLIC_VAL_BIT)) { - obj.setProperty("metallic", FALLTHROUGH); - } else if (material.key.isMetallic()) { - obj.setProperty("metallic", material.metallic); - } - - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::SCATTERING_VAL_BIT)) { - obj.setProperty("scattering", FALLTHROUGH); - } else if (material.key.isScattering()) { - obj.setProperty("scattering", material.scattering); - } - - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::UNLIT_VAL_BIT)) { - obj.setProperty("unlit", FALLTHROUGH); - } else if (material.key.isUnlit()) { - obj.setProperty("unlit", material.unlit); - } - - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::EMISSIVE_VAL_BIT)) { - obj.setProperty("emissive", FALLTHROUGH); - } else if (material.key.isEmissive()) { - obj.setProperty("emissive", vec3ColorToScriptValue(engine, material.emissive)); - } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::ALBEDO_VAL_BIT)) { obj.setProperty("albedo", FALLTHROUGH); } else if (material.key.isAlbedo()) { obj.setProperty("albedo", vec3ColorToScriptValue(engine, material.albedo)); } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::EMISSIVE_MAP_BIT)) { - obj.setProperty("emissiveMap", FALLTHROUGH); - } else if (!material.emissiveMap.isEmpty()) { - obj.setProperty("emissiveMap", material.emissiveMap); - } + if (material.model.toStdString() == graphics::Material::HIFI_PBR) { + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OPACITY_CUTOFF_VAL_BIT)) { + obj.setProperty("opacityCutoff", FALLTHROUGH); + } else if (material.key.isOpacityCutoff()) { + obj.setProperty("opacityCutoff", material.opacityCutoff); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::ALBEDO_MAP_BIT)) { - obj.setProperty("albedoMap", FALLTHROUGH); - } else if (!material.albedoMap.isEmpty()) { - obj.setProperty("albedoMap", material.albedoMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OPACITY_MAP_MODE_BIT)) { + obj.setProperty("opacityMapMode", FALLTHROUGH); + } else if (material.key.isOpacityMapMode()) { + obj.setProperty("opacityMapMode", material.opacityMapMode); + } - if (!material.opacityMap.isEmpty()) { - obj.setProperty("opacityMap", material.opacityMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::GLOSSY_VAL_BIT)) { + obj.setProperty("roughness", FALLTHROUGH); + } else if (material.key.isGlossy()) { + obj.setProperty("roughness", material.roughness); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT | graphics::MaterialKey::OPACITY_MASK_MAP_BIT)) { - obj.setProperty("opacityMapMode", FALLTHROUGH); - } else if (material.key.getOpacityMapMode() != graphics::Material::DEFAULT_OPACITY_MAP_MODE) { - obj.setProperty("opacityMapMode", material.opacityMapMode); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::METALLIC_VAL_BIT)) { + obj.setProperty("metallic", FALLTHROUGH); + } else if (material.key.isMetallic()) { + obj.setProperty("metallic", material.metallic); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OPACITY_CUTOFF_VAL_BIT)) { - obj.setProperty("opacityCutoff", FALLTHROUGH); - } else if (material.key.isOpacityCutoff()) { - obj.setProperty("opacityCutoff", material.opacityCutoff); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::SCATTERING_VAL_BIT)) { + obj.setProperty("scattering", FALLTHROUGH); + } else if (material.key.isScattering()) { + obj.setProperty("scattering", material.scattering); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OCCLUSION_MAP_BIT)) { - obj.setProperty("occlusionMap", FALLTHROUGH); - } else if (!material.occlusionMap.isEmpty()) { - obj.setProperty("occlusionMap", material.occlusionMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::UNLIT_VAL_BIT)) { + obj.setProperty("unlit", FALLTHROUGH); + } else if (material.key.isUnlit()) { + obj.setProperty("unlit", material.unlit); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::LIGHT_MAP_BIT)) { - obj.setProperty("lightMap", FALLTHROUGH); - } else if (!material.lightMap.isEmpty()) { - obj.setProperty("lightMap", material.lightMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::EMISSIVE_VAL_BIT)) { + obj.setProperty("emissive", FALLTHROUGH); + } else if (material.key.isEmissive()) { + obj.setProperty("emissive", vec3ColorToScriptValue(engine, material.emissive)); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::SCATTERING_MAP_BIT)) { - obj.setProperty("scatteringMap", FALLTHROUGH); - } else if (!material.scatteringMap.isEmpty()) { - obj.setProperty("scatteringMap", material.scatteringMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::EMISSIVE_MAP_BIT)) { + obj.setProperty("emissiveMap", FALLTHROUGH); + } else if (!material.emissiveMap.isEmpty()) { + obj.setProperty("emissiveMap", material.emissiveMap); + } - // Only set one of each of these - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::METALLIC_MAP_BIT)) { - obj.setProperty("metallicMap", FALLTHROUGH); - } else if (!material.metallicMap.isEmpty()) { - obj.setProperty("metallicMap", material.metallicMap); - } else if (!material.specularMap.isEmpty()) { - obj.setProperty("specularMap", material.specularMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::ALBEDO_MAP_BIT)) { + obj.setProperty("albedoMap", FALLTHROUGH); + } else if (!material.albedoMap.isEmpty()) { + obj.setProperty("albedoMap", material.albedoMap); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::ROUGHNESS_MAP_BIT)) { - obj.setProperty("roughnessMap", FALLTHROUGH); - } else if (!material.roughnessMap.isEmpty()) { - obj.setProperty("roughnessMap", material.roughnessMap); - } else if (!material.glossMap.isEmpty()) { - obj.setProperty("glossMap", material.glossMap); - } + if (!material.opacityMap.isEmpty()) { + obj.setProperty("opacityMap", material.opacityMap); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::NORMAL_MAP_BIT)) { - obj.setProperty("normalMap", FALLTHROUGH); - } else if (!material.normalMap.isEmpty()) { - obj.setProperty("normalMap", material.normalMap); - } else if (!material.bumpMap.isEmpty()) { - obj.setProperty("bumpMap", material.bumpMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OCCLUSION_MAP_BIT)) { + obj.setProperty("occlusionMap", FALLTHROUGH); + } else if (!material.occlusionMap.isEmpty()) { + obj.setProperty("occlusionMap", material.occlusionMap); + } - // These need to be implemented, but set the fallthrough for now - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM0)) { - obj.setProperty("texCoordTransform0", FALLTHROUGH); - } else if (material.texCoordTransforms[0] != mat4()) { - obj.setProperty("texCoordTransform0", mat4toScriptValue(engine, material.texCoordTransforms[0])); - } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM1)) { - obj.setProperty("texCoordTransform1", FALLTHROUGH); - } else if (material.texCoordTransforms[1] != mat4()) { - obj.setProperty("texCoordTransform1", mat4toScriptValue(engine, material.texCoordTransforms[1])); - } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::LIGHTMAP_PARAMS)) { - obj.setProperty("lightmapParams", FALLTHROUGH); - } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::MATERIAL_PARAMS)) { - obj.setProperty("materialParams", FALLTHROUGH); + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::LIGHT_MAP_BIT)) { + obj.setProperty("lightMap", FALLTHROUGH); + } else if (!material.lightMap.isEmpty()) { + obj.setProperty("lightMap", material.lightMap); + } + + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::SCATTERING_MAP_BIT)) { + obj.setProperty("scatteringMap", FALLTHROUGH); + } else if (!material.scatteringMap.isEmpty()) { + obj.setProperty("scatteringMap", material.scatteringMap); + } + + // Only set one of each of these + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::METALLIC_MAP_BIT)) { + obj.setProperty("metallicMap", FALLTHROUGH); + } else if (!material.metallicMap.isEmpty()) { + obj.setProperty("metallicMap", material.metallicMap); + } else if (!material.specularMap.isEmpty()) { + obj.setProperty("specularMap", material.specularMap); + } + + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::ROUGHNESS_MAP_BIT)) { + obj.setProperty("roughnessMap", FALLTHROUGH); + } else if (!material.roughnessMap.isEmpty()) { + obj.setProperty("roughnessMap", material.roughnessMap); + } else if (!material.glossMap.isEmpty()) { + obj.setProperty("glossMap", material.glossMap); + } + + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::NORMAL_MAP_BIT)) { + obj.setProperty("normalMap", FALLTHROUGH); + } else if (!material.normalMap.isEmpty()) { + obj.setProperty("normalMap", material.normalMap); + } else if (!material.bumpMap.isEmpty()) { + obj.setProperty("bumpMap", material.bumpMap); + } + + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM0)) { + obj.setProperty("texCoordTransform0", FALLTHROUGH); + } else if (material.texCoordTransforms[0] != mat4()) { + obj.setProperty("texCoordTransform0", mat4toScriptValue(engine, material.texCoordTransforms[0])); + } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM1)) { + obj.setProperty("texCoordTransform1", FALLTHROUGH); + } else if (material.texCoordTransforms[1] != mat4()) { + obj.setProperty("texCoordTransform1", mat4toScriptValue(engine, material.texCoordTransforms[1])); + } + + // These need to be implemented, but set the fallthrough for now + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::LIGHTMAP_PARAMS)) { + obj.setProperty("lightmapParams", FALLTHROUGH); + } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::MATERIAL_PARAMS)) { + obj.setProperty("materialParams", FALLTHROUGH); + } + + } else if (material.model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) { + obj.setProperty("procedural", material.procedural); } obj.setProperty("defaultFallthrough", material.defaultFallthrough); diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp index bc610108ec..4a56db0d04 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp @@ -23,27 +23,31 @@ scriptable::ScriptableMaterial& scriptable::ScriptableMaterial::operator=(const name = material.name; model = material.model; opacity = material.opacity; - roughness = material.roughness; - metallic = material.metallic; - scattering = material.scattering; - opacityCutoff = material.opacityCutoff; - unlit = material.unlit; - emissive = material.emissive; albedo = material.albedo; - emissiveMap = material.emissiveMap; - albedoMap = material.albedoMap; - opacityMap = material.opacityMap; - metallicMap = material.metallicMap; - specularMap = material.specularMap; - roughnessMap = material.roughnessMap; - glossMap = material.glossMap; - normalMap = material.normalMap; - bumpMap = material.bumpMap; - occlusionMap = material.occlusionMap; - lightMap = material.lightMap; - scatteringMap = material.scatteringMap; - opacityMapMode = material.opacityMapMode; + if (model.toStdString() == graphics::Material::HIFI_PBR) { + opacityCutoff = material.opacityCutoff; + opacityMapMode = material.opacityMapMode; + roughness = material.roughness; + metallic = material.metallic; + scattering = material.scattering; + unlit = material.unlit; + emissive = material.emissive; + emissiveMap = material.emissiveMap; + albedoMap = material.albedoMap; + opacityMap = material.opacityMap; + metallicMap = material.metallicMap; + specularMap = material.specularMap; + roughnessMap = material.roughnessMap; + glossMap = material.glossMap; + normalMap = material.normalMap; + bumpMap = material.bumpMap; + occlusionMap = material.occlusionMap; + lightMap = material.lightMap; + scatteringMap = material.scatteringMap; + } else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) { + procedural = material.procedural; + } defaultFallthrough = material.defaultFallthrough; propertyFallthroughs = material.propertyFallthroughs; @@ -58,77 +62,83 @@ scriptable::ScriptableMaterial::ScriptableMaterial(const graphics::MaterialPoint name = material->getName().c_str(); model = material->getModel().c_str(); opacity = material->getOpacity(); - - opacityMapMode = QString(graphics::MaterialKey::getOpacityMapModeName(material->getOpacityMapMode()).c_str()); - roughness = material->getRoughness(); - metallic = material->getMetallic(); - scattering = material->getScattering(); - opacityCutoff = material->getOpacityCutoff(); - unlit = material->isUnlit(); - emissive = material->getEmissive(); albedo = material->getAlbedo(); + + if (model.toStdString() == graphics::Material::HIFI_PBR) { + opacityCutoff = material->getOpacityCutoff(); + opacityMapMode = QString(graphics::MaterialKey::getOpacityMapModeName(material->getOpacityMapMode()).c_str()); + roughness = material->getRoughness(); + metallic = material->getMetallic(); + scattering = material->getScattering(); + unlit = material->isUnlit(); + emissive = material->getEmissive(); + + auto map = material->getTextureMap(graphics::Material::MapChannel::EMISSIVE_MAP); + if (map && map->getTextureSource()) { + emissiveMap = map->getTextureSource()->getUrl().toString(); + } + + map = material->getTextureMap(graphics::Material::MapChannel::ALBEDO_MAP); + if (map && map->getTextureSource()) { + albedoMap = map->getTextureSource()->getUrl().toString(); + if (map->useAlphaChannel()) { + opacityMap = albedoMap; + } + } + + map = material->getTextureMap(graphics::Material::MapChannel::METALLIC_MAP); + if (map && map->getTextureSource()) { + if (map->getTextureSource()->getType() == image::TextureUsage::Type::METALLIC_TEXTURE) { + metallicMap = map->getTextureSource()->getUrl().toString(); + } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::SPECULAR_TEXTURE) { + specularMap = map->getTextureSource()->getUrl().toString(); + } + } + + map = material->getTextureMap(graphics::Material::MapChannel::ROUGHNESS_MAP); + if (map && map->getTextureSource()) { + if (map->getTextureSource()->getType() == image::TextureUsage::Type::ROUGHNESS_TEXTURE) { + roughnessMap = map->getTextureSource()->getUrl().toString(); + } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::GLOSS_TEXTURE) { + glossMap = map->getTextureSource()->getUrl().toString(); + } + } + + map = material->getTextureMap(graphics::Material::MapChannel::NORMAL_MAP); + if (map && map->getTextureSource()) { + if (map->getTextureSource()->getType() == image::TextureUsage::Type::NORMAL_TEXTURE) { + normalMap = map->getTextureSource()->getUrl().toString(); + } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::BUMP_TEXTURE) { + bumpMap = map->getTextureSource()->getUrl().toString(); + } + } + + map = material->getTextureMap(graphics::Material::MapChannel::OCCLUSION_MAP); + if (map && map->getTextureSource()) { + occlusionMap = map->getTextureSource()->getUrl().toString(); + } + + map = material->getTextureMap(graphics::Material::MapChannel::LIGHT_MAP); + if (map && map->getTextureSource()) { + lightMap = map->getTextureSource()->getUrl().toString(); + } + + map = material->getTextureMap(graphics::Material::MapChannel::SCATTERING_MAP); + if (map && map->getTextureSource()) { + scatteringMap = map->getTextureSource()->getUrl().toString(); + } + + for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) { + texCoordTransforms[i] = material->getTexCoordTransform(i); + } + } else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) { + procedural = material->getProceduralString(); + } + defaultFallthrough = material->getDefaultFallthrough(); propertyFallthroughs = material->getPropertyFallthroughs(); + key = material->getKey(); - - auto map = material->getTextureMap(graphics::Material::MapChannel::EMISSIVE_MAP); - if (map && map->getTextureSource()) { - emissiveMap = map->getTextureSource()->getUrl().toString(); - } - - map = material->getTextureMap(graphics::Material::MapChannel::ALBEDO_MAP); - if (map && map->getTextureSource()) { - albedoMap = map->getTextureSource()->getUrl().toString(); - if (map->useAlphaChannel()) { - opacityMap = albedoMap; - } - } - - map = material->getTextureMap(graphics::Material::MapChannel::METALLIC_MAP); - if (map && map->getTextureSource()) { - if (map->getTextureSource()->getType() == image::TextureUsage::Type::METALLIC_TEXTURE) { - metallicMap = map->getTextureSource()->getUrl().toString(); - } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::SPECULAR_TEXTURE) { - specularMap = map->getTextureSource()->getUrl().toString(); - } - } - - map = material->getTextureMap(graphics::Material::MapChannel::ROUGHNESS_MAP); - if (map && map->getTextureSource()) { - if (map->getTextureSource()->getType() == image::TextureUsage::Type::ROUGHNESS_TEXTURE) { - roughnessMap = map->getTextureSource()->getUrl().toString(); - } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::GLOSS_TEXTURE) { - glossMap = map->getTextureSource()->getUrl().toString(); - } - } - - map = material->getTextureMap(graphics::Material::MapChannel::NORMAL_MAP); - if (map && map->getTextureSource()) { - if (map->getTextureSource()->getType() == image::TextureUsage::Type::NORMAL_TEXTURE) { - normalMap = map->getTextureSource()->getUrl().toString(); - } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::BUMP_TEXTURE) { - bumpMap = map->getTextureSource()->getUrl().toString(); - } - } - - map = material->getTextureMap(graphics::Material::MapChannel::OCCLUSION_MAP); - if (map && map->getTextureSource()) { - occlusionMap = map->getTextureSource()->getUrl().toString(); - } - - map = material->getTextureMap(graphics::Material::MapChannel::LIGHT_MAP); - if (map && map->getTextureSource()) { - lightMap = map->getTextureSource()->getUrl().toString(); - } - - map = material->getTextureMap(graphics::Material::MapChannel::SCATTERING_MAP); - if (map && map->getTextureSource()) { - scatteringMap = map->getTextureSource()->getUrl().toString(); - } - - for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) { - texCoordTransforms[i] = material->getTexCoordTransform(i); - } } } diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index dffc52e29f..d80c3adfbc 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -34,7 +34,6 @@ std::string MaterialKey::getOpacityMapModeName(OpacityMapMode mode) { return names[mode]; } - bool MaterialKey::getOpacityMapModeFromName(const std::string& modeName, MaterialKey::OpacityMapMode& mode) { for (int i = OPACITY_MAP_OPAQUE; i <= OPACITY_MAP_BLEND; i++) { mode = (MaterialKey::OpacityMapMode) i; @@ -45,6 +44,9 @@ bool MaterialKey::getOpacityMapModeFromName(const std::string& modeName, Materia return false; } +const std::string Material::HIFI_PBR { "hifi_pbr" }; +const std::string Material::HIFI_SHADER_SIMPLE { "hifi_shader_simple" }; + Material::Material() { for (int i = 0; i < NUM_TOTAL_FLAGS; i++) { _propertyFallthroughs[i] = false; diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 25ff711c0c..48ab8151c5 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -328,6 +328,7 @@ public: Material(); Material(const Material& material); + virtual ~Material() = default; Material& operator= (const Material& material); const MaterialKey& getKey() const { return _key; } @@ -409,11 +410,19 @@ public: bool getPropertyFallthrough(uint property) { return _propertyFallthroughs[property]; } void setPropertyDoesFallthrough(uint property) { _propertyFallthroughs[property] = true; } + virtual bool isProcedural() const { return false; } + virtual bool isEnabled() const { return true; } + virtual bool isReady() const { return true; } + virtual QString getProceduralString() const { return QString(); } + + static const std::string HIFI_PBR; + static const std::string HIFI_SHADER_SIMPLE; + protected: std::string _name { "" }; private: - std::string _model { "hifi_pbr" }; + std::string _model { HIFI_PBR }; mutable MaterialKey _key { 0 }; // Material properties diff --git a/libraries/model-baker/CMakeLists.txt b/libraries/model-baker/CMakeLists.txt index 6c0f220340..bf75db4750 100644 --- a/libraries/model-baker/CMakeLists.txt +++ b/libraries/model-baker/CMakeLists.txt @@ -1,7 +1,8 @@ set(TARGET_NAME model-baker) setup_hifi_library() -link_hifi_libraries(shared shaders task gpu graphics hfm material-networking) +link_hifi_libraries(shared shaders task gpu graphics hfm procedural) +include_hifi_library_headers(material-networking) include_hifi_library_headers(networking) include_hifi_library_headers(image) include_hifi_library_headers(ktx) diff --git a/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h index 7c94661b28..3e967a7d3f 100644 --- a/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h +++ b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h @@ -18,7 +18,7 @@ #include "Engine.h" #include "BakerTypes.h" -#include +#include class ParseMaterialMappingTask { public: diff --git a/libraries/model-networking/CMakeLists.txt b/libraries/model-networking/CMakeLists.txt index e79d18f779..b71d125586 100644 --- a/libraries/model-networking/CMakeLists.txt +++ b/libraries/model-networking/CMakeLists.txt @@ -1,8 +1,9 @@ set(TARGET_NAME model-networking) setup_hifi_library() -link_hifi_libraries(shared shaders networking graphics fbx material-networking model-baker) +link_hifi_libraries(shared shaders networking graphics fbx procedural model-baker) include_hifi_library_headers(hfm) include_hifi_library_headers(task) include_hifi_library_headers(gpu) include_hifi_library_headers(image) -include_hifi_library_headers(ktx) \ No newline at end of file +include_hifi_library_headers(ktx) +include_hifi_library_headers(material-networking) \ No newline at end of file diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 5b78c18184..615951345f 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -18,7 +18,7 @@ #include #include "FBXSerializer.h" -#include +#include #include #include "ModelLoader.h" diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index d7ce40641d..c1410a6bfc 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -1,17 +1,18 @@ set(TARGET_NAME physics) setup_hifi_library() -link_hifi_libraries(shared task workload fbx entities graphics shaders) +link_hifi_libraries(shared workload entities shaders) include_hifi_library_headers(networking) include_hifi_library_headers(gpu) include_hifi_library_headers(avatars) -include_hifi_library_headers(audio) include_hifi_library_headers(octree) -include_hifi_library_headers(animation) include_hifi_library_headers(material-networking) include_hifi_library_headers(model-networking) +include_hifi_library_headers(procedural) include_hifi_library_headers(image) include_hifi_library_headers(ktx) include_hifi_library_headers(gpu) include_hifi_library_headers(hfm) +include_hifi_library_headers(fbx) +include_hifi_library_headers(graphics) target_bullet() diff --git a/libraries/procedural/CMakeLists.txt b/libraries/procedural/CMakeLists.txt index d08a7aef02..d737d34e95 100644 --- a/libraries/procedural/CMakeLists.txt +++ b/libraries/procedural/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME procedural) setup_hifi_library() -link_hifi_libraries(shared gpu shaders networking graphics material-networking ktx image) +link_hifi_libraries(shared gpu shaders networking graphics material-networking ktx image hfm) diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index ce4fbb2a38..43c6b25dcb 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -29,6 +29,7 @@ Q_LOGGING_CATEGORY(proceduralLog, "hifi.gpu.procedural") // User-data parsing constants static const QString PROCEDURAL_USER_DATA_KEY = "ProceduralEntity"; +static const QString FRAGMENT_URL_KEY = "fragmentShaderURL"; static const QString URL_KEY = "shaderUrl"; static const QString VERSION_KEY = "version"; static const QString UNIFORMS_KEY = "uniforms"; @@ -40,7 +41,7 @@ static const std::string PROCEDURAL_VERSION = "//PROCEDURAL_VERSION"; bool operator==(const ProceduralData& a, const ProceduralData& b) { return ((a.version == b.version) && - (a.shaderUrl == b.shaderUrl) && + (a.fragmentShaderUrl == b.fragmentShaderUrl) && (a.uniforms == b.uniforms) && (a.channels == b.channels)); } @@ -56,7 +57,13 @@ QJsonValue ProceduralData::getProceduralData(const QString& proceduralJson) { return QJsonValue(); } - return doc.object()[PROCEDURAL_USER_DATA_KEY]; + auto object = doc.object(); + auto userDataIt = object.find(PROCEDURAL_USER_DATA_KEY); + if (userDataIt != object.end()) { + return userDataIt.value(); + } + + return object; } ProceduralData ProceduralData::parse(const QString& proceduralData) { @@ -84,11 +91,18 @@ void ProceduralData::parse(const QJsonObject& proceduralData) { } } - auto rawShaderUrl = proceduralData[URL_KEY].toString(); - shaderUrl = DependencyManager::get()->normalizeURL(rawShaderUrl); + { // Fragment shader URL (either fragmentShaderURL or shaderUrl) + auto rawShaderUrl = proceduralData[FRAGMENT_URL_KEY].toString(); + fragmentShaderUrl = DependencyManager::get()->normalizeURL(rawShaderUrl); + + if (fragmentShaderUrl.isEmpty()) { + rawShaderUrl = proceduralData[URL_KEY].toString(); + fragmentShaderUrl = DependencyManager::get()->normalizeURL(rawShaderUrl); + } + } // Empty shader URL isn't valid - if (shaderUrl.isEmpty()) { + if (fragmentShaderUrl.isEmpty()) { return; } @@ -96,12 +110,8 @@ void ProceduralData::parse(const QJsonObject& proceduralData) { channels = proceduralData[CHANNELS_KEY].toArray(); } -// Example -//{ -// "ProceduralEntity": { -// "shaderUrl": "file:///C:/Users/bdavis/Git/hifi/examples/shaders/test.fs", -// } -//} +std::function Procedural::opaqueStencil = [](gpu::StatePointer state) {}; +std::function Procedural::transparentStencil = [](gpu::StatePointer state) {}; Procedural::Procedural() { _opaqueState->setCullMode(gpu::State::CULL_NONE); @@ -109,12 +119,14 @@ Procedural::Procedural() { _opaqueState->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); + opaqueStencil(_opaqueState); _transparentState->setCullMode(gpu::State::CULL_NONE); _transparentState->setDepthTest(true, true, gpu::LESS_EQUAL); _transparentState->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); + transparentStencil(_transparentState); _standardInputsBuffer = std::make_shared(sizeof(StandardInputs), nullptr); } @@ -158,14 +170,14 @@ void Procedural::setProceduralData(const ProceduralData& proceduralData) { } } - if (proceduralData.shaderUrl != _data.shaderUrl) { - _data.shaderUrl = proceduralData.shaderUrl; - const auto& shaderUrl = _data.shaderUrl; + if (proceduralData.fragmentShaderUrl != _data.fragmentShaderUrl) { + _data.fragmentShaderUrl = proceduralData.fragmentShaderUrl; + const auto& shaderUrl = _data.fragmentShaderUrl; _shaderDirty = true; - _networkShader.reset(); - _shaderPath.clear(); - _shaderSource.clear(); + _networkFragmentShader.reset(); + _fragmentShaderPath.clear(); + _fragmentShaderSource.clear(); if (shaderUrl.isEmpty() || !shaderUrl.isValid()) { return; @@ -175,11 +187,11 @@ void Procedural::setProceduralData(const ProceduralData& proceduralData) { if (!QFileInfo(shaderUrl.toLocalFile()).exists()) { return; } - _shaderPath = shaderUrl.toLocalFile(); + _fragmentShaderPath = shaderUrl.toLocalFile(); } else if (shaderUrl.scheme() == URL_SCHEME_QRC) { - _shaderPath = ":" + shaderUrl.path(); + _fragmentShaderPath = ":" + shaderUrl.path(); } else { - _networkShader = ShaderCache::instance().getShader(shaderUrl); + _networkFragmentShader = ShaderCache::instance().getShader(shaderUrl); } } @@ -202,7 +214,7 @@ bool Procedural::isReady() const { } // Do we have a network or local shader, and if so, is it loaded? - if (_shaderPath.isEmpty() && (!_networkShader || !_networkShader->isLoaded())) { + if (_fragmentShaderPath.isEmpty() && (!_networkFragmentShader || !_networkFragmentShader->isLoaded())) { return false; } @@ -232,17 +244,17 @@ void Procedural::prepare(gpu::Batch& batch, _entityPosition = position; _entityOrientation = glm::mat3_cast(orientation); _entityCreated = created; - if (!_shaderPath.isEmpty()) { - auto lastModified = (uint64_t)QFileInfo(_shaderPath).lastModified().toMSecsSinceEpoch(); - if (lastModified > _shaderModified) { - QFile file(_shaderPath); + if (!_fragmentShaderPath.isEmpty()) { + auto lastModified = (uint64_t)QFileInfo(_fragmentShaderPath).lastModified().toMSecsSinceEpoch(); + if (lastModified > _fragmentShaderModified) { + QFile file(_fragmentShaderPath); file.open(QIODevice::ReadOnly); - _shaderSource = QTextStream(&file).readAll(); + _fragmentShaderSource = QTextStream(&file).readAll(); _shaderDirty = true; - _shaderModified = lastModified; + _fragmentShaderModified = lastModified; } - } else if (_shaderSource.isEmpty() && _networkShader && _networkShader->isLoaded()) { - _shaderSource = _networkShader->_source; + } else if (_fragmentShaderSource.isEmpty() && _networkFragmentShader && _networkFragmentShader->isLoaded()) { + _fragmentShaderSource = _networkFragmentShader->_source; _shaderDirty = true; } @@ -253,8 +265,13 @@ void Procedural::prepare(gpu::Batch& batch, auto pipeline = _proceduralPipelines.find(key); bool recompiledShader = false; if (pipeline == _proceduralPipelines.end()) { - if (!_vertexShader) { - _vertexShader = gpu::Shader::createVertex(_vertexSource); + gpu::Shader::Source vertexSource; + if (key.isSkinnedDQ()) { + vertexSource = _vertexSourceSkinnedDQ; + } else if (key.isSkinned()) { + vertexSource = _vertexSourceSkinned; + } else { + vertexSource = _vertexSource; } gpu::Shader::Source& fragmentSource = (key.isTransparent() && _transparentFragmentSource.valid()) ? _transparentFragmentSource : _opaqueFragmentSource; @@ -262,7 +279,7 @@ void Procedural::prepare(gpu::Batch& batch, // Build the fragment shader fragmentSource.replacements.clear(); fragmentSource.replacements[PROCEDURAL_VERSION] = "#define PROCEDURAL_V" + std::to_string(_data.version); - fragmentSource.replacements[PROCEDURAL_BLOCK] = _shaderSource.toStdString(); + fragmentSource.replacements[PROCEDURAL_BLOCK] = _fragmentShaderSource.toStdString(); // Set any userdata specified uniforms (if any) if (!_data.uniforms.empty()) { @@ -287,8 +304,9 @@ void Procedural::prepare(gpu::Batch& batch, // Leave this here for debugging //qCDebug(proceduralLog) << "FragmentShader:\n" << fragmentSource.getSource(shader::Dialect::glsl450, shader::Variant::Mono).c_str(); + gpu::ShaderPointer vertexShader = gpu::Shader::createVertex(vertexSource); gpu::ShaderPointer fragmentShader = gpu::Shader::createPixel(fragmentSource); - gpu::ShaderPointer program = gpu::Shader::createProgram(_vertexShader, fragmentShader); + gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShader, fragmentShader); _proceduralPipelines[key] = gpu::Pipeline::create(program, key.isTransparent() ? _transparentState : _opaqueState); @@ -303,10 +321,12 @@ void Procedural::prepare(gpu::Batch& batch, // FIXME: need to handle forward rendering batch.setPipeline(recompiledShader ? _proceduralPipelines[key] : pipeline->second); - if (_shaderDirty || _uniformsDirty) { + bool recreateUniforms = _shaderDirty || _uniformsDirty || recompiledShader || _prevKey != key; + if (recreateUniforms) { setupUniforms(); } + _prevKey = key; _shaderDirty = _uniformsDirty = false; for (auto lambda : _uniforms) { @@ -341,7 +361,7 @@ void Procedural::setupUniforms() { QJsonValue value = _data.uniforms[key]; if (value.isDouble()) { float v = value.toDouble(); - _uniforms.push_back([=](gpu::Batch& batch) { batch._glUniform1f(slot, v); }); + _uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform1f(slot, v); }); } else if (value.isArray()) { auto valueArray = value.toArray(); switch (valueArray.size()) { @@ -350,13 +370,13 @@ void Procedural::setupUniforms() { case 1: { float v = valueArray[0].toDouble(); - _uniforms.push_back([=](gpu::Batch& batch) { batch._glUniform1f(slot, v); }); + _uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform1f(slot, v); }); break; } case 2: { glm::vec2 v{ valueArray[0].toDouble(), valueArray[1].toDouble() }; - _uniforms.push_back([=](gpu::Batch& batch) { batch._glUniform2f(slot, v.x, v.y); }); + _uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform2f(slot, v.x, v.y); }); break; } @@ -366,7 +386,7 @@ void Procedural::setupUniforms() { valueArray[1].toDouble(), valueArray[2].toDouble(), }; - _uniforms.push_back([=](gpu::Batch& batch) { batch._glUniform3f(slot, v.x, v.y, v.z); }); + _uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform3f(slot, v.x, v.y, v.z); }); break; } @@ -378,7 +398,7 @@ void Procedural::setupUniforms() { valueArray[2].toDouble(), valueArray[3].toDouble(), }; - _uniforms.push_back([=](gpu::Batch& batch) { batch._glUniform4f(slot, v.x, v.y, v.z, v.w); }); + _uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform4f(slot, v.x, v.y, v.z, v.w); }); break; } } @@ -386,7 +406,7 @@ void Procedural::setupUniforms() { slot++; } - _uniforms.push_back([=](gpu::Batch& batch) { + _uniforms.push_back([this](gpu::Batch& batch) { _standardInputs.position = vec4(_entityPosition, 1.0f); // Minimize floating point error by doing an integer division to milliseconds, before the floating point division to seconds auto now = usecTimestampNow(); @@ -422,7 +442,7 @@ void Procedural::setupUniforms() { } _standardInputsBuffer->setSubData(0, _standardInputs); - batch.setUniformBuffer(0, _standardInputsBuffer, 0, sizeof(StandardInputs)); + batch.setUniformBuffer(procedural::slot::buffer::Inputs, _standardInputsBuffer, 0, sizeof(StandardInputs)); }); } @@ -432,3 +452,13 @@ glm::vec4 Procedural::getColor(const glm::vec4& entityColor) const { } return entityColor; } + +void graphics::ProceduralMaterial::initializeProcedural() { + _procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural); + _procedural._vertexSourceSkinned = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural_deformed); + _procedural._vertexSourceSkinnedDQ = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural_deformeddq); + + // FIXME: Setup proper uniform slots and use correct pipelines for forward rendering + _procedural._opaqueFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural); + _procedural._transparentFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural_translucent); +} \ No newline at end of file diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 956cef368f..aac353bf7c 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -21,11 +21,26 @@ #include #include #include +#include "ProceduralMaterialCache.h" using UniformLambdas = std::list>; const size_t MAX_PROCEDURAL_TEXTURE_CHANNELS{ 4 }; +/**jsdoc + * An object containing user-defined uniforms for communicating data to shaders. + * @typedef {object} ProceduralUniforms + */ + +/**jsdoc + * The data used to define a Procedural shader material. + * @typedef {object} ProceduralData + * @property {number} version=1 - The version of the procedural shader. + * @property {string} fragmentShaderURL - A link to a fragment shader. Currently, only GLSL shaders are supported. The shader must implement a different method depending on the version. + * shaderUrl is an alias. + * @property {string[]} channels=[] - An array of input texture URLs. Currently, up to 4 are supported. + * @property {ProceduralUniforms} uniforms={} - A {@link ProceduralUniforms} object containing all the custom uniforms to be passed to the shader. + */ struct ProceduralData { static QJsonValue getProceduralData(const QString& proceduralJson); @@ -34,7 +49,7 @@ struct ProceduralData { // Rendering object descriptions, from userData uint8_t version { 0 }; - QUrl shaderUrl; + QUrl fragmentShaderUrl; QJsonObject uniforms; QJsonArray channels; }; @@ -43,19 +58,23 @@ class ProceduralProgramKey { public: enum FlagBit { IS_TRANSPARENT = 0, + IS_SKINNED, + IS_SKINNED_DQ, + NUM_FLAGS }; - typedef std::bitset Flags; Flags _flags; bool isTransparent() const { return _flags[IS_TRANSPARENT]; } + bool isSkinned() const { return _flags[IS_SKINNED]; } + bool isSkinnedDQ() const { return _flags[IS_SKINNED_DQ]; } - ProceduralProgramKey(bool transparent = false) { - if (transparent) { - _flags.set(IS_TRANSPARENT); - } + ProceduralProgramKey(bool transparent = false, bool isSkinned = false, bool isSkinnedDQ = false) { + _flags.set(IS_TRANSPARENT, transparent); + _flags.set(IS_SKINNED, isSkinned); + _flags.set(IS_SKINNED_DQ, isSkinnedDQ); } }; namespace std { @@ -92,12 +111,16 @@ public: void setDoesFade(bool doesFade) { _doesFade = doesFade; } gpu::Shader::Source _vertexSource; + gpu::Shader::Source _vertexSourceSkinned; + gpu::Shader::Source _vertexSourceSkinnedDQ; gpu::Shader::Source _opaqueFragmentSource; gpu::Shader::Source _transparentFragmentSource; gpu::StatePointer _opaqueState { std::make_shared() }; gpu::StatePointer _transparentState { std::make_shared() }; + static std::function opaqueStencil; + static std::function transparentStencil; protected: // DO NOT TOUCH @@ -134,10 +157,10 @@ protected: int32_t _frameCount { 0 }; // Rendering object descriptions, from userData - QString _shaderSource; - QString _shaderPath; - uint64_t _shaderModified { 0 }; - NetworkShaderPointer _networkShader; + QString _fragmentShaderSource; + QString _fragmentShaderPath; + uint64_t _fragmentShaderModified { 0 }; + NetworkShaderPointer _networkFragmentShader; bool _shaderDirty { true }; bool _uniformsDirty { true }; @@ -147,8 +170,6 @@ protected: std::unordered_map _proceduralPipelines; - gpu::ShaderPointer _vertexShader; - StandardInputs _standardInputs; gpu::BufferPointer _standardInputsBuffer; @@ -165,5 +186,41 @@ private: mutable bool _hasStartedFade { false }; mutable bool _isFading { false }; bool _doesFade { true }; + ProceduralProgramKey _prevKey; mutable std::mutex _mutex; }; + +namespace graphics { + +class ProceduralMaterial : public NetworkMaterial { +public: + ProceduralMaterial() : NetworkMaterial() { initializeProcedural(); } + ProceduralMaterial(const NetworkMaterial& material) : NetworkMaterial(material) { initializeProcedural(); } + + bool isProcedural() const override { return true; } + bool isEnabled() const override { return _procedural.isEnabled(); } + bool isReady() const override { return _procedural.isReady(); } + QString getProceduralString() const override { return _proceduralString; } + + void setProceduralData(const QString& data) { + _proceduralString = data; + _procedural.setProceduralData(ProceduralData::parse(data)); + } + glm::vec4 getColor(const glm::vec4& color) const { return _procedural.getColor(color); } + bool isFading() const { return _procedural.isFading(); } + void setIsFading(bool isFading) { _procedural.setIsFading(isFading); } + uint64_t getFadeStartTime() const { return _procedural.getFadeStartTime(); } + void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, + const uint64_t& created, const ProceduralProgramKey key = ProceduralProgramKey()) { + _procedural.prepare(batch, position, size, orientation, created, key); + } + + void initializeProcedural(); + +private: + QString _proceduralString; + Procedural _procedural; +}; +typedef std::shared_ptr ProceduralMaterialPointer; + +} \ No newline at end of file diff --git a/libraries/procedural/src/procedural/ProceduralCommon.slh b/libraries/procedural/src/procedural/ProceduralCommon.slh index 6e73534440..2915f096e6 100644 --- a/libraries/procedural/src/procedural/ProceduralCommon.slh +++ b/libraries/procedural/src/procedural/ProceduralCommon.slh @@ -24,7 +24,7 @@ LAYOUT(binding=PROCEDURAL_TEXTURE_CHANNEL3) uniform sampler2D iChannel3; // comptability with existing procedural shaders that previously relied on these // inputs as uniforms, not members of a UBO -LAYOUT_STD140(binding=0) uniform standardInputsBuffer { +LAYOUT_STD140(binding=PROCEDURAL_BUFFER_INPUTS) uniform standardInputsBuffer { // Offset 0 vec4 date; // Offset 16, acts as vec4 for alignment purposes diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 5e8c6f4865..432e02fe10 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -19,10 +19,12 @@ ProceduralSkybox::ProceduralSkybox(uint64_t created) : graphics::Skybox(), _created(created) { // FIXME: support forward rendering for procedural skyboxes (needs haze calculation) - _procedural._vertexSource = gpu::Shader::createVertex(shader::graphics::vertex::skybox)->getSource(); + _procedural._vertexSource = shader::Source::get(shader::graphics::vertex::skybox); _procedural._opaqueFragmentSource = shader::Source::get(shader::procedural::fragment::proceduralSkybox); - // Adjust the pipeline state for background using the stencil test + _procedural.setDoesFade(false); + + // Adjust the pipeline state for background using the stencil test // Must match PrepareStencil::STENCIL_BACKGROUND const int8_t STENCIL_BACKGROUND = 0; _procedural._opaqueState->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_BACKGROUND, 0xFF, gpu::EQUAL, diff --git a/libraries/procedural/src/procedural/ShaderConstants.h b/libraries/procedural/src/procedural/ShaderConstants.h index cd0d997050..f1336b6479 100644 --- a/libraries/procedural/src/procedural/ShaderConstants.h +++ b/libraries/procedural/src/procedural/ShaderConstants.h @@ -14,17 +14,24 @@ #ifndef PROCEDURAL_SHADER_CONSTANTS_H #define PROCEDURAL_SHADER_CONSTANTS_H +#define PROCEDURAL_BUFFER_INPUTS 7 + #define PROCEDURAL_UNIFORM_CUSTOM 220 -#define PROCEDURAL_TEXTURE_CHANNEL0 0 -#define PROCEDURAL_TEXTURE_CHANNEL1 1 -#define PROCEDURAL_TEXTURE_CHANNEL2 2 -#define PROCEDURAL_TEXTURE_CHANNEL3 3 +#define PROCEDURAL_TEXTURE_CHANNEL0 2 +#define PROCEDURAL_TEXTURE_CHANNEL1 3 +#define PROCEDURAL_TEXTURE_CHANNEL2 4 +#define PROCEDURAL_TEXTURE_CHANNEL3 5 // & clusterMatrices, const std::vector& cauterizedClusterMatrices) { diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.h b/libraries/render-utils/src/CauterizedMeshPartPayload.h index 9a6cea8b9f..f1fe5faa35 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.h +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.h @@ -13,7 +13,7 @@ class CauterizedMeshPartPayload : public ModelMeshPartPayload { public: - CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform); + CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform, const uint64_t& created); // matrix palette skinning void updateClusterBuffer(const std::vector& clusterMatrices, diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 9cdefa0545..7f42b05fa4 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -85,7 +85,7 @@ void CauterizedModel::createRenderItemSet() { // Create the render payloads int numParts = (int)mesh->getNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { - auto ptr = std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset); + auto ptr = std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset, _created); _modelMeshRenderItems << std::static_pointer_cast(ptr); auto material = getGeometry()->getShapeMaterial(shapeID); _modelMeshMaterialNames.push_back(material ? material->getName() : ""); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 1a6e5dbadc..9525d9c105 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -11,15 +11,23 @@ #include "MeshPartPayload.h" +#include + #include #include #include #include "render-utils/ShaderConstants.h" +#include #include "DeferredLightingEffect.h" #include "RenderPipelines.h" +static const QString ENABLE_MESH_SHADERS_STRING { "HIFI_ENABLE_MESH_SHADERS" }; +static bool ENABLE_MESH_SHADERS = QProcessEnvironment::systemEnvironment().contains(ENABLE_MESH_SHADERS_STRING); + +bool MeshPartPayload::enableMeshShaders = false; + using namespace render; namespace render { @@ -49,7 +57,9 @@ template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderAr } } -MeshPartPayload::MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material) { +MeshPartPayload::MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material, const uint64_t& created) : + _created(created) +{ updateMeshPart(mesh, partIndex); addMaterial(graphics::MaterialLayer(material, 0)); } @@ -104,20 +114,30 @@ Item::Bound MeshPartPayload::getBound() const { } ShapeKey MeshPartPayload::getShapeKey() const { - graphics::MaterialKey drawMaterialKey = _drawMaterials.getMaterialKey(); - ShapeKey::Builder builder; - builder.withMaterial(); + graphics::MaterialPointer material = _drawMaterials.empty() ? nullptr : _drawMaterials.top().material; + graphics::MaterialKey drawMaterialKey = _drawMaterials.getMaterialKey(); if (drawMaterialKey.isTranslucent()) { builder.withTranslucent(); } - if (drawMaterialKey.isNormalMap()) { - builder.withTangents(); - } - if (drawMaterialKey.isLightMap()) { - builder.withLightMap(); + + if (material && material->isProcedural() && material->isReady()) { + builder.withOwnPipeline(); + } else { + builder.withMaterial(); + + if (drawMaterialKey.isNormalMap()) { + builder.withTangents(); + } + if (drawMaterialKey.isLightMap()) { + builder.withLightMap(); + } + if (drawMaterialKey.isUnlit()) { + builder.withUnlit(); + } } + return builder.build(); } @@ -153,9 +173,20 @@ void MeshPartPayload::render(RenderArgs* args) { //Bind the index buffer and vertex buffer and Blend shapes if needed bindMesh(batch); - // apply material properties - if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { - args->_details._materialSwitches++; + if (!_drawMaterials.empty() && _drawMaterials.top().material && _drawMaterials.top().material->isProcedural() && + _drawMaterials.top().material->isReady()) { + auto procedural = std::static_pointer_cast(_drawMaterials.top().material); + auto& schema = _drawMaterials.getSchemaBuffer().get(); + glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); + outColor = procedural->getColor(outColor); + procedural->prepare(batch, _drawTransform.getTranslation(), _drawTransform.getScale(), _drawTransform.getRotation(), _created, + ProceduralProgramKey(outColor.a < 1.0f)); + batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); + } else { + // apply material properties + if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { + args->_details._materialSwitches++; + } } // Draw! @@ -196,7 +227,8 @@ template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, Ren } -ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : +ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, + const Transform& transform, const Transform& offsetTransform, const uint64_t& created) : _meshIndex(meshIndex), _shapeID(shapeIndex) { @@ -248,6 +280,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in } #endif + _created = created; } void ModelMeshPartPayload::initCache(const ModelPointer& model) { @@ -350,43 +383,47 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, PrimitiveMode pr RenderPipelines::updateMultiMaterial(_drawMaterials); } + ShapeKey::Builder builder; + graphics::MaterialPointer material = _drawMaterials.empty() ? nullptr : _drawMaterials.top().material; graphics::MaterialKey drawMaterialKey = _drawMaterials.getMaterialKey(); - bool isTranslucent = drawMaterialKey.isTranslucent(); - bool hasTangents = drawMaterialKey.isNormalMap() && _hasTangents; - bool hasLightmap = drawMaterialKey.isLightMap(); - bool isUnlit = drawMaterialKey.isUnlit(); - - bool isDeformed = _isBlendShaped || _isSkinned; bool isWireframe = primitiveMode == PrimitiveMode::LINES; if (isWireframe) { - isTranslucent = hasTangents = hasLightmap = false; - } - - ShapeKey::Builder builder; - builder.withMaterial(); - - if (isTranslucent) { + builder.withWireframe(); + } else if (drawMaterialKey.isTranslucent()) { builder.withTranslucent(); } - if (hasTangents) { - builder.withTangents(); - } - if (hasLightmap) { - builder.withLightMap(); - } - if (isUnlit) { - builder.withUnlit(); - } - if (isDeformed) { + + if (_isSkinned || (_isBlendShaped && _meshBlendshapeBuffer)) { builder.withDeformed(); + if (useDualQuaternionSkinning) { + builder.withDualQuatSkinned(); + } } - if (isWireframe) { - builder.withWireframe(); - } - if (isDeformed && useDualQuaternionSkinning) { - builder.withDualQuatSkinned(); + + if (material && material->isProcedural() && material->isReady()) { + builder.withOwnPipeline(); + } else { + bool hasTangents = drawMaterialKey.isNormalMap() && _hasTangents; + bool hasLightmap = drawMaterialKey.isLightMap(); + bool isUnlit = drawMaterialKey.isUnlit(); + + if (isWireframe) { + hasTangents = hasLightmap = false; + } + + builder.withMaterial(); + + if (hasTangents) { + builder.withTangents(); + } + if (hasLightmap) { + builder.withLightMap(); + } + if (isUnlit) { + builder.withUnlit(); + } } _shapeKey = builder.build(); @@ -432,9 +469,23 @@ void ModelMeshPartPayload::render(RenderArgs* args) { batch.setDrawcallUniform(drawcallInfo); } - // apply material properties - if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { - args->_details._materialSwitches++; + if (!_drawMaterials.empty() && _drawMaterials.top().material && _drawMaterials.top().material->isProcedural() && + _drawMaterials.top().material->isReady()) { + if (!(enableMeshShaders && ENABLE_MESH_SHADERS)) { + return; + } + auto procedural = std::static_pointer_cast(_drawMaterials.top().material); + auto& schema = _drawMaterials.getSchemaBuffer().get(); + glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); + outColor = procedural->getColor(outColor); + procedural->prepare(batch, _drawTransform.getTranslation(), _drawTransform.getScale(), _drawTransform.getRotation(), _created, + ProceduralProgramKey(outColor.a < 1.0f, _shapeKey.isDeformed(), _shapeKey.isDualQuatSkinned())); + batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); + } else { + // apply material properties + if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { + args->_details._materialSwitches++; + } } // Draw! diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 641fc81487..18ef513a87 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -27,7 +27,7 @@ class Model; class MeshPartPayload { public: MeshPartPayload() = default; - MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material); + MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material, const uint64_t& created); virtual ~MeshPartPayload() = default; typedef render::Payload Payload; @@ -73,8 +73,11 @@ public: void addMaterial(graphics::MaterialLayer material); void removeMaterial(graphics::MaterialPointer material); + static bool enableMeshShaders; + protected: render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() }; + uint64_t _created; }; namespace render { @@ -86,7 +89,7 @@ namespace render { class ModelMeshPartPayload : public MeshPartPayload { public: - ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform); + ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform, const uint64_t& created); typedef render::Payload Payload; typedef Payload::DataPointer Pointer; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index a7e098e1b7..3a2e450d4b 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -50,7 +50,7 @@ int normalTypeVecTypeId = qRegisterMetaType>("QVectorgetNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { - _modelMeshRenderItems << std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset); + _modelMeshRenderItems << std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset, _created); auto material = getGeometry()->getShapeMaterial(shapeID); _modelMeshMaterialNames.push_back(material ? material->getName() : ""); _modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i }); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 2ea1f87fae..597fe552f7 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -99,7 +99,7 @@ public: static void setAbstractViewStateInterface(AbstractViewStateInterface* viewState) { _viewState = viewState; } - Model(QObject* parent = nullptr, SpatiallyNestable* spatiallyNestableOverride = nullptr); + Model(QObject* parent = nullptr, SpatiallyNestable* spatiallyNestableOverride = nullptr, uint64_t created = 0); virtual ~Model(); inline ModelPointer getThisPointer() const { @@ -506,6 +506,8 @@ protected: bool shouldInvalidatePayloadShapeKey(int meshIndex); + uint64_t _created; + private: float _loadingPriority { 0.0f }; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 518e43a8ec..2b0d197819 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -675,6 +675,7 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial case graphics::MaterialKey::METALLIC_VAL_BIT: case graphics::MaterialKey::GLOSSY_VAL_BIT: case graphics::MaterialKey::OPACITY_VAL_BIT: + case graphics::MaterialKey::OPACITY_CUTOFF_VAL_BIT: case graphics::MaterialKey::SCATTERING_VAL_BIT: case graphics::Material::TEXCOORDTRANSFORM0: case graphics::Material::TEXCOORDTRANSFORM1: diff --git a/libraries/render-utils/src/render-utils/simple_procedural.slp b/libraries/render-utils/src/render-utils/simple_procedural.slp index 1348d72a8d..219062d50c 100644 --- a/libraries/render-utils/src/render-utils/simple_procedural.slp +++ b/libraries/render-utils/src/render-utils/simple_procedural.slp @@ -1 +1 @@ -DEFINES translucent:f \ No newline at end of file +DEFINES translucent:f deformed:v/deformeddq:v \ No newline at end of file diff --git a/libraries/render-utils/src/simple_procedural.slv b/libraries/render-utils/src/simple_procedural.slv index 181afa50bd..a8d494f72d 100644 --- a/libraries/render-utils/src/simple_procedural.slv +++ b/libraries/render-utils/src/simple_procedural.slv @@ -17,6 +17,16 @@ <@include render-utils/ShaderConstants.h@> +<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@> + <@include MeshDeformer.slh@> + <@if HIFI_USE_DEFORMED@> + <$declareMeshDeformer(1, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> + <@else@> + <$declareMeshDeformer(1, _SCRIBE_NULL, 1, 1, 1)$> + <@endif@> + <$declareMeshDeformerActivation(1, 1)$> +<@endif@> + layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _positionMS; layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normalMS; @@ -25,13 +35,23 @@ layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; void main(void) { - _color = color_sRGBAToLinear(inColor); - _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); - _positionMS = inPosition; - _normalMS = inNormal.xyz; + vec4 positionMS = inPosition; + vec3 normalMS = inNormal.xyz; + +<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@> + evalMeshDeformer(inPosition, positionMS, inNormal.xyz, normalMS, + meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, + meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); +<@endif@> + + _positionMS = positionMS; + _normalMS = normalMS; TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> + <$transformModelToEyeAndClipPos(cam, obj, positionMS, _positionES, gl_Position)$> + <$transformModelToWorldDir(cam, obj, normalMS, _normalWS)$> + + _color = color_sRGBAToLinear(inColor); + _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); } \ No newline at end of file diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 82c408f386..0fefff1c4c 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -17,6 +17,12 @@ if (NOT ANDROID) endif () -link_hifi_libraries(shared networking octree shaders gpu procedural graphics material-networking model-networking ktx recording avatars fbx hfm entities controllers animation audio physics image midi) -# ui includes gl, but link_hifi_libraries does not use transitive includes, so gl must be explicit +link_hifi_libraries(shared networking shaders material-networking model-networking recording avatars fbx entities controllers animation audio midi) include_hifi_library_headers(gl) +include_hifi_library_headers(hfm) +include_hifi_library_headers(gpu) +include_hifi_library_headers(ktx) +include_hifi_library_headers(image) +include_hifi_library_headers(graphics) +include_hifi_library_headers(octree) +include_hifi_library_headers(procedural) \ No newline at end of file diff --git a/libraries/script-engine/src/Quat.cpp b/libraries/script-engine/src/Quat.cpp index afff0a6b03..8335cb9adf 100644 --- a/libraries/script-engine/src/Quat.cpp +++ b/libraries/script-engine/src/Quat.cpp @@ -16,8 +16,6 @@ #include -#include - #include "ScriptEngineLogging.h" #include "ScriptEngine.h" diff --git a/libraries/script-engine/src/SceneScriptingInterface.cpp b/libraries/script-engine/src/SceneScriptingInterface.cpp index 7b36b815fb..90159f8ee6 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.cpp +++ b/libraries/script-engine/src/SceneScriptingInterface.cpp @@ -11,129 +11,6 @@ #include "SceneScriptingInterface.h" -#include - -float SceneScripting::Location::getLongitude() const { - return _skyStage->getOriginLongitude(); -} - -float SceneScripting::Location::getLatitude() const { - return _skyStage->getOriginLatitude(); -} - -float SceneScripting::Location::getAltitude() const { - return _skyStage->getOriginSurfaceAltitude(); -} - -void SceneScripting::Location::setLongitude(float longitude) { - _skyStage->setOriginLongitude(longitude); -} - -void SceneScripting::Location::setLatitude(float latitude) { - _skyStage->setOriginLatitude(latitude); -} - -void SceneScripting::Location::setAltitude(float altitude) { - _skyStage->setOriginSurfaceAltitude(altitude); -} - -void SceneScripting::Time::setHour(float hour) { - _skyStage->setDayTime(hour); -} - -float SceneScripting::Time::getHour() const { - return _skyStage->getDayTime(); -} - -void SceneScripting::Time::setDay(int day) { - _skyStage->setYearTime(day); -} - -int SceneScripting::Time::getDay() const { - return _skyStage->getYearTime(); -} - -glm::vec3 SceneScripting::KeyLight::getColor() const { - return _skyStage->getSunColor(); -} - -void SceneScripting::KeyLight::setColor(const glm::vec3& color) { - _skyStage->setSunColor(color); -} - -float SceneScripting::KeyLight::getIntensity() const { - return _skyStage->getSunIntensity(); -} - -void SceneScripting::KeyLight::setIntensity(float intensity) { - _skyStage->setSunIntensity(intensity); -} - -float SceneScripting::KeyLight::getAmbientIntensity() const { - return _skyStage->getSunAmbientIntensity(); -} - -void SceneScripting::KeyLight::setAmbientIntensity(float intensity) { - _skyStage->setSunAmbientIntensity(intensity); -} - -void SceneScripting::KeyLight::setAmbientSphere(const gpu::SHPointer& sphere) { - _skyStage->setSunAmbientSphere(sphere); -} - -void SceneScripting::KeyLight::setAmbientMap(const gpu::TexturePointer& map) { - _skyStage->setSunAmbientMap(map); -} - - -glm::vec3 SceneScripting::KeyLight::getDirection() const { - return _skyStage->getSunDirection(); -} - -void SceneScripting::KeyLight::setDirection(const glm::vec3& direction) { - _skyStage->setSunDirection(direction); -} - -void SceneScripting::Stage::setOrientation(const glm::quat& orientation) const { - _skyStage->setOriginOrientation(orientation); -} - -void SceneScripting::Stage::setLocation(float longitude, float latitude, float altitude) { - _skyStage->setOriginLocation(longitude, latitude, altitude); -} - -void SceneScripting::Stage::setSunModelEnable(bool isEnabled) { - _skyStage->setSunModelEnable(isEnabled); -} - -bool SceneScripting::Stage::isSunModelEnabled() const { - return _skyStage->isSunModelEnabled(); -} - -void SceneScripting::Stage::setBackgroundMode(const QString& mode) { - if (mode == QString("inherit")) { - _skyStage->setBackgroundMode(graphics::SunSkyStage::NO_BACKGROUND); - } else if (mode == QString("skybox")) { - _skyStage->setBackgroundMode(graphics::SunSkyStage::SKY_BOX); - } -} - -QString SceneScripting::Stage::getBackgroundMode() const { - switch (_skyStage->getBackgroundMode()) { - case graphics::SunSkyStage::NO_BACKGROUND: - return QString("inherit"); - case graphics::SunSkyStage::SKY_BOX: - return QString("skybox"); - default: - return QString("inherit"); - }; -} - -SceneScriptingInterface::SceneScriptingInterface() : _stage{ new SceneScripting::Stage{ _skyStage } } { - // Let's make sure the sunSkyStage is using a proceduralSkybox - _skyStage->setSkybox(graphics::SkyboxPointer(new ProceduralSkybox())); -} - void SceneScriptingInterface::setShouldRenderAvatars(bool shouldRenderAvatars) { if (shouldRenderAvatars != _shouldRenderAvatars) { _shouldRenderAvatars = shouldRenderAvatars; @@ -146,8 +23,4 @@ void SceneScriptingInterface::setShouldRenderEntities(bool shouldRenderEntities) _shouldRenderEntities = shouldRenderEntities; emit shouldRenderEntitiesChanged(_shouldRenderEntities); } -} - -graphics::SunSkyStagePointer SceneScriptingInterface::getSkyStage() const { - return _skyStage; -} +} \ No newline at end of file diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index fa67666676..ce205bdf3c 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -12,183 +12,8 @@ #ifndef hifi_SceneScriptingInterface_h #define hifi_SceneScriptingInterface_h -#include // QObject -#include // Dependency - -#include "graphics/Stage.h" - -// TODO: if QT moc ever supports nested classes, subclass these to the interface instead of namespacing -namespace SceneScripting { - - /**jsdoc - * Stage location. - * @typedef {object} Stage.Location - * @property {number} longitude - Longitude. - * @property {number} latitude - Latitude. - * @property {number} altitude - Altitude. - */ - class Location : public QObject { - Q_OBJECT - - public: - Location(graphics::SunSkyStagePointer skyStage) : _skyStage{ skyStage } {} - - Q_PROPERTY(float longitude READ getLongitude WRITE setLongitude) - Q_PROPERTY(float latitude READ getLatitude WRITE setLatitude) - Q_PROPERTY(float altitude READ getAltitude WRITE setAltitude) - - float getLongitude() const; - float getLatitude() const; - float getAltitude() const; - void setLongitude(float longitude); - void setLatitude(float latitude); - void setAltitude(float altitude); - - protected: - graphics::SunSkyStagePointer _skyStage; - }; - using LocationPointer = std::unique_ptr; - - /**jsdoc - * Stage time. - * @typedef {object} Stage.Time - * @property {number} hour - Hour. - * @property {number} day - Day. - */ - class Time : public QObject { - Q_OBJECT - - public: - Time(graphics::SunSkyStagePointer skyStage) : _skyStage{ skyStage } {} - - Q_PROPERTY(float hour READ getHour WRITE setHour) - Q_PROPERTY(int day READ getDay WRITE setDay) - - float getHour() const; - void setHour(float hour); - int getDay() const; - void setDay(int day); - - protected: - graphics::SunSkyStagePointer _skyStage; - }; - using TimePointer = std::unique_ptr