Having the Qt Framework  as GUI  for OpenGL  can be helpful of course but sometimes it seems easier to use the native OpenGL functions directly.
This is exactly what we are going to see in this tutorial by mixing Qt and native OpenGL functions.
First to all 
VIDEO 
For this tutorial recipe we are going to use:
2 different pairs of shaders (vertex and fragment)  
2 VAOs 
2 VBOs 
2 EBOs 
Shaders will be placed in the "shader/" directory and other files directly at the root.
The mix will consist of getting the QOpenGLShaderProgram  class from Qt.
And of course the classic initializeGL (), resizeGL () and paintGL () from the QOpenGLWidget  class.
Other than that we'll get everything from the native OpenGL functions.
As we need 2 pairs of shaders we'll create and link them with 2 methods, each one creating a program linked with the 2 compiled shaders (vertex and fragment).
These 2 methods are initProgram1  and initProgram2 .
Then we create 2 methods in order to create our 2 VAOs  with their VBO  and EBO . 
That is vaoCreation1  and vaoCreation2  which use their own vector of vertexes and indexes.
In these methods you can see that only vaoCreation2 uses 2 layout  attributes (location = 0 and location = 1) in order to deal with positions and colors directly from the vector of vertexes.
The vaoCreation1 manages the colors from another way: with a uniform  attribute.
Indeed, from the paintGL  methods we check which program is currently running.
If it's program1 then we change the color of the shape with random numbers.
So it changes the colors directly from our code, not from the vector of vertexes anymore.
But when the program2 takes the lead we tells OpenGL to check which shader is activated.
And from the fragment2 shader we have a "if " statement which says that if the color is black (meaning no colors at all) we change this color to white.
But this is only true when the VAO1  is activated with the shader2 because there is no layoutColor in this case (location 1).
When the VAO2  is activated with the shader2 the color isn't black anymore, we use indeed the attribute layoutColor to retrieve colors from the vector of indexes.
Of course we use the keyboard to switch from shader1 to shader2 then from VAO1 to VAO2.
The keys are:
1 = shader1 
2 = shader2 
J = VAO1 
K = VAO2 
Moreover when we are with VAO1 we set the glPolygonMode  to FILL  and when with VAO2 we set to LINE .
To resume:
VAO1 and shader1 makes the shape changes with many colors 
VAO1 and shader2 makes the shape changes to white 
VAO2 and shader1 makes the shape changes with many colors 
VAO2 and shader2 makes the shape changes with colors taken from the vector of indexes. 
Let's code a bit BadprogMixQtOpenGL.cpp 
#include   "BadprogMixQtOpenGL.h" 
#include   "BadprogWidget.h" 
#include   <QDebug> 
// badprog.com 
BadprogMixQtOpenGL ::BadprogMixQtOpenGL (QWidget* parent )
  : QMainWindow (parent)
{
  // 
  ui .setupUi (this );
  // 
  BadprogWidget * bpWidget  = new  BadprogWidget (this );
  // 
  setWindowTitle ("Badprog - Mixing native OpenGL and Qt functions" );
  // 
  setCentralWidget (bpWidget );
}
	 
 
 
BadprogMixQtOpenGL.h 
#ifndef  BADPROG_MIX_QT_OPENGL_H 
#define   BADPROG_MIX_QT_OPENGL_H 
#include   <QtWidgets/QMainWindow> 
#include   "ui_BadprogMixQtOpenGL.h" 
// badprog.com 
class  BadprogMixQtOpenGL  : public  QMainWindow 
{
    Q_OBJECT 
public: 
    BadprogMixQtOpenGL (QWidget  * parent  = Q_NULLPTR);
private: 
    Ui ::BadprogMixQtOpenGL  ui ;
};
#endif  // !BADPROG_MIX_QT_OPENGL_H 
 
 
BadprogMixQtOpenGL.qrc 
<RCC>
    <qresource prefix="">
    <file alias="vertex_color1"     >./shader/shader_vertex_color1.glsl</file>
    <file alias="fragment_color1"   >./shader/shader_fragment_color1.glsl</file>
    <file alias="vertex_color2"     >./shader/shader_vertex_color2.glsl</file>
    <file alias="fragment_color2"   >./shader/shader_fragment_color2.glsl</file>
    </qresource>
</RCC> BadprogMixQtOpenGL.ui 
<UI version="4.0" >
 <class>BadprogMixQtOpenGL</class>
 <widget class="QMainWindow" name="BadprogMixQtOpenGL" >
  <property name="objectName" >
   <string notr="true">BadprogMixQtOpenGL</string>
  </property>
  <property name="geometry" >
   <rect>
    <x>0</x>
    <y>0</y>
    <width>600</width>
    <height>400</height>
   </rect>
  </property>
  <property name="windowTitle" >
   <string>BadprogMixQtOpenGL</string>
  </property>  <widget class="QMenuBar" name="menuBar" />
  <widget class="QToolBar" name="mainToolBar" />
  <widget class="QWidget" name="centralWidget" />
  <widget class="QStatusBar" name="statusBar" />
 </widget>
 <layoutDefault spacing="6" margin="11" />
 <pixmapfunction></pixmapfunction>
 <resources>
   <include location="BadprogMixQtOpenGL.qrc"/>
 </resources>
 <connections/>
</UI>  
BadprogWidget.cpp 
#include   "BadprogWidget.h" 
#include   <QOpenGLShaderProgram> 
#include   <QKeyEvent> 
// badprog.com 
// 
#define   MAX ( a ,  b ) (a)  > (b)  ? (a)  : (b) 
// ---------------------------------------------------------------------------- 
// CTOR 
// ---------------------------------------------------------------------------- 
BadprogWidget ::BadprogWidget (QWidget* parent )
  : QOpenGLWidget (parent)
{
  // 
  _vectorOfVertex1 = {
   0.5f ,  0.5f , 0.0f ,
   0.5f , -0.5f , 0.0f ,
  -0.5f , -0.5f , 0.0f ,
  -0.5f ,  0.5f , 0.0f 
};
  // 
  _vectorOfVertex2 = {
  // position           // color RGB 
  -0.2f , -0.2f , 0.0f ,   1.0f , 0.0f , 0.0f ,
  -0.3f , -0.3f , 0.0f ,   0.0f , 1.0f , 1.0f ,
  0.5f , 0.2f , 0.0f ,     0.0f , 1.0f , 1.0f ,
  0.0f ,  0.0f , 0.0f ,    1.0f , 0.5f , 0.5f ,
  0.5f ,  -0.5f , 0.0f ,   1.0f , 1.0f , 1.0f 
};
  // 
  _vectorOfIndex1 = {
  0 , 1 , 3 ,  
  1 , 2 , 3     
};
  // 
  _vectorOfIndex2  = {
  0 , 1 , 2 ,
  1 , 2 , 3 ,
  3 , 4 , 1 ,
  2 , 1 , 4 ,
};
  // 
  setFocusPolicy (Qt ::StrongFocus);
  // 
  _maxSizeArray  = MAX (_vectorOfIndex1 .size (), _vectorOfIndex2 .size ());
  // 
  _programMain  = nullptr ;
  _modePolygon  = GL_FILL;
}
// ---------------------------------------------------------------------------- 
// DTOR 
// ---------------------------------------------------------------------------- 
BadprogWidget ::~ BadprogWidget () {}
// ---------------------------------------------------------------------------- 
// 1. initializeGL 
// ---------------------------------------------------------------------------- 
void  BadprogWidget ::initializeGL () {
  // 
  initializeOpenGLFunctions ();
  // 
  initProgram1 ();
  initProgram2 ();
  // 
  vaoCreation1 ();
  vaoCreation2 ();
  // 
  _programMain  = _program1 ;
  _vaoMain  = _vao1 ;
}
// ---------------------------------------------------------------------------- 
// 2. resizeGL 
// ---------------------------------------------------------------------------- 
void  BadprogWidget ::resizeGL (int  width , int  height ) {
  // 
  glViewport (0 , 0 , width , height );
}
// ---------------------------------------------------------------------------- 
// 3. paintGL 
// ---------------------------------------------------------------------------- 
void  BadprogWidget ::paintGL () {
  // 
  glClearColor (0.2f , 0.2f , 0.2f , 1.0f );
  glClear (GL_COLOR_BUFFER_BIT);
  // 
  glPolygonMode (GL_FRONT_AND_BACK, _modePolygon );
  // 
  _programMain ->bind ();
  // 
  if  (_programMain  == _program1 ) {
    // 
    int  randInt1  = rand ();
    int  randInt2  = rand ();
    int  randInt3  = rand ();
    int  randInt4  = rand ();
   
    // 
    float  randFloat1  = (float )randInt1 ;
    float  randFloat2  = (float )randInt2 ;
    float  randFloat3  = (float )randInt3 ;
    float  randFloat4  = (float )randInt4 ;
    // 
    randFloat1  /= RAND_MAX;
    randFloat2  /= RAND_MAX;
    randFloat3  /= RAND_MAX;
    randFloat4  /= RAND_MAX;
    // 
    unsigned  int  uniformLocation  = glGetUniformLocation (_programMain ->programId (), "uniformColor" );
    // 
    glUniform4f (uniformLocation , randFloat1 , randFloat2 , randFloat3 , randFloat4 );
    update ();
  }
  // 
  glBindVertexArray (_vaoMain );
  glDrawElements (GL_TRIANGLES, _maxSizeArray , GL_UNSIGNED_INT, 0 );
}
// ============================================================================ 
// initProgram1 
// ============================================================================ 
void  BadprogWidget ::initProgram1 () {
  // Program. 
  _program1  = new  QOpenGLShaderProgram (this );
  _program1 ->addShaderFromSourceFile (QOpenGLShader ::Vertex, ":vertex_color1" );
  _program1 ->addShaderFromSourceFile (QOpenGLShader ::Fragment, ":fragment_color1" );
  // 
  _program1 ->link (); // linking 
}
// ============================================================================ 
// initProgram2 
// ============================================================================ 
void  BadprogWidget ::initProgram2 () {
  // Program. 
  _program2  = new  QOpenGLShaderProgram (this );
  _program2 ->addShaderFromSourceFile (QOpenGLShader ::Vertex, ":vertex_color2" );
  _program2 ->addShaderFromSourceFile (QOpenGLShader ::Fragment, ":fragment_color2" );
  // 
  _program2 ->link (); // linking 
}
// ---------------------------------------------------------------------------- 
// vaoCreation1 
// ---------------------------------------------------------------------------- 
void  BadprogWidget ::vaoCreation1 () {
  // VAO 1 
  glGenVertexArrays (1 , &_vao1 );
  glBindVertexArray (_vao1 );
  // VBO 1 with the source array 
  glGenBuffers (1 , &_vbo1 );
  glBindBuffer (GL_ARRAY_BUFFER, _vbo1 );
  glBufferData (GL_ARRAY_BUFFER, _vectorOfVertex1 .size () * sizeof (float ), &_vectorOfVertex1 .front (), GL_STATIC_DRAW);
  // EBO 1 with the index array 
  glGenBuffers (1 , &_ebo1 );
  glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, _ebo1 );
  glBufferData (GL_ELEMENT_ARRAY_BUFFER, _vectorOfIndex1 .size () * sizeof (float ), &_vectorOfIndex1 .front (), GL_STATIC_DRAW);
  // Location 0 
  glVertexAttribPointer (0 , 3 , GL_FLOAT, GL_FALSE, 3  * sizeof (GL_FLOAT), (void *)0 );
  // Activate the index "0" (location) 
  glEnableVertexAttribArray (0 );
}
// ---------------------------------------------------------------------------- 
// vaoCreation2 
// ---------------------------------------------------------------------------- 
void  BadprogWidget ::vaoCreation2 () {
  // VAO 2 
  glGenVertexArrays (1 , &_vao2 );
  glBindVertexArray (_vao2 );
  // VBO 2 with the source array 
  glGenBuffers (1 , &_vbo2 );
  glBindBuffer (GL_ARRAY_BUFFER, _vbo2 );
  glBufferData (GL_ARRAY_BUFFER, _vectorOfVertex2 .size () * sizeof (float ), &_vectorOfVertex2 .front (), GL_STATIC_DRAW);
  // EBO 2 with the index array 
  glGenBuffers (1 , &_ebo2 );
  glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, _ebo2 );
  glBufferData (GL_ELEMENT_ARRAY_BUFFER, _vectorOfIndex2 .size () * sizeof (float ), &_vectorOfIndex2 .front (), GL_STATIC_DRAW);
  // Location 0 
  glVertexAttribPointer (0 , 3 , GL_FLOAT, GL_FALSE, 6  * sizeof (GL_FLOAT), (void *)0 );
  // Activate the index "0" (location) 
  glEnableVertexAttribArray (0 );
  // Location 1 from Shader vertex 2 
  glVertexAttribPointer (1 , 3 , GL_FLOAT, GL_FALSE, 6  * sizeof (GL_FLOAT), (void *)(3  * sizeof (GL_FLOAT)));
  // Activate the index "1" (color) 
  glEnableVertexAttribArray (1 );
}
// ============================================================================ 
// keyPressEvent 
// ============================================================================ 
void  BadprogWidget ::keyPressEvent (QKeyEvent *  event ) {
  // 
  if  (Qt ::Key_1 == event ->key ()) {
    _programMain  = _program1 ;
    update ();
  }
  else  if  (Qt ::Key_2 == event ->key ()) {
    _programMain  = _program2 ;
    update ();
  }
  // 
  if  (Qt ::Key_J == event ->key ()) {
    _vaoMain  = _vao1 ;
    _modePolygon  = GL_FILL;
    update ();
  }
  else  if  (Qt ::Key_K == event ->key ()) {
    _vaoMain  = _vao2 ;
    _modePolygon  = GL_LINE;
    update ();
  }
}
 
 
BadprogWidget.h 
#ifndef  BADPROG_WIDGET_H 
#define   BADPROG_WIDGET_H 
#include   <QOpenGLWidget> 
#include   <QOpenGLFunctions> 
#include   <QOpenGLFunctions_4_5_Core> 
#include   <QOpenGLVertexArrayObject> 
#include   <QOpenGLBuffer> 
#include   <QOpenGLShaderProgram> 
// badprog.com 
class  QKeyEvent ;
class  BadprogWidget  : public  QOpenGLWidget , protected  QOpenGLFunctions_4_5_Core 
{
  Q_OBJECT 
public: 
  BadprogWidget (QWidget *  parent  = nullptr );
  ~BadprogWidget ();
  // 
public: 
  void  initProgram1 ();
  void  initProgram2 ();
  void  vaoCreation1 ();
  void  vaoCreation2 ();
  // 
protected: 
  void  initializeGL ()                   override ;
  void  paintGL ()                        override ;
  void  resizeGL (int  width , int  height )  override ;
  // Override 
  void  keyPressEvent (QKeyEvent *  event ) override ;
  // 
private: 
  QOpenGLShaderProgram* _programMain ;
  QOpenGLShaderProgram* _program1 ;
  QOpenGLShaderProgram* _program2 ;
  // VAO 
  GLuint _vaoMain ;
  GLuint _vao1 ;
  GLuint _vao2 ;
  // VBO 
  GLuint _vbo1 ;
  GLuint _vbo2 ;
  // EBO 
  GLuint _ebo1 ;
  GLuint _ebo2 ;
  // 
  std ::v ector<float > _vectorOfVertex1;
  std ::v ector<float > _vectorOfVertex2;
  std ::v ector<unsigned  int > _vectorOfIndex1;
  std ::v ector<unsigned  int > _vectorOfIndex2;
  int  _maxSizeArray ;
  GLint _modePolygon ;
};
#endif  // !BADPROG_WIDGET_H 
 
 
main.cpp 
#include   "BadprogMixQtOpenGL.h" 
#include   <QtWidgets/QApplication> 
// badprog.com 
int  main (int  argc , char  * argv [])
{
    QApplication a (argc , argv);
    BadprogMixQtOpenGL  w;
    w .show ();
    return  a .exec ();
}
 
 
shader/shader_fragment_color1.glsl 
#version  330  core
// badprog.com 
// out 
out  vec4  FragColor;
// in 
uniform  vec4  uniformColor;
// ---------------------------------------------------------------------------- 
// main 
// ---------------------------------------------------------------------------- 
void  main() {
    // 
    FragColor = uniformColor;
}
 
 
shader/shader_fragment_color2.glsl 
#version  330  core
// badprog.com 
// out 
out  vec4  FragColor;
// in 
in  vec3  shaderColor;
// ---------------------------------------------------------------------------- 
// main 
// ---------------------------------------------------------------------------- 
void  main() {
    // 
    FragColor = vec4 (shaderColor, 1 .0f);
}
 
 
shader/shader_vertex_color1.glsl 
#version  330  core
// badprog.com 
// layout 
layout  (location = 0 ) in  vec3  layoutPosition;
// ---------------------------------------------------------------------------- 
// main 
// ---------------------------------------------------------------------------- 
void  main() {
    // 
    gl_Position  = vec4 (layoutPosition, 1 .0f);
}
 
 
shader/shader_vertex_color2.glsl 
#version  330  core
// badprog.com 
// layout 
layout  (location = 0 ) in  vec3  layoutPosition;
layout  (location = 1 ) in  vec3  layoutColor;
// out 
out  vec3  shaderColor;
out  vec3  colorWhite;
// ---------------------------------------------------------------------------- 
// main 
// ---------------------------------------------------------------------------- 
void  main() {
    // 
    colorWhite.x = 1 .0f;
    colorWhite.y = 1 .0f;
    colorWhite.z = 1 .0f;
    // 
    gl_Position  = vec4 (layoutPosition, 1 .0f);
    shaderColor = layoutColor;
   
    // 
    if  (shaderColor.x <= 0 .0f && shaderColor.y <= 0 .0f && shaderColor.z <= 0 .0f) {
        shaderColor = colorWhite.xyz;
    }
}
 
 
Conclusion 
What's interesting here is to have the GUI completely managed by Qt and we don't have to bother with  different libraries with their esoteric include files.
Furthermore it's totally possible to pick which part of your program you'll make with native OpenGL functions or with Qt ones.
Thank you for reaching this line, I hope you enjoyed this tutorial.
See you for another tutorial 
Add new comment