WebGL - 带有高度图的纹理地形

时间:2011-10-03 16:42:49

标签: javascript webgl terrain three.js heightmap

我正在尝试使用WebGL创建3D地形。我有一个带有地形纹理的jpg,另一个带有高度值(-1到1)的jpg。

我查看了各种包装器库(如SpiderGL和Three.js),但是我找不到一个可变的示例,如果我这样做(比如在Three.js中)代码没有记录,我可以'弄清楚该怎么做。

任何人都可以给我一个很好的教程或示例吗?

在Three.js http://mrdoob.github.com/three.js/examples/webgl_geometry_terrain.html有一个例子,这几乎是我想要的。问题是他们随机创造了山脉的颜色和高度值。我想从2个不同的图像文件中读取这些值。

任何帮助都会得到满足。 感谢

5 个答案:

答案 0 :(得分:12)

在GitHub上查看这篇文章:

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

florianf联系在那里的例子帮助我做到了这一点。

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;
}

演示:http://oos.moxiecode.com/js_webgl/terrain/index.html

答案 1 :(得分:5)

我能想到的两种方法:

  1. 将您的风景顶点创建为平面网格。使用“顶点纹理查找”查询高度图并调整每个点的高度(可能是Y分量)。这可能是最简单的,但我认为浏览器对它的支持现在非常好。 (事实上​​,我找不到任何例子)
  2. 加载图像,将其渲染到画布,然后使用它来回读高度值。基于此构建静态网格物体。这可能会更快渲染,因为着色器的工作量较少。但是,它需要更多代码来构建网格。
  3. 有关阅读图像数据的示例,您可以查看this SO question.

答案 2 :(得分:2)

您可能对我关于此主题的博客文章感兴趣:http://www.pheelicks.com/2014/03/rendering-large-terrains/

我专注于如何有效地创建地形几何体,以便在近场和远处获得足够的细节。

您可以在此处查看结果的演示:http://felixpalmer.github.io/lod-terrain/并且所有代码都在github上:https://github.com/felixpalmer/lod-terrain

要将纹理应用于地形,您需要在片段着色器中执行纹理查找,将空间中的位置映射到纹理中的位置。 E.g。

vec2 st = vPosition.xy / 1024.0;
vec3 color = texture2D(uColorTexture, st)

答案 3 :(得分:1)

根据你的GLSL技能,你可以编写一个GLSL顶点着色器,将纹理指定给你的一个纹理通道,并读取顶点着色器中的值(我相信你需要一张现代卡来读取顶点着色器中的纹理)但这可能就是我显示我的年龄:P)

在顶点着色器中,根据从纹理中读取的值来平移顶点的z值。

答案 4 :(得分:0)

Babylon.js使这非常容易实现。您可以在以下位置查看示例: Heightmap Playground

他们甚至用它实现了Cannon.js物理引擎,因此你可以处理碰撞:Heightmap with collisions

注意:在撰写本文时,它仅适用于cannon.js物理插件,并且摩擦不起作用(必须设置为0)。此外,确保在设置物理状态之前设置网格/冒名顶替者的位置,否则您将获得奇怪的行为。

相关问题