【发布时间】:2020-09-07 12:49:29
【问题描述】:
这是带有 THREE.LOD() 对象的 Three.JS 小草图。 如您所见,共有 4 个级别具有独特的纹理。
现在,所有这些纹理都是在启动时预加载的。
有什么方法可以在放大时动态加载 1、2、3 级纹理?
是的,我可以在没有 THREE.LOD() 的情况下做同样的事情,只需编写我自己的自定义算法,该算法会在缩放时生成/删除平面,但我对内置的 THREE.LOD() 非常感兴趣。
var folder = "http://vault.vkuchinov.co.uk/test/assets";
var levels = [0xF25E6B, 0x4EA6A6, 0x8FD9D1, 0xF2B29B, 0xF28E85];
var renderer, scene, camera, controls, loader, lod, glsl, uniforms;
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
loader = new THREE.TextureLoader();
loader.crossOrigin = "";
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 51200);
camera.position.set(-2048, 2048, -2048);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 8;
controls.maxDistance = 5120;
controls.maxPolarAngle = Math.PI / 2;
lod = new THREE.LOD();
lod.name = "0,0";
generateTiles(lod, 2048, 2048, 2048, 0, 0x00FFFF);
scene.add(lod);
animate();
function animate(){
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
function generateTiles(parent_, width_, height_, zoom_, level_, hex_){
var id = parent_.name.split(",");
var colors = [0xFFFF00, 0xFF000, 0x00FF00, 0x0000FF, 0xFF00FF, 0xF0F0F0];
var group = new THREE.Group(), geometry, plane;
var dx = 0, dy = 0;
dy *= Math.pow(2, level_); dx *= Math.pow(2, level_);
var url = folder + "/textures/level" + level_ + "/" + id[0] + "_" + id[1] + ".jpg";
if(level_ < 3){
var uniforms = {
satellite: {
type: "t",
value: loader.load(url)
}
};
var glsl = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById("vertexTerrain").textContent,
fragmentShader: document.getElementById("fragmentTerrain").textContent,
lights: false,
fog: false,
transparent: true
});
glsl.extensions.derivatives = true;
geometry = new THREE.PlaneGeometry(width_, height_, 256, 256);
plane = new THREE.Mesh(geometry, glsl);
plane.rotation.set(-Math.PI / 2, 0, 0);
parent_.addLevel(plane, zoom_);
geometry = new THREE.PlaneGeometry(width_ / 2, height_ / 2, 128, 128);
var ix = (Number(id[0]) * 2);
var iy = (Number(id[1]) * 2);
var lod1 = new THREE.LOD();
var url1 = getURL(ix + "," + iy, width_ / 2, height_ / 2, zoom_ / 2, level_ + 1);
var uniforms1 = {
satellite: {
type: "t",
value: loader.load(url1)
}
};
var glsl1 = new THREE.ShaderMaterial({
uniforms: uniforms1,
vertexShader: document.getElementById("vertexTerrain").textContent,
fragmentShader: document.getElementById("fragmentTerrain").textContent,
lights: false,
fog: false,
transparent: true
});
glsl1.extensions.derivatives = true;
plane = new THREE.Mesh(geometry, glsl1);
plane.rotation.set(-Math.PI / 2, 0, 0);
lod1.addLevel(plane, zoom_ / 2);
lod1.position.set(-width_ / 4, 0, -height_ / 4);
lod1.name = ix + "," + iy;
group.add(lod1);
var lod2 = new THREE.LOD();
var url2 = getURL(ix + "," + (iy + 1), width_ / 2, height_ / 2, zoom_ / 2, level_ + 1);
var uniforms2 = {
satellite: {
type: "t",
value: loader.load(url2)
}
};
var glsl2 = new THREE.ShaderMaterial({
uniforms: uniforms2,
vertexShader: document.getElementById("vertexTerrain").textContent,
fragmentShader: document.getElementById("fragmentTerrain").textContent,
lights: false,
fog: false,
transparent: true
});
glsl2.extensions.derivatives = true;
plane = new THREE.Mesh(geometry, glsl2);
plane.rotation.set(-Math.PI / 2, 0, 0);
lod2.addLevel(plane, zoom_ / 2);
lod2.position.set(width_ / 4, 0, -height_ / 4);
lod2.name = ix + "," + (iy + 1);
group.add(lod2);
var lod3 = new THREE.LOD();
var url3 = getURL((ix + 1) + "," + iy, width_ / 2, height_ / 2, zoom_ / 2, level_ + 1);
var uniforms3 = {
satellite: {
type: "t",
value: loader.load(url3)
}
};
var glsl3 = new THREE.ShaderMaterial({
uniforms: uniforms3,
vertexShader: document.getElementById("vertexTerrain").textContent,
fragmentShader: document.getElementById("fragmentTerrain").textContent,
lights: false,
fog: false,
transparent: true
});
glsl3.extensions.derivatives = true;
plane = new THREE.Mesh(geometry, glsl3);
plane.rotation.set(-Math.PI / 2, 0, 0);
lod3.addLevel(plane, zoom_ / 2);
lod3.position.set(-width_ / 4, 0, height_ / 4);
lod3.name = (ix + 1) + "," + iy;
group.add(lod3);
var lod4 = new THREE.LOD();
var url4 = getURL((ix + 1) + "," + (iy + 1), width_ / 2, height_ / 2, zoom_ / 2, level_ + 1);
var uniforms4 = {
satellite: {
type: "t",
value: loader.load(url4)
}
};
var glsl4 = new THREE.ShaderMaterial({
uniforms: uniforms4,
vertexShader: document.getElementById("vertexTerrain").textContent,
fragmentShader: document.getElementById("fragmentTerrain").textContent,
lights: false,
fog: false,
transparent: true
});
glsl4.extensions.derivatives = true;
plane = new THREE.Mesh(geometry, glsl4);
plane.rotation.set(-Math.PI / 2, 0, 0);
lod4.addLevel(plane, zoom_ / 2);
lod4.position.set(width_ / 4, 0, height_ / 4);
lod4.name = (ix + 1) + "," + (iy + 1);
group.add(lod4);
parent_.addLevel(group, zoom_ / 2);
generateTiles(lod1, width_ / 2, height_ / 2, zoom_ / 2, level_ + 1, colors[level_]);
generateTiles(lod2, width_ / 2, height_ / 2, zoom_ / 2, level_ + 1, colors[level_]);
generateTiles(lod3, width_ / 2, height_ / 2, zoom_ / 2, level_ + 1, colors[level_]);
generateTiles(lod4, width_ / 2, height_ / 2, zoom_ / 2, level_ + 1, colors[level_]);
}
}
function getURL(name_, width_, height_, zoom_, level_){
var id = name_.split(",");
return folder + "/textures/level" + level_ + "/" + id[0] + "_" + id[1] + ".jpg";
}
body { margin: 0; }
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>GLSL Intersection</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://unpkg.com/three@0.116.0/build/three.min.js"></script>
<script src="https://unpkg.com/three@0.116.0/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
<script id="vertexTerrain" type="x-shader/x-vertex">
uniform sampler2D satellite;
varying vec2 vUv;
void main() {
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script id="fragmentTerrain" type="x-shader/x-fragment">
precision highp float;
precision highp int;
uniform sampler2D satellite;
varying vec2 vUv;
void main() {
gl_FragColor = texture2D(satellite, vUv);
}
</script>
</body>
</html>
【问题讨论】:
标签: three.js textures zooming levels