0

I have a problem with passing data to vertex shader. When I try to pass data to vertex shader it's simply not passed at all.

My PC spec needed:

OS: Windows 8 64-bit

Python: 2.7.6 64-bit

PyOpenGL: 3.0.2 64-bit

NumPy: 1.8.0 64-bit unofficial (but not the source of the problem)

Graphics Card: Radeon HD 8330

Code:

import sys
import os
import numpy
from math import sin, cos
from glfw import *
from OpenGL.GL import *

class App:
    def __init__(self):
        if not glfwInit():
            sys.exit()

        self.window = glfwCreateWindow(640, 480, "App", None, None)
        if not self.window:
            glfwTerminate()
            sys.exit()
        glfwMakeContextCurrent(self.window)

        glfwSetKeyCallback(self.window, self.onKey)

        vertexShaderSource = """
            #version 430 core

            layout (location = 0) in vec4 offset;

            void main(void) {
                const vec4 vertices[] = vec4[](
                    vec4( 0.25, -0.25, 0.5, 1.0),
                    vec4(-0.25, -0.25, 0.5, 1.0),
                    vec4( 0.25,  0.25, 0.5, 1.0));

                gl_Position = vertices[gl_VertexID] + offset;
            }
        """
        vertexShader = glCreateShader(GL_VERTEX_SHADER)
        glShaderSource(vertexShader, vertexShaderSource)
        glCompileShader(vertexShader)

        fragmentShaderSource = """
            #version 430 core

            out vec4 color;

            void main(void) {
                color = vec4(0.0, 0.8, 1.0, 1.0);
            }
        """
        fragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
        glShaderSource(fragmentShader, fragmentShaderSource)
        glCompileShader(fragmentShader)

        self.program = glCreateProgram()
        glAttachShader(self.program, vertexShader)
        glAttachShader(self.program, fragmentShader)
        glLinkProgram(self.program)

        glDeleteShader(vertexShader)
        glDeleteShader(fragmentShader)
        self.vertexArray = glGenVertexArrays(1)
        glBindVertexArray(self.vertexArray)

    def onKey(self, window, key, scancode, action, mods):
        if key == GLFW_KEY_ESCAPE and action == GLFW_PRESS:
            glfwSetWindowShouldClose(window, 1)

    def run(self):
        # render part
        while not glfwWindowShouldClose(self.window):
            self.render(glfwGetTime())
            glfwSwapBuffers(self.window)
            glfwPollEvents()

        # cleanup actions
        glDeleteVertexArrays(1, (self.vertexArray,))
        glDeleteProgram(self.program)
        glfwTerminate()

    def render(self, currentTime):
        color = 0.0, 0.25, 0.0, 1.0
        glClearBufferfv(GL_COLOR, 0, color)
        glUseProgram(self.program)
        offset = numpy.array((sin(currentTime) * 0.5, cos(currentTime) * 0.6, 0.0, 0.0), dtype = numpy.float32)
        #glVertexAttrib4fv(0, offset)
        glDrawArrays(GL_TRIANGLES, 0, 3)

if __name__ == '__main__':
    app = App()
    app.run()

I tried to use Python syntax for array (list and tuple) definition, but it didn't help, so I changed this sample to use NumPy Package (So NumPy cannot be source of the problem). After debugging in a lot of tools (I have AMD platform so I tried all AMD debugging software for GPU debugging + all software mentioned on https://www.opengl.org/wiki/Debugging_Tools) I have no result. I cannot determine source f the problem. Debugging software cannot show data passed to vertex shader. But from my two days experiments I got that data isn't passed to shader at all. So as I understand problem lies in glVertexAttrib4fv function. I tried to debug this function in PyCharm (it gets error when I try to use Python syntax for array definition: e.g. I get (array,) instead of array, but I don't get error when I use NumPy). I don't know what is going on, so I ask this question, if you need some more info, please ask.

P.S. This code was changed in order to not include a lot of source code files, so there's could be some errors that actually don't exist.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Sergey
  • 21
  • 1
  • You know you can do this too, right? `glVertexAttrib4f (0, sin (currentTime) * 0.5, cos (currentTime) * 0.6, 0.0, 0.0)` – Andon M. Coleman Jan 23 '14 at 22:14
  • Sorry, but this gives "TypeError: this function takes 2 arguments (5 given)" – Sergey Jan 23 '14 at 22:32
  • I'm sorry once again but line with glVertexAttrib4f function call is not commented actually, I simply cannot edit it now for some reason – Sergey Jan 23 '14 at 22:37
  • That is impossible. `glVertexAttrib4f ()` takes 5 parameters. I think you are confusing it with `4f` **`v`**. They are two different functions, and the reason I suggested it was to rule out any possible issues with your array. – Andon M. Coleman Jan 23 '14 at 22:38
  • Well, you may be confused by pyopengl syntax, it makes OpenGL function prototypes more pythonic, so glVertexAttrib4fv takes two arguments: argument position and it's value. See http://pyopengl.sourceforge.net/documentation/manual-3.0/glVertexAttrib.xhtml – Sergey Jan 23 '14 at 22:43
  • Thanks, I'll try to debug this version of glVertexAttrib also, but I was using glVertexAttrib4f **v** . This code was directly translated to Python from the OpenGL SuperBible book. There's some problem with data passing between pyopengl and shader. – Sergey Jan 23 '14 at 22:56
  • I tried to use glVertexAttrib4f but it gives the same result. I have no error or problem when using the AMD CodeXL debugging software. Maybe there's some stupid mistake but I don't see it. – Sergey Jan 23 '14 at 23:02
  • I'm not seeing any code to create the vertex attrib array for the offsets. glGenVertexArray doesn't create actual vertex data, it's a top level object that wraps a bunch of attribute arrays. At minimum you need to bind the vertex array, bind a buffer to GL_ARRAY_BUFFER, and call glVertexAttribPointer(0, ... – Hugh Fisher Jan 23 '14 at 23:06
  • You do not need a vertex attrib pointer in this case, the vertex positions are hard coded into the shader and `gl_VertexID` (which `glDrawArrays (...)` implicitly generates and increments for each vertex) is used to index those positions. `glVertexAttrib4fv (0, ...)` in this case tells GL to use a constant value every time it reads an attribute from generic attribute index **0**. – Andon M. Coleman Jan 23 '14 at 23:11
  • Thanks Andon, as I understand glVertexAttrib is a little bit different way of passing data to shader (http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml), but your and Hughs' comments gave me a clue that this issue could be related with glError function call after each OpenGL operation call. – Sergey Jan 23 '14 at 23:21
  • @Sergey: That was actually in response to Hugh Fisher's comment. Though I remember from a similar question on Stack Overflow recently that one individual was having trouble doing almost exactly the same thing using index **0** on his drivers. You might try changing this code to use index **1** instead. This would mean `layout (location = 1) in vec4 offset;` in your shader and `glVertexAttrib4fv (1, ...)` in your Python code. – Andon M. Coleman Jan 23 '14 at 23:27
  • 1
    Thanks @AndonM.Coleman, it finally works, but I still don't get real source of the problem. Could you provide me with a link to the Stack Overflow question mentioned by you? – Sergey Jan 23 '14 at 23:35
  • [This question](http://stackoverflow.com/questions/21080239/passing-attributes-to-opengl-vertex-shader-acts-strangely/) is very similar, in the comments section the author explains that using **0** is unreliable, but **1**-**15** works. – Andon M. Coleman Jan 23 '14 at 23:42
  • Thanks for help @AndonM.Coleman. I've spent a lot of time trying to solve this problem. – Sergey Jan 23 '14 at 23:45

0 Answers0