Shift scene + camera closer to the center to fix precision issues

This commit is contained in:
Lukas Rieger (Blue) 2022-10-15 00:38:10 +02:00
parent f53253381c
commit 7e9f0e0bd8
No known key found for this signature in database
GPG Key ID: 2D09EC5ED2687FF2
5 changed files with 56 additions and 27 deletions

View File

@ -95,6 +95,7 @@ export class MapViewer {
this.camera = new CombinedCamera(75, 1, 0.1, 10000, 0); this.camera = new CombinedCamera(75, 1, 0.1, 10000, 0);
this.skyboxCamera = new PerspectiveCamera(75, 1, 0.1, 10000); this.skyboxCamera = new PerspectiveCamera(75, 1, 0.1, 10000);
this.skyboxCamera.updateProjectionMatrix();
this.controlsManager = new ControlsManager(this, this.camera); this.controlsManager = new ControlsManager(this, this.camera);
@ -280,12 +281,11 @@ export class MapViewer {
delta: delta, delta: delta,
}); });
//render // render
this.renderer.clear(); this.renderer.clear();
//prepare skybox camera // prepare skybox camera
this.skyboxCamera.rotation.copy(this.camera.rotation); this.skyboxCamera.rotation.copy(this.camera.rotation);
this.skyboxCamera.updateProjectionMatrix();
// render skybox // render skybox
this.renderer.render(this.skyboxScene, this.skyboxCamera); this.renderer.render(this.skyboxScene, this.skyboxCamera);
@ -293,8 +293,19 @@ export class MapViewer {
if (this.map && this.map.isLoaded) { if (this.map && this.map.isLoaded) {
//update uniforms // shift whole scene including camera towards 0,0 to tackle shader-precision issues
const s = 10000;
const sX = Math.round(this.camera.position.x / s) * s;
const sZ = Math.round(this.camera.position.z / s) * s;
this.camera.position.x -= sX;
this.camera.position.z -= sZ;
// update uniforms
this.data.uniforms.hiresTileMap.value.pos.copy(this.map.hiresTileManager.centerTile); this.data.uniforms.hiresTileMap.value.pos.copy(this.map.hiresTileManager.centerTile);
this.data.uniforms.hiresTileMap.value.translate.set(
this.map.data.hires.translate.x - sX,
this.map.data.hires.translate.z - sZ
);
// prepare camera for lowres // prepare camera for lowres
const cameraFar = this.camera.far; const cameraFar = this.camera.far;
@ -307,7 +318,10 @@ export class MapViewer {
const highestLod = this.map.lowresTileManager.length - 1; const highestLod = this.map.lowresTileManager.length - 1;
for (let i = this.map.lowresTileManager.length - 1; i >= 0; i--) { for (let i = this.map.lowresTileManager.length - 1; i >= 0; i--) {
if (i === highestLod || this.controlsManager.distance < 1000 * Math.pow(this.map.data.lowres.lodFactor, i + 1)) { if (i === highestLod || this.controlsManager.distance < 1000 * Math.pow(this.map.data.lowres.lodFactor, i + 1)) {
this.renderer.render(this.map.lowresTileManager[i].scene, this.camera); let scenePos = this.map.lowresTileManager[i].scene.position;
scenePos.x = -sX;
scenePos.z = -sZ;
this.renderer.render(this.map.lowresTileManager[i].sceneParent, this.camera);
this.renderer.clearDepth(); this.renderer.clearDepth();
} }
} }
@ -317,8 +331,16 @@ export class MapViewer {
// render hires // render hires
if (this.controlsManager.distance < 1000) { if (this.controlsManager.distance < 1000) {
this.camera.updateProjectionMatrix(); this.camera.updateProjectionMatrix();
this.renderer.render(this.map.hiresTileManager.scene, this.camera); let scenePos = this.map.hiresTileManager.scene.position;
scenePos.x = -sX;
scenePos.z = -sZ;
this.renderer.render(this.map.hiresTileManager.sceneParent, this.camera);
} }
// shift back
this.camera.position.x += sX;
this.camera.position.z += sZ;
} }
// render markers // render markers

View File

@ -117,12 +117,12 @@ export class Map {
this.hiresMaterial = this.createHiresMaterial(hiresVertexShader, hiresFragmentShader, uniforms, textures); this.hiresMaterial = this.createHiresMaterial(hiresVertexShader, hiresFragmentShader, uniforms, textures);
this.hiresTileManager = new TileManager(new Scene(), new TileLoader(`${this.data.dataUrl}tiles/0/`, this.hiresMaterial, this.data.hires, this.loadBlocker, tileCacheHash), this.onTileLoad("hires"), this.onTileUnload("hires"), this.events); this.hiresTileManager = new TileManager(new TileLoader(`${this.data.dataUrl}tiles/0/`, this.hiresMaterial, this.data.hires, this.loadBlocker, tileCacheHash), this.onTileLoad("hires"), this.onTileUnload("hires"), this.events);
this.hiresTileManager.scene.autoUpdate = false; this.hiresTileManager.scene.autoUpdate = false;
this.lowresTileManager = []; this.lowresTileManager = [];
for (let i = 0; i < this.data.lowres.lodCount; i++) { for (let i = 0; i < this.data.lowres.lodCount; i++) {
this.lowresTileManager[i] = new TileManager(new Scene(), new LowresTileLoader(`${this.data.dataUrl}tiles/`, this.data.lowres, i + 1, lowresVertexShader, lowresFragmentShader, uniforms, async () => {}, tileCacheHash), this.onTileLoad("lowres"), this.onTileUnload("lowres"), this.events); this.lowresTileManager[i] = new TileManager(new LowresTileLoader(`${this.data.dataUrl}tiles/`, this.data.lowres, i + 1, lowresVertexShader, lowresFragmentShader, uniforms, async () => {}, tileCacheHash), this.onTileLoad("lowres"), this.onTileUnload("lowres"), this.events);
this.lowresTileManager[i].scene.autoUpdate = false; this.lowresTileManager[i].scene.autoUpdate = false;
} }

View File

@ -22,7 +22,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
import { Vector2 } from 'three'; import { Vector2, Scene, Group } from 'three';
import { Tile } from './Tile.js'; import { Tile } from './Tile.js';
import {alert, hashTile} from '../util/Utils.js'; import {alert, hashTile} from '../util/Utils.js';
import {TileMap} from "./TileMap"; import {TileMap} from "./TileMap";
@ -33,17 +33,19 @@ export class TileManager {
static tileMapHalfSize = TileManager.tileMapSize / 2; static tileMapHalfSize = TileManager.tileMapSize / 2;
/** /**
* @param scene {THREE.Scene}
* @param tileLoader {TileLoader | LowresTileLoader} * @param tileLoader {TileLoader | LowresTileLoader}
* @param onTileLoad {function(Tile)} * @param onTileLoad {function(Tile)}
* @param onTileUnload {function(Tile)} * @param onTileUnload {function(Tile)}
* @param events {EventTarget} * @param events {EventTarget}
*/ */
constructor(scene, tileLoader, onTileLoad = null, onTileUnload = null, events = null) { constructor(tileLoader, onTileLoad = null, onTileUnload = null, events = null) {
Object.defineProperty( this, 'isTileManager', { value: true } ); Object.defineProperty( this, 'isTileManager', { value: true } );
this.sceneParent = new Scene();
this.scene = new Group();
this.sceneParent.add(this.scene);
this.events = events; this.events = events;
this.scene = scene;
this.tileLoader = tileLoader; this.tileLoader = tileLoader;
this.onTileLoad = onTileLoad || function(){}; this.onTileLoad = onTileLoad || function(){};

View File

@ -33,30 +33,23 @@ attribute float sunlight;
attribute float blocklight; attribute float blocklight;
varying vec3 vPosition; varying vec3 vPosition;
//varying vec3 vWorldPosition;
varying vec3 vNormal; varying vec3 vNormal;
varying vec2 vUv; varying vec2 vUv;
varying vec3 vColor; varying vec3 vColor;
varying float vAo; varying float vAo;
varying float vSunlight; varying float vSunlight;
varying float vBlocklight; varying float vBlocklight;
//varying float vDistance;
void main() { void main() {
vec4 worldPos = modelMatrix * vec4(position, 1);
vec4 viewPos = viewMatrix * worldPos;
vPosition = position; vPosition = position;
//vWorldPosition = worldPos.xyz;
vNormal = normal; vNormal = normal;
vUv = uv; vUv = uv;
vColor = color; vColor = color;
vAo = ao; vAo = ao;
vSunlight = sunlight; vSunlight = sunlight;
vBlocklight = blocklight; vBlocklight = blocklight;
//vDistance = -viewPos.z
gl_Position = projectionMatrix * viewPos; gl_Position = projectionMatrix * (viewMatrix * modelMatrix * vec4(position, 1));
${ShaderChunk.logdepthbuf_vertex} ${ShaderChunk.logdepthbuf_vertex}
} }

View File

@ -36,6 +36,8 @@ export class CombinedCamera extends PerspectiveCamera {
constructor(fov, aspect, near, far, ortho) { constructor(fov, aspect, near, far, ortho) {
super(fov, aspect, near, far); super(fov, aspect, near, far);
this.needsUpdate = true;
this.data = { this.data = {
fov: this.fov, fov: this.fov,
aspect: this.aspect, aspect: this.aspect,
@ -49,29 +51,31 @@ export class CombinedCamera extends PerspectiveCamera {
// redirect parent properties // redirect parent properties
Object.defineProperty(this, "fov", { Object.defineProperty(this, "fov", {
get() { return this.data.fov }, get() { return this.data.fov },
set(value) { this.data.fov = value } set(value) { if (value !== this.data.fov) { this.data.fov = value; this.needsUpdate = true }}
}); });
Object.defineProperty(this, "aspect", { Object.defineProperty(this, "aspect", {
get() { return this.data.aspect }, get() { return this.data.aspect },
set(value) { this.data.aspect = value } set(value) { if (value !== this.data.aspect) { this.data.aspect = value; this.needsUpdate = true }}
}); });
Object.defineProperty(this, "near", { Object.defineProperty(this, "near", {
get() { return this.data.near }, get() { return this.data.near },
set(value) { this.data.near = value } set(value) { if (value !== this.data.near) { this.data.near = value; this.needsUpdate = true }}
}); });
Object.defineProperty(this, "far", { Object.defineProperty(this, "far", {
get() { return this.data.far }, get() { return this.data.far },
set(value) { this.data.far = value } set(value) { if (value !== this.data.far) { this.data.far = value; this.needsUpdate = true }}
}); });
Object.defineProperty(this, "zoom", { Object.defineProperty(this, "zoom", {
get() { return this.data.zoom }, get() { return this.data.zoom },
set(value) { this.data.zoom = value } set(value) { if (value !== this.data.zoom) { this.data.zoom = value; this.needsUpdate = true }}
}); });
this.updateProjectionMatrix(); this.updateProjectionMatrix();
} }
updateProjectionMatrix() { updateProjectionMatrix() {
if (!this.needsUpdate) return;
if (!this.ortographicProjection) if (!this.ortographicProjection)
this.ortographicProjection = new Matrix4(); this.ortographicProjection = new Matrix4();
@ -121,6 +125,7 @@ export class CombinedCamera extends PerspectiveCamera {
this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
this.needsUpdate = false;
} }
/** /**
@ -162,7 +167,10 @@ export class CombinedCamera extends PerspectiveCamera {
* @param value {number} * @param value {number}
*/ */
set ortho(value) { set ortho(value) {
if (value !== this.data.ortho){
this.data.ortho = value; this.data.ortho = value;
this.needsUpdate = true;
}
} }
/** /**
@ -176,6 +184,10 @@ export class CombinedCamera extends PerspectiveCamera {
* @param value {number} * @param value {number}
*/ */
set distance(value) { set distance(value) {
if (value !== this.data.distance) {
this.data.distance = value; this.data.distance = value;
this.needsUpdate = true;
} }
}
} }