Skip to content

Commit

Permalink
fix: support cameras array
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoiver committed May 20, 2024
1 parent 4c60621 commit b03c349
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 153 deletions.
6 changes: 4 additions & 2 deletions __tests__/demos/3d/webar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ export async function ar(context) {
});

// cube.setOrigin(300, 250, 200);
cube.setPosition(300, 250, 200);
cube.setPosition(300, 250, -200);

canvas.appendChild(cube);

// Called every time a XRSession requests that a new frame be drawn.
// @see https://github.com/immersive-web/webxr-samples/blob/main/immersive-ar-session.html#L173
canvas.addEventListener(CanvasEvent.AFTER_RENDER, () => {
cube.rotate(0, 0, 0);
cube.rotate(0, 0.2, 0);
});

canvas.getConfig().disableHitTesting = true;
Expand Down
27 changes: 1 addition & 26 deletions __tests__/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ function createSpecRender(object) {
shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm',
// enableAutoRendering: false,
// enableDirtyRectangleRendering: false,
// enableDirtyRectangleRenderingDebug: true,
enableDirtyRectangleRenderingDebug: true,
});

if (generate.initRenderer) {
Expand Down Expand Up @@ -244,31 +244,6 @@ function createSpecRender(object) {
});
}

if (
selectRenderer.value === 'canvas' &&
renderer.getConfig().enableDirtyRectangleRendering &&
renderer.getConfig().enableDirtyRectangleRenderingDebug
) {
// display dirty rectangle
const $dirtyRectangle = document.createElement('div');
$dirtyRectangle.style.cssText = `
position: absolute;
pointer-events: none;
background: rgba(255, 0, 0, 0.5);
`;
$div.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`;
});
}

container.append($div);
};
};
Expand Down
2 changes: 1 addition & 1 deletion packages/g-mobile-webgl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"@antv/g-plugin-html-renderer": "workspace:*",
"@antv/g-plugin-image-loader": "workspace:*",
"@antv/g-plugin-mobile-interaction": "workspace:*",
"@antv/g-device-api": "^1.3.6",
"@antv/g-device-api": "^1.6.10",
"@antv/util": "^3.3.5",
"tslib": "^2.5.3"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/g-plugin-3d/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"@antv/g-lite": "workspace:*",
"@antv/g-plugin-device-renderer": "workspace:*",
"@antv/g-shader-components": "workspace:*",
"@antv/g-device-api": "^1.3.6",
"@antv/g-device-api": "^1.6.10",
"gl-matrix": "^3.4.3",
"tslib": "^2.5.3"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/g-plugin-device-renderer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"@antv/g-plugin-image-loader": "workspace:*",
"@antv/g-shader-components": "workspace:*",
"@antv/util": "^3.3.5",
"@antv/g-device-api": "^1.3.6",
"@antv/g-device-api": "^1.6.10",
"@webgpu/types": "^0.1.6",
"earcut": "^2.2.3",
"eventemitter3": "^5.0.1",
Expand Down
248 changes: 146 additions & 102 deletions packages/g-plugin-device-renderer/src/RenderGraphPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import {
import type { BatchManager } from './renderer';
import type { TexturePool } from './TexturePool';
import { DeviceRendererPluginOptions } from './interfaces';
import { mat4 } from 'gl-matrix';
import { mat4, vec3 } from 'gl-matrix';

// scene uniform block index
export const SceneUniformBufferIndex = 0;
Expand Down Expand Up @@ -93,6 +93,14 @@ export class RenderGraphPlugin implements RenderingPlugin {
private capturePromise: Promise<string> | undefined;
private resolveCapturePromise: (dataURL: string) => void;

private cameras: {
viewport: XRViewport;
projectionMatrix: mat4;
viewMatrix: mat4;
cameraPosition: vec3;
isOrtho: boolean;
}[] = [];

getDevice(): Device {
return this.device;
}
Expand Down Expand Up @@ -258,8 +266,6 @@ export class RenderGraphPlugin implements RenderingPlugin {
config.disableRenderHooks = false;
});

// let usedViewport: XRViewport | undefined;

/**
* build frame graph at the beginning of each frame
*/
Expand All @@ -269,7 +275,6 @@ export class RenderGraphPlugin implements RenderingPlugin {
const session = frame?.session;
const { width, height } = this.context.config;
if (session) {
const camera = this.context.camera;
// Assumed to be a XRWebGLLayer for now.
let layer = session.renderState.baseLayer;
if (!layer) {
Expand All @@ -292,29 +297,60 @@ export class RenderGraphPlugin implements RenderingPlugin {
// XRFrame.getViewerPose can return null while the session attempts to establish tracking.
const pose = frame.getViewerPose(referenceSpace);
if (pose) {
// const p = pose.transform.position;
// In mobile AR, we only have one view.
const view = pose.views[0];
// const viewport = session.renderState.baseLayer!.getViewport(view)!;
// usedViewport = viewport;
// @ts-ignore
const cameraMatrix = mat4.fromValues(...view.transform.matrix);
cameraMatrix[12] *= width;
cameraMatrix[13] *= -height;
cameraMatrix[14] *= 500;

cameraMatrix[12] += width / 2;
cameraMatrix[13] += height / 2;
cameraMatrix[14] += 500 / 2;

// @ts-ignore
const projectionMatrix = mat4.fromValues(...view.projectionMatrix);
mat4.scale(projectionMatrix, projectionMatrix, [1, -1, 1]); // flipY

// @ts-ignore
camera.setProjectionMatrix(projectionMatrix);
camera.setMatrix(cameraMatrix);
pose.views.forEach((view, i) => {
const viewport =
session.renderState.baseLayer!.getViewport(view)!;

// @ts-ignore
const cameraMatrix = mat4.fromValues(...view.transform.matrix);
cameraMatrix[12] *= width;
cameraMatrix[13] *= -height;
cameraMatrix[14] *= 500;

cameraMatrix[12] += width / 2;
cameraMatrix[13] += height / 2;
cameraMatrix[14] += 500 / 2;

// Use this matrix without modification or decomposition
// @see https://immersive-web.github.io/webxr/#dom-xrview-projectionmatrix
const projectionMatrix = mat4.fromValues(
// @ts-ignore
...view.projectionMatrix,
);
// mat4.scale(projectionMatrix, projectionMatrix, [1, -1, 1]); // flipY

const { x, y, z } = pose.transform.position;
this.cameras[i] = {
viewport: {
x: viewport.x / layer.framebufferWidth,
y: viewport.y / layer.framebufferHeight,
width: viewport.width / layer.framebufferWidth,
height: viewport.height / layer.framebufferHeight,
},
projectionMatrix,
viewMatrix: mat4.invert(mat4.create(), cameraMatrix),
cameraPosition: [x, y, z],
isOrtho: false,
};
});
}
} else {
const camera = this.context.camera;
this.cameras = [
{
viewport: {
x: 0,
y: 0,
width: 1,
height: 1,
},
projectionMatrix: camera.getPerspective(),
viewMatrix: camera.getViewTransform(),
cameraPosition: camera.getPosition(),
isOrtho: camera.isOrtho(),
},
];
}

const canvas = this.swapChain.getCanvas() as HTMLCanvasElement;
Expand Down Expand Up @@ -372,24 +408,26 @@ export class RenderGraphPlugin implements RenderingPlugin {
'Main Depth',
);

// main render pass
this.builder.pushPass((pass) => {
pass.setDebugName('Main Render Pass');
// if (usedViewport) {
// const { x, y, width: vw, height: vh } = usedViewport;
// // pass.setViewport(x, y, vw / width / 2, vh / height / 2);
// console.log(x, y, vw, vh, width, height);
// }
pass.attachRenderTargetID(RGAttachmentSlot.Color0, mainColorTargetID);
pass.attachRenderTargetID(
RGAttachmentSlot.DepthStencil,
mainDepthTargetID,
);
pass.exec((passRenderer) => {
this.renderLists.world.drawOnPassRenderer(
renderInstManager.renderCache,
passRenderer,
this.cameras.forEach(({ viewport }) => {
// main render pass
this.builder.pushPass((pass) => {
pass.setDebugName('Main Render Pass');
const { x, y, width, height } = viewport;
pass.setViewport(x, y, width, height);
pass.attachRenderTargetID(
RGAttachmentSlot.Color0,
mainColorTargetID,
);
pass.attachRenderTargetID(
RGAttachmentSlot.DepthStencil,
mainDepthTargetID,
);
pass.exec((passRenderer) => {
this.renderLists.world.drawOnPassRenderer(
renderInstManager.renderCache,
passRenderer,
);
});
});
});

Expand All @@ -416,68 +454,74 @@ export class RenderGraphPlugin implements RenderingPlugin {
RenderGraphPlugin.tag,
(frame: XRFrame) => {
const renderInstManager = this.renderHelper.renderInstManager;

// TODO: time for GPU Animation
// const timeInMilliseconds = window.performance.now();

// Push our outer template, which contains the dynamic UBO bindings...
const template = this.renderHelper.pushTemplateRenderInst();
// SceneParams: binding = 0, ObjectParams: binding = 1
template.setBindingLayout({ numUniformBuffers: 2, numSamplers: 0 });
template.setMegaStateFlags(
setAttachmentStateSimple(
{
depthWrite: true,
blendConstant: TransparentBlack,
},
{
rgbBlendMode: BlendMode.ADD,
alphaBlendMode: BlendMode.ADD,
rgbBlendSrcFactor: BlendFactor.SRC_ALPHA,
alphaBlendSrcFactor: BlendFactor.ONE,
rgbBlendDstFactor: BlendFactor.ONE_MINUS_SRC_ALPHA,
alphaBlendDstFactor: BlendFactor.ONE_MINUS_SRC_ALPHA,
},
),
);

// Update Scene Params
const { width, height } = this.context.config;
const camera = this.context.camera;
template.setUniforms(SceneUniformBufferIndex, [
{
name: SceneUniform.PROJECTION_MATRIX,
value: camera.getPerspective(),
},
{
name: SceneUniform.VIEW_MATRIX,
value: camera.getViewTransform(),
},
{
name: SceneUniform.CAMERA_POSITION,
value: camera.getPosition(),
},
{
name: SceneUniform.DEVICE_PIXEL_RATIO,
value: this.context.contextService.getDPR(),
},
{
name: SceneUniform.VIEWPORT,
value: [width, height],
},
{
name: SceneUniform.IS_ORTHO,
value: camera.isOrtho() ? 1 : 0,
},
{
name: SceneUniform.IS_PICKING,
value: 0,
},
]);

this.batchManager.render(this.renderLists.world);
this.cameras.forEach(
({
viewport,
cameraPosition,
viewMatrix,
projectionMatrix,
isOrtho,
}) => {
const { width: normalizedW, height: normalizedH } = viewport;

// Push our outer template, which contains the dynamic UBO bindings...
const template = this.renderHelper.pushTemplateRenderInst();
// SceneParams: binding = 0, ObjectParams: binding = 1
template.setBindingLayout({ numUniformBuffers: 2, numSamplers: 0 });
template.setMegaStateFlags(
setAttachmentStateSimple(
{
depthWrite: true,
blendConstant: TransparentBlack,
},
{
rgbBlendMode: BlendMode.ADD,
alphaBlendMode: BlendMode.ADD,
rgbBlendSrcFactor: BlendFactor.SRC_ALPHA,
alphaBlendSrcFactor: BlendFactor.ONE,
rgbBlendDstFactor: BlendFactor.ONE_MINUS_SRC_ALPHA,
alphaBlendDstFactor: BlendFactor.ONE_MINUS_SRC_ALPHA,
},
),
);

renderInstManager.popTemplateRenderInst();
template.setUniforms(SceneUniformBufferIndex, [
{
name: SceneUniform.PROJECTION_MATRIX,
value: projectionMatrix,
},
{
name: SceneUniform.VIEW_MATRIX,
value: viewMatrix,
},
{
name: SceneUniform.CAMERA_POSITION,
value: cameraPosition,
},
{
name: SceneUniform.DEVICE_PIXEL_RATIO,
value: this.context.contextService.getDPR(),
},
{
name: SceneUniform.VIEWPORT,
value: [width * normalizedW, height * normalizedH],
},
{
name: SceneUniform.IS_ORTHO,
value: isOrtho ? 1 : 0,
},
{
name: SceneUniform.IS_PICKING,
value: 0,
},
]);

this.batchManager.render(this.renderLists.world);

renderInstManager.popTemplateRenderInst();
},
);

this.renderHelper.prepareToRender();
this.renderHelper.renderGraph.execute();
Expand Down
2 changes: 1 addition & 1 deletion packages/g-webgl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"@antv/g-plugin-html-renderer": "workspace:*",
"@antv/g-plugin-image-loader": "workspace:*",
"@antv/util": "^3.3.5",
"@antv/g-device-api": "^1.3.6",
"@antv/g-device-api": "^1.6.10",
"tslib": "^2.5.3"
},
"devDependencies": {
Expand Down
Loading

0 comments on commit b03c349

Please sign in to comment.