1 // Created on: 2011-07-13
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2013 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_AspectFace.hxx>
17 #include <OpenGl_Context.hxx>
18 #include <OpenGl_GraphicDriver.hxx>
19 #include <OpenGl_IndexBuffer.hxx>
20 #include <OpenGl_PointSprite.hxx>
21 #include <OpenGl_PrimitiveArray.hxx>
22 #include <OpenGl_ShaderManager.hxx>
23 #include <OpenGl_ShaderProgram.hxx>
24 #include <OpenGl_Structure.hxx>
25 #include <OpenGl_VertexBufferCompat.hxx>
26 #include <OpenGl_Workspace.hxx>
30 //! Convert index data type from size
31 inline GLenum toGlIndexType (const Standard_Integer theStride)
35 case 2: return GL_UNSIGNED_SHORT;
36 case 4: return GL_UNSIGNED_INT;
37 default: return GL_NONE;
41 //! Convert data type to GL info
42 inline GLenum toGlDataType (const Graphic3d_TypeOfData theType,
47 case Graphic3d_TOD_USHORT:
49 return GL_UNSIGNED_SHORT;
50 case Graphic3d_TOD_UINT:
52 return GL_UNSIGNED_INT;
53 case Graphic3d_TOD_VEC2:
56 case Graphic3d_TOD_VEC3:
59 case Graphic3d_TOD_VEC4:
62 case Graphic3d_TOD_VEC4UB:
64 return GL_UNSIGNED_BYTE;
72 //! Auxiliary template for VBO with interleaved attributes.
73 template<class TheBaseClass, int NbAttributes>
74 class OpenGl_VertexBufferT : public TheBaseClass
79 //! Create uninitialized VBO.
80 OpenGl_VertexBufferT (const Graphic3d_Attribute* theAttribs,
81 const Standard_Integer theStride)
84 memcpy (Attribs, theAttribs, sizeof(Graphic3d_Attribute) * NbAttributes);
87 //! Create uninitialized VBO.
88 OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
89 : Stride (theAttribs.Stride)
91 memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
94 virtual bool HasColorAttribute() const
96 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
98 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
99 if (anAttrib.Id == Graphic3d_TOA_COLOR)
107 virtual bool HasNormalAttribute() const
109 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
111 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
112 if (anAttrib.Id == Graphic3d_TOA_NORM)
120 virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
122 if (!TheBaseClass::IsValid())
127 TheBaseClass::Bind (theGlCtx);
129 const GLubyte* anOffset = TheBaseClass::myOffset;
130 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
132 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
133 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
134 if (aDataType == GL_NONE)
138 else if (anAttrib.Id == Graphic3d_TOA_POS)
140 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
144 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
148 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
150 if (!TheBaseClass::IsValid())
155 TheBaseClass::Bind (theGlCtx);
157 const GLubyte* anOffset = TheBaseClass::myOffset;
158 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
160 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
161 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
162 if (aDataType == GL_NONE)
167 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
168 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
172 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
174 if (!TheBaseClass::IsValid())
178 TheBaseClass::Unbind (theGlCtx);
180 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
182 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
183 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
189 Graphic3d_Attribute Attribs[NbAttributes];
190 Standard_Integer Stride;
194 // =======================================================================
195 // function : clearMemoryGL
197 // =======================================================================
198 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
200 if (!myVboIndices.IsNull())
202 myVboIndices->Release (theGlCtx.operator->());
203 myVboIndices.Nullify();
205 if (!myVboAttribs.IsNull())
207 myVboAttribs->Release (theGlCtx.operator->());
208 myVboAttribs.Nullify();
212 // =======================================================================
213 // function : initNormalVbo
215 // =======================================================================
216 Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
218 switch (myAttribs->NbAttributes)
220 case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
221 case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
222 case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
223 case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
224 case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
225 case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
226 case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
227 case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
228 case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
229 case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
232 if (!myVboAttribs->init (theCtx, 0, myAttribs->NbElements, myAttribs->Data(), GL_NONE, myAttribs->Stride))
234 TCollection_ExtendedString aMsg;
235 aMsg += "VBO creation for Primitive Array has failed for ";
236 aMsg += myAttribs->NbElements;
237 aMsg += " vertices. Out of memory?";
238 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
240 clearMemoryGL (theCtx);
241 return Standard_False;
243 else if (myIndices.IsNull())
245 return Standard_True;
248 myVboIndices = new OpenGl_IndexBuffer();
250 switch (myIndices->Stride)
254 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data()));
259 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data()));
264 clearMemoryGL (theCtx);
265 return Standard_False;
270 TCollection_ExtendedString aMsg;
271 aMsg += "VBO creation for Primitive Array has failed for ";
272 aMsg += myIndices->NbElements;
273 aMsg += " indices. Out of memory?";
274 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
275 clearMemoryGL (theCtx);
276 return Standard_False;
278 return Standard_True;
281 // =======================================================================
282 // function : buildVBO
284 // =======================================================================
285 Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
286 const Standard_Boolean theToKeepData) const
288 bool isNormalMode = theCtx->ToUseVbo();
289 if (myAttribs.IsNull()
290 || myAttribs->IsEmpty()
291 || myAttribs->NbElements < 1
292 || myAttribs->NbAttributes < 1
293 || myAttribs->NbAttributes > 10)
295 // vertices should be always defined - others are optional
296 return Standard_False;
300 && initNormalVbo (theCtx))
302 if (!theCtx->caps->keepArrayData
308 return Standard_True;
311 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
312 switch (myAttribs->NbAttributes)
314 case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
315 case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
316 case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
317 case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
318 case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
319 case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
320 case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
321 case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
322 case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
323 case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
325 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
326 if (!myIndices.IsNull())
328 Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
329 switch (myIndices->Stride)
333 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
338 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
343 return Standard_False;
346 myVboIndices = aVboIndices;
348 myVboAttribs = aVboAttribs;
349 if (!theCtx->caps->keepArrayData
352 // does not make sense for compatibility mode
353 //myIndices.Nullify();
354 //myAttribs.Nullify();
357 return Standard_True;
360 // =======================================================================
361 // function : drawArray
363 // =======================================================================
364 void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
365 const Graphic3d_Vec4* theFaceColors,
366 const Standard_Boolean theHasVertColor) const
368 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
369 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
370 bool hasVColors = theHasVertColor && !toHilight;
371 if (myVboAttribs.IsNull())
373 #if !defined(GL_ES_VERSION_2_0)
374 if (myDrawMode == GL_POINTS)
376 // extreme compatibility mode - without sprites but with markers
377 drawMarkers (theWorkspace);
383 myVboAttribs->BindAllAttributes (aGlContext);
384 if (theHasVertColor && toHilight)
386 // disable per-vertex color
387 OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
389 if (!myVboIndices.IsNull())
391 myVboIndices->Bind (aGlContext);
392 GLubyte* anOffset = myVboIndices->GetDataOffset();
393 if (!myBounds.IsNull())
395 // draw primitives by vertex count with the indices
396 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
397 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
399 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
400 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
401 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
402 anOffset += aStride * aNbElemsInGroup;
407 // draw one (or sequential) primitive by the indices
408 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
410 myVboIndices->Unbind (aGlContext);
412 else if (!myBounds.IsNull())
414 GLint aFirstElem = 0;
415 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
417 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
418 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
419 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
420 aFirstElem += aNbElemsInGroup;
425 if (myDrawMode == GL_POINTS)
427 drawMarkers (theWorkspace);
431 glDrawArrays (myDrawMode, 0, myVboAttribs->GetElemsNb());
436 myVboAttribs->UnbindAllAttributes (aGlContext);
440 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT;
444 // =======================================================================
445 // function : drawEdges
447 // =======================================================================
448 void OpenGl_PrimitiveArray::drawEdges (const TEL_COLOUR* theEdgeColour,
449 const Handle(OpenGl_Workspace)& theWorkspace) const
451 if (myVboAttribs.IsNull())
456 #if !defined(GL_ES_VERSION_2_0)
457 glDisable (GL_LIGHTING);
460 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
461 const OpenGl_AspectLine* anAspectLineOld = NULL;
463 anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
464 const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True);
466 #if !defined(GL_ES_VERSION_2_0)
467 glPushAttrib (GL_POLYGON_BIT);
468 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
471 if (aGlContext->IsGlGreaterEqual (2, 0))
473 aGlContext->ShaderManager()->BindProgram (anAspect, NULL, Standard_False, Standard_False, anAspect->ShaderProgramRes (aGlContext));
476 /// OCC22236 NOTE: draw edges for all situations:
477 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
478 /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
479 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
480 myVboAttribs->BindPositionAttribute (aGlContext);
481 aGlContext->SetColor4fv (*(const OpenGl_Vec4* )theEdgeColour->rgb);
482 if (!myVboIndices.IsNull())
484 myVboIndices->Bind (aGlContext);
485 GLubyte* anOffset = myVboIndices->GetDataOffset();
487 // draw primitives by vertex count with the indices
488 if (!myBounds.IsNull())
490 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
491 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
493 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
494 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
495 anOffset += aStride * aNbElemsInGroup;
498 // draw one (or sequential) primitive by the indices
501 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
503 myVboIndices->Unbind (aGlContext);
505 else if (!myBounds.IsNull())
507 GLint aFirstElem = 0;
508 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
510 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
511 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
512 aFirstElem += aNbElemsInGroup;
517 glDrawArrays (myDrawMode, 0, myAttribs->NbElements);
521 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
523 // restore line context
524 #if !defined(GL_ES_VERSION_2_0)
527 theWorkspace->SetAspectLine (anAspectLineOld);
530 // =======================================================================
531 // function : drawMarkers
533 // =======================================================================
534 void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
536 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True);
537 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
538 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
539 if (!aSpriteNorm.IsNull()
540 && !aSpriteNorm->IsDisplayList())
542 // Textured markers will be drawn with the point sprites
543 aCtx->SetPointSize (anAspectMarker->MarkerSize());
544 #if !defined(GL_ES_VERSION_2_0)
545 aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
546 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
549 aCtx->core11fwd->glEnable (GL_BLEND);
550 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
552 aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
554 aCtx->core11fwd->glDisable (GL_BLEND);
555 #if !defined(GL_ES_VERSION_2_0)
556 aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
558 aCtx->SetPointSize (1.0f);
561 else if (anAspectMarker->Type() == Aspect_TOM_POINT)
563 aCtx->SetPointSize (anAspectMarker->MarkerSize());
564 aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
565 aCtx->SetPointSize (1.0f);
567 #if !defined(GL_ES_VERSION_2_0)
568 // Textured markers will be drawn with the glBitmap
569 else if (anAspectMarker->Type() != Aspect_TOM_POINT
570 && !aSpriteNorm.IsNull())
572 /**if (!isHilight && (myPArray->vcolours != NULL))
574 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
576 glColor4ubv (myPArray->vcolours[anIter].GetData());
577 glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
578 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
583 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
585 aCtx->core11->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
586 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
593 // =======================================================================
594 // function : OpenGl_PrimitiveArray
596 // =======================================================================
597 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
598 const Graphic3d_TypeOfPrimitiveArray theType,
599 const Handle(Graphic3d_IndexBuffer)& theIndices,
600 const Handle(Graphic3d_Buffer)& theAttribs,
601 const Handle(Graphic3d_BoundBuffer)& theBounds)
603 : myIndices (theIndices),
604 myAttribs (theAttribs),
605 myBounds (theBounds),
606 myDrawMode (DRAW_MODE_NONE),
607 myIsVboInit (Standard_False)
609 if (theDriver != NULL)
611 myUID = theDriver->GetNextPrimitiveArrayUID();
614 if (!myIndices.IsNull()
615 && myIndices->NbElements < 1)
617 // dummy index buffer?
620 if (myAttribs.IsNull())
627 case Graphic3d_TOPA_POINTS:
628 myDrawMode = GL_POINTS;
630 case Graphic3d_TOPA_POLYLINES:
631 myDrawMode = GL_LINE_STRIP;
633 case Graphic3d_TOPA_SEGMENTS:
634 myDrawMode = GL_LINES;
636 case Graphic3d_TOPA_TRIANGLES:
637 myDrawMode = GL_TRIANGLES;
639 case Graphic3d_TOPA_TRIANGLESTRIPS:
640 myDrawMode = GL_TRIANGLE_STRIP;
642 case Graphic3d_TOPA_TRIANGLEFANS:
643 myDrawMode = GL_TRIANGLE_FAN;
645 #if !defined(GL_ES_VERSION_2_0)
646 case Graphic3d_TOPA_POLYGONS:
647 myDrawMode = GL_POLYGON;
649 case Graphic3d_TOPA_QUADRANGLES:
650 myDrawMode = GL_QUADS;
652 case Graphic3d_TOPA_QUADRANGLESTRIPS:
653 myDrawMode = GL_QUAD_STRIP;
656 case Graphic3d_TOPA_POLYGONS:
657 case Graphic3d_TOPA_QUADRANGLES:
658 case Graphic3d_TOPA_QUADRANGLESTRIPS:
660 case Graphic3d_TOPA_UNDEFINED:
665 // =======================================================================
666 // function : ~OpenGl_PrimitiveArray
668 // =======================================================================
669 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
674 // =======================================================================
675 // function : Release
677 // =======================================================================
678 void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
680 myIsVboInit = Standard_False;
681 if (!myVboIndices.IsNull())
685 theContext->DelayedRelease (myVboIndices);
687 myVboIndices.Nullify();
689 if (!myVboAttribs.IsNull())
693 theContext->DelayedRelease (myVboAttribs);
695 myVboAttribs.Nullify();
699 // =======================================================================
702 // =======================================================================
703 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
705 if (myDrawMode == DRAW_MODE_NONE)
710 const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True);
711 const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
712 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myDrawMode == GL_POINTS);
714 // create VBOs on first render call
715 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
718 // compatibility - keep data to draw markers using display lists
719 const Standard_Boolean toKeepData = myDrawMode == GL_POINTS
720 && !anAspectMarker->SpriteRes (aCtx).IsNull()
721 && anAspectMarker->SpriteRes (aCtx)->IsDisplayList();
722 buildVBO (aCtx, toKeepData);
723 myIsVboInit = Standard_True;
726 Tint aFrontLightingModel = anAspectFace->IntFront().color_mask;
727 const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront().matcol;
728 const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
729 const TEL_COLOUR* aLineColor = myDrawMode == GL_POINTS ? &anAspectMarker->Color() : &anAspectLine->Color();
731 // Use highlight colors
732 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
734 anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
735 aFrontLightingModel = 0;
738 const Standard_Boolean hasColorAttrib = !myVboAttribs.IsNull()
739 && myVboAttribs->HasColorAttribute();
740 const Standard_Boolean isLightOn = aFrontLightingModel != 0
741 && !myVboAttribs.IsNull()
742 && myVboAttribs->HasNormalAttribute();
743 #if !defined(GL_ES_VERSION_2_0)
744 // manage FFP lighting
747 glDisable (GL_LIGHTING);
751 glEnable (GL_LIGHTING);
754 // Temporarily disable environment mapping
755 Handle(OpenGl_Texture) aTextureBack;
756 if (myDrawMode <= GL_LINE_STRIP)
758 aTextureBack = theWorkspace->DisableTexture();
761 if ((myDrawMode > GL_LINE_STRIP && anAspectFace->InteriorStyle() != Aspect_IS_EMPTY) ||
762 (myDrawMode <= GL_LINE_STRIP))
764 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
765 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->InteriorStyle() != Aspect_IS_HIDDENLINE
768 const Standard_Boolean hasVertColor = hasColorAttrib && !toHilight;
769 if (aCtx->IsGlGreaterEqual (2, 0))
775 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
776 if (!aSpriteNorm.IsNull()
777 && !aSpriteNorm->IsDisplayList())
779 const Handle(OpenGl_PointSprite)& aSprite = (toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->IsValid())
780 ? anAspectMarker->SpriteHighlightRes (aCtx)
782 theWorkspace->EnableTexture (aSprite);
783 aCtx->ShaderManager()->BindProgram (anAspectMarker, aSprite, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
787 aCtx->ShaderManager()->BindProgram (anAspectMarker, NULL, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
794 aCtx->ShaderManager()->BindProgram (anAspectLine, NULL, isLightOn, hasVertColor, anAspectLine->ShaderProgramRes (aCtx));
799 aCtx->ShaderManager()->BindProgram (anAspectFace, theWorkspace->ActiveTexture(), isLightOn, hasVertColor, anAspectFace->ShaderProgramRes (aCtx));
805 aCtx->SetColor4fv (*(const OpenGl_Vec4* )(myDrawMode <= GL_LINE_STRIP ? aLineColor->rgb : anInteriorColor->rgb));
807 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
810 if (myDrawMode <= GL_LINE_STRIP)
812 theWorkspace->EnableTexture (aTextureBack);
816 if (anAspectFace->Edge()
817 || anAspectFace->InteriorStyle() == Aspect_IS_HIDDENLINE)
819 drawEdges (anEdgeColor, theWorkspace);
823 aCtx->BindProgram (NULL);