1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<base href="../../../" />
<script src="list.js"></script>
<script src="page.js"></script>
<link type="text/css" rel="stylesheet" href="page.css" />
</head>
<body>
<h1>[name]</h1>
<div>
<p>All objects by default automatically update their matrices if they have been added to the scene with</p>
<code>
var object = new THREE.Object3D();
scene.add( object );
</code>
or if they are the child of another object that has been added to the scene:
<code>
var object1 = new THREE.Object3D();
var object2 = new THREE.Object3D();
object1.add( object2 );
scene.add( object1 ); //object1 and object2 will automatically update their matrices
</code>
</div>
<p>However, if you know object will be static, you can disable this and update the transform matrix manually just when needed.</p>
<code>
object.matrixAutoUpdate = false;
object.updateMatrix();
</code>
<h2>Geometries</h2>
<div>
<h3>[page:BufferGeometry]</h3>
<div>
<p>
BufferGeometries store information (such as vertex positions, face indices, normals, colors,
UVs, and any custom attributes) in [page:BufferAttribute buffers] - that is,
[link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays typed arrays].
This makes them generally faster than standard Geometries, at the cost of being somewhat harder to
work with.
</p>
<p>
With regards to updating BufferGeometries, the most important thing to understand is that
you cannot resize buffers (this is very costly, basically the equivalent to creating a new geometry).
You can however update the content of buffers.
</p>
<p>
This means that if you know an attribute of your BufferGeometry will grow, say the number of vertices,
you must pre-allocate a buffer large enough to hold any new vertices that may be created. Of
course, this also means that there will be a maximum size for your BufferGeometry - there is
no way to create a BufferGeometry that can efficiently be extended indefinitely.
</p>
<p>
We'll use the example of a line that gets extended at render time. We'll allocate space
in the buffer for 500 vertices but draw only two at first, using [page:BufferGeometry.drawRange].
</p>
<code>
var MAX_POINTS = 500;
// geometry
var geometry = new THREE.BufferGeometry();
// attributes
var positions = new Float32Array( MAX_POINTS * 3 ); // 3 vertices per point
geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
// draw range
var drawCount = 2; // draw the first 2 points, only
geometry.setDrawRange( 0, drawCount );
// material
var material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
// line
var line = new THREE.Line( geometry, material );
scene.add( line );
</code>
<p>
Next we'll randomly add points to the line using a pattern like:
</p>
<code>
var positions = line.geometry.attributes.position.array;
var x, y, z, index;
x = y = z = index = 0;
for ( var 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>
If you want to change the <em>number of points</em> rendered after the first render, do this:
</p>
<code>
line.geometry.setDrawRange( 0, newValue );
</code>
<p>
If you want to change the position data values after the first render, you need to
set the needsUpdate flag like so:
</p>
<code>
line.geometry.attributes.position.needsUpdate = true; // required after the first render
</code>
<p>
If you change the position data values after the initial render, you may need to
call `.computeBoundingSphere()` in order to recalculate the geometry's bounding sphere.
</p>
<code>
line.geometry.computeBoundingSphere();
</code>
<p>
[link:http://jsfiddle.net/w67tzfhx/ Here is a fiddle] showing an animated line which you can adapt to your use case.
</p>
<h3>Examples:</h3>
[example:webgl_custom_attributes WebGL / custom / attributes]<br />
[example:webgl_buffergeometry_custom_attributes_particles WebGL / buffergeometry / custom / attributes / particles]
</div>
<h3>[page:Geometry]</h3>
<div>
<p>
The following flags control updating of various geometry attributes. Set flags only
for attributes that you need to update, updates are costly. Once buffers
change, these flags reset automatically back to false. You need to keep setting them to
true if you want to keep updating buffers. Note that this applies only to [page:Geometry]
and not to [page:BufferGeometry].
</p>
<code>
var geometry = new THREE.Geometry();
geometry.verticesNeedUpdate = true;
geometry.elementsNeedUpdate = true;
geometry.morphTargetsNeedUpdate = true;
geometry.uvsNeedUpdate = true;
geometry.normalsNeedUpdate = true;
geometry.colorsNeedUpdate = true;
geometry.tangentsNeedUpdate = true;
</code>
<p>
In versions prior to [link:https://github.com/mrdoob/three.js/releases/tag/r66 r66] meshes
additionally need the <em>dynamic</em> flag enabled (to keep internal typed arrays):
</p>
<code>
//removed after r66
geometry.dynamic = true;
</code>
<h3>Examples:</h3>
[example:webgl_geometry_dynamic WebGL / geometry / dynamic]<br />
</div>
</div>
<h2>Materials</h2>
<div>
<p>All uniforms values can be changed freely (e.g. colors, textures, opacity, etc), values are sent to the shader every frame.</p>
<p>Also GLstate related parameters can change any time (depthTest, blending, polygonOffset, etc).</p>
<p>The following properties can't be easily changed at runtime (once the material is rendered at least once):</p>
<ul>
<li>numbers and types of uniforms</li>
<li>presence or not of
<ul>
<li>texture</li>
<li>fog</li>
<li>vertex colors</li>
<li>skinning</li>
<li>morphing</li>
<li>shadow map</li>
<li>alpha test</li>
</ul>
</li>
</ul>
<p>Changes in these require building of new shader program. You'll need to set</p>
<code>material.needsUpdate = true</code>
<p>Bear in mind this might be quite slow and induce jerkiness in framerate (especially on Windows, as shader compilation is slower in DirectX than OpenGL).</p>
<p>For smoother experience you can emulate changes in these features to some degree by having "dummy" values like zero intensity lights, white textures, or zero density fog.</p>
<p>You can freely change the material used for geometry chunks, however you cannot change how an object is divided into chunks (according to face materials). </p>
<h3>If you need to have different configurations of materials during runtime:</h3>
<p>If the number of materials / chunks is small, you could pre-divide the object beforehand (e.g. hair / face / body / upper clothes / trousers for a human, front / sides / top / glass / tire / interior for a car). </p>
<p>If the number is large (e.g. each face could be potentially different), consider a different solution, such as using attributes / textures to drive different per-face look.</p>
<h3>Examples:</h3>
[example:webgl_materials_cars WebGL / materials / cars]<br />
[example:webgl_postprocessing_dof WebGL / webgl_postprocessing / dof]
</div>
<h2>Textures</h2>
<div>
<p>Image, canvas, video and data textures need to have the following flag set if they are changed:</p>
<code>
texture.needsUpdate = true;
</code>
<p>Render targets update automatically.</p>
<h3>Examples:</h3>
[example:webgl_materials_video WebGL / materials / video]<br />
[example:webgl_rtt WebGL / rtt]
</div>
<h2>Cameras</h2>
<div>
<p>A camera's position and target is updated automatically. If you need to change</p>
<ul>
<li>
fov
</li>
<li>
aspect
</li>
<li>
near
</li>
<li>
far
</li>
</ul>
<p>
then you'll need to recompute the projection matrix:
</p>
<code>
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
</code>
</div>
</body>
</html>
|