当尝试使用 THREE.InfiniteGridHelper 时,似乎没有办法导入不会生成错误的代码。即使复制粘贴代码也不起作用。
目前我已将代码复制并粘贴到我的 main.js 页面中,这给出了它给出的错误
未捕获的类型错误:“InfiniteGridHelper”是只读的 http://127.0.0.1:5000/static/main.js:10
我还尝试将代码粘贴到自己的 InfiniteGridHelper.js 页面中以在本地运行,从 https://mevedia.com/share/InfiniteGridHelper.js?c 导入代码,导入地图,并使用常规脚本标签。结果往往会在错误之间循环,例如
未捕获类型错误:THREE.InfiniteGridHelper 不是构造函数 http://127.0.0.1:5000/static/main.js:142
“语法错误:导入声明只能出现在模块的顶层”
未捕获的语法错误:请求的模块“http://127.0.0.1:5000/static/InfiniteGridHelper.js”不提供名为“InfiniteGridHelper”的导出
未捕获的引用错误:未定义三个 http://127.0.0.1:5000/static/InfiniteGridHelper.js:3
跨源请求被阻止:同源策略不允许读取 https://mevedia.com/share/InfiniteGridHelper.js?c 处的远程资源。 (原因:CORS 标头“Access-Control-Allow-Origin”丢失)。状态代码:200。
这个库上有一个 forum 似乎已被废弃,但看起来其他人能够让它工作,而且它似乎也可以在 codepen 上工作。我只是无法找到让它在本地运行的方法。
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// Author: Fyrestar https://mevedia.com (https://github.com/Fyrestar/THREE.InfiniteGridHelper)
THREE.InfiniteGridHelper = function InfiniteGridHelper( size1, size2, color, distance, axes = 'xzy' ) {
color = color || new THREE.Color( 'white' );
size1 = size1 || 10;
size2 = size2 || 100;
distance = distance || 8000;
const planeAxes = axes.substr( 0, 2 );
const geometry = new THREE.PlaneBufferGeometry( 2, 2, 1, 1 );
const material = new THREE.ShaderMaterial( {
side: THREE.DoubleSide,
uniforms: {
uSize1: {
value: size1
},
uSize2: {
value: size2
},
uColor: {
value: color
},
uDistance: {
value: distance
}
},
transparent: true,
vertexShader: `
varying vec3 worldPosition;
uniform float uDistance;
void main() {
vec3 pos = position.${axes} * uDistance;
pos.${planeAxes} += cameraPosition.${planeAxes};
worldPosition = pos;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: `
varying vec3 worldPosition;
uniform float uSize1;
uniform float uSize2;
uniform vec3 uColor;
uniform float uDistance;
float getGrid(float size) {
vec2 r = worldPosition.${planeAxes} / size;
vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);
float line = min(grid.x, grid.y);
return 1.0 - min(line, 1.0);
}
void main() {
float d = 1.0 - min(distance(cameraPosition.${planeAxes}, worldPosition.${planeAxes}) / uDistance, 1.0);
float g1 = getGrid(uSize1);
float g2 = getGrid(uSize2);
gl_FragColor = vec4(uColor.rgb, mix(g2, g1, g1) * pow(d, 3.0));
gl_FragColor.a = mix(0.5 * gl_FragColor.a, gl_FragColor.a, g2);
if ( gl_FragColor.a <= 0.0 ) discard;
}
`,
extensions: {
derivatives: true
}
} );
THREE.Mesh.call( this, geometry, material );
this.frustumCulled = false;
};
THREE.InfiniteGridHelper.prototype = {
...THREE.Mesh.prototype,
...THREE.Object3D.prototype,
...THREE.EventDispatcher.prototype
};
if ( parseInt( THREE.REVISION ) > 126 ) {
class InfiniteGridHelper extends THREE.Mesh {
constructor ( size1, size2, color, distance, axes = 'xzy' ) {
color = color || new THREE.Color( 'white' );
size1 = size1 || 10;
size2 = size2 || 100;
distance = distance || 8000;
const planeAxes = axes.substr( 0, 2 );
const geometry = new THREE.PlaneBufferGeometry( 2, 2, 1, 1 );
const material = new THREE.ShaderMaterial( {
side: THREE.DoubleSide,
uniforms: {
uSize1: {
value: size1
},
uSize2: {
value: size2
},
uColor: {
value: color
},
uDistance: {
value: distance
}
},
transparent: true,
vertexShader: `
varying vec3 worldPosition;
uniform float uDistance;
void main() {
vec3 pos = position.${axes} * uDistance;
pos.${planeAxes} += cameraPosition.${planeAxes};
worldPosition = pos;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: `
varying vec3 worldPosition;
uniform float uSize1;
uniform float uSize2;
uniform vec3 uColor;
uniform float uDistance;
float getGrid(float size) {
vec2 r = worldPosition.${planeAxes} / size;
vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);
float line = min(grid.x, grid.y);
return 1.0 - min(line, 1.0);
}
void main() {
float d = 1.0 - min(distance(cameraPosition.${planeAxes}, worldPosition.${planeAxes}) / uDistance, 1.0);
float g1 = getGrid(uSize1);
float g2 = getGrid(uSize2);
gl_FragColor = vec4(uColor.rgb, mix(g2, g1, g1) * pow(d, 3.0));
gl_FragColor.a = mix(0.5 * gl_FragColor.a, gl_FragColor.a, g2);
if ( gl_FragColor.a <= 0.0 ) discard;
}
`,
extensions: {
derivatives: true
}
} );
super( geometry, material );
this.frustumCulled = false;
}
}
Object.assign( InfiniteGridHelper.prototype, THREE.InfiniteGridHelper.prototype );
THREE.InfiniteGridHelper = InfiniteGridHelper;
}
// creating the scene
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth /
window.innerHeight, 0.1, 1000);
camera.position.set(0,0,5);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize',function(){
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize(width, height);
camera.aspect=window.innerWidth/ window.innerHeight;
camera.updateProjectionMatrix();
})
const controls = new OrbitControls( camera, renderer.domElement );
controls.update()
// Infinite Grid Helper
const gridHelper = new THREE.InfiniteGridHelper(10, 100);
scene.add(gridHelper);
scene.add( gridHelper );
// Create a simple cube
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshNormalMaterial(); // MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
controls.update()
}
animate();
<!DOCTYPE html>
<html>
<head>
<title>Three.js Scene</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script type="importmap"> { "imports":
{ "three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"}}
</script>
<script type="module" src="static/main.js"></script>
</body>
</html>
OrbitControls
的实施方式,我对InfiniteGridHelper
的实施进行了一些更改。因此,建议的实施如下:
import * as THREE from 'three';
class InfiniteGridHelper extends THREE.Mesh {
constructor ( size1, size2, color, distance, axes = 'xzy' ) {
color = color || new THREE.Color( 'white' );
size1 = size1 || 10;
size2 = size2 || 100;
distance = distance || 8000;
const planeAxes = axes.substr( 0, 2 );
const geometry = new THREE.PlaneGeometry( 2, 2, 1, 1 );
const material = new THREE.ShaderMaterial( {
side: THREE.DoubleSide,
uniforms: {
uSize1: {
value: size1
},
uSize2: {
value: size2
},
uColor: {
value: color
},
uDistance: {
value: distance
}
},
transparent: true,
vertexShader: `
varying vec3 worldPosition;
uniform float uDistance;
void main() {
vec3 pos = position.${axes} * uDistance;
pos.${planeAxes} += cameraPosition.${planeAxes};
worldPosition = pos;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: `
varying vec3 worldPosition;
uniform float uSize1;
uniform float uSize2;
uniform vec3 uColor;
uniform float uDistance;
float getGrid(float size) {
vec2 r = worldPosition.${planeAxes} / size;
vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);
float line = min(grid.x, grid.y);
return 1.0 - min(line, 1.0);
}
void main() {
float d = 1.0 - min(distance(cameraPosition.${planeAxes}, worldPosition.${planeAxes}) / uDistance, 1.0);
float g1 = getGrid(uSize1);
float g2 = getGrid(uSize2);
gl_FragColor = vec4(uColor.rgb, mix(g2, g1, g1) * pow(d, 3.0));
gl_FragColor.a = mix(0.5 * gl_FragColor.a, gl_FragColor.a, g2);
if ( gl_FragColor.a <= 0.0 ) discard;
}
`,
extensions: {
derivatives: true
}
} );
super( geometry, material );
this.frustumCulled = false;
}
}
export { InfiniteGridHelper };
考虑到
PlaneBufferGeometry
自 r145 以来已被弃用,我们必须将其替换为 PlaneGeometry
。
然后,我们必须将其导入到我们的脚本中:
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { InfiniteGridHelper } from './infinite-grid-helper.js';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth /
window.innerHeight, 0.1, 1000);
camera.position.set(0,0,5);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize',function(){
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize(width, height);
camera.aspect=window.innerWidth/ window.innerHeight;
camera.updateProjectionMatrix();
})
const controls = new OrbitControls( camera, renderer.domElement );
controls.update()
// Infinite Grid Helper
const gridHelper = new InfiniteGridHelper(10, 100);
scene.add(gridHelper);
scene.add( gridHelper );
// Create a simple cube
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshNormalMaterial(); // MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
controls.update()
}
animate();
最后,我们必须将其包含在 HTML 文件中:
<!DOCTYPE html>
<html>
<head>
<title>Three.js Scene</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script type="importmap"> { "imports":
{ "three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"}}
</script>
<script type="module" src="infinite-grid-helper.js"></script>
<script type="module" src="script.js"></script>
</body>
</html>
从本地服务器运行它,将产生以下结果: