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