Three.js中使用MarkPass(掩碼)的高級效果組合器

1盏缤、MarkPass的作用:

可以對指定的scene運(yùn)行后期效果。

2辨泳、效果圖:
3虱岂、使用步驟:
3.1、引入文件
import { RenderPass } from '../../node_modules/three/examples/jsm/postprocessing/RenderPass';
import { ShaderPass } from '../../node_modules/three/examples/jsm/postprocessing/ShaderPass';
import { ClearMaskPass, MaskPass } from 'three/examples/jsm/postprocessing/MaskPass';
import { CopyShader } from 'three/examples/jsm/shaders/CopyShader';
3.2菠红、過程概述:

(1)創(chuàng)建一個作為背景圖片的場景第岖。
(2)創(chuàng)建一個場景,里面包含一個看起來像地球的球體试溯。
(3)創(chuàng)建一個場景蔑滓,里面包含一個看起來像火星的球體。
(4)創(chuàng)建EffectComposer對象,用于將這三個場景渲染到一個圖片中键袱。
(5)在渲染為火星的球體上應(yīng)用彩色效果燎窘。
(6)在渲染為地球的球體上應(yīng)用褐色效果。

3.3蹄咖、注意事項:

1褐健、 我們直接使用場景的背景屬性來添加星光背景圖片。還有一種可選方式也可以同于添加背景圖片澜汤,那就是利用THREE.OrthoGraphicCamera(正交攝像機(jī))蚜迅。因為THREE.OrthoGraphicCamera不會根據(jù)物體距離攝像機(jī)的距離來縮放物體,所以可以添加一個正對攝像機(jī)的THREE.PlaneGeometry幾何體银亲,然后在上面添加圖片慢叨。
2、場景渲染時候需要將渲染器改為組合器的渲染器务蝠,并且需要將WebGLRenderer中autoClear設(shè)置為false

4拍谐、完整源代碼:
import { OrthographicCamera, Vector3, Scene, WebGLRenderer, Color, SphereGeometry, MeshPhongMaterial, TextureLoader, Mesh, Clock, AmbientLight, DirectionalLight, PlaneGeometry, MeshBasicMaterial, PerspectiveCamera } from 'three';
import { RenderPass } from '../../node_modules/three/examples/jsm/postprocessing/RenderPass';
import { ShaderPass } from '../../node_modules/three/examples/jsm/postprocessing/ShaderPass';
import { ClearMaskPass, MaskPass } from 'three/examples/jsm/postprocessing/MaskPass';
import { CopyShader } from 'three/examples/jsm/shaders/CopyShader';
import { OrbitControls } from '../../node_modules/three/examples/jsm/controls/OrbitControls';
import { SepiaShader } from '../../node_modules/three/examples/jsm/shaders/SepiaShader';
import { ColorifyShader } from '../../node_modules/three/examples/jsm/shaders/ColorifyShader';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
export class Effect {
    private sceneEarth!: Scene;
    private sceneMars!: Scene;
    private sceneBG!: Scene;
    private cameraBG!: OrthographicCamera;
    private camera!: PerspectiveCamera;
    private webGLRenderer!: WebGLRenderer;
    private earthSphere!: Mesh;
    private marsSphere!: Mesh;
    private earthMaterial!: MeshPhongMaterial;
    private marsMaterial!: MeshPhongMaterial;
    private clock !: Clock;
    private ambEarth!: AmbientLight;
    private ambMars!: AmbientLight;
    private dirEarth!: DirectionalLight;
    private dirMars!: DirectionalLight;
    private bgPass!: RenderPass;
    private earthPass!: RenderPass;
    private marsPass!: RenderPass;
    private composer!:EffectComposer;
    constructor() {
        this.clock = new Clock();
        // 創(chuàng)建三個場景
        this.sceneEarth = new Scene();
        this.sceneMars = new Scene();
        this.sceneBG = new Scene();

        // 相機(jī)設(shè)置
        this.camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
        this.camera.position.x = -10;
        this.camera.position.y = 15;
        this.camera.position.z = 25;
        this.camera.lookAt(new Vector3(0, 0, 0));

        this.cameraBG = new OrthographicCamera(-window.innerWidth, window.innerWidth, window.innerHeight, -window.innerHeight, -10000, 10000);
        this.cameraBG.position.z = 50;

        // 渲染器設(shè)置
        this.webGLRenderer = new WebGLRenderer({ antialias: true });
        this.webGLRenderer.setClearColor(0x000000, 1.0); //設(shè)置背景顏色
        this.webGLRenderer.setSize(window.innerWidth, window.innerHeight);
        this.webGLRenderer.setPixelRatio(window.devicePixelRatio);
        this.webGLRenderer.shadowMap.enabled = true;
        document.body.appendChild(this.webGLRenderer.domElement);

        // 地球
        this.earthSphere = this.createEarthMesh(new SphereGeometry(10, 40, 40));
        this.earthSphere.position.x = -10;
        this.sceneEarth.add(this.earthSphere);
        // 火星
        this.marsSphere = this.createMarshMesh(new SphereGeometry(5, 40, 40));
        this.earthSphere.position.x = 20;
        this.sceneMars.add(this.marsSphere);

        // 環(huán)境光
        this.ambEarth = new AmbientLight(0x181818);
        this.sceneEarth.add(this.ambEarth);
        this.ambMars = new AmbientLight(0x181818);
        this.sceneMars.add(this.ambMars);

        // 方向光
        this.dirEarth = new DirectionalLight(0xffffff, 0.6);
        this.dirEarth.position.set(550, 100, 550);
        this.sceneEarth.add(this.dirEarth);

        this.dirMars = new DirectionalLight(0xffffff, 0.6);
        this.dirMars.position.set(550, 100, 550);
        this.sceneMars.add(this.dirMars);

        // 背景平面
        const bgPlane = new PlaneGeometry(1, 1);
        const bgPlaneMaterial = new MeshBasicMaterial({
            map: new TextureLoader().load('../assets/starry-deep-outer-space-galaxy.jpg'),
            depthTest: false // 不啟動深度測試即設(shè)置成false就擁有類似透視的效果

        });
        const bgMesh = new Mesh(bgPlane, bgPlaneMaterial);
        bgMesh.position.z = -100;
        bgMesh.scale.set(window.innerWidth * 2, window.innerHeight * 2, 1);
        this.sceneBG.add(bgMesh);

        // 后期處理
        //RenderPass根據(jù)scene和camera渲染出一個場景,和普通的webGLRenderer一樣
        this.bgPass = new RenderPass(this.sceneBG, this.cameraBG);
        // this.bgPass.clear = false;
        this.earthPass = new RenderPass(this.sceneEarth, this.camera);
        this.earthPass.clear = false;//if set to true, the pass clears its buffer before rendering
        this.marsPass = new RenderPass(this.sceneMars, this.camera);
        this.marsPass.clear = false;
        
        const effectCopy = new ShaderPass(CopyShader);
        effectCopy.renderToScreen = true;

        const clearMark = new ClearMaskPass();
        // earth mark
        const earthMark = new MaskPass(this.sceneEarth, this.camera);
        // earthMark.inverse = true;

        //mars mark
        //sceneMask和clearMask可以理解成ps圖層的透明部分馏段。不添加mask轩拨,效果就應(yīng)用到整個場景,添加了就只應(yīng)用到場景中的物體院喜,用完記得需要清除亡蓉。
        //掩碼的作用:可以對指定的scene運(yùn)行后期效果
        const marsMark = new MaskPass(this.sceneMars, this.camera);

        const effectSepia = new ShaderPass(SepiaShader);//烏賊墨效果
        effectSepia.uniforms['amount'].value = 0.8;

        const effectColorify = new ShaderPass(ColorifyShader);//整個顏色覆蓋屏幕
        effectColorify.uniforms['color'].value.setRGB(0.5, 0.5, 1);

        // 組合通道
        this.composer = new EffectComposer(this.webGLRenderer);
        //需要注意的是需要將使用掩碼前,要將composer.renderTarget.stencilBuffer設(shè)置為true,用于限制渲染區(qū)域喷舀。
        //另外砍濒,使用完掩碼后,需要使用ClearMaskPass()去掉掩碼區(qū)域
        this.composer.renderTarget1.stencilBuffer = true;
        this.composer.renderTarget2.stencilBuffer = true;

        this.composer.addPass(this.bgPass);
        this.composer.addPass(this.earthPass);
        this.composer.addPass(this.marsPass);
        //掩碼的作用:可以對指定的scene運(yùn)行后期效果
        this.composer.addPass(marsMark);//添加掩碼硫麻,后續(xù)通道只會影響掩碼區(qū)域爸邢,取消掩碼需要加入THREE.ClearMaskPass通道
        this.composer.addPass(effectColorify);
        this.composer.addPass(clearMark);
        this.composer.addPass(earthMark);
        this.composer.addPass(effectSepia);
        this.composer.addPass(clearMark);
        this.composer.addPass(effectCopy);


        const orbitControls= new OrbitControls(this.camera, this.webGLRenderer.domElement);
        orbitControls.autoRotate =false;

        window.addEventListener('resize', ()=>this.onWindowResize());
        this.render();
    }
    private onWindowResize() {
        this.webGLRenderer.setSize(window.innerWidth, window.innerHeight);
        this.camera.aspect = window.innerWidth/window.innerHeight;
        this.camera.updateProjectionMatrix();

        this.cameraBG.left = -window.innerWidth;
        this.cameraBG.right = window.innerWidth;
        this.cameraBG.top = window.innerHeight;
        this.cameraBG.bottom = -window.innerHeight;
        this.cameraBG.updateProjectionMatrix();
    }
    private render() {
        this.webGLRenderer.autoClear = false;//一定要設(shè)置
        window.requestAnimationFrame(() => this.render());
        this.earthSphere.rotation.y+=0.02;
        this.marsSphere.rotation.y+=0.02;
        this.composer.render(this.clock.getDelta());//參數(shù)設(shè)置成兩幀間隔時間
    }
    private createMarshMesh(geom) {

        this.marsMaterial = new MeshPhongMaterial({
            map: new TextureLoader().load('../assets/Mars_2k-050104.png'),
            normalMap: new TextureLoader().load('../assets/Mars-normalmap_2k.png')
        });
        const mesh = new Mesh(geom, this.marsMaterial);
        return mesh;
    }

    private createEarthMesh(geom) {
        this.earthMaterial = new MeshPhongMaterial({
            map: new TextureLoader().load('../assets/Earth.png'),
            specularMap: new TextureLoader().load('../assets/EarthSpec.png'),
            normalMap: new TextureLoader().load('../assets/EarthNormal.png'),
            specular: new Color(0x4444aa)
        });
        const mesh = new Mesh(geom, this.earthMaterial);
        return mesh;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市拿愧,隨后出現(xiàn)的幾起案子杠河,更是在濱河造成了極大的恐慌,老刑警劉巖浇辜,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件券敌,死亡現(xiàn)場離奇詭異,居然都是意外死亡柳洋,警方通過查閱死者的電腦和手機(jī)待诅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熊镣,“玉大人咱士,你說我怎么就攤上這事立由。” “怎么了序厉?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長毕箍。 經(jīng)常有香客問我弛房,道長而柑,這世上最難降的妖魔是什么文捶? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任粹排,我火速辦了婚禮,結(jié)果婚禮上涩澡,老公的妹妹穿的比我還像新娘顽耳。我一直安慰自己,他們只是感情好射富,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布粥帚。 她就那樣靜靜地躺著胰耗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪芒涡。 梳的紋絲不亂的頭發(fā)上柴灯,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天费尽,我揣著相機(jī)與錄音,去河邊找鬼依啰。 笑死,一個胖子當(dāng)著我的面吹牛叹誉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播长豁,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼忙灼,長吁一口氣:“原來是場噩夢啊……” “哼钝侠!你這毒婦竟也來了酸舍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤啃勉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后叮阅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泣特,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年勒叠,在試婚紗的時候發(fā)現(xiàn)自己被綠了竞阐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡颗搂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出丢氢,到底是詐尸還是另有隱情先改,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布仇奶,位于F島的核電站貌嫡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏岛抄。R本人自食惡果不足惜狈茉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蹭秋。 院中可真熱鬧扰付,春花似錦仁讨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锐墙。三九已至,卻和暖如春溪北,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背之拨。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蚀乔,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓派撕,卻偏偏與公主長得像奶赔,于是被迫代替她去往敵國和親音念。 傳聞我的和親對象是個殘疾皇子际跪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Threejs 為什么喉钢? webGL太難用,太復(fù)雜出牧! 但是現(xiàn)代瀏覽器都支持 WebGL 這樣我們就不必使用 Fla...
    強(qiáng)某某閱讀 6,050評論 1 21
  • 準(zhǔn)備工作: 1舔痕、three.js https://threejs.org/build/three.js 2豹缀、搭建項...
    月_關(guān)閱讀 5,572評論 0 1
  • 1慨代、簡介 WebGL 是在瀏覽器中實現(xiàn)三維效果的一套規(guī)范,而 Three.js 可以看成是瀏覽器對 WebGL 規(guī)...
    風(fēng)之化身呀閱讀 3,502評論 0 4
  • 本文主要是講解 Three.js 的相關(guān)概念氮惯,幫助大家對 Three.js 以及相關(guān)知識形成比較完整的理解。今年來...
    Simon王小白閱讀 8,450評論 2 9
  • 久違的晴天妇汗,家長會说莫。 家長大會開好到教室時,離放學(xué)已經(jīng)沒多少時間了储狭。班主任說已經(jīng)安排了三個家長分享經(jīng)驗。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,523評論 16 22