Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebGL - Textured terrain with heightmap

I'm trying to create a 3D terrain using WebGL. I have a jpg with the texture for the terrain, and another jpg with the height values (-1 to 1).

I've looked at various wrapper libraries (like SpiderGL and Three.js), but I can't find a sutable example, and if I do (like in Three.js) the code is not documented and I can't figure out how to do it.

Can anyone give me a good tutorial or example?

There is an example at Three.js http://mrdoob.github.com/three.js/examples/webgl_geometry_terrain.html which is almost what I want. The problem is that they create the colour of the mountains and the height values randomly. I want to read these values from 2 different image files.

Any help would be appriciated. Thanks

like image 428
goocreations Avatar asked Oct 03 '11 16:10

goocreations


3 Answers

Check out this post over on GitHub:

https://github.com/mrdoob/three.js/issues/1003

The example linked there by florianf helped me to be able to do this.

function getHeightData(img) {
    var canvas = document.createElement( 'canvas' );
    canvas.width = 128;
    canvas.height = 128;
    var context = canvas.getContext( '2d' );

    var size = 128 * 128, data = new Float32Array( size );

    context.drawImage(img,0,0);

    for ( var i = 0; i < size; i ++ ) {
        data[i] = 0
    }

    var imgd = context.getImageData(0, 0, 128, 128);
    var pix = imgd.data;

    var j=0;
    for (var i = 0, n = pix.length; i < n; i += (4)) {
        var all = pix[i]+pix[i+1]+pix[i+2];
        data[j++] = all/30;
    }

    return data;
}

Demo: http://oos.moxiecode.com/js_webgl/terrain/index.html

like image 126
poshaughnessy Avatar answered Oct 30 '22 08:10

poshaughnessy


Two methods that I can think of:

  1. Create your landscape vertices as a flat grid. Use Vertex Texture Lookups to query your heightmap and modulate the height (probably your Y component) of each point. This would probably be the easiest, but I don't think browser support for it is very good right now. (In fact, I can't find any examples)
  2. Load the image, render it to a canvas, and use that to read back the height values. Build a static mesh based on that. This will probably be faster to render, since the shaders are doing less work. It requires more code to build the mesh, however.

For an example of reading image data, you can check out this SO question.

like image 5
Toji Avatar answered Oct 30 '22 07:10

Toji


You may be interested in my blog post on the topic: http://www.pheelicks.com/2014/03/rendering-large-terrains/

I focus on how to efficiently create your terrain geometry such that you get an adequate level of detail in the near field as well as far away.

You can view a demo of the result here: http://felixpalmer.github.io/lod-terrain/ and all the code is up on github: https://github.com/felixpalmer/lod-terrain

To apply a texture to the terrain, you need to do a texture lookup in the fragment shader, mapping the location in space to a position in your texture. E.g.

vec2 st = vPosition.xy / 1024.0;
vec3 color = texture2D(uColorTexture, st)
like image 2
pheelicks Avatar answered Oct 30 '22 08:10

pheelicks