Merge pull request #8369 from SamGondelman/loadingFade

Loading fade progress
This commit is contained in:
Brad Hefta-Gaub 2016-08-04 15:24:37 -07:00 committed by GitHub
commit 67cf105720
36 changed files with 299 additions and 114 deletions

View file

@ -776,7 +776,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const
{
PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderBevelCornersRect");
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, true, true, true);
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, true);
DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height,
bevelDistance, backgroundColor);
}

View file

@ -47,7 +47,7 @@ void Cube3DOverlay::render(RenderArgs* args) {
auto geometryCache = DependencyManager::get<GeometryCache>();
auto pipeline = args->_pipeline;
if (!pipeline) {
pipeline = _isSolid ? geometryCache->getShapePipeline() : geometryCache->getWireShapePipeline();
pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline();
}
if (_isSolid) {
@ -55,7 +55,7 @@ void Cube3DOverlay::render(RenderArgs* args) {
batch->setModelTransform(transform);
geometryCache->renderSolidCubeInstance(*batch, cubeColor, pipeline);
} else {
geometryCache->bindSimpleProgram(*batch, false, false, true, true);
geometryCache->bindSimpleProgram(*batch, false, false, false, true, true);
if (getIsDashedLine()) {
transform.setScale(1.0f);
batch->setModelTransform(transform);

View file

@ -57,12 +57,12 @@ void Line3DOverlay::render(RenderArgs* args) {
auto geometryCache = DependencyManager::get<GeometryCache>();
if (getIsDashedLine()) {
// TODO: add support for color to renderDashedLine()
geometryCache->bindSimpleProgram(*batch, false, false, true, true);
geometryCache->bindSimpleProgram(*batch, false, false, false, true, true);
geometryCache->renderDashedLine(*batch, _start, _end, colorv4, _geometryCacheID);
} else if (_glow > 0.0f) {
geometryCache->renderGlowLine(*batch, _start, _end, colorv4, _glow, _glowWidth, _geometryCacheID);
} else {
geometryCache->bindSimpleProgram(*batch, false, false, true, true);
geometryCache->bindSimpleProgram(*batch, false, false, false, true, true);
geometryCache->renderLine(*batch, _start, _end, colorv4, _geometryCacheID);
}
}

View file

@ -61,7 +61,7 @@ void Rectangle3DOverlay::render(RenderArgs* args) {
geometryCache->bindSimpleProgram(*batch);
geometryCache->renderQuad(*batch, topLeft, bottomRight, rectangleColor);
} else {
geometryCache->bindSimpleProgram(*batch, false, false, true, true);
geometryCache->bindSimpleProgram(*batch, false, false, false, true, true);
if (getIsDashedLine()) {
glm::vec3 point1(-halfDimensions.x, -halfDimensions.y, 0.0f);
glm::vec3 point2(halfDimensions.x, -halfDimensions.y, 0.0f);

View file

@ -47,7 +47,7 @@ void Shape3DOverlay::render(RenderArgs* args) {
auto geometryCache = DependencyManager::get<GeometryCache>();
auto pipeline = args->_pipeline;
if (!pipeline) {
pipeline = _isSolid ? geometryCache->getShapePipeline() : geometryCache->getWireShapePipeline();
pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline();
}
transform.setScale(dimensions);

View file

@ -46,7 +46,7 @@ void Sphere3DOverlay::render(RenderArgs* args) {
auto geometryCache = DependencyManager::get<GeometryCache>();
auto pipeline = args->_pipeline;
if (!pipeline) {
pipeline = _isSolid ? geometryCache->getShapePipeline() : geometryCache->getWireShapePipeline();
pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline();
}
if (_isSolid) {

View file

@ -19,7 +19,7 @@ namespace render {
if (payload->entity->getType() == EntityTypes::Light) {
return ItemKey::Builder::light();
}
if (payload && payload->entity->getType() == EntityTypes::PolyLine) {
if (payload && payload->entity->isTransparent()) {
return ItemKey::Builder::transparentShape();
}
}

View file

@ -96,8 +96,16 @@ public: \
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override { _renderHelper.removeFromScene(self, scene, pendingChanges); } \
virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); _renderHelper.notifyChanged(); } \
virtual void dimensionsChanged() override { EntityItem::dimensionsChanged(); _renderHelper.notifyChanged(); } \
void checkTransparency() { \
bool transparent = isTransparent(); \
if (transparent != prevIsTransparent) { \
_renderHelper.notifyChanged(); \
prevIsTransparent = transparent; \
} \
} \
private: \
SimpleRenderableEntityItem _renderHelper;
SimpleRenderableEntityItem _renderHelper; \
bool prevIsTransparent { isTransparent() };
#endif // hifi_RenderableEntityItem_h

View file

@ -93,6 +93,9 @@ public:
render::ItemID getMetaRenderItem() { return _myMetaItem; }
// Transparency is handled in ModelMeshPartPayload
bool isTransparent() override { return false; }
private:
QVariantMap parseTexturesToMap(QString textures);
void remapTextures();

View file

@ -167,6 +167,8 @@ void RenderablePolyLineEntityItem::update(const quint64& now) {
}
void RenderablePolyLineEntityItem::render(RenderArgs* args) {
checkTransparency();
QWriteLocker lock(&_quadReadWriteLock);
if (_points.size() < 2 || _normals.size () < 2 || _strokeWidths.size() < 2) {
return;
@ -204,5 +206,7 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) {
batch.setInputFormat(_format);
batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride);
batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime));
batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0);
};

View file

@ -30,7 +30,9 @@ public:
virtual void render(RenderArgs* args) override;
virtual void update(const quint64& now) override;
virtual bool needsToCallUpdate() const override { return true; };
virtual bool needsToCallUpdate() const override { return true; }
bool isTransparent() override { return true; }
SIMPLE_RENDERABLE();
@ -47,7 +49,6 @@ protected:
gpu::BufferView _uniformBuffer;
unsigned int _numVertices;
QVector<glm::vec3> _vertices;
};

View file

@ -596,6 +596,9 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
auto state = std::make_shared<gpu::State>();
state->setCullMode(gpu::State::CULL_BACK);
state->setDepthTest(true, true, gpu::LESS_EQUAL);
state->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);
_pipeline = gpu::Pipeline::create(program, state);
}
@ -642,6 +645,9 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
int voxelVolumeSizeLocation = _pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize");
batch._glUniform3f(voxelVolumeSizeLocation, voxelVolumeSize.x, voxelVolumeSize.y, voxelVolumeSize.z);
int alphaLocation = _pipeline->getProgram()->getUniforms().findLocation("alpha");
batch._glUniform1f(alphaLocation, 0.5f);
batch.drawIndexed(gpu::TRIANGLES, (gpu::uint32)mesh->getNumIndices(), 0);
}

View file

@ -50,7 +50,7 @@ public:
void initializePolyVox();
virtual void somethingChangedNotification() {
virtual void somethingChangedNotification() override {
// This gets called from EnityItem::readEntityDataFromBuffer every time a packet describing
// this entity comes from the entity-server. It gets called even if nothing has actually changed
// (see the comment in EntityItem.cpp). If that gets fixed, this could be used to know if we
@ -58,19 +58,19 @@ public:
// _needsModelReload = true;
}
virtual uint8_t getVoxel(int x, int y, int z);
virtual bool setVoxel(int x, int y, int z, uint8_t toValue);
virtual uint8_t getVoxel(int x, int y, int z) override;
virtual bool setVoxel(int x, int y, int z, uint8_t toValue) override;
void render(RenderArgs* args);
virtual bool supportsDetailedRayIntersection() const { return true; }
void render(RenderArgs* args) override;
virtual bool supportsDetailedRayIntersection() const override { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal,
void** intersectedObject, bool precisionPicking) const;
void** intersectedObject, bool precisionPicking) const override;
virtual void setVoxelData(QByteArray voxelData);
virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize);
virtual void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle);
virtual void setVoxelData(QByteArray voxelData) override;
virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize) override;
virtual void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) override;
glm::vec3 getSurfacePositionAdjustment() const;
glm::mat4 voxelToWorldMatrix() const;
@ -78,45 +78,45 @@ public:
glm::mat4 voxelToLocalMatrix() const;
glm::mat4 localToVoxelMatrix() const;
virtual ShapeType getShapeType() const;
virtual bool shouldBePhysical() const { return !isDead(); }
virtual bool isReadyToComputeShape();
virtual void computeShapeInfo(ShapeInfo& info);
virtual ShapeType getShapeType() const override;
virtual bool shouldBePhysical() const override { return !isDead(); }
virtual bool isReadyToComputeShape() override;
virtual void computeShapeInfo(ShapeInfo& info) override;
virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3& voxelCoords) const;
virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3& worldCoords) const;
virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3& voxelCoords) const;
virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3& localCoords) const;
virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3& voxelCoords) const override;
virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3& worldCoords) const override;
virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3& voxelCoords) const override;
virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3& localCoords) const override;
// coords are in voxel-volume space
virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue);
virtual bool setVoxelInVolume(glm::vec3 position, uint8_t toValue);
virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) override;
virtual bool setVoxelInVolume(glm::vec3 position, uint8_t toValue) override;
// coords are in world-space
virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue);
virtual bool setAll(uint8_t toValue);
virtual bool setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int toValue);
virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue) override;
virtual bool setAll(uint8_t toValue) override;
virtual bool setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int toValue) override;
virtual void setXTextureURL(QString xTextureURL);
virtual void setYTextureURL(QString yTextureURL);
virtual void setZTextureURL(QString zTextureURL);
virtual void setXTextureURL(QString xTextureURL) override;
virtual void setYTextureURL(QString yTextureURL) override;
virtual void setZTextureURL(QString zTextureURL) override;
virtual bool addToScene(EntityItemPointer self,
std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges);
render::PendingChanges& pendingChanges) override;
virtual void removeFromScene(EntityItemPointer self,
std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges);
render::PendingChanges& pendingChanges) override;
virtual void setXNNeighborID(const EntityItemID& xNNeighborID);
virtual void setYNNeighborID(const EntityItemID& yNNeighborID);
virtual void setZNNeighborID(const EntityItemID& zNNeighborID);
virtual void setXNNeighborID(const EntityItemID& xNNeighborID) override;
virtual void setYNNeighborID(const EntityItemID& yNNeighborID) override;
virtual void setZNNeighborID(const EntityItemID& zNNeighborID) override;
virtual void setXPNeighborID(const EntityItemID& xPNeighborID);
virtual void setYPNeighborID(const EntityItemID& yPNeighborID);
virtual void setZPNeighborID(const EntityItemID& zPNeighborID);
virtual void setXPNeighborID(const EntityItemID& xPNeighborID) override;
virtual void setYPNeighborID(const EntityItemID& yPNeighborID) override;
virtual void setZPNeighborID(const EntityItemID& zPNeighborID) override;
virtual void updateRegistrationPoint(const glm::vec3& value);
virtual void updateRegistrationPoint(const glm::vec3& value) override;
void setVoxelsFromData(QByteArray uncompressedData, quint16 voxelXSize, quint16 voxelYSize, quint16 voxelZSize);
void forEachVoxelValue(quint16 voxelXSize, quint16 voxelYSize, quint16 voxelZSize,
@ -131,6 +131,8 @@ public:
void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; }); }
bool isTransparent() override { return true; }
private:
// The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions
// may not match _voxelVolumeSize.
@ -161,7 +163,7 @@ private:
// these are run off the main thread
void decompressVolumeData();
void compressVolumeDataAndSendEditPacket();
virtual void getMesh(); // recompute mesh
virtual void getMesh() override; // recompute mesh
void computeShapeInfoWorker();
// these are cached lookups of _xNNeighborID, _yNNeighborID, _zNNeighborID, _xPNeighborID, _yPNeighborID, _zPNeighborID

View file

@ -40,7 +40,6 @@ static std::array<GeometryCache::Shape, entity::NUM_SHAPES> MAPPING { {
GeometryCache::Cylinder,
} };
RenderableShapeEntityItem::Pointer RenderableShapeEntityItem::baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties) {
Pointer entity = std::make_shared<RenderableShapeEntityItem>(entityID);
entity->setProperties(properties);
@ -72,10 +71,19 @@ void RenderableShapeEntityItem::setUserData(const QString& value) {
}
}
/*bool RenderableShapeEntityItem::isTransparent() {
if (_procedural && _procedural->ready()) {
return Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) < 1.0f;
} else {
return EntityItem::isTransparent();
}
}*/
void RenderableShapeEntityItem::render(RenderArgs* args) {
PerformanceTimer perfTimer("RenderableShapeEntityItem::render");
//Q_ASSERT(getType() == EntityTypes::Shape);
Q_ASSERT(args->_batch);
checkTransparency();
if (!_procedural) {
_procedural.reset(new Procedural(getUserData()));
@ -102,14 +110,17 @@ void RenderableShapeEntityItem::render(RenderArgs* args) {
if (_procedural->ready()) {
_procedural->prepare(batch, getPosition(), getDimensions(), getOrientation());
auto outColor = _procedural->getColor(color);
outColor.a *= Interpolate::calculateFadeRatio(_procedural->getFadeStartTime());
batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a);
DependencyManager::get<GeometryCache>()->renderShape(batch, MAPPING[_shape]);
} else {
// FIXME, support instanced multi-shape rendering using multidraw indirect
DependencyManager::get<GeometryCache>()->renderSolidShapeInstance(batch, MAPPING[_shape], color);
color.a *= Interpolate::calculateFadeRatio(_fadeStartTime);
auto geometryCache = DependencyManager::get<GeometryCache>();
auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
geometryCache->renderSolidShapeInstance(batch, MAPPING[_shape], color, pipeline);
}
static const auto triCount = DependencyManager::get<GeometryCache>()->getShapeTriangleCount(MAPPING[_shape]);
args->_details._trianglesRendered += (int)triCount;
}

View file

@ -21,11 +21,13 @@ public:
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
RenderableShapeEntityItem(const EntityItemID& entityItemID) : ShapeEntityItem(entityItemID) {}
RenderableShapeEntityItem(const EntityItemID& entityItemID) : ShapeEntityItem(entityItemID) { _procedural.reset(nullptr); }
void render(RenderArgs* args) override;
void setUserData(const QString& value) override;
// bool isTransparent() override;
SIMPLE_RENDERABLE();
private:

View file

@ -15,8 +15,6 @@
#include <PerfStat.h>
#include <Transform.h>
#include "RenderableTextEntityItem.h"
#include "GLMHelpers.h"
@ -29,10 +27,13 @@ EntityItemPointer RenderableTextEntityItem::factory(const EntityItemID& entityID
void RenderableTextEntityItem::render(RenderArgs* args) {
PerformanceTimer perfTimer("RenderableTextEntityItem::render");
Q_ASSERT(getType() == EntityTypes::Text);
checkTransparency();
static const float SLIGHTLY_BEHIND = -0.005f;
glm::vec4 textColor = glm::vec4(toGlm(getTextColorX()), 1.0f);
glm::vec4 backgroundColor = glm::vec4(toGlm(getBackgroundColorX()), 1.0f);
float fadeRatio = Interpolate::calculateFadeRatio(_fadeStartTime);
bool transparent = fadeRatio < 1.0f;
glm::vec4 textColor = glm::vec4(toGlm(getTextColorX()), fadeRatio);
glm::vec4 backgroundColor = glm::vec4(toGlm(getBackgroundColorX()), fadeRatio);
glm::vec3 dimensions = getDimensions();
// Render background
@ -62,7 +63,7 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
batch.setModelTransform(transformToTopLeft);
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, true);
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, transparent, false, false, true);
DependencyManager::get<GeometryCache>()->renderQuad(batch, minCorner, maxCorner, backgroundColor);
float scale = _lineHeight / _textRenderer->getFontSize();

View file

@ -164,6 +164,8 @@ bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) {
}
void RenderableWebEntityItem::render(RenderArgs* args) {
checkTransparency();
#ifdef WANT_EXTRA_DEBUGGING
{
gpu::Batch& batch = *args->_batch;
@ -181,6 +183,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) {
if (!buildWebSurface(static_cast<EntityTreeRenderer*>(args->_renderer))) {
return;
}
_fadeStartTime = usecTimestampNow();
#endif
}
@ -207,6 +210,9 @@ void RenderableWebEntityItem::render(RenderArgs* args) {
batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture);
}
float fadeRatio = Interpolate::calculateFadeRatio(_fadeStartTime);
batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio);
DependencyManager::get<GeometryCache>()->bindSimpleSRGBTexturedUnlitNoTexAlphaProgram(batch);
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
}

View file

@ -39,7 +39,7 @@ void main(void) {
vec3 color = varColor.rgb;
packDeferredFragmentTranslucent(
interpolatedNormal * frontCondition,
texel.a,
texel.a * varColor.a,
polyline.color * texel.rgb,
vec3(0.01, 0.01, 0.01),
10.0);

View file

@ -1,7 +1,7 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// model.frag
// polyvox.frag
// fragment shader
//
// Created by Seth Alves on 2015-8-3
@ -23,6 +23,7 @@ uniform sampler2D xMap;
uniform sampler2D yMap;
uniform sampler2D zMap;
uniform vec3 voxelVolumeSize;
uniform float alpha;
void main(void) {
vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz));
@ -41,5 +42,23 @@ void main(void) {
vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x);
vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0);
packDeferredFragment(_normal, 1.0, vec3(diffuse), DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, DEFAULT_OCCLUSION, DEFAULT_SCATTERING);
const float ALPHA_THRESHOLD = 0.999;
if (alpha < ALPHA_THRESHOLD) {
packDeferredFragmentTranslucent(
_normal,
alpha,
vec3(diffuse),
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);
} else {
packDeferredFragment(
_normal,
1.0,
vec3(diffuse),
DEFAULT_ROUGHNESS,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE,
DEFAULT_OCCLUSION,
DEFAULT_SCATTERING);
}
}

View file

@ -26,6 +26,7 @@
#include <Transform.h>
#include <Sound.h>
#include <SpatiallyNestable.h>
#include <Interpolate.h>
#include "EntityItemID.h"
#include "EntityItemPropertiesDefaults.h"
@ -435,6 +436,7 @@ public:
QUuid getOwningAvatarID() const { return _owningAvatarID; }
void setOwningAvatarID(const QUuid& owningAvatarID) { _owningAvatarID = owningAvatarID; }
virtual bool isTransparent() { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; }
protected:
@ -565,7 +567,7 @@ protected:
quint64 _lastUpdatedAngularVelocityTimestamp { 0 };
quint64 _lastUpdatedAccelerationTimestamp { 0 };
quint64 _fadeStartTime { usecTimestampNow() };
};
#endif // hifi_EntityItem_h

View file

@ -184,6 +184,7 @@ bool Procedural::ready() {
// Reset dirty flag after reading _proceduralData, but before releasing lock
// to avoid resetting it after more data is set
_proceduralDataDirty = false;
_fadeStartTime = usecTimestampNow();
}
if (!_enabled) {

View file

@ -42,6 +42,7 @@ public:
const gpu::ShaderPointer& getShader() const { return _shader; }
glm::vec4 getColor(const glm::vec4& entityColor);
quint64 getFadeStartTime() { return _fadeStartTime; }
uint8_t _version { 1 };
@ -106,6 +107,8 @@ private:
void setupUniforms();
void setupChannels(bool shouldCreate);
quint64 _fadeStartTime;
};
#endif

View file

@ -73,6 +73,8 @@ void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3
discard;
}
_fragColor0 = vec4(albedo.rgb, alpha);
_fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
}
<@endif@>

View file

@ -398,14 +398,25 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() {
return INSTANCED_SOLID_STREAM_FORMAT;
}
render::ShapePipelinePointer GeometryCache::_simplePipeline;
render::ShapePipelinePointer GeometryCache::_simpleOpaquePipeline;
render::ShapePipelinePointer GeometryCache::_simpleTransparentPipeline;
render::ShapePipelinePointer GeometryCache::_simpleWirePipeline;
GeometryCache::GeometryCache() :
_nextID(0) {
buildShapes();
GeometryCache::_simplePipeline =
std::make_shared<render::ShapePipeline>(getSimplePipeline(), nullptr,
GeometryCache::_simpleOpaquePipeline =
std::make_shared<render::ShapePipeline>(getSimplePipeline(false, false, true, false), nullptr,
[](const render::ShapePipeline&, gpu::Batch& batch) {
// Set the defaults needed for a simple program
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO,
DependencyManager::get<TextureCache>()->getWhiteTexture());
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING,
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
}
);
GeometryCache::_simpleTransparentPipeline =
std::make_shared<render::ShapePipeline>(getSimplePipeline(false, true, true, false), nullptr,
[](const render::ShapePipeline&, gpu::Batch& batch) {
// Set the defaults needed for a simple program
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO,
@ -1704,6 +1715,7 @@ class SimpleProgramKey {
public:
enum FlagBit {
IS_TEXTURED_FLAG = 0,
IS_TRANSPARENT_FLAG,
IS_CULLED_FLAG,
IS_UNLIT_FLAG,
HAS_DEPTH_BIAS_FLAG,
@ -1713,6 +1725,7 @@ public:
enum Flag {
IS_TEXTURED = (1 << IS_TEXTURED_FLAG),
IS_TRANSPARENT = (1 << IS_TRANSPARENT_FLAG),
IS_CULLED = (1 << IS_CULLED_FLAG),
IS_UNLIT = (1 << IS_UNLIT_FLAG),
HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG),
@ -1722,6 +1735,7 @@ public:
bool isFlag(short flagNum) const { return bool((_flags & flagNum) != 0); }
bool isTextured() const { return isFlag(IS_TEXTURED); }
bool isTransparent() const { return isFlag(IS_TRANSPARENT); }
bool isCulled() const { return isFlag(IS_CULLED); }
bool isUnlit() const { return isFlag(IS_UNLIT); }
bool hasDepthBias() const { return isFlag(HAS_DEPTH_BIAS); }
@ -1732,9 +1746,9 @@ public:
int getRaw() const { return *reinterpret_cast<const int*>(this); }
SimpleProgramKey(bool textured = false, bool culled = true,
SimpleProgramKey(bool textured = false, bool transparent = false, bool culled = true,
bool unlit = false, bool depthBias = false) {
_flags = (textured ? IS_TEXTURED : 0) | (culled ? IS_CULLED : 0) |
_flags = (textured ? IS_TEXTURED : 0) | (transparent ? IS_TRANSPARENT : 0) | (culled ? IS_CULLED : 0) |
(unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0);
}
@ -1781,8 +1795,8 @@ gpu::PipelinePointer GeometryCache::getSimpleSRGBTexturedUnlitNoTexAlphaPipeline
return _simpleSRGBTexturedUnlitNoTexAlphaPipeline;
}
void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, bool unlit, bool depthBiased) {
batch.setPipeline(getSimplePipeline(textured, culled, unlit, depthBiased));
void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool culled, bool unlit, bool depthBiased) {
batch.setPipeline(getSimplePipeline(textured, transparent, culled, unlit, depthBiased));
// If not textured, set a default albedo map
if (!textured) {
@ -1794,8 +1808,8 @@ void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool cul
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
}
gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled, bool unlit, bool depthBiased) {
SimpleProgramKey config { textured, culled, unlit, depthBiased };
gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBiased) {
SimpleProgramKey config { textured, transparent, culled, unlit, depthBiased };
// Compile the shaders
static std::once_flag once;
@ -1831,7 +1845,7 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled
state->setDepthBias(1.0f);
state->setDepthBiasSlopeScale(1.0f);
}
state->setBlendFunction(false,
state->setBlendFunction(config.isTransparent(),
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);

View file

@ -152,16 +152,17 @@ public:
// Bind the pipeline and get the state to render static geometry
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool transparent = false, bool culled = true,
bool unlit = false, bool depthBias = false);
// Get the pipeline to render static geometry
gpu::PipelinePointer getSimplePipeline(bool textured = false, bool culled = true,
gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true,
bool unlit = false, bool depthBias = false);
void bindSimpleSRGBTexturedUnlitNoTexAlphaProgram(gpu::Batch& batch);
gpu::PipelinePointer getSimpleSRGBTexturedUnlitNoTexAlphaPipeline();
render::ShapePipelinePointer getShapePipeline() { return GeometryCache::_simplePipeline; }
render::ShapePipelinePointer getOpaqueShapePipeline() { return GeometryCache::_simpleOpaquePipeline; }
render::ShapePipelinePointer getTransparentShapePipeline() { return GeometryCache::_simpleTransparentPipeline; }
render::ShapePipelinePointer getWireShapePipeline() { return GeometryCache::_simpleWirePipeline; }
// Static (instanced) geometry
@ -169,42 +170,42 @@ public:
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
void renderSolidShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1),
const render::ShapePipelinePointer& pipeline = _simplePipeline);
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
void renderSolidShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec3& color,
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) {
renderSolidShapeInstance(batch, shape, glm::vec4(color, 1.0f), pipeline);
}
void renderWireShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1),
const render::ShapePipelinePointer& pipeline = _simplePipeline);
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
void renderWireShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec3& color,
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) {
renderWireShapeInstance(batch, shape, glm::vec4(color, 1.0f), pipeline);
}
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color,
const render::ShapePipelinePointer& pipeline = _simplePipeline);
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec3& color,
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) {
renderSolidSphereInstance(batch, glm::vec4(color, 1.0f), pipeline);
}
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color,
const render::ShapePipelinePointer& pipeline = _simplePipeline);
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline);
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color,
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) {
renderWireSphereInstance(batch, glm::vec4(color, 1.0f), pipeline);
}
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color,
const render::ShapePipelinePointer& pipeline = _simplePipeline);
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec3& color,
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) {
renderSolidCubeInstance(batch, glm::vec4(color, 1.0f), pipeline);
}
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color,
const render::ShapePipelinePointer& pipeline = _simplePipeline);
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline);
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color,
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) {
renderWireCubeInstance(batch, glm::vec4(color, 1.0f), pipeline);
@ -416,7 +417,8 @@ private:
gpu::ShaderPointer _simpleShader;
gpu::ShaderPointer _unlitShader;
static render::ShapePipelinePointer _simplePipeline;
static render::ShapePipelinePointer _simpleOpaquePipeline;
static render::ShapePipelinePointer _simpleTransparentPipeline;
static render::ShapePipelinePointer _simpleWirePipeline;
gpu::PipelinePointer _glowLinePipeline;
QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;

View file

@ -13,6 +13,8 @@
#include <PerfStat.h>
#include <Interpolate.h>
#include "DeferredLightingEffect.h"
#include "Model.h"
@ -352,7 +354,6 @@ void ModelMeshPartPayload::initCache() {
}
void ModelMeshPartPayload::notifyLocationChanged() {
}
@ -392,6 +393,10 @@ ItemKey ModelMeshPartPayload::getKey() const {
}
}
if (Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f) {
builder.withTransparent();
}
return builder.build();
}
@ -443,7 +448,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const {
}
ShapeKey::Builder builder;
if (isTranslucent) {
if (isTranslucent || Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f) {
builder.withTranslucent();
}
if (hasTangents) {
@ -484,9 +489,9 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const {
batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2));
}
// TODO: Get rid of that extra call
if (!_hasColorAttrib) {
batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
float fadeRatio = Interpolate::calculateFadeRatio(_fadeStartTime);
if (!_hasColorAttrib || fadeRatio < 1.0f) {
batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio);
}
}
@ -517,7 +522,7 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline:
void ModelMeshPartPayload::render(RenderArgs* args) const {
PerformanceTimer perfTimer("ModelMeshPartPayload::render");
if (!_model->_readyWhenAdded || !_model->_isVisible) {
if (!_model->_readyWhenAdded || !_model->_isVisible || !_hasStartedFade) {
return; // bail asap
}

View file

@ -81,6 +81,11 @@ public:
void notifyLocationChanged() override;
void updateTransformForSkinnedMesh(const Transform& transform, const Transform& offsetTransform, const QVector<glm::mat4>& clusterMatrices);
// Entity fade in
void startFade() { _fadeStartTime = usecTimestampNow(); }
bool hasStartedFade() { return _hasStartedFade; }
void setHasStartedFade(bool hasStartedFade) { _hasStartedFade = hasStartedFade; }
// Render Item interface
render::ItemKey getKey() const override;
render::ShapeKey getShapeKey() const override; // shape interface
@ -99,6 +104,10 @@ public:
bool _isSkinned{ false };
bool _isBlendShaped{ false };
private:
quint64 _fadeStartTime { 0 };
bool _hasStartedFade { false };
};
namespace render {

View file

@ -211,6 +211,10 @@ void Model::updateRenderItems() {
render::PendingChanges pendingChanges;
foreach (auto itemID, self->_modelMeshRenderItems.keys()) {
pendingChanges.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, modelMeshOffset, deleteGeometryCounter](ModelMeshPartPayload& data) {
if (!data.hasStartedFade() && data._model && data._model->isLoaded() && data._model->getGeometry()->areTexturesLoaded()) {
data.startFade();
data.setHasStartedFade(true);
}
// Ensure the model geometry was not reset between frames
if (data._model && data._model->isLoaded() && deleteGeometryCounter == data._model->_deleteGeometryCounter) {
// lazy update of cluster matrices used for rendering. We need to update them here, so we can correctly update the bounding box.

View file

@ -48,7 +48,7 @@ void main() {
packDeferredFragmentTranslucent(
normalize(_normal),
a,
a * Color.a,
Color.rgb,
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);

View file

@ -49,11 +49,44 @@ void main(void) {
#endif
if (emissiveAmount > 0.0) {
packDeferredFragmentLightmap(
normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), DEFAULT_METALLIC, specular, specular);
const float ALPHA_THRESHOLD = 0.999;
if (_color.a < ALPHA_THRESHOLD) {
if (emissiveAmount > 0.0) {
// TODO: transparent emissive?
packDeferredFragmentTranslucent(
normal,
_color.a,
diffuse,
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);
} else {
packDeferredFragmentTranslucent(
normal,
_color.a,
diffuse,
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);
}
} else {
packDeferredFragment(
normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), length(specular), DEFAULT_EMISSIVE, DEFAULT_OCCLUSION, DEFAULT_SCATTERING);
if (emissiveAmount > 0.0) {
packDeferredFragmentLightmap(
normal,
1.0,
diffuse,
max(0, 1.0 - shininess / 128.0),
DEFAULT_METALLIC,
specular,
specular);
} else {
packDeferredFragment(
normal,
1.0,
diffuse,
max(0, 1.0 - shininess / 128.0),
length(specular),
DEFAULT_EMISSIVE,
DEFAULT_OCCLUSION,
DEFAULT_SCATTERING);
}
}
}

View file

@ -27,8 +27,18 @@ void main(void) {
vec4 texel = texture(originalTexture, _texCoord0.st);
texel = colorToLinearRGBA(texel);
packDeferredFragmentUnlit(
normalize(_normal),
1.0,
_color.rgb * texel.rgb);
const float ALPHA_THRESHOLD = 0.999;
if (_color.a * texel.a < ALPHA_THRESHOLD) {
packDeferredFragmentTranslucent(
normalize(_normal),
_color.a * texel.a,
_color.rgb * texel.rgb,
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);
} else {
packDeferredFragmentUnlit(
normalize(_normal),
1.0,
_color.rgb * texel.rgb);
}
}

View file

@ -29,13 +29,24 @@ void main(void) {
if (_color.a <= 0.0) {
texel = colorToLinearRGBA(texel);
}
packDeferredFragment(
normalize(_normal.xyz),
texel.a,
_color.rgb * texel.rgb,
DEFAULT_ROUGHNESS,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE,
DEFAULT_OCCLUSION,
DEFAULT_SCATTERING);
const float ALPHA_THRESHOLD = 0.999;
if (_color.a * texel.a < ALPHA_THRESHOLD) {
packDeferredFragmentTranslucent(
normalize(_normal),
_color.a * texel.a,
_color.rgb * texel.rgb,
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);
} else {
packDeferredFragment(
normalize(_normal),
1.0,
_color.rgb * texel.rgb,
DEFAULT_ROUGHNESS,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE,
DEFAULT_OCCLUSION,
DEFAULT_SCATTERING);
}
}

View file

@ -29,8 +29,18 @@ void main(void) {
texel = colorToLinearRGBA(texel);
}
packDeferredFragmentUnlit(
normalize(_normal),
texel.a,
_color.rgb * texel.rgb);
const float ALPHA_THRESHOLD = 0.999;
if (_color.a * texel.a < ALPHA_THRESHOLD) {
packDeferredFragmentTranslucent(
normalize(_normal),
_color.a * texel.a,
_color.rgb * texel.rgb,
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);
} else {
packDeferredFragmentUnlit(
normalize(_normal),
1.0,
_color.rgb * texel.rgb);
}
}

View file

@ -14,6 +14,8 @@
#include <assert.h>
#include <math.h>
#include "NumericalConstants.h"
float Interpolate::bezierInterpolate(float y1, float y2, float y3, float u) {
// https://en.wikipedia.org/wiki/Bezier_curve
assert(0.0f <= u && u <= 1.0f);
@ -58,3 +60,13 @@ float Interpolate::interpolate3Points(float y1, float y2, float y3, float u) {
}
}
}
float Interpolate::calculateFadeRatio(quint64 start) {
const float FADE_TIME = 1.0f;
float t = 2.0f * std::min(((float)(usecTimestampNow() - start)) / ((float)(FADE_TIME * USECS_PER_SECOND)), 1.0f);
float fadeRatio = (t < 1.0f) ? 0.5f * powf(2.0f, 10.0f * (t - 1.0f)) : 0.5f * (-powf(2.0f, -10.0f * (t - 1.0f)) + 2.0f);
// The easing function isn't exactly 1 at t = 2, so we need to scale the whole function up slightly
const float EASING_SCALE = 1.001f;
return std::min(EASING_SCALE * fadeRatio, 1.0f);
}

View file

@ -12,6 +12,8 @@
#ifndef hifi_Interpolate_h
#define hifi_Interpolate_h
#include "SharedUtil.h"
class Interpolate {
public:
@ -22,6 +24,8 @@ public:
// Interpolate at position u [0.0 - 1.0] between y values equally spaced along the x-axis such that the interpolated values
// pass through all three y values. Return value lies wholly within the range of y values passed in.
static float interpolate3Points(float y1, float y2, float y3, float u);
static float calculateFadeRatio(quint64 start);
};
#endif // hifi_Interpolate_h

View file

@ -78,7 +78,7 @@ void FloorTextureTest::renderTest(size_t testId, RenderArgs* args) {
texture->incremementMinMip();
}
geometryCache->bindSimpleProgram(batch, true, true, true);
geometryCache->bindSimpleProgram(batch, true, false, true, true);
batch.setInputBuffer(0, vertexBuffer, 0, sizeof(Vertex));
batch.setInputFormat(vertexFormat);
batch.setIndexBuffer(gpu::UINT16, indexBuffer, 0);