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_Aspects.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_View.hxx>
28 #include <OpenGl_Workspace.hxx>
29 #include <Graphic3d_TextureParams.hxx>
30 #include <NCollection_AlignedAllocator.hxx>
34 //! Convert data type to GL info
35 inline GLenum toGlDataType (const Graphic3d_TypeOfData theType,
40 case Graphic3d_TOD_USHORT:
42 return GL_UNSIGNED_SHORT;
43 case Graphic3d_TOD_UINT:
45 return GL_UNSIGNED_INT;
46 case Graphic3d_TOD_VEC2:
49 case Graphic3d_TOD_VEC3:
52 case Graphic3d_TOD_VEC4:
55 case Graphic3d_TOD_VEC4UB:
57 return GL_UNSIGNED_BYTE;
58 case Graphic3d_TOD_FLOAT:
68 //! Auxiliary template for VBO with interleaved attributes.
69 template<class TheBaseClass, int NbAttributes>
70 class OpenGl_VertexBufferT : public TheBaseClass
74 //! Create uninitialized VBO.
75 OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
76 : Stride (theAttribs.IsInterleaved() ? theAttribs.Stride : 0)
78 memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
81 virtual bool HasColorAttribute() const
83 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
85 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
86 if (anAttrib.Id == Graphic3d_TOA_COLOR)
94 virtual bool HasNormalAttribute() const
96 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
98 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
99 if (anAttrib.Id == Graphic3d_TOA_NORM)
107 virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
109 if (!TheBaseClass::IsValid())
114 TheBaseClass::Bind (theGlCtx);
116 const GLubyte* anOffset = TheBaseClass::myOffset;
117 const Standard_Size aMuliplier = Stride != 0 ? 1 : TheBaseClass::myElemsNb;
118 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
120 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
121 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
122 if (anAttrib.Id == Graphic3d_TOA_POS
123 && aDataType != GL_NONE)
125 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
129 anOffset += aMuliplier * Graphic3d_Attribute::Stride (anAttrib.DataType);
133 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
135 if (!TheBaseClass::IsValid())
140 TheBaseClass::Bind (theGlCtx);
142 const GLubyte* anOffset = TheBaseClass::myOffset;
143 const Standard_Size aMuliplier = Stride != 0 ? 1 : TheBaseClass::myElemsNb;
144 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
146 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
147 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
148 if (aDataType != GL_NONE)
150 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
152 anOffset += aMuliplier * Graphic3d_Attribute::Stride (anAttrib.DataType);
156 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
158 if (!TheBaseClass::IsValid())
162 TheBaseClass::Unbind (theGlCtx);
164 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
166 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
167 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
173 Graphic3d_Attribute Attribs[NbAttributes];
174 Standard_Integer Stride;
178 // =======================================================================
179 // function : clearMemoryGL
181 // =======================================================================
182 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
184 if (!myVboIndices.IsNull())
186 myVboIndices->Release (theGlCtx.operator->());
187 myVboIndices.Nullify();
189 if (!myVboAttribs.IsNull())
191 myVboAttribs->Release (theGlCtx.operator->());
192 myVboAttribs.Nullify();
196 // =======================================================================
197 // function : initNormalVbo
199 // =======================================================================
200 Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
202 switch (myAttribs->NbAttributes)
204 case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
205 case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
206 case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
207 case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
208 case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
209 case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
210 case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
211 case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
212 case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
213 case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
216 const Standard_Boolean isAttribMutable = myAttribs->IsMutable();
217 const Standard_Boolean isAttribInterleaved = myAttribs->IsInterleaved();
218 if (myAttribs->NbElements != myAttribs->NbMaxElements()
219 && myIndices.IsNull()
220 && (!isAttribInterleaved || isAttribMutable))
222 throw Standard_ProgramError ("OpenGl_PrimitiveArray::buildVBO() - vertex attribute data with reserved size is not supported");
225 // specify data type as Byte and NbComponents as Stride, so that OpenGl_VertexBuffer::EstimatedDataSize() will return correct value
226 const Standard_Integer aNbVertexes = (isAttribMutable || !isAttribInterleaved) ? myAttribs->NbMaxElements() : myAttribs->NbElements;
227 if (!myVboAttribs->init (theCtx, myAttribs->Stride, aNbVertexes, myAttribs->Data(), GL_UNSIGNED_BYTE, myAttribs->Stride))
229 TCollection_ExtendedString aMsg = TCollection_ExtendedString("VBO creation for Primitive Array has failed for ") + aNbVertexes + " vertices. Out of memory?";
230 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
232 clearMemoryGL (theCtx);
233 return Standard_False;
235 else if (myIndices.IsNull())
237 if (isAttribMutable && isAttribInterleaved)
239 // for mutable interlaced array we can change dynamically number of vertexes (they will be just skipped at the end of buffer);
240 // this doesn't matter in case if we have indexed array
241 myVboAttribs->SetElemsNb (myAttribs->NbElements);
243 return Standard_True;
246 const Standard_Integer aNbIndexes = !myIndices->IsMutable() ? myIndices->NbElements : myIndices->NbMaxElements();
247 myVboIndices = new OpenGl_IndexBuffer();
249 switch (myIndices->Stride)
253 isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast<const GLushort*> (myIndices->Data()));
254 myVboIndices->SetElemsNb (myIndices->NbElements);
255 myIndices->Validate();
260 isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast<const GLuint*> (myIndices->Data()));
261 myVboIndices->SetElemsNb (myIndices->NbElements);
262 myIndices->Validate();
267 clearMemoryGL (theCtx);
268 return Standard_False;
273 TCollection_ExtendedString aMsg = TCollection_ExtendedString("VBO creation for Primitive Array has failed for ") + aNbIndexes + " indices. Out of memory?";
274 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
275 clearMemoryGL (theCtx);
276 return Standard_False;
278 return Standard_True;
281 // =======================================================================
282 // function : buildVBO
284 // =======================================================================
285 Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
286 const Standard_Boolean theToKeepData) const
288 bool isNormalMode = theCtx->ToUseVbo();
289 clearMemoryGL (theCtx);
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
305 && !myAttribs->IsMutable())
312 myAttribs->Validate();
314 return Standard_True;
317 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
318 switch (myAttribs->NbAttributes)
320 case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
321 case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
322 case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
323 case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
324 case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
325 case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
326 case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
327 case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
328 case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
329 case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
331 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
332 if (!myIndices.IsNull())
334 Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
335 switch (myIndices->Stride)
339 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
344 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
349 return Standard_False;
352 myVboIndices = aVboIndices;
354 myVboAttribs = aVboAttribs;
355 if (!theCtx->caps->keepArrayData
358 // does not make sense for compatibility mode
359 //myIndices.Nullify();
360 //myAttribs.Nullify();
363 return Standard_True;
366 // =======================================================================
367 // function : updateVBO
369 // =======================================================================
370 void OpenGl_PrimitiveArray::updateVBO (const Handle(OpenGl_Context)& theCtx) const
372 if (!myAttribs.IsNull())
374 Graphic3d_BufferRange aRange = myAttribs->InvalidatedRange();
375 if (!aRange.IsEmpty()
376 && myVboAttribs->IsValid()
377 && !myVboAttribs->IsVirtual())
379 myVboAttribs->Bind (theCtx);
380 theCtx->core15fwd->glBufferSubData (myVboAttribs->GetTarget(),
383 myAttribs->Data() + aRange.Start);
384 myVboAttribs->Unbind (theCtx);
385 if (myAttribs->IsInterleaved())
387 myVboAttribs->SetElemsNb (myAttribs->NbElements);
390 myAttribs->Validate();
392 if (!myIndices.IsNull())
394 Graphic3d_BufferRange aRange = myIndices->InvalidatedRange();
395 if (!aRange.IsEmpty()
396 && myVboIndices->IsValid()
397 && !myVboIndices->IsVirtual())
399 myVboIndices->Bind (theCtx);
400 theCtx->core15fwd->glBufferSubData (myVboIndices->GetTarget(),
403 myIndices->Data() + aRange.Start);
404 myVboIndices->Unbind (theCtx);
405 myVboIndices->SetElemsNb (myIndices->NbElements);
407 myIndices->Validate();
411 // =======================================================================
412 // function : drawArray
414 // =======================================================================
415 void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
416 const Graphic3d_Vec4* theFaceColors,
417 const Standard_Boolean theHasVertColor) const
419 if (myVboAttribs.IsNull())
421 #if !defined(GL_ES_VERSION_2_0)
422 if (myDrawMode == GL_POINTS)
424 // extreme compatibility mode - without sprites but with markers
425 drawMarkers (theWorkspace);
431 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
432 const bool toHilight = theWorkspace->ToHighlight();
433 const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull()
434 && aGlContext->ActiveProgram()->HasTessellationStage()
437 myVboAttribs->BindAllAttributes (aGlContext);
438 if (theHasVertColor && toHilight)
440 // disable per-vertex color
441 OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
443 if (!myVboIndices.IsNull())
445 myVboIndices->Bind (aGlContext);
446 GLubyte* anOffset = myVboIndices->GetDataOffset();
447 if (!myBounds.IsNull())
449 // draw primitives by vertex count with the indices
450 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
451 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
453 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
454 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
455 glDrawElements (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
456 anOffset += aStride * aNbElemsInGroup;
461 // draw one (or sequential) primitive by the indices
462 glDrawElements (aDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
464 myVboIndices->Unbind (aGlContext);
466 else if (!myBounds.IsNull())
468 GLint aFirstElem = 0;
469 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
471 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
472 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
473 glDrawArrays (aDrawMode, aFirstElem, aNbElemsInGroup);
474 aFirstElem += aNbElemsInGroup;
479 if (myDrawMode == GL_POINTS)
481 drawMarkers (theWorkspace);
485 glDrawArrays (aDrawMode, 0, myVboAttribs->GetElemsNb());
490 myVboAttribs->UnbindAllAttributes (aGlContext);
493 // =======================================================================
494 // function : drawEdges
496 // =======================================================================
497 void OpenGl_PrimitiveArray::drawEdges (const Handle(OpenGl_Workspace)& theWorkspace) const
499 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
500 if (myVboAttribs.IsNull())
505 const OpenGl_Aspects* anAspect = theWorkspace->Aspects();
506 #if !defined(GL_ES_VERSION_2_0)
507 const Standard_Integer aPolyModeOld = aGlContext->SetPolygonMode (GL_LINE);
510 if (aGlContext->core20fwd != NULL)
512 aGlContext->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), anAspect->Aspect()->EdgeLineType(),
513 Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, Standard_False,
514 anAspect->ShaderProgramRes (aGlContext));
516 aGlContext->SetSampleAlphaToCoverage (aGlContext->ShaderManager()->MaterialState().HasAlphaCutoff());
517 const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull()
518 && aGlContext->ActiveProgram()->HasTessellationStage()
521 #if !defined(GL_ES_VERSION_2_0)
522 if (aGlContext->ActiveProgram().IsNull()
523 && aGlContext->core11 != NULL)
525 glDisable (GL_LIGHTING);
529 /// OCC22236 NOTE: draw edges for all situations:
530 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
531 /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
532 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
533 myVboAttribs->BindPositionAttribute (aGlContext);
535 aGlContext->SetColor4fv (theWorkspace->EdgeColor().a() >= 0.1f
536 ? theWorkspace->EdgeColor()
537 : theWorkspace->View()->BackgroundColor());
538 aGlContext->SetTypeOfLine (anAspect->Aspect()->EdgeLineType());
539 aGlContext->SetLineWidth (anAspect->Aspect()->EdgeWidth());
541 if (!myVboIndices.IsNull())
543 myVboIndices->Bind (aGlContext);
544 GLubyte* anOffset = myVboIndices->GetDataOffset();
546 // draw primitives by vertex count with the indices
547 if (!myBounds.IsNull())
549 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
550 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
552 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
553 glDrawElements (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
554 anOffset += aStride * aNbElemsInGroup;
557 // draw one (or sequential) primitive by the indices
560 glDrawElements (aDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
562 myVboIndices->Unbind (aGlContext);
564 else if (!myBounds.IsNull())
566 GLint aFirstElem = 0;
567 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
569 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
570 glDrawArrays (aDrawMode, aFirstElem, aNbElemsInGroup);
571 aFirstElem += aNbElemsInGroup;
576 glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
580 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
582 // restore line context
583 #if !defined(GL_ES_VERSION_2_0)
584 aGlContext->SetPolygonMode (aPolyModeOld);
588 // =======================================================================
589 // function : drawMarkers
591 // =======================================================================
592 void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
594 const OpenGl_Aspects* anAspectMarker = theWorkspace->Aspects();
595 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
596 const GLenum aDrawMode = !aCtx->ActiveProgram().IsNull()
597 && aCtx->ActiveProgram()->HasTessellationStage()
600 if (anAspectMarker->HasPointSprite (aCtx))
602 // Textured markers will be drawn with the point sprites
603 aCtx->SetPointSize (anAspectMarker->MarkerSize());
604 aCtx->SetPointSpriteOrigin();
605 #if !defined(GL_ES_VERSION_2_0)
606 if (aCtx->core11 != NULL)
608 aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
609 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
613 aCtx->core11fwd->glEnable (GL_BLEND);
614 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
616 aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
618 aCtx->core11fwd->glDisable (GL_BLEND);
619 #if !defined(GL_ES_VERSION_2_0)
620 if (aCtx->core11 != NULL)
622 if (aCtx->ShaderManager()->MaterialState().AlphaCutoff() >= ShortRealLast())
624 aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
628 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, aCtx->ShaderManager()->MaterialState().AlphaCutoff());
632 aCtx->SetPointSize (1.0f);
635 else if (anAspectMarker->Aspect()->MarkerType() == Aspect_TOM_POINT)
637 aCtx->SetPointSize (anAspectMarker->MarkerSize());
638 aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
639 aCtx->SetPointSize (1.0f);
641 #if !defined(GL_ES_VERSION_2_0)
642 // Textured markers will be drawn with the glBitmap
643 else if (anAspectMarker->Aspect()->MarkerType() != Aspect_TOM_POINT)
645 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx, false);
646 if (aSpriteNorm.IsNull())
651 /**if (!isHilight && (myPArray->vcolours != NULL))
653 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
655 glColor4ubv (myPArray->vcolours[anIter].GetData());
656 glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
657 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
662 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
664 aCtx->core11->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
665 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
672 // =======================================================================
673 // function : OpenGl_PrimitiveArray
675 // =======================================================================
676 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver)
678 : myDrawMode (DRAW_MODE_NONE),
679 myIsFillType(Standard_False),
680 myIsVboInit (Standard_False)
682 if (theDriver != NULL)
684 myUID = theDriver->GetNextPrimitiveArrayUID();
688 // =======================================================================
689 // function : OpenGl_PrimitiveArray
691 // =======================================================================
692 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
693 const Graphic3d_TypeOfPrimitiveArray theType,
694 const Handle(Graphic3d_IndexBuffer)& theIndices,
695 const Handle(Graphic3d_Buffer)& theAttribs,
696 const Handle(Graphic3d_BoundBuffer)& theBounds)
698 : myIndices (theIndices),
699 myAttribs (theAttribs),
700 myBounds (theBounds),
701 myDrawMode (DRAW_MODE_NONE),
702 myIsFillType(Standard_False),
703 myIsVboInit (Standard_False)
705 if (!myIndices.IsNull()
706 && myIndices->NbElements < 1)
708 // dummy index buffer?
712 if (theDriver != NULL)
714 myUID = theDriver->GetNextPrimitiveArrayUID();
715 #if defined (GL_ES_VERSION_2_0)
716 const Handle(OpenGl_Context)& aCtx = theDriver->GetSharedContext();
719 processIndices (aCtx);
724 setDrawMode (theType);
727 // =======================================================================
728 // function : ~OpenGl_PrimitiveArray
730 // =======================================================================
731 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
736 // =======================================================================
737 // function : Release
739 // =======================================================================
740 void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
742 myIsVboInit = Standard_False;
743 if (!myVboIndices.IsNull())
747 theContext->DelayedRelease (myVboIndices);
749 myVboIndices.Nullify();
751 if (!myVboAttribs.IsNull())
755 theContext->DelayedRelease (myVboAttribs);
757 myVboAttribs.Nullify();
761 // =======================================================================
764 // =======================================================================
765 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
767 if (myDrawMode == DRAW_MODE_NONE)
772 const OpenGl_Aspects* anAspectFace = theWorkspace->ApplyAspects();
773 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
775 const bool toEnableEnvMap = !aCtx->ActiveTextures().IsNull()
776 && aCtx->ActiveTextures() == theWorkspace->EnvironmentTexture();
777 bool toDrawArray = true;
778 int toDrawInteriorEdges = 0; // 0 - no edges, 1 - glsl edges, 2 - polygonMode
781 toDrawArray = anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_EMPTY;
782 if (anAspectFace->Aspect()->ToDrawEdges())
784 toDrawInteriorEdges = 1;
786 #if !defined(GL_ES_VERSION_2_0)
787 if (anAspectFace->Aspect()->EdgeLineType() != Aspect_TOL_SOLID
788 || aCtx->hasGeometryStage == OpenGl_FeatureNotAvailable
789 || aCtx->caps->usePolygonMode)
791 toDrawInteriorEdges = 2;
792 if (anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_EMPTY)
794 if (anAspectFace->Aspect()->EdgeLineType() != Aspect_TOL_SOLID)
800 aCtx->SetPolygonMode (GL_LINE);
809 if (myDrawMode == GL_POINTS)
811 if (anAspectFace->Aspect()->MarkerType() == Aspect_TOM_EMPTY)
818 if (anAspectFace->Aspect()->LineType() == Aspect_TOL_EMPTY)
825 // create VBOs on first render call
828 // compatibility - keep data to draw markers using display lists
829 Standard_Boolean toKeepData = myDrawMode == GL_POINTS
830 && anAspectFace->IsDisplayListSprite (aCtx);
831 #if defined (GL_ES_VERSION_2_0)
832 processIndices (aCtx);
834 buildVBO (aCtx, toKeepData);
835 myIsVboInit = Standard_True;
837 else if ((!myAttribs.IsNull()
838 && myAttribs->IsMutable())
839 || (!myIndices.IsNull()
840 && myIndices->IsMutable()))
845 Graphic3d_TypeOfShadingModel aShadingModel = Graphic3d_TOSM_UNLIT;
848 const bool hasColorAttrib = !myVboAttribs.IsNull()
849 && myVboAttribs->HasColorAttribute();
850 const bool toHilight = theWorkspace->ToHighlight();
851 const bool hasVertColor = hasColorAttrib && !toHilight;
852 const bool hasVertNorm = !myVboAttribs.IsNull() && myVboAttribs->HasNormalAttribute();
857 aShadingModel = aCtx->ShaderManager()->ChooseMarkerShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
858 aCtx->ShaderManager()->BindMarkerProgram (aCtx->ActiveTextures(),
859 aShadingModel, Graphic3d_AlphaMode_Opaque,
860 hasVertColor, anAspectFace->ShaderProgramRes (aCtx));
866 aShadingModel = aCtx->ShaderManager()->ChooseLineShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
867 aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(),
868 anAspectFace->Aspect()->LineType(),
870 Graphic3d_AlphaMode_Opaque,
872 anAspectFace->ShaderProgramRes (aCtx));
877 aShadingModel = aCtx->ShaderManager()->ChooseFaceShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
878 aCtx->ShaderManager()->BindFaceProgram (aCtx->ActiveTextures(),
880 aCtx->ShaderManager()->MaterialState().HasAlphaCutoff() ? Graphic3d_AlphaMode_Mask : Graphic3d_AlphaMode_Opaque,
881 toDrawInteriorEdges == 1 ? anAspectFace->Aspect()->InteriorStyle() : Aspect_IS_SOLID,
884 toDrawInteriorEdges == 1,
885 anAspectFace->ShaderProgramRes (aCtx));
886 if (toDrawInteriorEdges == 1)
888 aCtx->ShaderManager()->PushInteriorState (aCtx->ActiveProgram(), anAspectFace->Aspect());
894 #if !defined(GL_ES_VERSION_2_0)
895 // manage FFP lighting
896 if (aCtx->ActiveProgram().IsNull()
897 && aCtx->core11 != NULL)
899 if (aShadingModel == Graphic3d_TOSM_UNLIT)
901 glDisable (GL_LIGHTING);
905 glEnable (GL_LIGHTING);
910 if (!aCtx->ActiveTextures().IsNull()
911 && !aCtx->ActiveTextures()->IsEmpty()
912 && !aCtx->ActiveTextures()->First().IsNull()
913 && myDrawMode != GL_POINTS) // transformation is not supported within point sprites
915 aCtx->SetTextureMatrix (aCtx->ActiveTextures()->First()->Sampler()->Parameters());
917 aCtx->SetSampleAlphaToCoverage (aCtx->ShaderManager()->MaterialState().HasAlphaCutoff());
919 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_HIDDENLINE
922 const OpenGl_Vec4& anInteriorColor = theWorkspace->InteriorColor();
923 aCtx->SetColor4fv (anInteriorColor);
926 if (myDrawMode == GL_LINES
927 || myDrawMode == GL_LINE_STRIP)
929 aCtx->SetTypeOfLine (anAspectFace->Aspect()->LineType());
930 aCtx->SetLineWidth (anAspectFace->Aspect()->LineWidth());
933 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
937 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
939 // draw outline - only closed triangulation with defined vertex normals can be drawn in this way
940 if (anAspectFace->Aspect()->ToDrawSilhouette()
941 && aCtx->ToCullBackFaces()
942 && aCtx->ShaderManager()->BindOutlineProgram())
944 const Graphic3d_Vec2i aViewSize (aCtx->Viewport()[2], aCtx->Viewport()[3]);
945 const Standard_Integer aMin = aViewSize.minComp();
946 const GLfloat anEdgeWidth = (GLfloat )anAspectFace->Aspect()->EdgeWidth() * aCtx->LineWidthScale() / (GLfloat )aMin;
947 const GLfloat anOrthoScale = theWorkspace->View()->Camera()->IsOrthographic() ? (GLfloat )theWorkspace->View()->Camera()->Scale() : -1.0f;
949 const Handle(OpenGl_ShaderProgram)& anOutlineProgram = aCtx->ActiveProgram();
950 anOutlineProgram->SetUniform (aCtx, anOutlineProgram->GetStateLocation (OpenGl_OCCT_SILHOUETTE_THICKNESS), anEdgeWidth);
951 anOutlineProgram->SetUniform (aCtx, anOutlineProgram->GetStateLocation (OpenGl_OCCT_ORTHO_SCALE), anOrthoScale);
952 aCtx->SetColor4fv (anAspectFace->Aspect()->EdgeColorRGBA());
954 aCtx->core11fwd->glCullFace (GL_FRONT);
955 drawArray (theWorkspace, NULL, false);
957 aCtx->core11fwd->glCullFace (GL_BACK);
961 #if !defined(GL_ES_VERSION_2_0)
962 // draw triangulation edges using Polygon Mode
963 if (toDrawInteriorEdges == 2)
965 if (anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_HOLLOW
966 && anAspectFace->Aspect()->EdgeLineType() == Aspect_TOL_SOLID)
968 aCtx->SetPolygonMode (GL_FILL);
972 drawEdges (theWorkspace);
978 // =======================================================================
979 // function : setDrawMode
981 // =======================================================================
982 void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType)
984 if (myAttribs.IsNull())
986 myDrawMode = DRAW_MODE_NONE;
987 myIsFillType = false;
993 case Graphic3d_TOPA_POINTS:
994 myDrawMode = GL_POINTS;
995 myIsFillType = false;
997 case Graphic3d_TOPA_SEGMENTS:
998 myDrawMode = GL_LINES;
999 myIsFillType = false;
1001 case Graphic3d_TOPA_POLYLINES:
1002 myDrawMode = GL_LINE_STRIP;
1003 myIsFillType = false;
1005 case Graphic3d_TOPA_TRIANGLES:
1006 myDrawMode = GL_TRIANGLES;
1007 myIsFillType = true;
1009 case Graphic3d_TOPA_TRIANGLESTRIPS:
1010 myDrawMode = GL_TRIANGLE_STRIP;
1011 myIsFillType = true;
1013 case Graphic3d_TOPA_TRIANGLEFANS:
1014 myDrawMode = GL_TRIANGLE_FAN;
1015 myIsFillType = true;
1018 case Graphic3d_TOPA_LINES_ADJACENCY:
1019 myDrawMode = GL_LINES_ADJACENCY;
1020 myIsFillType = false;
1022 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
1023 myDrawMode = GL_LINE_STRIP_ADJACENCY;
1024 myIsFillType = false;
1026 case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
1027 myDrawMode = GL_TRIANGLES_ADJACENCY;
1028 myIsFillType = true;
1030 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
1031 myDrawMode = GL_TRIANGLE_STRIP_ADJACENCY;
1032 myIsFillType = true;
1035 #if !defined(GL_ES_VERSION_2_0)
1036 case Graphic3d_TOPA_QUADRANGLES:
1037 myDrawMode = GL_QUADS;
1038 myIsFillType = true;
1040 case Graphic3d_TOPA_QUADRANGLESTRIPS:
1041 myDrawMode = GL_QUAD_STRIP;
1042 myIsFillType = true;
1044 case Graphic3d_TOPA_POLYGONS:
1045 myDrawMode = GL_POLYGON;
1046 myIsFillType = true;
1049 case Graphic3d_TOPA_QUADRANGLES:
1050 case Graphic3d_TOPA_QUADRANGLESTRIPS:
1051 case Graphic3d_TOPA_POLYGONS:
1053 case Graphic3d_TOPA_UNDEFINED:
1054 myDrawMode = DRAW_MODE_NONE;
1055 myIsFillType = false;
1060 // =======================================================================
1061 // function : processIndices
1063 // =======================================================================
1064 Standard_Boolean OpenGl_PrimitiveArray::processIndices (const Handle(OpenGl_Context)& theContext) const
1066 if (myIndices.IsNull()
1067 || myAttribs.IsNull()
1068 || theContext->hasUintIndex)
1070 return Standard_True;
1073 if (myAttribs->NbElements > std::numeric_limits<GLushort>::max())
1075 Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (new NCollection_AlignedAllocator (16));
1076 if (!anAttribs->Init (myIndices->NbElements, myAttribs->AttributesArray(), myAttribs->NbAttributes))
1078 return Standard_False; // failed to initialize attribute array
1081 for (Standard_Integer anIdxIdx = 0; anIdxIdx < myIndices->NbElements; ++anIdxIdx)
1083 const Standard_Integer anIndex = myIndices->Index (anIdxIdx);
1084 memcpy (anAttribs->ChangeData() + myAttribs->Stride * anIdxIdx,
1085 myAttribs->Data() + myAttribs->Stride * anIndex,
1089 myIndices.Nullify();
1090 myAttribs = anAttribs;
1093 return Standard_True;
1096 // =======================================================================
1097 // function : InitBuffers
1099 // =======================================================================
1100 void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& theContext,
1101 const Graphic3d_TypeOfPrimitiveArray theType,
1102 const Handle(Graphic3d_IndexBuffer)& theIndices,
1103 const Handle(Graphic3d_Buffer)& theAttribs,
1104 const Handle(Graphic3d_BoundBuffer)& theBounds)
1106 // Release old graphic resources
1107 Release (theContext.get());
1109 myIndices = theIndices;
1110 myAttribs = theAttribs;
1111 myBounds = theBounds;
1112 #if defined(GL_ES_VERSION_2_0)
1113 processIndices (theContext);
1116 setDrawMode (theType);