Skip to content

Commit

Permalink
fix: PostProcessor drawing when no actors present
Browse files Browse the repository at this point in the history
  • Loading branch information
eonarheim committed Dec 23, 2024
1 parent e29dd75 commit 2588006
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 4 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Added

-
- New PostProcessor.onDraw() hook to handle uploading textures

### Fixed

- Fixed CollidePolygonPolygon crash with some defense against invalid separation
- Fixed issue with PostProcessor where it would not run correctly if no actors present

### Updates

Expand Down
12 changes: 12 additions & 0 deletions sandbox/tests/clip-canvas/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Clip Canvas</title>
</head>
<body>
<script src="../../lib/excalibur.js"></script>
<script src="index.js"></script>
</body>
</html>
55 changes: 55 additions & 0 deletions sandbox/tests/clip-canvas/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
var engine = new ex.Engine({
width: 800,
height: 800,
displayMode: ex.DisplayMode.FitScreen
});

var mouse = ex.vec(400, 400);

var canvas = new ex.Canvas({
width: 800,
height: 800,
draw: (ctx) => {
// Clipping path
ctx.beginPath();
ctx.rect(0, 0, 800, 800); // Outer rectangle
ctx.arc(mouse.x, mouse.y, 60, 0, Math.PI * 2, true); // Hole anticlockwise
ctx.clip();

// Draw background
ctx.fillStyle = ex.Color.Black.toString();
ctx.fillRect(0, 0, 800, 800);
}
});

engine.input.pointers.on('move', (evt) => {
mouse.x = evt.screenPos.x;
mouse.y = evt.screenPos.y;
canvas.flagDirty();
});

var mask = new ex.Actor({
anchor: ex.vec(0, 0),
pos: ex.vec(0, 0),
coordPlane: ex.CoordPlane.Screen,
z: 1 // on top
});
mask.graphics.use(canvas);
engine.add(mask);

var normal = new ex.Actor({
pos: ex.vec(400, 400),
color: ex.Color.Red,
width: 100,
height: 100
});

normal.actions.repeatForever((ctx) => {
ctx.moveBy({ offset: ex.vec(100, 0), duration: 1000 });
ctx.moveBy({ offset: ex.vec(0, 100), duration: 1000 });
ctx.moveBy({ offset: ex.vec(-100, 0), duration: 1000 });
ctx.moveBy({ offset: ex.vec(0, -100), duration: 1000 });
});
engine.add(normal);

engine.start();
12 changes: 12 additions & 0 deletions sandbox/tests/occluder/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Occluder</title>
</head>
<body>
<script src="../../lib/excalibur.js"></script>
<script src="index.js"></script>
</body>
</html>
98 changes: 98 additions & 0 deletions sandbox/tests/occluder/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
var occluder = new ex.ImageSource('test.png');

var shader = `#version 300 es
precision mediump float;
uniform sampler2D u_image; // Default texture slot
uniform sampler2D u_myTexture; // Slot 2 texture
uniform vec2 u_resolution;
uniform vec2 u_texturePosition; // Position of the second texture
uniform vec2 u_textureSize; // Size of the second texture
in vec2 v_uv;
out vec4 fragColor;
void main() {
vec2 pixelCoord = v_uv * u_resolution;
vec2 adjustedUV = (pixelCoord - u_texturePosition) / u_textureSize;
vec4 defaultColor = texture(u_image, v_uv);
vec4 secondTexture = texture(u_myTexture, adjustedUV);
vec4 endColor = mix(defaultColor, secondTexture, .5);
fragColor = vec4(endColor.rgb * endColor.a, endColor.a);
//fragColor = vec4(secondTexture.rgb * secondTexture.a, secondTexture.a);
}
`;

class LightingPostProcessor implements ex.PostProcessor {
private _shader: ex.ScreenShader | undefined;
gctx: ex.ExcaliburGraphicsContextWebGL;
texture: WebGLTexture;

constructor(public graphicsContext: ex.ExcaliburGraphicsContextWebGL) {
this.gctx = graphicsContext;
this.texture = this.graphicsContext.textureLoader.load(
occluder.image,
{ wrapping: { x: ex.ImageWrapping.Repeat, y: ex.ImageWrapping.Repeat } },
true
) as WebGLTexture;
console.log(occluder);

console.log(this.texture);
}

initialize(gl: WebGL2RenderingContext): void {
this._shader = new ex.ScreenShader(gl, shader);
}
getLayout(): ex.VertexLayout {
return this._shader.getLayout();
}
getShader(): ex.Shader {
return this._shader.getShader();
}
onUpdate(elapsed: number): void {
let myShader = this._shader?.getShader();

if (myShader) {
myShader.trySetUniformInt('u_myTexture', 1);
myShader.trySetUniformFloatVector('u_texturePosition', new ex.Vector(100.0, 100.0));
myShader.trySetUniformFloatVector('u_textureSize', new ex.Vector(64.0, 64.0));
}
}
onDraw(): void {
let myShader = this._shader?.getShader();
if (myShader) {
this.gctx.textureLoader.load(occluder.image);
myShader.setTexture(1, this.texture as WebGLTexture);
myShader.trySetUniformInt('u_myTexture', 1);
}
}
}

var game = new ex.Engine({
width: 600,
height: 400,
displayMode: ex.DisplayMode.FitScreenAndFill
});

var actor = new ex.Actor({
width: 100,
height: 100,
color: ex.Color.Red
});
actor.angularVelocity = 0.2;
actor.actions.repeatForever((ctx) => {
ctx.moveTo(ex.vec(1000, 0), 200);
ctx.moveTo(ex.vec(0, 400), 200);
ctx.moveTo(ex.vec(1000, 400), 200);
ctx.moveTo(ex.vec(0, 0), 200);
});
game.currentScene.add(actor);

var ctx = game.graphicsContext as ex.ExcaliburGraphicsContextWebGL;
game.start(new ex.Loader([occluder])).then(() => {
ctx.addPostProcessor(new LightingPostProcessor(ctx));
});
Binary file added sandbox/tests/occluder/test.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 1 addition & 2 deletions src/engine/Graphics/Context/ExcaliburGraphicsContextWebGL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -776,8 +776,7 @@ export class ExcaliburGraphicsContextWebGL implements ExcaliburGraphicsContext {

// post process step
if (this._postprocessors.length > 0) {
const source = currentTarget.toRenderSource();
source.use();
currentTarget.toRenderSource().use();
}

// flip flop render targets for post processing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,14 @@ export class ScreenPassPainter {

renderWithPostProcessor(postprocessor: PostProcessor): void {
const gl = this._gl;
postprocessor.getShader().use();
const shader = postprocessor.getShader();
shader.use();
postprocessor.getLayout().use();
gl.activeTexture(gl.TEXTURE0);
shader.trySetUniformInt('u_image', 0);
if (postprocessor.onDraw) {
postprocessor.onDraw();
}
gl.drawArrays(gl.TRIANGLES, 0, 6);
}

Expand Down
6 changes: 6 additions & 0 deletions src/engine/Graphics/PostProcessor/PostProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,10 @@ export interface PostProcessor {
* @param elapsed
*/
onUpdate?(elapsed: number): void;

/**
* Use the onDraw hook to upload any textures or command that need to run right before draw
* @param elapsed

Check warning on line 34 in src/engine/Graphics/PostProcessor/PostProcessor.ts

View workflow job for this annotation

GitHub Actions / build / build

@param "elapsed" does not match an existing function parameter

Check warning on line 34 in src/engine/Graphics/PostProcessor/PostProcessor.ts

View workflow job for this annotation

GitHub Actions / build

@param "elapsed" does not match an existing function parameter
*/
onDraw?(): void;
}

0 comments on commit 2588006

Please sign in to comment.