GLBasic forum

Main forum => GLBasic - en => Topic started by: FutureCow on 2012-Jun-09

Title: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: FutureCow on 2012-Jun-09
I have a 3D terrain object that is currently made up of lots of joined together squares (ie. it's drawn as one 3D object by my code). Currently I set my texture then draw the land object once per game loop.
Originally all the squares have the same texture, but over time I want to change some of them (eg. make some squares muddy).
Any idea what the best way to accomplish changing part of the texture of a 3D object is?

The only way I've come up with that would work : My terrain is currently 128x128 squares (ie. 32768 triangles) and I'm using x_collisionray to determine which grid location is under the cursor. I could draw each grid square as a separate 3D object and texture them separately but that's a lot of 3D objects draw every frame, and 32768 x_collisionray calls per frame (or even once a second) I'm guessing would make the program really slow.

A bit of googling initially led me to think that a vertex shader is what I'm after but now I'm not so sure - besides which I've got no idea how to write/implement one (assuming that IS what I'm looking for!)

If anyone has any great ideas I'd love to hear them!!!
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: mentalthink on 2012-Jun-09
Hi future, I thinked about this... I don´t know if can works... if I don´t understand bad you need change only a pieze whit X_collision ray, but how you have a lot of rectangles, you have the check the great number of tetures each sencond... well I thinked about this... if you divide the complete mesh in sectors more small, imagine a matrix of 128x128 divided in example  (32x4)x(32x4), making some rutine you detect in the quadrant you are actualy, and you only have to check (32x4)x(32x4) for the textures, if you make more small the quadrants , less calculations... the quadrants not actives in these same time have the default texture...

I don´t know if I expressed correctly, but I think this have to boost your application...

PS: Sometime I forgot to use... remenber XCullmode, because if you don´t use you draw twice faces of the triangles, and the performance goes slow  a great amount...

Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: mentalthink on 2012-Jun-09
Another idea, just comes to my brain....

And if you make a rectangle whit the primary texture, and depend de coordinates you point whit xcullmode, draw another rectangle over the principal mesh... whit this mode you don´t have to texturing 1000 rectangles per second, only the huge rectange, and the little rectangle, a bit upper the great mesh...
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: matchy on 2012-Jun-09
Use one object for the terrain mesh grid and just multiple split your texture image, for example set four quadrant textures on one sprite with grass, water, sand, mud and offset half of default when creating the mesh vertexes.  :good: It's basic 2d titling technique, right, or is there more to this? :-[
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: FutureCow on 2012-Jun-10
Thanks for the replies.
Metalthink - I can't split it up into sections easily. I have a camera that can rotate/zoom in any direction so depending on how you rotate and zoom the camera, you could have just 1 of the smaller meshes on the screen, or some of them, or all of them. The landscape is mountains, where parts of it can hide other parts of the landscape, so working out which meshes are on the screen would be a nightmare.

Matchy, I think I understand what you're saying but unfortunately that's a bit different to what I'm trying to do. To use the technique I think you're suggesting I need to be able to update the texture offset of each vertext. I can't find any command that allows me to do that which is what the problem is.

Just to clarify : My idea is that at the start all 128x128 tiles on my landscape are, for example, grass. A short while later, I might have to set, for example, 1352 of those squares to mud, 15 to snow, 823 to sand. Then a short while later, some of the snow might become ice, other snow ones may become grass again, some that were mud are now grass again, some previously untouched grass ones have become swampy etc. Being able to change the texture of each individual 3D tile is what I need to do.
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: matchy on 2012-Jun-10
Easy or I don't understand exactly what you mean. Like in Minecraft? The terrain is constantly being recreated to shift the texture offsets. I'm happy to provide sample code as long I am clear on what you really want and as far as I understand, even with animated texture (like for water).

Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: FutureCow on 2012-Jun-10
I'll put some images in to show what I mean.

Assume this is the initial landscape (it's not, I stole my image from another thread :D ) - also assume they are just textures and not flat colours. The landscape is a solid mesh where each vertex (tile corner) is (currently) an offset into a texture image that has images of snow, grass, mud etc textures.
(http://img85.imageshack.us/img85/9779/screen1sd.png)

Then you change only some of the tiles textures (again, assume the tile has a texture and not a flat colour). Note that not all the ones that were light blue have changed to purple, only one. Also one that was red is now purple.
(http://img685.imageshack.us/img685/1273/screen4qp.png)

Does that make it clearer?
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: matchy on 2012-Jun-10
I understand that but I'm still a little confused with the demo image. Can you have it so it looks like a landscape rather than a checkerboard?
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: FutureCow on 2012-Jun-10
Here's an actual screenshot. At the moment I've got it coloured based on height. I'm not sure why the colours are in bands running in 1 direction, it should be colouring in 2 directions. That's just temporary anyway until I get textures sorted. The theory is that every tile (tree's are every 2 tiles at the moment so that gives you an idea of the size tiles I'm working with) should be able to be changed based on how grassy it is. Lots of grass should be bright green. As it dries out, each tile will go towards dirt, and it should be able to have snow per tile etc.

(http://img836.imageshack.us/img836/6001/screen6pe.png)

It's exactly the same as the image from the previous post though, it should be able to be textured like a checkerboard potentially.
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: matchy on 2012-Jun-10
Okay, so now you want to mapped out streams, lakes, sand, whatever....something that resembles the surface of a landscape.
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: FutureCow on 2012-Jun-10
But importantly it has to be able to change reasonably frequently - I can make individual tiles a river now for example, but don't want to have them have to be a river for the whole game. I have to be able to make each tile change its texture while still having it part of the same mesh so I can run x_collisionray against it.
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: matchy on 2012-Jun-10
As I mentioned before, you just recreated the mesh and shift the texture offset in cycle according to a new tile map with a change from the ray collisions coordinates and click. So I imagine you click on a facet and it's quad texture is remapped to water/lake.

Why can't you do that?
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: FutureCow on 2012-Jun-10
Ah okay, when you were talking about the land being recreated before it didn't click to me that you were suggesting recreating the whole mesh each time to change the texture offsets.
I suppose that's doable. I was hoping more for a way to change one vertext without recreating the whole mesh to save the computational overhead. Failing that though recreating the whole mesh may be the way it'll have to go. Thanks Matchy!

I'll go with that unless anyone can suggest a way to change vertex information.
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: matchy on 2012-Jun-10
You simple can't modify a 3d object's vertices.  :zzz:

The technique is used for water and wave flags, regardless of texture mapping but then without changing the mesh an alternative is to simply redraw the sprite texture as a low res tile-map from a as many as like based textures 8x8. 1024 sprite / 128 tile = 8x8map to resemble grass, water, etc.  8)
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: erico on 2012-Jun-10
snif snif, funk funk, smells like powermonger...I´m getting excited with it! :-[
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: kanonet on 2012-Jun-10
Future i would forget X_Collisionray, just write your own so it doesnt matter if all tiles are in one mesh or if every tile is in its own mesh. Its not to difficult (as long as x and z coordinates are constant, only y is different - but you screnshot looks like this is the case), X_SCREEN2WORLD is a great help here.

How do you draw this currently and how do you texture it? Cuz i would expect it to be to slow if you make each tile an individual mesh and even more slow to texture it separately (x_settexture is slow).

Fastest GLB sollution (but still slow?) should be to draw all with one mesh and to texture it with only one big texture. So if you want to change your texture  for one tile, just change its part of the big texture (use an array and MEM2SPRITE) and texture the mesh with the modified texture. Downside of this method is, that you can only have low res textures for individual tiles (but tile are very small on your screenshot, so it would be ok?) and that you will get problems if you make a bigger terrain. Of cause you can split your mesh and texture in parts (especially if you make a bigger terrain). I dont know about the speed of MEM2SPRITE, but it should be ok, especially for big sprites, but it should be ok, cuz you only need to call it, when you change the texture, not every frame, splitting mesh and texture in smaller parts can help here too, but dont make to many of them (see speed of X_SETTEXTURE^^).

A 2nd way to do it would be to forget native GLB commands and use Opengl calls. I would recommand to have a look at glDrawArrays and it dependants, check my X_SPRITE replacement to see how to use them. Advantage would be, that you could draw the hole terrain in one mesh and you would be able to change texture coordinates for individual vertexes. So just have all types of landscape in one texture and ad start all tiles texture coordinates pointing at the grass part. Over time you could change this coordinates so it will point at mud etc. So you need just one (smaller) texture, no matter how many tiles you have and it will be way more faster than the native GLB way. Only downsides that i know so far is, that it would be a bit more difficult at the beginning and that your terrain would not be able to cast shadows, but you still can cast shadows at it if you want (and i dont know if collisions work, i guess no - but i already said, write your own one).

Just two ideas, hope this helps you. If you need help to implement one of them, just ask me.
Cheers.
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: FutureCow on 2012-Jun-11
No, nothing like powermonger (though it could easily be used for something similar). It's still a proof-of-concept at this point, I'll post details if it looks like I'm going to be able to produce the game I'm trying to.
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: Slydog on 2012-Jun-11
It may have been mentioned or suggested but I think your best option is to split your 128x128 map into smaller objects, such as 8x8 sections (which would be 16 by 16 of those small objects to fill 128x128).

Very similar to how MineCraft does it, except they have height / stacked objects to deal with.

The other advantage is it will draw faster if you are zoomed into a certain section where the entire field isn't in view.  You may have to do this manually, or maybe GLBasic or OpenGL does the occlusion culling for you.

It should be fairly fast to update / recreate an 8x8 object between frames. (rather than the entire 128x128 object!)
Title: Re: Changing terrain texture (ie. changing texture for part of a 3d object)
Post by: FutureCow on 2012-Jun-12
I had mostly dismissed the "split mesh into smaller meshes" plan as I didn't think it would give any savings when most tiles will change at various times (eg. a heavy snowstorm changes every tile to deep snow). What's probably obvious to everyone else - and hadn't occurred to me for some reason - is that the smaller meshes could be rebuilt in different game loops to spread the impact.

I'm not sure if the X_COLLISIONRAY statements will now add a lot more overhead as I'll have to do multiple checks rather than one, but hopefully OpenGL will know not to draw meshes that are off the screen and save cycles there.

Kanonet - if you want to lend any expertise here I'd be happy to hear it - my camera routine is pretty much a 6 degrees of freedom one (ie. it features tilt, zoom and movement so at any given time I might be zoomed so I can only see a few tiles, or zoomed out to see the entire mesh). I currently just do an X_SetTexture then a single draw object command.
I'm playing around with a few different ways to create the texture at the moment. Until I figure out the best way to do it, I'm currently just creating a 128x128 bitmap, drawing coloured pixels based on height at the correct location, then texturing the mesh with the image - 1 pixel per tile. I do want to do proper textures though rather than just 1 colour per tile.

Splitting the mesh might also change how I end up handling pathfinding on the terrain, I'll have to think about whether there are optimisations (or losses!!!) to be made there as a result too.... Hmmm....