Can a heightfield map have muliple textures applied

I have been playing around with creating heightfield maps and adding texture to them. I have only managed to add one texture. The concept I am looking for is horizontal layers for ocean, sand, rock, vegetation, then snow with a minZ and maxZ for each layer. Can this even be done with Panda3D using Python?

#########################################################
from direct.showbase.ShowBase import *
from panda3d.core import *

# Initialize the scene and set the background to sky blue ################
base = ShowBase()
base.setBackgroundColor(.5, .5, 1, 1)

# Setting up a slight fog to give a natural look when hiding the horizon edge ###########
myFog = Fog("Foggy")
myFog.setColor(0.5, 0.5, 1)
myFog.setExpDensity(0.0002)
render.setFog(myFog)

# Setting up the heightfield and mipmap terrain ##################
terrain = GeoMipTerrain("mySimpleTerrain")
terrain.setHeightfield("models/big-island.png")

# Set some terrain visual properties ####################
terrain.setBlockSize(32)
terrain.setNear(40)
terrain.setFar(100)
terrain.setFocalPoint(base.camera)
terrain.generate()

# Setup the root NodePath for the convenience of applying Node settings ###############
root = terrain.getRoot()
root.reparentTo(render)
root.setSz(500)

# Apply texture on the terrain #######################$
grass_tex = loader.loadTexture("models/ground.jpg")
grass_tex.setWrapU(Texture.WM_repeat)
grass_tex.setWrapV(Texture.WM_repeat)
root.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldPosition)
root.setTexScale(TextureStage.getDefault(),512,512)
root.set_texture(grass_tex)
root.setPos(-500,-200,-360)

# Position the camera to view the demo character. ###############
base.trackball.node().setPos(0, 30, 0)
render.setAntialias(AntialiasAttrib.MAuto)

# Create Ambient Light so that the shadows are not too dark ################
ambientLight = AmbientLight('ambientLight')
ambientLight.setColor((.2, .2, .2, 1))
ambientLightNP = render.attachNewNode(ambientLight)
render.setLight(ambientLightNP)

# Directional light that helps create natural shadows ##################
directionalLight = DirectionalLight('directionalLight')
directionalLight.setColor((0.8, 0.8, 0.8, 1))

# Use a 512x512 resolution shadow map
directionalLight.setShadowCaster(True, 512, 512)
directionalLightNP = render.attachNewNode(directionalLight)

# This light is facing forwards, away from the camera.
directionalLightNP.setHpr(0, -20, 0)
render.setLight(directionalLightNP)

# Run the scene in a loop
base.run()

The simplest way might be to apply a custom shader that handles such functionality, I think.

My guess is that you could check Z position of vertices and adjust their UV coordinates? Or split the geometry into parts for each horizontal layer and apply your textures. This you can do with just python/panda.

@Pignon . I did try loading the terrain multiple times with different textures for each render. It looked OK, however, it had an exponential impact on the FPS.

Maybe I need a new computer. Hahaha

You might be able to do this via cunning application of texture combine modes–specifically, the “CMInterpolate” mode.

However, there may be limits to the number of textures that you can apply in this way, which may make a full implementation of what you want infeasible.

If feasible, a shader really is likely to be the simplest and best-performing solution, I think.

The main limit of the texturing pipeline in this is that it comes after lighting, so blending successive passes will not include lighting information, unless you add another pass at the end to multiply in the primary colour. It is much better to create a shader.

1 Like

I dont understand what you did from your description but I would try to look for a shader solution as Thaumaturge and rdb suggested. You will have to learn them eventually anyway.

@Pignon. I created three separate heightfield maps by chopping off the top. Then I slightly offset the Z value. Snow first. Vegetation layer is raised. Flat terrain layer is last. Looked great.

I did play around with the shaders a bit. The results did not look correct in Linux. Looks much better in Windows. I don’t know if it is the OS or my graphics card.

I have less time to work on this because my son broke his leg and will be home a few weeks.
His school classroom is on the third floor with no elevator. I am his teacher now.

Does it chop off the mesh? Or just make it flat? I dont know how GeoMipTerrain works but if you lose so much fps I guess the chopping off doesnt remove the parts you dont need and you end up with 3x triangles to render?

@Pignon. Very correct. It was the 3X issue that got me. (snow layer not chopped. vegetation layer was chopped at the mesh level. the heightfield editor provided the chop feature.) That was my first attempt at a solution before I created this thread. However, I was also trying to use a 4096 heightfield on a 12 year old computer. For my terrain grid concept, I had to scale it down to 256. A single 1024 will also work.

I was also thinking about a different workflow. Write a routine to fix the edges on the heightfield so they can be joined without gaps. Save it as an egg file. Import into Blender. Add the multiple textures with Blender, but also add trees, roads, buildings, etc. Create many different terrain grids using the same heightfield. Then render each one as needed using the egg file in Panda3D. I have no idea how this strategy will impact the FPS.

A hybrid alternative to the above is to write a terrain editor with Panda3D. Provide many egg objects that can be placed on the terrain. Save the edit metadata in json files for each terrain grid. This alternative should result in a much faster workflow with unlimited potential.

Im pretty sure Blender can also create terrain from heightmaps. So you could use that instead and then export it to .bam or .egg if you dont need it to generate yourself. Blender can be used as sort of level editor for Panda.

@Pignon. Learning Blender is already my next step. I have only done simple mesh modelling before. I definite realize that Blender has become a very powerful tool, but the learning curve is going to be a challenge. Pure coding is simple for me. Everything is will require some effort. I need to learn Blender anyway to create and edit my models.

If I recall correctly, at least one terrain-focussed editor has been posted by a community member. It might be worth searching the forum to see whether some or another such community-made tool might not suit your purposes!

It’s hard to say without seeing the shader–and even then, for my part it might call for someone with more knowledge.

But–the question of time aside–I wouldn’t discard shaders based on that experience, I think. They can very much produce good results on both Windows and Linux, I believe. (I used them under Ubuntu Linux, for what it’s worth.)

@Thaumaturge. I was already leaning toward the graphic card being the culprit. I am using an old computer found in a storage room at my export company. I started the company 17 years ago. Use your imagination to the age of the computer. My guess is 12 years. I have also been away from computer programming for 15 years. Just like riding a bike. Never forget. Good thing I kept my reference manuals. hahahahahahaha

I will search for the terrain editor that you mentioned. I have already found lots of useful code snippets in this forum. BTW, I did work through your tutorial. It definitely had new stuff I did not see in the users guide. Thanks. Hands on tutorials will always be much better than reading a users guide.

1 Like

As to the computer, fair enough! Depending on what hardware it has, and what drivers it has loaded, you could indeed see issues on one platform or another.

(I recall that I used to have trouble with the drivers for my graphics card under Linux before I loaded the relevant proprietary drivers.)

As to the tutorial, it’s my pleasure–I’m glad if it proved useful to you. :slight_smile: