純前端實現圖片偽3D視差效果

作者:vivo 互聯網前端團隊- Su Ning

本文通過depth-anything獲取圖片的深度圖,同時基于pixi.js,通過著色器編程,實現了通過深度圖驅動的偽3D效果。該方案支持鼠標/手勢與手機陀螺儀雙模式交互,在保證性能的同時,為不同終端用戶提供沉浸式的視覺體驗。

本文提供配套演示代碼,可下載體驗:

Github | vivo-parallax

一、引言

在當今的網頁設計與交互中,3D 效果能極大地提升用戶的視覺體驗和沉浸感。但是3D的物料設計成本依然很高,不僅需要專門的設計師掌握專業的建模工具,而且高精度模型帶來的渲染壓力也使移動端適配變得困難。

在這樣的背景下,利用2D圖片實現偽3D的效果,就展現出獨特的價值。開發者能以極低的資源消耗,在常規圖片素材上構建出具有空間縱深的交互效果。這種技術路徑不僅規避了傳統3D內容生產的復雜性,同時實現了視覺效果與性能消耗的平衡。

二、實現思路

相比二維平面,三維物體多了一個 z 軸作為深度信息。要讓 2D 平面呈現 3D 縱深感,關鍵在于隨著視角偏移時,畫面中的物體產生不同程度的位移,從而營造前后視差,實現偽 3D 效果。

為此,我們可以通過深度圖來獲取圖片的深度信息,根據這些信息對圖片進行分層。當視角改變時,通過調整不同層的偏移來實現視差效果。

三、獲取深度圖

在前端獲取深度圖可以借助現有的預訓練模型。例如使用 @huggingface/transformers 庫,指定任務類型為 ‘depth-estimation’,并選擇合適的預訓練模型,目前的深度圖推理模型尺寸普遍比較大,綜合效果和模型尺寸最終選擇了 ‘Xenova/depth-anything-small-hf’,量化后的模型尺寸為27.5mb。

import { pipeline } from '@huggingface/transformers';
export async function depthEstimator(url) {const depth_estimator = await pipeline('depth-estimation', 'Xenova/depth-anything-small-hf');const output = await depth_estimator(url);const blob=await output.depth.toBlob()return URL.createObjectURL(blob)
}

四、視差效果的實現

若想借助深度圖實現圖片分層,可依據深度區間進行劃分。假設深度圖中純白的色值為 0,純黑色值為 1,若將圖片切分為兩層,那么第一層的色值范圍為 0 - 0.5,第二層則是 0.5 - 1。為使畫面過渡更自然,可適當增加分層的數量。當鏡頭偏移時,層數越小的圖片位移幅度越大,層數越大的圖片位移幅度越小,借此便能實現視差效果。

然而,簡單的分層會引發一個問題:不同層的位移可能導致上層的部分區域遮擋背景圖案,而另一側則會出現空白。

圖片

針對空白部分,可采用光線步進算法進行顏色采樣。

在此,我們選用 Pixi.js 來實現這一效果。作為一款輕量級的 2D 渲染引擎,Pixi.js 在跨平臺 2D 動畫、游戲及圖形界面開發領域表現出色。其精靈支持自定義渲染管線,通過定制圖片片段著色器,能夠輕松實現視差效果。

4.1 光線步進算法(Ray Marching)

首先我們獲取到需要采樣顏色的坐標ray_origin,并根據用戶的交互事件(鼠標,觸摸,陀螺儀)增加鏡頭偏移offset。得到光線發射的起始坐標。

設置采樣步數step,設置光線的偏移向量ray_direction,每一步將光線增加ray_direction/step的坐標。獲取到當前深度圖坐標的深度信息,由于顏色越淺數值越大,要對深度值進行反轉,比對此時光線的z軸是否大于深度的反轉值,如果滿足條件則挑出循環,取此時光線坐標圖片的顏色。

由于每一步增加的偏移值可能跨度比較大,即使滿足z軸大于深度反轉值的條件,但是二者值的差距依然過大,我們還需要做一個二分搜索來優化采樣結果。即偏移值大于深度值,但二者的差值大于閾值的時候,回退一步光線,并將步進值再除以2,可以顯著提升采樣的精度。

圖片

代碼實現

varying vec2 vTextureCoord;
uniform sampler2D depthMap;
uniform sampler2D uSampler;
uniform vec3 offset;
const float enlarge = 1.06;vec3 perspective(vec2 uv) {const int step_count = 5;vec3 ray_origin = vec3(uv - 0.5, 0);ray_origin.xy -= offset.xy;vec3 ray_direction = vec3(0, 0, 1);ray_direction.xy += offset.xy;ray_direction /= float(step_count);const float hit_threshold = 0.01;vec4 color = vec4(0.0);for (int i = 0; i < step_count; i++) {ray_origin += ray_direction;float scene_z = 1.0 - texture2D(depthMap, ray_origin.xy + 0.5).x;if (ray_origin.z > scene_z) {if (ray_origin.z - scene_z < hit_threshold) {break;}ray_origin -= ray_direction;ray_direction /= 2.0;}}color = texture2D(uSampler, ray_origin.xy + 0.5);return color.rgb;
}void main(void ) {vec2 uv = (vTextureCoord - vec2(0.5)) / vec2(enlarge) + vec2(0.5);gl_FragColor = vec4(perspective(uv),1.0);
}

五、深度圖膨脹

邊緣膨脹操作主要用于處理深度圖,通過對每個像素鄰域內的深度值進行分析和處理,增強圖像的邊緣,可以使視差圖的邊緣更加平滑。這里使用一個簡單的膨脹函數實現。

圖片

varying vec2 vFilterCoord;
varying vec2 vTextureCoord;
uniform float widthPx;
uniform float heightPx;
uniform float dilation;
uniform sampler2D uSampler;
const int MAX_RADIUS = 10;float dilate(vec2 uv, vec2 px) {float maxValue = 0.0;float minValue = 1.0;for (int x = -MAX\_RADIUS; x <= +MAX_RADIUS; x++) {for (int y = -MAX\_RADIUS; y <= +MAX_RADIUS; y++) {vec2 offset = vec2(float(x), float(y));if (length(offset) > float(MAX_RADIUS)) continue;offset *= px;vec2 uv2 = uv + offset;float val = texture2D(uSampler, uv2).x;maxValue = max(val, maxValue);minValue = min(val, minValue);}}return dilation < 0.0? minValue: maxValue;
}void main(void ) {const float dilationScale = 1.26;float dilationStep = abs(dilationScale * dilation) / float(MAX_RADIUS);float aspect = widthPx / heightPx;vec2 px =widthPx > heightPx? vec2(dilationStep / aspect, dilationStep): vec2(dilationStep, dilationStep * aspect);gl_FragColor = vec4(vec3(dilate(vTextureCoord, px)), 1.0);}

六、總結

綜上所述,我們先利用預訓練模型生成圖片的深度圖,再借助 Pixi.js 與光線步進算法達成視差效果,最終通過對深度圖進行膨脹處理,實現邊緣的平滑過渡。

通過上面的操作,我們成功實現了圖片的偽 3D 效果,為用戶帶來了更具沉浸感的視覺體驗。

在實際應用過程中,我們觀察到,當視角偏移幅度過大時畫面會出現采樣失真現象。為解決這一問題,后續可考慮采用動態調整光線步進參數的方法,根據視角變化實時優化光線傳播路徑,從而減少采樣誤差;或者引入屏幕空間遮擋關系,通過精準模擬物體間的遮擋效果,增強畫面的真實感與層次感。隨著 WebGPU 技術的逐步普及,這一方案還有極大的優化空間。我們可借助計算著色器強大的并行計算能力,對復雜的 3D 計算任務進行高效處理,進一步提升計算性能,為網頁端 3D 交互開辟更多可能性,打造更加流暢、逼真的 3D 交互場景。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85321.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85321.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85321.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

英語寫作中“專注于”focus on、concentrate的用法

Focus on在論文寫作中常用&#xff0c;指出研究點&#xff0c;例如&#xff1a; There are three approaches to achieving ID authentication. Our study will focus on ……&#xff08;有三種途徑實現身份認證&#xff0c;我們的研究專注于……&#xff09; concentrate &…

go環境配置

下載對應版本的 go 版本 https://go.dev/dl/ 配置 vim ~/.zshrc export GOROOT/usr/local/go export PATH$PATH:$GOROOT/binsource ~/.zshrc >>>>>> go versiongoland 配置&#xff1a; &#x1f50d; 一、什么是GOPATH&#xff1f; GOPATH 是舊的項目結…

AI Agent智能體:底層邏輯、原理與大模型關系深度解析·優雅草卓伊凡

AI Agent智能體&#xff1a;底層邏輯、原理與大模型關系深度解析優雅草卓伊凡 一、AI Agent的底層架構與核心原理 1.1 AI Agent的基本構成要素 AI Agent&#xff08;人工智能代理&#xff09;是一種能夠感知環境、自主決策并執行行動的智能系統。其核心架構包含以下關鍵組件…

【手搓一個原生全局loading組件解決頁面閃爍問題】

頁面閃爍效果1 頁面閃爍效果2 封裝一個全局loading組件 class GlobalLoading extends HTMLElement {constructor() {super();this.attachShadow({ mode: open });}connectedCallback() {this.render();this.init();}render() {this.shadowRoot.innerHTML <style>.load…

unix/linux source 命令,其高級使用

就像在物理學中,掌握了基本定律后,我們可以開始研究更復雜的系統和現象,source 的高級用法也是建立在對其基本行為深刻理解之上的。 讓我們一起探索 source 的高級應用領域: 1. 條件化加載 (Conditional Sourcing) 根據某些條件來決定是否 source 一個文件,或者 source…

DexGarmentLab 論文翻譯

單個 專家 演示 裝扮 15 任務 場景 2500+ 服裝 手套 棒球帽 褲子 圍巾 碗 帽子 上衣 外套 服裝-手部交互 捕捉 搖籃 夾緊 平滑 任務 ...... 投擲 懸掛 折疊 ... 多樣化位置 ... 多樣化 變形 ... 多樣化服裝形狀 類別級 一般化 類別級(有或沒有變形) 服裝具有相同結構 變形 生…

WPF-Prism學習筆記之 “導航功能和依賴注入“

新建空白模板(Prism) 新建好后會有自動創建ViewModels和Views 在"MainWindow.xaml"文件里面標題去綁定了一個屬性"Title"&#xff0c;而"MainWindowViewModel.cs"里面繼承一個非常重要的"BindbleBase"(prism框架里面非常重要的)。所以…

《C++初階之入門基礎》【C++的前世今生】

【C的前世今生】目錄 前言&#xff1a;---------------起源---------------一、歷史背景二、橫空出世---------------發展---------------三、標準立世C98&#xff1a;首個國際標準版本C03&#xff1a;小修訂版本 四、現代進化C11&#xff1a;現代C的開端C14&#xff1a;對C11的…

YOLOv5-入門篇筆記

1.創建環境 conda create -n yolvo5 python3.8 去pytorch.org下載1.8.2的版本。 pip --default-timeout1688 install torch1.8.2 torchvision0.9.2 torchaudio0.8.2 --extra-index-url https://download.pytorch.org/whl/lts/1.8/cu111 github上下載yolov5的zip pip --def…

【PostgreSQL 03】PostGIS空間數據深度實戰:從地圖服務到智慧城市

PostGIS空間數據深度實戰&#xff1a;從地圖服務到智慧城市 關鍵詞 PostGIS, 空間數據庫, 地理信息系統, GIS, 空間查詢, 地理分析, 位置服務, 智慧城市, 空間索引, 坐標系統 摘要 PostGIS是PostgreSQL的空間數據擴展&#xff0c;它將普通的關系數據庫轉變為強大的地理信息系統…

科技修真的解決方案

“科技修真”是一個結合現代科技與修真&#xff08;玄幻&#xff09;元素的創新概念&#xff0c;通常出現在科幻或玄幻文學作品中&#xff0c;但也可能指代現實中的科技與傳統文化、超自然理念的融合探索。以下是幾種可能的“科技修真”方案&#xff0c;涵蓋技術實現、文化融合…

STM32的HAL編碼流程總結(上部)

目錄 一、GPIO二、中斷系統三、USART串口通信四、I2C通信五、定時器 一、GPIO 1.選擇調試類型 在SYS中Debug選擇Serial Wire模式 2.選擇時鐘源 在RCC中將HSE和LSH都選擇為內部晶振 3.時鐘樹配置 4.GPIO配置 在芯片圖上選擇開啟的引腳和其功能 配置引腳的各自屬性 5.工…

java直接獲取MyBatis將要執行的動態sql命令(不是攔截器方式)

目錄 前言 一. 準備數據 1. 傳輸過來的json條件數據 2. mybatis 配置的動態sql 3. 想要的最終會執行的sql并返回給頁面展示 二. 實現方式 三. 最終代碼 前言 1.在平常開發過程中,MyBatis使用時非常多的,一般情況下我們只需要在控制臺看看MyBatis輸出的日志,要不就是實…

機器學習算法-決策樹

今天我們用一個 「相親決策」 的例子來講解決策樹算法&#xff0c;保證你輕松理解原理和實現&#xff01; &#x1f333; 決策樹是什么&#xff1f; 決策樹就像玩 「20個問題」猜謎游戲&#xff1a; 你心里想一個東西&#xff08;比如「蘋果」&#xff09; 朋友通過一系列問題…

2025——》VSCode Windows 最新安裝指南/VSCode安裝完成后如何驗證是否成功?2025最新VSCode安裝配置全攻略

1.VSCode Windows 最新安裝指南: 以下是 2025 年 Windows 系統下安裝 Visual Studio Code(VSCode)的最新指南,結合官方文檔與實際操作經驗整理而成: 一、下載官方安裝包: 1.訪問官網: 打開瀏覽器,進入 VSCode 官方下載頁面https://code.visualstudio.com/Download 2…

【Elasticsearch】suggest

在Elasticsearch中&#xff0c;suggest 是一個非常強大的功能&#xff0c;用于實現自動補全、拼寫糾錯和模糊搜索等功能。它可以幫助用戶更快地找到他們想要的內容&#xff0c;同時提升搜索體驗。以下是關于 suggest 的詳細使用方法和常見場景。 1\. Suggest 的基本概念 sugges…

[SAP] 如何查詢當前屏幕的Tcode?

事務代碼Tcode是SAP中到達特定屏幕的快捷路徑 如何查詢以下屏幕的事務碼Tcode&#xff1f; 要瀏覽當前所使用的屏幕的事務碼&#xff0c;可以選擇System | Status 這里的事務代碼是[VA22]&#xff0c;它是Change Quotation的事務代碼

PostgreSQL的擴展 dblink

PostgreSQL的擴展 dblink dblink 是 PostgreSQL 的一個核心擴展&#xff0c;允許在當前數據庫中訪問其他 PostgreSQL 數據庫的數據&#xff0c;實現跨數據庫查詢功能。 一、dblink 擴展安裝與啟用 1. 安裝擴展 -- 使用超級用戶安裝 CREATE EXTENSION dblink;2. 驗證安裝 -…

ADB推送文件到指定路徑解析

您執行的命令 adb push ota.zip /sdcard/Download 中&#xff0c;目標路徑 /sdcard/Download 是您顯式指定的&#xff0c;因此 ADB 會直接將文件推送到此位置。具體過程如下&#xff1a; 1. 命令結構解析 adb push&#xff1a;ADB 的推送指令。ota.zip&#xff1a;本地計算機上…

Linux 內核中 skb_orphan 的深度解析:從版本差異到核心機制

引言 在 Linux 內核網絡子系統中,struct sk_buff(簡稱 skb)是管理網絡數據包的核心數據結構。skb_orphan 作為其生命周期管理的關鍵函數,負責切斷 skb 與所屬 socket 的關聯,確保數據包在復雜處理流程中的獨立性。本文將從代碼實現、版本差異、使用場景等多個維度,深入解…