ThreeJS入门(二)绘制3d图形
<style>.artBox { font-size: 18px; }
.artBox > p { margin: 10px 0; }
#prevBox { position: fixed; top: 0; right: 0; bottom: 0; left: 0; background: rgba(255,255,255,.95); display: none; padding: 0; overflow: hidden; z-index: 1000; margin: 0; }
#prevBox::after { position: absolute; content: '关闭预览'; bottom: 10px; left: calc(50% - 40px); padding: 0 4px; width: 80px; height: 30px; line-height: 30px; text-align: center; border: 1px solid #efe; border-radius: 6px; background: #eee; font-size: 14px; box-shadow: 2px 2px 6px rgba(0,0,0,.25); cursor: pointer; }
iframe { position: relative; width: 100%; height: 100%; border: none; outline: none; box-sizing: border-box; margin: 0; }
</style>
<div id="prevBox"></div>
<div class="artBox">
<p>搭好了 ThreeJS 场子,接着自然就是踢馆——哦不,是绘制图形了!本讲从画一个静态的立方体入手,看看如何实现。</p>
<p>在 ThreeJS 的世界中,图像 = 几何体 + 材质,图像就是最终绘制成品,叫 Mesh,几何体叫 Geometry,是图像的框架,材质叫 Material,是图像的血肉。绘制过程,以本讲示例为例,可以这么理解:在场景 Scene 中,用特定的材质,比如不需要光照也能看得见的 ThreeJS 特制材料 MeshNormalMaterial,安装到指定的几何体框架,比如一个立方体 BoxGeometr。来看代码:</p>
<div class="hEdiv"><pre class="hEpre">
// ... 搭建场子代码略
var geometry = new THREE.BoxGeometry(); // 创建立方体几何体
var material = new THREE.MeshNormalMaterial(); // 创建自带颜色、有光泽的材质
var mesh = new THREE.Mesh(geometry, material); // 将几何体和材质组合起来
scene.add(mesh); // 将成品加入到场景中
renderer.render(scene, camera); // 渲染器渲染结果
</pre></div>
<p>这里,第一步,将 ThreeJS 封装的对象 THREE.BoxGeometry 即立方几何体实例化,这就是创建一个立方体的框架,并把该实例化的几何体命名为小写的 geometry;第二步,也是通过实例化 ThreeJS 封装对象的方式创建了自带光泽、颜色的材质 —— 法向量材质,将实例化的材质对象命名为小写的 material;第三步,通过 THREE.Mesh 对象的实例化创建了最终成品,即立方体图像,命名为小写的 mesh。这几步:</p>
<p>一、立方体几何体的创建可以带一些参数,常用到的参数时 x、y、z,即立方体在xyz三个方向上的尺寸,缺省时默认是 (1, 1, 1),可以修改试试。</p>
<p>二、材质在创建时可以使用 JS 的 { options } 方式配置参数,例如线框化、双面渲染,{ wireframe: true, side: THREE.DoubleSide }。一般来说,不同的材质配置方式不尽相同,但所有的材质都有共性,具体的内容可以自行网查。</p>
<p>三、组装成最终成品,即实例化 THREE.Mesh 则不能缺省参数,必须指定为前面创建的几何体和材质的变量名称。</p>
<p>第四步,注意绘制好的的成品 mesh 要加入到场景;最后一步,咔嚓,按下快门,即渲染器将场景和相机合作的结果渲染出来。</p>
<p>不过以上代码的运行结果可能会令人失望:只看到一个矩形。没关系,它的的确确是一个立方体,只是由于角度的问题让我们看不全它的真实面貌。我们可以使用图像的旋转方法 rotateX/Y/Z 将立方体 mess 在 xyz 方向都做一些调整,效果将十分完美。以下是完整代码:</p>
<div class="hEdiv"><pre class="hEpre">
<script type="module">
import * as THREE from 'https://esm.sh/three';
var scene = new THREE.Scene;
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var geometry = new THREE.BoxGeometry();
var material = new THREE.MeshNormalMaterial();
var mesh = new THREE.Mesh(geometry, material);
mesh.rotateX(0.5);
mesh.rotateY(0.5);
mesh.rotateZ(-0.5);
scene.add(mesh);
renderer.render(scene, camera);
</script>
</pre></div>
<blockquote><button id="btnPrev">运行代码</button></blockquote>
</div>
<script type="module">
import hlight from 'https://638183.freep.cn/638183/web/helight/helight1.js';
const pres = document.querySelectorAll('.hEpre');
const divs = document.querySelectorAll('.hEdiv');
divs.forEach( (div, key) => hlight.hl(div, pres));
const preView = (htmlCode, targetBox) => {
if (targetBox.innerHTML) return;
const iframe = document.createElement('iframe');
htmlCode = htmlCode + '<style>body {margin: 0; }</style>';
iframe.srcdoc = htmlCode;
targetBox.appendChild(iframe);
targetBox.style.display = 'block';
targetBox.onclick = () => {
targetBox.innerHTML = '';
targetBox.style.display = 'none';
}
};
const value = pres.textContent;
btnPrev.onclick = () => preView(value, prevBox);
</script> {:4_173:}一下子从自动旋转变成手工转向了。。
先试了111,还是现在的参数比较看了面数比较多 话说你发明的这着色代码好方便啊。。。。
本来对单词不敏感,这么一着色,各个结构就清楚多了。{:4_199:} 这个不是线框,而是接近实例的立方体。材质自带色彩,无法更改{:4_173:} 花飞飞 发表于 2025-5-22 20:53
这个不是线框,而是接近实例的立方体。材质自带色彩,无法更改
用来演示最合适 花飞飞 发表于 2025-5-22 20:49
话说你发明的这着色代码好方便啊。。。。
本来对单词不敏感,这么一着色,各个结构就清楚多了。
这是 ThreeJS 特殊材质的样纸 花飞飞 发表于 2025-5-22 20:48
一下子从自动旋转变成手工转向了。。
先试了111,还是现在的参数比较看了面数比较多
角度问题呢,各参数得配套。接受正负参数。这个和 PI 有关,就是 3.14,圆周率。也可以使用 Math.PI / n 来表示。
各参数中,几何体参数默认是 (1,1,1),xyz 方向的尺寸都是 1 个距离单位。数字越大,对应面越大。 这个讲解又是特别好呢,现在一点点更加清晰了。
黑黑很有讲解水平,这样分开来讲解,特别容易理解呢{:4_199:} 这里是把立方体图像做了调整,以便更好地观察。
如果不动图像,调整一下相机的角度,应该也能看到吧。{:4_204:} 这两节课都是最基础的呢,先理解了这个,然后再去加其他的东西,就不容易迷糊了{:4_173:} 红影 发表于 2025-5-22 21:52
这两节课都是最基础的呢,先理解了这个,然后再去加其他的东西,就不容易迷糊了
入门的时机最好不要错过 红影 发表于 2025-5-22 21:50
这里是把立方体图像做了调整,以便更好地观察。
如果不动图像,调整一下相机的角度,应该也能看到吧。{:4_ ...
方式很多。不过一般先动图片,这是是基础 红影 发表于 2025-5-22 21:48
这个讲解又是特别好呢,现在一点点更加清晰了。
黑黑很有讲解水平,这样分开来讲解,特别容易理解呢{:4_19 ...
不过,其实也是有前面的东东打底的 马黑黑 发表于 2025-5-22 22:34
入门的时机最好不要错过
嗯嗯,这个很重要{:4_187:} 马黑黑 发表于 2025-5-22 22:35
方式很多。不过一般先动图片,这是是基础
嗯嗯,知道了{:4_187:} 马黑黑 发表于 2025-5-22 22:35
不过,其实也是有前面的东东打底的
是的,前面迷糊了半天,看到这两节课豁然开朗的感觉{:4_199:} 讲的真好,谢谢马老师细致入微的讲解{:4_191:} 红影 发表于 2025-5-22 23:07
嗯嗯,这个很重要
{:4_190:} 红影 发表于 2025-5-22 23:08
是的,前面迷糊了半天,看到这两节课豁然开朗的感觉
这叫啥来着?山穷水复疑无路,柳暗花明又一村 杨帆 发表于 2025-5-23 07:16
讲的真好,谢谢马老师细致入微的讲解
{:4_191:}
页:
[1]
2