0031505: Point Cloud Rendering - fix on-screen statistics about number of visible...
[occt.git] / src / OpenGl / OpenGl_PrimitiveArray.cxx
CommitLineData
b311480e 1// Created on: 2011-07-13
2// Created by: Sergey ZERCHANINOV
de75ed09 3// Copyright (c) 2011-2013 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 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
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
b311480e 15
bf5f0ca2 16#include <OpenGl_Aspects.hxx>
30f0ad28 17#include <OpenGl_Context.hxx>
2166f0fa 18#include <OpenGl_GraphicDriver.hxx>
30f0ad28 19#include <OpenGl_IndexBuffer.hxx>
a577aaab 20#include <OpenGl_PointSprite.hxx>
30f0ad28 21#include <OpenGl_PrimitiveArray.hxx>
cc8cbabe 22#include <OpenGl_Sampler.hxx>
30f0ad28 23#include <OpenGl_ShaderManager.hxx>
24#include <OpenGl_ShaderProgram.hxx>
2166f0fa 25#include <OpenGl_Structure.hxx>
7d3e64ef 26#include <OpenGl_VertexBufferCompat.hxx>
6ef0d6f1 27#include <OpenGl_View.hxx>
bf75be98 28#include <OpenGl_Workspace.hxx>
6c6aadb1 29#include <Graphic3d_TextureParams.hxx>
e99a2f7c 30#include <NCollection_AlignedAllocator.hxx>
2166f0fa 31
30f0ad28 32namespace
33{
871fa103 34 //! Convert data type to GL info
35 inline GLenum toGlDataType (const Graphic3d_TypeOfData theType,
36 GLint& theNbComp)
37 {
38 switch (theType)
39 {
40 case Graphic3d_TOD_USHORT:
41 theNbComp = 1;
42 return GL_UNSIGNED_SHORT;
43 case Graphic3d_TOD_UINT:
44 theNbComp = 1;
45 return GL_UNSIGNED_INT;
46 case Graphic3d_TOD_VEC2:
47 theNbComp = 2;
48 return GL_FLOAT;
49 case Graphic3d_TOD_VEC3:
50 theNbComp = 3;
51 return GL_FLOAT;
52 case Graphic3d_TOD_VEC4:
53 theNbComp = 4;
54 return GL_FLOAT;
55 case Graphic3d_TOD_VEC4UB:
56 theNbComp = 4;
57 return GL_UNSIGNED_BYTE;
4a535d3f 58 case Graphic3d_TOD_FLOAT:
59 theNbComp = 1;
60 return GL_FLOAT;
871fa103 61 }
62 theNbComp = 0;
63 return GL_NONE;
64 }
65
30f0ad28 66}
67
871fa103 68//! Auxiliary template for VBO with interleaved attributes.
7d3e64ef 69template<class TheBaseClass, int NbAttributes>
70class OpenGl_VertexBufferT : public TheBaseClass
7fd59977 71{
871fa103 72public:
73
74 //! Create uninitialized VBO.
871fa103 75 OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
da87ddc3 76 : Stride (theAttribs.IsInterleaved() ? theAttribs.Stride : 0)
871fa103 77 {
78 memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
79 }
80
81 virtual bool HasColorAttribute() const
82 {
83 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
84 {
85 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
86 if (anAttrib.Id == Graphic3d_TOA_COLOR)
87 {
88 return true;
89 }
90 }
91 return false;
92 }
93
7d3e64ef 94 virtual bool HasNormalAttribute() const
95 {
96 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
97 {
98 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
99 if (anAttrib.Id == Graphic3d_TOA_NORM)
100 {
101 return true;
102 }
103 }
104 return false;
105 }
106
107 virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
871fa103 108 {
7d3e64ef 109 if (!TheBaseClass::IsValid())
871fa103 110 {
111 return;
112 }
113
7d3e64ef 114 TheBaseClass::Bind (theGlCtx);
871fa103 115 GLint aNbComp;
7d3e64ef 116 const GLubyte* anOffset = TheBaseClass::myOffset;
da87ddc3 117 const Standard_Size aMuliplier = Stride != 0 ? 1 : TheBaseClass::myElemsNb;
871fa103 118 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
119 {
120 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
121 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
34253146 122 if (anAttrib.Id == Graphic3d_TOA_POS
123 && aDataType != GL_NONE)
871fa103 124 {
7d3e64ef 125 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
871fa103 126 break;
127 }
128
da87ddc3 129 anOffset += aMuliplier * Graphic3d_Attribute::Stride (anAttrib.DataType);
871fa103 130 }
131 }
132
7d3e64ef 133 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
871fa103 134 {
7d3e64ef 135 if (!TheBaseClass::IsValid())
871fa103 136 {
137 return;
138 }
139
7d3e64ef 140 TheBaseClass::Bind (theGlCtx);
871fa103 141 GLint aNbComp;
7d3e64ef 142 const GLubyte* anOffset = TheBaseClass::myOffset;
da87ddc3 143 const Standard_Size aMuliplier = Stride != 0 ? 1 : TheBaseClass::myElemsNb;
871fa103 144 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
145 {
146 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
147 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
34253146 148 if (aDataType != GL_NONE)
871fa103 149 {
34253146 150 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
871fa103 151 }
da87ddc3 152 anOffset += aMuliplier * Graphic3d_Attribute::Stride (anAttrib.DataType);
871fa103 153 }
154 }
155
7d3e64ef 156 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
871fa103 157 {
7d3e64ef 158 if (!TheBaseClass::IsValid())
871fa103 159 {
160 return;
161 }
7d3e64ef 162 TheBaseClass::Unbind (theGlCtx);
871fa103 163
164 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
165 {
166 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
7d3e64ef 167 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
871fa103 168 }
169 }
170
34253146 171private:
871fa103 172
173 Graphic3d_Attribute Attribs[NbAttributes];
174 Standard_Integer Stride;
175
176};
7fd59977 177
2166f0fa
SK
178// =======================================================================
179// function : clearMemoryGL
180// purpose :
181// =======================================================================
5e27df78 182void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
7fd59977 183{
871fa103 184 if (!myVboIndices.IsNull())
2166f0fa 185 {
871fa103 186 myVboIndices->Release (theGlCtx.operator->());
187 myVboIndices.Nullify();
188 }
189 if (!myVboAttribs.IsNull())
190 {
191 myVboAttribs->Release (theGlCtx.operator->());
192 myVboAttribs.Nullify();
2166f0fa 193 }
7fd59977 194}
195
2166f0fa 196// =======================================================================
7d3e64ef 197// function : initNormalVbo
2166f0fa
SK
198// purpose :
199// =======================================================================
7d3e64ef 200Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
7fd59977 201{
7d3e64ef 202 switch (myAttribs->NbAttributes)
2166f0fa 203 {
7d3e64ef 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;
214 }
215
da87ddc3 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))
221 {
222 throw Standard_ProgramError ("OpenGl_PrimitiveArray::buildVBO() - vertex attribute data with reserved size is not supported");
223 }
224
15669413 225 // specify data type as Byte and NbComponents as Stride, so that OpenGl_VertexBuffer::EstimatedDataSize() will return correct value
da87ddc3 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))
7d3e64ef 228 {
da87ddc3 229 TCollection_ExtendedString aMsg = TCollection_ExtendedString("VBO creation for Primitive Array has failed for ") + aNbVertexes + " vertices. Out of memory?";
3b523c4c 230 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
7d3e64ef 231
232 clearMemoryGL (theCtx);
5e27df78 233 return Standard_False;
2166f0fa 234 }
7d3e64ef 235 else if (myIndices.IsNull())
236 {
da87ddc3 237 if (isAttribMutable && isAttribInterleaved)
238 {
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);
242 }
7d3e64ef 243 return Standard_True;
244 }
7fd59977 245
da87ddc3 246 const Standard_Integer aNbIndexes = !myIndices->IsMutable() ? myIndices->NbElements : myIndices->NbMaxElements();
7d3e64ef 247 myVboIndices = new OpenGl_IndexBuffer();
248 bool isOk = false;
249 switch (myIndices->Stride)
250 {
251 case 2:
252 {
da87ddc3 253 isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast<const GLushort*> (myIndices->Data()));
254 myVboIndices->SetElemsNb (myIndices->NbElements);
255 myIndices->Validate();
7d3e64ef 256 break;
257 }
258 case 4:
259 {
da87ddc3 260 isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast<const GLuint*> (myIndices->Data()));
261 myVboIndices->SetElemsNb (myIndices->NbElements);
262 myIndices->Validate();
7d3e64ef 263 break;
264 }
265 default:
266 {
267 clearMemoryGL (theCtx);
268 return Standard_False;
269 }
270 }
271 if (!isOk)
2166f0fa 272 {
da87ddc3 273 TCollection_ExtendedString aMsg = TCollection_ExtendedString("VBO creation for Primitive Array has failed for ") + aNbIndexes + " indices. Out of memory?";
3b523c4c 274 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
7d3e64ef 275 clearMemoryGL (theCtx);
276 return Standard_False;
7fd59977 277 }
7d3e64ef 278 return Standard_True;
279}
871fa103 280
7d3e64ef 281// =======================================================================
282// function : buildVBO
283// purpose :
284// =======================================================================
285Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
286 const Standard_Boolean theToKeepData) const
287{
288 bool isNormalMode = theCtx->ToUseVbo();
536d98e2 289 clearMemoryGL (theCtx);
7d3e64ef 290 if (myAttribs.IsNull()
291 || myAttribs->IsEmpty()
292 || myAttribs->NbElements < 1
293 || myAttribs->NbAttributes < 1
294 || myAttribs->NbAttributes > 10)
2166f0fa 295 {
7d3e64ef 296 // vertices should be always defined - others are optional
871fa103 297 return Standard_False;
7fd59977 298 }
871fa103 299
7d3e64ef 300 if (isNormalMode
301 && initNormalVbo (theCtx))
302 {
303 if (!theCtx->caps->keepArrayData
da87ddc3 304 && !theToKeepData
305 && !myAttribs->IsMutable())
7d3e64ef 306 {
307 myIndices.Nullify();
308 myAttribs.Nullify();
309 }
da87ddc3 310 else
311 {
312 myAttribs->Validate();
313 }
7d3e64ef 314 return Standard_True;
315 }
316
317 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
318 switch (myAttribs->NbAttributes)
319 {
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;
330 }
331 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
871fa103 332 if (!myIndices.IsNull())
2166f0fa 333 {
7d3e64ef 334 Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
871fa103 335 switch (myIndices->Stride)
5e27df78 336 {
871fa103 337 case 2:
338 {
7d3e64ef 339 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
871fa103 340 break;
341 }
342 case 4:
343 {
7d3e64ef 344 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
871fa103 345 break;
346 }
7d3e64ef 347 default:
348 {
349 return Standard_False;
350 }
5e27df78 351 }
7d3e64ef 352 myVboIndices = aVboIndices;
2166f0fa 353 }
7d3e64ef 354 myVboAttribs = aVboAttribs;
355 if (!theCtx->caps->keepArrayData
356 && !theToKeepData)
e276548b 357 {
7d3e64ef 358 // does not make sense for compatibility mode
359 //myIndices.Nullify();
360 //myAttribs.Nullify();
e276548b 361 }
7d3e64ef 362
2166f0fa 363 return Standard_True;
7fd59977 364}
365
2166f0fa 366// =======================================================================
da87ddc3 367// function : updateVBO
368// purpose :
369// =======================================================================
370void OpenGl_PrimitiveArray::updateVBO (const Handle(OpenGl_Context)& theCtx) const
371{
372 if (!myAttribs.IsNull())
373 {
374 Graphic3d_BufferRange aRange = myAttribs->InvalidatedRange();
375 if (!aRange.IsEmpty()
376 && myVboAttribs->IsValid()
377 && !myVboAttribs->IsVirtual())
378 {
379 myVboAttribs->Bind (theCtx);
380 theCtx->core15fwd->glBufferSubData (myVboAttribs->GetTarget(),
381 aRange.Start,
382 aRange.Length,
383 myAttribs->Data() + aRange.Start);
384 myVboAttribs->Unbind (theCtx);
385 if (myAttribs->IsInterleaved())
386 {
387 myVboAttribs->SetElemsNb (myAttribs->NbElements);
388 }
389 }
390 myAttribs->Validate();
391 }
392 if (!myIndices.IsNull())
393 {
394 Graphic3d_BufferRange aRange = myIndices->InvalidatedRange();
395 if (!aRange.IsEmpty()
396 && myVboIndices->IsValid()
397 && !myVboIndices->IsVirtual())
398 {
399 myVboIndices->Bind (theCtx);
400 theCtx->core15fwd->glBufferSubData (myVboIndices->GetTarget(),
401 aRange.Start,
402 aRange.Length,
403 myIndices->Data() + aRange.Start);
404 myVboIndices->Unbind (theCtx);
405 myVboIndices->SetElemsNb (myIndices->NbElements);
406 }
407 myIndices->Validate();
408 }
409}
410
411// =======================================================================
7d3e64ef 412// function : drawArray
2166f0fa
SK
413// purpose :
414// =======================================================================
7d3e64ef 415void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
8625ef7e 416 const Graphic3d_Vec4* theFaceColors,
417 const Standard_Boolean theHasVertColor) const
7fd59977 418{
7d3e64ef 419 if (myVboAttribs.IsNull())
2166f0fa 420 {
ca3c13d1 421 #if !defined(GL_ES_VERSION_2_0)
7d3e64ef 422 if (myDrawMode == GL_POINTS)
423 {
424 // extreme compatibility mode - without sprites but with markers
425 drawMarkers (theWorkspace);
426 }
ca3c13d1 427 #endif
7d3e64ef 428 return;
7fd59977 429 }
430
8e0a2b19 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()
435 ? GL_PATCHES
436 : myDrawMode;
7d3e64ef 437 myVboAttribs->BindAllAttributes (aGlContext);
8625ef7e 438 if (theHasVertColor && toHilight)
2166f0fa 439 {
8625ef7e 440 // disable per-vertex color
441 OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
7d3e64ef 442 }
443 if (!myVboIndices.IsNull())
444 {
445 myVboIndices->Bind (aGlContext);
446 GLubyte* anOffset = myVboIndices->GetDataOffset();
447 if (!myBounds.IsNull())
2166f0fa 448 {
7d3e64ef 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)
2166f0fa 452 {
7d3e64ef 453 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
8625ef7e 454 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
8e0a2b19 455 glDrawElements (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
7d3e64ef 456 anOffset += aStride * aNbElemsInGroup;
762aacae 457 }
bf75be98 458 }
2166f0fa
SK
459 else
460 {
7d3e64ef 461 // draw one (or sequential) primitive by the indices
8e0a2b19 462 glDrawElements (aDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
5e27df78 463 }
7d3e64ef 464 myVboIndices->Unbind (aGlContext);
7fd59977 465 }
7d3e64ef 466 else if (!myBounds.IsNull())
871fa103 467 {
7d3e64ef 468 GLint aFirstElem = 0;
469 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
470 {
471 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
8625ef7e 472 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
8e0a2b19 473 glDrawArrays (aDrawMode, aFirstElem, aNbElemsInGroup);
7d3e64ef 474 aFirstElem += aNbElemsInGroup;
475 }
871fa103 476 }
7d3e64ef 477 else
2166f0fa 478 {
7d3e64ef 479 if (myDrawMode == GL_POINTS)
480 {
481 drawMarkers (theWorkspace);
482 }
483 else
484 {
8e0a2b19 485 glDrawArrays (aDrawMode, 0, myVboAttribs->GetElemsNb());
7d3e64ef 486 }
2166f0fa
SK
487 }
488
7d3e64ef 489 // bind with 0
490 myVboAttribs->UnbindAllAttributes (aGlContext);
7fd59977 491}
492
2166f0fa 493// =======================================================================
7d3e64ef 494// function : drawEdges
2166f0fa
SK
495// purpose :
496// =======================================================================
bf5f0ca2 497void OpenGl_PrimitiveArray::drawEdges (const Handle(OpenGl_Workspace)& theWorkspace) const
7fd59977 498{
65360da3 499 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
7d3e64ef 500 if (myVboAttribs.IsNull())
501 {
502 return;
503 }
504
bf5f0ca2 505 const OpenGl_Aspects* anAspect = theWorkspace->Aspects();
ca3c13d1 506#if !defined(GL_ES_VERSION_2_0)
2a332745 507 const Standard_Integer aPolyModeOld = aGlContext->SetPolygonMode (GL_LINE);
ca3c13d1 508#endif
7d3e64ef 509
4e1523ef 510 if (aGlContext->core20fwd != NULL)
7d3e64ef 511 {
bf5f0ca2 512 aGlContext->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), anAspect->Aspect()->EdgeLineType(),
c40eb6b9 513 Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, Standard_False,
b6472664 514 anAspect->ShaderProgramRes (aGlContext));
2166f0fa 515 }
bf5f0ca2 516 aGlContext->SetSampleAlphaToCoverage (aGlContext->ShaderManager()->MaterialState().HasAlphaCutoff());
8e0a2b19 517 const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull()
518 && aGlContext->ActiveProgram()->HasTessellationStage()
519 ? GL_PATCHES
520 : myDrawMode;
dd1ae9df 521#if !defined(GL_ES_VERSION_2_0)
522 if (aGlContext->ActiveProgram().IsNull()
523 && aGlContext->core11 != NULL)
524 {
525 glDisable (GL_LIGHTING);
526 }
527#endif
7fd59977 528
5e27df78 529 /// OCC22236 NOTE: draw edges for all situations:
871fa103 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.
5e27df78 532 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
7d3e64ef 533 myVboAttribs->BindPositionAttribute (aGlContext);
ac116c22 534
bf5f0ca2 535 aGlContext->SetColor4fv (theWorkspace->EdgeColor().a() >= 0.1f
536 ? theWorkspace->EdgeColor()
537 : theWorkspace->View()->BackgroundColor());
3f1675c9 538 aGlContext->SetLineStipple(anAspect->Aspect()->LinePattern());
bf5f0ca2 539 aGlContext->SetLineWidth (anAspect->Aspect()->EdgeWidth());
ac116c22 540
7d3e64ef 541 if (!myVboIndices.IsNull())
bf75be98 542 {
7d3e64ef 543 myVboIndices->Bind (aGlContext);
544 GLubyte* anOffset = myVboIndices->GetDataOffset();
2166f0fa 545
7d3e64ef 546 // draw primitives by vertex count with the indices
547 if (!myBounds.IsNull())
2166f0fa 548 {
7d3e64ef 549 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
871fa103 550 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
2166f0fa 551 {
871fa103 552 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
8e0a2b19 553 glDrawElements (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
7d3e64ef 554 anOffset += aStride * aNbElemsInGroup;
7fd59977 555 }
556 }
7d3e64ef 557 // draw one (or sequential) primitive by the indices
2166f0fa
SK
558 else
559 {
8e0a2b19 560 glDrawElements (aDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
762aacae 561 }
7d3e64ef 562 myVboIndices->Unbind (aGlContext);
2166f0fa 563 }
7d3e64ef 564 else if (!myBounds.IsNull())
2166f0fa 565 {
7d3e64ef 566 GLint aFirstElem = 0;
567 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
2166f0fa 568 {
7d3e64ef 569 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
8e0a2b19 570 glDrawArrays (aDrawMode, aFirstElem, aNbElemsInGroup);
7d3e64ef 571 aFirstElem += aNbElemsInGroup;
7fd59977 572 }
2166f0fa 573 }
7d3e64ef 574 else
575 {
8e0a2b19 576 glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
7d3e64ef 577 }
578
579 // unbind buffers
580 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
2166f0fa 581
8625ef7e 582 // restore line context
2a332745 583#if !defined(GL_ES_VERSION_2_0)
584 aGlContext->SetPolygonMode (aPolyModeOld);
585#endif
7fd59977 586}
587
2166f0fa 588// =======================================================================
7d3e64ef 589// function : drawMarkers
a577aaab 590// purpose :
591// =======================================================================
7d3e64ef 592void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
a577aaab 593{
bf5f0ca2 594 const OpenGl_Aspects* anAspectMarker = theWorkspace->Aspects();
737e9a8d 595 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
8e0a2b19 596 const GLenum aDrawMode = !aCtx->ActiveProgram().IsNull()
597 && aCtx->ActiveProgram()->HasTessellationStage()
598 ? GL_PATCHES
599 : myDrawMode;
737e9a8d 600 if (anAspectMarker->HasPointSprite (aCtx))
a577aaab 601 {
602 // Textured markers will be drawn with the point sprites
8625ef7e 603 aCtx->SetPointSize (anAspectMarker->MarkerSize());
fd59283a 604 aCtx->SetPointSpriteOrigin();
ca3c13d1 605 #if !defined(GL_ES_VERSION_2_0)
4e1523ef 606 if (aCtx->core11 != NULL)
607 {
608 aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
609 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
610 }
ca3c13d1 611 #endif
a577aaab 612
8625ef7e 613 aCtx->core11fwd->glEnable (GL_BLEND);
614 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
a577aaab 615
8e0a2b19 616 aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
a577aaab 617
8625ef7e 618 aCtx->core11fwd->glDisable (GL_BLEND);
ca3c13d1 619 #if !defined(GL_ES_VERSION_2_0)
4e1523ef 620 if (aCtx->core11 != NULL)
621 {
c40eb6b9 622 if (aCtx->ShaderManager()->MaterialState().AlphaCutoff() >= ShortRealLast())
623 {
624 aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
625 }
626 else
627 {
628 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, aCtx->ShaderManager()->MaterialState().AlphaCutoff());
629 }
4e1523ef 630 }
ca3c13d1 631 #endif
8625ef7e 632 aCtx->SetPointSize (1.0f);
a577aaab 633 return;
634 }
bf5f0ca2 635 else if (anAspectMarker->Aspect()->MarkerType() == Aspect_TOM_POINT)
a577aaab 636 {
8625ef7e 637 aCtx->SetPointSize (anAspectMarker->MarkerSize());
8e0a2b19 638 aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
8625ef7e 639 aCtx->SetPointSize (1.0f);
a577aaab 640 }
ca3c13d1 641#if !defined(GL_ES_VERSION_2_0)
8625ef7e 642 // Textured markers will be drawn with the glBitmap
737e9a8d 643 else if (anAspectMarker->Aspect()->MarkerType() != Aspect_TOM_POINT)
a577aaab 644 {
737e9a8d 645 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx, false);
646 if (aSpriteNorm.IsNull())
647 {
648 return;
649 }
650
871fa103 651 /**if (!isHilight && (myPArray->vcolours != NULL))
a577aaab 652 {
871fa103 653 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
a577aaab 654 {
871fa103 655 glColor4ubv (myPArray->vcolours[anIter].GetData());
656 glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
a577aaab 657 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
658 }
659 }
871fa103 660 else*/
a577aaab 661 {
871fa103 662 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
a577aaab 663 {
8625ef7e 664 aCtx->core11->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
a577aaab 665 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
666 }
667 }
668 }
ca3c13d1 669#endif
a577aaab 670}
671
672// =======================================================================
2166f0fa
SK
673// function : OpenGl_PrimitiveArray
674// purpose :
675// =======================================================================
e1c659da 676OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver)
677
678: myDrawMode (DRAW_MODE_NONE),
8e0a2b19 679 myIsFillType(Standard_False),
e1c659da 680 myIsVboInit (Standard_False)
681{
682 if (theDriver != NULL)
683 {
684 myUID = theDriver->GetNextPrimitiveArrayUID();
685 }
686}
687
688// =======================================================================
689// function : OpenGl_PrimitiveArray
690// purpose :
691// =======================================================================
8d3f219f 692OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
693 const Graphic3d_TypeOfPrimitiveArray theType,
871fa103 694 const Handle(Graphic3d_IndexBuffer)& theIndices,
695 const Handle(Graphic3d_Buffer)& theAttribs,
696 const Handle(Graphic3d_BoundBuffer)& theBounds)
8d3f219f 697
871fa103 698: myIndices (theIndices),
699 myAttribs (theAttribs),
700 myBounds (theBounds),
701 myDrawMode (DRAW_MODE_NONE),
8e0a2b19 702 myIsFillType(Standard_False),
c827ea3a 703 myIsVboInit (Standard_False)
2166f0fa 704{
871fa103 705 if (!myIndices.IsNull()
706 && myIndices->NbElements < 1)
707 {
708 // dummy index buffer?
709 myIndices.Nullify();
710 }
871fa103 711
e99a2f7c 712 if (theDriver != NULL)
713 {
714 myUID = theDriver->GetNextPrimitiveArrayUID();
715 #if defined (GL_ES_VERSION_2_0)
716 const Handle(OpenGl_Context)& aCtx = theDriver->GetSharedContext();
717 if (!aCtx.IsNull())
718 {
719 processIndices (aCtx);
720 }
721 #endif
722 }
723
a79f67f8 724 setDrawMode (theType);
2166f0fa
SK
725}
726
727// =======================================================================
728// function : ~OpenGl_PrimitiveArray
729// purpose :
730// =======================================================================
5e27df78 731OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
2166f0fa 732{
5e27df78 733 //
734}
2166f0fa 735
5e27df78 736// =======================================================================
737// function : Release
738// purpose :
739// =======================================================================
10b9c7df 740void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
5e27df78 741{
c827ea3a 742 myIsVboInit = Standard_False;
871fa103 743 if (!myVboIndices.IsNull())
2166f0fa 744 {
10b9c7df 745 if (theContext)
5e27df78 746 {
871fa103 747 theContext->DelayedRelease (myVboIndices);
748 }
749 myVboIndices.Nullify();
750 }
751 if (!myVboAttribs.IsNull())
752 {
10b9c7df 753 if (theContext)
871fa103 754 {
755 theContext->DelayedRelease (myVboAttribs);
5e27df78 756 }
871fa103 757 myVboAttribs.Nullify();
2166f0fa
SK
758 }
759}
760
761// =======================================================================
3d60d73f 762// function : EstimatedDataSize
763// purpose :
764// =======================================================================
765Standard_Size OpenGl_PrimitiveArray::EstimatedDataSize() const
766{
767 Standard_Size aSize = 0;
768 if (!myVboAttribs.IsNull())
769 {
770 aSize += myVboAttribs->EstimatedDataSize();
771 }
772 if (!myVboIndices.IsNull())
773 {
774 aSize += myVboIndices->EstimatedDataSize();
775 }
776 return aSize;
777}
778
779// =======================================================================
b9f43ad1 780// function : UpdateDrawStats
781// purpose :
782// =======================================================================
783void OpenGl_PrimitiveArray::UpdateDrawStats (Graphic3d_FrameStatsDataTmp& theStats,
784 bool theIsDetailed) const
785{
786 ++theStats[Graphic3d_FrameStatsCounter_NbElemsNotCulled];
787 if (myIsFillType)
788 {
789 ++theStats[Graphic3d_FrameStatsCounter_NbElemsFillNotCulled];
790 }
791 else if (myDrawMode == GL_POINTS)
792 {
793 ++theStats[Graphic3d_FrameStatsCounter_NbElemsPointNotCulled];
794 }
795 else
796 {
797 ++theStats[Graphic3d_FrameStatsCounter_NbElemsLineNotCulled];
798 }
799
800 if (!theIsDetailed
801 || myVboAttribs.IsNull()
802 || !myVboAttribs->IsValid())
803 {
804 return;
805 }
806
807 const Standard_Integer aNbIndices = !myVboIndices.IsNull() ? myVboIndices->GetElemsNb() : myVboAttribs->GetElemsNb();
808 const Standard_Integer aNbBounds = !myBounds.IsNull() ? myBounds->NbBounds : 1;
809 switch (myDrawMode)
810 {
811 case GL_POINTS:
812 {
813 theStats[Graphic3d_FrameStatsCounter_NbPointsNotCulled] += aNbIndices;
814 break;
815 }
816 case GL_LINES:
817 {
818 theStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled] += aNbIndices / 2;
819 break;
820 }
821 case GL_LINE_STRIP:
822 {
823 theStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled] += aNbIndices - aNbBounds;
824 break;
825 }
826 case GL_LINES_ADJACENCY:
827 {
828 theStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled] += aNbIndices / 4;
829 break;
830 }
831 case GL_LINE_STRIP_ADJACENCY:
832 {
833 theStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled] += aNbIndices - 4 * aNbBounds;
834 break;
835 }
836 case GL_TRIANGLES:
837 {
838 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 3;
839 break;
840 }
841 case GL_TRIANGLE_STRIP:
842 case GL_TRIANGLE_FAN:
843 {
844 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices - 2 * aNbBounds;
845 break;
846 }
847 case GL_TRIANGLES_ADJACENCY:
848 {
849 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 6;
850 break;
851 }
852 case GL_TRIANGLE_STRIP_ADJACENCY:
853 {
854 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices - 4 * aNbBounds;
855 break;
856 }
857 #if !defined(GL_ES_VERSION_2_0)
858 case GL_QUADS:
859 {
860 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 2;
861 break;
862 }
863 case GL_QUAD_STRIP:
864 {
865 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += (aNbIndices / 2 - aNbBounds) * 2;
866 break;
867 }
868 #endif
869 }
870}
871
872// =======================================================================
2166f0fa
SK
873// function : Render
874// purpose :
875// =======================================================================
876void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
877{
871fa103 878 if (myDrawMode == DRAW_MODE_NONE)
bf75be98 879 {
2166f0fa 880 return;
bf75be98 881 }
2166f0fa 882
72f6dc61 883 const OpenGl_Aspects* anAspectFace = theWorkspace->Aspects();
58655684 884 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
2166f0fa 885
72f6dc61 886 bool toDrawArray = true, toSetLinePolygMode = false;
2a332745 887 int toDrawInteriorEdges = 0; // 0 - no edges, 1 - glsl edges, 2 - polygonMode
6ef0d6f1 888 if (myIsFillType)
3a4a3962 889 {
890 toDrawArray = anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_EMPTY;
2a332745 891 if (anAspectFace->Aspect()->ToDrawEdges())
892 {
893 toDrawInteriorEdges = 1;
894 toDrawArray = true;
895 #if !defined(GL_ES_VERSION_2_0)
896 if (anAspectFace->Aspect()->EdgeLineType() != Aspect_TOL_SOLID
897 || aCtx->hasGeometryStage == OpenGl_FeatureNotAvailable
898 || aCtx->caps->usePolygonMode)
899 {
900 toDrawInteriorEdges = 2;
901 if (anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_EMPTY)
902 {
903 if (anAspectFace->Aspect()->EdgeLineType() != Aspect_TOL_SOLID)
904 {
905 toDrawArray = false;
906 }
907 else
908 {
72f6dc61 909 toSetLinePolygMode = true;
2a332745 910 }
911 }
912 }
913 #endif
914 }
3a4a3962 915 }
6ef0d6f1 916 else
8625ef7e 917 {
3a4a3962 918 if (myDrawMode == GL_POINTS)
919 {
bf5f0ca2 920 if (anAspectFace->Aspect()->MarkerType() == Aspect_TOM_EMPTY)
6ef0d6f1 921 {
922 return;
923 }
3a4a3962 924 }
925 else
926 {
bf5f0ca2 927 if (anAspectFace->Aspect()->LineType() == Aspect_TOL_EMPTY)
6ef0d6f1 928 {
929 return;
930 }
931 }
6ef0d6f1 932 }
933
934 // create VBOs on first render call
935 if (!myIsVboInit)
936 {
937 // compatibility - keep data to draw markers using display lists
737e9a8d 938 Standard_Boolean toKeepData = myDrawMode == GL_POINTS
939 && anAspectFace->IsDisplayListSprite (aCtx);
6ef0d6f1 940 #if defined (GL_ES_VERSION_2_0)
941 processIndices (aCtx);
942 #endif
943 buildVBO (aCtx, toKeepData);
944 myIsVboInit = Standard_True;
945 }
946 else if ((!myAttribs.IsNull()
947 && myAttribs->IsMutable())
948 || (!myIndices.IsNull()
949 && myIndices->IsMutable()))
950 {
951 updateVBO (aCtx);
8625ef7e 952 }
7d3e64ef 953
db5d29de 954 Graphic3d_TypeOfShadingModel aShadingModel = Graphic3d_TOSM_UNLIT;
72f6dc61 955 anAspectFace = theWorkspace->ApplyAspects (false); // do not bind textures before binding the program
956 const Handle(OpenGl_TextureSet)& aTextureSet = theWorkspace->TextureSet();
957 const bool toEnableEnvMap = !aTextureSet.IsNull()
958 && aTextureSet == theWorkspace->EnvironmentTexture();
3a4a3962 959 if (toDrawArray)
7d3e64ef 960 {
db5d29de 961 const bool hasColorAttrib = !myVboAttribs.IsNull()
962 && myVboAttribs->HasColorAttribute();
963 const bool toHilight = theWorkspace->ToHighlight();
964 const bool hasVertColor = hasColorAttrib && !toHilight;
965 const bool hasVertNorm = !myVboAttribs.IsNull() && myVboAttribs->HasNormalAttribute();
8613985b 966 switch (myDrawMode)
8625ef7e 967 {
8613985b 968 case GL_POINTS:
8625ef7e 969 {
db5d29de 970 aShadingModel = aCtx->ShaderManager()->ChooseMarkerShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
72f6dc61 971 aCtx->ShaderManager()->BindMarkerProgram (aTextureSet,
737e9a8d 972 aShadingModel, Graphic3d_AlphaMode_Opaque,
973 hasVertColor, anAspectFace->ShaderProgramRes (aCtx));
8613985b 974 break;
975 }
976 case GL_LINES:
977 case GL_LINE_STRIP:
978 {
db5d29de 979 aShadingModel = aCtx->ShaderManager()->ChooseLineShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
737e9a8d 980 aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(),
bf5f0ca2 981 anAspectFace->Aspect()->LineType(),
dc89236f 982 aShadingModel,
c40eb6b9 983 Graphic3d_AlphaMode_Opaque,
8613985b 984 hasVertColor,
bf5f0ca2 985 anAspectFace->ShaderProgramRes (aCtx));
8613985b 986 break;
987 }
988 default:
989 {
db5d29de 990 aShadingModel = aCtx->ShaderManager()->ChooseFaceShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
72f6dc61 991 aCtx->ShaderManager()->BindFaceProgram (aTextureSet,
dc89236f 992 aShadingModel,
2a332745 993 aCtx->ShaderManager()->MaterialState().HasAlphaCutoff() ? Graphic3d_AlphaMode_Mask : Graphic3d_AlphaMode_Opaque,
994 toDrawInteriorEdges == 1 ? anAspectFace->Aspect()->InteriorStyle() : Aspect_IS_SOLID,
8613985b 995 hasVertColor,
996 toEnableEnvMap,
2a332745 997 toDrawInteriorEdges == 1,
8613985b 998 anAspectFace->ShaderProgramRes (aCtx));
2a332745 999 if (toDrawInteriorEdges == 1)
1000 {
1001 aCtx->ShaderManager()->PushInteriorState (aCtx->ActiveProgram(), anAspectFace->Aspect());
1002 }
72f6dc61 1003 #if !defined (GL_ES_VERSION_2_0)
1004 else if (toSetLinePolygMode)
1005 {
1006 aCtx->SetPolygonMode (GL_LINE);
1007 }
1008 #else
1009 (void )toSetLinePolygMode;
1010 #endif
8613985b 1011 break;
8625ef7e 1012 }
1013 }
1014
72f6dc61 1015 // bind textures after GLSL program to set mock textures to slots used by program
1016 aCtx->BindTextures (aTextureSet, aCtx->ActiveProgram());
1017 if (!aTextureSet.IsNull()
1018 && !aTextureSet->IsEmpty()
79f4f036 1019 && myDrawMode != GL_POINTS) // transformation is not supported within point sprites
1020 {
72f6dc61 1021 if (const Handle(OpenGl_Texture)& aFirstTexture = aTextureSet->First())
1022 {
1023 aCtx->SetTextureMatrix (aFirstTexture->Sampler()->Parameters());
1024 }
79f4f036 1025 }
bf5f0ca2 1026 aCtx->SetSampleAlphaToCoverage (aCtx->ShaderManager()->MaterialState().HasAlphaCutoff());
79f4f036 1027
6ef0d6f1 1028 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_HIDDENLINE
1029 ? myBounds->Colors
1030 : NULL;
bf5f0ca2 1031 const OpenGl_Vec4& anInteriorColor = theWorkspace->InteriorColor();
1032 aCtx->SetColor4fv (anInteriorColor);
6ef0d6f1 1033 if (!myIsFillType)
f9ba5c4d 1034 {
6ef0d6f1 1035 if (myDrawMode == GL_LINES
1036 || myDrawMode == GL_LINE_STRIP)
1037 {
3f1675c9 1038 aCtx->SetLineStipple(anAspectFace->Aspect()->LinePattern());
bf5f0ca2 1039 aCtx->SetLineWidth (anAspectFace->Aspect()->LineWidth());
6ef0d6f1 1040 }
1041
1042 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
6ef0d6f1 1043 return;
ac116c22 1044 }
7d3e64ef 1045
8625ef7e 1046 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
7d3e64ef 1047
6ef0d6f1 1048 // draw outline - only closed triangulation with defined vertex normals can be drawn in this way
1049 if (anAspectFace->Aspect()->ToDrawSilhouette()
1050 && aCtx->ToCullBackFaces()
1051 && aCtx->ShaderManager()->BindOutlineProgram())
1052 {
1053 const Graphic3d_Vec2i aViewSize (aCtx->Viewport()[2], aCtx->Viewport()[3]);
1054 const Standard_Integer aMin = aViewSize.minComp();
1055 const GLfloat anEdgeWidth = (GLfloat )anAspectFace->Aspect()->EdgeWidth() * aCtx->LineWidthScale() / (GLfloat )aMin;
1056 const GLfloat anOrthoScale = theWorkspace->View()->Camera()->IsOrthographic() ? (GLfloat )theWorkspace->View()->Camera()->Scale() : -1.0f;
1057
1058 const Handle(OpenGl_ShaderProgram)& anOutlineProgram = aCtx->ActiveProgram();
1059 anOutlineProgram->SetUniform (aCtx, anOutlineProgram->GetStateLocation (OpenGl_OCCT_SILHOUETTE_THICKNESS), anEdgeWidth);
1060 anOutlineProgram->SetUniform (aCtx, anOutlineProgram->GetStateLocation (OpenGl_OCCT_ORTHO_SCALE), anOrthoScale);
1061 aCtx->SetColor4fv (anAspectFace->Aspect()->EdgeColorRGBA());
1062
1063 aCtx->core11fwd->glCullFace (GL_FRONT);
1064 drawArray (theWorkspace, NULL, false);
1065
1066 aCtx->core11fwd->glCullFace (GL_BACK);
1067 }
8625ef7e 1068 }
6ef0d6f1 1069
2a332745 1070#if !defined(GL_ES_VERSION_2_0)
6ef0d6f1 1071 // draw triangulation edges using Polygon Mode
1072 if (toDrawInteriorEdges == 2)
7d3e64ef 1073 {
2a332745 1074 if (anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_HOLLOW
1075 && anAspectFace->Aspect()->EdgeLineType() == Aspect_TOL_SOLID)
1076 {
1077 aCtx->SetPolygonMode (GL_FILL);
1078 }
1079 else
30f0ad28 1080 {
bf5f0ca2 1081 drawEdges (theWorkspace);
30f0ad28 1082 }
1083 }
2a332745 1084#endif
2166f0fa 1085}
a79f67f8 1086
1087// =======================================================================
1088// function : setDrawMode
1089// purpose :
1090// =======================================================================
1091void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType)
1092{
1093 if (myAttribs.IsNull())
1094 {
1095 myDrawMode = DRAW_MODE_NONE;
8e0a2b19 1096 myIsFillType = false;
a79f67f8 1097 return;
1098 }
1099
1100 switch (theType)
1101 {
1102 case Graphic3d_TOPA_POINTS:
8e0a2b19 1103 myDrawMode = GL_POINTS;
1104 myIsFillType = false;
a79f67f8 1105 break;
1106 case Graphic3d_TOPA_SEGMENTS:
8e0a2b19 1107 myDrawMode = GL_LINES;
1108 myIsFillType = false;
1109 break;
1110 case Graphic3d_TOPA_POLYLINES:
1111 myDrawMode = GL_LINE_STRIP;
1112 myIsFillType = false;
a79f67f8 1113 break;
1114 case Graphic3d_TOPA_TRIANGLES:
8e0a2b19 1115 myDrawMode = GL_TRIANGLES;
1116 myIsFillType = true;
a79f67f8 1117 break;
1118 case Graphic3d_TOPA_TRIANGLESTRIPS:
8e0a2b19 1119 myDrawMode = GL_TRIANGLE_STRIP;
1120 myIsFillType = true;
a79f67f8 1121 break;
1122 case Graphic3d_TOPA_TRIANGLEFANS:
8e0a2b19 1123 myDrawMode = GL_TRIANGLE_FAN;
1124 myIsFillType = true;
a79f67f8 1125 break;
8e0a2b19 1126 //
1127 case Graphic3d_TOPA_LINES_ADJACENCY:
1128 myDrawMode = GL_LINES_ADJACENCY;
1129 myIsFillType = false;
a79f67f8 1130 break;
8e0a2b19 1131 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
1132 myDrawMode = GL_LINE_STRIP_ADJACENCY;
1133 myIsFillType = false;
1134 break;
1135 case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
1136 myDrawMode = GL_TRIANGLES_ADJACENCY;
1137 myIsFillType = true;
1138 break;
1139 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
1140 myDrawMode = GL_TRIANGLE_STRIP_ADJACENCY;
1141 myIsFillType = true;
1142 break;
1143 //
1144 #if !defined(GL_ES_VERSION_2_0)
a79f67f8 1145 case Graphic3d_TOPA_QUADRANGLES:
8e0a2b19 1146 myDrawMode = GL_QUADS;
1147 myIsFillType = true;
a79f67f8 1148 break;
1149 case Graphic3d_TOPA_QUADRANGLESTRIPS:
8e0a2b19 1150 myDrawMode = GL_QUAD_STRIP;
1151 myIsFillType = true;
a79f67f8 1152 break;
a79f67f8 1153 case Graphic3d_TOPA_POLYGONS:
8e0a2b19 1154 myDrawMode = GL_POLYGON;
1155 myIsFillType = true;
1156 break;
1157 #else
a79f67f8 1158 case Graphic3d_TOPA_QUADRANGLES:
1159 case Graphic3d_TOPA_QUADRANGLESTRIPS:
8e0a2b19 1160 case Graphic3d_TOPA_POLYGONS:
a79f67f8 1161 #endif
1162 case Graphic3d_TOPA_UNDEFINED:
8e0a2b19 1163 myDrawMode = DRAW_MODE_NONE;
1164 myIsFillType = false;
a79f67f8 1165 break;
1166 }
1167}
1168
1169// =======================================================================
e99a2f7c 1170// function : processIndices
1171// purpose :
1172// =======================================================================
1173Standard_Boolean OpenGl_PrimitiveArray::processIndices (const Handle(OpenGl_Context)& theContext) const
1174{
1175 if (myIndices.IsNull()
09f30297 1176 || myAttribs.IsNull()
e99a2f7c 1177 || theContext->hasUintIndex)
1178 {
1179 return Standard_True;
1180 }
1181
09f30297 1182 if (myAttribs->NbElements > std::numeric_limits<GLushort>::max())
e99a2f7c 1183 {
1184 Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (new NCollection_AlignedAllocator (16));
1185 if (!anAttribs->Init (myIndices->NbElements, myAttribs->AttributesArray(), myAttribs->NbAttributes))
1186 {
1187 return Standard_False; // failed to initialize attribute array
1188 }
1189
1190 for (Standard_Integer anIdxIdx = 0; anIdxIdx < myIndices->NbElements; ++anIdxIdx)
1191 {
1192 const Standard_Integer anIndex = myIndices->Index (anIdxIdx);
1193 memcpy (anAttribs->ChangeData() + myAttribs->Stride * anIdxIdx,
1194 myAttribs->Data() + myAttribs->Stride * anIndex,
1195 myAttribs->Stride);
1196 }
1197
1198 myIndices.Nullify();
1199 myAttribs = anAttribs;
1200 }
1201
1202 return Standard_True;
1203}
1204
1205// =======================================================================
a79f67f8 1206// function : InitBuffers
1207// purpose :
1208// =======================================================================
1209void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& theContext,
1210 const Graphic3d_TypeOfPrimitiveArray theType,
1211 const Handle(Graphic3d_IndexBuffer)& theIndices,
1212 const Handle(Graphic3d_Buffer)& theAttribs,
1213 const Handle(Graphic3d_BoundBuffer)& theBounds)
1214{
1215 // Release old graphic resources
ad67e367 1216 Release (theContext.get());
a79f67f8 1217
1218 myIndices = theIndices;
1219 myAttribs = theAttribs;
1220 myBounds = theBounds;
e99a2f7c 1221#if defined(GL_ES_VERSION_2_0)
1222 processIndices (theContext);
1223#endif
a79f67f8 1224
1225 setDrawMode (theType);
1226}
bc73b006 1227
1228// =======================================================================
1229// function : DumpJson
1230// purpose :
1231// =======================================================================
1232void OpenGl_PrimitiveArray::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1233{
1234 OCCT_DUMP_CLASS_BEGIN (theOStream, OpenGl_PrimitiveArray)
1235
1236 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, OpenGl_Element)
1237
1238 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myVboIndices.get())
1239 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myVboAttribs.get())
1240
1241 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myIndices.get())
1242 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myAttribs.get())
1243 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myBounds.get())
1244
1245 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDrawMode)
1246 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsFillType)
1247 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsVboInit)
1248 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myUID)
1249}