如果您想訂閱本博客內(nèi)容,每天自動(dòng)發(fā)到您的郵箱中, 請(qǐng)點(diǎn)這里
我們都知道,three.js庫(kù)里面內(nèi)置了很多著色器通道對(duì)象供我們渲染場(chǎng)景,本文將對(duì)EffectComposer、RenderPass、FilmPass這三個(gè)通道進(jìn)行學(xué)習(xí)和實(shí)現(xiàn):
1.RenderPass這個(gè)通道會(huì)在當(dāng)前場(chǎng)景(scene)和攝像機(jī)(camera)的基礎(chǔ)上渲染出一個(gè)新場(chǎng)景,新建:
-
let renderPass = new THREE.RenderPass(scene, camera);
2.FilmPass這個(gè)通道通過(guò)掃描線和失真模擬電視屏幕效果,實(shí)現(xiàn)的效果超有時(shí)代感,新建:
-
-
let effectFilm = new THREE.FilmPass(0.8, 0.325, 256, false);
-
-
effectFilm.renderToScreen = true;
3.EffectComposer可以理解為著色器通道容器,著色器通道按照先后順序添加進(jìn)來(lái)并執(zhí)行,新建:
-
-
let composer = new THREE.EffectComposer(renderer);
-
composer.addPass(renderPass);
-
composer.addPass(effectFilm);
本文實(shí)現(xiàn)的demo基于three.js_r86(請(qǐng)自行下載),代碼所用js文件和圖片都在下載的那個(gè)包里面,請(qǐng)讀者自行引用。
實(shí)現(xiàn)效果:
代碼:
-
<!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>
-
//檢測(cè)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);
-
-
//創(chuàng)建地球
-
sphere = createMesh(new THREE.SphereGeometry(10, 60, 60));
-
scene.add(sphere);
-
-
document.getElementById("container").appendChild(renderer.domElement);
-
-
/**
-
* 添加渲染通道
-
*/
-
//在當(dāng)前場(chǎng)景和攝像機(jī)的基礎(chǔ)上渲染一個(gè)新場(chǎng)景
-
let renderPass = new THREE.RenderPass(scene, camera);
-
//通過(guò)掃描線和失真來(lái)實(shí)現(xiàn)模擬電視屏幕的效果
-
let effectFilm = new THREE.FilmPass(0.8, 0.325, 256, false);
-
//將渲染結(jié)果輸出到屏幕
-
effectFilm.renderToScreen = true;
-
-
//渲染效果組合器,每個(gè)通道都按照傳入的順序執(zhí)行
-
composer = new THREE.EffectComposer(renderer);
-
composer.addPass(renderPass);
-
composer.addPass(effectFilm);
-
-
//菜單欄元素
-
let guiFields = {
-
"掃描線數(shù)量": 256,
-
"灰度圖像": false,
-
"掃描線強(qiáng)度": 0.3,
-
"粗糙程度": 0.8,
-
"updateEffectFilm": function () {
-
effectFilm.uniforms.grayscale.value = guiFields.灰度圖像;
-
effectFilm.uniforms.nIntensity.value = guiFields.粗糙程度;
-
effectFilm.uniforms.sIntensity.value = guiFields.掃描線強(qiáng)度;
-
effectFilm.uniforms.sCount.value = guiFields.掃描線數(shù)量;
-
}
-
};
-
-
//新建一個(gè)菜單欄
-
let gui = new dat.GUI();
-
gui.add(guiFields, "掃描線數(shù)量", 0, 2048).onChange(guiFields.updateEffectFilm);
-
gui.add(guiFields, "掃描線強(qiáng)度", 0, 1).onChange(guiFields.updateEffectFilm);
-
gui.add(guiFields, "粗糙程度", 0, 3).onChange(guiFields.updateEffectFilm);
-
gui.add(guiFields, "灰度圖像").onChange(guiFields.updateEffectFilm);
-
-
stats = initStats();
-
}
-
-
//創(chuàng)建一個(gè)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")}
-
};
-
-
//創(chuàng)建phong材料,并進(jìn)行相應(yīng)圖片的貼圖
-
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;
-
-
//新建一個(gè)mesh
-
let mesh = new THREE.SceneUtils.createMultiMaterialObject(geometry, [planetMaterial]);
-
-
return mesh;
-
}
-
-
//渲染更新場(chǎng)景
-
-
function render() {
-
stats.update();
-
let delta = clock.getDelta();
-
controls.update(delta);
-
sphere.rotation.y += 0.002;
-
requestAnimationFrame(render);
-
-
//沒(méi)有著色器通道系統(tǒng)默認(rèn)為WebGLRenderer.render
-
//使用著色器通道后,應(yīng)使用使用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>
藍(lán)藍(lán)設(shè)計(jì)( tweetduck.com )是一家專注而深入的界面設(shè)計(jì)公司,為期望卓越的國(guó)內(nèi)外企業(yè)提供卓越的UI界面設(shè)計(jì)、BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、 ipad界面設(shè)計(jì) 、 包裝設(shè)計(jì) 、 圖標(biāo)定制 、 用戶體驗(yàn) 、交互設(shè)計(jì)、 網(wǎng)站建設(shè) 、平面設(shè)計(jì)服務(wù)