Skip to main content
GameDev.net gamedev.net
🔒 Locked

Particle Engine Help(Code Included)

Started by Cakey Dec 11, 2008 at 3:11 PM 3 replies 1k views
Original Post
Cakey
Cakey
Hello I am working on my first particle engine ever. I think I understand the concept however it seems to be opperating pretty sluggish,50fps or so for 30 particles + game. My game before my particle engine was pumping along at about 90 fps+ and it's not complex at all. So correct me if I am wrong here, A particle is a quad floating infront of your screen(HUD of sorts?) textured using alpha-blending(to remove transparent colors). The way that these particles move are based then on other commands described. For my code I am trying to imitate snow, not perfectly by any means but I was wondering if anyone could introduce me to some GL Commands that might speed up what I am doing, or present a better method in doing this. I am not asking you for your particle engine or your code, just like he use this "blank" method in the GL object to texture it it renders quicker or something. YES I did read the NeHe ported tutorial however I couldn't figure out how to get his example running in/with my game without it either not being rendered or it consuming all of my other renderings(possibly having to do with the fact that I do not have the .getPixles() command in my JOGL library)... So i just wrote my own from scratch that is obviously insufficient...
import javax.media.opengl.GL;
import com.sun.opengl.util.texture.*;

public class ParticleHandler {
    private static final int MAX_PARTICLES = 30;
    private ImageHandler images = new ImageHandler();
    private Texture particleTexture;
    private int ScreenWidth, ScreenHeight; 
    private static class Particle {
        boolean alive = true;
        float fade;
        float speed;
        float[] xyz = {0, 0, 0};
        float[] size = {4.0f, 4.0f};
        double angle = 0;
    }
    
    private Particle[] particles = new Particle[MAX_PARTICLES];

    public void prepareParticles(GL gl, int ScreenW, int ScreenH) {
    	particleTexture = images.loadTexture("Particle.png");
    	ScreenWidth = ScreenW;
    	ScreenHeight = ScreenH;
        for (int loop = 0; loop < MAX_PARTICLES; loop++) {
            particles[loop] = new Particle();
            particles[loop].fade = (float) (2.0 * Math.random());  
            particles[loop].speed = (float) 1;
            particles[loop].xyz[0] = (float) (ScreenW * Math.random());
            particles[loop].xyz[1] = (float) (ScreenH * Math.random());
            particles[loop].angle = Math.toRadians(90);
        }
    }
    public void renderParticles(GL gl) {
    	gl.glEnable(GL.GL_BLEND);
	    	gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
	    	gl.glEnable(GL.GL_ALPHA_TEST);
	    	gl.glAlphaFunc(GL.GL_GREATER, 0);
		gl.glEnable(GL.GL_TEXTURE_2D);
		particleTexture.bind();

		gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
    	
        for (int loop = 0; loop < MAX_PARTICLES; loop++) {
            if (particles[loop].alive == true) {
            	float x = particles[loop].xyz[0], y = particles[loop].xyz[1], z = particles[loop].xyz[2];
                x += (float) (Math.cos(particles[loop].angle) * (particles[loop].speed));
                particles[loop].xyz[0] = x;
                y += (float) (Math.sin(particles[loop].angle) * (particles[loop].speed));
                particles[loop].xyz[1] = y;
                if(x > ScreenWidth || y > ScreenHeight || x < 0 || y < 0){particles[loop].alive = false;}
                
            	float xSize = particles[loop].size[0] * particles[loop].fade;
            	float ySize = particles[loop].size[1] * particles[loop].fade;
            	
                if(particles[loop].alive == true){
                	gl.glBegin(GL.GL_TRIANGLE_STRIP);
		                gl.glTexCoord2d(1, 1);
		                gl.glVertex3f(x + xSize, y + ySize, z);
		                gl.glTexCoord2d(0, 1);
		                gl.glVertex3f(x - xSize, y + ySize, z);
		                gl.glTexCoord2d(1, 0);
		                gl.glVertex3f(x + xSize, y - ySize, z);
		                gl.glTexCoord2d(0, 0);
		                gl.glVertex3f(x - xSize, y - ySize, z);
	                gl.glEnd();
                }
                if(particles[loop].alive == false){
                	particles[loop].xyz[0] = (float) (ScreenWidth * Math.random());
                    particles[loop].xyz[1] = (float) ((ScreenHeight/10) * Math.random());
                    particles[loop].alive = true;
                    particles[loop].fade = (float) (2.0 * Math.random());  
                }
            }
        }
		gl.glDisable(GL.GL_TEXTURE_2D);
		gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);
		gl.glDisable(GL.GL_ALPHA);gl.glDisable(GL.GL_BLEND);
    }
}
deadstar
deadstar
The only problem I can see is that you're rendering in immediate mode, although I'm unsure 30 quads would slow down an application that much.

First, try using a display list for the quad, and adjust the position and scale with glTranslate/glScale instead. If there's no significant improvement, take a look at vertex arrays and VBOs instead.
"The right, man, in the wrong, place, can make all the dif-fer-rence in the world..." - GMan, Half-Life 2   A blog of my SEGA Megadrive development adventures: http://www.bigevilcorporation.co.uk
Cakey
Cakey
You know what you are right about that translate(rather then just placing the vertices at different locations). I ran into that problem before.

In the NeHe example he uses a different method of texturing, lemme dig it up,
    private void loadGLTextures(GL gl) {   // Load image And Convert To Textures        TextureReader.Texture texture = null;        try {            texture = TextureReader.readTexture("demos/data/images/Particle.png");        } catch (IOException e) {            e.printStackTrace();            throw new RuntimeException(e);        }        gl.glGenTextures(1, textures, 0);  // Create Three Textures        // Create Nearest Filtered Texture        gl.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);        gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, 3, texture.getWidth(),                 texture.getHeight(), 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, texture.getPixels());    }
NeHe Particle Engine

Do you think that whatever in the lord's name this dude is doing here to texture his image would be more effecient then what I have? I realize he did something different to his textures in this example so he could alter their overall hues(would be a nice feature to have in mine XD).

Not to sound like a noob but I guess I am to the JOGL scene, but whaddya mean immediate mode(IE: ModelView, )?


Also thank you for the good input. :) Hopefully I can return the favor.
havok4567
havok4567
Immediate mode is using glBegin, glEnd and glVertex etc to pass individual vertices with function calls. This causes some overhead and can be made more efficient by defining an array (VBO or Vertex Buffer Object) that contains the vertice information for the object and passing it directly to your graphics card.
Cakey
Cakey
Everyday I learn something new:), I shall play with this VBO right after I read about it on that shwing tool known as google. Thanks.
[Edit:] Not going to lie there isn't too much info out there on JOGL VBO's. The NeHe tutorial only covers height-maps...Not the easiest step to take when your trying to understand primitives..

[Edited by - Cakey on December 11, 2008 8:33:23 PM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.