Why when I use QGLShaderProgram.bind() instead of link(), I get a black screen?
Unsolved
General and Desktop
-
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_())
-
Hi and welcome to devnet,
Do you mean that if you call link then bind, the shader doesn't work ?