这是我的项目结构:
我有一个简单的服务器设置来提供 Three.js 动画 服务器.js
const express = require('express');
const path = require('path')
const app = express();
app.use(express.static('public')
const port = 5000;
app.listen(port, ()=>{
console.log(`listening on port ${port}`)
});
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./styles.css" type="text/css" media="screen">
<script src="main.js" type="module"></script>
</head>
<body>
<h1>heloo</h1>
<canvas id="app"></canvas>
</body>
main.js
import * as THREE from 'https://unpkg.com/[email protected]/build/three.module.js';
import { OrbitControls } from 'https://unpkg.com/[email protected]/examples/jsm/controls/OrbitControls.js';
import vertexShader from "./glsl/vertex.glsl";
import fragmentShader from "./glsl/fragment.glsl";
import img from "./mannequin.jpg";
class Gl {
constructor() {
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
100
);
this.camera.position.z = 1;
this.renderer = new THREE.WebGLRenderer({
canvas: document.querySelector("#app"),
antialias: true
});
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.renderer.setClearColor(0xffffff, 1);
this.clock = new THREE.Clock();
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.onResize();
}
init() {
this.createMesh();
this.addEvents();
}
createMesh() {
this.geometry = new THREE.PlaneGeometry(0.4, 0.6, 32, 32);
this.material = new THREE.ShaderMaterial({
vertexShader,
fragmentShader,
uniforms: {
uTime: { value: 0.0 },
uTexture: { value: new THREE.TextureLoader().load(img) }
},
// wireframe: true,
side: THREE.DoubleSide
});
this.mesh = new THREE.Mesh(this.geometry, this.material);
this.scene.add(this.mesh);
}
addEvents() {
window.requestAnimationFrame(this.run.bind(this));
window.addEventListener("resize", this.onResize.bind(this), false);
}
run() {
requestAnimationFrame(this.run.bind(this));
this.render();
}
render() {
this.material.uniforms.uTime.value = this.clock.getElapsedTime();
this.renderer.render(this.scene, this.camera);
}
onResize() {
const w = window.innerWidth;
const h = window.innerHeight;
this.camera.aspect = w / h;
this.camera.updateProjectionMatrix();
this.renderer.setSize(w, h);
}
}
export default Gl;
const scene = new Gl();
scene.init();
当我启动服务器并转到本地主机端口时,我收到以下错误:
vertex.glsl:1 无法加载模块脚本:服务器以非 JavaScript MIME 类型“application/octet-stream”进行响应。根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查。
fragment.glsl:1 无法加载模块脚本:服务器以非 JavaScript MIME 类型“application/octet-stream”进行响应。根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查。
mannequin.jpg:1 无法加载模块脚本:服务器以非 JavaScript MIME 类型“image/jpeg”进行响应。根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查。
对我来说 glsl 的解决方法是:
const grassShader = {}
async function getShaders() {
grassShader.vert = (await fetch('./grass.vert.glsl').then(x => x.text()));
grassShader.frag = (await fetch('./grass.frag.glsl').then(x => x.text()));
}
await getShaders()
浏览器仅支持带有
import
的 JavaScript 模块。
如果您想导入其他内容(例如图像或 glsl 文件),那么您需要将 Webpack 与合适的加载器模块(例如 webpack-glsl-loader)一起使用,并在将其加载到浏览器之前构建应用程序。