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

13
我正在尝试使用WebGL创建3D地形。我有一个带有地形纹理的jpg文件和另一个带有高度值(从-1到1)的jpg文件。
我查看了各种包装库(如SpiderGL和Three.js),但是我找不到合适的示例,即使我找到了(例如在Three.js中),代码也没有文档说明,我无法弄清楚如何做。
有人可以给我提供一个好的教程或示例吗?
Three.js网站上有一个示例http://mrdoob.github.com/three.js/examples/webgl_geometry_terrain.html,几乎符合我的要求。问题是,他们随机创建山脉的颜色和高度值。我想从两个不同的图像文件中读取这些值。
感谢任何帮助。

1
请注意,JPEG 格式可能不适合地形图像,因为它是有损压缩的。JPEG 压缩会导致一些伪影和细节丢失,而这些问题在地形图中可能表现为你没有预料到的细微凸起。 - izb
5个回答

13

请看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


5
我能想到的两种方法如下:
  1. 将景观顶点创建为平面网格。使用顶点纹理查找来查询高度图并调节每个点的高度(可能是Y分量)。这可能是最简单的方法,但我认为当前浏览器对其的支持非常不好。(实际上,我找不到任何示例)
  2. 加载图像,将其渲染到画布上,并使用它来读取高度值。基于此构建静态网格。由于着色器要做的工作较少,因此这可能会更快地呈现。但是,构建网格需要更多的代码。
例如,要了解读取图像数据的示例,您可以查看此SO问题

1
在几乎所有情况下,选项2会更适合您。仅当您渲染的是地形时,选项1才适用,因为所有高程数据都将由着色器单独知道,您将需要其他手段来定位您的(可能是)其他场景对象。 - Chiguireitor

2
您可能对我关于这个主题的博客文章感兴趣:http://www.pheelicks.com/2014/03/rendering-large-terrains/ 我专注于如何高效地创建您的地形几何,以便在近处和远处都获得足够的细节水平。
您可以在此处查看结果的演示:http://felixpalmer.github.io/lod-terrain/,所有代码都在github上:https://github.com/felixpalmer/lod-terrain 要将纹理应用于地形,您需要在片段着色器中进行纹理查找,将空间位置映射到纹理中的位置。例如:
vec2 st = vPosition.xy / 1024.0;
vec3 color = texture2D(uColorTexture, st)

1
根据你的GLSL技能,你可以编写一个GLSL顶点着色器,将纹理赋值给其中一个纹理通道,并在顶点着色器中读取该值(我相信你需要一张现代卡才能在顶点着色器中读取纹理,但这可能只是我显老 :P) 在顶点着色器中,根据从纹理中读取的值将顶点的z值进行翻译。

0

Babylon.js使这个实现变得非常容易。您可以在以下链接中查看示例:高度图游乐场

他们甚至使用Cannon.js物理引擎进行了实现,因此您可以处理碰撞:带碰撞的高度图

注意:截至本文撰写时,它仅适用于cannon.js物理插件,并且摩擦力不起作用(必须设置为0)。此外,请确保在设置物理状态之前设置网格/模拟器的位置,否则会出现奇怪的行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接