It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I try to draw a basic texture in LWJGL, but I can't.
My main class:
package worldofportals;
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;
import worldofportals.texture.TextureLoader;
/**
* Initialize the program, handle the rendering, updating, the mouse and the
* keyboard events.
*
* #author Laxika
*/
public class WorldOfPortals {
/**
* Time at the last frame.
*/
private long lastFrame;
/**
* Frames per second.
*/
private int fps;
/**
* Last FPS time.
*/
private long lastFPS;
public static final int DISPLAY_HEIGHT = 1024;
public static final int DISPLAY_WIDTH = 768;
public static final Logger LOGGER = Logger.getLogger(WorldOfPortals.class.getName());
int tileId = 0;
static {
try {
LOGGER.addHandler(new FileHandler("errors.log", true));
} catch (IOException ex) {
LOGGER.log(Level.WARNING, ex.toString(), ex);
}
}
public static void main(String[] args) {
WorldOfPortals main = null;
try {
main = new WorldOfPortals();
main.create();
main.run();
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, ex.toString(), ex);
} finally {
if (main != null) {
main.destroy();
}
}
}
/**
* Create a new lwjgl frame.
*
* #throws LWJGLException
*/
public void create() throws LWJGLException {
//Display
Display.setDisplayMode(new DisplayMode(DISPLAY_WIDTH, DISPLAY_HEIGHT));
Display.setFullscreen(false);
Display.setTitle("World of Portals FPS: 0");
Display.create();
//Keyboard
Keyboard.create();
//Mouse
Mouse.setGrabbed(false);
Mouse.create();
//OpenGL
initGL();
resizeGL();
getDelta(); // call once before loop to initialise lastFrame
lastFPS = getTime();
glEnable(GL_TEXTURE_2D); //Enable texturing
tileId = TextureLoader.getInstance().loadTexture("img/tile1.png");
}
/**
* Destroy the game.
*/
public void destroy() {
//Methods already check if created before destroying.
Mouse.destroy();
Keyboard.destroy();
Display.destroy();
}
/**
* Initialize the GL.
*/
public void initGL() {
//2D Initialization
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
}
/**
* Handle the keyboard events.
*/
public void processKeyboard() {
}
/**
* Handle the mouse events.
*/
public void processMouse() {
}
/**
* Handle the rendering.
*/
public void render() {
glPushMatrix();
glClear(GL_COLOR_BUFFER_BIT);
for (int i = 0; i < 30; i++) {
for (int j = 30; j >= 0; j--) { // Changed loop condition here.
glBindTexture(GL_TEXTURE_2D, tileId);
// translate to the right location and prepare to draw
GL11.glTranslatef(20, 20, 0);
GL11.glColor3f(0, 0, 0);
// draw a quad textured to match the sprite
GL11.glBegin(GL11.GL_QUADS);
{
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(0, 64);
GL11.glVertex2f(0, DISPLAY_HEIGHT);
GL11.glTexCoord2f(64, 64);
GL11.glVertex2f(DISPLAY_WIDTH, DISPLAY_HEIGHT);
GL11.glTexCoord2f(64, 0);
GL11.glVertex2f(DISPLAY_WIDTH, 0);
}
GL11.glEnd();
}
}
// restore the model view matrix to prevent contamination
GL11.glPopMatrix();
}
/**
* Resize the GL.
*/
public void resizeGL() {
//2D Scene
glViewport(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0f, DISPLAY_WIDTH, 0.0f, DISPLAY_HEIGHT);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
}
public void run() {
while (!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
if (Display.isVisible()) {
processKeyboard();
processMouse();
update(getDelta());
render();
} else {
if (Display.isDirty()) {
render();
}
}
Display.update();
Display.sync(60);
}
}
/**
* Game update before render.
*/
public void update(int delta) {
updateFPS();
}
/**
* Get the time in milliseconds
*
* #return The system time in milliseconds
*/
public long getTime() {
return (Sys.getTime() * 1000) / Sys.getTimerResolution();
}
/**
* Calculate how many milliseconds have passed since last frame.
*
* #return milliseconds passed since last frame
*/
public int getDelta() {
long time = getTime();
int delta = (int) (time - lastFrame);
lastFrame = time;
return delta;
}
/**
* Calculate the FPS and set it in the title bar
*/
public void updateFPS() {
if (getTime() - lastFPS > 1000) {
Display.setTitle("World of Portals FPS: " + fps);
fps = 0;
lastFPS += 1000;
}
fps++;
}
}
And my texture loader:
package worldofportals.texture;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
import org.lwjgl.BufferUtils;
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.opengl.GL12;
public class TextureLoader {
private static final int BYTES_PER_PIXEL = 4;//3 for RGB, 4 for RGBA
private static TextureLoader instance;
private TextureLoader() {
}
public static TextureLoader getInstance() {
if (instance == null) {
instance = new TextureLoader();
}
return instance;
}
/**
* Load a texture from file.
*
* #param loc the location of the file
* #return the id of the texture
*/
public int loadTexture(String loc) {
BufferedImage image = loadImage(loc);
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();
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//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;
}
/**
* Load an image from disc.
*
* #param loc the location of the image
* #return the image
*/
private BufferedImage loadImage(String loc) {
try {
return ImageIO.read(new File(loc));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
It's not an actual game, just a test to learn and practice openGL in java. Also anyone can suggest me a good book on OpenGL?
Have you tried:
BufferedImage image = loadImage(loc);
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4);
Color c;
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
c = new Color(image.getRGB(x, y));
buffer.put((byte) c.getRed()); // Red component
buffer.put((byte) c.getGreen()); // Green component
buffer.put((byte) c.getBlue()); // Blue component
buffer.put((byte) c.getAlpha()); // Alpha component. Only for RGBA
}
}
Also, if you are going to put the Alpha component, you should either check the number of components, and add the alpha only if there is 4, or ALWAYS use 4. Also, do GL_RGBA instead of GL_RGBA8.
shouldn't you be calling the
Display.swapBuffers() after render?
Related
I have a 3d program that was working fine before I updated my nvidia gf 620m graphics drivers to version 22.21.13.8494 .Now whenever I run the program I get a black screen . I tried to find the source of the problem and it seems to be with the multisampling FBO in my program as the problem only occurs when its enabled.
My FBO class.
public class Fbo {
public static final int NONE = 0;
public static final int DEPTH_TEXTURE = 1;
public static final int DEPTH_RENDER_BUFFER = 2;
private final int width;
private final int height;
private int frameBuffer;
private boolean multisampleMultiTargets = false;
private int colourTexture;
private int depthTexture;
private int depthBuffer;
private int colourBuffer;
private int colourBuffer2;
/**
* Creates an FBO of a specified width and height, with the desired type of
* depth buffer attachment.
*
* #param width
* - the width of the FBO.
* #param height
* - the height of the FBO.
* #param depthBufferType
* - an int indicating the type of depth buffer attachment that
* this FBO should use.
*/
public Fbo(int width, int height, int depthBufferType) {
this.width = width;
this.height = height;
initialiseFrameBuffer(depthBufferType);
}
public Fbo(int width, int height) {
this.width = width;
this.height = height;
this.multisampleMultiTargets = true;
initialiseFrameBuffer(DEPTH_RENDER_BUFFER);
}
/**
* Deletes the frame buffer and its attachments when the game closes.
*/
public void cleanUp() {
GL30.glDeleteFramebuffers(frameBuffer);
GL11.glDeleteTextures(colourTexture);
GL11.glDeleteTextures(depthTexture);
GL30.glDeleteRenderbuffers(depthBuffer);
GL30.glDeleteRenderbuffers(colourBuffer);
GL30.glDeleteRenderbuffers(colourBuffer2);
}
/**
* Binds the frame buffer, setting it as the current render target. Anything
* rendered after this will be rendered to this FBO, and not to the screen.
*/
public void bindFrameBuffer() {
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, frameBuffer);
GL11.glViewport(0, 0, width, height);
}
/**
* Unbinds the frame buffer, setting the default frame buffer as the current
* render target. Anything rendered after this will be rendered to the
* screen, and not this FBO.
*/
public void unbindFrameBuffer() {
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight());
}
/**
* Binds the current FBO to be read from (not used in tutorial 43).
*/
public void bindToRead() {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, frameBuffer);
GL11.glReadBuffer(GL30.GL_COLOR_ATTACHMENT0);
}
/**
* #return The ID of the texture containing the colour buffer of the FBO.
*/
public int getColourTexture() {
return colourTexture;
}
/**
* #return The texture containing the FBOs depth buffer.
*/
public int getDepthTexture() {
return depthTexture;
}
/**
* Creates the FBO along with a colour buffer texture attachment, and
* possibly a depth buffer.
*
* #param type
* - the type of depth buffer attachment to be attached to the
* FBO.
*/
public void resolveToFbo(int readBuffer,Fbo outputFbo){
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER,outputFbo.frameBuffer);
GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER,this.frameBuffer);
GL11.glReadBuffer(readBuffer);
GL30.glBlitFramebuffer(0,0,width,height,0,0,outputFbo.width,outputFbo.height,GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT,GL11.GL_LINEAR);
this.unbindFrameBuffer();
}
public void resolveToScreen(){
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER,0);
GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER,this.frameBuffer);
GL11.glDrawBuffer(GL11.GL_BACK);
GL30.glBlitFramebuffer(0,0,width,height,0,0,Display.getWidth(),Display.getHeight(),GL11.GL_COLOR_BUFFER_BIT ,GL11.GL_LINEAR);
this.unbindFrameBuffer();
}
private void initialiseFrameBuffer(int type) {
createFrameBuffer();
if(multisampleMultiTargets){
colourBuffer = createMultisampledColourbuffer(GL30.GL_COLOR_ATTACHMENT0);
colourBuffer2 = createMultisampledColourbuffer(GL30.GL_COLOR_ATTACHMENT1);
}else{
createTextureAttachment();
}
if (type == DEPTH_RENDER_BUFFER) {
createDepthBufferAttachment();
} else if (type == DEPTH_TEXTURE) {
createDepthTextureAttachment();
}
unbindFrameBuffer();
}
/**
* Creates a new frame buffer object and sets the buffer to which drawing
* will occur - colour attachment 0. This is the attachment where the colour
* buffer texture is.
*
*/
private void createFrameBuffer() {
frameBuffer = GL30.glGenFramebuffers();
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBuffer);
determineDrawBuffer();
}
private void determineDrawBuffer(){
IntBuffer drawBuffers = BufferUtils.createIntBuffer(2);
drawBuffers.put(GL30.GL_COLOR_ATTACHMENT0);
if(this.multisampleMultiTargets){
drawBuffers.put(GL30.GL_COLOR_ATTACHMENT1);
}
drawBuffers.flip();
GL20.glDrawBuffers(drawBuffers);
}
/**
* Creates a texture and sets it as the colour buffer attachment for this
* FBO.
*/
private void createTextureAttachment() {
colourTexture = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, colourTexture);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE,
(ByteBuffer) null);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL11.GL_TEXTURE_2D, colourTexture,
0);
}
/**
* Adds a depth buffer to the FBO in the form of a texture, which can later
* be sampled.
*/
private void createDepthTextureAttachment() {
depthTexture = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, depthTexture);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL14.GL_DEPTH_COMPONENT24, width, height, 0, GL11.GL_DEPTH_COMPONENT,
GL11.GL_FLOAT, (ByteBuffer) null);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL11.GL_TEXTURE_2D, depthTexture, 0);
}
private int createMultisampledColourbuffer(int Attachment){
int colourBuffer = GL30.glGenRenderbuffers();
GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, colourBuffer);
GL30.glRenderbufferStorageMultisample(GL30.GL_RENDERBUFFER,4, GL11.GL_RGBA8, width, height);
GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER,Attachment, GL30.GL_RENDERBUFFER,
colourBuffer);
return colourBuffer;
}
/**
* Adds a depth buffer to the FBO in the form of a render buffer. This can't
* be used for sampling in the shaders.
*/
private void createDepthBufferAttachment() {
depthBuffer = GL30.glGenRenderbuffers();
GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBuffer);
if(!multisampleMultiTargets){
GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL14.GL_DEPTH_COMPONENT24, width, height);
}else{
GL30.glRenderbufferStorageMultisample(GL30.GL_RENDERBUFFER,4, GL14.GL_DEPTH_COMPONENT24, width, height);
}
GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL30.GL_RENDERBUFFER,
depthBuffer);
}
}
I've tried to implement an reaction-diffusion model on GPU with JOGL and GLSL.
I use a ping pong technique with 2 FramebufferObject ( I've tried too with one FBO and 2 Colors attachements without success).
Shader seems correct since I've tried it in unity (with some adaptations) and it works.
After one week of trying many things, i'm completely out of idea to make this code works. I'm really not specialist of JOGL, so maybe i miss something evident.
The result is an image which becomes white with time : no reaction-diffusion behaviors and I don't understand why !
Thanks in advance for helps. Here is my code :
package gpu2;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.nio.IntBuffer;
import java.nio.FloatBuffer;
import java.io.File;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.opengl.GLFBODrawable;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.FBObject.Colorbuffer;
import com.jogamp.opengl.FBObject.ColorAttachment;
import com.jogamp.opengl.FBObject.TextureAttachment;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.glsl.ShaderProgram;
import com.jogamp.opengl.util.glsl.ShaderUtil;
import com.jogamp.opengl.util.GLBuffers;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureIO;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLOffscreenAutoDrawable;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
import com.jogamp.opengl.GLDrawableFactory;
import static com.jogamp.opengl.GL.*; // GL constants
import static com.jogamp.opengl.GL2.*; // GL2 constants
import gpu2.ModelParam;
/**
* JOGL 2.0 Program Template (GLCanvas)
* This is a "Component" which can be added into a top-level "Container".
* It also handles the OpenGL events to render graphics.
*/
#SuppressWarnings("serial")
public class JOGL2Setup_GLCanvas extends GLCanvas implements GLEventListener {
// Define constants for the top-level container
private static String TITLE = "JOGL 2.0 Setup (GLCanvas)"; // window's title
private static final int CANVAS_WIDTH = 512; // width of the drawable
private static final int CANVAS_HEIGHT = 512; // height of the drawable
private static final int FPS = 30; // animator's target frames per second
private final float[] canvasVertices = {
-1f, -1f, 0.0f,
-1f, 1f, 0.0f,
1f, -1f, 0.0f,
1f, 1f, 0.0f,
};
private final float[] canvasTexCoords = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
};
/** The entry main() method to setup the top-level container and animator */
public static void main(String[] args) {
// Run the GUI codes in the event-dispatching thread for thread safety
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// Create the OpenGL rendering canvas
GLCanvas canvas = new JOGL2Setup_GLCanvas();
canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
// Create a animator that drives canvas' display() at the specified FPS.
final FPSAnimator animator = new FPSAnimator(canvas, FPS, true);
// Create the top-level container
final JFrame frame = new JFrame(); // Swing's JFrame or AWT's Frame
frame.getContentPane().add(canvas);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
// Use a dedicate thread to run the stop() to ensure that the
// animator stops before program exits.
new Thread() {
#Override
public void run() {
if (animator.isStarted()) animator.stop();
System.exit(0);
}
}.start();
}
});
frame.setTitle(TITLE);
frame.pack();
frame.setVisible(true);
animator.start(); // start the animation loop
}
});
}
// Setup OpenGL Graphics Renderer
private GLU glu; // for the GL Utility
private GL2 gl;
//OpenGl data
private int vboVertices;
private int vboTextCoord;
private Texture textureFile;
private FBObject fbo[];
private ShaderProgram shaderCompute;
private ShaderProgram shaderVisu;
private ShaderProgram shaderComputeInit;
private int currentSourceBuffer = 0;
private int currentDestBuffer = 1;
private int currentFrame = 0;
private int maxFrameCount = 5000000;
private float clearUniform = 0;
ModelParam params = new ModelParam();
public JOGL2Setup_GLCanvas() {
this.addGLEventListener(this);
}
#Override
public void init(GLAutoDrawable drawable) {
gl = drawable.getGL().getGL2(); // get the OpenGL graphics context
glu = new GLU(); // get GL Utilities
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // set background (clear) color
gl.glEnable(GL_TEXTURE_2D);
gl.glEnable( GL_COLOR_MATERIAL );
gl.glEnable( GL_FRAMEBUFFER );
gl.glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NEAREST); // best perspective correction
viewOrtho(gl);
gl.glViewport(0,0,CANVAS_WIDTH,CANVAS_HEIGHT);
int[] buffers = new int[2];
gl.glGenBuffers(2, buffers, 0);
vboVertices = buffers[0];
vboTextCoord = buffers[1];
gl.glBindBuffer(GL_ARRAY_BUFFER, vboVertices);
gl.glBufferData(GL_ARRAY_BUFFER, canvasVertices.length*(Float.SIZE/Byte.SIZE)*3, FloatBuffer.wrap(canvasVertices), GL_STATIC_DRAW);
gl.glBindBuffer(GL_ARRAY_BUFFER, vboTextCoord);
gl.glBufferData(GL_ARRAY_BUFFER, canvasTexCoords.length*(Float.SIZE/Byte.SIZE)*2, FloatBuffer.wrap(canvasTexCoords), GL_STATIC_DRAW);
gl.glBindBuffer( GL_ARRAY_BUFFER, 0 );
// ------------ create Texture Source------------------------
textureFile = initializeTexture();
if (textureFile==null) {
System.out.println("cannot load texture from disk");
}
// ------------ load shaders ------------------------
shaderCompute = loadShader(gl, "compute.vsh", "compute.fsh");
shaderComputeInit = loadShader(gl, "compute.vsh", "computeInit.fsh");
shaderVisu = loadShader(gl, "visu.vsh", "visu.fsh");
// ------------ create FBO ------------------------
initFBO();
}
/**
* Called back by the animator to perform rendering.
*/
#Override
public void display(GLAutoDrawable drawable) {
if (currentFrame < maxFrameCount) {
prepareNextStep();
renderToFBO();
currentFrame++;
}
renderFBOToScreen();
}
private void prepareNextStep() {
currentSourceBuffer = 1 - currentSourceBuffer;
currentDestBuffer = 1 - currentDestBuffer;
}
private void renderToFBO()
{
fbo[currentDestBuffer].bind(gl);
//gl.glClear(GL_COLOR_BUFFER_BIT);
viewOrtho(gl);
shaderCompute.useProgram(gl, true);
setShaderUniformFloat(gl, shaderCompute.program(), "diffuseU", 0.211f);
setShaderUniformFloat(gl, shaderCompute.program(), "diffuseV", 0.088f);
setShaderUniformFloat(gl, shaderCompute.program(), "feed", 0.007f);
setShaderUniformFloat(gl, shaderCompute.program(), "kill", 0.08f);
setShaderUniformFloat(gl, shaderCompute.program(), "Tech", 1f);
setShaderUniformFloat(gl, shaderCompute.program(), "currentFrame", currentFrame);
setShaderUniformFloat2(gl, shaderCompute.program(), "resolution", CANVAS_WIDTH, CANVAS_HEIGHT);
drawDataBuffer(shaderCompute, true);
shaderCompute.useProgram(gl, false);
fbo[currentDestBuffer].unbind(gl);
}
void drawDataBuffer(ShaderProgram currentShader, boolean sencondImage) {
// --- draw vbo
gl.glEnableClientState(GL_VERTEX_ARRAY);
gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//textcoords
gl.glBindBuffer(GL_ARRAY_BUFFER,vboTextCoord);
gl.glTexCoordPointer(2, GL_FLOAT, 0, 0);
//vertices
gl.glBindBuffer( GL_ARRAY_BUFFER, vboVertices );
gl.glVertexPointer(3, GL_FLOAT, 0, 0);
//activate texture data from last fbo
final FBObject.Colorbuffer texSource = (FBObject.Colorbuffer) fbo[currentSourceBuffer].getColorbuffer(0);
gl.glActiveTexture(GL_TEXTURE0);
gl.glBindTexture(GL_TEXTURE_2D, texSource.getName());
setShaderUniform1i(gl, currentShader.program(), "textureData", 0);
if (sencondImage) {
//activate texture with image from file
gl.glActiveTexture(GL_TEXTURE1);
gl.glBindTexture(GL_TEXTURE_2D, textureFile.getTextureObject());
textureFile.bind(gl);
setShaderUniform1i(gl, currentShader.program(), "textureImage", 1);
}
//draw buffer on screens
gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, canvasVertices.length / 3);
//disable texture image
if (sencondImage) {
gl.glActiveTexture(GL_TEXTURE1);
textureFile.disable(gl);
}
//disable texture data
gl.glActiveTexture(GL_TEXTURE0);
gl.glDisable(texSource.getName());
gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL_VERTEX_ARRAY);
}
public void renderFBOToScreen()
{
gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear color and depth buffers
gl.glLoadIdentity(); // reset the model-view matrix
viewOrtho(gl);
gl.glEnable(GL_TEXTURE_2D);
final FBObject.Colorbuffer tex0 = (FBObject.Colorbuffer) fbo[currentDestBuffer].getColorbuffer(0);
gl.glActiveTexture(GL_TEXTURE0);
gl.glBindTexture(GL_TEXTURE_2D, tex0.getName());
//activate shader
shaderVisu.useProgram(gl, true);
// --- draw vbo
gl.glEnableClientState(GL_VERTEX_ARRAY);
gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//textcoords
gl.glBindBuffer(GL_ARRAY_BUFFER, vboTextCoord);
gl.glTexCoordPointer(2, GL_FLOAT, 0, 0);
//vertices
gl.glBindBuffer( GL_ARRAY_BUFFER, vboVertices );
gl.glVertexPointer(3, GL_FLOAT, 0, 0);
//draw buffer on screens
gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, canvasVertices.length / 3);
gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL_VERTEX_ARRAY);
gl.glBindBuffer( GL_ARRAY_BUFFER, 0 );
//desactivate shader
shaderVisu.useProgram(gl, false);
}
private void initFBO()
{
try {
gl.glEnable(GL_TEXTURE_2D);
fbo = new FBObject[2];
//first fbo
fbo[currentSourceBuffer] = new FBObject(); // Create FrameBuffer
fbo[currentSourceBuffer].init(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0);
fbo[currentSourceBuffer].reset(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); // int width, height - size of FBO, can be resized with the same call
fbo[currentSourceBuffer].bind(gl);
int tex = genTexture(gl);
gl.glBindTexture(GL_TEXTURE_2D, tex);
gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, CANVAS_WIDTH, CANVAS_HEIGHT, 0, GL_RGBA, GL_FLOAT, null);
fbo[currentSourceBuffer].attachTexture2D(gl, 0, GL_RGBA32F, GL_RGBA, GL_FLOAT, GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
//gl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
int DrawBuffers[] = {GL_COLOR_ATTACHMENT0};
gl.glDrawBuffers(1, DrawBuffers, 0); // "1" is the size of DrawBuffers
fbo[currentSourceBuffer].unbind(gl);
//second fbo
fbo[currentDestBuffer] = new FBObject(); // Create FrameBuffer
fbo[currentDestBuffer].init(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0);
fbo[currentDestBuffer].reset(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); // int width, height - size of FBO, can be resized with the same call
fbo[currentDestBuffer].bind(gl);
tex = genTexture(gl);
gl.glBindTexture(GL_TEXTURE_2D, tex);
gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, CANVAS_WIDTH, CANVAS_HEIGHT, 0, GL_RGBA, GL_FLOAT, null);
fbo[currentDestBuffer].attachTexture2D(gl, 0, GL_RGBA32F, GL_RGBA, GL_FLOAT, GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
//ogl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
gl.glDrawBuffers(1, DrawBuffers, 1); // "1" is the size of DrawBuffers
fbo[currentDestBuffer].unbind(gl);
} catch (Exception e) {
System.out.println("Problem with fbo init " + e);
e.printStackTrace();
}
}
private Texture initializeTexture() {
Texture t = null;
try {
t = TextureIO.newTexture(new File("e:/shaders/wiki.jpg"), false);
t.setTexParameteri(gl, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
t.setTexParameteri(gl, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
t.setTexParameteri(gl, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
t.setTexParameteri(gl, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} catch (Exception e) {
System.out.println("Unable to read texture file: " + e);
e.printStackTrace();
}
return t;
}
private ShaderProgram loadShader(GL2 gl, String vertexShader, String fragmentShader)
{
ShaderCode vertShader = ShaderCode.create(gl, GL2.GL_VERTEX_SHADER, 1, getClass(), new String[]{"e:/shaders/"+vertexShader},false);
vertShader.compile(gl);
ShaderCode fragShader = ShaderCode.create(gl, GL2.GL_FRAGMENT_SHADER, 1, getClass(), new String[]{"e:/shaders/"+fragmentShader},false);
fragShader.compile(gl);
ShaderProgram newShader = new ShaderProgram();
newShader.init(gl);
newShader.add(vertShader);
newShader.add(fragShader);
newShader.link(gl, System.out);
vertShader.destroy(gl);
fragShader.destroy(gl);
return newShader;
}
public static void setShaderUniform1i(GL2 inGL,int inProgramID,String inName,int inValue) {
int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName);
if (tUniformLocation != -1) {
inGL.glUniform1i(tUniformLocation, inValue);
} else {
System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName);
}
}
public static void setShaderUniformFloat(GL2 inGL,int inProgramID,String inName,float inValue) {
int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName);
if (tUniformLocation != -1) {
inGL.glUniform1f(tUniformLocation, inValue);
} else {
System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName);
}
}
public static void setShaderUniformFloat2(GL2 inGL,int inProgramID,String inName,float inValue1 ,float inValue2) {
int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName);
if (tUniformLocation != -1) {
inGL.glUniform2f(tUniformLocation, inValue1, inValue2);
} else {
System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName);
}
}
private void viewOrtho(GL2 gl) // Set Up An Ortho View
{
gl.glMatrixMode(GL_PROJECTION); // Select Projection
gl.glPushMatrix(); // Push The Matrix
gl.glLoadIdentity(); // Reset The Matrix
gl.glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
gl.glMatrixMode(GL_MODELVIEW); // Select Modelview Matrix
gl.glPushMatrix(); // Push The Matrix
gl.glLoadIdentity(); // Reset The Matrix
}
private int genTexture(GL2 gl) {
final int[] tmp = new int[1];
gl.glGenTextures(1, tmp, 0);
return tmp[0];
}
/**
* Called back before the OpenGL context is destroyed. Release resource such as buffers.
*/
#Override
public void dispose(GLAutoDrawable drawable) { }
}
And the corresponding GLSL Shader :
#version 120
uniform sampler2D textureData;
uniform sampler2D textureImage;
uniform vec2 resolution;
uniform float diffuseU;
uniform float diffuseV;
uniform float feed;
uniform float kill;
uniform float Tech = 1.0;
uniform float currentFrame = 0.0;
void main() {
//coords
vec2 position = ( gl_FragCoord.xy / resolution.xy );
vec2 pixel = 1./resolution;
//get data from texture
vec4 imgSource = texture2D(textureImage, gl_TexCoord[0].st);
vec2 oldUV = texture2D(textureData, gl_TexCoord[0].st).rg;
if(currentFrame<10){
if (distance(position,vec2(0.5,0.5 - currentFrame * 0.01f)) < 0.2f)
oldUV = vec2(0.0,0.2);
else if (distance(position,vec2(0.5,0.5 - currentFrame * 0.01f)) < 0.3f)
oldUV = vec2(0.5,0.1);
else
oldUV = vec2(0.1,0.0);
gl_FragColor = vec4(oldUV.rg, 0.0, 1.0);
return;
}
//get neightboors
vec2 dataUp = texture2D(textureData, position + pixel * vec2(0., 1.)).rg;
vec2 dataDown = texture2D(textureData, position + pixel * vec2(0., -1.)).rg;
vec2 dataLeft = texture2D(textureData, position + pixel * vec2(-1., 0.)).rg;
vec2 dataRight = texture2D(textureData, position + pixel * vec2(1., 0.)).rg;
//adapt parameters
vec2 imgParam = imgSource.rg;
float dU = diffuseU ;//+ 0.01 * (imgParam - 0.5);
float dV = diffuseV ;//+ 0.01 * (imgParam - 0.5);
float F = feed ;//+ 0.01 * (imgParam - 0.5);
float K = kill ;//+ 0.01 * (imgParam - 0.5);
//compute new values
vec2 laplace = (dataUp+dataDown+dataLeft+dataRight) - 4.0 * oldUV;
float uvv = oldUV.r * oldUV.g * oldUV.g;
// calculate delta quantities
float du = dU * laplace.r - uvv + F*(1.0 - oldUV.r);
float dv = dV * laplace.g + uvv - (F+K)*oldUV.g;
vec2 newUV = oldUV + vec2(du, dv)* Tech;
gl_FragColor = vec4(newUV.rg, 0.0, 1.0);
}
Few considerations:
avoid deprecated OpenGL (and GLU), use GL4 (or GL3)
unless you need awt/swt/swing, prefer newt, more here
prefer Animator instead of FPSAnimator, more here
prefer direct buffers instead of arrays, since otherwise jogl has to create them underneath and you can't keep trace (= deallocate when done) of those native allocations
GL4 will allow you also to avoid all those uniform overhead (and also potential bugs) you have to deal with (especially during runtime), thanks to explicit locations
prefer direct buffer management instead of FBObject for the moment unless you really know what FBObject is doing. Once you get it working, you can move on using that class. This may be (one of the) cause your code is not working, because something is not getting setup up as you need. Moreover, the lines of codes needed to replace FBObject are essentially the same
(if you can't use explicit location for any reason) prefer some literal way to define the texture uniform location, it is usually another tricky part causing bugs, something like this
prefer also a sampler for the textures, gives you more flexibility
don't wait one week next time, let us know earlier! :) Frustation can be a nasty thing that put you down easily. Together we can help you getting it working ;)
I'm wondering how I would render a cube with a different PNG Texture on each side, and I'd like to stay away from other Third-Party Libraries other than LWJGL.
As of LWJGL3 bindings for the STB library have been included. This is a small single-file utility library that does things like loading textures, sound files or fonts.
For rendering a cube with a different texture on each side you have two options:
Render each face separately with another texture bound. This is the more straightforward option.
Make a texture atlas of all the textures and render the whole cube once. This is not as easy to do but will give better performance, especially when rendering multiple cubes.
Introductory tutorial on how to use textures. (It is in C++, but should be easy to convert to Java.)
Take a look at the LWJGL STBImage example.
/*
* Copyright LWJGL. All rights reserved.
* License terms: https://www.lwjgl.org/license
*/
package org.lwjgl.demo.stb;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;
import java.io.*;
import java.nio.*;
import java.util.*;
import static java.lang.Math.*;
import static org.lwjgl.demo.glfw.GLFWUtil.*;
import static org.lwjgl.demo.util.IOUtil.*;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.stb.STBImage.*;
import static org.lwjgl.stb.STBImageResize.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;
/** STB Image demo. */
public final class Image {
private final ByteBuffer image;
private final int w;
private final int h;
private final int comp;
private long window;
private int ww;
private int wh;
private boolean ctrlDown;
private int scale;
private Callback debugProc;
private Image(String imagePath) {
ByteBuffer imageBuffer;
try {
imageBuffer = ioResourceToByteBuffer(imagePath, 8 * 1024);
} catch (IOException e) {
throw new RuntimeException(e);
}
try (MemoryStack stack = stackPush()) {
IntBuffer w = stack.mallocInt(1);
IntBuffer h = stack.mallocInt(1);
IntBuffer comp = stack.mallocInt(1);
// Use info to read image metadata without decoding the entire image.
// We don't need this for this demo, just testing the API.
if (!stbi_info_from_memory(imageBuffer, w, h, comp)) {
throw new RuntimeException("Failed to read image information: " + stbi_failure_reason());
} else {
System.out.println("OK with reason: " + stbi_failure_reason());
}
System.out.println("Image width: " + w.get(0));
System.out.println("Image height: " + h.get(0));
System.out.println("Image components: " + comp.get(0));
System.out.println("Image HDR: " + stbi_is_hdr_from_memory(imageBuffer));
// Decode the image
image = stbi_load_from_memory(imageBuffer, w, h, comp, 0);
if (image == null) {
throw new RuntimeException("Failed to load image: " + stbi_failure_reason());
}
this.w = w.get(0);
this.h = h.get(0);
this.comp = comp.get(0);
}
}
public static void main(String[] args) {
String imagePath;
if (args.length == 0) {
System.out.println("Use 'ant demo -Dclass=org.lwjgl.demo.stb.Image -Dargs=<path>' to load a different image.\n");
imagePath = "lwjgl32.png";
} else {
imagePath = args[0];
}
new Image(imagePath).run();
}
private void run() {
try {
init();
loop();
} finally {
try {
destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void windowSizeChanged(long window, int width, int height) {
this.ww = width;
this.wh = height;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, width, height, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
private static void framebufferSizeChanged(long window, int width, int height) {
glViewport(0, 0, width, height);
}
private void init() {
GLFWErrorCallback.createPrint().set();
if (!glfwInit()) {
throw new IllegalStateException("Unable to initialize GLFW");
}
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
GLFWVidMode vidmode = Objects.requireNonNull(glfwGetVideoMode(glfwGetPrimaryMonitor()));
ww = max(800, min(w, vidmode.width() - 160));
wh = max(600, min(h, vidmode.height() - 120));
this.window = glfwCreateWindow(ww, wh, "STB Image Demo", NULL, NULL);
if (window == NULL) {
throw new RuntimeException("Failed to create the GLFW window");
}
// Center window
glfwSetWindowPos(
window,
(vidmode.width() - ww) / 2,
(vidmode.height() - wh) / 2
);
glfwSetWindowRefreshCallback(window, window -> render());
glfwSetWindowSizeCallback(window, this::windowSizeChanged);
glfwSetFramebufferSizeCallback(window, Image::framebufferSizeChanged);
glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
ctrlDown = (mods & GLFW_MOD_CONTROL) != 0;
if (action == GLFW_RELEASE) {
return;
}
switch (key) {
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, true);
break;
case GLFW_KEY_KP_ADD:
case GLFW_KEY_EQUAL:
setScale(scale + 1);
break;
case GLFW_KEY_KP_SUBTRACT:
case GLFW_KEY_MINUS:
setScale(scale - 1);
break;
case GLFW_KEY_0:
case GLFW_KEY_KP_0:
if (ctrlDown) {
setScale(0);
}
break;
}
});
glfwSetScrollCallback(window, (window, xoffset, yoffset) -> {
if (ctrlDown) {
setScale(scale + (int)yoffset);
}
});
// Create context
glfwMakeContextCurrent(window);
GL.createCapabilities();
debugProc = GLUtil.setupDebugMessageCallback();
glfwSwapInterval(1);
glfwShowWindow(window);
glfwInvoke(window, this::windowSizeChanged, Image::framebufferSizeChanged);
}
private void setScale(int scale) {
this.scale = max(-9, scale);
}
private void premultiplyAlpha() {
int stride = w * 4;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int i = y * stride + x * 4;
float alpha = (image.get(i + 3) & 0xFF) / 255.0f;
image.put(i + 0, (byte)round(((image.get(i + 0) & 0xFF) * alpha)));
image.put(i + 1, (byte)round(((image.get(i + 1) & 0xFF) * alpha)));
image.put(i + 2, (byte)round(((image.get(i + 2) & 0xFF) * alpha)));
}
}
}
private int createTexture() {
int texID = glGenTextures();
glBindTexture(GL_TEXTURE_2D, texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
int format;
if (comp == 3) {
if ((w & 3) != 0) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 2 - (w & 1));
}
format = GL_RGB;
} else {
premultiplyAlpha();
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
format = GL_RGBA;
}
glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, image);
ByteBuffer input_pixels = image;
int input_w = w;
int input_h = h;
int mipmapLevel = 0;
while (1 < input_w || 1 < input_h) {
int output_w = Math.max(1, input_w >> 1);
int output_h = Math.max(1, input_h >> 1);
ByteBuffer output_pixels = memAlloc(output_w * output_h * comp);
stbir_resize_uint8_generic(
input_pixels, input_w, input_h, input_w * comp,
output_pixels, output_w, output_h, output_w * comp,
comp, comp == 4 ? 3 : STBIR_ALPHA_CHANNEL_NONE, STBIR_FLAG_ALPHA_PREMULTIPLIED,
STBIR_EDGE_CLAMP,
STBIR_FILTER_MITCHELL,
STBIR_COLORSPACE_SRGB
);
if (mipmapLevel == 0) {
stbi_image_free(image);
} else {
memFree(input_pixels);
}
glTexImage2D(GL_TEXTURE_2D, ++mipmapLevel, format, output_w, output_h, 0, format, GL_UNSIGNED_BYTE, output_pixels);
input_pixels = output_pixels;
input_w = output_w;
input_h = output_h;
}
if (mipmapLevel == 0) {
stbi_image_free(image);
} else {
memFree(input_pixels);
}
return texID;
}
private void loop() {
int texID = createTexture();
glEnable(GL_TEXTURE_2D);
glClearColor(43f / 255f, 43f / 255f, 43f / 255f, 0f);
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
render();
}
glDisable(GL_TEXTURE_2D);
glDeleteTextures(texID);
}
private void render() {
glClear(GL_COLOR_BUFFER_BIT);
float scaleFactor = 1.0f + scale * 0.1f;
glPushMatrix();
glTranslatef(ww * 0.5f, wh * 0.5f, 0.0f);
glScalef(scaleFactor, scaleFactor, 1f);
glTranslatef(-w * 0.5f, -h * 0.5f, 0.0f);
glBegin(GL_QUADS);
{
glTexCoord2f(0.0f, 0.0f);
glVertex2f(0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(w, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(w, h);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(0.0f, h);
}
glEnd();
glPopMatrix();
glfwSwapBuffers(window);
}
private void destroy() {
if (debugProc != null) {
debugProc.free();
}
glfwFreeCallbacks(window);
glfwDestroyWindow(window);
glfwTerminate();
Objects.requireNonNull(glfwSetErrorCallback(null)).free();
}
}
edit: link updated and copied link contents.
I'm very new to IDEA, and I wonder why my Custom Component can't be added to the GUI. I created a new project and added a new GUI and a new class which is a Component.
Here's the code for the Component:
package comps;
import javax.swing.*;
/**
* Created by danielmartin1 on 25.03.15.
*/
public class TestComp extends JLabel {
}
I'm using OSX Yosemite, with the JDK 1.8
Hope anyone can help me.
Using the custom bundled IDEA helped. Now i can add any Custom Component the GUI.
But there are now some other problems:
First, the component doesn't look as it should in the form editor (it looks like a combobox),
and Second: My program crashes when trying to run if the layout is set to GridlayoutManager(IntelliJ). With Borderlayout selected, it is running and my component is shown (only at runtime) correctly.
So here is the code for my component:
package gui;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
public class CustomTracker extends JComponent implements MouseListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private boolean isSelected = false;
public String getText() {
return text;
}
public String text;
public int fontSize = 13;
private ImageIcon iIBack = new ImageIcon(getClass().getResource("/CheckBox/Tracker_Back.png"));
private ImageIcon iIButton = new ImageIcon(getClass().getResource("/CheckBox/Tracker_Button.png"));
private ImageIcon stretchedBack, stretchedButton;
private Font fontTracker = new Font("Arial", Font.BOLD, fontSize);
private Font fontText = new Font("Arial", Font.BOLD, fontSize);
private Color textColor = new Color(103, 125, 129);
private Color buttonColor = new Color(255, 255, 255);
private int backOriginalWidth, backOriginalHeight;
private int buttonOriginalWidth, buttonOriginalHeight;
private float scale = .7f;
/**
* Constructor
*
* #param text
* set the text of this component
*/
public CustomTracker(String text) {
this.text = text;
this.setSize(this.getWidth(), iIBack.getIconHeight());
this.addMouseListener(this);
this.backOriginalWidth = iIBack.getIconWidth();
this.backOriginalHeight = iIBack.getIconHeight();
this.buttonOriginalWidth = iIButton.getIconWidth();
this.buttonOriginalHeight = iIButton.getIconHeight();
// Stretch Back
Image img = iIBack.getImage();
Image newimg = img.getScaledInstance((int) (backOriginalWidth * scale), (int) (backOriginalHeight * scale), java.awt.Image.SCALE_SMOOTH);
stretchedBack = new ImageIcon(newimg);
// Stretch Button
img = iIButton.getImage();
newimg = img.getScaledInstance((int) (buttonOriginalWidth * scale), (int) (buttonOriginalHeight * scale), java.awt.Image.SCALE_SMOOTH);
stretchedButton = new ImageIcon(newimg);
// stretch font
this.fontSize = (int)(this.fontSize * scale);
this.fontTracker = new Font("Arial", Font.BOLD, fontSize);
}
/**
* get selected value
*/
// #Override
// public boolean isSelected() {
// return this.isSelected;
// }
/**
* set selected value
*
* #param selected
* the value
*/
public void setSelected(boolean selected) {
this.isSelected = selected;
}
#Override
public Dimension getMinimumSize() {
return new Dimension(this.getWidth(), this.getHeight());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(this.getWidth(), this.getHeight());
}
/**
* paint the component
*
* #param g
* the graphics object
*/
protected void paintComponent(Graphics g) {
// create a Graphics2D Object
Graphics2D g2d = (Graphics2D) g.create();
// Draw Box Image
g2d.drawImage(stretchedBack.getImage(), 0, 0, stretchedBack.getIconWidth(), stretchedBack.getIconHeight(), this);
// Set Font-Values
g2d.setFont(fontTracker);
g2d.setColor(buttonColor);
// Set text coordinates
int x;
int y = (int) (((iIBack.getIconHeight() / 2) + (fontSize / 2) + 1) * scale);
if (this.isSelected == true) {
g2d.drawImage(stretchedButton.getImage(), (int) (40 * scale), (int) (2 * scale), stretchedButton.getIconWidth(),
stretchedButton.getIconHeight(), this);
x = (int) (15 * scale);
g2d.drawString("ON", x, y);
} else {
g2d.drawImage(stretchedButton.getImage(), 0, (int) (2 * scale), stretchedButton.getIconWidth(), stretchedButton.getIconHeight(), this);
x = (int) (37 * scale);
g2d.drawString("OFF", x, y);
}
// Draw ON or OFF
g2d.drawString(getText(), (int)((iIBack.getIconWidth() + 10) * scale), y);
// Set Font-Values
g2d.setFont(fontText);
g2d.setColor(textColor);
// Set new y-Position
y = ((stretchedBack.getIconHeight() / 2) + (fontSize / 2) + 1);
// draw the text behind the Control
g2d.drawString(getText(), stretchedBack.getIconWidth() + 10, y);
// dispose Variables
g2d.dispose();
}
#Override
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, width, height);
}
/**
* set the text of this component
*
* #param text
* the text to display
*/
public void setText(String text) {
setText(text);
}
public void mouseClicked(MouseEvent e) {
this.isSelected = !this.isSelected;
repaint();
}
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}
Does anyone know a solution for these problems?
i am stuck on how to go ahead on creating a simple game for my project, it is simply a puzzle game where i have a image on the background and boxes will be covering the image, the boxes are to be matched and when matched they will remove themselves to reveal part of the image, currently what i have done is to draw the grids but how can i make them stacked against each other? do i make each generated grid a imageitem?
The canvas of generating the blocks
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.Sprite;
public class blockcanvas extends Canvas
{
private Image pokeballImage;
private int screenW,screenH,imageW,imageH;
public blockcanvas()
{
//get screen size
screenW = getWidth();
screenH = getHeight();
try {
pokeballImage = Image.createImage("/pokeball.png");
imageW = pokeballImage.getWidth();
imageH = pokeballImage.getHeight();
} catch (IOException e) {
e.printStackTrace();
}
}
protected void paint(Graphics g) {
g.setColor(255,255,255);
g.fillRect(0,0,getWidth(),getHeight());
drawPokeBall(g);
}
public void drawPokeBall(Graphics g)
{
int maxNumberOfBlockX = screenW / imageW;
int maxNumberOfBlockY = screenH / imageH;
Sprite pokeball = new Sprite(pokeballImage);
pokeball.defineCollisionRectangle(0,0,20,20);
pokeball.defineReferencePixel(imageW/2,imageH/2);
for (int i = 0; i <maxNumberOfBlockX; i++)
{
pokeball.setRefPixelPosition(i*20,0);
pokeball.paint(g);
}
for (int i = 0; i <maxNumberOfBlockY; i++)
{
pokeball.setRefPixelPosition(0,i*20);
pokeball.paint(g);
}
System.out.println(maxNumberOfBlockX);
}
}
The canvas for the image to be covered by blocks
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class gameCanvas extends Canvas
{
private Image image;
private int screenW,screenH;
blockcanvas block;
public gameCanvas()
{
block = new blockcanvas();
//get screen size
screenW = getWidth()/2;
screenH = getHeight()/2;
try {
image = Image.createImage("/gby001.gif");
} catch (IOException e) {
e.printStackTrace();
}
}
protected void paint(Graphics g) {
g.setColor(255,255,255);
g.fillRect(0,0,getWidth(),getHeight());
g.drawImage(resizeImage(image), 10, 10, Graphics.TOP | Graphics.LEFT);
block.drawPokeBall(g);
}
private Image resizeImage(Image src) {
int srcWidth = src.getWidth();
int srcHeight = src.getHeight();
Image tmp = Image.createImage(screenW, srcHeight);
Graphics g = tmp.getGraphics();
int ratio = (srcWidth << 16) / screenW;
int pos = ratio/2;
//Horizontal Resize
for (int x = 0; x < screenW; x++) {
g.setClip(x, 0, 1, srcHeight);
g.drawImage(src, x - (pos >> 16), 0, Graphics.LEFT | Graphics.TOP);
pos += ratio;
}
Image resizedImage = Image.createImage(screenW, screenH);
g = resizedImage.getGraphics();
ratio = (srcHeight << 16) / screenH;
pos = ratio/2;
//Vertical resize
for (int y = 0; y < screenH; y++) {
g.setClip(0, y, screenW, 1);
g.drawImage(tmp, 0, y - (pos >> 16), Graphics.LEFT | Graphics.TOP);
pos += ratio;
}
return resizedImage;
}//resize image
}
The main app
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import javax.microedition.lcdui.Canvas;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.io.*;
/**
* #author Lotus
*/
public class game extends MIDlet implements CommandListener{
//Variables Declartion
private Display theDisp;
private Command cmdExit,cmdGuess,cmdReturn;
private gameCanvas canvas1;
private blockcanvas canvas2;
private Image gameImage;
public game()
{
theDisp = Display.getDisplay(this);
cmdExit = new Command("Exit",Command.EXIT,1);
cmdGuess = new Command("Guess",Command.SCREEN,2);
cmdReturn = new Command("Back",Command.BACK,2);
canvas1 = new gameCanvas();
canvas2 = new blockcanvas();
canvas1.addCommand(cmdExit);
canvas1.addCommand(cmdGuess);
canvas1.setCommandListener(this);
}
public void startApp() {
theDisp.setCurrent(canvas1);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command c, Displayable d) {
if(c == cmdExit)
{
destroyApp(true);
notifyDestroyed();
}
else if(c== cmdGuess)
{
}
}
}
You may want to change
g.fillRect(i, i, 20, 20);
to something like
g.fillRect(i*20, i*20, 20, 20);