成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

如何用threejs實現實時多邊形折射

瀏覽:173日期:2024-03-27 13:53:48
前言

在本教程中,您將學習如何使用Three.js在三個步驟中使對象看起來像玻璃。

渲染3D對象時,無論使用某種3D軟件還是使用WebGL進行實時顯示,始終都必須為其分配材料以使其可見并具有所需的外觀。

可以使用Three.js之類的庫中的現成程序來模仿許多類型的材料,但是在本教程中,我將向您展示如何使用三個對象(三個步驟)使對象看起來像玻璃一樣。

步驟1:設定和正面折射

在本演示中,我將使用菱形幾何圖形,但是您可以跟隨一個簡單的盒子或任何其他幾何圖形。

讓我們建立我們的項目。我們需要一個渲染器,一個場景,一個透視相機和我們的幾何圖形。為了渲染我們的幾何圖形,我們需要為其分配材質。創建此材料將是本教程的主要重點。因此,繼續創建具有基本頂點和片段著色器的新ShaderMaterial。

與您期望的相反,我們的材料將不是透明的,實際上,我們將對鉆石后面的任何東西進行采樣和變形。為此,我們需要將場景(沒有菱形)渲染為紋理。我只是使用正交攝影機渲染全屏平面,但這也可能是充滿其他對象的場景。在Three.js中從菱形分割背景幾何圖形的最簡單方法是使用“圖層”。

this.orthoCamera = new THREE.OrthographicCamera( width / - 2,width / 2, height / 2, height / - 2, 1, 1000 );// assign the camera to layer 1 (layer 0 is default)this.orthoCamera.layers.set(1);const tex = await loadTexture(’texture.jpg’);this.quad = new THREE.Mesh(new THREE.PlaneBufferGeometry(), new THREE.MeshBasicMaterial({map: tex}));this.quad.scale.set(width, height, 1);// also move the plane to layer 1this.quad.layers.set(1);this.scene.add(this.quad);

我們的渲染循環如下所示:

this.envFBO = new THREE.WebGLRenderTarget(width, height);this.renderer.autoClear = false;render() { requestAnimationFrame( this.render ); this.renderer.clear(); // render background to fbo this.renderer.setRenderTarget(this.envFbo); this.renderer.render( this.scene, this.orthoCamera ); // render background to screen this.renderer.setRenderTarget(null); this.renderer.render( this.scene, this.orthoCamera ); this.renderer.clearDepth(); // render geometry to screen this.renderer.render( this.scene, this.camera );};

好吧,現在該花一點點理論了。透明材料(如玻璃)可以彎曲,因此可見。那是因為光在玻璃中的傳播要比空氣中的傳播慢,因此當光波以一定角度撞擊玻璃物體時,這種速度變化會導致光波改變方向。波浪方向的這種變化描述了折射現象。

如何用threejs實現實時多邊形折射

為了在代碼中復制這一點,我們將需要知道我們的眼睛向量與世界空間中鉆石表面(法線)向量之間的角度。讓我們更新頂點著色器以計算這些向量。

varying vec3 eyeVector;varying vec3 worldNormal;void main() { vec4 worldPosition = modelMatrix * vec4( position, 1.0); eyeVector = normalize(worldPos.xyz - cameraPosition); worldNormal = normalize( modelViewMatrix * vec4(normal, 0.0)).xyz; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}

在片段著色器中,我們現在可以將eyeVector和worldNormal用作glsl內置折射函數的前兩個參數。第三個參數是折射率的比率,即我們的快速介質(空氣)的折射率(IOR)除以我們的慢速介質(玻璃)的IOR。在這種情況下,該值為1.0 / 1.5,但是您可以調整該值以獲得所需的結果。例如,水的IOR為1.33,鉆石的IOR為2.42。

uniform sampler2D envMap;uniform vec2 resolution;varying vec3 worldNormal;varying vec3 viewDirection;void main() { // get screen coordinates vec2 uv = gl_FragCoord.xy / resolution; vec3 normal = worldNormal; // calculate refraction and add to the screen coordinates vec3 refracted = refract(eyeVector, normal, 1.0/ior); uv += refracted.xy;// sample the background texture vec4 tex = texture2D(envMap, uv); vec4 output = tex; gl_FragColor = vec4(output.rgb, 1.0);}

如何用threejs實現實時多邊形折射

真好!我們成功編寫了折射著色器。但是我們的鉆石幾乎看不見……部分原因是我們只處理了玻璃的一種視覺特性。并非所有的光都會穿過要折射的材料,實際上,一部分光會被反射。讓我們看看如何實現它!

步驟2:反射和菲涅耳方程

為了簡單起見,在本教程中,我們將不計算適當的反射,而僅將白色用作反射光。現在,我們怎么知道什么時候該反思,什么時候該折射?理論上,這取決于材料的折射率,當入射矢量和表面法線之間的角度大于臨界角時,光波將被反射。

如何用threejs實現實時多邊形折射

在片段著色器中,我們將使用菲涅耳方程來計算反射光線與折射光線之間的比率。不幸的是,glsl也沒有內置此方程式,但是您可以從這里復制它:

float Fresnel(vec3 eyeVector, vec3 worldNormal) { return pow( 1.0 + dot( eyeVector, worldNormal), 3.0 );}

現在,我們可以根據剛計算出的菲涅耳比,簡單地將折射紋理顏色與白色反射顏色混合。

uniform sampler2D envMap;uniform vec2 resolution;varying vec3 worldNormal;varying vec3 viewDirection;float Fresnel(vec3 eyeVector, vec3 worldNormal) { return pow( 1.0 + dot( eyeVector, worldNormal), 3.0 );}void main() { // get screen coordinates vec2 uv = gl_FragCoord.xy / resolution; vec3 normal = worldNormal; // calculate refraction and add to the screen coordinates vec3 refracted = refract(eyeVector, normal, 1.0/ior); uv += refracted.xy; // sample the background texture vec4 tex = texture2D(envMap, uv); vec4 output = tex; // calculate the Fresnel ratio float f = Fresnel(eyeVector, normal); // mix the refraction color and reflection color output.rgb = mix(output.rgb, vec3(1.0), f); gl_FragColor = vec4(output.rgb, 1.0);}

如何用threejs實現實時多邊形折射

看起來已經好多了,但是還有一些不足之處……嗯,我們看不到透明對象的另一面。讓我們解決這個問題!

步驟3:多邊折射

到目前為止,我們已經了解了有關反射和折射的知識,我們可以理解,光在離開對象之前可以在對象內部來回反彈幾次。

為了獲得物理上正確的結果,我們將必須跟蹤每條光線,但是不幸的是,這種計算量太大,無法實時渲染。因此,我將向您展示一個簡單的近似值,至少可以直觀地看到我們鉆石的背面。

在一個片段著色器中,我們需要幾何圖形的正面和背面的世界法線。由于我們不能同時渲染兩側,因此需要首先將背面法線渲染為紋理。

如何用threejs實現實時多邊形折射

讓我們像在步驟1中一樣制作一個新的ShaderMaterial,但是這次我們將世界法線渲染為gl_FragColor。

varying vec3 worldNormal;void main() { gl_FragColor = vec4(worldNormal, 1.0);}

接下來,我們將更新渲染循環以包括背面通道。

this.backfaceFbo = new THREE.WebGLRenderTarget(width, height);...render() { requestAnimationFrame( this.render ); this.renderer.clear(); // render background to fbo this.renderer.setRenderTarget(this.envFbo); this.renderer.render( this.scene, this.orthoCamera ); // render diamond back faces to fbo this.mesh.material = this.backfaceMaterial; this.renderer.setRenderTarget(this.backfaceFbo); this.renderer.clearDepth(); this.renderer.render( this.scene, this.camera ); // render background to screen this.renderer.setRenderTarget(null); this.renderer.render( this.scene, this.orthoCamera ); this.renderer.clearDepth(); // render diamond with refraction material to screen this.mesh.material = this.refractionMaterial; this.renderer.render( this.scene, this.camera );};

現在,我們在折射材料中采樣背面法線紋理。

vec3 backfaceNormal = texture2D(backfaceMap, uv).rgb;

最后,我們結合了正面和背面法線。

float a = 0.33;vec3 normal = worldNormal * (1.0 - a) - backfaceNormal * a;

在此等式中,a只是一個標量值,指示應應用背面法線的數量。

如何用threejs實現實時多邊形折射

我們做到了!我們可以看到鉆石的所有側面,僅是因為我們對鉆石的材質進行了折射和反射。

局限性

正如我已經解釋的那樣,用這種方法實時渲染物理上正確的透明材料是不可能的。當在彼此前面渲染多個玻璃對象時會發生另一個問題。由于我們僅對環境采樣一次,因此無法看透一連串的對象。最后,我在這里演示的屏幕空間折射在畫布的邊緣附近效果不佳,因為光線可能會折射到其邊界之外的值,并且在將背景場景渲染到渲染目標時我們沒有捕獲到該數據。

當然,有多種方法可以克服這些限制,但是對于您在WebGL中進行實時渲染,它們可能并不是全部很好的解決方案。

以上就是如何用threejs實現實時多邊形折射的詳細內容,更多關于JS庫的資料請關注好吧啦網其它相關文章!

標簽: JavaScript
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
在线一区二区视频| 中文字幕一区二区三区在线不卡| 亚洲欧美日韩国产| 精品国产精品网麻豆系列| 亚洲一区二区三区视频在线播放| 国产99久久久国产精品潘金网站| 国产一区二区黄色| 久久午夜羞羞影院免费观看| 亚洲成人资源在线| 91啪九色porn原创视频在线观看| 亚洲免费影院| 欧美国产欧美综合| 蜜臀av性久久久久av蜜臀妖精| 欧美激情1区2区3区| 欧美色图一区二区三区| 日韩午夜中文字幕| 精品写真视频在线观看| 日韩av一区二区在线影视| 国产精品456| 国产日韩欧美亚洲| 亚洲一区二区三区精品动漫 | 中文字幕中文字幕一区| 亚洲成av人片在线| eeuss鲁片一区二区三区在线看| 国产综合欧美| 精品美女一区二区| 亚洲第一电影网| 亚洲欧美综合另类在线卡通| 亚洲第一狼人社区| 欧美另类专区| 精品视频1区2区3区| 夜夜嗨av一区二区三区四季av| 成a人片亚洲日本久久| 欧美日韩精品福利| 偷拍亚洲欧洲综合| 野花国产精品入口| 中文字幕日韩一区| 91农村精品一区二区在线| 欧美日韩国产一二三| 亚洲蜜臀av乱码久久精品| 欧美欧美全黄| 久久综合色之久久综合| 国产成人夜色高潮福利影视| 色婷婷av久久久久久久| 亚洲精品免费播放| 欧美精品在线视频| 久久精品国产99国产| 日韩中文字幕区一区有砖一区| 欧美精品尤物在线| 午夜私人影院久久久久| 久久综合九色综合欧美亚洲| 日本福利一区二区| 欧美精品偷拍| 国产夜色精品一区二区av| 美国精品在线观看| 欧美人牲a欧美精品| 丁香婷婷深情五月亚洲| 激情视频一区二区| 成人性生交大片免费看在线播放| 欧美性一级生活| 精品一区二区三区在线观看国产| 色婷婷一区二区三区四区| 日韩精品一二三四| 久久三级福利| 日韩电影在线观看电影| 久久亚洲高清| 五月天一区二区| 国产xxx精品视频大全| 在线观看日韩精品| 激情综合网最新| 久久久久久久久岛国免费| 91久久国产综合久久蜜月精品 | 欧美日韩三级视频| 亚洲日本一区二区| 夜夜精品视频| 亚洲v中文字幕| 色婷婷av一区二区三区大白胸| 欧美一区二区三区视频在线| 在线观看成人av电影| 久久精品视频在线看| 国产传媒日韩欧美成人| 日本免费新一区视频| 午夜精品久久久久久| 亚洲欧美偷拍另类a∨色屁股| 亚洲精品欧美在线| 欧美专区18| 欧美在线高清| 美女精品一区二区| 久久国产精品久久久久久电车| 国产乱子轮精品视频| 亚洲精品偷拍| 国产精品国产精品国产专区不片 | 欧美日韩成人一区二区三区| 亚洲成人综合视频| 精品欧美乱码久久久久久| 精品国产三级a在线观看| 国产高清在线精品| 精品欧美乱码久久久久久1区2区| 欧美一区二区视频在线| 日韩美女视频一区| 久久久久一区二区三区| 久久成人免费网站| 国产自产高清不卡| 国产精品久线观看视频| 久久中文欧美| 色综合欧美在线| 黄色亚洲免费| 亚洲福利视频一区| 欧美日韩精品系列| 成人国产在线观看| 国产精品三级av在线播放| 亚洲国产高清视频| 图片区日韩欧美亚洲| 777精品伊人久久久久大香线蕉| 久久久蜜桃一区二区人| 94-欧美-setu| 亚洲精品视频免费看| 在线观看av不卡| 91久久久免费一区二区| 26uuu精品一区二区三区四区在线 26uuu精品一区二区在线观看 | 日本中文字幕一区二区视频 | 欧美国产精品一区| 亚洲高清久久| 久久不见久久见免费视频7| 欧美精品一区二区精品网| 日韩午夜在线| 狠狠色丁香久久婷婷综合丁香| 精品理论电影在线| 欧美一级专区| 国产成人啪午夜精品网站男同| 国产精品素人一区二区| 榴莲视频成人在线观看| 99免费精品视频| 婷婷成人激情在线网| 精品国产一区久久| 国产精品一区二区a| 国产美女在线精品| 中文字幕在线观看不卡| 欧美色视频在线| 亚洲成色最大综合在线| 国产精品久久久久天堂| 一区二区三区影院| 欧美tickling网站挠脚心| 欧美日韩综合网| 一本高清dvd不卡在线观看| 日韩一级视频免费观看在线| 亚洲综合色婷婷| 99热这里都是精品| 日韩一区二区三区视频在线观看| 精品免费一区二区三区| 国产婷婷一区二区| 五月天激情综合| 国产精品99久| 欧美福利专区| 成人免费高清在线观看| 日韩五码在线| 国产成人亚洲精品狼色在线| 亚洲国产精品人人做人人爽| 日韩欧美中文一区| 久久亚洲影院| 成人黄色一级视频| 蜜臀av国产精品久久久久| 亚洲色图自拍偷拍美腿丝袜制服诱惑麻豆| 欧美性猛交xxxx乱大交退制版| 亚洲视频中文| 国产成人啪免费观看软件| 天堂久久一区二区三区| 国产精品家庭影院| 欧美一区二区三区免费大片| 色综合久久99| 国产精品区免费视频| 色综合久久综合网97色综合| 精品一区二区久久| 亚洲国产精品一区二区久久| 国产精品婷婷午夜在线观看| 91麻豆精品国产| 91久久精品日日躁夜夜躁欧美| 99国产精品| 欧美日韩a区| 国精产品一区一区三区mba桃花| 99香蕉国产精品偷在线观看| 精品久久久久av影院| 亚洲免费观看视频| 国产一区二区成人久久免费影院| 欧美群妇大交群中文字幕| 国产成人在线视频网址| 久久久久久久久久美女| 亚洲国产精品第一区二区三区| 成人免费一区二区三区视频 | 精品99视频| 无码av中文一区二区三区桃花岛| 伊人一区二区三区| 激情五月婷婷综合网| 久久99国产精品久久99果冻传媒| 国产欧美日韩综合精品一区二区| 久久美女性网| 999亚洲国产精| 99热99精品| 欧美国产乱子伦 | 日本一区二区高清|