Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: [#1815] TileMap tiling artifact #2146

Merged
merged 17 commits into from
Dec 23, 2021
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Fixed

- Fixed [#1815] issue where Camera would jitter when using a strategies based off of actors in the previous frame.
- Fixed issue where TileMaps would sometimes have a geometry seam that may not fall on an actual screen pixel causing a visible gap between tiles and the background
-- ![image](https://user-images.githubusercontent.com/612071/144700377-ac4585ba-3f4c-44b8-95db-ad36c5fc9a32.png)
- Fixed unreleased issue where SpriteFonts log every frame they detect a misconfigured font.
- Fixed unreleased issue where clock when constraining fps would pass larger than expected elapsed times to the simulation causing things to "speed up" bizarrely
- Fixed unreleased issue where games with no resources would crash
Expand Down
42 changes: 31 additions & 11 deletions src/engine/Camera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -597,13 +597,21 @@ export class Camera extends Class implements CanUpdate, CanInitialize {
}
}
this._halfWidth = center.x;
this._halfHeight = center.x;
this._halfHeight = center.y;

// If the user has not set the camera pos, apply default center screen position
if (!this._posChanged) {
this.pos = center;
}

// First frame boostrap

// Run strategies for first frame
this.runStrategies(_engine, _engine.clock.elapsed());

// Setup the first frame viewport
this.updateViewport();

this.onInitialize(_engine);
super.emit('initialize', new InitializeEvent(_engine, this));
this._isInitialized = true;
Expand Down Expand Up @@ -642,6 +650,22 @@ export class Camera extends Class implements CanUpdate, CanInitialize {
super.once(eventName, handler);
}

public runStrategies(engine: Engine, delta: number) {
for (const s of this._cameraStrategies) {
this.pos = s.action.call(s, s.target, this, engine, delta);
}
}

public updateViewport() {
// recalc viewport
this._viewport = new BoundingBox(
this.x - this._halfWidth,
this.y - this._halfHeight,
this.x + this._halfWidth,
this.y + this._halfHeight
);
}

public update(_engine: Engine, delta: number) {
this._initialize(_engine);
this._preupdate(_engine, delta);
Expand Down Expand Up @@ -706,16 +730,9 @@ export class Camera extends Class implements CanUpdate, CanInitialize {
this._yShake = ((Math.random() * this._shakeMagnitudeY) | 0) + 1;
}

for (const s of this._cameraStrategies) {
this.pos = s.action.call(s, s.target, this, _engine, delta);
}
this.runStrategies(_engine, delta);

this._viewport = new BoundingBox(
this.x - this._halfWidth,
this.y - this._halfHeight,
this.x + this._halfWidth,
this.y + this._halfHeight
);
this.updateViewport();

this._postupdate(_engine, delta);
}
Expand All @@ -736,15 +753,18 @@ export class Camera extends Class implements CanUpdate, CanInitialize {
canvasWidth = ctx.width;
canvasHeight = ctx.height;
}

const focus = this.getFocus();
const pixelRatio = this._engine ? this._engine.pixelRatio : 1;
const zoom = this.zoom;

const newCanvasWidth = canvasWidth / zoom / pixelRatio;
const newCanvasHeight = canvasHeight / zoom / pixelRatio;

const cameraPos = vec(-focus.x + newCanvasWidth / 2 + this._xShake, -focus.y + newCanvasHeight / 2 + this._yShake);

ctx.scale(zoom, zoom);
ctx.translate(-focus.x + newCanvasWidth / 2 + this._xShake, -focus.y + newCanvasHeight / 2 + this._yShake);
ctx.translate(cameraPos.x, cameraPos.y);
}

/* istanbul ignore next */
Expand Down
15 changes: 12 additions & 3 deletions src/engine/Engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export class Engine extends Class implements CanInitialize, CanUpdate, CanDraw {

/**
* Direct access to the engine's 2D rendering context
* @deprecated will be removed v0.26.0
* @deprecated Will be removed in v0.26.0, use Engine.graphicsContext
*/
public ctx: CanvasRenderingContext2D;

Expand Down Expand Up @@ -397,6 +397,17 @@ export class Engine extends Class implements CanInitialize, CanUpdate, CanDraw {
*/
public enableCanvasTransparency: boolean = true;

/**
* Hints the graphics context to truncate fractional world space coordinates
*/
public get snapToPixel(): boolean {
return this.graphicsContext.snapToPixel;
};

public set snapToPixel(shouldSnapToPixel: boolean) {
this.graphicsContext.snapToPixel = shouldSnapToPixel;
};

/**
* The action to take when a fatal exception is thrown
*/
Expand Down Expand Up @@ -1208,7 +1219,6 @@ O|===|* >________________>\n\
// Configure resolution for loader, it expects resolution === viewport
this.screen.resolution = this.screen.viewport;
this.screen.applyResolutionAndViewport();
this.graphicsContext.updateViewport();
this._loader = loader;
this._loader.suppressPlayButton = this._suppressPlayButton || this._loader.suppressPlayButton;
this._loader.wireEngine(this);
Expand All @@ -1228,7 +1238,6 @@ O|===|* >________________>\n\
// reset back to previous user resolution/viewport
this.screen.popResolutionAndViewport();
this.screen.applyResolutionAndViewport();
this.graphicsContext.updateViewport();
}

this._loadingComplete = true;
Expand Down
9 changes: 8 additions & 1 deletion src/engine/Graphics/Context/ExcaliburGraphicsContext.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Vector } from '../../Math/vector';
import { Matrix } from '../../Math/matrix';
import { Color } from '../../Color';
import { ScreenDimension } from '../../Screen';
import { PostProcessor } from '../PostProcessor/PostProcessor';

export type HTMLImageSource = HTMLImageElement | HTMLCanvasElement;
Expand Down Expand Up @@ -89,10 +91,15 @@ export interface ExcaliburGraphicsContext {
*/
resetTransform(): void;

/**
* Gets the current transform
*/
getTransform(): Matrix;

/**
* Update the context with the current viewport dimensions (used in resizing)
*/
updateViewport(): void;
updateViewport(resolution: ScreenDimension): void;

/**
* Access the debug drawing api
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { Color } from '../../Color';
import { StateStack } from './state-stack';
import { GraphicsDiagnostics } from '../GraphicsDiagnostics';
import { DebugText } from './debug-text';
import { Matrix } from '../../Math/matrix';
import { ScreenDimension } from '../../Screen';
import { PostProcessor } from '../PostProcessor/PostProcessor';

class ExcaliburGraphicsContext2DCanvasDebug implements DebugDraw {
Expand Down Expand Up @@ -118,7 +120,7 @@ export class ExcaliburGraphicsContext2DCanvas implements ExcaliburGraphicsContex
this.__ctx.resetTransform();
}

public updateViewport(): void {
public updateViewport(_resolution: ScreenDimension): void {
// pass
}

Expand Down Expand Up @@ -251,6 +253,10 @@ export class ExcaliburGraphicsContext2DCanvas implements ExcaliburGraphicsContex
this.__ctx.scale(x, y);
}

public getTransform(): Matrix {
throw new Error('Not implemented');
}

public addPostProcessor(_postprocessor: PostProcessor) {
throw Error('Not implemented');
}
Expand Down
19 changes: 12 additions & 7 deletions src/engine/Graphics/Context/ExcaliburGraphicsContextWebGL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ class ExcaliburGraphicsContextWebGLDebug implements DebugDraw {
export interface WebGLGraphicsContextInfo {
transform: TransformStack;
state: StateStack;
matrix: Matrix;
ortho: Matrix;
context: ExcaliburGraphicsContextWebGL;
}

export class ExcaliburGraphicsContextWebGL implements ExcaliburGraphicsContext {
Expand Down Expand Up @@ -150,7 +151,7 @@ export class ExcaliburGraphicsContextWebGL implements ExcaliburGraphicsContext {
// If any dimension is greater than max texture size (divide by 4 bytes per pixel)
const maxDim = gl.getParameter(gl.MAX_TEXTURE_SIZE) / 4;
let supported = true;
if (dim.width > maxDim ||dim.height > maxDim) {
if (dim.width > maxDim || dim.height > maxDim) {
supported = false;
}
return supported;
Expand Down Expand Up @@ -189,9 +190,9 @@ export class ExcaliburGraphicsContextWebGL implements ExcaliburGraphicsContext {
gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
gl.blendFuncSeparate(gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);

this.__pointRenderer = new PointRenderer(gl, { matrix: this._ortho, transform: this._transform, state: this._state });
this.__lineRenderer = new LineRenderer(gl, { matrix: this._ortho, transform: this._transform, state: this._state });
this.__imageRenderer = new ImageRenderer(gl, { matrix: this._ortho, transform: this._transform, state: this._state });
this.__pointRenderer = new PointRenderer(gl, { ortho: this._ortho, transform: this._transform, state: this._state, context: this });
this.__lineRenderer = new LineRenderer(gl, { ortho: this._ortho, transform: this._transform, state: this._state, context: this });
this.__imageRenderer = new ImageRenderer(gl, { ortho: this._ortho, transform: this._transform, state: this._state, context: this });
this._screenRenderer = new ScreenRenderer(gl);

this._renderTarget = new RenderTarget({
Expand Down Expand Up @@ -226,9 +227,9 @@ export class ExcaliburGraphicsContextWebGL implements ExcaliburGraphicsContext {
this._transform.current = Matrix.identity();
}

public updateViewport(): void {
public updateViewport(resolution: ScreenDimension): void {
const gl = this.__gl;
this._ortho = this._ortho = Matrix.ortho(0, gl.canvas.width, gl.canvas.height, 0, 400, -400);
this._ortho = this._ortho = Matrix.ortho(0, resolution.width, resolution.height, 0, 400, -400);
this.__pointRenderer.shader.addUniformMatrix('u_matrix', this._ortho.data);
this.__lineRenderer.shader.addUniformMatrix('u_matrix', this._ortho.data);
this.__imageRenderer.shader.addUniformMatrix('u_matrix', this._ortho.data);
Expand Down Expand Up @@ -326,6 +327,10 @@ export class ExcaliburGraphicsContextWebGL implements ExcaliburGraphicsContext {
this._transform.current = matrix;
}

public getTransform(): Matrix {
return this._transform.current;
}

public addPostProcessor(postprocessor: PostProcessor) {
this._postprocessors.push(postprocessor);
postprocessor.intialize(this.__gl);
Expand Down
13 changes: 7 additions & 6 deletions src/engine/Graphics/Context/image-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { WebGLGraphicsContextInfo } from './ExcaliburGraphicsContextWebGL';
import { TextureLoader } from './texture-loader';
import { HTMLImageSource } from './ExcaliburGraphicsContext';
import { Color } from '../../Color';
import { Vector } from '../..';
import { Vector } from '../../Math/vector';

export class BatchImage extends BatchCommand<DrawImageCommand> {
public textures: WebGLTexture[] = [];
Expand Down Expand Up @@ -125,7 +125,7 @@ export class ImageRenderer extends BatchRenderer<DrawImageCommand> {
shader.addAttribute('a_textureIndex', 1, gl.FLOAT);
shader.addAttribute('a_opacity', 1, gl.FLOAT);
shader.addAttribute('a_color', 4, gl.FLOAT);
shader.addUniformMatrix('u_matrix', this._contextInfo.matrix.data);
shader.addUniformMatrix('u_matrix', this._contextInfo.ortho.data);
// Initialize texture slots to [0, 1, 2, 3, 4, .... maxGPUTextures]
shader.addUniformIntegerArray(
'u_textures',
Expand Down Expand Up @@ -180,6 +180,7 @@ export class ImageRenderer extends BatchRenderer<DrawImageCommand> {
dheight?: number
) {
const command = this.commands.get().init(graphic, sx, sy, swidth, sheight, dx, dy, dwidth, dheight);
command.snapToPixel = this._contextInfo?.context?.snapToPixel ?? false;
command.applyTransform(this._contextInfo.transform.current, this._contextInfo.state.current.opacity);
this.addCommand(command);
}
Expand Down Expand Up @@ -222,10 +223,10 @@ export class ImageRenderer extends BatchRenderer<DrawImageCommand> {

// potential optimization when divding by 2 (bitshift)
// Modifying the images to poweroftwo images warp the UV coordinates
let uvx0 = sx / potWidth;
let uvy0 = sy / potHeight;
let uvx1 = (sx + sw) / potWidth;
let uvy1 = (sy + sh) / potHeight;
let uvx0 = (sx) / potWidth;
let uvy0 = (sy) / potHeight;
let uvx1 = (sx + sw - 0.01) / potWidth;
let uvy1 = (sy + sh - 0.01) / potHeight;
if (textureId === -2) {
uvx0 = 0;
uvy0 = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/engine/Graphics/Context/line-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class LineRenderer extends BatchRenderer<DrawLine> {

shader.addAttribute('a_position', 2, gl.FLOAT);
shader.addAttribute('a_color', 4, gl.FLOAT);
shader.addUniformMatrix('u_matrix', this._contextInfo.matrix.data);
shader.addUniformMatrix('u_matrix', this._contextInfo.ortho.data);
return shader;
}

Expand Down
3 changes: 1 addition & 2 deletions src/engine/Graphics/Context/point-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { BatchRenderer } from './renderer';
import { BatchCommand } from './batch';
import { WebGLGraphicsContextInfo } from './ExcaliburGraphicsContextWebGL';
import { Pool, Poolable } from '../../Util/Pool';
// import { Random } from '../../Math/Index';

export class DrawPoint implements Poolable {
_pool?: Pool<this>;
Expand Down Expand Up @@ -37,7 +36,7 @@ export class PointRenderer extends BatchRenderer<DrawPoint> {
shader.addAttribute('a_position', 2, gl.FLOAT);
shader.addAttribute('a_color', 4, gl.FLOAT);
shader.addAttribute('a_size', 1, gl.FLOAT);
shader.addUniformMatrix('u_matrix', this._contextInfo.matrix.data);
shader.addUniformMatrix('u_matrix', this._contextInfo.ortho.data);
return shader;
}

Expand Down
14 changes: 14 additions & 0 deletions src/engine/Graphics/Context/shader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ export class Shader {
};
}

public addUniformFloat2(name: string, float1: number = 0, float2: number = 0) {
const gl = this._gl;
this.uniforms[name] = {
name,
type: '2f',
location: gl.getUniformLocation(this.program, name) ?? Error(`Could not find uniform [${name}]`),
data: [float1, float2]
};
}

/**
* Add a uniform array of numbers to the shader
* @param name Name of the uniform in the shader source
Expand Down Expand Up @@ -230,6 +240,10 @@ export class Shader {
gl.uniformMatrix4fv(uniform.location, false, uniform.data);
break;
}
case '2f': {
gl.uniform2f(uniform.location, uniform.data[0], uniform.data[1]);
break;
}
case 'numbers': {
gl.uniform1iv(uniform.location, uniform.data);
break;
Expand Down
2 changes: 1 addition & 1 deletion src/engine/Graphics/Context/shaders/image-fragment.glsl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifdef GL_OES_standard_derivatives
#extension GL_OES_standard_derivatives : enable
#endif
precision mediump float;
precision highp float;

// UV coord
varying vec2 v_texcoord;
Expand Down
1 change: 1 addition & 0 deletions src/engine/Graphics/Context/shaders/image-vertex.glsl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
precision highp float;
attribute vec4 a_position;

// Opacity
Expand Down
3 changes: 2 additions & 1 deletion src/engine/Graphics/Context/texture-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ export class TextureLoader {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

// NEAREST for pixels
// TODO support different sampler filter?
// NEAREST for pixel art
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

Expand Down
1 change: 1 addition & 0 deletions src/engine/Math/Index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './global-coordinates';
export * from './line';
export * from './projection';
export * from './ray';
export * from './util';
Loading