Merge pull request #3592 from samcake/temp0

Rendering resolution can be different than the native window resolution
This commit is contained in:
Andrzej Kapolka 2014-10-14 11:56:50 -07:00
commit ff368f9848
9 changed files with 85 additions and 126 deletions

View file

@ -179,7 +179,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
_runningScriptsWidgetWasVisible(false),
_trayIcon(new QSystemTrayIcon(_window)),
_lastNackTime(usecTimestampNow()),
_lastSendDownstreamAudioStats(usecTimestampNow())
_lastSendDownstreamAudioStats(usecTimestampNow()),
_renderResolutionScale(1.0f)
{
// read the ApplicationInfo.ini file for Name/Version/Domain information
QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat);
@ -598,7 +599,8 @@ void Application::paintGL() {
if (OculusManager::isConnected()) {
_textureCache.setFrameBufferSize(OculusManager::getRenderTargetSize());
} else {
_textureCache.setFrameBufferSize(_glWidget->getDeviceSize());
QSize fbSize = _glWidget->getDeviceSize() * _renderResolutionScale;
_textureCache.setFrameBufferSize(fbSize);
}
glEnable(GL_LINE_SMOOTH);
@ -696,6 +698,10 @@ void Application::paintGL() {
} else {
_glowEffect.prepare();
// Viewport is assigned to the size of the framebuffer
QSize size = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->size();
glViewport(0, 0, size.width(), size.height());
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
@ -3087,6 +3093,10 @@ glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) {
}
void Application::renderRearViewMirror(const QRect& region, bool billboard) {
// Grab current viewport to reset it at the end
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
bool eyeRelativeCamera = false;
if (billboard) {
_mirrorCamera.setFieldOfView(BILLBOARD_FIELD_OF_VIEW); // degees
@ -3118,14 +3128,17 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
// set the bounds of rear mirror view
if (billboard) {
glViewport(region.x(), _glWidget->getDeviceHeight() - region.y() - region.height(), region.width(), region.height());
glScissor(region.x(), _glWidget->getDeviceHeight() - region.y() - region.height(), region.width(), region.height());
QSize size = getTextureCache()->getFrameBufferSize();
glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height());
glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height());
} else {
// if not rendering the billboard, the region is in device independent coordinates; must convert to device
QSize size = getTextureCache()->getFrameBufferSize();
float ratio = QApplication::desktop()->windowHandle()->devicePixelRatio();
ratio = size.height() / (float)_glWidget->getDeviceHeight();
int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio;
glViewport(x, _glWidget->getDeviceHeight() - y - height, width, height);
glScissor(x, _glWidget->getDeviceHeight() - y - height, width, height);
glViewport(x, size.height() - y - height, width, height);
glScissor(x, size.height() - y - height, width, height);
}
bool updateViewFrustum = false;
updateProjectionMatrix(_mirrorCamera, updateViewFrustum);
@ -3193,7 +3206,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
}
// reset Viewport and projection matrix
glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight());
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
glDisable(GL_SCISSOR_TEST);
updateProjectionMatrix(_myCamera, updateViewFrustum);
}
@ -4230,3 +4243,7 @@ void Application::takeSnapshot() {
}
_snapshotShareDialog->show();
}
void Application::setRenderResolutionScale(float scale) {
_renderResolutionScale = scale;
}

View file

@ -301,6 +301,8 @@ public:
bool isLookingAtMyAvatar(Avatar* avatar);
float getRenderResolutionScale() const { return _renderResolutionScale; }
signals:
/// Fired when we're simulating; allows external parties to hook in.
@ -363,6 +365,8 @@ public slots:
void domainSettingsReceived(const QJsonObject& domainSettingsObject);
void setRenderResolutionScale(float scale);
void resetSensors();
private slots:
@ -618,6 +622,8 @@ private:
quint64 _lastNackTime;
quint64 _lastSendDownstreamAudioStats;
float _renderResolutionScale;
};
#endif // hifi_Application_h

View file

@ -377,7 +377,15 @@ Menu::Menu() :
shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::SimpleShadows, 0, false));
shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::CascadedShadows, 0, false));
QMenu* resolutionMenu = renderOptionsMenu->addMenu(MenuOption::RenderResolution);
QActionGroup* resolutionGroup = new QActionGroup(resolutionMenu);
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionOne, 0, false));
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionTwoThird, 0, false));
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionHalf, 0, false));
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionThird, 0, true));
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionQuarter, 0, false));
connect(resolutionMenu, SIGNAL(triggered(QAction*)), this, SLOT(changeRenderResolution(QAction*)));
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars, Qt::Key_Asterisk, true);
addCheckableActionToQMenuAndActionHash(renderOptionsMenu,
MenuOption::Voxels,
@ -386,11 +394,7 @@ Menu::Menu() :
appInstance,
SLOT(setRenderVoxels(bool)));
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableGlowEffect, 0, true);
addActionToQMenuAndActionHash(renderOptionsMenu,
MenuOption::GlowMode,
0,
appInstance->getGlowEffect(),
SLOT(cycleRenderMode()));
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Wireframe, Qt::ALT | Qt::Key_W, false);
addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, this, SLOT(lodTools()));
@ -1231,6 +1235,23 @@ void Menu::muteEnvironment() {
free(packet);
}
void Menu::changeRenderResolution(QAction* action) {
QString text = action->text();
if (text == MenuOption::RenderResolutionOne) {
Application::getInstance()->setRenderResolutionScale(1.f);
} else if (text == MenuOption::RenderResolutionTwoThird) {
Application::getInstance()->setRenderResolutionScale(0.666f);
} else if (text == MenuOption::RenderResolutionHalf) {
Application::getInstance()->setRenderResolutionScale(0.5f);
} else if (text == MenuOption::RenderResolutionThird) {
Application::getInstance()->setRenderResolutionScale(0.333f);
} else if (text == MenuOption::RenderResolutionQuarter) {
Application::getInstance()->setRenderResolutionScale(0.25f);
} else {
Application::getInstance()->setRenderResolutionScale(1.f);
}
}
void Menu::displayNameLocationResponse(const QString& errorString) {
if (!errorString.isEmpty()) {

View file

@ -225,6 +225,7 @@ private slots:
void displayAddressOfflineMessage();
void displayAddressNotFoundMessage();
void muteEnvironment();
void changeRenderResolution(QAction* action);
private:
static Menu* _instance;
@ -398,7 +399,6 @@ namespace MenuOption {
const QString FrustumRenderMode = "Render Mode";
const QString Fullscreen = "Fullscreen";
const QString FullscreenMirror = "Fullscreen Mirror";
const QString GlowMode = "Cycle Glow Mode";
const QString GlowWhenSpeaking = "Glow When Speaking";
const QString NamesAboveHeads = "Names Above Heads";
const QString GoToUser = "Go To User";
@ -441,6 +441,12 @@ namespace MenuOption {
const QString RenderHeadCollisionShapes = "Show Head Collision Shapes";
const QString RenderLookAtVectors = "Show Look-at Vectors";
const QString RenderSkeletonCollisionShapes = "Show Skeleton Collision Shapes";
const QString RenderResolution = "Scale Resolution";
const QString RenderResolutionOne = "1";
const QString RenderResolutionTwoThird = "2/3";
const QString RenderResolutionHalf = "1/2";
const QString RenderResolutionThird = "1/3";
const QString RenderResolutionQuarter = "1/4";
const QString ResetAvatarSize = "Reset Avatar Size";
const QString ResetSensors = "Reset Sensors";
const QString RunningScripts = "Running Scripts";

View file

@ -694,7 +694,7 @@ void Avatar::renderDisplayName() {
if (success) {
double textWindowHeight = abs(result1[1] - result0[1]);
float scaleFactor = QApplication::desktop()->windowHandle()->devicePixelRatio() *
float scaleFactor = Application::getInstance()->getRenderResolutionScale() *
((textWindowHeight > EPSILON) ? 1.0f / textWindowHeight : 1.0f);
glScalef(scaleFactor, scaleFactor, 1.0);

View file

@ -23,7 +23,6 @@
GlowEffect::GlowEffect()
: _initialized(false),
_renderMode(DIFFUSE_ADD_MODE),
_isOddFrame(false),
_isFirstFrame(true),
_intensity(0.0f) {
@ -41,9 +40,9 @@ GlowEffect::~GlowEffect() {
}
QOpenGLFramebufferObject* GlowEffect::getFreeFramebufferObject() const {
return (_renderMode == DIFFUSE_ADD_MODE && !_isOddFrame) ?
Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject() :
Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject();
return (_isOddFrame ?
Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject():
Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject());
}
static ProgramObject* createProgram(const QString& name) {
@ -137,31 +136,28 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) {
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
QOpenGLFramebufferObject* destFBO = toTexture ?
Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject() : NULL;
if (!Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect) || (_isEmpty && _renderMode != DIFFUSE_ADD_MODE)) {
if (!Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect) || _isEmpty) {
// copy the primary to the screen
if (QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO);
} else {
maybeBind(destFBO);
if (!destFBO) {
glViewport(0, 0, Application::getInstance()->getGLWidget()->getDeviceWidth(),
Application::getInstance()->getGLWidget()->getDeviceHeight());
}
glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glColor3f(1.0f, 1.0f, 1.0f);
renderFullscreenQuad();
renderFullscreenQuad();
glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
maybeRelease(destFBO);
}
} else if (_renderMode == ADD_MODE) {
maybeBind(destFBO);
_addProgram->bind();
renderFullscreenQuad();
_addProgram->release();
maybeRelease(destFBO);
} else if (_renderMode == DIFFUSE_ADD_MODE) {
} else {
// diffuse into the secondary/tertiary (alternating between frames)
QOpenGLFramebufferObject* oldDiffusedFBO =
Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject();
@ -197,6 +193,11 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) {
destFBO = oldDiffusedFBO;
}
maybeBind(destFBO);
if (!destFBO) {
glViewport(0, 0,
Application::getInstance()->getGLWidget()->getDeviceWidth(),
Application::getInstance()->getGLWidget()->getDeviceHeight());
}
_addSeparateProgram->bind();
renderFullscreenQuad();
_addSeparateProgram->release();
@ -205,70 +206,6 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) {
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
} else { // _renderMode == BLUR_ADD_MODE || _renderMode == BLUR_PERSIST_ADD_MODE
// 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();
if (_renderMode == BLUR_ADD_MODE) {
// render the secondary to the screen with the vertical blur
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture());
if (toTexture) {
destFBO = Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject();
}
maybeBind(destFBO);
_verticalBlurAddProgram->bind();
renderFullscreenQuad();
_verticalBlurAddProgram->release();
maybeRelease(destFBO);
} else { // _renderMode == BLUR_PERSIST_ADD_MODE
// render the secondary to the tertiary with vertical blur and persistence
QOpenGLFramebufferObject* tertiaryFBO =
Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject();
tertiaryFBO->bind();
glEnable(GL_BLEND);
glBlendFunc(GL_ONE_MINUS_CONSTANT_ALPHA, GL_CONSTANT_ALPHA);
const float PERSISTENCE_SMOOTHING = 0.9f;
glBlendColor(0.0f, 0.0f, 0.0f, _isFirstFrame ? 0.0f : PERSISTENCE_SMOOTHING);
glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture());
_verticalBlurProgram->bind();
renderFullscreenQuad();
_verticalBlurProgram->release();
glBlendColor(0.0f, 0.0f, 0.0f, 0.0f);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
glDisable(GL_BLEND);
// now add the tertiary to the primary buffer
tertiaryFBO->release();
glBindTexture(GL_TEXTURE_2D, primaryFBO->texture());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, tertiaryFBO->texture());
maybeBind(destFBO);
_addSeparateProgram->bind();
renderFullscreenQuad();
_addSeparateProgram->release();
maybeRelease(destFBO);
}
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
}
glPopMatrix();
@ -286,28 +223,6 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) {
return destFBO;
}
void GlowEffect::cycleRenderMode() {
switch(_renderMode = (RenderMode)((_renderMode + 1) % RENDER_MODE_COUNT)) {
case ADD_MODE:
qDebug() << "Glow mode: Add";
break;
case BLUR_ADD_MODE:
qDebug() << "Glow mode: Blur/add";
break;
case BLUR_PERSIST_ADD_MODE:
qDebug() << "Glow mode: Blur/persist/add";
break;
default:
case DIFFUSE_ADD_MODE:
qDebug() << "Glow mode: Diffuse/add";
break;
}
_isFirstFrame = true;
}
Glower::Glower(float amount) {
Application::getInstance()->getGlowEffect()->begin(amount);
}

View file

@ -51,17 +51,10 @@ public:
/// \return the framebuffer object to which we rendered, or NULL if to the frame buffer
QOpenGLFramebufferObject* render(bool toTexture = false);
public slots:
void cycleRenderMode();
private:
enum RenderMode { ADD_MODE, BLUR_ADD_MODE, BLUR_PERSIST_ADD_MODE, DIFFUSE_ADD_MODE, RENDER_MODE_COUNT };
bool _initialized;
RenderMode _renderMode;
ProgramObject* _addProgram;
ProgramObject* _horizontalBlurProgram;
ProgramObject* _verticalBlurAddProgram;

View file

@ -210,7 +210,7 @@ QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() {
if (!_primaryFramebufferObject) {
_primaryFramebufferObject = createFramebufferObject();
glGenTextures(1, &_primaryDepthTextureID);
glBindTexture(GL_TEXTURE_2D, _primaryDepthTextureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, _frameBufferSize.width(), _frameBufferSize.height(),

View file

@ -38,6 +38,7 @@ public:
/// Sets the desired texture resolution for the framebuffer objects.
void setFrameBufferSize(QSize frameBufferSize);
const QSize& getFrameBufferSize() const { return _frameBufferSize; }
/// Returns the ID of the permutation/normal texture used for Perlin noise shader programs. This texture
/// has two lines: the first, a set of random numbers in [0, 255] to be used as permutation offsets, and