Texturing Custom Meshes/Terrain

Started by
10 comments, last by Adrian Maggio 10 years, 4 months ago

Here's the scenario:

I procedurally generate terrain on the fly, creating an isosurface which is an overlay on top of a scalar field of data points. These underlying data points are basically voxel data, and I use the Marching Cubes algorithm to interpolate vertices, which are used to create the triangles for the meshes.

What I end up with is a contiguous terrain, which is split into chunks, with each chunk split into "blocks". Each block's outline, when looking from directly above, is a square, made up of up to 5 triangles.

The underlying mesh data (vertices, indices, texture coords, normals), are calculated for each "block", and then a mesh is built for each "chunk" (collection of blocks' data). Texture coords are determined for each triangle, and as such, you can see separate texture mappings for each triangle when looking at the textured mesh.

At a minimum, I would like to figure out how to apply the textures to each block as a whole, i.e.- stretch it over all the triangles in a block.

Better yet, I would like to implement something like texture-splatting on arbitrary regions of the terrain, spanning accross chunk and block boundaries, so that I can arbitrarily paint different textures where every I want them.

Ideally, I would like to do the splatting I mentioned procedurally, so that aspects of the terrain, (altitude, proximity), will determine what texture is used in what location.

Can someone clue me in to what is involved in achieving this?

I am using Ardor3D for mesh creation/texturing/etc...

Thanks!

Advertisement


At a minimum, I would like to figure out how to apply the textures to each block as a whole, i.e.- stretch it over all the triangles in a block.
i don't think I understand your problem. Your chunks are way too small by the way.

Textures go from 0.0 to 1.0 so you can just linearly interpolate positions of the vertices inside each chunk. The vertex to the left will have s=0, the one to the right s=1. You don't need to care about the actual position in the world, just the relative position of each vertex inside each chunk. Are you looking for the specific formula?

Previously "Krohm"

I would calculate all the vertex data before I'd cut the mesh into chunks, that makes it easier to generate continuous data (especially for the normals). I agree with Krohm, your chunks seem too small; I'd store at least some several thousand primitives per chunk.

Can you explain a bit more what kind of texture mapping you're trying to apply? If you use tileable textures there's no need to keep uvs in the 0 - 1 range. Since you have a uniform grid of vertices, you could also consider using vertex weight maps as splatting masks.

I never mentioned the chunk size. Without going into unnecessary details, I will say that a "block" consists of 0-5 triangles, depending on what Marching Cubes determines for that particular voxel. A chunk consists of 16x16x30 blocks. So that's 7680 blocks/chunk and potentially 38400 triangles/chunk, though in practice the triangle count is closer to 1280, (one layer of voxels). Only a small fraction of the blocks has any mesh data.

The concept of UV-mapping a texture to a mesh is not new to me. However, that standard case is not really what I'm looking for. I have smooth continuous terrain, and having regular blocks of texture just won't do.

Currently, I build a mesh for each chunk, which aggregates the triangle data from each block that has been touched by Marching Cubes.

I would like to be able to change the texture for any arbitrary area, based on location, altitude, material type, etc..., and also blend the boundaries between textures, similar to splatting.

Tell me more about vertex weight maps. I do have a uniform griz of vertices, in the x-z plane, at the block boundaries.

Texturing an arbitrary 3D surface is unfortunately not a thoroughly solved problem. However, there are a couple of common approaches:

- Pretend that your terrain is a simple height-map terrain, and just feed in the x,z positions of vertices as texture coordinates. This has the advantage of being very simple, but it results in stretched textures on slopes and overhangs, plus the inside of caves has the same texture as the ground above.

- Triplanar texture mapping (see this article for the basics). Effectively blends between a set of textures on each axis. Very flexible, looks great with careful texture design.

Either of the above can be combined with shader-based detail texture splatting to improve the look of the terrain. And you can drive the splatting through height, slope, etc. parameters for the procedural case.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Thank you. Good info, and awesome article.

Vertex splat-masks simply store their weight data at the vertex level (like vertex-normals, uvs etc.). They don't require uv-maps, but their drawback is the underlying vertex resolution needs to be high enough to be able to capture the desired amount of detail.

If the base-textures themselves tile, you won't have to assign each triangle its own texture space. This way more terrain doesn't linearly scale with more texture data.

splat.png

Would the techniques mentioned in this thread work across mesh boundaries? My terrain is made up of many smaller meshes.

Actually, I think I answered my own question regarding separate meshes. The voxel data, including the vertices I would use for the weight data, is already distributed in each block. So every separate mesh will already have the data it needs to paint textures. I think... in theory...


The voxel data, including the vertices I would use for the weight data, is already distributed in each block. So every separate mesh will already have the data it needs to paint textures. I think... in theory...

Most likely, yes. There are often various issues at the mesh boundaries which require workarounds. In particular:

- If your normal vectors don't match between the edges of neighbouring chunks you'll have issues matching the lighting across the seam. As long as you generate your normals directly from the 3D function, you should be fine.

- If you are placing mipmap'd textures across multiple tiles, the mipmap'ing doesn't always filter correctly on the edges. This can usually be remedied by clever mipmap generation.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

This topic is closed to new replies.

Advertisement