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