at main
5 folders
3 files
chore: split out vitest tests into visual & unit (#3508)
This splits out our vitest test suite into `unit` and `visual` tests. `unit` will run on chromium, while `visual` will run on chrome. I've removed firefox/webkit browsers as we were not running these in CI, and there's a discussion to be had about whether they even make sense to use in unit tests, or are they actually only valuable for visual tests. If the latter, we need to figure out how to not rely on Chrome for consistent screenshotting.
Tests that are visual simply need to contain `@visual` somewhere in it's test name or `describe` name. Unit tests will run for all tests without `@visual`, while visual tests will run all that contain `@visual`. I had considered splitting them out into different files under different folders, but it's nice to re-use the same setup/teardown logic. Otherwise I had to copy & paste all of that in both places.
I also made some other tweaks to our vitest config:
- I've removed the conditional exemption of `--disable-gpu` flag for Chromium on macOS, which although slower it ensures the visual tests pass. I suppose this is because it uses a software renderer.
- Changed the test pooling from `thread` to the default. I never saw a difference in speed but in theory the default (`fork`) is supposed to be faster
- Enabled fileParallelism for tests. I had run into WebGL context issues before, but now they seem to be gone, so this should lead to faster tests
- I've switched from Chrome to actual Chromium for the visual tests, and then lowered the tolerance on the TextSpec so that it could pass both in Windows/Ubuntu CI as well as macOS locally. I'm fine to undo this, but a lower tolerance on font tests might make sense to do anyway and this frees us from relying on Windows+Chrome to run these tests.
feat: Shader Pipelines (#3828)
This PR adds Shader pipeline capabilities to Materials/PostProcessors!
https://github.com/user-attachments/assets/256bdf2c-c09d-40db-b5cd-0e0e1776729c
1. You can stack fragment shaders on each other and re-use them to mix/match effects
- Built in uniforms are passed through each pass
- We support lists of glsl fragment strings or ShaderPasses, and ShaderPipelines that can wrap up multipass effects into a convient package
3. This enables effects like Blur/Bloom/Glow (built in ShaderPipelines) that are only easily possible with multipass workflows
Example using multiple strings
```typescript
// 3. Custom 2-pass pipeline from bare glsl strings
var redOnly = ex.glsl`
in vec2 v_uv;
uniform sampler2D u_image;
out vec4 fragColor;
void main() {
vec4 color = texture(u_image, v_uv);
fragColor = vec4(color.r + color.g + color.b, 0.0, 0.0, color.a);
}`;
var pulseBlue = ex.glsl`
in vec2 v_uv;
uniform sampler2D u_image;
uniform float u_time_ms;
out vec4 fragColor;
void main() {
vec4 color = texture(u_image, v_uv);
float pulse = (sin(u_time_ms / 300.0) + 1.0) / 2.0;
fragColor = vec4(color.r, 0.0, pulse * color.r, color.a);
}`;
var tinted = new ex.Actor({ pos: ex.vec(480, 150) });
tinted.graphics.use(swordImage.toSprite());
tinted.graphics.material = new ex.Material({
name: 'tint-pipeline',
graphicsContext,
passes: [redOnly, pulseBlue]
});
```
Built in effects!
```typescript
var bloomEffect = new ex.BloomEffect({ graphicsContext, threshold: 0.3, intensity: 1.5 });
var blooming = new ex.Actor({ pos: ex.vec(780, 150) });
blooming.graphics.use(swordImage.toSprite());
blooming.graphics.material = new ex.Material({
name: 'bloom-material',
graphicsContext,
passes: bloomEffect,
padding: 32
});
game.add(blooming);
```
Accidental bug fixes
- The time based uniforms in post processors were counting N times based on the number of postprocessors
This was re-implemented resurrected from my old branch back onto main
* https://github.com/excaliburjs/Excalibur/compare/main...feat/shader-pipelines
Huge thanks to Andrew Adamson's tutorials and code samples that provided the inspiration for the framebuffer technique
* https://youtu.be/bAq9Zk7BAWo?si=f4h0rBBR9T5yaS2W
* https://github.com/scriptfoundry/WebGL2-Videos-Materials/blob/main/25.framebuffer.basics.js