如何使用WebGL创建伪3D图像效果

Demo: tympanus.net/Tutorials/F...

code: github.com/akella/fake...

WebGL 如今变得越来越流行,它让我们能够为网页创建独特的交互式动画。你可能见过使用 Blotter.js 制作的文字扭曲效果,或者用 THREE.MeshLine 创建的动画线条。今天你将学习如何使用原生 WebGL 创建一个交互式的"伪"3D 效果。

如果你使用一些社交软件,可能见过 3D 照片。3D 照片让场景栩栩如生。我们可以用任意照片和一点点代码来重现这种效果。

通常,这类效果会依赖于 Three.js 或 Pixi.js,这些强大的库在编码时提供了许多有用的功能。今天我们不使用任何库,而是直接使用原生 WebGL API。

那么让我们开始吧。


入门准备

对于这个效果,我们将使用原生 WebGL API。

一个帮助你快速入门 WebGL 的网站: webglfundamentals.org

WebGL 常因其冗长而被诟病,这是有原因的。所有全屏着色器效果(即使是 2D 的)的基础都是某种平面或网格,即所谓的"四边形"(quad),它被拉伸到整个屏幕上。说到冗长,在 three.js 中我们只需写 THREE.PlaneGeometry(1,1) 就能创建一个 1×1 的平面,而在原生 WebGL 中我们需要这样做:

js 复制代码
let vertices = new Float32Array([
  -1, -1,
  1, -1,
  -1, 1,
  1, 1,
])
let buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

现在我们有了平面,就可以对使用顶点着色器和片段着色器了。


准备图像

为了让这个效果生效,我们需要为图像创建一个深度图(depth map) 。构建深度图的主要原则是:我们必须根据图像中物体的 Z 位置(即远近)来分离图像的不同部分,从而将前景与背景区分开。

为此,我们可以在 Photoshop 中打开图像,并按照以下方式在原始照片上绘制灰色区域:

(图像展示了一座山,你可以看到,物体离相机越近,深度图中的区域就越亮。)

下一节我们将解释为什么这种着色方式是有道理的。


着色器(Shaders)

渲染逻辑主要在着色器中完成。正如 MDN Web 文档中所述:

着色器是用 OpenGL ES 着色语言(GLSL)编写的程序,它接收构成形状的顶点的信息,并生成将像素渲染到屏幕上所需的数据:即像素的位置和颜色。绘制 WebGL 内容时会运行两个着色器函数:顶点着色器和片段着色器。

一个学习着色器的资源: The Book of Shaders

顶点着色器不会做太多事情,它只是显示顶点:

glsl 复制代码
attribute vec2 position;
void main() {
    gl_Position = vec4(position, 0, 1);
}

最有趣的部分将发生在片段着色器中。我们在其中加载两张图像:

glsl 复制代码
void main() {
    vec4 depth = texture2D(depthImage, uv);
    gl_FragColor = texture2D(originalImage, uv); // 仅显示原始照片
}

记住,深度图是黑白的。对着色器来说,颜色只是一个数字:1 是白色,0 是纯黑。uv 变量是一个二维坐标,用于存储要显示的像素信息。利用这两样东西,我们可以使用深度信息来稍微移动原始照片的像素。

让我们从鼠标移动开始:

glsl 复制代码
vec4 depth = texture2D(depthImage, uv);
gl_FragColor = texture2D(originalImage, uv + mouse);

看起来是这样的:

现在让我们加入深度:

glsl 复制代码
vec4 depth = texture2D(depthImage, uv);
gl_FragColor = texture2D(originalImage, uv + mouse * depth.r);

效果如下:

由于纹理是黑白的,我们可以只取红色通道(depth.r),并将其乘以鼠标在屏幕上的位置值。这意味着,像素越亮,它跟随鼠标移动的距离就越大;而暗的像素则几乎不动。就这么简单,却能产生如此漂亮的 3D 幻觉。


参考资料与致谢


原文:tympanus.net/codrops/201...

工具:huggingface.co/spaces/pyto...

相关推荐
爱看书的小沐11 小时前
【小沐杂货铺】基于Three.js绘制三维管道Pipe(WebGL、vue、react)
javascript·vue.js·webgl·three.js·管道·pipe·三维管道
梦凡尘2 天前
webgl 变换矩阵:旋转、平移、缩放
webgl
倚剑仙3 天前
Unity-WebGL开发——用IIS(Internet Information Services)部署webGL工程
unity·游戏引擎·webgl
xhload3d6 天前
热力图可视化为何被广泛应用?| 图扑数字孪生
3d·html5·webgl·数字孪生·可视化·热力图·三维建模·轻量化·电力能源·空间热力图
十年_H7 天前
Cesium 顶点着色器的数据来源
javascript·webgl·cesium
xhload3d13 天前
WebGL/Canvas 内存泄露分析
低代码·3d·html5·webgl·数字孪生·可视化·软件开发·工业互联网·内存泄漏·轻量化·技术应用·hightopo
爱看书的小沐15 天前
【小沐杂货铺】基于Three.js渲染三维风力发电机(WebGL、vue、react、WindTurbine)
javascript·vue.js·webgl·three.js·opengl·风力发电机·windturbine
郝学胜-神的一滴15 天前
Three.js光照技术详解:为3D场景注入灵魂
开发语言·前端·javascript·3d·web3·webgl
linweidong16 天前
让低端机也能飞:Canvas/WebGL/Viz 分层、降级渲染与数据抽样策略
前端框架·webgl·canvas·前端动画·前端面经·css渲染·动画优化
CAD老兵18 天前
打造高性能二维图纸渲染引擎系列(一):Batched Geometry 助你轻松渲染百万实体
前端·webgl·three.js