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>
31 //! Convert index data type from size
32 inline GLenum toGlIndexType (const Standard_Integer theStride)
36 case 2: return GL_UNSIGNED_SHORT;
37 case 4: return GL_UNSIGNED_INT;
38 default: return GL_NONE;
42 //! Convert data type to GL info
43 inline GLenum toGlDataType (const Graphic3d_TypeOfData theType,
48 case Graphic3d_TOD_USHORT:
50 return GL_UNSIGNED_SHORT;
51 case Graphic3d_TOD_UINT:
53 return GL_UNSIGNED_INT;
54 case Graphic3d_TOD_VEC2:
57 case Graphic3d_TOD_VEC3:
60 case Graphic3d_TOD_VEC4:
63 case Graphic3d_TOD_VEC4UB:
65 return GL_UNSIGNED_BYTE;
73 //! Auxiliary template for VBO with interleaved attributes.
74 template<class TheBaseClass, int NbAttributes>
75 class OpenGl_VertexBufferT : public TheBaseClass
80 //! Create uninitialized VBO.
81 OpenGl_VertexBufferT (const Graphic3d_Attribute* theAttribs,
82 const Standard_Integer theStride)
85 memcpy (Attribs, theAttribs, sizeof(Graphic3d_Attribute) * NbAttributes);
88 //! Create uninitialized VBO.
89 OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
90 : Stride (theAttribs.Stride)
92 memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
95 virtual bool HasColorAttribute() const
97 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
99 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
100 if (anAttrib.Id == Graphic3d_TOA_COLOR)
108 virtual bool HasNormalAttribute() const
110 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
112 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
113 if (anAttrib.Id == Graphic3d_TOA_NORM)
121 virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
123 if (!TheBaseClass::IsValid())
128 TheBaseClass::Bind (theGlCtx);
130 const GLubyte* anOffset = TheBaseClass::myOffset;
131 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
133 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
134 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
135 if (aDataType == GL_NONE)
139 else if (anAttrib.Id == Graphic3d_TOA_POS)
141 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
145 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
149 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
151 if (!TheBaseClass::IsValid())
156 TheBaseClass::Bind (theGlCtx);
158 const GLubyte* anOffset = TheBaseClass::myOffset;
159 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
161 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
162 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
163 if (aDataType == GL_NONE)
168 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
169 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
173 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
175 if (!TheBaseClass::IsValid())
179 TheBaseClass::Unbind (theGlCtx);
181 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
183 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
184 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
190 Graphic3d_Attribute Attribs[NbAttributes];
191 Standard_Integer Stride;
195 // =======================================================================
196 // function : clearMemoryGL
198 // =======================================================================
199 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
201 if (!myVboIndices.IsNull())
203 myVboIndices->Release (theGlCtx.operator->());
204 myVboIndices.Nullify();
206 if (!myVboAttribs.IsNull())
208 myVboAttribs->Release (theGlCtx.operator->());
209 myVboAttribs.Nullify();
213 // =======================================================================
214 // function : initNormalVbo
216 // =======================================================================
217 Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
219 switch (myAttribs->NbAttributes)
221 case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
222 case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
223 case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
224 case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
225 case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
226 case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
227 case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
228 case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
229 case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
230 case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
233 if (!myVboAttribs->init (theCtx, 0, myAttribs->NbElements, myAttribs->Data(), GL_NONE, myAttribs->Stride))
235 TCollection_ExtendedString aMsg;
236 aMsg += "VBO creation for Primitive Array has failed for ";
237 aMsg += myAttribs->NbElements;
238 aMsg += " vertices. Out of memory?";
239 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
241 clearMemoryGL (theCtx);
242 return Standard_False;
244 else if (myIndices.IsNull())
246 return Standard_True;
249 myVboIndices = new OpenGl_IndexBuffer();
251 switch (myIndices->Stride)
255 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data()));
260 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data()));
265 clearMemoryGL (theCtx);
266 return Standard_False;
271 TCollection_ExtendedString aMsg;
272 aMsg += "VBO creation for Primitive Array has failed for ";
273 aMsg += myIndices->NbElements;
274 aMsg += " indices. Out of memory?";
275 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
276 clearMemoryGL (theCtx);
277 return Standard_False;
279 return Standard_True;
282 // =======================================================================
283 // function : buildVBO
285 // =======================================================================
286 Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
287 const Standard_Boolean theToKeepData) const
289 bool isNormalMode = theCtx->ToUseVbo();
290 if (myAttribs.IsNull()
291 || myAttribs->IsEmpty()
292 || myAttribs->NbElements < 1
293 || myAttribs->NbAttributes < 1
294 || myAttribs->NbAttributes > 10)
296 // vertices should be always defined - others are optional
297 return Standard_False;
301 && initNormalVbo (theCtx))
303 if (!theCtx->caps->keepArrayData
309 return Standard_True;
312 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
313 switch (myAttribs->NbAttributes)
315 case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
316 case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
317 case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
318 case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
319 case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
320 case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
321 case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
322 case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
323 case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
324 case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
326 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
327 if (!myIndices.IsNull())
329 Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
330 switch (myIndices->Stride)
334 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
339 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
344 return Standard_False;
347 myVboIndices = aVboIndices;
349 myVboAttribs = aVboAttribs;
350 if (!theCtx->caps->keepArrayData
353 // does not make sense for compatibility mode
354 //myIndices.Nullify();
355 //myAttribs.Nullify();
358 return Standard_True;
361 // =======================================================================
362 // function : drawArray
364 // =======================================================================
365 void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
366 const Graphic3d_Vec4* theFaceColors,
367 const Standard_Boolean theHasVertColor) const
369 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
370 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
371 bool hasVColors = theHasVertColor && !toHilight;
372 if (myVboAttribs.IsNull())
374 #if !defined(GL_ES_VERSION_2_0)
375 if (myDrawMode == GL_POINTS)
377 // extreme compatibility mode - without sprites but with markers
378 drawMarkers (theWorkspace);
384 myVboAttribs->BindAllAttributes (aGlContext);
385 if (theHasVertColor && toHilight)
387 // disable per-vertex color
388 OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
390 if (!myVboIndices.IsNull())
392 myVboIndices->Bind (aGlContext);
393 GLubyte* anOffset = myVboIndices->GetDataOffset();
394 if (!myBounds.IsNull())
396 // draw primitives by vertex count with the indices
397 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
398 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
400 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
401 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
402 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
403 anOffset += aStride * aNbElemsInGroup;
408 // draw one (or sequential) primitive by the indices
409 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
411 myVboIndices->Unbind (aGlContext);
413 else if (!myBounds.IsNull())
415 GLint aFirstElem = 0;
416 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
418 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
419 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
420 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
421 aFirstElem += aNbElemsInGroup;
426 if (myDrawMode == GL_POINTS)
428 drawMarkers (theWorkspace);
432 glDrawArrays (myDrawMode, 0, myVboAttribs->GetElemsNb());
437 myVboAttribs->UnbindAllAttributes (aGlContext);
441 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT;
445 // =======================================================================
446 // function : drawEdges
448 // =======================================================================
449 void OpenGl_PrimitiveArray::drawEdges (const TEL_COLOUR* theEdgeColour,
450 const Handle(OpenGl_Workspace)& theWorkspace) const
452 if (myVboAttribs.IsNull())
457 #if !defined(GL_ES_VERSION_2_0)
458 glDisable (GL_LIGHTING);
461 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
462 const OpenGl_AspectLine* anAspectLineOld = NULL;
464 anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
465 const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True);
467 #if !defined(GL_ES_VERSION_2_0)
468 glPushAttrib (GL_POLYGON_BIT);
469 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
472 if (aGlContext->core20fwd != NULL)
474 aGlContext->ShaderManager()->BindProgram (anAspect, NULL, Standard_False, Standard_False, anAspect->ShaderProgramRes (aGlContext));
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);
482 aGlContext->SetColor4fv (*(const OpenGl_Vec4* )theEdgeColour->rgb);
483 if (!myVboIndices.IsNull())
485 myVboIndices->Bind (aGlContext);
486 GLubyte* anOffset = myVboIndices->GetDataOffset();
488 // draw primitives by vertex count with the indices
489 if (!myBounds.IsNull())
491 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
492 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
494 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
495 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
496 anOffset += aStride * aNbElemsInGroup;
499 // draw one (or sequential) primitive by the indices
502 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
504 myVboIndices->Unbind (aGlContext);
506 else if (!myBounds.IsNull())
508 GLint aFirstElem = 0;
509 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
511 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
512 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
513 aFirstElem += aNbElemsInGroup;
518 glDrawArrays (myDrawMode, 0, myAttribs->NbElements);
522 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
524 // restore line context
525 #if !defined(GL_ES_VERSION_2_0)
528 theWorkspace->SetAspectLine (anAspectLineOld);
531 // =======================================================================
532 // function : drawMarkers
534 // =======================================================================
535 void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
537 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True);
538 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
539 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
540 if (!aSpriteNorm.IsNull()
541 && !aSpriteNorm->IsDisplayList())
543 // Textured markers will be drawn with the point sprites
544 aCtx->SetPointSize (anAspectMarker->MarkerSize());
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->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->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,
605 const Graphic3d_TypeOfPrimitiveArray theType,
606 const Handle(Graphic3d_IndexBuffer)& theIndices,
607 const Handle(Graphic3d_Buffer)& theAttribs,
608 const Handle(Graphic3d_BoundBuffer)& theBounds)
610 : myIndices (theIndices),
611 myAttribs (theAttribs),
612 myBounds (theBounds),
613 myDrawMode (DRAW_MODE_NONE),
614 myIsVboInit (Standard_False)
616 if (theDriver != NULL)
618 myUID = theDriver->GetNextPrimitiveArrayUID();
621 if (!myIndices.IsNull()
622 && myIndices->NbElements < 1)
624 // dummy index buffer?
627 if (myAttribs.IsNull())
634 case Graphic3d_TOPA_POINTS:
635 myDrawMode = GL_POINTS;
637 case Graphic3d_TOPA_POLYLINES:
638 myDrawMode = GL_LINE_STRIP;
640 case Graphic3d_TOPA_SEGMENTS:
641 myDrawMode = GL_LINES;
643 case Graphic3d_TOPA_TRIANGLES:
644 myDrawMode = GL_TRIANGLES;
646 case Graphic3d_TOPA_TRIANGLESTRIPS:
647 myDrawMode = GL_TRIANGLE_STRIP;
649 case Graphic3d_TOPA_TRIANGLEFANS:
650 myDrawMode = GL_TRIANGLE_FAN;
652 #if !defined(GL_ES_VERSION_2_0)
653 case Graphic3d_TOPA_POLYGONS:
654 myDrawMode = GL_POLYGON;
656 case Graphic3d_TOPA_QUADRANGLES:
657 myDrawMode = GL_QUADS;
659 case Graphic3d_TOPA_QUADRANGLESTRIPS:
660 myDrawMode = GL_QUAD_STRIP;
663 case Graphic3d_TOPA_POLYGONS:
664 case Graphic3d_TOPA_QUADRANGLES:
665 case Graphic3d_TOPA_QUADRANGLESTRIPS:
667 case Graphic3d_TOPA_UNDEFINED:
672 // =======================================================================
673 // function : ~OpenGl_PrimitiveArray
675 // =======================================================================
676 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
681 // =======================================================================
682 // function : Release
684 // =======================================================================
685 void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
687 myIsVboInit = Standard_False;
688 if (!myVboIndices.IsNull())
692 theContext->DelayedRelease (myVboIndices);
694 myVboIndices.Nullify();
696 if (!myVboAttribs.IsNull())
700 theContext->DelayedRelease (myVboAttribs);
702 myVboAttribs.Nullify();
706 // =======================================================================
709 // =======================================================================
710 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
712 if (myDrawMode == DRAW_MODE_NONE)
717 const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True);
718 const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
719 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myDrawMode == GL_POINTS);
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 const Standard_Boolean toKeepData = myDrawMode == GL_POINTS
727 && !anAspectMarker->SpriteRes (aCtx).IsNull()
728 && anAspectMarker->SpriteRes (aCtx)->IsDisplayList();
729 buildVBO (aCtx, toKeepData);
730 myIsVboInit = Standard_True;
733 Tint aFrontLightingModel = anAspectFace->IntFront().color_mask;
734 const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront().matcol;
735 const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
736 const TEL_COLOUR* aLineColor = myDrawMode == GL_POINTS ? &anAspectMarker->Color() : &anAspectLine->Color();
738 // Use highlight colors
739 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
741 anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
742 aFrontLightingModel = 0;
745 const Standard_Boolean hasColorAttrib = !myVboAttribs.IsNull()
746 && myVboAttribs->HasColorAttribute();
747 const Standard_Boolean isLightOn = aFrontLightingModel != 0
748 && !myVboAttribs.IsNull()
749 && myVboAttribs->HasNormalAttribute();
750 #if !defined(GL_ES_VERSION_2_0)
751 // manage FFP lighting
752 if (aCtx->core11 != NULL)
756 glDisable (GL_LIGHTING);
760 glEnable (GL_LIGHTING);
764 // Temporarily disable environment mapping
765 Handle(OpenGl_Texture) aTextureBack;
766 if (myDrawMode <= GL_LINE_STRIP)
768 aTextureBack = theWorkspace->DisableTexture();
771 if ((myDrawMode > GL_LINE_STRIP && anAspectFace->InteriorStyle() != Aspect_IS_EMPTY) ||
772 (myDrawMode <= GL_LINE_STRIP))
774 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
775 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->InteriorStyle() != Aspect_IS_HIDDENLINE
778 const Standard_Boolean hasVertColor = hasColorAttrib && !toHilight;
779 if (aCtx->core20fwd != NULL)
785 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
786 if (!aSpriteNorm.IsNull()
787 && !aSpriteNorm->IsDisplayList())
789 const Handle(OpenGl_PointSprite)& aSprite = (toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->IsValid())
790 ? anAspectMarker->SpriteHighlightRes (aCtx)
792 theWorkspace->EnableTexture (aSprite);
793 aCtx->ShaderManager()->BindProgram (anAspectMarker, aSprite, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
797 aCtx->ShaderManager()->BindProgram (anAspectMarker, NULL, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
804 aCtx->ShaderManager()->BindProgram (anAspectLine, NULL, isLightOn, hasVertColor, anAspectLine->ShaderProgramRes (aCtx));
809 const Standard_Boolean isLightOnFace = isLightOn
810 && (theWorkspace->ActiveTexture().IsNull()
811 || theWorkspace->ActiveTexture()->GetParams()->IsModulate());
812 aCtx->ShaderManager()->BindProgram (anAspectFace, theWorkspace->ActiveTexture(), isLightOnFace, hasVertColor, anAspectFace->ShaderProgramRes (aCtx));
818 aCtx->SetColor4fv (*(const OpenGl_Vec4* )(myDrawMode <= GL_LINE_STRIP ? aLineColor->rgb : anInteriorColor->rgb));
820 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
823 if (myDrawMode <= GL_LINE_STRIP)
825 theWorkspace->EnableTexture (aTextureBack);
829 if (anAspectFace->Edge()
830 || anAspectFace->InteriorStyle() == Aspect_IS_HIDDENLINE)
832 drawEdges (anEdgeColor, theWorkspace);
836 aCtx->BindProgram (NULL);