Open GL and Only One Texture Loads

I’m unable to load more than one texture in OpenGL.
Only the last one I load ever renders, all subsequent polygons with any texture just use the first texture.
To make it more frustrating, all polygons rendered without a texture after are invisible.

I thought it was happening when I called OpenGL.glBindTexture, but I don’t believe that now. I think it’s happening when I load the textures while I’m initializing the scene (OpenGL.glTexImage2d)

Anyone have any words of wisdom?
I know there are a lot of OpenGL gurus on this forum

Thanks in advance.

I think is the oglname, look at xojo3d tutorial.

That’s the tutorial I copied and it’s not working.
They have a more advanced set of classes that doesn’t exhibit the same issue, but it would take forever to rework it into my project.

I’ll dig in there more to see if I can fugure out what they changed in the loading.

I use that library and load hundres of textures, maybe the tutorial fail in some part, look at oglname (it’s a number) always is different for diferrent textures.

Here is what I can now confirm:
The OGLNames are created correctly and are distinct
I’m referencing them correctly before rendering to the polygons.

I can verify that the wrapped object I have in the Xojo project have distinct images via their memory block size.
I can’t really tell what is inside the OpenGL environment (black box).

When I load the images in a loop, regardless of the name used, the 1st (and only the 1st) texture will load and nothing else will render correctly. I’m guessing all polygons after are anticipating a texture that isn’t drawn on them, so they are invisible.

Is there any function I need to call after loading a texture into OpenGL (when generating the OGLName) or after I set it so that a buffer (or something) will clear?

I’ve done some searches online and found that I’m not alone with this problem, although nobody else posted a way to resolve it… Some of those forums are just full of people being trolls… how refreshing the Xojo community is!

Curious, but how did you go about checking the amount of memory that was available to textures?

The wrapper referenced in (tutorial online) loads the graphics into a bitmap, ready for OpenGL. So with a breakpoint I can evaluate the properties.

I checked and that tutorial I do not test it, I use the X3 library, do you ask to @Alwyn Bester ?

Make sure you’re creating a new object to hold the texture every time. A common error is to reuse the object within the loop and append it to an array. The result is that all the array elements point to the same object, so they all see just the last values that were processed.

I had a look at the Xojo3D samples and found it gave an exception error on 64-bit Windows, especially with aggressive compiling. 32-bit Windows and macOS 64-bit was unaffected. I have no idea is this is related to your issue.

Chris, I just thought of something else you could check. I recall that some of the older OpenGL drivers requires that your texture resolutions are in perfect squares (e.g. 32x32, 64x64, 128x128 etc), and when you load a texture with any arbitrary resolution (e.g. 120x36) it fails.

I only has this issue with much older OpenGL drivers though. What version of windows are you using?

Tim yes, it’s a different object every time.
David, on Windows the only issue I had was with the high dpi setting on. It was strange, shrunk the rendering. I’m sure there is a flag that is needed so that it’ll behave.

Alwyn, I did note this early too. Your tutorial had a caution about that. I went back and resized my images correctly, but still no joy.
Failing to load would be great. The impact is that it renders everything else invisibly.

This is a real stumper. Perhaps I can build a simple example that exhibits it and post.

This would be helpful.

A few parts to look at might be: 1) coding of RGB values. Sometimes the values are RGB, while other times it’s BGRA. This can prevent textures from appearing. 2) there seems to be an error in the direction of Xojo windings (clockwise and counter-clockwise) in the OpenGL plugin which will draw the textures ‘away’ from your viewpoint 3) doublecheck messageblock references. I have made this mistake a few times with pointers.

There are other possible areas where coding textures could be not drawn and an example would be helpful. I know it’s a pain to make, and it’s really helpful to those helping you. :slight_smile:

Edit: Allwyns plugin works well. The Xojo OpenGL control has these issues.

Is it possible to add a project or zip to the thread? Seems that would be easier than trying to copy the relevant bits here.
I’m positive this will be a one line fix when it’s done… Sigh.

again here’s the scenario spelled out a little more clear (maybe it will jog something…)

** If anyone helps me solve this and is going to XDC there will surely be consumable rewards for the help!!! (?)

Situation 1

  1. Add two polygons
  2. Render
  3. They show properly

Situation 2

  1. add two polygons
  2. set them to the same texture (and only load one texture)
  3. all is ok

Situation 3

  1. add two polygons
  2. load two textures
  3. Assign one texture to each polygon.
  4. The first loaded texture shows on both polygons

Situation 4

  1. Rerun 2 or 3 (above)
  2. add another non-textured polygon
  3. It won’t show at all… If I comment out the textured polygons the non-textured will appear again.

It’s both very odd and distressing. I’ve lost over a day toiling with this.

I have this in the open event of my OpenG3Surface

[code]X3_Initialize

Dim m As new X3Core.X3Model()

m.Vertex.Append new X3Core.X3Vector( -1, -1, 0 ) // 0
m.Vertex.Append new X3Core.X3Vector( -1,1,0) // 1
m.Vertex.Append new X3Core.X3Vector( 1, 1, 0) // 2

m.Vertex.Append new X3Core.X3Vector( 1, -1, 0 ) // 3

dim p as new X3Core.X3Polygon( 0, 0, 1)
p.VIndex.Append 0
p.VIndex.Append 2
p.VIndex.Append 1
p.UVMap.Append new X3Core.X3UVCoordinate(0,1)
p.UVMap.Append new X3Core.X3UVCoordinate(1,0)
p.UVMap.Append new X3Core.X3UVCoordinate(0,0)

dim t as new X3Core.X3Texture( imageb ) // this is the only texture that will show regardless of what texture is loaded after.
p.Texture = t

m.AppendPolygon p

dim p2 as new X3Core.X3Polygon( 0, 0, 1)
p2.VIndex.Append 0
p2.VIndex.Append 3
p2.VIndex.Append 2
p2.UVMap.Append new X3Core.X3UVCoordinate(0,1)
p2.UVMap.Append new X3Core.X3UVCoordinate(1,1)
p2.UVMap.Append new X3Core.X3UVCoordinate(1,0)

dim t2 as new X3Core.X3Texture( imagea )
p2.Texture = t2

m.AppendPolygon p2
model.Append m

setMyPerspective
Render
[/code]

Using the X thoughtful examples from www.xojo3d.com, the constructor of the texture wrapper is as follows.

[code]’ www.Xojo3D.com

Dim x, y, offset As Integer
Dim textCol As Color
Dim textMaskCol As Color
Dim alpha As Byte
dim m as picture

if texture.HasAlphaChannel then
m = texture.CopyMask
end if
’ convert pictures to raw formats

Width = texture.Width
Height = texture.Height

RGBABitmap = new MemoryBlock(Height * Width * 4) ’ create a MemoryBlock for the OpenGL RGBA format

’ loop through all the pixels of the picture

offset = 0

for y = 0 to Height - 1

for x = 0 to Width - 1

' read the values of the current pixel

textCol = texture.RGBSurface.Pixel(x,y) ' get the color of the current pixel
if m <> nil then
  textMaskCol = m.RGBSurface.Pixel(x, y) ' get the mask (alpha) color of the current pixel
end if

' calculate the OpenGL alpha values, using the mask values of the pixel

alpha = 255 - (textMaskCol.Red + textMaskCol.Green + textMaskCol.Blue) / 3

' store the color and alpha values into our OpenGL texture bitmap

RGBABitmap.Byte(offset) = textCol.Red
RGBABitmap.Byte(offset + 1) = textCol.Green
RGBABitmap.Byte(offset + 2) = textCol.Blue
RGBABitmap.Byte(offset + 3) = alpha

offset = offset + 4 ' move to the next pixel in our OpenGL texture bitmap

next x

next y

’ load texture into OpenGL
OGLName = X3_LoadRGBATexture(RGBABitmap, Width, Height)[/code]

This is how the OGLName is created (many asked if this was the source of the problem)
I did have some issues with masks due to the old way vs new way Xojo implements, but the sample I have doesn’t use any masks.

Public Function X3_LoadRGBATexture(RGBABitmap As MemoryBlock, width As Integer, height As Integer) as Integer
  ' www.Xojo3D.com
  
  // IMPORTANT: Image dimensions must be in power of 2 (e.g. 8x8, 16x16, 32x32, 64x64, ...)
  
  Dim idMB As MemoryBlock
  Dim oglName As Integer
  
  ' ask OpenGL for an ID that we can use for our texture
  
  idMB = new MemoryBlock(4) ' create a memory block into which OpenGL will store the ID value
  OpenGL.glGenTextures(1, idMB) ' get the ID from OpenGL
  oglName = idMB.Long(0) ' store the value returned by OpenGL in an integer
  
  ' specify to OpenGL how this texture should be rendered
  
  OpenGL.glBindTexture(OpenGL.GL_TEXTURE_2D, OGLName) ' select the texture id that OpenGL allocated for our texture
  
  OpenGL.glTexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, OpenGL.GL_LINEAR) // set up settings
  OpenGL.glTexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, OpenGL.GL_LINEAR) // set up some more settings
  
  ' now we load the image bitmap
  
  OpenGL.glTexImage2d(OpenGL.GL_TEXTURE_2D, 0, 4, width, height , 0, OpenGL.GL_RGBA, OpenGL.GL_UNSIGNED_BYTE, RGBABitmap)
  
  return oglName
  
End Function

Finally the Render method and RenderModel that is called from it.

[code]Function Render() Handles Render as Boolean
OpenGL.glClearColor(1,1,1,1)
OpenGL.glClear(OpenGL.GL_COLOR_BUFFER_BIT + OpenGL.GL_DEPTH_BUFFER_BIT)
OpenGL.glPushMatrix
OpenGL.glTranslatef 0, -0.05, zoom

dim stepSize as double
dim i, j as integer

if model.Ubound = -1 then return true

X3_SetRotation model(0).Rotation

for i = 0 to model.Ubound
X3_RenderModel Model(i)
next

OpenGL.glPopMatrix ’ restore matrix

End Function
[/code]

Public Sub X3_RenderModel(model As X3Core.X3Model)
  ' www.Xojo3D.com
  
  Dim i, j As Integer
  Dim poly As X3Core.X3Polygon
  dim col as X3Core.X3Color
  
  if model = nil then return
  
  'X3_SetRotation model.Rotation
  
  if model.visible = false then return
  
  if model.Polygon.Ubound > -1 then
    OpenGL.glBegin OpenGL.GL_TRIANGLES ' start drawing triangle polygons
    openGL.glPolygonMode openGL.GL_FRONT, openGL.GL_FILL
  end if
  ' draw model polygons
  
  for i = 0 to model.Polygon.Ubound ' loop through all the polygons
    
    
    
    poly = model.Polygon(i) ' get the next polygon
    
    ' set the normal of the polygon
    
    OpenGL.glNormal3d poly.Normal.X, poly.Normal.Y, poly.Normal.Z
    
    ' is this polygon mapped with a texture, and if so, is the UV coordinates configured?
    
    'if (poly.TIndex >-1 ) and (poly.UVMap.Ubound >= poly.VIndex.Ubound) then
    if poly.Texture <> nil then
      
      ' yes, a texture is used
      
      OpenGL.glColor4d(1, 1, 1, 1) ' reset color to pure white
      
      OpenGL.glBindTexture(OpenGL.GL_TEXTURE_2D, poly.Texture.OGLName) ' bind to the polygon's texture
      
      ' loop through all the vertexes of the polygon
      
      for j = 0 to poly.VIndex.Ubound
        
        OpenGL.glTexCoord2d poly.UVMap(j).U, poly.UVMap(j).V ' set the texture UV-coordinates for next vertex
        OpenGL.glVertex3d model.Vertex(poly.vindex(j)).X, model.vertex(poly.vindex(j)).Y,model.vertex( poly.vindex(j)).Z ' add the vertex to the OpenGL vertex list
        
      next j
      
      OpenGL.glBindTexture(OpenGL.GL_TEXTURE_2D, 0) ' unbind from the polygon's texture
      
    else
      
      ' set the color of the polygon
      
      if poly.FillColor <> nil then ' is the color object set
        ' yes, so set the color
        OpenGL.glColor4d(poly.FillColor.Red, poly.FillColor.Green, poly.FillColor.Blue, poly.FillColor.Alpha)
      end if
      
      ' loop through all the vertexes of the polygon
      
      for j = 0 to poly.VIndex.Ubound 
        col = model.Vertex( poly.VIndex(j)).pointColor
        if col <> nil then
          openGL.glColor4D( col.Red, col.Green, col.Blue, 1)
        end if
        OpenGL.glVertex3d model.Vertex(poly.vindex(j)).X, model.vertex(poly.vindex(j)).Y,model.vertex( poly.vindex(j)).Z ' add the vertex to the OpenGL vertex list
        
      next j
      
    end if
    
  next i 
  
  OpenGL.glEnd ' end drawing of polygons
  
  
  
  
End Sub

(Yes, providing a zipped link to the entire project would be helpful).

I think your problem is that you are making illegal calls between glBegin and glEnd, specifically you are trying to change the bound texture. See https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glBegin.xml which lists the legal commands.

I think the solution here would be to modify X3_RenderModel so that the glEnd call is at the end of the loop that draws the polys. In other words, after the “next j” statement rather than after the “next i” statement.

Michael,

Tried it before, and again tonight. That didn’t do it.
Yet, I’m positive it’s something along this lines. So frustrating.

Thanks for taking the time to read, review and respond.

Michale,

To make this even worse…

If I use the following code only the second texture is ever available.
ImageA is a blue PNG
ImageB is a red PNG

if I set both polygons to texture to the first loaded, nothing shows.
If I set them both to the second loaded texture, they both show the correct texture.
If I set one to the first and the second to the second, they both load the second.
If I set one to the first, and remove the texture and UV coordinates of the second, the second still loads the texture. It’s too frustrating!

[code]Sub Open() Handles Open
X3_Initialize

Dim m As new X3Core.X3Model()
dim t1 as new X3Core.X3Texture( imagea )
dim t2 as new X3Core.X3Texture( imageb )

m.Vertex.Append new X3Core.X3Vector( -1, -1, 0 ) // 0
m.Vertex.Append new X3Core.X3Vector( -1,1,0) // 1
m.Vertex.Append new X3Core.X3Vector( 1, 1, 0) // 2

m.Vertex.Append new X3Core.X3Vector( 1, -1, 0 ) // 3

dim p as new X3Core.X3Polygon( 0, 0, 1)

p.VIndex.Append 0
p.VIndex.Append 2
p.VIndex.Append 1
p.UVMap.Append new X3Core.X3UVCoordinate(0,1)
p.UVMap.Append new X3Core.X3UVCoordinate(1,0)
p.UVMap.Append new X3Core.X3UVCoordinate(0,0)

p.Texture = t2

m.AppendPolygon p

dim p2 as new X3Core.X3Polygon( 0, 0, 1)
p2.VIndex.Append 0
p2.VIndex.Append 3
p2.VIndex.Append 2
p2.UVMap.Append new X3Core.X3UVCoordinate(0,1)
p2.UVMap.Append new X3Core.X3UVCoordinate(1,1)
p2.UVMap.Append new X3Core.X3UVCoordinate(1,0)

p2.Texture = t1

m.AppendPolygon p2
model.Append m

setMyPerspective
Render

End Sub[/code]

Hi Chris, I’m pretty sure my answer is the correct one but without a full demo project it’s nearly impossible to say what may be going on…

Michael, I have zero doubt that you are right! I’m just going to try to dig in and figure it out, hopefully without too much refactoring.
I may invest the time needed to use the latest version of their X3Core classes.

Michael, you were right on the money.

Thanks!