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 index data type from size
33 inline GLenum toGlIndexType (const Standard_Integer theStride)
37 case 2: return GL_UNSIGNED_SHORT;
38 case 4: return GL_UNSIGNED_INT;
39 default: return GL_NONE;
43 //! Convert data type to GL info
44 inline GLenum toGlDataType (const Graphic3d_TypeOfData theType,
49 case Graphic3d_TOD_USHORT:
51 return GL_UNSIGNED_SHORT;
52 case Graphic3d_TOD_UINT:
54 return GL_UNSIGNED_INT;
55 case Graphic3d_TOD_VEC2:
58 case Graphic3d_TOD_VEC3:
61 case Graphic3d_TOD_VEC4:
64 case Graphic3d_TOD_VEC4UB:
66 return GL_UNSIGNED_BYTE;
74 //! Auxiliary template for VBO with interleaved attributes.
75 template<class TheBaseClass, int NbAttributes>
76 class OpenGl_VertexBufferT : public TheBaseClass
81 //! Create uninitialized VBO.
82 OpenGl_VertexBufferT (const Graphic3d_Attribute* theAttribs,
83 const Standard_Integer theStride)
86 memcpy (Attribs, theAttribs, sizeof(Graphic3d_Attribute) * NbAttributes);
89 //! Create uninitialized VBO.
90 OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
91 : Stride (theAttribs.Stride)
93 memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
96 virtual bool HasColorAttribute() const
98 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
100 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
101 if (anAttrib.Id == Graphic3d_TOA_COLOR)
109 virtual bool HasNormalAttribute() const
111 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
113 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
114 if (anAttrib.Id == Graphic3d_TOA_NORM)
122 virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
124 if (!TheBaseClass::IsValid())
129 TheBaseClass::Bind (theGlCtx);
131 const GLubyte* anOffset = TheBaseClass::myOffset;
132 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
134 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
135 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
136 if (aDataType == GL_NONE)
140 else if (anAttrib.Id == Graphic3d_TOA_POS)
142 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
146 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
150 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
152 if (!TheBaseClass::IsValid())
157 TheBaseClass::Bind (theGlCtx);
159 const GLubyte* anOffset = TheBaseClass::myOffset;
160 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
162 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
163 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
164 if (aDataType == GL_NONE)
169 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
170 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
174 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
176 if (!TheBaseClass::IsValid())
180 TheBaseClass::Unbind (theGlCtx);
182 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
184 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
185 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
191 Graphic3d_Attribute Attribs[NbAttributes];
192 Standard_Integer Stride;
196 // =======================================================================
197 // function : clearMemoryGL
199 // =======================================================================
200 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
202 if (!myVboIndices.IsNull())
204 myVboIndices->Release (theGlCtx.operator->());
205 myVboIndices.Nullify();
207 if (!myVboAttribs.IsNull())
209 myVboAttribs->Release (theGlCtx.operator->());
210 myVboAttribs.Nullify();
214 // =======================================================================
215 // function : initNormalVbo
217 // =======================================================================
218 Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
220 switch (myAttribs->NbAttributes)
222 case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
223 case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
224 case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
225 case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
226 case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
227 case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
228 case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
229 case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
230 case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
231 case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
234 if (!myVboAttribs->init (theCtx, 0, myAttribs->NbElements, myAttribs->Data(), GL_NONE, myAttribs->Stride))
236 TCollection_ExtendedString aMsg;
237 aMsg += "VBO creation for Primitive Array has failed for ";
238 aMsg += myAttribs->NbElements;
239 aMsg += " vertices. Out of memory?";
240 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
242 clearMemoryGL (theCtx);
243 return Standard_False;
245 else if (myIndices.IsNull())
247 return Standard_True;
250 myVboIndices = new OpenGl_IndexBuffer();
252 switch (myIndices->Stride)
256 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data()));
261 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data()));
266 clearMemoryGL (theCtx);
267 return Standard_False;
272 TCollection_ExtendedString aMsg;
273 aMsg += "VBO creation for Primitive Array has failed for ";
274 aMsg += myIndices->NbElements;
275 aMsg += " indices. Out of memory?";
276 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
277 clearMemoryGL (theCtx);
278 return Standard_False;
280 return Standard_True;
283 // =======================================================================
284 // function : buildVBO
286 // =======================================================================
287 Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
288 const Standard_Boolean theToKeepData) const
290 bool isNormalMode = theCtx->ToUseVbo();
291 clearMemoryGL (theCtx);
292 if (myAttribs.IsNull()
293 || myAttribs->IsEmpty()
294 || myAttribs->NbElements < 1
295 || myAttribs->NbAttributes < 1
296 || myAttribs->NbAttributes > 10)
298 // vertices should be always defined - others are optional
299 return Standard_False;
303 && initNormalVbo (theCtx))
305 if (!theCtx->caps->keepArrayData
311 return Standard_True;
314 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
315 switch (myAttribs->NbAttributes)
317 case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
318 case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
319 case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
320 case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
321 case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
322 case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
323 case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
324 case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
325 case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
326 case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
328 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
329 if (!myIndices.IsNull())
331 Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
332 switch (myIndices->Stride)
336 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
341 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
346 return Standard_False;
349 myVboIndices = aVboIndices;
351 myVboAttribs = aVboAttribs;
352 if (!theCtx->caps->keepArrayData
355 // does not make sense for compatibility mode
356 //myIndices.Nullify();
357 //myAttribs.Nullify();
360 return Standard_True;
363 // =======================================================================
364 // function : drawArray
366 // =======================================================================
367 void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
368 const Graphic3d_Vec4* theFaceColors,
369 const Standard_Boolean theHasVertColor) const
371 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
372 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
373 bool hasVColors = theHasVertColor && !toHilight;
374 if (myVboAttribs.IsNull())
376 #if !defined(GL_ES_VERSION_2_0)
377 if (myDrawMode == GL_POINTS)
379 // extreme compatibility mode - without sprites but with markers
380 drawMarkers (theWorkspace);
386 myVboAttribs->BindAllAttributes (aGlContext);
387 if (theHasVertColor && toHilight)
389 // disable per-vertex color
390 OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
392 if (!myVboIndices.IsNull())
394 myVboIndices->Bind (aGlContext);
395 GLubyte* anOffset = myVboIndices->GetDataOffset();
396 if (!myBounds.IsNull())
398 // draw primitives by vertex count with the indices
399 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
400 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
402 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
403 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
404 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
405 anOffset += aStride * aNbElemsInGroup;
410 // draw one (or sequential) primitive by the indices
411 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
413 myVboIndices->Unbind (aGlContext);
415 else if (!myBounds.IsNull())
417 GLint aFirstElem = 0;
418 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
420 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
421 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
422 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
423 aFirstElem += aNbElemsInGroup;
428 if (myDrawMode == GL_POINTS)
430 drawMarkers (theWorkspace);
434 glDrawArrays (myDrawMode, 0, myVboAttribs->GetElemsNb());
439 myVboAttribs->UnbindAllAttributes (aGlContext);
443 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT;
447 // =======================================================================
448 // function : drawEdges
450 // =======================================================================
451 void OpenGl_PrimitiveArray::drawEdges (const TEL_COLOUR* theEdgeColour,
452 const Handle(OpenGl_Workspace)& theWorkspace) const
454 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
455 if (myVboAttribs.IsNull())
460 #if !defined(GL_ES_VERSION_2_0)
461 if (aGlContext->core11 != NULL)
463 glDisable (GL_LIGHTING);
467 const OpenGl_AspectLine* anAspectLineOld = NULL;
469 anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
470 const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True);
472 #if !defined(GL_ES_VERSION_2_0)
473 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
476 if (aGlContext->core20fwd != NULL)
478 aGlContext->ShaderManager()->BindProgram (anAspect, NULL, Standard_False, Standard_False, anAspect->ShaderProgramRes (aGlContext));
481 /// OCC22236 NOTE: draw edges for all situations:
482 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
483 /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
484 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
485 myVboAttribs->BindPositionAttribute (aGlContext);
487 aGlContext->SetColor4fv (*(const OpenGl_Vec4* )theEdgeColour->rgb);
488 aGlContext->SetTypeOfLine (anAspect->Type());
489 aGlContext->SetLineWidth (anAspect->Width());
491 if (!myVboIndices.IsNull())
493 myVboIndices->Bind (aGlContext);
494 GLubyte* anOffset = myVboIndices->GetDataOffset();
496 // draw primitives by vertex count with the indices
497 if (!myBounds.IsNull())
499 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
500 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
502 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
503 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
504 anOffset += aStride * aNbElemsInGroup;
507 // draw one (or sequential) primitive by the indices
510 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
512 myVboIndices->Unbind (aGlContext);
514 else if (!myBounds.IsNull())
516 GLint aFirstElem = 0;
517 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
519 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
520 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
521 aFirstElem += aNbElemsInGroup;
526 glDrawArrays (myDrawMode, 0, myAttribs->NbElements);
530 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
532 // restore line context
533 theWorkspace->SetAspectLine (anAspectLineOld);
536 // =======================================================================
537 // function : drawMarkers
539 // =======================================================================
540 void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
542 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True);
543 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
544 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
545 if (!aSpriteNorm.IsNull()
546 && !aSpriteNorm->IsDisplayList())
548 // Textured markers will be drawn with the point sprites
549 aCtx->SetPointSize (anAspectMarker->MarkerSize());
550 #if !defined(GL_ES_VERSION_2_0)
551 if (aCtx->core11 != NULL)
553 aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
554 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
558 aCtx->core11fwd->glEnable (GL_BLEND);
559 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
561 aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
563 aCtx->core11fwd->glDisable (GL_BLEND);
564 #if !defined(GL_ES_VERSION_2_0)
565 if (aCtx->core11 != NULL)
567 aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
570 aCtx->SetPointSize (1.0f);
573 else if (anAspectMarker->Type() == Aspect_TOM_POINT)
575 aCtx->SetPointSize (anAspectMarker->MarkerSize());
576 aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
577 aCtx->SetPointSize (1.0f);
579 #if !defined(GL_ES_VERSION_2_0)
580 // Textured markers will be drawn with the glBitmap
581 else if (anAspectMarker->Type() != Aspect_TOM_POINT
582 && !aSpriteNorm.IsNull())
584 /**if (!isHilight && (myPArray->vcolours != NULL))
586 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
588 glColor4ubv (myPArray->vcolours[anIter].GetData());
589 glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
590 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
595 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
597 aCtx->core11->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
598 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
605 // =======================================================================
606 // function : OpenGl_PrimitiveArray
608 // =======================================================================
609 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver)
611 : myDrawMode (DRAW_MODE_NONE),
612 myIsVboInit (Standard_False)
614 if (theDriver != NULL)
616 myUID = theDriver->GetNextPrimitiveArrayUID();
620 // =======================================================================
621 // function : OpenGl_PrimitiveArray
623 // =======================================================================
624 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
625 const Graphic3d_TypeOfPrimitiveArray theType,
626 const Handle(Graphic3d_IndexBuffer)& theIndices,
627 const Handle(Graphic3d_Buffer)& theAttribs,
628 const Handle(Graphic3d_BoundBuffer)& theBounds)
630 : myIndices (theIndices),
631 myAttribs (theAttribs),
632 myBounds (theBounds),
633 myDrawMode (DRAW_MODE_NONE),
634 myIsVboInit (Standard_False)
636 if (!myIndices.IsNull()
637 && myIndices->NbElements < 1)
639 // dummy index buffer?
643 if (theDriver != NULL)
645 myUID = theDriver->GetNextPrimitiveArrayUID();
646 #if defined (GL_ES_VERSION_2_0)
647 const Handle(OpenGl_Context)& aCtx = theDriver->GetSharedContext();
650 processIndices (aCtx);
655 setDrawMode (theType);
658 // =======================================================================
659 // function : ~OpenGl_PrimitiveArray
661 // =======================================================================
662 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
667 // =======================================================================
668 // function : Release
670 // =======================================================================
671 void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
673 myIsVboInit = Standard_False;
674 if (!myVboIndices.IsNull())
678 theContext->DelayedRelease (myVboIndices);
680 myVboIndices.Nullify();
682 if (!myVboAttribs.IsNull())
686 theContext->DelayedRelease (myVboAttribs);
688 myVboAttribs.Nullify();
692 // =======================================================================
695 // =======================================================================
696 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
698 if (myDrawMode == DRAW_MODE_NONE)
703 const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True);
704 const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
705 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myDrawMode == GL_POINTS);
707 // create VBOs on first render call
708 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
711 // compatibility - keep data to draw markers using display lists
712 const Standard_Boolean toKeepData = myDrawMode == GL_POINTS
713 && !anAspectMarker->SpriteRes (aCtx).IsNull()
714 && anAspectMarker->SpriteRes (aCtx)->IsDisplayList();
715 #if defined (GL_ES_VERSION_2_0)
716 processIndices (aCtx);
718 buildVBO (aCtx, toKeepData);
719 myIsVboInit = Standard_True;
722 Tint aFrontLightingModel = anAspectFace->IntFront().color_mask;
723 const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront().matcol;
724 const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
725 const TEL_COLOUR* aLineColor = myDrawMode == GL_POINTS ? &anAspectMarker->Color() : &anAspectLine->Color();
727 // Use highlight colors
728 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
730 anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
731 aFrontLightingModel = 0;
734 const Standard_Boolean hasColorAttrib = !myVboAttribs.IsNull()
735 && myVboAttribs->HasColorAttribute();
736 const Standard_Boolean isLightOn = aFrontLightingModel != 0
737 && !myVboAttribs.IsNull()
738 && myVboAttribs->HasNormalAttribute();
739 #if !defined(GL_ES_VERSION_2_0)
740 // manage FFP lighting
741 if (aCtx->core11 != NULL)
745 glDisable (GL_LIGHTING);
749 glEnable (GL_LIGHTING);
753 // Temporarily disable environment mapping
754 Handle(OpenGl_Texture) aTextureBack;
755 if (myDrawMode <= GL_LINE_STRIP)
757 aTextureBack = theWorkspace->DisableTexture();
760 if ((myDrawMode > GL_LINE_STRIP && anAspectFace->InteriorStyle() != Aspect_IS_EMPTY) ||
761 (myDrawMode <= GL_LINE_STRIP))
763 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
764 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->InteriorStyle() != Aspect_IS_HIDDENLINE
767 const Standard_Boolean hasVertColor = hasColorAttrib && !toHilight;
768 if (aCtx->core20fwd != NULL)
774 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
775 if (!aSpriteNorm.IsNull()
776 && !aSpriteNorm->IsDisplayList())
778 const Handle(OpenGl_PointSprite)& aSprite = (toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->IsValid())
779 ? anAspectMarker->SpriteHighlightRes (aCtx)
781 theWorkspace->EnableTexture (aSprite);
782 aCtx->ShaderManager()->BindProgram (anAspectMarker, aSprite, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
786 aCtx->ShaderManager()->BindProgram (anAspectMarker, NULL, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
793 aCtx->ShaderManager()->BindProgram (anAspectLine, NULL, isLightOn, hasVertColor, anAspectLine->ShaderProgramRes (aCtx));
798 const Standard_Boolean isLightOnFace = isLightOn
799 && (theWorkspace->ActiveTexture().IsNull()
800 || theWorkspace->ActiveTexture()->GetParams()->IsModulate());
801 aCtx->ShaderManager()->BindProgram (anAspectFace, theWorkspace->ActiveTexture(), isLightOnFace, hasVertColor, anAspectFace->ShaderProgramRes (aCtx));
807 aCtx->SetColor4fv (*(const OpenGl_Vec4* )(myDrawMode <= GL_LINE_STRIP ? aLineColor->rgb : anInteriorColor->rgb));
808 if (myDrawMode == GL_LINES
809 || myDrawMode == GL_LINE_STRIP)
811 aCtx->SetTypeOfLine (anAspectLine->Type());
812 aCtx->SetLineWidth (anAspectLine->Width());
815 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
818 if (myDrawMode <= GL_LINE_STRIP)
820 theWorkspace->EnableTexture (aTextureBack);
824 if (anAspectFace->Edge()
825 || anAspectFace->InteriorStyle() == Aspect_IS_HIDDENLINE)
827 drawEdges (anEdgeColor, theWorkspace);
829 // restore OpenGL polygon mode if needed
830 #if !defined(GL_ES_VERSION_2_0)
831 if (anAspectFace->InteriorStyle() >= Aspect_IS_HATCH)
833 glPolygonMode (GL_FRONT_AND_BACK,
834 anAspectFace->InteriorStyle() == Aspect_IS_POINT ? GL_POINT : GL_FILL);
840 aCtx->BindProgram (NULL);
843 // =======================================================================
844 // function : setDrawMode
846 // =======================================================================
847 void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType)
849 if (myAttribs.IsNull())
851 myDrawMode = DRAW_MODE_NONE;
857 case Graphic3d_TOPA_POINTS:
858 myDrawMode = GL_POINTS;
860 case Graphic3d_TOPA_POLYLINES:
861 myDrawMode = GL_LINE_STRIP;
863 case Graphic3d_TOPA_SEGMENTS:
864 myDrawMode = GL_LINES;
866 case Graphic3d_TOPA_TRIANGLES:
867 myDrawMode = GL_TRIANGLES;
869 case Graphic3d_TOPA_TRIANGLESTRIPS:
870 myDrawMode = GL_TRIANGLE_STRIP;
872 case Graphic3d_TOPA_TRIANGLEFANS:
873 myDrawMode = GL_TRIANGLE_FAN;
875 #if !defined(GL_ES_VERSION_2_0)
876 case Graphic3d_TOPA_POLYGONS:
877 myDrawMode = GL_POLYGON;
879 case Graphic3d_TOPA_QUADRANGLES:
880 myDrawMode = GL_QUADS;
882 case Graphic3d_TOPA_QUADRANGLESTRIPS:
883 myDrawMode = GL_QUAD_STRIP;
886 case Graphic3d_TOPA_POLYGONS:
887 case Graphic3d_TOPA_QUADRANGLES:
888 case Graphic3d_TOPA_QUADRANGLESTRIPS:
890 case Graphic3d_TOPA_UNDEFINED:
895 // =======================================================================
896 // function : processIndices
898 // =======================================================================
899 Standard_Boolean OpenGl_PrimitiveArray::processIndices (const Handle(OpenGl_Context)& theContext) const
901 if (myIndices.IsNull()
902 || theContext->hasUintIndex)
904 return Standard_True;
907 if (myIndices->NbElements > std::numeric_limits<GLushort>::max())
909 Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (new NCollection_AlignedAllocator (16));
910 if (!anAttribs->Init (myIndices->NbElements, myAttribs->AttributesArray(), myAttribs->NbAttributes))
912 return Standard_False; // failed to initialize attribute array
915 for (Standard_Integer anIdxIdx = 0; anIdxIdx < myIndices->NbElements; ++anIdxIdx)
917 const Standard_Integer anIndex = myIndices->Index (anIdxIdx);
918 memcpy (anAttribs->ChangeData() + myAttribs->Stride * anIdxIdx,
919 myAttribs->Data() + myAttribs->Stride * anIndex,
924 myAttribs = anAttribs;
927 return Standard_True;
930 // =======================================================================
931 // function : InitBuffers
933 // =======================================================================
934 void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& theContext,
935 const Graphic3d_TypeOfPrimitiveArray theType,
936 const Handle(Graphic3d_IndexBuffer)& theIndices,
937 const Handle(Graphic3d_Buffer)& theAttribs,
938 const Handle(Graphic3d_BoundBuffer)& theBounds)
940 // Release old graphic resources
941 Release (theContext.operator->());
943 myIndices = theIndices;
944 myAttribs = theAttribs;
945 myBounds = theBounds;
946 #if defined(GL_ES_VERSION_2_0)
947 processIndices (theContext);
950 setDrawMode (theType);