Jump to content


Seamus McNally's fire effect


12 replies to this topic

#1 SteveH

    New Member

  • Members
  • Pip
  • 9 posts

Posted 07 February 2009 - 08:48 PM

Hi, I've been working on this for a while and have run into a problem that I can't spot.

I'm using OpenGL and C++ and I'm not looking for optimizations just yet, just a solution to make this work. I originally had a working implementation where I just stored a buffer of unsigned bytes and just used a standard putpixel type function to render my particles, blurred it as necessary, then used glDrawPixels to render.

I'd like to have everything drawn using glBegin and glEnd calls now so I can have things like burning text. As a result, I've modified the way the code works and abstracted the blurring process and apply it to the whole screen using glReadPixels and glDrawPixels. This is my code as is. It works, but there's no blurring effect.

unsigned char* buffer = new unsigned char[640*480*3]; // this is created elsewhere obviously.

// main rendering loop.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glReadPixels(0,0,640,480,GL_RGB,GL_UNSIGNED_BYTE,buffer);

unsigned char pixel = 0;

for (int i=1923;i<640*480*3-3;i++)
{
	pixel = ((buffer[i] + buffer[i+3] + buffer[i-3] + buffer[i-1920]) >> 2) - 1;

	if (pixel >= 255)
		pixel = 0;
	if (pixel <= 0)
		pixel = 0;

	buffer[i] = pixel;
}

glDrawPixels(640,480,GL_RGB,GL_UNSIGNED_BYTE,buffer);
SwapBuffers(hDC);


And of course, assume that before glReadPixels is called, I'm making calls to glBegin(GL_POINTS); setting the color and vertex data and then calling glEnd(); As I said, it renders the points just fine, but with no blur effect.

#2 SteveH

    New Member

  • Members
  • Pip
  • 9 posts

Posted 13 February 2009 - 07:42 PM

Nobody has any input? This seems like a fairly straightforward problem... Surely someone here should have an answer...?

#3 Reedbeta

    DevMaster Staff

  • Administrators
  • 4969 posts
  • LocationBellevue, WA

Posted 13 February 2009 - 08:42 PM

The code looks fine to me. The only thing I can think of is maybe the raster position is set to something weird and the DrawPixels call is putting all its pixels off-screen, or something of that sort. Does it work if you set the blurred image as a texture and render a full-screen quad?
reedbeta.com - developer blog, OpenGL demos, and other projects

#4 monjardin

    Senior Member

  • Members
  • PipPipPipPip
  • 1033 posts

Posted 13 February 2009 - 08:55 PM

Try this:

unsigned char* buffer = new unsigned char[640*480*3]; // this is created elsewhere obviously.

// main rendering loop.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glReadPixels(0,0,640,480,GL_RGB,GL_UNSIGNED_BYTE,buffer);

unsigned int pixel = 0;

for (int i=1923;i<640*480*3-3;i++)
{
	pixel = (((unsigned int) buffer[i] + buffer[i+3] + buffer[i-3] + buffer[i-1920]) >> 2) - 1;
	buffer[i] = pixel >= 255 ? 0 : pixel;
}

glDrawPixels(640,480,GL_RGB,GL_UNSIGNED_BYTE,buffer);
SwapBuffers(hDC);

monjardin's JwN Meter (1,2,3,4,5,6):
|----|----|----|----|----|----|----|----|----|----|
*

#5 kusma

    Valued Member

  • Members
  • PipPipPip
  • 163 posts

Posted 15 February 2009 - 11:00 AM

The code seems to be confused about the resolution it's processing. The buffer allocated and read with glReadPixels seems to use 640 by 480, but the offsets to i seems to assume a screen width of 1920.

edit: never mind. 640 * 3 is 1920, I got confused and assumed you were working with FullHD-resolutions.

#6 SteveH

    New Member

  • Members
  • Pip
  • 9 posts

Posted 16 February 2009 - 03:38 AM

No the code works as long as I'm not using glReadPixels. If I just update my buffer pixel by pixel and implement the blur, then call glDrawPixels it works perfectly, but I don't want to have to write text pixel by pixel, so I'm looking to use glReadPixels to grab the entire screen, apply my blur to everything, then write it back with glDrawPixels.

I tried rendering to a texture and then just making a fullscreen quad, but that just made the entire screen change to the color of whatever pixel happened to be currently written to the buffer.

I could be wrong about this but I thought glReadPixels didn't need to be prefaced with a glRasterPos2i.

#7 Reedbeta

    DevMaster Staff

  • Administrators
  • 4969 posts
  • LocationBellevue, WA

Posted 16 February 2009 - 03:51 AM

It doesn't. I was thinking the glDrawPixels call was going off.

Regarding the fullscreen quad, you did set up texture coordinates for it, right? So the whole image gets mapped to the whole quad?
reedbeta.com - developer blog, OpenGL demos, and other projects

#8 SteveH

    New Member

  • Members
  • Pip
  • 9 posts

Posted 17 February 2009 - 12:38 AM

Here's what I'm at now and it's not even close to working. Not even the flashing lights anymore.


glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

	

glReadPixels(0, 0, 640, 480, GL_RGB, GL_UNSIGNED_BYTE, buffer);


unsigned int pixel = 0;


for (int i=1923;i<640*480*3-3;i++)

{

pixel = ((buffer[i] + buffer[i+3] + buffer[i-3] + buffer[i+1920]) >> 2) - 1;

		if (pixel >= 255) pixel = 0;

		if (pixel < 0) pixel = 0;

		buffer[i] = pixel;

	}


	for (i=0;i<1923;i++)

		buffer[i] = 0;


	glEnable(GL_TEXTURE_2D);

	glBindTexture(GL_TEXTURE_2D, texture);

	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 640, 480, GL_RGB, GL_UNSIGNED_BYTE, buffer);


	glBegin(GL_QUADS);

	glTexCoord2f(0, 0); glVertex2f(0, 0);

	glTexCoord2f(1, 0); glVertex2f(640, 0);

	glTexCoord2f(1, 1); glVertex2f(640, 480);

	glTexCoord2f(0, 1); glVertex2f(0, 480);

	glEnd();

	SwapBuffers(hdc);

To create the texture, I do this:


glEnable(GL_TEXTURE_2D);

glGenTextures(1, &texture);

glBindTexture(GL_TEXTURE_2D, texture);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);


And then of course, before all the rendering is done, I do something like this:


glBegin(GL_POINTS);

for (int i=0;i<particles.size();i++)

{

  if (particles[i].isAlive())

  {

    glColor3ub(particles[i].r, particles[i].g, particles[i].b);

    glVertex2f(particles[i].x, particles[i].y);

  }

}

glEnd();


Any ideas?

#9 Reedbeta

    DevMaster Staff

  • Administrators
  • 4969 posts
  • LocationBellevue, WA

Posted 17 February 2009 - 03:02 AM

Before you render the quad at the end, do you set up an appropriate projection matrix so that coordinates [0, 640] x [0, 480] are mapped to the screen? I would actually recommend setting the projection matrix to the identity, and using vertex coordinates (-1, -1), (1, -1), (1, 1), (-1, 1). Also don't forget to disable depth testing before drawing the quad, if you're using it elsewhere.
reedbeta.com - developer blog, OpenGL demos, and other projects

#10 SteveH

    New Member

  • Members
  • Pip
  • 9 posts

Posted 17 February 2009 - 05:48 AM

But I'm using an orthographic projection matrix set to 640 by 480. In order to make it 1, 1 wouldn't it have to be a 3 dimensional matrix? And if so, wouldn't that make things run slower?

#11 Reedbeta

    DevMaster Staff

  • Administrators
  • 4969 posts
  • LocationBellevue, WA

Posted 17 February 2009 - 06:13 AM

Ahh, okay. If you're setting an orthographic projection, that should be fine. However, based on what you said earlier, that it works if you render the image on the CPU and then use glDrawPixels, I think the problem is elsewhere. You might as well go back to glDrawPixels.

SteveH said:

wouldn't it have to be a 3 dimensional matrix? And if so, wouldn't that make things run slower?

No, what I was recommending is setting the projection matrix to the identity. It would be equivalent to an orthographic projection with left, bottom, right, top = -1, -1, 1, 1. For performance it shouldn't make a difference whether you use an orthographic or perspective matrix. The GPU does the same calculations either way.
reedbeta.com - developer blog, OpenGL demos, and other projects

#12 SteveH

    New Member

  • Members
  • Pip
  • 9 posts

Posted 17 February 2009 - 07:12 PM

Well the problem with just using glDrawPixels is that I can't use effects like burning text or burning anything, except individual pixels that I manually write to a buffer.

#13 Reedbeta

    DevMaster Staff

  • Administrators
  • 4969 posts
  • LocationBellevue, WA

Posted 17 February 2009 - 09:06 PM

I'm talking strictly about how you get the final pixels to the screen, after whatever effects you may run. I'm saying glDrawPixels is just as good for that as my suggested approach of setting a texture image and drawing a quad. In other words your original problem of the blur not showing up is caused by something further up the pipeline. I don't know what it might be.
reedbeta.com - developer blog, OpenGL demos, and other projects





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users