From 1f307e9667ae8c033e4d2dcec9605bc248d14c77 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 23 Dec 2014 09:50:38 -0800 Subject: [PATCH] more work on removing immediate mode GL_QUADS --- interface/src/ui/ApplicationOverlay.cpp | 49 +++---- .../src/ui/overlays/Rectangle3DOverlay.cpp | 12 +- interface/src/ui/overlays/Text3DOverlay.cpp | 9 +- .../src/RenderableTextEntityItem.cpp | 11 +- libraries/render-utils/src/GeometryCache.cpp | 138 ++++++++++++++++++ libraries/render-utils/src/GeometryCache.h | 28 ++++ 6 files changed, 195 insertions(+), 52 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index a34584b24c..079cb8c803 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -106,23 +106,14 @@ bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, } void renderReticle(glm::quat orientation, float alpha) { - glm::vec3 topLeft = getPoint(reticleSize / 2.0f, -reticleSize / 2.0f); - glm::vec3 topRight = getPoint(-reticleSize / 2.0f, -reticleSize / 2.0f); - glm::vec3 bottomLeft = getPoint(reticleSize / 2.0f, reticleSize / 2.0f); - glm::vec3 bottomRight = getPoint(-reticleSize / 2.0f, reticleSize / 2.0f); - glPushMatrix(); { glm::vec3 axis = glm::axis(orientation); glRotatef(glm::degrees(glm::angle(orientation)), axis.x, axis.y, axis.z); - - glBegin(GL_QUADS); { - glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], alpha); - - glTexCoord2f(0.0f, 0.0f); glVertex3f(topLeft.x, topLeft.y, topLeft.z); - glTexCoord2f(1.0f, 0.0f); glVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); - glTexCoord2f(1.0f, 1.0f); glVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); - glTexCoord2f(0.0f, 1.0f); glVertex3f(topRight.x, topRight.y, topRight.z); - } glEnd(); + glm::vec3 topLeft = getPoint(reticleSize / 2.0f, -reticleSize / 2.0f); + glm::vec3 bottomRight = getPoint(-reticleSize / 2.0f, reticleSize / 2.0f); + glm::vec2 texCoordTopLeft(0.0f, 0.0f); + glm::vec2 texCoordBottomRight(1.0f, 1.0f); + DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight); } glPopMatrix(); } @@ -371,15 +362,12 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as GLfloat x = -halfQuadWidth; GLfloat y = -halfQuadHeight; glDisable(GL_DEPTH_TEST); - - glBegin(GL_QUADS); - - glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + quadHeight, -distance); - glTexCoord2f(1.0f, 1.0f); glVertex3f(x + quadWidth, y + quadHeight, -distance); - glTexCoord2f(1.0f, 0.0f); glVertex3f(x + quadWidth, y, -distance); - glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, -distance); - - glEnd(); + + glm::vec3 topLeft(x, y + quadHeight, -distance); + glm::vec3 bottomRight(x + quadWidth, y, -distance); + glm::vec2 texCoordTopLeft(0.0f, 1.0f); + glm::vec2 texCoordBottomRight(1.0f, 0.0f); + DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight); GLCanvas::SharedPointer glCanvas = DependencyManager::get(); if (_crosshairTexture == 0) { @@ -395,16 +383,13 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as const float mouseX = (application->getMouseX() / (float)glCanvas->width()) * quadWidth; const float mouseY = (1.0 - (application->getMouseY() / (float)glCanvas->height())) * quadHeight; - glBegin(GL_QUADS); - glColor3f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2]); - - glTexCoord2d(0.0f, 0.0f); glVertex3f(x + mouseX, y + mouseY, -distance); - glTexCoord2d(1.0f, 0.0f); glVertex3f(x + mouseX + reticleSize, y + mouseY, -distance); - glTexCoord2d(1.0f, 1.0f); glVertex3f(x + mouseX + reticleSize, y + mouseY - reticleSize, -distance); - glTexCoord2d(0.0f, 1.0f); glVertex3f(x + mouseX, y + mouseY - reticleSize, -distance); - - glEnd(); + + glm::vec3 reticleTopLeft(x + mouseX, y + mouseY, -distance); + glm::vec3 reticleBottomRight(x + mouseX + reticleSize, y + mouseY - reticleSize, -distance); + glm::vec2 reticleTexCoordTopLeft(0.0f, 0.0f); + glm::vec2 reticleTexCoordBottomRight(1.0f, 1.0f); + DependencyManager::get()->renderQuad(reticleTopLeft, reticleBottomRight, reticleTexCoordTopLeft, reticleTexCoordBottomRight); glEnable(GL_DEPTH_TEST); diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp index 8e8c17743d..c315723798 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ b/interface/src/ui/overlays/Rectangle3DOverlay.cpp @@ -13,6 +13,7 @@ #include +#include #include #include @@ -66,14 +67,9 @@ void Rectangle3DOverlay::render(RenderArgs* args) { // for our overlay, is solid means we draw a solid "filled" rectangle otherwise we just draw a border line... if (getIsSolid()) { - glBegin(GL_QUADS); - - glVertex3f(-halfDimensions.x, 0.0f, -halfDimensions.y); - glVertex3f(halfDimensions.x, 0.0f, -halfDimensions.y); - glVertex3f(halfDimensions.x, 0.0f, halfDimensions.y); - glVertex3f(-halfDimensions.x, 0.0f, halfDimensions.y); - - glEnd(); + glm::vec3 topLeft(-halfDimensions.x, 0.0f, -halfDimensions.y); + glm::vec3 bottomRight(halfDimensions.x, 0.0f, halfDimensions.y); + DependencyManager::get()->renderQuad(topLeft, bottomRight); } else { if (getIsDashedLine()) { diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 9b80d873f9..92f6350936 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -100,12 +100,9 @@ void Text3DOverlay::render(RenderArgs* args) { const float SLIGHTLY_BEHIND = -0.005f; - glBegin(GL_QUADS); - glVertex3f(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); - glVertex3f(halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); - glVertex3f(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); - glVertex3f(-halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); - glEnd(); + glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); + glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); + DependencyManager::get()->renderQuad(topLeft, bottomRight); const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 40.0f; // this is a ratio determined through experimentation diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 24f4a71295..76431b55bc 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -12,6 +12,8 @@ #include #include + +#include #include #include @@ -51,12 +53,9 @@ void RenderableTextEntityItem::render(RenderArgs* args) { const float SLIGHTLY_BEHIND = -0.005f; - glBegin(GL_QUADS); - glVertex3f(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); - glVertex3f(halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); - glVertex3f(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); - glVertex3f(-halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); - glEnd(); + glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); + glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); + DependencyManager::get()->renderQuad(topLeft, bottomRight); const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 40.0f; // this is a ratio determined through experimentation diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index f6ea9247ce..391543acfd 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -787,6 +787,144 @@ void GeometryCache::renderQuad(const glm::vec2& topLeft, const glm::vec2& bottom glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } +void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomRight) { + Vec3Pair key(topLeft, bottomRight); + VerticesIndices& vbo = _quad3DVBOs[key]; + const int FLOATS_PER_VERTEX = 3; + const int NUM_BYTES_PER_VERTEX = FLOATS_PER_VERTEX * sizeof(GLfloat); + const int vertices = 4; + const int indices = 4; + if (vbo.first == 0) { + int vertexPoints = vertices * FLOATS_PER_VERTEX; + GLfloat* vertexData = new GLfloat[vertexPoints]; // only vertices + GLfloat* vertex = vertexData; + static GLubyte cannonicalIndices[indices] = { 0, 1, 2, 3 }; + int v = 0; + + vertex[v++] = topLeft.x; + vertex[v++] = topLeft.y; + vertex[v++] = topLeft.z; + + vertex[v++] = bottomRight.x; + vertex[v++] = topLeft.y; + vertex[v++] = topLeft.z; + + vertex[v++] = bottomRight.x; + vertex[v++] = bottomRight.y; + vertex[v++] = bottomRight.z; + + vertex[v++] = topLeft.x; + vertex[v++] = bottomRight.y; + vertex[v++] = bottomRight.z; + + glGenBuffers(1, &vbo.first); + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + glBufferData(GL_ARRAY_BUFFER, vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); + delete[] vertexData; + + GLushort* indexData = new GLushort[indices]; + GLushort* index = indexData; + for (int i = 0; i < indices; i++) { + index[i] = cannonicalIndices[i]; + } + + glGenBuffers(1, &vbo.second); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); + delete[] indexData; + + qDebug() << "new quad VBO made -- _quad3DVBOs.size():" << _quad3DVBOs.size(); + + } else { + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + } + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(FLOATS_PER_VERTEX, GL_FLOAT, FLOATS_PER_VERTEX * sizeof(float), 0); + glDrawRangeElementsEXT(GL_QUADS, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); + glDisableClientState(GL_VERTEX_ARRAY); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + + +void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomRight, + const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomRight) { + + Vec3PairVec2Pair key(Vec3Pair(topLeft, bottomRight), Vec2Pair(texCoordTopLeft, texCoordBottomRight)); + + VerticesIndices& vbo = _quad3DTextureVBOs[key]; + const int FLOATS_PER_VERTEX = 5; // text coords & vertices + const int NUM_BYTES_PER_VERTEX = FLOATS_PER_VERTEX * sizeof(GLfloat); + const int vertices = 4; + const int indices = 4; + if (vbo.first == 0) { + int vertexPoints = vertices * FLOATS_PER_VERTEX; + GLfloat* vertexData = new GLfloat[vertexPoints]; // text coords & vertices + GLfloat* vertex = vertexData; + static GLubyte cannonicalIndices[indices] = { 0, 1, 2, 3 }; + int v = 0; + + vertex[v++] = topLeft.x; + vertex[v++] = topLeft.y; + vertex[v++] = topLeft.z; + vertex[v++] = texCoordTopLeft.x; + vertex[v++] = texCoordTopLeft.y; + + vertex[v++] = bottomRight.x; + vertex[v++] = topLeft.y; + vertex[v++] = topLeft.z; + vertex[v++] = texCoordBottomRight.x; + vertex[v++] = texCoordTopLeft.y; + + vertex[v++] = bottomRight.x; + vertex[v++] = bottomRight.y; + vertex[v++] = bottomRight.z; + vertex[v++] = texCoordBottomRight.x; + vertex[v++] = texCoordBottomRight.y; + + vertex[v++] = topLeft.x; + vertex[v++] = bottomRight.y; + vertex[v++] = bottomRight.z; + vertex[v++] = texCoordTopLeft.x; + vertex[v++] = texCoordBottomRight.y; + + glGenBuffers(1, &vbo.first); + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + glBufferData(GL_ARRAY_BUFFER, vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); + delete[] vertexData; + + GLushort* indexData = new GLushort[indices]; + GLushort* index = indexData; + for (int i = 0; i < indices; i++) { + index[i] = cannonicalIndices[i]; + } + + glGenBuffers(1, &vbo.second); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); + delete[] indexData; + + qDebug() << "new quad + texture VBO made -- _quad3DTextureVBOs.size():" << _quad3DTextureVBOs.size(); + } else { + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(2, GL_FLOAT, NUM_BYTES_PER_VERTEX, 0); + glTexCoordPointer(2, GL_FLOAT, NUM_BYTES_PER_VERTEX, (const void *)(3 * sizeof(float))); + + glDrawRangeElementsEXT(GL_QUADS, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} QSharedPointer GeometryCache::getGeometry(const QUrl& url, const QUrl& fallback, bool delayLoad) { return getResource(url, fallback, delayLoad).staticCast(); } diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index f7971e78d6..aadbef77c5 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -34,6 +34,8 @@ class NetworkTexture; typedef QPair Vec2Pair; typedef QPair Vec2PairPair; +typedef QPair Vec3Pair; +typedef QPair Vec3PairVec2Pair; inline uint qHash(const glm::vec2& v, uint seed) { // multiply by prime numbers greater than the possible size @@ -53,6 +55,25 @@ inline uint qHash(const Vec2PairPair& v, uint seed) { + 5051 * v.second.second.x + 5059 * v.second.second.y, seed); } +inline uint qHash(const glm::vec3& v, uint seed) { + // multiply by prime numbers greater than the possible size + return qHash(v.x + 5009 * v.y + 5011 * v.z, seed); +} + +inline uint qHash(const Vec3Pair& v, uint seed) { + // multiply by prime numbers greater than the possible size + return qHash(v.first.x + 5009 * v.first.y + 5011 * v.first.z + + 5021 * v.second.x + 5023 * v.second.y + 5039 * v.second.z, seed); +} + +inline uint qHash(const Vec3PairVec2Pair& v, uint seed) { + // multiply by prime numbers greater than the possible size + return qHash(v.first.first.x + 5009 * v.first.first.y + 5011 * v.first.first.z + + 5021 * v.first.second.x + 5023 * v.first.second.y + 5039 * v.first.second.z + + 5051 * v.second.first.x + 5059 * v.second.first.y + + 5077 * v.second.second.x + 5081 * v.second.second.y, seed); +} + /// Stores cached geometry. class GeometryCache : public ResourceCache { @@ -77,6 +98,11 @@ public: const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomRight); + void renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomRight); + + void renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomRight, + const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomRight); + /// Loads geometry from the specified URL. /// \param fallback a fallback URL to load if the desired one is unavailable /// \param delayLoad if true, don't load the geometry immediately; wait until load is first requested @@ -103,6 +129,8 @@ private: QHash _solidCubeVBOs; QHash _quad2DVBOs; QHash _quad2DTextureVBOs; + QHash _quad3DVBOs; + QHash _quad3DTextureVBOs; QHash _gridBuffers;