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 (499)
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  
  BufferedImage to lwjgl texture  (Read 11997 times)
0 Members and 1 Guest are viewing this topic.
Offline PaidGEEK

Senior Member


Medals: 5
Projects: 3


twitter.com/PaidGEEK


« Posted 2012-01-14 16:56:59 »

Hi guys!
I have a simple question about converting a bufferedimage from java.awt library to lwjgl Texture. Basically i want to bind this texture to opengl ("texture.bind()") after i do some cropping from the main image (using "image.getSubImage(x,y,width,height)" or cropImageFilter()"). It's supposed to make a few textures from a bigger image just like minecraft does for it's fonts and so on. So can anyone give me a snippet how could i do this?

Improvisational programmer.
Offline theagentd
« Reply #1 - Posted 2012-01-14 18:43:24 »

1. Load image with ImageIO or any other method.
2. Crop out the different parts you want to smaller BufferedImages using getSubImage(...)
For each sub image:
   
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
        int[] pixels = new int[image.getWidth() * image.getHeight()];
        image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());

        ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * BYTES_PER_PIXEL); //4 for RGBA, 3 for RGB
       
        for(int y = 0; y < image.getHeight(); y++){
            for(int x = 0; x < image.getWidth(); x++){
                int pixel = pixels[y * image.getWidth() + x];
                buffer.put((byte) ((pixel >> 16) & 0xFF));     // Red component
               buffer.put((byte) ((pixel >> 8) & 0xFF));      // Green component
               buffer.put((byte) (pixel & 0xFF));               // Blue component
               buffer.put((byte) ((pixel >> 24) & 0xFF));    // Alpha component. Only for RGBA
           }
        }

        buffer.flip(); //FOR THE LOVE OF GOD DO NOT FORGET THIS

        // You now have a ByteBuffer filled with the color data of each pixel.
       // Now just create a texture ID and bind it. Then you can load it using
       // whatever OpenGL method you want, for example:
       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8A, image.getWidth(), image.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

Myomyomyo.
Offline PaidGEEK

Senior Member


Medals: 5
Projects: 3


twitter.com/PaidGEEK


« Reply #2 - Posted 2012-01-15 01:09:56 »

I can't get it to work. I get alot of errors like invalid enum or null pointer location using various methods in opengl. At the end i tryed displaying this buffer with drawPixels() method which kinda worked but image was completly messed up. Can you please show me how to bind this buffer, to gl_quads for example, correctly? I don't know exactly what im doing couse i started learning java about a month ago. Thanks for your help!

Improvisational programmer.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline theagentd
« Reply #3 - Posted 2012-01-15 01:24:37 »

I can't get it to work. I get alot of errors like invalid enum or null pointer location using various methods in opengl. At the end i tryed displaying this buffer with drawPixels() method which kinda worked but image was completly messed up. Can you please show me how to bind this buffer, to gl_quads for example, correctly? I don't know exactly what im doing couse i started learning java about a month ago. Thanks for your help!

If you're new to Java, then I recommend you to stay away from OpenGL and stick to Java2D which is easier to use.

Anyway, if you are using LWJGL I can give you a working example program, but if you're using JOGL you'll have to adapt it slightly yourself. Which one are you using?

Myomyomyo.
Offline PaidGEEK

Senior Member


Medals: 5
Projects: 3


twitter.com/PaidGEEK


« Reply #4 - Posted 2012-01-15 01:49:22 »

Im using LWJGL. I mean i made some pretty cool stuff already in opengl using textures mapping i just didn't get the chance to learn using this buffers yet.

Improvisational programmer.
Offline theagentd
« Reply #5 - Posted 2012-01-15 03:05:07 »

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  
package YOUR.PACKAGE.HERE;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL12;

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

public class BasicTextureTest {
   
   private static final int WIDTH = 800, HEIGHT = 600;
   
   public static void main(String[] args){
     
      try{
         Display.setDisplayMode(new DisplayMode(800, 600));
         Display.create();
      }catch(LWJGLException e){
         e.printStackTrace();
      }
     
      glMatrixMode(GL_PROJECTION);
      glOrtho(0, WIDTH, HEIGHT, 0, -1, 1); //2D projection matrix
     glMatrixMode(GL_MODELVIEW);
     
      glClearColor(0, 1, 0, 0); //Green clear color
     
     
      //Generate a small test image by drawing to a BufferedImage
     //It's of course also possible to just load an image using ImageIO.load()
     BufferedImage test = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2d = test.createGraphics();

      g2d.setColor(new Color(1.0f, 1.0f, 1.0f, 0.5f));
      g2d.fillRect(0, 0, 128, 128); //A transparent white background
     
      g2d.setColor(Color.red);
      g2d.drawRect(0, 0, 127, 127); //A red frame around the image
     g2d.fillRect(10, 10, 10, 10); //A red box
     
      g2d.setColor(Color.blue);
      g2d.drawString("Test image", 10, 64); //Some blue text
     
      int textureID = loadTexture(test);
     
      glEnable(GL_TEXTURE_2D); //Enable texturing
     
     
      while(!Display.isCloseRequested()){
         glClear(GL_COLOR_BUFFER_BIT);
         
         //Enable blending so the green background can be seen through the texture
        glEnable(GL_BLEND);
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
         
         glPushMatrix();
         glTranslatef(100, 100, 0);
         glBindTexture(GL_TEXTURE_2D, textureID);
         glBegin(GL_QUADS);
         {
            glTexCoord2f(0, 0);
            glVertex2f(0, 0);
           
            glTexCoord2f(1, 0);
            glVertex2f(128, 0);
           
            glTexCoord2f(1, 1);
            glVertex2f(128, 128);
           
            glTexCoord2f(0, 1);
            glVertex2f(0, 128);
         }
         glEnd();
         glPopMatrix();
         
         Display.update();
      }
   }
   
   private static final int BYTES_PER_PIXEL = 4;
   public static int loadTexture(BufferedImage image){
     
      int[] pixels = new int[image.getWidth() * image.getHeight()];
        image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());

        ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * BYTES_PER_PIXEL); //4 for RGBA, 3 for RGB
       
        for(int y = 0; y < image.getHeight(); y++){
            for(int x = 0; x < image.getWidth(); x++){
                int pixel = pixels[y * image.getWidth() + x];
                buffer.put((byte) ((pixel >> 16) & 0xFF));     // Red component
               buffer.put((byte) ((pixel >> 8) & 0xFF));      // Green component
               buffer.put((byte) (pixel & 0xFF));               // Blue component
               buffer.put((byte) ((pixel >> 24) & 0xFF));    // Alpha component. Only for RGBA
           }
        }

        buffer.flip(); //FOR THE LOVE OF GOD DO NOT FORGET THIS

        // You now have a ByteBuffer filled with the color data of each pixel.
       // Now just create a texture ID and bind it. Then you can load it using
       // whatever OpenGL method you want, for example:

      int textureID = glGenTextures(); //Generate texture ID
       glBindTexture(GL_TEXTURE_2D, textureID); //Bind texture ID
       
        //Setup wrap mode
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

        //Setup texture scaling filtering
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
       
        //Send texel data to OpenGL
       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
     
        //Return the texture ID so we can bind it later again
     return textureID;
   }
}

You should be able to extract what you want from this program. Note that I generate an image by drawing to a BufferedImage.

Myomyomyo.
Offline PaidGEEK

Senior Member


Medals: 5
Projects: 3


twitter.com/PaidGEEK


« Reply #6 - Posted 2012-01-15 12:05:30 »

It works great! I load it to gluPerspective and it finaly works. Thank you so much! Smiley

Improvisational programmer.
Offline theagentd
« Reply #7 - Posted 2012-01-15 12:47:34 »

No problem! =D Increasing the OpenGL population is something I enjoy doing!

Myomyomyo.
Offline roland
« Reply #8 - Posted 2012-01-25 05:18:38 »

 Shocked I was just looking for this. Thanks theagentd!!!!  Grin
Offline elix

Senior Newbie





« Reply #9 - Posted 2012-06-11 05:47:27 »

one more thanks  Wink
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline nsigma
« Reply #10 - Posted 2012-06-11 10:45:37 »

Well, as this thread has been woken up ...  Wink

I'm using a slightly different technique to write the pixel data to the texture, which may be useful and potentially faster if you have to update the texture from the pixel data (or BufferedImage) regularly.  It saves on doing all the bit massaging in Java by using the fact that GL_BGRA is the same as ARGB in reverse.  Alpha bias is used to correct the data if the pixel data has zero alpha values.  The data is obviously still going to need to be massaged, but hopefully doing it on the OpenGL side will be faster.

NB. My textures are already allocated (as RGBA8) by this point.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
int size = width * height;
if (buffer == null || buffer.capacity() < size) {
    buffer = BufferUtils.createIntBuffer(size);
}
texture.bind();
buffer.rewind();
buffer.put(pixels, 0, size);
buffer.rewind();
if (!alpha) {
    GL11.glPixelTransferf(GL11.GL_ALPHA_BIAS, 1);
}
GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D,
     0,
     0,
     0,
     width,
     height,
     GL12.GL_BGRA,
     GL12.GL_UNSIGNED_INT_8_8_8_8_REV,
     buffer);
if (!alpha) {
   GL11.glPixelTransferf(GL11.GL_ALPHA_BIAS, 0);
}

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline theagentd
« Reply #11 - Posted 2012-06-11 11:35:49 »

Yes, this should work perfectly fine and have much better performance assuming the swizzling is done on the GPU (which I see no reason for not happening) assuming it works. I've always thought that color is stored in ARGB in BufferedImages though. Is that not the case? You're using BGRA? Ah, GL_UNSIGNED_INT_8_8_8_8_REV. REV = reverse? Clever.

Then the only problem with this is that it transfers the alpha data too which consumes some extra bandwidth if it's not needed, but what the hell, the trade-off is still worth it. It also reduces the complexity of the loading, so I guess this is the best way of loading textures. Be sure to explain to newbies exactly what's happening in when doing this if you give them that code though, since it's far from clear how and why it works. =S Or just link them here, I guess. =D

Myomyomyo.
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 605
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #12 - Posted 2012-06-11 12:10:35 »

I've always thought that color is stored in ARGB in BufferedImages though. Is that not the case?

The way the pixels are stored is determined by the 3rd parameter in the constructor:
1  
BufferedImage(int width, int height, int imageType)


TYPE_USHORT_565_RGB, TYPE_4BYTE_ABGR, TYPE_INT_ARGB, etc.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline theagentd
« Reply #13 - Posted 2012-06-11 13:59:58 »

I've always thought that color is stored in ARGB in BufferedImages though. Is that not the case?

The way the pixels are stored is determined by the 3rd parameter in the constructor:
1  
BufferedImage(int width, int height, int imageType)


TYPE_USHORT_565_RGB, TYPE_4BYTE_ABGR, TYPE_INT_ARGB, etc.
Well, I think we all just plug the BufferedImage we get from ImageIO.load() into our renderers though... Wink It seems to always use TYPE_INT_ARGB though, right?

Myomyomyo.
Offline princec

JGO Kernel


Medals: 282
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #14 - Posted 2012-06-11 14:11:00 »

No, not always. On MacOS I've had it in the other endianness on PPC arch and that comes out as "custom" format in Java2D.

Cas Smiley

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 605
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #15 - Posted 2012-06-11 14:15:37 »

Well, I think we all just plug the BufferedImage we get from ImageIO.load() into our renderers though... Wink It seems to always use TYPE_INT_ARGB though, right?
Nope, it depends on the bytes it receives. It tries to pick a datatype that matches the native format. Reading multiple JPEGs can result into multiple data-types - same for PNG, obviously whether or not there is transparancy, but PNG's can also be indexed. The datatypes of BMP and GIF are constant, I think.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Orangy Tang

JGO Kernel


Medals: 51
Projects: 11


Monkey for a head


« Reply #16 - Posted 2012-06-11 14:29:02 »

Well, I think we all just plug the BufferedImage we get from ImageIO.load() into our renderers though...

I used to, but as mentioned already it won't always work. I pinched this method from someone in the lwjgl irc a while ago to convert to a custom ComponentColorModel which can be directly sent to OpenGL. It leaves the per-pixel manipulation up to j2d (which it's really good at):

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  
package com.triangularpixels.rebirth.renderer.image;

import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Hashtable;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;

public class TextureUtils
{
   static ComponentColorModel glRGBAColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
             new int[] {8,8,8,8},
             true,
             false,
             ComponentColorModel.TRANSLUCENT,
             DataBuffer.TYPE_BYTE);
             
   static ComponentColorModel glRGBColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
             new int[] {8,8,8,0},
             false,
             false,
             ComponentColorModel.OPAQUE,
             DataBuffer.TYPE_BYTE);
   
   public static BufferedImage createBufferedImage(final int width, final int height, TextureFormat format)
   {
      if (format == TextureFormat.RGB)
      {
         WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, 3, null);
         return new BufferedImage(TextureUtils.glRGBColorModel, raster, false, new Hashtable<String, Object>());
      }
      else if (format == TextureFormat.RGBA)
      {
         WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, 4, null);
         return new BufferedImage(TextureUtils.glRGBAColorModel, raster, false, new Hashtable<String, Object>());
      }
      else
      {
         assert false;
         return null;
      }
   }
   
   public static TextureFormat findFormat(BufferedImage img)
   {
      final int numBands = img.getRaster().getNumBands();
      return (numBands == 3) ? TextureFormat.RGB : TextureFormat.RGBA;
   }
   
   public static BufferedImage convertToGlFormat(BufferedImage inImage, final boolean flipY)
   {
      // If already in a suitable colour model then just return the input unchanged
     if ((inImage.getColorModel() == glRGBColorModel || inImage.getColorModel() == glRGBAColorModel)
            && !flipY)
      {
         return inImage;
      }
     
      TextureFormat format = TextureUtils.findFormat(inImage);
      BufferedImage outImage = TextureUtils.createBufferedImage(inImage.getWidth(), inImage.getHeight(), format);
     
      if (flipY)
      {
         outImage.getGraphics().drawImage(inImage,
               0, 0, inImage.getWidth(), inImage.getHeight(), // dest rect
              0, inImage.getHeight(), inImage.getWidth(), 0, // src rect
              null);
      }
      else
      {
         outImage.getGraphics().drawImage(inImage, 0, 0, null);
      }
     
      return outImage;
   }
   
   public static int createTexture(BufferedImage imageData, TextureFilter filterMode, TextureWrap wrapMode, final boolean flipY)
   {
      imageData = convertToGlFormat(imageData, flipY);
     
      TextureFormat format = TextureUtils.findFormat(imageData);
     
      IntBuffer buff = BufferUtils.createIntBuffer(16);
      buff.limit(1);
      GL11.glGenTextures(buff);
     
      final int textureId = buff.get();
     
      GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId);
     
      GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filterMode.glValue());
      GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filterMode.glValue());
     
      GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, wrapMode.glValue());
      GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, wrapMode.glValue());
     
      ByteBuffer scratch = ByteBuffer.allocateDirect(format.bytesPerPixel()*imageData.getWidth()*imageData.getHeight());

      Raster raster = imageData.getRaster();
      byte data[] = (byte[])raster.getDataElements(0, 0, imageData.getWidth(), imageData.getHeight(), null);
      scratch.clear();
      scratch.put(data);
      scratch.rewind();
     
      GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, format.glValue(),            // Mip level & internal format
                    imageData.getWidth(), imageData.getHeight(), 0,      // width, height, border
                    format.glValue(), GL11.GL_UNSIGNED_BYTE,         // pixel data format
                    scratch);                                 // pixel data
     
      return textureId;
   }
}


Feel free to pinch any bits of this you want.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline nsigma
« Reply #17 - Posted 2012-06-11 15:25:21 »

Yes, this should work perfectly fine and have much better performance assuming the swizzling is done on the GPU (which I see no reason for not happening) assuming it works. I've always thought that color is stored in ARGB in BufferedImages though. Is that not the case? You're using BGRA? Ah, GL_UNSIGNED_INT_8_8_8_8_REV. REV = reverse? Clever.

Yes, REV is reverse.  You could also swap the endian-ness of the IntBuffer to get the same effect - for some reason lost in the mists of time (which generally means anything past 5 min ago  Roll Eyes ) I decided on this way.  It feels like a hack but seems to work fine.  I needed it for the OpenGL pipeline in Praxis, which has its own optimized software pipeline.  In order to be able to develop the OpenGL pipeline incrementally I needed a fast way of dropping to the software pipeline for anything not yet implemented, which might involve updating the texture at 60fps.  Seems to work OK, if a little CPU intensive!  Grin

As others have said, the data in BufferedImages can be stored in a wide range of formats.  The getRGB() method in your code above will always return ARGB though.  However, it involves needlessly copying the data.

It leaves the per-pixel manipulation up to j2d (which it's really good at):

But better than the OpenGL driver / GPU???

I pinched this method from someone in the lwjgl irc a while ago

... [some code] ...

Feel free to pinch any bits of this you want.

LOL  Grin

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline Orangy Tang

JGO Kernel


Medals: 51
Projects: 11


Monkey for a head


« Reply #18 - Posted 2012-06-11 15:39:08 »

But better than the OpenGL driver / GPU???

Faster than manually looping over and converting the pixel data by hand I mean. And will be able to deal with whatever internal format you can throw at it.

I pinched this method from someone in the lwjgl irc a while ago

... [some code] ...

Feel free to pinch any bits of this you want.

LOL  Grin
I pinched the method, not the actual code above.  Roll Eyes

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline nsigma
« Reply #19 - Posted 2012-06-11 15:53:18 »

But better than the OpenGL driver / GPU???

Faster than manually looping over and converting the pixel data by hand I mean. And will be able to deal with whatever internal format you can throw at it.

Ah, OK - wasn't sure what that was in comparison to.  Having said that, I wouldn't assume that J2D will always perform better than manual looping and bit-shifting.

I pinched the method, not the actual code above.  Roll Eyes

Oops, different interpretations of 'method' - still amused me though.

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
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 (42 views)
2014-04-15 18:08:23

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

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

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

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

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

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

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

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

CJLetsGame (203 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!