Sign in to follow this  

Procedural terrain texture generation

This topic is 830 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a hexagonal grid of fields, each field has a certain terrain type. I assign every vertex of hexagon with terrain type and pass it as attribute to vertex and then fragment shader. Then I use the extrapolated value to blend terrain textures together.

 

For instance: 1 is grassy, 2 is desert.

 

Vertex shader:

varying vec2 vUv;
attribute float terrainType;
varying float vTerrainType;

void main()
{
   vUv = uv;
   vTerrainType = terrainType;
   vec4 mvPosition;
   mvPosition = modelViewMatrix * vec4( position, 1.0 );
   gl_Position = projectionMatrix * mvPosition;
}

Fragment shader:

uniform vec3 diffuse;
uniform float opacity;
varying vec2 vUv;
varying float vTerrainType;
uniform sampler2D map;
uniform sampler2D map1;

void main()
{
   gl_FragColor = vec4( diffuse, opacity );
   vec4 texelColor = texture2D( map, vUv ) * (2.0 - vTerrainType) + texture2D( map1, vUv ) * (vTerrainType - 1.0);
   gl_FragColor = gl_FragColor * texelColor;
}

Implementation is WebGL, if it makes any difference.

 

The result looks really unnatural, so is there any way to make it smoother and rounder?

 

PeqpEqm.jpg

Share this post


Link to post
Share on other sites

fist of all mvPosition = modelViewMatrix * vec4( position, 1.0 ); where is position then i dont see it how is that supposed to compile??

 

where is uv? post whole shader code...

Edited by ?W ?I ?R ?E ?D ? ?C ?A ?T

Share this post


Link to post
Share on other sites

fist of all mvPosition = modelViewMatrix * vec4( position, 1.0 ); where is position then i dont see it how is that supposed to compile??

 

where is uv? post whole shader code...

 

Well, Three.js decorates shader code and adds crapload of irrelevant attributes/uniforms and code, after stripping it's something like this:

precision highp float;
precision highp int;

uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
attribute vec3 position;
attribute vec2 uv;

varying vec2 vUv;
attribute float terrainType;
varying float vTerrainType;

void main()
{
   vUv = uv;
   vTerrainType = terrainType;
   vec4 mvPosition;
   mvPosition = modelViewMatrix * vec4( position, 1.0 );
   gl_Position = projectionMatrix * mvPosition;
}
precision highp float;
precision highp int;

uniform mat4 viewMatrix;
uniform vec3 cameraPosition;
uniform vec3 diffuse;
uniform float opacity;
varying vec2 vUv;
varying float vTerrainType;
uniform sampler2D map;
uniform sampler2D map1;

void main()
{
   gl_FragColor = vec4( diffuse, opacity );
   vec4 texelColor = texture2D( map, vUv ) * (2.0 - vTerrainType) + texture2D( map1, vUv ) * (vTerrainType - 1.0);
   gl_FragColor = gl_FragColor * texelColor;
}

Share this post


Link to post
Share on other sites

An alternative is to map a large texture across the hex grid, and use that texture to blend between terrain types. Example. Similar to how you would do it for a height-mapped terrain. This gives you finer-level detail to work with.

 

My project right now involves crazy amount of terrain. By crazy I mean around 300k fields, half of which will be water, rest landscape. So my goal is as much of procedural generation as possible. I plan on tiles of terrain textures I'll be using to generate entire world. Your solution would mean I'll have to store and pass to opengl lots of mask images to blend different terrain types, which I aim to avoid, that's why I'm looking for as much of procedural generation as possible.

Share this post


Link to post
Share on other sites

well i think he mean to scale the vertex if it is terrain (desert) by some amount value so then when you draw it with belnding it will overlap something so basically that means drawing bigger hexagon or whatever the shape is on smaller ones.

Share this post


Link to post
Share on other sites

well i think he mean to scale the vertex if it is terrain (desert) by some amount value so then when you draw it with belnding it will overlap something so basically that means drawing bigger hexagon or whatever the shape is on smaller ones.

 

Not entirely sure what you mean by "scaling vertex". Also you're referring the vertices on the edge between terrain types? Like on the edges of desert in the example I posted above?

Share this post


Link to post
Share on other sites
I don't mean any of that. I mean use a texture, draped across an entire chunk of level geometry, to blend between different terrain types.

You can procedurally generate the blend texture. In an RGBA texture you have 4 channels, which equates to 4 different terrain types. Each blend texture you add brings 4 more channels to the table.

If you use a technique such as is described here, then you can pack all of your terrain detail textures into a single atlas. That way, you only need 1 texture for the terrain atlas, and 1 large texture for each 4 terrain types for a given patch of terrain. If you implement biomes which can have drastically different terrain types, then you simply split the world up based on biome boundaries and use a terrain atlas and blend textures as appropriate.

If you use the technique described here then you can eliminate the smooth blend/fade between terrain types. In the image I linked earlier, I was using both of these techniques. Another example image from my heightmap editor (though not hex-based, the concept still applies): clicky Note that even if you elect not to use a large blend texture draped over the landscape, and instead choose to continue using a vertex attribute to supply the blending factors, you can still make use of this technique to mitigate the smoothness of the blend. I highly, highly recommend it.

This technique does not preclude procedural generation at all. If you have an algorithm for determining which areas of a texture will cover a given hex, then you can alter the blend values of the pixels at those locations in order to "set" a given hex to a terrain type. If you use a noise turbulence source or other source of randomized variation, you can "jitter" the boundaries to eliminate smoothness. Coupled with the technique above, of blending different types, the results can be quite amazing. My hex-based game is 100% procedurally generated. clicky clicky clicky I use these techniques (coupled with a tri-planar mapping technique, and am able to generate some quite large levels. It just requires a little wisdom and care in how the levels are partitioned based on environment. Edited by JTippetts

Share this post


Link to post
Share on other sites

Thanks for a great answer. Lots of good read there...

 

One large texture is not such a good idea, for a web based application especially, I suppose. I want to achieve good looking terrain on both close up and zoomed out views, which means I'll need good resolution, so loading lots of 4196x4196 images over web, even on demand, would be too heavy. Besides in this case I could just bake the complete texture instead.

 

Your last suggestions sounds really good, but I suppose by this

 

 

 


If you have an algorithm for determining which areas of a texture will cover a given hex

 

you mean an algorithm to know which pixel in fragment shader is covered by which field? Then based on some more information, such as distance from the boundary of two different terrain types, I can blend the texture much better than with just terrain type attribute on vertices?

Edited by denisve

Share this post


Link to post
Share on other sites

Got another suggestion on gamedev exchange. Pass the information about borders and vertex coordinate to fragment shader and then based on extrapolated coordinate calculate the distance to the border and calculate blending accordingly with the following suggested formula: clamp(pow(borderDistance, someExponent)*someScale, 0.0, 1.0)

 

Also was thinking about something like map editor, pretty much similar to Heroes VI map editor. Material library and placing the tiles manually. Then I can actually texture the edges any way I like. This won't be procedural though and will require lots of work designing the maps.

Share this post


Link to post
Share on other sites

This topic is 830 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this