Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (580)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  LWJGL OPENGL load non power of two texture error  (Read 3020 times)
0 Members and 1 Guest are viewing this topic.
Offline leoxy520

Senior Newbie





« Posted 2012-09-01 03:13:21 »

I am using a library that loads some images from files, but they are not png or jpeg files. The library can return bytebuffer of the image. So my question is how do I load a texture in opengl using this bytebuffer?
Thanks in advance.

I solved the first problem which was the original purpose of this thread. Now I am facing the problem of loading non power of two textures.
I get error like these when loading those kinds of textures "Number of remaining buffer elements is 113844, must be at least 128164. Because at most 128164 elements can be returned, a buffer with at least 128164 elements is required, regardless of actual returned element count"
I am fine with power of two texture though.

Here is my entire program demo.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
package Leo.Story.Game;
import java.io.FileNotFoundException;
import java.io.IOException;

import net.zepheus.nxjava.NXCanvasNode;
import net.zepheus.nxjava.NXFile;
import net.zepheus.nxjava.Texture;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GLContext;


import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;

public class Game {
   
   static NXFile charNX = null;
   
   
    public static void main(String args[]) {
        try {
            Display.setDisplayMode(new DisplayMode(640, 480));
            Display.setTitle("Texture Demo");
            Display.create();
            charNX = new NXFile("C:\\Users\\Leo\\Desktop\\map.nx");
        } catch (LWJGLException e) {
            e.printStackTrace();
            Display.destroy();
            System.exit(1);
        } catch (FileNotFoundException e) {
         
         e.printStackTrace();
      } catch (IOException e) {
         
         e.printStackTrace();
      }
       
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glPixelStorei(GL_PACK_ALIGNMENT, 1);
       
//        BufferedImage bi = ((NXCanvasNode)charNX.resolvePath("Back","Amoria.img","back","1")).getImage();
//        ByteBuffer bb = Game.convertImageData(bi);
       Texture texture = ((NXCanvasNode)charNX.resolvePath("Back","Amoria.img","back","0")).getTexture();
        glMatrixMode(GL_PROJECTION);
        glOrtho(0, 640, 480, 0, 1, -1);
        glMatrixMode(GL_MODELVIEW);
        glEnable(GL_TEXTURE_2D);
        System.out.println(texture.getWidth() + " " + texture.getHeight());
        int texid = glGenTextures();
        glBindTexture(GL_TEXTURE_2D, texid);
       
        // when texture area is small, bilinear filter the closest mipmap
       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
              GL_LINEAR );
        // when texture area is large, bilinear filter the original
       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

        // the texture wraps over at the edges (repeat)
       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.getHeight(), texture.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.getBuffer());
       
        boolean ext = GLContext.getCapabilities().GL_EXT_bgra;
        System.out.println(ext);
       
        while (!Display.isCloseRequested()) {
            glClear(GL_COLOR_BUFFER_BIT);
            glEnable( GL_TEXTURE_2D );
            glBindTexture( GL_TEXTURE_2D, texid );

            glBegin(GL_QUADS);
            glTexCoord2f(0, 0);
            glVertex2i(100, 100); // Upper-left
           glTexCoord2f(1, 0);
            glVertex2i(100+texture.getWidth(), 100); // Upper-right
           glTexCoord2f(1, 1);
            glVertex2i(100+texture.getWidth(), 100+texture.getHeight()); // Bottom-right
           glTexCoord2f(0, 1);
            glVertex2i(100, 100+texture.getHeight()); // Bottom-left
           glEnd();
            Display.update();
            Display.sync(60);
        }
        // Release the resources of the wood texture
     
        Display.destroy();
        System.exit(0);
    }
}
   
   
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #1 - Posted 2012-09-01 03:43:53 »

OpenGL only expects raw pixel data. If this library decodes the file data into raw pixel data, then you can directly feed this ByteBuffer to the GPU.

Offline leoxy520

Senior Newbie





« Reply #2 - Posted 2012-09-01 03:45:38 »

Thanks for your reply. If it does, what functions can I use to load the texture with this raw data. Tutorials on the internet only load from image file.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #3 - Posted 2012-09-01 03:53:21 »

glTexImage2D

If you didn't know that, then I suggest you learn OpenGL properly. I recommend this tutorial, however it's in C++ so here are the Java ports.

Offline leoxy520

Senior Newbie





« Reply #4 - Posted 2012-09-01 08:30:25 »

 I am working on a game project. I have everything set up, that I mean the game data files: sound, images, strings. However they are compressed, and I am using a library to retrieve the data for me. The library returns a bytebuffer, or a java bufferedImage.
I don't really want to get very technical with opengl, all I want is to load my image, display them and make my game. I have been googling a lot, but none of the results directly addresses my issue, so I hope someone here will help me.

       
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
public BufferedImage getBitmap(int id) {
      BufferedImage value;
      if(!low_memory && bmp_loaded != null && (value = bmp_loaded[id]) != null) {
         return value;
      } else {
         long offset = getBitmapOffset(id);
         if(offset == -1)
            throw new NXException("NX file does not this canvas.");
         
         lock();
         try {
            SeekableLittleEndianAccessor slea = getStreamAtOffset(offset);
           
            int width = slea.getUShort();
            int height = slea.getUShort();
            long length = slea.getUInt();
           
            ByteBuffer output = ByteBuffer.allocateDirect(width * height * 4);
            NXCompression.decompress(slea.getBuffer(), offset + 4, length + 4, output, 0);
            output.rewind();
            output.order(ByteOrder.LITTLE_ENDIAN);
           
            //TODO: optimize this without bitshifts.
           value = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            for (int h = 0; h < height; h++) {
               for (int w = 0; w < width; w++) {
                  int b = output.get() & 0xFF;
                  int g = output.get() & 0xFF;
                  int r = output.get() & 0xFF;
                  int a = output.get() & 0xFF;
                  value.setRGB(w, h, (a << 24) | (r << 16) | (g << 8) | b);
               }
            }
         } finally { unlock(); }
         
         if(!low_memory) bmp_loaded[id] = value;
         return value;
      }
   }

This code is to retrieve image from the file. It construct a bytebuffer and make a bufferedimage from it. Because opengl glteximage2d requires bytebuffer, I think i can just return the bytebuffer this method has. However, I don't know how to use that bytebuffer, what format it is in.. etc.

So yea, all I need is just a little function that makes me a texture to bind, map and display. Thanks for any help in advance.
Offline davedes
« Reply #5 - Posted 2012-09-01 09:02:10 »

Is that your code, or some from the library you're using? For the sake of ease you could just convert the BufferedImage back to a ByteBuffer and pass that (see this thread).

It would be better to skip the BufferedImage completely, though. You could use glTexImage2D with GL_RGBA as the "internalFormat", GL_BGRA as the "format" and GL_UNSIGNED_BYTE as the "type".

Some pseudo-code:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
            // ... NX lock/setup stuff ... // 
           
            int width = slea.getUShort();
            int height = slea.getUShort();
            long length = slea.getUInt();

            // ... NX decompresses into a ByteBuffer ... //
           ByteBuffer output = ByteBuffer.allocateDirect(width * height
                  * 4);
            NXCompression.decompress(slea.getBuffer(), offset + 4,
                  length + 4, output, 0);
            output.rewind();
            output.order(ByteOrder.LITTLE_ENDIAN);
           
           
            int tex = glGenTextures();
            glBindTexture(GL_TEXTURE_2D, tex);
           
            // ... setup wrap mode and filtering ... //
           
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, output);
           
            // ... NX unlock stuff ... //
           
            // ... return the texture, or cache ... //
           return tex;

Offline leoxy520

Senior Newbie





« Reply #6 - Posted 2012-09-01 09:21:48 »

Hey, thanks for the reply. This is an external library for reading NX file as you can already tell. I did know that I can convert the bufferedimage back to a bytebuffer, but that would be redundant because the library construct the bufferedimage from the bytebuffer! And yes, I would like to find a way to just pass the bytebuffer in the library to opengl, that was my main question. I don't really want to bother with the details of how this file reading library works, because I just want to make my game. I will try your method when I get back to my desktop, maybe tomorrow. Thanks again for you input.

edit: i don't know really know the format of the bytebuffer in the method. So are you sure from reading the method, that your suggestions are right and they opengl would recognize the bytebuffer and make me a happy texture?
Offline davedes
« Reply #7 - Posted 2012-09-01 09:45:44 »

edit: i don't know really know the format of the bytebuffer in the method. So are you sure from reading the method, that your suggestions are right and they opengl would recognize the bytebuffer and make me a happy texture?
It's all guesswork since I can't test it on your end. But the decompression appears to leave the byte buffer in BGRA format, which you can work with.

Unless I'm mistaken this requires the GL_EXT_bgra extension, which it should be on most computers. If not, you may have to swizzle the bytes yourself like they do in the BufferedImage method (except ordering it RGBA instead).

1  
2  
//check if extension is present
boolean ext = GLContext.getCapabilities().GL_EXT_bgra;

Offline theagentd
« Reply #8 - Posted 2012-09-01 21:36:56 »

Unless I'm mistaken this requires the GL_EXT_bgra extension, which it should be on most computers. If not, you may have to swizzle the bytes yourself like they do in the BufferedImage method (except ordering it RGBA instead).

1  
2  
//check if extension is present
boolean ext = GLContext.getCapabilities().GL_EXT_bgra;

That "extension" is supported by 100% of all implementations. No, literally. It's even core in 1.2. No need to check it.

Myomyomyo.
Offline leoxy520

Senior Newbie





« Reply #9 - Posted 2012-09-01 22:05:06 »

I was testing your suggestions and the parameter GL_BGRA gave me error in eclipse. "can't resolve to a variable."

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
package Leo.Story.Game;
import net.zepheus.nxjava.NXCanvasNode;
import net.zepheus.nxjava.NXFile;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GLContext;


import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;

import static org.lwjgl.opengl.GL11.*;


public class Game {
   
   static NXFile charNX = null;
   
   
    public static void main(String args[]) {
        try {
            Display.setDisplayMode(new DisplayMode(640, 480));
            Display.setTitle("Texture Demo");
            Display.create();
            charNX = new NXFile("C:\\Users\\Leo\\Desktop\\nx\\character.nx");
        } catch (LWJGLException e) {
            e.printStackTrace();
            Display.destroy();
            System.exit(1);
        } catch (FileNotFoundException e) {
         
         e.printStackTrace();
      } catch (IOException e) {
         
         e.printStackTrace();
      }
       
        ByteBuffer bb = ((NXCanvasNode)charNX.resolvePath("00002000.img","alert","0", "body")).getImageByteBuffer();
       
        glMatrixMode(GL_PROJECTION);
        glOrtho(0, 640, 480, 0, 1, -1);
        glMatrixMode(GL_MODELVIEW);
        glEnable(GL_TEXTURE_2D);
       
        int texid = glGenTextures();
        glBindTexture(GL_TEXTURE_2D, texid);
       
        // when texture area is small, bilinear filter the closest mipmap
       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                         GL_LINEAR_MIPMAP_NEAREST );
        // when texture area is large, bilinear filter the original
       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

        // the texture wraps over at the edges (repeat)
       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 24, 29, 0, GL_RGBA, GL_UNSIGNED_BYTE, bb);
       
        boolean ext = GLContext.getCapabilities().GL_EXT_bgra;
        System.out.println(ext);
       
        while (!Display.isCloseRequested()) {
            glClear(GL_COLOR_BUFFER_BIT);
            glEnable( GL_TEXTURE_2D );
            glBindTexture( GL_TEXTURE_2D, texid );

            glBegin(GL_QUADS);
            glTexCoord2f(0, 0);
            glVertex2i(100, 100); // Upper-left
           glTexCoord2f(1, 0);
            glVertex2i(124, 100); // Upper-right
           glTexCoord2f(1, 1);
            glVertex2i(124, 129); // Bottom-right
           glTexCoord2f(0, 1);
            glVertex2i(100, 129); // Bottom-left
           glEnd();
            Display.update();
            Display.sync(60);
        }
       
       
        Display.destroy();
        System.exit(0);
    }
}


This is my file so far, I hope I did everything correctly. The result is just a white rectangle(the texture quad?) on a black background. I couldn't compile with GL_BGRA as the second to the last parameter in glTexImage2D method, so I replaced it with GL_RBGA. It might be the problem.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #10 - Posted 2012-09-01 22:14:58 »

Try adding this: "import static org.lwjgl.opengl.GL12.*;" to your imports, then GL_BGRA will work Wink

Offline theagentd
« Reply #11 - Posted 2012-09-01 22:26:00 »

Yeah, since GL_BGRA was promoted to core OpenGL with OpenGL 1.2, it's in GL12.

On another note, GL_BGRA is in both GL12 and GL32, just like GL_RED was.

Myomyomyo.
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #12 - Posted 2012-09-01 22:30:59 »

Yeah, since GL_BGRA was promoted to core OpenGL with OpenGL 1.2, it's in GL12.

On another note, GL_BGRA is in both GL12 and GL32, just like GL_RED was.
Damnit all, someone really needs to check for these pesky duplicates. I'll report it.... *sigh*

EDIT: Reported Smiley

Offline leoxy520

Senior Newbie





« Reply #13 - Posted 2012-09-01 22:40:09 »

Ok, it compiles with GL_BGRA. But I still have the same result

I think the bytebuffer format is messed up in a way that opengl doesn't recognize it. And sadly I don't know how to modify the bytebuffer format to match opengl..
Offline theagentd
« Reply #14 - Posted 2012-09-01 22:53:45 »

Quote
1  
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 24, 29, 0, GL_RGBA, GL_UNSIGNED_BYTE, bb);
That texture resolution is a bit weird and most likely doesn't work correctly since it's not a multiple of 4, which OpenGL assumes. Try to add this before loading the texture (line 40 or so):

1  
2  
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ALIGNMENT, 1);


Alternatively try it with a simpler power-of-two texture? Draw a 32x32 pixel image in Paint or something.

Myomyomyo.
Offline leoxy520

Senior Newbie





« Reply #15 - Posted 2012-09-01 23:02:12 »

I thought opengl doesn't care if images are power of 2 anymore. The file I am loading from is made by other people, I can edit it but I don't want to edit all of them. If I need to load an actual image file, I wouldn't use bytebuffer in the first place. But I will try to find a power of 2 image from the file and try it.
Offline theagentd
« Reply #16 - Posted 2012-09-01 23:23:00 »

OpenGL doesn't require power of 2 textures anymore, but it still assumes that the pixels are aligned according to the GL_*PACK_ALIGNMENT, which defaults to 4 pixels. Just change it with the code I posted and your textures can be any size.

Myomyomyo.
Offline leoxy520

Senior Newbie





« Reply #17 - Posted 2012-09-01 23:49:04 »

I tried glPixelStorei already, and I got the same result. It must be the format of the bytebuffer.. I should just convert the bufferedimage to bytebuffer with prvoen method.
Offline davedes
« Reply #18 - Posted 2012-09-02 00:45:56 »

It's probably invalid because you haven't specified mipmaps. Use GL_LINEAR or GL_NEAREST as your filter modes.

Offline leoxy520

Senior Newbie





« Reply #19 - Posted 2012-09-02 01:10:33 »

Yes it was the mipmap! I changed it to linear and it worked! Thanks for all of you guys help!
Offline leoxy520

Senior Newbie





« Reply #20 - Posted 2012-09-02 02:57:05 »

Updated the thread with a new problem. More help needed  Cry
Offline theagentd
« Reply #21 - Posted 2012-09-02 14:11:46 »

It's probably invalid because you haven't specified mipmaps. Use GL_LINEAR or GL_NEAREST as your filter modes.
<a href="http://www.youtube.com/v/1W7c8QghPxk?version=3&amp;hl=en_US&amp;start=" target="_blank">http://www.youtube.com/v/1W7c8QghPxk?version=3&amp;hl=en_US&amp;start=</a>
Dammit!

Myomyomyo.
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #22 - Posted 2012-09-02 20:24:40 »

Oh my god I love that clip Grin

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (51 views)
2014-04-15 18:08:23

BurntPizza (47 views)
2014-04-15 03:46:01

UprightPath (63 views)
2014-04-14 17:39:50

UprightPath (45 views)
2014-04-14 17:35:47

Porlus (62 views)
2014-04-14 15:48:38

tom_mai78101 (86 views)
2014-04-10 04:04:31

BurntPizza (144 views)
2014-04-08 23:06:04

tom_mai78101 (243 views)
2014-04-05 13:34:39

trollwarrior1 (202 views)
2014-04-04 12:06:45

CJLetsGame (209 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!