Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 2011-07-13 |
2 | // Created by: Sergey ZERCHANINOV | |
de75ed09 | 3 | // Copyright (c) 2011-2013 OPEN CASCADE SAS |
b311480e | 4 | // |
973c2be1 | 5 | // This file is part of Open CASCADE Technology software library. |
b311480e | 6 | // |
d5f74e42 | 7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published | |
973c2be1 | 9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT | |
11 | // distribution for complete text of the license and disclaimer of any warranty. | |
b311480e | 12 | // |
973c2be1 | 13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. | |
b311480e | 15 | |
2166f0fa | 16 | #include <OpenGl_AspectFace.hxx> |
30f0ad28 | 17 | #include <OpenGl_Context.hxx> |
2166f0fa | 18 | #include <OpenGl_GraphicDriver.hxx> |
30f0ad28 | 19 | #include <OpenGl_IndexBuffer.hxx> |
a577aaab | 20 | #include <OpenGl_PointSprite.hxx> |
30f0ad28 | 21 | #include <OpenGl_PrimitiveArray.hxx> |
22 | #include <OpenGl_ShaderManager.hxx> | |
23 | #include <OpenGl_ShaderProgram.hxx> | |
2166f0fa | 24 | #include <OpenGl_Structure.hxx> |
7d3e64ef | 25 | #include <OpenGl_VertexBufferCompat.hxx> |
bf75be98 | 26 | #include <OpenGl_Workspace.hxx> |
2166f0fa | 27 | |
30f0ad28 | 28 | namespace |
29 | { | |
30 | template<class T> | |
7d3e64ef | 31 | const Handle(OpenGl_ShaderProgram)& bindProgram (const Handle(OpenGl_Workspace)& theWS, |
32 | const T* theAspect) | |
30f0ad28 | 33 | { |
7d3e64ef | 34 | const Handle(OpenGl_Context)& aCtx = theWS->GetGlContext(); |
30f0ad28 | 35 | const Handle(OpenGl_ShaderProgram)& aProgram = theAspect->ShaderProgramRes (theWS); |
7d3e64ef | 36 | aCtx->BindProgram (aProgram); |
30f0ad28 | 37 | if (aProgram.IsNull()) |
38 | { | |
7d3e64ef | 39 | return aCtx->ActiveProgram(); |
30f0ad28 | 40 | } |
7d3e64ef | 41 | |
42 | aProgram->ApplyVariables (aCtx); | |
30f0ad28 | 43 | |
44 | const OpenGl_MaterialState* aMaterialState = aCtx->ShaderManager()->MaterialState (aProgram); | |
45 | if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect) | |
46 | { | |
47 | aCtx->ShaderManager()->UpdateMaterialStateTo (aProgram, theAspect); | |
48 | } | |
49 | ||
50 | aCtx->ShaderManager()->PushState (aProgram); | |
7d3e64ef | 51 | return aProgram; |
52 | } | |
53 | ||
54 | inline const Handle(OpenGl_ShaderProgram)& bindProgram (const Handle(OpenGl_Workspace)& theWorkspace, | |
55 | const OpenGl_AspectFace* theAspectFace, | |
56 | const OpenGl_AspectLine* theAspectLine, | |
57 | const OpenGl_AspectMarker* theAspectMarker, | |
58 | const GLint theDrawMode) | |
59 | { | |
60 | if (!theWorkspace->GetGlContext()->IsGlGreaterEqual (2, 0)) | |
61 | { | |
62 | return theWorkspace->GetGlContext()->ActiveProgram(); | |
63 | } | |
64 | switch (theDrawMode) | |
65 | { | |
66 | case GL_POINTS: | |
67 | return bindProgram (theWorkspace, theAspectMarker); | |
68 | case GL_LINES: | |
69 | case GL_LINE_STRIP: | |
70 | return bindProgram (theWorkspace, theAspectLine); | |
71 | } | |
72 | return bindProgram (theWorkspace, theAspectFace); | |
30f0ad28 | 73 | } |
871fa103 | 74 | |
75 | //! Convert index data type from size | |
76 | inline GLenum toGlIndexType (const Standard_Integer theStride) | |
77 | { | |
78 | switch (theStride) | |
79 | { | |
80 | case 2: return GL_UNSIGNED_SHORT; | |
81 | case 4: return GL_UNSIGNED_INT; | |
82 | default: return GL_NONE; | |
83 | } | |
84 | } | |
85 | ||
86 | //! Convert data type to GL info | |
87 | inline GLenum toGlDataType (const Graphic3d_TypeOfData theType, | |
88 | GLint& theNbComp) | |
89 | { | |
90 | switch (theType) | |
91 | { | |
92 | case Graphic3d_TOD_USHORT: | |
93 | theNbComp = 1; | |
94 | return GL_UNSIGNED_SHORT; | |
95 | case Graphic3d_TOD_UINT: | |
96 | theNbComp = 1; | |
97 | return GL_UNSIGNED_INT; | |
98 | case Graphic3d_TOD_VEC2: | |
99 | theNbComp = 2; | |
100 | return GL_FLOAT; | |
101 | case Graphic3d_TOD_VEC3: | |
102 | theNbComp = 3; | |
103 | return GL_FLOAT; | |
104 | case Graphic3d_TOD_VEC4: | |
105 | theNbComp = 4; | |
106 | return GL_FLOAT; | |
107 | case Graphic3d_TOD_VEC4UB: | |
108 | theNbComp = 4; | |
109 | return GL_UNSIGNED_BYTE; | |
110 | } | |
111 | theNbComp = 0; | |
112 | return GL_NONE; | |
113 | } | |
114 | ||
30f0ad28 | 115 | } |
116 | ||
871fa103 | 117 | //! Auxiliary template for VBO with interleaved attributes. |
7d3e64ef | 118 | template<class TheBaseClass, int NbAttributes> |
119 | class OpenGl_VertexBufferT : public TheBaseClass | |
7fd59977 | 120 | { |
871fa103 | 121 | |
122 | public: | |
123 | ||
124 | //! Create uninitialized VBO. | |
125 | OpenGl_VertexBufferT (const Graphic3d_Attribute* theAttribs, | |
126 | const Standard_Integer theStride) | |
127 | : Stride (theStride) | |
128 | { | |
129 | memcpy (Attribs, theAttribs, sizeof(Graphic3d_Attribute) * NbAttributes); | |
130 | } | |
131 | ||
132 | //! Create uninitialized VBO. | |
133 | OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs) | |
134 | : Stride (theAttribs.Stride) | |
135 | { | |
136 | memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes); | |
137 | } | |
138 | ||
139 | virtual bool HasColorAttribute() const | |
140 | { | |
141 | for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter) | |
142 | { | |
143 | const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter]; | |
144 | if (anAttrib.Id == Graphic3d_TOA_COLOR) | |
145 | { | |
146 | return true; | |
147 | } | |
148 | } | |
149 | return false; | |
150 | } | |
151 | ||
7d3e64ef | 152 | virtual bool HasNormalAttribute() const |
153 | { | |
154 | for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter) | |
155 | { | |
156 | const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter]; | |
157 | if (anAttrib.Id == Graphic3d_TOA_NORM) | |
158 | { | |
159 | return true; | |
160 | } | |
161 | } | |
162 | return false; | |
163 | } | |
164 | ||
165 | virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const | |
871fa103 | 166 | { |
7d3e64ef | 167 | if (!TheBaseClass::IsValid()) |
871fa103 | 168 | { |
169 | return; | |
170 | } | |
171 | ||
7d3e64ef | 172 | TheBaseClass::Bind (theGlCtx); |
871fa103 | 173 | GLint aNbComp; |
7d3e64ef | 174 | const GLubyte* anOffset = TheBaseClass::myOffset; |
871fa103 | 175 | for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter) |
176 | { | |
177 | const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter]; | |
178 | const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp); | |
179 | if (aDataType == GL_NONE) | |
180 | { | |
181 | continue; | |
182 | } | |
183 | else if (anAttrib.Id == Graphic3d_TOA_POS) | |
184 | { | |
7d3e64ef | 185 | TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset); |
871fa103 | 186 | break; |
187 | } | |
188 | ||
189 | anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType); | |
190 | } | |
191 | } | |
192 | ||
7d3e64ef | 193 | virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const |
871fa103 | 194 | { |
7d3e64ef | 195 | if (!TheBaseClass::IsValid()) |
871fa103 | 196 | { |
197 | return; | |
198 | } | |
199 | ||
7d3e64ef | 200 | TheBaseClass::Bind (theGlCtx); |
871fa103 | 201 | GLint aNbComp; |
7d3e64ef | 202 | const GLubyte* anOffset = TheBaseClass::myOffset; |
871fa103 | 203 | for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter) |
204 | { | |
205 | const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter]; | |
206 | const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp); | |
207 | if (aDataType == GL_NONE) | |
208 | { | |
209 | continue; | |
210 | } | |
211 | ||
7d3e64ef | 212 | TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset); |
871fa103 | 213 | anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType); |
214 | } | |
215 | } | |
216 | ||
7d3e64ef | 217 | virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const |
871fa103 | 218 | { |
7d3e64ef | 219 | if (!TheBaseClass::IsValid()) |
871fa103 | 220 | { |
221 | return; | |
222 | } | |
7d3e64ef | 223 | TheBaseClass::Unbind (theGlCtx); |
871fa103 | 224 | |
225 | for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter) | |
226 | { | |
227 | const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter]; | |
7d3e64ef | 228 | TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id); |
871fa103 | 229 | } |
230 | } | |
231 | ||
232 | public: | |
233 | ||
234 | Graphic3d_Attribute Attribs[NbAttributes]; | |
235 | Standard_Integer Stride; | |
236 | ||
237 | }; | |
7fd59977 | 238 | |
2166f0fa SK |
239 | // ======================================================================= |
240 | // function : clearMemoryGL | |
241 | // purpose : | |
242 | // ======================================================================= | |
5e27df78 | 243 | void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const |
7fd59977 | 244 | { |
871fa103 | 245 | if (!myVboIndices.IsNull()) |
2166f0fa | 246 | { |
871fa103 | 247 | myVboIndices->Release (theGlCtx.operator->()); |
248 | myVboIndices.Nullify(); | |
249 | } | |
250 | if (!myVboAttribs.IsNull()) | |
251 | { | |
252 | myVboAttribs->Release (theGlCtx.operator->()); | |
253 | myVboAttribs.Nullify(); | |
2166f0fa | 254 | } |
7fd59977 | 255 | } |
256 | ||
2166f0fa | 257 | // ======================================================================= |
7d3e64ef | 258 | // function : initNormalVbo |
2166f0fa SK |
259 | // purpose : |
260 | // ======================================================================= | |
7d3e64ef | 261 | Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const |
7fd59977 | 262 | { |
7d3e64ef | 263 | switch (myAttribs->NbAttributes) |
2166f0fa | 264 | { |
7d3e64ef | 265 | case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break; |
266 | case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break; | |
267 | case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break; | |
268 | case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break; | |
269 | case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break; | |
270 | case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break; | |
271 | case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break; | |
272 | case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break; | |
273 | case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break; | |
274 | case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break; | |
275 | } | |
276 | ||
277 | if (!myVboAttribs->init (theCtx, 0, myAttribs->NbElements, myAttribs->Data(), GL_NONE, myAttribs->Stride)) | |
278 | { | |
279 | TCollection_ExtendedString aMsg; | |
280 | aMsg += "VBO creation for Primitive Array has failed for "; | |
281 | aMsg += myAttribs->NbElements; | |
282 | aMsg += " vertices. Out of memory?"; | |
283 | theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg); | |
284 | ||
285 | clearMemoryGL (theCtx); | |
5e27df78 | 286 | return Standard_False; |
2166f0fa | 287 | } |
7d3e64ef | 288 | else if (myIndices.IsNull()) |
289 | { | |
290 | return Standard_True; | |
291 | } | |
7fd59977 | 292 | |
7d3e64ef | 293 | myVboIndices = new OpenGl_IndexBuffer(); |
294 | bool isOk = false; | |
295 | switch (myIndices->Stride) | |
296 | { | |
297 | case 2: | |
298 | { | |
299 | isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data())); | |
300 | break; | |
301 | } | |
302 | case 4: | |
303 | { | |
304 | isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data())); | |
305 | break; | |
306 | } | |
307 | default: | |
308 | { | |
309 | clearMemoryGL (theCtx); | |
310 | return Standard_False; | |
311 | } | |
312 | } | |
313 | if (!isOk) | |
2166f0fa | 314 | { |
7d3e64ef | 315 | TCollection_ExtendedString aMsg; |
316 | aMsg += "VBO creation for Primitive Array has failed for "; | |
317 | aMsg += myIndices->NbElements; | |
318 | aMsg += " indices. Out of memory?"; | |
319 | theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg); | |
320 | clearMemoryGL (theCtx); | |
321 | return Standard_False; | |
7fd59977 | 322 | } |
7d3e64ef | 323 | return Standard_True; |
324 | } | |
871fa103 | 325 | |
7d3e64ef | 326 | // ======================================================================= |
327 | // function : buildVBO | |
328 | // purpose : | |
329 | // ======================================================================= | |
330 | Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx, | |
331 | const Standard_Boolean theToKeepData) const | |
332 | { | |
333 | bool isNormalMode = theCtx->ToUseVbo(); | |
334 | if (myAttribs.IsNull() | |
335 | || myAttribs->IsEmpty() | |
336 | || myAttribs->NbElements < 1 | |
337 | || myAttribs->NbAttributes < 1 | |
338 | || myAttribs->NbAttributes > 10) | |
2166f0fa | 339 | { |
7d3e64ef | 340 | // vertices should be always defined - others are optional |
871fa103 | 341 | return Standard_False; |
7fd59977 | 342 | } |
871fa103 | 343 | |
7d3e64ef | 344 | if (isNormalMode |
345 | && initNormalVbo (theCtx)) | |
346 | { | |
347 | if (!theCtx->caps->keepArrayData | |
348 | && !theToKeepData) | |
349 | { | |
350 | myIndices.Nullify(); | |
351 | myAttribs.Nullify(); | |
352 | } | |
353 | return Standard_True; | |
354 | } | |
355 | ||
356 | Handle(OpenGl_VertexBufferCompat) aVboAttribs; | |
357 | switch (myAttribs->NbAttributes) | |
358 | { | |
359 | case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break; | |
360 | case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break; | |
361 | case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break; | |
362 | case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break; | |
363 | case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break; | |
364 | case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break; | |
365 | case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break; | |
366 | case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break; | |
367 | case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break; | |
368 | case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break; | |
369 | } | |
370 | aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE); | |
871fa103 | 371 | if (!myIndices.IsNull()) |
2166f0fa | 372 | { |
7d3e64ef | 373 | Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat(); |
871fa103 | 374 | switch (myIndices->Stride) |
5e27df78 | 375 | { |
871fa103 | 376 | case 2: |
377 | { | |
7d3e64ef | 378 | aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT); |
871fa103 | 379 | break; |
380 | } | |
381 | case 4: | |
382 | { | |
7d3e64ef | 383 | aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT); |
871fa103 | 384 | break; |
385 | } | |
7d3e64ef | 386 | default: |
387 | { | |
388 | return Standard_False; | |
389 | } | |
5e27df78 | 390 | } |
7d3e64ef | 391 | myVboIndices = aVboIndices; |
2166f0fa | 392 | } |
7d3e64ef | 393 | myVboAttribs = aVboAttribs; |
394 | if (!theCtx->caps->keepArrayData | |
395 | && !theToKeepData) | |
e276548b | 396 | { |
7d3e64ef | 397 | // does not make sense for compatibility mode |
398 | //myIndices.Nullify(); | |
399 | //myAttribs.Nullify(); | |
e276548b | 400 | } |
7d3e64ef | 401 | |
2166f0fa | 402 | return Standard_True; |
7fd59977 | 403 | } |
404 | ||
2166f0fa | 405 | // ======================================================================= |
7d3e64ef | 406 | // function : drawArray |
2166f0fa SK |
407 | // purpose : |
408 | // ======================================================================= | |
7d3e64ef | 409 | void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace, |
410 | const Graphic3d_Vec4* theFaceColors) const | |
7fd59977 | 411 | { |
871fa103 | 412 | const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext(); |
871fa103 | 413 | const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0; |
414 | bool hasVColors = false; | |
7d3e64ef | 415 | if (myVboAttribs.IsNull()) |
2166f0fa | 416 | { |
ca3c13d1 | 417 | #if !defined(GL_ES_VERSION_2_0) |
7d3e64ef | 418 | if (myDrawMode == GL_POINTS) |
419 | { | |
420 | // extreme compatibility mode - without sprites but with markers | |
421 | drawMarkers (theWorkspace); | |
422 | } | |
ca3c13d1 | 423 | #endif |
7d3e64ef | 424 | return; |
7fd59977 | 425 | } |
426 | ||
7d3e64ef | 427 | myVboAttribs->BindAllAttributes (aGlContext); |
428 | if (myVboAttribs->HasColorAttribute()) | |
2166f0fa | 429 | { |
871fa103 | 430 | if (toHilight) |
2166f0fa | 431 | { |
7d3e64ef | 432 | // disable per-vertex colors |
433 | OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR); | |
7fd59977 | 434 | } |
7d3e64ef | 435 | else |
2166f0fa | 436 | { |
7d3e64ef | 437 | hasVColors = true; |
7fd59977 | 438 | } |
7d3e64ef | 439 | } |
440 | if (!myVboIndices.IsNull()) | |
441 | { | |
442 | myVboIndices->Bind (aGlContext); | |
443 | GLubyte* anOffset = myVboIndices->GetDataOffset(); | |
444 | if (!myBounds.IsNull()) | |
2166f0fa | 445 | { |
7d3e64ef | 446 | // draw primitives by vertex count with the indices |
447 | const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int); | |
448 | for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter) | |
2166f0fa | 449 | { |
7d3e64ef | 450 | const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter]; |
ca3c13d1 | 451 | #if !defined(GL_ES_VERSION_2_0) |
7d3e64ef | 452 | if (theFaceColors != NULL) glColor3fv (theFaceColors[aGroupIter].GetData()); |
ca3c13d1 | 453 | #endif |
7d3e64ef | 454 | glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset); |
455 | anOffset += aStride * aNbElemsInGroup; | |
762aacae | 456 | } |
bf75be98 | 457 | } |
2166f0fa SK |
458 | else |
459 | { | |
7d3e64ef | 460 | // draw one (or sequential) primitive by the indices |
461 | glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset); | |
5e27df78 | 462 | } |
7d3e64ef | 463 | myVboIndices->Unbind (aGlContext); |
7fd59977 | 464 | } |
7d3e64ef | 465 | else if (!myBounds.IsNull()) |
871fa103 | 466 | { |
7d3e64ef | 467 | GLint aFirstElem = 0; |
468 | for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter) | |
469 | { | |
470 | const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter]; | |
ca3c13d1 | 471 | #if !defined(GL_ES_VERSION_2_0) |
7d3e64ef | 472 | if (theFaceColors != NULL) glColor3fv (theFaceColors[aGroupIter].GetData()); |
ca3c13d1 | 473 | #endif |
7d3e64ef | 474 | glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup); |
475 | aFirstElem += aNbElemsInGroup; | |
476 | } | |
871fa103 | 477 | } |
7d3e64ef | 478 | else |
2166f0fa | 479 | { |
7d3e64ef | 480 | if (myDrawMode == GL_POINTS) |
481 | { | |
482 | drawMarkers (theWorkspace); | |
483 | } | |
484 | else | |
485 | { | |
486 | glDrawArrays (myDrawMode, 0, myVboAttribs->GetElemsNb()); | |
487 | } | |
2166f0fa SK |
488 | } |
489 | ||
7d3e64ef | 490 | // bind with 0 |
491 | myVboAttribs->UnbindAllAttributes (aGlContext); | |
492 | ||
493 | if (hasVColors) | |
494 | { | |
495 | theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; | |
496 | } | |
7fd59977 | 497 | } |
498 | ||
2166f0fa | 499 | // ======================================================================= |
7d3e64ef | 500 | // function : drawEdges |
2166f0fa SK |
501 | // purpose : |
502 | // ======================================================================= | |
7d3e64ef | 503 | void OpenGl_PrimitiveArray::drawEdges (const TEL_COLOUR* theEdgeColour, |
2166f0fa | 504 | const Handle(OpenGl_Workspace)& theWorkspace) const |
7fd59977 | 505 | { |
7d3e64ef | 506 | if (myVboAttribs.IsNull()) |
507 | { | |
508 | return; | |
509 | } | |
510 | ||
ca3c13d1 | 511 | #if !defined(GL_ES_VERSION_2_0) |
2166f0fa | 512 | glDisable (GL_LIGHTING); |
ca3c13d1 | 513 | #endif |
7fd59977 | 514 | |
2166f0fa SK |
515 | const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext(); |
516 | const OpenGl_AspectLine* anAspectLineOld = NULL; | |
7fd59977 | 517 | |
7d3e64ef | 518 | anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge()); |
519 | const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True); | |
30f0ad28 | 520 | |
ca3c13d1 | 521 | #if !defined(GL_ES_VERSION_2_0) |
7d3e64ef | 522 | glPushAttrib (GL_POLYGON_BIT); |
523 | glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); | |
ca3c13d1 | 524 | #endif |
7d3e64ef | 525 | |
526 | if (aGlContext->IsGlGreaterEqual (2, 0)) | |
527 | { | |
528 | bindProgram (theWorkspace, anAspect); | |
2166f0fa | 529 | } |
7fd59977 | 530 | |
5e27df78 | 531 | /// OCC22236 NOTE: draw edges for all situations: |
871fa103 | 532 | /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array |
533 | /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices. | |
5e27df78 | 534 | /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified |
7d3e64ef | 535 | myVboAttribs->BindPositionAttribute (aGlContext); |
ca3c13d1 | 536 | #if !defined(GL_ES_VERSION_2_0) |
7d3e64ef | 537 | glColor3fv (theEdgeColour->rgb); |
ca3c13d1 | 538 | #endif |
7d3e64ef | 539 | if (!myVboIndices.IsNull()) |
bf75be98 | 540 | { |
7d3e64ef | 541 | myVboIndices->Bind (aGlContext); |
542 | GLubyte* anOffset = myVboIndices->GetDataOffset(); | |
2166f0fa | 543 | |
7d3e64ef | 544 | // draw primitives by vertex count with the indices |
545 | if (!myBounds.IsNull()) | |
2166f0fa | 546 | { |
7d3e64ef | 547 | const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int); |
871fa103 | 548 | for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter) |
2166f0fa | 549 | { |
871fa103 | 550 | const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter]; |
7d3e64ef | 551 | glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset); |
552 | anOffset += aStride * aNbElemsInGroup; | |
7fd59977 | 553 | } |
554 | } | |
7d3e64ef | 555 | // draw one (or sequential) primitive by the indices |
2166f0fa SK |
556 | else |
557 | { | |
7d3e64ef | 558 | glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset); |
762aacae | 559 | } |
7d3e64ef | 560 | myVboIndices->Unbind (aGlContext); |
2166f0fa | 561 | } |
7d3e64ef | 562 | else if (!myBounds.IsNull()) |
2166f0fa | 563 | { |
7d3e64ef | 564 | GLint aFirstElem = 0; |
565 | for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter) | |
2166f0fa | 566 | { |
7d3e64ef | 567 | const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter]; |
568 | glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup); | |
569 | aFirstElem += aNbElemsInGroup; | |
7fd59977 | 570 | } |
2166f0fa | 571 | } |
7d3e64ef | 572 | else |
573 | { | |
574 | glDrawArrays (myDrawMode, 0, myAttribs->NbElements); | |
575 | } | |
576 | ||
577 | // unbind buffers | |
578 | myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS); | |
2166f0fa SK |
579 | |
580 | if (myDrawMode > GL_LINE_STRIP) | |
581 | { | |
582 | // Restore line context | |
583 | theWorkspace->SetAspectLine (anAspectLineOld); | |
ca3c13d1 | 584 | #if !defined(GL_ES_VERSION_2_0) |
7fd59977 | 585 | glPopAttrib(); |
ca3c13d1 | 586 | #endif |
7fd59977 | 587 | } |
588 | } | |
589 | ||
a577aaab | 590 | // ======================================================================= |
7d3e64ef | 591 | // function : drawMarkers |
a577aaab | 592 | // purpose : |
593 | // ======================================================================= | |
7d3e64ef | 594 | void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const |
a577aaab | 595 | { |
596 | const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True); | |
597 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); | |
30f0ad28 | 598 | const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (theWorkspace); |
a577aaab | 599 | const Standard_Boolean isHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT); |
600 | if (aCtx->IsGlGreaterEqual (2, 0) | |
601 | && !aSpriteNorm.IsNull() && !aSpriteNorm->IsDisplayList()) | |
602 | { | |
603 | // Textured markers will be drawn with the point sprites | |
ca3c13d1 | 604 | #if !defined(GL_ES_VERSION_2_0) |
a577aaab | 605 | glPointSize (anAspectMarker->MarkerSize()); |
ca3c13d1 | 606 | #endif |
a577aaab | 607 | |
608 | Handle(OpenGl_Texture) aTextureBack; | |
609 | if (anAspectMarker->Type() != Aspect_TOM_POINT) | |
610 | { | |
30f0ad28 | 611 | const Handle(OpenGl_PointSprite)& aSprite = (isHilight && anAspectMarker->SpriteHighlightRes (theWorkspace)->IsValid()) |
612 | ? anAspectMarker->SpriteHighlightRes (theWorkspace) | |
a577aaab | 613 | : aSpriteNorm; |
614 | aTextureBack = theWorkspace->EnableTexture (aSprite); | |
615 | ||
ca3c13d1 | 616 | #if !defined(GL_ES_VERSION_2_0) |
a577aaab | 617 | glEnable (GL_ALPHA_TEST); |
618 | glAlphaFunc (GL_GEQUAL, 0.1f); | |
ca3c13d1 | 619 | #endif |
a577aaab | 620 | |
621 | glEnable (GL_BLEND); | |
622 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
623 | } | |
624 | ||
871fa103 | 625 | glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements); |
a577aaab | 626 | |
627 | glDisable (GL_BLEND); | |
ca3c13d1 | 628 | #if !defined(GL_ES_VERSION_2_0) |
a577aaab | 629 | glDisable (GL_ALPHA_TEST); |
ca3c13d1 | 630 | #endif |
a577aaab | 631 | if (anAspectMarker->Type() != Aspect_TOM_POINT) |
632 | { | |
633 | theWorkspace->EnableTexture (aTextureBack); | |
634 | } | |
ca3c13d1 | 635 | #if !defined(GL_ES_VERSION_2_0) |
a577aaab | 636 | glPointSize (1.0f); |
ca3c13d1 | 637 | #endif |
a577aaab | 638 | return; |
639 | } | |
640 | ||
641 | // Textured markers will be drawn with the glBitmap | |
a577aaab | 642 | if (anAspectMarker->Type() == Aspect_TOM_POINT |
643 | || anAspectMarker->Type() == Aspect_TOM_O_POINT) | |
644 | { | |
abe46077 | 645 | const GLfloat aPntSize = anAspectMarker->Type() == Aspect_TOM_POINT |
646 | ? anAspectMarker->MarkerSize() | |
647 | : 0.0f; | |
ca3c13d1 | 648 | #if !defined(GL_ES_VERSION_2_0) |
abe46077 | 649 | if (aPntSize > 0.0f) |
650 | { | |
651 | glPointSize (aPntSize); | |
652 | } | |
ca3c13d1 | 653 | #endif |
871fa103 | 654 | glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements); |
ca3c13d1 | 655 | #if !defined(GL_ES_VERSION_2_0) |
abe46077 | 656 | if (aPntSize > 0.0f) |
657 | { | |
658 | glPointSize (1.0f); | |
659 | } | |
ca3c13d1 | 660 | #endif |
a577aaab | 661 | } |
662 | ||
ca3c13d1 | 663 | #if !defined(GL_ES_VERSION_2_0) |
a577aaab | 664 | if (anAspectMarker->Type() != Aspect_TOM_POINT |
665 | && !aSpriteNorm.IsNull()) | |
666 | { | |
871fa103 | 667 | /**if (!isHilight && (myPArray->vcolours != NULL)) |
a577aaab | 668 | { |
871fa103 | 669 | for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++) |
a577aaab | 670 | { |
871fa103 | 671 | glColor4ubv (myPArray->vcolours[anIter].GetData()); |
672 | glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData()); | |
a577aaab | 673 | aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext()); |
674 | } | |
675 | } | |
871fa103 | 676 | else*/ |
a577aaab | 677 | { |
871fa103 | 678 | for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++) |
a577aaab | 679 | { |
871fa103 | 680 | glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData()); |
a577aaab | 681 | aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext()); |
682 | } | |
683 | } | |
684 | } | |
ca3c13d1 | 685 | #endif |
a577aaab | 686 | } |
687 | ||
2166f0fa SK |
688 | // ======================================================================= |
689 | // function : OpenGl_PrimitiveArray | |
690 | // purpose : | |
691 | // ======================================================================= | |
8d3f219f | 692 | OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver, |
693 | const Graphic3d_TypeOfPrimitiveArray theType, | |
871fa103 | 694 | const Handle(Graphic3d_IndexBuffer)& theIndices, |
695 | const Handle(Graphic3d_Buffer)& theAttribs, | |
696 | const Handle(Graphic3d_BoundBuffer)& theBounds) | |
8d3f219f | 697 | |
871fa103 | 698 | : myIndices (theIndices), |
699 | myAttribs (theAttribs), | |
700 | myBounds (theBounds), | |
701 | myDrawMode (DRAW_MODE_NONE), | |
8d3f219f | 702 | myIsVboInit (Standard_False), |
703 | myUID (theDriver->GetNextPrimitiveArrayUID()) | |
2166f0fa | 704 | { |
871fa103 | 705 | if (!myIndices.IsNull() |
706 | && myIndices->NbElements < 1) | |
707 | { | |
708 | // dummy index buffer? | |
709 | myIndices.Nullify(); | |
710 | } | |
711 | if (myAttribs.IsNull()) | |
712 | { | |
713 | return; | |
714 | } | |
715 | ||
716 | switch (theType) | |
2166f0fa | 717 | { |
871fa103 | 718 | case Graphic3d_TOPA_POINTS: |
2166f0fa SK |
719 | myDrawMode = GL_POINTS; |
720 | break; | |
871fa103 | 721 | case Graphic3d_TOPA_POLYLINES: |
2166f0fa SK |
722 | myDrawMode = GL_LINE_STRIP; |
723 | break; | |
871fa103 | 724 | case Graphic3d_TOPA_SEGMENTS: |
2166f0fa SK |
725 | myDrawMode = GL_LINES; |
726 | break; | |
871fa103 | 727 | case Graphic3d_TOPA_TRIANGLES: |
2166f0fa SK |
728 | myDrawMode = GL_TRIANGLES; |
729 | break; | |
871fa103 | 730 | case Graphic3d_TOPA_TRIANGLESTRIPS: |
2166f0fa SK |
731 | myDrawMode = GL_TRIANGLE_STRIP; |
732 | break; | |
871fa103 | 733 | case Graphic3d_TOPA_TRIANGLEFANS: |
2166f0fa SK |
734 | myDrawMode = GL_TRIANGLE_FAN; |
735 | break; | |
ca3c13d1 | 736 | #if !defined(GL_ES_VERSION_2_0) |
737 | case Graphic3d_TOPA_POLYGONS: | |
738 | myDrawMode = GL_POLYGON; | |
739 | break; | |
740 | case Graphic3d_TOPA_QUADRANGLES: | |
741 | myDrawMode = GL_QUADS; | |
742 | break; | |
743 | case Graphic3d_TOPA_QUADRANGLESTRIPS: | |
744 | myDrawMode = GL_QUAD_STRIP; | |
745 | break; | |
746 | #else | |
747 | case Graphic3d_TOPA_POLYGONS: | |
748 | case Graphic3d_TOPA_QUADRANGLES: | |
749 | case Graphic3d_TOPA_QUADRANGLESTRIPS: | |
750 | #endif | |
871fa103 | 751 | case Graphic3d_TOPA_UNDEFINED: |
566f8441 | 752 | break; |
2166f0fa SK |
753 | } |
754 | } | |
755 | ||
756 | // ======================================================================= | |
757 | // function : ~OpenGl_PrimitiveArray | |
758 | // purpose : | |
759 | // ======================================================================= | |
5e27df78 | 760 | OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray() |
2166f0fa | 761 | { |
5e27df78 | 762 | // |
763 | } | |
2166f0fa | 764 | |
5e27df78 | 765 | // ======================================================================= |
766 | // function : Release | |
767 | // purpose : | |
768 | // ======================================================================= | |
10b9c7df | 769 | void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext) |
5e27df78 | 770 | { |
871fa103 | 771 | if (!myVboIndices.IsNull()) |
2166f0fa | 772 | { |
10b9c7df | 773 | if (theContext) |
5e27df78 | 774 | { |
871fa103 | 775 | theContext->DelayedRelease (myVboIndices); |
776 | } | |
777 | myVboIndices.Nullify(); | |
778 | } | |
779 | if (!myVboAttribs.IsNull()) | |
780 | { | |
10b9c7df | 781 | if (theContext) |
871fa103 | 782 | { |
783 | theContext->DelayedRelease (myVboAttribs); | |
5e27df78 | 784 | } |
871fa103 | 785 | myVboAttribs.Nullify(); |
2166f0fa SK |
786 | } |
787 | } | |
788 | ||
789 | // ======================================================================= | |
790 | // function : Render | |
791 | // purpose : | |
792 | // ======================================================================= | |
793 | void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const | |
794 | { | |
871fa103 | 795 | if (myDrawMode == DRAW_MODE_NONE) |
bf75be98 | 796 | { |
2166f0fa | 797 | return; |
bf75be98 | 798 | } |
2166f0fa | 799 | |
a577aaab | 800 | const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True); |
801 | const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True); | |
802 | const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myDrawMode == GL_POINTS); | |
803 | ||
2166f0fa | 804 | // create VBOs on first render call |
58655684 | 805 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
7d3e64ef | 806 | if (!myIsVboInit) |
2166f0fa | 807 | { |
7d3e64ef | 808 | // compatibility - keep data to draw markers using display lists |
809 | const Standard_Boolean toKeepData = myDrawMode == GL_POINTS | |
810 | && !anAspectMarker->SpriteRes (theWorkspace).IsNull() | |
811 | && anAspectMarker->SpriteRes (theWorkspace)->IsDisplayList(); | |
812 | buildVBO (aCtx, toKeepData); | |
5e27df78 | 813 | myIsVboInit = Standard_True; |
2166f0fa SK |
814 | } |
815 | ||
fd4a6963 | 816 | Tint aFrontLightingModel = anAspectFace->IntFront().color_mask; |
817 | const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront().matcol; | |
2166f0fa | 818 | const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color(); |
871fa103 | 819 | const TEL_COLOUR* aLineColor = myDrawMode == GL_POINTS ? &anAspectMarker->Color() : &anAspectLine->Color(); |
2166f0fa SK |
820 | |
821 | // Use highlight colors | |
822 | if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) | |
bf75be98 | 823 | { |
2166f0fa SK |
824 | anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor; |
825 | aFrontLightingModel = 0; | |
826 | } | |
827 | ||
ca3c13d1 | 828 | #if !defined(GL_ES_VERSION_2_0) |
7d3e64ef | 829 | // Temporarily disable environment mapping |
830 | if (myDrawMode <= GL_LINE_STRIP) | |
831 | { | |
832 | glPushAttrib (GL_ENABLE_BIT); | |
833 | glDisable (GL_TEXTURE_1D); | |
834 | glDisable (GL_TEXTURE_2D); | |
835 | } | |
836 | // manage FFP lighting | |
837 | if (aFrontLightingModel == 0 | |
838 | || myVboAttribs.IsNull() | |
839 | || !myVboAttribs->HasNormalAttribute()) | |
30f0ad28 | 840 | { |
7d3e64ef | 841 | glDisable (GL_LIGHTING); |
842 | } | |
843 | else | |
844 | { | |
845 | glEnable (GL_LIGHTING); | |
846 | } | |
ca3c13d1 | 847 | #endif |
7d3e64ef | 848 | |
849 | bindProgram (theWorkspace, | |
850 | anAspectFace, anAspectLine, anAspectMarker, | |
851 | myDrawMode); | |
852 | ||
853 | if ((myDrawMode > GL_LINE_STRIP && anAspectFace->InteriorStyle() != Aspect_IS_EMPTY) || | |
854 | (myDrawMode <= GL_LINE_STRIP)) | |
855 | { | |
856 | const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0; | |
857 | const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->InteriorStyle() != Aspect_IS_HIDDENLINE | |
858 | ? myBounds->Colors | |
859 | : NULL; | |
ca3c13d1 | 860 | #if !defined(GL_ES_VERSION_2_0) |
7d3e64ef | 861 | glColor3fv (myDrawMode <= GL_LINE_STRIP ? aLineColor->rgb : anInteriorColor->rgb); |
ca3c13d1 | 862 | #endif |
7d3e64ef | 863 | |
864 | drawArray (theWorkspace, aFaceColors); | |
865 | } | |
866 | ||
867 | if (myDrawMode > GL_LINE_STRIP) | |
868 | { | |
869 | if (anAspectFace->Edge() | |
870 | || anAspectFace->InteriorStyle() == Aspect_IS_HIDDENLINE) | |
30f0ad28 | 871 | { |
7d3e64ef | 872 | drawEdges (anEdgeColor, theWorkspace); |
30f0ad28 | 873 | } |
874 | } | |
875 | ||
ca3c13d1 | 876 | #if !defined(GL_ES_VERSION_2_0) |
7d3e64ef | 877 | if (myDrawMode <= GL_LINE_STRIP) |
878 | { | |
879 | glPopAttrib(); | |
880 | } | |
ca3c13d1 | 881 | #endif |
7d3e64ef | 882 | aCtx->BindProgram (NULL); |
2166f0fa | 883 | } |