简单的OpenGL / GLSL程序不起作用

时间:2012-12-01 11:28:36

标签: python opengl glsl pyside pyopengl

问题:这个简单的OpenGL / GLSL程序有什么问题? 它应该产生具有红绿色渐变的四边形。 但我只是得到一个黑色的窗口,没有错误信息。

import numpy
from OpenGL.GL import *
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtOpenGL import *

_vertexShaderSource = (
    'attribute vec2 a_position;'
    'attribute vec3 a_color;'
    'varying vec3 v_color;'
    ''
    'void main()'
    '{'
    '   gl_Position = vec4(a_position, 0.0, 1.0);'
    '   v_color = a_color;'
    '}'
)

_fragmentShaderSource = (
    'varying vec3 v_color;'
    ''
    'void main()'
    '{'
    '    gl_FragColor = vec4(v_color, 1.0);'
    '}'
)

_POSITION = 0
_COLOR = 1

class HelloWidget(QGLWidget):

    def __init__(self):
        QGLWidget.__init__(self)

    def initializeGL(self):
        self._shaderProgram = QGLShaderProgram(self.context())
        self._shaderProgram.addShaderFromSourceCode(QGLShader.Vertex, _vertexShaderSource)
        self._shaderProgram.addShaderFromSourceCode(QGLShader.Fragment, _fragmentShaderSource)
        self._shaderProgram.link()
        self._shaderProgram.bind()

        glBindAttribLocation(self._shaderProgram.programId(), _POSITION, 'a_position')
        glBindAttribLocation(self._shaderProgram.programId(), _COLOR, 'a_color')

    def paintGL(self):
        glViewport(0, 0, self.width(), self.height())
        glClear(GL_COLOR_BUFFER_BIT)

        position = numpy.ndarray([-0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5], numpy.float32)
        glVertexAttribPointer(_POSITION, 2, GL_FLOAT, False, 0, position)
        glEnableVertexAttribArray(_POSITION)

        color = numpy.ndarray([1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0], numpy.float32)
        glVertexAttribPointer(_COLOR, 3, GL_FLOAT, False, 0, color)
        glEnableVertexAttribArray(_COLOR)

        glDrawArrays(GL_QUADS, 0, 4)

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    w = HelloWidget()
    w.show()
    app.exec_()

答案:代码中有两个错误。

  1. 正如Brett Hale所指出的,glBindAttribLocation的来电必须在self._shaderProgram.link()之前。

  2. numpy.ndarray应替换为numpy.array

  3. 如果您解决了这两个问题,那么代码将按预期工作。

3 个答案:

答案 0 :(得分:2)

来自the man page for glBindAttribLocation:

  

程序对象之后发生的任何属性绑定          链接在下次程序对象出现之前不会生效          联的。

首先关联属性索引,然后链接程序。

或者,使用_POSITION_COLORglGetAttribLocation等分配值。


如@KillianDS所述,您可以在着色器中指定索引(位置),前提是您具有GL 3.3或更高版本。这是OS X的挫败感,只有保证 GL 3.2。


可能还值得指出核心配置文件中不支持GL_QUADS,因此可能需要解决这个问题,例如,使用2个三角形。

答案 1 :(得分:1)

我宁愿发表评论,但它很长。希望这可以帮助你:

由于您在顶点着色器中使用了attribute关键字(兼容性关键字),您能否澄清一下您使用的OpenGL和GLSL版本?我没有在代码中看到任何引用该版本的内容;我想念它吗?这可能有助于理解问题所在。

如果有可用的话,layout格式肯定会简化。 此外,您的着色器要求指定#version(至少在latest spec中,但我认为它适用于所有版本。) 1.10不需要(虽然仍然支持,但OP正在使用/打算使用。

答案 2 :(得分:0)

我不熟悉Python下的Qt,但我很确定你需要使用glUseProgram将着色器程序设置为活动状态。