Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (516)
Games in Android Showcase (123)
games submitted by our members
Games in WIP (577)
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  
  Texture grief  (Read 669 times)
0 Members and 1 Guest are viewing this topic.
Offline nerb
« Posted 2013-12-28 13:43:10 »

Howdy chaps,

I'm possibly opening myself up to some "LMGTFY" replies here, but I'm having some major trouble understanding the upload of 2d textures in LWJGL/OpenGL. I've been focusing on it all afternoon, but don't seem to be getting anywhere.

Assuming I've got an int[] filled with image data in the form of ARGB, how can I:

a) Prepare the data for OpenGL. Can I simply cram the data into an IntBuffer? (It appears I'll have to change ARGB to RGBA, but that should be trivial). I see one form of glTexImage2D() takes an IntBuffer, so I'm assuming that's all good?

b) Describe the data to OpenGL. Given I'm using the aforementioned RGBA IntBuffer, what should my call to glTexImage2D() look like? I'm struggling to understand the parameters, in particular internalformat, format and type. I've looked at the description in the OpenGL reference, but can't make head nor tail of it. Is anyone able to provide a more in-depth description of the parameters and their use?

Just for reference, the arguments to glTexImage2D are (with the params in bold giving me grief):
public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, java.nio.IntBuffer pixels)

Much appreciated,
nerb.


LMGTFM:
- So internalformat is how OpenGL should represent the texture data internally. All I want to do is display a sprite directly, as is, so I'm guessing GL_RGBA should suit my needs?
- format is the format of my pixel data. If I've got RGBA packed into an int, do I want to use GL_RGBA again?
- type is the type of data I'm uploading. Now this one confuses me a little. The data is packed into standard Java signed 32bit ints... So what type should I select? GL_INT?
Offline davedes
« Reply #1 - Posted 2013-12-28 15:06:17 »

See here:
https://github.com/mattdesl/lwjgl-basics/wiki/Textures

And some info here on buffers:
https://github.com/mattdesl/lwjgl-basics/wiki/Java-NIO-Buffers

- Usually just stick with RGBA for internalFormat.
- "format" depends on your buffer. If your integers are ARGB, then you need to use GL_ARGB (assuming it's supported).
- This would make sense. But all of demos I've seen either use unsigned byte, or unsigned int as data type. Odd since Java doesn't have any unsigned types. So it may just be that ByteBuffer/IntBuffer need GL_UNSIGNED_BYTE and GL_UNSIGNED_INT, respectively. You can use also use GL_UNSIGNED_INT_8_8_8_8. Maybe somebody with more expertise on endianness and NIO buffers can weigh in on that.

If you're trying to grab data from a BufferedImage, see here:
http://www.java-gaming.org/topics/bufferedimage-to-lwjgl-texture/25516/msg/234102/view.html#msg234102

Offline nerb
« Reply #2 - Posted 2013-12-29 08:56:14 »

Thanks very much for the reply davedes. The tutorial seemed to clear things up for me (or at least I thought...). It appears GL_UNSIGNED_INT_8_8_8_8 is the one to use if RGBA data is packed into an int. GL_UNSIGNED_INT seemed to cause OpenGL to expect an int for each channel.

All said and done, I'm still not problem-free. I've extracted my image data, pushed it off to OpenGL, however when I go to use the texture in my shaders I get nothing more than a black screen.

I've ripped up a quick example and dumped it in the pastebin, if anyone would care to have a look: http://pastebin.java-gaming.org/b069d24847b. I've created a giant, ugly init() method, just so that you can easily follow my workflow. Obviously the imgPath variable will need to be changed to point to your own image too. If the example was working correctly, it should've covered the screen in the chosen texture. (Nothing fancy, just a square filling the screen, no transformations or anything).

I'm not quite sure what I'm doing wrong. I'm guessing I haven't set some required state, or am doing something silly in my shaders?

Cheers muchly.

PS. Not sure if it is of any relevance, but my texture was a 128x128 32bit png. The RGBA data appeared as expected in the pixel ByteBuffer. I also checked my texture coordinates, and they are behaving as expected too.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline trollwarrior1
« Reply #3 - Posted 2013-12-29 09:54:55 »

I have trouble loading texture to opengl as well. I took this code from some website and modified for my own needs. You need to have a class folder in your project for this to work.

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  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.IOException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import javax.swing.ImageIcon;

import org.lwjgl.opengl.GL11;

public class SpriteSheet {

   private static List<SpriteSheet> sheets = new ArrayList<SpriteSheet>();
   private static ColorModel glAlphaColorModel = new ComponentColorModel(
         ColorSpace.getInstance(ColorSpace.CS_sRGB),
            new int[] {8,8,8,8},
            true,
            false,
            ComponentColorModel.TRANSLUCENT,
            DataBuffer.TYPE_BYTE);
   private static int target = GL11.GL_TEXTURE_2D;
   

   public static SpriteSheet sheet = new SpriteSheet("/image.png");
   
   public int id = 0;
   public int width, height;
   public String name;
   
   public SpriteSheet(String name) {
     
      this.name = name;
     
      try {
     
         BufferedImage image = loadBufferedImage(name);
         ByteBuffer imageByteBuffer = convertImageData(image);
         
         id = GL11.glGenTextures();
         
         bind();
         
         GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
         GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
         
         this.width = image.getWidth();
         this.height = image.getHeight();
         
         GL11.glTexImage2D(
               target,
               0,
               GL11.GL_RGBA,
               image.getWidth(),
               image.getHeight(),
               0,
               GL11.GL_RGBA,
               GL11.GL_UNSIGNED_BYTE,
               imageByteBuffer);
         
         
         sheets.add(this);
     
      }catch(IOException e) {
         e.printStackTrace();
      }
   }
   
   public SpriteSheet(int id, int width, int height) {
      this.id = id;
      this.width = width;
      this.height = height;
      this.name = "none";
   }
   
   @SuppressWarnings("rawtypes")
   private ByteBuffer convertImageData(BufferedImage image){
     
      ByteBuffer textureByteBuffer = null;
      WritableRaster raster = null;
      BufferedImage bufImage = null;
     
      raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, image.getWidth(), image.getHeight(), 4, null);
      bufImage = new BufferedImage(glAlphaColorModel, raster, false, new Hashtable());
     
      Graphics g = bufImage.getGraphics();
      g.drawImage(image, 0, 0, null);
     
      byte[] imageBytes = ((DataBufferByte) bufImage.getRaster().getDataBuffer()).getData();
     
      textureByteBuffer = ByteBuffer.allocateDirect(imageBytes.length);
      textureByteBuffer.order(ByteOrder.nativeOrder());
      textureByteBuffer.put(imageBytes, 0, imageBytes.length);
      textureByteBuffer.flip();
     
      return textureByteBuffer;
   }
   
   private BufferedImage loadBufferedImage(String name) throws IOException {
     
      URL url = SpriteSheet.class.getResource(name);
     
      Image img = new ImageIcon(url).getImage();
     
      BufferedImage image = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
       
      Graphics g = image.getGraphics();
     
      g.drawImage(img, 0, 0, image.getWidth(), image.getHeight(), null);
     
      g.dispose();
     
      int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());
     
      Color color = new Color(0, 0, 0, 0);
      for(int i=0;i<pixels.length;i++){
         if(pixels[i] == -65281) image.setRGB(i % image.getWidth(), i / image.getWidth(), color.getRGB()); // Replace certain colors with alpha
      }
     
      return image;
     
   }
   
   
   public void bind() {
      GL11.glBindTexture(target, id);
   }
   
}


When you want to create a Spritesheet, you type in path from your class folder to the file. Just study this you will understand.
Offline nerb
« Reply #4 - Posted 2013-12-29 10:23:19 »

Arrrgh... I think I've found my problem! I hadn't defined the min & mag filters (glTexParameteri() and all that). I thought they would default to something reasonable if I didn't explicitly state it, but obviously not.

Thanks to all that looked at it (and cheers for your reply nonetheless trollwarrior).
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.

TehJavaDev (33 views)
2014-10-27 03:28:38

TehJavaDev (26 views)
2014-10-27 03:27:51

DarkCart (41 views)
2014-10-26 19:37:11

Luminem (22 views)
2014-10-26 10:17:50

Luminem (27 views)
2014-10-26 10:14:04

theagentd (33 views)
2014-10-25 15:46:29

Longarmx (61 views)
2014-10-17 03:59:02

Norakomi (58 views)
2014-10-16 15:22:06

Norakomi (47 views)
2014-10-16 15:20:20

lcass (43 views)
2014-10-15 16:18:58
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
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!