Jump to content
  • Advertisement
Sign in to follow this  
Darragh

[solved] Vertex array woes

This topic is 4821 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Sigh.. Another day, another problem! This time from my old favorites- vertex arrays. [depressed] I have a little particle system up and running, but it is slow as hell because i'm using imediate mode rendering. This is always the way I do things, get it working first- then optimise later. Now its time to optimise, so I've chosen to use VAs to render my particles. Now this should have been easy enough since I've become used to using VAs- not so it seems. When I go to render my particles, the vertices are completely messed up altogether and everything is rendered pitch black. Something is *not* right but I can't finger what it is. I'm after going through the code time and again with a fine tooth comb and looked back at many examples of using VAs- everything appears correct. I'm completely stumped so maybe you guys might be able to help me spot where the problem is... Ok so here is a brief explanation of how I render my particles: 1- The vertices of the particles are passed in. The coordinates are centered around the origin and do not change- think of the particle vertices as being like a 'model' to which further transformations / rotations are performed to get it in the right position. 2- The vertices are rotated around the origin to face the camera by a vertex program. 3- The vertices are then translated by the particles position in world space. The particles position in world space is what I call the 'hinge'. The actual 'hinge' is passed into the vertex program as a normal- which is fine since I am not using lighting or anything like that. 4- Approriate colors and uv coords are also passed in etc.. I maintain a set of buffers to hold all of the data for the particles. The buffers are large enough to hold the maximum amount of particles which the program will allow. When I need to draw particles the relevant data is pushed onto these buffers and then drawn. Here is the actual code which sets up the buffers- i don't think there is any problem here though:

static void initParticles()
{
// CREATE SPARE PARTICLE OBJECTS

for ( int x = 0 ; x < MAX_PARTICLES ; x ++ )
	{
	
	particles[x] = new Particle
		(
		10000,
		
		0.0f,
		0.0f,
		0.0f,
		
		0.0f,
		0.0f,
		0.0f,
		
		0.0f,
		0.0f,
		0.0f
		
		);
	}
	
// ALLOCATE ENOUGH MEMORY FOR THE BUFFERS->

texCoordBuffer 	= BufferUtils.newFloatBuffer(2*4*MAX_PARTICLES);
vertexBuffer 	= BufferUtils.newFloatBuffer(3*4*MAX_PARTICLES);
colorBuffer 	= BufferUtils.newFloatBuffer(4*4*MAX_PARTICLES);
hingeBuffer 	= BufferUtils.newFloatBuffer(3*4*MAX_PARTICLES);

// INITALISE THE TEXCOORD BUFFER- WILL NOT CHANGE AGAIN:

for ( int x = 0; x < MAX_PARTICLES; x++)
	{
	
	texCoordBuffer.put
		(
		new float[]
			{
			0f,1f,
			1f,1f,
			1f,0f,
			0f,0f
			}
		);
	
	}

}





Now here is the actual rendering code for the particles- and most likely where the problem lies. Though I cannot see anything wrong with this code:

static void drawAllParticles(GL myGL)
{

// NO ACTIVE PARTICLES AT FIRST:

numActiveParticles = 0;

// RESET BUFFERS TO THE START:

vertexBuffer.position	(0);
colorBuffer.position	(0);
hingeBuffer.position	(0);

for ( int x = 0 ; x < MAX_PARTICLES ; x++ )
	{
	
	particle = particles[x];
	
	if 	( particle.particleActive )
		{
		
		// INCREASE NUMBER OF PARTICLES TO BE RENDERED //////////
		
		numActiveParticles++;
		
		/////////////////////////////////////////////////////////
		// ADD VERTICES TO THE BUFFER ///////////////////////////

		vertexBuffer.put
			(
			new float[] 
				{
				-particle.PARTICLE_SIZE,
				-particle.PARTICLE_SIZE,
				0
				
				+particle.PARTICLE_SIZE,
				-particle.PARTICLE_SIZE,
				0
			
				+particle.PARTICLE_SIZE,
				+particle.PARTICLE_SIZE,
				0
				
				-particle.PARTICLE_SIZE,
				+particle.PARTICLE_SIZE,
				0									
				}
			);					
			
		/////////////////////////////////////////////////////////
		// ADD COLORS TO THE BUFFER /////////////////////////////
		
		colorBuffer.put
			(
			new float[] 
				{
				particle.particle_red,
				particle.particle_green,
				particle.particle_blue,
				particle.particle_alpha,
				
				particle.particle_red,
				particle.particle_green,
				particle.particle_blue,
				particle.particle_alpha,
			
				particle.particle_red,
				particle.particle_green,
				particle.particle_blue,
				particle.particle_alpha,
				
				particle.particle_red,
				particle.particle_green,
				particle.particle_blue,
				particle.particle_alpha						
				}
			);	
			
		/////////////////////////////////////////////////////////
		// ADD HINGES TO THE BUFFER /////////////////////////////

		hingeBuffer.put
			(
			new float[] 
				{
				particle.position_x,
				particle.position_y,
				particle.position_z,
				
				particle.position_x,
				particle.position_y,
				particle.position_z,
			
				particle.position_x,
				particle.position_y,
				particle.position_z,
				
				particle.position_x,
				particle.position_y,
				particle.position_z							
				}
			);										
			
		}
	
	}


	
// BIND PARTICLE TEXTURE

myGL.glBindTexture
	(
	GL.GL_TEXTURE_2D,
	GL_TextureLoading.textureNumbersPredefined[Texture_list.TEXTURE_PARTICLE]
	);

// LOAD THE BILLBOARDING VERTEX PROGRAM

GL_LoadShaders.setShaderProgram(GL_LoadShaders.PROGRAM_BILLBOARD);
	
// SET PLAYER VIEWING ANGLE FOR VERTEX PROGRAM
	
GL_LoadShaders.setShaderVariableF
	(
	GL_LoadShaders.VARIABLE_BILLBOARD_YAW,
	Game.currentPlayer.yaw
	);

// GET GL STATE READY FOR DRAWING
	
myGL.glEnable		(GL.GL_TEXTURE_2D	);
myGL.glDisable		(GL.GL_CULL_FACE	);
myGL.glDisable		(GL.GL_BLEND		);
myGL.glDepthFunc	(GL.GL_ALWAYS		);
myGL.glDepthMask	(false				);
myGL.glBlendFunc	(GL.GL_ONE_MINUS_SRC_ALPHA,GL.GL_ONE);	
	
// COLOR POINTER ->

myGL.glEnableClientState(GL.GL_COLOR_ARRAY);

myGL.glColorPointer
	(
	4, 
	GL.GL_FLOAT, 
	0, 
	colorBuffer
	);

// PARTICLE HINGE POINTER (PASSED IN AS NORMALS) ->

myGL.glEnableClientState(GL.GL_NORMAL_ARRAY);

myGL.glNormalPointer
	(
	GL.GL_FLOAT, 
	0, 
	hingeBuffer
	);	
	
// TEX-COORD POINTER ->

myGL.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);

myGL.glTexCoordPointer
	(
	2, 
	GL.GL_FLOAT, 
	0, 
	texCoordBuffer
	);

// PARTICLE VERTEX POINTER ->

myGL.glEnableClientState(GL.GL_VERTEX_ARRAY);

myGL.glVertexPointer
	(
	3, 
	GL.GL_FLOAT, 
	0, 
	vertexBuffer
	);			

// DRAW THE PARTICLES

myGL.glDrawArrays
	(
	GL.GL_QUADS, 
	0,
	numActiveParticles*4
	); 
	
// DISABLE RELEVANT BUFFERS

myGL.glDisableClientState(GL.GL_COLOR_ARRAY			);
myGL.glDisableClientState(GL.GL_NORMAL_ARRAY		);
myGL.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY	);
myGL.glDisableClientState(GL.GL_VERTEX_ARRAY		);

// RETURN TO OGL'S NORMAL FIXED FUNCTIONALITY PIPELINE

GL_LoadShaders.setShaderProgram(GL_LoadShaders.PROGRAM_FIXED_FUNCTION);

// RESTORE SOME PREVIOUS GL SETTINGS

myGL.glEnable		(GL.GL_CULL_FACE	);
myGL.glDisable		(GL.GL_BLEND		);
myGL.glDepthMask	(true				);
myGL.glDepthFunc	(GL.GL_LESS			); 

}





Here is the old code which is immediate mode rendering. Even though this does the exact same thing, albeit slower, this code actually works perfectly- which has me confused further:

public void drawBillboardParticle(GL myGL)
{

// LOAD BILLBOARDING PROGRAM

GL_LoadShaders.setShaderProgram(GL_LoadShaders.PROGRAM_BILLBOARD);

// PLAYER VIEWING ANGLE FOR VERTEX PROGRAM

GL_LoadShaders.setShaderVariableF
	(
	GL_LoadShaders.VARIABLE_BILLBOARD_YAW,
	Game.currentPlayer.yaw
	);

myGL.glEnable	(GL.GL_TEXTURE_2D);
myGL.glEnable	(GL.GL_BLEND);
myGL.glDepthMask(false);
myGL.glBlendFunc(GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_ONE);

myGL.glBindTexture
	(
	GL.GL_TEXTURE_2D,
	GL_TextureLoading.textureNumbersPredefined[this.particleTexture]
	);

// BEGIN PARTICLE DRAWING
	
myGL.glBegin(GL.GL_QUADS);

// PARTICLE 'HINGE'

myGL.glNormal3f
	(
	this.position_x,
	this.position_y,
	this.position_z
	);

// PARTICLE COLOR
	
myGL.glColor4f
	(
	this.particle_red,
	this.particle_green,
	this.particle_blue,
	this.particle_alpha
	);
// VERTEX 1
	
myGL.glTexCoord2f
	(
	0f,
	1f
	);
	
myGL.glVertex3f
	(
	-PARTICLE_SIZE,
	-PARTICLE_SIZE,
	0
	);
	
// VERTEX 2

myGL.glTexCoord2f
	(
	1f,
	1f
	);	
	
myGL.glVertex3f
	(
	+PARTICLE_SIZE,
	-PARTICLE_SIZE,
	0
	);
	
// VERTEX 3
	
myGL.glTexCoord2f
	(
	1f,
	0f
	);	

myGL.glVertex3f
	(
	+PARTICLE_SIZE,
	+PARTICLE_SIZE,
	0
	);	
				

// VERTEX 4

myGL.glTexCoord2f
	(
	0f,
	0f
	);	
	
myGL.glVertex3f
	(
	-PARTICLE_SIZE,
	+PARTICLE_SIZE,
	0
	);	

				
myGL.glEnd		();

// SHUTDOWN PARTICLE DRAWING;
myGL.glDepthMask(true);		
myGL.glDisable	(GL.GL_BLEND);

GL_LoadShaders.setShaderProgram(GL_LoadShaders.PROGRAM_FIXED_FUNCTION);

}




If anyone has any ideas then it would be greatly appreciated, as I am completely lost as to what is going wrong here.. [Edited by - Darragh on June 8, 2005 7:41:52 PM]

Share this post


Link to post
Share on other sites
Advertisement
Hey guys, I managed to stumble across the solution last night so worry not! [smile]

The problem was caused by the Vertex Arrays using data from previously bound Vertex Buffer Objects- hence the weirdness. I use VBOs for rendering my models and VAs for the particles, however the VAs were always taking data from the VBOs for some reason.

The solution is a single line of code:

myGL.glBindBuffer(GL.GL_ARRAY_BUFFER,0);

This unbinds any active VBOs and stops the data being used in the VAs.

I certainly never seen this mentioned in any tutorials for VBOs/VAs - though none of them ever actually use the two together in the one program. If anyone is reading this then take note from my mistakes, and save yourself a lot of bother! Otherwise it'll drive you completely mad- I guarantee.. [lol]

Share this post


Link to post
Share on other sites
Indeed, this tip is in a sample from Game Tutorials (http://www.gametutorials.com/main.asp), even if I don't know if it's available among free tutorials! :D

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!