From 552d9fadd88862b3903c6d39f08e1395f7e1ab70 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Sep 2013 14:51:57 -0700 Subject: [PATCH] rearranged menus, some hacking on voxel shader --- interface/resources/shaders/passthrough.geom | 68 --- interface/resources/shaders/passthrough.vert | 6 +- interface/resources/shaders/voxel.geom | 86 ++++ interface/src/Application.cpp | 95 ++++- interface/src/Application.h | 6 +- interface/src/Menu.cpp | 221 +++++----- interface/src/Menu.h | 7 +- interface/src/VoxelSystem.cpp | 396 ++++++++++++------ interface/src/VoxelSystem.h | 18 + interface/src/renderer/TestGeometry.h | 44 -- .../{TestGeometry.cpp => VoxelShader.cpp} | 50 ++- interface/src/renderer/VoxelShader.h | 46 ++ 12 files changed, 670 insertions(+), 373 deletions(-) create mode 100644 interface/resources/shaders/voxel.geom delete mode 100644 interface/src/renderer/TestGeometry.h rename interface/src/renderer/{TestGeometry.cpp => VoxelShader.cpp} (50%) create mode 100644 interface/src/renderer/VoxelShader.h diff --git a/interface/resources/shaders/passthrough.geom b/interface/resources/shaders/passthrough.geom index 1ce193cda9..4ea2959b19 100644 --- a/interface/resources/shaders/passthrough.geom +++ b/interface/resources/shaders/passthrough.geom @@ -79,72 +79,4 @@ void main() EmitVertex(); } EndPrimitive(); - -/** - - for(i = 0; i < gl_VerticesIn; i++) { - green = vec4(0,1.0,0,1.0); - red = vec4(1.0,0,0,1.0); - //gl_FrontColor = gl_FrontColorIn[i]; - gl_FrontColor = red; - - // v -> v+x -> v+x+y - vertex = gl_PositionIn[i]; - gl_Position = vertex; - EmitVertex(); - vertex.x += 0.1f; - gl_Position = vertex; - EmitVertex(); - vertex.y += 0.1f; - gl_Position = vertex; - EmitVertex(); - EndPrimitive(); - - // v+x+y -> v+y -> v - vertex = gl_PositionIn[i]; - vertex.x += 0.1f; - vertex.y += 0.1f; - gl_Position = vertex; - EmitVertex(); - vertex.x -= 0.1f; - gl_Position = vertex; - EmitVertex(); - vertex.y -= 0.1f; - gl_Position = vertex; - EmitVertex(); - EndPrimitive(); - // v+z -> v+z+x -> v+z+x+y - gl_FrontColor = green; - vertex = gl_PositionIn[i]; - vertex.z -= 0.1f; - gl_Position = vertex; - EmitVertex(); - - vertex.x += 0.1f; - gl_Position = vertex; - EmitVertex(); - vertex.y += 0.1f; - gl_Position = vertex; - EmitVertex(); - EndPrimitive(); - - // v+z+x+y -> v+z+y -> v+z - vertex = gl_PositionIn[i]; - vertex.z -= 0.1f; - vertex.x += 0.1f; - vertex.y += 0.1f; - gl_Position = vertex; - EmitVertex(); - vertex.x -= 0.1f; - gl_Position = vertex; - EmitVertex(); - vertex.y -= 0.1f; - gl_Position = vertex; - EmitVertex(); - EndPrimitive(); - - } -**/ - - } \ No newline at end of file diff --git a/interface/resources/shaders/passthrough.vert b/interface/resources/shaders/passthrough.vert index a3a6219b6a..f770ab115f 100644 --- a/interface/resources/shaders/passthrough.vert +++ b/interface/resources/shaders/passthrough.vert @@ -1,6 +1,10 @@ #version 120 +attribute float voxelSizeIn; +varying float voxelSize; + void main(void) { gl_FrontColor = gl_Color; //vec4(1.0, 0.0, 0.0, 1.0); - gl_Position = gl_Vertex;// ftransform(); + gl_Position = gl_ModelViewMatrix * gl_Vertex;// ftransform(); + voxelSize = voxelSizeIn; } \ No newline at end of file diff --git a/interface/resources/shaders/voxel.geom b/interface/resources/shaders/voxel.geom new file mode 100644 index 0000000000..d3f0b89f10 --- /dev/null +++ b/interface/resources/shaders/voxel.geom @@ -0,0 +1,86 @@ +#version 120 +#extension GL_ARB_geometry_shader4 : enable + +// +// VOXEL GEOMETRY SHADER +// +// Input: gl_VerticesIn/gl_PositionIn +// GL_POINTS +// Assumes vertex shader has not transformed coordinates +// Each gl_PositionIn is the corner of voxel +// +// Second dataset (? similar to how voxel avatars pass in bones??) +// which is the voxel size +// +// Note: In vertex shader DON'T transform. Therefore passing the world coordinate xyz to geometric shader +// In geometric shader calculate xyz for triangles the same way we currently do triangles outside of OpenGL +// do transform on these triangles +// +// gl_Position = gl_ModelViewProjectionMatrix * cube_coord; +// +// Output: GL_TRIANGLE_STRIP +// +// Issues: +// do we need to handle lighting of these colors?? +// how do we handle normals? +// check for size=0 and don't output the primitive +// + +varying in float voxelSize[1]; + +const int VERTICES_PER_FACE = 4; +const int COORD_PER_VERTEX = 3; +const int COORD_PER_FACE = COORD_PER_VERTEX * VERTICES_PER_FACE; + +void faceOfVoxel(vec4 corner, float scale, float[COORD_PER_FACE] facePoints, vec4 color) { + for (int v = 0; v < VERTICES_PER_FACE; v++ ) { + vec4 vertex = corner; + for (int c = 0; c < COORD_PER_VERTEX; c++ ) { + int cIndex = c + (v * COORD_PER_VERTEX); + vertex[c] += (facePoints[cIndex] * scale); + } + gl_FrontColor = color; + gl_Position = gl_ProjectionMatrix * vertex; + EmitVertex(); + } + EndPrimitive(); +} + + +void main() +{ + //increment variable + int i; + vec4 corner; + float scale; + + float bottomFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1 ); + float topFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1 ); + float rightFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1 ); + float leftFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1 ); + float frontFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 ); + float backFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1 ); + + vec4 color,red,green,blue,yellow,cyan,purple; + + green = vec4(0,1.0,0,1.0); + red = vec4(1.0,0,0,1.0); + blue = vec4(0,0,1.0,1.0); + yellow = vec4(1.0,1.0,0,1.0); + cyan = vec4(0,1.0,1.0,1.0); + purple = vec4(1.0,0,1.0,1.0); + + for(i = 0; i < gl_VerticesIn; i++) { + gl_FrontColor = gl_FrontColorIn[i]; + corner = gl_PositionIn[i]; + scale = voxelSize[i]; + color = gl_FrontColorIn[i]; + + faceOfVoxel(corner, scale, bottomFace, color); + faceOfVoxel(corner, scale, topFace, color); + faceOfVoxel(corner, scale, rightFace, color); + faceOfVoxel(corner, scale, leftFace, color); + faceOfVoxel(corner, scale, frontFace, color); + faceOfVoxel(corner, scale, backFace, color); + } +} \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 503f8f434e..b10ed430bf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -542,6 +542,10 @@ void Application::keyPressEvent(QKeyEvent* event) { _myAvatar.setDriveKeys(UP, 1); } break; + + case Qt::Key_Asterisk: + Menu::getInstance()->triggerOption(MenuOption::Stars); + break; case Qt::Key_C: if (isShifted) { @@ -811,8 +815,6 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_F: if (isShifted) { Menu::getInstance()->triggerOption(MenuOption::DisplayFrustum); - } else { - Menu::getInstance()->triggerOption(MenuOption::Fullscreen); } break; case Qt::Key_V: @@ -1540,7 +1542,7 @@ void Application::init() { _glowEffect.init(); _ambientOcclusionEffect.init(); - _testGeometry.init(); + _voxelShader.init(); _handControl.setScreenDimensions(_glWidget->width(), _glWidget->height()); @@ -2581,9 +2583,92 @@ void Application::displaySide(Camera& whichCamera) { // brad's frustum for debugging if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum)) { - _testGeometry.begin(); renderViewFrustum(_viewFrustum); - _testGeometry.end(); + } + + // brad's voxel shader debugging + if (false) { + + const float TEST_STRIP_COLOR[] = { 0.0f, 1.0f, 0.0f }; + glColor3fv(TEST_STRIP_COLOR); + + _voxelShader.begin(); + const float VOXEL_COLOR[] = { 1.0f, 0.0f, 0.0f }; + glColor3fv(VOXEL_COLOR); + + struct VoxelData + { + float x, y, z; // position + float s; // size + unsigned char r,g,b; // color + }; + + VoxelData voxels[3]; + + //VERTEX 0 + voxels[0].x = 0.0; + voxels[0].y = 0.0; + voxels[0].z = 1.0; + voxels[0].s = 0.1; + voxels[0].r = 255; + voxels[0].g = 0; + voxels[0].b = 0; + + //VERTEX 1 + voxels[1].x = 1.0; + voxels[1].y = 0.0; + voxels[1].z = 0.0; + voxels[1].s = 0.2; + voxels[1].r = 0; + voxels[1].g = 255; + voxels[1].b = 0; + + //VERTEX 2 + voxels[2].x = 0.0; + voxels[2].y = 1.0; + voxels[2].z = 0.0; + voxels[2].s = 0.3; + voxels[2].r = 0; + voxels[2].g = 0; + voxels[2].b = 255; + + GLuint VertexVBOID; + GLuint IndexVBOID; + + glGenBuffers(1, &VertexVBOID); + glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID); + glBufferData(GL_ARRAY_BUFFER, sizeof(voxels), &voxels[0].x, GL_STATIC_DRAW); + + ushort indices[3]; + indices[0] = 0; + indices[1] = 1; + indices[2] = 2; + + glGenBuffers(1, &IndexVBOID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); + + //Define this somewhere in your header file + #define BUFFER_OFFSET(i) ((void*)(i)) + + glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(VoxelData), BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices + int loc = _voxelShader.attributeLocation("voxelSizeIn"); + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc, 1, GL_FLOAT, false, sizeof(VoxelData), BUFFER_OFFSET(3*sizeof(float))); + + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelData), BUFFER_OFFSET(4*sizeof(float)));//The starting point of colors + + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID); + glDrawElements(GL_POINTS, 3, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0)); //The starting point of the IBO + + glDeleteBuffers(1, &VertexVBOID); + glDeleteBuffers(1, &IndexVBOID); + + _voxelShader.end(); } // render voxel fades if they exist diff --git a/interface/src/Application.h b/interface/src/Application.h index 690dbc154c..0860d9057a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -51,7 +51,7 @@ #include "renderer/AmbientOcclusionEffect.h" #include "renderer/GeometryCache.h" #include "renderer/GlowEffect.h" -#include "renderer/TestGeometry.h" +#include "renderer/VoxelShader.h" #include "renderer/TextureCache.h" #include "ui/BandwidthDialog.h" #include "ui/ChatEntry.h" @@ -143,6 +143,8 @@ public: virtual void nodeAdded(Node* node); virtual void nodeKilled(Node* node); virtual void packetSentNotification(ssize_t length); + + VoxelShader& getVoxelShader() { return _voxelShader; } public slots: void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data); @@ -343,7 +345,7 @@ private: GlowEffect _glowEffect; AmbientOcclusionEffect _ambientOcclusionEffect; - TestGeometry _testGeometry; + VoxelShader _voxelShader; #ifndef _WIN32 Audio _audio; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 560f72807b..6f385c3e99 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -188,50 +188,36 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Fullscreen, - Qt::Key_F, + Qt::CTRL | Qt::META | Qt::Key_F, false, appInstance, SLOT(setFullscreen(bool))); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson, Qt::Key_P, true); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::Key_H); - addActionToQMenuAndActionHash(viewMenu, + QMenu* avatarSizeMenu = viewMenu->addMenu("Avatar Size"); + + addActionToQMenuAndActionHash(avatarSizeMenu, MenuOption::IncreaseAvatarSize, Qt::Key_Plus, appInstance->getAvatar(), SLOT(increaseSize())); - addActionToQMenuAndActionHash(viewMenu, + addActionToQMenuAndActionHash(avatarSizeMenu, MenuOption::DecreaseAvatarSize, Qt::Key_Minus, appInstance->getAvatar(), SLOT(decreaseSize())); - addActionToQMenuAndActionHash(viewMenu, + addActionToQMenuAndActionHash(avatarSizeMenu, MenuOption::ResetAvatarSize, 0, appInstance->getAvatar(), SLOT(resetSize())); - - - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::Key_H); - - addCheckableActionToQMenuAndActionHash(viewMenu, - MenuOption::SkeletonTracking, - 0, - false, - appInstance->getWebcam(), - SLOT(setSkeletonTrackingOn(bool))); - - addCheckableActionToQMenuAndActionHash(viewMenu, - MenuOption::LEDTracking, - 0, - false, - appInstance->getWebcam()->getGrabber(), - SLOT(setLEDTrackingOn(bool))); - + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::OffAxisProjection, 0, false); - + addDisabledActionAndSeparator(viewMenu, "Stats"); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Slash); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L); @@ -241,50 +227,119 @@ Menu::Menu() : addActionToQMenuAndActionHash(viewMenu, MenuOption::VoxelStats, 0, this, SLOT(voxelStatsDetails())); QMenu* developerMenu = addMenu("Developer"); - addDisabledActionAndSeparator(developerMenu, "Rendering"); - - addCheckableActionToQMenuAndActionHash(developerMenu, + + QMenu* renderOptionsMenu = developerMenu->addMenu("Rendering Options"); + + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars, Qt::Key_Asterisk, true); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, Qt::SHIFT | Qt::Key_A, true); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::GroundPlane, 0, true); + addActionToQMenuAndActionHash(renderOptionsMenu, + MenuOption::GlowMode, + 0, + appInstance->getGlowEffect(), + SLOT(cycleRenderMode())); + + QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxel Options"); + + addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::Voxels, Qt::SHIFT | Qt::Key_V, true, appInstance, SLOT(setRenderVoxels(bool))); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::VoxelTextures); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::AmbientOcclusion); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stars, 0, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Atmosphere, Qt::SHIFT | Qt::Key_A, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::GroundPlane, 0, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Avatars, 0, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::AvatarAsBalls); + addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures); + addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion); + addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseVoxelShader); - addActionToQMenuAndActionHash(developerMenu, + QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options"); + + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Avatars, 0, true); + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::AvatarAsBalls); + + addActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::VoxelMode, 0, appInstance->getAvatar()->getVoxels(), SLOT(cycleMode())); - addActionToQMenuAndActionHash(developerMenu, + addActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::FaceMode, 0, &appInstance->getAvatar()->getHead().getFace(), SLOT(cycleRenderMode())); - addActionToQMenuAndActionHash(developerMenu, - MenuOption::GlowMode, + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::UsePerlinFace, 0, false); + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::LookAtVectors, 0, true); + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::LookAtIndicator, 0, true); + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, + MenuOption::FaceshiftTCP, + 0, + false, + appInstance->getFaceshift(), + SLOT(setTCPEnabled(bool))); + + QMenu* webcamOptionsMenu = developerMenu->addMenu("Webcam Options"); + + addCheckableActionToQMenuAndActionHash(webcamOptionsMenu, + MenuOption::Webcam, + 0, + false, + appInstance->getWebcam(), + SLOT(setEnabled(bool))); + + addActionToQMenuAndActionHash(webcamOptionsMenu, + MenuOption::WebcamMode, 0, - appInstance->getGlowEffect(), - SLOT(cycleRenderMode())); + appInstance->getWebcam()->getGrabber(), + SLOT(cycleVideoSendMode())); + + addCheckableActionToQMenuAndActionHash(webcamOptionsMenu, + MenuOption::WebcamTexture, + 0, + false, + appInstance->getWebcam()->getGrabber(), + SLOT(setDepthOnly(bool))); + + QMenu* raveGloveOptionsMenu = developerMenu->addMenu("Rave Glove Options"); + + addCheckableActionToQMenuAndActionHash(raveGloveOptionsMenu, MenuOption::SimulateLeapHand); + addCheckableActionToQMenuAndActionHash(raveGloveOptionsMenu, MenuOption::TestRaveGlove); + + + QMenu* gyroOptionsMenu = developerMenu->addMenu("Gyro Options"); + addCheckableActionToQMenuAndActionHash(gyroOptionsMenu, MenuOption::GyroLook, 0, true); + addCheckableActionToQMenuAndActionHash(gyroOptionsMenu, MenuOption::HeadMouse); + + + QMenu* trackingOptionsMenu = developerMenu->addMenu("Tracking Options"); + addCheckableActionToQMenuAndActionHash(trackingOptionsMenu, + MenuOption::SkeletonTracking, + 0, + false, + appInstance->getWebcam(), + SLOT(setSkeletonTrackingOn(bool))); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::UsePerlinFace, 0, false); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::LookAtVectors, 0, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::LookAtIndicator, 0, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::FrameTimer); + addCheckableActionToQMenuAndActionHash(trackingOptionsMenu, + MenuOption::LEDTracking, + 0, + false, + appInstance->getWebcam()->getGrabber(), + SLOT(setLEDTrackingOn(bool))); addDisabledActionAndSeparator(developerMenu, "Testing"); + + QMenu* timingMenu = developerMenu->addMenu("Timing and Statistics Tools"); + addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::TestPing, 0, true); + addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::FrameTimer); + addActionToQMenuAndActionHash(timingMenu, MenuOption::RunTimingTests, 0, this, SLOT(runTests())); + addActionToQMenuAndActionHash(timingMenu, + MenuOption::TreeStats, + Qt::SHIFT | Qt::Key_S, + appInstance->getVoxels(), + SLOT(collectStatsForTreesAndVBOs())); QMenu* frustumMenu = developerMenu->addMenu("View Frustum Debugging Tools"); addCheckableActionToQMenuAndActionHash(frustumMenu, MenuOption::DisplayFrustum, Qt::SHIFT | Qt::Key_F); - addActionToQMenuAndActionHash(frustumMenu, MenuOption::FrustumRenderMode, Qt::SHIFT | Qt::Key_R, @@ -292,12 +347,6 @@ Menu::Menu() : SLOT(cycleFrustumRenderMode())); updateFrustumRenderModeAction(); - addActionToQMenuAndActionHash(developerMenu, MenuOption::RunTimingTests, 0, this, SLOT(runTests())); - addActionToQMenuAndActionHash(developerMenu, - MenuOption::TreeStats, - Qt::SHIFT | Qt::Key_S, - appInstance->getVoxels(), - SLOT(collectStatsForTreesAndVBOs())); QMenu* renderDebugMenu = developerMenu->addMenu("Render Debugging Tools"); addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::PipelineWarnings); @@ -337,18 +386,6 @@ Menu::Menu() : appInstance->getVoxels(), SLOT(falseColorizeInView())); - addActionToQMenuAndActionHash(renderDebugMenu, - MenuOption::FalseColorOccluded, - 0, - appInstance->getVoxels(), - SLOT(falseColorizeOccluded())); - - addActionToQMenuAndActionHash(renderDebugMenu, - MenuOption::FalseColorOccludedV2, - 0, - appInstance->getVoxels(), - SLOT(falseColorizeOccludedV2())); - addActionToQMenuAndActionHash(renderDebugMenu, MenuOption::FalseColorBySource, 0, @@ -361,32 +398,21 @@ Menu::Menu() : appInstance->getVoxels(), SLOT(trueColorize())); - - addCheckableActionToQMenuAndActionHash(developerMenu, - MenuOption::Webcam, - 0, - false, - appInstance->getWebcam(), - SLOT(setEnabled(bool))); - - addActionToQMenuAndActionHash(developerMenu, - MenuOption::WebcamMode, + addDisabledActionAndSeparator(renderDebugMenu, "Coverage Maps"); + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::FalseColorOccluded, 0, - appInstance->getWebcam()->getGrabber(), - SLOT(cycleVideoSendMode())); - addCheckableActionToQMenuAndActionHash(developerMenu, - MenuOption::WebcamTexture, - 0, - false, - appInstance->getWebcam()->getGrabber(), - SLOT(setDepthOnly(bool))); + appInstance->getVoxels(), + SLOT(falseColorizeOccluded())); - addCheckableActionToQMenuAndActionHash(developerMenu, - MenuOption::FaceshiftTCP, - 0, - false, - appInstance->getFaceshift(), - SLOT(setTCPEnabled(bool))); + addActionToQMenuAndActionHash(renderDebugMenu, + MenuOption::FalseColorOccludedV2, + 0, + appInstance->getVoxels(), + SLOT(falseColorizeOccludedV2())); + + addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::CoverageMap, Qt::SHIFT | Qt::CTRL | Qt::Key_O); + addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::CoverageMapV2, Qt::SHIFT | Qt::CTRL | Qt::Key_P); QMenu* audioDebugMenu = developerMenu->addMenu("Audio Debugging Tools"); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoAudio); @@ -406,47 +432,38 @@ Menu::Menu() : appInstance, SLOT(setListenModeSingleSource())); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::TestPing, 0, true); + QMenu* voxelProtoOptionsMenu = developerMenu->addMenu("Voxel Server Protocol Options"); - addCheckableActionToQMenuAndActionHash(developerMenu, + addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::SendVoxelColors, 0, true, appInstance->getAvatar(), SLOT(setWantColor(bool))); - addCheckableActionToQMenuAndActionHash(developerMenu, + addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::LowRes, 0, true, appInstance->getAvatar(), SLOT(setWantLowResMoving(bool))); - addCheckableActionToQMenuAndActionHash(developerMenu, + addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::DeltaSending, 0, true, appInstance->getAvatar(), SLOT(setWantDelta(bool))); - addCheckableActionToQMenuAndActionHash(developerMenu, + addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::OcclusionCulling, Qt::SHIFT | Qt::Key_C, true, appInstance->getAvatar(), SLOT(setWantOcclusionCulling(bool))); - - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::CoverageMap, Qt::SHIFT | Qt::CTRL | Qt::Key_O); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::CoverageMapV2, Qt::SHIFT | Qt::CTRL | Qt::Key_P); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::SimulateLeapHand); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::TestRaveGlove); - - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::GyroLook, 0, true); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::HeadMouse); - - addDisabledActionAndSeparator(developerMenu, "Voxels"); - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::DestructiveAddVoxel); + addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::DestructiveAddVoxel); + #ifndef Q_OS_MAC QMenu* helpMenu = addMenu("Help"); QAction* helpAction = helpMenu->addAction(MenuOption::AboutApp); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 78ef65221c..a30fc4cdb0 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -201,9 +201,7 @@ namespace MenuOption { const QString TransmitterDrive = "Transmitter Drive"; const QString UsePerlinFace = "Use Perlin's Face"; const QString Quit = "Quit"; - const QString Webcam = "Webcam"; - const QString WebcamMode = "Cycle Webcam Send Mode"; - const QString WebcamTexture = "Webcam Texture"; + const QString UseVoxelShader = "Use Voxel Shader"; const QString Voxels = "Voxels"; const QString VoxelAddMode = "Add Voxel Mode"; const QString VoxelColorMode = "Color Voxel Mode"; @@ -214,6 +212,9 @@ namespace MenuOption { const QString VoxelSelectMode = "Select Voxel Mode"; const QString VoxelStats = "Voxel Stats"; const QString VoxelTextures = "Voxel Textures"; + const QString Webcam = "Webcam"; + const QString WebcamMode = "Cycle Webcam Send Mode"; + const QString WebcamTexture = "Webcam Texture"; } #endif /* defined(__hifi__Menu__) */ diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index a1595f0de0..759a2f178a 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -74,6 +74,19 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float))); connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int))); + + _voxelShaderInitialized = false; + _initializingVoxelShader = false; + _writeVoxelShaderData = NULL; + _readVoxelShaderData = NULL; + + _readVerticesArray = NULL; + _writeVerticesArray = NULL; + _readColorsArray = NULL; + _writeColorsArray = NULL; + _writeVoxelDirtyArray = NULL; + _readVoxelDirtyArray = NULL; + } void VoxelSystem::nodeDeleted(VoxelNode* node) { @@ -125,13 +138,20 @@ VoxelSystem::~VoxelSystem() { glDeleteBuffers(1, &_vboNormalsID); glDeleteBuffers(1, &_vboColorsID); glDeleteBuffers(1, &_vboIndicesID); - + delete[] _readVerticesArray; delete[] _writeVerticesArray; delete[] _readColorsArray; delete[] _writeColorsArray; delete[] _writeVoxelDirtyArray; delete[] _readVoxelDirtyArray; + + // these are used when in VoxelShader mode. + glDeleteBuffers(1, &_vboVoxelsID); + glDeleteBuffers(1, &_vboVoxelsIndicesID); + + delete[] _writeVoxelShaderData; + delete[] _readVoxelShaderData; } delete _tree; @@ -141,6 +161,45 @@ VoxelSystem::~VoxelSystem() { VoxelNode::removeDeleteHook(this); } +bool VoxelSystem::getUseVoxelShader() { + bool useVoxelShader = false; //Menu::getInstance()->isOptionChecked(MenuOption::UseVoxelShader); + + return useVoxelShader; +} + +void VoxelSystem::initVoxelShader() { + GLuint* indicesArray = new GLuint[_maxVoxels]; + + // populate the indicesArray + // this will not change given new voxels, so we can set it all up now + for (int n = 0; n < _maxVoxels; n++) { + indicesArray[n] = n; + } + + // bind the indices VBO to the actual indices array + glGenBuffers(1, &_vboVoxelsIndicesID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, _maxVoxels, indicesArray, GL_STATIC_DRAW); + + + glGenBuffers(1, &_vboVoxelsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); + glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW); + + // delete the indices and normals arrays that are no longer needed + delete[] indicesArray; + + // we will track individual dirty sections with these arrays of bools + _writeVoxelDirtyArray = new bool[_maxVoxels]; + memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _readVoxelDirtyArray = new bool[_maxVoxels]; + memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + + // prep the data structures for incoming voxel data + _writeVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; + _readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; +} + void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) { _tree->loadVoxelsFile(fileName, wantColorRandomizer); setupNewVoxelsForDrawing(); @@ -398,18 +457,24 @@ void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() { void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd) { int segmentLength = (segmentEnd - segmentStart) + 1; + if (getUseVoxelShader()) { + GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData); + void* readDataAt = &_readVoxelShaderData[segmentStart]; + void* writeDataAt = &_writeVoxelShaderData[segmentStart]; + memcpy(readDataAt, writeDataAt, segmentSizeBytes); + } else { + GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); + GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); + GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes); - GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes); - - segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - GLubyte* readColorsAt = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - memcpy(readColorsAt, writeColorsAt, segmentSizeBytes); + segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); + segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); + GLubyte* readColorsAt = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + memcpy(readColorsAt, writeColorsAt, segmentSizeBytes); + } } void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) { @@ -532,11 +597,29 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) { void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex, float voxelScale, const nodeColor& color) { - for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { - GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); - *(writeColorsAt +j) = color[j % 3]; + + if (getUseVoxelShader()) { + VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex]; + writeVerticesAt->x = startVertex.x * TREE_SCALE; + writeVerticesAt->y = startVertex.y * TREE_SCALE; + writeVerticesAt->z = startVertex.z * TREE_SCALE; + writeVerticesAt->s = voxelScale * TREE_SCALE; + writeVerticesAt->r = color[RED_INDEX]; + writeVerticesAt->g = color[GREEN_INDEX]; + writeVerticesAt->b = color[BLUE_INDEX]; + + /** + printf("updateNodeInArrays() nodeIndex=%lu writeVerticesAt=[%f,%f,%f,%f (%u,%u,%u)]\n", + nodeIndex, writeVerticesAt->x, writeVerticesAt->y, writeVerticesAt->z, writeVerticesAt->s, + writeVerticesAt->r, writeVerticesAt->g, writeVerticesAt->b ); + **/ + } else { + for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { + GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); + GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); + *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); + *(writeColorsAt +j) = color[j % 3]; + } } } @@ -563,85 +646,89 @@ void VoxelSystem::init() { _voxelsInWriteArrays = 0; _voxelsInReadArrays = 0; - GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels]; - - // populate the indicesArray - // this will not change given new voxels, so we can set it all up now - for (int n = 0; n < _maxVoxels; n++) { - // fill the indices array - int voxelIndexOffset = n * INDICES_PER_VOXEL; - GLuint* currentIndicesPos = indicesArray + voxelIndexOffset; - int startIndex = (n * VERTICES_PER_VOXEL); - - for (int i = 0; i < INDICES_PER_VOXEL; i++) { - // add indices for this side of the cube - currentIndicesPos[i] = startIndex + identityIndices[i]; - } - } - - GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - GLfloat* normalsArrayEndPointer = normalsArray; - - // populate the normalsArray - for (int n = 0; n < _maxVoxels; n++) { - for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) { - *(normalsArrayEndPointer++) = identityNormals[i]; - } - } - // VBO for the verticesArray - glGenBuffers(1, &_vboVerticesID); - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + //initVoxelShader(); - // VBO for the normalsArray - glGenBuffers(1, &_vboNormalsID); - glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); - glBufferData(GL_ARRAY_BUFFER, - VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, - normalsArray, GL_STATIC_DRAW); + if (true) { + GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels]; - // VBO for colorsArray - glGenBuffers(1, &_vboColorsID); - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + // populate the indicesArray + // this will not change given new voxels, so we can set it all up now + for (int n = 0; n < _maxVoxels; n++) { + // fill the indices array + int voxelIndexOffset = n * INDICES_PER_VOXEL; + GLuint* currentIndicesPos = indicesArray + voxelIndexOffset; + int startIndex = (n * VERTICES_PER_VOXEL); - // VBO for the indicesArray - glGenBuffers(1, &_vboIndicesID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, - INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels, - indicesArray, GL_STATIC_DRAW); + for (int i = 0; i < INDICES_PER_VOXEL; i++) { + // add indices for this side of the cube + currentIndicesPos[i] = startIndex + identityIndices[i]; + } + } - // delete the indices and normals arrays that are no longer needed - delete[] indicesArray; - delete[] normalsArray; + GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + GLfloat* normalsArrayEndPointer = normalsArray; + + // populate the normalsArray + for (int n = 0; n < _maxVoxels; n++) { + for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) { + *(normalsArrayEndPointer++) = identityNormals[i]; + } + } + + glGenBuffers(1, &_vboVerticesID); + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + + // VBO for the normalsArray + glGenBuffers(1, &_vboNormalsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); + glBufferData(GL_ARRAY_BUFFER, + VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, + normalsArray, GL_STATIC_DRAW); + + // VBO for colorsArray + glGenBuffers(1, &_vboColorsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + + // VBO for the indicesArray + glGenBuffers(1, &_vboIndicesID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, + INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels, + indicesArray, GL_STATIC_DRAW); + + // delete the indices and normals arrays that are no longer needed + delete[] indicesArray; + delete[] normalsArray; - // we will track individual dirty sections with these arrays of bools - _writeVoxelDirtyArray = new bool[_maxVoxels]; - memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); - _readVoxelDirtyArray = new bool[_maxVoxels]; - memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + // we will track individual dirty sections with these arrays of bools + _writeVoxelDirtyArray = new bool[_maxVoxels]; + memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _readVoxelDirtyArray = new bool[_maxVoxels]; + memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); - // prep the data structures for incoming voxel data - _writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - _readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + // prep the data structures for incoming voxel data + _writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - _writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - _readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - // create our simple fragment shader if we're the first system to init - if (!_perlinModulateProgram.isLinked()) { - switchToResourcesParentIfRequired(); - _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/perlin_modulate.vert"); - _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/perlin_modulate.frag"); - _perlinModulateProgram.link(); + // create our simple fragment shader if we're the first system to init + if (!_perlinModulateProgram.isLinked()) { + switchToResourcesParentIfRequired(); + _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/perlin_modulate.vert"); + _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/perlin_modulate.frag"); + _perlinModulateProgram.link(); - _perlinModulateProgram.bind(); - _perlinModulateProgram.setUniformValue("permutationNormalTexture", 0); - _perlinModulateProgram.release(); + _perlinModulateProgram.bind(); + _perlinModulateProgram.setUniformValue("permutationNormalTexture", 0); + _perlinModulateProgram.release(); + } } _initialized = true; } @@ -714,17 +801,34 @@ void VoxelSystem::updateVBOs() { } void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd) { - int segmentLength = (segmentEnd - segmentStart) + 1; - GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); - segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); + if (getUseVoxelShader()) { + int segmentLength = (segmentEnd - segmentStart) + 1; + GLintptr segmentStartAt = segmentStart * sizeof(VoxelShaderVBOData); + GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData); + void* readVerticesFrom = &_readVoxelShaderData[segmentStart]; + + glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); + glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); + } else { + int segmentLength = (segmentEnd - segmentStart) + 1; + GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); + GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); + GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); + glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); +//printf("VoxelSystem::updateVBOSegment() segmentStart=%lu, segmentEnd=%lu, segmentSizeBytes=%lu \n", +// segmentStart, segmentEnd, segmentSizeBytes); + + + segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); + segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); + GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); + glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); + +//printf("VoxelSystem::updateVBOSegment() segmentStart=%lu, segmentEnd=%lu, segmentSizeBytes=%lu \n", +// segmentStart, segmentEnd, segmentSizeBytes); + } } void VoxelSystem::render(bool texture) { @@ -734,43 +838,85 @@ void VoxelSystem::render(bool texture) { pthread_mutex_lock(&_bufferWriteLock); updateVBOs(); + + //printf("render() _voxelsInReadArrays=%lu voxel shader=%s\n", _voxelsInReadArrays, debug::valueOf(getUseVoxelShader())); - // tell OpenGL where to find vertex and color information - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glVertexPointer(3, GL_FLOAT, 0, 0); - - glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); - glNormalPointer(GL_FLOAT, 0, 0); - - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); - - applyScaleAndBindProgram(texture); + if (getUseVoxelShader()) { - // for performance, enable backface culling - glEnable(GL_CULL_FACE); + Application::getInstance()->getVoxelShader().begin(); - // draw the number of voxels we have - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); - glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTICES_PER_VOXEL * _voxelsInReadArrays - 1, - 36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); + //Define this somewhere in your header file + #define BUFFER_OFFSET(i) ((void*)(i)) - glDisable(GL_CULL_FACE); + glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices + int loc = Application::getInstance()->getVoxelShader().attributeLocation("voxelSizeIn"); + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc, 1, GL_FLOAT, false, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(3*sizeof(float))); + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(4*sizeof(float)));//The starting point of colors - removeScaleAndReleaseProgram(texture); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID); + glDrawElements(GL_POINTS, _voxelsInReadArrays, GL_UNSIGNED_INT, BUFFER_OFFSET(0)); //The starting point of the IBO + + /** + for (int i=0; i < _voxelsInReadArrays; i++) { + VoxelShaderVBOData* readDataAt = &_readVoxelShaderData[i]; + printf("render() _voxelsInReadArrays=%lu i=%d readDataAt=[%f,%f,%f,%f (%u,%u,%u)]\n", + _voxelsInReadArrays, i, readDataAt->x, readDataAt->y, readDataAt->z, readDataAt->s, + readDataAt->r, readDataAt->g, readDataAt->b ); + } + **/ + + // deactivate vertex and color arrays after drawing + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + // bind with 0 to switch back to normal operation + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + Application::getInstance()->getVoxelShader().end(); + + } else { + // tell OpenGL where to find vertex and color information + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); + glVertexPointer(3, GL_FLOAT, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); + glNormalPointer(GL_FLOAT, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); + glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); + + applyScaleAndBindProgram(texture); - // deactivate vertex and color arrays after drawing - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); + // for performance, enable backface culling + glEnable(GL_CULL_FACE); - // bind with 0 to switch back to normal operation - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + // draw the number of voxels we have + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); + glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTICES_PER_VOXEL * _voxelsInReadArrays - 1, + 36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); + + glDisable(GL_CULL_FACE); + + removeScaleAndReleaseProgram(texture); + + // deactivate vertex and color arrays after drawing + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + // bind with 0 to switch back to normal operation + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } pthread_mutex_unlock(&_bufferWriteLock); } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 5ac5310b76..fe088ce042 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -23,11 +23,20 @@ #include "Camera.h" #include "Util.h" #include "world.h" +#include "renderer/VoxelShader.h" class ProgramObject; const int NUM_CHILDREN = 8; +struct VoxelShaderVBOData +{ + float x, y, z; // position + float s; // size + unsigned char r,g,b; // color +}; + + class VoxelSystem : public NodeData, public VoxelNodeDeleteHook, public NodeListHook { Q_OBJECT public: @@ -190,6 +199,15 @@ private: uint64_t _lastViewCulling; int _lastViewCullingElapsed; + bool getUseVoxelShader(); + void initVoxelShader(); + bool _voxelShaderInitialized; + bool _initializingVoxelShader; + GLuint _vboVoxelsID; /// when using voxel shader, we'll use this VBO + GLuint _vboVoxelsIndicesID; /// when using voxel shader, we'll use this VBO for our indexes + VoxelShaderVBOData* _writeVoxelShaderData; + VoxelShaderVBOData* _readVoxelShaderData; + GLuint _vboVerticesID; GLuint _vboNormalsID; GLuint _vboColorsID; diff --git a/interface/src/renderer/TestGeometry.h b/interface/src/renderer/TestGeometry.h deleted file mode 100644 index cec13196b0..0000000000 --- a/interface/src/renderer/TestGeometry.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// TestGeometry.h -// interface -// -// Created by Andrzej Kapolka on 8/7/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#ifndef __interface__TestGeometry__ -#define __interface__TestGeometry__ - -#include -#include - -class QOpenGLFramebufferObject; - -class ProgramObject; - -/// A generic full screen glow effect. -class TestGeometry : public QObject { - Q_OBJECT - -public: - TestGeometry(); - ~TestGeometry(); - - void init(); - - /// Starts using the geometry shader effect. - void begin(); - - /// Stops using the geometry shader effect. - void end(); - -public slots: - -private: - - bool _initialized; - - ProgramObject* _testProgram; -}; - -#endif /* defined(__interface__TestGeometry__) */ diff --git a/interface/src/renderer/TestGeometry.cpp b/interface/src/renderer/VoxelShader.cpp similarity index 50% rename from interface/src/renderer/TestGeometry.cpp rename to interface/src/renderer/VoxelShader.cpp index e30a210dde..b8a907c917 100644 --- a/interface/src/renderer/TestGeometry.cpp +++ b/interface/src/renderer/VoxelShader.cpp @@ -1,5 +1,5 @@ // -// TestGeometry.cpp +// VoxelShader.cpp // interface // // Created by Brad Hefta-Gaub on 9/22/13. @@ -11,55 +11,59 @@ #include #include "Application.h" -#include "TestGeometry.h" +#include "VoxelShader.h" #include "ProgramObject.h" #include "RenderUtil.h" -TestGeometry::TestGeometry() +VoxelShader::VoxelShader() : _initialized(false) { + _program = NULL; } -TestGeometry::~TestGeometry() { +VoxelShader::~VoxelShader() { if (_initialized) { - delete _testProgram; + delete _program; } } -static ProgramObject* createGeometryShaderProgram(const QString& name) { +ProgramObject* VoxelShader::createGeometryShaderProgram(const QString& name) { ProgramObject* program = new ProgramObject(); program->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/passthrough.vert" ); - - program->addShaderFromSourceFile(QGLShader::Geometry, "resources/shaders/" + name + ".geom" ); - - program->setGeometryInputType(GL_LINES); - program->setGeometryOutputType(GL_LINE_STRIP); - program->setGeometryOutputVertexCount(100); // hack? - + program->setGeometryInputType(GL_POINTS); + program->setGeometryOutputType(GL_TRIANGLE_STRIP); + const int VERTICES_PER_FACE = 4; + const int FACES_PER_VOXEL = 6; + const int VERTICES_PER_VOXEL = VERTICES_PER_FACE * FACES_PER_VOXEL; + program->setGeometryOutputVertexCount(VERTICES_PER_VOXEL); program->link(); - //program->log(); - return program; } -void TestGeometry::init() { +void VoxelShader::init() { if (_initialized) { qDebug("[ERROR] TestProgram is already initialized.\n"); return; } - switchToResourcesParentIfRequired(); - - _testProgram = createGeometryShaderProgram("passthrough"); + _program = createGeometryShaderProgram("voxel"); _initialized = true; } -void TestGeometry::begin() { - _testProgram->bind(); +void VoxelShader::begin() { + _program->bind(); } -void TestGeometry::end() { - _testProgram->release(); +void VoxelShader::end() { + _program->release(); +} + +int VoxelShader::attributeLocation(const char * name) const { + if (_program) { + return _program->attributeLocation(name); + } else { + return -1; + } } diff --git a/interface/src/renderer/VoxelShader.h b/interface/src/renderer/VoxelShader.h new file mode 100644 index 0000000000..33e8ea0073 --- /dev/null +++ b/interface/src/renderer/VoxelShader.h @@ -0,0 +1,46 @@ +// +// VoxelShader.h +// interface +// +// Created by Brad Hefta-Gaub on 9/23/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__VoxelShader__ +#define __interface__VoxelShader__ + +#include + +class ProgramObject; + +/// A generic full screen glow effect. +class VoxelShader : public QObject { + Q_OBJECT + +public: + VoxelShader(); + ~VoxelShader(); + + void init(); + + /// Starts using the voxel geometry shader effect. + void begin(); + + /// Stops using the voxel geometry shader effect. + void end(); + + /// Gets access to attributes from the shader program + int attributeLocation(const char * name) const; + + static ProgramObject* createGeometryShaderProgram(const QString& name); + +public slots: + +private: + + bool _initialized; + + ProgramObject* _program; +}; + +#endif /* defined(__interface__VoxelShader__) */