Environment mapping and performance issue

Started by
19 comments, last by TomKQT 10 years, 8 months ago

I'm trying to create dynamic cube map, having a serious problem with the performance, getting less than 20-25 FPS when I render the scene 6 times to create cube texture for environment mapping.

I think I need to render the scene with less resolution when I create the cube texture, not sure how...

How do I make the performance back to normal?

Advertisement

Do you create the texture with WRITE_ONLY flag in the default pool?

Perhaps since your total drawcalls and state changes have increased sevenfold, then you might have hit some limitations.

Do you create the texture with WRITE_ONLY flag in the default pool?

Shouldn't be relevant unless you're locking it; that would be a theoretical worst-case for performance: render as normal to backbuffer, LockRect it, LockRect a cube face, and memcpy the data over - ouch!!! (WRITE_ONLY woudn't help here though - it may even make things worse!)

Another bad case would be to StretchRect from the backbuffer to each cube face; I don't think that's going to drop to 20fps though.

The right way is to create a cubemap with D3DUSAGE_RENDERTARGET in D3DPOOL_DEFAULT, then set each face as a new render target, adjust the viewport to the size of the cubemap and the projection matrix to a 90 degree x and y FOV, clear the depth buffer, and draw the scene to that face. Do it 6 times, and you have your cubemap.

Of course, the 7x overhead in draw calls and state changes would still hurt here (as well as all of those render target switches and depth buffer clears).

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Can you describe more about the scene you are rendering, and the hardware you are working on? The bottleneck could be CPU calls due to the scene being rendered several times. Are there lots of draw calls being issued?

If so, can you do some instancing to help reduce the number of calls? In general, if your cube map size isn't ridiculously large then modern hardware should blow through an environment map with no problems...

@Jason Z: No, I don't really need to use instancing, I just have few models in the scene (sky, terrain and around 6-7 other models).

GPU: GTX 550 Ti

Hmmm, GTX 550 Ti should be fairly powerful for such a simple scene.

?You should implement a triangle count. From my experience, there is nothing you can do to a make an under 1 million triangle scene that uses a lot of vertex buffers run like crap and if it does, there is something wrong somewhere else. Either on the CPU side, or you are doing very heavy texture sampling. Or cascaded shadow mapping.

But for environmental mapping, you can use a fairly low resolution and very blurred image. You can omit small objects, use cheap filters, omit normal mapping, render meshes with a lower LOD, etc.. You could also recreate the cube map only once in a while, or when some object close to the environmental mapped object changes. You could render one face of a cube a frame, so you have a new cube every 6 frames, reducing you draw calls to 2x. Also, you should have very good batching behavior, but if you only have a few objects, this is probably not your bottleneck.

One thing that bothers me with this is that if many things in the scene should reflect stuff and the environment map is created from the camera position, what happens if a character stands between the shiny surface and the map? Should not the character be reflected aswell?

Very important question here is what does the game look like. Often environment mapping is just a subtle effect used on some shiny objects and the player almost doesn't pay attention to it. It makes the game look better, but nobody examines the reflection to verify how accurate it is. You can be fine with just few prerendered cubemaps for the scene or if you really need a dynamically updated cubemap then maybe you could be fine without any fancy shaders, without shadows etc. It's mostly about the basic feeling from the scene - the basic colors and shapes of objects in the scene.

But I repeat - it depends on the game. Simple reflections are fine for example for cars in racing games, metal parts of weapons in FPS games and so on. Also the shape of the reflective object is important - more complicated shapes are fine with less detailed cube map and vice versa. If you have a perfect reflective sphere in the middle of a room and you can slowly walk around it and examine it then you probably need great reflections to make it believable.

@Medo3337: What is the size of your environment map? Have you tried to decrease its resolution? If you have very few draw calls, and they aren't huge, then it is likely related to how large of a texture you are populating every frame.

Can you take a PIX frame grab and post it somewhere so that we can see what you are submitting to the API?

@Jason Z: I'm setting the cube texture resolution to 256, reducing the cube map resolution doesn't make any difference in performance.

@DwarvesH: I'm getting better performance when I render one cube side each frame instead of 6 per frame, however I'm not sure how can I make the performance even better.

How do I render meshes with a lower LOD? I'm using LPD3DXMESH.

This topic is closed to new replies.

Advertisement