Better way to render than pixel-by-pixel?

Started by Epicbo, March 27, 2012, 06:40:38

Previous topic - Next topic

Epicbo

Hi! I recently decided to learn OpenGL and now I've run into some problems. The problem im working on is a simple raycaster game. I've managed to make textured walls without any problem. However, now I attempt to make textured floor/ceiling and it's not working quite as good. The way do it (the way most tutorials tell me how to do it) is to loop through every pixel below and above the wall, calculating which part of a texture to use and then rendering the pixel. The calculations drops my FPS from 130 to 120, which is no big deal. Rendering the pixels drops my FPS from 120 to 3, making it completly unplayable.

Since im a complete beginner I dont know any method to speed this up. Perhaps you do? I was thinking something like getting the pixel data for the whole floor and then rendering it all at once might work, but I don't know how to do it. I don't even know if you can do that. Help would be very appreciated!

CodeBunny

You can render textured quads right? Why don't you just use those?

And what tutorials are you following??? D: That's some of the worst advice I've ever heard. I don't even know of a worse way to do it in OpenGL. Find a better tutorial suite.

A good rule of thumb with computer graphics (and most programming) is that some form of pre-compilation of data is useful for good performance. Examples:

  • You want to render an image, so you allocate a texture and store it on the graphics card.
  • You want to render geometry, so you store the vertex on the graphics card.
  • (many other examples - most of modern graphics programming is based on this rule)

Examples in other areas of programming:

  • You want entities to have pathfinding, so you create and store a map for them to reference.
  • You want to have platforming physics and a huge map, so you break it up into a tilemap.

If you find your code doing the same expensive computation every single iteration, you need to figure out a way to not do that. This is one of the simplest ways to consider optimization; you trade memory for performance.

matheus23

Intresting... Are you writing something like a fake-3D engine? Something like Doom? :D I really like the maths inside those games :)
My github account and currently active project: https://github.com/matheus23/UniverseEngine

Epicbo

The only tutorial i was following was the raycasting tutorial, which didn't cover the rendering at all. It only covered all the calculations etc.
All the raycasting tutorials I found told me to use "floor casting" to make textured floors/ceilings, which is looping through every pixel below and above the wall and calculating what part of the texture that specific pixel uses when rendering it. I don't see any other option to this, which doesn't matter because this isn't the problem. Ill write some psuedo-code to describet the problem. This is how my code kind of looks like now:

for (int x = 0; x<screenWidth; x++) {

// Raycast to get the height of the walls
raycast();

for (int y = wallEnd; y<screenHeight; y++) {

// Calculate what texture pixel to use for this specific texture
calculateTexel();


// This is the bad part.
renderPixel();

}
}


What I need to do is to remove renderPixel() from that loop and instead of rendering every pixel one-by-one, I need to render them all at once pretty much. I don't have the required knowledge how to do this though. The theoretical solution I could come up with in my head is that instead of rendering the pixel in the loop, you save the texel data and then later render the whole floor/ceiling using all that data.
There are probably better solutions but this is the best I could come up with. But like I said earlier, I'm completly new to OpenGL so I have no idea how to do this.

Quote from: matheus23 on March 27, 2012, 16:12:34
Intresting... Are you writing something like a fake-3D engine? Something like Doom? :D I really like the maths inside those games :)

Indeed I am. Although a better example would be Wolfenstein 3D, since the Doom engine is quite advanced for being a raycasting engine. I decided to do a raycaster because I didn't feel like doing a real 3D game and my game world only needs to be 2D.

RiverC

In the case of what I've been doing, the pixel-per-pixel work is done more or less on the graphics card, in the fragment shader. What I feed to the card is a quad with the mapping for a texture if one is to be used. This is then passed through the vertex shader to put the vertices I gave it into projection view, and then the colors are 'painted' by the fragment shader.

This looks like software raycasting, which (seems) like what you would do if you had no graphics card at all.

matheus23

QuoteWhat I need to do is to remove renderPixel() from that loop and instead of rendering every pixel one-by-one, I need to render them all at once pretty much.

Look at glDrawPixels. You will have to have a IntBuffer (or what ever you prefer. I think you could also use a ByteBuffer), to draw Directly to the OpenGL's FBO (FrameBufferObject (the final "Image", which will be drawn)).
My github account and currently active project: https://github.com/matheus23/UniverseEngine

Simon Felix

Raycasting, Floorcasting especially is only useful for software rendering. I suggest you switch to another technique.
Download Cultris II, the fastest Tetris clone from http://gewaltig.net/

Epicbo

Quote from: dr_evil on March 27, 2012, 21:57:08
Raycasting, Floorcasting especially is only useful for software rendering. I suggest you switch to another technique.

What other techniques are there? I've searched but I couldnt find any.  :(

Quote from: matheus23 on March 27, 2012, 19:32:15
QuoteWhat I need to do is to remove renderPixel() from that loop and instead of rendering every pixel one-by-one, I need to render them all at once pretty much.

Look at glDrawPixels. You will have to have a IntBuffer (or what ever you prefer. I think you could also use a ByteBuffer), to draw Directly to the OpenGL's FBO (FrameBufferObject (the final "Image", which will be drawn)).

I'll look into glDrawPixels and FBO, but how do I save texture data into a IntBuffer?

Simon Felix

Quote from: Epicbo on March 28, 2012, 06:28:50
Quote from: dr_evil on March 27, 2012, 21:57:08
Raycasting, Floorcasting especially is only useful for software rendering. I suggest you switch to another technique.

What other techniques are there? I've searched but I couldnt find any.  :(

Well, today's usual way: Render everything with polygons. Since it appears that you enjoy old material on this topic, there's a book I can highly recommend: Michael Abrash's Graphics Programming Black Book. Start at around chapter 50 and skip all the (beautiful) x86 asm: http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/graphics-programming-black-book-r1698
Download Cultris II, the fastest Tetris clone from http://gewaltig.net/