mirror of
https://github.com/overte-org/overte.git
synced 2025-08-13 05:30:18 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into 20628
This commit is contained in:
commit
7966f8c708
79 changed files with 1199 additions and 919 deletions
|
@ -1175,13 +1175,22 @@ void OctreeServer::aboutToFinish() {
|
|||
if (_jurisdictionSender) {
|
||||
_jurisdictionSender->terminating();
|
||||
}
|
||||
|
||||
QSet<SharedNodePointer> nodesToShutdown;
|
||||
|
||||
// force a shutdown of all of our OctreeSendThreads - at this point it has to be impossible for a
|
||||
// linkedDataCreateCallback to be called for a new node
|
||||
nodeList->eachNode([this](const SharedNodePointer& node) {
|
||||
// Force a shutdown of all of our OctreeSendThreads.
|
||||
// At this point it has to be impossible for a linkedDataCreateCallback to be called for a new node
|
||||
nodeList->eachNode([&nodesToShutdown](const SharedNodePointer& node) {
|
||||
nodesToShutdown << node;
|
||||
});
|
||||
|
||||
// What follows is a hack to force OctreeSendThreads to cleanup before the OctreeServer is gone.
|
||||
// I would prefer to allow the SharedNodePointer ref count drop to zero to do this automatically
|
||||
// but that isn't possible as long as the OctreeSendThread has an OctreeServer* that it uses.
|
||||
for (auto& node : nodesToShutdown) {
|
||||
qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *node;
|
||||
forceNodeShutdown(node);
|
||||
});
|
||||
}
|
||||
|
||||
if (_persistThread) {
|
||||
_persistThread->aboutToFinish();
|
||||
|
|
1
cmake/externals/boostconfig/CMakeLists.txt
vendored
1
cmake/externals/boostconfig/CMakeLists.txt
vendored
|
@ -16,3 +16,4 @@ ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
|||
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL)
|
||||
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
|
|
@ -10,15 +10,16 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
|
||||
|
||||
// The area over which the birds will fly
|
||||
var lowerCorner = { x: 1, y: 1, z: 1 };
|
||||
var upperCorner = { x: 10, y: 10, z: 10 };
|
||||
// The rectangular area in the domain where the flock will fly
|
||||
var lowerCorner = { x: 0, y: 0, z: 0 };
|
||||
var upperCorner = { x: 10, y: 10, z: 10 };
|
||||
var STARTING_FRACTION = 0.25;
|
||||
|
||||
var NUM_BIRDS = 50;
|
||||
var UPDATE_INTERVAL = 0.016;
|
||||
var playSounds = true;
|
||||
var SOUND_PROBABILITY = 0.001;
|
||||
var STARTING_LIFETIME = (1.0 / SOUND_PROBABILITY) * UPDATE_INTERVAL * 10;
|
||||
var numPlaying = 0;
|
||||
var BIRD_SIZE = 0.08;
|
||||
var BIRD_MASTER_VOLUME = 0.1;
|
||||
|
@ -35,6 +36,10 @@ var ALIGNMENT_FORCE = 1.5;
|
|||
var COHESION_FORCE = 1.0;
|
||||
var MAX_COHESION_VELOCITY = 0.5;
|
||||
|
||||
var followBirds = true;
|
||||
var AVATAR_FOLLOW_RATE = 0.001;
|
||||
var AVATAR_FOLLOW_VELOCITY_TIMESCALE = 2.0;
|
||||
var AVATAR_FOLLOW_ORIENTATION_RATE = 0.005;
|
||||
var floor = false;
|
||||
var MAKE_FLOOR = false;
|
||||
|
||||
|
@ -43,6 +48,9 @@ var averagePosition = { x: 0, y: 0, z: 0 };
|
|||
|
||||
var birdsLoaded = false;
|
||||
|
||||
var oldAvatarOrientation;
|
||||
var oldAvatarPosition;
|
||||
|
||||
var birds = [];
|
||||
var playing = [];
|
||||
|
||||
|
@ -115,8 +123,9 @@ function updateBirds(deltaTime) {
|
|||
birds[i].audioId = Audio.playSound(birds[i].sound, options);
|
||||
}
|
||||
numPlaying++;
|
||||
// Change size
|
||||
Entities.editEntity(birds[i].entityId, { dimensions: Vec3.multiply(1.5, properties.dimensions)});
|
||||
// Change size, and update lifetime to keep bird alive
|
||||
Entities.editEntity(birds[i].entityId, { dimensions: Vec3.multiply(1.5, properties.dimensions),
|
||||
lifetime: properties.ageInSeconds + STARTING_LIFETIME});
|
||||
|
||||
} else if (birds[i].audioId) {
|
||||
// If bird is playing a chirp
|
||||
|
@ -166,10 +175,24 @@ function updateBirds(deltaTime) {
|
|||
if (birdVelocitiesCounted > 0) {
|
||||
averageVelocity = Vec3.multiply(1.0 / birdVelocitiesCounted, sumVelocity);
|
||||
//print(Vec3.length(averageVelocity));
|
||||
if (followBirds) {
|
||||
MyAvatar.motorVelocity = averageVelocity;
|
||||
MyAvatar.motorTimescale = AVATAR_FOLLOW_VELOCITY_TIMESCALE;
|
||||
var polarAngles = Vec3.toPolar(Vec3.normalize(averageVelocity));
|
||||
if (!isNaN(polarAngles.x) && !isNaN(polarAngles.y)) {
|
||||
var birdDirection = Quat.fromPitchYawRollRadians(polarAngles.x, polarAngles.y + Math.PI, polarAngles.z);
|
||||
MyAvatar.orientation = Quat.mix(MyAvatar.orientation, birdDirection, AVATAR_FOLLOW_ORIENTATION_RATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (birdPositionsCounted > 0) {
|
||||
averagePosition = Vec3.multiply(1.0 / birdPositionsCounted, sumPosition);
|
||||
// If Following birds, update position
|
||||
if (followBirds) {
|
||||
MyAvatar.position = Vec3.sum(Vec3.multiply(AVATAR_FOLLOW_RATE, MyAvatar.position), Vec3.multiply(1.0 - AVATAR_FOLLOW_RATE, averagePosition));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Connect a call back that happens every frame
|
||||
|
@ -183,11 +206,14 @@ Script.scriptEnding.connect(function() {
|
|||
if (floor) {
|
||||
Entities.deleteEntity(floor);
|
||||
}
|
||||
MyAvatar.orientation = oldAvatarOrientation;
|
||||
MyAvatar.position = oldAvatarPosition;
|
||||
});
|
||||
|
||||
function loadBirds(howMany) {
|
||||
while (!Entities.serversExist() || !Entities.canRez()) {
|
||||
}
|
||||
oldAvatarOrientation = MyAvatar.orientation;
|
||||
oldAvatarPosition = MyAvatar.position;
|
||||
|
||||
var sound_filenames = ["bushtit_1.raw", "bushtit_2.raw", "bushtit_3.raw"];
|
||||
/* Here are more sounds/species you can use
|
||||
, "mexicanWhipoorwill.raw",
|
||||
|
@ -247,6 +273,7 @@ function loadBirds(howMany) {
|
|||
velocity: { x: 0, y: -0.1, z: 0 },
|
||||
linearDamping: LINEAR_DAMPING,
|
||||
collisionsWillMove: true,
|
||||
lifetime: STARTING_LIFETIME,
|
||||
color: colors[whichBird]
|
||||
}),
|
||||
audioId: false,
|
||||
|
|
|
@ -318,11 +318,15 @@ var toolBar = (function () {
|
|||
print("Resize failed: timed out waiting for model (" + url + ") to load");
|
||||
}
|
||||
} else {
|
||||
entityProperties.dimensions = naturalDimensions;
|
||||
Entities.editEntity(entityId, entityProperties);
|
||||
Entities.editEntity(entityId, { dimensions: naturalDimensions });
|
||||
|
||||
// Reset selection so that the selection overlays will be updated
|
||||
selectionManager.setSelections([entityId]);
|
||||
}
|
||||
}
|
||||
|
||||
selectionManager.setSelections([entityId]);
|
||||
|
||||
Script.setTimeout(resize, RESIZE_INTERVAL);
|
||||
} else {
|
||||
print("Can't add model: Model would be out of bounds.");
|
||||
|
|
|
@ -35,8 +35,32 @@
|
|||
function onRowClicked(e) {
|
||||
var id = this.dataset.entityId;
|
||||
var selection = [this.dataset.entityId];
|
||||
if (e.shiftKey) {
|
||||
if (e.ctrlKey) {
|
||||
selection = selection.concat(selectedEntities);
|
||||
} else if (e.shiftKey && selectedEntities.length > 0) {
|
||||
var previousItemFound = -1;
|
||||
var clickedItemFound = -1;
|
||||
for (var i in entityList.visibleItems) {
|
||||
if (clickedItemFound === -1 && this.dataset.entityId == entityList.visibleItems[i].values().id) {
|
||||
clickedItemFound = i;
|
||||
} else if(previousItemFound === -1 && selectedEntities[0] == entityList.visibleItems[i].values().id) {
|
||||
previousItemFound = i;
|
||||
}
|
||||
}
|
||||
if (previousItemFound !== -1 && clickedItemFound !== -1) {
|
||||
var betweenItems = [];
|
||||
var toItem = Math.max(previousItemFound, clickedItemFound);
|
||||
// skip first and last item in this loop, we add them to selection after the loop
|
||||
for (var i = (Math.min(previousItemFound, clickedItemFound) + 1); i < toItem; i++) {
|
||||
entityList.visibleItems[i].elm.className = 'selected';
|
||||
betweenItems.push(entityList.visibleItems[i].values().id);
|
||||
}
|
||||
if (previousItemFound > clickedItemFound) {
|
||||
// always make sure that we add the items in the right order
|
||||
betweenItems.reverse();
|
||||
}
|
||||
selection = selection.concat(betweenItems, selectedEntities);
|
||||
}
|
||||
}
|
||||
|
||||
selectedEntities = selection;
|
||||
|
@ -151,6 +175,17 @@
|
|||
refreshEntities();
|
||||
}
|
||||
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if (e.target.nodeName === "INPUT") {
|
||||
return;
|
||||
}
|
||||
var keyCode = e.keyCode;
|
||||
if (keyCode === 46) {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
|
||||
refreshEntities();
|
||||
}
|
||||
}, false);
|
||||
|
||||
if (window.EventBridge !== undefined) {
|
||||
EventBridge.scriptEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
|
|
|
@ -9,11 +9,9 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <sstream>
|
||||
#include "Application.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <cmath>
|
||||
#include <math.h>
|
||||
#include <sstream>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/component_wise.hpp>
|
||||
|
@ -61,6 +59,7 @@
|
|||
#include <DependencyManager.h>
|
||||
#include <EntityScriptingInterface.h>
|
||||
#include <ErrorDialog.h>
|
||||
#include <FramebufferCache.h>
|
||||
#include <gpu/Batch.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <gpu/GLBackend.h>
|
||||
|
@ -87,12 +86,12 @@
|
|||
#include <SettingHandle.h>
|
||||
#include <SimpleAverage.h>
|
||||
#include <SoundCache.h>
|
||||
#include <TextureCache.h>
|
||||
#include <Tooltip.h>
|
||||
#include <UserActivityLogger.h>
|
||||
#include <UUID.h>
|
||||
#include <VrMenu.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "AudioClient.h"
|
||||
#include "DiscoverabilityManager.h"
|
||||
#include "GLCanvas.h"
|
||||
|
@ -266,6 +265,8 @@ bool setupEssentials(int& argc, char** argv) {
|
|||
auto audioScope = DependencyManager::set<AudioScope>();
|
||||
auto deferredLightingEffect = DependencyManager::set<DeferredLightingEffect>();
|
||||
auto textureCache = DependencyManager::set<TextureCache>();
|
||||
auto framebufferCache = DependencyManager::set<FramebufferCache>();
|
||||
|
||||
auto animationCache = DependencyManager::set<AnimationCache>();
|
||||
auto ddeFaceTracker = DependencyManager::set<DdeFaceTracker>();
|
||||
auto modelBlender = DependencyManager::set<ModelBlender>();
|
||||
|
@ -732,6 +733,7 @@ Application::~Application() {
|
|||
DependencyManager::destroy<OffscreenUi>();
|
||||
DependencyManager::destroy<AvatarManager>();
|
||||
DependencyManager::destroy<AnimationCache>();
|
||||
DependencyManager::destroy<FramebufferCache>();
|
||||
DependencyManager::destroy<TextureCache>();
|
||||
DependencyManager::destroy<GeometryCache>();
|
||||
DependencyManager::destroy<ScriptCache>();
|
||||
|
@ -765,32 +767,8 @@ void Application::initializeGL() {
|
|||
}
|
||||
#endif
|
||||
|
||||
qCDebug(interfaceapp) << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
|
||||
qCDebug(interfaceapp) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
qCDebug(interfaceapp) << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR));
|
||||
qCDebug(interfaceapp) << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
|
||||
|
||||
#ifdef WIN32
|
||||
GLenum err = glewInit();
|
||||
if (GLEW_OK != err) {
|
||||
/* Problem: glewInit failed, something is seriously wrong. */
|
||||
qCDebug(interfaceapp, "Error: %s\n", glewGetErrorString(err));
|
||||
}
|
||||
qCDebug(interfaceapp, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
|
||||
|
||||
if (wglewGetExtension("WGL_EXT_swap_control")) {
|
||||
int swapInterval = wglGetSwapIntervalEXT();
|
||||
qCDebug(interfaceapp, "V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF"));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
// TODO: Write the correct code for Linux...
|
||||
/* if (wglewGetExtension("WGL_EXT_swap_control")) {
|
||||
int swapInterval = wglGetSwapIntervalEXT();
|
||||
qCDebug(interfaceapp, "V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF"));
|
||||
}*/
|
||||
#endif
|
||||
// Where the gpuContext is created and where the TRUE Backend is created and assigned
|
||||
_gpuContext = std::make_shared<gpu::Context>(new gpu::GLBackend());
|
||||
|
||||
initDisplay();
|
||||
qCDebug(interfaceapp, "Initialized Display.");
|
||||
|
@ -879,8 +857,9 @@ void Application::paintGL() {
|
|||
_glWidget->makeCurrent();
|
||||
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
gpu::Context context(new gpu::GLBackend());
|
||||
RenderArgs renderArgs(&context, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(),
|
||||
|
||||
|
||||
RenderArgs renderArgs(_gpuContext, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(),
|
||||
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
||||
|
||||
|
@ -896,24 +875,50 @@ void Application::paintGL() {
|
|||
PerformanceWarning warn(showWarnings, "Application::paintGL()");
|
||||
resizeGL();
|
||||
|
||||
// Before anything else, let's sync up the gpuContext with the true glcontext used in case anything happened
|
||||
renderArgs._context->syncCache();
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) {
|
||||
auto primaryFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferDepthColor();
|
||||
|
||||
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
||||
renderRearViewMirror(&renderArgs, _mirrorViewRect);
|
||||
renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
|
||||
|
||||
{
|
||||
float ratio = ((float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale());
|
||||
auto mirrorViewport = glm::ivec4(0, 0, _mirrorViewRect.width() * ratio, _mirrorViewRect.height() * ratio);
|
||||
auto mirrorViewportDest = mirrorViewport;
|
||||
|
||||
auto selfieFbo = DependencyManager::get<FramebufferCache>()->getSelfieFramebuffer();
|
||||
gpu::Batch batch;
|
||||
batch.setFramebuffer(selfieFbo);
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
batch.blit(primaryFbo, mirrorViewport, selfieFbo, mirrorViewportDest);
|
||||
batch.setFramebuffer(nullptr);
|
||||
renderArgs._context->render(batch);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("renderOverlay");
|
||||
|
||||
// NOTE: There is no batch associated with this renderArgs
|
||||
// the ApplicationOverlay class assumes it's viewport is setup to be the device size
|
||||
QSize size = qApp->getDeviceSize();
|
||||
renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height());
|
||||
renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height());
|
||||
_applicationOverlay.renderOverlay(&renderArgs);
|
||||
}
|
||||
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
||||
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, _myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN);
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !(_myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN));
|
||||
Application::getInstance()->cameraMenuChanged();
|
||||
}
|
||||
|
||||
// The render mode is default or mirror if the camera is in mirror mode, assigned further below
|
||||
renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
|
||||
|
||||
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||
// Always use the default eye position, not the actual head eye position.
|
||||
// Using the latter will cause the camera to wobble with idle animations,
|
||||
|
@ -950,6 +955,7 @@ void Application::paintGL() {
|
|||
glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) +
|
||||
(_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
|
||||
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
||||
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
||||
}
|
||||
|
||||
// Update camera position
|
||||
|
@ -957,13 +963,6 @@ void Application::paintGL() {
|
|||
_myCamera.update(1.0f / _fps);
|
||||
}
|
||||
|
||||
// Sync up the View Furstum with the camera
|
||||
// FIXME: it's happening again in the updateSHadow and it shouldn't, this should be the place
|
||||
loadViewFrustum(_myCamera, _viewFrustum);
|
||||
|
||||
|
||||
renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
|
||||
|
||||
if (OculusManager::isConnected()) {
|
||||
//When in mirror mode, use camera rotation. Otherwise, use body rotation
|
||||
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
|
@ -975,47 +974,28 @@ void Application::paintGL() {
|
|||
TV3DManager::display(&renderArgs, _myCamera);
|
||||
} else {
|
||||
PROFILE_RANGE(__FUNCTION__ "/mainRender");
|
||||
// Viewport is assigned to the size of the framebuffer
|
||||
QSize size = DependencyManager::get<FramebufferCache>()->getFrameBufferSize();
|
||||
renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height());
|
||||
|
||||
{
|
||||
gpu::Batch batch;
|
||||
auto primaryFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||
batch.setFramebuffer(primaryFbo);
|
||||
// clear the normal and specular buffers
|
||||
batch.clearFramebuffer(
|
||||
gpu::Framebuffer::BUFFER_COLOR0 |
|
||||
gpu::Framebuffer::BUFFER_COLOR1 |
|
||||
gpu::Framebuffer::BUFFER_COLOR2 |
|
||||
gpu::Framebuffer::BUFFER_DEPTH,
|
||||
vec4(vec3(0), 1), 1.0, 0.0);
|
||||
|
||||
// Viewport is assigned to the size of the framebuffer
|
||||
QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize();
|
||||
renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height());
|
||||
batch.setViewportTransform(renderArgs._viewport);
|
||||
renderArgs._context->render(batch);
|
||||
}
|
||||
|
||||
displaySide(&renderArgs, _myCamera);
|
||||
|
||||
if (_myCamera.getMode() != CAMERA_MODE_MIRROR && Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) {
|
||||
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
||||
renderRearViewMirror(&renderArgs, _mirrorViewRect);
|
||||
renderArgs._renderMode = RenderArgs::NORMAL_RENDER_MODE;
|
||||
}
|
||||
|
||||
{
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto primaryFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||
auto primaryFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferDepthColor();
|
||||
gpu::Batch batch;
|
||||
batch.blit(primaryFbo, glm::ivec4(0, 0, _renderResolution.x, _renderResolution.y),
|
||||
nullptr, glm::ivec4(0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height()));
|
||||
|
||||
batch.setFramebuffer(nullptr);
|
||||
|
||||
renderArgs._context->render(batch);
|
||||
}
|
||||
|
||||
_compositor.displayOverlayTexture(&renderArgs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!OculusManager::isConnected() || OculusManager::allowSwap()) {
|
||||
PROFILE_RANGE(__FUNCTION__ "/bufferSwap");
|
||||
_glWidget->swapBuffers();
|
||||
|
@ -1025,6 +1005,7 @@ void Application::paintGL() {
|
|||
OculusManager::endFrameTiming();
|
||||
}
|
||||
_frameCount++;
|
||||
_numFramesSinceLastResize++;
|
||||
Stats::getInstance()->setRenderDetails(renderArgs._details);
|
||||
}
|
||||
|
||||
|
@ -1078,8 +1059,9 @@ void Application::resizeGL() {
|
|||
}
|
||||
|
||||
if (_renderResolution != toGlm(renderSize)) {
|
||||
_numFramesSinceLastResize = 0;
|
||||
_renderResolution = toGlm(renderSize);
|
||||
DependencyManager::get<TextureCache>()->setFrameBufferSize(renderSize);
|
||||
DependencyManager::get<FramebufferCache>()->setFrameBufferSize(renderSize);
|
||||
|
||||
loadViewFrustum(_myCamera, _viewFrustum);
|
||||
}
|
||||
|
@ -1091,7 +1073,6 @@ void Application::resizeGL() {
|
|||
auto canvasSize = _glWidget->size();
|
||||
offscreenUi->resize(canvasSize);
|
||||
_glWidget->makeCurrent();
|
||||
|
||||
}
|
||||
|
||||
bool Application::importSVOFromURL(const QString& urlString) {
|
||||
|
@ -1845,11 +1826,15 @@ void Application::idle() {
|
|||
_idleLoopMeasuredJitter = _idleLoopStdev.getStDev();
|
||||
_idleLoopStdev.reset();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// After finishing all of the above work, ensure the idle timer is set to the proper interval,
|
||||
// depending on whether we're throttling or not
|
||||
idleTimer->start(_glWidget->isThrottleRendering() ? THROTTLED_IDLE_TIMER_DELAY : 1);
|
||||
// depending on whether we're throttling or not.
|
||||
// Once rendering is off on another thread we should be able to have Application::idle run at start(0) in
|
||||
// perpetuity and not expect events to get backed up.
|
||||
|
||||
static const int IDLE_TIMER_DELAY_MS = 2;
|
||||
idleTimer->start(_glWidget->isThrottleRendering() ? THROTTLED_IDLE_TIMER_DELAY : IDLE_TIMER_DELAY_MS);
|
||||
}
|
||||
|
||||
// check for any requested background downloads.
|
||||
|
@ -2326,23 +2311,21 @@ void Application::updateMyAvatarLookAtPosition() {
|
|||
lookAtSpot = _myAvatar->getHead()->getEyePosition() +
|
||||
(_myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE));
|
||||
}
|
||||
}
|
||||
|
||||
// Deflect the eyes a bit to match the detected gaze from Faceshift if active.
|
||||
// DDE doesn't track eyes.
|
||||
if (tracker && typeid(*tracker) == typeid(Faceshift) && !tracker->isMuted()) {
|
||||
float eyePitch = tracker->getEstimatedEyePitch();
|
||||
float eyeYaw = tracker->getEstimatedEyeYaw();
|
||||
const float GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT = 0.1f;
|
||||
glm::vec3 origin = _myAvatar->getHead()->getEyePosition();
|
||||
float pitchSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? -1.0f : 1.0f;
|
||||
float deflection = DependencyManager::get<Faceshift>()->getEyeDeflection();
|
||||
if (isLookingAtSomeone) {
|
||||
deflection *= GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT;
|
||||
}
|
||||
lookAtSpot = origin + _myCamera.getRotation() * glm::quat(glm::radians(glm::vec3(
|
||||
eyePitch * pitchSign * deflection, eyeYaw * deflection, 0.0f))) *
|
||||
// Deflect the eyes a bit to match the detected gaze from the face tracker if active.
|
||||
if (tracker && !tracker->isMuted()) {
|
||||
float eyePitch = tracker->getEstimatedEyePitch();
|
||||
float eyeYaw = tracker->getEstimatedEyeYaw();
|
||||
const float GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT = 0.1f;
|
||||
glm::vec3 origin = _myAvatar->getHead()->getEyePosition();
|
||||
float deflection = tracker->getEyeDeflection();
|
||||
if (isLookingAtSomeone) {
|
||||
deflection *= GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT;
|
||||
}
|
||||
lookAtSpot = origin + _myCamera.getRotation() * glm::quat(glm::radians(glm::vec3(
|
||||
eyePitch * deflection, eyeYaw * deflection, 0.0f))) *
|
||||
glm::inverse(_myCamera.getRotation()) * (lookAtSpot - origin);
|
||||
}
|
||||
}
|
||||
|
||||
_myAvatar->getHead()->setLookAtPosition(lookAtSpot);
|
||||
|
@ -2503,10 +2486,18 @@ void Application::update(float deltaTime) {
|
|||
_myAvatar->setDriveKeys(DOWN, _userInputMapper.getActionState(UserInputMapper::VERTICAL_DOWN));
|
||||
_myAvatar->setDriveKeys(LEFT, _userInputMapper.getActionState(UserInputMapper::LATERAL_LEFT));
|
||||
_myAvatar->setDriveKeys(RIGHT, _userInputMapper.getActionState(UserInputMapper::LATERAL_RIGHT));
|
||||
_myAvatar->setDriveKeys(ROT_UP, _userInputMapper.getActionState(UserInputMapper::PITCH_UP));
|
||||
_myAvatar->setDriveKeys(ROT_DOWN, _userInputMapper.getActionState(UserInputMapper::PITCH_DOWN));
|
||||
_myAvatar->setDriveKeys(ROT_LEFT, _userInputMapper.getActionState(UserInputMapper::YAW_LEFT));
|
||||
_myAvatar->setDriveKeys(ROT_RIGHT, _userInputMapper.getActionState(UserInputMapper::YAW_RIGHT));
|
||||
if (deltaTime > FLT_EPSILON) {
|
||||
// For rotations what we really want are meausures of "angles per second" (in order to prevent
|
||||
// fps-dependent spin rates) so we need to scale the units of the controller contribution.
|
||||
// (TODO?: maybe we should similarly scale ALL action state info, or change the expected behavior
|
||||
// controllers to provide a delta_per_second value rather than a raw delta.)
|
||||
const float EXPECTED_FRAME_RATE = 60.0f;
|
||||
float timeFactor = EXPECTED_FRAME_RATE * deltaTime;
|
||||
_myAvatar->setDriveKeys(ROT_UP, _userInputMapper.getActionState(UserInputMapper::PITCH_UP) / timeFactor);
|
||||
_myAvatar->setDriveKeys(ROT_DOWN, _userInputMapper.getActionState(UserInputMapper::PITCH_DOWN) / timeFactor);
|
||||
_myAvatar->setDriveKeys(ROT_LEFT, _userInputMapper.getActionState(UserInputMapper::YAW_LEFT) / timeFactor);
|
||||
_myAvatar->setDriveKeys(ROT_RIGHT, _userInputMapper.getActionState(UserInputMapper::YAW_RIGHT) / timeFactor);
|
||||
}
|
||||
}
|
||||
_myAvatar->setDriveKeys(BOOM_IN, _userInputMapper.getActionState(UserInputMapper::BOOM_IN));
|
||||
_myAvatar->setDriveKeys(BOOM_OUT, _userInputMapper.getActionState(UserInputMapper::BOOM_OUT));
|
||||
|
@ -2971,35 +2962,25 @@ PickRay Application::computePickRay(float x, float y) const {
|
|||
if (isHMDMode()) {
|
||||
getApplicationCompositor().computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction);
|
||||
} else {
|
||||
if (QThread::currentThread() == activeRenderingThread) {
|
||||
getDisplayViewFrustum()->computePickRay(x, y, result.origin, result.direction);
|
||||
} else {
|
||||
getViewFrustum()->computePickRay(x, y, result.origin, result.direction);
|
||||
}
|
||||
getViewFrustum()->computePickRay(x, y, result.origin, result.direction);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) {
|
||||
auto primaryFramebuffer = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer));
|
||||
|
||||
// clear the alpha channel so the background is transparent
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
|
||||
|
||||
const int BILLBOARD_SIZE = 64;
|
||||
// TODO: Pass a RenderArgs to renderAvatarBillboard
|
||||
renderRearViewMirror(renderArgs, QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE,
|
||||
BILLBOARD_SIZE, BILLBOARD_SIZE),
|
||||
true);
|
||||
QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32);
|
||||
glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits());
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
// Need to make sure the gl context is current here
|
||||
_glWidget->makeCurrent();
|
||||
|
||||
renderArgs->_renderMode = RenderArgs::DEFAULT_RENDER_MODE;
|
||||
renderRearViewMirror(renderArgs, QRect(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE), true);
|
||||
|
||||
auto primaryFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferDepthColor();
|
||||
QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32);
|
||||
renderArgs->_context->downloadFramebuffer(primaryFbo, glm::ivec4(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE), image);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
@ -3172,10 +3153,6 @@ namespace render {
|
|||
model::Skybox::render(batch, *(Application::getInstance()->getDisplayViewFrustum()), *skybox);
|
||||
}
|
||||
}
|
||||
// FIX ME - If I don't call this renderBatch() here, then the atmosphere and skybox don't render, but it
|
||||
// seems like these payloadRender() methods shouldn't be doing this. We need to investigate why the engine
|
||||
// isn't rendering our batch
|
||||
gpu::GLBackend::renderBatch(batch, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3307,10 +3284,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
sceneInterface->setEngineFeedOverlay3DItems(engineRC->_numFeedOverlay3DItems);
|
||||
sceneInterface->setEngineDrawnOverlay3DItems(engineRC->_numDrawnOverlay3DItems);
|
||||
}
|
||||
//Render the sixense lasers
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) {
|
||||
_myAvatar->renderLaserPointers(*renderArgs->_batch);
|
||||
}
|
||||
|
||||
if (!selfAvatarOnly) {
|
||||
// give external parties a change to hook in
|
||||
|
@ -3416,40 +3389,24 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi
|
|||
// set the bounds of rear mirror view
|
||||
gpu::Vec4i viewport;
|
||||
if (billboard) {
|
||||
QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize();
|
||||
viewport = gpu::Vec4i(region.x(), size.height() - region.y() - region.height(), region.width(), region.height());
|
||||
QSize size = DependencyManager::get<FramebufferCache>()->getFrameBufferSize();
|
||||
viewport = gpu::Vec4i(0, 0, region.width(), region.height());
|
||||
} else {
|
||||
// if not rendering the billboard, the region is in device independent coordinates; must convert to device
|
||||
QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize();
|
||||
QSize size = DependencyManager::get<FramebufferCache>()->getFrameBufferSize();
|
||||
float ratio = (float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale();
|
||||
int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio;
|
||||
viewport = gpu::Vec4i(x, size.height() - y - height, width, height);
|
||||
int x = region.x() * ratio;
|
||||
int y = region.y() * ratio;
|
||||
int width = region.width() * ratio;
|
||||
int height = region.height() * ratio;
|
||||
viewport = gpu::Vec4i(0, 0, width, height);
|
||||
}
|
||||
renderArgs->_viewport = viewport;
|
||||
|
||||
{
|
||||
gpu::Batch batch;
|
||||
batch.setViewportTransform(viewport);
|
||||
batch.setStateScissorRect(viewport);
|
||||
batch.clearFramebuffer(
|
||||
gpu::Framebuffer::BUFFER_COLOR0 |
|
||||
gpu::Framebuffer::BUFFER_COLOR1 |
|
||||
gpu::Framebuffer::BUFFER_COLOR2 |
|
||||
gpu::Framebuffer::BUFFER_DEPTH,
|
||||
vec4(vec3(0), 1), 1.0, 0.0, true);
|
||||
// Viewport is assigned to the size of the framebuffer
|
||||
renderArgs->_context->render(batch);
|
||||
}
|
||||
|
||||
bool updateViewFrustum = false;
|
||||
loadViewFrustum(_mirrorCamera, _viewFrustum);
|
||||
|
||||
|
||||
// render rear mirror view
|
||||
displaySide(renderArgs, _mirrorCamera, true, billboard);
|
||||
|
||||
renderArgs->_viewport = originalViewport;
|
||||
|
||||
}
|
||||
|
||||
void Application::resetSensors() {
|
||||
|
@ -4474,7 +4431,11 @@ void Application::friendsWindowClosed() {
|
|||
}
|
||||
|
||||
void Application::postLambdaEvent(std::function<void()> f) {
|
||||
QCoreApplication::postEvent(this, new LambdaEvent(f));
|
||||
if (this->thread() == QThread::currentThread()) {
|
||||
f();
|
||||
} else {
|
||||
QCoreApplication::postEvent(this, new LambdaEvent(f));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::initPlugins() {
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <ScriptEngine.h>
|
||||
#include <ShapeManager.h>
|
||||
#include <StDev.h>
|
||||
#include <TextureCache.h>
|
||||
#include <udt/PacketHeaders.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
|
@ -69,6 +68,7 @@
|
|||
#include "octree/OctreePacketProcessor.h"
|
||||
#include "UndoStackScriptingInterface.h"
|
||||
|
||||
#include "gpu/Context.h"
|
||||
#include "render/Engine.h"
|
||||
|
||||
class QGLWidget;
|
||||
|
@ -326,6 +326,10 @@ public:
|
|||
|
||||
render::ScenePointer getMain3DScene() const { return _main3DScene; }
|
||||
|
||||
gpu::ContextPointer getGPUContext() const { return _gpuContext; }
|
||||
|
||||
const QRect& getMirrorViewRect() const { return _mirrorViewRect; }
|
||||
|
||||
signals:
|
||||
|
||||
/// Fired when we're simulating; allows external parties to hook in.
|
||||
|
@ -482,6 +486,7 @@ private:
|
|||
glm::vec3 getSunDirection();
|
||||
|
||||
void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard = false);
|
||||
|
||||
void setMenuShortcutsEnabled(bool enabled);
|
||||
|
||||
static void attachNewHeadToNode(Node *newNode);
|
||||
|
@ -632,10 +637,12 @@ private:
|
|||
|
||||
render::ScenePointer _main3DScene{ new render::Scene() };
|
||||
render::EnginePointer _renderEngine{ new render::Engine() };
|
||||
gpu::ContextPointer _gpuContext; // initialized during window creation
|
||||
|
||||
Overlays _overlays;
|
||||
ApplicationOverlay _applicationOverlay;
|
||||
ApplicationCompositor _compositor;
|
||||
int _numFramesSinceLastResize = 0;
|
||||
};
|
||||
|
||||
#endif // hifi_Application_h
|
||||
|
|
|
@ -478,7 +478,6 @@ Menu::Menu() {
|
|||
qApp,
|
||||
SLOT(setLowVelocityFilter(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseMouseInput, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseLasers, 0, false);
|
||||
|
||||
MenuWrapper* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion");
|
||||
addCheckableActionToQMenuAndActionHash(leapOptionsMenu, MenuOption::LeapMotionOnHMD, 0, false);
|
||||
|
|
|
@ -272,7 +272,6 @@ namespace MenuOption {
|
|||
const QString SimpleShadows = "Simple";
|
||||
const QString SixenseEnabled = "Enable Hydra Support";
|
||||
const QString SixenseMouseInput = "Enable Sixense Mouse Input";
|
||||
const QString SixenseLasers = "Enable Sixense UI Lasers";
|
||||
const QString ShiftHipsForIdleAnimations = "Shift hips for idle animations";
|
||||
const QString Stars = "Stars";
|
||||
const QString Stats = "Stats";
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <mutex>
|
||||
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#include <gpu/GPUConfig.h>
|
||||
#include <gpu/Batch.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <NumericalConstants.h>
|
||||
|
@ -24,14 +24,17 @@
|
|||
#include <RenderArgs.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include "../../libraries/render-utils/standardTransformPNTC_vert.h"
|
||||
#include "../../libraries/render-utils/stars_vert.h"
|
||||
#include "../../libraries/render-utils/stars_frag.h"
|
||||
|
||||
#include "../../libraries/render-utils/standardTransformPNTC_vert.h"
|
||||
#include "../../libraries/render-utils/starsGrid_frag.h"
|
||||
|
||||
//static const float TILT = 0.23f;
|
||||
static const float TILT = 0.0f;
|
||||
static const unsigned int STARFIELD_NUM_STARS = 50000;
|
||||
static const unsigned int STARFIELD_SEED = 1;
|
||||
//static const float STAR_COLORIZATION = 0.1f;
|
||||
static const float STAR_COLORIZATION = 0.1f;
|
||||
|
||||
static const float TAU = 6.28318530717958f;
|
||||
//static const float HALF_TAU = TAU / 2.0f;
|
||||
|
@ -109,52 +112,81 @@ unsigned computeStarColor(float colorization) {
|
|||
return red | (green << 8) | (blue << 16);
|
||||
}
|
||||
|
||||
struct StarVertex {
|
||||
vec4 position;
|
||||
vec4 colorAndSize;
|
||||
};
|
||||
|
||||
// FIXME star colors
|
||||
void Stars::render(RenderArgs* renderArgs, float alpha) {
|
||||
static gpu::BufferPointer vertexBuffer;
|
||||
static gpu::Stream::FormatPointer streamFormat;
|
||||
static gpu::Element positionElement, colorElement;
|
||||
static gpu::PipelinePointer _pipeline;
|
||||
static gpu::PipelinePointer _gridPipeline;
|
||||
static gpu::PipelinePointer _starsPipeline;
|
||||
static int32_t _timeSlot{ -1 };
|
||||
static std::once_flag once;
|
||||
|
||||
const int VERTICES_SLOT = 0;
|
||||
//const int COLOR_SLOT = 2;
|
||||
const int COLOR_SLOT = 1;
|
||||
|
||||
std::call_once(once, [&] {
|
||||
{
|
||||
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert)));
|
||||
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(starsGrid_frag)));
|
||||
auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
|
||||
gpu::Shader::makeProgram((*program));
|
||||
_timeSlot = program->getBuffers().findLocation(UNIFORM_TIME_NAME);
|
||||
if (_timeSlot == gpu::Shader::INVALID_LOCATION) {
|
||||
_timeSlot = program->getUniforms().findLocation(UNIFORM_TIME_NAME);
|
||||
}
|
||||
auto state = gpu::StatePointer(new gpu::State());
|
||||
// enable decal blend
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_gridPipeline.reset(gpu::Pipeline::create(program, state));
|
||||
}
|
||||
{
|
||||
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(stars_vert)));
|
||||
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(stars_frag)));
|
||||
auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
|
||||
gpu::Shader::makeProgram((*program));
|
||||
auto state = gpu::StatePointer(new gpu::State());
|
||||
// enable decal blend
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_starsPipeline.reset(gpu::Pipeline::create(program, state));
|
||||
|
||||
}
|
||||
|
||||
QElapsedTimer startTime;
|
||||
startTime.start();
|
||||
vertexBuffer.reset(new gpu::Buffer);
|
||||
|
||||
srand(STARFIELD_SEED);
|
||||
unsigned limit = STARFIELD_NUM_STARS;
|
||||
std::vector<vec3> points;
|
||||
std::vector<StarVertex> points;
|
||||
points.resize(limit);
|
||||
for (size_t star = 0; star < limit; ++star) {
|
||||
points[star] = fromPolar(randPolar());
|
||||
//auto color = computeStarColor(STAR_COLORIZATION);
|
||||
//vertexBuffer->append(sizeof(color), (const gpu::Byte*)&color);
|
||||
points[star].position = vec4(fromPolar(randPolar()), 1);
|
||||
float size = frand() * 2.5f + 0.5f;
|
||||
if (frand() < STAR_COLORIZATION) {
|
||||
vec3 color(frand() / 2.0f + 0.5f, frand() / 2.0f + 0.5f, frand() / 2.0f + 0.5f);
|
||||
points[star].colorAndSize = vec4(color, size);
|
||||
} else {
|
||||
vec3 color(frand() / 2.0f + 0.5f);
|
||||
points[star].colorAndSize = vec4(color, size);
|
||||
}
|
||||
}
|
||||
vertexBuffer->append(sizeof(vec3) * limit, (const gpu::Byte*)&points[0]);
|
||||
streamFormat.reset(new gpu::Stream::Format()); // 1 for everyone
|
||||
streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
||||
positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element;
|
||||
double timeDiff = (double)startTime.nsecsElapsed() / 1000000.0; // ns to ms
|
||||
qDebug() << "Total time to generate stars: " << timeDiff << " msec";
|
||||
|
||||
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert)));
|
||||
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(stars_frag)));
|
||||
auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
|
||||
gpu::Shader::makeProgram((*program));
|
||||
_timeSlot = program->getBuffers().findLocation(UNIFORM_TIME_NAME);
|
||||
if (_timeSlot == gpu::Shader::INVALID_LOCATION) {
|
||||
_timeSlot = program->getUniforms().findLocation(UNIFORM_TIME_NAME);
|
||||
}
|
||||
auto state = gpu::StatePointer(new gpu::State());
|
||||
// enable decal blend
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_pipeline.reset(gpu::Pipeline::create(program, state));
|
||||
vertexBuffer->append(sizeof(StarVertex) * limit, (const gpu::Byte*)&points[0]);
|
||||
streamFormat.reset(new gpu::Stream::Format()); // 1 for everyone
|
||||
streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::XYZW), 0);
|
||||
streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::RGBA));
|
||||
positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element;
|
||||
colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element;
|
||||
});
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
@ -168,18 +200,31 @@ void Stars::render(RenderArgs* renderArgs, float alpha) {
|
|||
batch.setResourceTexture(0, textureCache->getWhiteTexture());
|
||||
|
||||
// Render the world lines
|
||||
batch.setPipeline(_pipeline);
|
||||
batch.setPipeline(_gridPipeline);
|
||||
static auto start = usecTimestampNow();
|
||||
float msecs = (float)(usecTimestampNow() - start) / (float)USECS_PER_MSEC;
|
||||
float secs = msecs / (float)MSECS_PER_SECOND;
|
||||
batch._glUniform1f(_timeSlot, secs);
|
||||
geometryCache->renderUnitCube(batch);
|
||||
|
||||
|
||||
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
|
||||
|
||||
static const size_t VERTEX_STRIDE = sizeof(StarVertex);
|
||||
size_t offset = offsetof(StarVertex, position);
|
||||
gpu::BufferView posView(vertexBuffer, offset, vertexBuffer->getSize(), VERTEX_STRIDE, positionElement);
|
||||
offset = offsetof(StarVertex, colorAndSize);
|
||||
gpu::BufferView colView(vertexBuffer, offset, vertexBuffer->getSize(), VERTEX_STRIDE, colorElement);
|
||||
|
||||
// Render the stars
|
||||
geometryCache->useSimpleDrawPipeline(batch);
|
||||
batch.setPipeline(_starsPipeline);
|
||||
batch._glEnable(GL_PROGRAM_POINT_SIZE_EXT);
|
||||
batch._glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||
batch._glEnable(GL_POINT_SMOOTH);
|
||||
|
||||
batch.setInputFormat(streamFormat);
|
||||
batch.setInputBuffer(VERTICES_SLOT, gpu::BufferView(vertexBuffer, positionElement));
|
||||
batch.setInputBuffer(VERTICES_SLOT, posView);
|
||||
batch.setInputBuffer(COLOR_SLOT, colView);
|
||||
batch.draw(gpu::Primitive::POINTS, STARFIELD_NUM_STARS);
|
||||
|
||||
renderArgs->_context->render(batch);
|
||||
}
|
||||
|
|
|
@ -77,13 +77,6 @@ const glm::vec3 randVector() {
|
|||
return glm::vec3(randFloat() - 0.5f, randFloat() - 0.5f, randFloat() - 0.5f) * 2.0f;
|
||||
}
|
||||
|
||||
void renderCollisionOverlay(int width, int height, float magnitude, float red, float blue, float green) {
|
||||
const float MIN_VISIBLE_COLLISION = 0.01f;
|
||||
if (magnitude > MIN_VISIBLE_COLLISION) {
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(0, 0, width, height, glm::vec4(red, blue, green, magnitude));
|
||||
}
|
||||
}
|
||||
|
||||
// Do some basic timing tests and report the results
|
||||
void runTimingTests() {
|
||||
// How long does it take to make a call to get the time?
|
||||
|
|
|
@ -23,8 +23,6 @@ const glm::vec3 randVector();
|
|||
|
||||
void renderWorldBox(gpu::Batch& batch);
|
||||
|
||||
void renderCollisionOverlay(int width, int height, float magnitude, float red = 0, float blue = 0, float green = 0);
|
||||
|
||||
void runTimingTests();
|
||||
void runUnitTests();
|
||||
|
||||
|
|
|
@ -316,15 +316,14 @@ void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::S
|
|||
}
|
||||
}
|
||||
|
||||
void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting) {
|
||||
void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||
if (_referential) {
|
||||
_referential->update();
|
||||
}
|
||||
|
||||
auto& batch = *renderArgs->_batch;
|
||||
|
||||
if (postLighting &&
|
||||
glm::distance(DependencyManager::get<AvatarManager>()->getMyAvatar()->getPosition(), _position) < 10.0f) {
|
||||
if (glm::distance(DependencyManager::get<AvatarManager>()->getMyAvatar()->getPosition(), _position) < 10.0f) {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto deferredLighting = DependencyManager::get<DeferredLightingEffect>();
|
||||
|
||||
|
@ -414,9 +413,9 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo
|
|||
: GLOW_FROM_AVERAGE_LOUDNESS;
|
||||
|
||||
// render body
|
||||
renderBody(renderArgs, frustum, postLighting, glowLevel);
|
||||
renderBody(renderArgs, frustum, glowLevel);
|
||||
|
||||
if (!postLighting && renderArgs->_renderMode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||
if (renderArgs->_renderMode != RenderArgs::SHADOW_RENDER_MODE) {
|
||||
// add local lights
|
||||
const float BASE_LIGHT_DISTANCE = 2.0f;
|
||||
const float LIGHT_EXPONENT = 1.0f;
|
||||
|
@ -431,21 +430,17 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo
|
|||
}
|
||||
}
|
||||
|
||||
if (postLighting) {
|
||||
bool renderSkeleton = Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionShapes);
|
||||
bool renderHead = Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionShapes);
|
||||
bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes);
|
||||
|
||||
if (renderSkeleton) {
|
||||
_skeletonModel.renderJointCollisionShapes(0.7f);
|
||||
}
|
||||
|
||||
if (renderHead && shouldRenderHead(renderArgs)) {
|
||||
getHead()->getFaceModel().renderJointCollisionShapes(0.7f);
|
||||
}
|
||||
if (renderBounding && shouldRenderHead(renderArgs)) {
|
||||
_skeletonModel.renderBoundingCollisionShapes(*renderArgs->_batch, 0.7f);
|
||||
}
|
||||
bool renderSkeleton = Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionShapes);
|
||||
bool renderHead = Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionShapes);
|
||||
bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes);
|
||||
if (renderSkeleton) {
|
||||
_skeletonModel.renderJointCollisionShapes(0.7f);
|
||||
}
|
||||
if (renderHead && shouldRenderHead(renderArgs)) {
|
||||
getHead()->getFaceModel().renderJointCollisionShapes(0.7f);
|
||||
}
|
||||
if (renderBounding && shouldRenderHead(renderArgs)) {
|
||||
_skeletonModel.renderBoundingCollisionShapes(*renderArgs->_batch, 0.7f);
|
||||
}
|
||||
|
||||
// Stack indicator spheres
|
||||
|
@ -569,24 +564,20 @@ void Avatar::fixupModelsInScene() {
|
|||
scene->enqueuePendingChanges(pendingChanges);
|
||||
}
|
||||
|
||||
void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) {
|
||||
void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel) {
|
||||
|
||||
fixupModelsInScene();
|
||||
|
||||
{
|
||||
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||
if (postLighting || renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||
// render the billboard until both models are loaded
|
||||
renderBillboard(renderArgs);
|
||||
}
|
||||
// render the billboard until both models are loaded
|
||||
renderBillboard(renderArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (postLighting) {
|
||||
getHand()->render(renderArgs, false);
|
||||
}
|
||||
getHand()->render(renderArgs, false);
|
||||
}
|
||||
getHead()->render(renderArgs, 1.0f, renderFrustum, postLighting);
|
||||
getHead()->render(renderArgs, 1.0f, renderFrustum);
|
||||
}
|
||||
|
||||
bool Avatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
||||
|
|
|
@ -81,8 +81,7 @@ public:
|
|||
void init();
|
||||
void simulate(float deltaTime);
|
||||
|
||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition,
|
||||
bool postLighting = false);
|
||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition);
|
||||
|
||||
bool addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene,
|
||||
render::PendingChanges& pendingChanges);
|
||||
|
@ -235,7 +234,7 @@ protected:
|
|||
|
||||
Transform calculateDisplayNameTransform(const ViewFrustum& frustum, float fontSize, const glm::ivec4& viewport) const;
|
||||
void renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, const glm::ivec4& viewport) const;
|
||||
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel = 0.0f);
|
||||
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f);
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const;
|
||||
virtual void fixupModelsInScene();
|
||||
|
||||
|
|
|
@ -72,8 +72,8 @@ void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentSta
|
|||
glm::translate(state.getDefaultTranslationInConstrainedFrame()) *
|
||||
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
|
||||
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f));
|
||||
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getCorrectedLookAtPosition() +
|
||||
_owningHead->getSaccade() - model->getTranslation(), 1.0f));
|
||||
glm::vec3 lookAtDelta = _owningHead->getCorrectedLookAtPosition() - model->getTranslation();
|
||||
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(lookAtDelta + glm::length(lookAtDelta) * _owningHead->getSaccade(), 1.0f));
|
||||
glm::quat between = rotationBetween(front, lookAt);
|
||||
const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE;
|
||||
state.setRotationInConstrainedFrame(glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
|
||||
|
|
|
@ -129,13 +129,14 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
|
|||
const float AVERAGE_SACCADE_INTERVAL = 6.0f;
|
||||
const float MICROSACCADE_MAGNITUDE = 0.002f;
|
||||
const float SACCADE_MAGNITUDE = 0.04f;
|
||||
const float NOMINAL_FRAME_RATE = 60.0f;
|
||||
|
||||
if (randFloat() < deltaTime / AVERAGE_MICROSACCADE_INTERVAL) {
|
||||
_saccadeTarget = MICROSACCADE_MAGNITUDE * randVector();
|
||||
} else if (randFloat() < deltaTime / AVERAGE_SACCADE_INTERVAL) {
|
||||
_saccadeTarget = SACCADE_MAGNITUDE * randVector();
|
||||
}
|
||||
_saccade += (_saccadeTarget - _saccade) * 0.5f;
|
||||
_saccade += (_saccadeTarget - _saccade) * pow(0.5f, NOMINAL_FRAME_RATE * deltaTime);
|
||||
|
||||
// Detect transition from talking to not; force blink after that and a delay
|
||||
bool forceBlink = false;
|
||||
|
@ -293,7 +294,7 @@ void Head::relaxLean(float deltaTime) {
|
|||
_deltaLeanForward *= relaxationFactor;
|
||||
}
|
||||
|
||||
void Head::render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum, bool postLighting) {
|
||||
void Head::render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum) {
|
||||
if (_renderLookatVectors) {
|
||||
renderLookatVectors(renderArgs, _leftEyePosition, _rightEyePosition, getCorrectedLookAtPosition());
|
||||
}
|
||||
|
@ -342,7 +343,8 @@ glm::quat Head::getCameraOrientation() const {
|
|||
|
||||
glm::quat Head::getEyeRotation(const glm::vec3& eyePosition) const {
|
||||
glm::quat orientation = getOrientation();
|
||||
return rotationBetween(orientation * IDENTITY_FRONT, _lookAtPosition + _saccade - eyePosition) * orientation;
|
||||
glm::vec3 lookAtDelta = _lookAtPosition - eyePosition;
|
||||
return rotationBetween(orientation * IDENTITY_FRONT, lookAtDelta + glm::length(lookAtDelta) * _saccade) * orientation;
|
||||
}
|
||||
|
||||
glm::vec3 Head::getScalePivot() const {
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
void init();
|
||||
void reset();
|
||||
void simulate(float deltaTime, bool isMine, bool billboard = false);
|
||||
void render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum, bool postLighting);
|
||||
void render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum);
|
||||
void setScale(float scale);
|
||||
void setPosition(glm::vec3 position) { _position = position; }
|
||||
void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; }
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
using namespace std;
|
||||
|
||||
const glm::vec3 DEFAULT_UP_DIRECTION(0.0f, 1.0f, 0.0f);
|
||||
const float YAW_SPEED = 500.0f; // degrees/sec
|
||||
const float YAW_SPEED = 150.0f; // degrees/sec
|
||||
const float PITCH_SPEED = 100.0f; // degrees/sec
|
||||
const float DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES = 30.0f;
|
||||
|
||||
|
@ -332,13 +332,13 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
|
|||
|
||||
|
||||
// virtual
|
||||
void MyAvatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting) {
|
||||
void MyAvatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||
// don't render if we've been asked to disable local rendering
|
||||
if (!_shouldRender) {
|
||||
return; // exit early
|
||||
}
|
||||
|
||||
Avatar::render(renderArgs, cameraPosition, postLighting);
|
||||
Avatar::render(renderArgs, cameraPosition);
|
||||
|
||||
// don't display IK constraints in shadow mode
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::ShowIKConstraints) &&
|
||||
|
@ -1226,7 +1226,7 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, const g
|
|||
Avatar::attach(modelURL, jointName, translation, rotation, scale, allowDuplicates, useSaved);
|
||||
}
|
||||
|
||||
void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) {
|
||||
void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel) {
|
||||
|
||||
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||
return; // wait until all models are loaded
|
||||
|
@ -1236,7 +1236,7 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bo
|
|||
|
||||
// Render head so long as the camera isn't inside it
|
||||
if (shouldRenderHead(renderArgs)) {
|
||||
getHead()->render(renderArgs, 1.0f, renderFrustum, postLighting);
|
||||
getHead()->render(renderArgs, 1.0f, renderFrustum);
|
||||
}
|
||||
getHand()->render(renderArgs, true);
|
||||
}
|
||||
|
@ -1290,22 +1290,34 @@ bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
|||
|
||||
void MyAvatar::updateOrientation(float deltaTime) {
|
||||
// Smoothly rotate body with arrow keys
|
||||
_bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime;
|
||||
_bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime;
|
||||
getHead()->setBasePitch(getHead()->getBasePitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime);
|
||||
float driveLeft = _driveKeys[ROT_LEFT] - _driveKeys[ROT_RIGHT];
|
||||
float targetSpeed = (_driveKeys[ROT_LEFT] - _driveKeys[ROT_RIGHT]) * YAW_SPEED;
|
||||
if (targetSpeed != 0.0f) {
|
||||
const float ROTATION_RAMP_TIMESCALE = 0.1f;
|
||||
float blend = deltaTime / ROTATION_RAMP_TIMESCALE;
|
||||
if (blend > 1.0f) {
|
||||
blend = 1.0f;
|
||||
}
|
||||
_bodyYawDelta = (1.0f - blend) * _bodyYawDelta + blend * targetSpeed;
|
||||
} else if (_bodyYawDelta != 0.0f) {
|
||||
// attenuate body rotation speed
|
||||
const float ROTATION_DECAY_TIMESCALE = 0.05f;
|
||||
float attenuation = 1.0f - deltaTime / ROTATION_DECAY_TIMESCALE;
|
||||
if (attenuation < 0.0f) {
|
||||
attenuation = 0.0f;
|
||||
}
|
||||
_bodyYawDelta *= attenuation;
|
||||
|
||||
float MINIMUM_ROTATION_RATE = 2.0f;
|
||||
if (fabsf(_bodyYawDelta) < MINIMUM_ROTATION_RATE) {
|
||||
_bodyYawDelta = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
getHead()->setBasePitch(getHead()->getBasePitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime);
|
||||
// update body orientation by movement inputs
|
||||
setOrientation(getOrientation() *
|
||||
glm::quat(glm::radians(glm::vec3(0.0f, _bodyYawDelta, 0.0f) * deltaTime)));
|
||||
|
||||
// decay body rotation momentum
|
||||
const float BODY_SPIN_FRICTION = 7.5f;
|
||||
float bodySpinMomentum = 1.0f - BODY_SPIN_FRICTION * deltaTime;
|
||||
if (bodySpinMomentum < 0.0f) { bodySpinMomentum = 0.0f; }
|
||||
_bodyYawDelta *= bodySpinMomentum;
|
||||
|
||||
float MINIMUM_ROTATION_RATE = 2.0f;
|
||||
if (fabs(_bodyYawDelta) < MINIMUM_ROTATION_RATE) { _bodyYawDelta = 0.0f; }
|
||||
glm::quat(glm::radians(glm::vec3(0.0f, _bodyYawDelta * deltaTime, 0.0f))));
|
||||
|
||||
if (qApp->isHMDMode()) {
|
||||
// these angles will be in radians
|
||||
|
@ -1532,13 +1544,16 @@ void MyAvatar::maybeUpdateBillboard() {
|
|||
return;
|
||||
}
|
||||
}
|
||||
gpu::Context context(new gpu::GLBackend());
|
||||
RenderArgs renderArgs(&context);
|
||||
|
||||
RenderArgs renderArgs(qApp->getGPUContext());
|
||||
QImage image = qApp->renderAvatarBillboard(&renderArgs);
|
||||
_billboard.clear();
|
||||
QBuffer buffer(&_billboard);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
image.save(&buffer, "PNG");
|
||||
#ifdef DEBUG
|
||||
image.save("billboard.png", "PNG");
|
||||
#endif
|
||||
_billboardValid = true;
|
||||
|
||||
sendBillboardPacket();
|
||||
|
|
|
@ -45,8 +45,8 @@ public:
|
|||
void preRender(RenderArgs* renderArgs);
|
||||
void updateFromTrackers(float deltaTime);
|
||||
|
||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting = false) override;
|
||||
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel = 0.0f) override;
|
||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPositio) override;
|
||||
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f) override;
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const override;
|
||||
|
||||
// setters
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <QMultiMap>
|
||||
|
||||
#include <CapsuleShape.h>
|
||||
#include <DeferredLightingEffect.h>
|
||||
#include <SphereShape.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
@ -375,13 +376,15 @@ void SkeletonModel::renderJointConstraints(gpu::Batch& batch, int jointIndex) {
|
|||
|
||||
}
|
||||
|
||||
renderOrientationDirections(jointIndex, position, _rotation * jointState.getRotation(), directionSize);
|
||||
renderOrientationDirections(batch, jointIndex, position, _rotation * jointState.getRotation(), directionSize);
|
||||
jointIndex = joint.parentIndex;
|
||||
|
||||
} while (jointIndex != -1 && geometry.joints.at(jointIndex).isFree);
|
||||
}
|
||||
|
||||
void SkeletonModel::renderOrientationDirections(int jointIndex, glm::vec3 position, const glm::quat& orientation, float size) {
|
||||
void SkeletonModel::renderOrientationDirections(gpu::Batch& batch, int jointIndex,
|
||||
glm::vec3 position, const glm::quat& orientation, float size) {
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
if (!_jointOrientationLines.contains(jointIndex)) {
|
||||
|
@ -398,13 +401,13 @@ void SkeletonModel::renderOrientationDirections(int jointIndex, glm::vec3 positi
|
|||
glm::vec3 pFront = position + orientation * IDENTITY_FRONT * size;
|
||||
|
||||
glm::vec3 red(1.0f, 0.0f, 0.0f);
|
||||
geometryCache->renderLine(position, pRight, red, jointLineIDs._right);
|
||||
geometryCache->renderLine(batch, position, pRight, red, jointLineIDs._right);
|
||||
|
||||
glm::vec3 green(0.0f, 1.0f, 0.0f);
|
||||
geometryCache->renderLine(position, pUp, green, jointLineIDs._up);
|
||||
geometryCache->renderLine(batch, position, pUp, green, jointLineIDs._up);
|
||||
|
||||
glm::vec3 blue(0.0f, 0.0f, 1.0f);
|
||||
geometryCache->renderLine(position, pFront, blue, jointLineIDs._front);
|
||||
geometryCache->renderLine(batch, position, pFront, blue, jointLineIDs._front);
|
||||
}
|
||||
|
||||
|
||||
|
@ -785,31 +788,34 @@ void SkeletonModel::resetShapePositionsToDefaultPose() {
|
|||
void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float alpha) {
|
||||
const int BALL_SUBDIVISIONS = 10;
|
||||
if (_shapes.isEmpty()) {
|
||||
// the bounding shape has not been propery computed
|
||||
// the bounding shape has not been properly computed
|
||||
// so no need to render it
|
||||
return;
|
||||
}
|
||||
|
||||
// draw a blue sphere at the capsule endpoint
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto deferredLighting = DependencyManager::get<DeferredLightingEffect>();
|
||||
Transform transform; // = Transform();
|
||||
|
||||
// draw a blue sphere at the capsule end point
|
||||
glm::vec3 endPoint;
|
||||
_boundingShape.getEndPoint(endPoint);
|
||||
endPoint = endPoint + _translation;
|
||||
Transform transform = Transform();
|
||||
transform.setTranslation(endPoint);
|
||||
batch.setModelTransform(transform);
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
geometryCache->renderSphere(batch, _boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS,
|
||||
deferredLighting->bindSimpleProgram(batch);
|
||||
geometryCache->renderSphere(batch, _boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS,
|
||||
glm::vec4(0.6f, 0.6f, 0.8f, alpha));
|
||||
|
||||
// draw a yellow sphere at the capsule startpoint
|
||||
// draw a yellow sphere at the capsule start point
|
||||
glm::vec3 startPoint;
|
||||
_boundingShape.getStartPoint(startPoint);
|
||||
startPoint = startPoint + _translation;
|
||||
glm::vec3 axis = endPoint - startPoint;
|
||||
Transform axisTransform = Transform();
|
||||
axisTransform.setTranslation(-axis);
|
||||
batch.setModelTransform(axisTransform);
|
||||
geometryCache->renderSphere(batch, _boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS,
|
||||
transform.setTranslation(startPoint);
|
||||
batch.setModelTransform(transform);
|
||||
deferredLighting->bindSimpleProgram(batch);
|
||||
geometryCache->renderSphere(batch, _boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS,
|
||||
glm::vec4(0.8f, 0.8f, 0.6f, alpha));
|
||||
|
||||
// draw a green cylinder between the two points
|
||||
|
|
|
@ -145,7 +145,8 @@ protected:
|
|||
private:
|
||||
|
||||
void renderJointConstraints(gpu::Batch& batch, int jointIndex);
|
||||
void renderOrientationDirections(int jointIndex, glm::vec3 position, const glm::quat& orientation, float size);
|
||||
void renderOrientationDirections(gpu::Batch& batch, int jointIndex,
|
||||
glm::vec3 position, const glm::quat& orientation, float size);
|
||||
|
||||
struct OrientationLineIDs {
|
||||
int _up;
|
||||
|
|
|
@ -157,6 +157,10 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui
|
|||
_reset(false),
|
||||
_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
|
||||
_rightBlinkIndex(1),
|
||||
_leftEyeDownIndex(4),
|
||||
_rightEyeDownIndex(5),
|
||||
_leftEyeInIndex(6),
|
||||
_rightEyeInIndex(7),
|
||||
_leftEyeOpenIndex(8),
|
||||
_rightEyeOpenIndex(9),
|
||||
_browDownLeftIndex(14),
|
||||
|
@ -173,6 +177,14 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui
|
|||
_filteredHeadTranslation(glm::vec3(0.0f)),
|
||||
_lastBrowUp(0.0f),
|
||||
_filteredBrowUp(0.0f),
|
||||
_eyePitch(0.0f),
|
||||
_eyeYaw(0.0f),
|
||||
_lastEyePitch(0.0f),
|
||||
_lastEyeYaw(0.0f),
|
||||
_filteredEyePitch(0.0f),
|
||||
_filteredEyeYaw(0.0f),
|
||||
_longTermAverageEyePitch(0.0f),
|
||||
_longTermAverageEyeYaw(0.0f),
|
||||
_lastEyeBlinks(),
|
||||
_filteredEyeBlinks(),
|
||||
_lastEyeCoefficients(),
|
||||
|
@ -282,6 +294,17 @@ void DdeFaceTracker::reset() {
|
|||
}
|
||||
}
|
||||
|
||||
void DdeFaceTracker::update(float deltaTime) {
|
||||
if (!isActive()) {
|
||||
return;
|
||||
}
|
||||
FaceTracker::update(deltaTime);
|
||||
|
||||
glm::vec3 headEulers = glm::degrees(glm::eulerAngles(_headRotation));
|
||||
_estimatedEyePitch = _eyePitch - headEulers.x;
|
||||
_estimatedEyeYaw = _eyeYaw - headEulers.y;
|
||||
}
|
||||
|
||||
bool DdeFaceTracker::isActive() const {
|
||||
return (_ddeProcess != NULL);
|
||||
}
|
||||
|
@ -436,6 +459,28 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
|
|||
_coefficients[_mouthSmileLeftIndex] = _coefficients[_mouthSmileLeftIndex] - SMILE_THRESHOLD;
|
||||
_coefficients[_mouthSmileRightIndex] = _coefficients[_mouthSmileRightIndex] - SMILE_THRESHOLD;
|
||||
|
||||
// Eye pitch and yaw
|
||||
// EyeDown coefficients work better over both +ve and -ve values than EyeUp values.
|
||||
// EyeIn coefficients work better over both +ve and -ve values than EyeOut values.
|
||||
// Pitch and yaw values are relative to the screen.
|
||||
const float EYE_PITCH_SCALE = -1500.0f; // Sign, scale, and average to be similar to Faceshift values.
|
||||
_eyePitch = EYE_PITCH_SCALE * (_coefficients[_leftEyeDownIndex] + _coefficients[_rightEyeDownIndex]);
|
||||
const float EYE_YAW_SCALE = 2000.0f; // Scale and average to be similar to Faceshift values.
|
||||
_eyeYaw = EYE_YAW_SCALE * (_coefficients[_leftEyeInIndex] + _coefficients[_rightEyeInIndex]);
|
||||
if (isFiltering) {
|
||||
const float EYE_VELOCITY_FILTER_STRENGTH = 0.005f;
|
||||
float pitchVelocity = fabsf(_eyePitch - _lastEyePitch) / _averageMessageTime;
|
||||
float pitchVelocityFilter = glm::clamp(pitchVelocity * EYE_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f);
|
||||
_filteredEyePitch = pitchVelocityFilter * _eyePitch + (1.0f - pitchVelocityFilter) * _filteredEyePitch;
|
||||
_lastEyePitch = _eyePitch;
|
||||
_eyePitch = _filteredEyePitch;
|
||||
float yawVelocity = fabsf(_eyeYaw - _lastEyeYaw) / _averageMessageTime;
|
||||
float yawVelocityFilter = glm::clamp(yawVelocity * EYE_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f);
|
||||
_filteredEyeYaw = yawVelocityFilter * _eyeYaw + (1.0f - yawVelocityFilter) * _filteredEyeYaw;
|
||||
_lastEyeYaw = _eyeYaw;
|
||||
_eyeYaw = _filteredEyeYaw;
|
||||
}
|
||||
|
||||
// Velocity filter EyeBlink values
|
||||
const float DDE_EYEBLINK_SCALE = 3.0f;
|
||||
float eyeBlinks[] = { DDE_EYEBLINK_SCALE * _coefficients[_leftBlinkIndex],
|
||||
|
|
|
@ -31,6 +31,7 @@ class DdeFaceTracker : public FaceTracker, public Dependency {
|
|||
public:
|
||||
virtual void init();
|
||||
virtual void reset();
|
||||
virtual void update(float deltaTime);
|
||||
|
||||
virtual bool isActive() const;
|
||||
virtual bool isTracking() const;
|
||||
|
@ -93,6 +94,11 @@ private:
|
|||
int _leftEyeOpenIndex;
|
||||
int _rightEyeOpenIndex;
|
||||
|
||||
int _leftEyeDownIndex;
|
||||
int _rightEyeDownIndex;
|
||||
int _leftEyeInIndex;
|
||||
int _rightEyeInIndex;
|
||||
|
||||
int _browDownLeftIndex;
|
||||
int _browDownRightIndex;
|
||||
int _browUpCenterIndex;
|
||||
|
@ -115,6 +121,16 @@ private:
|
|||
float _lastBrowUp;
|
||||
float _filteredBrowUp;
|
||||
|
||||
float _eyePitch; // Degrees, relative to screen
|
||||
float _eyeYaw;
|
||||
float _lastEyePitch;
|
||||
float _lastEyeYaw;
|
||||
float _filteredEyePitch;
|
||||
float _filteredEyeYaw;
|
||||
float _longTermAverageEyePitch = 0.0f;
|
||||
float _longTermAverageEyeYaw = 0.0f;
|
||||
bool _longTermAverageInitialized = false;
|
||||
|
||||
enum EyeState {
|
||||
EYE_UNCONTROLLED,
|
||||
EYE_OPEN,
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
const int FPS_TIMER_DELAY = 2000; // ms
|
||||
const int FPS_TIMER_DURATION = 2000; // ms
|
||||
|
||||
const float DEFAULT_EYE_DEFLECTION = 0.25f;
|
||||
Setting::Handle<float> FaceTracker::_eyeDeflection("faceshiftEyeDeflection", DEFAULT_EYE_DEFLECTION);
|
||||
|
||||
void FaceTracker::init() {
|
||||
_isMuted = Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking);
|
||||
_isInitialized = true; // FaceTracker can be used now
|
||||
|
@ -106,3 +109,7 @@ void FaceTracker::toggleMute() {
|
|||
_isMuted = !_isMuted;
|
||||
emit muteToggled();
|
||||
}
|
||||
|
||||
void FaceTracker::setEyeDeflection(float eyeDeflection) {
|
||||
_eyeDeflection.set(eyeDeflection);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include <SettingHandle.h>
|
||||
|
||||
/// Base class for face trackers (Faceshift, DDE).
|
||||
class FaceTracker : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -47,6 +49,9 @@ public:
|
|||
void setIsMuted(bool isMuted) { _isMuted = isMuted; }
|
||||
void toggleMute();
|
||||
|
||||
static float getEyeDeflection() { return _eyeDeflection.get(); }
|
||||
static void setEyeDeflection(float eyeDeflection);
|
||||
|
||||
signals:
|
||||
void muteToggled();
|
||||
|
||||
|
@ -77,6 +82,8 @@ private slots:
|
|||
private:
|
||||
bool _isCalculatingFPS = false;
|
||||
int _frameCount = 0;
|
||||
|
||||
static Setting::Handle<float> _eyeDeflection;
|
||||
};
|
||||
|
||||
#endif // hifi_FaceTracker_h
|
||||
|
|
|
@ -28,10 +28,8 @@ using namespace std;
|
|||
|
||||
const QString DEFAULT_FACESHIFT_HOSTNAME = "localhost";
|
||||
const quint16 FACESHIFT_PORT = 33433;
|
||||
const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f;
|
||||
|
||||
Faceshift::Faceshift() :
|
||||
_eyeDeflection("faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION),
|
||||
_hostname("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME)
|
||||
{
|
||||
#ifdef HAVE_FACESHIFT
|
||||
|
@ -306,10 +304,6 @@ void Faceshift::receive(const QByteArray& buffer) {
|
|||
FaceTracker::countFrame();
|
||||
}
|
||||
|
||||
void Faceshift::setEyeDeflection(float faceshiftEyeDeflection) {
|
||||
_eyeDeflection.set(faceshiftEyeDeflection);
|
||||
}
|
||||
|
||||
void Faceshift::setHostname(const QString& hostname) {
|
||||
_hostname.set(hostname);
|
||||
}
|
||||
|
|
|
@ -68,9 +68,6 @@ public:
|
|||
float getMouthSmileLeft() const { return getBlendshapeCoefficient(_mouthSmileLeftIndex); }
|
||||
float getMouthSmileRight() const { return getBlendshapeCoefficient(_mouthSmileRightIndex); }
|
||||
|
||||
float getEyeDeflection() { return _eyeDeflection.get(); }
|
||||
void setEyeDeflection(float faceshiftEyeDeflection);
|
||||
|
||||
QString getHostname() { return _hostname.get(); }
|
||||
void setHostname(const QString& hostname);
|
||||
|
||||
|
@ -134,7 +131,6 @@ private:
|
|||
float _longTermAverageEyeYaw = 0.0f;
|
||||
bool _longTermAverageInitialized = false;
|
||||
|
||||
Setting::Handle<float> _eyeDeflection;
|
||||
Setting::Handle<QString> _hostname;
|
||||
|
||||
// see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <PathUtils.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <UserActivityLogger.h>
|
||||
#include <FramebufferCache.h>
|
||||
|
||||
#include <OVR_CAPI_GL.h>
|
||||
|
||||
|
@ -646,7 +647,7 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const
|
|||
return;
|
||||
}
|
||||
|
||||
auto primaryFBO = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||
auto primaryFBO = DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFBO));
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
@ -706,7 +707,7 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const
|
|||
_activeEye = ovrEye_Count;
|
||||
|
||||
gpu::FramebufferPointer finalFbo;
|
||||
finalFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||
finalFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
// restore our normal viewport
|
||||
|
|
|
@ -520,8 +520,7 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) {
|
|||
triggerButton = Qt::LeftButton;
|
||||
}
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)
|
||||
|| Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) {
|
||||
pos = qApp->getApplicationCompositor().getPalmClickLocation(palm);
|
||||
} else {
|
||||
// Get directon relative to avatar orientation
|
||||
|
|
|
@ -142,3 +142,7 @@ QScriptValue WebWindowClass::constructor(QScriptContext* context, QScriptEngine*
|
|||
|
||||
return engine->newQObject(retVal);
|
||||
}
|
||||
|
||||
void WebWindowClass::setTitle(const QString& title) {
|
||||
_windowWidget->setWindowTitle(title);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ public slots:
|
|||
void raise();
|
||||
ScriptEventBridge* getEventBridge() const { return _eventBridge; }
|
||||
void addEventBridgeToWindowObject();
|
||||
void setTitle(const QString& title);
|
||||
|
||||
signals:
|
||||
void closed();
|
||||
|
|
|
@ -270,8 +270,8 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
|
|||
|
||||
gpu::Batch batch;
|
||||
geometryCache->useSimpleDrawPipeline(batch);
|
||||
batch._glDisable(GL_DEPTH_TEST);
|
||||
batch._glDisable(GL_CULL_FACE);
|
||||
//batch._glDisable(GL_DEPTH_TEST);
|
||||
//batch._glDisable(GL_CULL_FACE);
|
||||
//batch._glBindTexture(GL_TEXTURE_2D, texture);
|
||||
//batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
//batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
@ -491,24 +491,18 @@ void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) {
|
|||
|
||||
auto canvasSize = qApp->getCanvasSize();
|
||||
int mouseX, mouseY;
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) {
|
||||
QPoint res = getPalmClickLocation(palmData);
|
||||
mouseX = res.x();
|
||||
mouseY = res.y();
|
||||
} else {
|
||||
// Get directon relative to avatar orientation
|
||||
glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection();
|
||||
// Get directon relative to avatar orientation
|
||||
glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection();
|
||||
|
||||
// Get the angles, scaled between (-0.5,0.5)
|
||||
float xAngle = (atan2(direction.z, direction.x) + PI_OVER_TWO);
|
||||
float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)PI_OVER_TWO));
|
||||
// Get the angles, scaled between (-0.5,0.5)
|
||||
float xAngle = (atan2(direction.z, direction.x) + PI_OVER_TWO);
|
||||
float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)PI_OVER_TWO));
|
||||
|
||||
// Get the pixel range over which the xAngle and yAngle are scaled
|
||||
float cursorRange = canvasSize.x * SixenseManager::getInstance().getCursorPixelRangeMult();
|
||||
// Get the pixel range over which the xAngle and yAngle are scaled
|
||||
float cursorRange = canvasSize.x * SixenseManager::getInstance().getCursorPixelRangeMult();
|
||||
|
||||
mouseX = (canvasSize.x / 2.0f + cursorRange * xAngle);
|
||||
mouseY = (canvasSize.y / 2.0f + cursorRange * yAngle);
|
||||
}
|
||||
mouseX = (canvasSize.x / 2.0f + cursorRange * xAngle);
|
||||
mouseY = (canvasSize.y / 2.0f + cursorRange * yAngle);
|
||||
|
||||
//If the cursor is out of the screen then don't render it
|
||||
if (mouseX < 0 || mouseX >= (int)canvasSize.x || mouseY < 0 || mouseY >= (int)canvasSize.y) {
|
||||
|
@ -529,7 +523,7 @@ void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) {
|
|||
glm::vec2 texCoordTopLeft(0.0f, 0.0f);
|
||||
glm::vec2 texCoordBottomRight(1.0f, 1.0f);
|
||||
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
||||
glm::vec4(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f));
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <GLMHelpers.h>
|
||||
#include <gpu/GLBackend.h>
|
||||
#include <gpu/GLBackendShared.h>
|
||||
#include <FramebufferCache.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <OffscreenUi.h>
|
||||
#include <CursorManager.h>
|
||||
|
@ -93,6 +94,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) {
|
|||
// Now render the overlay components together into a single texture
|
||||
renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line
|
||||
renderAudioScope(renderArgs); // audio scope in the very back
|
||||
renderRearView(renderArgs); // renders the mirror view selfie
|
||||
renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture, and the text overlays from scripts
|
||||
renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope
|
||||
renderStatsAndLogs(renderArgs); // currently renders nothing
|
||||
|
@ -167,6 +169,39 @@ void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) {
|
|||
}
|
||||
|
||||
void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) {
|
||||
gpu::Batch& batch = *renderArgs->_batch;
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
auto framebuffer = DependencyManager::get<FramebufferCache>();
|
||||
auto selfieTexture = framebuffer->getSelfieFramebuffer()->getRenderBuffer(0);
|
||||
|
||||
int width = renderArgs->_viewport.z;
|
||||
int height = renderArgs->_viewport.w;
|
||||
mat4 legacyProjection = glm::ortho<float>(0, width, height, 0, ORTHO_NEAR_CLIP, ORTHO_FAR_CLIP);
|
||||
batch.setProjectionTransform(legacyProjection);
|
||||
batch.setModelTransform(Transform());
|
||||
batch.setViewTransform(Transform());
|
||||
|
||||
float screenRatio = ((float)qApp->getDevicePixelRatio());
|
||||
float renderRatio = ((float)screenRatio * qApp->getRenderResolutionScale());
|
||||
|
||||
auto viewport = qApp->getMirrorViewRect();
|
||||
glm::vec2 bottomLeft(viewport.left(), viewport.top() + viewport.height());
|
||||
glm::vec2 topRight(viewport.left() + viewport.width(), viewport.top());
|
||||
bottomLeft *= screenRatio;
|
||||
topRight *= screenRatio;
|
||||
glm::vec2 texCoordMinCorner(0.0f, 0.0f);
|
||||
glm::vec2 texCoordMaxCorner(viewport.width() * renderRatio / float(selfieTexture->getWidth()), viewport.height() * renderRatio / float(selfieTexture->getHeight()));
|
||||
|
||||
geometryCache->useSimpleDrawPipeline(batch, true);
|
||||
batch.setResourceTexture(0, selfieTexture);
|
||||
geometryCache->renderQuad(batch, bottomLeft, topRight, texCoordMinCorner, texCoordMaxCorner, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
|
||||
batch.setResourceTexture(0, renderArgs->_whiteTexture);
|
||||
geometryCache->useSimpleDrawPipeline(batch, false);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) {
|
||||
|
@ -209,7 +244,8 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr
|
|||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
geometryCache->useSimpleDrawPipeline(batch);
|
||||
batch.setProjectionTransform(mat4());
|
||||
batch.setModelTransform(mat4());
|
||||
batch.setModelTransform(Transform());
|
||||
batch.setViewTransform(Transform());
|
||||
batch.setResourceTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
batch._glLineWidth(CONNECTION_STATUS_BORDER_LINE_WIDTH);
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@ private:
|
|||
gpu::TexturePointer _overlayDepthTexture;
|
||||
gpu::TexturePointer _overlayColorTexture;
|
||||
gpu::FramebufferPointer _overlayFramebuffer;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_ApplicationOverlay_h
|
||||
|
|
|
@ -142,10 +142,10 @@ void PreferencesDialog::loadPreferences() {
|
|||
ui.ddeEyeClosingThresholdSlider->setValue(dde->getEyeClosingThreshold() *
|
||||
ui.ddeEyeClosingThresholdSlider->maximum());
|
||||
|
||||
auto faceshift = DependencyManager::get<Faceshift>();
|
||||
ui.faceshiftEyeDeflectionSider->setValue(faceshift->getEyeDeflection() *
|
||||
ui.faceshiftEyeDeflectionSider->maximum());
|
||||
ui.faceTrackerEyeDeflectionSider->setValue(FaceTracker::getEyeDeflection() *
|
||||
ui.faceTrackerEyeDeflectionSider->maximum());
|
||||
|
||||
auto faceshift = DependencyManager::get<Faceshift>();
|
||||
ui.faceshiftHostnameEdit->setText(faceshift->getHostname());
|
||||
|
||||
auto audio = DependencyManager::get<AudioClient>();
|
||||
|
@ -233,10 +233,10 @@ void PreferencesDialog::savePreferences() {
|
|||
dde->setEyeClosingThreshold(ui.ddeEyeClosingThresholdSlider->value() /
|
||||
(float)ui.ddeEyeClosingThresholdSlider->maximum());
|
||||
|
||||
auto faceshift = DependencyManager::get<Faceshift>();
|
||||
faceshift->setEyeDeflection(ui.faceshiftEyeDeflectionSider->value() /
|
||||
(float)ui.faceshiftEyeDeflectionSider->maximum());
|
||||
FaceTracker::setEyeDeflection(ui.faceTrackerEyeDeflectionSider->value() /
|
||||
(float)ui.faceTrackerEyeDeflectionSider->maximum());
|
||||
|
||||
auto faceshift = DependencyManager::get<Faceshift>();
|
||||
faceshift->setHostname(ui.faceshiftHostnameEdit->text());
|
||||
|
||||
qApp->setMaxOctreePacketsPerSecond(ui.maxOctreePPSSpin->value());
|
||||
|
|
|
@ -91,6 +91,7 @@ void BillboardOverlay::render(RenderArgs* args) {
|
|||
if (batch) {
|
||||
Transform transform = _transform;
|
||||
transform.postScale(glm::vec3(getDimensions(), 1.0f));
|
||||
transform.setRotation(rotation);
|
||||
|
||||
batch->setModelTransform(transform);
|
||||
batch->setResourceTexture(0, _texture->getGPUTexture());
|
||||
|
|
|
@ -85,7 +85,6 @@ TextOverlay::TextOverlay() :
|
|||
_topMargin(DEFAULT_MARGIN),
|
||||
_fontSize(DEFAULT_FONTSIZE)
|
||||
{
|
||||
|
||||
qApp->postLambdaEvent([=] {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [] {
|
||||
|
@ -117,7 +116,7 @@ TextOverlay::TextOverlay(const TextOverlay* textOverlay) :
|
|||
});
|
||||
});
|
||||
while (!_qmlElement) {
|
||||
QThread::sleep(1);
|
||||
QThread::msleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,14 +146,12 @@ xColor TextOverlay::getBackgroundColor() {
|
|||
}
|
||||
|
||||
void TextOverlay::render(RenderArgs* args) {
|
||||
if (!_qmlElement) {
|
||||
return;
|
||||
}
|
||||
if (_visible != _qmlElement->isVisible()) {
|
||||
_qmlElement->setVisible(_visible);
|
||||
}
|
||||
float pulseLevel = updatePulse();
|
||||
static float _oldPulseLevel = 0.0f;
|
||||
if (pulseLevel != _oldPulseLevel) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1468,13 +1468,13 @@
|
|||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Faceshift eye deflection</string>
|
||||
<string>Face tracker eye deflection</string>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>faceshiftEyeDeflectionSider</cstring>
|
||||
<cstring>faceTrackerEyeDeflectionSider</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -1497,7 +1497,7 @@
|
|||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="faceshiftEyeDeflectionSider">
|
||||
<widget class="QSlider" name="faceTrackerEyeDeflectionSider">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
|
|
|
@ -1114,11 +1114,15 @@ void AvatarData::sendIdentityPacket() {
|
|||
void AvatarData::sendBillboardPacket() {
|
||||
if (!_billboard.isEmpty()) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
auto billboardPacket = NLPacket::create(PacketType::AvatarBillboard, _billboard.size());
|
||||
billboardPacket->write(_billboard);
|
||||
|
||||
nodeList->broadcastToNodes(std::move(billboardPacket), NodeSet() << NodeType::AvatarMixer);
|
||||
|
||||
// This makes sure the billboard won't be too large to send.
|
||||
// Once more protocol changes are done and we can send blocks of data we can support sending > MTU sized billboards.
|
||||
if (_billboard.size() <= NLPacket::maxPayloadSize(PacketType::AvatarBillboard)) {
|
||||
auto billboardPacket = NLPacket::create(PacketType::AvatarBillboard, _billboard.size());
|
||||
billboardPacket->write(_billboard);
|
||||
|
||||
nodeList->broadcastToNodes(std::move(billboardPacket), NodeSet() << NodeType::AvatarMixer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -220,10 +220,7 @@ void Batch::setStateBlendFactor(const Vec4& factor) {
|
|||
void Batch::setStateScissorRect(const Vec4i& rect) {
|
||||
ADD_COMMAND(setStateScissorRect);
|
||||
|
||||
_params.push_back(rect.x);
|
||||
_params.push_back(rect.y);
|
||||
_params.push_back(rect.z);
|
||||
_params.push_back(rect.w);
|
||||
_params.push_back(cacheData(sizeof(Vec4i), &rect));
|
||||
}
|
||||
|
||||
void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) {
|
||||
|
|
|
@ -108,7 +108,6 @@ public:
|
|||
void blit(const FramebufferPointer& src, const Vec4i& srcViewport,
|
||||
const FramebufferPointer& dst, const Vec4i& dstViewport);
|
||||
|
||||
|
||||
// Query Section
|
||||
void beginQuery(const QueryPointer& query);
|
||||
void endQuery(const QueryPointer& query);
|
||||
|
|
|
@ -40,4 +40,8 @@ void Context::render(Batch& batch) {
|
|||
void Context::syncCache() {
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
_backend->syncCache();
|
||||
}
|
||||
}
|
||||
|
||||
void Context::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) {
|
||||
_backend->downloadFramebuffer(srcFramebuffer, region, destImage);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "Pipeline.h"
|
||||
#include "Framebuffer.h"
|
||||
|
||||
class QImage;
|
||||
|
||||
namespace gpu {
|
||||
|
||||
class Backend {
|
||||
|
@ -28,6 +30,8 @@ public:
|
|||
virtual~ Backend() {};
|
||||
virtual void render(Batch& batch) = 0;
|
||||
virtual void syncCache() = 0;
|
||||
virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0;
|
||||
|
||||
|
||||
class TransformObject {
|
||||
public:
|
||||
|
@ -121,6 +125,10 @@ public:
|
|||
|
||||
void syncCache();
|
||||
|
||||
// Downloading the Framebuffer is a synchronous action that is not efficient.
|
||||
// It s here for convenience to easily capture a snapshot
|
||||
void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage);
|
||||
|
||||
protected:
|
||||
Context(const Context& context);
|
||||
|
||||
|
@ -134,7 +142,7 @@ protected:
|
|||
|
||||
friend class Shader;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Context> ContextPointer;
|
||||
|
||||
};
|
||||
|
||||
|
|
22
libraries/gpu/src/gpu/DrawTextureOpaque.slf
Executable file
22
libraries/gpu/src/gpu/DrawTextureOpaque.slf
Executable file
|
@ -0,0 +1,22 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// Draw texture 0 fetched at texcoord.xy
|
||||
// Alpha is 1
|
||||
//
|
||||
// Created by Sam Gateau on 6/22/2015
|
||||
// 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
|
||||
//
|
||||
|
||||
|
||||
uniform sampler2D colorMap;
|
||||
|
||||
varying vec2 varTexcoord;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = vec4(texture2D(colorMap, varTexcoord).xyz, 1.0);
|
||||
}
|
|
@ -1,17 +1,17 @@
|
|||
//
|
||||
// Framebuffer.h
|
||||
// libraries/gpu/src/gpu
|
||||
//
|
||||
// Created by Sam Gateau on 4/12/2015.
|
||||
// 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
|
||||
//
|
||||
#ifndef hifi_gpu_Framebuffer_h
|
||||
#define hifi_gpu_Framebuffer_h
|
||||
|
||||
#include "Texture.h"
|
||||
//
|
||||
// Framebuffer.h
|
||||
// libraries/gpu/src/gpu
|
||||
//
|
||||
// Created by Sam Gateau on 4/12/2015.
|
||||
// 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
|
||||
//
|
||||
#ifndef hifi_gpu_Framebuffer_h
|
||||
#define hifi_gpu_Framebuffer_h
|
||||
|
||||
#include "Texture.h"
|
||||
#include <memory>
|
||||
|
||||
namespace gpu {
|
||||
|
@ -130,7 +130,7 @@ public:
|
|||
void resize( uint16 width, uint16 height, uint16 samples = 1 );
|
||||
|
||||
static const uint32 MAX_NUM_RENDER_BUFFERS = 8;
|
||||
static uint32 getMaxNumRenderBuffers() { return MAX_NUM_RENDER_BUFFERS; }
|
||||
static uint32 getMaxNumRenderBuffers() { return MAX_NUM_RENDER_BUFFERS; }
|
||||
|
||||
protected:
|
||||
SwapchainPointer _swapchain;
|
||||
|
@ -151,10 +151,10 @@ protected:
|
|||
// Non exposed
|
||||
Framebuffer(const Framebuffer& framebuffer) {}
|
||||
Framebuffer() {}
|
||||
|
||||
// This shouldn't be used by anything else than the Backend class with the proper casting.
|
||||
mutable GPUObject* _gpuObject = NULL;
|
||||
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
|
||||
|
||||
// This shouldn't be used by anything else than the Backend class with the proper casting.
|
||||
mutable GPUObject* _gpuObject = NULL;
|
||||
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
|
||||
GPUObject* getGPUObject() const { return _gpuObject; }
|
||||
friend class Backend;
|
||||
};
|
||||
|
@ -162,4 +162,4 @@ typedef std::shared_ptr<Framebuffer> FramebufferPointer;
|
|||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include <mutex>
|
||||
#include "GPULogging.h"
|
||||
#include "GLBackendShared.h"
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
@ -89,6 +90,39 @@ GLBackend::GLBackend() :
|
|||
_pipeline(),
|
||||
_output()
|
||||
{
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [] {
|
||||
qCDebug(gpulogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
|
||||
|
||||
qCDebug(gpulogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
|
||||
qCDebug(gpulogging) << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR));
|
||||
|
||||
qCDebug(gpulogging) << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
|
||||
|
||||
#ifdef WIN32
|
||||
GLenum err = glewInit();
|
||||
if (GLEW_OK != err) {
|
||||
/* Problem: glewInit failed, something is seriously wrong. */
|
||||
qCDebug(gpulogging, "Error: %s\n", glewGetErrorString(err));
|
||||
}
|
||||
qCDebug(gpulogging, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
|
||||
|
||||
if (wglewGetExtension("WGL_EXT_swap_control")) {
|
||||
int swapInterval = wglGetSwapIntervalEXT();
|
||||
qCDebug(gpulogging, "V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF"));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
// TODO: Write the correct code for Linux...
|
||||
/* if (wglewGetExtension("WGL_EXT_swap_control")) {
|
||||
int swapInterval = wglGetSwapIntervalEXT();
|
||||
qCDebug(gpulogging, "V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF"));
|
||||
}*/
|
||||
#endif
|
||||
});
|
||||
|
||||
initInput();
|
||||
initTransform();
|
||||
}
|
||||
|
@ -112,14 +146,6 @@ void GLBackend::render(Batch& batch) {
|
|||
}
|
||||
}
|
||||
|
||||
void GLBackend::renderBatch(Batch& batch, bool syncCache) {
|
||||
GLBackend backend;
|
||||
if (syncCache) {
|
||||
backend.syncCache();
|
||||
}
|
||||
backend.render(batch);
|
||||
}
|
||||
|
||||
bool GLBackend::checkGLError(const char* name) {
|
||||
GLenum error = glGetError();
|
||||
if (!error) {
|
||||
|
@ -166,6 +192,9 @@ void GLBackend::syncCache() {
|
|||
syncTransformStateCache();
|
||||
syncPipelineStateCache();
|
||||
syncInputStateCache();
|
||||
syncOutputStateCache();
|
||||
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
void GLBackend::do_draw(Batch& batch, uint32 paramOffset) {
|
||||
|
@ -253,6 +282,9 @@ void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) {
|
|||
glClearColor(color.x, color.y, color.z, color.w);
|
||||
glmask |= GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
|
||||
// Force the color mask cache to WRITE_ALL if not the case
|
||||
do_setStateColorWriteMask(State::ColorMask::WRITE_ALL);
|
||||
}
|
||||
|
||||
// Apply scissor if needed and if not already on
|
||||
|
|
|
@ -38,14 +38,9 @@ public:
|
|||
// Let's try to avoid to do that as much as possible!
|
||||
virtual void syncCache();
|
||||
|
||||
// Render Batch create a local Context and execute the batch with it
|
||||
// WARNING:
|
||||
// if syncCache is true, then the gpu::GLBackend will synchornize
|
||||
// its cache with the current gl state and it's BAD
|
||||
// If you know you don't rely on any state changed by naked gl calls then
|
||||
// leave to false where it belongs
|
||||
// if true, the needed resync IS EXPENSIVE
|
||||
static void renderBatch(Batch& batch, bool syncCache = false);
|
||||
// This is the ugly "download the pixels to sysmem for taking a snapshot"
|
||||
// Just avoid using it, it's ugly and will break performances
|
||||
virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage);
|
||||
|
||||
static bool checkGLError(const char* name = nullptr);
|
||||
|
||||
|
@ -392,11 +387,14 @@ protected:
|
|||
void do_setFramebuffer(Batch& batch, uint32 paramOffset);
|
||||
void do_blit(Batch& batch, uint32 paramOffset);
|
||||
|
||||
|
||||
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
||||
void syncOutputStateCache();
|
||||
|
||||
struct OutputStageState {
|
||||
|
||||
FramebufferPointer _framebuffer = nullptr;
|
||||
|
||||
GLuint _drawFBO = 0;
|
||||
|
||||
OutputStageState() {}
|
||||
} _output;
|
||||
|
||||
|
@ -447,7 +445,6 @@ protected:
|
|||
|
||||
typedef void (GLBackend::*CommandCall)(Batch&, uint32);
|
||||
static CommandCall _commandCalls[Batch::NUM_COMMANDS];
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -8,9 +8,12 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include <qimage.h>
|
||||
|
||||
#include "GPULogging.h"
|
||||
#include "GLBackendShared.h"
|
||||
|
||||
|
||||
using namespace gpu;
|
||||
|
||||
GLBackend::GLFramebuffer::GLFramebuffer() {}
|
||||
|
@ -34,6 +37,9 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe
|
|||
|
||||
// need to have a gpu object?
|
||||
if (!object) {
|
||||
GLint currentFBO;
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤tFBO);
|
||||
|
||||
GLuint fbo;
|
||||
glGenFramebuffers(1, &fbo);
|
||||
(void) CHECK_GL_ERROR();
|
||||
|
@ -84,6 +90,8 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe
|
|||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer);
|
||||
(void) CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -139,6 +147,9 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe
|
|||
object->_fbo = fbo;
|
||||
object->_colorBuffers = colorBuffers;
|
||||
Backend::setGPUObject(framebuffer, object);
|
||||
|
||||
// restore the current framebuffer
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, currentFBO);
|
||||
}
|
||||
|
||||
return object;
|
||||
|
@ -158,11 +169,24 @@ GLuint GLBackend::getFramebufferID(const FramebufferPointer& framebuffer) {
|
|||
}
|
||||
}
|
||||
|
||||
void GLBackend::syncOutputStateCache() {
|
||||
GLint currentFBO;
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤tFBO);
|
||||
|
||||
_output._drawFBO = currentFBO;
|
||||
_output._framebuffer.reset();
|
||||
}
|
||||
|
||||
|
||||
void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) {
|
||||
auto framebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint);
|
||||
|
||||
if (_output._framebuffer != framebuffer) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(framebuffer));
|
||||
auto newFBO = getFramebufferID(framebuffer);
|
||||
if (_output._drawFBO != newFBO) {
|
||||
_output._drawFBO = newFBO;
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, newFBO);
|
||||
}
|
||||
_output._framebuffer = framebuffer;
|
||||
}
|
||||
}
|
||||
|
@ -184,4 +208,38 @@ void GLBackend::do_blit(Batch& batch, uint32 paramOffset) {
|
|||
glBlitFramebuffer(srcvp.x, srcvp.y, srcvp.z, srcvp.w,
|
||||
dstvp.x, dstvp.y, dstvp.z, dstvp.w,
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
|
||||
(void) CHECK_GL_ERROR();
|
||||
|
||||
if (_output._framebuffer) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(_output._framebuffer));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLBackend::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) {
|
||||
auto readFBO = gpu::GLBackend::getFramebufferID(srcFramebuffer);
|
||||
if (srcFramebuffer && readFBO) {
|
||||
if ((srcFramebuffer->getWidth() < (region.x + region.z)) || (srcFramebuffer->getHeight() < (region.y + region.w))) {
|
||||
qCDebug(gpulogging) << "GLBackend::downloadFramebuffer : srcFramebuffer is too small to provide the region queried";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((destImage.width() < region.z) || (destImage.height() < region.w)) {
|
||||
qCDebug(gpulogging) << "GLBackend::downloadFramebuffer : destImage is too small to receive the region of the framebuffer";
|
||||
return;
|
||||
}
|
||||
|
||||
GLenum format = GL_BGRA;
|
||||
if (destImage.format() != QImage::Format_ARGB32) {
|
||||
qCDebug(gpulogging) << "GLBackend::downloadFramebuffer : destImage format must be FORMAT_ARGB32 to receive the region of the framebuffer";
|
||||
return;
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(srcFramebuffer));
|
||||
glReadPixels(region.x, region.y, region.z, region.w, format, GL_UNSIGNED_BYTE, destImage.bits());
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
|
||||
(void) CHECK_GL_ERROR();
|
||||
}
|
|
@ -757,11 +757,8 @@ void GLBackend::do_setStateBlendFactor(Batch& batch, uint32 paramOffset) {
|
|||
}
|
||||
|
||||
void GLBackend::do_setStateScissorRect(Batch& batch, uint32 paramOffset) {
|
||||
|
||||
Vec4 rect(batch._params[paramOffset + 0]._float,
|
||||
batch._params[paramOffset + 1]._float,
|
||||
batch._params[paramOffset + 2]._float,
|
||||
batch._params[paramOffset + 3]._float);
|
||||
Vec4i rect;
|
||||
memcpy(&rect, batch.editData(batch._params[paramOffset]._uint), sizeof(Vec4i));
|
||||
|
||||
glScissor(rect.x, rect.y, rect.z, rect.w);
|
||||
(void) CHECK_GL_ERROR();
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "DrawTexcoordRectTransformUnitQuad_vert.h"
|
||||
#include "DrawViewportQuadTransformTexcoord_vert.h"
|
||||
#include "DrawTexture_frag.h"
|
||||
#include "DrawTextureOpaque_frag.h"
|
||||
#include "DrawColoredTexture_frag.h"
|
||||
|
||||
using namespace gpu;
|
||||
|
@ -24,6 +25,7 @@ ShaderPointer StandardShaderLib::_drawTransformUnitQuadVS;
|
|||
ShaderPointer StandardShaderLib::_drawTexcoordRectTransformUnitQuadVS;
|
||||
ShaderPointer StandardShaderLib::_drawViewportQuadTransformTexcoordVS;
|
||||
ShaderPointer StandardShaderLib::_drawTexturePS;
|
||||
ShaderPointer StandardShaderLib::_drawTextureOpaquePS;
|
||||
ShaderPointer StandardShaderLib::_drawColoredTexturePS;
|
||||
StandardShaderLib::ProgramMap StandardShaderLib::_programs;
|
||||
|
||||
|
@ -82,6 +84,15 @@ ShaderPointer StandardShaderLib::getDrawTexturePS() {
|
|||
return _drawTexturePS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawTextureOpaquePS() {
|
||||
if (!_drawTextureOpaquePS) {
|
||||
_drawTextureOpaquePS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(DrawTextureOpaque_frag)));
|
||||
}
|
||||
return _drawTextureOpaquePS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawColoredTexturePS() {
|
||||
if (!_drawColoredTexturePS) {
|
||||
_drawColoredTexturePS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(DrawColoredTexture_frag)));
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
static ShaderPointer getDrawViewportQuadTransformTexcoordVS();
|
||||
|
||||
static ShaderPointer getDrawTexturePS();
|
||||
static ShaderPointer getDrawTextureOpaquePS();
|
||||
static ShaderPointer getDrawColoredTexturePS();
|
||||
|
||||
// The shader program combining the shaders available above, so they are unique
|
||||
|
@ -47,6 +48,7 @@ protected:
|
|||
static ShaderPointer _drawTexcoordRectTransformUnitQuadVS;
|
||||
static ShaderPointer _drawViewportQuadTransformTexcoordVS;
|
||||
static ShaderPointer _drawTexturePS;
|
||||
static ShaderPointer _drawTextureOpaquePS;
|
||||
static ShaderPointer _drawColoredTexturePS;
|
||||
|
||||
typedef std::map<std::pair<GetShader, GetShader>, ShaderPointer> ProgramMap;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
//
|
||||
|
||||
#include "Texture.h"
|
||||
#include <math.h>
|
||||
|
||||
#include <glm/gtc/constants.hpp>
|
||||
|
||||
#include <QDebug>
|
||||
|
|
|
@ -110,7 +110,7 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
|||
} else {
|
||||
// skybox has no cubemap, just clear the color buffer
|
||||
auto color = skybox.getColor();
|
||||
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(color, 0.0f), 0.0f, 0);
|
||||
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(color, 0.0f), 0.0f, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -280,7 +280,7 @@ void PacketReceiver::processDatagrams() {
|
|||
|
||||
auto it = _packetListenerMap.find(packet->getType());
|
||||
|
||||
if (it != _packetListenerMap.end()) {
|
||||
if (it != _packetListenerMap.end() && it->second.isValid()) {
|
||||
|
||||
auto listener = it.value();
|
||||
|
||||
|
@ -367,10 +367,12 @@ void PacketReceiver::processDatagrams() {
|
|||
}
|
||||
|
||||
} else {
|
||||
qWarning() << "No listener found for packet type " << nameForPacketType(packet->getType());
|
||||
|
||||
// insert a dummy listener so we don't print this again
|
||||
_packetListenerMap.insert(packet->getType(), { nullptr, QMetaMethod() });
|
||||
if (it == _packetListenerMap.end()) {
|
||||
qWarning() << "No listener found for packet type " << nameForPacketType(packet->getType());
|
||||
|
||||
// insert a dummy listener so we don't print this again
|
||||
_packetListenerMap.insert(packet->getType(), { nullptr, QMetaMethod() });
|
||||
}
|
||||
}
|
||||
|
||||
_packetListenerLock.unlock();
|
||||
|
|
|
@ -43,9 +43,18 @@ btConvexHullShape* ShapeFactory::createConvexHull(const QVector<glm::vec3>& poin
|
|||
|
||||
const float MIN_MARGIN = 0.01f;
|
||||
glm::vec3 diagonal = maxCorner - minCorner;
|
||||
float minDimension = glm::min(diagonal[0], diagonal[1]);
|
||||
minDimension = glm::min(minDimension, diagonal[2]);
|
||||
margin = glm::min(glm::max(0.5f * minDimension, MIN_MARGIN), margin);
|
||||
float smallestDimension = glm::min(diagonal[0], diagonal[1]);
|
||||
smallestDimension = glm::min(smallestDimension, diagonal[2]);
|
||||
const float MIN_DIMENSION = 2.0f * MIN_MARGIN + 0.001f;
|
||||
if (smallestDimension < MIN_DIMENSION) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (diagonal[i] < MIN_DIMENSION) {
|
||||
diagonal[i] = MIN_DIMENSION;
|
||||
}
|
||||
}
|
||||
smallestDimension = MIN_DIMENSION;
|
||||
}
|
||||
margin = glm::min(glm::max(0.5f * smallestDimension, MIN_MARGIN), margin);
|
||||
hull->setMargin(margin);
|
||||
|
||||
// add the points, correcting for margin
|
||||
|
|
|
@ -21,6 +21,9 @@ float evalOpaqueFinalAlpha(float alpha, float mapAlpha) {
|
|||
return mix(alpha * glowIntensity, 1.0 - alpha * glowIntensity, step(mapAlpha, alphaThreshold));
|
||||
}
|
||||
|
||||
const vec3 DEFAULT_SPECULAR = vec3(0.1);
|
||||
const float DEFAULT_SHININESS = 10;
|
||||
|
||||
void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) {
|
||||
if (alpha != glowIntensity) {
|
||||
discard;
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
|
||||
#include "AbstractViewStateInterface.h"
|
||||
#include "GeometryCache.h"
|
||||
#include "RenderUtil.h"
|
||||
#include "TextureCache.h"
|
||||
#include "FramebufferCache.h"
|
||||
|
||||
|
||||
#include "simple_vert.h"
|
||||
|
@ -142,6 +142,10 @@ void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured,
|
|||
bool emmisive, bool depthBias) {
|
||||
SimpleProgramKey config{textured, culled, emmisive, depthBias};
|
||||
batch.setPipeline(getPipeline(config));
|
||||
|
||||
gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader;
|
||||
int glowIntensity = program->getUniforms().findLocation("glowIntensity");
|
||||
batch._glUniform1f(glowIntensity, 1.0f);
|
||||
|
||||
if (!config.isTextured()) {
|
||||
// If it is not textured, bind white texture and keep using textured pipeline
|
||||
|
@ -215,42 +219,47 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu
|
|||
}
|
||||
|
||||
void DeferredLightingEffect::prepare(RenderArgs* args) {
|
||||
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
gpu::Batch batch;
|
||||
|
||||
// clear the normal and specular buffers
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR1, glm::vec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
const float MAX_SPECULAR_EXPONENT = 128.0f;
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR2, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f / MAX_SPECULAR_EXPONENT));
|
||||
|
||||
args->_context->syncCache();
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
auto primaryFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer();
|
||||
|
||||
batch.setFramebuffer(primaryFbo);
|
||||
// clear the normal and specular buffers
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR1, glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true);
|
||||
const float MAX_SPECULAR_EXPONENT = 128.0f;
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR2, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f / MAX_SPECULAR_EXPONENT), true);
|
||||
|
||||
args->_context->render(batch);
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer _copyFBO;
|
||||
|
||||
void DeferredLightingEffect::render(RenderArgs* args) {
|
||||
gpu::Batch batch;
|
||||
|
||||
// perform deferred lighting, rendering to free fbo
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||
|
||||
QSize framebufferSize = textureCache->getFrameBufferSize();
|
||||
QSize framebufferSize = framebufferCache->getFrameBufferSize();
|
||||
|
||||
// binding the first framebuffer
|
||||
auto freeFBO = DependencyManager::get<TextureCache>()->getSecondaryFramebuffer();
|
||||
batch.setFramebuffer(freeFBO);
|
||||
_copyFBO = framebufferCache->getFramebuffer();
|
||||
batch.setFramebuffer(_copyFBO);
|
||||
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
batch.clearColorFramebuffer(freeFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
batch.clearColorFramebuffer(_copyFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true);
|
||||
|
||||
batch.setResourceTexture(0, textureCache->getPrimaryColorTexture());
|
||||
batch.setResourceTexture(0, framebufferCache->getPrimaryColorTexture());
|
||||
|
||||
batch.setResourceTexture(1, textureCache->getPrimaryNormalTexture());
|
||||
batch.setResourceTexture(1, framebufferCache->getPrimaryNormalTexture());
|
||||
|
||||
batch.setResourceTexture(2, textureCache->getPrimarySpecularTexture());
|
||||
batch.setResourceTexture(2, framebufferCache->getPrimarySpecularTexture());
|
||||
|
||||
batch.setResourceTexture(3, textureCache->getPrimaryDepthTexture());
|
||||
batch.setResourceTexture(3, framebufferCache->getPrimaryDepthTexture());
|
||||
|
||||
float sMin = args->_viewport.x / (float)framebufferSize.width();
|
||||
float sWidth = args->_viewport.z / (float)framebufferSize.width();
|
||||
|
@ -267,7 +276,7 @@ void DeferredLightingEffect::render(RenderArgs* args) {
|
|||
const LightLocations* locations = &_directionalLightLocations;
|
||||
bool shadowsEnabled = _viewState->getShadowsEnabled();
|
||||
if (shadowsEnabled) {
|
||||
batch.setResourceTexture(4, textureCache->getShadowFramebuffer()->getDepthStencilBuffer());
|
||||
batch.setResourceTexture(4, framebufferCache->getShadowFramebuffer()->getDepthStencilBuffer());
|
||||
|
||||
program = _directionalLightShadowMap;
|
||||
locations = &_directionalLightShadowMapLocations;
|
||||
|
@ -294,7 +303,7 @@ void DeferredLightingEffect::render(RenderArgs* args) {
|
|||
}
|
||||
batch.setPipeline(program);
|
||||
}
|
||||
batch._glUniform1f(locations->shadowScale, 1.0f / textureCache->getShadowFramebuffer()->getWidth());
|
||||
batch._glUniform1f(locations->shadowScale, 1.0f / framebufferCache->getShadowFramebuffer()->getWidth());
|
||||
|
||||
} else {
|
||||
if (useSkyboxCubemap) {
|
||||
|
@ -529,44 +538,43 @@ void DeferredLightingEffect::render(RenderArgs* args) {
|
|||
batch.setResourceTexture(2, nullptr);
|
||||
batch.setResourceTexture(3, nullptr);
|
||||
|
||||
args->_context->syncCache();
|
||||
args->_context->render(batch);
|
||||
|
||||
// End of the Lighting pass
|
||||
}
|
||||
|
||||
|
||||
void DeferredLightingEffect::copyBack(RenderArgs* args) {
|
||||
gpu::Batch batch;
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
QSize framebufferSize = textureCache->getFrameBufferSize();
|
||||
|
||||
auto freeFBO = DependencyManager::get<TextureCache>()->getSecondaryFramebuffer();
|
||||
|
||||
batch.setFramebuffer(textureCache->getPrimaryFramebuffer());
|
||||
batch.setPipeline(_blitLightBuffer);
|
||||
|
||||
batch.setResourceTexture(0, freeFBO->getRenderBuffer(0));
|
||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||
QSize framebufferSize = framebufferCache->getFrameBufferSize();
|
||||
|
||||
// TODO why doesn't this blit work? It only seems to affect a small area below the rear view mirror.
|
||||
// auto destFbo = framebufferCache->getPrimaryFramebuffer();
|
||||
auto destFbo = framebufferCache->getPrimaryFramebufferDepthColor();
|
||||
// gpu::Vec4i vp = args->_viewport;
|
||||
// batch.blit(_copyFBO, vp, framebufferCache->getPrimaryFramebuffer(), vp);
|
||||
batch.setFramebuffer(destFbo);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setProjectionTransform(glm::mat4());
|
||||
batch.setViewTransform(Transform());
|
||||
|
||||
float sMin = args->_viewport.x / (float)framebufferSize.width();
|
||||
float sWidth = args->_viewport.z / (float)framebufferSize.width();
|
||||
float tMin = args->_viewport.y / (float)framebufferSize.height();
|
||||
float tHeight = args->_viewport.w / (float)framebufferSize.height();
|
||||
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
|
||||
Transform model;
|
||||
model.setTranslation(glm::vec3(sMin, tMin, 0.0));
|
||||
model.setScale(glm::vec3(sWidth, tHeight, 1.0));
|
||||
batch.setModelTransform(model);
|
||||
{
|
||||
float sMin = args->_viewport.x / (float)framebufferSize.width();
|
||||
float sWidth = args->_viewport.z / (float)framebufferSize.width();
|
||||
float tMin = args->_viewport.y / (float)framebufferSize.height();
|
||||
float tHeight = args->_viewport.w / (float)framebufferSize.height();
|
||||
Transform model;
|
||||
batch.setPipeline(_blitLightBuffer);
|
||||
model.setTranslation(glm::vec3(sMin, tMin, 0.0));
|
||||
model.setScale(glm::vec3(sWidth, tHeight, 1.0));
|
||||
batch.setModelTransform(model);
|
||||
}
|
||||
|
||||
batch.setResourceTexture(0, _copyFBO->getRenderBuffer(0));
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
|
||||
args->_context->syncCache();
|
||||
args->_context->render(batch);
|
||||
framebufferCache->releaseFramebuffer(_copyFBO);
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::setupTransparent(RenderArgs* args, int lightBufferUnit) {
|
||||
|
|
150
libraries/render-utils/src/FramebufferCache.cpp
Normal file
150
libraries/render-utils/src/FramebufferCache.cpp
Normal file
|
@ -0,0 +1,150 @@
|
|||
//
|
||||
// FramebufferCache.cpp
|
||||
// interface/src/renderer
|
||||
//
|
||||
// Created by Andrzej Kapolka on 8/6/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 "FramebufferCache.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <QMap>
|
||||
#include <QQueue>
|
||||
#include <gpu/Batch.h>
|
||||
#include <gpu/GPUConfig.h>
|
||||
#include "RenderUtilsLogging.h"
|
||||
|
||||
static QQueue<gpu::FramebufferPointer> _cachedFramebuffers;
|
||||
|
||||
FramebufferCache::FramebufferCache() {
|
||||
}
|
||||
|
||||
FramebufferCache::~FramebufferCache() {
|
||||
_cachedFramebuffers.clear();
|
||||
}
|
||||
|
||||
void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) {
|
||||
//If the size changed, we need to delete our FBOs
|
||||
if (_frameBufferSize != frameBufferSize) {
|
||||
_frameBufferSize = frameBufferSize;
|
||||
_primaryFramebufferFull.reset();
|
||||
_primaryFramebufferDepthColor.reset();
|
||||
_primaryDepthTexture.reset();
|
||||
_primaryColorTexture.reset();
|
||||
_primaryNormalTexture.reset();
|
||||
_primarySpecularTexture.reset();
|
||||
_selfieFramebuffer.reset();
|
||||
_cachedFramebuffers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferCache::createPrimaryFramebuffer() {
|
||||
_primaryFramebufferFull = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||
_primaryFramebufferDepthColor = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||
|
||||
auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
|
||||
auto width = _frameBufferSize.width();
|
||||
auto height = _frameBufferSize.height();
|
||||
|
||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
|
||||
_primaryColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler));
|
||||
_primaryNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler));
|
||||
_primarySpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler));
|
||||
|
||||
_primaryFramebufferFull->setRenderBuffer(0, _primaryColorTexture);
|
||||
_primaryFramebufferFull->setRenderBuffer(1, _primaryNormalTexture);
|
||||
_primaryFramebufferFull->setRenderBuffer(2, _primarySpecularTexture);
|
||||
|
||||
_primaryFramebufferDepthColor->setRenderBuffer(0, _primaryColorTexture);
|
||||
|
||||
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH);
|
||||
_primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler));
|
||||
|
||||
_primaryFramebufferFull->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
|
||||
|
||||
_primaryFramebufferDepthColor->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
|
||||
|
||||
_selfieFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||
auto tex = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width * 0.5, height * 0.5, defaultSampler));
|
||||
_selfieFramebuffer->setRenderBuffer(0, tex);
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer FramebufferCache::getPrimaryFramebuffer() {
|
||||
if (!_primaryFramebufferFull) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _primaryFramebufferFull;
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer FramebufferCache::getPrimaryFramebufferDepthColor() {
|
||||
if (!_primaryFramebufferDepthColor) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _primaryFramebufferDepthColor;
|
||||
}
|
||||
|
||||
|
||||
gpu::TexturePointer FramebufferCache::getPrimaryDepthTexture() {
|
||||
if (!_primaryDepthTexture) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _primaryDepthTexture;
|
||||
}
|
||||
|
||||
gpu::TexturePointer FramebufferCache::getPrimaryColorTexture() {
|
||||
if (!_primaryColorTexture) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _primaryColorTexture;
|
||||
}
|
||||
|
||||
gpu::TexturePointer FramebufferCache::getPrimaryNormalTexture() {
|
||||
if (!_primaryNormalTexture) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _primaryNormalTexture;
|
||||
}
|
||||
|
||||
gpu::TexturePointer FramebufferCache::getPrimarySpecularTexture() {
|
||||
if (!_primarySpecularTexture) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _primarySpecularTexture;
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer FramebufferCache::getFramebuffer() {
|
||||
if (_cachedFramebuffers.isEmpty()) {
|
||||
_cachedFramebuffers.push_back(gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height())));
|
||||
}
|
||||
gpu::FramebufferPointer result = _cachedFramebuffers.front();
|
||||
_cachedFramebuffers.pop_front();
|
||||
return result;
|
||||
}
|
||||
|
||||
void FramebufferCache::releaseFramebuffer(const gpu::FramebufferPointer& framebuffer) {
|
||||
if (QSize(framebuffer->getSize().x, framebuffer->getSize().y) == _frameBufferSize) {
|
||||
_cachedFramebuffers.push_back(framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer FramebufferCache::getShadowFramebuffer() {
|
||||
if (!_shadowFramebuffer) {
|
||||
const int SHADOW_MAP_SIZE = 2048;
|
||||
_shadowFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(SHADOW_MAP_SIZE));
|
||||
}
|
||||
return _shadowFramebuffer;
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer FramebufferCache::getSelfieFramebuffer() {
|
||||
if (!_selfieFramebuffer) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _selfieFramebuffer;
|
||||
}
|
73
libraries/render-utils/src/FramebufferCache.h
Normal file
73
libraries/render-utils/src/FramebufferCache.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/07/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
|
||||
//
|
||||
|
||||
#ifndef hifi_FramebufferCache_h
|
||||
#define hifi_FramebufferCache_h
|
||||
|
||||
#include <QSize>
|
||||
|
||||
#include <gpu/Framebuffer.h>
|
||||
#include <DependencyManager.h>
|
||||
|
||||
namespace gpu {
|
||||
class Batch;
|
||||
}
|
||||
|
||||
/// Stores cached textures, including render-to-texture targets.
|
||||
class FramebufferCache : public Dependency {
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
/// Sets the desired texture resolution for the framebuffer objects.
|
||||
void setFrameBufferSize(QSize frameBufferSize);
|
||||
const QSize& getFrameBufferSize() const { return _frameBufferSize; }
|
||||
|
||||
/// Returns a pointer to the primary framebuffer object. This render target includes a depth component, and is
|
||||
/// used for scene rendering.
|
||||
gpu::FramebufferPointer getPrimaryFramebuffer();
|
||||
gpu::FramebufferPointer getPrimaryFramebufferDepthColor();
|
||||
|
||||
gpu::TexturePointer getPrimaryDepthTexture();
|
||||
gpu::TexturePointer getPrimaryColorTexture();
|
||||
gpu::TexturePointer getPrimaryNormalTexture();
|
||||
gpu::TexturePointer getPrimarySpecularTexture();
|
||||
|
||||
/// Returns the framebuffer object used to render shadow maps;
|
||||
gpu::FramebufferPointer getShadowFramebuffer();
|
||||
|
||||
/// Returns the framebuffer object used to render selfie maps;
|
||||
gpu::FramebufferPointer getSelfieFramebuffer();
|
||||
|
||||
/// Returns a free framebuffer with a single color attachment for temp or intra-frame operations
|
||||
gpu::FramebufferPointer getFramebuffer();
|
||||
|
||||
// TODO add sync functionality to the release, so we don't reuse a framebuffer being read from
|
||||
/// Releases a free framebuffer back for reuse
|
||||
void releaseFramebuffer(const gpu::FramebufferPointer& framebuffer);
|
||||
|
||||
private:
|
||||
FramebufferCache();
|
||||
virtual ~FramebufferCache();
|
||||
|
||||
void createPrimaryFramebuffer();
|
||||
|
||||
gpu::FramebufferPointer _primaryFramebufferFull;
|
||||
gpu::FramebufferPointer _primaryFramebufferDepthColor;
|
||||
gpu::TexturePointer _primaryDepthTexture;
|
||||
gpu::TexturePointer _primaryColorTexture;
|
||||
gpu::TexturePointer _primaryNormalTexture;
|
||||
gpu::TexturePointer _primarySpecularTexture;
|
||||
|
||||
gpu::FramebufferPointer _shadowFramebuffer;
|
||||
|
||||
gpu::FramebufferPointer _selfieFramebuffer;
|
||||
|
||||
QSize _frameBufferSize{ 100, 100 };
|
||||
};
|
||||
|
||||
#endif // hifi_FramebufferCache_h
|
|
@ -29,6 +29,8 @@
|
|||
#include "standardTransformPNTC_vert.h"
|
||||
#include "standardDrawTexture_frag.h"
|
||||
|
||||
#include "gpu/StandardShaderLib.h"
|
||||
|
||||
//#define WANT_DEBUG
|
||||
|
||||
const int GeometryCache::UNKNOWN_ID = -1;
|
||||
|
@ -54,12 +56,6 @@ const int NUM_TRIANGLES_PER_QUAD = 2;
|
|||
const int NUM_VERTICES_PER_TRIANGULATED_QUAD = NUM_VERTICES_PER_TRIANGLE * NUM_TRIANGLES_PER_QUAD;
|
||||
const int NUM_COORDS_PER_VERTEX = 3;
|
||||
|
||||
void GeometryCache::renderSphere(float radius, int slices, int stacks, const glm::vec4& color, bool solid, int id) {
|
||||
gpu::Batch batch;
|
||||
renderSphere(batch, radius, slices, stacks, color, solid, id);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color, bool solid, int id) {
|
||||
bool registered = (id != UNKNOWN_ID);
|
||||
|
||||
|
@ -304,12 +300,6 @@ void GeometryCache::renderSphere(gpu::Batch& batch, float radius, int slices, in
|
|||
}
|
||||
}
|
||||
|
||||
void GeometryCache::renderGrid(int xDivisions, int yDivisions, const glm::vec4& color) {
|
||||
gpu::Batch batch;
|
||||
renderGrid(batch, xDivisions, yDivisions, color);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color) {
|
||||
IntPair key(xDivisions, yDivisions);
|
||||
Vec3Pair colorKey(glm::vec3(color.x, color.y, yDivisions), glm::vec3(color.z, color.y, xDivisions));
|
||||
|
@ -384,12 +374,6 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions
|
|||
batch.draw(gpu::LINES, vertices, 0);
|
||||
}
|
||||
|
||||
void GeometryCache::renderGrid(int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id) {
|
||||
gpu::Batch batch;
|
||||
renderGrid(batch, x, y, width, height, rows, cols, color, id);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
// TODO: why do we seem to create extra BatchItemDetails when we resize the window?? what's that??
|
||||
void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id) {
|
||||
#ifdef WANT_DEBUG
|
||||
|
@ -691,12 +675,6 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
|
|||
#endif
|
||||
}
|
||||
|
||||
void GeometryCache::renderVertices(gpu::Primitive primitiveType, int id) {
|
||||
gpu::Batch batch;
|
||||
renderVertices(batch, primitiveType, id);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderVertices(gpu::Batch& batch, gpu::Primitive primitiveType, int id) {
|
||||
BatchItemDetails& details = _registeredVertices[id];
|
||||
if (details.isCreated) {
|
||||
|
@ -706,12 +684,6 @@ void GeometryCache::renderVertices(gpu::Batch& batch, gpu::Primitive primitiveTy
|
|||
}
|
||||
}
|
||||
|
||||
void GeometryCache::renderSolidCube(float size, const glm::vec4& color) {
|
||||
gpu::Batch batch;
|
||||
renderSolidCube(batch, size, color);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color) {
|
||||
Vec2Pair colorKey(glm::vec2(color.x, color.y), glm::vec2(color.z, color.y));
|
||||
const int FLOATS_PER_VERTEX = 3;
|
||||
|
@ -833,12 +805,6 @@ void GeometryCache::renderSolidCube(gpu::Batch& batch, float size, const glm::ve
|
|||
batch.drawIndexed(gpu::TRIANGLES, indices);
|
||||
}
|
||||
|
||||
void GeometryCache::renderWireCube(float size, const glm::vec4& color) {
|
||||
gpu::Batch batch;
|
||||
renderWireCube(batch, size, color);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderWireCube(gpu::Batch& batch, float size, const glm::vec4& color) {
|
||||
Vec2Pair colorKey(glm::vec2(color.x, color.y),glm::vec2(color.z, color.y));
|
||||
const int FLOATS_PER_VERTEX = 3;
|
||||
|
@ -922,12 +888,6 @@ void GeometryCache::renderWireCube(gpu::Batch& batch, float size, const glm::vec
|
|||
batch.drawIndexed(gpu::LINES, indices);
|
||||
}
|
||||
|
||||
void GeometryCache::renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id) {
|
||||
gpu::Batch batch;
|
||||
renderBevelCornersRect(batch, x, y, width, height, bevelDistance, color, id);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id) {
|
||||
bool registered = (id != UNKNOWN_ID);
|
||||
Vec3Pair key(glm::vec3(x, y, 0.0f), glm::vec3(width, height, bevelDistance));
|
||||
|
@ -1029,12 +989,6 @@ void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int
|
|||
batch.draw(gpu::TRIANGLE_STRIP, details.vertices, 0);
|
||||
}
|
||||
|
||||
void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id) {
|
||||
gpu::Batch batch;
|
||||
renderQuad(batch, minCorner, maxCorner, color, id);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id) {
|
||||
bool registered = (id != UNKNOWN_ID);
|
||||
Vec4Pair key(glm::vec4(minCorner.x, minCorner.y, maxCorner.x, maxCorner.y), color);
|
||||
|
@ -1111,12 +1065,6 @@ void GeometryCache::renderUnitCube(gpu::Batch& batch) {
|
|||
renderSolidCube(batch, 1, color);
|
||||
}
|
||||
|
||||
void GeometryCache::renderUnitQuad(const glm::vec4& color, int id) {
|
||||
gpu::Batch batch;
|
||||
renderUnitQuad(batch, color, id);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, int id) {
|
||||
static const glm::vec2 topLeft(-1, 1);
|
||||
static const glm::vec2 bottomRight(1, -1);
|
||||
|
@ -1126,14 +1074,6 @@ void GeometryCache::renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, in
|
|||
}
|
||||
|
||||
|
||||
void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner,
|
||||
const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
|
||||
const glm::vec4& color, int id) {
|
||||
gpu::Batch batch;
|
||||
renderQuad(batch, minCorner, maxCorner, texCoordMinCorner, texCoordMaxCorner, color, id);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
|
||||
const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
|
||||
const glm::vec4& color, int id) {
|
||||
|
@ -1214,12 +1154,6 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co
|
|||
batch.draw(gpu::QUADS, 4, 0);
|
||||
}
|
||||
|
||||
void GeometryCache::renderQuad(const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id) {
|
||||
gpu::Batch batch;
|
||||
renderQuad(batch, minCorner, maxCorner, color, id);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id) {
|
||||
bool registered = (id != UNKNOWN_ID);
|
||||
Vec3PairVec4 key(Vec3Pair(minCorner, maxCorner), color);
|
||||
|
@ -1291,17 +1225,6 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co
|
|||
batch.draw(gpu::QUADS, 4, 0);
|
||||
}
|
||||
|
||||
void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomLeft,
|
||||
const glm::vec3& bottomRight, const glm::vec3& topRight,
|
||||
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
|
||||
const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight,
|
||||
const glm::vec4& color, int id) {
|
||||
gpu::Batch batch;
|
||||
renderQuad(batch, topLeft, bottomLeft, bottomRight, topRight, texCoordTopLeft, texCoordBottomLeft,
|
||||
texCoordBottomRight, texCoordTopRight, color, id);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, const glm::vec3& bottomLeft,
|
||||
const glm::vec3& bottomRight, const glm::vec3& topRight,
|
||||
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
|
||||
|
@ -1395,12 +1318,6 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons
|
|||
batch.draw(gpu::QUADS, 4, 0);
|
||||
}
|
||||
|
||||
void GeometryCache::renderDashedLine(const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id) {
|
||||
gpu::Batch batch;
|
||||
renderDashedLine(batch, start, end, color, id);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id) {
|
||||
bool registered = (id != UNKNOWN_ID);
|
||||
Vec3PairVec2Pair key(Vec3Pair(start, end), Vec2Pair(glm::vec2(color.x, color.y), glm::vec2(color.z, color.w)));
|
||||
|
@ -1555,13 +1472,6 @@ void GeometryCache::BatchItemDetails::clear() {
|
|||
stream.reset();
|
||||
}
|
||||
|
||||
void GeometryCache::renderLine(const glm::vec3& p1, const glm::vec3& p2,
|
||||
const glm::vec4& color1, const glm::vec4& color2, int id) {
|
||||
gpu::Batch batch;
|
||||
renderLine(batch, p1, p2, color1, color2, id);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
|
||||
const glm::vec4& color1, const glm::vec4& color2, int id) {
|
||||
|
||||
|
@ -1646,12 +1556,6 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm
|
|||
batch.draw(gpu::LINES, 2, 0);
|
||||
}
|
||||
|
||||
void GeometryCache::renderLine(const glm::vec2& p1, const glm::vec2& p2, const glm::vec4& color1, const glm::vec4& color2, int id) {
|
||||
gpu::Batch batch;
|
||||
renderLine(batch, p1, p2, color1, color2, id);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2,
|
||||
const glm::vec4& color1, const glm::vec4& color2, int id) {
|
||||
|
||||
|
@ -1749,7 +1653,7 @@ QSharedPointer<Resource> GeometryCache::createResource(const QUrl& url, const QS
|
|||
return geometry.staticCast<Resource>();
|
||||
}
|
||||
|
||||
void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch) {
|
||||
void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) {
|
||||
if (!_standardDrawPipeline) {
|
||||
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert)));
|
||||
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(standardDrawTexture_frag)));
|
||||
|
@ -1758,12 +1662,24 @@ void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch) {
|
|||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
|
||||
|
||||
// enable decal blend
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
|
||||
_standardDrawPipeline.reset(gpu::Pipeline::create(program, state));
|
||||
|
||||
|
||||
auto stateNoBlend = std::make_shared<gpu::State>();
|
||||
auto noBlendPS = gpu::StandardShaderLib::getDrawTextureOpaquePS();
|
||||
auto programNoBlend = gpu::ShaderPointer(gpu::Shader::createProgram(vs, noBlendPS));
|
||||
gpu::Shader::makeProgram((*programNoBlend));
|
||||
_standardDrawPipelineNoBlend.reset(gpu::Pipeline::create(programNoBlend, stateNoBlend));
|
||||
}
|
||||
if (noBlend) {
|
||||
batch.setPipeline(_standardDrawPipelineNoBlend);
|
||||
} else {
|
||||
batch.setPipeline(_standardDrawPipeline);
|
||||
}
|
||||
batch.setPipeline(_standardDrawPipeline);
|
||||
}
|
||||
|
||||
const float NetworkGeometry::NO_HYSTERESIS = -1.0f;
|
||||
|
|
|
@ -129,56 +129,35 @@ public:
|
|||
int allocateID() { return _nextID++; }
|
||||
static const int UNKNOWN_ID;
|
||||
|
||||
void renderSphere(float radius, int slices, int stacks, const glm::vec3& color, bool solid = true, int id = UNKNOWN_ID)
|
||||
{ renderSphere(radius, slices, stacks, glm::vec4(color, 1.0f), solid, id); }
|
||||
void renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec3& color, bool solid = true, int id = UNKNOWN_ID)
|
||||
{ renderSphere(batch, radius, slices, stacks, glm::vec4(color, 1.0f), solid, id); }
|
||||
|
||||
void renderSphere(float radius, int slices, int stacks, const glm::vec4& color, bool solid = true, int id = UNKNOWN_ID);
|
||||
void renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color, bool solid = true, int id = UNKNOWN_ID);
|
||||
|
||||
void renderGrid(int xDivisions, int yDivisions, const glm::vec4& color);
|
||||
void renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color);
|
||||
void renderGrid(int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
void renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
|
||||
void renderSolidCube(float size, const glm::vec4& color);
|
||||
void renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color);
|
||||
void renderWireCube(float size, const glm::vec4& color);
|
||||
void renderWireCube(gpu::Batch& batch, float size, const glm::vec4& color);
|
||||
void renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
void renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
|
||||
void renderUnitCube(gpu::Batch& batch);
|
||||
void renderUnitQuad(const glm::vec4& color = glm::vec4(1), int id = UNKNOWN_ID);
|
||||
void renderUnitQuad(gpu::Batch& batch, const glm::vec4& color = glm::vec4(1), int id = UNKNOWN_ID);
|
||||
|
||||
void renderQuad(int x, int y, int width, int height, const glm::vec4& color, int id = UNKNOWN_ID)
|
||||
{ renderQuad(glm::vec2(x,y), glm::vec2(x + width, y + height), color, id); }
|
||||
void renderQuad(gpu::Batch& batch, int x, int y, int width, int height, const glm::vec4& color, int id = UNKNOWN_ID)
|
||||
{ renderQuad(batch, glm::vec2(x,y), glm::vec2(x + width, y + height), color, id); }
|
||||
|
||||
// TODO: I think there's a bug in this version of the renderQuad() that's not correctly rebuilding the vbos
|
||||
// if the color changes by the corners are the same, as evidenced by the audio meter which should turn white
|
||||
// when it's clipping
|
||||
void renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
void renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
|
||||
void renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner,
|
||||
const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
|
||||
const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
void renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
|
||||
const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
|
||||
const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
|
||||
void renderQuad(const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
void renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
|
||||
void renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomLeft,
|
||||
const glm::vec3& bottomRight, const glm::vec3& topRight,
|
||||
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
|
||||
const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight,
|
||||
const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
void renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, const glm::vec3& bottomLeft,
|
||||
const glm::vec3& bottomRight, const glm::vec3& topRight,
|
||||
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
|
||||
|
@ -186,53 +165,33 @@ public:
|
|||
const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
|
||||
|
||||
void renderLine(const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& color, int id = UNKNOWN_ID)
|
||||
{ renderLine(p1, p2, color, color, id); }
|
||||
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& color, int id = UNKNOWN_ID)
|
||||
{ renderLine(batch, p1, p2, color, color, id); }
|
||||
|
||||
void renderLine(const glm::vec3& p1, const glm::vec3& p2,
|
||||
const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID)
|
||||
{ renderLine(p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); }
|
||||
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
|
||||
const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID)
|
||||
{ renderLine(batch, p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); }
|
||||
|
||||
void renderLine(const glm::vec3& p1, const glm::vec3& p2,
|
||||
const glm::vec4& color, int id = UNKNOWN_ID)
|
||||
{ renderLine(p1, p2, color, color, id); }
|
||||
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
|
||||
const glm::vec4& color, int id = UNKNOWN_ID)
|
||||
{ renderLine(batch, p1, p2, color, color, id); }
|
||||
|
||||
void renderLine(const glm::vec3& p1, const glm::vec3& p2,
|
||||
const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID);
|
||||
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
|
||||
const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID);
|
||||
|
||||
void renderDashedLine(const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
void renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
|
||||
void renderLine(const glm::vec2& p1, const glm::vec2& p2, const glm::vec3& color, int id = UNKNOWN_ID)
|
||||
{ renderLine(p1, p2, glm::vec4(color, 1.0f), id); }
|
||||
void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2, const glm::vec3& color, int id = UNKNOWN_ID)
|
||||
{ renderLine(batch, p1, p2, glm::vec4(color, 1.0f), id); }
|
||||
|
||||
void renderLine(const glm::vec2& p1, const glm::vec2& p2, const glm::vec4& color, int id = UNKNOWN_ID)
|
||||
{ renderLine(p1, p2, color, color, id); }
|
||||
void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2, const glm::vec4& color, int id = UNKNOWN_ID)
|
||||
{ renderLine(batch, p1, p2, color, color, id); }
|
||||
|
||||
|
||||
void renderLine(const glm::vec2& p1, const glm::vec2& p2,
|
||||
const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID)
|
||||
{ renderLine(p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); }
|
||||
void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2,
|
||||
const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID)
|
||||
{ renderLine(batch, p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); }
|
||||
|
||||
void renderLine(const glm::vec2& p1, const glm::vec2& p2,
|
||||
const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID);
|
||||
void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2,
|
||||
const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID);
|
||||
|
||||
|
@ -240,7 +199,6 @@ public:
|
|||
void updateVertices(int id, const QVector<glm::vec3>& points, const glm::vec4& color);
|
||||
void updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec2>& texCoords, const glm::vec4& color);
|
||||
void renderVertices(gpu::Batch& batch, gpu::Primitive primitiveType, int id);
|
||||
void renderVertices(gpu::Primitive primitiveType, int id);
|
||||
|
||||
/// Loads geometry from the specified URL.
|
||||
/// \param fallback a fallback URL to load if the desired one is unavailable
|
||||
|
@ -248,7 +206,7 @@ public:
|
|||
QSharedPointer<NetworkGeometry> getGeometry(const QUrl& url, const QUrl& fallback = QUrl(), bool delayLoad = false);
|
||||
|
||||
/// Set a batch to the simple pipeline, returning the previous pipeline
|
||||
void useSimpleDrawPipeline(gpu::Batch& batch);
|
||||
void useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend = false);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -263,6 +221,7 @@ private:
|
|||
typedef QPair<unsigned int, unsigned int> VerticesIndices;
|
||||
|
||||
gpu::PipelinePointer _standardDrawPipeline;
|
||||
gpu::PipelinePointer _standardDrawPipelineNoBlend;
|
||||
QHash<float, gpu::BufferPointer> _cubeVerticies;
|
||||
QHash<Vec2Pair, gpu::BufferPointer> _cubeColors;
|
||||
gpu::BufferPointer _wireCubeIndexBuffer;
|
||||
|
|
|
@ -946,7 +946,7 @@ void Model::removeFromScene(std::shared_ptr<render::Scene> scene, render::Pendin
|
|||
_readyWhenAdded = false;
|
||||
}
|
||||
|
||||
void Model::renderDebugMeshBoxes() {
|
||||
void Model::renderDebugMeshBoxes(gpu::Batch& batch) {
|
||||
int colorNdx = 0;
|
||||
_mutex.lock();
|
||||
foreach(AABox box, _calculatedMeshBoxes) {
|
||||
|
@ -995,7 +995,7 @@ void Model::renderDebugMeshBoxes() {
|
|||
{ 0.0f, 0.5f, 0.5f, 1.0f } };
|
||||
|
||||
DependencyManager::get<GeometryCache>()->updateVertices(_debugMeshBoxesID, points, color[colorNdx]);
|
||||
DependencyManager::get<GeometryCache>()->renderVertices(gpu::LINES, _debugMeshBoxesID);
|
||||
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINES, _debugMeshBoxesID);
|
||||
colorNdx++;
|
||||
}
|
||||
_mutex.unlock();
|
||||
|
|
|
@ -399,7 +399,7 @@ private:
|
|||
|
||||
|
||||
// debug rendering support
|
||||
void renderDebugMeshBoxes();
|
||||
void renderDebugMeshBoxes(gpu::Batch& batch);
|
||||
int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID;
|
||||
|
||||
// helper functions used by render() or renderInScene()
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <RenderArgs.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include "FramebufferCache.h"
|
||||
#include "DeferredLightingEffect.h"
|
||||
#include "TextureCache.h"
|
||||
|
||||
|
@ -27,6 +28,26 @@
|
|||
|
||||
using namespace render;
|
||||
|
||||
void SetupDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
auto primaryFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferDepthColor();
|
||||
|
||||
gpu::Batch batch;
|
||||
batch.setFramebuffer(nullptr);
|
||||
batch.setFramebuffer(primaryFbo);
|
||||
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
batch.clearFramebuffer(
|
||||
gpu::Framebuffer::BUFFER_COLOR0 |
|
||||
gpu::Framebuffer::BUFFER_DEPTH,
|
||||
vec4(vec3(0), 1), 1.0, 0.0, true);
|
||||
|
||||
args->_context->render(batch);
|
||||
}
|
||||
|
||||
void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
DependencyManager::get<DeferredLightingEffect>()->prepare(renderContext->args);
|
||||
}
|
||||
|
@ -41,6 +62,7 @@ void ResolveDeferred::run(const SceneContextPointer& sceneContext, const RenderC
|
|||
}
|
||||
|
||||
RenderDeferredTask::RenderDeferredTask() : Task() {
|
||||
_jobs.push_back(Job(new SetupDeferred::JobModel("SetupFramebuffer")));
|
||||
_jobs.push_back(Job(new DrawBackground::JobModel("DrawBackground")));
|
||||
|
||||
_jobs.push_back(Job(new PrepareDeferred::JobModel("PrepareDeferred")));
|
||||
|
@ -56,7 +78,6 @@ RenderDeferredTask::RenderDeferredTask() : Task() {
|
|||
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 ResetGLState::JobModel()));
|
||||
_jobs.push_back(Job(new RenderDeferred::JobModel("RenderDeferred")));
|
||||
_jobs.push_back(Job(new ResolveDeferred::JobModel("ResolveDeferred")));
|
||||
_jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent",
|
||||
|
@ -133,21 +154,12 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend
|
|||
batch.setViewTransform(viewMat);
|
||||
|
||||
{
|
||||
GLenum buffers[3];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||
batch._glDrawBuffers(bufferCount, buffers);
|
||||
const float OPAQUE_ALPHA_THRESHOLD = 0.5f;
|
||||
args->_alphaThreshold = OPAQUE_ALPHA_THRESHOLD;
|
||||
}
|
||||
|
||||
renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnOpaqueItems);
|
||||
|
||||
// Before rendering the batch make sure we re in sync with gl state
|
||||
args->_context->syncCache();
|
||||
renderContext->args->_context->syncCache();
|
||||
args->_context->render((*args->_batch));
|
||||
args->_batch = nullptr;
|
||||
}
|
||||
|
@ -171,21 +183,15 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const
|
|||
}
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f;
|
||||
|
||||
{
|
||||
GLenum buffers[3];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
batch._glDrawBuffers(bufferCount, buffers);
|
||||
const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f;
|
||||
args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD;
|
||||
}
|
||||
|
||||
|
||||
renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnTransparentItems);
|
||||
|
||||
// Before rendering the batch make sure we re in sync with gl state
|
||||
args->_context->syncCache();
|
||||
|
||||
args->_context->render((*args->_batch));
|
||||
args->_batch = nullptr;
|
||||
}
|
||||
|
@ -239,17 +245,17 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon
|
|||
}
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
batch.setPipeline(getOpaquePipeline());
|
||||
batch.setResourceTexture(0, args->_whiteTexture);
|
||||
|
||||
if (!inItems.empty()) {
|
||||
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0);
|
||||
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0, true);
|
||||
renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnOverlay3DItems);
|
||||
}
|
||||
|
||||
// Before rendering the batch make sure we re in sync with gl state
|
||||
args->_context->syncCache();
|
||||
args->_context->render((*args->_batch));
|
||||
args->_batch = nullptr;
|
||||
args->_whiteTexture.reset();
|
||||
|
|
|
@ -16,6 +16,13 @@
|
|||
|
||||
#include "gpu/Pipeline.h"
|
||||
|
||||
class SetupDeferred {
|
||||
public:
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||
|
||||
typedef render::Job::Model<SetupDeferred> JobModel;
|
||||
};
|
||||
|
||||
class PrepareDeferred {
|
||||
public:
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
//
|
||||
// RenderUtil.cpp
|
||||
// interface/src/renderer
|
||||
//
|
||||
// Created by Andrzej Kapolka on 8/15/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 <DependencyManager.h>
|
||||
#include "GeometryCache.h"
|
||||
|
||||
#include "RenderUtil.h"
|
||||
|
||||
void renderFullscreenQuad(float sMin, float sMax, float tMin, float tMax) {
|
||||
glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glm::vec2 topLeft(-1.0f, -1.0f);
|
||||
glm::vec2 bottomRight(1.0f, 1.0f);
|
||||
glm::vec2 texCoordTopLeft(sMin, tMin);
|
||||
glm::vec2 texCoordBottomRight(sMax, tMax);
|
||||
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color);
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
//
|
||||
// RenderUtil.h
|
||||
// interface/src/renderer
|
||||
//
|
||||
// Created by Andrzej Kapolka on 8/15/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
|
||||
//
|
||||
|
||||
#ifndef hifi_RenderUtil_h
|
||||
#define hifi_RenderUtil_h
|
||||
|
||||
/// Renders a quad from (-1, -1, 0) to (1, 1, 0) with texture coordinates from (sMin, tMin) to (sMax, tMax).
|
||||
void renderFullscreenQuad(float sMin = 0.0f, float sMax = 1.0f, float tMin = 0.0f, float tMax = 1.0f);
|
||||
|
||||
#endif // hifi_RenderUtil_h
|
|
@ -9,6 +9,13 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "TextureCache.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/random.hpp>
|
||||
|
||||
#include <gpu/Batch.h>
|
||||
#include <gpu/GLBackend.h>
|
||||
#include <gpu/GPUConfig.h>
|
||||
|
@ -19,21 +26,10 @@
|
|||
#include <QThreadPool>
|
||||
#include <qimagereader.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/random.hpp>
|
||||
|
||||
#include "RenderUtilsLogging.h"
|
||||
#include "TextureCache.h"
|
||||
|
||||
|
||||
#include <mutex>
|
||||
|
||||
TextureCache::TextureCache() :
|
||||
_permutationNormalTexture(0),
|
||||
_whiteTexture(0),
|
||||
_blueTexture(0),
|
||||
_frameBufferSize(100, 100)
|
||||
{
|
||||
TextureCache::TextureCache() {
|
||||
const qint64 TEXTURE_DEFAULT_UNUSED_MAX_SIZE = DEFAULT_UNUSED_MAX_SIZE;
|
||||
setUnusedResourceCacheSize(TEXTURE_DEFAULT_UNUSED_MAX_SIZE);
|
||||
}
|
||||
|
@ -41,23 +37,6 @@ TextureCache::TextureCache() :
|
|||
TextureCache::~TextureCache() {
|
||||
}
|
||||
|
||||
void TextureCache::setFrameBufferSize(QSize frameBufferSize) {
|
||||
//If the size changed, we need to delete our FBOs
|
||||
if (_frameBufferSize != frameBufferSize) {
|
||||
_frameBufferSize = frameBufferSize;
|
||||
|
||||
_primaryFramebuffer.reset();
|
||||
_primaryDepthTexture.reset();
|
||||
_primaryColorTexture.reset();
|
||||
_primaryNormalTexture.reset();
|
||||
_primarySpecularTexture.reset();
|
||||
|
||||
_secondaryFramebuffer.reset();
|
||||
|
||||
_tertiaryFramebuffer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// use fixed table of permutations. Could also make ordered list programmatically
|
||||
// and then shuffle algorithm. For testing, this ensures consistent behavior in each run.
|
||||
// this list taken from Ken Perlin's Improved Noise reference implementation (orig. in Java) at
|
||||
|
@ -175,113 +154,6 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, TextureType type
|
|||
return texture;
|
||||
}
|
||||
|
||||
void TextureCache::createPrimaryFramebuffer() {
|
||||
_primaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||
|
||||
auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
|
||||
auto width = _frameBufferSize.width();
|
||||
auto height = _frameBufferSize.height();
|
||||
|
||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
|
||||
_primaryColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler));
|
||||
_primaryNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler));
|
||||
_primarySpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler));
|
||||
|
||||
_primaryFramebuffer->setRenderBuffer(0, _primaryColorTexture);
|
||||
_primaryFramebuffer->setRenderBuffer(1, _primaryNormalTexture);
|
||||
_primaryFramebuffer->setRenderBuffer(2, _primarySpecularTexture);
|
||||
|
||||
|
||||
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH);
|
||||
_primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler));
|
||||
|
||||
_primaryFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer TextureCache::getPrimaryFramebuffer() {
|
||||
if (!_primaryFramebuffer) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _primaryFramebuffer;
|
||||
}
|
||||
|
||||
gpu::TexturePointer TextureCache::getPrimaryDepthTexture() {
|
||||
if (!_primaryDepthTexture) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _primaryDepthTexture;
|
||||
}
|
||||
|
||||
gpu::TexturePointer TextureCache::getPrimaryColorTexture() {
|
||||
if (!_primaryColorTexture) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _primaryColorTexture;
|
||||
}
|
||||
|
||||
gpu::TexturePointer TextureCache::getPrimaryNormalTexture() {
|
||||
if (!_primaryNormalTexture) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _primaryNormalTexture;
|
||||
}
|
||||
|
||||
gpu::TexturePointer TextureCache::getPrimarySpecularTexture() {
|
||||
if (!_primarySpecularTexture) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _primarySpecularTexture;
|
||||
}
|
||||
|
||||
GLuint TextureCache::getPrimaryDepthTextureID() {
|
||||
return gpu::GLBackend::getTextureID(getPrimaryDepthTexture());
|
||||
}
|
||||
|
||||
void TextureCache::setPrimaryDrawBuffers(bool color, bool normal, bool specular) {
|
||||
gpu::Batch batch;
|
||||
setPrimaryDrawBuffers(batch, color, normal, specular);
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
|
||||
void TextureCache::setPrimaryDrawBuffers(gpu::Batch& batch, bool color, bool normal, bool specular) {
|
||||
GLenum buffers[3];
|
||||
int bufferCount = 0;
|
||||
if (color) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
}
|
||||
if (normal) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||
}
|
||||
if (specular) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||
}
|
||||
batch._glDrawBuffers(bufferCount, buffers);
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer TextureCache::getSecondaryFramebuffer() {
|
||||
if (!_secondaryFramebuffer) {
|
||||
_secondaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height()));
|
||||
}
|
||||
return _secondaryFramebuffer;
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer TextureCache::getTertiaryFramebuffer() {
|
||||
if (!_tertiaryFramebuffer) {
|
||||
_tertiaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height()));
|
||||
}
|
||||
return _tertiaryFramebuffer;
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer TextureCache::getShadowFramebuffer() {
|
||||
if (!_shadowFramebuffer) {
|
||||
const int SHADOW_MAP_SIZE = 2048;
|
||||
_shadowFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(SHADOW_MAP_SIZE));
|
||||
|
||||
_shadowTexture = _shadowFramebuffer->getDepthStencilBuffer();
|
||||
}
|
||||
return _shadowFramebuffer;
|
||||
}
|
||||
|
||||
/// Returns a texture version of an image file
|
||||
gpu::TexturePointer TextureCache::getImageTexture(const QString& path) {
|
||||
QImage image = QImage(path).mirrored(false, true);
|
||||
|
@ -453,19 +325,6 @@ void ImageReader::run() {
|
|||
auto ntex = dynamic_cast<NetworkTexture*>(&*texture);
|
||||
if (ntex && (ntex->getType() == CUBE_TEXTURE)) {
|
||||
qCDebug(renderutils) << "Cube map size:" << _url << image.width() << image.height();
|
||||
} else {
|
||||
|
||||
// enforce a fixed maximum area (1024 * 2048)
|
||||
const int MAXIMUM_AREA_SIZE = 2097152;
|
||||
if (imageArea > MAXIMUM_AREA_SIZE) {
|
||||
float scaleRatio = sqrtf((float)MAXIMUM_AREA_SIZE) / sqrtf((float)imageArea);
|
||||
int resizeWidth = static_cast<int>(std::floor(scaleRatio * static_cast<float>(image.width())));
|
||||
int resizeHeight = static_cast<int>(std::floor(scaleRatio * static_cast<float>(image.height())));
|
||||
qCDebug(renderutils) << "Image greater than maximum size:" << _url << image.width() << image.height() <<
|
||||
" scaled to:" << resizeWidth << resizeHeight;
|
||||
image = image.scaled(resizeWidth, resizeHeight, Qt::IgnoreAspectRatio);
|
||||
imageArea = image.width() * image.height();
|
||||
}
|
||||
}
|
||||
|
||||
int opaquePixels = 0;
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
#define hifi_TextureCache_h
|
||||
|
||||
#include <gpu/Texture.h>
|
||||
#include <gpu/Framebuffer.h>
|
||||
|
||||
#include <model/Light.h>
|
||||
|
||||
#include <QImage>
|
||||
|
@ -39,10 +37,6 @@ class TextureCache : public ResourceCache, public Dependency {
|
|||
SINGLETON_DEPENDENCY
|
||||
|
||||
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
|
||||
/// the second, a set of random unit vectors to be used as noise gradients.
|
||||
|
@ -67,33 +61,6 @@ public:
|
|||
NetworkTexturePointer getTexture(const QUrl& url, TextureType type = DEFAULT_TEXTURE, bool dilatable = false,
|
||||
const QByteArray& content = QByteArray());
|
||||
|
||||
/// Returns a pointer to the primary framebuffer object. This render target includes a depth component, and is
|
||||
/// used for scene rendering.
|
||||
gpu::FramebufferPointer getPrimaryFramebuffer();
|
||||
|
||||
gpu::TexturePointer getPrimaryDepthTexture();
|
||||
gpu::TexturePointer getPrimaryColorTexture();
|
||||
gpu::TexturePointer getPrimaryNormalTexture();
|
||||
gpu::TexturePointer getPrimarySpecularTexture();
|
||||
|
||||
/// Returns the ID of the primary framebuffer object's depth texture. This contains the Z buffer used in rendering.
|
||||
uint32_t getPrimaryDepthTextureID();
|
||||
|
||||
/// Enables or disables draw buffers on the primary framebuffer. Note: the primary framebuffer must be bound.
|
||||
void setPrimaryDrawBuffers(bool color, bool normal = false, bool specular = false);
|
||||
void setPrimaryDrawBuffers(gpu::Batch& batch, bool color, bool normal = false, bool specular = false);
|
||||
|
||||
/// Returns a pointer to the secondary framebuffer object, used as an additional render target when performing full
|
||||
/// screen effects.
|
||||
gpu::FramebufferPointer getSecondaryFramebuffer();
|
||||
|
||||
/// Returns a pointer to the tertiary framebuffer object, used as an additional render target when performing full
|
||||
/// screen effects.
|
||||
gpu::FramebufferPointer getTertiaryFramebuffer();
|
||||
|
||||
/// Returns the framebuffer object used to render shadow maps;
|
||||
gpu::FramebufferPointer getShadowFramebuffer();
|
||||
|
||||
protected:
|
||||
|
||||
virtual QSharedPointer<Resource> createResource(const QUrl& url,
|
||||
|
@ -110,23 +77,7 @@ private:
|
|||
gpu::TexturePointer _blueTexture;
|
||||
gpu::TexturePointer _blackTexture;
|
||||
|
||||
|
||||
QHash<QUrl, QWeakPointer<NetworkTexture> > _dilatableNetworkTextures;
|
||||
|
||||
gpu::TexturePointer _primaryDepthTexture;
|
||||
gpu::TexturePointer _primaryColorTexture;
|
||||
gpu::TexturePointer _primaryNormalTexture;
|
||||
gpu::TexturePointer _primarySpecularTexture;
|
||||
gpu::FramebufferPointer _primaryFramebuffer;
|
||||
void createPrimaryFramebuffer();
|
||||
|
||||
gpu::FramebufferPointer _secondaryFramebuffer;
|
||||
gpu::FramebufferPointer _tertiaryFramebuffer;
|
||||
|
||||
gpu::FramebufferPointer _shadowFramebuffer;
|
||||
gpu::TexturePointer _shadowTexture;
|
||||
|
||||
QSize _frameBufferSize;
|
||||
};
|
||||
|
||||
/// A simple object wrapper for an OpenGL texture.
|
||||
|
|
|
@ -22,6 +22,5 @@ void main(void) {
|
|||
normalize(interpolatedNormal.xyz),
|
||||
glowIntensity,
|
||||
gl_Color.rgb,
|
||||
gl_FrontMaterial.specular.rgb,
|
||||
gl_FrontMaterial.shininess);
|
||||
DEFAULT_SPECULAR, DEFAULT_SHININESS);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,5 @@ void main(void) {
|
|||
normalize(interpolatedNormal.xyz),
|
||||
glowIntensity * texel.a,
|
||||
gl_Color.rgb * texel.rgb,
|
||||
gl_FrontMaterial.specular.rgb,
|
||||
gl_FrontMaterial.shininess);
|
||||
DEFAULT_SPECULAR, DEFAULT_SHININESS);
|
||||
}
|
|
@ -27,7 +27,6 @@ void main(void) {
|
|||
normalize(interpolatedNormal.xyz),
|
||||
glowIntensity * texel.a,
|
||||
gl_Color.rgb,
|
||||
gl_FrontMaterial.specular.rgb,
|
||||
gl_FrontMaterial.shininess,
|
||||
DEFAULT_SPECULAR, DEFAULT_SHININESS,
|
||||
texel.rgb);
|
||||
}
|
|
@ -1,63 +1,17 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
#line __LINE__
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// stars.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Bradley Austin Davis on 2015/06/19
|
||||
// Created by Bradley Austin Davis on 6/10/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
|
||||
//
|
||||
|
||||
varying vec2 varTexcoord;
|
||||
varying vec3 varNomral;
|
||||
varying vec3 varPosition;
|
||||
|
||||
uniform float iGlobalTime;
|
||||
|
||||
const float PI = 3.14159;
|
||||
const float TAU = 3.14159 * 2.0;
|
||||
const int latitudeCount = 5;
|
||||
const float latitudeDist = PI / 2.0 / float(latitudeCount);
|
||||
const int meridianCount = 4;
|
||||
const float merdianDist = PI / float(meridianCount);
|
||||
|
||||
|
||||
float clampLine(float val, float target) {
|
||||
return clamp((1.0 - abs((val - target)) - 0.998) * 500.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float latitude(vec2 pos, float angle) {
|
||||
float result = clampLine(pos.y, angle);
|
||||
if (angle != 0.0) {
|
||||
result += clampLine(pos.y, -angle);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float meridian(vec2 pos, float angle) {
|
||||
return clampLine(pos.x, angle) + clampLine(pos.x + PI, angle);
|
||||
}
|
||||
|
||||
vec2 toPolar(in vec3 dir) {
|
||||
vec2 polar = vec2(atan(dir.z, dir.x), asin(dir.y));
|
||||
return polar;
|
||||
}
|
||||
|
||||
void mainVR( out vec4 fragColor, in vec2 fragCoord, in vec3 fragRayOri, in vec3 fragRayDir )
|
||||
{
|
||||
vec2 polar = toPolar(fragRayDir);
|
||||
//polar.x += mod(iGlobalTime / 12.0, PI / 4.0) - PI / 4.0;
|
||||
float c = 0.0;
|
||||
for (int i = 0; i < latitudeCount - 1; ++i) {
|
||||
c += latitude(polar, float(i) * latitudeDist);
|
||||
}
|
||||
for (int i = 0; i < meridianCount; ++i) {
|
||||
c += meridian(polar, float(i) * merdianDist);
|
||||
}
|
||||
const vec3 col_lines = vec3(102.0 / 255.0, 136.0 / 255.0, 221.0 / 255.0);
|
||||
fragColor = vec4(c * col_lines, 0.2);
|
||||
}
|
||||
varying vec4 varColor;
|
||||
|
||||
void main(void) {
|
||||
mainVR(gl_FragColor, gl_FragCoord.xy, vec3(0.0), normalize(varPosition));
|
||||
gl_FragColor = varColor; //vec4(varColor, 1.0);
|
||||
}
|
||||
|
||||
|
|
32
libraries/render-utils/src/stars.slv
Normal file
32
libraries/render-utils/src/stars.slv
Normal file
|
@ -0,0 +1,32 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// standardTransformPNTC.slv
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Sam Gateau on 6/10/2015.
|
||||
// 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 vec3 varPosition;
|
||||
varying vec4 varColor;
|
||||
|
||||
|
||||
void main(void) {
|
||||
varColor = gl_Color.rgba;
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$>
|
||||
varPosition = gl_Vertex.xyz;
|
||||
gl_PointSize = gl_Color.a;
|
||||
}
|
63
libraries/render-utils/src/starsGrid.slf
Normal file
63
libraries/render-utils/src/starsGrid.slf
Normal file
|
@ -0,0 +1,63 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
#line __LINE__
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// stars.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Bradley Austin Davis on 2015/06/19
|
||||
|
||||
varying vec2 varTexcoord;
|
||||
varying vec3 varNomral;
|
||||
varying vec3 varPosition;
|
||||
|
||||
uniform float iGlobalTime;
|
||||
|
||||
const float PI = 3.14159;
|
||||
const float TAU = 3.14159 * 2.0;
|
||||
const int latitudeCount = 5;
|
||||
const float latitudeDist = PI / 2.0 / float(latitudeCount);
|
||||
const int meridianCount = 4;
|
||||
const float merdianDist = PI / float(meridianCount);
|
||||
|
||||
|
||||
float clampLine(float val, float target) {
|
||||
return clamp((1.0 - abs((val - target)) - 0.998) * 500.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float latitude(vec2 pos, float angle) {
|
||||
float result = clampLine(pos.y, angle);
|
||||
if (angle != 0.0) {
|
||||
result += clampLine(pos.y, -angle);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float meridian(vec2 pos, float angle) {
|
||||
return clampLine(pos.x, angle) + clampLine(pos.x + PI, angle);
|
||||
}
|
||||
|
||||
vec2 toPolar(in vec3 dir) {
|
||||
vec2 polar = vec2(atan(dir.z, dir.x), asin(dir.y));
|
||||
return polar;
|
||||
}
|
||||
|
||||
void mainVR( out vec4 fragColor, in vec2 fragCoord, in vec3 fragRayOri, in vec3 fragRayDir )
|
||||
{
|
||||
vec2 polar = toPolar(fragRayDir);
|
||||
//polar.x += mod(iGlobalTime / 12.0, PI / 4.0) - PI / 4.0;
|
||||
float c = 0.0;
|
||||
for (int i = 0; i < latitudeCount - 1; ++i) {
|
||||
c += latitude(polar, float(i) * latitudeDist);
|
||||
}
|
||||
for (int i = 0; i < meridianCount; ++i) {
|
||||
c += meridian(polar, float(i) * merdianDist);
|
||||
}
|
||||
const vec3 col_lines = vec3(102.0 / 255.0, 136.0 / 255.0, 221.0 / 255.0);
|
||||
fragColor = vec4(c * col_lines, 0.2);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
mainVR(gl_FragColor, gl_FragCoord.xy, vec3(0.0), normalize(varPosition));
|
||||
}
|
||||
|
|
@ -46,13 +46,21 @@
|
|||
|
||||
|
||||
static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine){
|
||||
qCDebug(scriptengine) << "script:print()<<" << context->argument(0).toString();
|
||||
QString message = context->argument(0).toString()
|
||||
.replace("\\", "\\\\")
|
||||
.replace("\n", "\\n")
|
||||
.replace("\r", "\\r")
|
||||
.replace("'", "\\'");
|
||||
QString message = "";
|
||||
for (int i = 0; i < context->argumentCount(); i++) {
|
||||
if (i > 0) {
|
||||
message += " ";
|
||||
}
|
||||
message += context->argument(i).toString();
|
||||
}
|
||||
qCDebug(scriptengine) << "script:print()<<" << message;
|
||||
|
||||
message = message.replace("\\", "\\\\")
|
||||
.replace("\n", "\\n")
|
||||
.replace("\r", "\\r")
|
||||
.replace("'", "\\'");
|
||||
engine->evaluate("Script.print('" + message + "')");
|
||||
|
||||
return QScriptValue();
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ public:
|
|||
RENDER_DEBUG_SIMULATION_OWNERSHIP = 2,
|
||||
};
|
||||
|
||||
RenderArgs(gpu::Context* context = nullptr,
|
||||
RenderArgs(std::shared_ptr<gpu::Context> context = nullptr,
|
||||
OctreeRenderer* renderer = nullptr,
|
||||
ViewFrustum* viewFrustum = nullptr,
|
||||
float sizeScale = 1.0f,
|
||||
|
@ -102,7 +102,7 @@ public:
|
|||
_shouldRender(shouldRender) {
|
||||
}
|
||||
|
||||
gpu::Context* _context = nullptr;
|
||||
std::shared_ptr<gpu::Context> _context = nullptr;
|
||||
OctreeRenderer* _renderer = nullptr;
|
||||
ViewFrustum* _viewFrustum = nullptr;
|
||||
glm::ivec4 _viewport{ 0, 0, 1, 1 };
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include "OffscreenUi.h"
|
||||
#include <QOpenGLFramebufferObject>
|
||||
#include <QOpenGLDebugLogger>
|
||||
#include <QQuickWindow>
|
||||
#include <QGLWidget>
|
||||
|
|
|
@ -118,6 +118,13 @@ void vhacd::VHACDUtil::fattenMeshes(const FBXMesh& mesh, FBXMesh& result,
|
|||
glm::vec3 p2 = result.vertices[index2];
|
||||
glm::vec3 av = (p0 + p1 + p2) / 3.0f; // center of the triangular face
|
||||
|
||||
glm::vec3 normal = glm::normalize(glm::cross(p1 - p0, p2 - p0));
|
||||
float threshold = 1.0f / sqrtf(3.0f);
|
||||
if (normal.y > -threshold && normal.y < threshold) {
|
||||
// this triangle is more a wall than a floor, skip it.
|
||||
continue;
|
||||
}
|
||||
|
||||
float dropAmount = 0;
|
||||
dropAmount = glm::max(glm::length(p1 - p0), dropAmount);
|
||||
dropAmount = glm::max(glm::length(p2 - p1), dropAmount);
|
||||
|
|
Loading…
Reference in a new issue