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>
27 #include <Graphic3d_TextureParams.hxx>
28 #include <NCollection_AlignedAllocator.hxx>
32 //! Convert data type to GL info
33 inline GLenum toGlDataType (const Graphic3d_TypeOfData theType,
38 case Graphic3d_TOD_USHORT:
40 return GL_UNSIGNED_SHORT;
41 case Graphic3d_TOD_UINT:
43 return GL_UNSIGNED_INT;
44 case Graphic3d_TOD_VEC2:
47 case Graphic3d_TOD_VEC3:
50 case Graphic3d_TOD_VEC4:
53 case Graphic3d_TOD_VEC4UB:
55 return GL_UNSIGNED_BYTE;
63 //! Auxiliary template for VBO with interleaved attributes.
64 template<class TheBaseClass, int NbAttributes>
65 class OpenGl_VertexBufferT : public TheBaseClass
70 //! Create uninitialized VBO.
71 OpenGl_VertexBufferT (const Graphic3d_Attribute* theAttribs,
72 const Standard_Integer theStride)
75 memcpy (Attribs, theAttribs, sizeof(Graphic3d_Attribute) * NbAttributes);
78 //! Create uninitialized VBO.
79 OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
80 : Stride (theAttribs.Stride)
82 memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
85 virtual bool HasColorAttribute() const
87 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
89 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
90 if (anAttrib.Id == Graphic3d_TOA_COLOR)
98 virtual bool HasNormalAttribute() const
100 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
102 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
103 if (anAttrib.Id == Graphic3d_TOA_NORM)
111 virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
113 if (!TheBaseClass::IsValid())
118 TheBaseClass::Bind (theGlCtx);
120 const GLubyte* anOffset = TheBaseClass::myOffset;
121 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
123 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
124 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
125 if (aDataType == GL_NONE)
129 else if (anAttrib.Id == Graphic3d_TOA_POS)
131 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
135 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
139 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
141 if (!TheBaseClass::IsValid())
146 TheBaseClass::Bind (theGlCtx);
148 const GLubyte* anOffset = TheBaseClass::myOffset;
149 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
151 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
152 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
153 if (aDataType == GL_NONE)
158 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
159 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
163 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
165 if (!TheBaseClass::IsValid())
169 TheBaseClass::Unbind (theGlCtx);
171 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
173 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
174 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
180 Graphic3d_Attribute Attribs[NbAttributes];
181 Standard_Integer Stride;
185 // =======================================================================
186 // function : clearMemoryGL
188 // =======================================================================
189 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
191 if (!myVboIndices.IsNull())
193 myVboIndices->Release (theGlCtx.operator->());
194 myVboIndices.Nullify();
196 if (!myVboAttribs.IsNull())
198 myVboAttribs->Release (theGlCtx.operator->());
199 myVboAttribs.Nullify();
203 // =======================================================================
204 // function : initNormalVbo
206 // =======================================================================
207 Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
209 switch (myAttribs->NbAttributes)
211 case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
212 case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
213 case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
214 case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
215 case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
216 case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
217 case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
218 case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
219 case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
220 case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
223 if (!myVboAttribs->init (theCtx, 0, myAttribs->NbElements, myAttribs->Data(), GL_NONE, myAttribs->Stride))
225 TCollection_ExtendedString aMsg;
226 aMsg += "VBO creation for Primitive Array has failed for ";
227 aMsg += myAttribs->NbElements;
228 aMsg += " vertices. Out of memory?";
229 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
231 clearMemoryGL (theCtx);
232 return Standard_False;
234 else if (myIndices.IsNull())
236 return Standard_True;
239 myVboIndices = new OpenGl_IndexBuffer();
241 switch (myIndices->Stride)
245 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data()));
250 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data()));
255 clearMemoryGL (theCtx);
256 return Standard_False;
261 TCollection_ExtendedString aMsg;
262 aMsg += "VBO creation for Primitive Array has failed for ";
263 aMsg += myIndices->NbElements;
264 aMsg += " indices. Out of memory?";
265 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
266 clearMemoryGL (theCtx);
267 return Standard_False;
269 return Standard_True;
272 // =======================================================================
273 // function : buildVBO
275 // =======================================================================
276 Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
277 const Standard_Boolean theToKeepData) const
279 bool isNormalMode = theCtx->ToUseVbo();
280 clearMemoryGL (theCtx);
281 if (myAttribs.IsNull()
282 || myAttribs->IsEmpty()
283 || myAttribs->NbElements < 1
284 || myAttribs->NbAttributes < 1
285 || myAttribs->NbAttributes > 10)
287 // vertices should be always defined - others are optional
288 return Standard_False;
292 && initNormalVbo (theCtx))
294 if (!theCtx->caps->keepArrayData
300 return Standard_True;
303 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
304 switch (myAttribs->NbAttributes)
306 case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
307 case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
308 case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
309 case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
310 case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
311 case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
312 case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
313 case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
314 case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
315 case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
317 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
318 if (!myIndices.IsNull())
320 Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
321 switch (myIndices->Stride)
325 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
330 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
335 return Standard_False;
338 myVboIndices = aVboIndices;
340 myVboAttribs = aVboAttribs;
341 if (!theCtx->caps->keepArrayData
344 // does not make sense for compatibility mode
345 //myIndices.Nullify();
346 //myAttribs.Nullify();
349 return Standard_True;
352 // =======================================================================
353 // function : drawArray
355 // =======================================================================
356 void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
357 const Graphic3d_Vec4* theFaceColors,
358 const Standard_Boolean theHasVertColor) const
360 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
361 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
362 bool hasVColors = theHasVertColor && !toHilight;
363 if (myVboAttribs.IsNull())
365 #if !defined(GL_ES_VERSION_2_0)
366 if (myDrawMode == GL_POINTS)
368 // extreme compatibility mode - without sprites but with markers
369 drawMarkers (theWorkspace);
375 myVboAttribs->BindAllAttributes (aGlContext);
376 if (theHasVertColor && toHilight)
378 // disable per-vertex color
379 OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
381 if (!myVboIndices.IsNull())
383 myVboIndices->Bind (aGlContext);
384 GLubyte* anOffset = myVboIndices->GetDataOffset();
385 if (!myBounds.IsNull())
387 // draw primitives by vertex count with the indices
388 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
389 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
391 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
392 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
393 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
394 anOffset += aStride * aNbElemsInGroup;
399 // draw one (or sequential) primitive by the indices
400 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
402 myVboIndices->Unbind (aGlContext);
404 else if (!myBounds.IsNull())
406 GLint aFirstElem = 0;
407 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
409 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
410 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
411 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
412 aFirstElem += aNbElemsInGroup;
417 if (myDrawMode == GL_POINTS)
419 drawMarkers (theWorkspace);
423 glDrawArrays (myDrawMode, 0, myVboAttribs->GetElemsNb());
428 myVboAttribs->UnbindAllAttributes (aGlContext);
432 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT;
436 // =======================================================================
437 // function : drawEdges
439 // =======================================================================
440 void OpenGl_PrimitiveArray::drawEdges (const TEL_COLOUR* theEdgeColour,
441 const Handle(OpenGl_Workspace)& theWorkspace) const
443 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
444 if (myVboAttribs.IsNull())
449 #if !defined(GL_ES_VERSION_2_0)
450 if (aGlContext->core11 != NULL)
452 glDisable (GL_LIGHTING);
456 const OpenGl_AspectLine* anAspectLineOld = NULL;
458 anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
459 const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True);
461 #if !defined(GL_ES_VERSION_2_0)
462 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
465 if (aGlContext->core20fwd != NULL)
467 aGlContext->ShaderManager()->BindProgram (anAspect, NULL, Standard_False, Standard_False, anAspect->ShaderProgramRes (aGlContext));
470 /// OCC22236 NOTE: draw edges for all situations:
471 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
472 /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
473 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
474 myVboAttribs->BindPositionAttribute (aGlContext);
476 aGlContext->SetColor4fv (*(const OpenGl_Vec4* )theEdgeColour->rgb);
477 aGlContext->SetTypeOfLine (anAspect->Type());
478 aGlContext->SetLineWidth (anAspect->Width());
480 if (!myVboIndices.IsNull())
482 myVboIndices->Bind (aGlContext);
483 GLubyte* anOffset = myVboIndices->GetDataOffset();
485 // draw primitives by vertex count with the indices
486 if (!myBounds.IsNull())
488 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
489 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
491 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
492 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
493 anOffset += aStride * aNbElemsInGroup;
496 // draw one (or sequential) primitive by the indices
499 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
501 myVboIndices->Unbind (aGlContext);
503 else if (!myBounds.IsNull())
505 GLint aFirstElem = 0;
506 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
508 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
509 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
510 aFirstElem += aNbElemsInGroup;
515 glDrawArrays (myDrawMode, 0, myAttribs->NbElements);
519 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
521 // restore line context
522 theWorkspace->SetAspectLine (anAspectLineOld);
525 // =======================================================================
526 // function : drawMarkers
528 // =======================================================================
529 void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
531 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True);
532 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
533 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
534 if (!aSpriteNorm.IsNull()
535 && !aSpriteNorm->IsDisplayList())
537 // Textured markers will be drawn with the point sprites
538 aCtx->SetPointSize (anAspectMarker->MarkerSize());
539 #if !defined(GL_ES_VERSION_2_0)
540 if (aCtx->core11 != NULL)
542 aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
543 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
547 aCtx->core11fwd->glEnable (GL_BLEND);
548 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
550 aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
552 aCtx->core11fwd->glDisable (GL_BLEND);
553 #if !defined(GL_ES_VERSION_2_0)
554 if (aCtx->core11 != NULL)
556 aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
559 aCtx->SetPointSize (1.0f);
562 else if (anAspectMarker->Type() == Aspect_TOM_POINT)
564 aCtx->SetPointSize (anAspectMarker->MarkerSize());
565 aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
566 aCtx->SetPointSize (1.0f);
568 #if !defined(GL_ES_VERSION_2_0)
569 // Textured markers will be drawn with the glBitmap
570 else if (anAspectMarker->Type() != Aspect_TOM_POINT
571 && !aSpriteNorm.IsNull())
573 /**if (!isHilight && (myPArray->vcolours != NULL))
575 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
577 glColor4ubv (myPArray->vcolours[anIter].GetData());
578 glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
579 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
584 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
586 aCtx->core11->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
587 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
594 // =======================================================================
595 // function : OpenGl_PrimitiveArray
597 // =======================================================================
598 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver)
600 : myDrawMode (DRAW_MODE_NONE),
601 myIsVboInit (Standard_False)
603 if (theDriver != NULL)
605 myUID = theDriver->GetNextPrimitiveArrayUID();
609 // =======================================================================
610 // function : OpenGl_PrimitiveArray
612 // =======================================================================
613 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
614 const Graphic3d_TypeOfPrimitiveArray theType,
615 const Handle(Graphic3d_IndexBuffer)& theIndices,
616 const Handle(Graphic3d_Buffer)& theAttribs,
617 const Handle(Graphic3d_BoundBuffer)& theBounds)
619 : myIndices (theIndices),
620 myAttribs (theAttribs),
621 myBounds (theBounds),
622 myDrawMode (DRAW_MODE_NONE),
623 myIsVboInit (Standard_False)
625 if (!myIndices.IsNull()
626 && myIndices->NbElements < 1)
628 // dummy index buffer?
632 if (theDriver != NULL)
634 myUID = theDriver->GetNextPrimitiveArrayUID();
635 #if defined (GL_ES_VERSION_2_0)
636 const Handle(OpenGl_Context)& aCtx = theDriver->GetSharedContext();
639 processIndices (aCtx);
644 setDrawMode (theType);
647 // =======================================================================
648 // function : ~OpenGl_PrimitiveArray
650 // =======================================================================
651 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
656 // =======================================================================
657 // function : Release
659 // =======================================================================
660 void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
662 myIsVboInit = Standard_False;
663 if (!myVboIndices.IsNull())
667 theContext->DelayedRelease (myVboIndices);
669 myVboIndices.Nullify();
671 if (!myVboAttribs.IsNull())
675 theContext->DelayedRelease (myVboAttribs);
677 myVboAttribs.Nullify();
681 // =======================================================================
684 // =======================================================================
685 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
687 if (myDrawMode == DRAW_MODE_NONE)
692 const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True);
693 const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
694 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myDrawMode == GL_POINTS);
696 // create VBOs on first render call
697 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
700 // compatibility - keep data to draw markers using display lists
701 const Standard_Boolean toKeepData = myDrawMode == GL_POINTS
702 && !anAspectMarker->SpriteRes (aCtx).IsNull()
703 && anAspectMarker->SpriteRes (aCtx)->IsDisplayList();
704 #if defined (GL_ES_VERSION_2_0)
705 processIndices (aCtx);
707 buildVBO (aCtx, toKeepData);
708 myIsVboInit = Standard_True;
711 Tint aFrontLightingModel = anAspectFace->IntFront().color_mask;
712 const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront().matcol;
713 const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
714 const TEL_COLOUR* aLineColor = myDrawMode == GL_POINTS ? &anAspectMarker->Color() : &anAspectLine->Color();
716 // Use highlight colors
717 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
719 anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
720 aFrontLightingModel = 0;
723 const Standard_Boolean hasColorAttrib = !myVboAttribs.IsNull()
724 && myVboAttribs->HasColorAttribute();
725 const Standard_Boolean isLightOn = aFrontLightingModel != 0
726 && !myVboAttribs.IsNull()
727 && myVboAttribs->HasNormalAttribute();
728 #if !defined(GL_ES_VERSION_2_0)
729 // manage FFP lighting
730 if (aCtx->core11 != NULL)
734 glDisable (GL_LIGHTING);
738 glEnable (GL_LIGHTING);
742 // Temporarily disable environment mapping
743 Handle(OpenGl_Texture) aTextureBack;
744 if (myDrawMode <= GL_LINE_STRIP)
746 aTextureBack = theWorkspace->DisableTexture();
749 if ((myDrawMode > GL_LINE_STRIP && anAspectFace->InteriorStyle() != Aspect_IS_EMPTY) ||
750 (myDrawMode <= GL_LINE_STRIP))
752 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
753 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->InteriorStyle() != Aspect_IS_HIDDENLINE
756 const Standard_Boolean hasVertColor = hasColorAttrib && !toHilight;
757 if (aCtx->core20fwd != NULL)
763 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
764 if (!aSpriteNorm.IsNull()
765 && !aSpriteNorm->IsDisplayList())
767 const Handle(OpenGl_PointSprite)& aSprite = (toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->IsValid())
768 ? anAspectMarker->SpriteHighlightRes (aCtx)
770 theWorkspace->EnableTexture (aSprite);
771 aCtx->ShaderManager()->BindProgram (anAspectMarker, aSprite, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
775 aCtx->ShaderManager()->BindProgram (anAspectMarker, NULL, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
782 aCtx->ShaderManager()->BindProgram (anAspectLine, NULL, isLightOn, hasVertColor, anAspectLine->ShaderProgramRes (aCtx));
787 const Handle(OpenGl_Texture)& aTexture = theWorkspace->ActiveTexture();
788 const Standard_Boolean isLightOnFace = isLightOn
789 && (aTexture.IsNull()
790 || aTexture->GetParams()->IsModulate());
791 aCtx->ShaderManager()->BindProgram (anAspectFace, aTexture, isLightOnFace, hasVertColor, anAspectFace->ShaderProgramRes (aCtx));
797 if (!theWorkspace->ActiveTexture().IsNull()
798 && myDrawMode != GL_POINTS) // transformation is not supported within point sprites
800 aCtx->SetTextureMatrix (theWorkspace->ActiveTexture()->GetParams());
803 aCtx->SetColor4fv (*(const OpenGl_Vec4* )(myDrawMode <= GL_LINE_STRIP ? aLineColor->rgb : anInteriorColor->rgb));
804 if (myDrawMode == GL_LINES
805 || myDrawMode == GL_LINE_STRIP)
807 aCtx->SetTypeOfLine (anAspectLine->Type());
808 aCtx->SetLineWidth (anAspectLine->Width());
811 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
814 if (myDrawMode <= GL_LINE_STRIP)
816 theWorkspace->EnableTexture (aTextureBack);
820 if (anAspectFace->Edge()
821 || anAspectFace->InteriorStyle() == Aspect_IS_HIDDENLINE)
823 drawEdges (anEdgeColor, theWorkspace);
825 // restore OpenGL polygon mode if needed
826 #if !defined(GL_ES_VERSION_2_0)
827 if (anAspectFace->InteriorStyle() >= Aspect_IS_HATCH)
829 glPolygonMode (GL_FRONT_AND_BACK,
830 anAspectFace->InteriorStyle() == Aspect_IS_POINT ? GL_POINT : GL_FILL);
836 aCtx->BindProgram (NULL);
839 // =======================================================================
840 // function : setDrawMode
842 // =======================================================================
843 void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType)
845 if (myAttribs.IsNull())
847 myDrawMode = DRAW_MODE_NONE;
853 case Graphic3d_TOPA_POINTS:
854 myDrawMode = GL_POINTS;
856 case Graphic3d_TOPA_POLYLINES:
857 myDrawMode = GL_LINE_STRIP;
859 case Graphic3d_TOPA_SEGMENTS:
860 myDrawMode = GL_LINES;
862 case Graphic3d_TOPA_TRIANGLES:
863 myDrawMode = GL_TRIANGLES;
865 case Graphic3d_TOPA_TRIANGLESTRIPS:
866 myDrawMode = GL_TRIANGLE_STRIP;
868 case Graphic3d_TOPA_TRIANGLEFANS:
869 myDrawMode = GL_TRIANGLE_FAN;
871 #if !defined(GL_ES_VERSION_2_0)
872 case Graphic3d_TOPA_POLYGONS:
873 myDrawMode = GL_POLYGON;
875 case Graphic3d_TOPA_QUADRANGLES:
876 myDrawMode = GL_QUADS;
878 case Graphic3d_TOPA_QUADRANGLESTRIPS:
879 myDrawMode = GL_QUAD_STRIP;
882 case Graphic3d_TOPA_POLYGONS:
883 case Graphic3d_TOPA_QUADRANGLES:
884 case Graphic3d_TOPA_QUADRANGLESTRIPS:
886 case Graphic3d_TOPA_UNDEFINED:
891 // =======================================================================
892 // function : processIndices
894 // =======================================================================
895 Standard_Boolean OpenGl_PrimitiveArray::processIndices (const Handle(OpenGl_Context)& theContext) const
897 if (myIndices.IsNull()
898 || theContext->hasUintIndex)
900 return Standard_True;
903 if (myIndices->NbElements > std::numeric_limits<GLushort>::max())
905 Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (new NCollection_AlignedAllocator (16));
906 if (!anAttribs->Init (myIndices->NbElements, myAttribs->AttributesArray(), myAttribs->NbAttributes))
908 return Standard_False; // failed to initialize attribute array
911 for (Standard_Integer anIdxIdx = 0; anIdxIdx < myIndices->NbElements; ++anIdxIdx)
913 const Standard_Integer anIndex = myIndices->Index (anIdxIdx);
914 memcpy (anAttribs->ChangeData() + myAttribs->Stride * anIdxIdx,
915 myAttribs->Data() + myAttribs->Stride * anIndex,
920 myAttribs = anAttribs;
923 return Standard_True;
926 // =======================================================================
927 // function : InitBuffers
929 // =======================================================================
930 void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& theContext,
931 const Graphic3d_TypeOfPrimitiveArray theType,
932 const Handle(Graphic3d_IndexBuffer)& theIndices,
933 const Handle(Graphic3d_Buffer)& theAttribs,
934 const Handle(Graphic3d_BoundBuffer)& theBounds)
936 // Release old graphic resources
937 Release (theContext.operator->());
939 myIndices = theIndices;
940 myAttribs = theAttribs;
941 myBounds = theBounds;
942 #if defined(GL_ES_VERSION_2_0)
943 processIndices (theContext);
946 setDrawMode (theType);