Files
apt-nl-map/static/Magic4/js/three.js-dev/docs/manual/zh/introduction/How-to-update-things.html
2024-12-04 10:21:04 +08:00

206 lines
6.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<base href="../../../" />
<script src="page.js"></script>
<link type="text/css" rel="stylesheet" href="page.css" />
</head>
<body>
<h1>如何更新场景([name]</h1>
<div>
<p>默认情况下,所有对象都会自动更新它们的矩阵(如果它们已添加到场景中)</p>
<code>
const object = new THREE.Object3D();
scene.add( object );
</code>
或者它们是已添加到场景中的另一个对象的子节点:
<code>
const object1 = new THREE.Object3D();
const object2 = new THREE.Object3D();
object1.add( object2 );
scene.add( object1 ); //object1 和 object2 会自动更新它们的矩阵
</code>
</div>
<p>但是,如果你知道对象将是静态的,则可以禁用此选项并在需要时手动更新转换矩阵。</p>
<code>
object.matrixAutoUpdate = false;
object.updateMatrix();
</code>
<h2>BufferGeometry</h2>
<div>
<p>
BufferGeometries 将信息例如顶点位置面索引法线颜色uv和任何自定义属性存储在[page:BufferAttribute buffers] —— 也就是,
[link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays typed arrays].
这使得它们通常比标准Geometries更快缺点是更难用。
</p>
<p>
关于更新BufferGeometries最重要的是理解你不能调整 buffers 大小这种操作开销很大相当于创建了个新的geometry
但你可以更新 buffers的内容。
</p>
<p>
这意味着如果你知道BufferGeometry的一个属性会增长比如顶点的数量
你必须预先分配足够大的buffer来容纳可能创建的任何新顶点。
当然这也意味着BufferGeometry将有一个最大大小 —— 无法创建一个可以高效地无限扩展的BufferGeometry。
</p>
<p>
我们以在渲染时扩展的line来示例。我们将分配可容纳500个顶点的空间但起初仅绘制2个使用
在500个顶点的缓冲区中但首先只使用 [page:BufferGeometry.drawRange]。
</p>
<code>
const MAX_POINTS = 500;
// geometry
const geometry = new THREE.BufferGeometry();
// attributes
const positions = new Float32Array( MAX_POINTS * 3 ); // 3 vertices per point
geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
// draw range
const drawCount = 2; // draw the first 2 points, only
geometry.setDrawRange( 0, drawCount );
// material
const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
// line
const line = new THREE.Line( geometry, material );
scene.add( line );
</code>
<p>
然后我们随机增加顶点到line中以这样的一种方式
</p>
<code>
const positions = line.geometry.attributes.position.array;
let x, y, z, index;
x = y = z = index = 0;
for ( let i = 0, l = MAX_POINTS; i < l; i ++ ) {
positions[ index ++ ] = x;
positions[ index ++ ] = y;
positions[ index ++ ] = z;
x += ( Math.random() - 0.5 ) * 30;
y += ( Math.random() - 0.5 ) * 30;
z += ( Math.random() - 0.5 ) * 30;
}
</code>
<p>
如果要更改第一次渲染后渲染的<em>点数</em>,执行以下操作:
</p>
<code>
line.geometry.setDrawRange( 0, newValue );
</code>
<p>
如果要在第一次渲染后更改position数值则需要像这样设置needsUpdate标志
</p>
<code>
line.geometry.attributes.position.needsUpdate = true; // 需要加在第一次渲染之后
</code>
<p>
<a href="https://jsfiddle.net/xvnctbL0/2/">这个fiddle</a>展示了一个你可以参考的运动的line。
</p>
<h3>例子</h3>
<p>
[example:webgl_custom_attributes WebGL / custom / attributes]<br />
[example:webgl_buffergeometry_custom_attributes_particles WebGL / buffergeometry / custom / attributes / particles]
</p>
</div>
<h2>材质Materials</h2>
<div>
<p>所有uniforms值都可以自由改变比如 colors, textures, opacity 等等这些数值在每帧都发给shader。</p>
<p>GL状态相关参数也可以随时改变depthTest, blending, polygonOffset 等)。</p>
<p>在运行时无法轻松更改以下属性一旦material被渲染了一次</p>
<ul>
<li>uniforms的数量和类型</li>
<li>是否存在
<ul>
<li>texture</li>
<li>fog</li>
<li>vertex colors</li>
<li>morphing</li>
<li>shadow map</li>
<li>alpha test</li>
</ul>
</li>
</ul>
<p>这些变化需要建立新的shader程序。你需要设置</p>
<code>material.needsUpdate = true</code>
<p>请记住这可能会非常缓慢并导致帧率的波动。特别是在Windows上因为shader编译在directx中比opengl慢</p>
<p>为了获得更流畅的体验,您可以通过“虚拟”值(如零强度光,白色纹理或零密度雾)在一定程度上模拟这些功能的变化。</p>
<p>您可以自由更改用于几何块的材质,但是无法更改对象如何划分为块(根据面材料)。</p>
<h3>如果你需要在运行时使用不同的材料配置:</h3>
<p>如果材料/块的数量很少,您可以事先预先划分物体(例如,人的头发/脸部/身体/上衣/裤子,汽车的前部/侧面/顶部/玻璃/轮胎/内部)。</p>
<p>如果数量很大(例如,每个面可能有所不同),请考虑不同的解决方案,例如使用属性/纹理来驱动不同的每个面部外观。</p>
<h3>例子</h3>
<p>
[example:webgl_materials_car WebGL / materials / car]<br />
[example:webgl_postprocessing_dof WebGL / webgl_postprocessing / dof]
</p>
</div>
<h2>纹理Textures</h2>
<div>
<p>如果更改了图像,画布,视频和数据纹理,则需要设置以下标志:</p>
<code>
texture.needsUpdate = true;
</code>
<p>渲染对象就会自动更新。</p>
<h3>例子</h3>
<p>
[example:webgl_materials_video WebGL / materials / video]<br />
[example:webgl_rtt WebGL / rtt]
</p>
</div>
<h2>相机Cameras</h2>
<div>
<p>相机的位置和目标会自动更新。 如果你需要改变</p>
<ul>
<li>
fov
</li>
<li>
aspect
</li>
<li>
near
</li>
<li>
far
</li>
</ul>
<p>
那么你需要重新计算投影矩阵:
</p>
<code>
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
</code>
</div>
</body>
</html>