diff --git a/examples/example/games/hitEffect.js b/examples/example/games/hitEffect.js new file mode 100644 index 0000000000..0ba9ea14d1 --- /dev/null +++ b/examples/example/games/hitEffect.js @@ -0,0 +1,28 @@ +// +// hitEffect.js +// examples +// +// Created by Eric Levin on July 20, 2015 +// Copyright 2015 High Fidelity, Inc. +// +// An example of how to toggle a screen-space hit effect using the Scene global object. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +var hitEffectEnabled = false; + +toggleHitEffect(); + +function toggleHitEffect() { + Script.setTimeout(function() { + hitEffectEnabled = !hitEffectEnabled; + Scene.setEngineDisplayHitEffect(hitEffectEnabled); + toggleHitEffect(); + }, 1000); +} + + + + + diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1f84e8a59f..3696d5c9c4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3270,6 +3270,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se renderContext._maxDrawnOverlay3DItems = sceneInterface->getEngineMaxDrawnOverlay3DItems(); renderContext._drawItemStatus = sceneInterface->doEngineDisplayItemStatus(); + renderContext._drawHitEffect = sceneInterface->doEngineDisplayHitEffect(); renderContext._occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugAmbientOcclusion); diff --git a/libraries/render-utils/src/HitEffect.cpp b/libraries/render-utils/src/HitEffect.cpp new file mode 100644 index 0000000000..f65bc7666f --- /dev/null +++ b/libraries/render-utils/src/HitEffect.cpp @@ -0,0 +1,86 @@ +// +// HitEffect.cpp +// interface/src/renderer +// +// Created by Andrzej Kapolka on 7/14/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL + + +#include + +#include +#include + +#include "AbstractViewStateInterface.h" +#include "HitEffect.h" +#include "TextureCache.h" +#include "DependencyManager.h" +#include "ViewFrustum.h" +#include "GeometryCache.h" + +#include + +#include "hit_effect_vert.h" +#include "hit_effect_frag.h" + + +HitEffect::HitEffect() { +} + +const gpu::PipelinePointer& HitEffect::getHitEffectPipeline() { + if (!_hitEffectPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(hit_effect_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(hit_effect_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(false, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + + // Good to go add the brand new pipeline + _hitEffectPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _hitEffectPipeline; +} + +void HitEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + RenderArgs* args = renderContext->args; + gpu::Batch batch; + + glm::mat4 projMat; + Transform viewMat; + args->_viewFrustum->evalProjectionMatrix(projMat); + args->_viewFrustum->evalViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + batch.setModelTransform(Transform()); + + batch.setPipeline(getHitEffectPipeline()); + + glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f); + glm::vec2 bottomLeft(-1.0f, -1.0f); + glm::vec2 topRight(1.0f, 1.0f); + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, color); + + + // Ready to render + args->_context->render((batch)); + +} + diff --git a/libraries/render-utils/src/HitEffect.h b/libraries/render-utils/src/HitEffect.h new file mode 100644 index 0000000000..91ac7e5700 --- /dev/null +++ b/libraries/render-utils/src/HitEffect.h @@ -0,0 +1,33 @@ +// +// hitEffect.h +// hifi +// +// Created by eric levin on 7/17/15. +// +// + +#ifndef hifi_hitEffect_h +#define hifi_hitEffect_h + +#include +#include "render/DrawTask.h" + +class AbstractViewStateInterface; +class ProgramObject; + +class HitEffect { +public: + + HitEffect(); + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + typedef render::Job::Model JobModel; + + const gpu::PipelinePointer& getHitEffectPipeline(); + +private: + + gpu::PipelinePointer _hitEffectPipeline; +}; + +#endif diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index cf9b455059..72738c56cf 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -1,3 +1,4 @@ + // // RenderDeferredTask.cpp // render-utils/src/ @@ -20,6 +21,7 @@ #include "FramebufferCache.h" #include "DeferredLightingEffect.h" #include "TextureCache.h" +#include "HitEffect.h" #include "render/DrawStatus.h" #include "AmbientOcclusionEffect.h" @@ -78,6 +80,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortOpaque", _jobs.back().getOutput()))); auto& renderedOpaques = _jobs.back().getOutput(); _jobs.push_back(Job(new DrawOpaqueDeferred::JobModel("DrawOpaqueDeferred", _jobs.back().getOutput()))); + _jobs.push_back(Job(new DrawLight::JobModel("DrawLight"))); _jobs.push_back(Job(new RenderDeferred::JobModel("RenderDeferred"))); _jobs.push_back(Job(new ResolveDeferred::JobModel("ResolveDeferred"))); @@ -105,8 +108,13 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _drawStatusJobIndex = _jobs.size() - 1; _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); + _jobs.push_back(Job(new HitEffect::JobModel("HitEffect"))); + _jobs.back().setEnabled(false); + _drawHitEffectJobIndex = _jobs.size() -1; + _jobs.push_back(Job(new ResetGLState::JobModel())); + // Give ourselves 3 frmaes of timer queries _timerQueries.push_back(std::make_shared()); @@ -133,6 +141,10 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend // Make sure we turn the displayItemStatus on/off setDrawItemStatus(renderContext->_drawItemStatus); + + //Make sure we display hit effect on screen, as desired from a script + setDrawHitEffect(renderContext->_drawHitEffect); + // TODO: turn on/off AO through menu item setOcclusionStatus(renderContext->_occlusionStatus); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index fdb75a87b1..0041f5d9aa 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -78,9 +78,13 @@ public: render::Jobs _jobs; int _drawStatusJobIndex = -1; + int _drawHitEffectJobIndex = -1; void setDrawItemStatus(bool draw) { if (_drawStatusJobIndex >= 0) { _jobs[_drawStatusJobIndex].setEnabled(draw); } } bool doDrawItemStatus() const { if (_drawStatusJobIndex >= 0) { return _jobs[_drawStatusJobIndex].isEnabled(); } else { return false; } } + + void setDrawHitEffect(bool draw) { if (_drawHitEffectJobIndex >= 0) { _jobs[_drawHitEffectJobIndex].setEnabled(draw); } } + bool doDrawHitEffect() const { if (_drawHitEffectJobIndex >=0) { return _jobs[_drawHitEffectJobIndex].isEnabled(); } else { return false; } } int _occlusionJobIndex = -1; diff --git a/libraries/render-utils/src/hit_effect.slf b/libraries/render-utils/src/hit_effect.slf new file mode 100644 index 0000000000..6c0dcd7a70 --- /dev/null +++ b/libraries/render-utils/src/hit_effect.slf @@ -0,0 +1,24 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// hit_effect.frag +// fragment shader +// +// Created by Eric Levin on 7/20 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include DeferredBufferWrite.slh@> + +varying vec2 varQuadPosition; + +void main(void) { + vec2 center = vec2(0.0, 0.0); + float distFromCenter = distance( vec2(0.0, 0.0), varQuadPosition); + float alpha = mix(0.0, 0.5, pow(distFromCenter,5.)); + gl_FragColor = vec4(1.0, 0.0, 0.0, alpha); +} \ No newline at end of file diff --git a/libraries/render-utils/src/hit_effect.slv b/libraries/render-utils/src/hit_effect.slv new file mode 100644 index 0000000000..d1efdebc18 --- /dev/null +++ b/libraries/render-utils/src/hit_effect.slv @@ -0,0 +1,24 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// hit_effect.vert +// vertex shader +// +// Created by Eric Levin on 7/20/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +varying vec2 varQuadPosition; + +void main(void) { + varQuadPosition = gl_Vertex.xy; + gl_Position = gl_Vertex; +} \ No newline at end of file diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 5bfece96cc..8d096c5e15 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -50,6 +50,7 @@ public: int _maxDrawnOverlay3DItems = -1; bool _drawItemStatus = false; + bool _drawHitEffect = false; bool _occlusionStatus = false; diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index d25ded1fc4..cb2f6b7b79 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -109,6 +109,9 @@ public: Q_INVOKABLE void setEngineDisplayItemStatus(bool display) { _drawItemStatus = display; } Q_INVOKABLE bool doEngineDisplayItemStatus() { return _drawItemStatus; } + + Q_INVOKABLE void setEngineDisplayHitEffect(bool display) { _drawHitEffect = display; } + Q_INVOKABLE bool doEngineDisplayHitEffect() { return _drawHitEffect; } signals: void shouldRenderAvatarsChanged(bool shouldRenderAvatars); @@ -141,6 +144,8 @@ protected: int _maxDrawnOverlay3DItems = -1; bool _drawItemStatus = false; + + bool _drawHitEffect = false; };