5e27df78 |
1 | // Created by: Kirill GAVRILOV |
d5f74e42 |
2 | // Copyright (c) 2013-2014 OPEN CASCADE SAS |
5e27df78 |
3 | // |
973c2be1 |
4 | // This file is part of Open CASCADE Technology software library. |
5e27df78 |
5 | // |
d5f74e42 |
6 | // This library is free software; you can redistribute it and/or modify it under |
7 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
8 | // by the Free Software Foundation, with special exception defined in the file |
9 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
10 | // distribution for complete text of the license and disclaimer of any warranty. |
5e27df78 |
11 | // |
973c2be1 |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
5e27df78 |
14 | |
15 | #ifndef _OpenGl_VertexBuffer_H__ |
16 | #define _OpenGl_VertexBuffer_H__ |
17 | |
18 | #include <OpenGl_GlCore20.hxx> |
19 | #include <OpenGl_Resource.hxx> |
871fa103 |
20 | #include <OpenGl_Context.hxx> |
7d3e64ef |
21 | #include <OpenGl_ShaderProgram.hxx> |
5e27df78 |
22 | |
871fa103 |
23 | #include <Graphic3d_IndexBuffer.hxx> |
5e27df78 |
24 | |
25 | //! Vertex Buffer Object - is a general storage object for vertex attributes (position, normal, color). |
26 | //! Notice that you should use OpenGl_IndexBuffer specialization for array of indices. |
27 | class OpenGl_VertexBuffer : public OpenGl_Resource |
28 | { |
29 | |
30 | public: |
31 | |
32 | //! Helpful constants |
33 | static const GLuint NO_BUFFER = 0; |
34 | |
a46ab511 |
35 | //! Format VBO target enumeration value. |
36 | Standard_EXPORT static TCollection_AsciiString FormatTarget (GLenum theTarget); |
37 | |
5e27df78 |
38 | public: |
39 | |
40 | //! Create uninitialized VBO. |
41 | Standard_EXPORT OpenGl_VertexBuffer(); |
42 | |
43 | //! Destroy object. |
44 | Standard_EXPORT virtual ~OpenGl_VertexBuffer(); |
45 | |
46 | Standard_EXPORT virtual GLenum GetTarget() const; |
47 | |
da87ddc3 |
48 | //! Return TRUE if this is a virtual (for backward compatibility) VBO object. |
49 | virtual bool IsVirtual() const { return false; } |
50 | |
5e27df78 |
51 | //! @return true if current object was initialized |
52 | inline bool IsValid() const |
53 | { |
54 | return myBufferId != NO_BUFFER; |
55 | } |
56 | |
57 | //! @return the number of components per generic vertex attribute. |
58 | inline GLuint GetComponentsNb() const |
59 | { |
60 | return myComponentsNb; |
61 | } |
62 | |
da87ddc3 |
63 | //! @return number of vertex attributes / number of vertices specified within ::Init() |
5e27df78 |
64 | inline GLsizei GetElemsNb() const |
65 | { |
66 | return myElemsNb; |
67 | } |
68 | |
da87ddc3 |
69 | //! Overrides the number of vertex attributes / number of vertexes. |
70 | //! It is up to user specifying this number correct (e.g. below initial value)! |
71 | void SetElemsNb (GLsizei theNbElems) { myElemsNb = theNbElems; } |
72 | |
5e27df78 |
73 | //! @return data type of each component in the array. |
74 | inline GLenum GetDataType() const |
75 | { |
76 | return myDataType; |
77 | } |
78 | |
7d3e64ef |
79 | //! @return offset to data, NULL by default |
80 | inline GLubyte* GetDataOffset() const |
81 | { |
82 | return myOffset; |
83 | } |
84 | |
5e27df78 |
85 | //! Creates VBO name (id) if not yet generated. |
86 | //! Data should be initialized by another method. |
7d3e64ef |
87 | Standard_EXPORT virtual bool Create (const Handle(OpenGl_Context)& theGlCtx); |
5e27df78 |
88 | |
89 | //! Destroy object - will release GPU memory if any. |
79104795 |
90 | Standard_EXPORT virtual void Release (OpenGl_Context* theGlCtx) Standard_OVERRIDE; |
5e27df78 |
91 | |
92 | //! Bind this VBO. |
7d3e64ef |
93 | Standard_EXPORT virtual void Bind (const Handle(OpenGl_Context)& theGlCtx) const; |
5e27df78 |
94 | |
95 | //! Unbind this VBO. |
7d3e64ef |
96 | Standard_EXPORT virtual void Unbind (const Handle(OpenGl_Context)& theGlCtx) const; |
5e27df78 |
97 | |
98 | //! Notice that VBO will be unbound after this call. |
99 | //! @param theComponentsNb - specifies the number of components per generic vertex attribute; must be 1, 2, 3, or 4; |
100 | //! @param theElemsNb - elements count; |
101 | //! @param theData - pointer to GLfloat data (vertices/normals etc.). |
871fa103 |
102 | bool Init (const Handle(OpenGl_Context)& theGlCtx, |
103 | const GLuint theComponentsNb, |
104 | const GLsizei theElemsNb, |
105 | const GLfloat* theData) |
106 | { |
107 | return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_FLOAT); |
108 | } |
5e27df78 |
109 | |
110 | //! Notice that VBO will be unbound after this call. |
111 | //! @param theComponentsNb - specifies the number of components per generic vertex attribute; must be 1, 2, 3, or 4; |
112 | //! @param theElemsNb - elements count; |
113 | //! @param theData - pointer to GLuint data (indices etc.). |
871fa103 |
114 | bool Init (const Handle(OpenGl_Context)& theGlCtx, |
115 | const GLuint theComponentsNb, |
116 | const GLsizei theElemsNb, |
117 | const GLuint* theData) |
118 | { |
119 | return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_UNSIGNED_INT); |
120 | } |
121 | |
122 | //! Notice that VBO will be unbound after this call. |
123 | //! @param theComponentsNb - specifies the number of components per generic vertex attribute; must be 1, 2, 3, or 4; |
124 | //! @param theElemsNb - elements count; |
125 | //! @param theData - pointer to GLushort data (indices etc.). |
126 | bool Init (const Handle(OpenGl_Context)& theGlCtx, |
127 | const GLuint theComponentsNb, |
128 | const GLsizei theElemsNb, |
129 | const GLushort* theData) |
130 | { |
131 | return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_UNSIGNED_SHORT); |
132 | } |
5e27df78 |
133 | |
134 | //! Notice that VBO will be unbound after this call. |
135 | //! @param theComponentsNb - specifies the number of components per generic vertex attribute; must be 1, 2, 3, or 4; |
136 | //! @param theElemsNb - elements count; |
137 | //! @param theData - pointer to GLubyte data (indices/colors etc.). |
871fa103 |
138 | bool Init (const Handle(OpenGl_Context)& theGlCtx, |
139 | const GLuint theComponentsNb, |
140 | const GLsizei theElemsNb, |
141 | const GLubyte* theData) |
142 | { |
143 | return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_UNSIGNED_BYTE); |
144 | } |
5e27df78 |
145 | |
146 | //! Notice that VBO will be unbound after this call. |
147 | //! Function replaces portion of data within this VBO using glBufferSubData(). |
148 | //! The VBO should be initialized before call. |
149 | //! @param theElemFrom - element id from which replace buffer data (>=0); |
99d99a6d |
150 | //! @param theElemsNb - elements count (theElemFrom + theElemsNb <= GetElemsNb()); |
5e27df78 |
151 | //! @param theData - pointer to GLfloat data. |
871fa103 |
152 | bool SubData (const Handle(OpenGl_Context)& theGlCtx, |
153 | const GLsizei theElemFrom, |
154 | const GLsizei theElemsNb, |
155 | const GLfloat* theData) |
156 | { |
157 | return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_FLOAT); |
158 | } |
5e27df78 |
159 | |
d4cefcc0 |
160 | //! Read back buffer sub-range. |
161 | //! Notice that VBO will be unbound after this call. |
162 | //! Function reads portion of data from this VBO using glGetBufferSubData(). |
163 | //! @param theElemFrom [in] element id from which replace buffer data (>=0); |
164 | //! @param theElemsNb [in] elements count (theElemFrom + theElemsNb <= GetElemsNb()); |
165 | //! @param theData [out] destination pointer to GLfloat data. |
166 | bool GetSubData (const Handle(OpenGl_Context)& theGlCtx, |
167 | const GLsizei theElemFrom, |
168 | const GLsizei theElemsNb, |
169 | GLfloat* theData) |
170 | { |
171 | return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_FLOAT); |
172 | } |
173 | |
99d99a6d |
174 | //! Notice that VBO will be unbound after this call. |
175 | //! Function replaces portion of data within this VBO using glBufferSubData(). |
176 | //! The VBO should be initialized before call. |
177 | //! @param theElemFrom element id from which replace buffer data (>=0); |
178 | //! @param theElemsNb elements count (theElemFrom + theElemsNb <= GetElemsNb()); |
179 | //! @param theData pointer to GLuint data. |
871fa103 |
180 | bool SubData (const Handle(OpenGl_Context)& theGlCtx, |
181 | const GLsizei theElemFrom, |
182 | const GLsizei theElemsNb, |
183 | const GLuint* theData) |
184 | { |
185 | return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_INT); |
186 | } |
187 | |
d4cefcc0 |
188 | //! Read back buffer sub-range. |
189 | //! Notice that VBO will be unbound after this call. |
190 | //! Function reads portion of data from this VBO using glGetBufferSubData(). |
191 | //! @param theElemFrom [in] element id from which replace buffer data (>=0); |
192 | //! @param theElemsNb [in] elements count (theElemFrom + theElemsNb <= GetElemsNb()); |
193 | //! @param theData [out] destination pointer to GLuint data. |
194 | bool GetSubData (const Handle(OpenGl_Context)& theGlCtx, |
195 | const GLsizei theElemFrom, |
196 | const GLsizei theElemsNb, |
197 | GLuint* theData) |
198 | { |
199 | return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_INT); |
200 | } |
201 | |
871fa103 |
202 | //! Notice that VBO will be unbound after this call. |
203 | //! Function replaces portion of data within this VBO using glBufferSubData(). |
204 | //! The VBO should be initialized before call. |
205 | //! @param theElemFrom element id from which replace buffer data (>=0); |
206 | //! @param theElemsNb elements count (theElemFrom + theElemsNb <= GetElemsNb()); |
207 | //! @param theData pointer to GLushort data. |
208 | bool SubData (const Handle(OpenGl_Context)& theGlCtx, |
209 | const GLsizei theElemFrom, |
210 | const GLsizei theElemsNb, |
211 | const GLushort* theData) |
212 | { |
213 | return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_SHORT); |
214 | } |
99d99a6d |
215 | |
d4cefcc0 |
216 | //! Read back buffer sub-range. |
217 | //! Notice that VBO will be unbound after this call. |
218 | //! Function reads portion of data from this VBO using glGetBufferSubData(). |
219 | //! @param theElemFrom [in] element id from which replace buffer data (>=0); |
220 | //! @param theElemsNb [in] elements count (theElemFrom + theElemsNb <= GetElemsNb()); |
221 | //! @param theData [out] destination pointer to GLushort data. |
222 | bool GetSubData (const Handle(OpenGl_Context)& theGlCtx, |
223 | const GLsizei theElemFrom, |
224 | const GLsizei theElemsNb, |
225 | GLushort* theData) |
226 | { |
227 | return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_SHORT); |
228 | } |
229 | |
99d99a6d |
230 | //! Notice that VBO will be unbound after this call. |
231 | //! Function replaces portion of data within this VBO using glBufferSubData(). |
232 | //! The VBO should be initialized before call. |
233 | //! @param theElemFrom element id from which replace buffer data (>=0); |
234 | //! @param theElemsNb elements count (theElemFrom + theElemsNb <= GetElemsNb()); |
235 | //! @param theData pointer to GLubyte data. |
871fa103 |
236 | bool SubData (const Handle(OpenGl_Context)& theGlCtx, |
237 | const GLsizei theElemFrom, |
238 | const GLsizei theElemsNb, |
239 | const GLubyte* theData) |
240 | { |
241 | return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_BYTE); |
242 | } |
99d99a6d |
243 | |
d4cefcc0 |
244 | //! Read back buffer sub-range. |
245 | //! Notice that VBO will be unbound after this call. |
246 | //! Function reads portion of data from this VBO using glGetBufferSubData(). |
247 | //! @param theElemFrom [in] element id from which replace buffer data (>=0); |
248 | //! @param theElemsNb [in] elements count (theElemFrom + theElemsNb <= GetElemsNb()); |
249 | //! @param theData [out] destination pointer to GLubyte data. |
250 | bool GetSubData (const Handle(OpenGl_Context)& theGlCtx, |
251 | const GLsizei theElemFrom, |
252 | const GLsizei theElemsNb, |
253 | GLubyte* theData) |
254 | { |
255 | return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_BYTE); |
256 | } |
257 | |
5e27df78 |
258 | //! Bind this VBO to active GLSL program. |
259 | Standard_EXPORT void BindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx, |
260 | const GLuint theAttribLoc) const; |
261 | |
262 | //! Unbind any VBO from active GLSL program. |
263 | Standard_EXPORT void UnbindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx, |
264 | const GLuint theAttribLoc) const; |
265 | |
7d3e64ef |
266 | //! Bind this VBO and enable specified attribute in OpenGl_Context::ActiveProgram() or FFP. |
5e27df78 |
267 | //! @param theGlCtx - handle to bound GL context; |
268 | //! @param theMode - array mode (GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, GL_COLOR_ARRAY, GL_INDEX_ARRAY, GL_TEXTURE_COORD_ARRAY). |
7d3e64ef |
269 | void BindAttribute (const Handle(OpenGl_Context)& theCtx, |
270 | const Graphic3d_TypeOfAttribute theMode) const |
271 | { |
272 | if (IsValid()) |
273 | { |
274 | Bind (theCtx); |
275 | bindAttribute (theCtx, theMode, static_cast<GLint> (myComponentsNb), myDataType, 0, myOffset); |
276 | } |
277 | } |
5e27df78 |
278 | |
7d3e64ef |
279 | //! Unbind this VBO and disable specified attribute in OpenGl_Context::ActiveProgram() or FFP. |
280 | //! @param theCtx handle to bound GL context |
281 | //! @param theMode array mode |
282 | void UnbindAttribute (const Handle(OpenGl_Context)& theCtx, |
283 | const Graphic3d_TypeOfAttribute theMode) const |
284 | { |
285 | if (IsValid()) |
286 | { |
287 | Unbind (theCtx); |
288 | unbindAttribute (theCtx, theMode); |
289 | } |
290 | } |
5e27df78 |
291 | |
871fa103 |
292 | public: //! @name advanced methods |
293 | |
15669413 |
294 | //! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules. |
295 | virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE |
296 | { |
297 | return IsValid() |
298 | ? sizeOfGlType (myDataType) * myComponentsNb * myElemsNb |
299 | : 0; |
300 | } |
301 | |
871fa103 |
302 | //! @return size of specified GL type |
303 | static size_t sizeOfGlType (const GLenum theType) |
304 | { |
305 | switch (theType) |
306 | { |
307 | case GL_BYTE: |
308 | case GL_UNSIGNED_BYTE: return sizeof(GLubyte); |
309 | case GL_SHORT: |
310 | case GL_UNSIGNED_SHORT: return sizeof(GLushort); |
ca3c13d1 |
311 | #ifdef GL_INT |
871fa103 |
312 | case GL_INT: |
ca3c13d1 |
313 | #endif |
871fa103 |
314 | case GL_UNSIGNED_INT: return sizeof(GLuint); |
315 | case GL_FLOAT: return sizeof(GLfloat); |
ca3c13d1 |
316 | #ifdef GL_DOUBLE |
871fa103 |
317 | case GL_DOUBLE: return sizeof(GLdouble); |
ca3c13d1 |
318 | #endif |
871fa103 |
319 | default: return 0; |
320 | } |
321 | } |
322 | |
323 | //! Initialize buffer with new data. |
7d3e64ef |
324 | Standard_EXPORT virtual bool init (const Handle(OpenGl_Context)& theGlCtx, |
325 | const GLuint theComponentsNb, |
326 | const GLsizei theElemsNb, |
327 | const void* theData, |
328 | const GLenum theDataType, |
329 | const GLsizei theStride); |
871fa103 |
330 | |
331 | //! Initialize buffer with new data. |
332 | bool init (const Handle(OpenGl_Context)& theGlCtx, |
333 | const GLuint theComponentsNb, |
334 | const GLsizei theElemsNb, |
335 | const void* theData, |
336 | const GLenum theDataType) |
337 | { |
338 | return init (theGlCtx, theComponentsNb, theElemsNb, theData, theDataType, GLsizei(theComponentsNb) * GLsizei(sizeOfGlType (theDataType))); |
339 | } |
340 | |
341 | //! Update part of the buffer with new data. |
7d3e64ef |
342 | Standard_EXPORT virtual bool subData (const Handle(OpenGl_Context)& theGlCtx, |
343 | const GLsizei theElemFrom, |
344 | const GLsizei theElemsNb, |
345 | const void* theData, |
346 | const GLenum theDataType); |
347 | |
d4cefcc0 |
348 | //! Read back buffer sub-range. |
349 | Standard_EXPORT virtual bool getSubData (const Handle(OpenGl_Context)& theGlCtx, |
350 | const GLsizei theElemFrom, |
351 | const GLsizei theElemsNb, |
352 | void* theData, |
353 | const GLenum theDataType); |
354 | |
7d3e64ef |
355 | //! Setup array pointer - either for active GLSL program OpenGl_Context::ActiveProgram() |
356 | //! or for FFP using bindFixed() when no program bound. |
357 | static void bindAttribute (const Handle(OpenGl_Context)& theGlCtx, |
358 | const Graphic3d_TypeOfAttribute theMode, |
359 | const GLint theNbComp, |
360 | const GLenum theDataType, |
361 | const GLsizei theStride, |
362 | const GLvoid* theOffset); |
363 | |
364 | //! Disable GLSL array pointer - either for active GLSL program OpenGl_Context::ActiveProgram() |
365 | //! or for FFP using unbindFixed() when no program bound. |
366 | static void unbindAttribute (const Handle(OpenGl_Context)& theGlCtx, |
367 | const Graphic3d_TypeOfAttribute theMode); |
368 | |
369 | private: |
ca3c13d1 |
370 | #if !defined(GL_ES_VERSION_2_0) |
871fa103 |
371 | //! Setup FFP array pointer. |
372 | static void bindFixed (const Handle(OpenGl_Context)& theGlCtx, |
373 | const Graphic3d_TypeOfAttribute theMode, |
374 | const GLint theNbComp, |
375 | const GLenum theDataType, |
376 | const GLsizei theStride, |
7d3e64ef |
377 | const GLvoid* theOffset); |
871fa103 |
378 | |
379 | //! Disable FFP array pointer. |
380 | static void unbindFixed (const Handle(OpenGl_Context)& theGlCtx, |
7d3e64ef |
381 | const Graphic3d_TypeOfAttribute theMode); |
8613985b |
382 | |
383 | //! Disable FFP color array pointer. |
f114566d |
384 | Standard_EXPORT static void unbindFixedColor (const Handle(OpenGl_Context)& theCtx); |
8613985b |
385 | |
ca3c13d1 |
386 | #endif |
871fa103 |
387 | public: //! @name methods for interleaved attributes array |
388 | |
7d3e64ef |
389 | //! @return true if buffer contains per-vertex color attribute |
390 | Standard_EXPORT virtual bool HasColorAttribute() const; |
391 | |
392 | //! @return true if buffer contains per-vertex normal attribute |
393 | Standard_EXPORT virtual bool HasNormalAttribute() const; |
871fa103 |
394 | |
7d3e64ef |
395 | //! Bind all vertex attributes to active program OpenGl_Context::ActiveProgram() or for FFP. |
396 | //! Default implementation does nothing. |
397 | Standard_EXPORT virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const; |
871fa103 |
398 | |
7d3e64ef |
399 | //! Bind vertex position attribute only. Default implementation does nothing. |
400 | Standard_EXPORT virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const; |
871fa103 |
401 | |
7d3e64ef |
402 | //! Unbind all vertex attributes. Default implementation does nothing. |
403 | Standard_EXPORT virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const; |
871fa103 |
404 | |
bc73b006 |
405 | //! Dumps the content of me into the stream |
406 | Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE; |
407 | |
5e27df78 |
408 | protected: |
409 | |
7d3e64ef |
410 | GLubyte* myOffset; //!< offset to data |
411 | GLuint myBufferId; //!< VBO name (index) |
412 | GLuint myComponentsNb; //!< Number of components per generic vertex attribute, must be 1, 2, 3, or 4 |
413 | GLsizei myElemsNb; //!< Number of vertex attributes / number of vertices |
414 | GLenum myDataType; //!< Data type (GL_FLOAT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE etc.) |
5e27df78 |
415 | |
416 | public: |
417 | |
92efcf78 |
418 | DEFINE_STANDARD_RTTIEXT(OpenGl_VertexBuffer,OpenGl_Resource) // Type definition |
5e27df78 |
419 | |
420 | }; |
421 | |
422 | DEFINE_STANDARD_HANDLE(OpenGl_VertexBuffer, OpenGl_Resource) |
423 | |
7d3e64ef |
424 | #include <OpenGl_VertexBuffer.lxx> |
425 | |
5e27df78 |
426 | #endif // _OpenGl_VertexBuffer_H__ |