Enhance OceanLOD to consider view direction in LOD updates and adjust grid size parameters

This commit is contained in:
2026-01-31 22:50:05 +01:00
parent e9512fb88a
commit c19854aefc
2 changed files with 53 additions and 18 deletions

View File

@@ -1,7 +1,7 @@
import { Grid } from './Grid'; import { Grid } from './Grid';
import { vec3 } from 'gl-matrix'; import { vec3 } from 'gl-matrix';
/** Manages multiple ocean grid patches with LOD based on camera distance */ /** Manages multiple ocean grid patches with LOD based on camera distance and view cone */
export class OceanLOD { export class OceanLOD {
private grids: Array<{ private grids: Array<{
grid: Grid; grid: Grid;
@@ -12,14 +12,15 @@ export class OceanLOD {
}> = []; }> = [];
private readonly LOD_LEVELS = [ private readonly LOD_LEVELS = [
{ distance: 2.0, gridSize: 128 }, // Closest - highest detail { distance: 2.0, gridSize: 256 }, // Closest - highest detail
{ distance: 5.0, gridSize: 64 }, // Medium distance { distance: 5.0, gridSize: 128 }, // Medium distance
{ distance: 10.0, gridSize: 32 }, // Far distance { distance: 10.0, gridSize: 64 }, // Far distance
{ distance: 20.0, gridSize: 16 }, // Very far - lowest detail { distance: 20.0, gridSize: 32 }, // Very far - lowest detail
]; ];
private readonly PATCH_SIZE = 2.0; // World size of each patch private readonly PATCH_SIZE = 2.0; // World size of each patch
private readonly PATCHES_PER_SIDE = 7; // 7x7 = 49 patches total private readonly PATCHES_PER_SIDE = 7; // 7x7 = 49 patches total
private readonly VIEW_CONE_COS = Math.cos(Math.PI * 0.45); // ~81 degree half-angle (wider than typical FOV)
constructor() { constructor() {
this.createGridPatches(); this.createGridPatches();
@@ -52,22 +53,56 @@ export class OceanLOD {
} }
} }
/** Update LOD based on camera position */ /** Update LOD based on camera position and view direction */
updateLOD(gl: WebGL2RenderingContext, cameraPos: vec3): void { updateLOD(gl: WebGL2RenderingContext, cameraPos: vec3, cameraTarget: vec3): void {
for (const patch of this.grids) { // Calculate view direction (normalized)
// Calculate distance from camera to patch center const viewDir = vec3.create();
const dx = patch.centerX - cameraPos[0]; vec3.subtract(viewDir, cameraTarget, cameraPos);
const dy = patch.centerY - cameraPos[1]; vec3.normalize(viewDir, viewDir);
const distance = Math.sqrt(dx * dx + dy * dy);
// Determine appropriate LOD level for (const patch of this.grids) {
// Calculate vector from camera to patch center (on XY plane, Z=0 for ocean surface)
const toPatch = vec3.fromValues(
patch.centerX - cameraPos[0],
patch.centerY - cameraPos[1],
0 - cameraPos[2] // Ocean is at Z=0
);
const distance = vec3.length(toPatch);
// Normalize direction to patch
const toPatchDir = vec3.create();
vec3.normalize(toPatchDir, toPatch);
// Calculate dot product with view direction (how aligned is patch with where we're looking)
const dotProduct = vec3.dot(viewDir, toPatchDir);
// Determine if patch is in front of camera and within view cone
const isInFront = dotProduct > -0.2; // Slightly behind is ok for edge cases
const isInViewCone = dotProduct > this.VIEW_CONE_COS;
// Calculate LOD level
let newLodLevel = 3; // Default to lowest detail let newLodLevel = 3; // Default to lowest detail
if (!isInFront) {
// Behind camera - always lowest detail
newLodLevel = 3;
} else if (isInViewCone) {
// In view cone - use distance-based LOD
for (let i = 0; i < this.LOD_LEVELS.length; i++) { for (let i = 0; i < this.LOD_LEVELS.length; i++) {
if (distance < this.LOD_LEVELS[i].distance) { if (distance < this.LOD_LEVELS[i].distance) {
newLodLevel = i; newLodLevel = i;
break; break;
} }
} }
} else {
// In front but outside view cone - reduce detail by 1-2 levels
for (let i = 0; i < this.LOD_LEVELS.length; i++) {
if (distance < this.LOD_LEVELS[i].distance) {
newLodLevel = Math.min(i + 2, 3); // Reduce detail
break;
}
}
}
// Only recreate grid if LOD level changed // Only recreate grid if LOD level changed
if (newLodLevel !== patch.lodLevel) { if (newLodLevel !== patch.lodLevel) {

View File

@@ -190,8 +190,8 @@ function drawScene() {
camera.setRotationY((curRotY += mouseXVel * Config.MOUSE_SENSITIVITY + keyboardRotationY)); camera.setRotationY((curRotY += mouseXVel * Config.MOUSE_SENSITIVITY + keyboardRotationY));
var view = camera.getViewMatrix(); var view = camera.getViewMatrix();
// Update LOD based on camera position // Update LOD based on camera position and view direction
oceanLOD.updateLOD(gl, camera.pos); oceanLOD.updateLOD(gl, camera.pos, camera.target);
var model = mat4.create(); var model = mat4.create();
mat4.identity(model); mat4.identity(model);