I made a terrain of many small tiles with individual textures each. Of course its very slow if i dont call flattenStrong (130 fps instead of 3).
How can I get this texture-effect without the need to call 30sec-flatten?
Is there evan a way to get it faster than with flattening?
(yes i know geomip is made for such terrains but i dont get that texturing there)
if you dont need to regenerate it on every game start, you could use writeBamFile to cache it on disk. othervise split it into chunks or generate the terrain by writing the whole terrain into a model at once (using the vertexwriters).
bam-ing it is a good idea and ill do that if there is no other way, thx.
is there a way to get that texturing with geomipterrain or heightfieldtesselator without making one huge texture which makes panda exit?
Yes there is.
You’ll need to have two or more UV sets. One set covers the whole terrain and the other is repeated many times (tileing). The first set is a mask it, where it’s white texture #1 will be visible where it’s black texture #2 will show, gray colors will be a blend of #1 and #2.
This is called multitexturing.
Look up the forum for YARR if I’m not wrong it used this for geomitmapterrain.
What do you mean, using shaders making it slow? Modern GPUs translate everything to shaders anyway, so you shouldn’t be seeing a performance impact if you use a shader.
i meant that it propably will get slow when i use 50 layers - thats about the number of different tile-textures i need.
even though it could be fast enough - there should be a less brute-force way than excessive multitexturing.
im not totally happy with the current aproach: flattenStrong-bam-ing the whole terrain makes visibility-checks which could improve performance useless. i think ill have to subdivide the terrain eg in 8x8-parts for flattening so vis-check could help.
Are you sure you’ll need 50 layers on each and every tile?
You can have for example grass, rock, moss, dirt on some tiles, sand, pebbles, leaves, mud on some other and so on. You can have a colour variation layer or bake that into vertex colour.
i thought if i use geomip then i have to texture the whole terrain with one multitexture. this way ther would be layers for eg:
red flowers, yellow flowers, …, mixed fowers, wet grass, dry grass, sand-rocks, granite, mud, street, fallen leaves,…
class Tileset(object):
def __init__(self, templateString):
self.ts = templateString #some %-string like "tilesetname/tile-%02i.png" for warzone-tiles
self.loaded = dict() #already loaded textures
def getTex(self, num):
try:
return self.loaded[num]
except KeyError:
tex = Texture()
tex.load(self.ts % num)
tex.setWrapU(Texture.WMClamp)
tex.setWrapV(Texture.WMClamp)
tex.setMinfilter(Texture.FTLinearMipmapLinear)
tex.compressRamImage()
self.loaded[num] = tex
return tex
class Terrain(NodePath):
def __init__(self, heightmap, tileset, tilemap, hscale=32, blocksize=8):
self.tilemap = tilemap #which tile-type (in this version only texture) to put where
self.tileset = tileset #currently ony a wrapper for texture management and loading
self.terrain = GeoMipTerrain("")
self.terrain.setHeightfield(heightmap) #heightmap is obvious...
self.terrain.setBruteforce(True) #this is just a first implementation - should work without this as well. but beware when updating...
self.terrain.setBlockSize(blocksize) #attention: one texture per block
self.xTiles = heightmap.getReadXSize() / blocksize #tilemap has to be at least this large
self.yTiles = heightmap.getReadYSize() / blocksize
NodePath.__init__(self, self.terrain.getRoot())
self.setSz(hscale)
self.terrain.generate()
for x in xrange(self.xTiles):
for y in xrange(self.yTiles):
self.texTile(x, y)
def texTile(self, x, y): #puts a texture on the tile
v = self.tilemap.getGrayVal(x, self.yTiles - y - 1)
tile = self.getTile(x, y)
tile.setTexture(self.tileset.get(v))
tile.setTexPos(TextureStage.getDefault(), -x, -y, 0)
tile.setTexScale(TextureStage.getDefault(), self.xTiles, self.yTiles)
def getTile(self, mx, my): #the geomip's function only returns immutable tiles
return self.find("gmm%ix%i" % (mx, my))
def getTileAt(self, x, y):
return self.find("gmm%ix%i" % tuple(self.terrain.getBlockFromPos(x, y)))
#example
terrain=Terrain(PNMImage("heightfield.png"),Tileset("tilesetname/tile-%02i.png"),PNMImage("tiles.png"))
edit: added comments (i hope they make it understandeable)