compiling shaders in pyqt

  • Last Update :
  • Techknowledgy :

A solution would look like:

...
class ExampleQGLWidget(QGLWidget):

   def __init__(self, parent):
   QGLWidget.__init__(self, parent)
self.shaderProgram = QGLShaderProgram()

self.makeCurrent()

print self.shaderProgram.addShaderFromSourceFile(QGLShader.Vertex, "shader.vert")
print self.shaderProgram.addShaderFromSourceFile(QGLShader.Fragment, "shader.frag")
print self.shaderProgram.log()
self.shaderProgram.link()

self.doneCurrent()

glViewport(0, 0, 640, 480)
   ...

Suggestion : 2

 November 07, 2021     glsl, opengl, pyqt, python, qt     No comments   

File shader.vert

void main(void) {
   gl_Position = ftransform();
}

File shader.frag

void main(void) {
   gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

File test_shaders.py

from OpenGL.GL
import *
from OpenGL.GLU
import *
from PyQt4
import QtCore, QtGui
from PyQt4.QtOpenGL
import *

class ExampleQGLWidget(QGLWidget):

   def __init__(self, parent):
   QGLWidget.__init__(self, parent)
self.shaderProgram = QGLShaderProgram()
print self.shaderProgram.addShaderFromSourceFile(QGLShader.Vertex, "shader.vert")
print self.shaderProgram.addShaderFromSourceFile(QGLShader.Fragment, "shader.frag")
print self.shaderProgram.log()
self.shaderProgram.link()
glViewport(0, 0, 640, 480)

def paintGL(self):
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
self.shaderProgram.bind()

def resizeGL(self, w, h):
   glViewport(0, 0, w, h)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()

def initializeGL(self):
   glClearColor(0.0, 0.0, 0.0, 1.0)
glClearDepth(1.0)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()

class TestContainer(QtGui.QMainWindow):

   def __init__(self):
   QtGui.QMainWindow.__init__(self)
widget = ExampleQGLWidget(self)
self.setCentralWidget(widget)

if __name__ == '__main__':
   app = QtGui.QApplication(['Shader Example'])
window = TestContainer()
window.show()
app.exec_()

Suggestion : 3

QOpenGLShader and QOpenGLShaderProgram shelter the programmer from the details of compiling and linking vertex and fragment shaders.,The QOpenGLShaderProgram class allows OpenGL shader programs to be linked and used. More…,The QOpenGLShaderProgram class makes the process of writing portable shaders easier by prefixing all shader programs with the following lines on desktop OpenGL:,This function is intended to be a short-cut for quickly adding vertex and fragment shaders to a shader program without creating an instance of QOpenGLShader first.

QOpenGLShader shader(QOpenGLShader::Vertex);
shader.compileSourceCode(code);

QOpenGLShaderProgram program(context);
program.addShader( & shader);
program.link();

program.bind();
#define highp
#define mediump
#define lowp
program.addShaderFromSourceCode(QOpenGLShader::Vertex,
   "attribute highp vec4 vertex;\n"
   "uniform highp mat4 matrix;\n"
   "void main(void)\n"
   "{\n"
   "   gl_Position = matrix * vertex;\n"
   "}");
program.addShaderFromSourceCode(QOpenGLShader::Fragment,
   "uniform mediump vec4 color;\n"
   "void main(void)\n"
   "{\n"
   "   gl_FragColor = color;\n"
   "}");
program.link();
program.bind();

int vertexLocation = program.attributeLocation("vertex");
int matrixLocation = program.uniformLocation("matrix");
int colorLocation = program.uniformLocation("color");
static GLfloat
const triangleVertices[] = {
   60.0 f,
   10.0 f,
   0.0 f,
   110.0 f,
   110.0 f,
   0.0 f,
   10.0 f,
   110.0 f,
   0.0 f
};

QColor color(0, 255, 0, 255);

QMatrix4x4 pmvMatrix;
pmvMatrix.ortho(rect());

program.enableAttributeArray(vertexLocation);
program.setAttributeArray(vertexLocation, triangleVertices, 3);
program.setUniformValue(matrixLocation, pmvMatrix);
program.setUniformValue(colorLocation, color);

glDrawArrays(GL_TRIANGLES, 0, 3);

program.disableAttributeArray(vertexLocation);

Suggestion : 4

OpenGL.GL.shaders.compileProgram() , .compileProgram()

def _init_shaders(self):
   ""
"Initializes the shaders used to render the textures fullscreen quad."
""
vs = shaders.compileShader(_VERTEX_SHADER, GL.GL_VERTEX_SHADER)
fs = shaders.compileShader(_FRAGMENT_SHADER, GL.GL_FRAGMENT_SHADER)
self._shader = shaders.compileProgram(vs, fs)

stride = _FLOATS_PER_VERTEX * _SIZE_OF_FLOAT
var_position = GL.glGetAttribLocation(self._shader, _VAR_POSITION)
GL.glVertexAttribPointer(
   var_position, 2, GL.GL_FLOAT, GL.GL_FALSE, stride, None)
GL.glEnableVertexAttribArray(var_position)

var_uv = GL.glGetAttribLocation(self._shader, _VAR_UV)
uv_offset = ctypes.c_void_p(_FLOATS_PER_XY * _SIZE_OF_FLOAT)
GL.glVertexAttribPointer(
   var_uv, 2, GL.GL_FLOAT, GL.GL_FALSE, stride, uv_offset)
GL.glEnableVertexAttribArray(var_uv)

self._var_texture_sampler = GL.glGetUniformLocation(
   self._shader, _VAR_TEXTURE_SAMPLER)
def shader(self):
   if self.compiled is None:
   try:
   self.compiled = shaders.compileShader(self.code, self.shaderType)
except NullFunctionError:
   raise Exception("This OpenGL implementation does not support shader programs; many OpenGL features in pyqtgraph will not work.")
except RuntimeError as exc:
   # # Format compile errors a bit more nicely
if len(exc.args) == 3:
   err, code, typ = exc.args
if not err.startswith('Shader compile failure'):
   raise
code = code[0].decode('utf_8').split('\n')
err, c, msgs = err.partition(':')
err = err + '\n'
msgs = re.sub('b\'', '', msgs)
msgs = re.sub('\'$', '', msgs)
msgs = re.sub('\\\\n', '\n', msgs)
msgs = msgs.split('\n')
errNums = [()] * len(code)
for i, msg in enumerate(msgs):
   msg = msg.strip()
if msg == '':
   continue
m = re.match(r '(\d+\:)?\d+\((\d+)\)', msg)
if m is not None:
   line = int(m.groups()[1])
errNums[line - 1] = errNums[line - 1] + (str(i + 1), )
#code[line - 1] = '%d\t%s' % (i + 1, code[line - 1])
err = err + "%d %s\n" % (i + 1, msg)
errNums = [','.join(n) for n in errNums]
maxlen = max(map(len, errNums))
code = [errNums[i] + " " * (maxlen - len(errNums[i])) + line
   for i, line in enumerate(code)
]
err = err + '\n'.join(code)
raise Exception(err)
else:
   raise
return self.compiled
def _load_shaders(self, vertex_shader, fragment_shader):
   ""
"Load and compile shaders from strings.
""
"
shader = shaders.compileProgram(
   shaders.compileShader(vertex_shader, GL_VERTEX_SHADER),
   shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER)
)

return shader
def compileProgram(self, vertCode, fragCode):
   ""
"
A compileProgram version that ensures we don 't recompile unnecessarily.
""
"
program = self.__cache.get((vertCode, fragCode), None)
if program:
   return program
program = compileProgram(
   shaders.compileShader(vertCode, GL_VERTEX_SHADER),
   shaders.compileShader(fragCode, GL_FRAGMENT_SHADER),
   validate = canValidateShaders()
)
self.__cache[(vertCode, fragCode)] = program
return program
def _add_to_context(self):
   if self._program_id is not None:
   raise ValueError('Shader program already in context')
shader_ids = []

# Load vert shader
shader_ids.append(gl_shader_utils.compileShader(
   self._load(self.vertex_shader), GL_VERTEX_SHADER))
# Load frag shader
shader_ids.append(gl_shader_utils.compileShader(
   self._load(self.fragment_shader), GL_FRAGMENT_SHADER))
# Load geometry shader
if self.geometry_shader is not None:
   shader_ids.append(gl_shader_utils.compileShader(
      self._load(self.geometry_shader), GL_GEOMETRY_SHADER))

# Bind empty VAO PYOPENGL BUG
if self._vao_id is None:
   self._vao_id = glGenVertexArrays(1)
glBindVertexArray(self._vao_id)

# Compile program
self._program_id = gl_shader_utils.compileProgram( * shader_ids)

# Unbind empty VAO PYOPENGL BUG
glBindVertexArray(0)
def init_gl(self):
   vertex_shader = compileShader(
      shader_string(""
         "
         layout(location = 0) in vec3 in_Position; layout(location = 1) in vec3 in_Normal; layout(location = 2) in vec2 in_TexCoord;

         layout(location = 0) uniform mat4 projection = mat4(1); layout(location = 4) uniform mat4 model_view = mat4(1); layout(location = 8) uniform mat4 normal_matrix = mat4(1);

         out vec3 color; out vec2 fragTexCoord;

         void main() {
            gl_Position = projection * model_view * vec4(in_Position, 1.0);
            vec3 normal = normalize((normal_matrix * vec4(in_Normal, 0)).xyz);
            color = (normal + vec3(1, 1, 1)) * 0.5; // color by normal
            fragTexCoord = in_TexCoord;
            // color = vec3(in_TexCoord, 0.5); // color by texture coordinate
         }
         ""
         "),
         GL.GL_VERTEX_SHADER) fragment_shader = compileShader(
         shader_string(""
            "
            uniform sampler2D diffuse; in vec3 color; in vec2 fragTexCoord; out vec4 fragColor;

            void main() {
               // fragColor = vec4(color, 1.0);
               fragColor = texture(diffuse, fragTexCoord);
            }
            ""
            "),
            GL.GL_FRAGMENT_SHADER) self.shader = compileProgram(vertex_shader, fragment_shader) self._check_devices() GL.glEnable(GL.GL_DEPTH_TEST)