diff --git a/interface/resources/shaders/horizontal_blur.frag b/interface/resources/shaders/horizontal_blur.frag new file mode 100644 index 0000000000..695de1a538 --- /dev/null +++ b/interface/resources/shaders/horizontal_blur.frag @@ -0,0 +1,24 @@ +#version 120 + +// +// horizontal_blur.frag +// fragment shader +// +// Created by Andrzej Kapolka on 8/8/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +// the texture containing the original color +uniform sampler2D originalTexture; + +void main(void) { + float ds = dFdx(gl_TexCoord[0].s); + gl_FragColor = (texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * -7.5, 0.0)) + + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * -5.5, 0.0)) + + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * -3.5, 0.0)) + + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * -1.5, 0.0)) + + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * 1.5, 0.0)) + + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * 3.5, 0.0)) + + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * 5.5, 0.0)) + + texture2D(originalTexture, gl_TexCoord[0].st + vec2(ds * 7.5, 0.0))) / 8.0; +} diff --git a/interface/resources/shaders/vertical_blur.frag b/interface/resources/shaders/vertical_blur.frag new file mode 100644 index 0000000000..6e49c5b553 --- /dev/null +++ b/interface/resources/shaders/vertical_blur.frag @@ -0,0 +1,28 @@ +#version 120 + +// +// vertical_blur.frag +// fragment shader +// +// Created by Andrzej Kapolka on 8/8/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +// the texture containing the original color +uniform sampler2D originalTexture; + +// the texture containing the horizontally blurred color +uniform sampler2D horizontallyBlurredTexture; + +void main(void) { + float dt = dFdy(gl_TexCoord[0].t); + vec4 blurred = (texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * -7.5)) + + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * -5.5)) + + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * -3.5)) + + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * -1.5)) + + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * 1.5)) + + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * 3.5)) + + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * 5.5)) + + texture2D(horizontallyBlurredTexture, gl_TexCoord[0].st + vec2(0.0, dt * 7.5))) / 8.0; + gl_FragColor = blurred * blurred.a + texture2D(originalTexture, gl_TexCoord[0].st) * (1.0 + blurred.a * 0.5); +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 082d942ee7..0b68887725 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3872,7 +3872,6 @@ int Application::parseVoxelStats(unsigned char* messageData, ssize_t messageLeng _voxelFades.push_back(fade); } // store jurisdiction details for later use - // This is bit of fiddling is because JurisdictionMap assumes it is the owner of the values used to construct it // but VoxelSceneStats thinks it's just returning a reference to it's contents. So we need to make a copy of the // details from the VoxelSceneStats to construct the JurisdictionMap diff --git a/interface/src/Application.h b/interface/src/Application.h index 9ef808f603..bfa4c53137 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -46,6 +46,7 @@ #include "avatar/Avatar.h" #include "avatar/HandControl.h" #include "renderer/GeometryCache.h" +#include "renderer/GlowEffect.h" #include "renderer/TextureCache.h" #include "ui/BandwidthDialog.h" #include "ui/ChatEntry.h" @@ -104,6 +105,7 @@ public: void updateParticleSystem(float deltaTime); + QGLWidget* getGLWidget() { return _glWidget; } Avatar* getAvatar() { return &_myAvatar; } Audio* getAudio() { return &_audio; } Camera* getCamera() { return &_myCamera; } @@ -122,6 +124,7 @@ public: QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; } GeometryCache* getGeometryCache() { return &_geometryCache; } TextureCache* getTextureCache() { return &_textureCache; } + GlowEffect* getGlowEffect() { return &_glowEffect; } void resetSongMixMenuItem(); void setupWorldLight(Camera& whichCamera); @@ -440,6 +443,7 @@ private: TextureCache _textureCache; ParticleSystem _particleSystem; + GlowEffect _glowEffect; #ifndef _WIN32 Audio _audio; @@ -453,7 +457,6 @@ private: VoxelPacketReceiver _voxelReceiver; VoxelEditPacketSender _voxelEditSender; - unsigned char _incomingPacket[MAX_PACKET_SIZE]; int _packetCount; int _packetsPerSecond; diff --git a/interface/src/VoxelEditPacketSender.cpp b/interface/src/VoxelEditPacketSender.cpp index 64016bc592..5155619b7e 100644 --- a/interface/src/VoxelEditPacketSender.cpp +++ b/interface/src/VoxelEditPacketSender.cpp @@ -14,9 +14,7 @@ #include "VoxelEditPacketSender.h" VoxelEditPacketSender::VoxelEditPacketSender(Application* app) : - _app(app), - _currentType(PACKET_TYPE_UNKNOWN), - _currentSize(0) + _app(app) { } @@ -32,7 +30,7 @@ void VoxelEditPacketSender::sendVoxelEditMessage(PACKET_TYPE type, VoxelDetail& int totalBytesSent = 0; if (createVoxelEditMessage(type, 0, 1, &detail, bufferOut, sizeOut)){ - actuallySendMessage(bufferOut, sizeOut); + actuallySendMessage(UNKNOWN_NODE_ID, bufferOut, sizeOut); // sends to all servers... not ideal! delete[] bufferOut; } @@ -40,16 +38,13 @@ void VoxelEditPacketSender::sendVoxelEditMessage(PACKET_TYPE type, VoxelDetail& _app->_bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(totalBytesSent); } -void VoxelEditPacketSender::actuallySendMessage(unsigned char* bufferOut, ssize_t sizeOut) { - qDebug("VoxelEditPacketSender::actuallySendMessage() sizeOut=%lu\n", sizeOut); +void VoxelEditPacketSender::actuallySendMessage(uint16_t nodeID, unsigned char* bufferOut, ssize_t sizeOut) { + qDebug("VoxelEditPacketSender::actuallySendMessage() sizeOut=%lu target NodeID=%d\n", sizeOut, nodeID); NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { // only send to the NodeTypes that are NODE_TYPE_VOXEL_SERVER - if (node->getActiveSocket() != NULL && node->getType() == NODE_TYPE_VOXEL_SERVER) { - - // We want to filter out edit messages for voxel servers based on the server's Jurisdiction - // But we can't really do that with a packed message, since each edit message could be destined - // for a different voxel server... + if (node->getActiveSocket() != NULL && node->getType() == NODE_TYPE_VOXEL_SERVER && + ((node->getNodeID() == nodeID) || (nodeID == (uint16_t)UNKNOWN_NODE_ID)) ) { sockaddr* nodeAddress = node->getActiveSocket(); queuePacket(*nodeAddress, bufferOut, sizeOut); } @@ -57,59 +52,64 @@ void VoxelEditPacketSender::actuallySendMessage(unsigned char* bufferOut, ssize_ } void VoxelEditPacketSender::queueVoxelEditMessage(PACKET_TYPE type, unsigned char* codeColorBuffer, ssize_t length) { -/**** // We want to filter out edit messages for voxel servers based on the server's Jurisdiction // But we can't really do that with a packed message, since each edit message could be destined // for a different voxel server... So we need to actually manage multiple queued packets... one // for each voxel server + NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { // only send to the NodeTypes that are NODE_TYPE_VOXEL_SERVER if (node->getActiveSocket() != NULL && node->getType() == NODE_TYPE_VOXEL_SERVER) { // we need to get the jurisdiction for this // here we need to get the "pending packet" for this server + uint16_t nodeID = node->getNodeID(); + const JurisdictionMap& map = _app->_voxelServerJurisdictions[nodeID]; + + if (map.isMyJurisdiction(codeColorBuffer, CHECK_NODE_ONLY) == JurisdictionMap::WITHIN) { - // If we're switching type, then we send the last one and start over - if ((type != _currentType && _currentSize > 0) || (_currentSize + length >= MAX_PACKET_SIZE)) { - flushQueue(); - initializePacket(type); + // do I need this??? + //if (_pendingEditPackets.find(nodeID) == _pendingEditPackets.end()) { + // _pendingEditPackets[nodeID] = + //} + EditPacketBuffer& packetBuffer = _pendingEditPackets[nodeID]; + packetBuffer._nodeID = nodeID; + + // If we're switching type, then we send the last one and start over + if ((type != packetBuffer._currentType && packetBuffer._currentSize > 0) || + (packetBuffer._currentSize + length >= MAX_PACKET_SIZE)) { + flushQueue(packetBuffer); + initializePacket(packetBuffer, type); + } + + // If the buffer is empty and not correctly initialized for our type... + if (type != packetBuffer._currentType && packetBuffer._currentSize == 0) { + initializePacket(packetBuffer, type); + } + + memcpy(&packetBuffer._currentBuffer[packetBuffer._currentSize], codeColorBuffer, length); + packetBuffer._currentSize += length; } - - // If the buffer is empty and not correctly initialized for our type... - if (type != _currentType && _currentSize == 0) { - initializePacket(type); - } - - memcpy(&_currentBuffer[_currentSize], codeColorBuffer, length); - _currentSize += length; } } -****/ - // If we're switching type, then we send the last one and start over - if ((type != _currentType && _currentSize > 0) || (_currentSize + length >= MAX_PACKET_SIZE)) { - flushQueue(); - initializePacket(type); - } - - // If the buffer is empty and not correctly initialized for our type... - if (type != _currentType && _currentSize == 0) { - initializePacket(type); - } - - memcpy(&_currentBuffer[_currentSize], codeColorBuffer, length); - _currentSize += length; } void VoxelEditPacketSender::flushQueue() { - actuallySendMessage(&_currentBuffer[0], _currentSize); - _currentSize = 0; - _currentType = PACKET_TYPE_UNKNOWN; + for (std::map::iterator i = _pendingEditPackets.begin(); i != _pendingEditPackets.end(); i++) { + flushQueue(i->second); + } } -void VoxelEditPacketSender::initializePacket(PACKET_TYPE type) { - _currentSize = populateTypeAndVersion(&_currentBuffer[0], type); - unsigned short int* sequenceAt = (unsigned short int*)&_currentBuffer[_currentSize]; - *sequenceAt = 0; - _currentSize += sizeof(unsigned short int); // set to command + sequence - _currentType = type; +void VoxelEditPacketSender::flushQueue(EditPacketBuffer& packetBuffer) { + actuallySendMessage(packetBuffer._nodeID, &packetBuffer._currentBuffer[0], packetBuffer._currentSize); + packetBuffer._currentSize = 0; + packetBuffer._currentType = PACKET_TYPE_UNKNOWN; +} + +void VoxelEditPacketSender::initializePacket(EditPacketBuffer& packetBuffer, PACKET_TYPE type) { + packetBuffer._currentSize = populateTypeAndVersion(&packetBuffer._currentBuffer[0], type); + unsigned short int* sequenceAt = (unsigned short int*)&packetBuffer._currentBuffer[packetBuffer._currentSize]; + *sequenceAt = 0; + packetBuffer._currentSize += sizeof(unsigned short int); // set to command + sequence + packetBuffer._currentType = type; } diff --git a/interface/src/VoxelEditPacketSender.h b/interface/src/VoxelEditPacketSender.h index 5bcc73e7a5..f0d18e85f4 100644 --- a/interface/src/VoxelEditPacketSender.h +++ b/interface/src/VoxelEditPacketSender.h @@ -16,6 +16,15 @@ class Application; +class EditPacketBuffer { +public: + EditPacketBuffer() { _currentSize = 0; _currentType = PACKET_TYPE_UNKNOWN; _nodeID = UNKNOWN_NODE_ID; } + uint16_t _nodeID; + PACKET_TYPE _currentType; + unsigned char _currentBuffer[MAX_PACKET_SIZE]; + ssize_t _currentSize; +}; + class VoxelEditPacketSender : public PacketSender { public: VoxelEditPacketSender(Application* app); @@ -23,15 +32,14 @@ public: // Some ways you can send voxel edit messages... void sendVoxelEditMessage(PACKET_TYPE type, VoxelDetail& detail); // sends it right away void queueVoxelEditMessage(PACKET_TYPE type, unsigned char* codeColorBuffer, ssize_t length); // queues it into a multi-command packet - void flushQueue(); // flushes any queued packets + void flushQueue(); // flushes all queued packets private: - void actuallySendMessage(unsigned char* bufferOut, ssize_t sizeOut); - void initializePacket(PACKET_TYPE type); + void actuallySendMessage(uint16_t nodeID, unsigned char* bufferOut, ssize_t sizeOut); + void initializePacket(EditPacketBuffer& packetBuffer, PACKET_TYPE type); + void flushQueue(EditPacketBuffer& packetBuffer); // flushes specific queued packet - Application* _app; - PACKET_TYPE _currentType ; - unsigned char _currentBuffer[MAX_PACKET_SIZE]; - ssize_t _currentSize; + Application* _app; + std::map _pendingEditPackets; }; #endif // __shared__VoxelEditPacketSender__ diff --git a/interface/src/VoxelFade.cpp b/interface/src/VoxelFade.cpp index 0bbcbeedc1..8ce68c9724 100644 --- a/interface/src/VoxelFade.cpp +++ b/interface/src/VoxelFade.cpp @@ -10,14 +10,15 @@ #include +#include "Application.h" #include "VoxelFade.h" const float VoxelFade::FADE_OUT_START = 0.5f; -const float VoxelFade::FADE_OUT_END = 0.0f; -const float VoxelFade::FADE_OUT_STEP = -0.005f; -const float VoxelFade::FADE_IN_START = 0.0f; +const float VoxelFade::FADE_OUT_END = 0.05f; +const float VoxelFade::FADE_OUT_STEP = 0.9f; +const float VoxelFade::FADE_IN_START = 0.05f; const float VoxelFade::FADE_IN_END = 0.5f; -const float VoxelFade::FADE_IN_STEP = 0.005f; +const float VoxelFade::FADE_IN_STEP = 1.1f; const float VoxelFade::DEFAULT_RED = 0.5f; const float VoxelFade::DEFAULT_GREEN = 0.5f; const float VoxelFade::DEFAULT_BLUE = 0.5f; @@ -32,6 +33,8 @@ VoxelFade::VoxelFade(FadeDirection direction, float red, float green, float blue } void VoxelFade::render() { + Application::getInstance()->getGlowEffect()->begin(); + glDisable(GL_LIGHTING); glPushMatrix(); glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE); @@ -45,7 +48,10 @@ void VoxelFade::render() { glPopMatrix(); glEnable(GL_LIGHTING); - opacity += (direction == FADE_OUT) ? FADE_OUT_STEP : FADE_IN_STEP; + + Application::getInstance()->getGlowEffect()->end(); + + opacity *= (direction == FADE_OUT) ? FADE_OUT_STEP : FADE_IN_STEP; } bool VoxelFade::isDone() const { @@ -55,4 +61,4 @@ bool VoxelFade::isDone() const { return opacity >= FADE_IN_END; } return true; // unexpected case, assume we're done -} \ No newline at end of file +} diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 5351f129be..becf9f868f 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -695,8 +695,7 @@ void VoxelSystem::render(bool texture) { applyScaleAndBindProgram(texture); - // for performance, disable blending and enable backface culling - glDisable(GL_BLEND); + // for performance, enable backface culling glEnable(GL_CULL_FACE); // draw the number of voxels we have @@ -704,7 +703,6 @@ void VoxelSystem::render(bool texture) { glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTICES_PER_VOXEL * _voxelsInReadArrays - 1, 36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); - glEnable(GL_BLEND); glDisable(GL_CULL_FACE); removeScaleAndReleaseProgram(texture); diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp new file mode 100644 index 0000000000..11c73dd12d --- /dev/null +++ b/interface/src/renderer/GlowEffect.cpp @@ -0,0 +1,128 @@ +// +// GlowEffect.cpp +// interface +// +// Created by Andrzej Kapolka on 8/7/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include + +#include "Application.h" +#include "GlowEffect.h" +#include "ProgramObject.h" + +static ProgramObject* createBlurProgram(const QString& direction) { + ProgramObject* program = new ProgramObject(); + program->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/" + direction + "_blur.frag"); + program->link(); + + program->bind(); + program->setUniformValue("originalTexture", 0); + program->release(); + + return program; +} + +void GlowEffect::init() { + switchToResourcesParentIfRequired(); + _horizontalBlurProgram = createBlurProgram("horizontal"); + _verticalBlurProgram = createBlurProgram("vertical"); + + _verticalBlurProgram->bind(); + _verticalBlurProgram->setUniformValue("horizontallyBlurredTexture", 1); + _verticalBlurProgram->release(); +} + +void GlowEffect::prepare() { + Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + _isEmpty = true; +} + +void GlowEffect::begin(float amount) { + glBlendColor(0.0f, 0.0f, 0.0f, amount); + _isEmpty = false; +} + +void GlowEffect::end() { + glBlendColor(0.0f, 0.0f, 0.0f, 0.0f); +} + +static void renderFullscreenQuad() { + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); + glVertex2f(-1.0f, -1.0f); + glTexCoord2f(1.0f, 0.0f); + glVertex2f(1.0f, -1.0f); + glTexCoord2f(1.0f, 1.0f); + glVertex2f(1.0f, 1.0f); + glTexCoord2f(0.0f, 1.0f); + glVertex2f(-1.0f, 1.0f); + glEnd(); +} + +void GlowEffect::render() { + QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject(); + primaryFBO->release(); + glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); + + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + + if (_isEmpty) { + // copy the primary to the screen + if (QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { + QOpenGLFramebufferObject::blitFramebuffer(NULL, primaryFBO); + + } else { + glEnable(GL_TEXTURE_2D); + glDisable(GL_LIGHTING); + glColor3f(1.0f, 1.0f, 1.0f); + renderFullscreenQuad(); + glDisable(GL_TEXTURE_2D); + glEnable(GL_LIGHTING); + } + } else { + // render the primary to the secondary with the horizontal blur + QOpenGLFramebufferObject* secondaryFBO = + Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject(); + secondaryFBO->bind(); + + _horizontalBlurProgram->bind(); + renderFullscreenQuad(); + _horizontalBlurProgram->release(); + + secondaryFBO->release(); + + // render the secondary to the screen with the vertical blur + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture()); + + _verticalBlurProgram->bind(); + renderFullscreenQuad(); + _verticalBlurProgram->release(); + + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0); + } + + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glEnable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + glBindTexture(GL_TEXTURE_2D, 0); +} diff --git a/interface/src/renderer/GlowEffect.h b/interface/src/renderer/GlowEffect.h new file mode 100644 index 0000000000..06ca6e5712 --- /dev/null +++ b/interface/src/renderer/GlowEffect.h @@ -0,0 +1,34 @@ +// +// GlowEffect.h +// interface +// +// Created by Andrzej Kapolka on 8/7/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__GlowEffect__ +#define __interface__GlowEffect__ + +class ProgramObject; + +class GlowEffect { +public: + + void init(); + + void prepare(); + + void begin(float amount = 1.0f); + void end(); + + void render(); + +private: + + ProgramObject* _horizontalBlurProgram; + ProgramObject* _verticalBlurProgram; + + bool _isEmpty; +}; + +#endif /* defined(__interface__GlowEffect__) */ diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index 1c832a648e..8ff1673d18 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -5,17 +5,28 @@ // Created by Andrzej Kapolka on 8/6/13. // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +#include +#include + #include +#include "Application.h" #include "TextureCache.h" -TextureCache::TextureCache() : _permutationNormalTextureID(0) { +TextureCache::TextureCache() : _permutationNormalTextureID(0), + _primaryFramebufferObject(NULL), _secondaryFramebufferObject(NULL) { } TextureCache::~TextureCache() { if (_permutationNormalTextureID != 0) { glDeleteTextures(1, &_permutationNormalTextureID); } + if (_primaryFramebufferObject != NULL) { + delete _primaryFramebufferObject; + } + if (_secondaryFramebufferObject != NULL) { + delete _secondaryFramebufferObject; + } } GLuint TextureCache::getPermutationNormalTextureID() { @@ -43,3 +54,35 @@ GLuint TextureCache::getPermutationNormalTextureID() { } return _permutationNormalTextureID; } + +QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() { + if (_primaryFramebufferObject == NULL) { + _primaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size(), + QOpenGLFramebufferObject::Depth); + Application::getInstance()->getGLWidget()->installEventFilter(this); + } + return _primaryFramebufferObject; +} + +QOpenGLFramebufferObject* TextureCache::getSecondaryFramebufferObject() { + if (_secondaryFramebufferObject == NULL) { + _secondaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size()); + Application::getInstance()->getGLWidget()->installEventFilter(this); + } + return _secondaryFramebufferObject; +} + +bool TextureCache::eventFilter(QObject* watched, QEvent* event) { + if (event->type() == QEvent::Resize) { + QSize size = static_cast(event)->size(); + if (_primaryFramebufferObject != NULL && _primaryFramebufferObject->size() != size) { + delete _primaryFramebufferObject; + _primaryFramebufferObject = NULL; + } + if (_secondaryFramebufferObject != NULL && _secondaryFramebufferObject->size() != size) { + delete _secondaryFramebufferObject; + _secondaryFramebufferObject = NULL; + } + } + return false; +} diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index 9804f038ba..29920e1f1f 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -9,9 +9,13 @@ #ifndef __interface__TextureCache__ #define __interface__TextureCache__ +#include + #include "InterfaceConfig.h" -class TextureCache { +class QOpenGLFramebufferObject; + +class TextureCache : public QObject { public: TextureCache(); @@ -19,9 +23,17 @@ public: GLuint getPermutationNormalTextureID(); + QOpenGLFramebufferObject* getPrimaryFramebufferObject(); + QOpenGLFramebufferObject* getSecondaryFramebufferObject(); + + virtual bool eventFilter(QObject* watched, QEvent* event); + private: GLuint _permutationNormalTextureID; + + QOpenGLFramebufferObject* _primaryFramebufferObject; + QOpenGLFramebufferObject* _secondaryFramebufferObject; }; #endif /* defined(__interface__TextureCache__) */