Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/core/game/game.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ LOADING_MANAGER.onLoad = () => {
/** @typedef {(state: State, action: Type.Action) => State} Reducer */
/** @typedef {(context: Context) => void} Observer */
/** @typedef {(state: State, context: Context, delta: number) => void} Ticker */
/** @typedef {(context: Context) => void} PostRenderCallback */
/** @typedef {(state: State, context: Context) => void} PostRenderCallback */
/** @typedef {() => { reduce?: Reducer, observe?: Observer, tick?: Ticker, post_render?: PostRenderCallback }} Module */
/** @typedef {import("three").AnimationAction} AnimAction */

Expand Down Expand Up @@ -351,8 +351,8 @@ const MODULES = [
game_audio,
game_entities,
game_terrain,
game_minimap,
game_water,
game_minimap,
game_connect,
game_entites_stroll,
game_damage_ui,
Expand Down Expand Up @@ -711,7 +711,7 @@ function animate() {
modules
.map(({ post_render }) => post_render)
.filter(Boolean)
.forEach(post_render => post_render(context))
.forEach(post_render => post_render(state, context))

const next_frame_duration = 1000 / state.settings.target_fps

Expand Down
12 changes: 1 addition & 11 deletions src/core/game/rendering/underwater_pass.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
Color,
NoBlending,
PerspectiveCamera,
RawShaderMaterial,
Expand All @@ -21,8 +20,6 @@ class UnderwaterPass extends Pass {
this.#camera = new PerspectiveCamera()
this.needsSwap = true

this.color = new Color(0x3f7be2)

const noise = `// Simplex 3D Noise
// by Ian McEwan, Ashima Arts
//
Expand Down Expand Up @@ -104,7 +101,6 @@ class UnderwaterPass extends Pass {
depthWrite: false,
uniforms: {
uTexture: { value: null },
uColor: { value: this.color },
uTime: { value: 0 },
uAspectRatio: { value: 1 },
},
Expand All @@ -119,7 +115,6 @@ class UnderwaterPass extends Pass {
fragmentShader: `precision mediump float;

uniform sampler2D uTexture;
uniform vec3 uColor;
uniform float uTime;
uniform float uAspectRatio;

Expand All @@ -143,7 +138,7 @@ class UnderwaterPass extends Pass {
uv = fract(vUv + dUv);
uv = clamp(uv, vec2(0), vec2(1));

gl_FragColor = vec4(uColor, 1) * texture2D(uTexture, uv);
gl_FragColor = texture2D(uTexture, uv);
}`,
})

Expand All @@ -162,11 +157,6 @@ class UnderwaterPass extends Pass {

renderer.setRenderTarget(this.renderToScreen ? null : write_buffer)
this.#material.uniforms.uTexture.value = read_buffer.texture
this.#material.uniforms.uColor.value = new Color().lerpColors(
this.color,
new Color(0xffffff),
0.15,
)
this.#material.uniforms.uTime.value = performance.now() / 3000
this.#material.uniforms.uAspectRatio.value =
read_buffer.width / read_buffer.height
Expand Down
9 changes: 7 additions & 2 deletions src/core/modules/game_camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ const CAMERA_MAX_DISTANCE = 50
/** @type {Type.Module} */
export default function () {
return {
tick(state, { camera_controls, dispatch, camera, physics }, delta) {
tick(
state,
{ camera_controls, dispatch, camera, physics, voxel_engine },
delta,
) {
const player = current_three_character(state)
if (!player?.position) return

Expand All @@ -40,7 +44,8 @@ export default function () {
}
camera_controls.update(delta)

const is_underwater = camera.position.y <= world_settings.getSeaLevel()
const is_underwater =
camera.position.y <= voxel_engine.water_data.map.waterLevel
if (camera_state.is_underwater !== is_underwater) {
dispatch('action/camera_went_underwater', is_underwater)
}
Expand Down
17 changes: 8 additions & 9 deletions src/core/modules/game_lights.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,17 @@ export default function () {
}

function update_fog(camera_is_underwater, color) {
scene.fog.color = color.clone()
camera.far = camera_is_underwater ? 250 : 3000
// @ts-ignore
const /** @type import('three').Fog */ scene_fog = scene.fog

scene_fog.color = color.clone()
if (camera_is_underwater) {
// @ts-ignore
scene.fog.near = 0
// @ts-ignore
scene.fog.far = 0.2 * camera.far
scene_fog.near = 0
} else {
// @ts-ignore
scene.fog.near = 0.25 * camera.far
// @ts-ignore
scene.fog.far = 0.98 * camera.far
scene_fog.near = 0.25 * camera.far
}
scene_fog.far = 0.98 * camera.far
}

aiter(abortable(typed_on(events, 'STATE_UPDATED', { signal }))).reduce(
Expand Down
2 changes: 1 addition & 1 deletion src/core/modules/game_minimap.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default function () {
window.addEventListener('resize', update_screen_position, { signal })
update_screen_position()
},
post_render({ renderer, voxel_engine }) {
post_render(_, { renderer, voxel_engine }) {
voxel_engine.minimap.render(renderer)
},
}
Expand Down
11 changes: 3 additions & 8 deletions src/core/modules/game_render.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,9 @@ export default function () {

volumetric_fog_pass.enabled =
postprocessing.volumetric_fog_pass.enabled
volumetric_fog_pass.uniformity =
postprocessing.volumetric_fog_pass.uniformity
volumetric_fog_pass.uniformity = camera_is_underwater
? 0.75
: postprocessing.volumetric_fog_pass.uniformity
volumetric_fog_pass.smoothness =
postprocessing.volumetric_fog_pass.smoothness
volumetric_fog_pass.fog_density =
Expand All @@ -233,12 +234,6 @@ export default function () {
postprocessing.underwater_pass.enabled && camera_is_underwater
}

const water_color = state.settings.water.color
if (!last_water_color || !last_water_color.equals(water_color)) {
last_water_color = water_color
underwater_pass.color = last_water_color
}

const lights_changed =
state.settings.sky.lights.version !== last_sky_lights_version
if (lights_changed) {
Expand Down
97 changes: 74 additions & 23 deletions src/core/modules/game_sky.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { lerp, smoothstep } from 'three/src/math/MathUtils.js'
import { aiter } from 'iterator-helper'

import { abortable } from '../utils/iterator.js'
import { abortable, typed_on } from '../utils/iterator.js'
import night_nx from '../../assets/skybox/night_nx.png'
import night_ny from '../../assets/skybox/night_ny.png'
import night_nz from '../../assets/skybox/night_nz.png'
Expand All @@ -27,7 +27,7 @@ import night_pz from '../../assets/skybox/night_pz.png'
/** @type {Type.Module} */
export default function () {
return {
observe({ scene, events, signal, dispatch, renderer }) {
observe({ scene, events, signal, dispatch, renderer, get_state }) {
const day_duration_in_seconds = 2000 // duration of a complete day/night cycle
const day_autoupdate_delay_in_milliseconds = 500 // delay between updates
const day_autoupdate_step =
Expand All @@ -47,7 +47,18 @@ export default function () {

const fog_color_uniform = { value: new Color() }

const material = new ShaderMaterial({
const skybox_material_vertex = `
varying vec3 vRayDirection;

void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
gl_Position.z = gl_Position.w; // set z to camera.far

vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
vRayDirection = worldPosition.xyz;
}`

const skybox_material = new ShaderMaterial({
name: 'skybox_shader',
uniforms: {
uSunDirection: { value: new Vector3() },
Expand All @@ -58,16 +69,7 @@ export default function () {
uNightRotation: { value: new Matrix4() },
uFogColor: fog_color_uniform,
},
vertexShader: `
varying vec3 vRayDirection;

void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
gl_Position.z = gl_Position.w; // set z to camera.far

vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
vRayDirection = worldPosition.xyz;
}`,
vertexShader: skybox_material_vertex,
fragmentShader: `
uniform vec3 uSunDirection; // normalized
uniform float uSunSize;
Expand Down Expand Up @@ -119,13 +121,33 @@ export default function () {
depthWrite: false,
})

const skybox_mesh = new Mesh(new BoxGeometry(1, 1, 1), material)
const skybox_underwater_material = new ShaderMaterial({
name: 'skybox_shader_flat',
uniforms: {
uColor: { value: new Color(0xff0000) },
},
vertexShader: skybox_material_vertex,
fragmentShader: `
uniform vec3 uColor;

varying vec3 vRayDirection;

void main() {
vec3 rayDirection = normalize(vRayDirection);
vec3 color = mix(vec3(0), uColor, smoothstep(-1.2, -.2, rayDirection.y));
gl_FragColor = vec4(color, 1);
}`,
side: BackSide,
depthWrite: false,
})

const skybox_mesh = new Mesh(new BoxGeometry(1, 1, 1), skybox_material)
skybox_mesh.scale.setScalar(450000)
scene.add(skybox_mesh)

const update_sun_size = (/** @type {number} */ value) => {
material.uniforms.uSunSize.value = value
material.uniforms.uSunGlowSize.value = 10 * value
skybox_material.uniforms.uSunSize.value = value
skybox_material.uniforms.uSunGlowSize.value = 10 * value
}

const sun_colors = [
Expand Down Expand Up @@ -168,17 +190,18 @@ export default function () {
0.00001 + 1.99999 * Math.PI * day_time,
0.1,
)
material.uniforms.uSunDirection.value = sun_position
skybox_material.uniforms.uSunDirection.value = sun_position

const sun_color = compute_sun_color(sun_position)
const is_day = smoothstep(sun_position.y, -0.3, 0.0)
// const sun_color = sun_color_raw.lerp(sun_color_raw, is_day)
material.uniforms.uSunColor.value = sun_color
skybox_material.uniforms.uSunColor.value = sun_color

material.uniforms.uNightRotation.value = new Matrix4().makeRotationAxis(
night_rotation_axis,
Math.PI * day_time,
)
skybox_material.uniforms.uNightRotation.value =
new Matrix4().makeRotationAxis(
night_rotation_axis,
Math.PI * day_time,
)

sky_lights_version = (sky_lights_version + 1) % 1000

Expand Down Expand Up @@ -260,6 +283,16 @@ export default function () {
scene.environment = cube_rendertarget.texture
const cube_camera = new CubeCamera(1, 100000, cube_rendertarget)

const update_skybox = () => {
if (get_state().settings.camera.is_underwater) {
skybox_underwater_material.uniforms.uColor.value.copy(scene.fog.color)
skybox_mesh.material = skybox_underwater_material
} else {
skybox_mesh.material = skybox_material
}
cube_camera.update(renderer, skybox_mesh)
}

events.on('SKY_CYCLE_PAUSED', (/** @type {boolean} */ paused) => {
day_autoupdate_paused = paused
})
Expand All @@ -269,7 +302,7 @@ export default function () {
set_day_time(value)
}

cube_camera.update(renderer, skybox_mesh)
update_skybox()
})

events.once('STATE_UPDATED', state => {
Expand All @@ -283,6 +316,24 @@ export default function () {
setInterval(day_autoupdate_delay_in_milliseconds, null, { signal }),
),
).forEach(update_day_time)

aiter(abortable(typed_on(events, 'STATE_UPDATED', { signal }))).reduce(
({ last_camera_is_underwater }, state) => {
if (
state.settings.camera.is_underwater !== last_camera_is_underwater
) {
update_skybox()
last_camera_is_underwater = state.settings.camera.is_underwater
}

return {
last_camera_is_underwater,
}
},
{
last_camera_is_underwater: false,
},
)
},
reduce(state, { type, payload }) {
if (type === 'action/sky_lights_change') {
Expand Down
Loading