首页 > 编程学习 > threejs 知识点

threejs 知识点

发布时间:2022/11/24 23:17:39

开始

  • 中文文档 threejs
  • 通过分析AST自动重构three.js的老旧代码

备份

  • 修改材质
<li  onclick="MChangeTexture('models/kitchen/Texture/t3');">紫罗兰</li>
<li  onclick="MChangeTexture('models/kitchen/123.fbm');">灰色</li>
<li  onclick="MChangeTexture('models/kitchen/Texture/t1');">蓝色</li>
<li  onclick="MChangeTexture('models/kitchen/Texture/t2');">橙色</li>

基础

场景 scene

// 创建场景
scene = new THREE.Scene();//场景
var scene;
function initScene() {scene = new THREE.Scene();
}

相机 camera

/* 
创建相机fov 角度aspect 宽高比near 近景far 远景
*/
camera =  new THREE.PerspectiveCamera(angle, SCREEN_WIDTH / SCREEN_HEIGHT, nearest, farthest);
// 位置设置 默认位置:0,0,0
camera.position.set(20, 20, 30);//相机
var camera;
function initCamera() {camera = new THREE.PerspectiveCamera(70, width / height, 1, 1000);camera.position.x = 0;camera.position.y = 900;camera.position.z = 0;camera.lookAt(new THREE.Vector3(0,0,0));
}

平行光

// 平行光
var light = new THREE.DirectionalLight(16777215, 1);
/*x 向右y 向上z 屏幕里面射向屏幕外面
*/
light.position.set(0, 50, 50);
scene.add(light);// 方法
//光源
var light;
function initLight() {light = new THREE.DirectionalLight(0xFF0000, 1.0, 0);light.position.set(100, 100, 200);scene.add(light);
}

坐标系

// 坐标系 名称改为 AxesHelper
var axes = new THREE.AxisHelper(30);
scene.add(axes);

加载

// 加载提示
var manager = new THREE.LoadingManager();
manager.onProgress = function(item, loaded, total){console.log(item, loaded, total);
};

渲染器

renderer = new THREE.WebGLRenderer({antialias: true,    // 平滑效果alpha: true,    // canvas背景透明
});
renderer.setPixelRatio(window.devicePixelRatio);
// 设置渲染范围
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
// 在容器中渲染位置
container.appendChild(renderer.domElement);

控制器 Controls

controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0, 0);
animate();
window.addEventListener('resize', onWindowResize, false);// 方法
function initControls() {controls = new THREE.OrbitControls(camera, renderer.domElement);//设置控制器的中心点//controls.target.set( 0, 100, 0 );// 如果使用animate方法时,将此函数删除//controls.addEventListener( 'change', render );// 使动画循环使用时阻尼或自转 意思是否有惯性controls.enableDamping = true;//动态阻尼系数 就是鼠标拖拽旋转灵敏度//controls.dampingFactor = 0.25;//是否可以缩放controls.enableZoom = true;//是否自动旋转controls.autoRotate = false;controls.autoRotateSpeed = 0.5;//设置相机距离原点的最远距离controls.minDistance = 1;//设置相机距离原点的最远距离controls.maxDistance = 2000;//是否开启右键拖拽controls.enablePan = true;
}

动画 animation

function animate() {//更新控制器render();//更新性能插件stats.update();controls.update();renderer.render( scene, camera );// 绘制下一帧动画requestAnimationFrame(animate);
}

绘制 draw

function draw() {initGui();initRender();initScene();initCamera();initLight();initModel();initControls();initStats();animate();window.onresize = onWindowResize;
}

模型

导出

  • json 模型导出 Blender

名称设置

[外链图片转存失败(img-iTOE27Cn-1567579302212)(C:\Users\JACKY\Desktop\学习文档\image\threejs\001.png)]

fbx动画

fbx_loader.load('./models/gf/run.fbx', function(object){object.mixer = new THREE.AnimationMixer(object);mixers.push(object.mixer);var action = object.mixer.clipAction(object.animations[0]);action.play();object.scale.multiplyScalar(.5);object.position.set(-3, 0, 0);scene.add(object);
}, onProgress, onError);

加载贴图

texturePlante = THREE.ImageUtils.loadTexture("model/xishouci/obj132VRay.jpg",null,function(t){});//模型贴图// 加载后内部
object.traverse( function ( child ) {var mat = new THREE.MeshPhysicalMaterial({emissive:0xffffff,// emissive默认黑色,设置为白色color:0xffffff,emissiveMap: texturePlante,})  child.material=mat;if ( child.isMesh ) {child.castShadow = true;child.receiveShadow = true;};
});
var js_loader = new THREE.JSONLoader(manager);

json静态模型一

js_loader.load('./models/hmj/frame001.json', function(geometry, materials){var material = new THREE.MultiMaterial(materials);var mesh = new THREE.Mesh(geometry, material);mesh.scale.multiplyScalar(.06);scene.add(mesh);
}, onProgress, onError);

json静态模型二

var object_loader = new THREE.ObjectLoader(manager);object_loader.load('./models/teapot-claraio.json', function(object){object.scale.multiplyScalar(5);scene.add(object);
});

json动画

js_loader.load('./models/body/climb.js', function(geometry, materials){for(var i = 0; i < materials.length; i++){materials[i].skinning = true;}var material = new THREE.MultiMaterial(materials);var mesh = new THREE.SkinnedMesh(geometry, material);var mixer = new THREE.AnimationMixer(mesh);mixers.push(mixer);mixer.clipAction(geometry.animations[0]).play();mesh.scale.multiplyScalar(.05);mesh.lookAt(new THREE.Vector3(0, 0, 0));mesh.position.set(3, 0, 0);scene.add(mesh);
}, onProgress, onError);
var obj_loader = new THREE.OBJLoader(manager);
obj_loader.setPath('./models/mooncake/');		

obj静态模型一

var tga_loader = new THREE.TGALoader();
var material = new THREE.MeshPhongMaterial({map: tga_loader.load('./models/mooncake/Sofa_OS_0727_01___Default_Diffuse.tga'),normalMap: tga_loader.load('./models/mooncake/Sofa_OS_0727_01___Default_Normal.tga'),specularMap: tga_loader.load('./models/mooncake/Sofa_OS_0727_01___Default_S.tga'),bumpMap: tga_loader.load('./models/mooncake/Sofa_OS_0727_01___Default_Bump.tga')
});
obj_loader.load('mooncake.obj', function(group){var geometry = group.children[0].geometry;geometry.attributes.uv2 = geometry.attributes.uv;geometry.center();var mesh = new THREE.Mesh(geometry, material);mesh.scale.multiplyScalar(.1);scene.add(mesh);
}, onProgress, onError);

obj静态模型二

THREE.Loader.Handlers.add(/\.tga$/i, new THREE.TGALoader());
var mtl_loader = new THREE.MTLLoader();
mtl_loader.setPath('./models/mooncake/');
mtl_loader.load('mooncake.mtl', function(materials){materials.preload();obj_loader.setMaterials(materials);obj_loader.load('mooncake.obj', function(object){object.scale.multiplyScalar(.1);scene.add(object);}, onProgress, onError);
});

两种模型切换

var meshes = {}; addObj = function(url){ var objectloading = url; var loader = new THREE.OBJLoader(manager); loader.load(objectloading, function (object) { object.traverse(function (child) { if (child instanceof THREE.Mesh) { child.material.map = texture; } }); object.position.y = -30; meshes[url] = object; scene.add(object); }, onProgress, onError); 
} removeObj = function(url){ scene.remove(meshes[url]); delete meshes[url]; 
} //在点击一个按钮
removeObj('obj/male02/old.obj'); 
addObj('obj/male02/new.obj'); //然后在另一个按钮点击:
removeObj('obj/male02/new.obj'); 
addObj('obj/male02/old.obj'); 

模型居中

var box3 = new THREE.Box3()
// 计算层级模型group的包围盒
// 模型group是加载一个三维模型返回的对象,包含多个网格模型
box3.expandByObject(object)
// 计算一个层级模型对应包围盒的几何体中心在世界坐标中的位置
var center = new THREE.Vector3()
box3.getCenter(center)
// console.log('查看几何体中心坐标', center);// 重新设置模型的位置,使之居中。
object.position.x = object.position.x - center.x
object.position.y = object.position.y - center.y
object.position.z = object.position.z - center.z

Shader

error

  • WebGL时,遇到dFdx不能使用的解决方法

    # 需要初始化时,在 
    var gl = canvas.getContext('webgl'); 
    # 后加上 
    gl.getExtension('OES_standard_derivatives'); 
    # 以及在片元着色器开头加上 
    #extension GL_OES_standard_derivatives : enable# HTML
    <canvas id="sandbox"></canvas># JavaScript
    var container = document.getElementById("sandbox");
    gl = container.getContext("webgl");
    if (!gl){console.error("WebGL failed to initialize");
    }else{console.debug("WebGL initialization successful");
    }
    var extension = gl.getExtension("OES_standard_derivatives");
    if (!extension){console.error("Extension 'OES_standard_derivatives' was not found");
    }else{console.debug("Extension 'OES_standard_derivatives' was found");
    }
    

demo

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>Three框架</title><script src="http://test.tp5.com/static/js/master/build/three.js"></script><script src="http://test.tp5.com/static/js/master/js/libs/stats.min.js"></script><style type="text/css">div#canvas-frame {border: none;cursor: pointer;width: 100%;height: 600px;background-color: #EEEEEE;}</style></head><body onload="threeStart();"><div id="canvas-frame"></div></body><script id="fragment_shader" type="x-shader/x-fragment">uniform float time;varying vec2 vUv;void main( void ) {vec2 position = - 1.0 + 2.0 * vUv;float red = abs( sin( position.x * position.y + time / 5.0 ) );float green = abs( sin( position.x * position.y + time / 4.0 ) );float blue = abs( sin( position.x * position.y + time / 3.0 ) );gl_FragColor = vec4( red, green, blue, 1.0 );}</script><script id="vertexShader" type="x-shader/x-vertex">varying vec2 vUv;void main(){vUv = uv;vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );gl_Position = projectionMatrix * mvPosition;}</script><script>      var renderer;var stats;var clock;var uniforms1;var camera;var scene;var light;var mesh;//初始化webglfunction initThree() {width = document.getElementById('canvas-frame').clientWidth;height = document.getElementById('canvas-frame').clientHeight;renderer = new THREE.WebGLRenderer();renderer.setSize(width, height);document.getElementById('canvas-frame').appendChild(renderer.domElement);renderer.setClearColor(0xFFFFFF, 1.0);clock = new THREE.Clock();stats = new Stats();stats.domElement.style.position = 'absolute';stats.domElement.style.left = '0px';stats.domElement.style.top = '0px';document.getElementById('canvas-frame').appendChild(stats.domElement);}//设置相机function initCamera() {camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);            camera.position.set(0,0,600);camera.up = new THREE.Vector3(0,1,0);camera.lookAt(0,0,0);}//初始化场景function initScene() {scene = new THREE.Scene();}//设置化灯光function initLight() {light = new THREE.AmbientLight(0xFF0000);light.position.set(100, 100, 200);scene.add(light);            }//几何物体function initObject() {uniforms1 = {time: { value: 1.0 }};var params = uniforms1;var geometry = new THREE.CylinderGeometry(100, 150, 400);var material = new THREE.ShaderMaterial({uniforms: params,vertexShader: document.getElementById('vertexShader').textContent,fragmentShader: document.getElementById('fragment_shader').textContent});mesh = new THREE.Mesh(geometry, material);mesh.position = new THREE.Vector3(0, 0, 0);scene.add(mesh);}//运行webglfunction threeStart() {initThree();initCamera();initScene();initLight();initObject();animation();    }//设置动态场景function animation() {var delta = clock.getDelta();uniforms1.time.value += delta * 5;renderer.render(scene, camera);requestAnimationFrame(animation);stats.update();           }</script>
</html>  

性能提高

场景删除

//删除group
function deleteGroup(name) {let group = scene.getObjectByName(name);if (!group) return;//删除掉所有的模型组内的meshgroup.traverse(function (item) {if (item instanceof THREE.Mesh) {item.geometry.dispose(); //删除几何体item.material.dispose(); //删除材质}});scene.remove(group);
}

需要的时候渲染

var renderEnabled;
function animate() {if (renderEnabled) {renderer.render(scene, camera);}requestAnimationFrame(animate);
}animate();

掉帧

//调用一次可以渲染三秒
let timeOut = null;
function timeRender() {//设置为可渲染状态renderEnabled = true;//清除上次的延迟器if (timeOut) {clearTimeout(timeOut);}timeOut = setTimeout(function () {renderEnabled = false;}, 3000);
}

代码顺序

initThree

initCamera

initScene

initLight

initObject

renderer.clear

renderer.render(scene, camera)

LineBasicMaterial

Color:线条的颜色,用16进制来表示,默认的颜色是白色。Linewidth:线条的宽度,默认时候1个单位宽度。Linecap:线条两端的外观,默认是圆角端点,当线条较粗的时候才看得出效果,如果线条很细,那么你几乎看不出效果了。Linejoin:两个线条的连接点处的外观,默认是“round”,表示圆角。VertexColors:定义线条材质是否使用顶点颜色,这是一个boolean值。意思是,线条各部分的颜色会根据顶点的颜色来进行插值。

[外链图片转存失败(img-cUeQRFbs-1567579302213)(C:\Users\JACKY\Desktop\学习文档\image\threejs\图片1.jpg)]

webgl 使用右手坐标系

[外链图片转存失败(img-wmS4VzGW-1567579302213)(C:\Users\JACKY\Desktop\学习文档\image\threejs\33.jpg)]

Stat

一个监控程序 帧数、每帧时间、内存使用量的js库

  • 监控内存:–enable-precise-memory-info

  • var stats = new Stats();
    stats.setMode( 1 ); // 0: fps, 1: ms, 2: mbstats.domElement.style.position = 'absolute';
    stats.domElement.style.left = '0px';
    stats.domElement.style.top = '0px';document.body.appendChild( stats.domElement );var update = function () {stats.begin();// monitored code goes herestats.end();requestAnimationFrame( update );
    };
    requestAnimationFrame( update );
    

twwenjs

OrthographicCamera

正投影相机

THREE.OrthographicCamera = function ( left, right, top, bottom, near, far) 

[外链图片转存失败(img-DOWsjHPm-1567579302213)(C:\Users\JACKY\Desktop\学习文档\image\threejs\扥赛风.jpg)]

PerspectiveCamera

PerspectiveCamera( fov, aspect, near, far )

[外链图片转存失败(img-o8WI9rq6-1567579302214)(C:\Users\JACKY\Desktop\学习文档\image\threejs\112.jpg)]

[外链图片转存失败(img-KDjbEkzr-1567579302214)(C:\Users\JACKY\Desktop\学习文档\image\threejs\113.jpg)]

camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
// 位置
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 600;
// 快门指向位置
camera.up.x = 0;
camera.up.y = 1;
camera.up.z = 0;
// 相机指向位置,代表一个方向,不是代表一个点
camera.lookAt({x : 0,y : 0,z : 0
});

旋转

围绕某个轴旋转

  • 拇指指向旋转轴的正方向,四指弯曲的方向为旋转的正方向
  • [外链图片转存失败(img-8VSFhMEr-1567579302214)(C:\Users\JACKY\Desktop\学习文档\image\threejs\图片21.jpg)]

围绕自己旋转

围绕其他物体旋转

场景动起来

原理

/*
渲染的时候,我们调用的是渲染器的render() 函数。代码如下:
renderer.render( scene, camera );如果不断的改变物体的颜色,那么就需要不断的绘制新的场景,所以我们最好的方式,是让画面执行一个循环,不断的调用render来重绘,这个循环就是渲染循环,在游戏中,也叫游戏循环。
*/
function animate() {render();requestAnimationFrame( animate );
}
  • 变化物体的位置
  • 变化相机的位置

相机

  • 投影区别

[外链图片转存失败(img-ZJVopsj2-1567579302215)(C:\Users\JACKY\Desktop\学习文档\image\threejs\camera.jpg)]

框架

基础代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8">    <title>Three.js</title>     <script src="../../../Import/three.js"> </script>     <script src="../../../Import/stats.js"></script>     <script src="../../../Import/Setting.js"> </script>    <style type="text/css">div#canvas-frame {          border: none;    cursor: pointer;          width: 100%;       height: 850px;      background-color: #333333;      }</style><script>       let renderer; function initThree() {          //TODO        }let camera;function initCamera() {           //TODO      } let scene;function initScene() {           //TODO      } let light;function initLight() {          //TODO   } let cube; function initObject() {           //TODO   }        //提前定义好的一个功能文件,方便以后的每一个程序调用     function initSetting() {loadAutoScreen(camera, renderer);//自适应屏幕      loadFullScreen();//网页全屏播放     loadStats();//性能检测插件        }function threeStart() {initSetting();initThree();initCamera(); initScene(); initLight(); initObject();animation();}function animation() {renderer.clear();renderer.render(scene, camera); stats.update();requestAnimationFrame(animation);}   </script>
</head><body onload="threeStart()"><div id="canvas-frame"></div>
</body></html>

函数工具

//进入全屏模式的函数 function loadFullScreen() {    
//进入全屏    
function requestFullScreen(element) {let de = document.querySelector(element) || document.documentElement;if (de.requestFullscreen) {de.requestFullscreen();} else if (de.mozRequestFullScreen) {de.mozRequestFullScreen();} else if (de.webkitRequestFullScreen) {de.webkitRequestFullScreen();}
}
//退出全屏  
function exitFullscreen(element) {let de = document.querySelector(element) || document.documentElement;if (de.exitFullscreen) {de.exitFullscreen();} else if (de.mozCancelFullScreen) {de.mozCancelFullScreen();} else if (de.webkitCancelFullScreen) {de.webkitCancelFullScreen();}
}    
//监听事件
document.onkeydown = function (ev) {keydownForScreen(ev);}
//按键检测,112对应键盘的F2,可以检测其他的键位    
function keydownForScreen(ev) {if (ev.keyCode == 113) {requestFullScreen(); requestFullScreen('body');requestFullScreen('#main');}
}}
//加载性能监视器的函数
function loadStats() {stats = new Stats(); stats.domElement.style.position = 'absolute';stats.domElement.style.left = '8px'; stats.domElement.style.top = '8px';let body = document.getElementsByTagName('body'); body[0].appendChild(stats.domElement);
}
//屏幕适应的函数
function loadAutoScreen(camera, renderer) {window.addEventListener('resize', onResize, false); function onResize() {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight);}
}

工具使用

Blender

导入文件

[外链图片转存失败(img-mS3Ya8Ek-1567579302215)(C:\Users\JACKY\Desktop\学习文档\image\threejs\0190812105536.png)]

结束


本文链接:https://www.ngui.cc/el/2111857.html
Copyright © 2010-2022 ngui.cc 版权所有 |关于我们| 联系方式| 豫B2-20100000