views:

365

answers:

4

I have been tasked with solving a problem that is outside of my domain of knowledge and I was hoping I could get some troubleshooting advice from someone more experienced with openGL (I have very little experience with openGL). We are working on a cross platform application that is implemented in a common lisp implementation called ccl. In this application we have a need to display some 3D objects that display text. On the mac, all of the text displays fine but on the PC instead of displaying the text it displays some other texture. At first I thought that maybe the wrong texture was just being referenced so I tried changing the texture number but none of the textures in the list appeared to be the text (or if it was the texture was distorted and did not look like text). I know this problem is very vague and I am not looking for someone to post a solution, but I was wondering if people could suggest places I might look to try and get a handle on this issue.

Here is the method that ends up creating the texture from a file (sorry the code is written in lisp using cocoa/cocotron) also when I added the print statements to print the pixels wide and pixels high both turned out to be powers of 2 (512):

(defun CREATE-IMAGE-FROM-FILE (Filename &key Verbose Forced-Depth (Flip-Vertical t)) "
in:  Filename string-or-pathname, &key Verbose boolean, Forced-Depth int, 
out: Pixels byte-vector,
   Width Height Forced-Depth int; Has-Alpha boolean.
   Create an image buffer from <Filename>
   - File must be 32 bit ARGB compatible, e.g., .png with mask or 24 bit RGB."
(print "CREATE IMAGE FROM FILE")
(print Filename)
(when Verbose (format t "CREATE-IMAGE-FROM-FILE: ~A~%" Filename))
(let* ((Image-Representation (#/retain (ns-image-rep-from-file (native-string       (namestring (translate-logical-pathname Filename)))))))
;; should massage data: GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV for best performance
;; http://developer.apple.com/documentation/graphicsimaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html
(when (%null-ptr-p Image-Representation)
  (format t "~%missing texture ~S" Filename)
  (return-from create-image-from-file))
;; do the OpenGL vertical image flip
(when Flip-Vertical
  (flip-vertical-buffer 
   (#/bitmapData Image-Representation) 
   (* (#/bytesPerRow Image-Representation) (#/pixelsHigh Image-Representation))
   (#/bytesPerRow Image-Representation)))
(print (#/pixelsWide Image-Representation))
(print (#/pixelsHigh Image-Representation))
(values 
 (#/bitmapData Image-Representation)
 (#/pixelsWide Image-Representation)
 (#/pixelsHigh Image-Representation)
 (#/bitsPerPixel Image-Representation)
 (#/hasAlpha Image-Representation)
 (#/bitmapFormat Image-Representation))))


(defmethod DISPLAY-VERTEX-ARRAYS ((Self string-shape))
  (glEnable gl_texture_2d)
  (cond
   ;; Color!
   ((color-vector Self)
    (glcolor3ubv (color-vector Self))
    (gltexenvi gl_texture_env gl_texture_env_mode gl_blend))
   ;; Black
   (t 
    (gltexenvi gl_texture_env gl_texture_env_mode gl_modulate)))
   (glbindtexture gl_texture_2d (texture (font Self)))
   (glInterleavedArrays GL_T2F_V3F (va-stride Self) (vertex-arrays Self))
   (glDrawArrays gl_quads 0 (va-elements-count Self)) 
   (gltexenvi gl_texture_env gl_texture_env_mode gl_modulate)
   (glDisable gl_texture_2d)
   ;; if color was use better reset to white? 
   (when (color-vector Self) (glColor3f 1.0 1.0 1.0)))

alt text

alt text

A: 

Here is my 2 cents.

I've experienced problems with textures with strange sizes. When the ARB_texture_non_power_of_two extension is supported, theorically the graphic system could manage texture with sizes not having a non power of two extents, but actually it doesn't with any combination.

I've found that on NVIDIA cards, on Windows OSes, 2D texture not having extents a multiple of 2 are not displayed correctly (say, 231x73), and with some other NVIDIA cards doesn't manage textures with extents not being multiple of 4 (maybe the driver, maybe the graphic card, still unknown issue).

So, my advice is to investigate about texture sizes.

Luca
Thank you very much for your suggestion but unfortunately that does not seem to be the problem. I added the code that actually creates the texture and when you look at the pixel width and height they are both 512.
Mike2012
+2  A: 

It's a shot in the dark, but fonts tend to get set up early because it's no fun being without text. So check that the first call to wglMakeCurrent precedes the glGenTextures used to create the name for the font texture.

More generally, whilst I've only ever used OpenGL from C++, I've had a certain amount of wierd behaviour that I've had to track down. So I suggest two things that I've found helpful when working with OpenGL fairly directly:

Firstly, insert calls to glGetError in as many places as possible. Putting this after every single OpenGL call -- except for a call to wglMakeCurrent to deactivate the current context, since glGetError always returns an error with no context -- is always good.

Something simple like assert(glGetError()==GL_NO_ERROR) is a reasonable start (or pick any othe method of breaking into the debugger that lets you carry on anyway to see what happens next) and if you check the docs for glGetError you can probably come up with something more comprehensive.

Secondly, on Windows at least, make sure that you are always operating with a valid current context. This is particularly important for the calls to glGenTextures that generate texture names.

assert(wglGetCurrentContext()) will do the trick here, ideally just before every block of OpenGL calls, except of course for whichever call to wglMakeCurrent sets the current context.

brone
A: 

Is the text drawn after the boxes are drawn?

It looks less to me like a problem with turning on the text texture, than with turning the box one off.

Kim Reece
A: 

Kim Reece is on the right track. One could say that the texture state for the boxes is leaking into the rendering of the words. The code you posted is not the source of the problem. You need find the code that is actually rendering the boxes and the words and make sure that the font texture is bound using glBindTexture before the word polys are drawn. Now, some of this depends on whether your app is using "raw" OpenGL or is using a library on top to construct a "scene graph" and abstract away these low-level details. Can you post more info on what you're using?

CCL is great! I used to use it almost exclusively.

Tim
Thank you very much for your advice Tim, and Kim Reece. I posted the code above that actually draws the text object. It is a method called display-vertex-arrays, which gets called from the draw method (the draw method basically pushes, does some scaling, calls display-vertex-arrays then pops). It seems that this method does in fact call glbindtexture before drawing the vertex array. I agree CCL is pretty sweet!
Mike2012
You might check that the value of (texture (font string-shape)) looks reasonable and is different from the texture of the boxes. Also, you might want to trace what happens to the return value of create-image-from-file; make sure that the image is made into a texture without errors, etc.
Tim