Archived

This topic is now archived and is closed to further replies.

WarAmp

Texture Switching vs Bandwidth

Recommended Posts

Ok, I know this question is best answered by experimentation, but given my current render setup, alot of code would need to be rewritten to test it, so i'm turning to you kind folks for advice. My current terrain rendering system does this:
For each texture layer
{
   Bind Texture
   For each terrain chunk (33x33 vertices, 24 Bytes/Vertex)
   {
      glVertexPointer, glColorPointer, glTexCoordpointer
      glDrawElements()
   }
}
Now as you can see, this results in me sending each terrain chunk to the card for each texture layer being used (300 chunks * 4 Layers) == Lots of bandwidth a frame. How expensive is texture state changing? Would it be faster for me to send each chunk once, and texture switch 300 * 4 times instead? Waramp. "Before you insult a man, walk a mile in his shoes. That way, when you do insult him, you'll be a mile away, and you'll have his shoes." [edited by - waramp on May 19, 2004 1:16:25 PM] [edited by - waramp on May 19, 2004 1:33:18 PM]

Share this post


Link to post
Share on other sites
dont know if anything in opengl would work as some kind of cache, but even if you would do

for chunk
..for texture
....drawelements

wouldnt you still be sending it 4 times? so i guess it comes down to: is bindtexture or vertexpointer more expensive?

Share this post


Link to post
Share on other sites
I was thinking I would only have to VertexPointer once...and it would stay on the card until I vertexPointer''ed again wouldn''t it?

I would have to ColorPointer each time tho...



Waramp.

Before you insult a man, walk a mile in his shoes.
That way, when you do insult him, you''ll be a mile away, and you''ll have his shoes.

Share this post


Link to post
Share on other sites
Binding textures is expensive, it upsets texture caches on the video card, so try and keep it to a minimum. A simple optimisation to your current scheme would be to not render chunks if they don't contain the current texture. e.g.


for each texture
for each chunk
if this chunk contains the current texture
set pointers and draw


If you have a card that supports hardware T&L, also look into vertex buffer objects (vbo). These will allow you to put the vertex data onto the video card so then you'll only be specifying which vbo to use rather than causing all the vertex data to be copied again.


dave j

[edited by - dave j on May 19, 2004 5:08:48 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by dave j
Binding textures is expensive, it upsets texture caches on the video card, so try and keep it to a minimum. A simple optimisation to your current scheme would be to not render chunks if they don''t contain the current texture. e.g.


for each texture
for each chunk
if this chunk contains the current texture
set pointers and draw




That''s running at O(n^t), where t is the amount of textures and n is the amount of chunks. That is not good.

If you want to keep them sorted, think about putting them into a BST/red-black tree, or even in a heap. That way, they''ll remain sorted and you can access them with O(n) or O(nlogn).

Share this post


Link to post
Share on other sites
quote:
Original post by sirSolarius
quote:
Original post by dave j
Binding textures is expensive, it upsets texture caches on the video card, so try and keep it to a minimum. A simple optimisation to your current scheme would be to not render chunks if they don''t contain the current texture. e.g.


for each texture
for each chunk
if this chunk contains the current texture
set pointers and draw




That''s running at O(n^t), where t is the amount of textures and n is the amount of chunks. That is not good.



O(n*t) surely. Anyway, I did mention it was a *simple optimisation* to what WarAmp already had.

quote:

If you want to keep them sorted, think about putting them into a BST/red-black tree, or even in a heap. That way, they''ll remain sorted and you can access them with O(n) or O(nlogn).



Well we could have mentioned frustum culling and multi-texturing/texture combiners/fragment programs to apply more than one texture per pass but I find it''s generally easier to learn in small steps.


dave j

Share this post


Link to post
Share on other sites
Geforce2 MX400, can''t apply more than 1 texture to the terrain per pass without using combine4_nv (trying to use ARB extensions only)

I do only render chunks that utilize the current texture
Each vertex can have up to 8 textures applied to it, so I keep a bitmask of all the textures used in a patch, so

if (pPatch->m_nUsedTextures & (1 << pTexture->ID))
{
RenderPatch(pPatch);
}

Thats roughly what happens anyways.

VBO''s are my next option I guess. Time to figure them out.

Waramp.

Before you insult a man, walk a mile in his shoes.
That way, when you do insult him, you''ll be a mile away, and you''ll have his shoes.

Share this post


Link to post
Share on other sites
quote:
Original post by WarAmp
Geforce2 MX400, can''t apply more than 1 texture to the terrain per pass without using combine4_nv (trying to use ARB extensions only)



I''m quite shocked by that tbh, my old TNT2 could layer 2 textures at once and i''m pretty sure my GF2MX I had could (i''d have to check that, its currently in my mum''s computer).
Even Delphi3D''s hardware list agrees with me : clicky
Unless the MX400 was an even more crippled version of the MX series, but only one texture at a time does seem pretty silly, at the time it was released that would have been a 3 or 4 year step back in tech o.O

Share this post


Link to post
Share on other sites
Oh it has 2 Texture Units, but each vertex has up to 8 textures (t0..t7), and so that means 8 weights (w0..w7).
(note that the sum of all weights == 1.0)

ie: Final Vertex Color = w0*t0 + w1*t1 + .. + w7*t7.

so I would need to be able to do wn*tn + w(n+1)*t(n+1) in 2 units, and I can't figure out how without the use of the combine4_nv extension.

If you know of a way to do ab + cd with 2 units with ARB extensions only, please let me know.

currently I do wn * tn in Unit 1, and the Cloud shadows + vertex lighting in Unit 2.

Waramp.

Before you insult a man, walk a mile in his shoes.
That way, when you do insult him, you'll be a mile away, and you'll have his shoes.

[edited by - waramp on May 19, 2004 9:26:44 PM]

Share this post


Link to post
Share on other sites
gf2mx & gf4mx both have 2 texture per pass.

Are all layers the same 4 textures, or could they be 4 out of a palette of many textures? There is a huge difference.

You could draw all layers in view that have textures a & b in common in one pass, then draw textures with c & d in another pass. This breaks down if you have layers e,f,g,h, etc.

In the case of only 4 terrain types, do two passes with two textures each.

In the case of many terrain types visible at once, probably just do one pass of all geometry having each layer type, so :

1) switch texture
2) draw all geometry using this texture

repeat.

Share this post


Link to post
Share on other sites
quote:
Original post by WarAmp
Oh it has 2 Texture Units, but each vertex has up to 8 textures (t0..t7), and so that means 8 weights (w0..w7).
(note that the sum of all weights == 1.0)

ie: Final Vertex Color = w0*t0 + w1*t1 + .. + w7*t7.

so I would need to be able to do wn*tn + w(n+1)*t(n+1) in 2 units, and I can''t figure out how without the use of the combine4_nv extension.

If you know of a way to do ab + cd with 2 units with ARB extensions only, please let me know.



Yeah, i see what you mean, NV_com4 has a nice little a0a2 + a1a3 version of GL_ADD you can use and it seems no amount of messing with the GL_INTERPOLATE_ARB (a0a2 + a1(1-a2) tex_env_combine function will let it work :|

Granted you could do it with the NV_com4 extension on NV cards and ATI''s fragment_shader extension on ATI cards, but as you want to stick with ARB stuff thats not much use

Share this post


Link to post
Share on other sites
SimmerD: They are all uniqe textures, its based off Yann''s Terrain Texturing thread on here.

I don''t think I explained myself clearly, a gf2MX cannot do:
Tex0 * a + Tex1 * b in one pass. (Using ARB extensions).



Waramp.

Before you insult a man, walk a mile in his shoes.
That way, when you do insult him, you''ll be a mile away, and you''ll have his shoes.

Share this post


Link to post
Share on other sites
Sorry to pseudo-necro this thread, but I figured a way to do AB + CD in 2 texture units.

A, B = Textures 0 and 1.
x, y = Texture Weights 0 and 1.

in order to do Ax + By in 2 units with OpenGL1.1 + ARB:

note that if y == 0, then don't bother with the divide.
Primary Color(x/y, x/y, x/y, y);

Texture 0: RGB: Modulate(Primary Color, A), Alpha: Anything.
Texture 1: RGB: Add(Previous, B), Alpha: Replace(Primary Color.Alpha)

glBlendFunc(SRC_ALPHA, ONE (or whatever you need))

This ends up being: (A(x/y) + B)y = Ax + By.

yay!


Waramp.

Before you insult a man, walk a mile in his shoes.
That way, when you do insult him, you'll be a mile away, and you'll have his shoes.

[edited by - waramp on May 28, 2004 5:19:55 PM]

Share this post


Link to post
Share on other sites