2

I'm trying to learn PyOpenGL, but I'm not sure how to use gluLookAt to move the camera. I've got an image displaying, but I think I might be missing something that allows me to use gluLookAt? Incoming wall o'text, I'm not sure where the problem might be. I've cut out the shaders and the texture code, because I don't think it's relevant, but if it is, I can post it.

import sys
import ctypes
import numpy

from OpenGL import GL, GLU
from OpenGL.GL import shaders
from OpenGL.arrays import vbo

import pygame
from numpy import array

class OpenGLSprite():
    def __init__(self,_sprite='',_vertexShader = None, _fragmentShader = None):
        if not isinstance(_sprite, pygame.Surface):
            self.sprite = pygame.image.load(_sprite)
        else: self.sprite = _sprite

        vertexData = numpy.array([
             # X    Y   Z   U,   V
            -1.0, -1.0, 0, 0.0, 0.0,
            -1.0,  1.0, 0, 0.0, 1.0,
             1.0,  1.0, 0, 1.0, 1.0,

             1.0,  1.0, 0, 1.0, 1.0,
             1.0, -1.0, 0, 1.0, 0.0,
            -1.0, -1.0, 0, 0.0, 0.0,

            ], dtype=numpy.float32)

        self.loadTexture()
        self.buildShaders(_vertexShader, _fragmentShader)

        self.VAO = GL.glGenVertexArrays(1)
        GL.glBindVertexArray(self.VAO)

        self.VBO = GL.glGenBuffers(1)
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.VBO)
        GL.glBufferData(GL.GL_ARRAY_BUFFER, vertexData.nbytes, vertexData,
            GL.GL_STATIC_DRAW)

        positionAttrib = GL.glGetAttribLocation(self.shaderProgram, 'position')
        coordsAttrib = GL.glGetAttribLocation(self.shaderProgram, 'texCoords')

        GL.glEnableVertexAttribArray(0)
        GL.glEnableVertexAttribArray(1)
        GL.glVertexAttribPointer(positionAttrib, 3, GL.GL_FLOAT, GL.GL_FALSE, 20,
            None)
        # the last parameter is a pointer
        GL.glVertexAttribPointer(coordsAttrib, 2, GL.GL_FLOAT, GL.GL_TRUE, 20,
            ctypes.c_void_p(12))

        # load texture and assign texture unit for shaders
        self.texUnitUniform = GL.glGetUniformLocation(self.shaderProgram, 'texUnit')

        # Finished
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0)
        GL.glBindVertexArray(0)

    def render(self):
        GL.glClearColor(0, 0, 0, 1)
        GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)

        # active shader program
        GL.glUseProgram(self.shaderProgram)

        try:
            # Activate texture
            GL.glActiveTexture(GL.GL_TEXTURE0)
            GL.glBindTexture(GL.GL_TEXTURE_2D, self.texture)
            GL.glUniform1i(self.texUnitUniform, 0)

            # Activate array
            GL.glBindVertexArray(self.VAO)

            # draw triangle
            GL.glDrawArrays(GL.GL_TRIANGLES, 0, 6)
        finally:
            GL.glBindVertexArray(0)
            GL.glUseProgram(0)


def main():
    pygame.init()
    screen = pygame.display.set_mode((640,480),pygame.OPENGL|pygame.DOUBLEBUF)
    GL.glClearColor(0.5, 0.5, 0.5, 1.0)

    camX = 0.0
    camZ = 3.0

    sprite = OpenGLSprite('logo-bluebg-square.png')

    status = 0

    while status == 0:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                status = 1
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    status = 1
                if event.key == pygame.K_LEFT:
                    camX -= 0.1
                if event.key == pygame.K_LEFT:
                    camX += 0.1

        GLU.gluLookAt(camX,0.0,camZ,
                      0.0,0.0,0.0,
                      0.0,1.0,0.0)

        sprite.render()

        pygame.display.flip()

    return 0

if __name__ == '__main__': 
    main()

The gluLookAt in the main game loop doesn't seem to do anything, no matter what parameters I modify. Changing camX with the keys isn't affecting anything, it just keeps looking at the surface straight on. From what I understand, the first three inputs to gluLookAt should be the location of the "Camera", correct? So if it's looking to the origin and the X position of the camera is moving, it should be rotating and moving the surface, right? Is there something special I have to do when setting up the object to allow it to work with gluLookAt? Do I have to do something after calling it to apply the transform to something? Does it need to be in the drawing code of the object, or the gameLoop?

Matthew Fournier
  • 1,077
  • 2
  • 17
  • 32
  • I haven't used pyopengl myself. However, as far as I know, gluLookAt operates on the matrix stack. Are your shaders accessing the top of the matrix stack (e.g., `gl_ModelViewMatrix` or `gl_ModelViewProjectionMatrix`)? Also, I don't see a `glViewport` or `gluPerspective` call anywhere. `gluLookAt` probably won't do what you want without calls to those somewhere in your code. Good luck! – cxw Oct 11 '16 at 20:33

1 Answers1

2

The GLU library is for use with the fixed-function pipeline. It doesn't work with modern OpenGL, when you're using vertex shaders (at least, not unless you're doing compatibility-profile stuff, but it looks like you're not doing that). Instead, you will create the equivalent matrix, and use it as part of one of your uniforms.

The GLM source code for the equivalent function is available on GitHub in glm/glm/gtc/matrix_transform.inl, in the function lookAtRH. Use this function to create your matrix, multiply it by any other components of your view matrix, and set it as a uniform in your vertex shader.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • It seems like every time I hit a snag, it's because of an example or tutorial doing Legacy OpenGL without telling me. Thanks, I'll try to figure out the GLM LookAt. How do I use GLM in Python? That was the issue I ran into before, which eventually led me to find GLULookAt – Matthew Fournier Oct 11 '16 at 20:51
  • You can't use GLM in Python, but GLM is MIT licensed and you can reimplement `gluLookAt()` in Python. – Dietrich Epp Oct 11 '16 at 20:58
  • So, I am supposed to use gluLookAt then? I'm confused again. – Matthew Fournier Oct 11 '16 at 21:13
  • The `gluLookAt()` function does two things: it creates a matrix and multiplies that matrix into the matrix stack. The matrix stack doesn't exist any more, so you just copy the code which creates the matrix. – Dietrich Epp Oct 11 '16 at 21:20
  • There is probably a Python library which implements this already, but I don't know which library does that. – Dietrich Epp Oct 11 '16 at 21:22