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;
56 case Graphic3d_TOD_FLOAT:
66 //! Auxiliary template for VBO with interleaved attributes.
67 template<class TheBaseClass, int NbAttributes>
68 class OpenGl_VertexBufferT : public TheBaseClass
73 //! Create uninitialized VBO.
74 OpenGl_VertexBufferT (const Graphic3d_Attribute* theAttribs,
75 const Standard_Integer theStride)
78 memcpy (Attribs, theAttribs, sizeof(Graphic3d_Attribute) * NbAttributes);
81 //! Create uninitialized VBO.
82 OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
83 : Stride (theAttribs.Stride)
85 memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
88 virtual bool HasColorAttribute() const
90 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
92 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
93 if (anAttrib.Id == Graphic3d_TOA_COLOR)
101 virtual bool HasNormalAttribute() const
103 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
105 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
106 if (anAttrib.Id == Graphic3d_TOA_NORM)
114 virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
116 if (!TheBaseClass::IsValid())
121 TheBaseClass::Bind (theGlCtx);
123 const GLubyte* anOffset = TheBaseClass::myOffset;
124 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
126 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
127 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
128 if (aDataType == GL_NONE)
132 else if (anAttrib.Id == Graphic3d_TOA_POS)
134 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
138 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
142 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
144 if (!TheBaseClass::IsValid())
149 TheBaseClass::Bind (theGlCtx);
151 const GLubyte* anOffset = TheBaseClass::myOffset;
152 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
154 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
155 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
156 if (aDataType == GL_NONE)
161 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
162 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
166 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
168 if (!TheBaseClass::IsValid())
172 TheBaseClass::Unbind (theGlCtx);
174 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
176 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
177 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
183 Graphic3d_Attribute Attribs[NbAttributes];
184 Standard_Integer Stride;
188 // =======================================================================
189 // function : clearMemoryGL
191 // =======================================================================
192 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
194 if (!myVboIndices.IsNull())
196 myVboIndices->Release (theGlCtx.operator->());
197 myVboIndices.Nullify();
199 if (!myVboAttribs.IsNull())
201 myVboAttribs->Release (theGlCtx.operator->());
202 myVboAttribs.Nullify();
206 // =======================================================================
207 // function : initNormalVbo
209 // =======================================================================
210 Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
212 switch (myAttribs->NbAttributes)
214 case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
215 case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
216 case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
217 case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
218 case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
219 case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
220 case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
221 case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
222 case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
223 case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
226 if (!myVboAttribs->init (theCtx, 0, myAttribs->NbElements, myAttribs->Data(), GL_NONE, myAttribs->Stride))
228 TCollection_ExtendedString aMsg;
229 aMsg += "VBO creation for Primitive Array has failed for ";
230 aMsg += myAttribs->NbElements;
231 aMsg += " vertices. Out of memory?";
232 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
234 clearMemoryGL (theCtx);
235 return Standard_False;
237 else if (myIndices.IsNull())
239 return Standard_True;
242 myVboIndices = new OpenGl_IndexBuffer();
244 switch (myIndices->Stride)
248 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data()));
253 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data()));
258 clearMemoryGL (theCtx);
259 return Standard_False;
264 TCollection_ExtendedString aMsg;
265 aMsg += "VBO creation for Primitive Array has failed for ";
266 aMsg += myIndices->NbElements;
267 aMsg += " indices. Out of memory?";
268 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
269 clearMemoryGL (theCtx);
270 return Standard_False;
272 return Standard_True;
275 // =======================================================================
276 // function : buildVBO
278 // =======================================================================
279 Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
280 const Standard_Boolean theToKeepData) const
282 bool isNormalMode = theCtx->ToUseVbo();
283 clearMemoryGL (theCtx);
284 if (myAttribs.IsNull()
285 || myAttribs->IsEmpty()
286 || myAttribs->NbElements < 1
287 || myAttribs->NbAttributes < 1
288 || myAttribs->NbAttributes > 10)
290 // vertices should be always defined - others are optional
291 return Standard_False;
295 && initNormalVbo (theCtx))
297 if (!theCtx->caps->keepArrayData
303 return Standard_True;
306 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
307 switch (myAttribs->NbAttributes)
309 case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
310 case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
311 case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
312 case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
313 case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
314 case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
315 case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
316 case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
317 case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
318 case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
320 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
321 if (!myIndices.IsNull())
323 Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
324 switch (myIndices->Stride)
328 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
333 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
338 return Standard_False;
341 myVboIndices = aVboIndices;
343 myVboAttribs = aVboAttribs;
344 if (!theCtx->caps->keepArrayData
347 // does not make sense for compatibility mode
348 //myIndices.Nullify();
349 //myAttribs.Nullify();
352 return Standard_True;
355 // =======================================================================
356 // function : drawArray
358 // =======================================================================
359 void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
360 const Graphic3d_Vec4* theFaceColors,
361 const Standard_Boolean theHasVertColor) const
363 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
364 const bool toHilight = theWorkspace->ToHighlight();
365 bool hasVColors = theHasVertColor && !toHilight;
366 if (myVboAttribs.IsNull())
368 #if !defined(GL_ES_VERSION_2_0)
369 if (myDrawMode == GL_POINTS)
371 // extreme compatibility mode - without sprites but with markers
372 drawMarkers (theWorkspace);
378 myVboAttribs->BindAllAttributes (aGlContext);
379 if (theHasVertColor && toHilight)
381 // disable per-vertex color
382 OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
384 if (!myVboIndices.IsNull())
386 myVboIndices->Bind (aGlContext);
387 GLubyte* anOffset = myVboIndices->GetDataOffset();
388 if (!myBounds.IsNull())
390 // draw primitives by vertex count with the indices
391 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
392 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
394 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
395 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
396 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
397 anOffset += aStride * aNbElemsInGroup;
402 // draw one (or sequential) primitive by the indices
403 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
405 myVboIndices->Unbind (aGlContext);
407 else if (!myBounds.IsNull())
409 GLint aFirstElem = 0;
410 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
412 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
413 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
414 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
415 aFirstElem += aNbElemsInGroup;
420 if (myDrawMode == GL_POINTS)
422 drawMarkers (theWorkspace);
426 glDrawArrays (myDrawMode, 0, myVboAttribs->GetElemsNb());
431 myVboAttribs->UnbindAllAttributes (aGlContext);
435 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT;
439 // =======================================================================
440 // function : drawEdges
442 // =======================================================================
443 void OpenGl_PrimitiveArray::drawEdges (const OpenGl_Vec4& theEdgeColour,
444 const Handle(OpenGl_Workspace)& theWorkspace) const
446 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
447 if (myVboAttribs.IsNull())
452 #if !defined(GL_ES_VERSION_2_0)
453 if (aGlContext->core11 != NULL)
455 glDisable (GL_LIGHTING);
459 const OpenGl_AspectLine* anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace()->AspectEdge());
460 const OpenGl_AspectLine* anAspect = theWorkspace->ApplyAspectLine();
462 #if !defined(GL_ES_VERSION_2_0)
463 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
466 if (aGlContext->core20fwd != NULL)
468 aGlContext->ShaderManager()->BindLineProgram (NULL,
469 anAspect->Aspect()->Type() != Aspect_TOL_SOLID,
472 anAspect->ShaderProgramRes (aGlContext));
475 /// OCC22236 NOTE: draw edges for all situations:
476 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
477 /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
478 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
479 myVboAttribs->BindPositionAttribute (aGlContext);
481 aGlContext->SetColor4fv (theEdgeColour);
482 aGlContext->SetTypeOfLine (anAspect->Aspect()->Type());
483 aGlContext->SetLineWidth (anAspect->Aspect()->Width());
485 if (!myVboIndices.IsNull())
487 myVboIndices->Bind (aGlContext);
488 GLubyte* anOffset = myVboIndices->GetDataOffset();
490 // draw primitives by vertex count with the indices
491 if (!myBounds.IsNull())
493 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
494 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
496 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
497 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
498 anOffset += aStride * aNbElemsInGroup;
501 // draw one (or sequential) primitive by the indices
504 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
506 myVboIndices->Unbind (aGlContext);
508 else if (!myBounds.IsNull())
510 GLint aFirstElem = 0;
511 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
513 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
514 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
515 aFirstElem += aNbElemsInGroup;
520 glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
524 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
526 // restore line context
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->ApplyAspectMarker();
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 aCtx->SetPointSpriteOrigin();
545 #if !defined(GL_ES_VERSION_2_0)
546 if (aCtx->core11 != NULL)
548 aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
549 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
553 aCtx->core11fwd->glEnable (GL_BLEND);
554 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
556 aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
558 aCtx->core11fwd->glDisable (GL_BLEND);
559 #if !defined(GL_ES_VERSION_2_0)
560 if (aCtx->core11 != NULL)
562 aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
565 aCtx->SetPointSize (1.0f);
568 else if (anAspectMarker->Aspect()->Type() == Aspect_TOM_POINT)
570 aCtx->SetPointSize (anAspectMarker->MarkerSize());
571 aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
572 aCtx->SetPointSize (1.0f);
574 #if !defined(GL_ES_VERSION_2_0)
575 // Textured markers will be drawn with the glBitmap
576 else if (anAspectMarker->Aspect()->Type() != Aspect_TOM_POINT
577 && !aSpriteNorm.IsNull())
579 /**if (!isHilight && (myPArray->vcolours != NULL))
581 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
583 glColor4ubv (myPArray->vcolours[anIter].GetData());
584 glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
585 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
590 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
592 aCtx->core11->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
593 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
600 // =======================================================================
601 // function : OpenGl_PrimitiveArray
603 // =======================================================================
604 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver)
606 : myDrawMode (DRAW_MODE_NONE),
607 myIsVboInit (Standard_False)
609 if (theDriver != NULL)
611 myUID = theDriver->GetNextPrimitiveArrayUID();
615 // =======================================================================
616 // function : OpenGl_PrimitiveArray
618 // =======================================================================
619 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
620 const Graphic3d_TypeOfPrimitiveArray theType,
621 const Handle(Graphic3d_IndexBuffer)& theIndices,
622 const Handle(Graphic3d_Buffer)& theAttribs,
623 const Handle(Graphic3d_BoundBuffer)& theBounds)
625 : myIndices (theIndices),
626 myAttribs (theAttribs),
627 myBounds (theBounds),
628 myDrawMode (DRAW_MODE_NONE),
629 myIsVboInit (Standard_False)
631 if (!myIndices.IsNull()
632 && myIndices->NbElements < 1)
634 // dummy index buffer?
638 if (theDriver != NULL)
640 myUID = theDriver->GetNextPrimitiveArrayUID();
641 #if defined (GL_ES_VERSION_2_0)
642 const Handle(OpenGl_Context)& aCtx = theDriver->GetSharedContext();
645 processIndices (aCtx);
650 setDrawMode (theType);
653 // =======================================================================
654 // function : ~OpenGl_PrimitiveArray
656 // =======================================================================
657 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
662 // =======================================================================
663 // function : Release
665 // =======================================================================
666 void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
668 myIsVboInit = Standard_False;
669 if (!myVboIndices.IsNull())
673 theContext->DelayedRelease (myVboIndices);
675 myVboIndices.Nullify();
677 if (!myVboAttribs.IsNull())
681 theContext->DelayedRelease (myVboAttribs);
683 myVboAttribs.Nullify();
687 // =======================================================================
690 // =======================================================================
691 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
693 if (myDrawMode == DRAW_MODE_NONE)
698 const OpenGl_AspectFace* anAspectFace = theWorkspace->ApplyAspectFace();
699 const OpenGl_AspectLine* anAspectLine = theWorkspace->ApplyAspectLine();
700 const OpenGl_AspectMarker* anAspectMarker = myDrawMode == GL_POINTS
701 ? theWorkspace->ApplyAspectMarker()
702 : theWorkspace->AspectMarker();
704 // create VBOs on first render call
705 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
708 // compatibility - keep data to draw markers using display lists
709 const Standard_Boolean toKeepData = myDrawMode == GL_POINTS
710 && !anAspectMarker->SpriteRes (aCtx).IsNull()
711 && anAspectMarker->SpriteRes (aCtx)->IsDisplayList();
712 #if defined (GL_ES_VERSION_2_0)
713 processIndices (aCtx);
715 buildVBO (aCtx, toKeepData);
716 myIsVboInit = Standard_True;
719 const Standard_Boolean hasColorAttrib = !myVboAttribs.IsNull()
720 && myVboAttribs->HasColorAttribute();
721 const Standard_Boolean isLightOn = !anAspectFace->IsNoLighting()
722 && !myVboAttribs.IsNull()
723 && myVboAttribs->HasNormalAttribute();
724 #if !defined(GL_ES_VERSION_2_0)
725 // manage FFP lighting
726 if (aCtx->core11 != NULL)
730 glDisable (GL_LIGHTING);
734 glEnable (GL_LIGHTING);
738 // Temporarily disable environment mapping
739 Handle(OpenGl_Texture) aTextureBack;
740 if (myDrawMode <= GL_LINE_STRIP)
742 aTextureBack = theWorkspace->DisableTexture();
745 if ((myDrawMode > GL_LINE_STRIP && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_EMPTY) ||
746 (myDrawMode <= GL_LINE_STRIP))
748 const bool toHilight = theWorkspace->ToHighlight();
749 const Standard_Boolean hasVertColor = hasColorAttrib && !toHilight;
750 if (aCtx->core20fwd != NULL)
756 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
757 if (!aSpriteNorm.IsNull()
758 && !aSpriteNorm->IsDisplayList())
760 const Handle(OpenGl_PointSprite)& aSprite = (toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->IsValid())
761 ? anAspectMarker->SpriteHighlightRes (aCtx)
763 theWorkspace->EnableTexture (aSprite);
764 aCtx->ShaderManager()->BindMarkerProgram (aSprite, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
768 aCtx->ShaderManager()->BindMarkerProgram (NULL, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
775 aCtx->ShaderManager()->BindLineProgram (NULL,
776 anAspectLine->Aspect()->Type() != Aspect_TOL_SOLID,
779 anAspectLine->ShaderProgramRes (aCtx));
784 const Handle(OpenGl_Texture)& aTexture = theWorkspace->ActiveTexture();
785 const Standard_Boolean isLightOnFace = isLightOn
786 && (aTexture.IsNull()
787 || aTexture->GetParams()->IsModulate());
788 const Standard_Boolean toEnableEnvMap = (!aTexture.IsNull() && (aTexture == theWorkspace->EnvironmentTexture()));
789 aCtx->ShaderManager()->BindFaceProgram (aTexture,
793 anAspectFace->ShaderProgramRes (aCtx));
799 // All primitives should gather material properties from the AspectFace in shading mode
802 aCtx->SetShadingMaterial (anAspectFace, theWorkspace->ToHighlight() ? theWorkspace->HighlightColor : NULL);
805 if (!theWorkspace->ActiveTexture().IsNull()
806 && myDrawMode != GL_POINTS) // transformation is not supported within point sprites
808 aCtx->SetTextureMatrix (theWorkspace->ActiveTexture()->GetParams());
811 if (myDrawMode <= GL_LINE_STRIP)
813 const OpenGl_Vec4& aLineColor = myDrawMode == GL_POINTS ? theWorkspace->MarkerColor() : theWorkspace->LineColor();
814 aCtx->SetColor4fv (aLineColor);
818 const OpenGl_Vec4& anInteriorColor = theWorkspace->InteriorColor();
819 aCtx->SetColor4fv (anInteriorColor);
821 if (myDrawMode == GL_LINES
822 || myDrawMode == GL_LINE_STRIP)
824 aCtx->SetTypeOfLine (anAspectLine->Aspect()->Type());
825 aCtx->SetLineWidth (anAspectLine->Aspect()->Width());
828 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_HIDDENLINE
832 const Standard_Boolean isHighlightWithTransparency = toHilight &&
833 myDrawMode > GL_LINE_STRIP &&
834 theWorkspace->InteriorColor().a() > 0.05f;
835 GLint aPrevBlendSrc = GL_SRC_ALPHA, aPrevBlendDst = GL_ONE_MINUS_SRC_ALPHA;
836 GLboolean wasBlendEnabled = GL_FALSE;
837 if (isHighlightWithTransparency)
839 wasBlendEnabled = glIsEnabled (GL_BLEND);
840 #if !defined(GL_ES_VERSION_2_0)
841 glGetIntegerv (GL_BLEND_SRC, &aPrevBlendSrc);
842 glGetIntegerv (GL_BLEND_DST, &aPrevBlendDst);
844 if (!wasBlendEnabled)
848 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
851 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
853 if (isHighlightWithTransparency)
855 glBlendFunc (aPrevBlendSrc, aPrevBlendDst);
856 if (!wasBlendEnabled)
858 glDisable (GL_BLEND);
863 if (myDrawMode <= GL_LINE_STRIP)
865 theWorkspace->EnableTexture (aTextureBack);
869 if (anAspectFace->Aspect()->ToDrawEdges()
870 || anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE)
872 const OpenGl_Vec4& anEdgeColor = theWorkspace->EdgeColor();
873 drawEdges (anEdgeColor, theWorkspace);
875 // restore OpenGL polygon mode if needed
876 #if !defined(GL_ES_VERSION_2_0)
877 if (anAspectFace->Aspect()->InteriorStyle() >= Aspect_IS_HATCH)
879 glPolygonMode (GL_FRONT_AND_BACK,
880 anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_POINT ? GL_POINT : GL_FILL);
886 aCtx->BindProgram (NULL);
889 // =======================================================================
890 // function : setDrawMode
892 // =======================================================================
893 void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType)
895 if (myAttribs.IsNull())
897 myDrawMode = DRAW_MODE_NONE;
903 case Graphic3d_TOPA_POINTS:
904 myDrawMode = GL_POINTS;
906 case Graphic3d_TOPA_POLYLINES:
907 myDrawMode = GL_LINE_STRIP;
909 case Graphic3d_TOPA_SEGMENTS:
910 myDrawMode = GL_LINES;
912 case Graphic3d_TOPA_TRIANGLES:
913 myDrawMode = GL_TRIANGLES;
915 case Graphic3d_TOPA_TRIANGLESTRIPS:
916 myDrawMode = GL_TRIANGLE_STRIP;
918 case Graphic3d_TOPA_TRIANGLEFANS:
919 myDrawMode = GL_TRIANGLE_FAN;
921 #if !defined(GL_ES_VERSION_2_0)
922 case Graphic3d_TOPA_POLYGONS:
923 myDrawMode = GL_POLYGON;
925 case Graphic3d_TOPA_QUADRANGLES:
926 myDrawMode = GL_QUADS;
928 case Graphic3d_TOPA_QUADRANGLESTRIPS:
929 myDrawMode = GL_QUAD_STRIP;
932 case Graphic3d_TOPA_POLYGONS:
933 case Graphic3d_TOPA_QUADRANGLES:
934 case Graphic3d_TOPA_QUADRANGLESTRIPS:
936 case Graphic3d_TOPA_UNDEFINED:
941 // =======================================================================
942 // function : processIndices
944 // =======================================================================
945 Standard_Boolean OpenGl_PrimitiveArray::processIndices (const Handle(OpenGl_Context)& theContext) const
947 if (myIndices.IsNull()
948 || theContext->hasUintIndex)
950 return Standard_True;
953 if (myIndices->NbElements > std::numeric_limits<GLushort>::max())
955 Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (new NCollection_AlignedAllocator (16));
956 if (!anAttribs->Init (myIndices->NbElements, myAttribs->AttributesArray(), myAttribs->NbAttributes))
958 return Standard_False; // failed to initialize attribute array
961 for (Standard_Integer anIdxIdx = 0; anIdxIdx < myIndices->NbElements; ++anIdxIdx)
963 const Standard_Integer anIndex = myIndices->Index (anIdxIdx);
964 memcpy (anAttribs->ChangeData() + myAttribs->Stride * anIdxIdx,
965 myAttribs->Data() + myAttribs->Stride * anIndex,
970 myAttribs = anAttribs;
973 return Standard_True;
976 // =======================================================================
977 // function : InitBuffers
979 // =======================================================================
980 void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& theContext,
981 const Graphic3d_TypeOfPrimitiveArray theType,
982 const Handle(Graphic3d_IndexBuffer)& theIndices,
983 const Handle(Graphic3d_Buffer)& theAttribs,
984 const Handle(Graphic3d_BoundBuffer)& theBounds)
986 // Release old graphic resources
987 Release (theContext.operator->());
989 myIndices = theIndices;
990 myAttribs = theAttribs;
991 myBounds = theBounds;
992 #if defined(GL_ES_VERSION_2_0)
993 processIndices (theContext);
996 setDrawMode (theType);