1 /* 2 * Stellarium 3 * Copyright (C) 2016 Florian Schaukowitsch 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. 18 */ 19 20 #ifndef STELOPENGLARRAY_HPP 21 #define STELOPENGLARRAY_HPP 22 23 #include "VecMath.hpp" 24 25 #include <QLoggingCategory> 26 #include <QOpenGLBuffer> 27 #include <QOpenGLFunctions> 28 #include <QOpenGLVertexArrayObject> 29 #include <QVector> 30 31 class StelOBJ; 32 class QOpenGLFunctions; 33 34 Q_DECLARE_LOGGING_CATEGORY(stelOpenGLArray) 35 36 //! Encapsulates vertex data stored in the OpenGL server memory, which can be used for fast drawing commands, 37 //! without repeated CPU-GPU data uploads. 38 //! Each StelOpenGLArray uses a single vertex buffer for vertex data, an element index buffer, 39 //! and a vertex array object for faster binding if the hardware supports it. 40 class StelOpenGLArray 41 { 42 public: 43 //! Specifies the attribute location used for the glVertexAttribPointer calls. 44 //! Shaders should be configured to use these locations before linking, 45 //! so that a single vertex format can be used for all shaders. 46 enum AttributeLocation 47 { 48 //! This is the OpenGL attribute location where 3D vertex positions are mapped to 49 ATTLOC_VERTEX, 50 //! This is the OpenGL attribute location where 2D vertex texture coordinates are mapped to 51 ATTLOC_TEXCOORD, 52 //! This is the OpenGL attribute location where 3D vertex normals are mapped to 53 ATTLOC_NORMAL, 54 //! This is the OpenGL attribute location where vertex tangents are mapped to 55 ATTLOC_TANGENT, 56 //! This is the OpenGL attribute location where vertex bitangents are mapped to 57 ATTLOC_BITANGENT, 58 //! The attribute locations starting with this index are unused, and should be used for custom 59 //! vertex attributes not supported by this class 60 ATTLOC_SIZE 61 }; 62 63 //! Constructs an empty StelOpenGLArray. No OpenGL objects are created with this call, 64 //! so this can be used without a GL context. 65 StelOpenGLArray(); 66 //! Releases the OpenGL data, if it has not happened yet. 67 ~StelOpenGLArray(); 68 69 //! Releases the OpenGL data. Requires a valid context. 70 void clear(); 71 72 //! Loads the data from the given OBJ file into OpenGL buffers. 73 //! The StelOBJ instance is not required after this constructor, 74 //! the data has been copied to OpenGL. 75 //! 76 //! The data is stored in an interleaved format, i.e. the vertex buffer is 77 //! a vector of StelOBJ::Vertex structs 78 //! @return false if the data could not be loaded into GL 79 //! @param obj The StelOBJ instance which data should be transferred to GL 80 //! @param useTangents Whether to also load tangent/bitangent data, or skip it to save GL memory 81 //! @note Requires a valid bound GL context 82 bool load(const StelOBJ* obj, bool useTangents = true); 83 84 //! Binds this array for drawing/manipulating with OpenGL 85 //! @note Requires a valid bound GL context 86 void bind(); 87 //! Releases the bound array data. 88 //! @note Requires a valid bound GL context 89 void release(); 90 91 //! Issues a glDrawElements call for all indices stored in this array. 92 //! Does not bind the array first. draw() const93 inline void draw() const 94 { 95 draw(0,m_indexCount); 96 } 97 //! Issues a glDrawElements call for the \p count indices starting at \p offset 98 //! Does not bind the array first. draw(int offset,int count) const99 inline void draw(int offset, int count) const 100 { 101 gl->glDrawElements(GL_TRIANGLES, count, m_indexBufferType, reinterpret_cast<const GLvoid*>(static_cast<unsigned long long>(offset) * m_indexBufferTypeSize)); 102 } 103 104 //! Returns the buffer used for the vertex data. getVertexBuffer() const105 const QOpenGLBuffer& getVertexBuffer() const { return m_vertexBuffer; } 106 //! Returns the buffer used for the element index data. getIndexBuffer() const107 const QOpenGLBuffer& getIndexBuffer() const { return m_indexBuffer; } 108 //! Returns the VAO which is used, when possible getVAO() const109 const QOpenGLVertexArrayObject& getVAO() const { return m_vao; } 110 111 //! Returns the type used for element index data in this instance. 112 //! This is either GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT or GL_UNSIGNED_INT (if hardware supports it). 113 //! The actual type is chosen depending on the requirements of the data passed into load(). getIndexBufferType() const114 GLenum getIndexBufferType() const { return m_indexBufferType; } 115 //! Returns the size in bytes for the type from getIndexBufferType() getIndexBufferTypeSize() const116 size_t getIndexBufferTypeSize() const { return m_indexBufferTypeSize; } 117 //! Returns the number of indices stored in this array getIndexCount() const118 int getIndexCount() const { return m_indexCount; } 119 120 //! Initializes some global GL state. Requires a valid bound GL context. 121 static void initGL(); 122 //! Returns true if the hardware supports use of 123 //! [vertex array objects](https://www.opengl.org/wiki/Vertex_Specification#Vertex_Array_Object). 124 //! These are used if possible to increase performance, because the driver 125 //! does not need to re-validate the vertex attribute state for each draw call. 126 //! @note The result of this function is valid only after calling initGL() in a GL context. supportsVertexArrayObject()127 static bool supportsVertexArrayObject() { return s_vaosSupported; } 128 //! Returns true if the hardware supports use of (unsigned) integer element indices, instead of just byte and short. 129 //! This is required for loading larger models (>65535 vertices) without manual splitting supportsIntegerElementIndex()130 static bool supportsIntegerElementIndex() { return s_intElementBuffersSupported; } 131 private: 132 QOpenGLBuffer m_vertexBuffer; 133 QOpenGLBuffer m_indexBuffer; 134 QOpenGLVertexArrayObject m_vao; 135 GLenum m_indexBufferType; 136 size_t m_indexBufferTypeSize; 137 int m_indexCount; 138 size_t m_memoryUsage; 139 140 quintptr m_offsets[ATTLOC_SIZE]; 141 GLint m_sizes[ATTLOC_SIZE]; 142 GLenum m_types[ATTLOC_SIZE]; 143 GLsizei m_strides[ATTLOC_SIZE]; 144 145 void bindBuffers(); 146 void releaseBuffers(); 147 148 static QOpenGLFunctions* gl; 149 static bool s_vaosSupported; 150 static bool s_intElementBuffersSupported; 151 }; 152 153 #endif // STELOPENGLARRAY_HPP 154