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;
}
}