├── screenshot01.png
├── screenshot02.png
├── screenshot03.png
├── screenshot04.png
├── screenshot05.png
├── screenshot06.png
├── src
├── textures
│ ├── water
│ │ ├── Water_002_OCC.jpg
│ │ ├── Water_002_COLOR.jpg
│ │ ├── Water_002_DISP.png
│ │ ├── Water_002_NORM.jpg
│ │ └── Water_002_ROUGH.jpg
│ ├── slime
│ │ ├── alien-slime1-ao.png
│ │ ├── alien-slime1-albedo.png
│ │ ├── alien-slime1-height.png
│ │ ├── alien-slime1-metallic.png
│ │ ├── alien-slime1-normal-ogl.png
│ │ └── alien-slime1-roughness.png
│ └── soil
│ │ ├── Rock_Moss_001_height.png
│ │ ├── Rock_Moss_001_normal.jpg
│ │ ├── Rock_Moss_001_basecolor.jpg
│ │ ├── Rock_Moss_001_roughness.jpg
│ │ └── Rock_Moss_001_ambientOcclusion.jpg
├── index.html
├── index.ts
├── sine_wave_plane.ts
├── sine_cos_wave_plane.ts
├── sine_cos_slime_wave_plane.ts
├── sine_cos_water_wave_plane.ts
├── sphere_with_waves.ts
└── terrain_editor.ts
├── .gitignore
├── tsconfig.json
├── webpack.config.js
├── package.json
├── LICENSE
└── README.md
/screenshot01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/screenshot01.png
--------------------------------------------------------------------------------
/screenshot02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/screenshot02.png
--------------------------------------------------------------------------------
/screenshot03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/screenshot03.png
--------------------------------------------------------------------------------
/screenshot04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/screenshot04.png
--------------------------------------------------------------------------------
/screenshot05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/screenshot05.png
--------------------------------------------------------------------------------
/screenshot06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/screenshot06.png
--------------------------------------------------------------------------------
/src/textures/water/Water_002_OCC.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/water/Water_002_OCC.jpg
--------------------------------------------------------------------------------
/src/textures/slime/alien-slime1-ao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/slime/alien-slime1-ao.png
--------------------------------------------------------------------------------
/src/textures/water/Water_002_COLOR.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/water/Water_002_COLOR.jpg
--------------------------------------------------------------------------------
/src/textures/water/Water_002_DISP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/water/Water_002_DISP.png
--------------------------------------------------------------------------------
/src/textures/water/Water_002_NORM.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/water/Water_002_NORM.jpg
--------------------------------------------------------------------------------
/src/textures/water/Water_002_ROUGH.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/water/Water_002_ROUGH.jpg
--------------------------------------------------------------------------------
/src/textures/slime/alien-slime1-albedo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/slime/alien-slime1-albedo.png
--------------------------------------------------------------------------------
/src/textures/slime/alien-slime1-height.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/slime/alien-slime1-height.png
--------------------------------------------------------------------------------
/src/textures/soil/Rock_Moss_001_height.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/soil/Rock_Moss_001_height.png
--------------------------------------------------------------------------------
/src/textures/soil/Rock_Moss_001_normal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/soil/Rock_Moss_001_normal.jpg
--------------------------------------------------------------------------------
/src/textures/slime/alien-slime1-metallic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/slime/alien-slime1-metallic.png
--------------------------------------------------------------------------------
/src/textures/slime/alien-slime1-normal-ogl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/slime/alien-slime1-normal-ogl.png
--------------------------------------------------------------------------------
/src/textures/slime/alien-slime1-roughness.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/slime/alien-slime1-roughness.png
--------------------------------------------------------------------------------
/src/textures/soil/Rock_Moss_001_basecolor.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/soil/Rock_Moss_001_basecolor.jpg
--------------------------------------------------------------------------------
/src/textures/soil/Rock_Moss_001_roughness.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/soil/Rock_Moss_001_roughness.jpg
--------------------------------------------------------------------------------
/src/textures/soil/Rock_Moss_001_ambientOcclusion.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamani-coding/threejs-buffergeometry-examples/HEAD/src/textures/soil/Rock_Moss_001_ambientOcclusion.jpg
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .cache/
3 | coverage/
4 | dist/*
5 | !dist/index.html
6 | node_modules/
7 | *.log
8 |
9 | # OS generated files
10 | .DS_Store
11 | .DS_Store?
12 | ._*
13 | .Spotlight-V100
14 | .Trashes
15 | ehthumbs.db
16 | Thumbs.db
17 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "./dist/",
4 | "sourceMap": true,
5 | "noImplicitAny": true,
6 | "module": "CommonJS",
7 | "target": "es5",
8 | "allowJs": true
9 | }
10 | }
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | three.js example
6 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { sine_cos_slime_wave_plane } from "./sine_cos_slime_wave_plane";
2 | import { sine_cos_water_wave_plane } from "./sine_cos_water_wave_plane";
3 | import { sine_cos_wave_plane } from "./sine_cos_wave_plane";
4 | import { sine_wave_plane } from "./sine_wave_plane";
5 | import { sphere_with_waves } from "./sphere_with_waves";
6 | import { terrain_editor } from "./terrain_editor";
7 |
8 | // sine_wave_plane();
9 | // sine_cos_wave_plane();
10 | // sine_cos_slime_wave_plane();
11 | // sine_cos_water_wave_plane();
12 | // sphere_with_waves();
13 | terrain_editor();
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const src = path.resolve(__dirname, 'src');
4 |
5 | module.exports = {
6 | mode: 'development',
7 | entry: './src/index.ts',
8 | devtool: 'inline-source-map',
9 | module: {
10 | rules: [
11 | {
12 | test: /\.tsx?$/,
13 | use: 'ts-loader',
14 | exclude: /node_modules/
15 | }
16 | ]
17 | },
18 | resolve: {
19 | extensions: ['.tsx', '.ts', '.js']
20 | },
21 | output: {
22 | filename: 'index.js',
23 | path: src
24 | },
25 | devServer: {
26 | static: src,
27 | },
28 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "threejs-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "npm run build && npm run serve",
8 | "build": "webpack",
9 | "serve": "webpack serve"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "npm-run-all": "^4.1.5",
16 | "ts-loader": "^8.1.0",
17 | "typescript": "^4.2.3",
18 | "webpack": "^5.89.0",
19 | "webpack-cli": "^5.1.4",
20 | "webpack-dev-server": "^4.15.1"
21 | },
22 | "dependencies": {
23 | "@types/three": "^0.131.0",
24 | "three": "^0.132.2"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 tamani-coding
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # threejs-buffergeometry-examples
2 | threejs-buffergeometry-examples
3 |
4 | `npm install` and `npm run start`
5 |
6 | Try the [Stackblitz](https://stackblitz.com/github/tamani-coding/threejs-buffergeometry-examples)
7 |
8 | Go to index.ts and uncomment the example which you want to run.
9 |
10 | ## textures
11 |
12 | https://freepbr.com/c/organic/
13 |
14 | https://3dtextures.me/
15 |
16 | ## screenshots
17 |
18 | 
19 | 
20 | 
21 | 
22 | 
23 | 
24 |
--------------------------------------------------------------------------------
/src/sine_wave_plane.ts:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
3 |
4 | export function sine_wave_plane() {
5 | // SCENE
6 | const scene = new THREE.Scene();
7 | scene.background = new THREE.Color(0xa8def0);
8 |
9 | // CAMERA
10 | const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
11 | camera.position.y = 5;
12 |
13 | // RENDERER
14 | const renderer = new THREE.WebGLRenderer({ antialias: true });
15 | renderer.setSize(window.innerWidth, window.innerHeight);
16 | renderer.setPixelRatio(window.devicePixelRatio);
17 | renderer.shadowMap.enabled = true
18 |
19 | // CONTROLS
20 | const controls = new OrbitControls(camera, renderer.domElement);
21 | controls.target = new THREE.Vector3(0, 0, -40);
22 | controls.update();
23 |
24 | // AMBIENT LIGHT
25 | scene.add(new THREE.AmbientLight(0xffffff, 0.5));
26 | // DIRECTIONAL LIGHT
27 | const dirLight = new THREE.DirectionalLight(0xffffff, 1.0)
28 | dirLight.position.x += 20
29 | dirLight.position.y += 20
30 | dirLight.position.z += 20
31 | dirLight.castShadow = true
32 | dirLight.shadow.mapSize.width = 4096;
33 | dirLight.shadow.mapSize.height = 4096;
34 | const d = 25;
35 | dirLight.shadow.camera.left = - d;
36 | dirLight.shadow.camera.right = d;
37 | dirLight.shadow.camera.top = d;
38 | dirLight.shadow.camera.bottom = - d;
39 | dirLight.position.z = -30;
40 |
41 | let target = new THREE.Object3D();
42 | target.position.z = -30;
43 | dirLight.target = target;
44 | dirLight.target.updateMatrixWorld();
45 |
46 | dirLight.shadow.camera.lookAt(0, 0, -30);
47 | scene.add(dirLight);
48 | // scene.add( new THREE.CameraHelper( dirLight.shadow.camera ) );
49 |
50 | const geometry = new THREE.PlaneBufferGeometry(30, 30, 200, 200);
51 | const plane = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial({ color: 0xf2a23a }));
52 | plane.receiveShadow = true;
53 | plane.castShadow = true;
54 | plane.rotation.x = - Math.PI / 2;
55 | plane.position.z = - 30;
56 | scene.add(plane);
57 |
58 | const count: number = geometry.attributes.position.count;
59 |
60 | // ANIMATE
61 | function animate() {
62 |
63 | // SINE WAVE
64 | const now = Date.now() / 300;
65 | for (let i = 0; i < count; i++) {
66 | const x = geometry.attributes.position.getX(i);
67 |
68 | // SINE WAVE
69 | const xangle = x + now
70 | const xsin = Math.sin(xangle)
71 | geometry.attributes.position.setZ(i, xsin);
72 | }
73 | geometry.computeVertexNormals();
74 | geometry.attributes.position.needsUpdate = true;
75 |
76 | renderer.render(scene, camera);
77 | requestAnimationFrame(animate);
78 | }
79 | document.body.appendChild(renderer.domElement);
80 | animate();
81 |
82 | // RESIZE HANDLER
83 | function onWindowResize() {
84 | camera.aspect = window.innerWidth / window.innerHeight;
85 | camera.updateProjectionMatrix();
86 | renderer.setSize(window.innerWidth, window.innerHeight);
87 | }
88 | window.addEventListener('resize', onWindowResize);
89 | }
--------------------------------------------------------------------------------
/src/sine_cos_wave_plane.ts:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
3 |
4 | export function sine_cos_wave_plane() {
5 | // SCENE
6 | const scene = new THREE.Scene();
7 | scene.background = new THREE.Color(0xa8def0);
8 |
9 | // CAMERA
10 | const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
11 | camera.position.y = 5;
12 |
13 | // RENDERER
14 | const renderer = new THREE.WebGLRenderer({ antialias: true });
15 | renderer.setSize(window.innerWidth, window.innerHeight);
16 | renderer.setPixelRatio(window.devicePixelRatio);
17 | renderer.shadowMap.enabled = true
18 |
19 | // CONTROLS
20 | const controls = new OrbitControls(camera, renderer.domElement);
21 | controls.target = new THREE.Vector3(0, 0, -40);
22 | controls.update();
23 |
24 | // AMBIENT LIGHT
25 | scene.add(new THREE.AmbientLight(0xffffff, 0.5));
26 | // DIRECTIONAL LIGHT
27 | const dirLight = new THREE.DirectionalLight(0xffffff, 1.0)
28 | dirLight.position.x += 20
29 | dirLight.position.y += 20
30 | dirLight.position.z += 20
31 | dirLight.castShadow = true
32 | dirLight.shadow.mapSize.width = 4096;
33 | dirLight.shadow.mapSize.height = 4096;
34 | const d = 25;
35 | dirLight.shadow.camera.left = - d;
36 | dirLight.shadow.camera.right = d;
37 | dirLight.shadow.camera.top = d;
38 | dirLight.shadow.camera.bottom = - d;
39 | dirLight.position.z = -30;
40 |
41 | let target = new THREE.Object3D();
42 | target.position.z = -20;
43 | dirLight.target = target;
44 | dirLight.target.updateMatrixWorld();
45 |
46 | dirLight.shadow.camera.lookAt(0, 0, -30);
47 | scene.add(dirLight);
48 | // scene.add(new THREE.CameraHelper(dirLight.shadow.camera));
49 |
50 | const geometry = new THREE.PlaneBufferGeometry(30, 30, 200, 200);
51 | const plane = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial({ color: 0xf2a23a }));
52 | plane.receiveShadow = true;
53 | plane.castShadow = true;
54 | plane.rotation.x = - Math.PI / 2;
55 | plane.position.z = - 30;
56 | scene.add(plane);
57 |
58 | const count: number = geometry.attributes.position.count;
59 |
60 | // ANIMATE
61 | function animate() {
62 |
63 | // SINE WAVE
64 | const now = Date.now() / 300;
65 | for (let i = 0; i < count; i++) {
66 | const x = geometry.attributes.position.getX(i)
67 | const y = geometry.attributes.position.getY(i)
68 |
69 | const xangle = x + now
70 | const xsin = Math.sin(xangle)
71 | const yangle = y + now
72 | const ycos = Math.cos(yangle)
73 |
74 | geometry.attributes.position.setZ(i, xsin + ycos)
75 | }
76 | geometry.computeVertexNormals()
77 | geometry.attributes.position.needsUpdate = true;
78 |
79 | renderer.render(scene, camera);
80 | requestAnimationFrame(animate);
81 | }
82 | document.body.appendChild(renderer.domElement);
83 | animate();
84 |
85 | // RESIZE HANDLER
86 | function onWindowResize() {
87 | camera.aspect = window.innerWidth / window.innerHeight;
88 | camera.updateProjectionMatrix();
89 | renderer.setSize(window.innerWidth, window.innerHeight);
90 | }
91 | window.addEventListener('resize', onWindowResize);
92 | }
--------------------------------------------------------------------------------
/src/sine_cos_slime_wave_plane.ts:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
3 |
4 | export function sine_cos_slime_wave_plane() {
5 | // SCENE
6 | const scene = new THREE.Scene();
7 | scene.background = new THREE.Color(0xa8def0);
8 |
9 | // CAMERA
10 | const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
11 | camera.position.y = 5;
12 |
13 | // RENDERER
14 | const renderer = new THREE.WebGLRenderer({ antialias: true });
15 | renderer.setSize(window.innerWidth, window.innerHeight);
16 | renderer.setPixelRatio(window.devicePixelRatio);
17 | renderer.shadowMap.enabled = true
18 |
19 | // CONTROLS
20 | const controls = new OrbitControls(camera, renderer.domElement);
21 | controls.target = new THREE.Vector3(0, 0, -40);
22 | controls.update();
23 |
24 | // AMBIENT LIGHT
25 | scene.add(new THREE.AmbientLight(0xffffff, 0.5));
26 | // DIRECTIONAL LIGHT
27 | const dirLight = new THREE.DirectionalLight(0xffffff, 1.0)
28 | dirLight.position.x += 20
29 | dirLight.position.y += 20
30 | dirLight.position.z += 20
31 | dirLight.castShadow = true
32 | dirLight.shadow.mapSize.width = 4096;
33 | dirLight.shadow.mapSize.height = 4096;
34 | const d = 25;
35 | dirLight.shadow.camera.left = - d;
36 | dirLight.shadow.camera.right = d;
37 | dirLight.shadow.camera.top = d;
38 | dirLight.shadow.camera.bottom = - d;
39 | dirLight.position.z = -30;
40 |
41 | let target = new THREE.Object3D();
42 | target.position.z = -20;
43 | dirLight.target = target;
44 | dirLight.target.updateMatrixWorld();
45 |
46 | dirLight.shadow.camera.lookAt(0, 0, -30);
47 | scene.add(dirLight);
48 | // scene.add(new THREE.CameraHelper(dirLight.shadow.camera));
49 |
50 | // TEXTURES
51 | const textureLoader = new THREE.TextureLoader();
52 |
53 | const slimeBaseColor = textureLoader.load("./textures/slime/alien-slime1-albedo.png");
54 | const slimeNormalMap = textureLoader.load("./textures/slime/alien-slime1-normal-ogl.png");
55 | const slimeHeightMap = textureLoader.load("./textures/slime/alien-slime1-height.png");
56 | const slimeRoughness = textureLoader.load("./textures/slime/alien-slime1-roughness.png");
57 | const slimeAmbientOcclusion = textureLoader.load("./textures/slime/alien-slime1-ao.png");
58 |
59 | // PLANE
60 | const geometry = new THREE.PlaneBufferGeometry(30, 30, 200, 200);
61 | const plane = new THREE.Mesh(geometry,
62 | new THREE.MeshStandardMaterial({
63 | map: slimeBaseColor,
64 | normalMap: slimeNormalMap,
65 | displacementMap: slimeHeightMap, displacementScale: 0.01,
66 | roughnessMap: slimeRoughness, roughness: 0,
67 | aoMap: slimeAmbientOcclusion }));
68 | plane.receiveShadow = true;
69 | plane.castShadow = true;
70 | plane.rotation.x = - Math.PI / 2;
71 | plane.position.z = - 30;
72 | scene.add(plane);
73 |
74 | const count: number = geometry.attributes.position.count;
75 | const damping = 0.75;
76 |
77 | // ANIMATE
78 | function animate() {
79 |
80 | // SINE WAVE
81 | const now = Date.now() / 400;
82 | for (let i = 0; i < count; i++) {
83 | const x = geometry.attributes.position.getX(i)
84 | const y = geometry.attributes.position.getY(i)
85 |
86 | const xangle = x + now
87 | const xsin = Math.sin(xangle) * damping
88 | const yangle = y + now
89 | const ycos = Math.cos(yangle) * damping
90 |
91 | geometry.attributes.position.setZ(i, xsin + ycos)
92 | }
93 | geometry.computeVertexNormals();
94 | geometry.attributes.position.needsUpdate = true;
95 |
96 | renderer.render(scene, camera);
97 | requestAnimationFrame(animate);
98 | }
99 | document.body.appendChild(renderer.domElement);
100 | animate();
101 |
102 | // RESIZE HANDLER
103 | function onWindowResize() {
104 | camera.aspect = window.innerWidth / window.innerHeight;
105 | camera.updateProjectionMatrix();
106 | renderer.setSize(window.innerWidth, window.innerHeight);
107 | }
108 | window.addEventListener('resize', onWindowResize);
109 | }
--------------------------------------------------------------------------------
/src/sine_cos_water_wave_plane.ts:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
3 |
4 | export function sine_cos_water_wave_plane() {
5 | // SCENE
6 | const scene = new THREE.Scene();
7 | scene.background = new THREE.Color(0xa8def0);
8 |
9 | // CAMERA
10 | const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
11 | camera.position.y = 5;
12 |
13 | // RENDERER
14 | const renderer = new THREE.WebGLRenderer({ antialias: true });
15 | renderer.setSize(window.innerWidth, window.innerHeight);
16 | renderer.setPixelRatio(window.devicePixelRatio);
17 | renderer.shadowMap.enabled = true
18 |
19 | // CONTROLS
20 | const controls = new OrbitControls(camera, renderer.domElement);
21 | controls.target = new THREE.Vector3(0, 0, -40);
22 | controls.update();
23 |
24 | // AMBIENT LIGHT
25 | scene.add(new THREE.AmbientLight(0xffffff, 0.5));
26 | // DIRECTIONAL LIGHT
27 | const dirLight = new THREE.DirectionalLight(0xffffff, 1.0)
28 | dirLight.position.x += 20
29 | dirLight.position.y += 20
30 | dirLight.position.z += 20
31 | dirLight.castShadow = true
32 | dirLight.shadow.mapSize.width = 4096;
33 | dirLight.shadow.mapSize.height = 4096;
34 | const d = 25;
35 | dirLight.shadow.camera.left = - d;
36 | dirLight.shadow.camera.right = d;
37 | dirLight.shadow.camera.top = d;
38 | dirLight.shadow.camera.bottom = - d;
39 | dirLight.position.z = -30;
40 |
41 | let target = new THREE.Object3D();
42 | target.position.z = -20;
43 | dirLight.target = target;
44 | dirLight.target.updateMatrixWorld();
45 |
46 | dirLight.shadow.camera.lookAt(0, 0, -30);
47 | scene.add(dirLight);
48 | // scene.add(new THREE.CameraHelper(dirLight.shadow.camera));
49 |
50 |
51 | // TEXTURES
52 | const textureLoader = new THREE.TextureLoader();
53 |
54 | const waterBaseColor = textureLoader.load("./textures/water/Water_002_COLOR.jpg");
55 | const waterNormalMap = textureLoader.load("./textures/water/Water_002_NORM.jpg");
56 | const waterHeightMap = textureLoader.load("./textures/water/Water_002_DISP.png");
57 | const waterRoughness = textureLoader.load("./textures/water/Water_002_ROUGH.jpg");
58 | const waterAmbientOcclusion = textureLoader.load("./textures/water/Water_002_OCC.jpg");
59 |
60 | // PLANE
61 | const WIDTH = 30;
62 | const HEIGHT = 30;
63 | const geometry = new THREE.PlaneBufferGeometry(WIDTH, HEIGHT, 200, 200);
64 | const plane = new THREE.Mesh(geometry,
65 | new THREE.MeshStandardMaterial({
66 | map: waterBaseColor,
67 | normalMap: waterNormalMap,
68 | displacementMap: waterHeightMap, displacementScale: 0.01,
69 | roughnessMap: waterRoughness, roughness: 0,
70 | aoMap: waterAmbientOcclusion }));
71 | plane.receiveShadow = true;
72 | plane.castShadow = true;
73 | plane.rotation.x = - Math.PI / 2;
74 | plane.position.z = - 30;
75 | scene.add(plane);
76 |
77 | const count: number = geometry.attributes.position.count;
78 | const damping = 0.25;
79 | // ANIMATE
80 | function animate() {
81 |
82 | // SINE WAVE
83 | const now_slow = Date.now() / 400;
84 | for (let i = 0; i < count; i++) {
85 | const x = geometry.attributes.position.getX(i)
86 | const y = geometry.attributes.position.getY(i)
87 |
88 | const xangle = x + now_slow
89 | const xsin = Math.sin(xangle) * damping
90 | const yangle = y + now_slow
91 | const ycos = Math.cos(yangle) * damping
92 |
93 | geometry.attributes.position.setZ(i, xsin + ycos)
94 | }
95 | geometry.computeVertexNormals();
96 | geometry.attributes.position.needsUpdate = true;
97 |
98 | renderer.render(scene, camera);
99 | requestAnimationFrame(animate);
100 | }
101 | document.body.appendChild(renderer.domElement);
102 | animate();
103 |
104 | // RESIZE HANDLER
105 | function onWindowResize() {
106 | camera.aspect = window.innerWidth / window.innerHeight;
107 | camera.updateProjectionMatrix();
108 | renderer.setSize(window.innerWidth, window.innerHeight);
109 | }
110 | window.addEventListener('resize', onWindowResize);
111 | }
--------------------------------------------------------------------------------
/src/sphere_with_waves.ts:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
3 |
4 | export function sphere_with_waves() {
5 | // SCENE
6 | const scene = new THREE.Scene();
7 | scene.background = new THREE.Color(0xa8def0);
8 |
9 | // CAMERA
10 | const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
11 | camera.position.y = 5;
12 |
13 | // RENDERER
14 | const renderer = new THREE.WebGLRenderer({ antialias: true });
15 | renderer.setSize(window.innerWidth, window.innerHeight);
16 | renderer.setPixelRatio(window.devicePixelRatio);
17 | renderer.shadowMap.enabled = true
18 |
19 | // CONTROLS
20 | const controls = new OrbitControls(camera, renderer.domElement);
21 | controls.target = new THREE.Vector3(0, 0, -40);
22 | controls.update();
23 |
24 | // AMBIENT LIGHT
25 | scene.add(new THREE.AmbientLight(0xffffff, 0.5));
26 | // DIRECTIONAL LIGHT
27 | const dirLight = new THREE.DirectionalLight(0xffffff, 1.0)
28 | dirLight.position.x += 20
29 | dirLight.position.y += 20
30 | dirLight.position.z += 20
31 | dirLight.castShadow = true
32 | dirLight.shadow.mapSize.width = 4096;
33 | dirLight.shadow.mapSize.height = 4096;
34 | const d = 10;
35 | dirLight.shadow.camera.left = - d;
36 | dirLight.shadow.camera.right = d;
37 | dirLight.shadow.camera.top = d;
38 | dirLight.shadow.camera.bottom = - d;
39 | dirLight.position.z = -25;
40 |
41 | let target = new THREE.Object3D();
42 | target.position.z = -30;
43 | dirLight.target = target;
44 | dirLight.target.updateMatrixWorld();
45 |
46 | dirLight.shadow.camera.lookAt(0, 0, -30);
47 | scene.add(dirLight);
48 | // scene.add(new THREE.CameraHelper(dirLight.shadow.camera));
49 |
50 |
51 | // TEXTURES
52 | const textureLoader = new THREE.TextureLoader();
53 |
54 | const waterBaseColor = textureLoader.load("./textures/water/Water_002_COLOR.jpg");
55 | const waterNormalMap = textureLoader.load("./textures/water/Water_002_NORM.jpg");
56 | const waterHeightMap = textureLoader.load("./textures/water/Water_002_DISP.png");
57 | const waterRoughness = textureLoader.load("./textures/water/Water_002_ROUGH.jpg");
58 | const waterAmbientOcclusion = textureLoader.load("./textures/water/Water_002_OCC.jpg");
59 |
60 | // PLANE
61 | const geometry = new THREE.SphereBufferGeometry(6, 128, 128);
62 | const sphere = new THREE.Mesh(geometry,
63 | new THREE.MeshStandardMaterial({
64 | map: waterBaseColor,
65 | normalMap: waterNormalMap,
66 | displacementMap: waterHeightMap, displacementScale: 0.01,
67 | roughnessMap: waterRoughness, roughness: 0,
68 | aoMap: waterAmbientOcclusion
69 | }));
70 | sphere.receiveShadow = true;
71 | sphere.castShadow = true;
72 | sphere.rotation.x = - Math.PI / 4;
73 | sphere.position.z = - 30;
74 | scene.add(sphere);
75 |
76 | const count: number = geometry.attributes.position.count;
77 |
78 | const position_clone = JSON.parse(JSON.stringify(geometry.attributes.position.array)) as Float32Array;
79 | const normals_clone = JSON.parse(JSON.stringify(geometry.attributes.normal.array)) as Float32Array;
80 | const damping = 0.2;
81 |
82 | // ANIMATE
83 | function animate() {
84 | const now = Date.now() / 200;
85 |
86 | // iterate all vertices
87 | for (let i = 0; i < count; i++) {
88 | // indices
89 | const ix = i * 3
90 | const iy = i * 3 + 1
91 | const iz = i * 3 + 2
92 |
93 | // use uvs to calculate wave
94 | const uX = geometry.attributes.uv.getX(i) * Math.PI * 16
95 | const uY = geometry.attributes.uv.getY(i) * Math.PI * 16
96 |
97 | // calculate current vertex wave height
98 | const xangle = (uX + now)
99 | const xsin = Math.sin(xangle) * damping
100 | const yangle = (uY + now)
101 | const ycos = Math.cos(yangle) * damping
102 |
103 | // set new position
104 | geometry.attributes.position.setX(i, position_clone[ix] + normals_clone[ix] * (xsin + ycos))
105 | geometry.attributes.position.setY(i, position_clone[iy] + normals_clone[iy] * (xsin + ycos))
106 | geometry.attributes.position.setZ(i, position_clone[iz] + normals_clone[iz] * (xsin + ycos))
107 | }
108 | geometry.computeVertexNormals();
109 | geometry.attributes.position.needsUpdate = true;
110 |
111 | renderer.render(scene, camera);
112 | requestAnimationFrame(animate);
113 | }
114 | document.body.appendChild(renderer.domElement);
115 | animate();
116 |
117 | // RESIZE HANDLER
118 | function onWindowResize() {
119 | camera.aspect = window.innerWidth / window.innerHeight;
120 | camera.updateProjectionMatrix();
121 | renderer.setSize(window.innerWidth, window.innerHeight);
122 | }
123 | window.addEventListener('resize', onWindowResize);
124 | }
--------------------------------------------------------------------------------
/src/terrain_editor.ts:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
3 |
4 | export function terrain_editor() {
5 | // SCENE
6 | const scene = new THREE.Scene();
7 | scene.background = new THREE.Color(0xa8def0);
8 |
9 | // CAMERA
10 | const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
11 | camera.position.y = 25;
12 | camera.position.z = 50;
13 | camera.position.x = -50;
14 |
15 | // RENDERER
16 | const renderer = new THREE.WebGLRenderer({ antialias: true });
17 | renderer.setSize(window.innerWidth, window.innerHeight);
18 | renderer.setPixelRatio(window.devicePixelRatio);
19 | renderer.shadowMap.enabled = true
20 |
21 | // CONTROLS
22 | const controls = new OrbitControls(camera, renderer.domElement);
23 | controls.target = new THREE.Vector3(0, 0, -25);
24 | controls.update();
25 |
26 | // AMBIENT LIGHT
27 | scene.add(new THREE.AmbientLight(0xffffff, 0.5));
28 | // DIRECTIONAL LIGHT
29 | const dirLight = new THREE.DirectionalLight(0xffffff, 1.0)
30 | dirLight.position.x += 40
31 | dirLight.position.y += 60
32 | dirLight.position.z = -40
33 | dirLight.castShadow = true
34 | dirLight.shadow.mapSize.width = 4096;
35 | dirLight.shadow.mapSize.height = 4096;
36 | const d = 100;
37 | dirLight.shadow.camera.left = - d;
38 | dirLight.shadow.camera.right = d;
39 | dirLight.shadow.camera.top = d;
40 | dirLight.shadow.camera.bottom = - d;
41 |
42 | let target = new THREE.Object3D();
43 | target.position.z = -20;
44 | dirLight.target = target;
45 | dirLight.target.updateMatrixWorld();
46 |
47 | dirLight.shadow.camera.lookAt(0, 0, -30);
48 | scene.add(dirLight);
49 | // scene.add(new THREE.CameraHelper(dirLight.shadow.camera));
50 |
51 | // TEXTURES
52 | const textureLoader = new THREE.TextureLoader();
53 |
54 | const soilBaseColor = textureLoader.load("./textures/soil/Rock_Moss_001_basecolor.jpg");
55 | const soilNormalMap = textureLoader.load("./textures/soil/Rock_Moss_001_normal.jpg");
56 | const soilHeightMap = textureLoader.load("./textures/soil/Rock_Moss_001_height.png");
57 | const soilRoughness = textureLoader.load("./textures/soil/Rock_Moss_001_roughness.jpg");
58 | const soilAmbientOcclusion = textureLoader.load("./textures/soil/Rock_Moss_001_ambientOcclusion.jpg");
59 |
60 | // PLANE
61 | const WIDTH = 100;
62 | const HEIGHT = 100;
63 | const geometry = new THREE.PlaneBufferGeometry(WIDTH, HEIGHT, 300, 300);
64 | const plane = new THREE.Mesh(geometry,
65 | new THREE.MeshStandardMaterial({
66 | map: soilBaseColor,
67 | normalMap: soilNormalMap,
68 | displacementMap: soilHeightMap, displacementScale: 2,
69 | roughnessMap: soilRoughness, roughness: 0,
70 | aoMap: soilAmbientOcclusion
71 | }));
72 | plane.receiveShadow = true;
73 | plane.castShadow = true;
74 | plane.rotation.x = - Math.PI / 2;
75 | plane.position.z = - 30;
76 | scene.add(plane);
77 |
78 | // CLICK EVENT
79 | const raycaster = new THREE.Raycaster(); // create once
80 | const clickMouse = new THREE.Vector2(); // create once
81 | const vector3 = new THREE.Vector3(); // create once
82 | const MAX_CLICK_DISTANCE = 10
83 | window.addEventListener('click', event => {
84 |
85 | // THREE RAYCASTER
86 | clickMouse.x = (event.clientX / window.innerWidth) * 2 - 1;
87 | clickMouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
88 |
89 | raycaster.setFromCamera(clickMouse, camera);
90 | const found = raycaster.intersectObjects(scene.children);
91 | if (found.length > 0 && (found[0].object as THREE.Mesh).geometry) {
92 | const mesh = found[0].object as THREE.Mesh
93 | const geometry = mesh.geometry
94 | const point = found[0].point
95 |
96 | for (let i = 0; i < geometry.attributes.position.count; i++) {
97 | vector3.setX(geometry.attributes.position.getX(i))
98 | vector3.setY(geometry.attributes.position.getY(i))
99 | vector3.setZ(geometry.attributes.position.getZ(i))
100 | const toWorld = mesh.localToWorld(vector3)
101 |
102 | const distance = point.distanceTo(toWorld)
103 | if (distance < MAX_CLICK_DISTANCE) {
104 | geometry.attributes.position.setZ(i, geometry.attributes.position.getZ(i) + (MAX_CLICK_DISTANCE - distance) / 2)
105 | }
106 | }
107 | geometry.computeVertexNormals()
108 | geometry.attributes.position.needsUpdate = true
109 | }
110 | })
111 |
112 | // ANIMATE
113 | function animate() {
114 | renderer.render(scene, camera);
115 | requestAnimationFrame(animate);
116 | }
117 | document.body.appendChild(renderer.domElement);
118 | animate();
119 |
120 | // RESIZE HANDLER
121 | function onWindowResize() {
122 | camera.aspect = window.innerWidth / window.innerHeight;
123 | camera.updateProjectionMatrix();
124 | renderer.setSize(window.innerWidth, window.innerHeight);
125 | }
126 | window.addEventListener('resize', onWindowResize);
127 | }
--------------------------------------------------------------------------------