feat: Lighting (#3824)
Basic lighting system huzzah! big thanks to @jyoung4242 for struggling and pioneering this approach in their original branch https://github.com/jyoung4242/canvasOverlayLighting
https://github.com/user-attachments/assets/33a49359-9824-4d31-97f4-e76a208249c0
## Features
Lighting is potentially performance impacting so we decided to flag it on the engine config like physics
```typescript
const game = new ex.Engine({
lighting: true,
...
});
```
Additionally the ambient light is configured in the engine config as well. It can be overriden per scene if desired by updating the LightingSystem args.
```typescript
const game = new ex.Engine({
lighting: {
enabled: true,
ambientIntensity: 0.1,
ambientColor: ex.Color.fromRGB(60, 60, 200)
}
});
```
1. Point Light Component
2. Cone Light Component
3. Occluders! (The thing that cast shadows
We have 3 by default
Box, Circle, and Polygon
```typescript
var crate = new ex.Actor({ pos: ex.vec(520, 260), width: 40, height: 40, color: ex.Color.Brown });
crate.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'box', width: 40, height: 40 } }));
crate.actions.repeatForever((ctx) => ctx.rotateBy({ angleRadiansOffset: Math.PI, duration: 4000 }));
game.add(crate);
var pillar = new ex.Actor({ pos: ex.vec(300, 180), radius: 25, color: ex.Color.Gray });
pillar.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'circle', radius: 25 } }));
game.add(pillar);
var wedge = new ex.Actor({
pos: ex.vec(460, 460),
color: ex.Color.DarkGray,
collider: ex.Shape.Polygon([ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)])
});
wedge.addComponent(
new ex.LightOccluderComponent({ shape: { kind: 'polygon', vertices: [ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)] } })
);
game.add(wedge);
```
5. Darkness Component
Whole screen darkness overlay (note missing width/height)
```typescript
var environment = new ex.Actor({ name: 'environment' });
environment.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(0, 0, 10),
intensity: 0.9,
}));
game.add(environment);
```
Specific area darkness with width/height
```typescript
var room = new ex.Actor({ name: 'room', pos: ex.vec(750, 150) });
room.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(5, 5, 20),
intensity: 0.95,
width: 300,
height: 200,
}));
game.add(room);
```
6. Lighting System
Uses a ex.ScreenElement -> ex.Canvas under the hood, you can specify the z axis that shadows live.
This is using 2D canvas destination-out and radial gradients to make the "light" work.
7. Flickering System
Completely optional handles the flickering modulation behavior, primary and secondary frequencies configurable
Co-authored-by: Justin Young <62815737+jyoung4242@users.noreply.github.com>
feat: Lighting (#3824)
Basic lighting system huzzah! big thanks to @jyoung4242 for struggling and pioneering this approach in their original branch https://github.com/jyoung4242/canvasOverlayLighting
https://github.com/user-attachments/assets/33a49359-9824-4d31-97f4-e76a208249c0
## Features
Lighting is potentially performance impacting so we decided to flag it on the engine config like physics
```typescript
const game = new ex.Engine({
lighting: true,
...
});
```
Additionally the ambient light is configured in the engine config as well. It can be overriden per scene if desired by updating the LightingSystem args.
```typescript
const game = new ex.Engine({
lighting: {
enabled: true,
ambientIntensity: 0.1,
ambientColor: ex.Color.fromRGB(60, 60, 200)
}
});
```
1. Point Light Component
2. Cone Light Component
3. Occluders! (The thing that cast shadows
We have 3 by default
Box, Circle, and Polygon
```typescript
var crate = new ex.Actor({ pos: ex.vec(520, 260), width: 40, height: 40, color: ex.Color.Brown });
crate.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'box', width: 40, height: 40 } }));
crate.actions.repeatForever((ctx) => ctx.rotateBy({ angleRadiansOffset: Math.PI, duration: 4000 }));
game.add(crate);
var pillar = new ex.Actor({ pos: ex.vec(300, 180), radius: 25, color: ex.Color.Gray });
pillar.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'circle', radius: 25 } }));
game.add(pillar);
var wedge = new ex.Actor({
pos: ex.vec(460, 460),
color: ex.Color.DarkGray,
collider: ex.Shape.Polygon([ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)])
});
wedge.addComponent(
new ex.LightOccluderComponent({ shape: { kind: 'polygon', vertices: [ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)] } })
);
game.add(wedge);
```
5. Darkness Component
Whole screen darkness overlay (note missing width/height)
```typescript
var environment = new ex.Actor({ name: 'environment' });
environment.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(0, 0, 10),
intensity: 0.9,
}));
game.add(environment);
```
Specific area darkness with width/height
```typescript
var room = new ex.Actor({ name: 'room', pos: ex.vec(750, 150) });
room.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(5, 5, 20),
intensity: 0.95,
width: 300,
height: 200,
}));
game.add(room);
```
6. Lighting System
Uses a ex.ScreenElement -> ex.Canvas under the hood, you can specify the z axis that shadows live.
This is using 2D canvas destination-out and radial gradients to make the "light" work.
7. Flickering System
Completely optional handles the flickering modulation behavior, primary and secondary frequencies configurable
Co-authored-by: Justin Young <62815737+jyoung4242@users.noreply.github.com>
feat: Lighting (#3824)
Basic lighting system huzzah! big thanks to @jyoung4242 for struggling and pioneering this approach in their original branch https://github.com/jyoung4242/canvasOverlayLighting
https://github.com/user-attachments/assets/33a49359-9824-4d31-97f4-e76a208249c0
## Features
Lighting is potentially performance impacting so we decided to flag it on the engine config like physics
```typescript
const game = new ex.Engine({
lighting: true,
...
});
```
Additionally the ambient light is configured in the engine config as well. It can be overriden per scene if desired by updating the LightingSystem args.
```typescript
const game = new ex.Engine({
lighting: {
enabled: true,
ambientIntensity: 0.1,
ambientColor: ex.Color.fromRGB(60, 60, 200)
}
});
```
1. Point Light Component
2. Cone Light Component
3. Occluders! (The thing that cast shadows
We have 3 by default
Box, Circle, and Polygon
```typescript
var crate = new ex.Actor({ pos: ex.vec(520, 260), width: 40, height: 40, color: ex.Color.Brown });
crate.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'box', width: 40, height: 40 } }));
crate.actions.repeatForever((ctx) => ctx.rotateBy({ angleRadiansOffset: Math.PI, duration: 4000 }));
game.add(crate);
var pillar = new ex.Actor({ pos: ex.vec(300, 180), radius: 25, color: ex.Color.Gray });
pillar.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'circle', radius: 25 } }));
game.add(pillar);
var wedge = new ex.Actor({
pos: ex.vec(460, 460),
color: ex.Color.DarkGray,
collider: ex.Shape.Polygon([ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)])
});
wedge.addComponent(
new ex.LightOccluderComponent({ shape: { kind: 'polygon', vertices: [ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)] } })
);
game.add(wedge);
```
5. Darkness Component
Whole screen darkness overlay (note missing width/height)
```typescript
var environment = new ex.Actor({ name: 'environment' });
environment.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(0, 0, 10),
intensity: 0.9,
}));
game.add(environment);
```
Specific area darkness with width/height
```typescript
var room = new ex.Actor({ name: 'room', pos: ex.vec(750, 150) });
room.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(5, 5, 20),
intensity: 0.95,
width: 300,
height: 200,
}));
game.add(room);
```
6. Lighting System
Uses a ex.ScreenElement -> ex.Canvas under the hood, you can specify the z axis that shadows live.
This is using 2D canvas destination-out and radial gradients to make the "light" work.
7. Flickering System
Completely optional handles the flickering modulation behavior, primary and secondary frequencies configurable
Co-authored-by: Justin Young <62815737+jyoung4242@users.noreply.github.com>
feat: Lighting (#3824)
Basic lighting system huzzah! big thanks to @jyoung4242 for struggling and pioneering this approach in their original branch https://github.com/jyoung4242/canvasOverlayLighting
https://github.com/user-attachments/assets/33a49359-9824-4d31-97f4-e76a208249c0
## Features
Lighting is potentially performance impacting so we decided to flag it on the engine config like physics
```typescript
const game = new ex.Engine({
lighting: true,
...
});
```
Additionally the ambient light is configured in the engine config as well. It can be overriden per scene if desired by updating the LightingSystem args.
```typescript
const game = new ex.Engine({
lighting: {
enabled: true,
ambientIntensity: 0.1,
ambientColor: ex.Color.fromRGB(60, 60, 200)
}
});
```
1. Point Light Component
2. Cone Light Component
3. Occluders! (The thing that cast shadows
We have 3 by default
Box, Circle, and Polygon
```typescript
var crate = new ex.Actor({ pos: ex.vec(520, 260), width: 40, height: 40, color: ex.Color.Brown });
crate.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'box', width: 40, height: 40 } }));
crate.actions.repeatForever((ctx) => ctx.rotateBy({ angleRadiansOffset: Math.PI, duration: 4000 }));
game.add(crate);
var pillar = new ex.Actor({ pos: ex.vec(300, 180), radius: 25, color: ex.Color.Gray });
pillar.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'circle', radius: 25 } }));
game.add(pillar);
var wedge = new ex.Actor({
pos: ex.vec(460, 460),
color: ex.Color.DarkGray,
collider: ex.Shape.Polygon([ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)])
});
wedge.addComponent(
new ex.LightOccluderComponent({ shape: { kind: 'polygon', vertices: [ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)] } })
);
game.add(wedge);
```
5. Darkness Component
Whole screen darkness overlay (note missing width/height)
```typescript
var environment = new ex.Actor({ name: 'environment' });
environment.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(0, 0, 10),
intensity: 0.9,
}));
game.add(environment);
```
Specific area darkness with width/height
```typescript
var room = new ex.Actor({ name: 'room', pos: ex.vec(750, 150) });
room.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(5, 5, 20),
intensity: 0.95,
width: 300,
height: 200,
}));
game.add(room);
```
6. Lighting System
Uses a ex.ScreenElement -> ex.Canvas under the hood, you can specify the z axis that shadows live.
This is using 2D canvas destination-out and radial gradients to make the "light" work.
7. Flickering System
Completely optional handles the flickering modulation behavior, primary and secondary frequencies configurable
Co-authored-by: Justin Young <62815737+jyoung4242@users.noreply.github.com>
feat: Lighting (#3824)
Basic lighting system huzzah! big thanks to @jyoung4242 for struggling and pioneering this approach in their original branch https://github.com/jyoung4242/canvasOverlayLighting
https://github.com/user-attachments/assets/33a49359-9824-4d31-97f4-e76a208249c0
## Features
Lighting is potentially performance impacting so we decided to flag it on the engine config like physics
```typescript
const game = new ex.Engine({
lighting: true,
...
});
```
Additionally the ambient light is configured in the engine config as well. It can be overriden per scene if desired by updating the LightingSystem args.
```typescript
const game = new ex.Engine({
lighting: {
enabled: true,
ambientIntensity: 0.1,
ambientColor: ex.Color.fromRGB(60, 60, 200)
}
});
```
1. Point Light Component
2. Cone Light Component
3. Occluders! (The thing that cast shadows
We have 3 by default
Box, Circle, and Polygon
```typescript
var crate = new ex.Actor({ pos: ex.vec(520, 260), width: 40, height: 40, color: ex.Color.Brown });
crate.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'box', width: 40, height: 40 } }));
crate.actions.repeatForever((ctx) => ctx.rotateBy({ angleRadiansOffset: Math.PI, duration: 4000 }));
game.add(crate);
var pillar = new ex.Actor({ pos: ex.vec(300, 180), radius: 25, color: ex.Color.Gray });
pillar.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'circle', radius: 25 } }));
game.add(pillar);
var wedge = new ex.Actor({
pos: ex.vec(460, 460),
color: ex.Color.DarkGray,
collider: ex.Shape.Polygon([ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)])
});
wedge.addComponent(
new ex.LightOccluderComponent({ shape: { kind: 'polygon', vertices: [ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)] } })
);
game.add(wedge);
```
5. Darkness Component
Whole screen darkness overlay (note missing width/height)
```typescript
var environment = new ex.Actor({ name: 'environment' });
environment.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(0, 0, 10),
intensity: 0.9,
}));
game.add(environment);
```
Specific area darkness with width/height
```typescript
var room = new ex.Actor({ name: 'room', pos: ex.vec(750, 150) });
room.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(5, 5, 20),
intensity: 0.95,
width: 300,
height: 200,
}));
game.add(room);
```
6. Lighting System
Uses a ex.ScreenElement -> ex.Canvas under the hood, you can specify the z axis that shadows live.
This is using 2D canvas destination-out and radial gradients to make the "light" work.
7. Flickering System
Completely optional handles the flickering modulation behavior, primary and secondary frequencies configurable
Co-authored-by: Justin Young <62815737+jyoung4242@users.noreply.github.com>
feat: Lighting (#3824)
Basic lighting system huzzah! big thanks to @jyoung4242 for struggling and pioneering this approach in their original branch https://github.com/jyoung4242/canvasOverlayLighting
https://github.com/user-attachments/assets/33a49359-9824-4d31-97f4-e76a208249c0
## Features
Lighting is potentially performance impacting so we decided to flag it on the engine config like physics
```typescript
const game = new ex.Engine({
lighting: true,
...
});
```
Additionally the ambient light is configured in the engine config as well. It can be overriden per scene if desired by updating the LightingSystem args.
```typescript
const game = new ex.Engine({
lighting: {
enabled: true,
ambientIntensity: 0.1,
ambientColor: ex.Color.fromRGB(60, 60, 200)
}
});
```
1. Point Light Component
2. Cone Light Component
3. Occluders! (The thing that cast shadows
We have 3 by default
Box, Circle, and Polygon
```typescript
var crate = new ex.Actor({ pos: ex.vec(520, 260), width: 40, height: 40, color: ex.Color.Brown });
crate.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'box', width: 40, height: 40 } }));
crate.actions.repeatForever((ctx) => ctx.rotateBy({ angleRadiansOffset: Math.PI, duration: 4000 }));
game.add(crate);
var pillar = new ex.Actor({ pos: ex.vec(300, 180), radius: 25, color: ex.Color.Gray });
pillar.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'circle', radius: 25 } }));
game.add(pillar);
var wedge = new ex.Actor({
pos: ex.vec(460, 460),
color: ex.Color.DarkGray,
collider: ex.Shape.Polygon([ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)])
});
wedge.addComponent(
new ex.LightOccluderComponent({ shape: { kind: 'polygon', vertices: [ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)] } })
);
game.add(wedge);
```
5. Darkness Component
Whole screen darkness overlay (note missing width/height)
```typescript
var environment = new ex.Actor({ name: 'environment' });
environment.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(0, 0, 10),
intensity: 0.9,
}));
game.add(environment);
```
Specific area darkness with width/height
```typescript
var room = new ex.Actor({ name: 'room', pos: ex.vec(750, 150) });
room.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(5, 5, 20),
intensity: 0.95,
width: 300,
height: 200,
}));
game.add(room);
```
6. Lighting System
Uses a ex.ScreenElement -> ex.Canvas under the hood, you can specify the z axis that shadows live.
This is using 2D canvas destination-out and radial gradients to make the "light" work.
7. Flickering System
Completely optional handles the flickering modulation behavior, primary and secondary frequencies configurable
Co-authored-by: Justin Young <62815737+jyoung4242@users.noreply.github.com>
feat: Lighting (#3824)
Basic lighting system huzzah! big thanks to @jyoung4242 for struggling and pioneering this approach in their original branch https://github.com/jyoung4242/canvasOverlayLighting
https://github.com/user-attachments/assets/33a49359-9824-4d31-97f4-e76a208249c0
## Features
Lighting is potentially performance impacting so we decided to flag it on the engine config like physics
```typescript
const game = new ex.Engine({
lighting: true,
...
});
```
Additionally the ambient light is configured in the engine config as well. It can be overriden per scene if desired by updating the LightingSystem args.
```typescript
const game = new ex.Engine({
lighting: {
enabled: true,
ambientIntensity: 0.1,
ambientColor: ex.Color.fromRGB(60, 60, 200)
}
});
```
1. Point Light Component
2. Cone Light Component
3. Occluders! (The thing that cast shadows
We have 3 by default
Box, Circle, and Polygon
```typescript
var crate = new ex.Actor({ pos: ex.vec(520, 260), width: 40, height: 40, color: ex.Color.Brown });
crate.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'box', width: 40, height: 40 } }));
crate.actions.repeatForever((ctx) => ctx.rotateBy({ angleRadiansOffset: Math.PI, duration: 4000 }));
game.add(crate);
var pillar = new ex.Actor({ pos: ex.vec(300, 180), radius: 25, color: ex.Color.Gray });
pillar.addComponent(new ex.LightOccluderComponent({ shape: { kind: 'circle', radius: 25 } }));
game.add(pillar);
var wedge = new ex.Actor({
pos: ex.vec(460, 460),
color: ex.Color.DarkGray,
collider: ex.Shape.Polygon([ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)])
});
wedge.addComponent(
new ex.LightOccluderComponent({ shape: { kind: 'polygon', vertices: [ex.vec(-30, 20), ex.vec(30, 20), ex.vec(0, -30)] } })
);
game.add(wedge);
```
5. Darkness Component
Whole screen darkness overlay (note missing width/height)
```typescript
var environment = new ex.Actor({ name: 'environment' });
environment.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(0, 0, 10),
intensity: 0.9,
}));
game.add(environment);
```
Specific area darkness with width/height
```typescript
var room = new ex.Actor({ name: 'room', pos: ex.vec(750, 150) });
room.addComponent(new ex.DarknessComponent({
color: ex.Color.fromRGB(5, 5, 20),
intensity: 0.95,
width: 300,
height: 200,
}));
game.add(room);
```
6. Lighting System
Uses a ex.ScreenElement -> ex.Canvas under the hood, you can specify the z axis that shadows live.
This is using 2D canvas destination-out and radial gradients to make the "light" work.
7. Flickering System
Completely optional handles the flickering modulation behavior, primary and secondary frequencies configurable
Co-authored-by: Justin Young <62815737+jyoung4242@users.noreply.github.com>