瀏覽代碼

Initial commit.

Simon 5 年之前
父節點
當前提交
1d9e33f1df

+ 68 - 0
base.css

@@ -0,0 +1,68 @@
+#model {
+  width: 100%;
+  height: 100%;
+  position: fixed;
+  top: 0;
+  left: 0;
+  z-index: -1;
+}
+
+.row {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-around;
+}
+
+.page {
+  width: 1000px;
+  margin: 1em;
+}
+
+.title {
+  height: 500px;
+  width: 100%;
+}
+
+.titleText {
+  font-family: 'Epilogue', sans-serif;
+  font-size: 5em;
+  color: white;
+  padding: 1em;
+  text-shadow: 4px 4px grey;
+}
+
+.content {
+  width: 100%;
+}
+
+.section {
+  width: 300px;
+  height: 500px;
+  background-color: rgba(0, 0, 0, 0.5);
+  margin-top: 20px;
+}
+
+.sectionText {
+  font-family: 'Epilogue', sans-serif;
+  color: white;
+  margin: 1.5em 0.5em;
+}
+
+canvas {
+  width: 100%;
+  height: 100%;
+  margin: 0;
+  overflow: hidden;
+  outline: none;
+}
+
+body {
+  width: 100%;
+  height: 100%;
+  margin: 0;
+  padding: 0;
+  overscroll-behavior: none;
+  background-image: url("./resources/background.jpg");
+  background-attachment: fixed;
+  background-repeat: no-repeat;
+}

+ 49 - 0
index.html

@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>3D on a Webpage</title>
+  <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+  <link href="https://fonts.googleapis.com/css2?family=Epilogue&display=swap" rel="stylesheet">
+  <link rel="stylesheet" type="text/css" href="base.css">
+</head>
+<body>
+  <script src="./main.js" type="module">
+  </script>
+  <div class="row">
+    <div class="page">
+      <div class="title">
+        <div class="row">
+          <div class="titleText">
+            Remember to Subscribe!
+          </div>
+        </div>
+      </div>
+      <div class="content">
+        <div class="row">
+          <div class="section">
+            <div class="sectionText">Code is up on github.</div>
+          </div>
+          <div class="section">
+            <div class="sectionText">Leave a comment, let me know if you liked the video.</div>
+          </div>
+          <div class="section">
+            <div class="sectionText">Also let me know if you have other topics you want covered.</div>
+          </div>
+        </div>
+        <div class="row">
+          <div class="section">
+            <div class="sectionText">Something something...</div>
+          </div>
+          <div class="section">
+            <div class="sectionText">I like beer.</div>
+          </div>
+          <div class="section">
+            <div class="sectionText">klaatu verata nikto</div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+  <div id="model"></div>
+</body>
+</html>

+ 150 - 0
main.js

@@ -0,0 +1,150 @@
+import * as THREE from 'https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js';
+
+import {FBXLoader} from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/loaders/FBXLoader.js';
+import {OrbitControls} from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/controls/OrbitControls.js';
+
+
+class Website3DDemo {
+  constructor() {
+    this._Initialize();
+  }
+
+  _Initialize() {
+    this._threejs = new THREE.WebGLRenderer({
+      antialias: true,
+      alpha: true,
+    });
+    this._threejs.shadowMap.enabled = true;
+    this._threejs.shadowMap.type = THREE.PCFSoftShadowMap;
+    this._threejs.physicallyCorrectLights = true;
+    this._threejs.toneMapping = THREE.ACESFilmicToneMapping;
+    this._threejs.outputEncoding = THREE.sRGBEncoding;
+
+    const modelDiv = document.getElementById('model');
+    modelDiv.appendChild(this._threejs.domElement);
+
+    this._threejs.setSize(modelDiv.offsetWidth, modelDiv.offsetHeight);
+
+    window.addEventListener('resize', () => {
+      this._OnWindowResize();
+    }, false);
+
+    const fov = 60;
+    const aspect = modelDiv.offsetWidth / modelDiv.offsetHeight;
+    const near = 1.0;
+    const far = 1000.0;
+    this._camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
+    this._camera.position.set(15, 15, 20);
+
+    this._scene = new THREE.Scene();
+
+    let light = new THREE.DirectionalLight(0xFFFFFF, 1.0);
+    light.position.set(20, 100, 10);
+    light.target.position.set(0, 0, 0);
+    light.castShadow = true;
+    light.shadow.bias = -0.001;
+    light.shadow.mapSize.width = 2048;
+    light.shadow.mapSize.height = 2048;
+    light.shadow.camera.near = 0.1;
+    light.shadow.camera.far = 500.0;
+    light.shadow.camera.near = 0.5;
+    light.shadow.camera.far = 500.0;
+    light.shadow.camera.left = 100;
+    light.shadow.camera.right = -100;
+    light.shadow.camera.top = 100;
+    light.shadow.camera.bottom = -100;
+    this._scene.add(light);
+
+    light = new THREE.AmbientLight(0xFFFFFF);
+    this._scene.add(light);
+
+    this._controls = new OrbitControls(
+        this._camera, this._threejs.domElement);
+    this._controls.target.set(0, 10, 0);
+    this._controls.update();
+
+    this._LoadAnimatedModelAndPlay(
+        './resources/zombie/', 'mremireh_o_desbiens.fbx',
+        'Silly Dancing.fbx', new THREE.Vector3(0, 0, 0));
+
+    this._LoadAnimatedModelAndPlay(
+        './resources/zombie/', 'mremireh_o_desbiens.fbx',
+        'Silly Dancing.fbx', new THREE.Vector3(-20, 0, -20));
+
+    this._LoadAnimatedModelAndPlay(
+        './resources/zombie/', 'mremireh_o_desbiens.fbx',
+        'Silly Dancing.fbx', new THREE.Vector3(20, 0, -20));
+  
+    this._mixers = [];
+    this._previousRAF = null;
+
+    this._scrollAmount = 0.0;
+    this._RAF();
+  }
+
+  _LoadAnimatedModelAndPlay(path, modelFile, animFile, offset) {
+    const loader = new FBXLoader();
+    loader.setPath(path);
+    loader.load(modelFile, (fbx) => {
+      fbx.scale.setScalar(0.1);
+      fbx.traverse(c => {
+        c.castShadow = true;
+      });
+      fbx.position.copy(offset);
+
+      const anim = new FBXLoader();
+      anim.setPath(path);
+      anim.load(animFile, (anim) => {
+        const m = new THREE.AnimationMixer(fbx);
+        this._mixers.push(m);
+        const idle = m.clipAction(anim.animations[0]);
+        idle.play();
+      });
+      this._scene.add(fbx);
+    });
+  }
+
+  OnScroll(pos) {
+    const amount = Math.min(pos / 500.0, 1.0);
+    this._camera.position.set(-15 + amount * (15 - -15), 15, 20);
+    this._controls.update();
+  }
+
+  _OnWindowResize() {
+    this._camera.aspect = window.innerWidth / window.innerHeight;
+    this._camera.updateProjectionMatrix();
+    this._threejs.setSize(window.innerWidth, window.innerHeight);
+  }
+
+  _Step(timeElapsed) {
+    const timeElapsedS = timeElapsed * 0.001;
+    if (this._mixers) {
+      this._mixers.map(m => m.update(timeElapsedS));
+    }
+  }
+
+  _RAF() {
+    requestAnimationFrame((t) => {
+      if (this._previousRAF === null) {
+        this._previousRAF = t;
+      }
+
+      this._RAF();
+
+      this._threejs.render(this._scene, this._camera);
+      this._Step(t - this._previousRAF);
+      this._previousRAF = t;
+    });
+  }
+}
+
+
+let _APP = null;
+
+window.addEventListener('DOMContentLoaded', () => {
+  _APP = new Website3DDemo();
+});
+
+window.addEventListener('scroll', (e) => {
+  _APP.OnScroll(window.scrollY);
+});

二進制
resources/background.jpg


二進制
resources/enterprise/scene.bin


+ 431 - 0
resources/enterprise/scene.gltf

@@ -0,0 +1,431 @@
+{
+  "accessors": [
+    {
+      "bufferView": 2,
+      "componentType": 5126,
+      "count": 90,
+      "max": [
+        5.4255342483520508,
+        18.788362503051758,
+        0.22034774720668793
+      ],
+      "min": [
+        -5.4255342483520508,
+        -0.95324015617370605,
+        -1.24922776222229
+      ],
+      "type": "VEC3"
+    },
+    {
+      "bufferView": 2,
+      "byteOffset": 1080,
+      "componentType": 5126,
+      "count": 90,
+      "max": [
+        0.98772847652435303,
+        0.12709265947341919,
+        0.99189198017120361
+      ],
+      "min": [
+        -0.9877278208732605,
+        -0.017344960942864418,
+        -0.99936473369598389
+      ],
+      "type": "VEC3"
+    },
+    {
+      "bufferView": 3,
+      "componentType": 5126,
+      "count": 90,
+      "max": [
+        0.9999280571937561,
+        0.99999243021011353,
+        0.053187757730484009,
+        1
+      ],
+      "min": [
+        -0.99936473369598389,
+        -0.99999243021011353,
+        -0.054964534938335419,
+        1
+      ],
+      "type": "VEC4"
+    },
+    {
+      "bufferView": 1,
+      "componentType": 5126,
+      "count": 90,
+      "max": [
+        1.0011260509490967,
+        0.99958771467208862
+      ],
+      "min": [
+        -0.0021580678876489401,
+        -0.048297841101884842
+      ],
+      "type": "VEC2"
+    },
+    {
+      "bufferView": 0,
+      "componentType": 5125,
+      "count": 102,
+      "max": [
+        89
+      ],
+      "min": [
+        0
+      ],
+      "type": "SCALAR"
+    },
+    {
+      "bufferView": 2,
+      "byteOffset": 2160,
+      "componentType": 5126,
+      "count": 36898,
+      "max": [
+        5.9383130073547363,
+        20.315641403198242,
+        0.8145749568939209
+      ],
+      "min": [
+        -5.9383130073547363,
+        -5.9156408309936523,
+        -4.5757746696472168
+      ],
+      "type": "VEC3"
+    },
+    {
+      "bufferView": 2,
+      "byteOffset": 444936,
+      "componentType": 5126,
+      "count": 36898,
+      "max": [
+        1,
+        1,
+        1
+      ],
+      "min": [
+        -1,
+        -1,
+        -1
+      ],
+      "type": "VEC3"
+    },
+    {
+      "bufferView": 3,
+      "byteOffset": 1440,
+      "componentType": 5126,
+      "count": 36898,
+      "max": [
+        1,
+        1,
+        1,
+        1
+      ],
+      "min": [
+        -1,
+        -1,
+        -1,
+        -1
+      ],
+      "type": "VEC4"
+    },
+    {
+      "bufferView": 1,
+      "byteOffset": 720,
+      "componentType": 5126,
+      "count": 36898,
+      "max": [
+        1,
+        1
+      ],
+      "min": [
+        -2.9802320611338473e-08,
+        -2.9802320611338473e-08
+      ],
+      "type": "VEC2"
+    },
+    {
+      "bufferView": 1,
+      "byteOffset": 295904,
+      "componentType": 5126,
+      "count": 36898,
+      "max": [
+        1,
+        1
+      ],
+      "min": [
+        -2.9802320611338473e-08,
+        -2.9802320611338473e-08
+      ],
+      "type": "VEC2"
+    },
+    {
+      "bufferView": 0,
+      "byteOffset": 408,
+      "componentType": 5125,
+      "count": 41742,
+      "max": [
+        36897
+      ],
+      "min": [
+        0
+      ],
+      "type": "SCALAR"
+    }
+  ],
+  "asset": {
+    "extras": {
+      "author": "Wholock (https://sketchfab.com/wholock)",
+      "license": "CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)",
+      "source": "https://sketchfab.com/3d-models/star-trek-dsc-enterprise-98cdebaa7fae4752bcaa5a35453d224c",
+      "title": "Star Trek - DSC Enterprise"
+    },
+    "generator": "Sketchfab-6.28.0",
+    "version": "2.0"
+  },
+  "bufferViews": [
+    {
+      "buffer": 0,
+      "byteLength": 167376,
+      "byteOffset": 0,
+      "name": "floatBufferViews",
+      "target": 34963
+    },
+    {
+      "buffer": 0,
+      "byteLength": 591088,
+      "byteOffset": 167376,
+      "byteStride": 8,
+      "name": "floatBufferViews",
+      "target": 34962
+    },
+    {
+      "buffer": 0,
+      "byteLength": 887712,
+      "byteOffset": 758464,
+      "byteStride": 12,
+      "name": "floatBufferViews",
+      "target": 34962
+    },
+    {
+      "buffer": 0,
+      "byteLength": 591808,
+      "byteOffset": 1646176,
+      "byteStride": 16,
+      "name": "floatBufferViews",
+      "target": 34962
+    }
+  ],
+  "buffers": [
+    {
+      "byteLength": 2237984,
+      "uri": "scene.bin"
+    }
+  ],
+  "images": [
+    {
+      "uri": "textures/material_0_baseColor.png"
+    },
+    {
+      "uri": "textures/material_0_metallicRoughness.png"
+    },
+    {
+      "uri": "textures/material_1_baseColor.png"
+    },
+    {
+      "uri": "textures/material_1_metallicRoughness.png"
+    },
+    {
+      "uri": "textures/material_1_emissive.png"
+    }
+  ],
+  "materials": [
+    {
+      "alphaMode": "BLEND",
+      "doubleSided": true,
+      "name": "material_0",
+      "pbrMetallicRoughness": {
+        "baseColorFactor": [
+          0,
+          0,
+          0,
+          1
+        ],
+        "baseColorTexture": {
+          "index": 0,
+          "texCoord": 0
+        },
+        "metallicFactor": 0,
+        "metallicRoughnessTexture": {
+          "index": 1,
+          "texCoord": 0
+        },
+        "roughnessFactor": 1
+      }
+    },
+    {
+      "doubleSided": true,
+      "emissiveFactor": [
+        1,
+        1,
+        1
+      ],
+      "emissiveTexture": {
+        "index": 4,
+        "texCoord": 0
+      },
+      "name": "material_1",
+      "pbrMetallicRoughness": {
+        "baseColorFactor": [
+          1,
+          1,
+          1,
+          1
+        ],
+        "baseColorTexture": {
+          "index": 2,
+          "texCoord": 0
+        },
+        "metallicFactor": 0,
+        "metallicRoughnessTexture": {
+          "index": 3,
+          "texCoord": 0
+        },
+        "roughnessFactor": 1
+      }
+    }
+  ],
+  "meshes": [
+    {
+      "primitives": [
+        {
+          "attributes": {
+            "NORMAL": 1,
+            "POSITION": 0,
+            "TANGENT": 2,
+            "TEXCOORD_0": 3
+          },
+          "indices": 4,
+          "material": 0,
+          "mode": 4
+        }
+      ]
+    },
+    {
+      "primitives": [
+        {
+          "attributes": {
+            "NORMAL": 6,
+            "POSITION": 5,
+            "TANGENT": 7,
+            "TEXCOORD_0": 8,
+            "TEXCOORD_1": 9
+          },
+          "indices": 10,
+          "material": 1,
+          "mode": 4
+        }
+      ]
+    }
+  ],
+  "nodes": [
+    {
+      "children": [
+        1
+      ],
+      "name": "RootNode (gltf orientation matrix)",
+      "rotation": [
+        -0.70710678118654746,
+        -0,
+        -0,
+        0.70710678118654757
+      ]
+    },
+    {
+      "children": [
+        2
+      ],
+      "matrix": [
+        -1,
+        -2.832769343193999e-16,
+        0,
+        0,
+        2.832769343193999e-16,
+        -1,
+        0,
+        0,
+        0,
+        0,
+        1,
+        0,
+        8.58306884765625e-06,
+        14.400014877319336,
+        0,
+        1
+      ],
+      "name": "RootNode (model correction matrix)"
+    },
+    {
+      "children": [
+        3
+      ],
+      "name": "4a2eb119de1c4469b931259a089f7654.lwo"
+    },
+    {
+      "children": [
+        4,
+        5
+      ],
+      "name": "Enterprise"
+    },
+    {
+      "mesh": 0,
+      "name": ""
+    },
+    {
+      "mesh": 1,
+      "name": ""
+    }
+  ],
+  "samplers": [
+    {
+      "magFilter": 9729,
+      "minFilter": 9987,
+      "wrapS": 10497,
+      "wrapT": 10497
+    }
+  ],
+  "scene": 0,
+  "scenes": [
+    {
+      "name": "OSG_Scene",
+      "nodes": [
+        0
+      ]
+    }
+  ],
+  "textures": [
+    {
+      "sampler": 0,
+      "source": 0
+    },
+    {
+      "sampler": 0,
+      "source": 1
+    },
+    {
+      "sampler": 0,
+      "source": 2
+    },
+    {
+      "sampler": 0,
+      "source": 3
+    },
+    {
+      "sampler": 0,
+      "source": 4
+    }
+  ]
+}
+

二進制
resources/enterprise/textures/material_0_baseColor.png


二進制
resources/enterprise/textures/material_0_metallicRoughness.png


二進制
resources/enterprise/textures/material_1_baseColor.png


二進制
resources/enterprise/textures/material_1_emissive.png


二進制
resources/enterprise/textures/material_1_metallicRoughness.png


+ 2 - 0
resources/readme.txt

@@ -0,0 +1,2 @@
+Enterprise Model: https://sketchfab.com/3d-models/star-trek-dsc-enterprise-98cdebaa7fae4752bcaa5a35453d224c
+Zombie model: https://www.mixamo.com/#/?page=1&query=mremireh+o+desbiens&type=Character

二進制
resources/zombie/Silly Dancing.fbx


二進制
resources/zombie/dance.fbx


二進制
resources/zombie/idle.fbx


二進制
resources/zombie/mremireh_o_desbiens.fbx


二進制
resources/zombie/walk.fbx