Why when I use QGLShaderProgram.bind() instead of link(), I get a black screen?



  • Hi everybody,

    I do not know why nothing appears on my OpenGL widget (see code below) when I use QGLShaderProgram.bind(), while it works when I only use QGLShaderProgram.link() in my initializeGL functions?

    Here is my code:

    My shaders:

    vertex_code = """
        #version 440 core
    
        uniform float scale;
        uniform mat4 Model;
        uniform mat4 View;
        uniform mat4 Projection;
    
        in vec2 position;   
        in vec4 color;     
    
        out vec4 v_color;
    
    
        void main()
        {
            gl_Position =  Projection * View * Model * vec4(scale*position, 0.0, 1.0);
            v_color = color;
    
        } """
    
    
    
    fragment_code = """
        #version 440 core
    
        in vec4 v_color;
    
    
    
        void main()
        {
            gl_FragColor = v_color;
    
    
        } """
    

    The square to render:

    class GeometricObject:

    def __init__(self):
        self.vertices = np.array([[1, 1],
                                  [1, -1],
                                  [-1, -1],
                                  [-1, 1]])
    
        self.indices = np.array([[0, 1, 3],
                                  [1, 2, 3],
                                  ])
    
        tmp = np.ones(shape=(4,3))
        tmp2 = np.ones(shape=(4,1))
        tmp = np.hstack((tmp, tmp2 ))   
    
    
        self.colors = tmp     
    

    My widgetGL:

    class GLWidget(QtOpenGL.QGLWidget):
    
        def __init__(self, parent=None):
            super(GLWidget, self).__init__(QtOpenGL.QGLFormat(QtOpenGL.QGL.SampleBuffers), parent)
            self.shaderProgram = QtOpenGL.QGLShaderProgram()
            self.listOfLayers = []
            self.listOfVerticesBuffers = []
            self.listOfIndicesBuffers = []
            self.listOfColorsBuffers = []
    
    
    
    
        def initializeGL(self):       
    
            self.shaderProgram.addShaderFromSourceCode(QtOpenGL.QGLShader.Vertex, vertex_code)
            self.shaderProgram.addShaderFromSourceCode(QtOpenGL.QGLShader.Fragment, fragment_code)
            #self.shaderProgram.link()     
            res=self.shaderProgram.bind()
    
            if res is True:
                print('Program has successfully been binded')
            else:
                raise ValueError('Bind fail')
    
    
        def paintGL(self):
    
            if not self.listOfLayers:
                print('No layer detected')
            else:
                print('Existing layer')
    
    
                gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
    
                gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_FILL)
    
                print('there are %i objects available'%(len(self.listOfLayers)))
                for i, obj in enumerate(self.listOfLayers):       
                    print('looping')
                    print(self.shaderProgram.programId())
                    loc_pos = gl.glGetAttribLocation(self.shaderProgram.programId(), "position")
                    gl.glEnableVertexAttribArray(loc_pos)
                    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.listOfVerticesBuffers[i])
                    gl.glVertexAttribPointer(loc_pos, 2, gl.GL_DOUBLE, False, 0,  ctypes.c_void_p(0))
                    print('ok')
    
                    loc_col = gl.glGetAttribLocation(self.shaderProgram.programId(), "color")
                    gl.glEnableVertexAttribArray(loc_col)
                    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.listOfColorsBuffers[i])
                    gl.glVertexAttribPointer(loc_col, 4, gl.GL_DOUBLE, False, 0,  ctypes.c_void_p(0))
    
    
                    gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.listOfIndicesBuffers[i])
                    gl.glDrawElements(gl.GL_TRIANGLES, obj.indices.size, gl.GL_UNSIGNED_INT, ctypes.c_void_p(0))
                    print('draw ok')
    
    
    
    
    
    
        def keyPressEvent(self, e):
            if e.key()==QtCore.Qt.Key_Minus:
                print('- pressed')
    
    
    
    
    
        def addLayer(self, anObject):
    
            self.makeCurrent()
            self.listOfLayers.append(anObject)
            # generate buffers
            verticesBuffer = gl.glGenBuffers(1)
            indicesBuffer = gl.glGenBuffers(1)
            colorsBuffer = gl.glGenBuffers(1)
    
            self.listOfVerticesBuffers.append(verticesBuffer)
            self.listOfIndicesBuffers.append(indicesBuffer)
            self.listOfColorsBuffers.append(colorsBuffer)
    
            # format arrays
            vertices = np.ascontiguousarray(anObject.vertices.flatten(), dtype=np.double)
            indices = np.ascontiguousarray(anObject.indices.flatten(), dtype=np.uint32)
            colors = np.ascontiguousarray(anObject.colors.flatten(), dtype=np.double)
    
            # transfer data to GPU buffers
            gl.glBindBuffer(gl.GL_ARRAY_BUFFER, verticesBuffer)
            gl.glBufferData(gl.GL_ARRAY_BUFFER, vertices.nbytes, vertices, gl.GL_DYNAMIC_DRAW)
    
    
            # COLOR ARRAY
            gl.glBindBuffer(gl.GL_ARRAY_BUFFER, colorsBuffer)
            gl.glBufferData(gl.GL_ARRAY_BUFFER, colors.nbytes, colors, gl.GL_DYNAMIC_DRAW)   
    
    
            # INDEX ARRAY
            gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, indicesBuffer)
            gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, indices.nbytes, indices, gl.GL_DYNAMIC_DRAW)
    
            self.paintGL()
    

    The main window with a GLWidget attached to it:

    class MainWindow(QtGui.QMainWindow):
    
        def __init__(self):
            super(MainWindow, self).__init__()
    
            # create layout
            layout_panel = QtGui.QGridLayout()
            layout_final = QtGui.QHBoxLayout()
    
            # instance widgets      
            self.widgetGL = GLWidget()
            self.currentH5File = QtGui.QLineEdit()
            self.button = QtGui.QPushButton("Push to add an object")
            self.button2 = QtGui.QPushButton("Another button")
    
            # adapt widgets        
            self.currentH5File.setReadOnly(True)
            #self.currentH5File.resize()
            # add
            layout_panel.addWidget(self.button, 0, 0, 1, 1)
            layout_panel.addWidget(self.currentH5File, 1, 0, 1, 1)
            layout_panel.addWidget(self.button2, 2, 0, 1, 1)
    
            layout_final.addLayout(layout_panel)
    
            layout_final.addWidget(self.widgetGL, 3)
    
    
            window = QtGui.QWidget()
            window.setLayout(layout_final)
    
    
            self.button.clicked.connect(self.addLayer)
    
            self.setCentralWidget(window)
            self.setWindowTitle('PyPractis')
            self.resize(640, 480)        
    
            self.show()
    
    
        def keyPressEvent(self, e):
            self.widgetGL.keyPressEvent(e)
    
    
        def addLayer(self):
            self.widgetGL.addLayer(GeometricObject())
    
    

    The main:

    app = QtGui.QApplication(sys.argv)
      window = MainWindow()
      sys.exit(app.exec_())
    
    
    


  • Moreover, I also just realize that my square is always drawn in white while it should be rendered with a random color.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Do you mean that if you call link then bind, the shader doesn't work ?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.