From d12c48275f168dbbf05be92c7c46667a8487f5ca Mon Sep 17 00:00:00 2001 From: "Lukas Rieger (Blue)" Date: Mon, 8 Aug 2022 21:31:28 +0200 Subject: [PATCH] First basic support for lowres changes --- src/MapViewer.js | 2 +- src/map/LowresTileLoader.js | 115 +++++++++++++++++++++++++ src/map/Map.js | 5 +- src/map/TileManager.js | 4 +- src/map/lowres/LowresFragmentShader.js | 27 ++++-- src/map/lowres/LowresVertexShader.js | 16 ++-- src/util/Utils.js | 2 +- 7 files changed, 152 insertions(+), 19 deletions(-) create mode 100644 src/map/LowresTileLoader.js diff --git a/src/MapViewer.js b/src/MapViewer.js index 2d08521..a391524 100644 --- a/src/MapViewer.js +++ b/src/MapViewer.js @@ -291,7 +291,7 @@ export class MapViewer { this.renderer.render(this.map.lowresTileManager.scene, this.camera); this.renderer.clearDepth(); - if (this.controlsManager.distance < 2000) { + if (this.controlsManager.distance < 1000) { this.renderer.render(this.map.hiresTileManager.scene, this.camera); } } diff --git a/src/map/LowresTileLoader.js b/src/map/LowresTileLoader.js new file mode 100644 index 0000000..593e5f4 --- /dev/null +++ b/src/map/LowresTileLoader.js @@ -0,0 +1,115 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +import {pathFromCoords} from "../util/Utils"; +import { + TextureLoader, + Mesh, + PlaneBufferGeometry, + VertexColors, + FrontSide, + ShaderMaterial, + NearestFilter, + ClampToEdgeWrapping, + NearestMipMapLinearFilter, + RepeatWrapping, +} from "three"; + +export class LowresTileLoader { + + constructor(tilePath, vertexShader, fragmentShader, tileCacheHash = 0, layer = 0) { + Object.defineProperty( this, 'isLowresTileLoader', { value: true } ); + + this.tilePath = tilePath; + this.layer = layer; + this.tileCacheHash = tileCacheHash; + + this.vertexShader = vertexShader; + this.fragmentShader = fragmentShader; + + this.textureLoader = new TextureLoader(); + this.geometry = new PlaneBufferGeometry( + 500, 500, + 100, 100 + ); + this.geometry.deleteAttribute('normal'); + this.geometry.deleteAttribute('uv'); + this.geometry.rotateX(-Math.PI / 2); + this.geometry.translate(250, 0, 250); + } + + load = (tileX, tileZ) => { + let tileUrl = this.tilePath + pathFromCoords(tileX, tileZ) + '.png'; + + return new Promise((resolve, reject) => { + this.textureLoader.load(tileUrl + '?' + this.tileCacheHash, + texture => { + texture.anisotropy = 1; + texture.generateMipmaps = false; + texture.magFilter = NearestFilter; + texture.minFilter = texture.generateMipmaps ? NearestMipMapLinearFilter : NearestFilter; + texture.wrapS = ClampToEdgeWrapping; + texture.wrapT = ClampToEdgeWrapping; + texture.flipY = false; + texture.flatShading = true; + + let material = new ShaderMaterial({ + uniforms: { + textureImage: { + type: 't', + value: texture + } + }, + vertexShader: this.vertexShader, + fragmentShader: this.fragmentShader, + transparent: false, + depthWrite: true, + depthTest: true, + vertexColors: VertexColors, + side: FrontSide, + wireframe: false, + }); + + let object = new Mesh(this.geometry, material); + if (this.layer) object.layers.set(this.layer); + + let tileSize = {x:500, z:500}; + let translate = {x:0, z:0}; + let scale = {x:1, z:1}; + object.position.set(tileX * tileSize.x + translate.x, 0, tileZ * tileSize.z + translate.z); + object.scale.set(scale.x, 1, scale.z); + + object.userData.tileUrl = tileUrl; + + object.updateMatrixWorld(true); + + resolve(object); + }, + undefined, + reject + ); + }); + } + +} diff --git a/src/map/Map.js b/src/map/Map.js index 0827be3..6188c39 100644 --- a/src/map/Map.js +++ b/src/map/Map.js @@ -39,6 +39,7 @@ import { import {alert, dispatchEvent, generateCacheHash, hashTile, stringToImage, vecArrToObj} from "../util/Utils"; import {TileManager} from "./TileManager"; import {TileLoader} from "./TileLoader"; +import {LowresTileLoader} from "./LowresTileLoader"; export class Map { @@ -114,8 +115,8 @@ export class Map { this.hiresMaterial = this.createHiresMaterial(hiresVertexShader, hiresFragmentShader, uniforms, textures); - this.hiresTileManager = new TileManager(new Scene(), new TileLoader(`${this.data.dataUrl}hires/`, this.hiresMaterial, this.data.hires, tileCacheHash), this.onTileLoad("hires"), this.onTileUnload("hires"), this.events); - this.lowresTileManager = new TileManager(new Scene(), new TileLoader(`${this.data.dataUrl}lowres/`, this.lowresMaterial, this.data.lowres, tileCacheHash), this.onTileLoad("lowres"), this.onTileUnload("lowres"), this.events); + this.hiresTileManager = new TileManager(new Scene(), new TileLoader(`${this.data.dataUrl}tiles/0/`, this.hiresMaterial, this.data.hires, tileCacheHash), this.onTileLoad("hires"), this.onTileUnload("hires"), this.events); + this.lowresTileManager = new TileManager(new Scene(), new LowresTileLoader(`${this.data.dataUrl}tiles/1/`, lowresVertexShader, lowresFragmentShader, tileCacheHash), this.onTileLoad("lowres"), this.onTileUnload("lowres"), this.events); this.hiresTileManager.scene.autoUpdate = false; this.lowresTileManager.scene.autoUpdate = false; diff --git a/src/map/TileManager.js b/src/map/TileManager.js index c7837b6..3f6d76a 100644 --- a/src/map/TileManager.js +++ b/src/map/TileManager.js @@ -34,7 +34,7 @@ export class TileManager { /** * @param scene {THREE.Scene} - * @param tileLoader {TileLoader} + * @param tileLoader {TileLoader | LowresTileLoader} * @param onTileLoad {function(Tile)} * @param onTileUnload {function(Tile)} * @param events {EventTarget} @@ -197,7 +197,7 @@ export class TileManager { if (error.target && error.target.status === 404) return; if (error.type && error.type === "abort") return; - alert(this.events, "Failed to load tile: " + error, "warning"); + //alert(this.events, "Failed to load tile: " + error.type, "warning"); }) .finally(() => { this.tileMap.setTile(tile.x - this.centerTile.x + TileManager.tileMapHalfSize, tile.z - this.centerTile.y + TileManager.tileMapHalfSize, TileMap.LOADED); diff --git a/src/map/lowres/LowresFragmentShader.js b/src/map/lowres/LowresFragmentShader.js index 5110dcc..8659176 100644 --- a/src/map/lowres/LowresFragmentShader.js +++ b/src/map/lowres/LowresFragmentShader.js @@ -39,9 +39,10 @@ struct TileMap { vec2 pos; }; -uniform float sunlightStrength; -uniform float ambientLight; -uniform TileMap hiresTileMap; +//uniform float sunlightStrength; +//uniform float ambientLight; +//uniform TileMap hiresTileMap; +uniform sampler2D textureImage; varying vec3 vPosition; varying vec3 vWorldPosition; @@ -52,15 +53,25 @@ varying float vDistance; void main() { //discard if hires tile is loaded at that position - if (vDistance < 1900.0 && texture(hiresTileMap.map, ((vWorldPosition.xz - hiresTileMap.translate) / hiresTileMap.scale - hiresTileMap.pos) / hiresTileMap.size + 0.5).r >= 1.0) discard; + //if (vDistance < 1900.0 && texture(hiresTileMap.map, ((vWorldPosition.xz - hiresTileMap.translate) / hiresTileMap.scale - hiresTileMap.pos) / hiresTileMap.size + 0.5).r >= 1.0) discard; - vec4 color = vec4(vColor, 1.0); + //vec4 color = vec4(vColor, 1.0); - float diff = max(dot(vNormal, vec3(0.3637, 0.7274, 0.5819)), 0.0) * 0.3 + 0.7; - color *= diff; + //float diff = max(dot(vNormal, vec3(0.3637, 0.7274, 0.5819)), 0.0) * 0.3 + 0.7; + //color *= diff; - color *= mix(sunlightStrength, 1.0, ambientLight); + //color *= mix(sunlightStrength, 1.0, ambientLight); + //vec4 color = vec4(0.3637, 0.7274, 0.5819, 1.0); + vec4 color = texture(textureImage, vec2(vPosition.x / 500.0, vPosition.z / 1000.0)); + + float height = texture(textureImage, vec2(vPosition.x / 500.0, (vPosition.z + 500.0) / 1000.0)).b * 255.0; + float heightX = texture(textureImage, vec2((vPosition.x + 1.0) / 500.0, (vPosition.z + 500.0) / 1000.0)).b * 255.0; + float heightZ = texture(textureImage, vec2(vPosition.x / 500.0, (vPosition.z + 501.0) / 1000.0)).b * 255.0; + float diff = (height - heightX) + (height - heightZ); + + color.rgb += clamp(diff * 0.04, -0.2, 0.04); + gl_FragColor = color; ${ShaderChunk.logdepthbuf_fragment} diff --git a/src/map/lowres/LowresVertexShader.js b/src/map/lowres/LowresVertexShader.js index 22f21c6..6ab35d3 100644 --- a/src/map/lowres/LowresVertexShader.js +++ b/src/map/lowres/LowresVertexShader.js @@ -28,6 +28,8 @@ export const LOWRES_VERTEX_SHADER = ` #include ${ShaderChunk.logdepthbuf_pars_vertex} +uniform sampler2D textureImage; + varying vec3 vPosition; varying vec3 vWorldPosition; varying vec3 vNormal; @@ -36,14 +38,18 @@ varying vec3 vColor; varying float vDistance; void main() { - vec4 worldPos = modelMatrix * vec4(position, 1); + vPosition = position; + + vec4 color = texture(textureImage, vec2(position.x / 500.0, (position.z + 500.0) / 1000.0)); + vPosition.y += color.b * 255.0; + + vec4 worldPos = modelMatrix * vec4(vPosition, 1); vec4 viewPos = viewMatrix * worldPos; - vPosition = position; vWorldPosition = worldPos.xyz; - vNormal = normal; - vUv = uv; - vColor = color; + //vNormal = normal; + //vUv = uv; + //vColor = color; vDistance = -viewPos.z; gl_Position = projectionMatrix * viewPos; diff --git a/src/util/Utils.js b/src/util/Utils.js index 72ae605..7d18426 100644 --- a/src/util/Utils.js +++ b/src/util/Utils.js @@ -374,7 +374,7 @@ export const softClamp = (value, min, max, stiffness) => { } export const vecArrToObj = (val, useZ = false) => { - if (val.length >= 2) { + if (val && val.length >= 2) { if (useZ) return {x: val[0], z: val[1]}; return {x: val[0], y: val[1]}; }