Skip to content
Merged
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
22 changes: 22 additions & 0 deletions src/engine/workers/GameWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -650,13 +650,24 @@ export class WorkerGame extends GameCore {
private collectUnitRenderState(): UnitRenderState[] {
const states: UnitRenderState[] = [];
const entities = this.world.getEntitiesWith('Transform', 'Unit', 'Health', 'Selectable');
const localPlayerId = this.config.playerId;

for (const entity of entities) {
const transform = entity.get<Transform>('Transform')!;
const unit = entity.get<Unit>('Unit')!;
const health = entity.get<Health>('Health')!;
const selectable = entity.get<Selectable>('Selectable')!;

// Filter enemy units based on fog of war visibility
// Only send enemy units to renderer if they're currently visible to local player
const isOwnedByLocalPlayer = selectable.playerId === localPlayerId;
if (!isOwnedByLocalPlayer) {
const isVisible = this.visionSystem.isVisible(localPlayerId, transform.x, transform.y);
if (!isVisible) {
continue; // Skip enemy units not in line of sight
}
}

states.push({
id: entity.id,
x: transform.x,
Expand Down Expand Up @@ -723,13 +734,24 @@ export class WorkerGame extends GameCore {
private collectBuildingRenderState(): BuildingRenderState[] {
const states: BuildingRenderState[] = [];
const entities = this.world.getEntitiesWith('Transform', 'Building', 'Health', 'Selectable');
const localPlayerId = this.config.playerId;

for (const entity of entities) {
const transform = entity.get<Transform>('Transform')!;
const building = entity.get<Building>('Building')!;
const health = entity.get<Health>('Health')!;
const selectable = entity.get<Selectable>('Selectable')!;

// Filter enemy buildings based on fog of war exploration
// Buildings remain visible once explored (unlike units which require line of sight)
const isOwnedByLocalPlayer = selectable.playerId === localPlayerId;
if (!isOwnedByLocalPlayer) {
const isExplored = this.visionSystem.isExplored(localPlayerId, transform.x, transform.y);
if (!isExplored) {
continue; // Skip enemy buildings in unexplored areas
}
}

states.push({
id: entity.id,
x: transform.x,
Expand Down
10 changes: 7 additions & 3 deletions src/rendering/tsl/effects/EffectPasses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -920,10 +920,14 @@ export function createFogOfWarPass(
finalColor.addAssign(rimContribution);

// ============================================
// VOLUMETRIC FOG (high/ultra quality only)
// VOLUMETRIC FOG - DISABLED
// ============================================
// For quality >= 2, add raymarched volumetric fog depth
const useVolumetric = uQuality.greaterThanEqual(2);
// Volumetric fog raymarch disabled for fog of war - it causes positional
// shifts due to camera angle bias when sampling visibility along rays.
// AAA RTS games use texture-based fog of war, not volumetric raymarching.
// The surface-based effects (desaturation, darkening, clouds) provide
// the correct visual feedback without coordinate system issues.
const useVolumetric = float(0).greaterThan(1); // Always false

// Use direct camera position uniform (more reliable than matrix extraction)
const pixelWorldPos = vec3(worldX, worldY, worldZ);
Expand Down
Loading