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_Sampler.hxx>
23 #include <OpenGl_ShaderManager.hxx>
24 #include <OpenGl_ShaderProgram.hxx>
25 #include <OpenGl_Structure.hxx>
26 #include <OpenGl_VertexBufferCompat.hxx>
27 #include <OpenGl_Workspace.hxx>
28 #include <Graphic3d_TextureParams.hxx>
29 #include <NCollection_AlignedAllocator.hxx>
33 //! Convert data type to GL info
34 inline GLenum toGlDataType (const Graphic3d_TypeOfData theType,
39 case Graphic3d_TOD_USHORT:
41 return GL_UNSIGNED_SHORT;
42 case Graphic3d_TOD_UINT:
44 return GL_UNSIGNED_INT;
45 case Graphic3d_TOD_VEC2:
48 case Graphic3d_TOD_VEC3:
51 case Graphic3d_TOD_VEC4:
54 case Graphic3d_TOD_VEC4UB:
56 return GL_UNSIGNED_BYTE;
57 case Graphic3d_TOD_FLOAT:
67 //! Auxiliary template for VBO with interleaved attributes.
68 template<class TheBaseClass, int NbAttributes>
69 class OpenGl_VertexBufferT : public TheBaseClass
74 //! Create uninitialized VBO.
75 OpenGl_VertexBufferT (const Graphic3d_Attribute* theAttribs,
76 const Standard_Integer theStride)
79 memcpy (Attribs, theAttribs, sizeof(Graphic3d_Attribute) * NbAttributes);
82 //! Create uninitialized VBO.
83 OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
84 : Stride (theAttribs.Stride)
86 memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
89 virtual bool HasColorAttribute() const
91 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
93 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
94 if (anAttrib.Id == Graphic3d_TOA_COLOR)
102 virtual bool HasNormalAttribute() const
104 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
106 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
107 if (anAttrib.Id == Graphic3d_TOA_NORM)
115 virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
117 if (!TheBaseClass::IsValid())
122 TheBaseClass::Bind (theGlCtx);
124 const GLubyte* anOffset = TheBaseClass::myOffset;
125 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
127 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
128 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
129 if (aDataType == GL_NONE)
133 else if (anAttrib.Id == Graphic3d_TOA_POS)
135 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
139 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
143 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
145 if (!TheBaseClass::IsValid())
150 TheBaseClass::Bind (theGlCtx);
152 const GLubyte* anOffset = TheBaseClass::myOffset;
153 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
155 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
156 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
157 if (aDataType == GL_NONE)
162 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
163 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
167 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
169 if (!TheBaseClass::IsValid())
173 TheBaseClass::Unbind (theGlCtx);
175 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
177 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
178 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
184 Graphic3d_Attribute Attribs[NbAttributes];
185 Standard_Integer Stride;
189 // =======================================================================
190 // function : clearMemoryGL
192 // =======================================================================
193 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
195 if (!myVboIndices.IsNull())
197 myVboIndices->Release (theGlCtx.operator->());
198 myVboIndices.Nullify();
200 if (!myVboAttribs.IsNull())
202 myVboAttribs->Release (theGlCtx.operator->());
203 myVboAttribs.Nullify();
207 // =======================================================================
208 // function : initNormalVbo
210 // =======================================================================
211 Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
213 switch (myAttribs->NbAttributes)
215 case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
216 case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
217 case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
218 case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
219 case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
220 case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
221 case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
222 case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
223 case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
224 case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
227 // specify data type as Byte and NbComponents as Stride, so that OpenGl_VertexBuffer::EstimatedDataSize() will return correct value
228 if (!myVboAttribs->init (theCtx, myAttribs->Stride, myAttribs->NbElements, myAttribs->Data(), GL_UNSIGNED_BYTE, myAttribs->Stride))
230 TCollection_ExtendedString aMsg;
231 aMsg += "VBO creation for Primitive Array has failed for ";
232 aMsg += myAttribs->NbElements;
233 aMsg += " vertices. Out of memory?";
234 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
236 clearMemoryGL (theCtx);
237 return Standard_False;
239 else if (myIndices.IsNull())
241 return Standard_True;
244 myVboIndices = new OpenGl_IndexBuffer();
246 switch (myIndices->Stride)
250 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data()));
255 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data()));
260 clearMemoryGL (theCtx);
261 return Standard_False;
266 TCollection_ExtendedString aMsg;
267 aMsg += "VBO creation for Primitive Array has failed for ";
268 aMsg += myIndices->NbElements;
269 aMsg += " indices. Out of memory?";
270 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
271 clearMemoryGL (theCtx);
272 return Standard_False;
274 return Standard_True;
277 // =======================================================================
278 // function : buildVBO
280 // =======================================================================
281 Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
282 const Standard_Boolean theToKeepData) const
284 bool isNormalMode = theCtx->ToUseVbo();
285 clearMemoryGL (theCtx);
286 if (myAttribs.IsNull()
287 || myAttribs->IsEmpty()
288 || myAttribs->NbElements < 1
289 || myAttribs->NbAttributes < 1
290 || myAttribs->NbAttributes > 10)
292 // vertices should be always defined - others are optional
293 return Standard_False;
297 && initNormalVbo (theCtx))
299 if (!theCtx->caps->keepArrayData
305 return Standard_True;
308 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
309 switch (myAttribs->NbAttributes)
311 case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
312 case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
313 case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
314 case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
315 case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
316 case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
317 case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
318 case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
319 case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
320 case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
322 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
323 if (!myIndices.IsNull())
325 Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
326 switch (myIndices->Stride)
330 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
335 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
340 return Standard_False;
343 myVboIndices = aVboIndices;
345 myVboAttribs = aVboAttribs;
346 if (!theCtx->caps->keepArrayData
349 // does not make sense for compatibility mode
350 //myIndices.Nullify();
351 //myAttribs.Nullify();
354 return Standard_True;
357 // =======================================================================
358 // function : drawArray
360 // =======================================================================
361 void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
362 const Graphic3d_Vec4* theFaceColors,
363 const Standard_Boolean theHasVertColor) const
365 if (myVboAttribs.IsNull())
367 #if !defined(GL_ES_VERSION_2_0)
368 if (myDrawMode == GL_POINTS)
370 // extreme compatibility mode - without sprites but with markers
371 drawMarkers (theWorkspace);
377 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
378 const bool toHilight = theWorkspace->ToHighlight();
379 const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull()
380 && aGlContext->ActiveProgram()->HasTessellationStage()
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 (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
402 anOffset += aStride * aNbElemsInGroup;
407 // draw one (or sequential) primitive by the indices
408 glDrawElements (aDrawMode, 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 (aDrawMode, aFirstElem, aNbElemsInGroup);
420 aFirstElem += aNbElemsInGroup;
425 if (myDrawMode == GL_POINTS)
427 drawMarkers (theWorkspace);
431 glDrawArrays (aDrawMode, 0, myVboAttribs->GetElemsNb());
436 myVboAttribs->UnbindAllAttributes (aGlContext);
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 const OpenGl_AspectLine* anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace()->AspectEdge());
453 const OpenGl_AspectLine* anAspect = theWorkspace->ApplyAspectLine();
455 #if !defined(GL_ES_VERSION_2_0)
456 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
459 if (aGlContext->core20fwd != NULL)
461 aGlContext->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), anAspect->Aspect()->Type(),
462 Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, Standard_False,
463 anAspect->ShaderProgramRes (aGlContext));
465 const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull()
466 && aGlContext->ActiveProgram()->HasTessellationStage()
469 #if !defined(GL_ES_VERSION_2_0)
470 if (aGlContext->ActiveProgram().IsNull()
471 && aGlContext->core11 != NULL)
473 glDisable (GL_LIGHTING);
477 /// OCC22236 NOTE: draw edges for all situations:
478 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
479 /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
480 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
481 myVboAttribs->BindPositionAttribute (aGlContext);
483 aGlContext->SetColor4fv (theEdgeColour);
484 aGlContext->SetTypeOfLine (anAspect->Aspect()->Type());
485 aGlContext->SetLineWidth (anAspect->Aspect()->Width());
487 if (!myVboIndices.IsNull())
489 myVboIndices->Bind (aGlContext);
490 GLubyte* anOffset = myVboIndices->GetDataOffset();
492 // draw primitives by vertex count with the indices
493 if (!myBounds.IsNull())
495 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
496 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
498 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
499 glDrawElements (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
500 anOffset += aStride * aNbElemsInGroup;
503 // draw one (or sequential) primitive by the indices
506 glDrawElements (aDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
508 myVboIndices->Unbind (aGlContext);
510 else if (!myBounds.IsNull())
512 GLint aFirstElem = 0;
513 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
515 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
516 glDrawArrays (aDrawMode, aFirstElem, aNbElemsInGroup);
517 aFirstElem += aNbElemsInGroup;
522 glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
526 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
528 // restore line context
529 theWorkspace->SetAspectLine (anAspectLineOld);
532 // =======================================================================
533 // function : drawMarkers
535 // =======================================================================
536 void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
538 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->ApplyAspectMarker();
539 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
540 const GLenum aDrawMode = !aCtx->ActiveProgram().IsNull()
541 && aCtx->ActiveProgram()->HasTessellationStage()
545 const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectMarker->SpriteRes (aCtx);
546 const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast<const OpenGl_PointSprite*> (aSpriteNormRes->First().get()) : NULL;
547 if (aSpriteNorm != NULL
548 && !aSpriteNorm->IsDisplayList())
550 // Textured markers will be drawn with the point sprites
551 aCtx->SetPointSize (anAspectMarker->MarkerSize());
552 aCtx->SetPointSpriteOrigin();
553 #if !defined(GL_ES_VERSION_2_0)
554 if (aCtx->core11 != NULL)
556 aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
557 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
561 aCtx->core11fwd->glEnable (GL_BLEND);
562 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
564 aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
566 aCtx->core11fwd->glDisable (GL_BLEND);
567 #if !defined(GL_ES_VERSION_2_0)
568 if (aCtx->core11 != NULL)
570 if (aCtx->ShaderManager()->MaterialState().AlphaCutoff() >= ShortRealLast())
572 aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
576 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, aCtx->ShaderManager()->MaterialState().AlphaCutoff());
580 aCtx->SetPointSize (1.0f);
583 else if (anAspectMarker->Aspect()->Type() == Aspect_TOM_POINT)
585 aCtx->SetPointSize (anAspectMarker->MarkerSize());
586 aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
587 aCtx->SetPointSize (1.0f);
589 #if !defined(GL_ES_VERSION_2_0)
590 // Textured markers will be drawn with the glBitmap
591 else if (anAspectMarker->Aspect()->Type() != Aspect_TOM_POINT
592 && aSpriteNorm != NULL)
594 /**if (!isHilight && (myPArray->vcolours != NULL))
596 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
598 glColor4ubv (myPArray->vcolours[anIter].GetData());
599 glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
600 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
605 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
607 aCtx->core11->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
608 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
615 // =======================================================================
616 // function : OpenGl_PrimitiveArray
618 // =======================================================================
619 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver)
621 : myDrawMode (DRAW_MODE_NONE),
622 myIsFillType(Standard_False),
623 myIsVboInit (Standard_False)
625 if (theDriver != NULL)
627 myUID = theDriver->GetNextPrimitiveArrayUID();
631 // =======================================================================
632 // function : OpenGl_PrimitiveArray
634 // =======================================================================
635 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
636 const Graphic3d_TypeOfPrimitiveArray theType,
637 const Handle(Graphic3d_IndexBuffer)& theIndices,
638 const Handle(Graphic3d_Buffer)& theAttribs,
639 const Handle(Graphic3d_BoundBuffer)& theBounds)
641 : myIndices (theIndices),
642 myAttribs (theAttribs),
643 myBounds (theBounds),
644 myDrawMode (DRAW_MODE_NONE),
645 myIsFillType(Standard_False),
646 myIsVboInit (Standard_False)
648 if (!myIndices.IsNull()
649 && myIndices->NbElements < 1)
651 // dummy index buffer?
655 if (theDriver != NULL)
657 myUID = theDriver->GetNextPrimitiveArrayUID();
658 #if defined (GL_ES_VERSION_2_0)
659 const Handle(OpenGl_Context)& aCtx = theDriver->GetSharedContext();
662 processIndices (aCtx);
667 setDrawMode (theType);
670 // =======================================================================
671 // function : ~OpenGl_PrimitiveArray
673 // =======================================================================
674 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
679 // =======================================================================
680 // function : Release
682 // =======================================================================
683 void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
685 myIsVboInit = Standard_False;
686 if (!myVboIndices.IsNull())
690 theContext->DelayedRelease (myVboIndices);
692 myVboIndices.Nullify();
694 if (!myVboAttribs.IsNull())
698 theContext->DelayedRelease (myVboAttribs);
700 myVboAttribs.Nullify();
704 // =======================================================================
707 // =======================================================================
708 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
710 if (myDrawMode == DRAW_MODE_NONE)
715 const OpenGl_AspectFace* anAspectFace = theWorkspace->ApplyAspectFace();
716 const OpenGl_AspectLine* anAspectLine = theWorkspace->ApplyAspectLine();
717 const OpenGl_AspectMarker* anAspectMarker = myDrawMode == GL_POINTS
718 ? theWorkspace->ApplyAspectMarker()
719 : theWorkspace->AspectMarker();
721 // create VBOs on first render call
722 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
725 // compatibility - keep data to draw markers using display lists
726 Standard_Boolean toKeepData = Standard_False;
727 if (myDrawMode == GL_POINTS)
729 const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectMarker->SpriteRes (aCtx);
730 const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast<const OpenGl_PointSprite*> (aSpriteNormRes->First().get()) : NULL;
731 toKeepData = aSpriteNorm != NULL
732 && aSpriteNorm->IsDisplayList();
734 #if defined (GL_ES_VERSION_2_0)
735 processIndices (aCtx);
737 buildVBO (aCtx, toKeepData);
738 myIsVboInit = Standard_True;
741 // Temporarily disable environment mapping
742 Handle(OpenGl_TextureSet) aTextureBack;
743 bool toDrawArray = true;
744 if (myDrawMode > GL_LINE_STRIP)
746 toDrawArray = anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_EMPTY;
748 else if (myDrawMode <= GL_LINE_STRIP)
750 aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
751 if (myDrawMode == GL_POINTS)
753 toDrawArray = anAspectMarker->Aspect()->Type() != Aspect_TOM_EMPTY;
757 toDrawArray = anAspectLine->Aspect()->Type() != Aspect_TOL_EMPTY;
761 Graphic3d_TypeOfShadingModel aShadingModel = Graphic3d_TOSM_UNLIT;
764 const bool hasColorAttrib = !myVboAttribs.IsNull()
765 && myVboAttribs->HasColorAttribute();
766 const bool toHilight = theWorkspace->ToHighlight();
767 const bool hasVertColor = hasColorAttrib && !toHilight;
768 const bool hasVertNorm = !myVboAttribs.IsNull() && myVboAttribs->HasNormalAttribute();
773 aShadingModel = aCtx->ShaderManager()->ChooseMarkerShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
774 const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectMarker->SpriteRes (aCtx);
775 const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast<const OpenGl_PointSprite*> (aSpriteNormRes->First().get()) : NULL;
776 if (aSpriteNorm != NULL
777 && !aSpriteNorm->IsDisplayList())
779 const Handle(OpenGl_TextureSet)& aSprite = toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->First()->IsValid()
780 ? anAspectMarker->SpriteHighlightRes (aCtx)
782 aCtx->BindTextures (aSprite);
783 aCtx->ShaderManager()->BindMarkerProgram (aSprite, aShadingModel, Graphic3d_AlphaMode_Opaque, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
787 aCtx->ShaderManager()->BindMarkerProgram (Handle(OpenGl_TextureSet)(), aShadingModel, Graphic3d_AlphaMode_Opaque, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
794 aShadingModel = aCtx->ShaderManager()->ChooseLineShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
795 aCtx->ShaderManager()->BindLineProgram (NULL,
796 anAspectLine->Aspect()->Type(),
798 Graphic3d_AlphaMode_Opaque,
800 anAspectLine->ShaderProgramRes (aCtx));
805 aShadingModel = aCtx->ShaderManager()->ChooseFaceShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
806 const Handle(OpenGl_TextureSet)& aTextures = aCtx->ActiveTextures();
807 const Standard_Boolean toEnableEnvMap = (!aTextures.IsNull() && (aTextures == theWorkspace->EnvironmentTexture()));
808 aCtx->ShaderManager()->BindFaceProgram (aTextures,
810 anAspectFace->Aspect()->AlphaMode(),
813 anAspectFace->ShaderProgramRes (aCtx));
818 #if !defined(GL_ES_VERSION_2_0)
819 // manage FFP lighting
820 if (aCtx->ActiveProgram().IsNull()
821 && aCtx->core11 != NULL)
823 if (aShadingModel == Graphic3d_TOSM_UNLIT)
825 glDisable (GL_LIGHTING);
829 glEnable (GL_LIGHTING);
834 if (!aCtx->ActiveTextures().IsNull()
835 && !aCtx->ActiveTextures()->IsEmpty()
836 && !aCtx->ActiveTextures()->First().IsNull()
837 && myDrawMode != GL_POINTS) // transformation is not supported within point sprites
839 aCtx->SetTextureMatrix (aCtx->ActiveTextures()->First()->Sampler()->Parameters());
842 if (myDrawMode <= GL_LINE_STRIP)
844 const OpenGl_Vec4& aLineColor = myDrawMode == GL_POINTS ? theWorkspace->MarkerColor() : theWorkspace->LineColor();
845 aCtx->SetColor4fv (aLineColor);
849 const OpenGl_Vec4& anInteriorColor = theWorkspace->InteriorColor();
850 aCtx->SetColor4fv (anInteriorColor);
852 if (myDrawMode == GL_LINES
853 || myDrawMode == GL_LINE_STRIP)
855 aCtx->SetTypeOfLine (anAspectLine->Aspect()->Type());
856 aCtx->SetLineWidth (anAspectLine->Aspect()->Width());
859 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_HIDDENLINE
862 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
865 if (myDrawMode <= GL_LINE_STRIP)
867 aCtx->BindTextures (aTextureBack);
871 if (anAspectFace->Aspect()->ToDrawEdges()
872 || anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE)
874 const OpenGl_Vec4& anEdgeColor = theWorkspace->EdgeColor();
875 drawEdges (anEdgeColor, theWorkspace);
877 // restore OpenGL polygon mode if needed
878 #if !defined(GL_ES_VERSION_2_0)
879 if (anAspectFace->Aspect()->InteriorStyle() >= Aspect_IS_HATCH)
881 glPolygonMode (GL_FRONT_AND_BACK,
882 anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_POINT ? GL_POINT : GL_FILL);
889 // =======================================================================
890 // function : setDrawMode
892 // =======================================================================
893 void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType)
895 if (myAttribs.IsNull())
897 myDrawMode = DRAW_MODE_NONE;
898 myIsFillType = false;
904 case Graphic3d_TOPA_POINTS:
905 myDrawMode = GL_POINTS;
906 myIsFillType = false;
908 case Graphic3d_TOPA_SEGMENTS:
909 myDrawMode = GL_LINES;
910 myIsFillType = false;
912 case Graphic3d_TOPA_POLYLINES:
913 myDrawMode = GL_LINE_STRIP;
914 myIsFillType = false;
916 case Graphic3d_TOPA_TRIANGLES:
917 myDrawMode = GL_TRIANGLES;
920 case Graphic3d_TOPA_TRIANGLESTRIPS:
921 myDrawMode = GL_TRIANGLE_STRIP;
924 case Graphic3d_TOPA_TRIANGLEFANS:
925 myDrawMode = GL_TRIANGLE_FAN;
929 case Graphic3d_TOPA_LINES_ADJACENCY:
930 myDrawMode = GL_LINES_ADJACENCY;
931 myIsFillType = false;
933 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
934 myDrawMode = GL_LINE_STRIP_ADJACENCY;
935 myIsFillType = false;
937 case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
938 myDrawMode = GL_TRIANGLES_ADJACENCY;
941 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
942 myDrawMode = GL_TRIANGLE_STRIP_ADJACENCY;
946 #if !defined(GL_ES_VERSION_2_0)
947 case Graphic3d_TOPA_QUADRANGLES:
948 myDrawMode = GL_QUADS;
951 case Graphic3d_TOPA_QUADRANGLESTRIPS:
952 myDrawMode = GL_QUAD_STRIP;
955 case Graphic3d_TOPA_POLYGONS:
956 myDrawMode = GL_POLYGON;
960 case Graphic3d_TOPA_QUADRANGLES:
961 case Graphic3d_TOPA_QUADRANGLESTRIPS:
962 case Graphic3d_TOPA_POLYGONS:
964 case Graphic3d_TOPA_UNDEFINED:
965 myDrawMode = DRAW_MODE_NONE;
966 myIsFillType = false;
971 // =======================================================================
972 // function : processIndices
974 // =======================================================================
975 Standard_Boolean OpenGl_PrimitiveArray::processIndices (const Handle(OpenGl_Context)& theContext) const
977 if (myIndices.IsNull()
978 || myAttribs.IsNull()
979 || theContext->hasUintIndex)
981 return Standard_True;
984 if (myAttribs->NbElements > std::numeric_limits<GLushort>::max())
986 Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (new NCollection_AlignedAllocator (16));
987 if (!anAttribs->Init (myIndices->NbElements, myAttribs->AttributesArray(), myAttribs->NbAttributes))
989 return Standard_False; // failed to initialize attribute array
992 for (Standard_Integer anIdxIdx = 0; anIdxIdx < myIndices->NbElements; ++anIdxIdx)
994 const Standard_Integer anIndex = myIndices->Index (anIdxIdx);
995 memcpy (anAttribs->ChangeData() + myAttribs->Stride * anIdxIdx,
996 myAttribs->Data() + myAttribs->Stride * anIndex,
1000 myIndices.Nullify();
1001 myAttribs = anAttribs;
1004 return Standard_True;
1007 // =======================================================================
1008 // function : InitBuffers
1010 // =======================================================================
1011 void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& theContext,
1012 const Graphic3d_TypeOfPrimitiveArray theType,
1013 const Handle(Graphic3d_IndexBuffer)& theIndices,
1014 const Handle(Graphic3d_Buffer)& theAttribs,
1015 const Handle(Graphic3d_BoundBuffer)& theBounds)
1017 // Release old graphic resources
1018 Release (theContext.operator->());
1020 myIndices = theIndices;
1021 myAttribs = theAttribs;
1022 myBounds = theBounds;
1023 #if defined(GL_ES_VERSION_2_0)
1024 processIndices (theContext);
1027 setDrawMode (theType);