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