three实现天文学家的三维城堡代码

代码语言:html

所属分类:三维

代码描述:three实现天文学家的三维城堡代码

代码标签: three 天文 学家 三维 城堡 代码

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <style>
    :root { color-scheme: dark; }
    * { box-sizing: border-box; }
    html, body { width: 100%; height: 100%; margin: 0; overflow: hidden; background: #080b11; }
    body { font-family: Inter, ui-sans-serif, system-ui, sans-serif; }
    #scene { position: fixed; inset: 0; }
    canvas { display: block; width: 100%; height: 100%; }
    .hint {
      position: fixed;
      left: 50%;
      bottom: 18px;
      z-index: 2;
      transform: translateX(-50%);
      color: rgba(190, 202, 211, .58);
      font-size: 8px;
      letter-spacing: .14em;
      text-transform: uppercase;
      white-space: nowrap;
      pointer-events: none;
    }
    .vignette {
      position: fixed;
      inset: 0;
      z-index: 1;
      background: radial-gradient(circle at 50% 42%, transparent 48%, rgba(0, 0, 0, .42) 115%);
      pointer-events: none;
    }
    @media (max-width: 640px) {
      .hint { bottom: 12px; font-size: 7px; }
    }
  </style>
  <script type="importmap">
    {"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.174.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.174.0/examples/jsm/"}}
  </script>
</head>
<body>
  <div id="scene"></div>
  <div class="hint">Drag to orbit · Scroll or pinch to zoom</div>
  <div class="vignette"></div>
  <script type="module">
    import * as THREE from "three";
    import { OrbitControls } from "three/addons/controls/OrbitControls.js";
    import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";
    import { RenderPass } from "three/addons/postprocessing/RenderPass.js";
    import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js";
    import { OutputPass } from "three/addons/postprocessing/OutputPass.js";

    const container = document.getElementById("scene");
    const reducedMotion = matchMedia("(prefers-reduced-motion: reduce)").matches;
    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x080b11);
    scene.fog = new THREE.Fog(0x080b11, 25, 48);

    const renderer = new THREE.WebGLRenderer({ antialias: true, powerPreference: "high-performance" });
    renderer.setPixelRatio(Math.min(devicePixelRatio, 1.75));
    renderer.setSize(innerWidth, innerHeight);
    renderer.outputColorSpace = THREE.SRGBColorSpace;
    renderer.toneMapping = THREE.ACESFilmicToneMapping;
    renderer.toneMappingExposure = 1.06;
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    renderer.domElement.setAttribute("role", "img");
    renderer.domElement.setAttribute("aria-label", "Interactive isolated model of the Astral Tide Citadel on a flat plane.");
    container.appendChild(renderer.domElement);

    const camera = new THREE.PerspectiveCamera(innerWidth / innerHeight < .72 ? 56 : 38, innerWidth / innerHeight, .1, 100);
    camera.position.set(16.4, 9.4, 19.2);
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.target.set(0, 3.35, -1.35);
    controls.enableDamping = true;
    controls.dampingFactor = .055;
    controls.minDistance = 8;
    controls.maxDistance = 38;
    controls.maxPolarAngle = Math.PI * .49;
    controls.update();

    const composer = new EffectComposer(renderer);
    composer.addPass(new RenderPass(scene, camera));
    composer.addPass(new UnrealBloomPass(new THREE.Vector2(innerWidth, innerHeight), .34, .55, .86));
    composer.addPass(new OutputPass());

    let randomSeed = 92741;
    function random() {
      randomSeed = (randomSeed * 1664525 + 1013904223) >>> 0;
      return randomSeed / 4294967296;
    }
    function range(min, max) { return min + (max - min) * random(); }
    function setShadow(object, cast = true, receive = true) {
      object.castShadow = cast;
      object.receiveShadow = receive;
      return object;
    }
    function addMesh(parent, geometry, material, x = 0, y = 0, z = 0, rx = 0, ry = 0, rz = 0) {
      const object = setShadow(new THREE.Mesh(geometry, material));
      object.position.set(x, y, z);
      object.rotation.set(rx, ry, rz);
      parent.add(object);
      return object;
    }
    function makeBrickTexture(base, mortar, accent) {
      const canvas = document.createElement("canvas");
      canvas.width = canvas.height = 512;
      const context = canvas.getContext("2d");
      context.fillStyle = mortar;
      context.fillRect(0, 0, 512, 512);
      const rows = 12;
      const height = 512 / rows;
      for (let row = 0; row < rows; row++) {
        const offset = row % 2 ? -30 : 0;
        for (let x = offset; x < 530; x += 63) {
          const light = range(-12, 13);
          context.fillStyle = `rgb(${Math.max(0, parseInt(base.slice(1, 3), 16) + light)},${Math.max(0, parseInt(base.slice(3, 5), 16) + light)},${Math.max(0, parseInt(base.slice(5, 7), 16) + light)})`;
          context.fillRect(x + 2, row * height + 2, 59, height - 4);
          context.fillStyle = accent;
          context.globalAlpha = .13;
          context.fillRect(x + 4, row * height + 4, 54, 3);
          context.globalAlpha = 1;
        }
      }
      const texture = new THREE.CanvasTexture(canvas);
      texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
      texture.repeat.set(3.4, 3.4);
      texture.color.........完整代码请登录后点击上方下载按钮下载查看

网友评论0