merging master

This commit is contained in:
milad 2019-11-05 17:30:09 -08:00
parent e08ddf521c
commit c6f7c058bc
58 changed files with 724 additions and 871 deletions

View file

@ -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)

View file

@ -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());

View file

@ -106,7 +106,7 @@
#include <MessagesClient.h>
#include <hfm/ModelFormatRegistry.h>
#include <model-networking/ModelCacheScriptingInterface.h>
#include <material-networking/MaterialCacheScriptingInterface.h>
#include <procedural/MaterialCacheScriptingInterface.h>
#include <material-networking/TextureCacheScriptingInterface.h>
#include <ModelEntityItem.h>
#include <NetworkAccessManager.h>
@ -159,7 +159,8 @@
#include <RenderableEntityItem.h>
#include <RenderableTextEntityItem.h>
#include <RenderableWebEntityItem.h>
#include <material-networking/MaterialCache.h>
#include <StencilMaskPass.h>
#include <procedural/ProceduralMaterialCache.h>
#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<AvatarManager>();
auto avatar = avatarManager->getAvatarBySessionID(avatarID);
auto avatar = static_pointer_cast<Avatar>(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<AvatarManager>();
auto avatar = avatarManager->getAvatarBySessionID(avatarID);
auto avatar = static_pointer_cast<Avatar>(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<SceneScriptingInterface>()->getSkyStage();
skyStage->setBackgroundMode(graphics::SunSkyStage::SKY_DEFAULT);
DependencyManager::get<AnimationCache>()->clearUnusedResources();
DependencyManager::get<SoundCache>()->clearUnusedResources();
DependencyManager::get<MaterialCache>()->clearUnusedResources();

View file

@ -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<ModelBlender>().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<render::DrawStatus>("RenderMainView.DrawStatus");
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::HighlightTransitions, 0, false,

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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;

View file

@ -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)

View file

@ -55,8 +55,6 @@
#include "HeadData.h"
#include "PathUtils.h"
#include <graphics/Material.h>
using AvatarSharedPointer = std::shared_ptr<AvatarData>;
using AvatarWeakPointer = std::weak_ptr<AvatarData>;
using AvatarHash = QHash<QUuid, AvatarSharedPointer>;
@ -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; }

View file

@ -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 {

View file

@ -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)

View file

@ -17,7 +17,7 @@
#include "TextureBaker.h"
#include "baking/TextureFileNamer.h"
#include <material-networking/MaterialCache.h>
#include <procedural/ProceduralMaterialCache.h>
static const QString BAKED_MATERIAL_EXTENSION = ".baked.json";

View file

@ -22,7 +22,7 @@
#include "Baker.h"
#include <material-networking/MaterialCache.h>
#include <graphics/Material.h>
extern const QString BAKED_TEXTURE_KTX_EXT;
extern const QString BAKED_META_TEXTURE_SUFFIX;

View file

@ -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()

View file

@ -11,6 +11,8 @@
#include "RenderPipelines.h"
#include "GeometryCache.h"
#include <procedural/Procedural.h>
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<GeometryCache>()->renderSphere(batch);
// Draw!
DependencyManager::get<GeometryCache>()->renderSphere(batch);
} else {
auto proceduralDrawMaterial = std::static_pointer_cast<graphics::ProceduralMaterial>(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<GeometryCache>()->renderWireSphere(batch, outColor);
} else {
DependencyManager::get<GeometryCache>()->renderSphere(batch, outColor);
}
}
args->_details._trianglesRendered += (int)DependencyManager::get<GeometryCache>()->getSphereTriangleCount();
}

View file

@ -13,7 +13,7 @@
#include <MaterialEntityItem.h>
#include <material-networking/MaterialCache.h>
#include <procedural/ProceduralMaterialCache.h>
class NetworkMaterial;

View file

@ -1316,7 +1316,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
// Check for addition
if (_hasModel && !model) {
model = std::make_shared<Model>(nullptr, entity.get());
model = std::make_shared<Model>(nullptr, entity.get(), _created);
connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate);
connect(model.get(), &Model::setURLFinished, this, [&](bool didVisualGeometryRequestSucceed) {
setKey(didVisualGeometryRequestSucceed);

View file

@ -12,17 +12,11 @@
#include <gpu/Batch.h>
#include <DependencyManager.h>
#include <StencilMaskPass.h>
#include <GeometryCache.h>
#include <PerfStat.h>
#include <shaders/Shaders.h>
#include "RenderPipelines.h"
//#define SHAPE_ENTITY_USE_FADE_EFFECT
#ifdef SHAPE_ENTITY_USE_FADE_EFFECT
#include <FadeEffect.h>
#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<bool>([&] {
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<graphics::ProceduralMaterial>(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<graphics::ProceduralMaterial>(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<graphics::ProceduralMaterial>(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<bool>([&] {
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<bool>([&] {
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<graphics::MultiMaterial::Schema>();
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<graphics::ProceduralMaterial>(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,

View file

@ -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<graphics::Material> _material { std::make_shared<graphics::Material>() };
std::shared_ptr<graphics::ProceduralMaterial> _material { std::make_shared<graphics::ProceduralMaterial>() };
glm::vec3 _color { NAN };
float _alpha;

View file

@ -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)

View file

@ -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;

View file

@ -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

View file

@ -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<uint, bool> propertyFallthroughs; // not actually exposed to script
QString procedural;
graphics::MaterialKey key { 0 };
};

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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;

View file

@ -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

View file

@ -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)

View file

@ -18,7 +18,7 @@
#include "Engine.h"
#include "BakerTypes.h"
#include <material-networking/MaterialCache.h>
#include <procedural/ProceduralMaterialCache.h>
class ParseMaterialMappingTask {
public:

View file

@ -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)
include_hifi_library_headers(ktx)
include_hifi_library_headers(material-networking)

View file

@ -18,7 +18,7 @@
#include <graphics/Asset.h>
#include "FBXSerializer.h"
#include <material-networking/MaterialCache.h>
#include <procedural/ProceduralMaterialCache.h>
#include <material-networking/TextureCache.h>
#include "ModelLoader.h"

View file

@ -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()

View file

@ -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)

View file

@ -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<ResourceManager>()->normalizeURL(rawShaderUrl);
{ // Fragment shader URL (either fragmentShaderURL or shaderUrl)
auto rawShaderUrl = proceduralData[FRAGMENT_URL_KEY].toString();
fragmentShaderUrl = DependencyManager::get<ResourceManager>()->normalizeURL(rawShaderUrl);
if (fragmentShaderUrl.isEmpty()) {
rawShaderUrl = proceduralData[URL_KEY].toString();
fragmentShaderUrl = DependencyManager::get<ResourceManager>()->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<void(gpu::StatePointer)> Procedural::opaqueStencil = [](gpu::StatePointer state) {};
std::function<void(gpu::StatePointer)> 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<gpu::Buffer>(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);
}

View file

@ -21,11 +21,26 @@
#include <gpu/Batch.h>
#include <material-networking/ShaderCache.h>
#include <material-networking/TextureCache.h>
#include "ProceduralMaterialCache.h"
using UniformLambdas = std::list<std::function<void(gpu::Batch& batch)>>;
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.
* <code>shaderUrl</code> 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<NUM_FLAGS> 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::State>() };
gpu::StatePointer _transparentState { std::make_shared<gpu::State>() };
static std::function<void(gpu::StatePointer)> opaqueStencil;
static std::function<void(gpu::StatePointer)> 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<ProceduralProgramKey, gpu::PipelinePointer> _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<ProceduralMaterial> ProceduralMaterialPointer;
}

View file

@ -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

View file

@ -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,

View file

@ -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
// <!
namespace procedural { namespace slot {
namespace buffer {
enum Bufffer {
Inputs = PROCEDURAL_BUFFER_INPUTS,
};
}
namespace uniform {
enum Uniform {

View file

@ -18,8 +18,9 @@
using namespace render;
CauterizedMeshPartPayload::CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform)
: ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform) {}
CauterizedMeshPartPayload::CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex,
const Transform& transform, const Transform& offsetTransform, const uint64_t& created)
: ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform, created) {}
void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector<glm::mat4>& clusterMatrices,
const std::vector<glm::mat4>& cauterizedClusterMatrices) {

View file

@ -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<glm::mat4>& clusterMatrices,

View file

@ -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<CauterizedMeshPartPayload>(shared_from_this(), i, partIndex, shapeID, transform, offset);
auto ptr = std::make_shared<CauterizedMeshPartPayload>(shared_from_this(), i, partIndex, shapeID, transform, offset, _created);
_modelMeshRenderItems << std::static_pointer_cast<ModelMeshPartPayload>(ptr);
auto material = getGeometry()->getShapeMaterial(shapeID);
_modelMeshMaterialNames.push_back(material ? material->getName() : "");

View file

@ -11,15 +11,23 @@
#include "MeshPartPayload.h"
#include <QProcess>
#include <PerfStat.h>
#include <DualQuaternion.h>
#include <graphics/ShaderConstants.h>
#include "render-utils/ShaderConstants.h"
#include <procedural/Procedural.h>
#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<const graphics::Mesh>& mesh, int partIndex, graphics::MaterialPointer material) {
MeshPartPayload::MeshPartPayload(const std::shared_ptr<const graphics::Mesh>& 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<graphics::ProceduralMaterial>(_drawMaterials.top().material);
auto& schema = _drawMaterials.getSchemaBuffer().get<graphics::MultiMaterial::Schema>();
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<graphics::ProceduralMaterial>(_drawMaterials.top().material);
auto& schema = _drawMaterials.getSchemaBuffer().get<graphics::MultiMaterial::Schema>();
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!

View file

@ -27,7 +27,7 @@ class Model;
class MeshPartPayload {
public:
MeshPartPayload() = default;
MeshPartPayload(const std::shared_ptr<const graphics::Mesh>& mesh, int partIndex, graphics::MaterialPointer material);
MeshPartPayload(const std::shared_ptr<const graphics::Mesh>& mesh, int partIndex, graphics::MaterialPointer material, const uint64_t& created);
virtual ~MeshPartPayload() = default;
typedef render::Payload<MeshPartPayload> 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<ModelMeshPartPayload> Payload;
typedef Payload::DataPointer Pointer;

View file

@ -50,7 +50,7 @@ int normalTypeVecTypeId = qRegisterMetaType<QVector<NormalType>>("QVector<Normal
float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f;
#define HTTP_INVALID_COM "http://invalid.com"
Model::Model(QObject* parent, SpatiallyNestable* spatiallyNestableOverride) :
Model::Model(QObject* parent, SpatiallyNestable* spatiallyNestableOverride, uint64_t created) :
QObject(parent),
_renderGeometry(),
_renderWatcher(_renderGeometry),
@ -64,7 +64,8 @@ Model::Model(QObject* parent, SpatiallyNestable* spatiallyNestableOverride) :
_snapModelToRegistrationPoint(false),
_snappedToRegistrationPoint(false),
_url(HTTP_INVALID_COM),
_renderItemKeyGlobalFlags(render::ItemKey::Builder().withVisible().withTagBits(render::hifi::TAG_ALL_VIEWS).build())
_renderItemKeyGlobalFlags(render::ItemKey::Builder().withVisible().withTagBits(render::hifi::TAG_ALL_VIEWS).build()),
_created(created)
{
// we may have been created in the network thread, but we live in the main thread
if (_viewState) {
@ -1488,7 +1489,7 @@ void Model::createRenderItemSet() {
// Create the render payloads
int numParts = (int)mesh->getNumParts();
for (int partIndex = 0; partIndex < numParts; partIndex++) {
_modelMeshRenderItems << std::make_shared<ModelMeshPartPayload>(shared_from_this(), i, partIndex, shapeID, transform, offset);
_modelMeshRenderItems << std::make_shared<ModelMeshPartPayload>(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 });

View file

@ -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 };

View file

@ -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:

View file

@ -1 +1 @@
DEFINES translucent:f
DEFINES translucent:f deformed:v/deformeddq:v

View file

@ -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);
}

View file

@ -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)

View file

@ -16,8 +16,6 @@
#include <QDebug>
#include <OctreeConstants.h>
#include "ScriptEngineLogging.h"
#include "ScriptEngine.h"

View file

@ -11,129 +11,6 @@
#include "SceneScriptingInterface.h"
#include <procedural/ProceduralSkybox.h>
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;
}
}

View file

@ -12,183 +12,8 @@
#ifndef hifi_SceneScriptingInterface_h
#define hifi_SceneScriptingInterface_h
#include <qscriptengine.h> // QObject
#include <DependencyManager.h> // 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<Location>;
/**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<Time>;
/**jsdoc
* Stage key light.
* @typedef {object} Stage.KeyLight
* @property {Vec3} color - Color.
* @property {number} intensity - Intensity.
* @property {number} ambientIntensity - Ambient intensity.
* @property {Vec3} direction - Direction.
*/
class KeyLight : public QObject {
Q_OBJECT
public:
KeyLight(graphics::SunSkyStagePointer skyStage) : _skyStage{ skyStage } {}
Q_PROPERTY(glm::vec3 color READ getColor WRITE setColor)
Q_PROPERTY(float intensity READ getIntensity WRITE setIntensity)
Q_PROPERTY(float ambientIntensity READ getAmbientIntensity WRITE setAmbientIntensity)
Q_PROPERTY(glm::vec3 direction READ getDirection WRITE setDirection)
glm::vec3 getColor() const;
void setColor(const glm::vec3& color);
float getIntensity() const;
void setIntensity(float intensity);
float getAmbientIntensity() const;
void setAmbientIntensity(float intensity);
glm::vec3 getDirection() const;
// setDirection is only effective if stage Sun model is disabled
void setDirection(const glm::vec3& direction);
// AmbientTexture is unscriptable - it must be set through the zone entity
void setAmbientSphere(const gpu::SHPointer& sphere);
void resetAmbientSphere() { setAmbientSphere(nullptr); }
void setAmbientMap(const gpu::TexturePointer& map);
protected:
graphics::SunSkyStagePointer _skyStage;
};
using KeyLightPointer = std::unique_ptr<KeyLight>;
/**jsdoc
* The <code>Stage</code> class is no longer used.
*
* <p>Provided as a property in the {@link Scene} API.</p>
*
* <p class="important">Deprecated: This class is deprecated and will be removed.</p>
*
* @class Stage
*
* @hifi-interface
* @hifi-client-entity
* @hifi-avatar
*
* @property {string} backgroundMode - Background mode.
* <p class="important">Deprecated: This property is deprecated and will be removed.</p>
* @property {Stage.KeyLight} keyLight - Key light.
* <p class="important">Deprecated: This property is deprecated and will be removed.</p>
* @property {Stage.Location} location - Location.
* <p class="important">Deprecated: This property is deprecated and will be removed.</p>
* @property {boolean} sunModel - Sun model.
* <p class="important">Deprecated: This property is deprecated and will be removed.</p>
* @property {Stage.Time} time - Time.
* <p class="important">Deprecated: This property is deprecated and will be removed.</p>
*/
class Stage : public QObject {
Q_OBJECT
public:
Stage(graphics::SunSkyStagePointer skyStage)
: _skyStage{ skyStage },
_location{ new Location{ skyStage } }, _time{ new Time{ skyStage } }, _keyLight{ new KeyLight{ skyStage } }{}
/**jsdoc
* @function Stage.setOrientation
* @param {Quat} orientation - Orientation.
* @deprecated This method is deprecated and will be removed.
*/
Q_INVOKABLE void setOrientation(const glm::quat& orientation) const;
Q_PROPERTY(Location* location READ getLocation)
Location* getLocation() const { return _location.get(); }
/**jsdoc
* @function Stage.setLocation
* @param {number} longitude - Longitude.
* @param {number} latitude - Latitude.
* @param {number} altitude - Altitude.
* @deprecated This method is deprecated and will be removed.
*/
Q_INVOKABLE void setLocation(float longitude, float latitude, float altitude);
Q_PROPERTY(Time* time READ getTime)
Time* getTime() const { return _time.get(); }
Q_PROPERTY(KeyLight* keyLight READ getKeyLight)
KeyLight* getKeyLight() const { return _keyLight.get(); }
// Enable/disable the stage sun model which uses the key light to simulate
// the sun light based on the location of the stage relative to earth and the current time
Q_PROPERTY(bool sunModel READ isSunModelEnabled WRITE setSunModelEnable)
void setSunModelEnable(bool isEnabled);
bool isSunModelEnabled() const;
Q_PROPERTY(QString backgroundMode READ getBackgroundMode WRITE setBackgroundMode)
void setBackgroundMode(const QString& mode);
QString getBackgroundMode() const;
protected:
graphics::SunSkyStagePointer _skyStage;
LocationPointer _location;
TimePointer _time;
KeyLightPointer _keyLight;
};
using StagePointer = std::unique_ptr<Stage>;
};
#include <qscriptengine.h>
#include <DependencyManager.h>
/**jsdoc
* The <code>Scene</code> API provides some control over what is rendered.
@ -202,9 +27,6 @@ namespace SceneScripting {
* @property {boolean} shouldRenderAvatars - <code>true</code> if avatars are rendered, <code>false</code> if they aren't.
* @property {boolean} shouldRenderEntities - <code>true</code> if entities (domain, avatar, and local) are rendered,
* <code>false</code> if they aren't.
* @property {Stage} stage - Stage. <em>Read-only.</em>
* <p class="important">Deprecated: This property is deprecated and will be removed. Use {@link Entities| Zone entities}
* for lighting instead.</p>
*/
class SceneScriptingInterface : public QObject, public Dependency {
Q_OBJECT
@ -218,11 +40,6 @@ public:
void setShouldRenderAvatars(bool shouldRenderAvatars);
void setShouldRenderEntities(bool shouldRenderEntities);
Q_PROPERTY(SceneScripting::Stage* stage READ getStage)
SceneScripting::Stage* getStage() const { return _stage.get(); }
graphics::SunSkyStagePointer getSkyStage() const;
signals:
/**jsdoc
@ -247,14 +64,8 @@ signals:
void shouldRenderEntitiesChanged(bool shouldRenderEntities);
protected:
SceneScriptingInterface();
~SceneScriptingInterface() {};
graphics::SunSkyStagePointer _skyStage = std::make_shared<graphics::SunSkyStage>();
SceneScripting::StagePointer _stage;
bool _shouldRenderAvatars = true;
bool _shouldRenderEntities = true;
bool _shouldRenderAvatars { true };
bool _shouldRenderEntities { true };
};
#endif // hifi_SceneScriptingInterface_h

View file

@ -62,7 +62,8 @@ void MainWindow::restoreGeometry() {
// see http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application
QRect windowGeometry = QGuiApplication::primaryScreen()->availableGeometry();
#if defined(Q_OS_MAC)
windowGeometry.setSize((windowGeometry.size() * 0.5f));
const float MACOS_INITIAL_WINDOW_SCALE = 0.8f;
windowGeometry.setSize((windowGeometry.size() * MACOS_INITIAL_WINDOW_SCALE));
#endif
QRect geometry = _windowGeometry.get(windowGeometry);
#if defined(Q_OS_MAC)

View file

@ -77,7 +77,6 @@
#include <EntityTreeRenderer.h>
#include <AbstractViewStateInterface.h>
#include <AddressManager.h>
#include <SceneScriptingInterface.h>
#include "Camera.hpp"
@ -372,53 +371,7 @@ public:
virtual EntityDynamicPointer factoryBA(EntityItemPointer ownerEntity, QByteArray data) override { return nullptr; }
};
// Background Render Data & rendering functions
class BackgroundRenderData {
public:
typedef render::Payload<BackgroundRenderData> Payload;
typedef Payload::DataPointer Pointer;
static render::ItemID _item; // unique WorldBoxRenderData
};
render::ItemID BackgroundRenderData::_item = 0;
QSharedPointer<FileLogger> logger;
namespace render {
template <>
const ItemKey payloadGetKey(const BackgroundRenderData::Pointer& stuff) {
return ItemKey::Builder::background();
}
template <>
const Item::Bound payloadGetBound(const BackgroundRenderData::Pointer& stuff) {
return Item::Bound();
}
template <>
void payloadRender(const BackgroundRenderData::Pointer& background, RenderArgs* args) {
Q_ASSERT(args->_batch);
gpu::Batch& batch = *args->_batch;
// Background rendering decision
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
auto backgroundMode = skyStage->getBackgroundMode();
switch (backgroundMode) {
case graphics::SunSkyStage::SKY_BOX: {
auto skybox = skyStage->getSkybox();
if (skybox) {
PerformanceTimer perfTimer("skybox");
skybox->render(batch, args->getViewFrustum());
break;
}
}
default:
// this line intentionally left blank
break;
}
}
} // namespace render
OffscreenGLCanvas* _chromiumShareContext{ nullptr };
Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext* context);
@ -468,7 +421,6 @@ public:
DependencyManager::set<AnimationCache>();
DependencyManager::set<ModelBlender>();
DependencyManager::set<PathUtils>();
DependencyManager::set<SceneScriptingInterface>();
DependencyManager::set<TestActionFactory>();
}
@ -856,22 +808,8 @@ private:
getEntities()->update(false);
// The pending changes collecting the changes here
render::Transaction transaction;
// FIXME: Move this out of here!, Background / skybox should be driven by the enityt content just like the other entities
// Background rendering decision
if (!render::Item::isValidID(BackgroundRenderData::_item)) {
auto backgroundRenderData = std::make_shared<BackgroundRenderData>();
auto backgroundRenderPayload = std::make_shared<BackgroundRenderData::Payload>(backgroundRenderData);
BackgroundRenderData::_item = _main3DScene->allocateID();
transaction.resetItem(BackgroundRenderData::_item, backgroundRenderPayload);
}
{
PerformanceTimer perfTimer("SceneProcessTransaction");
_main3DScene->enqueueTransaction(transaction);
_main3DScene->processTransactionQueue();
}
}

View file

@ -2,7 +2,7 @@ set(TARGET_NAME oven)
setup_hifi_project(Widgets Gui Concurrent)
link_hifi_libraries(shared shaders image gpu ktx fbx hfm baking graphics networking material-networking model-baker task)
link_hifi_libraries(shared shaders image gpu ktx fbx hfm baking graphics networking procedural material-networking model-baker task)
setup_memory_debugger()

View file

@ -21,7 +21,7 @@
#include <ResourceManager.h>
#include <ResourceRequestObserver.h>
#include <ResourceCache.h>
#include <material-networking/MaterialCache.h>
#include <procedural/ProceduralMaterialCache.h>
#include <material-networking/TextureCache.h>
#include <hfm/ModelFormatRegistry.h>
#include <FBXSerializer.h>

View file

@ -14,6 +14,8 @@
#include <QtCore/QCommandLineParser>
#include <QtCore/QUrl>
#include <iostream>
#include <image/TextureProcessing.h>
#include <TextureBaker.h>