three.js用THREE.CubeCamera和環境貼圖建立反光效果
阿新 • • 發佈:2018-12-09
在在文章:three.js貼圖之CubeTextureLoader全景貼圖中已經講過全景貼圖的應用,本文將進一步擴充套件全景貼圖的功能,結合THREE.CubeCamera功能,創建出一個具有反光效果的場景,首先來看看看看THREE.CubeCamera的用法:
let cubeCamera = new THREE.CubeCamera(0.1, 10000, 128);//例項化一個cubeCamera scene.add(cubeCamera);//將其新增到場景中 let dynamicEnvMaterial = new THREE.MeshBasicMaterial({ envMap: cubeCamera.renderTarget, side: THREE.DoubleSide }); //新建一個動態環境材料,envMap為環境貼圖,設定為cubeCamera的渲染目標 cubeCamera.updateCubeMap(renderer, scene);//更新渲染立方體貼圖
THREE.CubeCamera(near, far, cubeResolution)總共接收三個引數,前兩個引數表示最近距離和最遠距離,和THREE.PerspectiveCamera中的near和far一個道理,最後一個引數按字面理解為立方體解析度,通俗的理解為物體對場景反光的清晰度,即越大越清晰,可以qumo取128、256、512、1080等;本文實現一個球將周圍場景反光,le類似於於鏡子,你可以在球的表面上看到周圍場景的映象。demo實現效果如下圖:
demo程式碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>場景反光</title> <script type="text/javascript" src="build/three.js"></script> <script type="text/javascript" src="js/controls/OrbitControls.js"></script> <script type="text/javascript" src="js/libs/stats.js"></script> <style> body { margin: 0px; overflow: hidden; } </style> </head> <body> <script type="text/javascript" > let container1 = document.createElement('div'); document.body.appendChild(container1); let container2 = document.createElement('div'); document.body.appendChild(container2); let scene = undefined; let renderer = undefined; let camera = undefined; let cubeCamera = undefined; let pointLight = ambientLight = undefined; let sphere = undefined, cube = undefined; let controls = undefined; let stats = undefined; main(); render(); function main() { initScene(); initRenderer(container1); initCamera(); initLight(); initControls(); createScene(); initStats(container2); window.addEventListener('resize', onWindowResize, false); } function initScene() { scene = new THREE.Scene(); } function initCamera() { camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(0, 5, 35); camera.lookAt(scene.position); } function initRenderer(container1) { renderer = new THREE.WebGLRenderer({antialias:true}); renderer.setClearColor(0xffffff, 1.0); renderer.setSize(window.innerWidth, window.innerHeight); container1.appendChild(renderer.domElement); } function initLight() { ambientLight = new THREE.AmbientLight(0xffffff, 0.35); scene.add(ambientLight); pointLight = new THREE.PointLight(0xffffff); pointLight.position.set(10, 10, 10); scene.add(pointLight); } function initControls() { controls = new THREE.OrbitControls(camera, renderer.domElement); controls.autoRotate = false; controls.enableKeys = true; } function textureBox() { let geometry = new THREE.BoxGeometry(3, 3, 3, 30, 30, 30); let map = new THREE.TextureLoader().load('textures/brick_bump.jpg'); let material = new THREE.MeshPhongMaterial({map:map, side: THREE.DoubleSide}); let box = new THREE.Mesh(geometry, material); scene.add(box); } function createScene() { //建立一個立方體貼圖 let textureCube = new THREE.CubeTextureLoader().setPath("textures/cube/Park3Med/") .load([ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ]); textureCube.format = THREE.RGBFormat; textureCube.mapping = THREE.CubeReflectionMapping; //建立使用者shader let shader = THREE.ShaderLib["cube"]; shader.uniforms["tCube"].value = textureCube; let material = new THREE.ShaderMaterial({ fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: shader.uniforms, side: THREE.DoubleSide }); let skyBox = new THREE.Mesh(new THREE.BoxGeometry(800, 800, 800), material); scene.add(skyBox); cubeCamera = new THREE.CubeCamera(0.1, 10000, 1080); scene.add(cubeCamera); let sphereGeo = new THREE.SphereGeometry(10, 30, 30); let cubeGeo = new THREE.BoxGeometry(10, 10, 10, 10, 10, 10); let dynamicEnvMaterial = new THREE.MeshBasicMaterial({ envMap: cubeCamera.renderTarget, side: THREE.DoubleSide }); let envMaterial = new THREE.MeshBasicMaterial({ envMap: textureCube, side:THREE.DoubleSide }); sphere = new THREE.Mesh(sphereGeo, dynamicEnvMaterial); scene.add(sphere); cube = new THREE.Mesh(cubeGeo, envMaterial); cube.position.set(30, 0, 0); scene.add(cube); } function initStats(container2) { stats = new Stats(); stats.setMode(0); stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; container2.appendChild(stats.domElement); } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight); } function render() { controls.update(); stats.update(); // sphere.visible = false; cubeCamera.updateCubeMap(renderer, scene); // sphere.visible = true; cube.rotation.x += 0.01; cube.rotation.y += 0.01; requestAnimationFrame(render); renderer.render(scene, camera); } </script> </body> </html>