overte/tests-manual/gpu/src/TestWindow.cpp
2018-05-09 13:20:47 -07:00

194 lines
6.4 KiB
C++

//
// Created by Bradley Austin Davis on 2016/05/16
// Copyright 2014 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 "TestWindow.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <QtCore/QTimer>
#include <QtGui/QResizeEvent>
#include <gl/GLHelpers.h>
#include <gpu/gl/GLBackend.h>
#include <GeometryCache.h>
#include <DeferredLightingEffect.h>
#include <FramebufferCache.h>
#include <TextureCache.h>
#ifdef DEFERRED_LIGHTING
extern void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter);
extern void initStencilPipeline(gpu::PipelinePointer& pipeline);
#endif
TestWindow::TestWindow() {
setSurfaceType(QSurface::OpenGLSurface);
auto timer = new QTimer(this);
timer->setTimerType(Qt::PreciseTimer);
timer->setInterval(5);
connect(timer, &QTimer::timeout, [&] { draw(); });
timer->start();
connect(qApp, &QCoreApplication::aboutToQuit, [this, timer] {
timer->stop();
_aboutToQuit = true;
});
#ifdef DEFERRED_LIGHTING
_light->setType(graphics::Light::SUN);
_light->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset::OLD_TOWN_SQUARE);
_light->setIntensity(1.0f);
_light->setAmbientIntensity(0.5f);
_light->setColor(vec3(1.0f));
_light->setPosition(vec3(1, 1, 1));
_renderContext->args = _renderArgs;
#endif
QSurfaceFormat format = getDefaultOpenGLSurfaceFormat();
format.setOption(QSurfaceFormat::DebugContext);
//format.setSwapInterval(0);
setFormat(format);
_glContext.setFormat(format);
_glContext.create();
_glContext.makeCurrent(this);
show();
}
void TestWindow::initGl() {
_glContext.makeCurrent(this);
gpu::Context::init<gpu::gl::GLBackend>();
_renderArgs->_context = std::make_shared<gpu::Context>();
_glContext.makeCurrent(this);
DependencyManager::set<GeometryCache>();
DependencyManager::set<TextureCache>();
DependencyManager::set<FramebufferCache>();
DependencyManager::set<DeferredLightingEffect>();
resize(QSize(800, 600));
#ifdef DEFERRED_LIGHTING
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
deferredLightingEffect->init();
initDeferredPipelines(*_shapePlumber, nullptr, nullptr);
#endif
}
void TestWindow::resizeWindow(const QSize& size) {
_size = size;
_renderArgs->_viewport = ivec4(0, 0, _size.width(), _size.height());
auto fboCache = DependencyManager::get<FramebufferCache>();
if (fboCache) {
fboCache->setFrameBufferSize(_size);
}
}
void TestWindow::beginFrame() {
#ifdef DEFERRED_LIGHTING
gpu::FramebufferPointer primaryFramebuffer;
_preparePrimaryFramebuffer.run(_renderContext, primaryFramebuffer);
DeferredFrameTransformPointer frameTransform;
_generateDeferredFrameTransform.run(_renderContext, glm::vec2(0.0f, 0.0f), frameTransform);
LightingModelPointer lightingModel;
_generateLightingModel.run(_renderContext, lightingModel);
_prepareDeferredInputs.edit0() = primaryFramebuffer;
_prepareDeferredInputs.edit1() = lightingModel;
_prepareDeferred.run(_renderContext, _prepareDeferredInputs, _prepareDeferredOutputs);
_renderDeferredInputs.edit0() = frameTransform; // Pass the deferredFrameTransform
_renderDeferredInputs.edit1() = _prepareDeferredOutputs.get0(); // Pass the deferredFramebuffer
_renderDeferredInputs.edit2() = lightingModel; // Pass the lightingModel
// the rest of the renderDeferred inputs can be omitted
#else
gpu::doInBatch("TestWindow::beginFrame", _renderArgs->_context, [&](gpu::Batch& batch) {
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLORS, { 0.0f, 0.1f, 0.2f, 1.0f });
batch.clearDepthFramebuffer(1e4);
batch.setViewportTransform({ 0, 0, _size.width() * devicePixelRatio(), _size.height() * devicePixelRatio() });
});
#endif
gpu::doInBatch("TestWindow::beginFrame", _renderArgs->_context, [&](gpu::Batch& batch) {
batch.setViewportTransform(_renderArgs->_viewport);
batch.setStateScissorRect(_renderArgs->_viewport);
batch.setProjectionTransform(_projectionMatrix);
});
}
void TestWindow::endFrame() {
#ifdef DEFERRED_LIGHTING
RenderArgs* args = _renderContext->args;
gpu::doInBatch("TestWindow::endFrame::begin", args->_context, [&](gpu::Batch& batch) {
args->_batch = &batch;
auto deferredFboColorDepthStencil = _prepareDeferredOutputs.get0()->getDeferredFramebufferDepthColor();
batch.setViewportTransform(args->_viewport);
batch.setStateScissorRect(args->_viewport);
batch.setFramebuffer(deferredFboColorDepthStencil);
batch.setPipeline(_opaquePipeline);
batch.draw(gpu::TRIANGLE_STRIP, 4);
batch.setResourceTexture(0, nullptr);
});
_renderDeferred.run(_renderContext, _renderDeferredInputs);
gpu::doInBatch("TestWindow::endFrame::blit", _renderArgs->_context, [&](gpu::Batch& batch) {
PROFILE_RANGE_BATCH(batch, "blit");
// Blit to screen
auto framebufferCache = DependencyManager::get<FramebufferCache>();
// auto framebuffer = framebufferCache->getLightingFramebuffer();
auto framebuffer = _prepareDeferredOutputs.get0()->getLightingFramebuffer();
batch.blit(framebuffer, _renderArgs->_viewport, nullptr, _renderArgs->_viewport);
});
#endif
gpu::doInBatch("TestWindow::endFrame::finish", _renderArgs->_context, [&](gpu::Batch& batch) {
batch.resetStages();
});
_glContext.swapBuffers(this);
}
void TestWindow::draw() {
if (_aboutToQuit) {
return;
}
// Attempting to draw before we're visible and have a valid size will
// produce GL errors.
if (!isVisible() || _size.width() <= 0 || _size.height() <= 0) {
return;
}
if (!_glContext.makeCurrent(this)) {
return;
}
static std::once_flag once;
std::call_once(once, [&] { initGl(); });
beginFrame();
renderFrame();
endFrame();
}
void TestWindow::resizeEvent(QResizeEvent* ev) {
resizeWindow(ev->size());
float fov_degrees = 60.0f;
float aspect_ratio = (float)_size.width() / _size.height();
float near_clip = 0.1f;
float far_clip = 1000.0f;
_projectionMatrix = glm::perspective(glm::radians(fov_degrees), aspect_ratio, near_clip, far_clip);
}