0027622: Data Exchange - STL file having less than 4 triangles cannot be read
[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>
3946774d 33#include <OpenGl_Workspace.hxx>
392ac980 34#include <OSD_Environment.hxx>
35#include <OSD_File.hxx>
6262338c 36#include <Prs3d_Drawer.hxx>
3946774d 37#include <Prs3d_Presentation.hxx>
38#include <Prs3d_Root.hxx>
392ac980 39#include <Prs3d_ShadingAspect.hxx>
3946774d 40#include <Select3D_SensitiveCurve.hxx>
41#include <SelectMgr_EntityOwner.hxx>
42#include <SelectMgr_Selection.hxx>
43#include <TCollection_AsciiString.hxx>
3c4153af 44#include <V3d_View.hxx>
392ac980 45#include <V3d_Viewer.hxx>
392ac980 46#include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
47#include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
92efcf78 48#include <OpenGl_Group.hxx>
3946774d 49
50extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
51 const Handle(AIS_InteractiveObject)& theAISObj,
52 Standard_Boolean theReplaceIfExists = Standard_True);
392ac980 53extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
3946774d 54
c04c30b3 55namespace {
56
3946774d 57//=======================================================================
58//function : VUserDraw
59//purpose : Checks availability and operation of UserDraw feature
60//=======================================================================
3946774d 61
62class VUserDrawObj : public AIS_InteractiveObject
63{
64public:
65 // CASCADE RTTI
92efcf78 66 DEFINE_STANDARD_RTTI_INLINE(VUserDrawObj,AIS_InteractiveObject);
3946774d 67
68 VUserDrawObj()
69 {
70 myCoords[0] = -10.;
71 myCoords[1] = -20.;
72 myCoords[2] = -30.;
73 myCoords[3] = 10.;
74 myCoords[4] = 20.;
75 myCoords[5] = 30.;
76 }
77
78public:
79 class Element : public OpenGl_Element
80 {
81 private:
82 Handle(VUserDrawObj) myIObj;
83
84 public:
a521d90d 85 Element (const Handle(VUserDrawObj)& theIObj) : myIObj (theIObj) {}
3946774d 86
a521d90d 87 virtual ~Element() {}
3946774d 88
89 virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const
90 {
91 if (!myIObj.IsNull())
92 myIObj->Render(theWorkspace);
93 }
94
10b9c7df 95 virtual void Release (OpenGl_Context*)
5e27df78 96 {
97 //
98 }
99
3946774d 100 public:
101 DEFINE_STANDARD_ALLOC
102 };
103
104private:
105 // Virtual methods implementation
106 void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
107 const Handle(Prs3d_Presentation)& thePresentation,
79104795 108 const Standard_Integer theMode) Standard_OVERRIDE;
3946774d 109
110 void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
79104795 111 const Standard_Integer theMode) Standard_OVERRIDE;
3946774d 112
113 // Called by VUserDrawElement
114 void Render(const Handle(OpenGl_Workspace)& theWorkspace) const;
3946774d 115
a521d90d 116private:
3946774d 117 GLfloat myCoords[6];
3946774d 118 friend class Element;
119};
ec357c5c 120
a521d90d 121void VUserDrawObj::Compute(const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
122 const Handle(Prs3d_Presentation)& thePrs,
35e08fe8 123 const Standard_Integer /*theMode*/)
3946774d 124{
a521d90d 125 thePrs->Clear();
126
127 Graphic3d_Vec4 aBndMin (myCoords[0], myCoords[1], myCoords[2], 1.0f);
128 Graphic3d_Vec4 aBndMax (myCoords[3], myCoords[4], myCoords[5], 1.0f);
129 Handle(OpenGl_Group) aGroup = Handle(OpenGl_Group)::DownCast (thePrs->NewGroup());
130 aGroup->SetMinMaxValues (aBndMin.x(), aBndMin.y(), aBndMin.z(),
131 aBndMax.x(), aBndMax.y(), aBndMax.z());
132 VUserDrawObj::Element* anElem = new VUserDrawObj::Element (this);
133 aGroup->AddElement(anElem);
134
135 // invalidate bounding box of the scene
136 thePrsMgr->StructureManager()->Update (thePrsMgr->StructureManager()->UpdateMode());
3946774d 137}
138
139void VUserDrawObj::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
35e08fe8 140 const Standard_Integer /*theMode*/)
3946774d 141{
142 Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner(this);
143 Handle(TColgp_HArray1OfPnt) aPnts = new TColgp_HArray1OfPnt(1, 5);
144 aPnts->SetValue(1, gp_Pnt(myCoords[0], myCoords[1], myCoords[2]));
145 aPnts->SetValue(2, gp_Pnt(myCoords[3], myCoords[4], myCoords[2]));
146 aPnts->SetValue(3, gp_Pnt(myCoords[3], myCoords[4], myCoords[5]));
147 aPnts->SetValue(4, gp_Pnt(myCoords[0], myCoords[1], myCoords[5]));
148 aPnts->SetValue(5, gp_Pnt(myCoords[0], myCoords[1], myCoords[2]));
149 Handle(Select3D_SensitiveCurve) aSensitive = new Select3D_SensitiveCurve(anEntityOwner, aPnts);
150 theSelection->Add(aSensitive);
151}
152
3946774d 153void VUserDrawObj::Render(const Handle(OpenGl_Workspace)& theWorkspace) const
154{
a521d90d 155 // this sample does not use GLSL programs - make sure it is disabled
156 Handle(OpenGl_Context) aCtx = theWorkspace->GetGlContext();
157 aCtx->BindProgram (NULL);
158
3946774d 159 // To test linking against OpenGl_Workspace and all aspect classes
160 const OpenGl_AspectLine* aLA = theWorkspace->AspectLine(0);
3946774d 161 const OpenGl_AspectMarker* aMA = theWorkspace->AspectMarker(0);
162 aMA->Type();
163 const OpenGl_AspectText* aTA = theWorkspace->AspectText(0);
a174a3c5 164 aTA->FontName();
3946774d 165 TEL_COLOUR aColor = theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT ?
166 *(theWorkspace->HighlightColor) : aLA->Color();
167
3946774d 168 // Finally draw something to make sure UserDraw really works
169 glPushAttrib(GL_ENABLE_BIT);
170 glDisable(GL_LIGHTING);
171 glColor4fv(aColor.rgb);
172 glBegin(GL_LINE_LOOP);
173 glVertex3f(myCoords[0], myCoords[1], myCoords[2]);
174 glVertex3f(myCoords[3], myCoords[4], myCoords[2]);
175 glVertex3f(myCoords[3], myCoords[4], myCoords[5]);
176 glVertex3f(myCoords[0], myCoords[1], myCoords[5]);
177 glEnd();
178 glPopAttrib();
179}
180
c04c30b3 181} // end of anonymous namespace
182
3946774d 183static Standard_Integer VUserDraw (Draw_Interpretor& di,
184 Standard_Integer argc,
185 const char ** argv)
186{
187 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
188 if (aContext.IsNull())
189 {
190 di << argv[0] << "Call 'vinit' before!\n";
191 return 1;
192 }
193
dc3fe572 194 Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5e27df78 195 if (aDriver.IsNull())
196 {
197 std::cerr << "Graphic driver not available.\n";
198 return 1;
199 }
200
3946774d 201 if (argc > 2)
202 {
203 di << argv[0] << "Wrong number of arguments, only the object name expected\n";
204 return 1;
205 }
206
207 TCollection_AsciiString aName (argv[1]);
208 VDisplayAISObject(aName, Handle(AIS_InteractiveObject)());
209
3946774d 210 Handle(VUserDrawObj) anIObj = new VUserDrawObj();
211 VDisplayAISObject(aName, anIObj);
212
213 return 0;
214}
215
3c4153af 216//==============================================================================
217//function : VFeedback
218//purpose :
219//==============================================================================
220
221static int VFeedback (Draw_Interpretor& theDI,
35e08fe8 222 Standard_Integer /*theArgNb*/,
223 const char** /*theArgVec*/)
3c4153af 224{
225 // get the active view
226 Handle(V3d_View) aView = ViewerTest::CurrentView();
227 if (aView.IsNull())
228 {
229 std::cerr << "No active view. Please call vinit.\n";
230 return 1;
231 }
232
233 unsigned int aBufferSize = 1024 * 1024;
234 for (;;)
235 {
236 size_t aBytes = (size_t )aBufferSize * sizeof(GLfloat);
237 if (aBytes / sizeof(GLfloat) != (size_t )aBufferSize)
238 {
239 // finito la commedia
240 std::cerr << "Can not allocate buffer - requested size ("
241 << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat)))
242 << " MiB) is out of address space\n";
243 return 1;
244 }
245
246 GLfloat* aBuffer = (GLfloat* )Standard::Allocate (aBytes);
247 if (aBuffer == NULL)
248 {
249 // finito la commedia
250 std::cerr << "Can not allocate buffer with size ("
251 << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat)))
252 << " MiB)\n";
253 return 1;
254 }
255
256 glFeedbackBuffer ((GLsizei )aBufferSize, GL_2D, aBuffer);
257 glRenderMode (GL_FEEDBACK);
258
259 aView->Redraw();
260
261 GLint aResult = glRenderMode (GL_RENDER);
262 if (aResult < 0)
263 {
264 aBufferSize *= 2;
265
266 void* aPtr = aBuffer;
267 Standard::Free (aPtr);
268 aBuffer = NULL;
269 continue;
270 }
271
272 std::cout << "FeedBack result= " << aResult << "\n";
273 GLint aPntNb = 0;
274 GLint aTriNb = 0;
275 GLint aQuadsNb = 0;
276 GLint aPolyNb = 0;
277 GLint aNodesNb = 0;
278 GLint aLinesNb = 0;
279 GLint aBitmapsNb = 0;
280 GLint aPassThrNb = 0;
281 GLint aUnknownNb = 0;
282 const GLint NODE_VALUES = 2; // GL_2D
283 for (GLint anIter = 0; anIter < aResult;)
284 {
285 const GLfloat aPos = aBuffer[anIter];
286 switch ((GLint )aPos)
287 {
288 case GL_POINT_TOKEN:
289 {
290 ++aPntNb;
291 ++aNodesNb;
292 anIter += 1 + NODE_VALUES;
293 break;
294 }
295 case GL_LINE_RESET_TOKEN:
296 case GL_LINE_TOKEN:
297 {
298 ++aLinesNb;
299 aNodesNb += 2;
300 anIter += 1 + 2 * NODE_VALUES;
301 break;
302 }
303 case GL_POLYGON_TOKEN:
304 {
305 const GLint aCount = (GLint )aBuffer[++anIter];
306 aNodesNb += aCount;
307 anIter += aCount * NODE_VALUES + 1;
308 if (aCount == 3)
309 {
310 ++aTriNb;
311 }
312 else if (aCount == 4)
313 {
314 ++aQuadsNb;
315 }
316 else
317 {
318 ++aPolyNb;
319 }
320 break;
321 }
322 case GL_BITMAP_TOKEN:
323 case GL_DRAW_PIXEL_TOKEN:
324 case GL_COPY_PIXEL_TOKEN:
325 {
326 ++aBitmapsNb;
327 anIter += 1 + NODE_VALUES;
328 break;
329 }
330 case GL_PASS_THROUGH_TOKEN:
331 {
332 ++aPassThrNb;
333 anIter += 2; // header + value
334 break;
335 }
336 default:
337 {
338 ++anIter;
339 ++aUnknownNb;
340 break;
341 }
342 }
343 }
344 void* aPtr = aBuffer;
345 Standard::Free (aPtr);
346
347 // return statistics
348 theDI << "Total nodes: " << aNodesNb << "\n"
349 << "Points: " << aPntNb << "\n"
350 << "Line segments: " << aLinesNb << "\n"
351 << "Triangles: " << aTriNb << "\n"
352 << "Quads: " << aQuadsNb << "\n"
353 << "Polygons: " << aPolyNb << "\n"
354 << "Bitmap tokens: " << aBitmapsNb << "\n"
355 << "Pass through: " << aPassThrNb << "\n"
356 << "UNKNOWN: " << aUnknownNb << "\n";
357
358 double aLen2D = double(aNodesNb * 2 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
359 double aLen3D = double(aNodesNb * 3 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
360 double aLen3D_rgba = double(aNodesNb * 7 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
361 theDI << "Buffer size GL_2D: " << aLen2D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"
362 << "Buffer size GL_3D: " << aLen3D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"
363 << "Buffer size GL_3D_COLOR: " << aLen3D_rgba * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n";
364 return 0;
365 }
366}
367
1981cb22 368//==============================================================================
369//function : VImmediateFront
370//purpose :
371//==============================================================================
372
35e08fe8 373static int VImmediateFront (Draw_Interpretor& /*theDI*/,
1981cb22 374 Standard_Integer theArgNb,
375 const char** theArgVec)
376{
377 // get the context
378 Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
379 if (aContextAIS.IsNull())
380 {
381 std::cerr << "No active view. Please call vinit.\n";
382 return 1;
383 }
384
dc3fe572 385 Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
386
1981cb22 387 if (aDriver.IsNull())
388 {
389 std::cerr << "Graphic driver not available.\n";
390 return 1;
391 }
392
393 if (theArgNb < 2)
394 {
1981cb22 395 std::cerr << "Wrong number of arguments.\n";
396 return 1;
397 }
398
c357e426 399 ViewerTest::CurrentView()->View()->SetImmediateModeDrawToFront (atoi(theArgVec[1]) != 0);
400
1981cb22 401 return 0;
402}
403
dac04bfa 404//==============================================================================
405//function : VGlInfo
406//purpose :
407//==============================================================================
408
409static int VGlInfo (Draw_Interpretor& theDI,
410 Standard_Integer theArgNb,
411 const char** theArgVec)
412{
413 // get the active view
414 Handle(V3d_View) aView = ViewerTest::CurrentView();
415 if (aView.IsNull())
416 {
417 std::cerr << "No active view. Please call vinit.\n";
418 return 1;
419 }
420
421 if (theArgNb <= 1)
422 {
c357e426 423 Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
4e1523ef 424 if (aDriver.IsNull())
425 {
426 std::cerr << "Error: view does not use OpenGL.\n";
427 return 1;
428 }
429 Handle(OpenGl_Context) aCtx = aDriver->GetSharedContext();
430 Standard_CString aDebugInfo = !aCtx.IsNull() && aCtx->IsDebugContext()
431 ? " GLdebug = ON\n"
432 : "";
dac04bfa 433 theDI << "OpenGL info:\n"
434 << " GLvendor = '" << (const char* )glGetString(GL_VENDOR) << "'\n"
435 << " GLdevice = '" << (const char* )glGetString(GL_RENDERER) << "'\n"
436 << " GLversion = '" << (const char* )glGetString(GL_VERSION) << "'\n"
58655684 437 << " GLSLversion = '" << (const char* )glGetString(GL_SHADING_LANGUAGE_VERSION) << "'\n"
438 << aDebugInfo;
dac04bfa 439 return 0;
440 }
441
442 const Standard_Boolean isList = theArgNb >= 3;
443 for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter)
444 {
445 TCollection_AsciiString aName (theArgVec[anIter]);
446 aName.UpperCase();
447 const char* aValue = NULL;
448 if (aName.Search ("VENDOR") != -1)
449 {
450 aValue = (const char* )glGetString (GL_VENDOR);
451 }
452 else if (aName.Search ("RENDERER") != -1)
453 {
454 aValue = (const char* )glGetString (GL_RENDERER);
455 }
456 else if (aName.Search ("SHADING_LANGUAGE_VERSION") != -1
457 || aName.Search ("GLSL") != -1)
458 {
459 aValue = (const char* )glGetString (GL_SHADING_LANGUAGE_VERSION);
460 }
461 else if (aName.Search ("VERSION") != -1)
462 {
463 aValue = (const char* )glGetString (GL_VERSION);
464 }
465 else if (aName.Search ("EXTENSIONS") != -1)
466 {
467 aValue = (const char* )glGetString (GL_EXTENSIONS);
468 }
469 else
470 {
471 std::cerr << "Unknown key '" << aName.ToCString() << "'\n";
472 return 1;
473 }
474
475 if (isList)
476 {
477 theDI << "{" << aValue << "} ";
478 }
479 else
480 {
481 theDI << aValue;
482 }
483 }
484
485 return 0;
486}
487
392ac980 488
489//==============================================================================
490//function : VShaderProg
491//purpose : Sets the pair of vertex and fragment shaders for the object
492//==============================================================================
493static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/,
494 Standard_Integer theArgNb,
495 const char** theArgVec)
496{
497 Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
498 if (aCtx.IsNull())
499 {
500 std::cerr << "Use 'vinit' command before " << theArgVec[0] << "\n";
501 return 1;
502 }
503 else if (theArgNb < 2)
504 {
505 std::cerr << theArgVec[0] << " syntax error: lack of arguments\n";
506 return 1;
507 }
508
509 TCollection_AsciiString aLastArg (theArgVec[theArgNb - 1]);
510 aLastArg.UpperCase();
511 const Standard_Boolean toTurnOff = aLastArg == "OFF";
512 Standard_Integer anArgsNb = theArgNb - 1;
513 Handle(Graphic3d_ShaderProgram) aProgram;
514 if (!toTurnOff
515 && aLastArg == "PHONG")
516 {
517 aProgram = new Graphic3d_ShaderProgram (Graphic3d_ShaderProgram::ShaderName_Phong);
518 }
519 if (!toTurnOff
520 && aProgram.IsNull())
521 {
522 if (theArgNb < 3)
523 {
524 std::cerr << theArgVec[0] << " syntax error: lack of arguments\n";
525 return 1;
526 }
527
528 const TCollection_AsciiString aSrcVert = theArgVec[theArgNb - 2];
529 const TCollection_AsciiString aSrcFrag = theArgVec[theArgNb - 1];
530 if (!aSrcVert.IsEmpty()
531 && !OSD_File (aSrcVert).Exists())
532 {
533 std::cerr << "Non-existing vertex shader source\n";
534 return 1;
535 }
536 if (!aSrcFrag.IsEmpty()
537 && !OSD_File (aSrcFrag).Exists())
538 {
539 std::cerr << "Non-existing fragment shader source\n";
540 return 1;
541 }
542
543 aProgram = new Graphic3d_ShaderProgram();
544 aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aSrcVert));
545 aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_FRAGMENT, aSrcFrag));
546 anArgsNb = theArgNb - 2;
547 }
548
549 Handle(AIS_InteractiveObject) anIO;
550 if (anArgsNb <= 1
551 || *theArgVec[1] == '*')
552 {
553 for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
554 anIter.More(); anIter.Next())
555 {
556 anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
557 if (!anIO.IsNull())
558 {
559 anIO->Attributes()->ShadingAspect()->Aspect()->SetShaderProgram (aProgram);
560 aCtx->Redisplay (anIO, Standard_False);
561 }
562 }
563 aCtx->UpdateCurrentViewer();
564 return 0;
565 }
566
567 for (Standard_Integer anArgIter = 1; anArgIter < anArgsNb; ++anArgIter)
568 {
569 const TCollection_AsciiString aName (theArgVec[anArgIter]);
570 if (!GetMapOfAIS().IsBound2 (aName))
571 {
572 std::cerr << "Warning: " << aName.ToCString() << " is not displayed\n";
573 continue;
574 }
575 anIO = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aName));
576 if (anIO.IsNull())
577 {
578 std::cerr << "Warning: " << aName.ToCString() << " is not an AIS object\n";
579 continue;
580 }
581 anIO->Attributes()->ShadingAspect()->Aspect()->SetShaderProgram (aProgram);
582 aCtx->Redisplay (anIO, Standard_False);
583 }
584
585 aCtx->UpdateCurrentViewer();
586 return 0;
587}
588
3946774d 589//=======================================================================
590//function : OpenGlCommands
591//purpose :
592//=======================================================================
593
594void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands)
595{
596 const char* aGroup ="Commands for low-level TKOpenGl features";
597
598 theCommands.Add("vuserdraw",
599 "vuserdraw : name - simulates drawing with help of UserDraw",
600 __FILE__, VUserDraw, aGroup);
3c4153af 601 theCommands.Add("vfeedback",
602 "vfeedback : perform test GL feedback rendering",
603 __FILE__, VFeedback, aGroup);
1981cb22 604 theCommands.Add("vimmediatefront",
605 "vimmediatefront : render immediate mode to front buffer or to back buffer",
606 __FILE__, VImmediateFront, aGroup);
dac04bfa 607 theCommands.Add("vglinfo",
608 "vglinfo [GL_VENDOR] [GL_RENDERER] [GL_VERSION] [GL_SHADING_LANGUAGE_VERSION] [GL_EXTENSIONS]"
609 " : prints GL info",
610 __FILE__, VGlInfo, aGroup);
392ac980 611 theCommands.Add("vshaderprog",
612 " 'vshaderprog [name] pathToVertexShader pathToFragmentShader'"
613 "\n\t\t: or 'vshaderprog [name] off' to disable GLSL program"
614 "\n\t\t: or 'vshaderprog [name] phong' to enable per-pixel lighting calculations"
615 "\n\t\t: * might be used to specify all displayed objects",
616 __FILE__, VShaderProg, aGroup);
3946774d 617}