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.
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!
@Chris H Only the last one I load ever renders
@Chris H When I load the images in a loop
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.
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.
@Chris H 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. :)
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!!! (ツ)
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
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
Using the X thoughtful examples from www.xojo3d.com , the constructor of the texture wrapper is as follows.
' 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)
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.
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
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.
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!
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
I had the same problem. I'm new to OpenGL and started the X3 Tutorials on www.xojo3d.com. As I always do, I made small changes to the supplied examples to see if I understood it all and these changes gave the expected results.
When I came to chapter 11 - Texture mapping - I experienced the same weird behavior as Chris: only one Texture seemed to load, impossible to see two or more different ones.
I finally gave up, and downloaded the final X3Core Library from this site. It has a few small bugs, but not difficult to repair. What's more important: it handles more than one Texture at a time!
So my advice to Chris is to look into the source of this Library and see what the changes are between the final Library against its state as in chapter 11. Or just use this final X3Core Library, as I do now.
I noticed a strange difference: on a Mac everything appears mirrored compared to Windows. Thanks to the Tutorials I was able to write a workaround for this.
I use this X3 Library to my full satisfaction but I have a question to users/developers: I think it must be possible to make images/textures (semi)transparent. But how to achieve with this Library?