-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy paththree.examples.note.js
1387 lines (1091 loc) · 49.7 KB
/
three.examples.note.js
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
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
getWorldDirection
Octree
collider: new THREE.Sphere(new THREE.Vector3(0, - 100, 0), SPHERE_RADIUS),
import { Capsule } from 'three/addons/math/Capsule.js';
function updateSpheres(deltaTime) {
spheres.forEach(sphere => {
sphere.collider.center.addScaledVector(sphere.velocity, deltaTime);
const result = worldOctree.sphereIntersect(sphere.collider);
if (result) {
sphere.velocity.addScaledVector(result.normal, - result.normal.dot(sphere.velocity) * 1.5);
sphere.collider.center.add(result.normal.multiplyScalar(result.depth));
} else {
sphere.velocity.y -= GRAVITY * deltaTime;
}
const damping = Math.exp(- 1.5 * deltaTime) - 1;
sphere.velocity.addScaledVector(sphere.velocity, damping);
playerSphereCollision(sphere);
});
spheresCollisions();
for (const sphere of spheres) {
sphere.mesh.position.copy(sphere.collider.center);
}
}
box.intersectsTriangle(triangle)
if (subTrees[i].box.intersectsTriangle(triangle)) {
subTrees[i].triangles.push(triangle);
}
sphere.intersectsPlane(_plane)
misc_animation_groups.html
const quaternionKF = new THREE.QuaternionKeyframeTrack('.quaternion', [0, 1, 2], [qInitial.x, qInitial.y, qInitial.z, qInitial.w, qFinal.x, qFinal.y, qFinal.z, qFinal.w, qInitial.x, qInitial.y, qInitial.z, qInitial.w]);
const colorKF = new THREE.ColorKeyframeTrack('.material.color', [0, 1, 2], [1, 0, 0, 0, 1, 0, 0, 0, 1], THREE.InterpolateDiscrete);
const opacityKF = new THREE.NumberKeyframeTrack('.material.opacity', [0, 1, 2], [1, 0, 1]);
misc_boxselection.html
框选
import { SelectionBox } from 'three/addons/interactive/SelectionBox.js';
import {
BufferAttribute,
BufferGeometry,
FramebufferTexture,
Frustum, LOD, Material, MeshLambertMaterial, ShaderMaterial,
} from 'three';
const _frustum = new Frustum();
if (frustum.containsPoint(_center)) {
this.collection.push(object);
}
misc_controls_arcball.html
misc_controls_pointerlock.html
fpv
function animate() {
requestAnimationFrame(animate);
const time = performance.now();
if (controls.isLocked === true) {
raycaster.ray.origin.copy(controls.getObject().position);
raycaster.ray.origin.y -= 10;
const intersections = raycaster.intersectObjects(objects, false);
const onObject = intersections.length > 0;
const delta = (time - prevTime) / 1000;
velocity.x -= velocity.x * 10.0 * delta;
velocity.z -= velocity.z * 10.0 * delta;
velocity.y -= 9.8 * 100.0 * delta; // 100.0 = mass
direction.z = Number(moveForward) - Number(moveBackward);
direction.x = Number(moveRight) - Number(moveLeft);
direction.normalize(); // this ensures consistent movements in all directions
if (moveForward || moveBackward) velocity.z -= direction.z * 400.0 * delta;
if (moveLeft || moveRight) velocity.x -= direction.x * 400.0 * delta;
if (onObject === true) {
velocity.y = Math.max(0, velocity.y);
canJump = true;
}
controls.moveRight(- velocity.x * delta);
controls.moveForward(- velocity.z * delta);
controls.getObject().position.y += (velocity.y * delta); // new behavior
if (controls.getObject().position.y < 10) {
velocity.y = 0;
controls.getObject().position.y = 10;
canJump = true;
}
}
prevTime = time;
renderer.render(scene, camera);
}
misc_controls_trackball.html
惯性可有
misc_controls_transform.html
位移工具
misc_lookat.html
lookat 用例
misc_uv_tests.html
uv用例
physics_ ***
物理效果
svg_ ***
SVGRenderer
webaudio
audioLoader
THREE.PositionalAudio(listener);
webgl_animation_ ***
const animations = gltf.animations;
mixer = new THREE.AnimationMixer(model);
idleAction = mixer.clipAction(animations[0]);
walkAction = mixer.clipAction(animations[3]);
runAction = mixer.clipAction(animations[1]);
actions = [idleAction, walkAction, runAction];
activateAllActions();
animate();
webgl_buffergeometry_compression.html
几何压缩
webgl_buffergeometry_custom_attributes_particles.html
webgl_buffergeometry_rawshader.html
自定义着色器
webgl_buffergeometry_glbufferattribute.html
// 操作gl buffer
const rgb = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, rgb);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
geometry.setAttribute('color', new THREE.GLBufferAttribute(rgb, gl.FLOAT, 3, 4, particles));
webgl_buffergeometry_indexed.html
indices
webgl_buffergeometry_instancing_billboards.html
// instance 的buffer geometry, 顶点一份,可以实例化多个,每个读取不同的translate attr
instanceBufferGeometry + InterleavedBufferAttribute
webgl_buffergeometry_instancing_interleaved.html
instanceBufferGeometry + InterleavedBufferAttribute
webgl_buffergeometry_instancing.html
// const geometry = new THREE.InstancedBufferGeometry();
geometry.instanceCount = instances;
对比instancemesh
webgl_instancing_ *.html
webgl_buffergeometry_lines_indexed.html
webgl_buffergeometry_lines.html
geometry.morphAttributes
// geometry.morphAttributes.position = [ morphTarget ];
webgl_buffergeometry_points_interleaved.html
InterleavedBuffer InterleavedBufferAttribute
webgl_buffergeometry_selective_draw.
// 设置attribute的visible,隐藏线段
geometry.attributes.visible.array
webgl_buffergeometry_uint.html
设置法向量
geometry.setAttribute('position', positionAttribute);
geometry.setAttribute('normal', normalAttribute);
geometry.setAttribute('color', colorAttribute);
webgl_camera_array.html
THREE.ArrayCamera(cameras);
webgl_camera_cinematic.html
webgl_camera_logarithmicdepthbuffer.html
renderer logarithmicDepthBuffer z取对数
webgl_clipping_advanced.html
Material.clippingPlanes
Material.clipShadows
Material.clipIntersection 显示被切的与物体的交集
**
webgl_clipping_stencil.html
stencil操作
Material.stencilWrite : Boolean
Material.stencilWriteMask : Integer
Material.stencilFunc : Integer
Material.stencilRef : Integer
Material.stencilFuncMask : Integer
Material.stencilFail : Integer
Material.stencilZFail : Integer
Material.stencilZPass : Integer
webgl_custom_attributes_ *
geometry.attributes
ShaderMaterial.uniforms
const material = new THREE.ShaderMaterial({
uniforms: {
color: { value: new THREE.Color(0xffffff) },
pointTexture: { value: new THREE.TextureLoader().load('textures/sprites/spark1.png') }
},
vertexShader: document.getElementById('vertexshader').textContent,
fragmentShader: document.getElementById('fragmentshader').textContent,
blending: THREE.AdditiveBlending,
depthTest: false,
transparent: true
});
webgl_depth_texture.html
Framebuffer
webgl_framebuffer_texture.html
FramebufferTexture // This class can only be used in combination with WebGLRenderer.copyFramebufferToTexture().
// render scene into target
renderer.setRenderTarget(target);
renderer.render(scene, camera);
// render post FX
postMaterial.uniforms.tDiffuse.value = target.texture;
postMaterial.uniforms.tDepth.value = target.depthTexture;
renderer.setRenderTarget(null);
renderer.render(postScene, postCamera);
controls.update(); // required because damping is enabled
stats.update();
webgl_furnace_test.html
MeshPhysicalMaterial.envMap
const material = new THREE.MeshPhysicalMaterial({
roughness: x / 10,
metalness: y / 10,
color: 0xffffff,
envMap: radianceMap,
envMapIntensity: 1,
transmission: 0,
ior: 1.5
});
function createEnvironment() {
const envScene = new THREE.Scene();
envScene.background = new THREE.Color(COLOR);
const pmremGenerator = new THREE.PMREMGenerator(renderer);
radianceMap = pmremGenerator.fromScene(envScene).texture;
pmremGenerator.dispose();
scene.background = envScene.background;
}
webgl_geometries.html
各种THREE的geometries
webgl_geometries_parametric.html
ParametricGeometries
ParametricGeometry
webgl_geometry_colors_lookuptable.html
lut color
webgl_geometry_convex.html
ConvexGeometry
webgl_geometry_dynamic.html
水体
海面
起伏
webgl_gpgpu_water.html
webgl_geometry_shapes.html
webgl_geometry_extrude_shapes.html
挤出
const closedSpline = new THREE.CatmullRomCurve3([
new THREE.Vector3(- 60, - 100, 60),
new THREE.Vector3(- 60, 20, 60),
new THREE.Vector3(- 60, 120, 60),
new THREE.Vector3(60, 20, - 60),
new THREE.Vector3(60, - 100, - 60)
]);
const extrudeSettings1 = {
steps: 100,
bevelEnabled: false,
extrudePath: closedSpline
};
const pts1 = [], count = 3;
for (let i = 0; i < count; i++) {
const l = 20;
const a = 2 * i / count * Math.PI;
pts1.push(new THREE.Vector2(Math.cos(a) * l, Math.sin(a) * l));
}
const shape1 = new THREE.Shape(pts1);
const geometry1 = new THREE.ExtrudeGeometry(shape1, extrudeSettings1);
const material1 = new THREE.MeshLambertMaterial({ color: 0xb00000, wireframe: false });
const mesh1 = new THREE.Mesh(geometry1, material1);
THREE.MathUtils.randFloat
webgl_geometry_nurbs.html
NURBSCurve
NURBSSurface
ParametricGeometry
webgl_geometry_spline_editor.html
spline edit
webgl_geometry_teapot.html
texture
reflection
map
envMap
webgl_geometry_terrain.html
webgl_geometry_terrain_raycast.html
地形
随机地形
非camera的lookat
function generateHeight(width, height) {
const size = width * height, data = new Uint8Array(size),
perlin = new ImprovedNoise(), z = Math.random() * 100;
let quality = 1;
for (let j = 0; j < 4; j++) {
for (let i = 0; i < size; i++) {
const x = i % width, y = ~ ~(i / width);
data[i] += Math.abs(perlin.noise(x / quality, y / quality, z) * quality * 1.75);
}
quality *= 5;
}
return data;
}
webgl_geometry_terrain.html
随机色背景
webgl_geometry_text_ **.html
文字
webgl_gpgpu_birds.html
webgl_gpgpu_birds_gltf.html
鸟群
计算着色器
webgl_gpgpu_ *.html
GPUComputationRenderer
webgl_helpers.html
GridHelper
PolarGridHelper
webgl_instancing_ *
instance mesh
webgl_instancing_performance.html
instance 与 merge 性能对比(fps,显存,内存,cpu)
geometry merge
BufferGeometryUtils.mergeGeometries
webgl_instancing_raycast.html
instance mesh 的射线检测
const intersection = raycaster.intersectObject(mesh);
if (intersection.length > 0) {
const instanceId = intersection[0].instanceId;
mesh.getColorAt(instanceId, color);
if (color.equals(white)) {
mesh.setColorAt(instanceId, color.setHex(Math.random() * 0xffffff));
mesh.instanceColor.needsUpdate = true;
}
}
webgl_layers.html
图层
const layer = (i % 3);
const object = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({ color: colors[layer] }));
object.layers.set(layer);
webgl_lensflares.html
FlyControls
太阳光效果
粒子效果
import { Lensflare, LensflareElement } from 'three/addons/objects/Lensflare.js';
const textureFlare0 = textureLoader.load('textures/lensflare/lensflare0.png');
const textureFlare3 = textureLoader.load('textures/lensflare/lensflare3.png');
addLight(0.55, 0.9, 0.5, 5000, 0, - 1000);
addLight(0.08, 0.8, 0.5, 0, 0, - 1000);
addLight(0.995, 0.5, 0.9, 5000, 5000, - 1000);
function addLight(h, s, l, x, y, z) {
const light = new THREE.PointLight(0xffffff, 1.5, 2000, 0);
light.color.setHSL(h, s, l);
light.position.set(x, y, z);
scene.add(light);
const lensflare = new Lensflare();
lensflare.addElement(new LensflareElement(textureFlare0, 700, 0, light.color));
lensflare.addElement(new LensflareElement(textureFlare3, 60, 0.6));
lensflare.addElement(new LensflareElement(textureFlare3, 70, 0.7));
lensflare.addElement(new LensflareElement(textureFlare3, 120, 0.9));
lensflare.addElement(new LensflareElement(textureFlare3, 70, 1));
light.add(lensflare);
}
webgl_lightprobe.html
webgl_lightprobe_cubecamera.html
反射效果
CubeCamera
import { LightProbeHelper } from 'three/addons/helpers/LightProbeHelper.js';
import { LightProbeGenerator } from 'three/addons/lights/LightProbeGenerator.js';
import { text } from 'stream/consumers';
webgl_lights_hemisphere.html
HemisphereLight
shader天空盒
const skyGeo = new THREE.SphereGeometry(4000, 32, 15);
const skyMat = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.BackSide
});
gltf动画
AnimationMixer
loader.load('models/gltf/Flamingo.glb', function (gltf) {
const mesh = gltf.scene.children[0];
const s = 0.35;
mesh.scale.set(s, s, s);
mesh.position.y = 15;
mesh.rotation.y = - 1;
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add(mesh);
const mixer = new THREE.AnimationMixer(mesh);
mixer.clipAction(gltf.animations[0]).setDuration(1).play();
mixers.push(mixer);
});
webgl_lights_physical.html
灯光效果
webgl_lights_rectarealight.html
RectAreaLightHelper
RectAreaLightUniformsLib
webgl_lights_spotlight.html
点光源
点光源设置map
spotLight = new THREE.SpotLight(0xffffff, 100);
spotLight.position.set(2.5, 5, 2.5);
spotLight.angle = Math.PI / 6;
spotLight.penumbra = 1;
spotLight.decay = 2;
spotLight.distance = 0;
spotLight.map = textures['disturb.jpg'];
webgl_lights_spotlights.html
TWEEN
SpotLightHelper spotlight的外轮廓
function tween(light) {
new TWEEN.Tween(light).to({
angle: (Math.random() * 0.7) + 0.1,
penumbra: Math.random() + 1
}, Math.random() * 3000 + 2000)
.easing(TWEEN.Easing.Quadratic.Out).start();
new TWEEN.Tween(light.position).to({
x: (Math.random() * 3) - 1.5,
y: (Math.random() * 1) + 1.5,
z: (Math.random() * 3) - 1.5
}, Math.random() * 3000 + 2000)
.easing(TWEEN.Easing.Quadratic.Out).start();
}
webgl_lines_ **.html
webgl_loader_fbx.html
fbx 动画
loader.load('models/fbx/Samba Dancing.fbx', function (object) {
mixer = new THREE.AnimationMixer(object);
const action = mixer.clipAction(object.animations[0]);
action.play();
});
function animate() {
const delta = clock.getDelta();
if (mixer) mixer.update(delta);
renderer.render(scene, camera);
}
webgl_loader_gltf_instancing.html
hdr loader
hdr天空盒
gltf instance
new RGBELoader()
.setPath('textures/equirectangular/')
.load('royal_esplanade_1k.hdr', function (texture) {
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.background = texture;
scene.environment = texture;
const loader = new GLTFLoader().setPath('models/gltf/DamagedHelmet/glTF-instancing/');
loader.load('DamagedHelmetGpuInstancing.gltf', function (gltf) {
scene.add(gltf.scene);
render();
});
});
webgl_loader_gltf_iridescence.html
环境反射
scene.environment = texture;
webgl_loader_gltf_lights.html
环境反射
自发光
webgl_loader_gltf_sheen.html
renderer.toneMapping
renderer.toneMappingExposure
material.sheen
光泽
webgl_loader_gltf_transmission.html
renderer.setAnimationLoop
webgl_loader_gltf_variants.html
gltf variant 切换
webgl_loader_imagebitmap.html
ImageBitmapLoader
webgl_loader_ldraw.html
乐高
ldraw
building step
4dbim
webgl_loader_pcd.html
点云
PCDLoader
webgl_loader_pdb.html
.pdb文件
Protein Data Bank
webgl_loader_stl.html
webgl_loader_ply.html
DirectionalLight.castShadow
DirectionalLight.shadow.camera
DirectionalLight.shadow.mapSize
射灯产生阴影选项
If set to true light will cast dynamic shadows.Warning: This is expensive and requires tweaking to get shadows looking right.
webgl_loader_svg.html
svg loader
材质:
DDSLoader
webgl_loader_texture_dds.html
EXRLoader
webgl_loader_texture_exr.html
RGBELoader
webgl_loader_texture_hdr.html
材质曝光
renderer.toneMapping = THREE.ReinhardToneMapping;
renderer.toneMappingExposure = params.exposure;
KTXLoader
webgl_loader_texture_ktx.html
KTX2Loader
webgl_loader_texture_ktx2.html
不同的材质压缩
LogLuvLoader
webgl_loader_texture_logluv.html
webgl_loader_texture_lottie.html
场景的环境贴图
scene.environment
Sets the environment map for all physical materials in the scene.However, it's not possible to overwrite an existing texture assigned to MeshStandardMaterial.envMap.
RoundedBoxGeometry
PMREMGenerator
预过滤的 Mipmapped 辐射环境贴图
Prefiltered, Mipmapped Radiance Environment Map(PMREM)
const environment = new RoomEnvironment(renderer);
const pmremGenerator = new THREE.PMREMGenerator(renderer);
scene.environment = pmremGenerator.fromScene(environment).texture;
Lottie 是一个应用十分广泛动画库,适用于Android、iOS、Web、ReactNative、Windows的库,它解析了用Bodymovin导出为json的Adobe After Effects动画,并在移动和网络上进行了原生渲染。其和 GSAP 这类专注动画曲线、插值等js动画库不同,它本质上是一套跨平台的平面动画解决方案。其提供了一套完整得从AE到各个终端的工具流,通过AE的插件将设计师做的动画导出成一套定义好的json文件,之后再通过渲染器进行渲染,它提供了“SVG”、“Canvas”和“HTML”三种渲染模式,最常用的是第一种和第二种。
webgl_loader_texture_pvrtc.html
pvr
webgl_loader_texture_rgbm.html
rgbm
webgl_loader_texture_rgbm.html
tga
webgl_loader_texture_tiff.html
tiff
webgl_loader_ttf.html
text
webgl_loader_vox.html
VOXLoader, VOXMesh
webgl_lod.html
LOD
webgl_marchingcubes.html
ToonShader
ToonShader1, ToonShader2, ToonShaderHatching, ToonShaderDotted
各种 Material
material.envMap
material.metalness
material.roughness
material.shininess
MarchingCubes
水滴效果
webgl_materials_alphahash.html
composer
pass
TAARenderPass
IcosahedronGeometry
material.alphaHash
Enables alpha hashed transparency, an alternative to.transparent or.alphaTest.The material will not be rendered if opacity is lower than a random threshold.
webgl_materials_blending_custom.html
material.blending
material.blendSrc
material.blendDst
material.blendEquation
webgl_materials_bumpmap.html
material.bumpMap
webgl_materials_car.html
RGBELoader
scene.environment
scene.environment = new RGBELoader().load('textures/equirectangular/venice_sunset_1k.hdr');
OrbitControls
controls.maxDistance
webgl_materials_channels.html
VelocityShader
material.aoMap,
material.normalMap,
material.displacementMap,
displacementScale: SCALE,
displacementBias: BIAS,
MeshDepthMaterial
VelocityShader
webgl_materials_cubemap_dynamic.html
material.envMap
material.roughness
material.metalness
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.background = texture;
scene.environment = texture; // Sets the environment map for all physical materials in the scene.
webgl_materials_cubemap_mipmaps.html
CubeTextureLoader
customizedCubeTexture.mipmaps = mipmaps; // Array of user-specified mipmaps (optional).
for (let level = 0; level <= maxLevel; ++level) {
const urls = [];
for (let face = 0; face < 6; ++face) {
urls.push(path + 'cube_m0' + level + '_c0' + face + format);
}
const mipmapLevel = level;
pendings.push(loadCubeTexture(urls).then(function (cubeTexture) {
mipmaps[mipmapLevel] = cubeTexture;
}));
}
// mipmap 与纹理过滤
// https://blog.csdn.net/qq_42428486/article/details/118856697
1.最近过滤,选最近的像素
2.线性过滤 计算一个插值
// mipmap 多级渐远纹理
越远的物体纹理分辨率越低,过滤更准确
webgl_materials_cubemap_refraction.html
geometry.computeVertexNormals();
// Computes vertex normals for the given vertex data.For indexed geometries, the method sets each vertex normal to be the average of the face normals of the faces that share that vertex.
// For non - indexed geometries, vertices are not shared, and the method sets each vertex normal to be the same as the face normal.
texture.mapping // How the image is applied to the object.
textureCube.mapping = THREE.CubeRefractionMapping;
// CubeReflectionMapping and CubeRefractionMapping are for use with a CubeTexture, which is made up of six textures, one for each face of the cube
// CubeReflectionMapping is the default for a CubeTexture.
// Mapping Modes
// THREE.UVMapping
// THREE.CubeReflectionMapping
// THREE.CubeRefractionMapping
// THREE.EquirectangularReflectionMapping
// THREE.EquirectangularRefractionMapping
// THREE.CubeUVReflectionMapping
webgl_materials_cubemap_render_to_mipmaps.html
WebGLCubeRenderTarget
着色器里配置mipmap
// 生成mipmap
const mesh = new THREE.Mesh(geometry, material);
const cubeCamera = new THREE.CubeCamera(1, 10, cubeMapRenderTarget);
const mipmapCount = Math.floor(Math.log2(Math.max(cubeMapRenderTarget.width, cubeMapRenderTarget.height)));
for (let mipmap = 0; mipmap < mipmapCount; mipmap++) {
material.uniforms.mipIndex.value = mipmap;
material.needsUpdate = true;
cubeMapRenderTarget.viewport.set(0, 0, cubeMapRenderTarget.width >> mipmap, cubeMapRenderTarget.height >> mipmap);
cubeCamera.activeMipmapLevel = mipmap;
cubeCamera.update(renderer, mesh);
}
fragmentShader: /* glsl */ `
uniform samplerCube cubeTexture;
varying vec3 vWorldDirection;
uniform float mipIndex;
#include <common>
void main() {
vec3 cubeCoordinates = normalize(vWorldDirection);
// Colorize mip levels
vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
if (mipIndex == 0.0) color.rgb = vec3(1.0, 1.0, 1.0);
else if (mipIndex == 1.0) color.rgb = vec3(0.0, 0.0, 1.0);
else if (mipIndex == 2.0) color.rgb = vec3(0.0, 1.0, 1.0);
else if (mipIndex == 3.0) color.rgb = vec3(0.0, 1.0, 0.0);
else if (mipIndex == 4.0) color.rgb = vec3(1.0, 1.0, 0.0);
gl_FragColor = textureCube(cubeTexture, cubeCoordinates, 0.0) * color;
}
`
const material = new THREE.ShaderMaterial({
name: 'FilterCubemap',
uniforms: THREE.UniformsUtils.clone(CubemapFilterShader.uniforms),
vertexShader: CubemapFilterShader.vertexShader,
fragmentShader: CubemapFilterShader.fragmentShader,
side: THREE.BackSide,
blending: THREE.NoBlending,
});
material.uniforms.cubeTexture.value = sourceCubeTexture;
// 根据mipmap和当前的环境进行渲染
const mesh = new THREE.Mesh(geometry, material);
const cubeCamera = new THREE.CubeCamera(1, 10, cubeMapRenderTarget);
const mipmapCount = Math.floor(Math.log2(Math.max(cubeMapRenderTarget.width, cubeMapRenderTarget.height)));
for (let mipmap = 0; mipmap < mipmapCount; mipmap++) {
material.uniforms.mipIndex.value = mipmap;
material.needsUpdate = true;
cubeMapRenderTarget.viewport.set(0, 0, cubeMapRenderTarget.width >> mipmap, cubeMapRenderTarget.height >> mipmap);
cubeCamera.activeMipmapLevel = mipmap;
cubeCamera.update(renderer, mesh);
}
webgl_materials_cubemap.html
CubeTextureLoader
CubeRefractionMapping
MeshLambertMaterial.combine // How to combine the result of the surface's color with the environment map, if any.
MeshLambertMaterial.reflectivity
webgl_materials_curvature.html
curvature 曲率
concave 凹
convex 凸
根据曲率 凹面着色 凸面着色 等高线 heatmap
geometry.attributes.normal //法向量
//filter the curvature array to only show concave values
function filterConcave(curvature) {
for (let i = 0; i < curvature.length; i++) {
curvature[i] = Math.abs(clamp(curvature[i], - 1, 0));
}
}
//filter the curvature array to only show convex values
function filterConvex(curvature) {
for (let i = 0; i < curvature.length; i++) {
curvature[i] = clamp(curvature[i], 0, 1);
}
}
<script id="vertexShaderRaw" type="x-shader/x-vertex">
attribute float curvature;
varying float vCurvature;
void main() {
vec3 p = position;
vec4 modelViewPosition = modelViewMatrix * vec4( p , 1.0 );
gl_Position = projectionMatrix * modelViewPosition;
vCurvature = curvature;
}
</script>
<script id="fragmentShaderRaw" type="x-shader/x-fragment">
varying vec3 vViewPosition;
varying float vCurvature;
void main() {
gl_FragColor = vec4( vCurvature * 2.0, 0.0, 0.0, 1.0 );
}
</script>
webgl_materials_displacementmap.html
材质参数
material.displacementMap
// (置换贴图,也叫移位贴图)可以改变模型对象的几何形状,因此在提供最真实的效果的同时也会大幅增加渲染性能的开销。
// The displacement map affects the position of the mesh's vertices.
// Unlike other maps which only affect the light and shade of the material the displaced vertices can cast shadows, block other objects, and otherwise act as real geometry. The displacement texture is an image where the value of each pixel (white being the highest) is mapped against, and repositions, the vertices of the mesh.
webgl_materials_envmaps_exr.html
EXRLoader
EXR视差贴图模型
PMREMGenerator
EquirectangularReflectionMapping
texture.mapping = THREE.EquirectangularReflectionMapping;
new EXRLoader().load('textures/piz_compressed.exr', function (texture) {
texture.mapping = THREE.EquirectangularReflectionMapping;
exrCubeRenderTarget = pmremGenerator.fromEquirectangular(texture);
exrBackground = texture;
});
new THREE.TextureLoader().load('textures/equirectangular.png', function (texture) {
texture.mapping = THREE.EquirectangularReflectionMapping;
texture.colorSpace = THREE.SRGBColorSpace;
pngCubeRenderTarget = pmremGenerator.fromEquirectangular(texture);
pngBackground = texture;
});
const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
// This class generates a Prefiltered, Mipmapped Radiance Environment Map (PMREM) from a cubeMap environment texture.
// This allows different levels of blur to be quickly accessed based on material roughness.
// Unlike a traditional mipmap chain, it only goes down to the LOD_MIN level (above), and then creates extra even more filtered 'mips' at the same LOD_MIN resolution, associated with higher roughness levels. In this way we maintain resolution
webgl_materials_envmaps_groundprojected.html
GroundProjectedSkybox
天空盒和地形混合体
webgl_materials_envmaps_hdr.html
HDRCubeTextureLoader
HDR envmap
LDR envmap
RGBM envmap
HDR high dynamic Range
RGBMLoader
PMREMGenerator
DebugEnvironment
const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileCubemapShader();
const hdrUrls = ['px.hdr', 'nx.hdr', 'py.hdr', 'ny.hdr', 'pz.hdr', 'nz.hdr'];
hdrCubeMap = new HDRCubeTextureLoader()
.setPath('./textures/cube/pisaHDR/')
.load(hdrUrls, function () {
hdrCubeRenderTarget = pmremGenerator.fromCubemap(hdrCubeMap);
hdrCubeMap.magFilter = THREE.LinearFilter;
hdrCubeMap.needsUpdate = true;
});
const ldrUrls = ['px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png'];
ldrCubeMap = new THREE.CubeTextureLoader()
.setPath('./textures/cube/pisa/')
.load(ldrUrls, function () {
ldrCubeRenderTarget = pmremGenerator.fromCubemap(ldrCubeMap);
});
const rgbmUrls = ['px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png'];
rgbmCubeMap = new RGBMLoader().setMaxRange(16)
.setPath('./textures/cube/pisaRGBM16/')
.loadCubemap(rgbmUrls, function () {
rgbmCubeRenderTarget = pmremGenerator.fromCubemap(rgbmCubeMap);
});
const envScene = new DebugEnvironment();
generatedCubeRenderTarget = pmremGenerator.fromScene(envScene);
switch (params.envMap) {
case 'Generated':
renderTarget = generatedCubeRenderTarget; // debug env
cubeMap = generatedCubeRenderTarget.texture;
break;
case 'LDR':
renderTarget = ldrCubeRenderTarget;
cubeMap = ldrCubeMap;
break;
case 'HDR':
renderTarget = hdrCubeRenderTarget;
cubeMap = hdrCubeMap;
break;
case 'RGBM16':
renderTarget = rgbmCubeRenderTarget;
cubeMap = rgbmCubeMap;
break;
}