Move circle3d and text overlays to batches

This commit is contained in:
Ryan Huffman 2015-06-19 09:45:13 -07:00
parent c9a7136d51
commit 690e2e38f2
5 changed files with 496 additions and 485 deletions

View file

@ -101,205 +101,207 @@ void Circle3DOverlay::render(RenderArgs* args) {
bool colorChanged = colorX.red != _lastColor.red || colorX.green != _lastColor.green || colorX.blue != _lastColor.blue; bool colorChanged = colorX.red != _lastColor.red || colorX.green != _lastColor.green || colorX.blue != _lastColor.blue;
_lastColor = colorX; _lastColor = colorX;
glDisable(GL_LIGHTING);
glm::vec3 position = getPosition(); glm::vec3 position = getPosition();
glm::vec3 center = getCenter(); glm::vec3 center = getCenter();
glm::vec2 dimensions = getDimensions(); glm::vec2 dimensions = getDimensions();
glm::quat rotation = getRotation(); glm::quat rotation = getRotation();
float glowLevel = getGlowLevel(); auto batch = args->_batch;
Glower* glower = NULL;
if (glowLevel > 0.0f) {
glower = new Glower(glowLevel);
}
glPushMatrix(); if (batch) {
glTranslatef(position.x, position.y, position.z); Transform transform;
glm::vec3 axis = glm::axis(rotation); transform.setTranslation(position);
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); transform.setRotation(rotation);
glPushMatrix(); transform.setScale(glm::vec3(dimensions.x, dimensions.y, 1.0f) / 2.0f);
glm::vec3 positionToCenter = center - position;
glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z);
glScalef(dimensions.x / 2.0f, dimensions.y / 2.0f, 1.0f);
glLineWidth(_lineWidth); batch->setModelTransform(transform);
auto geometryCache = DependencyManager::get<GeometryCache>(); batch->_glLineWidth(_lineWidth);
// for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise auto geometryCache = DependencyManager::get<GeometryCache>();
// we just draw a line...
if (getIsSolid()) {
if (_quadVerticesID == GeometryCache::UNKNOWN_ID) {
_quadVerticesID = geometryCache->allocateID();
}
if (geometryChanged || colorChanged) { // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
// we just draw a line...
if (getIsSolid()) {
if (_quadVerticesID == GeometryCache::UNKNOWN_ID) {
_quadVerticesID = geometryCache->allocateID();
}
QVector<glm::vec2> points; if (geometryChanged || colorChanged) {
float angle = startAt; QVector<glm::vec2> points;
float angleInRadians = glm::radians(angle);
glm::vec2 firstInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
glm::vec2 firstOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
points << firstInnerPoint << firstOuterPoint; float angle = startAt;
float angleInRadians = glm::radians(angle);
glm::vec2 firstInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius);
glm::vec2 firstOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
while (angle < endAt) { points << firstInnerPoint << firstOuterPoint;
angleInRadians = glm::radians(angle);
glm::vec2 thisInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
glm::vec2 thisOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
points << thisOuterPoint << thisInnerPoint; while (angle < endAt) {
angle += SLICE_ANGLE;
}
// get the last slice portion....
angle = endAt;
angleInRadians = glm::radians(angle); angleInRadians = glm::radians(angle);
glm::vec2 lastInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius); glm::vec2 thisInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius);
glm::vec2 lastOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); glm::vec2 thisOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
points << lastOuterPoint << lastInnerPoint; points << thisOuterPoint << thisInnerPoint;
geometryCache->updateVertices(_quadVerticesID, points, color); angle += SLICE_ANGLE;
} }
geometryCache->renderVertices(gpu::QUAD_STRIP, _quadVerticesID); // get the last slice portion....
angle = endAt;
angleInRadians = glm::radians(angle);
glm::vec2 lastInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius);
glm::vec2 lastOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
// Add quads for the back side
while (angle > startAt) {
angleInRadians = glm::radians(angle);
glm::vec2 thisInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius);
glm::vec2 thisOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
points << thisOuterPoint << thisInnerPoint;
angle -= SLICE_ANGLE;
}
// get the last slice portion....
angle = startAt;
angleInRadians = glm::radians(angle);
lastInnerPoint = glm::vec2(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius);
lastOuterPoint = glm::vec2(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
points << lastOuterPoint << lastInnerPoint;
geometryCache->updateVertices(_quadVerticesID, points, color);
}
geometryCache->renderVertices(*batch, gpu::QUAD_STRIP, _quadVerticesID);
} else {
if (_lineVerticesID == GeometryCache::UNKNOWN_ID) {
_lineVerticesID = geometryCache->allocateID();
}
if (geometryChanged || colorChanged) {
QVector<glm::vec2> points;
float angle = startAt;
float angleInRadians = glm::radians(angle);
glm::vec2 firstPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
points << firstPoint;
while (angle < endAt) {
angle += SLICE_ANGLE;
angleInRadians = glm::radians(angle);
glm::vec2 thisPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
points << thisPoint;
if (getIsDashedLine()) {
angle += SLICE_ANGLE / 2.0f; // short gap
angleInRadians = glm::radians(angle);
glm::vec2 dashStartPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
points << dashStartPoint;
}
}
// get the last slice portion....
angle = endAt;
angleInRadians = glm::radians(angle);
glm::vec2 lastPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
points << lastPoint;
geometryCache->updateVertices(_lineVerticesID, points, color);
}
if (getIsDashedLine()) {
geometryCache->renderVertices(*batch, gpu::LINES, _lineVerticesID);
} else { } else {
if (_lineVerticesID == GeometryCache::UNKNOWN_ID) { geometryCache->renderVertices(*batch, gpu::LINE_STRIP, _lineVerticesID);
_lineVerticesID = geometryCache->allocateID(); }
} }
if (geometryChanged || colorChanged) { // draw our tick marks
QVector<glm::vec2> points; // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
// we just draw a line...
if (getHasTickMarks()) {
float angle = startAt; if (_majorTicksVerticesID == GeometryCache::UNKNOWN_ID) {
_majorTicksVerticesID = geometryCache->allocateID();
}
if (_minorTicksVerticesID == GeometryCache::UNKNOWN_ID) {
_minorTicksVerticesID = geometryCache->allocateID();
}
if (geometryChanged) {
QVector<glm::vec2> majorPoints;
QVector<glm::vec2> minorPoints;
// draw our major tick marks
if (getMajorTickMarksAngle() > 0.0f && getMajorTickMarksLength() != 0.0f) {
float tickMarkAngle = getMajorTickMarksAngle();
float angle = startAt - fmod(startAt, tickMarkAngle) + tickMarkAngle;
float angleInRadians = glm::radians(angle); float angleInRadians = glm::radians(angle);
glm::vec2 firstPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); float tickMarkLength = getMajorTickMarksLength();
points << firstPoint; float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
float endRadius = startRadius + tickMarkLength;
while (angle < endAt) { while (angle <= endAt) {
angle += SLICE_ANGLE;
angleInRadians = glm::radians(angle); angleInRadians = glm::radians(angle);
glm::vec2 thisPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
points << thisPoint;
if (getIsDashedLine()) { glm::vec2 thisPointA(cos(angleInRadians) * startRadius, sin(angleInRadians) * startRadius);
angle += SLICE_ANGLE / 2.0f; // short gap glm::vec2 thisPointB(cos(angleInRadians) * endRadius, sin(angleInRadians) * endRadius);
angleInRadians = glm::radians(angle);
glm::vec2 dashStartPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); majorPoints << thisPointA << thisPointB;
points << dashStartPoint;
} angle += tickMarkAngle;
} }
// get the last slice portion....
angle = endAt;
angleInRadians = glm::radians(angle);
glm::vec2 lastPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
points << lastPoint;
geometryCache->updateVertices(_lineVerticesID, points, color);
} }
if (getIsDashedLine()) { // draw our minor tick marks
geometryCache->renderVertices(gpu::LINES, _lineVerticesID); if (getMinorTickMarksAngle() > 0.0f && getMinorTickMarksLength() != 0.0f) {
} else {
geometryCache->renderVertices(gpu::LINE_STRIP, _lineVerticesID); float tickMarkAngle = getMinorTickMarksAngle();
float angle = startAt - fmod(startAt, tickMarkAngle) + tickMarkAngle;
float angleInRadians = glm::radians(angle);
float tickMarkLength = getMinorTickMarksLength();
float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
float endRadius = startRadius + tickMarkLength;
while (angle <= endAt) {
angleInRadians = glm::radians(angle);
glm::vec2 thisPointA(cos(angleInRadians) * startRadius, sin(angleInRadians) * startRadius);
glm::vec2 thisPointB(cos(angleInRadians) * endRadius, sin(angleInRadians) * endRadius);
minorPoints << thisPointA << thisPointB;
angle += tickMarkAngle;
}
} }
xColor majorColorX = getMajorTickMarksColor();
glm::vec4 majorColor(majorColorX.red / MAX_COLOR, majorColorX.green / MAX_COLOR, majorColorX.blue / MAX_COLOR, alpha);
geometryCache->updateVertices(_majorTicksVerticesID, majorPoints, majorColor);
xColor minorColorX = getMinorTickMarksColor();
glm::vec4 minorColor(minorColorX.red / MAX_COLOR, minorColorX.green / MAX_COLOR, minorColorX.blue / MAX_COLOR, alpha);
geometryCache->updateVertices(_minorTicksVerticesID, minorPoints, minorColor);
} }
// draw our tick marks geometryCache->renderVertices(*batch, gpu::LINES, _majorTicksVerticesID);
// for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
// we just draw a line...
if (getHasTickMarks()) {
if (_majorTicksVerticesID == GeometryCache::UNKNOWN_ID) { geometryCache->renderVertices(*batch, gpu::LINES, _minorTicksVerticesID);
_majorTicksVerticesID = geometryCache->allocateID(); }
}
if (_minorTicksVerticesID == GeometryCache::UNKNOWN_ID) {
_minorTicksVerticesID = geometryCache->allocateID();
}
if (geometryChanged) { if (geometryChanged) {
QVector<glm::vec2> majorPoints; _lastStartAt = startAt;
QVector<glm::vec2> minorPoints; _lastEndAt = endAt;
_lastInnerRadius = innerRadius;
// draw our major tick marks _lastOuterRadius = outerRadius;
if (getMajorTickMarksAngle() > 0.0f && getMajorTickMarksLength() != 0.0f) { }
float tickMarkAngle = getMajorTickMarksAngle();
float angle = startAt - fmodf(startAt, tickMarkAngle) + tickMarkAngle;
float angleInRadians = glm::radians(angle);
float tickMarkLength = getMajorTickMarksLength();
float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
float endRadius = startRadius + tickMarkLength;
while (angle <= endAt) {
angleInRadians = glm::radians(angle);
glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius);
majorPoints << thisPointA << thisPointB;
angle += tickMarkAngle;
}
}
// draw our minor tick marks
if (getMinorTickMarksAngle() > 0.0f && getMinorTickMarksLength() != 0.0f) {
float tickMarkAngle = getMinorTickMarksAngle();
float angle = startAt - fmodf(startAt, tickMarkAngle) + tickMarkAngle;
float angleInRadians = glm::radians(angle);
float tickMarkLength = getMinorTickMarksLength();
float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
float endRadius = startRadius + tickMarkLength;
while (angle <= endAt) {
angleInRadians = glm::radians(angle);
glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius);
minorPoints << thisPointA << thisPointB;
angle += tickMarkAngle;
}
}
xColor majorColorX = getMajorTickMarksColor();
glm::vec4 majorColor(majorColorX.red / MAX_COLOR, majorColorX.green / MAX_COLOR, majorColorX.blue / MAX_COLOR, alpha);
geometryCache->updateVertices(_majorTicksVerticesID, majorPoints, majorColor);
xColor minorColorX = getMinorTickMarksColor();
glm::vec4 minorColor(minorColorX.red / MAX_COLOR, minorColorX.green / MAX_COLOR, minorColorX.blue / MAX_COLOR, alpha);
geometryCache->updateVertices(_minorTicksVerticesID, minorPoints, minorColor);
}
geometryCache->renderVertices(gpu::LINES, _majorTicksVerticesID);
geometryCache->renderVertices(gpu::LINES, _minorTicksVerticesID);
}
glPopMatrix();
glPopMatrix();
if (geometryChanged) {
_lastStartAt = startAt;
_lastEndAt = endAt;
_lastInnerRadius = innerRadius;
_lastOuterRadius = outerRadius;
}
if (glower) {
delete glower;
} }
} }

View file

@ -14,6 +14,8 @@
#include "Application.h" #include "Application.h"
#include "Text3DOverlay.h" #include "Text3DOverlay.h"
#include <RenderDeferredTask.h>
const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 }; const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
const float DEFAULT_BACKGROUND_ALPHA = 0.7f; const float DEFAULT_BACKGROUND_ALPHA = 0.7f;
const float DEFAULT_MARGIN = 0.1f; const float DEFAULT_MARGIN = 0.1f;
@ -52,7 +54,7 @@ Text3DOverlay::~Text3DOverlay() {
xColor Text3DOverlay::getBackgroundColor() { xColor Text3DOverlay::getBackgroundColor() {
if (_colorPulse == 0.0f) { if (_colorPulse == 0.0f) {
return _backgroundColor; return _backgroundColor;
} }
float pulseLevel = updatePulse(); float pulseLevel = updatePulse();
@ -75,19 +77,23 @@ void Text3DOverlay::render(RenderArgs* args) {
return; // do nothing if we're not visible return; // do nothing if we're not visible
} }
glPushMatrix(); { auto batch = args->_batch;
glTranslatef(_position.x, _position.y, _position.z);
if (batch) {
glm::quat rotation; glm::quat rotation;
if (_isFacingAvatar) { if (_isFacingAvatar) {
// rotate about vertical to face the camera // rotate about vertical to face the camera
rotation = Application::getInstance()->getCamera()->getRotation(); rotation = Application::getInstance()->getCamera()->getRotation();
} else { } else {
rotation = getRotation(); rotation = getRotation();
} }
glm::vec3 axis = glm::axis(rotation); Transform transform;
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); transform.setTranslation(_position);
transform.setRotation(rotation);
batch->setModelTransform(transform);
const float MAX_COLOR = 255.0f; const float MAX_COLOR = 255.0f;
xColor backgroundColor = getBackgroundColor(); xColor backgroundColor = getBackgroundColor();
@ -96,40 +102,42 @@ void Text3DOverlay::render(RenderArgs* args) {
glm::vec2 dimensions = getDimensions(); glm::vec2 dimensions = getDimensions();
glm::vec2 halfDimensions = dimensions * 0.5f; glm::vec2 halfDimensions = dimensions * 0.5f;
const float SLIGHTLY_BEHIND = -0.005f; const float SLIGHTLY_BEHIND = -0.005f;
glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND);
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, quadColor); DependencyManager::get<GeometryCache>()->renderQuad(*batch, topLeft, bottomRight, quadColor);
// Same font properties as textSize() // Same font properties as textSize()
float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO; float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO;
float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
glTranslatef(-(halfDimensions.x - _leftMargin), halfDimensions.y - _topMargin, 0.0f); float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
glm::vec2 clipMinimum(0.0f, 0.0f); glm::vec2 clipMinimum(0.0f, 0.0f);
glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor, glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor,
(dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor); (dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor);
glScalef(scaleFactor, -scaleFactor, scaleFactor); transform.setScale(glm::vec3(scaleFactor, -scaleFactor, scaleFactor));
enableClipPlane(GL_CLIP_PLANE0, -1.0f, 0.0f, 0.0f, clipMinimum.x + clipDimensions.x); transform.preTranslate(glm::vec3(-(halfDimensions.x - _leftMargin), halfDimensions.y - _topMargin, 0.0f));
enableClipPlane(GL_CLIP_PLANE1, 1.0f, 0.0f, 0.0f, -clipMinimum.x); batch->setModelTransform(transform);
enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipDimensions.y);
enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y); // enableClipPlane(GL_CLIP_PLANE0, -1.0f, 0.0f, 0.0f, clipMinimum.x + clipDimensions.x);
// enableClipPlane(GL_CLIP_PLANE1, 1.0f, 0.0f, 0.0f, -clipMinimum.x);
glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() }; // enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipDimensions.y);
_textRenderer->draw(0, 0, _text, textColor); // enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y);
glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() };
_textRenderer->draw(*batch, 0, 0, _text, textColor);
// glDisable(GL_CLIP_PLANE0);
// glDisable(GL_CLIP_PLANE1);
// glDisable(GL_CLIP_PLANE2);
// glDisable(GL_CLIP_PLANE3);
batch->setPipeline(DrawOverlay3D::getOpaquePipeline());
}
glDisable(GL_CLIP_PLANE0);
glDisable(GL_CLIP_PLANE1);
glDisable(GL_CLIP_PLANE2);
glDisable(GL_CLIP_PLANE3);
} glPopMatrix();
} }
void Text3DOverlay::enableClipPlane(GLenum plane, float x, float y, float z, float w) { void Text3DOverlay::enableClipPlane(GLenum plane, float x, float y, float z, float w) {

View file

@ -17,7 +17,7 @@
#include <QString> #include <QString>
#include <RenderArgs.h> #include <RenderArgs.h>
#include <TextRenderer.h> #include <TextRenderer3D.h>
#include "Planar3DOverlay.h" #include "Planar3DOverlay.h"
@ -62,7 +62,7 @@ public:
private: private:
void enableClipPlane(GLenum plane, float x, float y, float z, float w); void enableClipPlane(GLenum plane, float x, float y, float z, float w);
TextRenderer* _textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); TextRenderer3D* _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
QString _text; QString _text;
xColor _backgroundColor; xColor _backgroundColor;

View file

@ -1,244 +1,245 @@
// //
// RenderDeferredTask.cpp // RenderDeferredTask.cpp
// render-utils/src/ // render-utils/src/
// //
// Created by Sam Gateau on 5/29/15. // Created by Sam Gateau on 5/29/15.
// Copyright 20154 High Fidelity, Inc. // Copyright 20154 High Fidelity, Inc.
// //
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "RenderDeferredTask.h" #include "RenderDeferredTask.h"
#include "gpu/Batch.h" #include "gpu/Batch.h"
#include "gpu/Context.h" #include "gpu/Context.h"
#include "DeferredLightingEffect.h" #include "DeferredLightingEffect.h"
#include "ViewFrustum.h" #include "ViewFrustum.h"
#include "RenderArgs.h" #include "RenderArgs.h"
#include "TextureCache.h" #include "TextureCache.h"
#include <PerfStat.h> #include <PerfStat.h>
#include "overlay3D_vert.h" #include "overlay3D_vert.h"
#include "overlay3D_frag.h" #include "overlay3D_frag.h"
using namespace render; using namespace render;
template <> void render::jobRun(const PrepareDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { template <> void render::jobRun(const PrepareDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("PrepareDeferred"); PerformanceTimer perfTimer("PrepareDeferred");
DependencyManager::get<DeferredLightingEffect>()->prepare(); DependencyManager::get<DeferredLightingEffect>()->prepare();
} }
template <> void render::jobRun(const RenderDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { template <> void render::jobRun(const RenderDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("RenderDeferred"); PerformanceTimer perfTimer("RenderDeferred");
DependencyManager::get<DeferredLightingEffect>()->render(); DependencyManager::get<DeferredLightingEffect>()->render();
// renderContext->args->_context->syncCache(); // renderContext->args->_context->syncCache();
} }
template <> void render::jobRun(const ResolveDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { template <> void render::jobRun(const ResolveDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("ResolveDeferred"); PerformanceTimer perfTimer("ResolveDeferred");
DependencyManager::get<DeferredLightingEffect>()->copyBack(renderContext->args); DependencyManager::get<DeferredLightingEffect>()->copyBack(renderContext->args);
renderContext->args->_context->syncCache(); renderContext->args->_context->syncCache();
} }
RenderDeferredTask::RenderDeferredTask() : Task() { RenderDeferredTask::RenderDeferredTask() : Task() {
_jobs.push_back(Job(PrepareDeferred())); _jobs.push_back(Job(PrepareDeferred()));
_jobs.push_back(Job(DrawBackground())); _jobs.push_back(Job(DrawBackground()));
_jobs.push_back(Job(DrawOpaqueDeferred())); _jobs.push_back(Job(DrawOpaqueDeferred()));
_jobs.push_back(Job(DrawLight())); _jobs.push_back(Job(DrawLight()));
_jobs.push_back(Job(ResetGLState())); _jobs.push_back(Job(ResetGLState()));
_jobs.push_back(Job(RenderDeferred())); _jobs.push_back(Job(RenderDeferred()));
_jobs.push_back(Job(ResolveDeferred())); _jobs.push_back(Job(ResolveDeferred()));
_jobs.push_back(Job(DrawTransparentDeferred())); _jobs.push_back(Job(DrawTransparentDeferred()));
_jobs.push_back(Job(DrawOverlay3D())); _jobs.push_back(Job(DrawOverlay3D()));
_jobs.push_back(Job(ResetGLState())); _jobs.push_back(Job(ResetGLState()));
} }
RenderDeferredTask::~RenderDeferredTask() { RenderDeferredTask::~RenderDeferredTask() {
} }
void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
// sanity checks // sanity checks
assert(sceneContext); assert(sceneContext);
if (!sceneContext->_scene) { if (!sceneContext->_scene) {
return; return;
} }
// Is it possible that we render without a viewFrustum ? // Is it possible that we render without a viewFrustum ?
if (!(renderContext->args && renderContext->args->_viewFrustum)) { if (!(renderContext->args && renderContext->args->_viewFrustum)) {
return; return;
} }
renderContext->args->_context->syncCache(); renderContext->args->_context->syncCache();
for (auto job : _jobs) { for (auto job : _jobs) {
job.run(sceneContext, renderContext); job.run(sceneContext, renderContext);
} }
}; };
template <> void render::jobRun(const DrawOpaqueDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { template <> void render::jobRun(const DrawOpaqueDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("DrawOpaqueDeferred"); PerformanceTimer perfTimer("DrawOpaqueDeferred");
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
// render opaques // render opaques
auto& scene = sceneContext->_scene; auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withoutLayered()); auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withoutLayered());
auto& renderDetails = renderContext->args->_details; auto& renderDetails = renderContext->args->_details;
ItemIDsBounds inItems; ItemIDsBounds inItems;
inItems.reserve(items.size()); inItems.reserve(items.size());
for (auto id : items) { for (auto id : items) {
inItems.emplace_back(ItemIDAndBounds(id)); inItems.emplace_back(ItemIDAndBounds(id));
} }
ItemIDsBounds& renderedItems = inItems; ItemIDsBounds& renderedItems = inItems;
renderContext->_numFeedOpaqueItems = renderedItems.size(); renderContext->_numFeedOpaqueItems = renderedItems.size();
ItemIDsBounds culledItems; ItemIDsBounds culledItems;
culledItems.reserve(inItems.size()); culledItems.reserve(inItems.size());
if (renderContext->_cullOpaque) { if (renderContext->_cullOpaque) {
renderDetails.pointTo(RenderDetails::OPAQUE_ITEM); renderDetails.pointTo(RenderDetails::OPAQUE_ITEM);
cullItems(sceneContext, renderContext, renderedItems, culledItems); cullItems(sceneContext, renderContext, renderedItems, culledItems);
renderDetails.pointTo(RenderDetails::OTHER_ITEM); renderDetails.pointTo(RenderDetails::OTHER_ITEM);
renderedItems = culledItems; renderedItems = culledItems;
} }
renderContext->_numDrawnOpaqueItems = renderedItems.size(); renderContext->_numDrawnOpaqueItems = renderedItems.size();
ItemIDsBounds sortedItems; ItemIDsBounds sortedItems;
sortedItems.reserve(culledItems.size()); sortedItems.reserve(culledItems.size());
if (renderContext->_sortOpaque) { if (renderContext->_sortOpaque) {
depthSortItems(sceneContext, renderContext, true, renderedItems, sortedItems); // Sort Front to back opaque items! depthSortItems(sceneContext, renderContext, true, renderedItems, sortedItems); // Sort Front to back opaque items!
renderedItems = sortedItems; renderedItems = sortedItems;
} }
// ItemIDsBounds sortedItems; // ItemIDsBounds sortedItems;
/* ItemMaterialBucketMap stateSortedItems; /* ItemMaterialBucketMap stateSortedItems;
stateSortedItems.allocateStandardMaterialBuckets(); stateSortedItems.allocateStandardMaterialBuckets();
if (true) { if (true) {
for (auto& itemIDAndBound : renderedItems) { for (auto& itemIDAndBound : renderedItems) {
stateSortedItems.insert(itemIDAndBound.id, scene->getItem(itemIDAndBound.id).getMaterialKey()); stateSortedItems.insert(itemIDAndBound.id, scene->getItem(itemIDAndBound.id).getMaterialKey());
} }
} }
*/ */
if (renderContext->_renderOpaque) { if (renderContext->_renderOpaque) {
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
gpu::Batch batch; gpu::Batch batch;
args->_batch = &batch; args->_batch = &batch;
glm::mat4 projMat; glm::mat4 projMat;
Transform viewMat; Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat); args->_viewFrustum->evalViewTransform(viewMat);
if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f));
} }
batch.setProjectionTransform(projMat); batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat); batch.setViewTransform(viewMat);
{ {
GLenum buffers[3]; GLenum buffers[3];
int bufferCount = 0; int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
batch._glDrawBuffers(bufferCount, buffers); batch._glDrawBuffers(bufferCount, buffers);
} }
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnOpaqueItems); renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnOpaqueItems);
args->_context->render((*args->_batch)); args->_context->render((*args->_batch));
args->_batch = nullptr; args->_batch = nullptr;
} }
} }
template <> void render::jobRun(const DrawTransparentDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { template <> void render::jobRun(const DrawTransparentDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("DrawTransparentDeferred"); PerformanceTimer perfTimer("DrawTransparentDeferred");
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
// render transparents // render transparents
auto& scene = sceneContext->_scene; auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape().withoutLayered()); auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape().withoutLayered());
auto& renderDetails = renderContext->args->_details; auto& renderDetails = renderContext->args->_details;
ItemIDsBounds inItems; ItemIDsBounds inItems;
inItems.reserve(items.size()); inItems.reserve(items.size());
for (auto id : items) { for (auto id : items) {
inItems.push_back(id); inItems.push_back(id);
} }
ItemIDsBounds& renderedItems = inItems; ItemIDsBounds& renderedItems = inItems;
renderContext->_numFeedTransparentItems = renderedItems.size(); renderContext->_numFeedTransparentItems = renderedItems.size();
ItemIDsBounds culledItems; ItemIDsBounds culledItems;
if (renderContext->_cullTransparent) { if (renderContext->_cullTransparent) {
renderDetails.pointTo(RenderDetails::TRANSLUCENT_ITEM); renderDetails.pointTo(RenderDetails::TRANSLUCENT_ITEM);
cullItems(sceneContext, renderContext, inItems, culledItems); cullItems(sceneContext, renderContext, inItems, culledItems);
renderDetails.pointTo(RenderDetails::OTHER_ITEM); renderDetails.pointTo(RenderDetails::OTHER_ITEM);
renderedItems = culledItems; renderedItems = culledItems;
} }
renderContext->_numDrawnTransparentItems = renderedItems.size(); renderContext->_numDrawnTransparentItems = renderedItems.size();
ItemIDsBounds sortedItems; ItemIDsBounds sortedItems;
if (renderContext->_sortTransparent) { if (renderContext->_sortTransparent) {
depthSortItems(sceneContext, renderContext, false, renderedItems, sortedItems); // Sort Back to front transparent items! depthSortItems(sceneContext, renderContext, false, renderedItems, sortedItems); // Sort Back to front transparent items!
renderedItems = sortedItems; renderedItems = sortedItems;
} }
if (renderContext->_renderTransparent) { if (renderContext->_renderTransparent) {
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
gpu::Batch batch; gpu::Batch batch;
args->_batch = &batch; args->_batch = &batch;
glm::mat4 projMat; glm::mat4 projMat;
Transform viewMat; Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat); args->_viewFrustum->evalViewTransform(viewMat);
if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f));
} }
batch.setProjectionTransform(projMat); batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat); batch.setViewTransform(viewMat);
const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f; const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f;
{ {
GLenum buffers[3]; GLenum buffers[3];
int bufferCount = 0; int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
batch._glDrawBuffers(bufferCount, buffers); batch._glDrawBuffers(bufferCount, buffers);
args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD; args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD;
} }
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnTransparentItems); renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnTransparentItems);
// Before rendering the batch make sure we re in sync with gl state // Before rendering the batch make sure we re in sync with gl state
args->_context->syncCache(); args->_context->syncCache();
args->_context->render((*args->_batch)); args->_context->render((*args->_batch));
args->_batch = nullptr; args->_batch = nullptr;
// reset blend function to standard... // reset blend function to standard...
// glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); // glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
} }
} }
const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() const { gpu::PipelinePointer DrawOverlay3D::_opaquePipeline;
const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() {
if (!_opaquePipeline) { if (!_opaquePipeline) {
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(overlay3D_vert))); auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(overlay3D_vert)));
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(overlay3D_frag))); auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(overlay3D_frag)));
@ -251,53 +252,53 @@ const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() const {
_opaquePipeline.reset(gpu::Pipeline::create(program, state)); _opaquePipeline.reset(gpu::Pipeline::create(program, state));
} }
return _opaquePipeline; return _opaquePipeline;
} }
template <> void render::jobRun(const DrawOverlay3D& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { template <> void render::jobRun(const DrawOverlay3D& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("DrawOverlay3D"); PerformanceTimer perfTimer("DrawOverlay3D");
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
// render backgrounds // render backgrounds
auto& scene = sceneContext->_scene; auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withLayered()); auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withLayered());
ItemIDsBounds inItems; ItemIDsBounds inItems;
inItems.reserve(items.size()); inItems.reserve(items.size());
for (auto id : items) { for (auto id : items) {
auto& item = scene->getItem(id); auto& item = scene->getItem(id);
if (item.getKey().isVisible() && (item.getLayer() == 1)) { if (item.getKey().isVisible() && (item.getLayer() == 1)) {
inItems.emplace_back(id); inItems.emplace_back(id);
} }
} }
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
gpu::Batch batch; gpu::Batch batch;
args->_batch = &batch; args->_batch = &batch;
args->_whiteTexture = DependencyManager::get<TextureCache>()->getWhiteTexture(); args->_whiteTexture = DependencyManager::get<TextureCache>()->getWhiteTexture();
glm::mat4 projMat; glm::mat4 projMat;
Transform viewMat; Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat); args->_viewFrustum->evalViewTransform(viewMat);
if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f));
} }
batch.setProjectionTransform(projMat); batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat); batch.setViewTransform(viewMat);
batch.setPipeline(job.getOpaquePipeline()); batch.setPipeline(job.getOpaquePipeline());
batch.setUniformTexture(0, args->_whiteTexture); batch.setUniformTexture(0, args->_whiteTexture);
if (!inItems.empty()) { 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);
renderItems(sceneContext, renderContext, inItems); renderItems(sceneContext, renderContext, inItems);
} }
// Before rendering the batch make sure we re in sync with gl state // Before rendering the batch make sure we re in sync with gl state
args->_context->syncCache(); args->_context->syncCache();
args->_context->render((*args->_batch)); args->_context->render((*args->_batch));
args->_batch = nullptr; args->_batch = nullptr;
args->_whiteTexture.reset(); args->_whiteTexture.reset();
} }

View file

@ -53,9 +53,9 @@ template <> void jobRun(const DrawTransparentDeferred& job, const SceneContextPo
} }
class DrawOverlay3D { class DrawOverlay3D {
mutable gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable
public: public:
const gpu::PipelinePointer& getOpaquePipeline() const; static const gpu::PipelinePointer& getOpaquePipeline();
}; };
namespace render { namespace render {
template <> void jobRun(const DrawOverlay3D& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); template <> void jobRun(const DrawOverlay3D& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);