diff --git a/interface/resources/shaders/metavoxel_point.vert b/interface/resources/shaders/metavoxel_point.vert new file mode 100644 index 0000000000..be04462375 --- /dev/null +++ b/interface/resources/shaders/metavoxel_point.vert @@ -0,0 +1,22 @@ +#version 120 + +// +// metavoxel_point.vert +// vertex shader +// +// Created by Andrzej Kapolka on 12/12/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +uniform float pointScale; + +void main(void) { + + // pass along the vertex color + gl_FrontColor = gl_Color; + + // extract the first four components of the vertex for position + gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1.0); + + gl_PointSize = pointScale * gl_Vertex.w / gl_Position.w; +} diff --git a/interface/src/renderer/MetavoxelSystem.cpp b/interface/src/renderer/MetavoxelSystem.cpp index 7cb5987bb7..c5c8ab327f 100644 --- a/interface/src/renderer/MetavoxelSystem.cpp +++ b/interface/src/renderer/MetavoxelSystem.cpp @@ -8,41 +8,112 @@ #include +#include + +#include "Application.h" #include "MetavoxelSystem.h" -class PointVisitor : public MetavoxelVisitor { -public: - - virtual bool visit(const MetavoxelInfo& info); -}; +ProgramObject MetavoxelSystem::_program; +int MetavoxelSystem::_pointScaleLocation; -bool PointVisitor::visit(const MetavoxelInfo& info) { - QRgb color = info.attributeValues.at(0).getInlineValue(); - QRgb normal = info.attributeValues.at(1).getInlineValue(); - - return true; +MetavoxelSystem::MetavoxelSystem() : + _buffer(QOpenGLBuffer::VertexBuffer), + _pointVisitor(_points) { } void MetavoxelSystem::init() { + if (!_program.isLinked()) { + switchToResourcesParentIfRequired(); + _program.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/metavoxel_point.vert"); + _program.link(); + + _pointScaleLocation = _program.uniformLocation("pointScale"); + } + MetavoxelPath p1; - p1 += 0; - p1 += 1; - p1 += 2; + p1 += 7; + p1 += 7; + p1 += 7; AttributePointer color = AttributeRegistry::getInstance()->getAttribute("color"); void* white = encodeInline(qRgba(0xFF, 0xFF, 0xFF, 0xFF)); _data.setAttributeValue(p1, AttributeValue(color, &white)); + + _buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw); + _buffer.create(); } void MetavoxelSystem::simulate(float deltaTime) { + _points.clear(); + QVector attributes; attributes << AttributeRegistry::getInstance()->getColorAttribute(); attributes << AttributeRegistry::getInstance()->getNormalAttribute(); - PointVisitor visitor; - _data.visitVoxels(attributes, visitor); + _data.visitVoxels(attributes, _pointVisitor); + + _buffer.bind(); + int bytes = _points.size() * sizeof(Point); + if (_buffer.size() < bytes) { + _buffer.allocate(_points.constData(), bytes); + } else { + _buffer.write(0, _points.constData(), bytes); + } + _buffer.release(); } void MetavoxelSystem::render() { + int viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + const int VIEWPORT_WIDTH_INDEX = 2; + const int VIEWPORT_HEIGHT_INDEX = 3; + float viewportWidth = viewport[VIEWPORT_WIDTH_INDEX]; + float viewportHeight = viewport[VIEWPORT_HEIGHT_INDEX]; + float viewportDiagonal = sqrtf(viewportWidth*viewportWidth + viewportHeight*viewportHeight); + float worldDiagonal = glm::distance(Application::getInstance()->getViewFrustum()->getNearBottomLeft(), + Application::getInstance()->getViewFrustum()->getNearTopRight()); + + _program.bind(); + _program.setUniformValue(_pointScaleLocation, viewportDiagonal * + Application::getInstance()->getViewFrustum()->getNearClip() / worldDiagonal); + + _buffer.bind(); + + Point* pt = 0; + glVertexPointer(4, GL_FLOAT, sizeof(Point), &pt->vertex); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Point), &pt->color); + glNormalPointer(GL_BYTE, sizeof(Point), &pt->normal); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB); + glDrawArrays(GL_POINTS, 0, _points.size()); + + glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + + _buffer.release(); + + _program.release(); +} + +bool MetavoxelSystem::PointVisitor::visit(const MetavoxelInfo& info) { + if (!info.isLeaf) { + return true; + } + QRgb color = info.attributeValues.at(0).getInlineValue(); + QRgb normal = info.attributeValues.at(1).getInlineValue(); + int alpha = qAlpha(color); + if (alpha > 0) { + Point point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size), + { qRed(color), qGreen(color), qBlue(color), alpha }, { qRed(normal), qGreen(normal), qBlue(normal) } }; + _points.append(point); + } + return false; } diff --git a/interface/src/renderer/MetavoxelSystem.h b/interface/src/renderer/MetavoxelSystem.h index ffb73290f3..4eaa4aaa95 100644 --- a/interface/src/renderer/MetavoxelSystem.h +++ b/interface/src/renderer/MetavoxelSystem.h @@ -9,20 +9,51 @@ #ifndef __interface__MetavoxelSystem__ #define __interface__MetavoxelSystem__ +#include +#include + +#include + #include +#include "ProgramObject.h" + /// Renders a metavoxel tree. class MetavoxelSystem { public: + MetavoxelSystem(); + void init(); void simulate(float deltaTime); void render(); private: + + class Point { + public: + glm::vec4 vertex; + quint8 color[4]; + quint8 normal[3]; + }; - MetavoxelData _data; + class PointVisitor : public MetavoxelVisitor { + public: + PointVisitor(QVector& points) : _points(points) { } + virtual bool visit(const MetavoxelInfo& info); + + protected: + QVector& _points; + }; + + static ProgramObject _program; + static int _pointScaleLocation; + + MetavoxelData _data; + QVector _points; + PointVisitor _pointVisitor; + QOpenGLBuffer _buffer; }; #endif /* defined(__interface__MetavoxelSystem__) */ diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index c99364aaa9..874dfbcf84 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -33,7 +33,8 @@ const int Y_MAXIMUM_FLAG = 2; const int Z_MAXIMUM_FLAG = 4; void Visitation::apply() { - if (!visitor.visit(info) || allNodesLeaves()) { + info.isLeaf = allNodesLeaves(); + if (!visitor.visit(info) || info.isLeaf) { return; } Visitation nextVisitation = { visitor, QVector(nodes.size()), diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index bbdf17c99c..adc4d1341c 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -103,6 +103,7 @@ public: glm::vec3 minimum; ///< the minimum extent of the area covered by the voxel float size; ///< the size of the voxel in all dimensions QVector attributeValues; + bool isLeaf; }; /// Interface for visitors to metavoxels.