Skip to content

Commit

Permalink
fix: account for camera rotation when clearing dirty rectangle #1116
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoiver committed Aug 9, 2022
1 parent cd9a778 commit c506540
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 38 deletions.
47 changes: 31 additions & 16 deletions packages/g-plugin-canvas-renderer/src/CanvasRendererPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ export class CanvasRendererPlugin implements RenderingPlugin {
private vpMatrix = mat4.create();
private dprMatrix = mat4.create();
private tmpMat4 = mat4.create();
private tmpVec3 = vec3.create();
private vec3a = vec3.create();
private vec3b = vec3.create();
private vec3c = vec3.create();
private vec3d = vec3.create();

apply(renderingService: RenderingService) {
const canvas = this.renderingContext.root.ownerDocument.defaultView;
Expand Down Expand Up @@ -211,17 +214,24 @@ export class CanvasRendererPlugin implements RenderingPlugin {
const dirtyRect = this.convertAABB2Rect(dirtyRenderBounds);
const { x, y, width, height } = dirtyRect;

const tl = vec3.transformMat4(this.tmpVec3, vec3.fromValues(x, y, 0), this.vpMatrix);
const tl = vec3.transformMat4(this.vec3a, vec3.fromValues(x, y, 0), this.vpMatrix);
const tr = vec3.transformMat4(this.vec3b, vec3.fromValues(x + width, y, 0), this.vpMatrix);
const bl = vec3.transformMat4(this.vec3c, vec3.fromValues(x, y + height, 0), this.vpMatrix);
const br = vec3.transformMat4(
vec3.create(),
this.vec3d,
vec3.fromValues(x + width, y + height, 0),
this.vpMatrix,
);

const ix = Math.floor(tl[0]);
const iy = Math.floor(tl[1]);
const iwidth = Math.ceil(br[0] - tl[0]);
const iheight = Math.ceil(br[1] - tl[1]);
const minx = Math.min(tl[0], tr[0], br[0], bl[0]);
const miny = Math.min(tl[1], tr[1], br[1], bl[1]);
const maxx = Math.max(tl[0], tr[0], br[0], bl[0]);
const maxy = Math.max(tl[1], tr[1], br[1], bl[1]);

const ix = Math.floor(minx);
const iy = Math.floor(miny);
const iwidth = Math.ceil(maxx - minx);
const iheight = Math.ceil(maxy - miny);

context.save();
this.clearRect(context, ix, iy, iwidth, iheight);
Expand All @@ -244,7 +254,12 @@ export class CanvasRendererPlugin implements RenderingPlugin {
if (enableDirtyRectangleRenderingDebug) {
canvas.dispatchEvent(
new CustomEvent(CanvasEvent.DIRTY_RECTANGLE, {
dirtyRect,
dirtyRect: {
x: ix,
y: iy,
width: iwidth,
height: iheight,
},
}),
);
}
Expand Down Expand Up @@ -507,19 +522,19 @@ export class CanvasRendererPlugin implements RenderingPlugin {
// apply clip shape's RTS
if (matrix) {
mat4.copy(this.tmpMat4, object.getLocalTransform());
this.tmpVec3[0] = tx;
this.tmpVec3[1] = ty;
this.tmpVec3[2] = 0;
mat4.translate(this.tmpMat4, this.tmpMat4, this.tmpVec3);
this.vec3a[0] = tx;
this.vec3a[1] = ty;
this.vec3a[2] = 0;
mat4.translate(this.tmpMat4, this.tmpMat4, this.vec3a);
mat4.multiply(this.tmpMat4, matrix, this.tmpMat4);
mat4.multiply(this.tmpMat4, this.vpMatrix, this.tmpMat4);
} else {
// apply RTS transformation in world space
mat4.copy(this.tmpMat4, object.getWorldTransform());
this.tmpVec3[0] = tx;
this.tmpVec3[1] = ty;
this.tmpVec3[2] = 0;
mat4.translate(this.tmpMat4, this.tmpMat4, this.tmpVec3);
this.vec3a[0] = tx;
this.vec3a[1] = ty;
this.vec3a[2] = 0;
mat4.translate(this.tmpMat4, this.tmpMat4, this.vec3a);
mat4.multiply(this.tmpMat4, this.vpMatrix, this.tmpMat4);
}

Expand Down
13 changes: 6 additions & 7 deletions packages/site/docs/api/renderer/canvas.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,13 @@ canvas.addEventListener(CanvasEvent.DIRTY_RECTANGLE, (e) => {
const { dirtyRect } = e.detail;
const { x, y, width, height } = dirtyRect;
// convert from canvas coords to viewport
const tl = canvas.canvas2Viewport({ x, y });
const br = canvas.canvas2Viewport({ x: x + width, y: y + height });
const dpr = window.devicePixelRatio;
$dirtyRectangle.style.left = `${tl.x}px`;
$dirtyRectangle.style.top = `${tl.y}px`;
$dirtyRectangle.style.width = `${br.x - tl.x}px`;
$dirtyRectangle.style.height = `${br.y - tl.y}px`;
// convert from canvas coords to viewport
$dirtyRectangle.style.left = `${x / dpr}px`;
$dirtyRectangle.style.top = `${y / dpr}px`;
$dirtyRectangle.style.width = `${width / dpr}px`;
$dirtyRectangle.style.height = `${height / dpr}px`;
});
```
Expand Down
13 changes: 6 additions & 7 deletions packages/site/docs/api/renderer/canvas.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,13 @@ canvas.addEventListener(CanvasEvent.DIRTY_RECTANGLE, (e) => {
const { dirtyRect } = e.detail;
const { x, y, width, height } = dirtyRect;
// convert from canvas coords to viewport
const tl = canvas.canvas2Viewport({ x, y });
const br = canvas.canvas2Viewport({ x: x + width, y: y + height });
const dpr = window.devicePixelRatio;
$dirtyRectangle.style.left = `${tl.x}px`;
$dirtyRectangle.style.top = `${tl.y}px`;
$dirtyRectangle.style.width = `${br.x - tl.x}px`;
$dirtyRectangle.style.height = `${br.y - tl.y}px`;
// convert from canvas coords to viewport
$dirtyRectangle.style.left = `${x / dpr}px`;
$dirtyRectangle.style.top = `${y / dpr}px`;
$dirtyRectangle.style.width = `${width / dpr}px`;
$dirtyRectangle.style.height = `${height / dpr}px`;
});
```
Expand Down
25 changes: 24 additions & 1 deletion packages/site/examples/event/demo/coordinates.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import * as lil from 'lil-gui';
import Stats from 'stats.js';

// create a renderer
const canvasRenderer = new CanvasRenderer();
const canvasRenderer = new CanvasRenderer({
enableDirtyRectangleRenderingDebug: true,
});
const webglRenderer = new WebGLRenderer();
const svgRenderer = new SVGRenderer();
const canvaskitRenderer = new CanvaskitRenderer({
Expand Down Expand Up @@ -123,6 +125,27 @@ canvas.addEventListener(CanvasEvent.READY, () => {
}
});

// display dirty rectangle
const $dirtyRectangle = document.createElement('div');
$dirtyRectangle.style.cssText = `
position: absolute;
pointer-events: none;
background: rgba(255, 0, 0, 0.5);
`;
$wrapper.appendChild($dirtyRectangle);

canvas.addEventListener(CanvasEvent.DIRTY_RECTANGLE, (e) => {
const { dirtyRect } = e.detail;
const { x, y, width, height } = dirtyRect;
const dpr = window.devicePixelRatio;

// convert from canvas coords to viewport
$dirtyRectangle.style.left = `${x / dpr}px`;
$dirtyRectangle.style.top = `${y / dpr}px`;
$dirtyRectangle.style.width = `${width / dpr}px`;
$dirtyRectangle.style.height = `${height / dpr}px`;
});

// GUI
const gui = new lil.GUI({ autoPlace: false });
$wrapper.appendChild(gui.domElement);
Expand Down
13 changes: 6 additions & 7 deletions packages/site/examples/perf/demo/canvas-dirty-rectangle.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,11 @@ $wrapper.appendChild($dirtyRectangle);
canvas.addEventListener(CanvasEvent.DIRTY_RECTANGLE, (e) => {
const { dirtyRect } = e.detail;
const { x, y, width, height } = dirtyRect;
const dpr = window.devicePixelRatio;

const tl = canvas.canvas2Viewport({ x, y });
const br = canvas.canvas2Viewport({ x: x + width, y: y + height });

$dirtyRectangle.style.left = `${tl.x}px`;
$dirtyRectangle.style.top = `${tl.y}px`;
$dirtyRectangle.style.width = `${br.x - tl.x}px`;
$dirtyRectangle.style.height = `${br.y - tl.y}px`;
// convert from canvas coords to viewport
$dirtyRectangle.style.left = `${x / dpr}px`;
$dirtyRectangle.style.top = `${y / dpr}px`;
$dirtyRectangle.style.width = `${width / dpr}px`;
$dirtyRectangle.style.height = `${height / dpr}px`;
});

0 comments on commit c506540

Please sign in to comment.