From 0ed868077d23b851aae8dbfb6b370df2f925e2e3 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 3 Nov 2015 10:02:51 -0800 Subject: [PATCH] Added additive blending as option for particle effect --- .../RenderableParticleEffectEntityItem.cpp | 34 +++++++++++++++---- .../src/RenderableParticleEffectEntityItem.h | 6 ++-- .../entities/src/EntityItemProperties.cpp | 10 ++++++ libraries/entities/src/EntityItemProperties.h | 1 + libraries/entities/src/EntityPropertyFlags.h | 1 + .../entities/src/ParticleEffectEntityItem.cpp | 11 +++++- .../entities/src/ParticleEffectEntityItem.h | 9 ++++- 7 files changed, 61 insertions(+), 11 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index bc82159fbd..db0972a180 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -114,8 +114,7 @@ namespace render { } } -gpu::PipelinePointer RenderableParticleEffectEntityItem::_texturedPipeline; -gpu::PipelinePointer RenderableParticleEffectEntityItem::_untexturedPipeline; + EntityItemPointer RenderableParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { return std::make_shared(entityID, properties); @@ -203,8 +202,17 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { // sort particles back to front // NOTE: this is view frustum might be one frame out of date. + auto frustum = AbstractViewStateInterface::instance()->getCurrentViewFrustum(); + // No need to sort if we're doing additive blending + if (_additiveBlending != true) { + ::zSortAxis = frustum->getDirection(); + qSort(particleDetails.begin(), particleDetails.end(), zSort); + } + + + // allocate vertices _vertices.clear(); @@ -307,12 +315,21 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { } void RenderableParticleEffectEntityItem::createPipelines() { + bool writeToDepthBuffer = false; + gpu::State::BlendArg destinationColorBlendArg; + if (_additiveBlending) { + destinationColorBlendArg = gpu::State::ONE; + } + else { + destinationColorBlendArg = gpu::State::INV_SRC_ALPHA; + writeToDepthBuffer = true; + } if (!_untexturedPipeline) { auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setDepthTest(true, writeToDepthBuffer, gpu::LESS_EQUAL); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, - gpu::State::ONE, gpu::State::FACTOR_ALPHA, + destinationColorBlendArg, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); auto vertShader = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(untextured_particle_vert))); auto fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(untextured_particle_frag))); @@ -322,13 +339,18 @@ void RenderableParticleEffectEntityItem::createPipelines() { if (!_texturedPipeline) { auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, false, gpu::LESS_EQUAL); + + + bool writeToDepthBuffer = !_additiveBlending; + qDebug() << "ADDITIVE BLENDING" << _additiveBlending; + state->setDepthTest(true, writeToDepthBuffer, gpu::LESS_EQUAL); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, - gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, + destinationColorBlendArg, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); auto vertShader = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(textured_particle_vert))); auto fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_frag))); auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vertShader, fragShader)); _texturedPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); + } } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 5d69d19026..678f7eb904 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -38,11 +38,11 @@ protected: uint32_t rgba; }; - static void createPipelines(); + void createPipelines(); std::vector _vertices; - static gpu::PipelinePointer _untexturedPipeline; - static gpu::PipelinePointer _texturedPipeline; + gpu::PipelinePointer _untexturedPipeline; + gpu::PipelinePointer _texturedPipeline; render::ScenePointer _scene; NetworkTexturePointer _texture; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 002f1bb527..4f5d256969 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -195,6 +195,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_ALPHA_SPREAD, alphaSpread); CHECK_PROPERTY_CHANGE(PROP_ALPHA_START, alphaStart); CHECK_PROPERTY_CHANGE(PROP_ALPHA_FINISH, alphaFinish); + CHECK_PROPERTY_CHANGE(PROP_ADDITIVE_BLENDING, additiveBlending); CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL); CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL); CHECK_PROPERTY_CHANGE(PROP_VISIBLE, visible); @@ -351,6 +352,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_SPREAD, alphaSpread); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_START, alphaStart); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_FINISH, alphaFinish); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ADDITIVE_BLENDING, additiveBlending); + } // Models only @@ -502,6 +505,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaSpread, float, setAlphaSpread); COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaStart, float, setAlphaStart); COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaFinish, float, setAlphaFinish); + COPY_PROPERTY_FROM_QSCRIPTVALUE(additiveBlending, bool, setAdditiveBlending); COPY_PROPERTY_FROM_QSCRIPTVALUE(modelURL, QString, setModelURL); COPY_PROPERTY_FROM_QSCRIPTVALUE(compoundShapeURL, QString, setCompoundShapeURL); COPY_PROPERTY_FROM_QSCRIPTVALUE(glowLevel, float, setGlowLevel); @@ -650,6 +654,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_ALPHA_SPREAD, AlphaSpread, alphaSpread, float); ADD_PROPERTY_TO_MAP(PROP_ALPHA_START, AlphaStart, alphaStart, float); ADD_PROPERTY_TO_MAP(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float); + ADD_PROPERTY_TO_MAP(PROP_ADDITIVE_BLENDING, AdditiveBlending, additiveBlending, bool); ADD_PROPERTY_TO_MAP(PROP_MODEL_URL, ModelURL, modelURL, QString); ADD_PROPERTY_TO_MAP(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString); ADD_PROPERTY_TO_MAP(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, glm::vec3); @@ -959,6 +964,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, properties.getAlphaSpread()); APPEND_ENTITY_PROPERTY(PROP_ALPHA_START, properties.getAlphaStart()); APPEND_ENTITY_PROPERTY(PROP_ALPHA_FINISH, properties.getAlphaFinish()); + APPEND_ENTITY_PROPERTY(PROP_ADDITIVE_BLENDING, properties.getAdditiveBlending()); } if (properties.getType() == EntityTypes::Zone) { @@ -1241,6 +1247,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_SPREAD, float, setAlphaSpread); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_START, float, setAlphaStart); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_FINISH, float, setAlphaFinish); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ADDITIVE_BLENDING, bool, setAdditiveBlending); } if (properties.getType() == EntityTypes::Zone) { @@ -1579,6 +1586,9 @@ QList EntityItemProperties::listChangedProperties() { if (alphaFinishChanged()) { out += "alphaFinish"; } + if (additiveBlendingChanged()) { + out += "additiveBlending"; + } if (modelURLChanged()) { out += "modelURL"; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index b95f4d35f4..84a5aeca5d 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -159,6 +159,7 @@ public: DEFINE_PROPERTY(PROP_RADIUS_SPREAD, RadiusSpread, radiusSpread, float, ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD); DEFINE_PROPERTY(PROP_RADIUS_START, RadiusStart, radiusStart, float, ParticleEffectEntityItem::DEFAULT_RADIUS_START); DEFINE_PROPERTY(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float, ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH); + DEFINE_PROPERTY(PROP_ADDITIVE_BLENDING, AdditiveBlending, additiveBlending, bool, ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING); DEFINE_PROPERTY_REF(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID); DEFINE_PROPERTY_GROUP(KeyLight, keyLight, KeyLightPropertyGroup); DEFINE_PROPERTY_REF(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3, PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 65060c8d45..b11d4d738b 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -142,6 +142,7 @@ enum EntityPropertyList { PROP_POLAR_FINISH, PROP_AZIMUTH_START, PROP_AZIMUTH_FINISH, + PROP_ADDITIVE_BLENDING, PROP_ANIMATION_LOOP, PROP_ANIMATION_FIRST_FRAME, diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index ddd79375b3..00ff0ed72a 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -94,6 +94,7 @@ const float ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD = 0.0f; const float ParticleEffectEntityItem::DEFAULT_RADIUS_START = DEFAULT_PARTICLE_RADIUS; const float ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH = DEFAULT_PARTICLE_RADIUS; const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = ""; +const bool ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING = false; EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -121,7 +122,8 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte _alphaMiddles(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), _alphaFinishes(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), _particleMaxBound(glm::vec3(1.0f, 1.0f, 1.0f)), - _particleMinBound(glm::vec3(-1.0f, -1.0f, -1.0f)) + _particleMinBound(glm::vec3(-1.0f, -1.0f, -1.0f)) , + _additiveBlending(DEFAULT_ADDITIVE_BLENDING) { _type = EntityTypes::ParticleEffect; @@ -355,6 +357,8 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(EntityPropertyFlags COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaStart, getAlphaStart); COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaFinish, getAlphaFinish); COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(additiveBlending, getAdditiveBlending); + return properties; } @@ -392,6 +396,7 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaStart, setAlphaStart); SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaFinish, setAlphaFinish); SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(additiveBlending, setAdditiveBlending); if (somethingChanged) { bool wantDebug = false; @@ -435,6 +440,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch if (args.bitstreamVersion < VERSION_ENTITIES_PARTICLE_ELLIPSOID_EMITTER) { // OLD PROP_EMIT_VELOCITY FAKEOUT SKIP_ENTITY_PROPERTY(PROP_EMIT_SPEED, glm::vec3); + SKIP_ENTITY_PROPERTY(PROP_ADDITIVE_BLENDING, bool) } if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLE_MODIFICATIONS) { @@ -481,6 +487,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch READ_ENTITY_PROPERTY(PROP_POLAR_FINISH, float, setPolarFinish); READ_ENTITY_PROPERTY(PROP_AZIMUTH_START, float, setAzimuthStart); READ_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, float, setAzimuthFinish); + READ_ENTITY_PROPERTY(PROP_ADDITIVE_BLENDING, bool, setAdditiveBlending); } return bytesRead; @@ -520,6 +527,7 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea requestedProperties += PROP_POLAR_FINISH; requestedProperties += PROP_AZIMUTH_START; requestedProperties += PROP_AZIMUTH_FINISH; + requestedProperties += PROP_ADDITIVE_BLENDING; return requestedProperties; } @@ -562,6 +570,7 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_POLAR_FINISH, getPolarFinish()); APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_START, getAzimuthStart()); APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, getAzimuthFinish()); + APPEND_ENTITY_PROPERTY(PROP_ADDITIVE_BLENDING, getAdditiveBlending()); } bool ParticleEffectEntityItem::isEmittingParticles() const { diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 029d65cfc0..6560a7bc33 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -209,6 +209,12 @@ public: } } + static const bool DEFAULT_ADDITIVE_BLENDING; + bool getAdditiveBlending() const { return _additiveBlending; } + void setAdditiveBlending(bool additiveBlending) { + _additiveBlending = additiveBlending; + } + protected: bool isAnimatingSomething() const; @@ -219,7 +225,6 @@ protected: void extendBounds(const glm::vec3& point); void integrateParticle(quint32 index, float deltaTime); quint32 getLivingParticleCount() const; - // the properties of this entity rgbColor _color; xColor _colorStart = DEFAULT_COLOR; @@ -284,6 +289,8 @@ protected: // bounding volume glm::vec3 _particleMaxBound; glm::vec3 _particleMinBound; + + bool _additiveBlending; }; #endif // hifi_ParticleEffectEntityItem_h