/**
* File: JoglTransparencyDemo.java
*
* This file is free to use and modify as it is for educational use.
*
* Version:
* 1.1 Initial Version
*
*/
package com.momega.spacesimulator.transparent;
import java.awt.BorderLayout;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageProducer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureIO;
import com.momega.spacesimulator.opengl.GLUtils;
import com.momega.spacesimulator.renderer.TransparencyImageFilter;
/**
* A simple example of how to map a textures to a GL_QUAD this is the basis for
* all your textures mapping needs. However, this does not involve a more optimal
* approaches which is to use buffers. If you are intending to make a high
* performance application you should look into using buffers instead of the
* glVertex, glColor, glTexCoord calls, since each call must send information to
* the GPU for rendering. Buffers can send large amounts of data and be sent to
* the GPU less often instead of each frame.
*/
public class JoglTransparencyDemo extends JFrame implements GLEventListener {
private static final long serialVersionUID = 1895393500372450368L;
private static final String WINDOW_TITLE = "JOGL: Basic Transparency Demo";
private static final int WND_HEIGHT = 64;
private static final int WND_WIDTH = 915;
/**
* Main application entry-point.
*
* @param args
* Command line arguements
*/
public static void main(String[] args) {
// queue on the event thread to reduce the likelihood of threading
// issues with swing.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JoglTransparencyDemo(); // create and show the app
}
});
}
private Animator anim; //Used for rendering the scene to our canvas
private Texture bkTexture; //The fully opaque background textures
private GLCanvas canvas; //Our visible java.awt.Canvas component
/**
* Our constructor that sets up and starts the application. This does not
* immediately initialize the scene.
*/
public JoglTransparencyDemo() {
super(WINDOW_TITLE); // window title
setLayout(new BorderLayout()); // our generic fill the window layout.
// create the canvas, animator, and other objects
setup();
// need to wait till the window and all components are shown before
// starting the jogl rendering thread.
addComponentListener(new ComponentAdapter() {
@Override
public void componentShown(ComponentEvent e) {
start();
}
});
// setup the JFrame size and starting location
setSize(WND_WIDTH, WND_HEIGHT);
setLocationRelativeTo(null); // center window on screen
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true); // display the window
}
/**
* Called by the drawable to perform rendering by the client.
*
* @param drawable
* The display context to render to
*/
public void display(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
// variables for controlling the rendered geometry
float startX = 0f;
float startY = 0f;
float width = 1f;
float height = 1f;
// This is the good part
// This clears the backbuffer and allows us to draw on a clean surface.
gl.glClear(GL2.GL_COLOR_BUFFER_BIT); // use the clear color we set
gl.glColor3dv(new double[] {1,0,0}, 0);
gl.glBegin(GL2.GL_QUADS); // the gl draw mode
gl.glVertex2d(0, 0.3);
gl.glVertex2d(1, 0.3);
gl.glVertex2d(1, 0.6);
gl.glVertex2d(0, 0.6);
gl.glEnd();
gl.glColor3dv(new double[] {1,1,1}, 0);
bkTexture.bind(gl); //bind the textures we want to be used
gl.glBegin(GL2.GL_QUADS); // the gl draw mode
// set the textures coordinates for the next vertex
gl.glTexCoord2d(1.0, 1.0);
// add a two-dimensional vertex
gl.glVertex2f(startX + width, startY);
gl.glTexCoord2d(0.0, 1.0);
gl.glVertex2f(startX, startY);
gl.glTexCoord2d(0.0, 0.0);
gl.glVertex2f(startX, startY + height);
gl.glTexCoord2d(1.0, 0.0);
gl.glVertex2f(startX + width, startY + height);
gl.glEnd();
// Really basic and most common alpha blend function
gl.glEnable(GL2.GL_BLEND);
gl.glBlendFunc(GL2.GL_ONE, GL2.GL_ONE_MINUS_SRC_ALPHA);
// bkTexture.disable(gl);
// gl.glDisable(GL2.GL_BLEND);
}
/**
* Called by the drawable when the display mode or the display device
* associated with the GLDrawable has changed
*/
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged,
boolean deviceChanged) {
// TODO: reset the device states
}
/**
* Called by the drawable immediately after the OpenGL context is
* initialized; the GLContext has already been made current when this method
* is called.
*
* @param drawable
* The display context to render to
*/
public void init(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glEnable(GL2.GL_SMOOTH);
// enable 2D textures
gl.glEnable(GL2.GL_TEXTURE_2D);
// select modulate to mix textures with color for shading
gl.glTexEnvf(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE);
InputStream is = createTransparentStream("/rings/saturnringcolor.jpg", "/rings/saturnringpattern.gif");
// create the textures, you may need to find an alternative if this
// method is not available for the jogl version you use.
//BufferedImage image = createBackgroundImage();
//bkTexture = AWTTextureIO.newTexture(GLProfile.getDefault(), image, false);
bkTexture = GLUtils.loadTexture(gl, is, TextureIO.PNG , false);
// bkTexture = GLUtils.loadTexture(gl, getClass(), "/rings/SatRing.png", "png", true);
// set the textures parameters to allow for properly displaying
bkTexture.setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_S, GL2.GL_REPEAT);
bkTexture.setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_T, GL2.GL_REPEAT);
bkTexture.setTexParameteri(gl, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
bkTexture.setTexParameteri(gl, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);
// should be done in the draw method
bkTexture.bind(gl); // only after setting textures properties
gl.glClearDepth(1.0f); // set clear depth value to farthest
// now we set the stage basically
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // the color to use when
// clearing the screen
gl.glMatrixMode(GL2.GL_PROJECTION); //
gl.glLoadIdentity(); // the identity matrix
gl.glOrtho(0, 1, 0, 1, -1, 1);
}
protected InputStream createTransparentStream(String fileName, String transparencyFileName) {
try {
InputStream is = getClass().getResourceAsStream(fileName);
BufferedImage source = ImageIO.read(is);
InputStream tis = getClass().getResourceAsStream(transparencyFileName);
BufferedImage transparency = ImageIO.read(tis);
ImageProducer ip = new FilteredImageSource(source.getSource(), new TransparencyImageFilter(transparency));
Image image = Toolkit.getDefaultToolkit().createImage(ip);
BufferedImage im = imageToBufferedImage(image, image.getWidth(null), image.getHeight(null));
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(im, "png", os);
InputStream fis = new ByteArrayInputStream(os.toByteArray());
return fis;
} catch (IOException io) {
throw new IllegalStateException(io);
}
}
private BufferedImage imageToBufferedImage(Image image, int width, int height)
{
BufferedImage dest = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE);
Graphics2D g2 = dest.createGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
return dest;
}
/**
* Called by the drawable when the surface resizes itself. Used to reset the
* viewport dimensions.
*
* @param drawable
* The display context to render to
*/
public void reshape(GLAutoDrawable drawable, int x, int y, int width,
int height) {
// TODO: adjust the scene
}
/**
* Create the GLCanvas and set properties for the graphics device
* initialization, such as bits per channel. And advanced features for
* improved rendering performance such as the stencil buffer.
*/
private void setup() {
GLProfile glp = GLProfile.getDefault();
// Specifies a set of OpenGL capabilities, based on your profile.
GLCapabilities caps = new GLCapabilities(glp);
caps.setDoubleBuffered(true);
caps.setHardwareAccelerated(true);
// create the canvas for drawing
canvas = new GLCanvas(caps);
// create the render thread
anim = new Animator();
// add the canvas to the main window
add(canvas, BorderLayout.CENTER);
// need this to receive callbacks for rendering (i.e. display() method)
canvas.addGLEventListener(this);
}
/**
* Add and start the animator for rendering our scene.
*/
private void start() {
anim.add(canvas);
anim.start();
}
@Override
public void dispose(GLAutoDrawable drawable) {
// TODO Auto-generated method stub
}
}