Search code examples
opengllispcommon-lisptexturessdl

Unable to get textures to work in OpenGL in Common Lisp


I am building a simple Solar system model and trying to set textures on some spheres.

The geometry is properly generated, and I tried a couple different ways to generate the texture coordinates. At present I am relying on glu:quadric-texture for generating the coordinates when glu:sphere is called.

However, the textures never appear - objects are rendered in flat colors.

I went through several OpenGL guides and I do not think I am missing a step, but who knows.

Here is what is roughly happening:

  • call gl:enable :texture-2d to turn on textures
  • load images using cl-jpeg
  • call gl:bind-texture
  • copy data from image using gl:tex-image-2d
  • generate texture ids with gl:gen-textures. Also tried generating ids one by one instead of all at once, which had no effect.
  • during drawing create new quadric, enable texture coordinates generation and bind the texture before generating the quadric points:
    (let ((q (glu:new-quadric)))
      (if (planet-state-texture-id ps)
          (progn (gl:enable :texture-gen-s)
                 (gl:enable :texture-gen-t)
                 (glu:quadric-texture q :true)
                 (gl:bind-texture :texture-2d planet-texture-id)))
        (glu:quadric-texture q :false))
      (glu:sphere q
                  planet-diameter
                  *sphere-resolution*
                  *sphere-resolution*)

I also tried a more manual method of texture coordinates generation, which had no effect.

Out of ideas here…

When the program runs, I can see the textures are loaded and texture ids are reserved, it prints

loading texture from textures/2k_neptune.jpg with id 1919249769
Loaded data. Image dimensions: 1024x2048

Solution

  • I don't know if you've discovered a solution to your problem, but after creating a test image, and modifying some of your code, I was able to get the texture to be applied to the sphere.

    The problem comes into play with the fact that you are attempting to upload textures to the GPU before you've enabled them. (gl:enable :texture-2d) has to be called before you start handling texture/image data. I'd recommend putting the let* block with the planets-init that is in the main function after 'setup-gl', and also moving the 'format' function with the planets data to work correctly without an error coming up.
    My recommendation is something like:

    (let ((camera ...
       ...
      (setup-gl ...)
      (let* ((planets...
        ...
        (format ... planet-state)
    

    In your draw-planet function, you'll want to add (gl:bind-texture :texture-2d 0) at the end of it so that the texture isn't used for another object, like the orbital path.
    As is, the (gl:color 1.0 ...) before the (gl:quadratic-texture ...) will modify the color of the rendered object, so it may not look like what you're expecting it to look like.

    Edit: I should've clarified this, but as your code stands it goes

    initialize-planets > make-textures > enable-textures > render
    

    When it should be

    enable-textures > init-planets > make-textures > render
    

    You're correct about not missing a step, the steps in your code are just misordered.