0

After a fairly long Google Session I have enough from it!

I had a python/opengl application with some simple Quad's where I used gluLookAt to move around on the scene. Then I needed just 1 Texture on one of those Quad's, so I obviously use a shader progam for this single Quad now.

Now when I use gluLookAt, the Quad with the Texture doesn't move, what I also can understand.

Now is there any way to somehow get the gluLookAt function to working with the shader program, get the Current Matrix Stack so I can feed the shader programm with it or do I have to rewrite the hole application and reinvent the glulookup function like he did(either in the shader or on the CPU)?

EDIT1: I use:

EDIT2 (My Solution):

Since I opened this thread, some things have changed but with the guideance of you I managed to get a modern & stable solution.

There are 3 Main components which I have to draw. A static Field, some Lines (for better visualisation) and some Movable Quads.

The Field is now written once to a VBO in an Array. (major improvement compared to single drawing commands)

The moveable squares and lines work on the same principle, but they are dynamic and must be reuploaded with each frame.

Foreach type of object I have a vertex + fragment shader program. I'am aware that I could use just one big one but that's not like it's supposed to be.

Each Matrix (Model,View,Projection) Is assigned to a uniform which then are multiplied with the Vertices from the VBO in the vertex shader.

Field Vertex Shader (Example):

#version 330

uniform mat4 uniform_Model;
uniform mat4 uniform_View;
uniform mat4 uniform_Projection;

in vec3 Quad_Color_Attrib;
in vec3 Quad_Size_Attrib;

out vec3 frag_ColorId;

void main()
{
    // Pass the tex coord straight through to the fragment shader
    frag_ColorId = Quad_Color_Attrib;

    // Remember : inverted !
    gl_Position = uniform_Projection * uniform_View * uniform_Model * vec4(Quad_Size_Attrib,1);
}

What I asked for wasn't the right way to do it. (Combining old and new OpenGL) Unfortunatly I can't share the hole code as it is but I here you can find all opengl key codes:

Vertex/Fragment Shader Program Loader:

Link to a gist

Initialize Vertex/Fragment Shader (in this case for the field)

def init_field(self, p_VertexShaderPath, p_FragmentShaderPath, p_FieldList, p_FieldCount):
    # ############### Field Shader ###############

    # Shader Program
    self.m_FieldShader = LoadShaders(p_VertexShaderPath, p_FragmentShaderPath)
    glUseProgram(self.m_FieldShader)

    # VAO
    self.m_FieldVAO = glGenVertexArrays(1)
    glBindVertexArray(self.m_FieldVAO)

    # Field Definition        
    self.m_FieldCount = p_FieldCount
    t_Vertices = []

    for t_FieldNr in p_FieldList:
        x = p_FieldList[t_FieldNr].m_XPos
        y = p_FieldList[t_FieldNr].m_YPos
        cr = p_FieldList[t_FieldNr].m_Color[0]/255
        cg = p_FieldList[t_FieldNr].m_Color[1]/255
        cb = p_FieldList[t_FieldNr].m_Color[2]/255

        t_Vertices.extend([
             x - 0.5,  y + 0.5, 0.0,  cr, cg, cb,   #  0----1
             x + 0.5,  y + 0.5, 0.0,  cr, cg, cb,   #  |    |
             x + 0.5,  y - 0.5, 0.0,  cr, cg, cb,   #  |    |
             x - 0.5,  y - 0.5, 0.0,  0, 0, 0    #  3----2
        ])

    t_FieldVerticesBuffer = numpy.array(t_Vertices, dtype = numpy.float32)

    # VBO
    self.m_FieldVBO = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, self.m_FieldVBO)
    glBufferData(GL_ARRAY_BUFFER, t_FieldVerticesBuffer.nbytes, t_FieldVerticesBuffer, GL_STATIC_DRAW)

    # VBO Size Attrib
    self.m_FieldVerticesAttrib = glGetAttribLocation(self.m_FieldShader, "Quad_Size_Attrib")
    glEnableVertexAttribArray(self.m_FieldVerticesAttrib)
    glVertexAttribPointer(self.m_FieldVerticesAttrib,
                          3, 
                          GL_FLOAT, 
                          GL_FALSE, 
                          ctypes.sizeof(6*GLfloat), 
                          ctypes.c_void_p(0))

    # VBO Color Attrib                      
    self.m_FieldColorAttrib = glGetAttribLocation(self.m_FieldShader, "Quad_Color_Attrib")
    glEnableVertexAttribArray(self.m_FieldColorAttrib)
    glVertexAttribPointer(self.m_FieldColorAttrib,
                          3, 
                          GL_FLOAT, 
                          GL_FALSE, 
                          ctypes.sizeof(6*GLfloat), 
                          ctypes.c_void_p(12))

    # Uniform Locations
    self.m_Field_ModelMat_Uniform = glGetUniformLocation(self.m_FieldShader, 'uniform_Model')
    self.m_Field_ViewMat_Uniform = glGetUniformLocation(self.m_FieldShader, 'uniform_View')
    self.m_Field_ProjectionMat_Uniform = glGetUniformLocation(self.m_FieldShader, 'uniform_Projection')

    # Detach Shader & VAO
    glBindVertexArray(0)  # unbind the VAO
    glUseProgram(0)  # Disable shader

Screen Draw Cycle

This now is just psydo code:

OpenGLEnv.Clear()
OpenGLEnv.SetCamera()
OpenGLEnv.DrawField()
OpenGLEnv.FlipBuffer()

So SetCamera set's the ViewMat and ProjectionMat.

def SetCamera(self, camera, zoom_distance):
    self.m_ViewMat = lookAt(glm.vec3(-camera[0], -camera[1], zoom_distance),  # Camera is at (x,x,x), in World Space
                            glm.vec3(-camera[0], -camera[1], -100),  # and looks at the origin
                            glm.vec3(0, 1, 0)) #  Head is up (set to 0,-1,0 to look upside-down)
    self.m_ProjectionMat = perspective(45, self.m_AspectRatio, 1, 1000.0)

Draw Field Routine

With this Function I will draw the Vertices from the VBO.

def DrawField(self):
    glUseProgram(self.m_FieldShader)       # Use shader

    self.m_ModelMat = glm.mat4(1)  # Reset ModelMat
    # ############################
    # 1. Scale          self.ModelMat = scale(self.ModelMat,glm.vec3(10,10,10))
    # 2. Rotation       self.ModelMat = rotate(self.ModelMat, self.test, glm.vec3(0,1,0))
    # 3. Translate      self.ModelMat = translate(self.ModelMat,glm.vec3(0,0,0))
    ####################################

    glUniformMatrix4fv(self.m_Field_ModelMat_Uniform, 1, GL_FALSE, numpy.squeeze(numpy.asarray(self.m_ModelMat.value)))
    glUniformMatrix4fv(self.m_Field_ViewMat_Uniform, 1, GL_FALSE, numpy.squeeze(numpy.asarray(self.m_ViewMat.value)))
    glUniformMatrix4fv(self.m_Field_ProjectionMat_Uniform, 1, GL_FALSE, numpy.squeeze(numpy.asarray(self.m_ProjectionMat.value)))

    glBindVertexArray(self.m_FieldVAO)
    glBindBuffer(GL_ARRAY_BUFFER, self.m_FieldVBO)

    # Draw Field
    glDrawArrays(GL_QUADS, 0, 4*self.m_FieldCount)

    # Disable shader and unbind VAO
    glBindVertexArray(0)
    glUseProgram(0)

Used Librarys:

noscript
  • 77
  • 1
  • 12
  • 4
    I suggest using a math library instead of trying to fiddle around with the matrix stack. [glm](https://glm.g-truc.net/0.9.8/index.html) might be a good choice and also provides a lookat function. For the rest of your question: It depends on which version and profile you use. – BDL Oct 12 '17 at 12:46
  • Sorry for not mentioning it, I work with Python ^^ Okay you would go with a manual calculation of the Matrices... Thanks for your Advice. – noscript Oct 12 '17 at 12:57
  • 1
    There is python version of glm also . Please see following link https://github.com/mackst/glm. It is not as full functional as glm but has functions you need. – Paritosh Kulkarni Oct 12 '17 at 13:17
  • can you show us the code where you use your glulookAt, tell us what do you mean by "I used gluLookAt to move around on the scene" and finally how do you set the vertex of your quad to the vertex shader with th shader code also – Paltoquet Oct 12 '17 at 13:48
  • It's roughly like [this](https://gist.github.com/iwaynee/9a4a3352b8779d9261c58c83f66ed341) I'm sorry I can't show all the 500 Lines of the OpenGL part. – noscript Oct 12 '17 at 14:08
  • how do you set "uniform vec3 Position;" something close to glUniform3fv(self.FieldPositionUniform, 1 , FieldPos) – Paltoquet Oct 12 '17 at 15:07
  • 1
    Side note: If you must use `gluLookAt` and friends, I would consider using GLSL 120 + OpenGL 2.1 instead and try to stick to as much of the "modern subset" of it as you can (i.e. using VBOs at least). If you use GLSL 120, then you can use predefined variables like `gl_ModelViewMatrix` and `gl_ProjectionMatrix` in your shader instead to access the "fixed function" matrix function stacks. – CodeSurgeon Oct 12 '17 at 23:39
  • @CodeSurgeon I knew it exists! Thanks! 'gl_ModelViewMatrix' and 'gl_ProjectionMatrix' i was looking for. It's so damn confusing with all those diffrent versions. I'd whish I could just use the latest version where I don't have to use certain things, but It isn't possible because python -.- – noscript Oct 13 '17 at 05:14
  • 2
    That being said, I am using python as well and it most certainly **isn't** impossible per se to create your own uniform matrices to pass into your shaders, just more frustrating. While you "can" pass in raw numpy matrices to the `glUniform*` commands, you then lose out on these convenience functions. I personally ended up writing my own matrix math classes in cython, but if you need a pure python solution, I would check out `pyrr` or `pyeuclid` for python 3d math libraries. – CodeSurgeon Oct 13 '17 at 05:22
  • @noscript I edited my answer. – Luatic Oct 13 '17 at 16:12

1 Answers1

1

You may decide :

  1. You may use OpenGL 2, what makes things much easier and means no shader programming but less efficiency.

  2. If you have to draw at least 1000 triangles or want to add bumpmapping or other special effects, you should maybe consider a shader. That means :

  3. Do not use Python & Pyopengl if you are aiming at high efficiency(own experience)

    • Id suggest you Java and jogl(My configuration currently). Then I could provide you my camera class.
  4. I will maybe also port my camera class to Python, but it depends on the jogl Matrix4 class and so on, but is easy if pyopengl also offers this math helper classes(Matrix4, Quaternion, ...)

EDIT :

Vertex Shader :

#version 330

uniform mat4 uniform_Transformation;
uniform mat4 uniform_Modelview;
uniform mat4 uniform_Projection;

in vec4 attribute_Position;
in vec4 texcoords;

out vec4 texcoords_pass;

void main(void) 
{ 
  texcoords_pass=texcoords;
  vec4 transformedPoint=attribute_Position*uniform_Transformation;
  vec4 toCamera=transformedPoint*uniform_Modelview;
  gl_Position = vec4(toCamera*uniform_Projection);
}

Fragment Shader :

#version 330

uniform sampler2D tex;

in vec2 texcoords_pass;

out vec4 mgl_FragColor;

void main (void)
{ 
  vec4 texture_color =  texture(tex,texcoords_pass);
  if (texture_color.w == 0) {
      discard;
  }
  mgl_FragColor=vec4(texture_color.x,texture_color.y,texture_color.z,1.0f);
}

About the matrices :

  • uniform_Transformation is the Transformation matrix. It is used to rotate, scale, flip, mirror and move your models, in your case quads.

  • uniform_Modelview is the View matrix. It's basically the camera. It defines how the camera is rotated and where it is located.

  • uniform_Projection is the Projection matrix. It's about the perspective projection. Read more about it here : http://www.songho.ca/opengl/gl_projectionmatrix.html

Hope it helps !

Luatic
  • 8,513
  • 2
  • 13
  • 34
  • 1
    "OpenGL 2 ... means no shaders" OpenGL 2.0 & 2.1 both had shaders. – genpfault Oct 12 '17 at 20:08
  • I have to draw about 800 to 1000 Quads with this solution. In fact it's moreless a 2D environment but I must be able to move around, zoom and so on. There's a much bigger script behind it and this part is just the Graphical Interface part, so changing is pain ^^ If I'd knew this from the beginning It would be in C++. I think you all know this thing with changing goals... It doesn't look promising after a quick google that pyopengl will provide this but maybe some other lib's. Now I have to decide which way I'll take. – noscript Oct 13 '17 at 05:30
  • @genpfault Yes, I know, but for GL 2, you have default shaders, you mustn't do them yourself. – Luatic Oct 13 '17 at 15:59
  • @noscript : Maybe you won't need your ''script behind'' anymore, because model, transformation and projection matrix are quite easy to understand, and allow you to apply transformations very easily. – Luatic Oct 26 '17 at 10:02
  • Sorry for not answering here. I'm actually working on it and very close to the end. I load the verticies to a VBO. I have vertex & fragment shaders for diffrent objects now. This is the important line of my solution atm. `gl_Position = uniform_Projection * uniform_View * uniform_Model * vec4(Puck_Size_Attrib,1);` I changed my solution from taking a picture as background to some independent "quads" or Pixel. More on this later. – noscript Oct 26 '17 at 11:24
  • @noscript Okay. – Luatic Oct 27 '17 at 18:14
  • @user7185318 look at the first post. – noscript Nov 09 '17 at 11:56