Archived

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

Mescalito

Textures and terrain rendering

Recommended Posts

Hi I''m currently writing a terrain rendering engine with Direct3D (ver 8.1), the terrain is drawn with only one DrawPrimitive (I use triangle strip), and my pixel shader contains x,y and z positions, u and v texture coordonates and a diffuse color. I''ve got a problem when using textures. I want to work with 32*32 textures stored in a single texture(the bmp file is 256*256 so I''ve got 64 textures in one...) But I don''t know how to apply a texture to each triangle of my terrain (I know how to apply a single texture for the entire terrain but with many textures ??) Should I use another set of u & v texture coordonates ? How ? Thank you.

Share this post


Link to post
Share on other sites
I just posted that exact same question a couple days ago, look here. I am trying to figure out the problem as well.

http://www.gamedev.net/community/forums/topic.asp?topic_id=119888

Share this post


Link to post
Share on other sites
I can imagine you doing this two ways. When loading your terrain create a blank texture large enough to hold all of the tiles when they are paced on the geometry, and copy all of the individual tile''s texture''s into that one using device->copyrects. This way you can render the terrain from one texture that is a compilation of all the tiles. This is the method I would use - it''s very easy.

Another way, if you insist on each tile having it''s own texture is to render the terrains geometry in a loop, where each iteration you use device->settexture, and then give device->drawprimitive an argument that tells it what part of the vertex buffer to render from. I would not reccomend this method, it seems like it would be slower.

Share this post


Link to post
Share on other sites
Yes, you use texture coords. Imagine one quad of your terrain...the texture coords of the quad are (0,0), (0,1), (1,1), and (1,0) respectively. This will map the ENTIRE texture over the quad.

But, of course, you don''t want that. You want the upper left subtexture in your larger texture. The subtexture covers 1/8th of your main texture in both the x and y directions. So, you need to set your coords to be (0,0), (0,.125), (.125, .125), (.125,0). 0.125 is 1/8 - if you had 16 textures in each of 16 rows, you''d want 1/16, etc.

To get the next texture over, you''d offset the texture coords by 1/8 in the X direction.

I hope this makes sense, as I''m typing quick and watching the football game. It''s the same technique I use - I have 64 256x256 textures packed into a 2048x2048 terrain texture. Also, you might have to add a little extra onto each texture to make sure you don''t include the last line of the texture next to the one you want to use.



Share this post


Link to post
Share on other sites
First of all thank you for the posts.

Wolliwer, I understood what is is your way to do it.
I think it is easy to implement and it''s also a good way to implement other stuffs like shadows, terrain modifiers...
I''ll try this.

But what about the memory usage for it, it seems a good idea for small maps but for huge ones ? Is there a "better" ways (one who doesn''t need too much memory)

AJF, I didn''t understand what was your way.
I know all you said and I can implement that but for a given squad there are only 4 coordonates and not 8 ! So we have to use the same texture for the entire map ?!...

Share this post


Link to post
Share on other sites
hi mescalito,

ajf solution i think is the best way indeed. i think his trying to say is, you have only one texture for your terrain. And it''s all up to you how big you like your terrain. Then when specifying their uv coordinates, you wouldn''t map each quad inside your VB to the whole texture but instead, you just map a piece/portion on the texture terrain,

this way, once call to settexture, one call to draw primitive,

Share this post


Link to post
Share on other sites
I have spent all day yesterday, and today figure out this exact same problem. AJFs plan will not work at all, though it sounds like it would.

You cannot simply "offset" the texture coordinates for a triagngle strip of vertex data. Each point is passed only ONCE. For example, if you want your texture at (.125,.125) placed at your 0x0 terrain grid, and (.375,.375) at you 1x0 terrain grid you must remember your first quad goes from .125 to .250, then from .375 to .5. You must define 2 vertex points at the same place at point 1x0, because you must set one to end the triangle with .250 then start the next triangle at the same point using .375. I have spent countless hours trying to figure out this problem and the only way to do it is to add those extra vertex points into your index buffer. Then make a programmable vertex shader exactly how S1CA explained in my post (URL above).

I will let you know if I think of a better way.

Share this post


Link to post
Share on other sites
I think one solution can be to use triangle list instead of triangle strip, so you can define an own UV map for every triangle!

Share this post


Link to post
Share on other sites
Carradine, you can''t do what you are thinking you can do. A point can only have one set of texture coords in single-pass texturing. You have to store two points with the same world-space location in order to assign two different texture coords.

Unless, of course, you define your FVF format to contain more than one set of texture coords, and somehow know in your custom shader which set to used based on what triangle you are rendering.

I use triangle lists to string 2 triangles together for a quad, and draw on a quad by quad basis with one texture. Each set of four points in the buffer define one quad. Each set of four points is followed by another 4 points, 2 of which share the same physical location as 2 points in the previous quad. Yeah, it uses memory, but memory is cheap

Of course, this is just my solution and there''s always better. Good luck.

Share this post


Link to post
Share on other sites
exactly AJF - just as I do it. But make sure you use an indexed triangle list. Make a vertex buffer with four vertices per landscape square. Fill an indexed buffer to draw all triangles.
Its a lot more vertices than with 1 big texture, but it really doesnt make such a difference.

Eventually you will want to use a dynamic vertex buffer if you want to cull and update your landscape data frame-by-frame.

Putting all textures in one big texture is not always a good idea, especially if you want to use mip-mapping, since sub-textures can ''bleed'' into each other. The alternative is just to sort the terrain sqs by texture and draw in a few passes (1 for each texture).
A*

Share this post


Link to post
Share on other sites
I think I''ve finally understood AJF/AndyM method to draw a map, and it can be implemented with only one DrawPrimitive (with TRIANGLE_STRIP).

So for 2 squads we won''t draw 4 tris but 6. And we won''t need 6 vertices but 8. I''ll try the two methods to determine which is the fastest.

And one more time thank you everbody !

Share this post


Link to post
Share on other sites
quote:
Original post by Mescalito
I think I''ve finally understood AJF/AndyM method to draw a map, and it can be implemented with only one DrawPrimitive (with TRIANGLE_STRIP).

So for 2 squads we won''t draw 4 tris but 6. And we won''t need 6 vertices but 8. I''ll try the two methods to determine which is the fastest.

And one more time thank you everbody !


No I think you are confused. Forget triangle strips, they only offer small speed improvements and only when used properly.

Lookup INDEXED triangle LISTs. Per quad you have 4 vertices, but six indices which specify two triangles made from the 4 vertices.
Put them all in one big vertex and index buffer (or feed them into dynamic vertex buffers).

Share this post


Link to post
Share on other sites
Actually AJF that is exactly what I was trying to describe, I suppose I wasnt doing very well in my explanation. I came to same conclusion as everyone else here, except I will be using one large triangle strip to draw the mesh, and storing two textures into the vertex buffer then using the programmable vertex shader to access those points. For me specifically, on a 10x10 grid of height data, creating triangle strips increases my index buffer size by only 1.5 times (10x10x4 vertices per quad), while using triangle lists would be 2 times the number in index numbers (10x10x6). This is compared to the original drawing of one large triangle strip without texture coordinate mapping (10x10x2) of course these are all approximate only to my version of vertices. (I know the numbers dont add up correctly, it is based on my curent algorithms).

Share this post


Link to post
Share on other sites
I''ve read several tuts about index buffer and indexed primitives.
I know how it works.

So to do what i want I have to give 4 vertices by squad on my terrain (vertices containing UV texture coo.)
2 of 4 vertices are used once more for the next squad.

For a 10x10 grid terrain, I''ll use 400 vertices, and it will drawn with a DrawIndexedPrimitive(D3DPT_TRIANGLELIST) to give some 200 triangles.

Is that OK ???!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Hey all

I''ma newb in directX, been working with The nebula device for a while, but moving on to low-level DX now.

I''m busy building a terrain from a heightmap bmp and almost got it working, but for one thing. Currently I have a vertex buffer set up correctly, but the index buffer is giving me hasstles. I build up one tristrip for the whole terrain, but every second strip is missing. Apparently it''s something to do with the triangle wrapping ? But I know nothing of that.

Help please...

Share this post


Link to post
Share on other sites