1. 程式人生 > >使用three.js的著色器通道一之渲染地球模型

使用three.js的著色器通道一之渲染地球模型

我們都知道,three.js庫裡面內建了很多著色器通道物件供我們渲染場景,本文將對EffectComposer、RenderPass、FilmPass這三個通道進行學習和實現:

1.RenderPass這個通道會在當前場景(scene)和攝像機(camera)的基礎上渲染出一個新場景,新建:

let renderPass = new THREE.RenderPass(scene, camera);

2.FilmPass這個通道通過掃描線和失真模擬電視螢幕效果,實現的效果超有時代感,新建:

/*四個引數分別為粗糙程度,掃描線強度,掃描線數量,是否轉換為灰度圖*/
let effectFilm = new THREE.FilmPass(0.8, 0.325, 256, false);
//將渲染結果輸出到螢幕
effectFilm.renderToScreen = true;

3.EffectComposer可以理解為著色器通道容器,著色器通道按照先後順序新增進來並執行,新建:

 /*渲染效果組合器,每個通道都按照傳入的順序執行*/
 let composer = new THREE.EffectComposer(renderer);
 composer.addPass(renderPass);
 composer.addPass(effectFilm);

本文實現的demo基於three.js_r86(請自行下載),程式碼所用js檔案和圖片都在下載的那個包裡面,請讀者自行引用。

實現效果:




程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>shader_2_earth</title>
    <style>
        body{
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>
<script src="build/three.js"></script>
<script src="js/libs/stats.min.js"></script>
<script src="js/libs/dat.gui.min.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/Detector.js"></script>

<script src="js/postprocessing/EffectComposer.js"></script>
<script src="js/postprocessing/ShaderPass.js"></script>
<script src="js/postprocessing/MaskPass.js"></script>
<script src="js/postprocessing/FilmPass.js"></script>
<script src="js/postprocessing/BloomPass.js"></script>
<script src="js/postprocessing/RenderPass.js"></script>

<script src="js/shaders/CopyShader.js"></script>
<script src="js/shaders/FilmShader.js"></script>

<div id="stats"></div>
<div id="container"></div>
<script>
    //檢測webgl的相容性
   if(!Detector.webgl) Detector.addGetWebGLMessage();

   let scene;
   let camera, renderer, sphere, controls, stats;
   let ambientLight, spotLight;
   let composer;
   let clock;

   main();
   render();

   function main() {
       scene = new THREE.Scene();

       camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);
       camera.position.set(-10, 15, 25);
       camera.lookAt(new THREE.Vector3(0, 0, 0));

       renderer = new THREE.WebGLRenderer({antialias:true});
       renderer.setClearColor(new THREE.Color(0,0,0));
       renderer.setSize(window.innerWidth, window.innerHeight);
       renderer.shadowMapEnabled = true;

       controls = new THREE.OrbitControls(camera);
       controls.autoRotate = false;

       clock = new THREE.Clock();

       ambientLight = new THREE.AmbientLight(0x181818);
       scene.add(ambientLight);

       spotLight = new THREE.SpotLight(0xffffff);
       spotLight.position.set(550, 100, 550);
       spotLight.intensity = 0.6;
       scene.add(spotLight);

       //建立地球
       sphere = createMesh(new THREE.SphereGeometry(10, 60, 60));
       scene.add(sphere);

       document.getElementById("container").appendChild(renderer.domElement);

       /**
        * 新增渲染通道
        */
       //在當前場景和攝像機的基礎上渲染一個新場景
       let renderPass = new THREE.RenderPass(scene, camera);
       //通過掃描線和失真來實現模擬電視螢幕的效果
       let effectFilm = new THREE.FilmPass(0.8, 0.325, 256, false);
       //將渲染結果輸出到螢幕
       effectFilm.renderToScreen = true;

       //渲染效果組合器,每個通道都按照傳入的順序執行
       composer = new THREE.EffectComposer(renderer);
       composer.addPass(renderPass);
       composer.addPass(effectFilm);

       //選單欄元素
       let guiFields = {
           "掃描線數量": 256,
           "灰度影象": false,
           "掃描線強度": 0.3,
           "粗糙程度": 0.8,
           "updateEffectFilm": function () {
               effectFilm.uniforms.grayscale.value = guiFields.灰度影象;
               effectFilm.uniforms.nIntensity.value = guiFields.粗糙程度;
               effectFilm.uniforms.sIntensity.value = guiFields.掃描線強度;
               effectFilm.uniforms.sCount.value = guiFields.掃描線數量;
           }
       };

       //新建一個選單欄
       let gui = new dat.GUI();
       gui.add(guiFields, "掃描線數量", 0, 2048).onChange(guiFields.updateEffectFilm);
       gui.add(guiFields, "掃描線強度", 0, 1).onChange(guiFields.updateEffectFilm);
       gui.add(guiFields, "粗糙程度", 0, 3).onChange(guiFields.updateEffectFilm);
       gui.add(guiFields, "灰度影象").onChange(guiFields.updateEffectFilm);

       stats = initStats();
   }

   //建立一個Mesh
   function createMesh(geometry) {

       //初始化紋理載入器
       let textureLoader = new THREE.TextureLoader();
       //載入圖片
       let uniforms = {
           planetTexture:{value:textureLoader.load("textures/planets/earth_atmos_2048.jpg")},
           specularTexture:{value:textureLoader.load("textures/planets/earth_specular_2048.jpg")},
           normalTexture:{value:textureLoader.load("textures/planets/earth_normal_2048.jpg")}
       };

       //建立phong材料,並進行相應圖片的貼圖
       let planetMaterial = new THREE.MeshPhongMaterial();
       planetMaterial.specularMap = uniforms.specularTexture.value;
       planetMaterial.specular = new THREE.Color(0x4444aa);

       planetMaterial.normalMap = uniforms.normalTexture.value;
       planetMaterial.map = uniforms.planetTexture.value;

       //新建一個mesh
       let mesh = new THREE.SceneUtils.createMultiMaterialObject(geometry, [planetMaterial]);

       return mesh;
   }

   //渲染更新場景

   function render() {
       stats.update();
       let delta = clock.getDelta();
       controls.update(delta);
       sphere.rotation.y += 0.002;
       requestAnimationFrame(render);

       //沒有著色器通道系統預設為WebGLRenderer.render
       //使用著色器通道後,應使用使用composer.render
       composer.render(delta);
   }

   //左上角幀顯示
   function initStats() {
       let stats = new Stats();
       stats.setMode(0);
       stats.domElement.style.position = 'absolute';
       stats.domElement.style.left = '0px';
       stats.domElement.style.top = '0px';
       document.getElementById("stats").appendChild(stats.domElement);

       return stats;
   }
</script>
</body>
</html>

相關推薦

使用three.js著色通道渲染地球模型

我們都知道,three.js庫裡面內建了很多著色器通道物件供我們渲染場景,本文將對EffectComposer、RenderPass、FilmPass這三個通道進行學習和實現:1.RenderPass這個通道會在當前場景(scene)和攝像機(camera)的基礎上渲染出一個

three.js 著色材質glsl內建函式

郭先生髮現在開始學習three.js著色器材質時,我們經常會無從下手,辛苦寫下的著色器,也會因莫名的報錯而手足無措。原因是著色器材質它涉及到另一種語言–GLSL,只有懂了這個語言,我們才能更好的寫出著色器材質,利用好的我們的GPU。這篇說一說glsl內建函式。 1. 和角度相關的函式 下面是一個和角度相關的函

three.js 著色器材質初識著色

說起three.js,著色器材質總是繞不過的話題,今天郭先生就說一說什麼是著色器材質。著色器材質是很需要靈感和數學知識的,可以用簡短的程式碼和繪製出十分豐富的影象,可以說著色器材質是脫離three.js的另一塊知識,因此它十分難講,我們只能在一個一個案例中逐漸掌握著色器語言的使用技巧。 1. 什麼是著色器材質

three.js 著色器材質變數(

上一篇說頂點著色器和片元著色器的皮毛,這篇郭先生說一說著色器變數,通過變數可以設定材質。先看看今天要做的如下圖。線上案例請點選部落格原文。 在這個案例之前,我們先複習一下著色器變數 Uniforms是所有頂點都具有相同的值的變數。 比如燈光,霧,和陰影貼圖就是被儲存在uniforms中的資料。 unifo

three.js 著色器材質變數(二)

上一篇郭先生在例子中用到了著色器變數中的uniform和varying。這篇繼續結合例子將一下attribute變數,在使用過程中也發現由於three.js的版本迭代,之前的一些屬性和引數已經發生了改變,ShaderMaterial也不需要傳遞attributes屬性值,檢視原始碼我們可以看到如果傳遞了att

three.js 著色器材質紋理

今天郭先生說一說如何在three.js著色器中新增紋理,先看看今天要完成的效果,線上案例請點選部落格原文。 這裡我們分別引入三個紋理,分別是地球的表面紋理,對應的海拔灰度圖,和雲朵的紋理。使用表面紋理還是地球的外貌,海拔灰度圖給地球新增凹凸效果,雲朵紋理給地球新增雲朵效果。下面我們說一說程式碼。 1. 繪製

Three.js入門篇()創建一個場景

style api text webgl () mes utf 動畫 fun 上一面講述了向場景中添加物體對象。這一篇準備把每個功能點細細的講述一遍,一方面是為了加深自己的理解。另一方面希望能夠 幫助到有需要的人。 一、在學習WEBGL的時候,你應該先了解要創建一個WebG

JS 裝飾篇就夠

finall 裝飾類 child rec symbol etop 組合 定義 陌生 更多文章,請在Github blog查看 在 ES6 中增加了對類對象的相關定義和操作(比如 class 和 extends ),這就使得我們在多個不同類之間共享或者擴展一些方法或者行為的時

js定時(執行次、重複執行)

1,只執行一次的定時器 <script> //定時器 非同步執行 function hello(){ alert("hello"); } //使用方法名字執行方法 var t1 = window.setTimeout(hello,1000); va

探索three.js中的各種材質共有屬性

探索three.js中的各種材質 之共有屬性 共有屬性又分基礎屬性、融合屬性、高階屬性 1.基礎屬性:這些屬性是最常用到的。 .id:Integer識別符號 用來標識材質,在建立時賦值 .uuid:String UUID 材質例項的UUI

幾何著色) 基本概念

最近想做一些渲染的東西,接觸到了幾何著色器,發現了幾何著色器的強大之處,幾何著色器位於頂點和片元著色器之間,幾何著色器能夠產生0個以上的基礎圖元,它能起到一定的裁剪作用、同時也能產生比頂點著色器輸入更多的基礎圖元。 它可以做的事情非常的酷炫,例如:表面法線的視覺化和實現三維

three.js學習:紋理Texture平面紋理

img can wid 技術分享 chapter sid ats ani pan index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF

Node.js 切近實戰(十) 實時通訊

今天我們主要看一下Socket.IO實時通訊,先看一下介面。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

Node.js實操練習()Node.js+MySQL+RESTful

前言 最近學習了一下node.js相關的內容,在這裡初步做個小總結,說實話關於本篇部落格的相關內容,自己很久之前就已經有過學習,但是你懂的,“好記性不如爛筆筒”,學過的東西不做筆記的話,很容易就會忘記的一乾二淨,往往的結果就是自己又要重頭開始學習,這是一個非常痛苦的過程。沒有辦法,為了

three.js 著色器材質內建變數

這篇郭先生說一下three.js著色器的內建變數,分別是 gl_PointSize:在點渲染模式中,控制方形點區域渲染畫素大小(注意這裡是畫素大小,而不是three.js單位,因此在移動相機是,所看到該點在螢幕中的大小不變) gl_Position:控制頂點選完的位置 gl_FragColor:片元的RGB

Three.js 從記憶體刪除scene中remove的模型資料,釋放記憶體

當需要動態更新顯示不同的模型,從 scene 中 remove 的模型還會在記憶體中,如果多次進行更新操作就會大量佔用記憶體資源,甚至使瀏覽器崩潰,以下程式碼功能為從記憶體中清除模型資料。 程式碼 /** * 清除模型,模型中有 group 和 scene,需要進行判斷 *

UE4旅途渲染模型變黑(2UV坑)及陰影不清問題

       小白歡迎評論,共同探討,共同進步 (PS:二次修改博文)   先說一下UE4最近遇到的坑吧,之前的再慢慢整理。   PS:這個坑填一填,解決方法找到了。         模型什麼的都沒有問題,額,我就想知道這是什麼鬼???         烘焙前  

three.js 第二篇:場景 相機 渲染 物體之間的關系

沒有 向量 res width asi erer 透明 app oge w我用畫畫來形容他們之間的關系 場景就是紙張 相機就是我們的眼睛 物體就是在我們腦海中構思的那個畫面 渲染器就是繪畫這個動作 場景(Scene):   初始化:var scene = new THR

three.js引擎基礎知識—攝像機、場景及渲染

blog new ram end 內部 渲染器 tro element col 一、three.js采用右手坐標系: x軸正方向向右,y軸正方向向上,z軸由屏幕從裏向外,如下圖右: 二、3D編程三要素:場景、渲染器、攝像機 1.場景:創建的物品和模型都需放入場景中 t

three.js中render渲染與html中body顯示之間的聯絡

  方法一: three.js中生成html5中的body。 <body onload="draw();"> </body> function initRender() { renderer = new THREE.WebGLRender