0029337: Visualization, TKOpenGl - visual artifacts on Intel Broadwell GPU
[occt.git] / src / ViewerTest / ViewerTest_OpenGlCommands.cxx
CommitLineData
6aca4d39 1// Created on: 2012-04-09
3946774d 2// Created by: Sergey ANIKIN
6aca4d39 3// Copyright (c) 2012-2014 OPEN CASCADE SAS
3946774d 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
3946774d 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.
3946774d 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
3946774d 15
3946774d 16#include <ViewerTest.hxx>
17
5e27df78 18#include <AIS_InteractiveContext.hxx>
3946774d 19#include <AIS_InteractiveObject.hxx>
20#include <Draw.hxx>
21#include <Draw_Interpretor.hxx>
22#include <Graphic3d_Group.hxx>
392ac980 23#include <Graphic3d_ShaderObject.hxx>
24#include <Graphic3d_ShaderProgram.hxx>
3946774d 25#include <OpenGl_AspectFace.hxx>
26#include <OpenGl_AspectLine.hxx>
27#include <OpenGl_AspectMarker.hxx>
28#include <OpenGl_AspectText.hxx>
3946774d 29#include <OpenGl_Context.hxx>
30#include <OpenGl_Element.hxx>
3946774d 31#include <OpenGl_GlCore20.hxx>
5e27df78 32#include <OpenGl_GraphicDriver.hxx>
8613985b 33#include <OpenGl_ShaderManager.hxx>
3946774d 34#include <OpenGl_Workspace.hxx>
392ac980 35#include <OSD_Environment.hxx>
36#include <OSD_File.hxx>
6262338c 37#include <Prs3d_Drawer.hxx>
3946774d 38#include <Prs3d_Presentation.hxx>
39#include <Prs3d_Root.hxx>
2831708b 40#include <Prs3d_LineAspect.hxx>
392ac980 41#include <Prs3d_ShadingAspect.hxx>
3946774d 42#include <Select3D_SensitiveCurve.hxx>
43#include <SelectMgr_EntityOwner.hxx>
44#include <SelectMgr_Selection.hxx>
45#include <TCollection_AsciiString.hxx>
3c4153af 46#include <V3d_View.hxx>
392ac980 47#include <V3d_Viewer.hxx>
392ac980 48#include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
49#include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
92efcf78 50#include <OpenGl_Group.hxx>
3946774d 51
52extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
53 const Handle(AIS_InteractiveObject)& theAISObj,
54 Standard_Boolean theReplaceIfExists = Standard_True);
392ac980 55extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
3946774d 56
c04c30b3 57namespace {
58
3946774d 59//=======================================================================
60//function : VUserDraw
61//purpose : Checks availability and operation of UserDraw feature
62//=======================================================================
3946774d 63
64class VUserDrawObj : public AIS_InteractiveObject
65{
66public:
67 // CASCADE RTTI
92efcf78 68 DEFINE_STANDARD_RTTI_INLINE(VUserDrawObj,AIS_InteractiveObject);
3946774d 69
70 VUserDrawObj()
71 {
72 myCoords[0] = -10.;
73 myCoords[1] = -20.;
74 myCoords[2] = -30.;
75 myCoords[3] = 10.;
76 myCoords[4] = 20.;
77 myCoords[5] = 30.;
78 }
79
80public:
81 class Element : public OpenGl_Element
82 {
83 private:
84 Handle(VUserDrawObj) myIObj;
85
86 public:
a521d90d 87 Element (const Handle(VUserDrawObj)& theIObj) : myIObj (theIObj) {}
3946774d 88
a521d90d 89 virtual ~Element() {}
3946774d 90
91 virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const
92 {
93 if (!myIObj.IsNull())
94 myIObj->Render(theWorkspace);
95 }
96
10b9c7df 97 virtual void Release (OpenGl_Context*)
5e27df78 98 {
99 //
100 }
101
3946774d 102 public:
103 DEFINE_STANDARD_ALLOC
104 };
105
106private:
107 // Virtual methods implementation
108 void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
109 const Handle(Prs3d_Presentation)& thePresentation,
79104795 110 const Standard_Integer theMode) Standard_OVERRIDE;
3946774d 111
112 void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
79104795 113 const Standard_Integer theMode) Standard_OVERRIDE;
3946774d 114
115 // Called by VUserDrawElement
116 void Render(const Handle(OpenGl_Workspace)& theWorkspace) const;
3946774d 117
a521d90d 118private:
3946774d 119 GLfloat myCoords[6];
3946774d 120 friend class Element;
121};
ec357c5c 122
a521d90d 123void VUserDrawObj::Compute(const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
124 const Handle(Prs3d_Presentation)& thePrs,
35e08fe8 125 const Standard_Integer /*theMode*/)
3946774d 126{
a521d90d 127 thePrs->Clear();
128
129 Graphic3d_Vec4 aBndMin (myCoords[0], myCoords[1], myCoords[2], 1.0f);
130 Graphic3d_Vec4 aBndMax (myCoords[3], myCoords[4], myCoords[5], 1.0f);
131 Handle(OpenGl_Group) aGroup = Handle(OpenGl_Group)::DownCast (thePrs->NewGroup());
132 aGroup->SetMinMaxValues (aBndMin.x(), aBndMin.y(), aBndMin.z(),
133 aBndMax.x(), aBndMax.y(), aBndMax.z());
2831708b 134 aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
a521d90d 135 VUserDrawObj::Element* anElem = new VUserDrawObj::Element (this);
136 aGroup->AddElement(anElem);
137
138 // invalidate bounding box of the scene
cfece3ef 139 thePrsMgr->StructureManager()->Update();
3946774d 140}
141
142void VUserDrawObj::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
35e08fe8 143 const Standard_Integer /*theMode*/)
3946774d 144{
145 Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner(this);
146 Handle(TColgp_HArray1OfPnt) aPnts = new TColgp_HArray1OfPnt(1, 5);
147 aPnts->SetValue(1, gp_Pnt(myCoords[0], myCoords[1], myCoords[2]));
148 aPnts->SetValue(2, gp_Pnt(myCoords[3], myCoords[4], myCoords[2]));
149 aPnts->SetValue(3, gp_Pnt(myCoords[3], myCoords[4], myCoords[5]));
150 aPnts->SetValue(4, gp_Pnt(myCoords[0], myCoords[1], myCoords[5]));
151 aPnts->SetValue(5, gp_Pnt(myCoords[0], myCoords[1], myCoords[2]));
152 Handle(Select3D_SensitiveCurve) aSensitive = new Select3D_SensitiveCurve(anEntityOwner, aPnts);
153 theSelection->Add(aSensitive);
154}
155
3946774d 156void VUserDrawObj::Render(const Handle(OpenGl_Workspace)& theWorkspace) const
157{
1136702b 158 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
a521d90d 159
3946774d 160 // To test linking against OpenGl_Workspace and all aspect classes
f9ba5c4d 161 const OpenGl_AspectMarker* aMA = theWorkspace->AspectMarker();
b6472664 162 aMA->Aspect()->Type();
f9ba5c4d 163 const OpenGl_AspectText* aTA = theWorkspace->AspectText();
b6472664 164 aTA->Aspect()->Font();
165 OpenGl_Vec4 aColor = theWorkspace->LineColor();
3946774d 166
1136702b 167 aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), false, false, false, Handle(OpenGl_ShaderProgram)());
168 aCtx->SetColor4fv (aColor);
169
170 const OpenGl_Vec3 aVertArray[4] =
171 {
172 OpenGl_Vec3(myCoords[0], myCoords[1], myCoords[2]),
173 OpenGl_Vec3(myCoords[3], myCoords[4], myCoords[2]),
174 OpenGl_Vec3(myCoords[3], myCoords[4], myCoords[5]),
175 OpenGl_Vec3(myCoords[0], myCoords[1], myCoords[5]),
176 };
177 Handle(OpenGl_VertexBuffer) aVertBuffer = new OpenGl_VertexBuffer();
178 aVertBuffer->Init (aCtx, 3, 4, aVertArray[0].GetData());
179
3946774d 180 // Finally draw something to make sure UserDraw really works
1136702b 181 aVertBuffer->BindAttribute (aCtx, Graphic3d_TOA_POS);
182 glDrawArrays(GL_LINE_LOOP, 0, aVertBuffer->GetElemsNb());
183 aVertBuffer->UnbindAttribute(aCtx, Graphic3d_TOA_POS);
184 aVertBuffer->Release (aCtx.get());
3946774d 185}
186
c04c30b3 187} // end of anonymous namespace
188
3946774d 189static Standard_Integer VUserDraw (Draw_Interpretor& di,
190 Standard_Integer argc,
191 const char ** argv)
192{
193 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
194 if (aContext.IsNull())
195 {
196 di << argv[0] << "Call 'vinit' before!\n";
197 return 1;
198 }
199
dc3fe572 200 Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5e27df78 201 if (aDriver.IsNull())
202 {
203 std::cerr << "Graphic driver not available.\n";
204 return 1;
205 }
206
3946774d 207 if (argc > 2)
208 {
209 di << argv[0] << "Wrong number of arguments, only the object name expected\n";
210 return 1;
211 }
212
213 TCollection_AsciiString aName (argv[1]);
214 VDisplayAISObject(aName, Handle(AIS_InteractiveObject)());
215
3946774d 216 Handle(VUserDrawObj) anIObj = new VUserDrawObj();
217 VDisplayAISObject(aName, anIObj);
218
219 return 0;
220}
221
3c4153af 222//==============================================================================
223//function : VFeedback
224//purpose :
225//==============================================================================
226
227static int VFeedback (Draw_Interpretor& theDI,
35e08fe8 228 Standard_Integer /*theArgNb*/,
229 const char** /*theArgVec*/)
3c4153af 230{
1ce0716b 231#if !defined(GL_ES_VERSION_2_0)
3c4153af 232 // get the active view
233 Handle(V3d_View) aView = ViewerTest::CurrentView();
234 if (aView.IsNull())
235 {
236 std::cerr << "No active view. Please call vinit.\n";
237 return 1;
238 }
239
240 unsigned int aBufferSize = 1024 * 1024;
241 for (;;)
242 {
243 size_t aBytes = (size_t )aBufferSize * sizeof(GLfloat);
244 if (aBytes / sizeof(GLfloat) != (size_t )aBufferSize)
245 {
246 // finito la commedia
247 std::cerr << "Can not allocate buffer - requested size ("
248 << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat)))
249 << " MiB) is out of address space\n";
250 return 1;
251 }
252
253 GLfloat* aBuffer = (GLfloat* )Standard::Allocate (aBytes);
254 if (aBuffer == NULL)
255 {
256 // finito la commedia
257 std::cerr << "Can not allocate buffer with size ("
258 << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat)))
259 << " MiB)\n";
260 return 1;
261 }
262
263 glFeedbackBuffer ((GLsizei )aBufferSize, GL_2D, aBuffer);
264 glRenderMode (GL_FEEDBACK);
265
266 aView->Redraw();
267
268 GLint aResult = glRenderMode (GL_RENDER);
269 if (aResult < 0)
270 {
271 aBufferSize *= 2;
272
273 void* aPtr = aBuffer;
274 Standard::Free (aPtr);
275 aBuffer = NULL;
276 continue;
277 }
278
279 std::cout << "FeedBack result= " << aResult << "\n";
280 GLint aPntNb = 0;
281 GLint aTriNb = 0;
282 GLint aQuadsNb = 0;
283 GLint aPolyNb = 0;
284 GLint aNodesNb = 0;
285 GLint aLinesNb = 0;
286 GLint aBitmapsNb = 0;
287 GLint aPassThrNb = 0;
288 GLint aUnknownNb = 0;
289 const GLint NODE_VALUES = 2; // GL_2D
290 for (GLint anIter = 0; anIter < aResult;)
291 {
292 const GLfloat aPos = aBuffer[anIter];
293 switch ((GLint )aPos)
294 {
295 case GL_POINT_TOKEN:
296 {
297 ++aPntNb;
298 ++aNodesNb;
299 anIter += 1 + NODE_VALUES;
300 break;
301 }
302 case GL_LINE_RESET_TOKEN:
303 case GL_LINE_TOKEN:
304 {
305 ++aLinesNb;
306 aNodesNb += 2;
307 anIter += 1 + 2 * NODE_VALUES;
308 break;
309 }
310 case GL_POLYGON_TOKEN:
311 {
312 const GLint aCount = (GLint )aBuffer[++anIter];
313 aNodesNb += aCount;
314 anIter += aCount * NODE_VALUES + 1;
315 if (aCount == 3)
316 {
317 ++aTriNb;
318 }
319 else if (aCount == 4)
320 {
321 ++aQuadsNb;
322 }
323 else
324 {
325 ++aPolyNb;
326 }
327 break;
328 }
329 case GL_BITMAP_TOKEN:
330 case GL_DRAW_PIXEL_TOKEN:
331 case GL_COPY_PIXEL_TOKEN:
332 {
333 ++aBitmapsNb;
334 anIter += 1 + NODE_VALUES;
335 break;
336 }
337 case GL_PASS_THROUGH_TOKEN:
338 {
339 ++aPassThrNb;
340 anIter += 2; // header + value
341 break;
342 }
343 default:
344 {
345 ++anIter;
346 ++aUnknownNb;
347 break;
348 }
349 }
350 }
351 void* aPtr = aBuffer;
352 Standard::Free (aPtr);
353
354 // return statistics
355 theDI << "Total nodes: " << aNodesNb << "\n"
356 << "Points: " << aPntNb << "\n"
357 << "Line segments: " << aLinesNb << "\n"
358 << "Triangles: " << aTriNb << "\n"
359 << "Quads: " << aQuadsNb << "\n"
360 << "Polygons: " << aPolyNb << "\n"
361 << "Bitmap tokens: " << aBitmapsNb << "\n"
362 << "Pass through: " << aPassThrNb << "\n"
363 << "UNKNOWN: " << aUnknownNb << "\n";
364
365 double aLen2D = double(aNodesNb * 2 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
366 double aLen3D = double(aNodesNb * 3 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
367 double aLen3D_rgba = double(aNodesNb * 7 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
368 theDI << "Buffer size GL_2D: " << aLen2D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"
369 << "Buffer size GL_3D: " << aLen3D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"
370 << "Buffer size GL_3D_COLOR: " << aLen3D_rgba * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n";
371 return 0;
372 }
1ce0716b 373#else
374 (void )theDI;
375 std::cout << "Command is unsupported on current platform.\n";
376 return 1;
377#endif
3c4153af 378}
379
1981cb22 380//==============================================================================
381//function : VImmediateFront
382//purpose :
383//==============================================================================
384
35e08fe8 385static int VImmediateFront (Draw_Interpretor& /*theDI*/,
1981cb22 386 Standard_Integer theArgNb,
387 const char** theArgVec)
388{
389 // get the context
390 Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
391 if (aContextAIS.IsNull())
392 {
393 std::cerr << "No active view. Please call vinit.\n";
394 return 1;
395 }
396
dc3fe572 397 Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
398
1981cb22 399 if (aDriver.IsNull())
400 {
401 std::cerr << "Graphic driver not available.\n";
402 return 1;
403 }
404
405 if (theArgNb < 2)
406 {
1981cb22 407 std::cerr << "Wrong number of arguments.\n";
408 return 1;
409 }
410
c357e426 411 ViewerTest::CurrentView()->View()->SetImmediateModeDrawToFront (atoi(theArgVec[1]) != 0);
412
1981cb22 413 return 0;
414}
415
26d9c835 416//! Search the info from the key.
417inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
418 const TCollection_AsciiString& theKey)
419{
420 for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
421 {
422 if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
423 {
424 return anIter.Value();
425 }
426 }
427 return TCollection_AsciiString();
428}
429
dac04bfa 430//==============================================================================
431//function : VGlInfo
432//purpose :
433//==============================================================================
434
435static int VGlInfo (Draw_Interpretor& theDI,
436 Standard_Integer theArgNb,
437 const char** theArgVec)
438{
439 // get the active view
440 Handle(V3d_View) aView = ViewerTest::CurrentView();
441 if (aView.IsNull())
442 {
443 std::cerr << "No active view. Please call vinit.\n";
444 return 1;
445 }
446
26d9c835 447 Standard_Integer anArgIter = 1;
448 Graphic3d_DiagnosticInfo anInfoLevel = Graphic3d_DiagnosticInfo_Basic;
449 if (theArgNb == 2)
dac04bfa 450 {
26d9c835 451 TCollection_AsciiString aName (theArgVec[1]);
452 aName.LowerCase();
453 if (aName == "-short")
4e1523ef 454 {
26d9c835 455 ++anArgIter;
456 anInfoLevel = Graphic3d_DiagnosticInfo_Short;
457 }
458 else if (aName == "-basic")
459 {
460 ++anArgIter;
461 anInfoLevel = Graphic3d_DiagnosticInfo_Basic;
4e1523ef 462 }
26d9c835 463 else if (aName == "-complete"
464 || aName == "-full")
465 {
466 ++anArgIter;
467 anInfoLevel = Graphic3d_DiagnosticInfo_Complete;
468 }
469 }
470
471 TColStd_IndexedDataMapOfStringString aDict;
472 if (anArgIter >= theArgNb)
473 {
474 aView->DiagnosticInformation (aDict, anInfoLevel);
475 TCollection_AsciiString aText;
476 for (TColStd_IndexedDataMapOfStringString::Iterator aValueIter (aDict); aValueIter.More(); aValueIter.Next())
477 {
478 if (!aText.IsEmpty())
479 {
480 aText += "\n";
481 }
482 aText += TCollection_AsciiString(" ") + aValueIter.Key() + ": " + aValueIter.Value();
483 }
484
dac04bfa 485 theDI << "OpenGL info:\n"
26d9c835 486 << aText;
dac04bfa 487 return 0;
488 }
489
490 const Standard_Boolean isList = theArgNb >= 3;
26d9c835 491 aView->DiagnosticInformation (aDict, Graphic3d_DiagnosticInfo_Complete);
492 for (; anArgIter < theArgNb; ++anArgIter)
dac04bfa 493 {
26d9c835 494 TCollection_AsciiString aName (theArgVec[anArgIter]);
dac04bfa 495 aName.UpperCase();
26d9c835 496 TCollection_AsciiString aValue;
dac04bfa 497 if (aName.Search ("VENDOR") != -1)
498 {
26d9c835 499 aValue = searchInfo (aDict, "GLvendor");
dac04bfa 500 }
501 else if (aName.Search ("RENDERER") != -1)
502 {
26d9c835 503 aValue = searchInfo (aDict, "GLdevice");
dac04bfa 504 }
505 else if (aName.Search ("SHADING_LANGUAGE_VERSION") != -1
506 || aName.Search ("GLSL") != -1)
507 {
26d9c835 508 aValue = searchInfo (aDict, "GLSLversion");
dac04bfa 509 }
510 else if (aName.Search ("VERSION") != -1)
511 {
26d9c835 512 aValue = searchInfo (aDict, "GLversion");
dac04bfa 513 }
514 else if (aName.Search ("EXTENSIONS") != -1)
515 {
26d9c835 516 aValue = searchInfo (aDict, "GLextensions");
dac04bfa 517 }
518 else
519 {
520 std::cerr << "Unknown key '" << aName.ToCString() << "'\n";
521 return 1;
522 }
523
524 if (isList)
525 {
526 theDI << "{" << aValue << "} ";
527 }
528 else
529 {
530 theDI << aValue;
531 }
532 }
533
534 return 0;
535}
536
8e0a2b19 537//! Parse shader type argument.
538static bool parseShaderTypeArg (Graphic3d_TypeOfShaderObject& theType,
539 const TCollection_AsciiString& theArg)
540{
541 if (theArg == "-vertex"
542 || theArg == "-vert")
543 {
544 theType = Graphic3d_TOS_VERTEX;
545 }
546 else if (theArg == "-tessevaluation"
547 || theArg == "-tesseval"
548 || theArg == "-evaluation"
549 || theArg == "-eval")
550 {
551 theType = Graphic3d_TOS_TESS_EVALUATION;
552 }
553 else if (theArg == "-tesscontrol"
554 || theArg == "-tessctrl"
555 || theArg == "-control"
556 || theArg == "-ctrl")
557 {
558 theType = Graphic3d_TOS_TESS_CONTROL;
559 }
560 else if (theArg == "-geometry"
561 || theArg == "-geom")
562 {
563 theType = Graphic3d_TOS_GEOMETRY;
564 }
565 else if (theArg == "-fragment"
566 || theArg == "-frag")
567 {
568 theType = Graphic3d_TOS_FRAGMENT;
569 }
570 else if (theArg == "-compute"
571 || theArg == "-comp")
572 {
573 theType = Graphic3d_TOS_COMPUTE;
574 }
575 else
576 {
577 return false;
578 }
579 return true;
580}
392ac980 581
582//==============================================================================
583//function : VShaderProg
584//purpose : Sets the pair of vertex and fragment shaders for the object
585//==============================================================================
586static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/,
587 Standard_Integer theArgNb,
588 const char** theArgVec)
589{
590 Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
591 if (aCtx.IsNull())
592 {
8e0a2b19 593 std::cout << "Error: no active view.\n";
392ac980 594 return 1;
595 }
596 else if (theArgNb < 2)
597 {
8e0a2b19 598 std::cout << "Syntax error: lack of arguments\n";
392ac980 599 return 1;
600 }
601
8e0a2b19 602 bool isExplicitShaderType = false;
603 Handle(Graphic3d_ShaderProgram) aProgram = new Graphic3d_ShaderProgram();
604 NCollection_Sequence<Handle(AIS_InteractiveObject)> aPrsList;
605 Graphic3d_GroupAspect aGroupAspect = Graphic3d_ASPECT_FILL_AREA;
606 bool isSetGroupAspect = false;
607 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
392ac980 608 {
8e0a2b19 609 TCollection_AsciiString anArg (theArgVec[anArgIter]);
610 anArg.LowerCase();
611 Graphic3d_TypeOfShaderObject aShaderTypeArg = Graphic3d_TypeOfShaderObject(-1);
612 if (!aProgram.IsNull()
613 && aProgram->ShaderObjects().IsEmpty()
614 && (anArg == "-off"
615 || anArg == "off"))
616 {
617 aProgram.Nullify();
618 }
619 else if (!aProgram.IsNull()
620 && aProgram->ShaderObjects().IsEmpty()
621 && (anArg == "-phong"
622 || anArg == "phong"))
623 {
624 const TCollection_AsciiString& aShadersRoot = Graphic3d_ShaderProgram::ShadersFolder();
625 if (aShadersRoot.IsEmpty())
626 {
627 std::cout << "Error: both environment variables CSF_ShadersDirectory and CASROOT are undefined!\n"
628 "At least one should be defined to load Phong program.\n";
629 return 1;
630 }
ee5befae 631
8e0a2b19 632 const TCollection_AsciiString aSrcVert = aShadersRoot + "/PhongShading.vs";
633 const TCollection_AsciiString aSrcFrag = aShadersRoot + "/PhongShading.fs";
634 if (!aSrcVert.IsEmpty()
635 && !OSD_File (aSrcVert).Exists())
636 {
637 std::cout << "Error: PhongShading.vs is not found\n";
638 return 1;
639 }
640 if (!aSrcFrag.IsEmpty()
641 && !OSD_File (aSrcFrag).Exists())
642 {
643 std::cout << "Error: PhongShading.fs is not found\n";
644 return 1;
645 }
ee5befae 646
8e0a2b19 647 aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aSrcVert));
648 aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_FRAGMENT, aSrcFrag));
ee5befae 649 }
8e0a2b19 650 else if (aPrsList.IsEmpty()
651 && anArg == "*")
ee5befae 652 {
8e0a2b19 653 //
392ac980 654 }
8e0a2b19 655 else if (!isSetGroupAspect
656 && anArgIter + 1 < theArgNb
657 && (anArg == "-primtype"
658 || anArg == "-primitivetype"
659 || anArg == "-groupaspect"
660 || anArg == "-aspecttype"
661 || anArg == "-aspect"))
662 {
663 isSetGroupAspect = true;
664 TCollection_AsciiString aPrimTypeStr (theArgVec[++anArgIter]);
665 aPrimTypeStr.LowerCase();
666 if (aPrimTypeStr == "line")
667 {
668 aGroupAspect = Graphic3d_ASPECT_LINE;
669 }
670 else if (aPrimTypeStr == "tris"
671 || aPrimTypeStr == "triangles"
672 || aPrimTypeStr == "fill"
673 || aPrimTypeStr == "fillarea"
674 || aPrimTypeStr == "shading"
675 || aPrimTypeStr == "shade")
676 {
677 aGroupAspect = Graphic3d_ASPECT_FILL_AREA;
678 }
679 else if (aPrimTypeStr == "text")
680 {
681 aGroupAspect = Graphic3d_ASPECT_TEXT;
682 }
683 else if (aPrimTypeStr == "marker"
684 || aPrimTypeStr == "point"
685 || aPrimTypeStr == "pnt")
686 {
687 aGroupAspect = Graphic3d_ASPECT_MARKER;
688 }
689 else
690 {
691 std::cerr << "Syntax error at '" << aPrimTypeStr << "'\n";
692 return 1;
693 }
392ac980 694 }
8e0a2b19 695 else if (anArgIter + 1 < theArgNb
696 && !aProgram.IsNull()
697 && aProgram->Header().IsEmpty()
698 && (anArg == "-version"
699 || anArg == "-glslversion"
700 || anArg == "-header"
701 || anArg == "-glslheader"))
392ac980 702 {
8e0a2b19 703 TCollection_AsciiString aHeader (theArgVec[++anArgIter]);
704 if (aHeader.IsIntegerValue())
705 {
706 aHeader = TCollection_AsciiString ("#version ") + aHeader;
707 }
708 aProgram->SetHeader (aHeader);
cc8cbabe 709 }
8e0a2b19 710 else if (!anArg.StartsWith ("-")
711 && GetMapOfAIS().IsBound2 (theArgVec[anArgIter]))
cc8cbabe 712 {
8e0a2b19 713 Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (theArgVec[anArgIter]));
714 if (anIO.IsNull())
715 {
716 std::cerr << "Syntax error: " << theArgVec[anArgIter] << " is not an AIS object\n";
717 return 1;
718 }
719 aPrsList.Append (anIO);
392ac980 720 }
8e0a2b19 721 else if (!aProgram.IsNull()
722 && ((anArgIter + 1 < theArgNb && parseShaderTypeArg (aShaderTypeArg, anArg))
723 || (!isExplicitShaderType && aProgram->ShaderObjects().Size() < 2)))
392ac980 724 {
8e0a2b19 725 TCollection_AsciiString aShaderPath (theArgVec[anArgIter]);
726 if (aShaderTypeArg != Graphic3d_TypeOfShaderObject(-1))
392ac980 727 {
8e0a2b19 728 aShaderPath = (theArgVec[++anArgIter]);
729 isExplicitShaderType = true;
fb66bb28 730 }
731
8e0a2b19 732 const bool isSrcFile = OSD_File (aShaderPath).Exists();
733 Handle(Graphic3d_ShaderObject) aShader = isSrcFile
734 ? Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aShaderPath)
735 : Graphic3d_ShaderObject::CreateFromSource(Graphic3d_TOS_VERTEX, aShaderPath);
736 const TCollection_AsciiString& aShaderSrc = aShader->Source();
737
738 const bool hasVertPos = aShaderSrc.Search ("gl_Position") != -1;
b17e5bae 739 const bool hasFragColor = aShaderSrc.Search ("occSetFragColor") != -1
740 || aShaderSrc.Search ("occFragColor") != -1
8e0a2b19 741 || aShaderSrc.Search ("gl_FragColor") != -1
742 || aShaderSrc.Search ("gl_FragData") != -1;
743 Graphic3d_TypeOfShaderObject aShaderType = aShaderTypeArg;
744 if (aShaderType == Graphic3d_TypeOfShaderObject(-1))
fb66bb28 745 {
8e0a2b19 746 if (hasVertPos
747 && !hasFragColor)
748 {
749 aShaderType = Graphic3d_TOS_VERTEX;
750 }
751 if (hasFragColor
752 && !hasVertPos)
753 {
754 aShaderType = Graphic3d_TOS_FRAGMENT;
755 }
392ac980 756 }
8e0a2b19 757 if (aShaderType == Graphic3d_TypeOfShaderObject(-1))
fb66bb28 758 {
8e0a2b19 759 std::cerr << "Error: non-existing or invalid shader source\n";
760 return 1;
fb66bb28 761 }
8e0a2b19 762
763 aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aShaderType, aShaderSrc));
764 }
765 else
766 {
767 std::cerr << "Syntax error at '" << anArg << "'\n";
768 return 1;
392ac980 769 }
392ac980 770 }
771
b17e5bae 772 if (!aProgram.IsNull()
773 && ViewerTest::CurrentView()->RenderingParams().TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
774 {
775 aProgram->SetNbFragmentOutputs (2);
776 aProgram->SetWeightOitOutput (true);
777 }
778
8e0a2b19 779 ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aGlobalPrsIter (GetMapOfAIS());
780 NCollection_Sequence<Handle(AIS_InteractiveObject)>::Iterator aPrsIter (aPrsList);
781 const bool isGlobalList = aPrsList.IsEmpty();
782 for (;;)
392ac980 783 {
8e0a2b19 784 Handle(AIS_InteractiveObject) anIO;
785 if (isGlobalList)
392ac980 786 {
8e0a2b19 787 if (!aGlobalPrsIter.More())
788 {
789 break;
790 }
791 anIO = Handle(AIS_InteractiveObject)::DownCast (aGlobalPrsIter.Key1());
792 aGlobalPrsIter.Next();
793 if (anIO.IsNull())
794 {
795 continue;
796 }
392ac980 797 }
8e0a2b19 798 else
392ac980 799 {
8e0a2b19 800 if (!aPrsIter.More())
801 {
802 break;
803 }
804 anIO = aPrsIter.Value();
805 aPrsIter.Next();
392ac980 806 }
fb66bb28 807
8e0a2b19 808 if (anIO->Attributes()->SetShaderProgram (aProgram, aGroupAspect, true))
fb66bb28 809 {
fb66bb28 810 aCtx->Redisplay (anIO, Standard_False);
811 }
812 else
813 {
fb66bb28 814 anIO->SynchronizeAspects();
815 }
392ac980 816 }
817
818 aCtx->UpdateCurrentViewer();
819 return 0;
820}
821
3946774d 822//=======================================================================
823//function : OpenGlCommands
824//purpose :
825//=======================================================================
826
827void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands)
828{
829 const char* aGroup ="Commands for low-level TKOpenGl features";
830
831 theCommands.Add("vuserdraw",
832 "vuserdraw : name - simulates drawing with help of UserDraw",
833 __FILE__, VUserDraw, aGroup);
3c4153af 834 theCommands.Add("vfeedback",
835 "vfeedback : perform test GL feedback rendering",
836 __FILE__, VFeedback, aGroup);
1981cb22 837 theCommands.Add("vimmediatefront",
838 "vimmediatefront : render immediate mode to front buffer or to back buffer",
839 __FILE__, VImmediateFront, aGroup);
dac04bfa 840 theCommands.Add("vglinfo",
26d9c835 841 "vglinfo [-short|-basic|-complete]"
842 "\n\t\t: [GL_VENDOR] [GL_RENDERER] [GL_VERSION]"
843 "\n\t\t: [GL_SHADING_LANGUAGE_VERSION] [GL_EXTENSIONS]"
844 "\n\t\t: print OpenGL info",
dac04bfa 845 __FILE__, VGlInfo, aGroup);
8e0a2b19 846 theCommands.Add("vshader",
847 "vshader name -vert VertexShader -frag FragmentShader [-geom GeometryShader]"
848 "\n\t\t: [-off] [-phong] [-aspect {shading|line|point|text}=shading]"
849 "\n\t\t: [-header VersionHeader]"
850 "\n\t\t: [-tessControl TessControlShader -tesseval TessEvaluationShader]"
851 "\n\t\t: Assign custom GLSL program to presentation aspects.",
392ac980 852 __FILE__, VShaderProg, aGroup);
8e0a2b19 853 theCommands.Add("vshaderprog", "Alias for vshader", __FILE__, VShaderProg, aGroup);
3946774d 854}