Hey all, I am having some trouble with the code below. This code is just to take a screenshot and display it, but when I can get the screen shot working quickly enough I plan to break the image up and ‘shatter’ it like a baseball going through a window. The first and important problem is that it takes too long, in my example it’s taking 1300 ms to complete taking the screenshot (392x360 size GLCanvas), converting it to a 512x512 image so I can use it as a texture. Creating a 256x256 sized image instead takes 800 ms, I think I can be happy if it can be reduced to 200 ms or less but I’m not sure it can be done, even with a 256x256 sized texture. The other problem I’m having is that the resulting image is quite a bit darker than the original scene. I’ve tried shutting off lighting in case the lighting calculations hadn’t been applied to the image before the screen shot or if maybe lighting was being applied twice (once to the original scene and again to the texture when it’s redisplayed) but that didn’t seem to be part of the problem. I did try using the other setRGB method of ImageBuffer to set the pixel information all at once in bulk, but this actually took about 200 ms longer to finish because it required an extra array to be created (pretty sure in C++ I could have just used a byte array and grabbed the alpha channel too and then cast it as an int array to avoid the problem of creating an extra array but I’m pretty sure that even if that worked in java it’d be a pretty bad idea so I’m not trying it). To use the code below, put the following line at the bottom of your drawing code. Since this will overlay the rest of the scene, so you probably will want to shut off drawing the rest of the scene after si has been created. Also note that in the ShatteredImage class in Display it may be necessary to set the vertixes away from the camera more or move the camera back.
Anyway, if anyone can help get this code sped up enough, I will post the final code so anyone can use it (final code being the window shattering effect).
/******** Code to use at end of your drawing ********/
ShatteredImage si = null;
if (si == null) {
Dimension d = glcanvas.getSize();
si = new ShatterImage(R,gl,d.width,d.height);
}
if (si != null) {
si.display(gl,timeDif);
}
/******** Class that takes the screenshot ********/
import java.util.;
import java.awt.image.;
import java.awt.;
import javax.swing.;
import net.java.games.jogl.;
import java.nio.;
import java.awt.color.*;
public class ShatterImage {
Random R;
byte[] image;
public ShatterImage(Random R,GL gl,int width,int height) {
this.R = R;
System.out.println(System.currentTimeMillis());
image = new byte[width*height*3];
//int[] tempimage = new int[width*height];
gl.glReadPixels(0, 0, width, height, GL.GL_RGB, GL.GL_BYTE, image);
BufferedImage bi = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
for (int i = 0; i < height; i++) {
for (int i2 = 0; i2< width; i2++) {
int color = 0;
int r = image[(i*width*3)+i2*3];
int g = image[((i*width*3)+i2*3)+1];
int b = image[((i*width*3)+i2*3)+2];
color = r * 0x010000 + g * 0x000100 + b;
bi.setRGB(i2,i,color);
//tempimage[i*width+i2] = color;
}
}
//bi.setRGB(0,0,width,height,tempimage,0,width);
System.out.println(System.currentTimeMillis());
Image scale = bi.getScaledInstance(512,512,Image.SCALE_FAST);
bi = new BufferedImage(512,512,BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
g2.drawImage(scale,0,0,null);
ByteBuffer bb = convertImageData(bi);
System.out.println(System.currentTimeMillis());
gl.glBindTexture(GL.GL_TEXTURE_2D, 400);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl.glTexImage2D(GL.GL_TEXTURE_2D,0,GL.GL_RGB,512,512,0,GL.GL_RGB,GL.GL_UNSIGNED_BYTE,bb );
System.out.println(System.currentTimeMillis());
}
private ByteBuffer convertImageData(BufferedImage bufferedImage)
{
ComponentColorModel glColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[] {8,8,8,0},false,false,ComponentColorModel.OPAQUE,DataBuffer.TYPE_BYTE);
ByteBuffer imageBuffer = null;
WritableRaster raster;
BufferedImage texImage;
int texWidth = bufferedImage.getWidth();
int texHeight = bufferedImage.getHeight();
raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,texWidth,texHeight,3,null);
texImage = new BufferedImage(glColorModel,raster,false,new Hashtable());
Graphics g = texImage.getGraphics();
g.drawImage(bufferedImage,0,0,null);
byte[] data = ((DataBufferByte) texImage.getRaster().getDataBuffer()).getData();
imageBuffer = ByteBuffer.allocateDirect(data.length);
imageBuffer.order(ByteOrder.nativeOrder());
imageBuffer.put(data, 0, data.length);
return imageBuffer;
}
public void display(GL gl,long timeDiff) {
float halfsize = 5f;
gl.glBindTexture(GL.GL_TEXTURE_2D,400);
gl.glBegin(GL.GL_QUADS);
gl.glNormal3f( 0.0f, 0.0f, 1.0f);
gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-halfsize, -halfsize, -0f);
gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( halfsize, -halfsize, -0f);
gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( halfsize, halfsize, -0f);
gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-halfsize, halfsize, -0f);
gl.glEnd();
}
}