通过使用数组实现连续内存,从而提高程序加载速度,
在绘制几十万个三角形的时候让它的帧数也保持在60帧
效果:
代码:
<!doctype html> <html> <head> <meta charset="utf-8"/> <title>Cube</title> <style>body{background:#CCCCCC;margin:0;padding:0;}</style> <script src="js/three.js"></script> <!--<script src="js/three.min.js"></script>--> </head> <body> <script> var width = window.innerWidth*98/100; var height = window.innerHeight*98/100; var scene = new THREE.Scene(); scene.fog = new THREE.Fog(0xcccccc, 2000, 3500); //雾效(0xcccccc:颜色;2000:近平面;3500:远平面)近平面要大于camera的近平面,远平面要小于camera的远平面 var camera = new THREE.PerspectiveCamera(27, width/height, 1,3500); camera.position.z = 2750; // scene.add(new THREE.AmbientLight(0x444444)); //添加环境光 var light1 = new THREE.DirectionalLight(0xffffff, 0.5); light1.position.set(1, 1, 1); scene.add(light1); var light2 = new THREE.DirectionalLight(0xffffff, 1.5); light2.position.set(0, -1, 0); scene.add(light2); var triangles = 160000; var geometry = new THREE.BufferGeometry(); geometry.attributes = { index:{ itemSize:1, array:new Uint16Array(triangles * 3), //根据指定长度创建一个无符号的16位整形数组 numItems:triangles * 3 }, position:{ itemSize:3, array:new Float32Array(triangles * 3 * 3), //一个三角形有三个顶点,一个顶点有x,y,z三个值 numItems:triangles * 3 * 3 }, normal:{ itemSize:3, array:new Float32Array(triangles * 3 * 3), numItems:triangles * 3 * 3 }, color:{ itemSize:3, array:new Float32Array(triangles * 3 * 3), numItems:triangles * 3 * 3 } } var flag = 65535/3; //16位的整形最大能表示65535 var indexes = geometry.attributes.index.array; for(var i=0; i<indexes.length; i++){ indexes[i] = i % (flag*3); } geometry.offsets = []; var offsets = triangles/flag; for(var i=0; i<offsets; i++){ //console.log(i); var offset = { start: i*flag*3, index: i*flag*3, count: Math.min(triangles-(i*flag),flag)*3 }; geometry.offsets.push(offset); } var positions = geometry.attributes.position.array; var normals = geometry.attributes.normal.array; var colors = geometry.attributes.color.array; var A = new THREE.Vector3(); var B = new THREE.Vector3(); var C = new THREE.Vector3(); var CB = new THREE.Vector3(); var AB = new THREE.Vector3(); var color = new THREE.Color(); var l = 600; //立方体的边长 var o = 12; //三角形大小 console.log(positions.length); for(var i=0; i<positions.length; i+=9){ var x = Math.random()*l - l/2; var y = Math.random()*l - l/2; var z = Math.random()*l - l/2; var Ax = x + (Math.random()*o - o/2); var Ay = y + (Math.random()*o - o/2); var Az = z + (Math.random()*o - o/2); var Bx = x + (Math.random()*o - o/2); var By = y + (Math.random()*o - o/2); var Bz = z + (Math.random()*o - o/2); var Cx = x + (Math.random()*o - o/2); var Cy = y + (Math.random()*o - o/2); var Cz = z + (Math.random()*o - o/2); positions[i] = Ax; positions[i+1] = Ay; positions[i+2] = Az; positions[i+3] = Bx; positions[i+4] = By; positions[i+5] = Bz; positions[i+6] = Cx; positions[i+7] = Cy; positions[i+8] = Cz; A.set(Ax, Ay, Az); B.set(Bx, By, Bz); C.set(Cx, Cy, Cz); CB.subVectors(C, B); AB.subVectors(A, B); CB.cross(AB); CB.normalize(); //规范化(将法向量的长度规范为1) var Nx = CB*x; var Ny = CB*y; var Nz = CB*z; normals[i] = Nx; normals[i + 1] = Ny; normals[i + 2] = Nz; normals[i + 3] = Nx; normals[i + 4] = Ny; normals[i + 5] = Nz; normals[i + 6] = Nx; normals[i + 7] = Ny; normals[i + 8] = Nz; //颜色用R,G,B来表示,R/G/B每个分量的取值范围是0~1 var r = x/l + 0.5; var g = y/l + 0.5; var b = z/l + 0.5; //console.log("r: " + r + "\tg: " + g + "\tb: " + b); color.setRGB(r, g, b); color[i] = color.r; color[i + 1] = color.g; color[i + 2] = color.b color[i + 3] = color.r; color[i + 4] = color.g; color[i + 5] = color.b; color[i + 6] = color.r; color[i + 7] = color.g; color[i + 8] = color.b; } //geometry.computeBoundingSphere(); //计算边界椭圆 //var material = new THREE.MeshPhongMaterial({color:0xffffff,side:THREE.DoubleSide,vertexColors:THREE.VertexColors}); var material = new THREE.MeshPhongMaterial( { color: 0xaaaaaa, ambient: 0xaaaaaa, specular: 0xffffff, shininess: 250, side: THREE.DoubleSide, vertexColors: THREE.VertexColors } ); var mesh = new THREE.Mesh(geometry, material); scene.add(mesh); var renderer = new THREE.WebGLRenderer(); //renderer = new THREE.WebGLRenderer( { antialias: false, clearColor: 0x333333, clearAlpha: 1, alpha: false } ); renderer.setSize(width, height); renderer.setClearColor(scene.fog.color, 1); //renderer.gammaInput = true; //renderer.gammaOutput = true; //renderer.physicallyBasedShading = true; document.body.appendChild(renderer.domElement); function render(){ mesh.rotation.x += 0.005; mesh.rotation.y += 0.005; renderer.render(scene, camera); requestAnimationFrame(render); } render(); </script> </body> </html>
附注:
笔者当前使用的three.js版本是r56