three实现三维山坡上的寺庙场景代码
代码语言:html
所属分类:其他
代码由minimax-m3.1-flash ai生成,可能有错误,仅供参考:点击查看提示词
代码描述:three实现三维山坡上的寺庙场景代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>云隐禅寺 · 山坡寺庙三维场景</title>
<style>
:root{
--ink:#e8e3d8; --ink-dim:#a7a094; --gold:#d8b26a; --line:rgba(216,178,106,.28);
--glass:rgba(18,20,24,.58);
}
*{box-sizing:border-box}
html,body{margin:0;height:100%;overflow:hidden;background:#0a0d12;color:var(--ink);
font-family:"PingFang SC","Microsoft YaHei","Noto Sans SC",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;}
canvas{display:block}
#app{position:fixed;inset:0}
/* ---------- 加载 ---------- */
#loader{position:fixed;inset:0;z-index:50;display:flex;flex-direction:column;align-items:center;justify-content:center;
gap:18px;background:radial-gradient(120% 90% at 50% 30%,#1d2733 0%,#0a0d12 70%);transition:opacity .9s ease}
#loader.hide{opacity:0;pointer-events:none}
.lbrand{font-size:26px;letter-spacing:.42em;color:var(--gold);text-indent:.42em;font-weight:300}
.lsub{font-size:12px;letter-spacing:.32em;color:var(--ink-dim);text-indent:.32em}
.lbar{width:min(320px,64vw);height:2px;background:rgba(255,255,255,.12);border-radius:2px;overflow:hidden}
.lbar i{display:block;height:100%;width:0%;background:linear-gradient(90deg,#8a6a32,var(--gold));transition:width .3s}
.ltip{font-size:11px;color:#6f6a60;letter-spacing:.16em;min-height:14px}
/* ---------- 标题 ---------- */
#title{position:fixed;left:26px;top:24px;z-index:20;pointer-events:none;transition:opacity .6s}
#title h1{margin:0;font-size:22px;font-weight:300;letter-spacing:.34em;text-indent:.34em;
color:#f2ece0;text-shadow:0 2px 18px rgba(0,0,0,.75)}
#title p{margin:6px 0 0;font-size:11px;letter-spacing:.24em;color:#cbc2b0;text-shadow:0 1px 10px rgba(0,0,0,.8)}
/* ---------- 控制面板 ---------- */
#panel{position:fixed;right:18px;top:18px;z-index:20;width:246px;padding:16px 16px 14px;border-radius:14px;
background:var(--glass);backdrop-filter:blur(16px) saturate(140%);-webkit-backdrop-filter:blur(16px);
border:1px solid var(--line);box-shadow:0 18px 50px rgba(0,0,0,.5);font-size:12px;
transition:transform .35s cubic-bezier(.2,.8,.2,1),opacity .35s}
#panel.hidden{transform:translateX(280px);opacity:0;pointer-events:none}
#panel .row{display:flex;align-items:center;justify-content:space-between;margin:9px 0 4px;color:var(--ink-dim)}
#panel .row b{color:var(--ink);font-weight:500;font-variant-numeric:tabular-nums}
.grp{border-top:1px solid rgba(255,255,255,.08);margin-top:12px;padding-top:4px}
.grp:first-of-type{border-top:none;margin-top:0;padding-top:0}
.seclabel{font-size:10px;letter-spacing:.26em;color:#8d8577;margin:10px 0 6px}
input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:16px;background:transparent;cursor:pointer}
input[type=range]::-webkit-slider-runnable-track{height:2px;background:rgba(255,255,255,.16);border-radius:2px}
input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;border-radius:50%;
background:var(--gold);margin-top:-5px;box-shadow:0 0 8px rgba(216,178,106,.6)}
input[type=range]::-moz-range-track{height:2px;background:rgba(255,255,255,.16);border-radius:2px}
input[type=range]::-moz-range-thumb{width:12px;height:12px;border:none;border-radius:50%;background:var(--gold)}
.btns{display:flex;flex-wrap:wrap;gap:5px}
button{flex:1 1 auto;min-width:0;padding:6px 4px;font-size:11px;letter-spacing:.06em;color:var(--ink);
background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-radius:8px;cursor:pointer;
transition:.18s;white-space:nowrap;font-family:inherit}
button:hover{background:rgba(216,178,106,.18);border-color:rgba(216,178,106,.45);color:#fff}
button.on{background:linear-gradient(180deg,rgba(216,178,106,.34),rgba(216,178,106,.16));
border-color:rgba(216,178,106,.6);color:#fff6e2}
.toggles{display:grid;grid-template-columns:1fr 1fr;gap:5px}
#stats{position:fixed;left:26px;bottom:20px;z-index:20;font-size:11px;letter-spacing:.1em;color:#b9b2a4;
text-shadow:0 1px 8px rgba(0,0,0,.8);font-variant-numeric:tabular-nums}
#hint{position:fixed;left:50%;bottom:18px;transform:translateX(-50%);z-index:20;font-size:11px;letter-spacing:.2em;
color:#b9b2a4;text-shadow:0 1px 8px rgba(0,0,0,.8);pointer-events:none;transition:opacity .8s}
#toast{position:fixed;left:50%;top:26px;transform:translateX(-50%);z-index:40;padding:8px 16px;border-radius:20px;
background:rgba(18,20,24,.8);border:1px solid var(--line);font-size:12px;letter-spacing:.14em;opacity:0;
transition:opacity .35s;pointer-events:none;backdrop-filter:blur(10px)}
#toast.show{opacity:1}
#toggle{position:fixed;right:18px;top:18px;z-index:21;width:34px;height:34px;padding:0;flex:none;border-radius:10px;
display:none;align-items:center;justify-content:center;font-size:15px}
#toggle.show{display:flex}
@media (max-width:720px){
#panel{width:210px;right:10px;top:10px;padding:12px}
#title{left:14px;top:14px}#title h1{font-size:17px}
#stats{left:14px;bottom:12px}
}
</style>
</head>
<body>
<div id="app"></div>
<div id="loader">
<div class="lbrand">云隐禅寺</div>
<div class="lbar"><i id="lbar-fill"></i></div>
<div class="ltip" id="ltip">正在开山辟地…</div>
</div>
<div id="title">
<h1>云隐禅寺</h1>
<p id="subtitle">AIKOU MOUNTAIN · TEMPLE IN THE CLOUDS</p>
</div>
<button id="toggle">☰</button>
<div id="panel">
<div class="grp">
<div class="seclabel">时 刻</div>
<div class="row"><span>时间</span><b id="v-time">16:21</b></div>
<input type="range" id="s-time" min="4" max="23" step="0.02" value="16.35" />
<div class="btns" style="margin-top:6px">
<button data-time="5.6">晨</button><button data-time="8.4">上午</button>
<button data-time="12">正午</button><button data-time="16.35" class="on">黄昏</button><button data-time="21.2">夜</button>
</div>
</div>
<div class="grp">
<div class="seclabel">机 位</div>
<div class="btns">
<button data-cam="0">远眺</button><button data-cam="1">山门</button>
<button data-cam="2">庭院</button><button data-cam="3">檐角</button><button data-cam="4">俯瞰</button>
</div>
</div>
<div class="grp">
<div class="seclabel">气 象</div>
<div class="toggles">
<button data-tog="rain">细雨</button><button data-tog="snow">飞雪</button>
<button data-tog="cloud">云海</button><button data-tog="fog">浓雾</button>
</div>
<div class="row" style="margin-top:10px"><span>雾气</span><b id="v-fog">0.20</b></div>
<input type="range" id="s-fog" min="0" max="1" step="0.01" value="0.2" />
</div>
<div class="grp">
<div class="seclabel">画 质</div>
<div class="btns">
<button data-q="low">流畅</button><button data-q="mid" class="on">均衡</button><button data-q="high">极致</button>
</div>
<div class="btns" style="margin-top:5px">
<button id="b-auto">自动漫游</button><button id="b-shot">保存截图</button>
</div>
</div>
<div class="grp">
<div class="seclabel">状 态</div>
<div class="row"><span>帧率</span><b id="v-fps">--</b></div>
<div class="row"><span>绘制调用</span><b id="v-calls">--</b></div>
</div>
</div>
<div id="stats">拖拽旋转 · 滚轮缩放 · 右键平移 · H 隐藏面板 · 空格 漫游</div>
<div id="hint">点击「均衡」画质体验最佳</div>
<div id="toast"></div>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.186.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.186.0/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { Sky } from 'three/addons/objects/Sky.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';
import { mergeGeometries } from 'three/addons/utils/BufferGeometryUtils.js';
/* =====================================================================
* 云隐禅寺 — 基础层:随机数 / 噪声 / 纹理工厂 / 材质库
* ===================================================================*/
const QS = new URLSearchParams(location.search);
const num = (k, d) => (QS.has(k) ? parseFloat(QS.get(k)) : d);
/* 固定随机种子:保证每次打开场景布局一致(可复现) */
const SEED = 20240711;
let _rnd = mulberry32(SEED);
const R = () => _rnd();
function reseed(s){ _rnd = mulberry32(s); }
/* 画质档:决定草量、树量、阴影贴图与后期 */
const QUALITY = {
low: { grass: 0, treeMul: 0.3, shadow: 1024, bloom: false, particles: 0.3, rocks: 0.3, aa: false },
mid: { grass: 40000,treeMul: 0.75, shadow: 2048, bloom: true, particles: 1.0, rocks: 0.7, aa: true },
high: { grass: 95000,treeMul: 1.0, shadow: 4096, bloom: true, particles: 1.6, rocks: 1.0, aa: true },
};
/* 自动挑画质:移动端 / 软件渲染 / 低端 GPU 自动降档 */
function autoQuality(){
if (QS.get('q') && QUALITY[QS.get('q')]) return QS.get('q');
const mobile = /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent);
if (mobile) return 'low';
try{
const c = document.createElement('canvas');
const gl = c.getContext('webgl2') || c.getContext('webgl');
const dbg = gl && gl.getExtension('WEBGL_debug_renderer_info');
const r = dbg ? String(gl.getParameter(dbg.UNMASKED_RENDERER_WEBGL)) : '';
if (/swiftshader|llvmpipe|software|basic render/i.test(r)) return 'low';
if (/(intel).*(hd graphics (2|3|4|5)|uhd graphics 6)/i.test(r)) return 'mid';
}catch(e){}
return (navigator.hardwareConcurrency || 4) <= 4 ? 'mid' : 'mid';
}
let QKEY = autoQuality();
let Q = QUALITY[QKEY];
if (num('grass', -1) >= 0) Q = { ...Q, grass: num('grass', 0) };
if (num('trees', -1) >= 0) Q = { ...Q, treeMul: num('trees', 1) };
/* 世界尺度(米) */
const W = {
field: 420, // 地形边长
seg: 300, // 地形分段
plateauH: 17.5, // 台地高度
plateauR: 34, // 台地半径
gateZ: 30, // 山门位置
bottomZ: 132, // 山脚
};
/* ---------------- 随机 / 噪声 ---------------- */
function mulberry32(a){ return function(){ a|=0; a = a + 0x6D2B79F5 | 0;
let t = Math.imul(a ^ a>>>15, 1 | a); t = t + Math.imul(t ^ t>>>7, 61 | t) ^ t;
return ((t ^ t>>>14) >>> 0) / 4294967296; }; }
function hash2(x, y, seed = 0){
let h = Math.imul(x, 374761393) ^ Math.imul(y, 668265263) ^ Math.imul(seed, 1274126177);
h = Math.imul(h ^ (h >>> 13), 1274126177);
h ^= h >>> 16;
return (h >>> 0) / 4294967296;
}
const sstep = t => t * t * (3 - 2 * t);
function vnoise(x, y, seed = 0){
const ix = Math.floor(x), iy = Math.floor(y);
const fx = sstep(x - ix), fy = sstep(y - iy);
const a = hash2(ix, iy, seed), b = hash2(ix + 1, iy, seed);
const c = hash2(ix, iy + 1, seed), d = hash2(ix + 1, iy + 1, seed);
return (a + (b - a) * fx) * (1 - fy) + (c + (d - c) * fx) * fy;
}
function fbm(x, y, oct = 4, seed =.........完整代码请登录后点击上方下载按钮下载查看















网友评论0