diff --git a/BlueMapCommon/webapp/public/lang/en.conf b/BlueMapCommon/webapp/public/lang/en.conf index 31107a95..b3fbdfd9 100644 --- a/BlueMapCommon/webapp/public/lang/en.conf +++ b/BlueMapCommon/webapp/public/lang/en.conf @@ -83,6 +83,9 @@ light: "Light" contrast: "Contrast" } + chunkBorders: { + button: "Show chunk borders" + } debug: { button: "Debug" } diff --git a/BlueMapCommon/webapp/public/lang/nl.conf b/BlueMapCommon/webapp/public/lang/nl.conf index b196b593..f79eb64b 100644 --- a/BlueMapCommon/webapp/public/lang/nl.conf +++ b/BlueMapCommon/webapp/public/lang/nl.conf @@ -83,6 +83,9 @@ light: "Licht" contrast: "Contrast" } + chunkBorders: { + button: "Laat chunk grenzen zien" + } debug: { button: "Debug" } diff --git a/BlueMapCommon/webapp/src/components/Menu/SettingsMenu.vue b/BlueMapCommon/webapp/src/components/Menu/SettingsMenu.vue index 155f2e61..8cc6e45e 100644 --- a/BlueMapCommon/webapp/src/components/Menu/SettingsMenu.vue +++ b/BlueMapCommon/webapp/src/components/Menu/SettingsMenu.vue @@ -56,6 +56,8 @@ >{{lang.name}} + {{ $t("chunkBorders.button") }} + {{ $t("debug.button") }} {{ $t("resetAllSettings.button") }} @@ -105,6 +107,9 @@ name: "SettingsMenu", } }, methods: { + switchChunkBorders() { + this.$bluemap.setChunkBorders(!this.mapViewer.uniforms.chunkBorders.value); + }, switchDebug() { this.$bluemap.setDebug(!this.appState.debug); }, @@ -121,4 +126,4 @@ name: "SettingsMenu", \ No newline at end of file + diff --git a/BlueMapCommon/webapp/src/js/BlueMapApp.js b/BlueMapCommon/webapp/src/js/BlueMapApp.js index dc0ba1aa..27b70744 100644 --- a/BlueMapCommon/webapp/src/js/BlueMapApp.js +++ b/BlueMapCommon/webapp/src/js/BlueMapApp.js @@ -525,6 +525,10 @@ export class BlueMapApp { this.appState.controls.state = "free"; } + setChunkBorders(chunkBorders) { + this.mapViewer.data.uniforms.chunkBorders.value = chunkBorders; + } + setDebug(debug) { this.appState.debug = debug; @@ -608,6 +612,7 @@ export class BlueMapApp { this.setTheme(this.loadUserSetting("theme", this.appState.theme)); this.setScreenshotClipboard(this.loadUserSetting("screenshotClipboard", this.appState.screenshot.clipboard)); await setLanguage(this.loadUserSetting("lang", i18n.locale.value)); + this.setChunkBorders(this.loadUserSetting("chunkBorders", this.mapViewer.data.uniforms.chunkBorders.value)) this.setDebug(this.loadUserSetting("debug", this.appState.debug)); alert(this.events, "Settings loaded!", "info"); @@ -629,6 +634,7 @@ export class BlueMapApp { this.saveUserSetting("theme", this.appState.theme); this.saveUserSetting("screenshotClipboard", this.appState.screenshot.clipboard); this.saveUserSetting("lang", i18n.locale.value); + this.saveUserSetting("chunkBorders", this.mapViewer.data.uniforms.chunkBorders.value); this.saveUserSetting("debug", this.appState.debug); alert(this.events, "Settings saved!", "info"); diff --git a/BlueMapCommon/webapp/src/js/MapViewer.js b/BlueMapCommon/webapp/src/js/MapViewer.js index c29bd9bd..868b4563 100644 --- a/BlueMapCommon/webapp/src/js/MapViewer.js +++ b/BlueMapCommon/webapp/src/js/MapViewer.js @@ -61,6 +61,7 @@ export class MapViewer { ambientLight: { value: 0 }, skyColor: { value: new Color(0.5, 0.5, 1) }, voidColor: { value: new Color(0, 0, 0) }, + chunkBorders: { value: false }, hiresTileMap: { value: { map: null, diff --git a/BlueMapCommon/webapp/src/js/map/hires/HiresFragmentShader.js b/BlueMapCommon/webapp/src/js/map/hires/HiresFragmentShader.js index 5fa5da16..e50c75d9 100644 --- a/BlueMapCommon/webapp/src/js/map/hires/HiresFragmentShader.js +++ b/BlueMapCommon/webapp/src/js/map/hires/HiresFragmentShader.js @@ -24,6 +24,7 @@ */ import { ShaderChunk } from 'three'; +// language=GLSL export const HIRES_FRAGMENT_SHADER = ` ${ShaderChunk.logdepthbuf_pars_fragment} @@ -31,6 +32,7 @@ ${ShaderChunk.logdepthbuf_pars_fragment} #define texture texture2D #endif +uniform float distance; uniform sampler2D textureImage; uniform float sunlightStrength; uniform float ambientLight; @@ -38,9 +40,10 @@ uniform float animationFrameHeight; uniform float animationFrameIndex; uniform float animationInterpolationFrameIndex; uniform float animationInterpolation; +uniform bool chunkBorders; varying vec3 vPosition; -//varying vec3 vWorldPosition; +varying vec3 vWorldPosition; varying vec3 vNormal; varying vec2 vUv; varying vec3 vColor; @@ -68,6 +71,25 @@ void main() { float light = mix(vBlocklight, max(vSunlight, vBlocklight), sunlightStrength); color.rgb *= mix(ambientLight, 1.0, light / 15.0); + if (chunkBorders) { + vec4 lineColour = vec4(1.0, 0.0, 1.0, 0.4); + float lineInterval = 16.0; + float lineThickness = 0.125; //width of two Minecraft pixels + float offset = 0.5; + + vec2 worldPos = vWorldPosition.xz; + worldPos += offset; + float x = abs(mod(worldPos.x, lineInterval) - offset); + float y = abs(mod(worldPos.y, lineInterval) - offset); + bool isChunkBorder = x < lineThickness || y < lineThickness; + + //only show line on upwards facing surfaces + bool showChunkBorder = isChunkBorder && vNormal.y > 0.1; + + float distFac = smoothstep(200.0, 600.0, distance); + color.rgb = mix(mix(color.rgb, lineColour.rgb, float(showChunkBorder) * lineColour.a), color.rgb, distFac); + } + gl_FragColor = color; ${ShaderChunk.logdepthbuf_fragment} diff --git a/BlueMapCommon/webapp/src/js/map/hires/HiresVertexShader.js b/BlueMapCommon/webapp/src/js/map/hires/HiresVertexShader.js index d919f420..ed15ccbf 100644 --- a/BlueMapCommon/webapp/src/js/map/hires/HiresVertexShader.js +++ b/BlueMapCommon/webapp/src/js/map/hires/HiresVertexShader.js @@ -33,6 +33,7 @@ attribute float sunlight; attribute float blocklight; varying vec3 vPosition; +varying vec3 vWorldPosition; varying vec3 vNormal; varying vec2 vUv; varying vec3 vColor; @@ -42,6 +43,8 @@ varying float vBlocklight; void main() { vPosition = position; + vec4 worldPos = modelMatrix * vec4(vPosition, 1); + vWorldPosition = worldPos.xyz; vNormal = normal; vUv = uv; vColor = color; diff --git a/BlueMapCommon/webapp/src/js/map/lowres/LowresFragmentShader.js b/BlueMapCommon/webapp/src/js/map/lowres/LowresFragmentShader.js index 095d2b5a..da702b8a 100644 --- a/BlueMapCommon/webapp/src/js/map/lowres/LowresFragmentShader.js +++ b/BlueMapCommon/webapp/src/js/map/lowres/LowresFragmentShader.js @@ -24,6 +24,7 @@ */ import { ShaderChunk } from 'three'; +// language=GLSL export const LOWRES_FRAGMENT_SHADER = ` ${ShaderChunk.logdepthbuf_pars_fragment} @@ -51,6 +52,7 @@ uniform vec2 textureSize; uniform float lod; uniform float lodScale; uniform vec3 voidColor; +uniform bool chunkBorders; varying vec3 vPosition; varying vec3 vWorldPosition; @@ -98,9 +100,10 @@ void main() { float ao = 0.0; float aoStrength = 0.0; + float distFac = smoothstep(200.0, 600.0, distance); if(lod == 1.0) { aoStrength = smoothstep(PI - 0.8, PI - 0.2, acos(-clamp(viewMatrix[1][2], 0.0, 1.0))); - aoStrength *= 1.0 - smoothstep(200.0, 600.0, distance); + aoStrength *= 1.0 - distFac; if (aoStrength > 0.0) { const float r = 3.0; @@ -123,6 +126,21 @@ void main() { float light = mix(blockLight, 15.0, sunlightStrength); color.rgb *= mix(ambientLight, 1.0, light / 15.0); + if (chunkBorders) { + vec4 lineColour = vec4(1.0, 0.0, 1.0, 0.4); + float lineInterval = 16.0; + float lineThickness = 0.125; //width of two Minecraft pixels + float offset = 0.5; + + vec2 worldPos = vWorldPosition.xz; + worldPos += offset; + float x = abs(mod(worldPos.x, lineInterval) - offset); + float y = abs(mod(worldPos.y, lineInterval) - offset); + bool isChunkBorder = x < lineThickness || y < lineThickness; + + color.rgb = mix(mix(color.rgb, lineColour.rgb, float(isChunkBorder) * lineColour.a), color.rgb, distFac); + } + vec3 adjustedVoidColor = adjustColor(voidColor); //where there's transparency, there is void that needs to be coloured color.rgb = mix(adjustedVoidColor, color.rgb, color.a);