mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-07 10:02:24 +02:00
Merge pull request #16453 from sabrina-shanman/instancing
Merge master into instancing
This commit is contained in:
commit
28b68b6fce
69 changed files with 2701 additions and 2620 deletions
|
@ -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)
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
@ -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"
|
||||
|
@ -2090,7 +2091,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;
|
||||
|
@ -2099,13 +2100,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();
|
||||
|
@ -7084,10 +7087,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();
|
||||
|
|
|
@ -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::MaterialProceduralShaders, 0, false);
|
||||
connect(action, &QAction::triggered, [action] {
|
||||
MeshPartPayload::enableMaterialProceduralShaders = action->isChecked();
|
||||
});
|
||||
|
||||
{
|
||||
auto drawStatusConfig = qApp->getRenderEngine()->getConfiguration()->getConfig<render::DrawStatus>("RenderMainView.DrawStatus");
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::HighlightTransitions, 0, false,
|
||||
|
|
|
@ -228,6 +228,7 @@ namespace MenuOption {
|
|||
const QString ForceCoarsePicking = "Force Coarse Picking";
|
||||
const QString ComputeBlendshapes = "Compute Blendshapes";
|
||||
const QString HighlightTransitions = "Highlight Transitions";
|
||||
const QString MaterialProceduralShaders = "Enable Procedural Materials";
|
||||
}
|
||||
|
||||
#endif // hifi_Menu_h
|
||||
|
|
|
@ -100,7 +100,7 @@ static const QString USER_RECENTER_MODEL_DISABLE_HMD_LEAN = QStringLiteral("Disa
|
|||
|
||||
const QString HEAD_BLEND_DIRECTIONAL_ALPHA_NAME = "lookAroundAlpha";
|
||||
const QString HEAD_BLEND_LINEAR_ALPHA_NAME = "lookBlendAlpha";
|
||||
const float HEAD_ALPHA_BLENDING = 1.0f;
|
||||
const QString SEATED_HEAD_BLEND_LINEAR_ALPHA_NAME = "seatedLookBlendAlpha";
|
||||
|
||||
const QString POINT_REACTION_NAME = "point";
|
||||
const QString POINT_BLEND_DIRECTIONAL_ALPHA_NAME = "pointAroundAlpha";
|
||||
|
@ -6672,8 +6672,17 @@ glm::vec3 MyAvatar::aimToBlendValues(const glm::vec3& aimVector, const glm::quat
|
|||
|
||||
void MyAvatar::resetHeadLookAt() {
|
||||
if (_skeletonModel->isLoaded()) {
|
||||
_skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, glm::vec3(),
|
||||
HEAD_BLEND_LINEAR_ALPHA_NAME, HEAD_ALPHA_BLENDING);
|
||||
if (isSeated()) {
|
||||
_skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, glm::vec3(),
|
||||
HEAD_BLEND_LINEAR_ALPHA_NAME, 0.0f);
|
||||
_skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, glm::vec3(),
|
||||
SEATED_HEAD_BLEND_LINEAR_ALPHA_NAME, 1.0f);
|
||||
} else {
|
||||
_skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, glm::vec3(),
|
||||
HEAD_BLEND_LINEAR_ALPHA_NAME, 1.0f);
|
||||
_skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, glm::vec3(),
|
||||
SEATED_HEAD_BLEND_LINEAR_ALPHA_NAME, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6686,13 +6695,22 @@ void MyAvatar::resetLookAtRotation(const glm::vec3& avatarPosition, const glm::q
|
|||
resetHeadLookAt();
|
||||
}
|
||||
|
||||
void MyAvatar::updateHeadLookAt(float deltaTime) {
|
||||
void MyAvatar::updateHeadLookAt(float deltaTime) {
|
||||
if (_skeletonModel->isLoaded()) {
|
||||
glm::vec3 lookAtTarget = _scriptControlsHeadLookAt ? _lookAtScriptTarget : _lookAtCameraTarget;
|
||||
glm::vec3 aimVector = lookAtTarget - getDefaultEyePosition();
|
||||
glm::vec3 lookAtBlend = MyAvatar::aimToBlendValues(aimVector, getWorldOrientation());
|
||||
_skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, lookAtBlend,
|
||||
HEAD_BLEND_LINEAR_ALPHA_NAME, HEAD_ALPHA_BLENDING);
|
||||
if (isSeated()) {
|
||||
_skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, lookAtBlend,
|
||||
HEAD_BLEND_LINEAR_ALPHA_NAME, 0.0f);
|
||||
_skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, lookAtBlend,
|
||||
SEATED_HEAD_BLEND_LINEAR_ALPHA_NAME, 1.0f);
|
||||
} else {
|
||||
_skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, lookAtBlend,
|
||||
HEAD_BLEND_LINEAR_ALPHA_NAME, 1.0f);
|
||||
_skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, lookAtBlend,
|
||||
SEATED_HEAD_BLEND_LINEAR_ALPHA_NAME, 0.0f);
|
||||
}
|
||||
|
||||
if (_scriptControlsHeadLookAt) {
|
||||
_scriptHeadControlTimer += deltaTime;
|
||||
|
|
|
@ -102,6 +102,16 @@ void setupPreferences() {
|
|||
|
||||
preference->setItems(refreshRateProfiles);
|
||||
preferences->addPreference(preference);
|
||||
|
||||
auto getterMaterialProceduralShaders = []() -> bool {
|
||||
auto menu = Menu::getInstance();
|
||||
return menu->isOptionChecked(MenuOption::MaterialProceduralShaders);
|
||||
};
|
||||
auto setterMaterialProceduralShaders = [](bool value) {
|
||||
auto menu = Menu::getInstance();
|
||||
menu->setIsOptionChecked(MenuOption::MaterialProceduralShaders, value);
|
||||
};
|
||||
preferences->addPreference(new CheckPreference(GRAPHICS_QUALITY, "Enable Procedural Materials", getterMaterialProceduralShaders, setterMaterialProceduralShaders));
|
||||
}
|
||||
{
|
||||
// Expose the Viewport Resolution Scale
|
||||
|
|
|
@ -1187,12 +1187,12 @@ void AudioClient::processWebrtcFarEnd(const int16_t* samples, int numFrames, int
|
|||
const webrtc::StreamConfig streamConfig = webrtc::StreamConfig(sampleRate, numChannels);
|
||||
const int numChunk = (int)streamConfig.num_frames();
|
||||
|
||||
if (sampleRate > WEBRTC_SAMPLE_RATE_MAX) {
|
||||
qCWarning(audioclient) << "WebRTC does not support" << sampleRate << "output sample rate.";
|
||||
return;
|
||||
}
|
||||
if (numChannels > WEBRTC_CHANNELS_MAX) {
|
||||
qCWarning(audioclient) << "WebRTC does not support" << numChannels << "output channels.";
|
||||
static int32_t lastWarningHash = 0;
|
||||
if (sampleRate > WEBRTC_SAMPLE_RATE_MAX || numChannels > WEBRTC_CHANNELS_MAX) {
|
||||
if (lastWarningHash != ((sampleRate << 8) | numChannels)) {
|
||||
lastWarningHash = ((sampleRate << 8) | numChannels);
|
||||
qCWarning(audioclient) << "AEC not unsupported for output format: sampleRate =" << sampleRate << "numChannels =" << numChannels;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1227,18 +1227,14 @@ void AudioClient::processWebrtcFarEnd(const int16_t* samples, int numFrames, int
|
|||
void AudioClient::processWebrtcNearEnd(int16_t* samples, int numFrames, int numChannels, int sampleRate) {
|
||||
|
||||
const webrtc::StreamConfig streamConfig = webrtc::StreamConfig(sampleRate, numChannels);
|
||||
const int numChunk = (int)streamConfig.num_frames();
|
||||
assert(numFrames == (int)streamConfig.num_frames()); // WebRTC requires exactly 10ms of input
|
||||
|
||||
if (sampleRate > WEBRTC_SAMPLE_RATE_MAX) {
|
||||
qCWarning(audioclient) << "WebRTC does not support" << sampleRate << "input sample rate.";
|
||||
return;
|
||||
}
|
||||
if (numChannels > WEBRTC_CHANNELS_MAX) {
|
||||
qCWarning(audioclient) << "WebRTC does not support" << numChannels << "input channels.";
|
||||
return;
|
||||
}
|
||||
if (numFrames != numChunk) {
|
||||
qCWarning(audioclient) << "WebRTC requires exactly 10ms of input.";
|
||||
static int32_t lastWarningHash = 0;
|
||||
if (sampleRate > WEBRTC_SAMPLE_RATE_MAX || numChannels > WEBRTC_CHANNELS_MAX) {
|
||||
if (lastWarningHash != ((sampleRate << 8) | numChannels)) {
|
||||
lastWarningHash = ((sampleRate << 8) | numChannels);
|
||||
qCWarning(audioclient) << "AEC not unsupported for input format: sampleRate =" << sampleRate << "numChannels =" << numChannels;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include <MaterialEntityItem.h>
|
||||
|
||||
#include <material-networking/MaterialCache.h>
|
||||
#include <procedural/ProceduralMaterialCache.h>
|
||||
|
||||
class NetworkMaterial;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "Engine.h"
|
||||
#include "BakerTypes.h"
|
||||
|
||||
#include <material-networking/MaterialCache.h>
|
||||
#include <procedural/ProceduralMaterialCache.h>
|
||||
|
||||
class ParseMaterialMappingTask {
|
||||
public:
|
||||
|
|
|
@ -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)
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
//
|
||||
// MaterialCacheScriptingInterface.cpp
|
||||
// libraries/mmodel-networking/src/model-networking
|
||||
//
|
||||
// Created by Sam Gateau on 17 September 2019.
|
||||
// Copyright 2019 High Fidelity, Inc.
|
|
@ -1,6 +1,5 @@
|
|||
//
|
||||
// MaterialCacheScriptingInterface.h
|
||||
// libraries/material-networking/src/material-networking
|
||||
// ProceduralMaterialCacheScriptingInterface.h
|
||||
//
|
||||
// Created by Sam Gateau on 17 September 2019.
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
|
@ -10,14 +9,14 @@
|
|||
//
|
||||
#pragma once
|
||||
|
||||
#ifndef hifi_MaterialCacheScriptingInterface_h
|
||||
#define hifi_MaterialCacheScriptingInterface_h
|
||||
#ifndef hifi_ProceduralMaterialCacheScriptingInterface_h
|
||||
#define hifi_ProceduralMaterialCacheScriptingInterface_h
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <ResourceCache.h>
|
||||
|
||||
#include "MaterialCache.h"
|
||||
#include "ProceduralMaterialCache.h"
|
||||
|
||||
class MaterialCacheScriptingInterface : public ScriptableResourceCache, public Dependency {
|
||||
Q_OBJECT
|
||||
|
@ -27,7 +26,7 @@ class MaterialCacheScriptingInterface : public ScriptableResourceCache, public D
|
|||
/**jsdoc
|
||||
* The <code>TextureCache</code> API manages texture cache resources.
|
||||
*
|
||||
* @namespace TextureCache
|
||||
* @namespace MaterialCache
|
||||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
|
@ -48,4 +47,4 @@ public:
|
|||
MaterialCacheScriptingInterface();
|
||||
};
|
||||
|
||||
#endif // hifi_MaterialCacheScriptingInterface_h
|
||||
#endif // hifi_ProceduralMaterialCacheScriptingInterface_h
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include "MaterialCache.h"
|
||||
#include "ProceduralMaterialCache.h"
|
||||
|
||||
#include "QJsonObject"
|
||||
#include "QJsonDocument"
|
||||
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include "RegisteredMetaTypes.h"
|
||||
|
||||
#include "Procedural.h"
|
||||
|
||||
NetworkMaterialResource::NetworkMaterialResource(const QUrl& url) :
|
||||
Resource(url) {}
|
||||
|
||||
|
@ -112,20 +114,22 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
|
|||
* A material used in a {@link Entities.MaterialResource|MaterialResource}.
|
||||
* @typedef {object} Entities.Material
|
||||
* @property {string} model="hifi_pbr" - Different material models support different properties and rendering modes.
|
||||
* Supported models are: <code>"hifi_pbr"</code>.
|
||||
* Supported models are: <code>"hifi_pbr"</code>, <code>"hifi_shader_simple"</code>.
|
||||
* @property {string} name="" - A name for the material. Supported by all material models.
|
||||
* @property {ColorFloat|RGBS|string} emissive - The emissive color, i.e., the color that the material emits. A
|
||||
* {@link ColorFloat} value is treated as sRGB and must have component values in the range <code>0.0</code> –
|
||||
* <code>1.0</code>. A {@link RGBS} value can be either RGB or sRGB.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {number|string} opacity=1.0 - The opacity, range <code>0.0</code> – <code>1.0</code>.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {number|string} opacity=1.0 - The opacity, range <code>0.0</code> – <code>1.0</code>.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> and
|
||||
* <code>"hifi_shader_simple"</code> models only.
|
||||
* @property {boolean|string} unlit=false - <code>true</code> if the material is unaffected by lighting, <code>false</code> if
|
||||
* it is lit by the key light and local lights.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {ColorFloat|RGBS|string} albedo - The albedo color. A {@link ColorFloat} value is treated as sRGB and must have
|
||||
* component values in the range <code>0.0</code> – <code>1.0</code>. A {@link RGBS} value can be either RGB or sRGB.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {ColorFloat|RGBS|string} albedo - The albedo color. A {@link ColorFloat} value is treated as sRGB and must have
|
||||
* component values in the range <code>0.0</code> – <code>1.0</code>. A {@link RGBS} value can be either RGB or sRGB.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> and
|
||||
* <code>"hifi_shader_simple"</code> models only.
|
||||
* @property {number|string} roughness - The roughness, range <code>0.0</code> – <code>1.0</code>.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {number|string} metallic - The metallicness, range <code>0.0</code> – <code>1.0</code>.
|
||||
|
@ -183,25 +187,25 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
|
|||
* <p><em>Currently not used.</em></p>
|
||||
* @property {boolean} defaultFallthrough=false - <code>true</code> if all properties fall through to the material below
|
||||
* unless they are set, <code>false</code> if properties respect their individual fall-through settings.
|
||||
* <code>"hifi_pbr"</code> model only.
|
||||
* <code>"hifi_pbr"</code> and <code>"hifi_shader_simple"</code> models only.
|
||||
* @property {ProceduralData} procedural - The definition of a procedural shader material. <code>"hifi_shader_simple"</code> model only.
|
||||
*/
|
||||
// Note: See MaterialEntityItem.h for default values used in practice.
|
||||
std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource::parseJSONMaterial(const QJsonObject& materialJSON, const QUrl& baseUrl) {
|
||||
std::string name = "";
|
||||
std::shared_ptr<NetworkMaterial> material = std::make_shared<NetworkMaterial>();
|
||||
std::shared_ptr<NetworkMaterial> networkMaterial;
|
||||
|
||||
const std::string HIFI_PBR = "hifi_pbr";
|
||||
std::string modelString = HIFI_PBR;
|
||||
std::string modelString = graphics::Material::HIFI_PBR;
|
||||
auto modelJSONIter = materialJSON.find("model");
|
||||
if (modelJSONIter != materialJSON.end() && modelJSONIter.value().isString()) {
|
||||
modelString = modelJSONIter.value().toString().toStdString();
|
||||
material->setModel(modelString);
|
||||
}
|
||||
|
||||
std::array<glm::mat4, graphics::Material::NUM_TEXCOORD_TRANSFORMS> texcoordTransforms;
|
||||
|
||||
if (modelString == HIFI_PBR) {
|
||||
const QString FALLTHROUGH("fallthrough");
|
||||
const QString FALLTHROUGH("fallthrough");
|
||||
if (modelString == graphics::Material::HIFI_PBR) {
|
||||
auto material = std::make_shared<NetworkMaterial>();
|
||||
for (auto& key : materialJSON.keys()) {
|
||||
if (key == "name") {
|
||||
auto nameJSON = materialJSON.value(key);
|
||||
|
@ -209,11 +213,6 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
|||
name = nameJSON.toString().toStdString();
|
||||
material->setName(name);
|
||||
}
|
||||
} else if (key == "model") {
|
||||
auto modelJSON = materialJSON.value(key);
|
||||
if (modelJSON.isString()) {
|
||||
material->setModel(modelJSON.toString().toStdString());
|
||||
}
|
||||
} else if (key == "emissive") {
|
||||
auto value = materialJSON.value(key);
|
||||
if (value.isString() && value.toString() == FALLTHROUGH) {
|
||||
|
@ -268,13 +267,15 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
|||
}
|
||||
} else if (key == "opacityMapMode") {
|
||||
auto value = materialJSON.value(key);
|
||||
auto valueString = (value.isString() ? value.toString() : "");
|
||||
if (valueString == FALLTHROUGH) {
|
||||
material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::OPACITY_MAP_MODE_BIT);
|
||||
} else {
|
||||
graphics::MaterialKey::OpacityMapMode mode;
|
||||
if (graphics::MaterialKey::getOpacityMapModeFromName(valueString.toStdString(), mode)) {
|
||||
material->setOpacityMapMode(mode);
|
||||
if (value.isString()) {
|
||||
auto valueString = value.toString();
|
||||
if (valueString == FALLTHROUGH) {
|
||||
material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::OPACITY_MAP_MODE_BIT);
|
||||
} else {
|
||||
graphics::MaterialKey::OpacityMapMode mode;
|
||||
if (graphics::MaterialKey::getOpacityMapModeFromName(valueString.toStdString(), mode)) {
|
||||
material->setOpacityMapMode(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (key == "opacityCutoff") {
|
||||
|
@ -455,17 +456,61 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do this after the texture maps are defined, so it overrides the default transforms
|
||||
for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) {
|
||||
mat4 newTransform = texcoordTransforms[i];
|
||||
if (newTransform != mat4() || newTransform != material->getTexCoordTransform(i)) {
|
||||
material->setTexCoordTransform(i, newTransform);
|
||||
// Do this after the texture maps are defined, so it overrides the default transforms
|
||||
for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) {
|
||||
mat4 newTransform = texcoordTransforms[i];
|
||||
if (newTransform != mat4() || newTransform != material->getTexCoordTransform(i)) {
|
||||
material->setTexCoordTransform(i, newTransform);
|
||||
}
|
||||
}
|
||||
networkMaterial = material;
|
||||
} else if (modelString == graphics::Material::HIFI_SHADER_SIMPLE) {
|
||||
auto material = std::make_shared<graphics::ProceduralMaterial>();
|
||||
for (auto& key : materialJSON.keys()) {
|
||||
if (key == "name") {
|
||||
auto nameJSON = materialJSON.value(key);
|
||||
if (nameJSON.isString()) {
|
||||
name = nameJSON.toString().toStdString();
|
||||
material->setName(name);
|
||||
}
|
||||
} else if (key == "opacity") {
|
||||
auto value = materialJSON.value(key);
|
||||
if (value.isString() && value.toString() == FALLTHROUGH) {
|
||||
material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::OPACITY_VAL_BIT);
|
||||
} else if (value.isDouble()) {
|
||||
material->setOpacity(value.toDouble());
|
||||
}
|
||||
} else if (key == "albedo") {
|
||||
auto value = materialJSON.value(key);
|
||||
if (value.isString() && value.toString() == FALLTHROUGH) {
|
||||
material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::ALBEDO_VAL_BIT);
|
||||
} else {
|
||||
glm::vec3 color;
|
||||
bool isSRGB;
|
||||
bool valid = parseJSONColor(value, color, isSRGB);
|
||||
if (valid) {
|
||||
material->setAlbedo(color, isSRGB);
|
||||
}
|
||||
}
|
||||
} else if (key == "defaultFallthrough") {
|
||||
auto value = materialJSON.value(key);
|
||||
if (value.isBool()) {
|
||||
material->setDefaultFallthrough(value.toBool());
|
||||
}
|
||||
} else if (key == "procedural") {
|
||||
auto value = materialJSON.value(key);
|
||||
material->setProceduralData(QJsonDocument::fromVariant(value.toVariant()).toJson());
|
||||
}
|
||||
}
|
||||
networkMaterial = material;
|
||||
}
|
||||
|
||||
return std::pair<std::string, std::shared_ptr<NetworkMaterial>>(name, material);
|
||||
if (networkMaterial) {
|
||||
networkMaterial->setModel(modelString);
|
||||
}
|
||||
|
||||
return std::pair<std::string, std::shared_ptr<NetworkMaterial>>(name, networkMaterial);
|
||||
}
|
||||
|
||||
NetworkMaterialResourcePointer MaterialCache::getMaterial(const QUrl& url) {
|
|
@ -14,7 +14,7 @@
|
|||
#include <graphics/Material.h>
|
||||
#include <hfm/HFM.h>
|
||||
|
||||
#include "TextureCache.h"
|
||||
#include <material-networking/TextureCache.h>
|
||||
|
||||
class NetworkMaterial : public graphics::Material {
|
||||
public:
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
|
||||
using namespace render;
|
||||
|
||||
CauterizedMeshPartPayload::CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform)
|
||||
: ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform) {}
|
||||
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) {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
class CauterizedMeshPartPayload : public ModelMeshPartPayload {
|
||||
public:
|
||||
CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform);
|
||||
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,
|
||||
|
|
|
@ -67,7 +67,7 @@ void CauterizedModel::createRenderItemSet() {
|
|||
for (int shapeID = 0; shapeID < (int) shapes.size(); shapeID++) {
|
||||
const auto& shape = shapes[shapeID];
|
||||
|
||||
_modelMeshRenderItems << std::make_shared<CauterizedMeshPartPayload>(shared_from_this(), shape.mesh, shape.meshPart, shapeID, transform);
|
||||
_modelMeshRenderItems << std::make_shared<CauterizedMeshPartPayload>(shared_from_this(), shape.mesh, shape.meshPart, shapeID, transform, offset, _created);
|
||||
|
||||
auto material = getNetworkModel()->getShapeMaterial(shapeID);
|
||||
_modelMeshMaterialNames.push_back(material ? material->getName() : "");
|
||||
|
|
|
@ -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_MATERIAL_PROCEDURAL_SHADERS_STRING { "HIFI_ENABLE_MATERIAL_PROCEDURAL_SHADERS" };
|
||||
static bool ENABLE_MATERIAL_PROCEDURAL_SHADERS = QProcessEnvironment::systemEnvironment().contains(ENABLE_MATERIAL_PROCEDURAL_SHADERS_STRING);
|
||||
|
||||
bool MeshPartPayload::enableMaterialProceduralShaders = 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));
|
||||
}
|
||||
|
@ -108,20 +118,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();
|
||||
}
|
||||
|
||||
|
@ -157,9 +177,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!
|
||||
|
@ -200,7 +231,8 @@ template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, Ren
|
|||
|
||||
}
|
||||
|
||||
ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform) :
|
||||
ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex,
|
||||
const Transform& transform, const Transform& offsetTransform, const uint64_t& created) :
|
||||
_meshIndex(meshIndex),
|
||||
_shapeID(shapeIndex) {
|
||||
|
||||
|
@ -237,6 +269,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in
|
|||
}
|
||||
#endif
|
||||
|
||||
_created = created;
|
||||
}
|
||||
|
||||
void ModelMeshPartPayload::initCache(const ModelPointer& model) {
|
||||
|
@ -335,43 +368,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();
|
||||
|
@ -417,9 +454,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 (!(enableMaterialProceduralShaders && ENABLE_MATERIAL_PROCEDURAL_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!
|
||||
|
|
|
@ -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;
|
||||
|
@ -72,8 +72,11 @@ public:
|
|||
void addMaterial(graphics::MaterialLayer material);
|
||||
void removeMaterial(graphics::MaterialPointer material);
|
||||
|
||||
static bool enableMaterialProceduralShaders;
|
||||
|
||||
protected:
|
||||
render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() };
|
||||
uint64_t _created;
|
||||
};
|
||||
|
||||
namespace render {
|
||||
|
@ -85,7 +88,7 @@ namespace render {
|
|||
|
||||
class ModelMeshPartPayload : public MeshPartPayload {
|
||||
public:
|
||||
ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform);
|
||||
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;
|
||||
|
|
|
@ -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) {
|
||||
|
@ -1497,7 +1498,7 @@ void Model::createRenderItemSet() {
|
|||
for (uint32_t shapeID = 0; shapeID < shapes.size(); shapeID++) {
|
||||
const auto& shape = shapes[shapeID];
|
||||
|
||||
_modelMeshRenderItems << std::make_shared<ModelMeshPartPayload>(shared_from_this(), shape.mesh, shape.meshPart, shapeID, transform);
|
||||
_modelMeshRenderItems << std::make_shared<ModelMeshPartPayload>(shared_from_this(), shape.mesh, shape.meshPart, shapeID, transform, offset, _created);
|
||||
|
||||
auto material = getNetworkModel()->getShapeMaterial(shapeID);
|
||||
_modelMeshMaterialNames.push_back(material ? material->getName() : "");
|
||||
|
|
|
@ -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 {
|
||||
|
@ -518,6 +518,8 @@ protected:
|
|||
|
||||
bool shouldInvalidatePayloadShapeKey(int meshIndex);
|
||||
|
||||
uint64_t _created;
|
||||
|
||||
private:
|
||||
float _loadingPriority { 0.0f };
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -1 +1 @@
|
|||
DEFINES translucent:f
|
||||
DEFINES translucent:f deformed:v/deformeddq:v
|
|
@ -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);
|
||||
}
|
|
@ -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)
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
#include <QDebug>
|
||||
|
||||
#include <OctreeConstants.h>
|
||||
|
||||
#include "ScriptEngineLogging.h"
|
||||
#include "ScriptEngine.h"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 253 KiB |
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
|
@ -1,12 +1,5 @@
|
|||
var customEmojiList = [
|
||||
{
|
||||
"name": "sam",
|
||||
"filename": "sam.png",
|
||||
"keywords": [
|
||||
"sam",
|
||||
"troll"
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
if (module.exports) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <QtCore/QCommandLineParser>
|
||||
#include <QtCore/QUrl>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <image/TextureProcessing.h>
|
||||
#include <TextureBaker.h>
|
||||
|
||||
|
|
Loading…
Reference in a new issue