Shadertoy著色器移植到Three.js經驗總結

Shadertoy是一個流行的在線平臺,用于創建和分享WebGL片段著色器。里面有很多令人驚嘆的畫面,甚至3D場景。本人也移植了幾個ShaderToy上的著色器。本文將詳細介紹移植過程中需要注意的關鍵點。

1. 基本結構差異

想要移植ShaderToy的shader到three.js,需要先了解他們直接的差異。他們之間的差異主要在以下幾個方面:

  1. ShaderToy沒有頂點著色器
    ShaderTory上面的shader只有片元著色器,沒有幾何,移植到three.js上需要構造一個默認的頂點著色器,同時提供幾何信息。這個也比較簡單,使用兩個三角形鋪面整個視口即可。其實用其他的方式也可以,例如用一個大的三角形,只要有個物體幾何能充滿整個視口即可。

  2. ShaderToy提供了很多內置變量
    ShaderToy提供了不少內置變量,,在three.js中需要咱們自己用uniform來傳入。ShaderToy內置變量處理方法如下:

全局變量含義three.js修改方案核心代碼
uniform vec3 iResolution;視口大小,單位像素uniforms.iResolution = { value: new THREE.Vector2(options.width, options.hieght) }
uniform float iTime;從開始運行到現在的時間,單位秒var clock = new THREE.Clock();
this.uniforms.iTime.value = this.clock.getElapsedTime();
uniform float iTimeDelta;上一幀渲染到現在的時間,單位秒var clock = new THREE.Clock();
this.uniforms.iTimeDelta.value = this.clock.getDelta();
uniform int iFrame;第幾幀this.uniforms.iFrame.value = this.uniforms.iFrame.value + 1;
uniform float iChannelTime[4];//
uniform vec3 iChannelResolution[4];每個通道的分辨率,單位像素uniforms[“iChannelResolution”] = { type: “v3v”, value: [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), ] };
uniform vec4 iMouse;是vec4類型,xy是鼠標當前位置與單擊位置,zw是單擊位置document.addEventListener(‘mousemove’, (e) => { material.uniforms.iMouse.value.x = e.clientX; material.uniforms.iMouse.value.y = window.innerHeight - e.clientY; }); document.addEventListener(‘mousedown’, (e) => { material.uniforms.iMouse.value.z = e.clientX; material.uniforms.iMouse.value.w = window.innerHeight - e.clientY; });
uniform samplerXX iChanneli;通道的紋理uniforms[“iChannel” + i] = { type: “t”, value: texture }
  1. ShaderToy語法的差異

ShaderToy語法核心都是 GLSL,只是在在變量命名、輸入輸出方式、內置函數/變量等方面存在區別。以下是關鍵語法差異的對比:

ShaderToythree.js
入口函數是:mainImage(out vec4 fragColor, in vec2 fragCoord)入口函數是:void main()
fragCoord當前像素的坐標用的是gl_FragCoord
用變量fragColor作為輸出通過 gl_FragColor 變量輸出
不需要定義變量精度需定義精度:precision highp float; precision highp int;precision highp sampler2D;precision highp samplerCube;

移植基本模版

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Shadertoy to Three.js</title><style>body {margin: 0;overflow: hidden;}canvas {display: block;}</style>
</head><body><script src="./three.min.js"></script><script>const scene = new THREE.Scene();const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);const renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);console.log(renderer.capabilities.isWebGL2)const geometry = new THREE.BufferGeometry();geometry.setAttribute("position", new THREE.Float32BufferAttribute([-1, -1, 0,1, -1, 0,1, 1, 0,-1, 1, 0], 3))geometry.setIndex([0, 1, 2, 0, 2, 3]);const material = new THREE.RawShaderMaterial({uniforms: {iResolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },iTime: { value: 0 },mouse: { value: new THREE.Vector4(0, 0, 0, 0) },},// glslVersion: THREE.GLSL3,vertexShader: `#version 300 esin vec3 position;void main() {gl_Position = vec4(position, 1.0);}`,fragmentShader: `#version 300 es
precision highp float;
precision highp int;
precision highp sampler2D;
precision highp samplerCube;
out vec4 fragColor;uniform vec2 iResolution;
uniform float iTime;void main(  )
{vec2 uv = gl_FragCoord.xy/iResolution.xy;// [0,1]uv -= 0.5;uv.x *= iResolution.x / iResolution.y;float d = length(uv);float r = 0.3;float c = smoothstep(r, r + 0.002, d);fragColor = vec4(vec3(c), 1.);
}
`});const plane = new THREE.Mesh(geometry, material);scene.add(plane);window.addEventListener('resize', () => {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);material.uniforms.iResolution.value.set(window.innerWidth, window.innerHeight);});document.addEventListener('mousemove', (e) => {material.uniforms.iMouse.value.x = e.clientX;material.uniforms.iMouse.value.y = window.innerHeight - e.clientY;});document.addEventListener('mousedown', (e) => {material.uniforms.iMouse.value.z = e.clientX;material.uniforms.iMouse.value.w = window.innerHeight - e.clientY;});function animate() {requestAnimationFrame(animate);material.uniforms.iTime.value = performance.now() / 1000; // 秒為單位renderer.render(scene, camera);}animate();</script>
</body></html>

這個模版是畫圓的實例,效果如下:

有以下幾點需要注意:

  1. 兩個三角形面片的坐標已經在[-1, 1]之間,不需要在VertexShader進行坐標變換,所有頂點著色器代碼沒有MVP矩陣:
#version 300 es
in vec3 position;
void main() {gl_Position = vec4(position, 1.0);
}
  1. 使用了RawShaderMaterial而不是ShaderMaterial,這樣可對Shader代碼進行完全掌控
  2. 語法上使用了WebGL2.0的語法,如果使用1.0的語法,需去掉版本聲明、一些關鍵字

最后展示一個稍微復雜點的Shader效果:

結語

將Shadertoy著色器移植到Three.js需要對兩者之間的差異有清晰理解。正確處理全局變量、語法、渲染管線等關方面的差異,可將絕大多數Shadertoy效果成功移植到Three.js項目中。

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

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

相關文章

StarRocks SRCA 考試心得總結

文章目錄 前言0 什么是StarRcoks&#xff1f;1. 關于 SRCA 考試2. 備考資料與學習方式2.1 官方文檔與教程2.2 在線培訓課程2.3 實戰演練 3. 重點考試內容3.1 StarRocks 架構與原理3.2 數據導入與導出3.3 SQL 查詢優化3.4 性能調優 4. 備考建議4.1 多做實操4.2 注重考試中的細節…

什么是 Spring Profiles 以及如何在 Spring Boot 中使用:配置與實踐指南

在現代應用開發中&#xff0c;應用程序通常需要在不同環境&#xff08;如開發、測試、生產&#xff09;中運行&#xff0c;每個環境可能有不同的配置&#xff08;如數據庫、日志級別、消息隊列&#xff09;。Spring Profiles 是 Spring 框架提供的一項功能&#xff0c;用于根據…

Spring Cloud Gateway限流:基于Redis的請求限流實現

文章目錄 引言一、Spring Cloud Gateway限流基礎1.1 限流機制概述1.2 Redis分布式限流原理 二、實現基于Redis的限流方案2.1 環境準備與依賴配置2.2 配置限流策略2.3 自定義限流響應 三、高級應用與最佳實踐3.1 動態限流規則調整3.2 優先級與降級策略3.3 監控與告警 總結 引言 …

keil修改字體無效,修改字體為“微軟雅黑”方法

在網上下載了微軟雅黑字體&#xff0c;微軟雅黑參考下載鏈接 結果在Edit->Configuration中找不到這個字體 這個時候可以在keil的安裝目錄中找到UV4/global.prop文件 用記事本打開它進行編輯&#xff0c;把字體名字改成微軟雅黑 重新打開keil就發現字體成功修改了。 這個…

CSS文字特效實例:猜猜我是誰

CSS文字特效實例&#xff1a;猜猜我是誰 引言 在之前的文章中&#xff0c;我們分別實現了空心文字、文字填充、文字模糊、文字裂開等效果。本文將使用一個小實例&#xff0c;組合使用相關特效&#xff1a;當鼠標懸停在圖片上時&#xff0c;其余圖片模糊&#xff0c;且文字會上…

美團社招一面

美團社招一面 做題 1、面試題 <style> .outer{width: 100px;background: red;height: 100px; }.inner {width: 50px;height: 50px;background: green; }</style> <div class"outer"><div class"inner"></div> </div>…

InitializingBean接口和@PostConstruct-筆記

1. InitializingBean 簡介 1.1 功能簡介 InitializingBean 是 Spring 框架中的一個接口&#xff0c;用在 Bean 初始化后執行自定義邏輯。它提供了 afterPropertiesSet() 方法&#xff0c;該方法在以下時機被 Spring 容器自動調用&#xff1a; 屬性注入完成后&#xff08;即所…

《代碼整潔之道》第9章 單元測試 - 筆記

測試驅動開發 (TDD) 是一種編寫整潔代碼的“規程”或“方法論”&#xff0c;而不僅僅是測試技術。 JaCoCo 在運行測試后生成詳細的覆蓋率報告的工具&#xff0c; maven 引用。 測試驅動開發 測試驅動開發&#xff08;TDD&#xff09;是什么&#xff1f; TDD 不是說寫完代碼…

openGauss新特性 | DataKit支持PostgreSQL到openGauss的遷移能力

Postgresql-\>openGauss遷移工具debezium-connector-postgres 可獲得性 本特性自openGauss 7.0.0-RC1版本開始引入。 特性簡介 debezium-connector-postgres工具是一個基于Java語言的Postgresql到openGauss的復制工具。該工具提供了初始全量數據及對象&#xff08;視圖、…

在MySQL Shell里 重啟MySQL 8.4實例

前一段時間看到MySQL官方視頻的Oracle工程師在mysql shell里面重啟mysql實例&#xff0c;感覺這個操作很方便&#xff0c;所以來試試&#xff0c;下面為該工程師的操作截圖 1.MySQL Shell 通過root用戶連上mysql&#xff0c;shutdown mysql實例 [rootmysql8_3 bin]# mysqlshMy…

truffle

文章目錄 truffle目錄結構各文件作用在本地測試合約 truffle 項目來自https://github.com/Dapp-Learning-DAO/Dapp-Learning/blob/main/basic/04-web3js-truffle/README-CN.md Truffle 是基于 Solidity 語言的一套開發框架&#xff0c;它簡化了去中心化應用&#xff08;Dapp&…

SpringCloud核心組件Eureka菜鳥教程

關于Spring Cloud Eureka的核心概念 Eureka 是 Netflix 開源的一款基于 REST 的服務發現工具&#xff0c;主要用于中間層服務器的云端負載均衡。它通過維護一個服務注冊表來實現服務之間的通信1。在 Spring Cloud 中&#xff0c;Eureka 提供了一個高可用的服務注冊與發現機制&a…

職業教育新形態數字教材的建設與應用:重構教育生態的數字化革命

教育部新時代職業學校名師(名匠)名校長培養計劃專題 四川省第四批職業學校名師(名匠)培養計劃專題 在某職業院校的智能制造課堂上&#xff0c;學生佩戴VR設備&#xff0c;通過數字教材中的虛擬工廠完成設備裝配訓練&#xff0c;系統實時生成操作評分與改進建議。這一場景折射出…

基于Python的攜程國際機票價格抓取與分析

一、項目背景與目標 攜程作為中國領先的在線旅行服務平臺&#xff0c;提供了豐富的機票預訂服務。其國際機票價格受多種因素影響&#xff0c;包括季節、節假日、航班時刻等。通過抓取攜程國際機票價格數據&#xff0c;我們可以進行價格趨勢分析、性價比評估以及旅行規劃建議等…

Windows 圖形顯示驅動開發-初始化WDDM 1.2 和 PnP

(WDDM) 1.2 及更高版本顯示微型端口驅動程序的所有 Windows 顯示驅動程序都必須支持以下行為&#xff0c;以響應即插即用 (PnP) 基礎結構啟動和停止請求。 根據驅動程序返回成功或失敗代碼&#xff0c;或者系統硬件是基于基本輸入/輸出系統 (BIOS) 還是統一可擴展固件接口 (UEF…

【1區SCI】Fusion entropy融合熵,多尺度,復合多尺度、時移多尺度、層次 + 故障識別、診斷-matlab代碼

引言 2024年9月&#xff0c;研究者在數學領域國際頂級SCI期刊《Chaos, Solitons & Fractals》&#xff08;JCR 1區&#xff0c;中科院1區 Top&#xff09;上以“Fusion entropy and its spatial post-multiscale version: Methodology and application”為題發表最新科學研…

高并發架構設計之緩存

一、引言 緩存技術作為高并發架構設計的基石之一&#xff0c;通過數據暫存和快速訪問機制&#xff0c;在提升系統性能、降低后端負載方面發揮著不可替代的作用。優秀的緩存設計能夠將系統吞吐量提升數個數量級&#xff0c;將響應時間從秒級降至毫秒級&#xff0c;甚至成為系統…

Unity AI-使用Ollama本地大語言模型運行框架運行本地Deepseek等模型實現聊天對話(一)

一、Ollama介紹 官方網頁&#xff1a;Ollama官方網址 中文文檔參考&#xff1a;Ollama中文文檔 相關教程&#xff1a;Ollama教程 Ollama 是一個開源的工具&#xff0c;旨在簡化大型語言模型&#xff08;LLM&#xff09;在本地計算機上的運行和管理。它允許用戶無需復雜的配置…

Docker Python 鏡像使用指南

1. 使用 Python 鏡像創建容器 docker run -itd -v /data:/data python:latest 作用&#xff1a;創建一個基于 python:latest 鏡像的容器&#xff0c;并后臺運行。 參數說明&#xff1a; -itd&#xff1a;交互式后臺運行&#xff08;-i 交互模式&#xff0c;-t 分配偽終端&…

matlab中Simscape的調用-入門

Simscape 是由 MathWorks 公司開發的一款基于物理建模的仿真工具&#xff0c;它建立在 MATLAB/Simulink 平臺之上&#xff0c;專門用于建模和仿真多領域物理系統。 主要特點 多領域建模&#xff1a;Simscape 提供了豐富的物理元件庫&#xff0c;涵蓋了機械、電氣、液壓、氣動…