0030483: Visualization, Path Tracing - make Tile Size configurable
[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
c40eb6b9 167 aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), Aspect_TOL_SOLID,
168 Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, false,
169 Handle(OpenGl_ShaderProgram)());
1136702b 170 aCtx->SetColor4fv (aColor);
171
172 const OpenGl_Vec3 aVertArray[4] =
173 {
174 OpenGl_Vec3(myCoords[0], myCoords[1], myCoords[2]),
175 OpenGl_Vec3(myCoords[3], myCoords[4], myCoords[2]),
176 OpenGl_Vec3(myCoords[3], myCoords[4], myCoords[5]),
177 OpenGl_Vec3(myCoords[0], myCoords[1], myCoords[5]),
178 };
179 Handle(OpenGl_VertexBuffer) aVertBuffer = new OpenGl_VertexBuffer();
180 aVertBuffer->Init (aCtx, 3, 4, aVertArray[0].GetData());
181
3946774d 182 // Finally draw something to make sure UserDraw really works
1136702b 183 aVertBuffer->BindAttribute (aCtx, Graphic3d_TOA_POS);
184 glDrawArrays(GL_LINE_LOOP, 0, aVertBuffer->GetElemsNb());
185 aVertBuffer->UnbindAttribute(aCtx, Graphic3d_TOA_POS);
186 aVertBuffer->Release (aCtx.get());
3946774d 187}
188
c04c30b3 189} // end of anonymous namespace
190
3946774d 191static Standard_Integer VUserDraw (Draw_Interpretor& di,
192 Standard_Integer argc,
193 const char ** argv)
194{
195 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
196 if (aContext.IsNull())
197 {
198 di << argv[0] << "Call 'vinit' before!\n";
199 return 1;
200 }
201
dc3fe572 202 Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5e27df78 203 if (aDriver.IsNull())
204 {
205 std::cerr << "Graphic driver not available.\n";
206 return 1;
207 }
208
3946774d 209 if (argc > 2)
210 {
211 di << argv[0] << "Wrong number of arguments, only the object name expected\n";
212 return 1;
213 }
214
215 TCollection_AsciiString aName (argv[1]);
216 VDisplayAISObject(aName, Handle(AIS_InteractiveObject)());
217
3946774d 218 Handle(VUserDrawObj) anIObj = new VUserDrawObj();
219 VDisplayAISObject(aName, anIObj);
220
221 return 0;
222}
223
3c4153af 224//==============================================================================
225//function : VFeedback
226//purpose :
227//==============================================================================
228
229static int VFeedback (Draw_Interpretor& theDI,
35e08fe8 230 Standard_Integer /*theArgNb*/,
231 const char** /*theArgVec*/)
3c4153af 232{
1ce0716b 233#if !defined(GL_ES_VERSION_2_0)
3c4153af 234 // get the active view
235 Handle(V3d_View) aView = ViewerTest::CurrentView();
236 if (aView.IsNull())
237 {
238 std::cerr << "No active view. Please call vinit.\n";
239 return 1;
240 }
241
242 unsigned int aBufferSize = 1024 * 1024;
243 for (;;)
244 {
245 size_t aBytes = (size_t )aBufferSize * sizeof(GLfloat);
246 if (aBytes / sizeof(GLfloat) != (size_t )aBufferSize)
247 {
248 // finito la commedia
249 std::cerr << "Can not allocate buffer - requested size ("
250 << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat)))
251 << " MiB) is out of address space\n";
252 return 1;
253 }
254
255 GLfloat* aBuffer = (GLfloat* )Standard::Allocate (aBytes);
256 if (aBuffer == NULL)
257 {
258 // finito la commedia
259 std::cerr << "Can not allocate buffer with size ("
260 << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat)))
261 << " MiB)\n";
262 return 1;
263 }
264
265 glFeedbackBuffer ((GLsizei )aBufferSize, GL_2D, aBuffer);
266 glRenderMode (GL_FEEDBACK);
267
268 aView->Redraw();
269
270 GLint aResult = glRenderMode (GL_RENDER);
271 if (aResult < 0)
272 {
273 aBufferSize *= 2;
274
275 void* aPtr = aBuffer;
276 Standard::Free (aPtr);
277 aBuffer = NULL;
278 continue;
279 }
280
281 std::cout << "FeedBack result= " << aResult << "\n";
282 GLint aPntNb = 0;
283 GLint aTriNb = 0;
284 GLint aQuadsNb = 0;
285 GLint aPolyNb = 0;
286 GLint aNodesNb = 0;
287 GLint aLinesNb = 0;
288 GLint aBitmapsNb = 0;
289 GLint aPassThrNb = 0;
290 GLint aUnknownNb = 0;
291 const GLint NODE_VALUES = 2; // GL_2D
292 for (GLint anIter = 0; anIter < aResult;)
293 {
294 const GLfloat aPos = aBuffer[anIter];
295 switch ((GLint )aPos)
296 {
297 case GL_POINT_TOKEN:
298 {
299 ++aPntNb;
300 ++aNodesNb;
301 anIter += 1 + NODE_VALUES;
302 break;
303 }
304 case GL_LINE_RESET_TOKEN:
305 case GL_LINE_TOKEN:
306 {
307 ++aLinesNb;
308 aNodesNb += 2;
309 anIter += 1 + 2 * NODE_VALUES;
310 break;
311 }
312 case GL_POLYGON_TOKEN:
313 {
314 const GLint aCount = (GLint )aBuffer[++anIter];
315 aNodesNb += aCount;
316 anIter += aCount * NODE_VALUES + 1;
317 if (aCount == 3)
318 {
319 ++aTriNb;
320 }
321 else if (aCount == 4)
322 {
323 ++aQuadsNb;
324 }
325 else
326 {
327 ++aPolyNb;
328 }
329 break;
330 }
331 case GL_BITMAP_TOKEN:
332 case GL_DRAW_PIXEL_TOKEN:
333 case GL_COPY_PIXEL_TOKEN:
334 {
335 ++aBitmapsNb;
336 anIter += 1 + NODE_VALUES;
337 break;
338 }
339 case GL_PASS_THROUGH_TOKEN:
340 {
341 ++aPassThrNb;
342 anIter += 2; // header + value
343 break;
344 }
345 default:
346 {
347 ++anIter;
348 ++aUnknownNb;
349 break;
350 }
351 }
352 }
353 void* aPtr = aBuffer;
354 Standard::Free (aPtr);
355
356 // return statistics
357 theDI << "Total nodes: " << aNodesNb << "\n"
358 << "Points: " << aPntNb << "\n"
359 << "Line segments: " << aLinesNb << "\n"
360 << "Triangles: " << aTriNb << "\n"
361 << "Quads: " << aQuadsNb << "\n"
362 << "Polygons: " << aPolyNb << "\n"
363 << "Bitmap tokens: " << aBitmapsNb << "\n"
364 << "Pass through: " << aPassThrNb << "\n"
365 << "UNKNOWN: " << aUnknownNb << "\n";
366
367 double aLen2D = double(aNodesNb * 2 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
368 double aLen3D = double(aNodesNb * 3 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
369 double aLen3D_rgba = double(aNodesNb * 7 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
370 theDI << "Buffer size GL_2D: " << aLen2D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"
371 << "Buffer size GL_3D: " << aLen3D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"
372 << "Buffer size GL_3D_COLOR: " << aLen3D_rgba * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n";
373 return 0;
374 }
1ce0716b 375#else
376 (void )theDI;
377 std::cout << "Command is unsupported on current platform.\n";
378 return 1;
379#endif
3c4153af 380}
381
1981cb22 382//==============================================================================
383//function : VImmediateFront
384//purpose :
385//==============================================================================
386
35e08fe8 387static int VImmediateFront (Draw_Interpretor& /*theDI*/,
1981cb22 388 Standard_Integer theArgNb,
389 const char** theArgVec)
390{
391 // get the context
392 Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
393 if (aContextAIS.IsNull())
394 {
395 std::cerr << "No active view. Please call vinit.\n";
396 return 1;
397 }
398
dc3fe572 399 Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
400
1981cb22 401 if (aDriver.IsNull())
402 {
403 std::cerr << "Graphic driver not available.\n";
404 return 1;
405 }
406
407 if (theArgNb < 2)
408 {
1981cb22 409 std::cerr << "Wrong number of arguments.\n";
410 return 1;
411 }
412
c357e426 413 ViewerTest::CurrentView()->View()->SetImmediateModeDrawToFront (atoi(theArgVec[1]) != 0);
414
1981cb22 415 return 0;
416}
417
26d9c835 418//! Search the info from the key.
419inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
420 const TCollection_AsciiString& theKey)
421{
422 for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
423 {
424 if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
425 {
426 return anIter.Value();
427 }
428 }
429 return TCollection_AsciiString();
430}
431
dac04bfa 432//==============================================================================
433//function : VGlInfo
434//purpose :
435//==============================================================================
436
437static int VGlInfo (Draw_Interpretor& theDI,
438 Standard_Integer theArgNb,
439 const char** theArgVec)
440{
441 // get the active view
442 Handle(V3d_View) aView = ViewerTest::CurrentView();
443 if (aView.IsNull())
444 {
445 std::cerr << "No active view. Please call vinit.\n";
446 return 1;
447 }
448
26d9c835 449 Standard_Integer anArgIter = 1;
450 Graphic3d_DiagnosticInfo anInfoLevel = Graphic3d_DiagnosticInfo_Basic;
451 if (theArgNb == 2)
dac04bfa 452 {
26d9c835 453 TCollection_AsciiString aName (theArgVec[1]);
454 aName.LowerCase();
455 if (aName == "-short")
4e1523ef 456 {
26d9c835 457 ++anArgIter;
458 anInfoLevel = Graphic3d_DiagnosticInfo_Short;
459 }
460 else if (aName == "-basic")
461 {
462 ++anArgIter;
463 anInfoLevel = Graphic3d_DiagnosticInfo_Basic;
4e1523ef 464 }
26d9c835 465 else if (aName == "-complete"
466 || aName == "-full")
467 {
468 ++anArgIter;
469 anInfoLevel = Graphic3d_DiagnosticInfo_Complete;
470 }
471 }
472
473 TColStd_IndexedDataMapOfStringString aDict;
474 if (anArgIter >= theArgNb)
475 {
476 aView->DiagnosticInformation (aDict, anInfoLevel);
477 TCollection_AsciiString aText;
478 for (TColStd_IndexedDataMapOfStringString::Iterator aValueIter (aDict); aValueIter.More(); aValueIter.Next())
479 {
480 if (!aText.IsEmpty())
481 {
482 aText += "\n";
483 }
484 aText += TCollection_AsciiString(" ") + aValueIter.Key() + ": " + aValueIter.Value();
485 }
486
dac04bfa 487 theDI << "OpenGL info:\n"
26d9c835 488 << aText;
dac04bfa 489 return 0;
490 }
491
492 const Standard_Boolean isList = theArgNb >= 3;
26d9c835 493 aView->DiagnosticInformation (aDict, Graphic3d_DiagnosticInfo_Complete);
494 for (; anArgIter < theArgNb; ++anArgIter)
dac04bfa 495 {
26d9c835 496 TCollection_AsciiString aName (theArgVec[anArgIter]);
dac04bfa 497 aName.UpperCase();
26d9c835 498 TCollection_AsciiString aValue;
dac04bfa 499 if (aName.Search ("VENDOR") != -1)
500 {
26d9c835 501 aValue = searchInfo (aDict, "GLvendor");
dac04bfa 502 }
503 else if (aName.Search ("RENDERER") != -1)
504 {
26d9c835 505 aValue = searchInfo (aDict, "GLdevice");
dac04bfa 506 }
507 else if (aName.Search ("SHADING_LANGUAGE_VERSION") != -1
508 || aName.Search ("GLSL") != -1)
509 {
26d9c835 510 aValue = searchInfo (aDict, "GLSLversion");
dac04bfa 511 }
512 else if (aName.Search ("VERSION") != -1)
513 {
26d9c835 514 aValue = searchInfo (aDict, "GLversion");
dac04bfa 515 }
516 else if (aName.Search ("EXTENSIONS") != -1)
517 {
26d9c835 518 aValue = searchInfo (aDict, "GLextensions");
dac04bfa 519 }
520 else
521 {
522 std::cerr << "Unknown key '" << aName.ToCString() << "'\n";
523 return 1;
524 }
525
526 if (isList)
527 {
528 theDI << "{" << aValue << "} ";
529 }
530 else
531 {
532 theDI << aValue;
533 }
534 }
535
536 return 0;
537}
538
8e0a2b19 539//! Parse shader type argument.
540static bool parseShaderTypeArg (Graphic3d_TypeOfShaderObject& theType,
541 const TCollection_AsciiString& theArg)
542{
543 if (theArg == "-vertex"
544 || theArg == "-vert")
545 {
546 theType = Graphic3d_TOS_VERTEX;
547 }
548 else if (theArg == "-tessevaluation"
549 || theArg == "-tesseval"
550 || theArg == "-evaluation"
551 || theArg == "-eval")
552 {
553 theType = Graphic3d_TOS_TESS_EVALUATION;
554 }
555 else if (theArg == "-tesscontrol"
556 || theArg == "-tessctrl"
557 || theArg == "-control"
558 || theArg == "-ctrl")
559 {
560 theType = Graphic3d_TOS_TESS_CONTROL;
561 }
562 else if (theArg == "-geometry"
563 || theArg == "-geom")
564 {
565 theType = Graphic3d_TOS_GEOMETRY;
566 }
567 else if (theArg == "-fragment"
568 || theArg == "-frag")
569 {
570 theType = Graphic3d_TOS_FRAGMENT;
571 }
572 else if (theArg == "-compute"
573 || theArg == "-comp")
574 {
575 theType = Graphic3d_TOS_COMPUTE;
576 }
577 else
578 {
579 return false;
580 }
581 return true;
582}
392ac980 583
584//==============================================================================
585//function : VShaderProg
586//purpose : Sets the pair of vertex and fragment shaders for the object
587//==============================================================================
588static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/,
589 Standard_Integer theArgNb,
590 const char** theArgVec)
591{
592 Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
593 if (aCtx.IsNull())
594 {
8e0a2b19 595 std::cout << "Error: no active view.\n";
392ac980 596 return 1;
597 }
598 else if (theArgNb < 2)
599 {
8e0a2b19 600 std::cout << "Syntax error: lack of arguments\n";
392ac980 601 return 1;
602 }
603
8e0a2b19 604 bool isExplicitShaderType = false;
605 Handle(Graphic3d_ShaderProgram) aProgram = new Graphic3d_ShaderProgram();
606 NCollection_Sequence<Handle(AIS_InteractiveObject)> aPrsList;
607 Graphic3d_GroupAspect aGroupAspect = Graphic3d_ASPECT_FILL_AREA;
608 bool isSetGroupAspect = false;
609 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
392ac980 610 {
8e0a2b19 611 TCollection_AsciiString anArg (theArgVec[anArgIter]);
612 anArg.LowerCase();
613 Graphic3d_TypeOfShaderObject aShaderTypeArg = Graphic3d_TypeOfShaderObject(-1);
614 if (!aProgram.IsNull()
615 && aProgram->ShaderObjects().IsEmpty()
616 && (anArg == "-off"
617 || anArg == "off"))
618 {
619 aProgram.Nullify();
620 }
621 else if (!aProgram.IsNull()
622 && aProgram->ShaderObjects().IsEmpty()
623 && (anArg == "-phong"
624 || anArg == "phong"))
625 {
626 const TCollection_AsciiString& aShadersRoot = Graphic3d_ShaderProgram::ShadersFolder();
627 if (aShadersRoot.IsEmpty())
628 {
629 std::cout << "Error: both environment variables CSF_ShadersDirectory and CASROOT are undefined!\n"
630 "At least one should be defined to load Phong program.\n";
631 return 1;
632 }
ee5befae 633
8e0a2b19 634 const TCollection_AsciiString aSrcVert = aShadersRoot + "/PhongShading.vs";
635 const TCollection_AsciiString aSrcFrag = aShadersRoot + "/PhongShading.fs";
636 if (!aSrcVert.IsEmpty()
637 && !OSD_File (aSrcVert).Exists())
638 {
639 std::cout << "Error: PhongShading.vs is not found\n";
640 return 1;
641 }
642 if (!aSrcFrag.IsEmpty()
643 && !OSD_File (aSrcFrag).Exists())
644 {
645 std::cout << "Error: PhongShading.fs is not found\n";
646 return 1;
647 }
ee5befae 648
8e0a2b19 649 aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aSrcVert));
650 aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_FRAGMENT, aSrcFrag));
ee5befae 651 }
8e0a2b19 652 else if (aPrsList.IsEmpty()
653 && anArg == "*")
ee5befae 654 {
8e0a2b19 655 //
392ac980 656 }
8e0a2b19 657 else if (!isSetGroupAspect
658 && anArgIter + 1 < theArgNb
659 && (anArg == "-primtype"
660 || anArg == "-primitivetype"
661 || anArg == "-groupaspect"
662 || anArg == "-aspecttype"
663 || anArg == "-aspect"))
664 {
665 isSetGroupAspect = true;
666 TCollection_AsciiString aPrimTypeStr (theArgVec[++anArgIter]);
667 aPrimTypeStr.LowerCase();
668 if (aPrimTypeStr == "line")
669 {
670 aGroupAspect = Graphic3d_ASPECT_LINE;
671 }
672 else if (aPrimTypeStr == "tris"
673 || aPrimTypeStr == "triangles"
674 || aPrimTypeStr == "fill"
675 || aPrimTypeStr == "fillarea"
676 || aPrimTypeStr == "shading"
677 || aPrimTypeStr == "shade")
678 {
679 aGroupAspect = Graphic3d_ASPECT_FILL_AREA;
680 }
681 else if (aPrimTypeStr == "text")
682 {
683 aGroupAspect = Graphic3d_ASPECT_TEXT;
684 }
685 else if (aPrimTypeStr == "marker"
686 || aPrimTypeStr == "point"
687 || aPrimTypeStr == "pnt")
688 {
689 aGroupAspect = Graphic3d_ASPECT_MARKER;
690 }
691 else
692 {
693 std::cerr << "Syntax error at '" << aPrimTypeStr << "'\n";
694 return 1;
695 }
392ac980 696 }
8e0a2b19 697 else if (anArgIter + 1 < theArgNb
698 && !aProgram.IsNull()
699 && aProgram->Header().IsEmpty()
700 && (anArg == "-version"
701 || anArg == "-glslversion"
702 || anArg == "-header"
703 || anArg == "-glslheader"))
392ac980 704 {
8e0a2b19 705 TCollection_AsciiString aHeader (theArgVec[++anArgIter]);
706 if (aHeader.IsIntegerValue())
707 {
708 aHeader = TCollection_AsciiString ("#version ") + aHeader;
709 }
710 aProgram->SetHeader (aHeader);
cc8cbabe 711 }
8e0a2b19 712 else if (!anArg.StartsWith ("-")
713 && GetMapOfAIS().IsBound2 (theArgVec[anArgIter]))
cc8cbabe 714 {
8f521168 715 Handle(AIS_InteractiveObject) anIO = GetMapOfAIS().Find2 (theArgVec[anArgIter]);
8e0a2b19 716 if (anIO.IsNull())
717 {
718 std::cerr << "Syntax error: " << theArgVec[anArgIter] << " is not an AIS object\n";
719 return 1;
720 }
721 aPrsList.Append (anIO);
392ac980 722 }
8e0a2b19 723 else if (!aProgram.IsNull()
724 && ((anArgIter + 1 < theArgNb && parseShaderTypeArg (aShaderTypeArg, anArg))
725 || (!isExplicitShaderType && aProgram->ShaderObjects().Size() < 2)))
392ac980 726 {
8e0a2b19 727 TCollection_AsciiString aShaderPath (theArgVec[anArgIter]);
728 if (aShaderTypeArg != Graphic3d_TypeOfShaderObject(-1))
392ac980 729 {
8e0a2b19 730 aShaderPath = (theArgVec[++anArgIter]);
731 isExplicitShaderType = true;
fb66bb28 732 }
733
8e0a2b19 734 const bool isSrcFile = OSD_File (aShaderPath).Exists();
735 Handle(Graphic3d_ShaderObject) aShader = isSrcFile
736 ? Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aShaderPath)
737 : Graphic3d_ShaderObject::CreateFromSource(Graphic3d_TOS_VERTEX, aShaderPath);
738 const TCollection_AsciiString& aShaderSrc = aShader->Source();
739
740 const bool hasVertPos = aShaderSrc.Search ("gl_Position") != -1;
b17e5bae 741 const bool hasFragColor = aShaderSrc.Search ("occSetFragColor") != -1
742 || aShaderSrc.Search ("occFragColor") != -1
8e0a2b19 743 || aShaderSrc.Search ("gl_FragColor") != -1
744 || aShaderSrc.Search ("gl_FragData") != -1;
745 Graphic3d_TypeOfShaderObject aShaderType = aShaderTypeArg;
746 if (aShaderType == Graphic3d_TypeOfShaderObject(-1))
fb66bb28 747 {
8e0a2b19 748 if (hasVertPos
749 && !hasFragColor)
750 {
751 aShaderType = Graphic3d_TOS_VERTEX;
752 }
753 if (hasFragColor
754 && !hasVertPos)
755 {
756 aShaderType = Graphic3d_TOS_FRAGMENT;
757 }
392ac980 758 }
8e0a2b19 759 if (aShaderType == Graphic3d_TypeOfShaderObject(-1))
fb66bb28 760 {
8e0a2b19 761 std::cerr << "Error: non-existing or invalid shader source\n";
762 return 1;
fb66bb28 763 }
8e0a2b19 764
765 aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aShaderType, aShaderSrc));
766 }
767 else
768 {
769 std::cerr << "Syntax error at '" << anArg << "'\n";
770 return 1;
392ac980 771 }
392ac980 772 }
773
b17e5bae 774 if (!aProgram.IsNull()
775 && ViewerTest::CurrentView()->RenderingParams().TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
776 {
777 aProgram->SetNbFragmentOutputs (2);
778 aProgram->SetWeightOitOutput (true);
779 }
780
8e0a2b19 781 ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aGlobalPrsIter (GetMapOfAIS());
782 NCollection_Sequence<Handle(AIS_InteractiveObject)>::Iterator aPrsIter (aPrsList);
783 const bool isGlobalList = aPrsList.IsEmpty();
784 for (;;)
392ac980 785 {
8e0a2b19 786 Handle(AIS_InteractiveObject) anIO;
787 if (isGlobalList)
392ac980 788 {
8e0a2b19 789 if (!aGlobalPrsIter.More())
790 {
791 break;
792 }
8f521168 793 anIO = aGlobalPrsIter.Key1();
8e0a2b19 794 aGlobalPrsIter.Next();
795 if (anIO.IsNull())
796 {
797 continue;
798 }
392ac980 799 }
8e0a2b19 800 else
392ac980 801 {
8e0a2b19 802 if (!aPrsIter.More())
803 {
804 break;
805 }
806 anIO = aPrsIter.Value();
807 aPrsIter.Next();
392ac980 808 }
fb66bb28 809
8e0a2b19 810 if (anIO->Attributes()->SetShaderProgram (aProgram, aGroupAspect, true))
fb66bb28 811 {
fb66bb28 812 aCtx->Redisplay (anIO, Standard_False);
813 }
814 else
815 {
fb66bb28 816 anIO->SynchronizeAspects();
817 }
392ac980 818 }
819
820 aCtx->UpdateCurrentViewer();
821 return 0;
822}
823
3946774d 824//=======================================================================
825//function : OpenGlCommands
826//purpose :
827//=======================================================================
828
829void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands)
830{
831 const char* aGroup ="Commands for low-level TKOpenGl features";
832
833 theCommands.Add("vuserdraw",
834 "vuserdraw : name - simulates drawing with help of UserDraw",
835 __FILE__, VUserDraw, aGroup);
3c4153af 836 theCommands.Add("vfeedback",
837 "vfeedback : perform test GL feedback rendering",
838 __FILE__, VFeedback, aGroup);
1981cb22 839 theCommands.Add("vimmediatefront",
840 "vimmediatefront : render immediate mode to front buffer or to back buffer",
841 __FILE__, VImmediateFront, aGroup);
dac04bfa 842 theCommands.Add("vglinfo",
26d9c835 843 "vglinfo [-short|-basic|-complete]"
844 "\n\t\t: [GL_VENDOR] [GL_RENDERER] [GL_VERSION]"
845 "\n\t\t: [GL_SHADING_LANGUAGE_VERSION] [GL_EXTENSIONS]"
846 "\n\t\t: print OpenGL info",
dac04bfa 847 __FILE__, VGlInfo, aGroup);
8e0a2b19 848 theCommands.Add("vshader",
849 "vshader name -vert VertexShader -frag FragmentShader [-geom GeometryShader]"
850 "\n\t\t: [-off] [-phong] [-aspect {shading|line|point|text}=shading]"
851 "\n\t\t: [-header VersionHeader]"
852 "\n\t\t: [-tessControl TessControlShader -tesseval TessEvaluationShader]"
853 "\n\t\t: Assign custom GLSL program to presentation aspects.",
392ac980 854 __FILE__, VShaderProg, aGroup);
8e0a2b19 855 theCommands.Add("vshaderprog", "Alias for vshader", __FILE__, VShaderProg, aGroup);
3946774d 856}