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 (anAttrib.Id == Graphic3d_TOA_POS
130 && aDataType != GL_NONE)
132 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
136 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
140 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
142 if (!TheBaseClass::IsValid())
147 TheBaseClass::Bind (theGlCtx);
149 const GLubyte* anOffset = TheBaseClass::myOffset;
150 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
152 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
153 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
154 if (aDataType != GL_NONE)
156 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
158 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
162 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
164 if (!TheBaseClass::IsValid())
168 TheBaseClass::Unbind (theGlCtx);
170 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
172 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
173 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
179 Graphic3d_Attribute Attribs[NbAttributes];
180 Standard_Integer Stride;
184 // =======================================================================
185 // function : clearMemoryGL
187 // =======================================================================
188 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
190 if (!myVboIndices.IsNull())
192 myVboIndices->Release (theGlCtx.operator->());
193 myVboIndices.Nullify();
195 if (!myVboAttribs.IsNull())
197 myVboAttribs->Release (theGlCtx.operator->());
198 myVboAttribs.Nullify();
202 // =======================================================================
203 // function : initNormalVbo
205 // =======================================================================
206 Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
208 switch (myAttribs->NbAttributes)
210 case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
211 case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
212 case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
213 case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
214 case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
215 case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
216 case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
217 case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
218 case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
219 case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
222 // specify data type as Byte and NbComponents as Stride, so that OpenGl_VertexBuffer::EstimatedDataSize() will return correct value
223 if (!myVboAttribs->init (theCtx, myAttribs->Stride, myAttribs->NbElements, myAttribs->Data(), GL_UNSIGNED_BYTE, myAttribs->Stride))
225 TCollection_ExtendedString aMsg;
226 aMsg += "VBO creation for Primitive Array has failed for ";
227 aMsg += myAttribs->NbElements;
228 aMsg += " vertices. Out of memory?";
229 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
231 clearMemoryGL (theCtx);
232 return Standard_False;
234 else if (myIndices.IsNull())
236 return Standard_True;
239 myVboIndices = new OpenGl_IndexBuffer();
241 switch (myIndices->Stride)
245 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data()));
250 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data()));
255 clearMemoryGL (theCtx);
256 return Standard_False;
261 TCollection_ExtendedString aMsg;
262 aMsg += "VBO creation for Primitive Array has failed for ";
263 aMsg += myIndices->NbElements;
264 aMsg += " indices. Out of memory?";
265 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
266 clearMemoryGL (theCtx);
267 return Standard_False;
269 return Standard_True;
272 // =======================================================================
273 // function : buildVBO
275 // =======================================================================
276 Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
277 const Standard_Boolean theToKeepData) const
279 bool isNormalMode = theCtx->ToUseVbo();
280 clearMemoryGL (theCtx);
281 if (myAttribs.IsNull()
282 || myAttribs->IsEmpty()
283 || myAttribs->NbElements < 1
284 || myAttribs->NbAttributes < 1
285 || myAttribs->NbAttributes > 10)
287 // vertices should be always defined - others are optional
288 return Standard_False;
292 && initNormalVbo (theCtx))
294 if (!theCtx->caps->keepArrayData
300 return Standard_True;
303 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
304 switch (myAttribs->NbAttributes)
306 case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
307 case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
308 case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
309 case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
310 case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
311 case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
312 case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
313 case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
314 case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
315 case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
317 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
318 if (!myIndices.IsNull())
320 Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
321 switch (myIndices->Stride)
325 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
330 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
335 return Standard_False;
338 myVboIndices = aVboIndices;
340 myVboAttribs = aVboAttribs;
341 if (!theCtx->caps->keepArrayData
344 // does not make sense for compatibility mode
345 //myIndices.Nullify();
346 //myAttribs.Nullify();
349 return Standard_True;
352 // =======================================================================
353 // function : drawArray
355 // =======================================================================
356 void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
357 const Graphic3d_Vec4* theFaceColors,
358 const Standard_Boolean theHasVertColor) const
360 if (myVboAttribs.IsNull())
362 #if !defined(GL_ES_VERSION_2_0)
363 if (myDrawMode == GL_POINTS)
365 // extreme compatibility mode - without sprites but with markers
366 drawMarkers (theWorkspace);
372 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
373 const bool toHilight = theWorkspace->ToHighlight();
374 const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull()
375 && aGlContext->ActiveProgram()->HasTessellationStage()
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 (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
397 anOffset += aStride * aNbElemsInGroup;
402 // draw one (or sequential) primitive by the indices
403 glDrawElements (aDrawMode, 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 (aDrawMode, aFirstElem, aNbElemsInGroup);
415 aFirstElem += aNbElemsInGroup;
420 if (myDrawMode == GL_POINTS)
422 drawMarkers (theWorkspace);
426 glDrawArrays (aDrawMode, 0, myVboAttribs->GetElemsNb());
431 myVboAttribs->UnbindAllAttributes (aGlContext);
434 // =======================================================================
435 // function : drawEdges
437 // =======================================================================
438 void OpenGl_PrimitiveArray::drawEdges (const OpenGl_Vec4& theEdgeColour,
439 const Handle(OpenGl_Workspace)& theWorkspace) const
441 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
442 if (myVboAttribs.IsNull())
447 const OpenGl_AspectLine* anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace()->AspectEdge());
448 const OpenGl_AspectLine* anAspect = theWorkspace->ApplyAspectLine();
450 #if !defined(GL_ES_VERSION_2_0)
451 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
454 if (aGlContext->core20fwd != NULL)
456 aGlContext->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), anAspect->Aspect()->Type(),
457 Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, Standard_False,
458 anAspect->ShaderProgramRes (aGlContext));
460 const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull()
461 && aGlContext->ActiveProgram()->HasTessellationStage()
464 #if !defined(GL_ES_VERSION_2_0)
465 if (aGlContext->ActiveProgram().IsNull()
466 && aGlContext->core11 != NULL)
468 glDisable (GL_LIGHTING);
472 /// OCC22236 NOTE: draw edges for all situations:
473 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
474 /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
475 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
476 myVboAttribs->BindPositionAttribute (aGlContext);
478 aGlContext->SetColor4fv (theEdgeColour);
479 aGlContext->SetTypeOfLine (anAspect->Aspect()->Type());
480 aGlContext->SetLineWidth (anAspect->Aspect()->Width());
482 if (!myVboIndices.IsNull())
484 myVboIndices->Bind (aGlContext);
485 GLubyte* anOffset = myVboIndices->GetDataOffset();
487 // draw primitives by vertex count with the indices
488 if (!myBounds.IsNull())
490 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
491 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
493 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
494 glDrawElements (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
495 anOffset += aStride * aNbElemsInGroup;
498 // draw one (or sequential) primitive by the indices
501 glDrawElements (aDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
503 myVboIndices->Unbind (aGlContext);
505 else if (!myBounds.IsNull())
507 GLint aFirstElem = 0;
508 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
510 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
511 glDrawArrays (aDrawMode, aFirstElem, aNbElemsInGroup);
512 aFirstElem += aNbElemsInGroup;
517 glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
521 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
523 // restore line context
524 theWorkspace->SetAspectLine (anAspectLineOld);
527 // =======================================================================
528 // function : drawMarkers
530 // =======================================================================
531 void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
533 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->ApplyAspectMarker();
534 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
535 const GLenum aDrawMode = !aCtx->ActiveProgram().IsNull()
536 && aCtx->ActiveProgram()->HasTessellationStage()
540 const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectMarker->SpriteRes (aCtx);
541 const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast<const OpenGl_PointSprite*> (aSpriteNormRes->First().get()) : NULL;
542 if (aSpriteNorm != NULL
543 && !aSpriteNorm->IsDisplayList())
545 // Textured markers will be drawn with the point sprites
546 aCtx->SetPointSize (anAspectMarker->MarkerSize());
547 aCtx->SetPointSpriteOrigin();
548 #if !defined(GL_ES_VERSION_2_0)
549 if (aCtx->core11 != NULL)
551 aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
552 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
556 aCtx->core11fwd->glEnable (GL_BLEND);
557 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
559 aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
561 aCtx->core11fwd->glDisable (GL_BLEND);
562 #if !defined(GL_ES_VERSION_2_0)
563 if (aCtx->core11 != NULL)
565 if (aCtx->ShaderManager()->MaterialState().AlphaCutoff() >= ShortRealLast())
567 aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
571 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, aCtx->ShaderManager()->MaterialState().AlphaCutoff());
575 aCtx->SetPointSize (1.0f);
578 else if (anAspectMarker->Aspect()->Type() == Aspect_TOM_POINT)
580 aCtx->SetPointSize (anAspectMarker->MarkerSize());
581 aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
582 aCtx->SetPointSize (1.0f);
584 #if !defined(GL_ES_VERSION_2_0)
585 // Textured markers will be drawn with the glBitmap
586 else if (anAspectMarker->Aspect()->Type() != Aspect_TOM_POINT
587 && aSpriteNorm != NULL)
589 /**if (!isHilight && (myPArray->vcolours != NULL))
591 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
593 glColor4ubv (myPArray->vcolours[anIter].GetData());
594 glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
595 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
600 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
602 aCtx->core11->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
603 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
610 // =======================================================================
611 // function : OpenGl_PrimitiveArray
613 // =======================================================================
614 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver)
616 : myDrawMode (DRAW_MODE_NONE),
617 myIsFillType(Standard_False),
618 myIsVboInit (Standard_False)
620 if (theDriver != NULL)
622 myUID = theDriver->GetNextPrimitiveArrayUID();
626 // =======================================================================
627 // function : OpenGl_PrimitiveArray
629 // =======================================================================
630 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
631 const Graphic3d_TypeOfPrimitiveArray theType,
632 const Handle(Graphic3d_IndexBuffer)& theIndices,
633 const Handle(Graphic3d_Buffer)& theAttribs,
634 const Handle(Graphic3d_BoundBuffer)& theBounds)
636 : myIndices (theIndices),
637 myAttribs (theAttribs),
638 myBounds (theBounds),
639 myDrawMode (DRAW_MODE_NONE),
640 myIsFillType(Standard_False),
641 myIsVboInit (Standard_False)
643 if (!myIndices.IsNull()
644 && myIndices->NbElements < 1)
646 // dummy index buffer?
650 if (theDriver != NULL)
652 myUID = theDriver->GetNextPrimitiveArrayUID();
653 #if defined (GL_ES_VERSION_2_0)
654 const Handle(OpenGl_Context)& aCtx = theDriver->GetSharedContext();
657 processIndices (aCtx);
662 setDrawMode (theType);
665 // =======================================================================
666 // function : ~OpenGl_PrimitiveArray
668 // =======================================================================
669 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
674 // =======================================================================
675 // function : Release
677 // =======================================================================
678 void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
680 myIsVboInit = Standard_False;
681 if (!myVboIndices.IsNull())
685 theContext->DelayedRelease (myVboIndices);
687 myVboIndices.Nullify();
689 if (!myVboAttribs.IsNull())
693 theContext->DelayedRelease (myVboAttribs);
695 myVboAttribs.Nullify();
699 // =======================================================================
702 // =======================================================================
703 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
705 if (myDrawMode == DRAW_MODE_NONE)
710 const OpenGl_AspectFace* anAspectFace = theWorkspace->ApplyAspectFace();
711 const OpenGl_AspectLine* anAspectLine = theWorkspace->ApplyAspectLine();
712 const OpenGl_AspectMarker* anAspectMarker = myDrawMode == GL_POINTS
713 ? theWorkspace->ApplyAspectMarker()
714 : theWorkspace->AspectMarker();
716 // create VBOs on first render call
717 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
720 // compatibility - keep data to draw markers using display lists
721 Standard_Boolean toKeepData = Standard_False;
722 if (myDrawMode == GL_POINTS)
724 const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectMarker->SpriteRes (aCtx);
725 const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast<const OpenGl_PointSprite*> (aSpriteNormRes->First().get()) : NULL;
726 toKeepData = aSpriteNorm != NULL
727 && aSpriteNorm->IsDisplayList();
729 #if defined (GL_ES_VERSION_2_0)
730 processIndices (aCtx);
732 buildVBO (aCtx, toKeepData);
733 myIsVboInit = Standard_True;
736 // Temporarily disable environment mapping
737 Handle(OpenGl_TextureSet) aTextureBack;
738 bool toDrawArray = true;
739 if (myDrawMode > GL_LINE_STRIP)
741 toDrawArray = anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_EMPTY;
743 else if (myDrawMode <= GL_LINE_STRIP)
745 aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
746 if (myDrawMode == GL_POINTS)
748 toDrawArray = anAspectMarker->Aspect()->Type() != Aspect_TOM_EMPTY;
752 toDrawArray = anAspectLine->Aspect()->Type() != Aspect_TOL_EMPTY;
756 Graphic3d_TypeOfShadingModel aShadingModel = Graphic3d_TOSM_UNLIT;
759 const bool hasColorAttrib = !myVboAttribs.IsNull()
760 && myVboAttribs->HasColorAttribute();
761 const bool toHilight = theWorkspace->ToHighlight();
762 const bool hasVertColor = hasColorAttrib && !toHilight;
763 const bool hasVertNorm = !myVboAttribs.IsNull() && myVboAttribs->HasNormalAttribute();
768 aShadingModel = aCtx->ShaderManager()->ChooseMarkerShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
769 const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectMarker->SpriteRes (aCtx);
770 const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast<const OpenGl_PointSprite*> (aSpriteNormRes->First().get()) : NULL;
771 if (aSpriteNorm != NULL
772 && !aSpriteNorm->IsDisplayList())
774 const Handle(OpenGl_TextureSet)& aSprite = toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->First()->IsValid()
775 ? anAspectMarker->SpriteHighlightRes (aCtx)
777 aCtx->BindTextures (aSprite);
778 aCtx->ShaderManager()->BindMarkerProgram (aSprite, aShadingModel, Graphic3d_AlphaMode_Opaque, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
782 aCtx->ShaderManager()->BindMarkerProgram (Handle(OpenGl_TextureSet)(), aShadingModel, Graphic3d_AlphaMode_Opaque, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
789 aShadingModel = aCtx->ShaderManager()->ChooseLineShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
790 aCtx->ShaderManager()->BindLineProgram (NULL,
791 anAspectLine->Aspect()->Type(),
793 Graphic3d_AlphaMode_Opaque,
795 anAspectLine->ShaderProgramRes (aCtx));
800 aShadingModel = aCtx->ShaderManager()->ChooseFaceShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
801 const Handle(OpenGl_TextureSet)& aTextures = aCtx->ActiveTextures();
802 const Standard_Boolean toEnableEnvMap = (!aTextures.IsNull() && (aTextures == theWorkspace->EnvironmentTexture()));
803 aCtx->ShaderManager()->BindFaceProgram (aTextures,
805 anAspectFace->Aspect()->AlphaMode(),
808 anAspectFace->ShaderProgramRes (aCtx));
813 #if !defined(GL_ES_VERSION_2_0)
814 // manage FFP lighting
815 if (aCtx->ActiveProgram().IsNull()
816 && aCtx->core11 != NULL)
818 if (aShadingModel == Graphic3d_TOSM_UNLIT)
820 glDisable (GL_LIGHTING);
824 glEnable (GL_LIGHTING);
829 if (!aCtx->ActiveTextures().IsNull()
830 && !aCtx->ActiveTextures()->IsEmpty()
831 && !aCtx->ActiveTextures()->First().IsNull()
832 && myDrawMode != GL_POINTS) // transformation is not supported within point sprites
834 aCtx->SetTextureMatrix (aCtx->ActiveTextures()->First()->Sampler()->Parameters());
837 if (myDrawMode <= GL_LINE_STRIP)
839 const OpenGl_Vec4& aLineColor = myDrawMode == GL_POINTS ? theWorkspace->MarkerColor() : theWorkspace->LineColor();
840 aCtx->SetColor4fv (aLineColor);
844 const OpenGl_Vec4& anInteriorColor = theWorkspace->InteriorColor();
845 aCtx->SetColor4fv (anInteriorColor);
847 if (myDrawMode == GL_LINES
848 || myDrawMode == GL_LINE_STRIP)
850 aCtx->SetTypeOfLine (anAspectLine->Aspect()->Type());
851 aCtx->SetLineWidth (anAspectLine->Aspect()->Width());
854 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_HIDDENLINE
857 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
860 if (myDrawMode <= GL_LINE_STRIP)
862 aCtx->BindTextures (aTextureBack);
866 if (anAspectFace->Aspect()->ToDrawEdges()
867 || anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE)
869 const OpenGl_Vec4& anEdgeColor = theWorkspace->EdgeColor();
870 drawEdges (anEdgeColor, theWorkspace);
872 // restore OpenGL polygon mode if needed
873 #if !defined(GL_ES_VERSION_2_0)
874 if (anAspectFace->Aspect()->InteriorStyle() >= Aspect_IS_HATCH)
876 glPolygonMode (GL_FRONT_AND_BACK,
877 anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_POINT ? GL_POINT : GL_FILL);
884 // =======================================================================
885 // function : setDrawMode
887 // =======================================================================
888 void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType)
890 if (myAttribs.IsNull())
892 myDrawMode = DRAW_MODE_NONE;
893 myIsFillType = false;
899 case Graphic3d_TOPA_POINTS:
900 myDrawMode = GL_POINTS;
901 myIsFillType = false;
903 case Graphic3d_TOPA_SEGMENTS:
904 myDrawMode = GL_LINES;
905 myIsFillType = false;
907 case Graphic3d_TOPA_POLYLINES:
908 myDrawMode = GL_LINE_STRIP;
909 myIsFillType = false;
911 case Graphic3d_TOPA_TRIANGLES:
912 myDrawMode = GL_TRIANGLES;
915 case Graphic3d_TOPA_TRIANGLESTRIPS:
916 myDrawMode = GL_TRIANGLE_STRIP;
919 case Graphic3d_TOPA_TRIANGLEFANS:
920 myDrawMode = GL_TRIANGLE_FAN;
924 case Graphic3d_TOPA_LINES_ADJACENCY:
925 myDrawMode = GL_LINES_ADJACENCY;
926 myIsFillType = false;
928 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
929 myDrawMode = GL_LINE_STRIP_ADJACENCY;
930 myIsFillType = false;
932 case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
933 myDrawMode = GL_TRIANGLES_ADJACENCY;
936 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
937 myDrawMode = GL_TRIANGLE_STRIP_ADJACENCY;
941 #if !defined(GL_ES_VERSION_2_0)
942 case Graphic3d_TOPA_QUADRANGLES:
943 myDrawMode = GL_QUADS;
946 case Graphic3d_TOPA_QUADRANGLESTRIPS:
947 myDrawMode = GL_QUAD_STRIP;
950 case Graphic3d_TOPA_POLYGONS:
951 myDrawMode = GL_POLYGON;
955 case Graphic3d_TOPA_QUADRANGLES:
956 case Graphic3d_TOPA_QUADRANGLESTRIPS:
957 case Graphic3d_TOPA_POLYGONS:
959 case Graphic3d_TOPA_UNDEFINED:
960 myDrawMode = DRAW_MODE_NONE;
961 myIsFillType = false;
966 // =======================================================================
967 // function : processIndices
969 // =======================================================================
970 Standard_Boolean OpenGl_PrimitiveArray::processIndices (const Handle(OpenGl_Context)& theContext) const
972 if (myIndices.IsNull()
973 || myAttribs.IsNull()
974 || theContext->hasUintIndex)
976 return Standard_True;
979 if (myAttribs->NbElements > std::numeric_limits<GLushort>::max())
981 Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (new NCollection_AlignedAllocator (16));
982 if (!anAttribs->Init (myIndices->NbElements, myAttribs->AttributesArray(), myAttribs->NbAttributes))
984 return Standard_False; // failed to initialize attribute array
987 for (Standard_Integer anIdxIdx = 0; anIdxIdx < myIndices->NbElements; ++anIdxIdx)
989 const Standard_Integer anIndex = myIndices->Index (anIdxIdx);
990 memcpy (anAttribs->ChangeData() + myAttribs->Stride * anIdxIdx,
991 myAttribs->Data() + myAttribs->Stride * anIndex,
996 myAttribs = anAttribs;
999 return Standard_True;
1002 // =======================================================================
1003 // function : InitBuffers
1005 // =======================================================================
1006 void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& theContext,
1007 const Graphic3d_TypeOfPrimitiveArray theType,
1008 const Handle(Graphic3d_IndexBuffer)& theIndices,
1009 const Handle(Graphic3d_Buffer)& theAttribs,
1010 const Handle(Graphic3d_BoundBuffer)& theBounds)
1012 // Release old graphic resources
1013 Release (theContext.operator->());
1015 myIndices = theIndices;
1016 myAttribs = theAttribs;
1017 myBounds = theBounds;
1018 #if defined(GL_ES_VERSION_2_0)
1019 processIndices (theContext);
1022 setDrawMode (theType);