mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 07:53:10 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into voxel_sending_helper
Conflicts: interface/src/Application.cpp interface/src/Application.h
This commit is contained in:
commit
f09dcfa4b7
12 changed files with 350 additions and 67 deletions
24
interface/resources/shaders/horizontal_blur.frag
Normal file
24
interface/resources/shaders/horizontal_blur.frag
Normal file
|
@ -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;
|
||||
}
|
28
interface/resources/shaders/vertical_blur.frag
Normal file
28
interface/resources/shaders/vertical_blur.frag
Normal file
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<uint16_t,EditPacketBuffer>::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;
|
||||
}
|
||||
|
|
|
@ -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<uint16_t,EditPacketBuffer> _pendingEditPackets;
|
||||
};
|
||||
#endif // __shared__VoxelEditPacketSender__
|
||||
|
|
|
@ -10,14 +10,15 @@
|
|||
|
||||
#include <VoxelConstants.h>
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
128
interface/src/renderer/GlowEffect.cpp
Normal file
128
interface/src/renderer/GlowEffect.cpp
Normal file
|
@ -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 <QOpenGLFramebufferObject>
|
||||
|
||||
#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);
|
||||
}
|
34
interface/src/renderer/GlowEffect.h
Normal file
34
interface/src/renderer/GlowEffect.h
Normal file
|
@ -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__) */
|
|
@ -5,17 +5,28 @@
|
|||
// Created by Andrzej Kapolka on 8/6/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
|
||||
#include <QGLWidget>
|
||||
#include <QOpenGLFramebufferObject>
|
||||
|
||||
#include <glm/gtc/random.hpp>
|
||||
|
||||
#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<QResizeEvent*>(event)->size();
|
||||
if (_primaryFramebufferObject != NULL && _primaryFramebufferObject->size() != size) {
|
||||
delete _primaryFramebufferObject;
|
||||
_primaryFramebufferObject = NULL;
|
||||
}
|
||||
if (_secondaryFramebufferObject != NULL && _secondaryFramebufferObject->size() != size) {
|
||||
delete _secondaryFramebufferObject;
|
||||
_secondaryFramebufferObject = NULL;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -9,9 +9,13 @@
|
|||
#ifndef __interface__TextureCache__
|
||||
#define __interface__TextureCache__
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#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__) */
|
||||
|
|
Loading…
Reference in a new issue