如何使用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...

相关推荐
ThreePointsHeat2 天前
Unity WebGL打包后启动方法,部署本地服务器
unity·游戏引擎·webgl
林枫依依4 天前
电脑配置流程(WebGL项目)
webgl
冥界摄政王5 天前
CesiumJS学习第四章 替换指定3D建筑模型
3d·vue·html·webgl·js·cesium
温宇飞7 天前
高效的线性采样高斯模糊
javascript·webgl
冥界摄政王8 天前
Cesium学习第一章 安装下载 基于vue3引入Cesium项目开发
vue·vue3·html5·webgl·cesium
光影少年11 天前
三维前端需要会哪些东西
前端·webgl
nnsix11 天前
Unity WebGL jslib 通信时,传入字符串,变成数值 问题
webgl
二狗哈11 天前
Cesium快速入门34:3dTile高级样式设置
前端·javascript·算法·3d·webgl·cesium·地图可视化
AlanHou11 天前
Three.js:Web 最重要的 3D 渲染引擎的技术综述
前端·webgl·three.js
二狗哈12 天前
Cesium快速入门33:tile3d设置样式
3d·状态模式·webgl·cesium·地图可视化