Problems with Particles

Started by penguin, April 06, 2011, 13:55:30

Previous topic - Next topic

Fool Running

Do you have any setup on the points rendering? (i.e. Are you enabling GL_POINT_SMOOTH (round points instead of square) and/or GL_POINT_SPRITE_ARB (drawing points with generated texture coordinates)?)
If so, try disabling them. Certain combinations of settings for points rendering don't work correctly and result is the points not showing up.

EDIT:
The problem I remember was when you enable GL_POINT_SMOOTH and GL_POINT_SPRITE_ARB at the same time. The points don't show up (and will suffer performance-wise).
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

jediTofu

This was made back when I was first learning LWJGL.  I tried to clean it up a bit.  It also had tons and tons of testing stuff I was doing that I had to strip out to just have particle stuff haha.  It's not very good, just very very simple particle system.  This may help you figure out the problem.  There's actually a pretty good particle system tutorial/demo somewhere using LWJGL; maybe the ninja cave tutorials?

I was just going to add it as an attachment...but these forums won't let you attach a .java file......oh, the irony

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

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.LinkedList;
import java.util.ListIterator;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Cursor;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.Log;

/**
 * @author jediTofu
 */
public class Particles {
  public static void main(String[] args) {
    Particles p = null;
    try {
      p = new Particles();
      while(!Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)
        && !Display.isCloseRequested()) {
        if(Display.isVisible()) {
          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
          p.run();
        }
        else {
          try { Thread.sleep(100); } catch(Exception e) {}
        }
        Display.update();
        Display.sync(100);
      }
    }
    catch(Exception ex) {
      ex.printStackTrace();
      System.exit(1300);
    }
    finally {
      if(p != null) {
        p.destroy();
      }
    }
  }

  //lwjgl
  public static int HEIGHT = 768;//Display.getDesktopDisplayMode().getHeight();
  public static int WIDTH = 1024;//Display.getDesktopDisplayMode().getWidth();
  public static boolean IS_FULLSCREEN = false;
  public static boolean MOUSE_IS_GRABBED = false;

  //particles
  public static int MAX_PARTICLES = 1000;
  public static int PARTICLE_HEIGHT = 64;
  public static int PARTICLE_WIDTH = 64;
  public static float PARTICLE_X_FACTOR = 4.0f;
  public static float PARTICLE_Y_FACTOR = 4.0f;
  public LinkedList<Particle> particleList = new LinkedList<Particle>();
  public Texture particleTexture = null;
  public int particleX = 0;
  public int particleY = 0;

  public Particles() throws LWJGLException,FileNotFoundException,IOException {
    //progress bar
    int progress = 0;

    JProgressBar progressBar = new JProgressBar(0,5);
    progressBar.setPreferredSize(new Dimension(300,50));
    progressBar.setStringPainted(true);

    JLabel label = new JLabel("Loading...",JLabel.CENTER);

    JPanel panel = new JPanel(new BorderLayout());
    panel.add(progressBar,BorderLayout.PAGE_START);
    panel.add(label,BorderLayout.CENTER);

    JDialog dialog = new JDialog((JDialog)null,"Loading");
    dialog.setAlwaysOnTop(true);
    dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
    dialog.getContentPane().add(panel);
    dialog.pack();
    dialog.setLocationRelativeTo(null);
    dialog.setVisible(true);
    dialog.toFront();

    //lwjgl
    label.setText("Setting up LWJGL Display...");
    Display.setDisplayMode(findDisplayMode(WIDTH,HEIGHT));
    Display.setFullscreen(IS_FULLSCREEN);
    Display.setTitle("Particles");
    Display.create();
    dialog.setLocationRelativeTo(null);
    progressBar.setValue(++progress);

    label.setText("Setting up LWJGL Keyboard...");
    Keyboard.create();
    progressBar.setValue(++progress);

    label.setText("Setting up LWJGL Mouse...");
    Mouse.create();
    Mouse.setGrabbed(MOUSE_IS_GRABBED);
    progressBar.setValue(++progress);

    //opengl
    label.setText("Setting up OpenGL...");
    glEnable(GL_TEXTURE_2D);
		glShadeModel(GL_SMOOTH);
		glDisable(GL_DEPTH_TEST);
		glDisable(GL_LIGHTING);

    glClearColor(0.0f,0.0f,0.0f,0.0f);
    glClearDepth(1.0);

    glAlphaFunc(GL_GREATER,0.1f) ;
    glEnable(GL_ALPHA_TEST) ;

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

    glViewport(0,0,WIDTH,HEIGHT);
    glMatrixMode(GL_MODELVIEW);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0,WIDTH,0.0,HEIGHT,1.0,-1.0);
    glMatrixMode(GL_MODELVIEW);
    progressBar.setValue(++progress);

    //texture
    label.setText("Loading Textures...");
    particleTexture = TextureLoader.getTexture("PNG",new FileInputStream("particle.png"));
    progressBar.setValue(++progress);

    dialog.dispose();
  }

  public void destroy() {
    if(particleTexture != null) {
      particleTexture.release();
    }
    Mouse.destroy();
    Keyboard.destroy();
    Display.destroy();
  }

  public void drawParticle(float x,float y,float red,float green,float blue,float alpha) {
    x -= particleX + (PARTICLE_WIDTH / 2);
    y -= particleY + (PARTICLE_HEIGHT / 2);

    particleTexture.bind();
    //glPushMatrix();
    //glTranslatef(x,y,0);
    glColor4f(red,green,blue,alpha);
    glBegin(GL_QUADS);
    glTexCoord2f(0,0);
    glVertex2f(x,y);
    glTexCoord2f(1,0);
    glVertex2f(x + particleTexture.getTextureWidth(),y);
    glTexCoord2f(1,1);
    glVertex2f(x + particleTexture.getTextureWidth(),y + particleTexture.getTextureHeight());
    glTexCoord2f(0,1);
    glVertex2f(x,y + particleTexture.getTextureHeight());
    glEnd();
    //glPopMatrix();
  }

  public DisplayMode findDisplayMode(int width,int height) {
    return(findDisplayMode(width,height,Display.getDesktopDisplayMode().getBitsPerPixel()));
  }

  public DisplayMode findDisplayMode(int width,int height,int bpp) {
    try {
      for(DisplayMode mode: Display.getAvailableDisplayModes()) {
        if(mode.getBitsPerPixel() == bpp && mode.getHeight() == height
          && mode.getWidth() == width) {
          return(mode);
        }
      }
    }
    catch(LWJGLException ex) {
    }
    return(null);
  }

  public void run() {
    //drawParticle(0,0,1.0f,0.0f,0.0f,1.0f);

    for(ListIterator<Particle> it = particleList.listIterator(); it.hasNext();) {
      Particle p = it.next();
      if(p.isDead()) {
        it.remove();
        p = null;
      }
      else {
        p.play();
        p.age(1.0);
      }
    }

    if(particleList.size() < MAX_PARTICLES
      && (Mouse.getDX() != 0 || Mouse.getDY() != 0)) {
      for(int i = 0; i < 40; i++) {
        float red=0.0f,green=0.0f,blue=0.0f;
        switch((int)(Math.random() * 4.0)) {
          case 0: red   = (float)Math.random(); break;
          case 1: green = (float)Math.random(); break;
          case 2: blue  = (float)Math.random(); break;
          case 3: red = green = blue = (float)Math.random(); break;
        }

        particleList.add(new Particle
          ((float)Math.random() / 40.0f
          ,Mouse.getX()
          ,Mouse.getY()
          ,(float)Math.random() + (float)(int)(Math.random() * PARTICLE_X_FACTOR) * ((int)(Math.random() * 2.0) == 0 ? 1 : -1)
          ,(float)Math.random() + (float)(int)(Math.random() * PARTICLE_Y_FACTOR) * ((int)(Math.random() * 2.0) == 0 ? 1 : -1)
          ,red,green,blue));
      }
    }
  }

  public class Particle {
    private float blue;
    private float green;
    private float lifespan;
    private float lifeVelocity;
    private float red;
    private float x;
    private float xVelocity;
    private float y;
    private float yVelocity;

    public Particle(float lifeVelocity,float x,float y,float xVelocity,float yVelocity,float red,float green,float blue) {
      this.blue = blue;
      this.green = green;
      this.lifespan = 1.0f;
      this.lifeVelocity = lifeVelocity;
      this.red = red;
      this.x = x;
      this.xVelocity = xVelocity;
      this.y = y;
      this.yVelocity = yVelocity;
    }

    // delta is meant for smoother timing, but not using it right now up above
    public void age(double delta) {
      /*switch((int)(Math.random() * 2)) {
        case 0: x -= xVelocity; break;
        case 1: x += xVelocity; break;
      }
      switch((int)(Math.random() * 2)) {
        case 0: y -= yVelocity; break;
        case 1: y += yVelocity; break;
      }*/
      x += xVelocity * delta;
      y += yVelocity * delta;
      lifespan -= lifeVelocity * delta;
      if(lifespan < 0.0f) {
        lifespan = 0.0f;
      }
    }

    public boolean isDead() {
      return(lifespan <= 0.0f || x < (-PARTICLE_WIDTH) || x > WIDTH
        || y < (-PARTICLE_HEIGHT) || y > HEIGHT);
    }

    public void play() {
      /*glColor3f(red * lifespan,green * lifespan,blue * lifespan);
      glBegin(GL_POINTS);
      glVertex2f(x * lifespan,y / lifespan);
      glVertex2f(x,y);
      glEnd();*/
      //drawParticle(x * lifespan,y / lifespan,red,green,blue,lifespan);
      drawParticle(x,y,red,green,blue,lifespan);
    }
  }
}
cool story, bro

penguin

I've tried my things now, but my Object will still get drawn without a texture if the particle emitter is added to my "world".
If I don't add the emitter to my "world", my figure will get drawn with textures.

I've uploaded a version of my full code, because i think i've posted not enough code.

It's uploaded here: http://www.xup.in/dl,67746377/IceEngine.zip/

I hope someone can help me, I've worked on this for much hours now.

Edit://

Found the mistake, but don't know how to fix it.
When the particles colour is set, the model that should have a texture gets the same colour.

CodeBunny

I don't really have time to go through your engine, but it sounds to me like you only bind your texture once.

If you disable and enable textures, I believe that the end result is that you don't have any texture bound - as if you had called GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0).

So, for each time you render your object, bind the texture again and see what happens.

I'm pretty sure this is your problem. In your initial particle code, you called:

        GL11.glBegin(GL11.GL_TRIANGLE_STRIP);

        GL11.glColor3f(myColor.getRed(), myColor.getGreen(), myColor.getBlue());
        position.z = - 2.0f;
        GL11.glVertex3f(position.x+size, position.y+size, position.z);
        GL11.glVertex3f(position.x-size, position.y+size, position.z);
        GL11.glVertex3f(position.x+size, position.y-size, position.z);
        GL11.glVertex3f(position.x-size, position.y-size, position.z);

        GL11.glEnd();


There isn't any code to map each vertex to a texture coordinate. Thus, they all have the same coordinate and you get a monochromatic quad, and if that's a transparent spot, you obviously don't see anything.

penguin

I have no problems with particles anymore, I patched everything and it now runs fine, but the other stuff won't work if my ParticleEmitter is added to the world.
This is because i set the Color for the Particles in each draw and if i draw another Object (Like an Model with UV-Mapping) it have the same color like my particles and there is no texture on them.

But if i don't add the ParticleEmitter to the World the Models get drawn fine, so i think i must clear some type of a colorbuffer in opengl.

CodeBunny

When you draw your models, do you re-bind the texture every time you pass through the rendering code?