From 8ca3630cfa37a8387fdad65365338675b64c0548 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 6 Jul 2016 12:37:36 -0700 Subject: [PATCH] Support glow effect in 3D line overlays --- interface/src/ui/overlays/Line3DOverlay.cpp | 21 +- interface/src/ui/overlays/Line3DOverlay.h | 6 + libraries/render-utils/src/GeometryCache.cpp | 573 +++++++++++-------- libraries/render-utils/src/GeometryCache.h | 4 + libraries/render-utils/src/glowLine.slf | 32 ++ libraries/render-utils/src/glowLine.slg | 127 ++++ libraries/render-utils/src/glowLine.slv | 26 + 7 files changed, 545 insertions(+), 244 deletions(-) create mode 100644 libraries/render-utils/src/glowLine.slf create mode 100644 libraries/render-utils/src/glowLine.slg create mode 100644 libraries/render-utils/src/glowLine.slv diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index d53b287f76..c9a8b19f6a 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -55,12 +55,14 @@ void Line3DOverlay::render(RenderArgs* args) { batch->setModelTransform(_transform); auto geometryCache = DependencyManager::get(); - geometryCache->bindSimpleProgram(*batch, false, false, true, true); if (getIsDashedLine()) { // TODO: add support for color to renderDashedLine() + geometryCache->bindSimpleProgram(*batch, false, false, true, true); geometryCache->renderDashedLine(*batch, _start, _end, colorv4, _geometryCacheID); + } else if (_glow > 0.0f) { + geometryCache->renderGlowLine(*batch, _start, _end, colorv4, _glow, _glowWidth, _geometryCacheID); } else { - + geometryCache->bindSimpleProgram(*batch, false, false, true, true); geometryCache->renderLine(*batch, _start, _end, colorv4, _geometryCacheID); } } @@ -68,7 +70,7 @@ void Line3DOverlay::render(RenderArgs* args) { const render::ShapeKey Line3DOverlay::getShapeKey() { auto builder = render::ShapeKey::Builder().withOwnPipeline(); - if (getAlpha() != 1.0f) { + if (getAlpha() != 1.0f || _glow > 0.0f) { builder.withTranslucent(); } return builder.build(); @@ -94,6 +96,19 @@ void Line3DOverlay::setProperties(const QVariantMap& properties) { if (end.isValid()) { setEnd(vec3FromVariant(end)); } + + auto glow = properties["glow"]; + if (glow.isValid()) { + setGlow(glow.toFloat()); + if (_glow > 0.0f) { + _alpha = 0.5f; + } + } + + auto glowWidth = properties["glow"]; + if (glowWidth.isValid()) { + setGlow(glowWidth.toFloat()); + } } QVariant Line3DOverlay::getProperty(const QString& property) { diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h index db50d11276..d066677c70 100644 --- a/interface/src/ui/overlays/Line3DOverlay.h +++ b/interface/src/ui/overlays/Line3DOverlay.h @@ -30,10 +30,14 @@ public: // getters const glm::vec3& getStart() const { return _start; } const glm::vec3& getEnd() const { return _end; } + const float& getGlow() const { return _glow; } + const float& getGlowWidth() const { return _glowWidth; } // setters void setStart(const glm::vec3& start) { _start = start; } void setEnd(const glm::vec3& end) { _end = end; } + void setGlow(const float& glow) { _glow = glow; } + void setGlowWidth(const float& glowWidth) { _glowWidth = glowWidth; } void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; @@ -43,6 +47,8 @@ public: protected: glm::vec3 _start; glm::vec3 _end; + float _glow { 0.0 }; + float _glowWidth { 0.0 }; int _geometryCacheID; }; diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 9ea4bd9905..e692a663c9 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -33,6 +34,9 @@ #include "simple_vert.h" #include "simple_textured_frag.h" #include "simple_textured_unlit_frag.h" +#include "glowLine_vert.h" +#include "glowLine_geom.h" +#include "glowLine_frag.h" #include "grid_frag.h" @@ -43,9 +47,9 @@ const int GeometryCache::UNKNOWN_ID = -1; static const int VERTICES_PER_TRIANGLE = 3; -static const gpu::Element POSITION_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ }; -static const gpu::Element NORMAL_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ }; -static const gpu::Element COLOR_ELEMENT{ gpu::VEC4, gpu::NUINT8, gpu::RGBA }; +static const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ }; +static const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ }; +static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA }; static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT; static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT; @@ -190,7 +194,7 @@ void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) { - using namespace geometry; + using namespace geometry; Index baseVertex = (Index)(vertexBuffer->getSize() / SHAPE_VERTEX_STRIDE); VertexVector vertices; @@ -254,7 +258,7 @@ void GeometryCache::buildShapes() { setupFlatShape(_shapes[Octahedron], geometry::octahedron(), _shapeVertices, _shapeIndices); // Dodecahedron setupFlatShape(_shapes[Dodecahedron], geometry::dodecahedron(), _shapeVertices, _shapeIndices); - + // Sphere // FIXME this uses way more vertices than required. Should find a way to calculate the indices // using shared vertices for better vertex caching @@ -266,7 +270,7 @@ void GeometryCache::buildShapes() { { Index baseVertex = (Index)(_shapeVertices->getSize() / SHAPE_VERTEX_STRIDE); ShapeData& shapeData = _shapes[Line]; - shapeData.setupVertices(_shapeVertices, VertexVector{ + shapeData.setupVertices(_shapeVertices, VertexVector { vec3(-0.5, 0, 0), vec3(-0.5f, 0, 0), vec3(0.5f, 0, 0), vec3(0.5f, 0, 0) }); @@ -312,32 +316,31 @@ render::ShapePipelinePointer GeometryCache::_simplePipeline; render::ShapePipelinePointer GeometryCache::_simpleWirePipeline; GeometryCache::GeometryCache() : - _nextID(0) -{ +_nextID(0) { buildShapes(); GeometryCache::_simplePipeline = std::make_shared(getSimplePipeline(), nullptr, - [](const render::ShapePipeline&, gpu::Batch& batch) { - // Set the defaults needed for a simple program - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, - DependencyManager::get()->getWhiteTexture()); - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); - } - ); + [](const render::ShapePipeline&, gpu::Batch& batch) { + // Set the defaults needed for a simple program + batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, + DependencyManager::get()->getWhiteTexture()); + batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, + DependencyManager::get()->getNormalFittingTexture()); + } + ); GeometryCache::_simpleWirePipeline = std::make_shared(getSimplePipeline(false, false, true, true), nullptr, - [](const render::ShapePipeline&, gpu::Batch& batch) { } - ); + [](const render::ShapePipeline&, gpu::Batch& batch) {} + ); } GeometryCache::~GeometryCache() { - #ifdef WANT_DEBUG - qCDebug(renderutils) << "GeometryCache::~GeometryCache()... "; - qCDebug(renderutils) << " _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size(); - qCDebug(renderutils) << " _line3DVBOs.size():" << _line3DVBOs.size(); - qCDebug(renderutils) << " BatchItemDetails... population:" << GeometryCache::BatchItemDetails::population; - #endif //def WANT_DEBUG +#ifdef WANT_DEBUG + qCDebug(renderutils) << "GeometryCache::~GeometryCache()... "; + qCDebug(renderutils) << " _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size(); + qCDebug(renderutils) << " _line3DVBOs.size():" << _line3DVBOs.size(); + qCDebug(renderutils) << " BatchItemDetails... population:" << GeometryCache::BatchItemDetails::population; +#endif //def WANT_DEBUG } void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) { @@ -384,9 +387,9 @@ void GeometryCache::renderWireSphere(gpu::Batch& batch) { } void GeometryCache::renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, - int majorRows, int majorCols, float majorEdge, - int minorRows, int minorCols, float minorEdge, - const glm::vec4& color, bool isLayered, int id) { + int majorRows, int majorCols, float majorEdge, + int minorRows, int minorCols, float minorEdge, + const glm::vec4& color, bool isLayered, int id) { static const glm::vec2 MIN_TEX_COORD(0.0f, 0.0f); static const glm::vec2 MAX_TEX_COORD(1.0f, 1.0f); @@ -433,9 +436,9 @@ void GeometryCache::updateVertices(int id, const QVector& points, con if (details.isCreated) { details.clear(); - #ifdef WANT_DEBUG - qCDebug(renderutils) << "updateVertices()... RELEASING REGISTERED"; - #endif // def WANT_DEBUG +#ifdef WANT_DEBUG + qCDebug(renderutils) << "updateVertices()... RELEASING REGISTERED"; +#endif // def WANT_DEBUG } const int FLOATS_PER_VERTEX = 2 + 3; // vertices + normals @@ -444,7 +447,7 @@ void GeometryCache::updateVertices(int id, const QVector& points, con details.isCreated = true; details.vertices = points.size(); details.vertexSize = FLOATS_PER_VERTEX; - + auto verticesBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); @@ -466,9 +469,9 @@ void GeometryCache::updateVertices(int id, const QVector& points, con details.vertexSize = FLOATS_PER_VERTEX; int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); + ((int(color.y * 255.0f) & 0xFF) << 8) | + ((int(color.z * 255.0f) & 0xFF) << 16) | + ((int(color.w * 255.0f) & 0xFF) << 24); float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX]; float* vertex = vertexData; @@ -477,13 +480,13 @@ void GeometryCache::updateVertices(int id, const QVector& points, con int* colorDataAt = colorData; const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); - foreach (const glm::vec2& point, points) { + foreach(const glm::vec2& point, points) { *(vertex++) = point.x; *(vertex++) = point.y; *(vertex++) = NORMAL.x; *(vertex++) = NORMAL.y; *(vertex++) = NORMAL.z; - + *(colorDataAt++) = compactColor; } @@ -492,18 +495,18 @@ void GeometryCache::updateVertices(int id, const QVector& points, con delete[] vertexData; delete[] colorData; - #ifdef WANT_DEBUG - qCDebug(renderutils) << "new registered linestrip buffer made -- _registeredVertices.size():" << _registeredVertices.size(); - #endif +#ifdef WANT_DEBUG + qCDebug(renderutils) << "new registered linestrip buffer made -- _registeredVertices.size():" << _registeredVertices.size(); +#endif } void GeometryCache::updateVertices(int id, const QVector& points, const glm::vec4& color) { BatchItemDetails& details = _registeredVertices[id]; if (details.isCreated) { details.clear(); - #ifdef WANT_DEBUG - qCDebug(renderutils) << "updateVertices()... RELEASING REGISTERED"; - #endif // def WANT_DEBUG +#ifdef WANT_DEBUG + qCDebug(renderutils) << "updateVertices()... RELEASING REGISTERED"; +#endif // def WANT_DEBUG } const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals @@ -512,7 +515,7 @@ void GeometryCache::updateVertices(int id, const QVector& points, con details.isCreated = true; details.vertices = points.size(); details.vertexSize = FLOATS_PER_VERTEX; - + auto verticesBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); @@ -534,9 +537,9 @@ void GeometryCache::updateVertices(int id, const QVector& points, con details.vertexSize = FLOATS_PER_VERTEX; int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); + ((int(color.y * 255.0f) & 0xFF) << 8) | + ((int(color.z * 255.0f) & 0xFF) << 16) | + ((int(color.w * 255.0f) & 0xFF) << 24); float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX]; float* vertex = vertexData; @@ -545,14 +548,14 @@ void GeometryCache::updateVertices(int id, const QVector& points, con int* colorDataAt = colorData; const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); - foreach (const glm::vec3& point, points) { + foreach(const glm::vec3& point, points) { *(vertex++) = point.x; *(vertex++) = point.y; *(vertex++) = point.z; *(vertex++) = NORMAL.x; *(vertex++) = NORMAL.y; *(vertex++) = NORMAL.z; - + *(colorDataAt++) = compactColor; } @@ -561,9 +564,9 @@ void GeometryCache::updateVertices(int id, const QVector& points, con delete[] vertexData; delete[] colorData; - #ifdef WANT_DEBUG - qCDebug(renderutils) << "new registered linestrip buffer made -- _registeredVertices.size():" << _registeredVertices.size(); - #endif +#ifdef WANT_DEBUG + qCDebug(renderutils) << "new registered linestrip buffer made -- _registeredVertices.size():" << _registeredVertices.size(); +#endif } void GeometryCache::updateVertices(int id, const QVector& points, const QVector& texCoords, const glm::vec4& color) { @@ -571,9 +574,9 @@ void GeometryCache::updateVertices(int id, const QVector& points, con if (details.isCreated) { details.clear(); - #ifdef WANT_DEBUG - qCDebug(renderutils) << "updateVertices()... RELEASING REGISTERED"; - #endif // def WANT_DEBUG +#ifdef WANT_DEBUG + qCDebug(renderutils) << "updateVertices()... RELEASING REGISTERED"; +#endif // def WANT_DEBUG } const int FLOATS_PER_VERTEX = 3 + 3 + 2; // vertices + normals + tex coords @@ -584,7 +587,7 @@ void GeometryCache::updateVertices(int id, const QVector& points, con details.isCreated = true; details.vertices = points.size(); details.vertexSize = FLOATS_PER_VERTEX; - + auto verticesBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); @@ -609,9 +612,9 @@ void GeometryCache::updateVertices(int id, const QVector& points, con details.vertexSize = FLOATS_PER_VERTEX; int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); + ((int(color.y * 255.0f) & 0xFF) << 8) | + ((int(color.z * 255.0f) & 0xFF) << 16) | + ((int(color.w * 255.0f) & 0xFF) << 24); float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX]; float* vertex = vertexData; @@ -640,9 +643,9 @@ void GeometryCache::updateVertices(int id, const QVector& points, con delete[] vertexData; delete[] colorData; - #ifdef WANT_DEBUG - qCDebug(renderutils) << "new registered linestrip buffer made -- _registeredVertices.size():" << _registeredVertices.size(); - #endif +#ifdef WANT_DEBUG + qCDebug(renderutils) << "new registered linestrip buffer made -- _registeredVertices.size():" << _registeredVertices.size(); +#endif } void GeometryCache::renderVertices(gpu::Batch& batch, gpu::Primitive primitiveType, int id) { @@ -664,27 +667,27 @@ void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int Vec3Pair& lastKey = _lastRegisteredBevelRects[id]; if (lastKey != key) { details.clear(); - _lastRegisteredBevelRects[id] = key; - #ifdef WANT_DEBUG - qCDebug(renderutils) << "renderBevelCornersRect()... RELEASING REGISTERED"; - #endif // def WANT_DEBUG + _lastRegisteredBevelRects[id] = key; +#ifdef WANT_DEBUG + qCDebug(renderutils) << "renderBevelCornersRect()... RELEASING REGISTERED"; +#endif // def WANT_DEBUG } - #ifdef WANT_DEBUG +#ifdef WANT_DEBUG else { qCDebug(renderutils) << "renderBevelCornersRect()... REUSING PREVIOUSLY REGISTERED"; } - #endif // def WANT_DEBUG +#endif // def WANT_DEBUG } if (!details.isCreated) { static const int FLOATS_PER_VERTEX = 2; // vertices static const int NUM_VERTICES = 8; static const int NUM_FLOATS = NUM_VERTICES * FLOATS_PER_VERTEX; - + details.isCreated = true; details.vertices = NUM_VERTICES; details.vertexSize = FLOATS_PER_VERTEX; - + auto verticesBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); @@ -694,7 +697,7 @@ void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int details.colorBuffer = colorBuffer; details.streamFormat = streamFormat; details.stream = stream; - + details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); @@ -713,7 +716,7 @@ void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int // 2 8 // // \ / // // 4 ------ 6 // - + // 1 vertexBuffer[vertexPoint++] = x; vertexBuffer[vertexPoint++] = y + height - bevelDistance; @@ -738,13 +741,13 @@ void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int // 8 vertexBuffer[vertexPoint++] = x + width; vertexBuffer[vertexPoint++] = y + bevelDistance; - + int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); + ((int(color.y * 255.0f) & 0xFF) << 8) | + ((int(color.z * 255.0f) & 0xFF) << 16) | + ((int(color.w * 255.0f) & 0xFF) << 24); int colors[NUM_VERTICES] = { compactColor, compactColor, compactColor, compactColor, - compactColor, compactColor, compactColor, compactColor }; + compactColor, compactColor, compactColor, compactColor }; details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); @@ -766,16 +769,16 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co Vec4Pair & lastKey = _lastRegisteredQuad2D[id]; if (lastKey != key) { details.clear(); - _lastRegisteredQuad2D[id] = key; - #ifdef WANT_DEBUG - qCDebug(renderutils) << "renderQuad() 2D ... RELEASING REGISTERED"; - #endif // def WANT_DEBUG + _lastRegisteredQuad2D[id] = key; +#ifdef WANT_DEBUG + qCDebug(renderutils) << "renderQuad() 2D ... RELEASING REGISTERED"; +#endif // def WANT_DEBUG } - #ifdef WANT_DEBUG +#ifdef WANT_DEBUG else { qCDebug(renderutils) << "renderQuad() 2D ... REUSING PREVIOUSLY REGISTERED"; } - #endif // def WANT_DEBUG +#endif // def WANT_DEBUG } const int FLOATS_PER_VERTEX = 2 + 3; // vertices + normals @@ -788,7 +791,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co details.isCreated = true; details.vertices = VERTICES; details.vertexSize = FLOATS_PER_VERTEX; - + auto verticesBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); @@ -798,7 +801,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co details.colorBuffer = colorBuffer; details.streamFormat = streamFormat; details.stream = stream; - + details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); @@ -808,7 +811,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); - float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { + float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { minCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, maxCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, minCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, @@ -817,9 +820,9 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co const int NUM_COLOR_SCALARS_PER_QUAD = 4; int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); + ((int(color.y * 255.0f) & 0xFF) << 8) | + ((int(color.z * 255.0f) & 0xFF) << 16) | + ((int(color.w * 255.0f) & 0xFF) << 24); int colors[NUM_COLOR_SCALARS_PER_QUAD] = { compactColor, compactColor, compactColor, compactColor }; details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); @@ -841,13 +844,13 @@ void GeometryCache::renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, in 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) { + const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner, + const glm::vec4& color, int id) { bool registered = (id != UNKNOWN_ID); Vec4PairVec4 key(Vec4Pair(glm::vec4(minCorner.x, minCorner.y, maxCorner.x, maxCorner.y), - glm::vec4(texCoordMinCorner.x, texCoordMinCorner.y, texCoordMaxCorner.x, texCoordMaxCorner.y)), - color); + glm::vec4(texCoordMinCorner.x, texCoordMinCorner.y, texCoordMaxCorner.x, texCoordMaxCorner.y)), + color); BatchItemDetails& details = registered ? _registeredQuad2DTextures[id] : _quad2DTextures[key]; // if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed @@ -855,16 +858,16 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co Vec4PairVec4& lastKey = _lastRegisteredQuad2DTexture[id]; if (lastKey != key) { details.clear(); - _lastRegisteredQuad2DTexture[id] = key; - #ifdef WANT_DEBUG - qCDebug(renderutils) << "renderQuad() 2D+texture ... RELEASING REGISTERED"; - #endif // def WANT_DEBUG + _lastRegisteredQuad2DTexture[id] = key; +#ifdef WANT_DEBUG + qCDebug(renderutils) << "renderQuad() 2D+texture ... RELEASING REGISTERED"; +#endif // def WANT_DEBUG } - #ifdef WANT_DEBUG +#ifdef WANT_DEBUG else { qCDebug(renderutils) << "renderQuad() 2D+texture ... REUSING PREVIOUSLY REGISTERED"; } - #endif // def WANT_DEBUG +#endif // def WANT_DEBUG } const int FLOATS_PER_VERTEX = 2 + 3 + 2; // vertices + normals + tex coords @@ -879,7 +882,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co details.isCreated = true; details.vertices = VERTICES; details.vertexSize = FLOATS_PER_VERTEX; - + auto verticesBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); @@ -891,7 +894,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co details.streamFormat = streamFormat; details.stream = stream; - + // zzmp: fix the normal across all renderQuad details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); @@ -903,7 +906,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); - float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { + float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { minCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMinCorner.x, texCoordMinCorner.y, maxCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMaxCorner.x, texCoordMinCorner.y, minCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMinCorner.x, texCoordMaxCorner.y, @@ -913,9 +916,9 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co const int NUM_COLOR_SCALARS_PER_QUAD = 4; int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); + ((int(color.y * 255.0f) & 0xFF) << 8) | + ((int(color.z * 255.0f) & 0xFF) << 16) | + ((int(color.w * 255.0f) & 0xFF) << 24); int colors[NUM_COLOR_SCALARS_PER_QUAD] = { compactColor, compactColor, compactColor, compactColor }; details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); @@ -937,16 +940,16 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co Vec3PairVec4& lastKey = _lastRegisteredQuad3D[id]; if (lastKey != key) { details.clear(); - _lastRegisteredQuad3D[id] = key; - #ifdef WANT_DEBUG - qCDebug(renderutils) << "renderQuad() 3D ... RELEASING REGISTERED"; - #endif // def WANT_DEBUG + _lastRegisteredQuad3D[id] = key; +#ifdef WANT_DEBUG + qCDebug(renderutils) << "renderQuad() 3D ... RELEASING REGISTERED"; +#endif // def WANT_DEBUG } - #ifdef WANT_DEBUG +#ifdef WANT_DEBUG else { qCDebug(renderutils) << "renderQuad() 3D ... REUSING PREVIOUSLY REGISTERED"; } - #endif // def WANT_DEBUG +#endif // def WANT_DEBUG } const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals @@ -959,7 +962,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co details.isCreated = true; details.vertices = VERTICES; details.vertexSize = FLOATS_PER_VERTEX; - + auto verticesBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); @@ -971,7 +974,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co details.streamFormat = streamFormat; details.stream = stream; - + details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); @@ -981,7 +984,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); - float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { + float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { minCorner.x, minCorner.y, minCorner.z, NORMAL.x, NORMAL.y, NORMAL.z, maxCorner.x, minCorner.y, minCorner.z, NORMAL.x, NORMAL.y, NORMAL.z, minCorner.x, maxCorner.y, maxCorner.z, NORMAL.x, NORMAL.y, NORMAL.z, @@ -990,9 +993,9 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co const int NUM_COLOR_SCALARS_PER_QUAD = 4; int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); + ((int(color.y * 255.0f) & 0xFF) << 8) | + ((int(color.z * 255.0f) & 0xFF) << 16) | + ((int(color.w * 255.0f) & 0xFF) << 24); int colors[NUM_COLOR_SCALARS_PER_QUAD] = { compactColor, compactColor, compactColor, compactColor }; details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); @@ -1004,28 +1007,28 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co batch.draw(gpu::TRIANGLE_STRIP, 4, 0); } -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, - const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight, - const glm::vec4& color, int id) { +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, + const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight, + const glm::vec4& color, int id) { + +#ifdef WANT_DEBUG + qCDebug(renderutils) << "renderQuad() vec3 + texture VBO..."; + qCDebug(renderutils) << " topLeft:" << topLeft; + qCDebug(renderutils) << " bottomLeft:" << bottomLeft; + qCDebug(renderutils) << " bottomRight:" << bottomRight; + qCDebug(renderutils) << " topRight:" << topRight; + qCDebug(renderutils) << " texCoordTopLeft:" << texCoordTopLeft; + qCDebug(renderutils) << " texCoordBottomRight:" << texCoordBottomRight; + qCDebug(renderutils) << " color:" << color; +#endif //def WANT_DEBUG - #ifdef WANT_DEBUG - qCDebug(renderutils) << "renderQuad() vec3 + texture VBO..."; - qCDebug(renderutils) << " topLeft:" << topLeft; - qCDebug(renderutils) << " bottomLeft:" << bottomLeft; - qCDebug(renderutils) << " bottomRight:" << bottomRight; - qCDebug(renderutils) << " topRight:" << topRight; - qCDebug(renderutils) << " texCoordTopLeft:" << texCoordTopLeft; - qCDebug(renderutils) << " texCoordBottomRight:" << texCoordBottomRight; - qCDebug(renderutils) << " color:" << color; - #endif //def WANT_DEBUG - bool registered = (id != UNKNOWN_ID); Vec3PairVec4Pair key(Vec3Pair(topLeft, bottomRight), - Vec4Pair(glm::vec4(texCoordTopLeft.x,texCoordTopLeft.y,texCoordBottomRight.x,texCoordBottomRight.y), - color)); - + Vec4Pair(glm::vec4(texCoordTopLeft.x, texCoordTopLeft.y, texCoordBottomRight.x, texCoordBottomRight.y), + color)); + BatchItemDetails& details = registered ? _registeredQuad3DTextures[id] : _quad3DTextures[key]; // if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed @@ -1034,15 +1037,15 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons if (lastKey != key) { details.clear(); _lastRegisteredQuad3DTexture[id] = key; - #ifdef WANT_DEBUG - qCDebug(renderutils) << "renderQuad() 3D+texture ... RELEASING REGISTERED"; - #endif // def WANT_DEBUG +#ifdef WANT_DEBUG + qCDebug(renderutils) << "renderQuad() 3D+texture ... RELEASING REGISTERED"; +#endif // def WANT_DEBUG } - #ifdef WANT_DEBUG +#ifdef WANT_DEBUG else { qCDebug(renderutils) << "renderQuad() 3D+texture ... REUSING PREVIOUSLY REGISTERED"; } - #endif // def WANT_DEBUG +#endif // def WANT_DEBUG } const int FLOATS_PER_VERTEX = 3 + 3 + 2; // vertices + normals + tex coords @@ -1058,7 +1061,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons details.isCreated = true; details.vertices = VERTICES; details.vertexSize = FLOATS_PER_VERTEX; // NOTE: this isn't used for BatchItemDetails maybe we can get rid of it - + auto verticesBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); @@ -1068,7 +1071,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons details.colorBuffer = colorBuffer; details.streamFormat = streamFormat; details.stream = stream; - + details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET); @@ -1088,9 +1091,9 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons const int NUM_COLOR_SCALARS_PER_QUAD = 4; int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); + ((int(color.y * 255.0f) & 0xFF) << 8) | + ((int(color.z * 255.0f) & 0xFF) << 16) | + ((int(color.w * 255.0f) & 0xFF) << 24); int colors[NUM_COLOR_SCALARS_PER_QUAD] = { compactColor, compactColor, compactColor, compactColor }; details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); @@ -1103,7 +1106,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons } void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, - const float dash_length, const float gap_length, int id) { + const float dash_length, const float gap_length, 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))); @@ -1114,18 +1117,18 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, if (_lastRegisteredDashedLines[id] != key) { details.clear(); _lastRegisteredDashedLines[id] = key; - #ifdef WANT_DEBUG - qCDebug(renderutils) << "renderDashedLine()... RELEASING REGISTERED"; - #endif // def WANT_DEBUG +#ifdef WANT_DEBUG + qCDebug(renderutils) << "renderDashedLine()... RELEASING REGISTERED"; +#endif // def WANT_DEBUG } } if (!details.isCreated) { int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); + ((int(color.y * 255.0f) & 0xFF) << 8) | + ((int(color.z * 255.0f) & 0xFF) << 16) | + ((int(color.w * 255.0f) & 0xFF) << 24); // draw each line segment with appropriate gaps const float SEGMENT_LENGTH = dash_length + gap_length; @@ -1143,7 +1146,7 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, details.vertices = (segmentCountFloor + 1) * 2; details.vertexSize = FLOATS_PER_VERTEX; details.isCreated = true; - + auto verticesBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); @@ -1209,13 +1212,13 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, delete[] vertexData; delete[] colorData; - #ifdef WANT_DEBUG +#ifdef WANT_DEBUG if (registered) { qCDebug(renderutils) << "new registered dashed line buffer made -- _registeredVertices:" << _registeredDashedLines.size(); } else { qCDebug(renderutils) << "new dashed lines buffer made -- _dashedLines:" << _dashedLines.size(); } - #endif +#endif } batch.setInputFormat(details.streamFormat); @@ -1227,41 +1230,39 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, int GeometryCache::BatchItemDetails::population = 0; GeometryCache::BatchItemDetails::BatchItemDetails() : - verticesBuffer(NULL), - colorBuffer(NULL), - streamFormat(NULL), - stream(NULL), - vertices(0), - vertexSize(0), - isCreated(false) -{ +verticesBuffer(NULL), +colorBuffer(NULL), +streamFormat(NULL), +stream(NULL), +vertices(0), +vertexSize(0), +isCreated(false) { population++; - #ifdef WANT_DEBUG - qCDebug(renderutils) << "BatchItemDetails()... population:" << population << "**********************************"; - #endif +#ifdef WANT_DEBUG + qCDebug(renderutils) << "BatchItemDetails()... population:" << population << "**********************************"; +#endif } GeometryCache::BatchItemDetails::BatchItemDetails(const GeometryCache::BatchItemDetails& other) : - verticesBuffer(other.verticesBuffer), - colorBuffer(other.colorBuffer), - streamFormat(other.streamFormat), - stream(other.stream), - vertices(other.vertices), - vertexSize(other.vertexSize), - isCreated(other.isCreated) -{ +verticesBuffer(other.verticesBuffer), +colorBuffer(other.colorBuffer), +streamFormat(other.streamFormat), +stream(other.stream), +vertices(other.vertices), +vertexSize(other.vertexSize), +isCreated(other.isCreated) { population++; - #ifdef WANT_DEBUG - qCDebug(renderutils) << "BatchItemDetails()... population:" << population << "**********************************"; - #endif +#ifdef WANT_DEBUG + qCDebug(renderutils) << "BatchItemDetails()... population:" << population << "**********************************"; +#endif } GeometryCache::BatchItemDetails::~BatchItemDetails() { population--; - clear(); - #ifdef WANT_DEBUG - qCDebug(renderutils) << "~BatchItemDetails()... population:" << population << "**********************************"; - #endif + clear(); +#ifdef WANT_DEBUG + qCDebug(renderutils) << "~BatchItemDetails()... population:" << population << "**********************************"; +#endif } void GeometryCache::BatchItemDetails::clear() { @@ -1272,23 +1273,23 @@ void GeometryCache::BatchItemDetails::clear() { stream.reset(); } -void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, - const glm::vec4& color1, const glm::vec4& color2, int id) { - +void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, + const glm::vec4& color1, const glm::vec4& color2, int id) { + bool registered = (id != UNKNOWN_ID); Vec3Pair key(p1, p2); BatchItemDetails& details = registered ? _registeredLine3DVBOs[id] : _line3DVBOs[key]; int compactColor1 = ((int(color1.x * 255.0f) & 0xFF)) | - ((int(color1.y * 255.0f) & 0xFF) << 8) | - ((int(color1.z * 255.0f) & 0xFF) << 16) | - ((int(color1.w * 255.0f) & 0xFF) << 24); + ((int(color1.y * 255.0f) & 0xFF) << 8) | + ((int(color1.z * 255.0f) & 0xFF) << 16) | + ((int(color1.w * 255.0f) & 0xFF) << 24); int compactColor2 = ((int(color2.x * 255.0f) & 0xFF)) | - ((int(color2.y * 255.0f) & 0xFF) << 8) | - ((int(color2.z * 255.0f) & 0xFF) << 16) | - ((int(color2.w * 255.0f) & 0xFF) << 24); + ((int(color2.y * 255.0f) & 0xFF) << 8) | + ((int(color2.z * 255.0f) & 0xFF) << 16) | + ((int(color2.w * 255.0f) & 0xFF) << 24); // if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed @@ -1296,16 +1297,16 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm Vec3Pair& lastKey = _lastRegisteredLine3D[id]; if (lastKey != key) { details.clear(); - _lastRegisteredLine3D[id] = key; - #ifdef WANT_DEBUG - qCDebug(renderutils) << "renderLine() 3D ... RELEASING REGISTERED line"; - #endif // def WANT_DEBUG + _lastRegisteredLine3D[id] = key; +#ifdef WANT_DEBUG + qCDebug(renderutils) << "renderLine() 3D ... RELEASING REGISTERED line"; +#endif // def WANT_DEBUG } - #ifdef WANT_DEBUG +#ifdef WANT_DEBUG else { qCDebug(renderutils) << "renderLine() 3D ... REUSING PREVIOUSLY REGISTERED line"; } - #endif // def WANT_DEBUG +#endif // def WANT_DEBUG } const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals @@ -1317,7 +1318,7 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm details.isCreated = true; details.vertices = vertices; details.vertexSize = FLOATS_PER_VERTEX; - + auto verticesBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); @@ -1327,7 +1328,7 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm details.colorBuffer = colorBuffer; details.streamFormat = streamFormat; details.stream = stream; - + details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); @@ -1338,7 +1339,7 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm const glm::vec3 NORMAL(1.0f, 0.0f, 0.0f); float vertexBuffer[vertices * FLOATS_PER_VERTEX] = { p1.x, p1.y, p1.z, NORMAL.x, NORMAL.y, NORMAL.z, - p2.x, p2.y, p2.z, NORMAL.x, NORMAL.y, NORMAL.z}; + p2.x, p2.y, p2.z, NORMAL.x, NORMAL.y, NORMAL.z }; const int NUM_COLOR_SCALARS = 2; int colors[NUM_COLOR_SCALARS] = { compactColor1, compactColor2 }; @@ -1346,13 +1347,13 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); - #ifdef WANT_DEBUG - if (id == UNKNOWN_ID) { - qCDebug(renderutils) << "new renderLine() 3D VBO made -- _line3DVBOs.size():" << _line3DVBOs.size(); - } else { - qCDebug(renderutils) << "new registered renderLine() 3D VBO made -- _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size(); - } - #endif +#ifdef WANT_DEBUG + if (id == UNKNOWN_ID) { + qCDebug(renderutils) << "new renderLine() 3D VBO made -- _line3DVBOs.size():" << _line3DVBOs.size(); + } else { + qCDebug(renderutils) << "new registered renderLine() 3D VBO made -- _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size(); + } +#endif } // this is what it takes to render a quad @@ -1361,23 +1362,23 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm batch.draw(gpu::LINES, 2, 0); } -void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2, - const glm::vec4& color1, const glm::vec4& color2, int id) { - +void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2, + const glm::vec4& color1, const glm::vec4& color2, int id) { + bool registered = (id != UNKNOWN_ID); Vec2Pair key(p1, p2); BatchItemDetails& details = registered ? _registeredLine2DVBOs[id] : _line2DVBOs[key]; int compactColor1 = ((int(color1.x * 255.0f) & 0xFF)) | - ((int(color1.y * 255.0f) & 0xFF) << 8) | - ((int(color1.z * 255.0f) & 0xFF) << 16) | - ((int(color1.w * 255.0f) & 0xFF) << 24); + ((int(color1.y * 255.0f) & 0xFF) << 8) | + ((int(color1.z * 255.0f) & 0xFF) << 16) | + ((int(color1.w * 255.0f) & 0xFF) << 24); int compactColor2 = ((int(color2.x * 255.0f) & 0xFF)) | - ((int(color2.y * 255.0f) & 0xFF) << 8) | - ((int(color2.z * 255.0f) & 0xFF) << 16) | - ((int(color2.w * 255.0f) & 0xFF) << 24); + ((int(color2.y * 255.0f) & 0xFF) << 8) | + ((int(color2.z * 255.0f) & 0xFF) << 16) | + ((int(color2.w * 255.0f) & 0xFF) << 24); // if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed @@ -1386,15 +1387,15 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm if (lastKey != key) { details.clear(); _lastRegisteredLine2D[id] = key; - #ifdef WANT_DEBUG - qCDebug(renderutils) << "renderLine() 2D ... RELEASING REGISTERED line"; - #endif // def WANT_DEBUG +#ifdef WANT_DEBUG + qCDebug(renderutils) << "renderLine() 2D ... RELEASING REGISTERED line"; +#endif // def WANT_DEBUG } - #ifdef WANT_DEBUG +#ifdef WANT_DEBUG else { qCDebug(renderutils) << "renderLine() 2D ... REUSING PREVIOUSLY REGISTERED line"; } - #endif // def WANT_DEBUG +#endif // def WANT_DEBUG } const int FLOATS_PER_VERTEX = 2; @@ -1404,7 +1405,7 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm details.isCreated = true; details.vertices = vertices; details.vertexSize = FLOATS_PER_VERTEX; - + auto verticesBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); @@ -1414,7 +1415,7 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm details.colorBuffer = colorBuffer; details.streamFormat = streamFormat; details.stream = stream; - + details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); @@ -1430,13 +1431,103 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); - #ifdef WANT_DEBUG - if (id == UNKNOWN_ID) { - qCDebug(renderutils) << "new renderLine() 2D VBO made -- _line3DVBOs.size():" << _line2DVBOs.size(); - } else { - qCDebug(renderutils) << "new registered renderLine() 2D VBO made -- _registeredLine2DVBOs.size():" << _registeredLine2DVBOs.size(); - } - #endif +#ifdef WANT_DEBUG + if (id == UNKNOWN_ID) { + qCDebug(renderutils) << "new renderLine() 2D VBO made -- _line3DVBOs.size():" << _line2DVBOs.size(); + } else { + qCDebug(renderutils) << "new registered renderLine() 2D VBO made -- _registeredLine2DVBOs.size():" << _registeredLine2DVBOs.size(); + } +#endif + } + + // this is what it takes to render a quad + batch.setInputFormat(details.streamFormat); + batch.setInputStream(0, *details.stream); + batch.draw(gpu::LINES, 2, 0); +} + + +void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, + const glm::vec4& color, float glowIntensity, float glowWidth, int id) { + if (glowIntensity <= 0) { + renderLine(batch, p1, p2, color, id); + return; + } + + // Compile the shaders + static std::once_flag once; + std::call_once(once, [&] { + auto state = std::make_shared(); + auto VS = gpu::Shader::createVertex(std::string(glowLine_vert)); + auto GS = gpu::Shader::createGeometry(std::string(glowLine_geom)); + auto PS = gpu::Shader::createPixel(std::string(glowLine_frag)); + auto program = gpu::Shader::createProgram(VS, GS, PS); + state->setCullMode(gpu::State::CULL_BACK); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + state->setDepthBias(1.0f); + state->setDepthBiasSlopeScale(1.0f); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), render::ShapePipeline::Slot::MAP::NORMAL_FITTING)); + gpu::Shader::makeProgram(*program, slotBindings); + _glowLinePipeline = gpu::Pipeline::create(program, state); + }); + + batch.setPipeline(_glowLinePipeline); + + Vec3Pair key(p1, p2); + bool registered = (id != UNKNOWN_ID); + BatchItemDetails& details = registered ? _registeredLine3DVBOs[id] : _line3DVBOs[key]; + + int compactColor = ((int(color.x * 255.0f) & 0xFF)) | + ((int(color.y * 255.0f) & 0xFF) << 8) | + ((int(color.z * 255.0f) & 0xFF) << 16) | + ((int(color.w * 255.0f) & 0xFF) << 24); + + // if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed + if (registered && details.isCreated) { + Vec3Pair& lastKey = _lastRegisteredLine3D[id]; + if (lastKey != key) { + details.clear(); + _lastRegisteredLine3D[id] = key; + } + } + + const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals + const int NUM_POS_COORDS = 3; + const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float); + const int vertices = 2; + if (!details.isCreated) { + details.isCreated = true; + details.vertices = vertices; + details.vertexSize = FLOATS_PER_VERTEX; + + auto verticesBuffer = std::make_shared(); + auto colorBuffer = std::make_shared(); + auto streamFormat = std::make_shared(); + auto stream = std::make_shared(); + + details.verticesBuffer = verticesBuffer; + details.colorBuffer = colorBuffer; + details.streamFormat = streamFormat; + details.stream = stream; + + details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); + details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); + details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + + details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); + details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); + + const glm::vec3 NORMAL(1.0f, 0.0f, 0.0f); + float vertexBuffer[vertices * FLOATS_PER_VERTEX] = { + p1.x, p1.y, p1.z, NORMAL.x, NORMAL.y, NORMAL.z, + p2.x, p2.y, p2.z, NORMAL.x, NORMAL.y, NORMAL.z }; + + const int NUM_COLOR_SCALARS = 2; + int colors[NUM_COLOR_SCALARS] = { compactColor, compactColor }; + details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); + details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); } // this is what it takes to render a quad @@ -1532,7 +1623,7 @@ public: SimpleProgramKey(bool textured = false, bool culled = true, - bool unlit = false, bool depthBias = false) { + bool unlit = false, bool depthBias = false) { _flags = (textured ? IS_TEXTURED : 0) | (culled ? IS_CULLED : 0) | (unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0); } @@ -1562,7 +1653,7 @@ void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool cul } gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled, bool unlit, bool depthBiased) { - SimpleProgramKey config{ textured, culled, unlit, depthBiased }; + SimpleProgramKey config { textured, culled, unlit, depthBiased }; // Compile the shaders static std::once_flag once; @@ -1570,10 +1661,10 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled auto VS = gpu::Shader::createVertex(std::string(simple_vert)); auto PS = gpu::Shader::createPixel(std::string(simple_textured_frag)); auto PSUnlit = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag)); - + _simpleShader = gpu::Shader::createProgram(VS, PS); _unlitShader = gpu::Shader::createProgram(VS, PSUnlit); - + gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), render::ShapePipeline::Slot::MAP::NORMAL_FITTING)); gpu::Shader::makeProgram(*_simpleShader, slotBindings); @@ -1610,16 +1701,16 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled uint32_t toCompactColor(const glm::vec4& color) { uint32_t compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); + ((int(color.y * 255.0f) & 0xFF) << 8) | + ((int(color.z * 255.0f) & 0xFF) << 16) | + ((int(color.w * 255.0f) & 0xFF) << 24); return compactColor; } static const size_t INSTANCE_COLOR_BUFFER = 0; void renderInstances(gpu::Batch& batch, const glm::vec4& color, bool isWire, - const render::ShapePipelinePointer& pipeline, GeometryCache::Shape shape) { + const render::ShapePipelinePointer& pipeline, GeometryCache::Shape shape) { // Add pipeline to name std::string instanceName = (isWire ? "wire_shapes_" : "solid_shapes_") + std::to_string(shape) + "_" + std::to_string(std::hash()(pipeline)); @@ -1663,7 +1754,7 @@ void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& #ifdef DEBUG_SHAPES static auto startTime = usecTimestampNow(); renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { - + auto usecs = usecTimestampNow(); usecs -= startTime; auto msecs = usecs / USECS_PER_MSEC; @@ -1671,7 +1762,7 @@ void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& seconds /= MSECS_PER_SECOND; float fractionalSeconds = seconds - floor(seconds); int shapeIndex = (int)seconds; - + // Every second we flip to the next shape. static const int SHAPE_COUNT = 5; GeometryCache::Shape shapes[SHAPE_COUNT] = { @@ -1681,10 +1772,10 @@ void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& GeometryCache::Icosahedron, GeometryCache::Line, }; - + shapeIndex %= SHAPE_COUNT; GeometryCache::Shape shape = shapes[shapeIndex]; - + // For the first half second for a given shape, show the wireframe, for the second half, show the solid. if (fractionalSeconds > 0.5f) { renderInstances(INSTANCE_NAME, batch, color, true, pipeline, shape); diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 9f18f1644c..647fa9889c 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -259,6 +259,9 @@ public: 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 renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, + const glm::vec4& color, float glowIntensity = 1.0f, float glowWidth = 0.05f, 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) { renderDashedLine(batch, start, end, color, 0.05f, 0.025f, id); } @@ -403,6 +406,7 @@ private: gpu::ShaderPointer _unlitShader; static render::ShapePipelinePointer _simplePipeline; static render::ShapePipelinePointer _simpleWirePipeline; + gpu::PipelinePointer _glowLinePipeline; QHash _simplePrograms; }; diff --git a/libraries/render-utils/src/glowLine.slf b/libraries/render-utils/src/glowLine.slf new file mode 100644 index 0000000000..93a12fe5ca --- /dev/null +++ b/libraries/render-utils/src/glowLine.slf @@ -0,0 +1,32 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// Created by Bradley Austin Davis on 2016/07/05 +// Copyright 2013-2016 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 +// + +layout(location = 0) in vec4 inColor; +layout(location = 1) in vec3 inLineDistance; + +out vec4 _fragColor; + +void main(void) { + vec2 d = inLineDistance.xy; + d.y = abs(d.y); + d.x = abs(d.x); + if (d.x > 1.0) { + d.x = (d.x - 1.0) / 0.02; + } else { + d.x = 0.0; + } + float alpha = 1.0 - length(d); + if (alpha < 0.01) { + discard; + } + alpha = pow(alpha, 10.0); + _fragColor = vec4(inColor.rgb, alpha); +} diff --git a/libraries/render-utils/src/glowLine.slg b/libraries/render-utils/src/glowLine.slg new file mode 100644 index 0000000000..c577112abb --- /dev/null +++ b/libraries/render-utils/src/glowLine.slg @@ -0,0 +1,127 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// Created by Bradley Austin Davis on 2016/07/05 +// Copyright 2013-2016 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 +// +#extension GL_EXT_geometry_shader4 : enable + +layout(location = 0) in vec4 inColor[]; + +layout(location = 0) out vec4 outColor; +layout(location = 1) out vec3 outLineDistance; + +layout(lines) in; +layout(triangle_strip, max_vertices = 24) out; + +struct TransformCamera { + mat4 _view; + mat4 _viewInverse; + mat4 _projectionViewUntranslated; + mat4 _projection; + mat4 _projectionInverse; + vec4 _viewport; +}; + +layout(std140) uniform transformCameraBuffer { + TransformCamera _camera; +}; + +TransformCamera getTransformCamera() { + return _camera; +} + +vec3 getEyeWorldPos() { + return _camera._viewInverse[3].xyz; +} + + + + +vec3 ndcToEyeSpace(in vec4 v) { + TransformCamera cam = getTransformCamera(); + vec4 u = cam._projectionInverse * v; + return u.xyz / u.w; +} + +vec2 toScreenSpace(in vec4 v) +{ + TransformCamera cam = getTransformCamera(); + vec4 u = cam._projection * cam._view * v; + return u.xy / u.w; +} + +vec3[2] getOrthogonals(in vec3 n, float scale) { + float yDot = abs(dot(n, vec3(0, 1, 0))); + + vec3 result[2]; + if (yDot < 0.9) { + result[0] = normalize(cross(n, vec3(0, 1, 0))); + } else { + result[0] = normalize(cross(n, vec3(1, 0, 0))); + } + // The cross of result[0] and n is orthogonal to both, which are orthogonal to each other + result[1] = cross(result[0], n); + result[0] *= scale; + result[1] *= scale; + return result; +} + + +vec2 orthogonal(vec2 v) { + vec2 result = v.yx; + result.y *= -1.0; + return result; +} + +void main() { + vec2 endpoints[2]; + vec3 eyeSpace[2]; + TransformCamera cam = getTransformCamera(); + for (int i = 0; i < 2; ++i) { + eyeSpace[i] = ndcToEyeSpace(gl_PositionIn[i]); + endpoints[i] = gl_PositionIn[i].xy / gl_PositionIn[i].w; + } + vec2 lineNormal = normalize(endpoints[1] - endpoints[0]); + vec2 lineOrthogonal = orthogonal(lineNormal); + lineNormal *= 0.02; + lineOrthogonal *= 0.02; + + gl_Position = gl_PositionIn[0]; + gl_Position.xy -= lineNormal; + gl_Position.xy -= lineOrthogonal; + outColor = inColor[0]; + outLineDistance = vec3(-1.02, -1, gl_Position.z); + EmitVertex(); + + gl_Position = gl_PositionIn[0]; + gl_Position.xy -= lineNormal; + gl_Position.xy += lineOrthogonal; + outColor = inColor[0]; + outLineDistance = vec3(-1.02, 1, gl_Position.z); + EmitVertex(); + + gl_Position = gl_PositionIn[1]; + gl_Position.xy += lineNormal; + gl_Position.xy -= lineOrthogonal; + outColor = inColor[1]; + outLineDistance = vec3(1.02, -1, gl_Position.z); + EmitVertex(); + + gl_Position = gl_PositionIn[1]; + gl_Position.xy += lineNormal; + gl_Position.xy += lineOrthogonal; + outColor = inColor[1]; + outLineDistance = vec3(1.02, 1, gl_Position.z); + EmitVertex(); + + EndPrimitive(); +} + + + + diff --git a/libraries/render-utils/src/glowLine.slv b/libraries/render-utils/src/glowLine.slv new file mode 100644 index 0000000000..aa126fe31a --- /dev/null +++ b/libraries/render-utils/src/glowLine.slv @@ -0,0 +1,26 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// Created by Bradley Austin Davis on 2016/07/05 +// Copyright 2013-2016 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/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +layout(location = 0) out vec4 _color; + +void main(void) { + _color = inColor; + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> +} \ No newline at end of file