이 글은 주로 누구나 Threejs를 빨리 시작할 수 있도록 작성되었습니다. 관심 있는 친구들이 참고할 수 있습니다.
이제 모든 것이 3D로, 3D로 영화를 보고, 3D로 게임을 할 수 있습니다. 3D 택시가 곧 출시될 예정입니다. 그렇다면 프론트엔드 개발의 표준 언어로서 JS와 3D도 큰 뉴스를 만들 수 있을까요? 최근에 이벤트를 하다가 3D 파노라마 영상을 재생해야 할 필요성을 느꼈습니다. 그런데 브라우저에서 3D 이미지를 그리기 위한 JS 라이브러리인 Threejs을 공부했습니다( https://github.com/mrdoob/3.js) 이 글은 노트이며, 빨리 시작하고 싶은 학생들에게 도움이 되었으면 좋겠습니다.
최소 환경 우선 Threejs를 정식으로 배우기 전에 먼저 설명해야 할 몇 가지 개념이 있습니다.Threejs는 실제로 HTML5의 하위 수준에서 캔버스 API를 호출하여 그리기를 구현합니다. 하지만 일반적인 2D 이미지 그리기와는 달리 Threejs는 하단 수준에서 캔버스의 webgl 컨텍스트를 사용하여 3D 그리기를 구현합니다. webgl 컨텍스트 자체는 GPU의 직접 작동 에 가깝습니다. 이는 사용하기에 매우 직관적이지 않습니다. 이러한 이유로 Threejs는 최상위 수준에서 3D 드로잉에 필요한 다양한 요소(예: 장면, 카메라, 조명, 기하학적 이미지, 재료) 등)이 캡슐화되어 있습니다. Threejs를 사용하여 그려야 하는 경우 최소 그리기 환경만 만들면 됩니다. 이 최소 그리기 환경에는
1. 장면--표시해야 하는 모든 3D 객체 및 기타 관련 요소를 포함합니다.
2. 카메라 - 3D 장면이 2D 캔버스에 투영되는 방식을 결정합니다.
3. 렌더러 - 최종 드로잉에 사용됩니다. 브러시
의 구체적인 코드는 다음과 같습니다.<p class="km_insert_code"> import { Scene, PerspectiveCamera, WebGLRenderer } from ‘three’; var scene = new Scene(); // 创建场景 var camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000); // 创建摄影机 camera.position.z = 8; var renderer = new WebGLRenderer(); // 创建渲染器 renderer.setSize(window.innerWidth, window.innerHeight); // 设置画布大小 renderer.setPixelRatio(window.devicePixelRatio); // 设置像素比,针对高清屏 renderer.setClearColor(0x000000, 1); // 设置默认背景色 document.body.appendChild(renderer.domElement); // 把画笔插入到dom中</p>몇 줄의 간단한 코드만으로
최소 드로잉 환경을 구축할 수 있습니다. 이 환경에 표시되어야 하는 3D 객체는 캔버스에 그려지고 화면에 표시됩니다.
3D**Object**
환경과 함께 우리는 Threejs에게 어떤 객체를 표시해야 하는지 알려줘야 합니다. 이렇게 하려면 먼저 표시할 객체를 정의한 다음 이를 장면에 추가해야 합니다.<p class="km_insert_code"> import { Mesh, MeshBasicMaterial, BoxGeometry } from ‘three’; var geometry = new BoxGeometry(1, 1, 1); // 创建一个长方体,用来定义物体的形状 var material = new MeshBasicMaterial({ color: 0xff0000 }); // 创建一个材质,用来定义物体的颜色 var mesh = new Mesh(geometry, material); // 使用形状和素材,来定义物体 scene.add(mesh); renderer.render(scene, camera);</p>효과부터 먼저 살펴볼까요 왜 이렇게 지루하게 느껴지나요, 하하하, 어쨌든 우리는 이미 그림을 그릴 수 있습니다.
texture가 무엇인지, geometry와 material이 무엇에 사용되는지에 대한 질문이 생길 것입니다. 응. 실제로 Threejs는 3D 객체를 정의할 때 두 가지 정보를 제공해야 하는데, 첫 번째는 객체의 각 점과 면의 좌표 정보인 모양 정보입니다. Threejs에게 객체의 색상, 질감, 반사 및 기타 정보를 알려줍니다. 이 정보를 통해 Threejs는 이 객체를 렌더링하는 방법을 알고 있습니다. 위의 새로운 BoxGeometry(1, 1, 1)은 Threejs에게 길이, 너비, 높이가 1인 직사각형을 표시하고 싶다고 알려줍니다. 그리고 새로운 MeshBasicMaterial({ color: 0xff0000})은 Threejs에게 이 직육면체가 빨간색임을 알리는 것입니다. 마지막으로 모양과 재질을 기반으로 새로운 Mesh(기하학, 재질), 표시할 객체가 생성됩니다. Threejs에서 직육면체를 생성하려면 BoxGeometry를 정의해야 한다고 위에서 언급했습니다. 직육면체 외에도 Threejs는 모양도 생성할 수 있습니다. 1 BoxGeometry--cuboid
2.CircleGeometry--圆形平面
3.CylinderGeometry--圆柱体
4.PlaneGeometry--方形平面
5.RingGeometry--环形平面
6.SphereGeometry--球形
7.TextGeometry--文字
8.TorusGeometry--圆环
9.TubeGeometry--圆管
另外上面写到的MeshBasicMaterial,其实是指一个直接就能显示颜色的材质。什么叫直接显示颜色呢?这里要涉及到Threejs里的灯光设置。物体的材质由于确定物体的颜色,纹理,以及反光等属性。要反光,首先需要有一个光源:
<p class="km_insert_code"> import { SpotLight } from ‘three’; var light = new SpotLight(0xffffff); light.position.z = 5; light.position.x = 5; light.position.y = 5; scene.add(light);</p>
这里我们定义了一个白光源,具体的效果如下:
为了可以看清楚效果,我在场景中加入了一个绿色平面,可以看到,这个绿色平面上的反光是从下到上减弱,可见,这个光源是在画面的下方。
如果我把光源的强度减弱,那么平面上的反光也会跟着减弱:
但不知大家有木有发现,绿色平面上的反光是减弱了,但红色的那个长方体,还是一样的红,完全没有变化。其实这就体现出不同材质的区别了,在红色长方体上,我采用的是MeshBasicMaterial这种材质,而在绿色平面上,我采用的是另一种称为MeshLambertMaterial的材质,这种材质的特点是漫反射强烈,主要用来模拟真实环境下的物体,例如木材,石料等物质的反光情况。另外Threejs还有另外一种材质叫MeshPhongMaterial,这种材质主要是镜面反射强烈,用来模拟镜子,金属等拥有高光的物体就比较合适。
MeshLambertMaterial和MeshPhongMaterial两种材质,都是需要光照才能看到的,如果场景中没有光源,你将会什么都看不到。相反我们在红色长方体上采用的材质是MeshBasicMaterial,这种材质即使没有光,也可以看到,你可以想象为它自己发光吧,如果用技术一点的话来说,就是MeshLambertMaterial和MeshPhongMaterial两种材质需要根据场景光线的数值来计算显示在屏幕上的颜色,而MeshBasicMaterial则忽略光线的作用,是什么颜色,就直接显示什么颜色,但也由于这种材质忽略了光照的作用,那么它也不会有任何阴影的效果。所以这种材质就叫Basic,用来做演示就十分合适。一下就是Threejs提供给我们用到的其他材质
1.MeshBasicMaterial
2.MeshLambertMaterial--漫反射材质
3.MeshPhongMaterial--镜面反射材质
4.MeshDepthMaterial--根据物体上每一点到摄像机的远近来显示颜色,远的显示黑色,近的显示白色
5.MeshNormalMaterial--根据物体上每一面的法向量方向来显示颜色
如果绘制3D物体时,只能使用纯色,那也未免太单调了,没关系,Threejs提供了接口来帮忙解决这个问题。Threejs的材质,除了可以设置颜色,还支持纹理贴图,我们可以把一个图片,覆盖在3D物体上作为他的纹理,这样就可以利用这些贴图来模拟更真实的场景
<p class="km_insert_code"> import { TextureLoader, MeshLambertMaterial } from ‘three’; var texture = new TextureLoader().load(‘./assets/texture/crate.gif’); var material = new MeshLambertMaterial({ map: texture });</p>
上面的代码中,我们通过TextureLoader来加载一个gif图作为纹理,并且把这个纹理通过map属性映射到了材质上,加上材质后,整个物体就更加真实了
3D动画
能绘图了,但如何加入动画呢?其实很简单,在之前的代码中已经讲解过,Threejs是通过渲染器来绘图的,你可以想象成拍照。我们在场景中摆好灯光,摆好道具,渲染器咔嚓一下,就把当前的画面绘制下来了。那如果要做成动画,只需要在渲染器来个定时连拍就可以拉。具体如下。
<p class="km_insert_code"> function render() { requestAnimationFrame(render); update(); renderer.render(scene, camera); } function update() { // update your view } </p>
这里我们通过requestAnimationFrame接口,来做定时刷新,每次进入render方法,都会先去执行update方法(用于更新场景),然后让渲染器拍照(renderer.render(scene, camera)),最后等待下一次render。在update方法中,我们可以修改场景中所有物体的参数,例如,我们可以试着让盒子在屏幕中转动:
<p class="km_insert_code"> function update() { box.rotation.x += 0.005; box.rotation.y += 0.01; } </p>
最后的最后,其实Threejs还有很多额外的能力,例如刚刚我们使用图片作为纹理,那么我们也可以使用视频作为纹理,把这个纹理贴到一个盒子上,通过陀螺仪来控制摄像机的拍摄方向,就可以作出一个全景视频啦。Threejs也支持粒子系统,模型数据导入,自定义着色器等一系列高级功能,大家也赶快掌握起来吧。
위 내용은 Threejs로 빠른 시작의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!