diff --git a/.eslintignore b/.eslintignore index 60a4e5bd5..19eeadf09 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,3 +5,5 @@ lib dist node_modules rollup.config.js +site +__tests__ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 752f64ed1..0d6744069 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,7 +40,7 @@ jobs: "link": { "title": "🚀 开始自动发布 🚀", "text": "🔗 请点击链接查看详情", - "messageUrl": "https://github.com/antvis/G/actions/workflows/auto-release.yml", + "messageUrl": "https://github.com/antvis/G/actions/workflows/release.yml", "picUrl": "https://gw.alipayobjects.com/zos/antfincdn/9Ivxcn0hFl/Gtoutu.png" } } @@ -73,7 +73,7 @@ jobs: "link": { "title": "🚨 自动发布失败 🚨", "text": "🔗 请点击链接查看具体原因, 及时修复, 尝试点击右上角 [Re-run all jobs] 重试, 或手动发布 🚑", - "messageUrl": "https://github.com/antvis/G/actions/workflows/auto-release.yml", + "messageUrl": "https://github.com/antvis/G/actions/workflows/release.yml", "picUrl": "https://gw.alipayobjects.com/zos/antfincdn/9Ivxcn0hFl/Gtoutu.png" } } diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d2cc7f655..384d9614b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,6 +8,7 @@ concurrency: jobs: test: + name: Test # jest-electron 需要 macOS 环境, 但是 免费用户 并发有限制, 容易排队 https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners # runs-on: macos-latest # (目前 macos-latest 对应的是 Big Sur 11, macos-12 对应 Monterey 12) # macOS 3-core CPU, 其他 2-core CPU diff --git a/__tests__/integration/__node__tests__/webgl/d3-barchart.spec.js b/__tests__/integration/__node__tests__/webgl/d3-barchart.spec.js new file mode 100644 index 000000000..11de64307 --- /dev/null +++ b/__tests__/integration/__node__tests__/webgl/d3-barchart.spec.js @@ -0,0 +1,213 @@ +const fs = require('fs'); +const { createCanvas } = require('canvas'); +const d3 = require('d3'); +const { Canvas, Rectangle } = require('@antv/g'); +const { Renderer } = require('@antv/g-webgl'); +const { createPNGFromRawdata, sleep, diff } = require('../../util'); +const weatherDataset = require('../../data/weather.json'); + +// create a renderer, unregister plugin relative to DOM +const renderer = new Renderer({ + targets: ['webgl1'], +}); +const domInteractionPlugin = renderer.getPlugin('dom-interaction'); +renderer.unregisterPlugin(domInteractionPlugin); + +const width = 600; +const height = 500; +const gl = require('gl')(width, height, { + antialias: false, + preserveDrawingBuffer: true, + stencil: true, +}); +const mockCanvas = { + width, + height, + getContext: () => { + gl.canvas = mockCanvas; + // 模拟 DOM API,返回小程序 context,它应当和 CanvasRenderingContext2D 一致 + // @see https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/getContext + return gl; + }, + getBoundingClientRect: () => { + // 模拟 DOM API,返回小程序 context 相对于视口的位置 + // @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect + return new Rectangle(0, 0, width, height); + }, +}; + +// create a node-canvas +const offscreenNodeCanvas = createCanvas(1, 1); +const canvas = new Canvas({ + width, + height, + canvas: mockCanvas, // use headless-gl + renderer, + offscreenCanvas: offscreenNodeCanvas, +}); + +const RESULT_IMAGE = '/d3-barchart.png'; +const BASELINE_IMAGE_DIR = '/snapshots'; + +describe('Render D3 barchart with g-webgl', () => { + afterEach(() => { + canvas.removeChildren(); + fs.rmSync(__dirname + RESULT_IMAGE); + }); + + afterAll(() => { + canvas.destroy(); + }); + + it('should render D3 barchart on server-side correctly.', async () => { + await canvas.ready; + + const drawBars = async () => { + // 1. Access data + const dataset = weatherDataset; + const metricAccessor = (d) => d.humidity; + const yAccessor = (d) => d.length; + + // 2. Create chart dimensions + const width = 600; + let dimensions = { + width: width, + height: width * 0.6, + margin: { + top: 30, + right: 10, + bottom: 50, + left: 50, + }, + }; + dimensions.boundedWidth = + dimensions.width - dimensions.margin.left - dimensions.margin.right; + dimensions.boundedHeight = + dimensions.height - dimensions.margin.top - dimensions.margin.bottom; + + // 3. Draw canvas + const wrapper = d3.select( + canvas.document.documentElement, // use GCanvas' document element instead of a real DOM + ); + + const bounds = wrapper + .append('g') + .style( + 'transform', + `translate(${dimensions.margin.left}px, ${dimensions.margin.top}px)`, + ); + + // 4. Create scales + + const xScale = d3 + .scaleLinear() + .domain(d3.extent(dataset, metricAccessor)) + .range([0, dimensions.boundedWidth]) + .nice(); + + const binsGenerator = d3 + .bin() + .domain(xScale.domain()) + .value(metricAccessor) + .thresholds(12); + + const bins = binsGenerator(dataset); + + const yScale = d3 + .scaleLinear() + .domain([0, d3.max(bins, yAccessor)]) + .range([dimensions.boundedHeight, 0]) + .nice(); + + // 5. Draw data + const binsGroup = bounds.append('g'); + const binGroups = binsGroup + .selectAll('g') + .data(bins) + .join('g') + .attr('class', 'bin'); + + const barPadding = 1; + const barRects = binGroups + .append('rect') + .attr('x', (d) => xScale(d.x0) + barPadding / 2) + .attr('y', (d) => yScale(yAccessor(d))) + .attr('width', (d) => + d3.max([0, xScale(d.x1) - xScale(d.x0) - barPadding]), + ) + .attr('height', (d) => dimensions.boundedHeight - yScale(yAccessor(d))) + .attr('fill', 'cornflowerblue') + .on('mouseenter', function (e) { + d3.select(e.target).attr('fill', 'red'); + }) + .on('mouseleave', function (e) { + d3.select(e.target).attr('fill', 'cornflowerblue'); + }); + + const barText = binGroups + .filter(yAccessor) + .append('text') + .attr('x', (d) => xScale(d.x0) + (xScale(d.x1) - xScale(d.x0)) / 2) + .attr('y', (d) => yScale(yAccessor(d)) - 5) + .text(yAccessor) + .attr('fill', 'darkgrey') + .style('text-anchor', 'middle') + .style('font-size', '12px') + .style('font-family', 'sans-serif'); + + const mean = d3.mean(dataset, metricAccessor); + const meanLine = bounds + .append('line') + .attr('x1', xScale(mean)) + .attr('x2', xScale(mean)) + .attr('y1', -15) + .attr('y2', dimensions.boundedHeight) + .attr('stroke-width', 1) + .attr('stroke', 'maroon') + .attr('stroke-dasharray', '2px 4px'); + + const meanLabel = bounds + .append('text') + .attr('x', xScale(mean)) + .attr('y', -20) + .text('mean') + .attr('fill', 'maroon') + .style('font-size', '12px') + .style('text-anchor', 'middle'); + + // 6. Draw peripherals + const xAxisGenerator = d3.axisBottom().scale(xScale); + + const xAxis = bounds + .append('g') + .call(xAxisGenerator) + .attr('transform', `translateY(${dimensions.boundedHeight}px)`) + .attr('fill', 'black'); + + const xAxisLabel = xAxis + .append('text') + .attr('x', dimensions.boundedWidth / 2) + .attr('y', dimensions.margin.bottom - 10) + .attr('fill', 'black') + .style('font-size', '10px') + .text('Humidity') + .style('text-transform', 'capitalize'); + }; + + drawBars(); + + await sleep(200); + + const pixels = new Uint8Array(width * height * 4); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + + await createPNGFromRawdata(__dirname + RESULT_IMAGE, width, height, pixels); + + expect( + diff( + __dirname + RESULT_IMAGE, + __dirname + BASELINE_IMAGE_DIR + RESULT_IMAGE, + ), + ).toBeLessThan(50); + }); +}); diff --git a/__tests__/integration/__node__tests__/webgl/d3-linechart.spec.js b/__tests__/integration/__node__tests__/webgl/d3-linechart.spec.js new file mode 100644 index 000000000..d07a31d9c --- /dev/null +++ b/__tests__/integration/__node__tests__/webgl/d3-linechart.spec.js @@ -0,0 +1,177 @@ +const fs = require('fs'); +const { createCanvas } = require('canvas'); +const d3 = require('d3'); +const { Canvas, Rectangle } = require('@antv/g'); +const { Renderer } = require('@antv/g-webgl'); +const { createPNGFromRawdata, sleep, diff } = require('../../util'); +const weatherDataset = require('../../data/weather.json'); + +// create a renderer, unregister plugin relative to DOM +const renderer = new Renderer({ + targets: ['webgl1'], +}); +const domInteractionPlugin = renderer.getPlugin('dom-interaction'); +renderer.unregisterPlugin(domInteractionPlugin); + +const width = 600; +const height = 500; +const gl = require('gl')(width, height, { + antialias: false, + preserveDrawingBuffer: true, + stencil: true, +}); +const mockCanvas = { + width, + height, + getContext: () => { + gl.canvas = mockCanvas; + // 模拟 DOM API,返回小程序 context,它应当和 CanvasRenderingContext2D 一致 + // @see https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/getContext + return gl; + }, + getBoundingClientRect: () => { + // 模拟 DOM API,返回小程序 context 相对于视口的位置 + // @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect + return new Rectangle(0, 0, width, height); + }, +}; + +// create a node-canvas +const offscreenNodeCanvas = createCanvas(1, 1); +const canvas = new Canvas({ + width, + height, + canvas: mockCanvas, // use headless-gl + renderer, + offscreenCanvas: offscreenNodeCanvas, +}); + +const RESULT_IMAGE = '/d3-linechart.png'; +const BASELINE_IMAGE_DIR = '/snapshots'; + +describe('Render D3 linechart with g-webgl', () => { + afterEach(() => { + canvas.removeChildren(); + fs.rmSync(__dirname + RESULT_IMAGE); + }); + + afterAll(() => { + canvas.destroy(); + }); + + it('should render D3 linechart on server-side correctly.', async () => { + await canvas.ready; + + const drawLineChart = () => { + // 1. Access data + const data = weatherDataset; + const parseDate = d3.timeParse('%Y-%m-%d'); + //define x axis with xAccessor, wrape with parseDate from above + const xAccessor = (d) => parseDate(d['date']); + const yAccessor = (d) => d['temperatureMax']; + + // 2. Create chart dimensions + const width = 600; + let dimensions = { + width: width, + height: width * 0.6, + margin: { + top: 30, + right: 10, + bottom: 50, + left: 50, + }, + }; + dimensions.boundedWidth = + dimensions.width - dimensions.margin.left - dimensions.margin.right; + dimensions.boundedHeight = + dimensions.height - dimensions.margin.top - dimensions.margin.bottom; + + // 3. Draw canvas + const container = d3 + .select( + canvas.document.documentElement, // use GCanvas' document element instead of a real DOM + ) + .append('g') + .attr('x', dimensions.margin.left) + .attr('y', dimensions.margin.top); + + // 4. Create scales + + const yScale = d3 + .scaleLinear() + //domain is the min and max input value, range is min and max output + //domain should be the smallest and largest numbers our y axis will need to handle — in this case the lowest and highest max temperature in our dataset. + // could define ourselves with .domain([0, 100]) + //better to use d3.extent, which will figure if out for us + //needs two parameters, the data and the yAccessor (temp max) + .domain(d3.extent(data, yAccessor)) + //range, in this case, should be min and max on xaxis. Can use boundedHeight to stay within margins + .range([dimensions.boundedHeight, 0]); + + //Draw a rectangle covering all temps below freezing. + //define scale - 32 degrees + const freezingTemperaturePlacement = yScale(32); + //create the rectangle with x,y, width and height + const freezingTemperatures = container + .append('rect') + .attr('x', 0) + .attr('width', dimensions.boundedWidth) + .attr('y', freezingTemperaturePlacement) + .attr('height', dimensions.boundedHeight - freezingTemperaturePlacement) + .attr('fill', '#e0f3f3'); + + const xScale = d3 + .scaleTime() + .domain(d3.extent(data, xAccessor)) + .range([0, dimensions.boundedWidth]); + + // 5. Draw data + + //We transform our data point with both the accessor function and the scale to get the scaled value in pixel space. + + const lineGenerator = d3 + .line() + .x((d) => xScale(xAccessor(d))) + .y((d) => yScale(yAccessor(d))); + + //Now add the path element to the points + // Will be filled by default. Use styles to add a stroke + const line = container + .append('path') + .attr('d', lineGenerator(data)) + .attr('fill', 'none') + .attr('stroke', '#af9358') + .attr('stroke-width', 2); + + // 6. Draw Axis + + const yAxisGenerator = d3.axisLeft().scale(yScale); + + const yAxis = container.append('g').call(yAxisGenerator); + + const xAxisGenerator = d3.axisBottom().scale(xScale); + + const xAxis = container + .append('g') + .call(xAxisGenerator) + .style('transform', `translateY(${dimensions.boundedHeight}px)`); + }; + + drawLineChart(); + + await sleep(200); + + const pixels = new Uint8Array(width * height * 4); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + + await createPNGFromRawdata(__dirname + RESULT_IMAGE, width, height, pixels); + + expect( + diff( + __dirname + RESULT_IMAGE, + __dirname + BASELINE_IMAGE_DIR + RESULT_IMAGE, + ), + ).toBeLessThan(50); + }); +}); diff --git a/__tests__/integration/__node__tests__/webgl/d3-scatterchart.spec.js b/__tests__/integration/__node__tests__/webgl/d3-scatterchart.spec.js new file mode 100644 index 000000000..f919e1b82 --- /dev/null +++ b/__tests__/integration/__node__tests__/webgl/d3-scatterchart.spec.js @@ -0,0 +1,185 @@ +const fs = require('fs'); +const { createCanvas } = require('canvas'); +const d3 = require('d3'); +const { Canvas, Rectangle } = require('@antv/g'); +const { Renderer } = require('@antv/g-webgl'); +const { createPNGFromRawdata, sleep, diff } = require('../../util'); +const weatherDataset = require('../../data/weather.json'); + +// create a renderer, unregister plugin relative to DOM +const renderer = new Renderer({ + targets: ['webgl1'], +}); +const domInteractionPlugin = renderer.getPlugin('dom-interaction'); +renderer.unregisterPlugin(domInteractionPlugin); + +const width = 600; +const height = 500; +const gl = require('gl')(width, height, { + antialias: false, + preserveDrawingBuffer: true, + stencil: true, +}); +const mockCanvas = { + width, + height, + getContext: () => { + gl.canvas = mockCanvas; + // 模拟 DOM API,返回小程序 context,它应当和 CanvasRenderingContext2D 一致 + // @see https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/getContext + return gl; + }, + getBoundingClientRect: () => { + // 模拟 DOM API,返回小程序 context 相对于视口的位置 + // @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect + return new Rectangle(0, 0, width, height); + }, +}; + +// create a node-canvas +const offscreenNodeCanvas = createCanvas(1, 1); +const canvas = new Canvas({ + width, + height, + canvas: mockCanvas, // use headless-gl + renderer, + offscreenCanvas: offscreenNodeCanvas, +}); + +const RESULT_IMAGE = '/d3-scatterchart.png'; +const BASELINE_IMAGE_DIR = '/snapshots'; + +describe('Render D3 scatterchart with g-webgl', () => { + afterEach(() => { + canvas.removeChildren(); + fs.rmSync(__dirname + RESULT_IMAGE); + }); + + afterAll(() => { + canvas.destroy(); + }); + + it('should render D3 linechart on server-side correctly.', async () => { + await canvas.ready; + + const drawScatter = () => { + // 1. Access data + const dataset = weatherDataset; + const xAccessor = (d) => d.dewPoint; + const yAccessor = (d) => d.humidity; + const colorAccessor = (d) => d.cloudCover; + + // 2. Create chart dimensions + const width = 600; + let dimensions = { + width: width, + height: width, + margin: { + top: 10, + right: 10, + bottom: 50, + left: 50, + }, + }; + dimensions.boundedWidth = + dimensions.width - dimensions.margin.left - dimensions.margin.right; + dimensions.boundedHeight = + dimensions.height - dimensions.margin.top - dimensions.margin.bottom; + + // 3. Draw canvas + const bounds = d3 + .select( + canvas.document.documentElement, // use GCanvas' document element instead of a real DOM + ) + .append('g') + .attr('x', dimensions.margin.left) + .attr('y', dimensions.margin.top); + + // 4. Create scales + + const xScale = d3 + .scaleLinear() + .domain(d3.extent(dataset, xAccessor)) + .range([0, dimensions.boundedWidth]) + .nice(); + + const yScale = d3 + .scaleLinear() + .domain(d3.extent(dataset, yAccessor)) + .range([dimensions.boundedHeight, 0]) + .nice(); + + const colorScale = d3 + .scaleLinear() + .domain(d3.extent(dataset, colorAccessor)) + .range(['skyblue', 'darkslategrey']); + + // 5. Draw data + + const dots = bounds.selectAll('circle').data(dataset); + + dots + .join('circle') + .attr('cx', (d) => xScale(xAccessor(d))) + .attr('cy', (d) => yScale(yAccessor(d))) + .attr('r', 5) + .attr('fill', (d) => colorScale(colorAccessor(d))); + + // 6. Draw Preipherals - x axis and y axis + + //create a variable for xaxis and define it + const xAxisGenerator = d3.axisBottom().scale(xScale); + + //add to the bounds + const xAxis = bounds + .append('g') + .call(xAxisGenerator) + //move to the bottom of the screen + .style('transform', `translateY(${dimensions.boundedHeight}px)`); + + const xAxisLabel = xAxis + .append('text') + .attr('x', dimensions.boundedWidth / 2) + .attr('y', dimensions.margin.bottom - 10) + .attr('fill', 'black') + .style('font-size', '1.4em') + .html('Dew point (°F)'); + + //same thing with the y axis + const yAxisGenerator = d3 + .axisLeft() + .scale(yScale) + //define the number of ticks that you want + .ticks(4); + + const yAxis = bounds.append('g').call(yAxisGenerator); + + const yAxisLabel = yAxis + .append('text') + //using negative dimensions so we can rotate below with transform + .attr('x', -dimensions.boundedHeight / 2) + .attr('y', -dimensions.margin.left + 10) + .style('fill', 'black') + .text('Relative Humidity') + .style('transform', 'rotate(-90deg)') + .style('font-size', '1.4em') + .style('text-anchor', 'middle'); + }; + + drawScatter(); + + await sleep(200); + + const pixels = new Uint8Array(width * height * 4); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + + await createPNGFromRawdata(__dirname + RESULT_IMAGE, width, height, pixels); + + expect( + diff( + __dirname + RESULT_IMAGE, + __dirname + BASELINE_IMAGE_DIR + RESULT_IMAGE, + ), + ).toBeLessThan(50); + }); +}); diff --git a/__tests__/integration/__node__tests__/webgl/snapshots/d3-barchart.png b/__tests__/integration/__node__tests__/webgl/snapshots/d3-barchart.png new file mode 100644 index 000000000..ced8c8df4 Binary files /dev/null and b/__tests__/integration/__node__tests__/webgl/snapshots/d3-barchart.png differ diff --git a/__tests__/integration/__node__tests__/webgl/snapshots/d3-linechart.png b/__tests__/integration/__node__tests__/webgl/snapshots/d3-linechart.png new file mode 100644 index 000000000..eb7cefeb0 Binary files /dev/null and b/__tests__/integration/__node__tests__/webgl/snapshots/d3-linechart.png differ diff --git a/__tests__/integration/__node__tests__/webgl/snapshots/d3-scatterchart.png b/__tests__/integration/__node__tests__/webgl/snapshots/d3-scatterchart.png new file mode 100644 index 000000000..41103c7af Binary files /dev/null and b/__tests__/integration/__node__tests__/webgl/snapshots/d3-scatterchart.png differ diff --git a/__tests__/unit/camera/camera.spec.ts b/__tests__/unit/camera/camera.spec.ts index 82de6b138..d108f7294 100644 --- a/__tests__/unit/camera/camera.spec.ts +++ b/__tests__/unit/camera/camera.spec.ts @@ -5,6 +5,7 @@ import { AdvancedCamera, CameraProjectionMode, Canvas, + ClipSpaceNearZ, } from '../../../packages/g/src'; expect.extend({ toBeDeepCloseTo, toMatchCloseTo }); @@ -127,6 +128,153 @@ describe('Camera', () => { expect(camera.getAzimuth()).toBe(0); }); + it('should create an orthoZO camera correctly', () => { + const width = 600; + const height = 500; + const camera = new AdvancedCamera(); + camera.clipSpaceNearZ = ClipSpaceNearZ.ZERO; + camera + .setPosition(width / 2, height / 2, 500) + .setFocalPoint(width / 2, height / 2, 0) + .setOrthographic( + width / -2, + width / 2, + height / -2, + height / 2, + 0.1, + 1000, + ); + + expect(camera.getProjectionMode()).toBe(CameraProjectionMode.ORTHOGRAPHIC); + expect(camera.getZoom()).toBe(1); + expect(camera.getFar()).toBe(1000); + expect(camera.getNear()).toBe(0.1); + expect(camera.getPosition()).toStrictEqual(vec3.fromValues(300, 250, 500)); + expect(camera.getFocalPoint()).toStrictEqual(vec3.fromValues(300, 250, 0)); + expect(camera.getDistance()).toBe(500); + + expect(camera.getViewTransform()).toStrictEqual( + mat4.fromValues(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -300, -250, -500, 1), + ); + expect(camera.getWorldTransform()).toStrictEqual( + mat4.fromValues(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 300, 250, 500, 1), + ); + + expect(camera.getPerspective()).toBeDeepCloseTo( + mat4.fromValues( + 0.0033333334140479565, + 0, + 0, + 0, + -0, + 0.004000000189989805, + -0, + -0, + 0, + 0, + -0.0020002000965178013, + 0, + -0, + 0, + -0.00010001000191550702, + 1, + ), + ); + }); + + it('should create an perspective camera correctly', () => { + const width = 600; + const height = 500; + const camera = new AdvancedCamera(); + camera + .setPosition(width / 2, height / 2, 500) + .setFocalPoint(width / 2, height / 2, 0) + .setPerspective(0.1, 1000, 45, width / height); + + expect(camera.getProjectionMode()).toBe(CameraProjectionMode.PERSPECTIVE); + expect(camera.getZoom()).toBe(1); + expect(camera.getFar()).toBe(1000); + expect(camera.getNear()).toBe(0.1); + expect(camera.getPosition()).toStrictEqual(vec3.fromValues(300, 250, 500)); + expect(camera.getFocalPoint()).toStrictEqual(vec3.fromValues(300, 250, 0)); + expect(camera.getDistance()).toBe(500); + + expect(camera.getViewTransform()).toStrictEqual( + mat4.fromValues(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -300, -250, -500, 1), + ); + expect(camera.getWorldTransform()).toStrictEqual( + mat4.fromValues(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 300, 250, 500, 1), + ); + + expect(camera.getPerspective()).toBeDeepCloseTo( + mat4.fromValues( + 2.0118446350097656, + 0, + 0, + 0, + -0, + -2.4142136573791504, + -0, + -0, + 0, + 0, + -1.0002000331878662, + -1, + -0, + 0, + -0.20002000033855438, + 0, + ), + ); + }); + + it('should create an perspectiveZO camera correctly', () => { + const width = 600; + const height = 500; + const camera = new AdvancedCamera(); + camera.clipSpaceNearZ = ClipSpaceNearZ.ZERO; + camera + .setPosition(width / 2, height / 2, 500) + .setFocalPoint(width / 2, height / 2, 0) + .setPerspective(0.1, 1000, 45, width / height); + + expect(camera.getProjectionMode()).toBe(CameraProjectionMode.PERSPECTIVE); + expect(camera.getZoom()).toBe(1); + expect(camera.getFar()).toBe(1000); + expect(camera.getNear()).toBe(0.1); + expect(camera.getPosition()).toStrictEqual(vec3.fromValues(300, 250, 500)); + expect(camera.getFocalPoint()).toStrictEqual(vec3.fromValues(300, 250, 0)); + expect(camera.getDistance()).toBe(500); + + expect(camera.getViewTransform()).toStrictEqual( + mat4.fromValues(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -300, -250, -500, 1), + ); + expect(camera.getWorldTransform()).toStrictEqual( + mat4.fromValues(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 300, 250, 500, 1), + ); + + expect(camera.getPerspective()).toBeDeepCloseTo( + mat4.fromValues( + 2.0118446350097656, + 0, + 0, + 0, + -0, + -2.4142136573791504, + -0, + -0, + 0, + 0, + -1.0002000331878662, + -1, + -0, + 0, + -0.10001000016927719, + 0, + ), + ); + }); + it('should setDistance correctly.', () => { const width = 600; const height = 500; diff --git a/packages/g-lite/src/AbstractRenderer.ts b/packages/g-lite/src/AbstractRenderer.ts index 1d4a1771d..8fd28d759 100644 --- a/packages/g-lite/src/AbstractRenderer.ts +++ b/packages/g-lite/src/AbstractRenderer.ts @@ -1,7 +1,7 @@ import type { CanvasContext } from './dom'; import { GlobalRuntime } from './global-runtime'; import type { RenderingPlugin } from './services'; -import type { RendererConfig } from './types'; +import { ClipSpaceNearZ, RendererConfig } from './types'; export interface RendererPlugin { name: string; @@ -36,6 +36,12 @@ export abstract class AbstractRendererPlugin } export interface IRenderer { + /** + * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1], + * which matches WebGPU/Vulkan/DirectX/Metal's clip volume, while [-1, 1] matches WebGL/OpenGL's clip volume. + */ + clipSpaceNearZ: ClipSpaceNearZ; + getConfig: () => RendererConfig; /** @@ -60,6 +66,7 @@ export interface IRenderer { } export class AbstractRenderer implements IRenderer { + clipSpaceNearZ = ClipSpaceNearZ.NEGATIVE_ONE; private plugins: RendererPlugin[] = []; private config: RendererConfig; diff --git a/packages/g-lite/src/Canvas.ts b/packages/g-lite/src/Canvas.ts index 3040e02dd..ded778205 100644 --- a/packages/g-lite/src/Canvas.ts +++ b/packages/g-lite/src/Canvas.ts @@ -21,7 +21,12 @@ import { FrustumCullingStrategy } from './plugins/FrustumCullingStrategy'; import { PrepareRendererPlugin } from './plugins/PrepareRendererPlugin'; import { EventService, RenderReason, RenderingService } from './services'; import type { PointLike } from './shapes'; -import type { CanvasConfig, Cursor, InteractivePointerEvent } from './types'; +import type { + CanvasConfig, + ClipSpaceNearZ, + Cursor, + InteractivePointerEvent, +} from './types'; import { caf, cleanExistedCanvas, @@ -227,7 +232,7 @@ export class Canvas extends EventTarget implements ICanvas { alwaysTriggerPointerEventOnCanvas, }); - this.initDefaultCamera(canvasWidth, canvasHeight); + this.initDefaultCamera(canvasWidth, canvasHeight, renderer.clipSpaceNearZ); this.initRenderer(renderer, true); } @@ -251,9 +256,14 @@ export class Canvas extends EventTarget implements ICanvas { }; } - private initDefaultCamera(width: number, height: number) { + private initDefaultCamera( + width: number, + height: number, + clipSpaceNearZ: ClipSpaceNearZ, + ) { // set a default ortho camera const camera = new runtime.CameraContribution(); + camera.clipSpaceNearZ = clipSpaceNearZ; camera .setType(CameraType.EXPLORING, CameraTrackingMode.DEFAULT) diff --git a/packages/g-lite/src/camera/Camera.ts b/packages/g-lite/src/camera/Camera.ts index 7f9799eae..b0955eda2 100644 --- a/packages/g-lite/src/camera/Camera.ts +++ b/packages/g-lite/src/camera/Camera.ts @@ -3,7 +3,7 @@ import type { vec2 } from 'gl-matrix'; import { mat3, mat4, quat, vec3, vec4 } from 'gl-matrix'; import type { Canvas } from '../Canvas'; import { Frustum } from '../shapes'; -import type { TypeEasingFunction } from '../types'; +import { ClipSpaceNearZ, TypeEasingFunction } from '../types'; import { ERROR_MSG_METHOD_NOT_IMPLEMENTED } from '../utils/error'; import { createVec3, @@ -37,47 +37,50 @@ const MIN_DISTANCE = 0.0002; export class Camera implements ICamera { canvas: Canvas; + /** + * Clip space near Z, default to range `[-1, 1]` + */ + clipSpaceNearZ = ClipSpaceNearZ.NEGATIVE_ONE; + eventEmitter = new EventEmitter(); /** - * 相机矩阵 + * Matrix of camera */ protected matrix = mat4.create(); /** - * u 轴 + * u axis +X is right * @see http://learnwebgl.brown37.net/07_cameras/camera_introduction.html#a-camera-definition */ protected right = vec3.fromValues(1, 0, 0); /** - * v 轴 +Y is down + * v axis +Y is up */ protected up = vec3.fromValues(0, 1, 0); /** - * n 轴 +Z is inside + * n axis +Z is inside */ protected forward = vec3.fromValues(0, 0, 1); /** - * 相机位置 + * Position of camera. */ protected position = vec3.fromValues(0, 0, 1); /** - * 视点位置 + * Position of focal point. */ protected focalPoint = vec3.fromValues(0, 0, 0); /** - * 视点到相机位置的向量 - * focalPoint - position + * vector from focalPoint to position */ protected distanceVector = vec3.fromValues(0, 0, -1); /** - * 相机位置到视点距离 * length(focalPoint - position) */ protected distance = 1; @@ -490,6 +493,7 @@ export class Camera implements ICamera { top - height, near, this.far, + this.clipSpaceNearZ === ClipSpaceNearZ.ZERO, ); // flipY since the origin of OpenGL/WebGL is bottom-left compared with top-left in Canvas2D mat4.scale( @@ -542,7 +546,11 @@ export class Camera implements ICamera { bottom = top - scaleH * this.view.height; } - mat4.ortho(this.projectionMatrix, left, right, bottom, top, near, far); + if (this.clipSpaceNearZ === ClipSpaceNearZ.NEGATIVE_ONE) { + mat4.ortho(this.projectionMatrix, left, right, bottom, top, near, far); + } else { + mat4.orthoZO(this.projectionMatrix, left, right, bottom, top, near, far); + } // flipY since the origin of OpenGL/WebGL is bottom-left compared with top-left in Canvas2D mat4.scale( diff --git a/packages/g-lite/src/plugins/EventPlugin.ts b/packages/g-lite/src/plugins/EventPlugin.ts index 3ae830171..3163eb24d 100644 --- a/packages/g-lite/src/plugins/EventPlugin.ts +++ b/packages/g-lite/src/plugins/EventPlugin.ts @@ -29,14 +29,17 @@ export class EventPlugin implements RenderingPlugin { const canvas = this.context.renderingContext.root.ownerDocument.defaultView; - this.context.eventService.setPickHandler((position: EventPosition) => { - const { picked } = this.context.renderingService.hooks.pickSync.call({ - position, - picked: [], - topmost: true, // we only concern the topmost element - }); - return picked[0] || null; - }); + this.context.eventService.setPickHandler( + async (position: EventPosition) => { + const { picked } = + await this.context.renderingService.hooks.pick.promise({ + position, + picked: [], + topmost: true, // we only concern the topmost element + }); + return picked[0] || null; + }, + ); renderingService.hooks.pointerWheel.tap( EventPlugin.tag, diff --git a/packages/g-lite/src/services/EventService.ts b/packages/g-lite/src/services/EventService.ts index ba4e141d0..ca665410d 100644 --- a/packages/g-lite/src/services/EventService.ts +++ b/packages/g-lite/src/services/EventService.ts @@ -18,7 +18,7 @@ import { Point } from '../shapes'; import type { Cursor, EventPosition } from '../types'; import { isElement } from '../utils/dom'; -type Picker = (position: EventPosition) => IEventTarget | null; +type Picker = (position: EventPosition) => Promise; type TrackingData = { pressTargetsByButton: Record; clicksByButton: Record< @@ -180,12 +180,8 @@ export class EventService { } } - onPointerDown = (from: FederatedPointerEvent) => { - // if (!(from instanceof FederatedPointerEvent)) { - // return; - // } - - const e = this.createPointerEvent(from); + onPointerDown = async (from: FederatedPointerEvent) => { + const e = await this.createPointerEvent(from); this.dispatchEvent(e, 'pointerdown'); @@ -203,13 +199,9 @@ export class EventService { this.freeEvent(e); }; - onPointerUp = (from: FederatedPointerEvent) => { - // if (!(from instanceof FederatedPointerEvent)) { - // return; - // } - + onPointerUp = async (from: FederatedPointerEvent) => { const now = performance.now(); - const e = this.createPointerEvent( + const e = await this.createPointerEvent( from, undefined, undefined, @@ -315,12 +307,8 @@ export class EventService { this.freeEvent(e); }; - onPointerMove = (from: FederatedPointerEvent) => { - // if (!(from instanceof FederatedPointerEvent)) { - // return; - // } - - const e = this.createPointerEvent( + onPointerMove = async (from: FederatedPointerEvent) => { + const e = await this.createPointerEvent( from, undefined, undefined, @@ -337,7 +325,7 @@ export class EventService { if (trackingData.overTargets && outTarget !== e.target) { // pointerout always occurs on the overTarget when the pointer hovers over another element. const outType = from.type === 'mousemove' ? 'mouseout' : 'pointerout'; - const outEvent = this.createPointerEvent( + const outEvent = await this.createPointerEvent( from, outType, outTarget || undefined, @@ -349,7 +337,7 @@ export class EventService { // If the pointer exits overTarget and its descendants, then a pointerleave event is also fired. This event // is dispatched to all ancestors that no longer capture the pointer. if (!e.composedPath().includes(outTarget!)) { - const leaveEvent = this.createPointerEvent( + const leaveEvent = await this.createPointerEvent( from, 'pointerleave', outTarget || undefined, @@ -451,11 +439,7 @@ export class EventService { this.freeEvent(e); }; - onPointerOut = (from: FederatedPointerEvent) => { - // if (!(from instanceof FederatedPointerEvent)) { - // return; - // } - + onPointerOut = async (from: FederatedPointerEvent) => { const trackingData = this.trackingData(from.pointerId); if (trackingData.overTargets) { @@ -464,7 +448,7 @@ export class EventService { const outTarget = this.findMountedTarget(trackingData.overTargets); // pointerout first - const outEvent = this.createPointerEvent( + const outEvent = await this.createPointerEvent( from, 'pointerout', outTarget || undefined, @@ -475,7 +459,7 @@ export class EventService { // pointerleave(s) are also dispatched b/c the pointer must've left rootTarget and its descendants to // get an upstream pointerout event (upstream events do not know rootTarget has descendants). - const leaveEvent = this.createPointerEvent( + const leaveEvent = await this.createPointerEvent( from, 'pointerleave', outTarget || undefined, @@ -509,13 +493,9 @@ export class EventService { this.cursor = null; }; - onPointerOver = (from: FederatedPointerEvent) => { - // if (!(from instanceof FederatedPointerEvent)) { - // return; - // } - + onPointerOver = async (from: FederatedPointerEvent) => { const trackingData = this.trackingData(from.pointerId); - const e = this.createPointerEvent(from); + const e = await this.createPointerEvent(from); const isMouse = e.pointerType === 'mouse' || e.pointerType === 'pen'; @@ -553,16 +533,12 @@ export class EventService { this.freeEvent(enterEvent); }; - onPointerUpOutside = (from: FederatedPointerEvent) => { - // if (!(from instanceof FederatedPointerEvent)) { - // return; - // } - + onPointerUpOutside = async (from: FederatedPointerEvent) => { const trackingData = this.trackingData(from.pointerId); const pressTarget = this.findMountedTarget( trackingData.pressTargetsByButton[from.button], ); - const e = this.createPointerEvent(from); + const e = await this.createPointerEvent(from); if (pressTarget) { let currentTarget: IEventTarget | null = pressTarget; @@ -592,27 +568,27 @@ export class EventService { this.freeEvent(e); }; - onWheel = (from: FederatedWheelEvent) => { + onWheel = async (from: FederatedWheelEvent) => { // if (!(from instanceof FederatedWheelEvent)) { // return; // } - const wheelEvent = this.createWheelEvent(from); + const wheelEvent = await this.createWheelEvent(from); this.dispatchEvent(wheelEvent); this.freeEvent(wheelEvent); }; - onClick = (from: FederatedPointerEvent) => { + onClick = async (from: FederatedPointerEvent) => { if (this.context.config.useNativeClickEvent) { - const e = this.createPointerEvent(from); + const e = await this.createPointerEvent(from); this.dispatchEvent(e); this.freeEvent(e); } }; - onPointerCancel = (from: FederatedPointerEvent) => { - const e = this.createPointerEvent( + onPointerCancel = async (from: FederatedPointerEvent) => { + const e = await this.createPointerEvent( from, undefined, undefined, @@ -707,7 +683,7 @@ export class EventService { return propagationPath; } - hitTest(position: EventPosition): IEventTarget | null { + async hitTest(position: EventPosition): Promise { const { viewportX, viewportY } = position; const { width, height } = this.context.config; // outside canvas @@ -721,7 +697,7 @@ export class EventService { } return ( - this.pickHandler(position) || + (await this.pickHandler(position)) || this.rootTarget || // return Document null ); @@ -772,9 +748,9 @@ export class EventService { return null; } - private pickTarget( + private async pickTarget( event: FederatedPointerEvent | FederatedWheelEvent, - ): INode { + ): Promise { return this.hitTest({ clientX: event.clientX, clientY: event.clientY, @@ -782,15 +758,15 @@ export class EventService { viewportY: event.viewportY, x: event.canvasX, y: event.canvasY, - }) as INode; + }) as Promise; } - private createPointerEvent( + private async createPointerEvent( from: FederatedPointerEvent, type?: string, target?: IEventTarget, fallbackTarget?: IEventTarget, - ): FederatedPointerEvent { + ): Promise { const event = this.allocateEvent(FederatedPointerEvent); this.copyPointerData(from, event); @@ -804,7 +780,8 @@ export class EventService { event.target = target ?? (existedHTML || - (this.isNativeEventFromCanvas(event) && this.pickTarget(event)) || + (this.isNativeEventFromCanvas(event) && + (await this.pickTarget(event))) || fallbackTarget); if (typeof type === 'string') { @@ -814,7 +791,9 @@ export class EventService { return event; } - private createWheelEvent(from: FederatedWheelEvent): FederatedWheelEvent { + private async createWheelEvent( + from: FederatedWheelEvent, + ): Promise { const event = this.allocateEvent(FederatedWheelEvent); this.copyWheelData(from, event); @@ -826,7 +805,7 @@ export class EventService { const existedHTML = this.getExistedHTML(event); event.target = existedHTML || - (this.isNativeEventFromCanvas(event) && this.pickTarget(event)); + (this.isNativeEventFromCanvas(event) && (await this.pickTarget(event))); return event; } diff --git a/packages/g-lite/src/types.ts b/packages/g-lite/src/types.ts index 0558e77e1..e543390ce 100644 --- a/packages/g-lite/src/types.ts +++ b/packages/g-lite/src/types.ts @@ -331,6 +331,11 @@ export type Cursor = | 'zoom-in' | 'zoom-out'; +export enum ClipSpaceNearZ { + ZERO, + NEGATIVE_ONE, +} + export interface RendererConfig { /** * enable dirty check for displayobject diff --git a/packages/g-lite/src/utils/math.ts b/packages/g-lite/src/utils/math.ts index 9ba806a1e..28c5c1cec 100644 --- a/packages/g-lite/src/utils/math.ts +++ b/packages/g-lite/src/utils/math.ts @@ -222,14 +222,24 @@ export function makePerspective( bottom: number, near: number, far: number, + zero = false, ) { const x = (2 * near) / (right - left); const y = (2 * near) / (top - bottom); const a = (right + left) / (right - left); const b = (top + bottom) / (top - bottom); - const c = -(far + near) / (far - near); - const d = (-2 * far * near) / (far - near); + + let c: number; + let d: number; + + if (zero) { + c = -far / (far - near); + d = (-far * near) / (far - near); + } else { + c = -(far + near) / (far - near); + d = (-2 * far * near) / (far - near); + } out[0] = x; out[1] = 0; diff --git a/packages/g-plugin-box2d/src/Box2DPlugin.ts b/packages/g-plugin-box2d/src/Box2DPlugin.ts index 098e7b2f6..4023501d8 100644 --- a/packages/g-plugin-box2d/src/Box2DPlugin.ts +++ b/packages/g-plugin-box2d/src/Box2DPlugin.ts @@ -399,34 +399,39 @@ export class Box2DPlugin implements RenderingPlugin { } private async loadBox2D(): Promise { - const hasSIMD = WebAssembly.validate( - new Uint8Array([ - 0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 123, 3, 2, 1, 0, 10, 10, - 1, 8, 0, 65, 0, 253, 15, 253, 98, 11, - ]), - ); - const moduleName = hasSIMD ? './Box2D.simd' : './Box2D'; - - // awaiting gives us a better stack trace (at the cost of an extra microtask) - const modulePromise = await new Promise((resolve, reject) => { - const tag = document.createElement('script'); - tag.onload = () => { - resolve(window.Box2D); - return false; - }; - tag.onerror = () => { - reject( - new Error( - `Failed to load Box2D. Check your browser console for network errors.`, - ), - ); - return false; - }; - tag.src = `${BOX2D_UMD_DIR}/${moduleName}.js`; - document.getElementsByTagName('head')[0].appendChild(tag); - }); - - const Box2DFactory = await modulePromise; - return await Box2DFactory(); + if (window.Box2D) { + // @ts-ignore + return await (window.Box2D()); + } else { + const hasSIMD = WebAssembly.validate( + new Uint8Array([ + 0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 123, 3, 2, 1, 0, 10, + 10, 1, 8, 0, 65, 0, 253, 15, 253, 98, 11, + ]), + ); + const moduleName = hasSIMD ? './Box2D.simd' : './Box2D'; + + // awaiting gives us a better stack trace (at the cost of an extra microtask) + const modulePromise = await new Promise((resolve, reject) => { + const tag = document.createElement('script'); + tag.onload = () => { + resolve(window.Box2D); + return false; + }; + tag.onerror = () => { + reject( + new Error( + `Failed to load Box2D. Check your browser console for network errors.`, + ), + ); + return false; + }; + tag.src = `${BOX2D_UMD_DIR}/${moduleName}.js`; + document.getElementsByTagName('head')[0].appendChild(tag); + }); + + const Box2DFactory = await modulePromise; + return await Box2DFactory(); + } } } diff --git a/packages/g-plugin-device-renderer/src/PickingPlugin.ts b/packages/g-plugin-device-renderer/src/PickingPlugin.ts index 6ed25ddaa..d1339de3d 100644 --- a/packages/g-plugin-device-renderer/src/PickingPlugin.ts +++ b/packages/g-plugin-device-renderer/src/PickingPlugin.ts @@ -83,18 +83,20 @@ export class PickingPlugin implements RenderingPlugin { */ renderingService.hooks.pickSync.tap( PickingPlugin.tag, - (result: PickingResult) => this.pick(result), + (result: PickingResult) => { + throw new Error('Sync version is not implemented.'); + }, ); renderingService.hooks.pick.tapPromise( PickingPlugin.tag, - async (result: PickingResult) => { + (result: PickingResult) => { return this.pick(result); }, ); } - private pick(result: PickingResult) { + private async pick(result: PickingResult) { const { topmost, position } = result; // use viewportX/Y @@ -119,7 +121,7 @@ export class PickingPlugin implements RenderingPlugin { // implements multi-layer picking // @see https://github.com/antvis/g/issues/948 - const pickedDisplayObjects = this.pickByRectangleInDepth( + const pickedDisplayObjects = await this.pickByRectangleInDepth( new Rectangle( clamp(Math.round(xInDevicePixel), 0, width - 1), clamp(Math.round(yInDevicePixel), 0, height - 1), @@ -133,16 +135,16 @@ export class PickingPlugin implements RenderingPlugin { return result; } - private pickByRectangleInDepth( + private async pickByRectangleInDepth( rect: Rectangle, depth = MAX_PICKING_DEPTH, - ): DisplayObject[] { + ): Promise { let picked = null; let counter = 1; const targets = []; do { - picked = this.pickByRectangle(rect, picked); + picked = await this.pickByRectangle(rect, picked); if (picked) { counter++; @@ -169,10 +171,10 @@ export class PickingPlugin implements RenderingPlugin { /** * return displayobjects in target rectangle */ - private pickByRectangle( + private async pickByRectangle( rect: Rectangle, picked: DisplayObject, - ): DisplayObject | null { + ): Promise { const device = this.renderGraphPlugin.getDevice(); const renderLists = this.renderGraphPlugin.getRenderLists(); @@ -213,161 +215,168 @@ export class PickingPlugin implements RenderingPlugin { // account for current view offset const currentView = { ...camera.getView() }; - // prevent unused RTs like main color being destroyed - this.renderHelper.renderGraph.renderTargetDeadPool.forEach((rt) => { - rt.age = -1; - }); + return new Promise((resolve) => { + // prevent unused RTs like main color being destroyed + this.renderHelper.renderGraph.renderTargetDeadPool.forEach((rt) => { + rt.age = -1; + }); - // picking pass - let target: DisplayObject; - builder.pushPass((pass) => { - pass.setDebugName('Picking Pass'); - pass.attachRenderTargetID(RGAttachmentSlot.Color0, pickingColorTargetID); - pass.attachRenderTargetID( - RGAttachmentSlot.DepthStencil, - mainDepthTargetID, - ); - pass.exec((passRenderer) => { - renderLists.picking.drawOnPassRenderer( - renderInstManager.renderCache, - passRenderer, + // picking pass + builder.pushPass((pass) => { + pass.setDebugName('Picking Pass'); + pass.attachRenderTargetID( + RGAttachmentSlot.Color0, + pickingColorTargetID, ); - }); - pass.post((scope) => { - const texture = scope.getRenderTargetTexture(RGAttachmentSlot.Color0); - - const readback = device.createReadback(); - - // restore previous view - if (currentView && currentView.enabled) { - camera.setViewOffset( - currentView.fullWidth, - currentView.fullHeight, - currentView.offsetX, - currentView.offsetY, - currentView.width, - currentView.height, + pass.attachRenderTargetID( + RGAttachmentSlot.DepthStencil, + mainDepthTargetID, + ); + pass.exec((passRenderer) => { + renderLists.picking.drawOnPassRenderer( + renderInstManager.renderCache, + passRenderer, ); - } else { - camera.clearViewOffset(); - } - - camera.setEnableUpdate(true); - - const pickedColors = readback.readTexture( - texture, - 0, - 0, - width, - height, - new Uint8Array(width * height * 4), - ) as Uint8Array; - - let pickedFeatureIdx = -1; - - if ( - pickedColors && - (pickedColors[0] !== 0 || - pickedColors[1] !== 0 || - pickedColors[2] !== 0) - ) { - pickedFeatureIdx = - this.pickingIdGenerator.decodePickingColor(pickedColors); - } - - if (pickedFeatureIdx > -1) { - const pickedDisplayObject = - this.pickingIdGenerator.getById(pickedFeatureIdx); - - if ( - pickedDisplayObject && - pickedDisplayObject.isVisible() && - pickedDisplayObject.isInteractive() - ) { - target = pickedDisplayObject; + }); + pass.post((scope) => { + const texture = scope.getRenderTargetTexture(RGAttachmentSlot.Color0); + + const readback = device.createReadback(); + + // restore previous view + if (currentView && currentView.enabled) { + camera.setViewOffset( + currentView.fullWidth, + currentView.fullHeight, + currentView.offsetX, + currentView.offsetY, + currentView.width, + currentView.height, + ); + } else { + camera.clearViewOffset(); } - } - readback.destroy(); + + camera.setEnableUpdate(true); + + readback + .readTexture( + texture, + 0, + 0, + width, + height, + new Uint8Array(width * height * 4), + ) + .then((pickedColors: Uint8Array) => { + let target: DisplayObject; + let pickedFeatureIdx = -1; + + if ( + pickedColors && + (pickedColors[0] !== 0 || + pickedColors[1] !== 0 || + pickedColors[2] !== 0) + ) { + pickedFeatureIdx = + this.pickingIdGenerator.decodePickingColor(pickedColors); + } + + if (pickedFeatureIdx > -1) { + const pickedDisplayObject = + this.pickingIdGenerator.getById(pickedFeatureIdx); + + if ( + pickedDisplayObject && + pickedDisplayObject.isVisible() && + pickedDisplayObject.isInteractive() + ) { + target = pickedDisplayObject; + } + } + readback.destroy(); + + resolve(target); + }); + }); }); - }); - // Push our outer template, which contains the dynamic UBO bindings... - const template = this.renderHelper.pushTemplateRenderInst(); - // SceneParams: binding = 0, ObjectParams: binding = 1 - template.setBindingLayouts([{ numUniformBuffers: 2, numSamplers: 0 }]); - template.setMegaStateFlags( - setAttachmentStateSimple( + // Push our outer template, which contains the dynamic UBO bindings... + const template = this.renderHelper.pushTemplateRenderInst(); + // SceneParams: binding = 0, ObjectParams: binding = 1 + template.setBindingLayouts([{ numUniformBuffers: 2, numSamplers: 0 }]); + template.setMegaStateFlags( + setAttachmentStateSimple( + { + depthWrite: true, + }, + { + rgbBlendMode: BlendMode.Add, + rgbBlendSrcFactor: BlendFactor.One, + rgbBlendDstFactor: BlendFactor.Zero, + alphaBlendMode: BlendMode.Add, + alphaBlendSrcFactor: BlendFactor.One, + alphaBlendDstFactor: BlendFactor.Zero, + }, + ), + ); + + // Update Scene Params + const { width: canvasWidth, height: canvasHeight } = this.context.config; + const dpr = this.context.contextService.getDPR(); + + camera.setEnableUpdate(false); + camera.setViewOffset( + canvasWidth * dpr, + canvasHeight * dpr, + x, + y, + width, + height, + ); + + template.setUniforms(SceneUniformBufferIndex, [ { - depthWrite: true, + name: SceneUniform.PROJECTION_MATRIX, + value: camera.getPerspective(), }, { - rgbBlendMode: BlendMode.Add, - rgbBlendSrcFactor: BlendFactor.One, - rgbBlendDstFactor: BlendFactor.Zero, - alphaBlendMode: BlendMode.Add, - alphaBlendSrcFactor: BlendFactor.One, - alphaBlendDstFactor: BlendFactor.Zero, + name: SceneUniform.VIEW_MATRIX, + value: camera.getViewTransform(), }, - ), - ); - - // Update Scene Params - const { width: canvasWidth, height: canvasHeight } = this.context.config; - const dpr = this.context.contextService.getDPR(); - - camera.setEnableUpdate(false); - camera.setViewOffset( - canvasWidth * dpr, - canvasHeight * dpr, - x, - y, - width, - height, - ); - - 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: [canvasWidth, canvasHeight], - }, - { - name: SceneUniform.IS_ORTHO, - value: camera.isOrtho() ? 1 : 0, - }, - { - name: SceneUniform.IS_PICKING, - value: 1, - }, - ]); - - if (picked) { - this.batchManager.updateAttribute(picked, 'pointerEvents', false, true); - } - this.batchManager.render(renderLists.picking, true); + { + name: SceneUniform.CAMERA_POSITION, + value: camera.getPosition(), + }, + { + name: SceneUniform.DEVICE_PIXEL_RATIO, + value: this.context.contextService.getDPR(), + }, + { + name: SceneUniform.VIEWPORT, + value: [canvasWidth, canvasHeight], + }, + { + name: SceneUniform.IS_ORTHO, + value: camera.isOrtho() ? 1 : 0, + }, + { + name: SceneUniform.IS_PICKING, + value: 1, + }, + ]); - renderInstManager.popTemplateRenderInst(); + if (picked) { + this.batchManager.updateAttribute(picked, 'pointerEvents', false, true); + } + this.batchManager.render(renderLists.picking, true); - this.renderHelper.prepareToRender(); - this.renderHelper.renderGraph.execute(); + renderInstManager.popTemplateRenderInst(); - renderInstManager.resetRenderInsts(); + this.renderHelper.prepareToRender(); + this.renderHelper.renderGraph.execute(); - return target; + renderInstManager.resetRenderInsts(); + }); } } diff --git a/packages/g-plugin-device-renderer/src/RenderGraphPlugin.ts b/packages/g-plugin-device-renderer/src/RenderGraphPlugin.ts index 0de67c12d..7c41ad3e5 100644 --- a/packages/g-plugin-device-renderer/src/RenderGraphPlugin.ts +++ b/packages/g-plugin-device-renderer/src/RenderGraphPlugin.ts @@ -17,6 +17,7 @@ import { SwapChain, Texture, TextureDescriptor, + TransparentBlack, TransparentWhite, } from './platform'; import { @@ -240,20 +241,26 @@ export class RenderGraphPlugin implements RenderingPlugin { const renderInstManager = this.renderHelper.renderInstManager; this.builder = this.renderHelper.renderGraph.newGraphBuilder(); - // use canvas.background - const backgroundColor = parseColor( - this.context.config.background, - ) as CSSRGB; - const clearColor = this.context.config.background - ? // use premultipliedAlpha - // @see https://canvatechblog.com/alpha-blending-and-webgl-99feb392779e - colorNewFromRGBA( - (Number(backgroundColor.r) / 255) * Number(backgroundColor.alpha), - (Number(backgroundColor.g) / 255) * Number(backgroundColor.alpha), - (Number(backgroundColor.b) / 255) * Number(backgroundColor.alpha), - Number(backgroundColor.alpha), - ) - : TransparentWhite; + let clearColor; + if (this.context.config.background === 'transparent') { + clearColor = TransparentBlack; + } else { + // use canvas.background + const backgroundColor = parseColor( + this.context.config.background, + ) as CSSRGB; + + clearColor = this.context.config.background + ? // use premultipliedAlpha + // @see https://canvatechblog.com/alpha-blending-and-webgl-99feb392779e + colorNewFromRGBA( + (Number(backgroundColor.r) / 255) * Number(backgroundColor.alpha), + (Number(backgroundColor.g) / 255) * Number(backgroundColor.alpha), + (Number(backgroundColor.b) / 255) * Number(backgroundColor.alpha), + Number(backgroundColor.alpha), + ) + : TransparentWhite; + } // retrieve at each frame since canvas may resize const renderInput = { @@ -328,7 +335,7 @@ export class RenderGraphPlugin implements RenderingPlugin { setAttachmentStateSimple( { depthWrite: true, - blendConstant: TransparentWhite, + blendConstant: TransparentBlack, }, { rgbBlendMode: BlendMode.Add, diff --git a/packages/g-plugin-device-renderer/src/TexturePool.ts b/packages/g-plugin-device-renderer/src/TexturePool.ts index 37c683a1e..7095a00b2 100644 --- a/packages/g-plugin-device-renderer/src/TexturePool.ts +++ b/packages/g-plugin-device-renderer/src/TexturePool.ts @@ -80,11 +80,21 @@ export class TexturePool { if (image) { image.onload = () => { - this.textureCache[id].setImageData(image); - this.textureCache[id].emit(TextureEvent.LOADED); - this.context.renderingService.dirtify(); - if (successCallback) { - successCallback(this.textureCache[id]); + const onSuccess = (bitmap: ImageBitmap | HTMLImageElement) => { + this.textureCache[id].setImageData(bitmap); + this.textureCache[id].emit(TextureEvent.LOADED); + this.context.renderingService.dirtify(); + if (successCallback) { + successCallback(this.textureCache[id]); + } + }; + + if (runtime.globalThis.createImageBitmap) { + runtime.globalThis + .createImageBitmap(image) + .then((bitmap: ImageBitmap) => onSuccess(bitmap)); + } else { + onSuccess(image); } }; image.onerror = () => {}; diff --git a/packages/g-plugin-device-renderer/src/geometries/BufferGeometry.ts b/packages/g-plugin-device-renderer/src/geometries/BufferGeometry.ts index 19df8a414..21bf3696f 100644 --- a/packages/g-plugin-device-renderer/src/geometries/BufferGeometry.ts +++ b/packages/g-plugin-device-renderer/src/geometries/BufferGeometry.ts @@ -13,7 +13,6 @@ import { Format, PrimitiveTopology, } from '../platform'; -import { align } from '../platform/utils'; export function makeStaticDataBuffer( device: Device, @@ -21,7 +20,7 @@ export function makeStaticDataBuffer( data: ArrayBufferLike, ): Buffer { const buffer = device.createBuffer({ - viewOrSize: align(data.byteLength, 4) / 4, + viewOrSize: data.byteLength, usage, hint: BufferFrequencyHint.Static, }); diff --git a/packages/g-plugin-device-renderer/src/meshes/Instanced.ts b/packages/g-plugin-device-renderer/src/meshes/Instanced.ts index 498d34cf3..a355c64cd 100644 --- a/packages/g-plugin-device-renderer/src/meshes/Instanced.ts +++ b/packages/g-plugin-device-renderer/src/meshes/Instanced.ts @@ -140,6 +140,11 @@ export abstract class Instanced { */ protected lightReceived = false; + /** + * + */ + protected divisor = 1; + protected abstract createMaterial(objects: DisplayObject[]): void; get instance() { @@ -263,6 +268,7 @@ export abstract class Instanced { const packedFillStroke: number[] = []; const packedStyle: number[] = []; const packedPicking: number[] = []; + const divisor = this.divisor; // const useNormal = this.material.defines.NORMAL; @@ -358,19 +364,19 @@ export abstract class Instanced { // format: Format.F32_RGB, // bufferByteOffset: 4 * 0, // location: Number(NORMAL_MATRIX0), - // divisor: 1, + // divisor // }, // { // format: Format.F32_RGB, // bufferByteOffset: 4 * 3, // location: Number(NORMAL_MATRIX1), - // divisor: 1, + // divisor // }, // { // format: Format.F32_RGB, // bufferByteOffset: 4 * 6, // location: Number(NORMAL_MATRIX2), - // divisor: 1, + // divisor // }, // ], // data: new Float32Array(normalMatrix), @@ -389,25 +395,25 @@ export abstract class Instanced { format: Format.F32_RGBA, bufferByteOffset: 4 * 0, location: VertexAttributeLocation.MODEL_MATRIX0, - divisor: 1, + divisor, }, { format: Format.F32_RGBA, bufferByteOffset: 4 * 4, location: VertexAttributeLocation.MODEL_MATRIX1, - divisor: 1, + divisor, }, { format: Format.F32_RGBA, bufferByteOffset: 4 * 8, location: VertexAttributeLocation.MODEL_MATRIX2, - divisor: 1, + divisor, }, { format: Format.F32_RGBA, bufferByteOffset: 4 * 12, location: VertexAttributeLocation.MODEL_MATRIX3, - divisor: 1, + divisor, }, ], data: new Float32Array(packedModelMatrix), @@ -422,7 +428,7 @@ export abstract class Instanced { format: Format.F32_RGBA, bufferByteOffset: 4 * 0, location: VertexAttributeLocation.PACKED_COLOR, - divisor: 1, + divisor, }, ], data: new Float32Array(packedFillStroke), @@ -437,13 +443,13 @@ export abstract class Instanced { format: Format.F32_RGBA, bufferByteOffset: 4 * 0, location: VertexAttributeLocation.PACKED_STYLE1, - divisor: 1, + divisor, }, { format: Format.F32_RGBA, bufferByteOffset: 4 * 4, location: VertexAttributeLocation.PACKED_STYLE2, - divisor: 1, + divisor, }, ], data: new Float32Array(packedStyle), @@ -458,7 +464,7 @@ export abstract class Instanced { format: Format.F32_RGBA, bufferByteOffset: 4 * 0, location: VertexAttributeLocation.PICKING_COLOR, - divisor: 1, + divisor, }, ], data: new Float32Array(packedPicking), diff --git a/packages/g-plugin-device-renderer/src/meshes/InstancedPath.ts b/packages/g-plugin-device-renderer/src/meshes/InstancedPath.ts new file mode 100644 index 000000000..960b0a1b2 --- /dev/null +++ b/packages/g-plugin-device-renderer/src/meshes/InstancedPath.ts @@ -0,0 +1,188 @@ +/** + * Instanced line which has a better performance. + * @see https://www.yuque.com/antv/ou292n/gg1gh5 + */ +import { DisplayObject } from '@antv/g-lite'; +import { Format, VertexBufferFrequency } from '../platform'; +import frag from '../shader/line.frag'; +import vert from '../shader/line.vert'; +import { enumToObject } from '../utils/enum'; +import { + Instanced, + VertexAttributeBufferIndex, + VertexAttributeLocation, +} from './Instanced'; +import { updateBuffer } from './Line'; + +enum LineVertexAttributeBufferIndex { + PACKED = VertexAttributeBufferIndex.POSITION + 1, + VERTEX_NUM, + TRAVEL, +} + +enum LineVertexAttributeLocation { + PREV = VertexAttributeLocation.POSITION, + POINT1, + POINT2, + NEXT, + VERTEX_JOINT, + VERTEX_NUM, + TRAVEL, +} + +/** + * Used for Path only contains 2 commands, e.g. [[M], [C]] + */ +export class InstancedPathMesh extends Instanced { + shouldMerge(object: DisplayObject, index: number) { + const shouldMerge = super.shouldMerge(object, index); + if (!shouldMerge) { + return false; + } + + return true; + } + + createMaterial(objects: DisplayObject[]): void { + this.material.vertexShader = vert; + this.material.fragmentShader = frag; + this.material.defines = { + ...this.material.defines, + ...enumToObject(LineVertexAttributeLocation), + INSTANCED: true, + }; + } + + createGeometry(objects: DisplayObject[]): void { + const indices: number[] = []; + const pointsBuffer: number[] = []; + const travelBuffer: number[] = []; + let instancedCount = 0; + let offset = 0; + objects.forEach((object) => { + const { + pointsBuffer: pBuffer, + travelBuffer: tBuffer, + instancedCount: count, + } = updateBuffer(object); + + instancedCount += count; + + pointsBuffer.push(...pBuffer); + travelBuffer.push(...tBuffer); + + indices.push( + 0 + offset, + 2 + offset, + 1 + offset, + 0 + offset, + 3 + offset, + 2 + offset, + 4 + offset, + 6 + offset, + 5 + offset, + 4 + offset, + 7 + offset, + 6 + offset, + 4 + offset, + 7 + offset, + 8 + offset, + ); + offset += 9; + }); + + this.geometry.setVertexBuffer({ + bufferIndex: LineVertexAttributeBufferIndex.PACKED, + byteStride: 4 * (3 + 3 + 3 + 3), + frequency: VertexBufferFrequency.PerInstance, + attributes: [ + { + format: Format.F32_RG, + bufferByteOffset: 4 * 0, + byteStride: 4 * 3, + location: LineVertexAttributeLocation.PREV, + divisor: 1, + }, + { + format: Format.F32_RG, + bufferByteOffset: 4 * 3, + byteStride: 4 * 3, + location: LineVertexAttributeLocation.POINT1, + divisor: 1, + }, + { + format: Format.F32_R, + bufferByteOffset: 4 * 5, + byteStride: 4 * 3, + location: LineVertexAttributeLocation.VERTEX_JOINT, + divisor: 1, + }, + { + format: Format.F32_RG, + bufferByteOffset: 4 * 6, + byteStride: 4 * 3, + location: LineVertexAttributeLocation.POINT2, + divisor: 1, + }, + { + format: Format.F32_RG, + bufferByteOffset: 4 * 9, + byteStride: 4 * 3, + location: LineVertexAttributeLocation.NEXT, + divisor: 1, + }, + ], + data: new Float32Array(pointsBuffer), + }); + this.geometry.setVertexBuffer({ + bufferIndex: LineVertexAttributeBufferIndex.VERTEX_NUM, + byteStride: 4 * 1, + frequency: VertexBufferFrequency.PerInstance, + attributes: [ + { + format: Format.F32_R, + bufferByteOffset: 4 * 0, + byteStride: 4 * 1, + location: LineVertexAttributeLocation.VERTEX_NUM, + divisor: 0, + }, + ], + data: new Float32Array([0, 1, 2, 3, 4, 5, 6, 7, 8]), + }); + this.geometry.setVertexBuffer({ + bufferIndex: LineVertexAttributeBufferIndex.TRAVEL, + byteStride: 4 * 1, + frequency: VertexBufferFrequency.PerInstance, + attributes: [ + { + format: Format.F32_R, + bufferByteOffset: 4 * 0, + byteStride: 4 * 1, + location: LineVertexAttributeLocation.TRAVEL, + divisor: 1, + }, + ], + data: new Float32Array(travelBuffer), + }); + + // this attribute only changes for each 9 instance + this.divisor = instancedCount / objects.length; + // use default common attributes + super.createGeometry(objects); + + this.geometry.vertexCount = 15; + this.geometry.instancedCount = instancedCount; + this.geometry.setIndexBuffer(new Uint32Array(indices)); + } + + updateAttribute( + objects: DisplayObject[], + startIndex: number, + name: string, + value: any, + ) { + super.updateAttribute(objects, startIndex, name, value); + + this.updateBatchedAttribute(objects, startIndex, name, value); + } +} diff --git a/packages/g-plugin-device-renderer/src/meshes/Line.ts b/packages/g-plugin-device-renderer/src/meshes/Line.ts index e5e51f6dd..4974cf0f0 100644 --- a/packages/g-plugin-device-renderer/src/meshes/Line.ts +++ b/packages/g-plugin-device-renderer/src/meshes/Line.ts @@ -700,8 +700,8 @@ export function updateBuffer(object: DisplayObject, needEarcut = false) { // const needDash = !isNil(lineDash); let dist = 0; - const pointsBuffer = []; - const travelBuffer = []; + const pointsBuffer: number[] = []; + const travelBuffer: number[] = []; for (let i = 0; i < points.length; i += stridePoints) { // calc travel // if (needDash) { diff --git a/packages/g-plugin-device-renderer/src/meshes/Text.ts b/packages/g-plugin-device-renderer/src/meshes/Text.ts index f84805cf5..8f54226b4 100644 --- a/packages/g-plugin-device-renderer/src/meshes/Text.ts +++ b/packages/g-plugin-device-renderer/src/meshes/Text.ts @@ -154,64 +154,47 @@ export class TextMesh extends Instanced { this.geometry.setVertexBuffer({ bufferIndex: TextVertexAttributeBufferIndex.INSTANCED, byteStride: 4 * (4 * 4 + 4 + 4 + 4 + 4), // 32 - // frequency: VertexBufferFrequency.PerInstance, frequency: VertexBufferFrequency.PerVertex, attributes: [ { format: Format.F32_RGBA, bufferByteOffset: 4 * 0, location: VertexAttributeLocation.MODEL_MATRIX0, - // byteStride: 4 * 4, - // divisor: 1, }, { format: Format.F32_RGBA, bufferByteOffset: 4 * 4, location: VertexAttributeLocation.MODEL_MATRIX1, - // byteStride: 4 * 4, - // divisor: 1, }, { format: Format.F32_RGBA, bufferByteOffset: 4 * 8, location: VertexAttributeLocation.MODEL_MATRIX2, - // byteStride: 4 * 4, - // divisor: 1, }, { format: Format.F32_RGBA, bufferByteOffset: 4 * 12, location: VertexAttributeLocation.MODEL_MATRIX3, - // byteStride: 4 * 4, - // divisor: 1, }, { format: Format.F32_RGBA, bufferByteOffset: 4 * 16, location: VertexAttributeLocation.PACKED_COLOR, - // byteStride: 4 * 4, - // divisor: 1, }, { format: Format.F32_RGBA, bufferByteOffset: 4 * 20, location: VertexAttributeLocation.PACKED_STYLE1, - // byteStride: 4 * 4, - // divisor: 1, }, { format: Format.F32_RGBA, bufferByteOffset: 4 * 24, location: VertexAttributeLocation.PACKED_STYLE2, - // byteStride: 4 * 4, - // divisor: 1, }, { format: Format.F32_RGBA, bufferByteOffset: 4 * 28, location: VertexAttributeLocation.PICKING_COLOR, - // byteStride: 4 * 4, - // divisor: 1, }, ], data: new Float32Array(packed), @@ -540,7 +523,7 @@ export class TextMesh extends Instanced { ...encodedPickingColor, object.sortable.renderOrder * RENDER_ORDER_SCALE, ]; - // FIXME: instanced + // Can't use instanced here since the total number of each Text can be different. charPackedBuffer.push(...packed, ...packed, ...packed, ...packed); // interleaved uv & offsets diff --git a/packages/g-plugin-device-renderer/src/meshes/index.ts b/packages/g-plugin-device-renderer/src/meshes/index.ts index 60b51eb20..701e9e8a7 100644 --- a/packages/g-plugin-device-renderer/src/meshes/index.ts +++ b/packages/g-plugin-device-renderer/src/meshes/index.ts @@ -1,6 +1,7 @@ export * from './Instanced'; export * from './SDF'; export * from './InstancedLine'; +export * from './InstancedPath'; export * from './Line'; export * from './Fill'; export * from './Image'; diff --git a/packages/g-plugin-device-renderer/src/platform/interfaces.ts b/packages/g-plugin-device-renderer/src/platform/interfaces.ts index 3ca52f1b4..bf9133fb4 100644 --- a/packages/g-plugin-device-renderer/src/platform/interfaces.ts +++ b/packages/g-plugin-device-renderer/src/platform/interfaces.ts @@ -79,7 +79,7 @@ export interface Readback extends ResourceBase { dst: ArrayBufferView, dstOffset?: number, length?: number, - ) => ArrayBufferView; + ) => Promise; readBuffer: ( b: Buffer, diff --git a/packages/g-plugin-device-renderer/src/platform/utils/states.ts b/packages/g-plugin-device-renderer/src/platform/utils/states.ts index 553a431b1..f89308138 100644 --- a/packages/g-plugin-device-renderer/src/platform/utils/states.ts +++ b/packages/g-plugin-device-renderer/src/platform/utils/states.ts @@ -15,7 +15,7 @@ import { StencilOp, TextureDimension, } from '../interfaces'; -import { colorCopy, colorNewCopy, TransparentWhite } from './color'; +import { colorCopy, colorNewCopy, TransparentBlack } from './color'; // import { reverseDepthForCompareMode } from './depth'; export function isPowerOfTwo(n: number): boolean { @@ -231,7 +231,7 @@ export const defaultMegaState: MegaStateDescriptor = { }, ], - blendConstant: colorNewCopy(TransparentWhite), + blendConstant: colorNewCopy(TransparentBlack), depthWrite: true, depthCompare: CompareMode.LessEqual, // depthCompare: reverseDepthForCompareMode(CompareMode.LessEqual), diff --git a/packages/g-plugin-device-renderer/src/render/DynamicUniformBuffer.ts b/packages/g-plugin-device-renderer/src/render/DynamicUniformBuffer.ts index b6738470c..5aa198230 100644 --- a/packages/g-plugin-device-renderer/src/render/DynamicUniformBuffer.ts +++ b/packages/g-plugin-device-renderer/src/render/DynamicUniformBuffer.ts @@ -8,6 +8,9 @@ export class DynamicUniformBuffer { private uniformBufferWordAlignment: number; private uniformBufferMaxPageWordSize: number; + /** + * Word count, 4 bytes per word + */ private currentBufferWordSize = -1; private currentWordOffset = 0; buffer: Buffer | null = null; @@ -108,7 +111,8 @@ export class DynamicUniformBuffer { } this.buffer = this.device.createBuffer({ - viewOrSize: this.currentBufferWordSize, + // in bytes length + viewOrSize: this.currentBufferWordSize * 4, usage: BufferUsage.UNIFORM, hint: BufferFrequencyHint.Dynamic, }); diff --git a/packages/g-plugin-device-renderer/src/renderer/Path.ts b/packages/g-plugin-device-renderer/src/renderer/Path.ts index c3edd4ace..1e63ba554 100644 --- a/packages/g-plugin-device-renderer/src/renderer/Path.ts +++ b/packages/g-plugin-device-renderer/src/renderer/Path.ts @@ -9,7 +9,12 @@ import type { ParsedPolylineStyleProps, } from '@antv/g-lite'; import { Shape } from '@antv/g-lite'; -import { FillMesh, InstancedLineMesh, LineMesh } from '../meshes'; +import { + FillMesh, + InstancedLineMesh, + InstancedPathMesh, + LineMesh, +} from '../meshes'; import { Batch } from './Batch'; /** @@ -17,26 +22,40 @@ import { Batch } from './Batch'; * @see https://github.com/antvis/G/issues/1113 */ export class PathRenderer extends Batch { - meshes = [FillMesh, LineMesh, InstancedLineMesh]; + meshes = [FillMesh, LineMesh, InstancedLineMesh, InstancedPathMesh]; shouldSubmitRenderInst(object: DisplayObject, index: number) { const { fill, stroke, opacity, strokeOpacity, lineDash, lineWidth } = object.parsedStyle as ParsedBaseStyleProps; const nodeName = object.nodeName; const hasStroke = stroke && !(stroke as CSSRGB).isNone; - const hasDash = lineDash && lineDash.length && lineDash.every((item) => item !== 0); + const hasDash = + lineDash && lineDash.length && lineDash.every((item) => item !== 0); const isLine = this.isLine(object); + const isOneCommandPath = this.isOneCommandPath(object); object.renderable.proxyNodeName = isLine ? Shape.LINE : null; // Polyline don't need fill - if (index === 0 && (object.nodeName === Shape.POLYLINE || (fill as CSSRGB).isNone)) { + if ( + index === 0 && + (isOneCommandPath || + object.nodeName === Shape.POLYLINE || + (fill as CSSRGB).isNone) + ) { return false; } // stroke mesh if (index === 1) { - if (isLine || strokeOpacity === 0 || opacity === 0 || lineWidth === 0 || !hasStroke) { + if ( + isLine || + isOneCommandPath || + strokeOpacity === 0 || + opacity === 0 || + lineWidth === 0 || + !hasStroke + ) { return false; } @@ -51,6 +70,10 @@ export class PathRenderer extends Batch { return isLine; } + if (index === 3) { + return isOneCommandPath; + } + return true; } @@ -61,16 +84,25 @@ export class PathRenderer extends Batch { } = object.parsedStyle as ParsedPathStyleProps; // only contains M & L commands - if (absolutePath.length === 2 && absolutePath[0][0] === 'M' && absolutePath[1][0] === 'L') { + if ( + absolutePath.length === 2 && + absolutePath[0][0] === 'M' && + absolutePath[1][0] === 'L' + ) { return true; } } else if (object.nodeName === Shape.POLYLINE) { const { points: { points }, } = object.parsedStyle as ParsedPolylineStyleProps; - const tangent = (points[1][0] - points[1][1]) / (points[0][0] - points[0][1]); + const tangent = + (points[1][0] - points[1][1]) / (points[0][0] - points[0][1]); for (let i = 1; i < points.length - 1; i++) { - if ((points[i + 1][0] - points[i + 1][1]) / (points[i][0] - points[i][1]) !== tangent) { + if ( + (points[i + 1][0] - points[i + 1][1]) / + (points[i][0] - points[i][1]) !== + tangent + ) { return false; } } @@ -80,4 +112,22 @@ export class PathRenderer extends Batch { return false; } + + private isOneCommandPath(object: DisplayObject) { + if (object.nodeName === Shape.PATH) { + const { + path: { absolutePath }, + } = object.parsedStyle as ParsedPathStyleProps; + + // only contains M & C commands + if ( + absolutePath.length === 2 && + absolutePath[0][0] === 'M' && + absolutePath[1][0] === 'C' + ) { + return true; + } + } + return false; + } } diff --git a/packages/g-plugin-device-renderer/src/shader/compiler.ts b/packages/g-plugin-device-renderer/src/shader/compiler.ts index 63e6aa6de..ecd1fcb49 100644 --- a/packages/g-plugin-device-renderer/src/shader/compiler.ts +++ b/packages/g-plugin-device-renderer/src/shader/compiler.ts @@ -201,7 +201,7 @@ layout(set = ${set}, binding = ${binding++}) uniform sampler S_${samplerName}; }); rest = rest.replace( - type === 'frag' ? /^\b(varying|in)\b/gm : /^\b(varying|out)\b/gm, + type === 'frag' ? /^\s*\b\s*(varying|in)\b/gm : /^\s*\b(varying|out)\b/gm, (substr, tok) => { return `layout(location = ${location++}) ${tok}`; }, diff --git a/packages/g-plugin-device-renderer/src/shader/line.frag b/packages/g-plugin-device-renderer/src/shader/line.frag index 70e2aa446..067617228 100644 --- a/packages/g-plugin-device-renderer/src/shader/line.frag +++ b/packages/g-plugin-device-renderer/src/shader/line.frag @@ -1,5 +1,10 @@ #pragma glslify: import('@antv/g-shader-components/scene.both.glsl') -#pragma glslify: import('@antv/g-shader-components/line.both.glsl') + +#ifdef INSTANCED + #pragma glslify: import('@antv/g-shader-components/batch.declaration.frag') +#else + #pragma glslify: import('@antv/g-shader-components/line.both.glsl') +#endif in vec4 v_Distance; in vec4 v_Arc; @@ -8,12 +13,14 @@ in float v_Travel; out vec4 outputColor; -#define COLOR_SCALE 1. / 255. - void main(){ - if (u_Visible < 0.5) { - discard; - } + #ifdef INSTANCED + #pragma glslify: import('@antv/g-shader-components/batch.frag') + #else + if (u_Visible < 0.5) { + discard; + } + #endif float alpha = 1.0; float lineWidth = v_Distance.w; @@ -56,16 +63,23 @@ void main(){ alpha *= max(min(v_Distance.z + 0.5, 1.0), 0.0); } - if (u_Dash + u_Gap > 1.0) { - float scalingFactor = sqrt(u_ModelMatrix[0][0] * u_ModelMatrix[0][0] + u_ModelMatrix[0][1] * u_ModelMatrix[0][1] + u_ModelMatrix[0][2] * u_ModelMatrix[0][2]); - float travel = mod(v_Travel + u_Gap * scalingFactor * 0.5 + u_DashOffset, u_Dash * scalingFactor + u_Gap * scalingFactor) - (u_Gap * scalingFactor * 0.5); - float left = max(travel - 0.5, -0.5); - float right = min(travel + 0.5, u_Gap * scalingFactor + 0.5); - alpha *= max(0.0, right - left); - } + #ifdef INSTANCED + #else + if (u_Dash + u_Gap > 1.0) { + float scalingFactor = sqrt(u_ModelMatrix[0][0] * u_ModelMatrix[0][0] + u_ModelMatrix[0][1] * u_ModelMatrix[0][1] + u_ModelMatrix[0][2] * u_ModelMatrix[0][2]); + float travel = mod(v_Travel + u_Gap * scalingFactor * 0.5 + u_DashOffset, u_Dash * scalingFactor + u_Gap * scalingFactor) - (u_Gap * scalingFactor * 0.5); + float left = max(travel - 0.5, -0.5); + float right = min(travel + 0.5, u_Gap * scalingFactor + 0.5); + alpha *= max(0.0, right - left); + } + #endif if (u_IsPicking > 0.5) { - vec3 pickingColor = COLOR_SCALE * u_PickingColor; + #ifdef INSTANCED + vec3 pickingColor = u_PickingColor; + #else + vec3 pickingColor = u_PickingColor / 255.0; + #endif if (pickingColor.x == 0.0 && pickingColor.y == 0.0 && pickingColor.z == 0.0) { discard; } diff --git a/packages/g-plugin-device-renderer/src/shader/line.vert b/packages/g-plugin-device-renderer/src/shader/line.vert index 2c9456ab4..936613e85 100644 --- a/packages/g-plugin-device-renderer/src/shader/line.vert +++ b/packages/g-plugin-device-renderer/src/shader/line.vert @@ -1,5 +1,10 @@ #pragma glslify: import('@antv/g-shader-components/scene.both.glsl') -#pragma glslify: import('@antv/g-shader-components/line.both.glsl') + +#ifdef INSTANCED + #pragma glslify: import('@antv/g-shader-components/batch.declaration.vert') +#else + #pragma glslify: import('@antv/g-shader-components/line.both.glsl') +#endif layout(location = PREV) in vec2 a_Prev; layout(location = POINT1) in vec2 a_Point1; @@ -22,6 +27,13 @@ const float CAP_SQUARE = 2.0; const float CAP_ROUND = 3.0; const float CAP_BUTT2 = 4.0; +#ifdef INSTANCED + const float u_Expand = 1.0; + const float u_MiterLimit = 5.0; + const float u_ScaleMode = 1.0; + const float u_Alignment = 0.5; +#endif + out vec4 v_Distance; out vec4 v_Arc; out float v_Type; @@ -48,6 +60,10 @@ vec2 doBisect( } void main() { + #ifdef INSTANCED + #pragma glslify: import('@antv/g-shader-components/batch.vert') + #endif + vec2 pointA = (u_ModelMatrix * vec4(a_Point1, 0., 1.0)).xy; vec2 pointB = (u_ModelMatrix * vec4(a_Point2, 0., 1.0)).xy; @@ -66,12 +82,12 @@ void main() { } if (u_ScaleMode > 2.5) { - lineWidth *= length(u_ModelMatrix * vec4(1.0, 0.0, 0.0, 0.0)); + lineWidth *= length(u_ModelMatrix * vec4(1.0, 0.0, 0.0, 0.0)); } else if (u_ScaleMode > 1.5) { - lineWidth *= length(u_ModelMatrix * vec4(0.0, 1.0, 0.0, 0.0)); + lineWidth *= length(u_ModelMatrix * vec4(0.0, 1.0, 0.0, 0.0)); } else if (u_ScaleMode > 0.5) { - vec2 avgDiag = (u_ModelMatrix * vec4(1.0, 1.0, 0.0, 0.0)).xy; - lineWidth *= sqrt(dot(avgDiag, avgDiag) * 0.5); + vec2 avgDiag = (u_ModelMatrix * vec4(1.0, 1.0, 0.0, 0.0)).xy; + lineWidth *= sqrt(dot(avgDiag, avgDiag) * 0.5); } float capType = floor(type / 32.0); type -= capType * 32.0; @@ -82,214 +98,213 @@ void main() { vec2 pos; if (capType == CAP_ROUND) { - if (a_VertexNum < 3.5) { + if (a_VertexNum < 3.5) { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); return; - } - type = JOINT_CAP_ROUND; - capType = 0.0; + } + type = JOINT_CAP_ROUND; + capType = 0.0; } if (type >= BEVEL) { - float dy = lineWidth + u_Expand; - float inner = 0.0; - if (a_VertexNum >= 1.5) { + float dy = lineWidth + u_Expand; + float inner = 0.0; + if (a_VertexNum >= 1.5) { dy = -dy; inner = 1.0; - } + } - vec2 base, next, xBasis2, bisect; - float flag = 0.0; - float sign2 = 1.0; - if (a_VertexNum < 0.5 || a_VertexNum > 2.5 && a_VertexNum < 3.5) { + vec2 base, next, xBasis2, bisect; + float flag = 0.0; + float sign2 = 1.0; + if (a_VertexNum < 0.5 || a_VertexNum > 2.5 && a_VertexNum < 3.5) { next = (u_ModelMatrix * vec4(a_Prev, 0.0, 1.0)).xy; base = pointA; flag = type - floor(type / 2.0) * 2.0; sign2 = -1.0; - - } else { + } else { next = (u_ModelMatrix * vec4(a_Next, 0.0, 1.0)).xy; base = pointB; if (type >= MITER && type < MITER + 3.5) { - flag = step(MITER + 1.5, type); - // check miter limit here? - } + flag = step(MITER + 1.5, type); + // check miter limit here? } - xBasis2 = next - base; - float len2 = length(xBasis2); - vec2 norm2 = vec2(xBasis2.y, -xBasis2.x) / len2; - float D = norm.x * norm2.y - norm.y * norm2.x; - if (D < 0.0) { + } + xBasis2 = next - base; + float len2 = length(xBasis2); + vec2 norm2 = vec2(xBasis2.y, -xBasis2.x) / len2; + float D = norm.x * norm2.y - norm.y * norm2.x; + if (D < 0.0) { inner = 1.0 - inner; - } - norm2 *= sign2; + } + norm2 *= sign2; - if (abs(lineAlignment) > 0.01) { + if (abs(lineAlignment) > 0.01) { float shift = lineWidth * lineAlignment; pointA += norm * shift; pointB += norm * shift; if (abs(D) < 0.01) { - base += norm * shift; + base += norm * shift; } else { - base += doBisect(norm, len, norm2, len2, shift, 0.0); - } + base += doBisect(norm, len, norm2, len2, shift, 0.0); } + } - float collinear = step(0.0, dot(norm, norm2)); - v_Type = 0.0; - float dy2 = -1000.0; - float dy3 = -1000.0; - if (abs(D) < 0.01 && collinear < 0.5) { + float collinear = step(0.0, dot(norm, norm2)); + v_Type = 0.0; + float dy2 = -1000.0; + float dy3 = -1000.0; + if (abs(D) < 0.01 && collinear < 0.5) { if (type >= ROUND && type < ROUND + 1.5) { - type = JOINT_CAP_ROUND; - } - //TODO: BUTT here too + type = JOINT_CAP_ROUND; } + // TODO: BUTT here too + } - if (a_VertexNum < 3.5) { + if (a_VertexNum < 3.5) { if (abs(D) < 0.01) { - pos = dy * norm; + pos = dy * norm; } else { - if (flag < 0.5 && inner < 0.5) { + if (flag < 0.5 && inner < 0.5) { pos = dy * norm; - } else { + } else { pos = doBisect(norm, len, norm2, len2, dy, inner); - } + } } if (capType >= CAP_BUTT && capType < CAP_ROUND) { - float extra = step(CAP_SQUARE, capType) * lineWidth; - vec2 back = -forward; - if (a_VertexNum < 0.5 || a_VertexNum > 2.5) { + float extra = step(CAP_SQUARE, capType) * lineWidth; + vec2 back = -forward; + if (a_VertexNum < 0.5 || a_VertexNum > 2.5) { pos += back * (u_Expand + extra); dy2 = u_Expand; - } else { + } else { dy2 = dot(pos + base - pointA, back) - extra; - } + } } if (type >= JOINT_CAP_BUTT && type < JOINT_CAP_SQUARE + 0.5) { - float extra = step(JOINT_CAP_SQUARE, type) * lineWidth; - if (a_VertexNum < 0.5 || a_VertexNum > 2.5) { + float extra = step(JOINT_CAP_SQUARE, type) * lineWidth; + if (a_VertexNum < 0.5 || a_VertexNum > 2.5) { dy3 = dot(pos + base - pointB, forward) - extra; - } else { + } else { pos += forward * (u_Expand + extra); dy3 = u_Expand; if (capType >= CAP_BUTT) { - dy2 -= u_Expand + extra; - } + dy2 -= u_Expand + extra; } + } } - } else if (type >= JOINT_CAP_ROUND && type < JOINT_CAP_ROUND + 1.5) { + } else if (type >= JOINT_CAP_ROUND && type < JOINT_CAP_ROUND + 1.5) { if (inner > 0.5) { - dy = -dy; - inner = 0.0; + dy = -dy; + inner = 0.0; } vec2 d2 = abs(dy) * forward; if (a_VertexNum < 4.5) { - dy = -dy; - pos = dy * norm; + dy = -dy; + pos = dy * norm; } else if (a_VertexNum < 5.5) { - pos = dy * norm; + pos = dy * norm; } else if (a_VertexNum < 6.5) { - pos = dy * norm + d2; - v_Arc.x = abs(dy); + pos = dy * norm + d2; + v_Arc.x = abs(dy); } else { - dy = -dy; - pos = dy * norm + d2; - v_Arc.x = abs(dy); + dy = -dy; + pos = dy * norm + d2; + v_Arc.x = abs(dy); } dy2 = 0.0; v_Arc.y = dy; v_Arc.z = 0.0; v_Arc.w = lineWidth; v_Type = 3.0; - } else if (abs(D) < 0.01) { + } else if (abs(D) < 0.01) { pos = dy * norm; - } else { + } else { if (type >= ROUND && type < ROUND + 1.5) { - if (inner > 0.5) { + if (inner > 0.5) { dy = -dy; inner = 0.0; - } - if (a_VertexNum < 4.5) { + } + if (a_VertexNum < 4.5) { pos = doBisect(norm, len, norm2, len2, -dy, 1.0); - } else if (a_VertexNum < 5.5) { + } else if (a_VertexNum < 5.5) { pos = dy * norm; - } else if (a_VertexNum > 7.5) { + } else if (a_VertexNum > 7.5) { pos = dy * norm2; - } else { + } else { pos = doBisect(norm, len, norm2, len2, dy, 0.0); float d2 = abs(dy); if (length(pos) > abs(dy) * 1.5) { - if (a_VertexNum < 6.5) { + if (a_VertexNum < 6.5) { pos.x = dy * norm.x - d2 * norm.y; pos.y = dy * norm.y + d2 * norm.x; - } else { + } else { pos.x = dy * norm2.x + d2 * norm2.y; pos.y = dy * norm2.y - d2 * norm2.x; - } - } + } } - vec2 norm3 = normalize(norm + norm2); - float sign = step(0.0, dy) * 2.0 - 1.0; - v_Arc.x = sign * dot(pos, norm3); - v_Arc.y = pos.x * norm3.y - pos.y * norm3.x; - v_Arc.z = dot(norm, norm3) * lineWidth; - v_Arc.w = lineWidth; - dy = -sign * dot(pos, norm); - dy2 = -sign * dot(pos, norm2); - dy3 = v_Arc.z - v_Arc.x; - v_Type = 3.0; + } + vec2 norm3 = normalize(norm + norm2); + float sign = step(0.0, dy) * 2.0 - 1.0; + v_Arc.x = sign * dot(pos, norm3); + v_Arc.y = pos.x * norm3.y - pos.y * norm3.x; + v_Arc.z = dot(norm, norm3) * lineWidth; + v_Arc.w = lineWidth; + dy = -sign * dot(pos, norm); + dy2 = -sign * dot(pos, norm2); + dy3 = v_Arc.z - v_Arc.x; + v_Type = 3.0; } else { - float hit = 0.0; - if (type >= BEVEL && type < BEVEL + 1.5) { + float hit = 0.0; + if (type >= BEVEL && type < BEVEL + 1.5) { if (dot(norm, norm2) > 0.0) { - type = MITER; - } + type = MITER; } - if (type >= MITER && type < MITER + 3.5) { + } + if (type >= MITER && type < MITER + 3.5) { if (inner > 0.5) { - dy = -dy; - inner = 0.0; + dy = -dy; + inner = 0.0; } float sign = step(0.0, dy) * 2.0 - 1.0; pos = doBisect(norm, len, norm2, len2, dy, 0.0); if (length(pos) > abs(dy) * u_MiterLimit) { - type = BEVEL; + type = BEVEL; } else { - if (a_VertexNum < 4.5) { + if (a_VertexNum < 4.5) { dy = -dy; pos = doBisect(norm, len, norm2, len2, dy, 1.0); - } else if (a_VertexNum < 5.5) { + } else if (a_VertexNum < 5.5) { pos = dy * norm; - } else if (a_VertexNum > 6.5) { + } else if (a_VertexNum > 6.5) { pos = dy * norm2; - } - v_Type = 1.0; - dy = -sign * dot(pos, norm); - dy2 = -sign * dot(pos, norm2); - hit = 1.0; - } + } + v_Type = 1.0; + dy = -sign * dot(pos, norm); + dy2 = -sign * dot(pos, norm2); + hit = 1.0; } - if (type >= BEVEL && type < BEVEL + 1.5) { + } + if (type >= BEVEL && type < BEVEL + 1.5) { if (inner > 0.5) { - dy = -dy; - inner = 0.0; + dy = -dy; + inner = 0.0; } float d2 = abs(dy); vec2 pos3 = vec2(dy * norm.x - d2 * norm.y, dy * norm.y + d2 * norm.x); vec2 pos4 = vec2(dy * norm2.x + d2 * norm2.y, dy * norm2.y - d2 * norm2.x); if (a_VertexNum < 4.5) { - pos = doBisect(norm, len, norm2, len2, -dy, 1.0); + pos = doBisect(norm, len, norm2, len2, -dy, 1.0); } else if (a_VertexNum < 5.5) { - pos = dy * norm; + pos = dy * norm; } else if (a_VertexNum > 7.5) { - pos = dy * norm2; + pos = dy * norm2; } else { - if (a_VertexNum < 6.5) { + if (a_VertexNum < 6.5) { pos = pos3; - } else { + } else { pos = pos4; - } + } } vec2 norm3 = normalize(norm + norm2); float sign = step(0.0, dy) * 2.0 - 1.0; @@ -298,17 +313,17 @@ void main() { dy3 = (-sign * dot(pos, norm3)) + lineWidth; v_Type = 4.0; hit = 1.0; - } - if (hit < 0.5) { + } + if (hit < 0.5) { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); return; - } - } + } } - pos += base; - v_Distance = vec4(dy, dy2, dy3, lineWidth) * u_DevicePixelRatio; - v_Arc = v_Arc * u_DevicePixelRatio; - v_Travel = a_Travel + dot(pos - pointA, vec2(-norm.y, norm.x)); + } + pos += base; + v_Distance = vec4(dy, dy2, dy3, lineWidth) * u_DevicePixelRatio; + v_Arc = v_Arc * u_DevicePixelRatio; + v_Travel = a_Travel + dot(pos - pointA, vec2(-norm.y, norm.x)); } gl_Position = u_ProjectionMatrix * u_ViewMatrix * vec4(pos, u_ZIndex, 1.0); diff --git a/packages/g-plugin-physx/package.json b/packages/g-plugin-physx/package.json index c9824706e..ef58c400f 100644 --- a/packages/g-plugin-physx/package.json +++ b/packages/g-plugin-physx/package.json @@ -39,6 +39,7 @@ }, "dependencies": { "@antv/g-lite": "workspace:*", + "gl-matrix": "^3.4.3", "tslib": "^2.5.3" }, "publishConfig": { diff --git a/packages/g-plugin-physx/src/PhysXPlugin.ts b/packages/g-plugin-physx/src/PhysXPlugin.ts index 2a961ed9c..490b729cd 100644 --- a/packages/g-plugin-physx/src/PhysXPlugin.ts +++ b/packages/g-plugin-physx/src/PhysXPlugin.ts @@ -1,3 +1,4 @@ +import { quat } from 'gl-matrix'; import type { DisplayObject, FederatedEvent, @@ -19,6 +20,32 @@ export enum PhysXRuntimeMode { JavaScript, } +/** + * Flags which affect the behavior of Shapes. + */ +export enum ShapeFlag { + /** The shape will partake in collision in the physical simulation. */ + SIMULATION_SHAPE = 1 << 0, + /** The shape will partake in scene queries (ray casts, overlap tests, sweeps, ...). */ + SCENE_QUERY_SHAPE = 1 << 1, + /** The shape is a trigger which can send reports whenever other shapes enter/leave its volume. */ + TRIGGER_SHAPE = 1 << 2, +} + +/** + * Describes how physics materials of the colliding objects are combined. + */ +enum CombineMode { + /** Averages the friction/bounce of the two colliding materials. */ + Average, + /** Uses the smaller friction/bounce of the two colliding materials. */ + Minimum, + /** Multiplies the friction/bounce of the two colliding materials. */ + Multiply, + /** Uses the larger friction/bounce of the two colliding materials. */ + Maximum, +} + export class PhysXPlugin implements RenderingPlugin { static tag = 'PhysX'; @@ -40,8 +67,18 @@ export class PhysXPlugin implements RenderingPlugin { } }; + const handleUnmounted = (e: FederatedEvent) => { + const PhysX = this.PhysX; + const target = e.target as DisplayObject; + + if (PhysX) { + this.bodies.get(target).body.release(); + } + }; + renderingService.hooks.initAsync.tapPromise(PhysXPlugin.tag, async () => { canvas.addEventListener(ElementEvent.MOUNTED, handleMounted); + canvas.addEventListener(ElementEvent.UNMOUNTED, handleUnmounted); this.PhysX = (await this.initPhysX()) as any; this.createScene(); @@ -57,6 +94,9 @@ export class PhysXPlugin implements RenderingPlugin { this.bodies.forEach(({ body, displayObject }) => { const transform = body.getGlobalPose(); const { translation, rotation } = transform; + + // console.log(translation, rotation, displayObject); + displayObject.setPosition( translation.x, translation.y, @@ -76,60 +116,66 @@ export class PhysXPlugin implements RenderingPlugin { renderingService.hooks.destroy.tap(PhysXPlugin.tag, () => { canvas.removeEventListener(ElementEvent.MOUNTED, handleMounted); + canvas.removeEventListener(ElementEvent.UNMOUNTED, handleUnmounted); }); } // @see https://github.com/oasis-engine/engine/blob/main/packages/physics-physx/src/PhysXPhysics.ts#L39 - private initPhysX( + private async initPhysX( runtimeMode: PhysXRuntimeMode = PhysXRuntimeMode.Auto, ): Promise { - const scriptPromise = new Promise((resolve) => { - const script = document.createElement('script'); - document.body.appendChild(script); - script.async = true; - script.onload = resolve; - - const supported = (() => { - try { - if ( - typeof WebAssembly === 'object' && - typeof WebAssembly.instantiate === 'function' - ) { - const module = new WebAssembly.Module( - Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00), - ); - if (module instanceof WebAssembly.Module) - return ( - new WebAssembly.Instance(module) instanceof WebAssembly.Instance + if ((window).PHYSX) { + return await (window).PHYSX(); + } else { + const scriptPromise = new Promise((resolve) => { + const script = document.createElement('script'); + document.body.appendChild(script); + script.async = true; + script.onload = resolve; + + const supported = (() => { + try { + if ( + typeof WebAssembly === 'object' && + typeof WebAssembly.instantiate === 'function' + ) { + const module = new WebAssembly.Module( + Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00), ); + if (module instanceof WebAssembly.Module) + return ( + new WebAssembly.Instance(module) instanceof + WebAssembly.Instance + ); + } + } catch (e) {} + return false; + })(); + if (runtimeMode == PhysXRuntimeMode.Auto) { + if (supported) { + runtimeMode = PhysXRuntimeMode.WebAssembly; + } else { + runtimeMode = PhysXRuntimeMode.JavaScript; } - } catch (e) {} - return false; - })(); - if (runtimeMode == PhysXRuntimeMode.Auto) { - if (supported) { - runtimeMode = PhysXRuntimeMode.WebAssembly; - } else { - runtimeMode = PhysXRuntimeMode.JavaScript; } - } - if (runtimeMode == PhysXRuntimeMode.JavaScript) { - script.src = - 'https://gw.alipayobjects.com/os/lib/oasis-engine/physics-physx/0.6.0-alpha.1/dist/physx.release.js'; - } else if (runtimeMode == PhysXRuntimeMode.WebAssembly) { - script.src = - 'https://gw.alipayobjects.com/os/lib/oasis-engine/physics-physx/0.6.0-alpha.1/dist/physx.release.js'; - } - }); + if (runtimeMode == PhysXRuntimeMode.JavaScript) { + script.src = + 'https://gw.alipayobjects.com/os/lib/oasis-engine/physics-physx/1.0.0-alpha.4/libs/physx.release.js.js'; + } else if (runtimeMode == PhysXRuntimeMode.WebAssembly) { + script.src = + 'https://gw.alipayobjects.com/os/lib/oasis-engine/physics-physx/1.0.0-alpha.4/libs/physx.release.js'; + } + }); - return new Promise((resolve) => { - scriptPromise.then(() => { - (window).PHYSX().then((PHYSX: any) => { - resolve(PHYSX); + return new Promise((resolve) => { + scriptPromise.then(() => { + (window).PHYSX().then((PHYSX: any) => { + resolve(PHYSX); + }); }); }); - }); + } } private createScene() { @@ -143,11 +189,19 @@ export class PhysXPlugin implements RenderingPlugin { defaultErrorCallback, ); const triggerCallback = { - onContactBegin: () => {}, - onContactEnd: () => {}, + onContactBegin: () => { + console.log('begin...'); + }, + onContactEnd: (index1, index2) => { + console.log('end...', index1, index2); + }, onContactPersist: () => {}, - onTriggerBegin: () => {}, - onTriggerEnd: () => {}, + onTriggerBegin: () => { + console.log('triggerbegin...'); + }, + onTriggerEnd: () => { + console.log('triggerend...'); + }, }; const physxSimulationCallbackInstance = PhysX.PxSimulationEventCallback.implement(triggerCallback); @@ -166,6 +220,11 @@ export class PhysXPlugin implements RenderingPlugin { physxSimulationCallbackInstance, ); this.scene = this.physics.createScene(sceneDesc); + this.scene.setGravity({ + x: 0, + y: 100, + z: 0, + }); } private addActor(target: DisplayObject) { @@ -175,7 +234,7 @@ export class PhysXPlugin implements RenderingPlugin { const PhysX = this.PhysX; const pos = target.getPosition(); - const rotation = target.getRotation(); + const rotation = quat.normalize(quat.create(), target.getRotation()); // use box by default const geometry = new PhysX.PxBoxGeometry( @@ -184,14 +243,19 @@ export class PhysXPlugin implements RenderingPlugin { halfExtents[1], halfExtents[2] || 0.1, // account for 2D shapes ); - const material = this.physics.createMaterial(0.2, 0.2, 0.2); + const material = this.physics.createMaterial(0.5, 0.1, 2); + material.setFrictionCombineMode(CombineMode.Average); + material.setRestitutionCombineMode(CombineMode.Average); + + // @see https://gameworksdocs.nvidia.com/PhysX/4.1/documentation/physxapi/files/structPxShapeFlag.html#a6edb481aaa3a998c5d6dd3fc4ad87f1aa7fa4fea0eecda9cc80a7aaa11a22df52 const flags = new PhysX.PxShapeFlags( - // @see https://gameworksdocs.nvidia.com/PhysX/4.1/documentation/physxapi/files/structPxShapeFlag.html#a6edb481aaa3a998c5d6dd3fc4ad87f1aa7fa4fea0eecda9cc80a7aaa11a22df52 - PhysX.PxShapeFlag.eSCENE_QUERY_Shape.value | - PhysX.PxShapeFlag.eSIMULATION_Shape.value, + ShapeFlag.SCENE_QUERY_SHAPE | ShapeFlag.SIMULATION_SHAPE, + // ShapeFlag.TRIGGER_SHAPE, ); // @see https://gameworksdocs.nvidia.com/PhysX/4.1/documentation/physxapi/files/classPxPhysics.html#abc564607f208cbc1944880172a3d62fe - const shape = this.physics.createShape(geometry, material, false, flags); + const shape = this.physics.createShape(geometry, material, true, flags); + shape.setUUID(target.entity); + const transform = { translation: { x: pos[0], @@ -217,6 +281,13 @@ export class PhysXPlugin implements RenderingPlugin { // @see https://gameworksdocs.nvidia.com/PhysX/4.1/documentation/physxapi/files/classPxRigidActor.html#a022e098ea67bc8ec87f93c2f18a4db6f body.attachShape(shape); + + // if (body.setRigidBodyFlag) { + // body.setRigidBodyFlag(PhysX.PxRigidBodyFlag.eENABLE_CCD, true); + // } + + body.setGlobalPose(transform, true); + this.bodies.set(target, { displayObject: target, body, @@ -224,11 +295,6 @@ export class PhysXPlugin implements RenderingPlugin { // @see https://gameworksdocs.nvidia.com/PhysX/4.1/documentation/physxapi/files/classPxScene.html#a033c70c3094db21a2c51246e1a65a0e5 this.scene.addActor(body, null); - this.scene.setGravity({ - x: 0, - y: 100, // flipY - z: 0, - }); } } } diff --git a/packages/g-plugin-webgl-device/src/WebGLDeviceContribution.ts b/packages/g-plugin-webgl-device/src/WebGLDeviceContribution.ts index a50533194..b2e91b229 100644 --- a/packages/g-plugin-webgl-device/src/WebGLDeviceContribution.ts +++ b/packages/g-plugin-webgl-device/src/WebGLDeviceContribution.ts @@ -14,7 +14,7 @@ export class WebGLDeviceContribution implements DeviceContribution { // @see https://webglfundamentals.org/webgl/lessons/webgl-qna-how-to-use-the-stencil-buffer.html stencil: true, // @see https://webglfundamentals.org/webgl/lessons/webgl-and-alpha.html - // premultipliedAlpha: true, + premultipliedAlpha: true, }; this.handleContextEvents($canvas); diff --git a/packages/g-plugin-webgl-device/src/platform/Buffer.ts b/packages/g-plugin-webgl-device/src/platform/Buffer.ts index 0a5ee46be..ab2370065 100644 --- a/packages/g-plugin-webgl-device/src/platform/Buffer.ts +++ b/packages/g-plugin-webgl-device/src/platform/Buffer.ts @@ -1,7 +1,8 @@ -import type { +import { Buffer, BufferDescriptor, BufferFrequencyHint, + align, } from '@antv/g-plugin-device-renderer'; import { assert, @@ -72,9 +73,14 @@ export class Buffer_GL extends ResourceBase_GL implements Buffer { } } + // const byteSize = isNumber(viewOrSize) + // ? viewOrSize * 4 + // : viewOrSize.byteLength * 4; + const byteSize = isNumber(viewOrSize) - ? viewOrSize * 4 - : viewOrSize.byteLength * 4; + ? align(viewOrSize, 4) + : align(viewOrSize.byteLength, 4); + this.gl_buffer_pages = []; let pageByteSize: number; diff --git a/packages/g-plugin-webgl-device/src/platform/Readback.ts b/packages/g-plugin-webgl-device/src/platform/Readback.ts index cce958537..170ddb34d 100644 --- a/packages/g-plugin-webgl-device/src/platform/Readback.ts +++ b/packages/g-plugin-webgl-device/src/platform/Readback.ts @@ -1,4 +1,9 @@ -import type { Buffer, Readback, Texture } from '@antv/g-plugin-device-renderer'; +import { + Buffer, + Readback, + Texture, + getFormatByteSize, +} from '@antv/g-plugin-device-renderer'; import { GL, ResourceType } from '@antv/g-plugin-device-renderer'; import { clamp } from '@antv/util'; import type { Device_GL } from './Device'; @@ -71,7 +76,7 @@ export class Readback_GL extends ResourceBase_GL implements Readback { /** * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_best_practices#use_non-blocking_async_data_readback */ - readTexture( + async readTexture( t: Texture, x: number, y: number, @@ -80,60 +85,68 @@ export class Readback_GL extends ResourceBase_GL implements Readback { dstBuffer: ArrayBufferView, dstOffset = 0, length = dstBuffer.byteLength || 0, - ): ArrayBufferView { + ): Promise { const gl = this.device.gl; const texture = t as Texture_GL; - // const gl_format = this.device.translateTextureFormat(texture.pixelFormat); + const gl_format = this.device.translateTextureFormat(texture.pixelFormat); const gl_type = this.device.translateTextureType(texture.pixelFormat); - // const formatByteSize = getFormatByteSize(texture.pixelFormat); - - // if (isWebGL2(gl)) { - // this.gl_pbo = this.device.ensureResourceExists(gl.createBuffer()); - // // PIXEL_PACK_BUFFER: Buffer used for pixel transfer operations - // // @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindBuffer - // gl.bindBuffer(gl.PIXEL_PACK_BUFFER, this.gl_pbo); - // // STREAM_READ: The contents are intended to be specified once by reading data from WebGL, and queried at most a few times by the application - // // @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData - // gl.bufferData(gl.PIXEL_PACK_BUFFER, length, gl.STREAM_READ); - // gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null); - - // gl.bindFramebuffer(GL.READ_FRAMEBUFFER, this.device.readbackFramebuffer); - // gl.framebufferTexture2D( - // GL.READ_FRAMEBUFFER, - // GL.COLOR_ATTACHMENT0, - // GL.TEXTURE_2D, - // texture.gl_texture, - // 0, - // ); - - // gl.bindBuffer(gl.PIXEL_PACK_BUFFER, this.gl_pbo); - // gl.readPixels(x, y, width, height, gl_format, gl_type, dstOffset * formatByteSize); - // gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null); - - // return this.getBufferSubDataAsync( - // gl.PIXEL_PACK_BUFFER, - // this.gl_pbo, - // 0, - // dstBuffer, - // dstOffset, - // length, - // ); - // } else { - gl.bindFramebuffer(GL.FRAMEBUFFER, this.device.readbackFramebuffer); - gl.framebufferTexture2D( - GL.FRAMEBUFFER, - GL.COLOR_ATTACHMENT0, - GL.TEXTURE_2D, - texture.gl_texture, - 0, - ); - // slow requires roundtrip to GPU - // @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/pixelStorei - gl.pixelStorei(gl.PACK_ALIGNMENT, 4); - gl.readPixels(x, y, width, height, gl.RGBA, gl_type, dstBuffer); - return dstBuffer; - // } + const formatByteSize = getFormatByteSize(texture.pixelFormat); + + if (isWebGL2(gl)) { + this.gl_pbo = this.device.ensureResourceExists(gl.createBuffer()); + // PIXEL_PACK_BUFFER: Buffer used for pixel transfer operations + // @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindBuffer + gl.bindBuffer(gl.PIXEL_PACK_BUFFER, this.gl_pbo); + // STREAM_READ: The contents are intended to be specified once by reading data from WebGL, and queried at most a few times by the application + // @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData + gl.bufferData(gl.PIXEL_PACK_BUFFER, length, gl.STREAM_READ); + gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null); + + gl.bindFramebuffer(GL.READ_FRAMEBUFFER, this.device.readbackFramebuffer); + gl.framebufferTexture2D( + GL.READ_FRAMEBUFFER, + GL.COLOR_ATTACHMENT0, + GL.TEXTURE_2D, + texture.gl_texture, + 0, + ); + + gl.bindBuffer(gl.PIXEL_PACK_BUFFER, this.gl_pbo); + gl.readPixels( + x, + y, + width, + height, + gl_format, + gl_type, + dstOffset * formatByteSize, + ); + gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null); + + return this.getBufferSubDataAsync( + gl.PIXEL_PACK_BUFFER, + this.gl_pbo, + 0, + dstBuffer, + dstOffset, + length, + ); + } else { + gl.bindFramebuffer(GL.FRAMEBUFFER, this.device.readbackFramebuffer); + gl.framebufferTexture2D( + GL.FRAMEBUFFER, + GL.COLOR_ATTACHMENT0, + GL.TEXTURE_2D, + texture.gl_texture, + 0, + ); + // slow requires roundtrip to GPU + // @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/pixelStorei + gl.pixelStorei(gl.PACK_ALIGNMENT, 4); + gl.readPixels(x, y, width, height, gl.RGBA, gl_type, dstBuffer); + return dstBuffer; + } } async readBuffer( diff --git a/packages/g-plugin-webgpu-device/src/platform/Buffer.ts b/packages/g-plugin-webgpu-device/src/platform/Buffer.ts index f76ab8191..195205cc0 100644 --- a/packages/g-plugin-webgpu-device/src/platform/Buffer.ts +++ b/packages/g-plugin-webgpu-device/src/platform/Buffer.ts @@ -1,14 +1,13 @@ -import type { Buffer, BufferDescriptor } from '@antv/g-plugin-device-renderer'; +import { + Buffer, + BufferDescriptor, + align, +} from '@antv/g-plugin-device-renderer'; import { BufferUsage, ResourceType } from '@antv/g-plugin-device-renderer'; import type { IDevice_WebGPU } from './interfaces'; import { ResourceBase_WebGPU } from './ResourceBase'; import { translateBufferUsage } from './utils'; - -function isView( - viewOrSize: ArrayBufferView | number, -): viewOrSize is ArrayBufferView { - return (viewOrSize as ArrayBufferView).byteLength !== undefined; -} +import { isNumber } from '@antv/util'; export class Buffer_WebGPU extends ResourceBase_WebGPU implements Buffer { type: ResourceType.Buffer = ResourceType.Buffer; @@ -17,9 +16,12 @@ export class Buffer_WebGPU extends ResourceBase_WebGPU implements Buffer { */ gpuBuffer: GPUBuffer; + /** + * size in bytes + */ size: number; - view: ArrayBufferView; + view: ArrayBufferView | null; usage: BufferUsage; @@ -37,10 +39,6 @@ export class Buffer_WebGPU extends ResourceBase_WebGPU implements Buffer { const { usage, viewOrSize } = descriptor; const useMapRead = !!(usage & BufferUsage.MAP_READ); - // const alignedLength = isView(viewOrSize) - // ? viewOrSize.byteLength - // : viewOrSize * 4; // 4 bytes alignments (because of the upload which requires this) - this.usage = translateBufferUsage(usage); // Buffer usages (BufferUsage::(MapRead|CopyDst|Storage)) is invalid. If a buffer usage contains BufferUsage::MapRead the only other allowed usage is BufferUsage::CopyDst. @@ -49,20 +47,26 @@ export class Buffer_WebGPU extends ResourceBase_WebGPU implements Buffer { this.usage = BufferUsage.MAP_READ | BufferUsage.COPY_DST; } - const mapBuffer = isView(viewOrSize); + const mapBuffer = !isNumber(viewOrSize); + + // this.size = isView(viewOrSize) ? viewOrSize.byteLength : viewOrSize * 4; + this.view = !isNumber(viewOrSize) ? viewOrSize : null; - this.size = isView(viewOrSize) ? viewOrSize.byteLength : viewOrSize * 4; - this.view = isView(viewOrSize) ? viewOrSize : null; + // 4 bytes alignments (because of the upload which requires this) + this.size = isNumber(viewOrSize) + ? align(viewOrSize, 4) + : align(viewOrSize.byteLength, 4); - if (isView(viewOrSize)) { - // this.setSubData(0, new Uint8Array(viewOrSize.buffer)); + if (!isNumber(viewOrSize)) { this.gpuBuffer = this.device.device.createBuffer({ usage: this.usage, size: this.size, mappedAtCreation: true, }); + + const ctor = (viewOrSize && viewOrSize.constructor) || Float32Array; // @ts-ignore - new Uint8Array(this.gpuBuffer.getMappedRange()).set(viewOrSize); + new ctor(this.gpuBuffer.getMappedRange()).set(viewOrSize); this.gpuBuffer.unmap(); } else { this.gpuBuffer = this.device.device.createBuffer({ diff --git a/packages/g-plugin-webgpu-device/src/platform/Device.ts b/packages/g-plugin-webgpu-device/src/platform/Device.ts index fcb07e9dc..3d5830d69 100644 --- a/packages/g-plugin-webgpu-device/src/platform/Device.ts +++ b/packages/g-plugin-webgpu-device/src/platform/Device.ts @@ -206,8 +206,9 @@ export class Device_WebGPU implements SwapChain, IDevice_WebGPU { device: this.device, format: this.swapChainFormat, usage: this.swapChainTextureUsage, - // @see https://www.w3.org/TR/webgpu/#enumdef-gpucanvascompositingalphamode - alphaMode: 'opaque', + // @see https://www.w3.org/TR/webgpu/#gpucanvasalphamode + // alphaMode: 'opaque', + alphaMode: 'premultiplied', }); } diff --git a/packages/g-plugin-webgpu-device/src/platform/Readback.ts b/packages/g-plugin-webgpu-device/src/platform/Readback.ts index a5ac50534..7d67b2d90 100644 --- a/packages/g-plugin-webgpu-device/src/platform/Readback.ts +++ b/packages/g-plugin-webgpu-device/src/platform/Readback.ts @@ -20,7 +20,7 @@ export class Readback_WebGPU extends ResourceBase_WebGPU implements Readback { super({ id, device }); } - readTexture( + async readTexture( t: Texture, x: number, y: number, @@ -29,8 +29,10 @@ export class Readback_WebGPU extends ResourceBase_WebGPU implements Readback { dst: ArrayBufferView, dstOffset = 0, length = 0, - ): ArrayBufferView { + ): Promise { const texture = t as Texture_WebGPU; + + // FIXME: default to 0 for now const faceIndex = 0; const blockInformation = this.getBlockInformationFromFormat(texture.format); @@ -38,6 +40,7 @@ export class Readback_WebGPU extends ResourceBase_WebGPU implements Readback { const bytesPerRow = Math.ceil(width / blockInformation.width) * blockInformation.length; + // bytesPerRow (4) is not a multiple of 256, so we need to align it to 256. const bytesPerRowAligned = Math.ceil(bytesPerRow / 256) * 256; const size = bytesPerRowAligned * height; @@ -75,9 +78,14 @@ export class Readback_WebGPU extends ResourceBase_WebGPU implements Readback { this.device.device.queue.submit([commandEncoder.finish()]); - // FIXME: read from buffer - // return this.readBuffer(buffer, size, dst, dstOffset, length, texture.pixelFormat); - return null; + return this.readBuffer( + buffer, + 0, + dst.byteLength === size ? dst : null, + dstOffset, + size, + texture.pixelFormat, + ); } readBuffer( diff --git a/packages/g-plugin-webgpu-device/src/platform/RenderPass.ts b/packages/g-plugin-webgpu-device/src/platform/RenderPass.ts index b345641f1..ded9da5c8 100644 --- a/packages/g-plugin-webgpu-device/src/platform/RenderPass.ts +++ b/packages/g-plugin-webgpu-device/src/platform/RenderPass.ts @@ -4,7 +4,6 @@ import { RenderPass, RenderPassDescriptor, RenderPipeline, - TransparentWhite, } from '@antv/g-plugin-device-renderer'; import { assert, @@ -107,7 +106,6 @@ export class RenderPass_WebGPU implements RenderPass { dstAttachment.loadOp = 'load'; } else { dstAttachment.loadOp = 'clear'; - console.log(clearColor, TransparentWhite); dstAttachment.clearValue = clearColor; } dstAttachment.storeOp = descriptor.colorStore[i] ? 'store' : 'discard'; diff --git a/packages/g-plugin-webgpu-device/src/platform/Texture.ts b/packages/g-plugin-webgpu-device/src/platform/Texture.ts index 354033206..ca7641002 100644 --- a/packages/g-plugin-webgpu-device/src/platform/Texture.ts +++ b/packages/g-plugin-webgpu-device/src/platform/Texture.ts @@ -8,7 +8,7 @@ import { ResourceType } from '@antv/g-plugin-device-renderer'; import type { IDevice_WebGPU, TextureShared_WebGPU } from './interfaces'; import { ResourceBase_WebGPU } from './ResourceBase'; -// @see https://toji.github.io/webgpu-best-practices/img-textures.html +// @see https://toji.dev/webgpu-best-practices/img-textures export class Texture_WebGPU extends ResourceBase_WebGPU @@ -56,8 +56,38 @@ export class Texture_WebGPU ); } - setImageData(data: TexImageSource, level: number) { - // TODO: https://www.w3.org/TR/webgpu/#image-copies + setImageData(data: TexImageSource | ArrayBufferView[], level: number) { + // @see https://www.w3.org/TR/webgpu/#image-copies + // @see https://www.w3.org/TR/webgpu/#dom-gpuqueue-copyexternalimagetotexture + // const isArray = Array.isArray(data); + // if (!isArray) { + // // if (this.gpuTexture) { + // // this.gpuTexture.destroy(); + // // } + // const textureDescriptor: GPUTextureDescriptor = { + // // Unlike in WebGL, the size of our texture must be set at texture creation time. + // // This means we have to wait until the image is loaded to create the texture, since we won't + // // know the size until then. + // size: { width: data.width, height: data.height }, + // format: 'rgba8unorm', + // usage: + // GPUTextureUsage.TEXTURE_BINDING | + // GPUTextureUsage.COPY_DST | + // GPUTextureUsage.RENDER_ATTACHMENT, + // }; + // const texture = this.device.device.createTexture(textureDescriptor); + // this.gpuTexture = texture; + // this.gpuTextureView = texture.createView(); + // this.width = data.width; + // this.height = data.height; + // this.device.device.queue.copyExternalImageToTexture( + // { source: data }, + // { texture }, + // textureDescriptor.size, + // ); + // } else { + // // TODO: support ArrayBufferView[] + // } } destroy() { diff --git a/packages/g-plugin-webgpu-device/src/platform/interfaces.ts b/packages/g-plugin-webgpu-device/src/platform/interfaces.ts index e6a441af4..61c189f0e 100644 --- a/packages/g-plugin-webgpu-device/src/platform/interfaces.ts +++ b/packages/g-plugin-webgpu-device/src/platform/interfaces.ts @@ -9,7 +9,9 @@ import type { Device, BindingLayoutSamplerDescriptor, BindingLayoutDescriptor, + Buffer, } from '@antv/g-plugin-device-renderer'; +import { BufferDescriptor } from '@antv/g-plugin-device-renderer'; export interface TextureSharedDescriptor { dimension: TextureDimension; @@ -46,6 +48,7 @@ export interface IDevice_WebGPU extends Device { device: GPUDevice; getFallbackSampler: (samplerEntry: BindingLayoutSamplerDescriptor) => Sampler; getFallbackTexture: (samplerEntry: BindingLayoutSamplerDescriptor) => Texture; + createBuffer: (descriptor: BufferDescriptor) => Buffer; createTextureShared: ( descriptor: TextureSharedDescriptor, texture: TextureShared_WebGPU, diff --git a/packages/g-webgpu/src/index.ts b/packages/g-webgpu/src/index.ts index 63b557ee0..47dd5cd39 100644 --- a/packages/g-webgpu/src/index.ts +++ b/packages/g-webgpu/src/index.ts @@ -1,4 +1,4 @@ -import type { RendererConfig } from '@antv/g-lite'; +import { ClipSpaceNearZ, RendererConfig } from '@antv/g-lite'; import { AbstractRenderer } from '@antv/g-lite'; import * as DeviceRenderer from '@antv/g-plugin-device-renderer'; import * as DomInteraction from '@antv/g-plugin-dom-interaction'; @@ -15,6 +15,8 @@ interface WebGPURendererConfig extends RendererConfig { } export class Renderer extends AbstractRenderer { + clipSpaceNearZ = ClipSpaceNearZ.ZERO; + constructor(config?: Partial) { super(config); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e84efb239..99e5ec980 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -812,6 +812,9 @@ importers: '@antv/g-lite': specifier: workspace:* version: link:../g-lite + gl-matrix: + specifier: ^3.4.3 + version: 3.4.3 tslib: specifier: ^2.5.3 version: 2.5.3 @@ -1153,14 +1156,14 @@ importers: site: dependencies: '@antv/g-components': - specifier: ^1.9.0 + specifier: ^1.9.1 version: link:../packages/g-components - '@antv/g-plugin-dragndrop': - specifier: ^1.8.0 - version: link:../packages/g-plugin-dragndrop - '@antv/g-svg': - specifier: ^1.10.0 - version: link:../packages/g-svg + '@antv/g-mobile-webgl': + specifier: ^0.9.1 + version: link:../packages/g-mobile-webgl + '@antv/g-plugin-image-loader': + specifier: ^1.3.1 + version: link:../packages/g-plugin-image-loader '@antv/g6': specifier: ^4.5.2 version: 4.5.2 @@ -1549,12 +1552,12 @@ packages: tslib: 2.5.3 dev: false - /@antv/g-camera-api@1.0.40(@antv/g-lite@1.0.70): + /@antv/g-camera-api@1.0.40(@antv/g-lite@1.2.1): resolution: {integrity: sha512-GhhNdrPlT+Pw9RtBqMsBEQxrXhbR8nbva4WxJ381/o4gTdSzF+DBEt4uND3u5mv910HeC2iNbq+8itQhMFvlTw==} peerDependencies: '@antv/g-lite': ^1.0.0 dependencies: - '@antv/g-lite': 1.0.70 + '@antv/g-lite': 1.2.1 '@antv/util': 3.3.1(gl-matrix@3.4.3) gl-matrix: 3.4.3 dev: false @@ -1571,38 +1574,37 @@ packages: tslib: 2.5.3 dev: false - /@antv/g-css-layout-api@1.0.38(@antv/g-lite@1.0.70): + /@antv/g-css-layout-api@1.0.38(@antv/g-lite@1.2.1): resolution: {integrity: sha512-2KFNXOXVN20hVVFSyDiShLdFF1Bnc2whPDNQpfUgWlwlBTeUDx3Bd1tnNEuPg6MDQkV4luPE/1rEe8o6fOE3zg==} peerDependencies: '@antv/g-lite': ^1.0.0 dependencies: - '@antv/g-lite': 1.0.70 + '@antv/g-lite': 1.2.1 dev: false - /@antv/g-css-typed-om-api@1.0.38(@antv/g-lite@1.0.70): + /@antv/g-css-typed-om-api@1.0.38(@antv/g-lite@1.2.1): resolution: {integrity: sha512-eDLGxlzMyoJGdbORHeajC23JNXV3TjVInegFZdiZdYmS4jNBQzK/8Y7HKdlelfGTJZs4m19i5diHCSyQebNJoQ==} peerDependencies: '@antv/g-lite': ^1.0.0 dependencies: - '@antv/g-lite': 1.0.70 + '@antv/g-lite': 1.2.1 dev: false - /@antv/g-dom-mutation-observer-api@1.0.38(@antv/g-lite@1.0.70): + /@antv/g-dom-mutation-observer-api@1.0.38(@antv/g-lite@1.2.1): resolution: {integrity: sha512-RIuXxTh5cFZz6OWc0D3n0ExlCEqBO/s5EQmLRB7QQTCBjrhBTqvJT7AV8Bp6reeBkCLyZ8eBjwIjc2LX9iWFnw==} peerDependencies: '@antv/g-lite': ^1.0.0 dependencies: - '@antv/g-lite': 1.0.70 + '@antv/g-lite': 1.2.1 dev: false - /@antv/g-lite@1.0.70: - resolution: {integrity: sha512-/ACSlRJXzC84+szMMKeV9AbvuJclnSMCdSyghqMVzeuYr5YE6mtWwLk+dOWAHgX/F0nJCpjQkIvcMdXGqakLzw==} + /@antv/g-lite@1.2.1: + resolution: {integrity: sha512-NxSqvhK62fvm+r/SPM1CP0HdUl2mJarV6mM/l77paCgFaEMpU+1veWdF97N1cUQ8QFOmgaodr5aiZBz0rkn8ag==} dependencies: - '@antv/g-math': 1.7.49 + '@antv/g-math': 2.0.1 '@antv/util': 3.3.1(gl-matrix@3.4.3) - '@types/offscreencanvas': 2019.6.4 d3-color: 1.4.0 - eventemitter3: 4.0.7 + eventemitter3: 5.0.1 gl-matrix: 3.4.3 rbush: 3.0.1 tslib: 2.5.3 @@ -1615,36 +1617,33 @@ packages: gl-matrix: 3.4.3 dev: false - /@antv/g-math@1.7.49: - resolution: {integrity: sha512-6eVtmtkmPAjqQrg1TZ6MICtHmBUv2jCDbgRpHl3VmX48KPPOaBlbkZlhh0ZEAEMN1ex075W8kYr/+xDHnhCvKg==} + /@antv/g-math@2.0.1: + resolution: {integrity: sha512-Y1DREalYzUMaglD0m6V9s9UxsseXgSmwNA3l9zDHRH1CXDLcvtmrku+DQM9oCgPtbPWV43AdyAYoNT3WLyL/WA==} dependencies: + '@antv/util': 3.3.1(gl-matrix@3.4.3) gl-matrix: 3.4.3 tslib: 2.5.3 dev: false - /@antv/g-plugin-device-renderer@1.7.70(@antv/g-lite@packages+g-lite): - resolution: {integrity: sha512-S7SbGqo9G2z3voBuOBMfTaiNkjTcBWxpVjIyMJ/R3CMqXuLtXC2DMi0VGtte2iAfcFyF2V4S56Y/kAklii7I8A==} - peerDependencies: - '@antv/g-lite': ^1.0.0 + /@antv/g-plugin-device-renderer@1.9.1: + resolution: {integrity: sha512-Q+/6TKqZOPDkIragpIdzSVPfXEZ72SM0LzBT7K5Hu5ttDL6yFNGACKdhJjdbEhG32ycY6sI8qLLX5aVbrOehVg==} dependencies: - '@antv/g-lite': link:packages/g-lite - '@antv/g-plugin-image-loader': 1.1.54(@antv/g-lite@packages+g-lite)(gl-matrix@3.4.3) - '@antv/g-shader-components': 1.7.55 + '@antv/g-lite': 1.2.1 + '@antv/g-math': 2.0.1 + '@antv/g-plugin-image-loader': 1.3.1 + '@antv/g-shader-components': 1.8.1 '@antv/util': 3.3.1(gl-matrix@3.4.3) - '@types/offscreencanvas': 2019.6.4 '@webgpu/types': 0.1.33 earcut: 2.2.3 - eventemitter3: 4.0.7 + eventemitter3: 5.0.1 gl-matrix: 3.4.3 tslib: 2.5.3 dev: false - /@antv/g-plugin-dom-interaction@1.7.52(@antv/g-lite@packages+g-lite): - resolution: {integrity: sha512-ZJgzI2CCfqzORsF3LkZkcmpDXzQbZGMVGTnz5CT26/cuBxVARutNjDN/YaUvtdgfG71Rngc5aIHfhO8A1FX7gw==} - peerDependencies: - '@antv/g-lite': ^1.0.0 + /@antv/g-plugin-dom-interaction@1.9.1: + resolution: {integrity: sha512-wtXIeQwZFm6Ij0HL0B5ZZtbnI4WNMCu8mw5Zl0jlq3RRtyHP/PYYd+3R3QQ5bePpZbPr4qns0sD0EqD4hUDgTg==} dependencies: - '@antv/g-lite': link:packages/g-lite + '@antv/g-lite': 1.2.1 tslib: 2.5.3 dev: false @@ -1659,37 +1658,32 @@ packages: tslib: 2.5.3 dev: false - /@antv/g-plugin-html-renderer@1.7.56(@antv/g-lite@packages+g-lite): - resolution: {integrity: sha512-8EqM3KxHdHmXLhvDWEWSmoBMTkydLiJAgc5nHHXknpCJUQ5SpsATBftnqKi51jPWo8Pm933sQoWSF0tZG/zC1A==} - peerDependencies: - '@antv/g-lite': ^1.0.0 + /@antv/g-plugin-html-renderer@1.9.1: + resolution: {integrity: sha512-bk94rLrQ2wclVt2aghWytTr8Ur9a0ImMcf2V2vmoatjD1+/k+EtsF230RcoflVk9MGr4Cn0LqFXVIiPSmckYHw==} dependencies: - '@antv/g-lite': link:packages/g-lite + '@antv/g-lite': 1.2.1 '@antv/util': 3.3.1(gl-matrix@3.4.3) gl-matrix: 3.4.3 tslib: 2.5.3 dev: false - /@antv/g-plugin-image-loader@1.1.54(@antv/g-lite@packages+g-lite)(gl-matrix@3.4.3): - resolution: {integrity: sha512-3udyGozFpE4mjsLOxegikYNNfb0RpHmSbvrZj5psTX4UVFB3V2eopKoRF2JYa3kUjnRzLJ3sDh0przr2K01tvg==} - peerDependencies: - '@antv/g-lite': ^1.0.0 + /@antv/g-plugin-image-loader@1.3.1: + resolution: {integrity: sha512-IdrlWjN6vBWjoqSu58ZbeL3Ta8q+Eq+686dMa0yCMCRnVlmym/mcW2JzCCA+IUcaCM39UEiDmyinJs8Ic04X9A==} dependencies: - '@antv/g-lite': link:packages/g-lite + '@antv/g-lite': 1.2.1 '@antv/util': 3.3.1(gl-matrix@3.4.3) + gl-matrix: 3.4.3 tslib: 2.5.3 - transitivePeerDependencies: - - gl-matrix dev: false - /@antv/g-plugin-webgl-device@1.7.54(@antv/g-lite@packages+g-lite)(@antv/g-plugin-device-renderer@1.7.70)(gl-matrix@3.4.3): + /@antv/g-plugin-webgl-device@1.7.54(@antv/g-lite@packages+g-lite)(@antv/g-plugin-device-renderer@1.9.1)(gl-matrix@3.4.3): resolution: {integrity: sha512-1Bnf+eb5HcK7plBYSBAKQDc+KWW0VZ3paFv8rEfJCnp7nTt4kHH2j9wdjwHztft4eOaxdRH1hdV1Aom05sahqg==} peerDependencies: '@antv/g-lite': ^1.0.0 '@antv/g-plugin-device-renderer': ^1.0.0 dependencies: '@antv/g-lite': link:packages/g-lite - '@antv/g-plugin-device-renderer': 1.7.70(@antv/g-lite@packages+g-lite) + '@antv/g-plugin-device-renderer': 1.9.1 '@antv/util': 3.3.1(gl-matrix@3.4.3) eventemitter3: 4.0.7 tslib: 2.5.3 @@ -1697,8 +1691,8 @@ packages: - gl-matrix dev: false - /@antv/g-shader-components@1.7.55: - resolution: {integrity: sha512-EV7L6yKw/qnQa+xKZiRyGC7ec4OTkrpIhJRsP2A1SHI4LA6q5ptJpR8xEjkc0Hcv4r0MluY6ECV74GDQwQXgeA==} + /@antv/g-shader-components@1.8.1: + resolution: {integrity: sha512-HzJPafrwhK6Qhjt3LSCYNL/YQOblCsQuUVFDlNXgUSrM20GwJ4kVhMxGxZ1Obo5d05DJ3siiSevFUf+iVmSWLA==} dev: false /@antv/g-svg@0.5.7: @@ -1711,12 +1705,12 @@ packages: tslib: 2.5.3 dev: false - /@antv/g-web-animations-api@1.0.39(@antv/g-lite@1.0.70)(gl-matrix@3.4.3): + /@antv/g-web-animations-api@1.0.39(@antv/g-lite@1.2.1)(gl-matrix@3.4.3): resolution: {integrity: sha512-0QXVzjk8kKrVokxHLLphkJsMPvbhLgcQN8/eVUdPaj+A0Yf6Cpg/hquYaGBBuqzwoMVB0ROUsIvwXgRtoXQONA==} peerDependencies: '@antv/g-lite': ^1.0.0 dependencies: - '@antv/g-lite': 1.0.70 + '@antv/g-lite': 1.2.1 '@antv/util': 3.3.1(gl-matrix@3.4.3) transitivePeerDependencies: - gl-matrix @@ -1728,11 +1722,11 @@ packages: '@antv/g-lite': ^1.0.0 dependencies: '@antv/g-lite': link:packages/g-lite - '@antv/g-plugin-device-renderer': 1.7.70(@antv/g-lite@packages+g-lite) - '@antv/g-plugin-dom-interaction': 1.7.52(@antv/g-lite@packages+g-lite) - '@antv/g-plugin-html-renderer': 1.7.56(@antv/g-lite@packages+g-lite) - '@antv/g-plugin-image-loader': 1.1.54(@antv/g-lite@packages+g-lite)(gl-matrix@3.4.3) - '@antv/g-plugin-webgl-device': 1.7.54(@antv/g-lite@packages+g-lite)(@antv/g-plugin-device-renderer@1.7.70)(gl-matrix@3.4.3) + '@antv/g-plugin-device-renderer': 1.9.1 + '@antv/g-plugin-dom-interaction': 1.9.1 + '@antv/g-plugin-html-renderer': 1.9.1 + '@antv/g-plugin-image-loader': 1.3.1 + '@antv/g-plugin-webgl-device': 1.7.54(@antv/g-lite@packages+g-lite)(@antv/g-plugin-device-renderer@1.9.1)(gl-matrix@3.4.3) '@antv/util': 3.3.1(gl-matrix@3.4.3) transitivePeerDependencies: - gl-matrix @@ -1853,12 +1847,12 @@ packages: /@antv/g@5.16.33(gl-matrix@3.4.3): resolution: {integrity: sha512-11F82JsrXeJZTZSREiaPhnILkzoHqajkebA4fkPQ4XXjpoAcpIEow//NF8LbJOr3c1hogTyDh+aofwFeY+JnMw==} dependencies: - '@antv/g-camera-api': 1.0.40(@antv/g-lite@1.0.70) - '@antv/g-css-layout-api': 1.0.38(@antv/g-lite@1.0.70) - '@antv/g-css-typed-om-api': 1.0.38(@antv/g-lite@1.0.70) - '@antv/g-dom-mutation-observer-api': 1.0.38(@antv/g-lite@1.0.70) - '@antv/g-lite': 1.0.70 - '@antv/g-web-animations-api': 1.0.39(@antv/g-lite@1.0.70)(gl-matrix@3.4.3) + '@antv/g-camera-api': 1.0.40(@antv/g-lite@1.2.1) + '@antv/g-css-layout-api': 1.0.38(@antv/g-lite@1.2.1) + '@antv/g-css-typed-om-api': 1.0.38(@antv/g-lite@1.2.1) + '@antv/g-dom-mutation-observer-api': 1.0.38(@antv/g-lite@1.2.1) + '@antv/g-lite': 1.2.1 + '@antv/g-web-animations-api': 1.0.39(@antv/g-lite@1.2.1)(gl-matrix@3.4.3) transitivePeerDependencies: - gl-matrix dev: false diff --git a/site/examples/3d/3d-basic/demo/webgpu.js b/site/examples/3d/3d-basic/demo/webgpu.js index 10d42d9ad..4bbc30c94 100644 --- a/site/examples/3d/3d-basic/demo/webgpu.js +++ b/site/examples/3d/3d-basic/demo/webgpu.js @@ -1,4 +1,13 @@ -import { Canvas, CanvasEvent, Circle } from '@antv/g'; +import { + Canvas, + CanvasEvent, + Circle, + Ellipse, + Rect, + Image, + Line, + Path, +} from '@antv/g'; import { Renderer as WebGPURenderer } from '@antv/g-webgpu'; import Stats from 'stats.js'; @@ -18,28 +27,76 @@ const canvas = new Canvas({ const circle = new Circle({ style: { - x: 250, - y: 250, - r: 250, + cx: 100, + cy: 100, + r: 50, fill: 'green', cursor: 'pointer', }, }); -// const icon = new Image({ -// style: { -// x: 200, -// y: 200, -// z: 0, -// width: 200, -// height: 200, -// src: 'https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*N4ZMS7gHsUIAAAAAAAAAAABkARQnAQ', -// isBillboard: true, -// }, -// }); +const ellipse = new Ellipse({ + style: { + cx: 200, + cy: 100, + rx: 100, + ry: 50, + fill: 'red', + }, +}); + +const rect = new Rect({ + style: { + x: 300, + y: 100, + width: 100, + height: 50, + fill: 'blue', + stroke: 'yellow', + lineWidth: 2, + }, +}); + +const line = new Line({ + style: { + x1: 200, + y1: 100, + x2: 400, + y2: 100, + stroke: '#1890FF', + lineWidth: 2, + }, +}); + +const path = new Path({ + style: { + transform: 'translate(200, 100) scale(10)', + d: 'M2 4C0.8954304997175604 3.9999999991219815 -1.3527075029566811e-16 4.895430499717561 0 6C0 6 0 9.9375 0 12C1.3527075029566811e-16 13.10456950028244 0.8954304997175604 14.00000000087802 2 14C8 14 10.25 14 14 14C15.104569499040734 13.99999999912198 16 13.104569499040734 16 12C16 9 16 7.875 16 6C16 4.895430500959266 15.104569499040734 4.0000000008780185 14 4C13.414 4 13.194249999999998 4 12.828 4C12.297610373455704 3.9998867247945213 11.788985462367364 3.7890987493850155 11.414 3.414C11 3 10.84475 2.8447500000000003 10.586 2.5860000000000003C10.211014537632636 2.210901250614985 9.702389626544296 2.0001132752054787 9.172 2.0000000000000004C8 2.0000000000000004 7.560500000000001 2.0000000000000004 6.828000000000001 2.0000000000000004C6.297610373455706 2.0001132752054787 5.788985462367367 2.210901250614985 5.4140000000000015 2.5860000000000003C5.000000000000002 3 4.844750000000001 3.1552499999999997 4.586000000000001 3.414C4.211014537632636 3.7890987493850155 3.7023896265442966 3.9998867247945213 3.1720000000000015 4C2.5860000000000016 4 2.3662500000000017 4 2.0000000000000018 4C2.000000000000001 4 2.000000000000001 4 2 4M10.5 8.5C10.5 6.575499102701247 8.416666666666666 5.372686041889527 6.75 6.334936490538903C5.976497308103742 6.781518477924107 5.5 7.606836025229591 5.5 8.5C5.5 10.424500897298753 7.583333333333334 11.627313958110474 9.25 10.665063509461097C10.023502691896258 10.218481522075892 10.5 9.39316397477041 10.5 8.5C10.5 8.5 10.5 8.5 10.5 8.5M2.5 6C2.1150998205402494 6.000000000305956 1.874537208444147 5.583333333830511 2.0669872979090567 5.2500000003442C2.1563036954051213 5.095299461648009 2.321367204761929 4.999999999858005 2.5 5C2.8849001794597506 5.000000000305956 3.125462791688336 5.416666667163845 2.933012701693495 5.7500000003442C2.8436963042354777 5.904700538406512 2.6786327946700927 5.999999999858005 2.5 6C2.5 6 2.5 6 2.5 6M11.5 8.5C11.5 11.194301256218253 8.583333333333334 12.878239541354663 6.250000000000001 11.531088913245537C5.167096231345241 10.90587413090625 4.5 9.750429564678573 4.5 8.5C4.5 5.805698743781747 7.416666666666667 4.121760458645338 9.75 5.468911086754464C10.832903768654761 6.094125869093751 11.5 7.249570435321427 11.5 8.5C11.5 8.5 11.5 8.5 11.5 8.5', + lineWidth: 1, + lineJoin: 'round', + stroke: '#54BECC', + cursor: 'pointer', + }, +}); + +const image = new Image({ + style: { + x: 200, + y: 200, + z: 0, + width: 200, + height: 200, + src: 'https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*N4ZMS7gHsUIAAAAAAAAAAABkARQnAQ', + }, +}); canvas.addEventListener(CanvasEvent.READY, () => { canvas.appendChild(circle); + canvas.appendChild(ellipse); + canvas.appendChild(rect); + canvas.appendChild(line); + canvas.appendChild(path); + canvas.appendChild(image); }); // stats diff --git a/site/examples/animation/animation-basic/demo/current-time.js b/site/examples/animation/animation-basic/demo/current-time.js index 8d586c009..3dc105e60 100644 --- a/site/examples/animation/animation-basic/demo/current-time.js +++ b/site/examples/animation/animation-basic/demo/current-time.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/animation-basic/demo/delay.js b/site/examples/animation/animation-basic/demo/delay.js index 2cc764bd9..041ccfee3 100644 --- a/site/examples/animation/animation-basic/demo/delay.js +++ b/site/examples/animation/animation-basic/demo/delay.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/animation-basic/demo/easing.js b/site/examples/animation/animation-basic/demo/easing.js index 24a98ef2e..a9e3fb58e 100644 --- a/site/examples/animation/animation-basic/demo/easing.js +++ b/site/examples/animation/animation-basic/demo/easing.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/animation-basic/demo/lifecycle.js b/site/examples/animation/animation-basic/demo/lifecycle.js index a92e2838e..05bdb1fc1 100644 --- a/site/examples/animation/animation-basic/demo/lifecycle.js +++ b/site/examples/animation/animation-basic/demo/lifecycle.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/animation-basic/demo/multiple-attributes.js b/site/examples/animation/animation-basic/demo/multiple-attributes.js index e4c983b16..70312c1e1 100644 --- a/site/examples/animation/animation-basic/demo/multiple-attributes.js +++ b/site/examples/animation/animation-basic/demo/multiple-attributes.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/animation-basic/demo/onframe.js b/site/examples/animation/animation-basic/demo/onframe.js index bc0c3a8ee..5263abe49 100644 --- a/site/examples/animation/animation-basic/demo/onframe.js +++ b/site/examples/animation/animation-basic/demo/onframe.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/animation-basic/demo/opacity.js b/site/examples/animation/animation-basic/demo/opacity.js index 9d2f73d72..ccb6a23c6 100644 --- a/site/examples/animation/animation-basic/demo/opacity.js +++ b/site/examples/animation/animation-basic/demo/opacity.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/animation-basic/demo/sequence.js b/site/examples/animation/animation-basic/demo/sequence.js index d29983039..a7b65ca91 100644 --- a/site/examples/animation/animation-basic/demo/sequence.js +++ b/site/examples/animation/animation-basic/demo/sequence.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/animation-basic/demo/visibility.js b/site/examples/animation/animation-basic/demo/visibility.js index fdfbdde7b..4321d139d 100644 --- a/site/examples/animation/animation-basic/demo/visibility.js +++ b/site/examples/animation/animation-basic/demo/visibility.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/animation-effects/demo/animations.js b/site/examples/animation/animation-effects/demo/animations.js index 87e772ea4..951330413 100644 --- a/site/examples/animation/animation-effects/demo/animations.js +++ b/site/examples/animation/animation-effects/demo/animations.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/animation-effects/demo/line-dash.js b/site/examples/animation/animation-effects/demo/line-dash.js index c7f3d526a..8496b16af 100644 --- a/site/examples/animation/animation-effects/demo/line-dash.js +++ b/site/examples/animation/animation-effects/demo/line-dash.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/animation-effects/demo/marching-ants.js b/site/examples/animation/animation-effects/demo/marching-ants.js index b286806a8..fa7ddd879 100644 --- a/site/examples/animation/animation-effects/demo/marching-ants.js +++ b/site/examples/animation/animation-effects/demo/marching-ants.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/animation-effects/demo/multiple-animations-per-element.js b/site/examples/animation/animation-effects/demo/multiple-animations-per-element.js index 3f0639cb5..9eab3d18e 100644 --- a/site/examples/animation/animation-effects/demo/multiple-animations-per-element.js +++ b/site/examples/animation/animation-effects/demo/multiple-animations-per-element.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/animation-effects/demo/offset-path.js b/site/examples/animation/animation-effects/demo/offset-path.js index dc50fd198..483775ea3 100644 --- a/site/examples/animation/animation-effects/demo/offset-path.js +++ b/site/examples/animation/animation-effects/demo/offset-path.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/morph/demo/convert-to-path.js b/site/examples/animation/morph/demo/convert-to-path.js index 8890c1a91..aac9c1c6c 100644 --- a/site/examples/animation/morph/demo/convert-to-path.js +++ b/site/examples/animation/morph/demo/convert-to-path.js @@ -31,7 +31,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/morph/demo/issue.js b/site/examples/animation/morph/demo/issue.js index d1db28e93..c0581abb2 100644 --- a/site/examples/animation/morph/demo/issue.js +++ b/site/examples/animation/morph/demo/issue.js @@ -22,7 +22,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/animation/morph/demo/morph.js b/site/examples/animation/morph/demo/morph.js index 22b1a64a8..7424304b7 100644 --- a/site/examples/animation/morph/demo/morph.js +++ b/site/examples/animation/morph/demo/morph.js @@ -30,7 +30,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/camera/camera-action/demo/action.js b/site/examples/camera/camera-action/demo/action.js index dc62b01bd..b80f62678 100644 --- a/site/examples/camera/camera-action/demo/action.js +++ b/site/examples/camera/camera-action/demo/action.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/camera/camera-action/demo/zoom-by-point.js b/site/examples/camera/camera-action/demo/zoom-by-point.js index e2732cf9e..e8fe4a7e1 100644 --- a/site/examples/camera/camera-action/demo/zoom-by-point.js +++ b/site/examples/camera/camera-action/demo/zoom-by-point.js @@ -25,7 +25,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/camera/camera-animation/demo/landmark2.js b/site/examples/camera/camera-animation/demo/landmark2.js index 0d95cf182..85db899e3 100644 --- a/site/examples/camera/camera-animation/demo/landmark2.js +++ b/site/examples/camera/camera-animation/demo/landmark2.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/canvas/canvas-basic/demo/coordinates.js b/site/examples/canvas/canvas-basic/demo/coordinates.js index 13899b4f9..04a8c8435 100644 --- a/site/examples/canvas/canvas-basic/demo/coordinates.js +++ b/site/examples/canvas/canvas-basic/demo/coordinates.js @@ -22,7 +22,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/canvas/canvas-basic/demo/element-from-point.js b/site/examples/canvas/canvas-basic/demo/element-from-point.js index 5dff8248c..9898c70e7 100644 --- a/site/examples/canvas/canvas-basic/demo/element-from-point.js +++ b/site/examples/canvas/canvas-basic/demo/element-from-point.js @@ -29,7 +29,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/canvas/container/demo/supports-css-transform.js b/site/examples/canvas/container/demo/supports-css-transform.js index f868316c2..19c2a8a26 100644 --- a/site/examples/canvas/container/demo/supports-css-transform.js +++ b/site/examples/canvas/container/demo/supports-css-transform.js @@ -14,7 +14,9 @@ $wrapper.style.transform = 'scale(1.1)'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); diff --git a/site/examples/ecosystem/d3/demo/d3-annotation.js b/site/examples/ecosystem/d3/demo/d3-annotation.js index 9408cb602..319eb1b7b 100644 --- a/site/examples/ecosystem/d3/demo/d3-annotation.js +++ b/site/examples/ecosystem/d3/demo/d3-annotation.js @@ -33,7 +33,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const cssSelectPlugin = new PluginCSSSelect(); diff --git a/site/examples/ecosystem/d3/demo/d3-barchart.js b/site/examples/ecosystem/d3/demo/d3-barchart.js index ad0c011e8..f2b7094fb 100644 --- a/site/examples/ecosystem/d3/demo/d3-barchart.js +++ b/site/examples/ecosystem/d3/demo/d3-barchart.js @@ -20,7 +20,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/d3/demo/d3-force-directed-graph.js b/site/examples/ecosystem/d3/demo/d3-force-directed-graph.js index 0c71212cf..18a8a3caa 100644 --- a/site/examples/ecosystem/d3/demo/d3-force-directed-graph.js +++ b/site/examples/ecosystem/d3/demo/d3-force-directed-graph.js @@ -17,7 +17,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/d3/demo/d3-geo-polygon.js b/site/examples/ecosystem/d3/demo/d3-geo-polygon.js index d5038aa51..d74e13545 100644 --- a/site/examples/ecosystem/d3/demo/d3-geo-polygon.js +++ b/site/examples/ecosystem/d3/demo/d3-geo-polygon.js @@ -49,7 +49,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); - const webgpuRenderer = new WebGPURenderer(); + const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', + }); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/d3/demo/d3-geo.js b/site/examples/ecosystem/d3/demo/d3-geo.js index 8573fbaa7..f5e1e8869 100644 --- a/site/examples/ecosystem/d3/demo/d3-geo.js +++ b/site/examples/ecosystem/d3/demo/d3-geo.js @@ -145,7 +145,9 @@ function zoom( canvasRenderer.registerPlugin(new PluginRoughCanvasRenderer()); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); - const webgpuRenderer = new WebGPURenderer(); + const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', + }); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/d3/demo/d3-linechart.js b/site/examples/ecosystem/d3/demo/d3-linechart.js index fa55e1694..86637b012 100644 --- a/site/examples/ecosystem/d3/demo/d3-linechart.js +++ b/site/examples/ecosystem/d3/demo/d3-linechart.js @@ -20,7 +20,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/d3/demo/d3-piechart.js b/site/examples/ecosystem/d3/demo/d3-piechart.js index 65664d7b3..562fd22e0 100644 --- a/site/examples/ecosystem/d3/demo/d3-piechart.js +++ b/site/examples/ecosystem/d3/demo/d3-piechart.js @@ -20,7 +20,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/d3/demo/d3-scatterplot.js b/site/examples/ecosystem/d3/demo/d3-scatterplot.js index bca2668d6..40af40519 100644 --- a/site/examples/ecosystem/d3/demo/d3-scatterplot.js +++ b/site/examples/ecosystem/d3/demo/d3-scatterplot.js @@ -20,7 +20,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/image-exporter/demo/image-exporter.js b/site/examples/ecosystem/image-exporter/demo/image-exporter.js index eb8340e78..33e43b7b3 100644 --- a/site/examples/ecosystem/image-exporter/demo/image-exporter.js +++ b/site/examples/ecosystem/image-exporter/demo/image-exporter.js @@ -23,7 +23,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/lite/demo/lite.js b/site/examples/ecosystem/lite/demo/lite.js index a3763a6f2..24fe7429d 100644 --- a/site/examples/ecosystem/lite/demo/lite.js +++ b/site/examples/ecosystem/lite/demo/lite.js @@ -20,7 +20,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/lottie/demo/ant.js b/site/examples/ecosystem/lottie/demo/ant.js index a3bcae28a..f64c2700b 100644 --- a/site/examples/ecosystem/lottie/demo/ant.js +++ b/site/examples/ecosystem/lottie/demo/ant.js @@ -17,7 +17,9 @@ import * as d3 from 'd3'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/lottie/demo/arrow.js b/site/examples/ecosystem/lottie/demo/arrow.js index f600b73af..ed2340320 100644 --- a/site/examples/ecosystem/lottie/demo/arrow.js +++ b/site/examples/ecosystem/lottie/demo/arrow.js @@ -17,7 +17,9 @@ import * as d3 from 'd3'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/lottie/demo/lottie-player-assets.js b/site/examples/ecosystem/lottie/demo/lottie-player-assets.js index aed451238..ae605854f 100644 --- a/site/examples/ecosystem/lottie/demo/lottie-player-assets.js +++ b/site/examples/ecosystem/lottie/demo/lottie-player-assets.js @@ -17,7 +17,9 @@ import * as d3 from 'd3'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/lottie/demo/lottie-player-basic-shapes.js b/site/examples/ecosystem/lottie/demo/lottie-player-basic-shapes.js index 3064819b9..9b77923c6 100644 --- a/site/examples/ecosystem/lottie/demo/lottie-player-basic-shapes.js +++ b/site/examples/ecosystem/lottie/demo/lottie-player-basic-shapes.js @@ -16,7 +16,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/lottie/demo/lottie-player-transform.js b/site/examples/ecosystem/lottie/demo/lottie-player-transform.js index ab337cdb6..24c624740 100644 --- a/site/examples/ecosystem/lottie/demo/lottie-player-transform.js +++ b/site/examples/ecosystem/lottie/demo/lottie-player-transform.js @@ -17,7 +17,9 @@ import * as d3 from 'd3'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/lottie/demo/radar.js b/site/examples/ecosystem/lottie/demo/radar.js index f75091549..d0be6ea19 100644 --- a/site/examples/ecosystem/lottie/demo/radar.js +++ b/site/examples/ecosystem/lottie/demo/radar.js @@ -17,7 +17,9 @@ import * as d3 from 'd3'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/lottie/demo/spring.js b/site/examples/ecosystem/lottie/demo/spring.js index d75158e22..c671f01b0 100644 --- a/site/examples/ecosystem/lottie/demo/spring.js +++ b/site/examples/ecosystem/lottie/demo/spring.js @@ -17,7 +17,9 @@ import * as d3 from 'd3'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/lottie/demo/use-animations.js b/site/examples/ecosystem/lottie/demo/use-animations.js index 0db77867e..36ea4d672 100644 --- a/site/examples/ecosystem/lottie/demo/use-animations.js +++ b/site/examples/ecosystem/lottie/demo/use-animations.js @@ -17,7 +17,9 @@ import * as d3 from 'd3'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/ecosystem/observable-plot/demo/dot.js b/site/examples/ecosystem/observable-plot/demo/dot.js index efb60dc98..d51e6a9d3 100644 --- a/site/examples/ecosystem/observable-plot/demo/dot.js +++ b/site/examples/ecosystem/observable-plot/demo/dot.js @@ -12,7 +12,9 @@ import * as Plot from '@observablehq/plot'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/event/dragndrop/demo/drag.js b/site/examples/event/dragndrop/demo/drag.js index acbc0f63a..303ff3d60 100644 --- a/site/examples/event/dragndrop/demo/drag.js +++ b/site/examples/event/dragndrop/demo/drag.js @@ -25,7 +25,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/event/dragndrop/demo/interact.js b/site/examples/event/dragndrop/demo/interact.js index 9f4275e3c..81addeded 100644 --- a/site/examples/event/dragndrop/demo/interact.js +++ b/site/examples/event/dragndrop/demo/interact.js @@ -27,7 +27,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // register css select plugin canvasRenderer.registerPlugin(new Plugin()); diff --git a/site/examples/event/event-others/demo/builtin.js b/site/examples/event/event-others/demo/builtin.js index 7d6fcb81e..f1cb8147b 100644 --- a/site/examples/event/event-others/demo/builtin.js +++ b/site/examples/event/event-others/demo/builtin.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/event/event-others/demo/custom.js b/site/examples/event/event-others/demo/custom.js index 757437d01..aa6aa11e3 100644 --- a/site/examples/event/event-others/demo/custom.js +++ b/site/examples/event/event-others/demo/custom.js @@ -23,7 +23,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/event/event-others/demo/delegate.js b/site/examples/event/event-others/demo/delegate.js index c51dfa435..916f7e7b8 100644 --- a/site/examples/event/event-others/demo/delegate.js +++ b/site/examples/event/event-others/demo/delegate.js @@ -28,7 +28,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/event/event-others/demo/deprecated-delegate.js b/site/examples/event/event-others/demo/deprecated-delegate.js index 9768616c6..896d83a11 100644 --- a/site/examples/event/event-others/demo/deprecated-delegate.js +++ b/site/examples/event/event-others/demo/deprecated-delegate.js @@ -28,7 +28,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/event/event-others/demo/mutation-observer.js b/site/examples/event/event-others/demo/mutation-observer.js index 95d7a19c5..bde2d94b9 100644 --- a/site/examples/event/event-others/demo/mutation-observer.js +++ b/site/examples/event/event-others/demo/mutation-observer.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/event/event-others/demo/touch.js b/site/examples/event/event-others/demo/touch.js index 71022fd0d..5865dd092 100644 --- a/site/examples/event/event-others/demo/touch.js +++ b/site/examples/event/event-others/demo/touch.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/event/gesture/demo/hammer.js b/site/examples/event/gesture/demo/hammer.js index bde5834c5..45ed8ec85 100644 --- a/site/examples/event/gesture/demo/hammer.js +++ b/site/examples/event/gesture/demo/hammer.js @@ -21,7 +21,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/event/picking/demo/circle.js b/site/examples/event/picking/demo/circle.js index 8568d84b7..f9af48356 100644 --- a/site/examples/event/picking/demo/circle.js +++ b/site/examples/event/picking/demo/circle.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/event/picking/demo/shapes.js b/site/examples/event/picking/demo/shapes.js index c109cce84..a6ca27fd2 100644 --- a/site/examples/event/picking/demo/shapes.js +++ b/site/examples/event/picking/demo/shapes.js @@ -23,7 +23,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/gpgpu/basic-algorithm/demo/add-2-vectors-webgl.js b/site/examples/gpgpu/basic-algorithm/demo/add-2-vectors-webgl.js deleted file mode 100644 index 96b41ba0e..000000000 --- a/site/examples/gpgpu/basic-algorithm/demo/add-2-vectors-webgl.js +++ /dev/null @@ -1,90 +0,0 @@ -import { Canvas, CanvasEvent } from '@antv/g'; -import { Kernel, Plugin } from '@antv/g-plugin-gpgpu'; -import { DeviceRenderer, Renderer } from '@antv/g-webgl'; - -const { BufferUsage } = DeviceRenderer; - -const CANVAS_SIZE = 1; -const $canvas = document.createElement('canvas'); - -// use WebGPU -const renderer = new Renderer(); -renderer.registerPlugin(new Plugin()); - -// create a canvas -const canvas = new Canvas({ - canvas: $canvas, - width: CANVAS_SIZE, - height: CANVAS_SIZE, - renderer, -}); - -canvas.addEventListener(CanvasEvent.READY, () => { - const plugin = renderer.getPlugin('device-renderer'); - const device = plugin.getDevice(); - - const kernel = new Kernel(device, { - bundle: { - shaders: { - WGSL: '', - GLSL450: - '\n\n\nbool gWebGPUDebug = false;\nvec4 gWebGPUDebugOutput = vec4(0.0);\n\nivec3 globalInvocationID = ivec3(gl_GlobalInvocationID);\nivec3 workGroupSize = ivec3(gl_WorkGroupSize);\nivec3 workGroupID = ivec3(gl_WorkGroupID);\nivec3 localInvocationID = ivec3(gl_LocalInvocationID);\nivec3 numWorkGroups = ivec3(gl_NumWorkGroups);\nint localInvocationIndex = int(gl_LocalInvocationIndex);\n\n\nlayout(std430, set = 0, binding = 0) buffer GWebGPUBuffer0 {\n float vectorA[];\n} gWebGPUBuffer0;\n\nlayout(std430, set = 0, binding = 1) buffer readonly GWebGPUBuffer1 {\n float vectorB[];\n} gWebGPUBuffer1;\n\n\n\nlayout (\n local_size_x = 8,\n local_size_y = 1,\n local_size_z = 1\n) in;\n\n\nfloat sum(float a, float b) {return a + b;}\nvoid main() {float a = gWebGPUBuffer0.vectorA[globalInvocationID.x];\nfloat b = gWebGPUBuffer1.vectorB[globalInvocationID.x];\ngWebGPUBuffer0.vectorA[globalInvocationID.x] = sum(a, b);}\n', - GLSL100: - '#ifdef GL_FRAGMENT_PRECISION_HIGH\n precision highp float;\n#else\n precision mediump float;\n#endif\n\n\nfloat epsilon = 0.00001;\nvec2 addrTranslation_1Dto2D(float address1D, vec2 texSize) {\n vec2 conv_const = vec2(1.0 / texSize.x, 1.0 / (texSize.x * texSize.y));\n vec2 normAddr2D = float(address1D) * conv_const;\n return vec2(fract(normAddr2D.x + epsilon), normAddr2D.y);\n}\n\nvoid barrier() {}\n \n\nuniform vec2 u_OutputTextureSize;\nuniform int u_OutputTexelCount;\nvarying vec2 v_TexCoord;\n\nbool gWebGPUDebug = false;\nvec4 gWebGPUDebugOutput = vec4(0.0);\n\n\nuniform sampler2D vectorA;\nuniform vec2 vectorASize;\nfloat getDatavectorA(vec2 address2D) {\n return float(texture2D(vectorA, address2D).r);\n}\nfloat getDatavectorA(float address1D) {\n return getDatavectorA(addrTranslation_1Dto2D(address1D, vectorASize));\n}\nfloat getDatavectorA(int address1D) {\n return getDatavectorA(float(address1D));\n}\nuniform sampler2D vectorB;\nuniform vec2 vectorBSize;\nfloat getDatavectorB(vec2 address2D) {\n return float(texture2D(vectorB, address2D).r);\n}\nfloat getDatavectorB(float address1D) {\n return getDatavectorB(addrTranslation_1Dto2D(address1D, vectorBSize));\n}\nfloat getDatavectorB(int address1D) {\n return getDatavectorB(float(address1D));\n}\nfloat sum(float a, float b) {\nivec3 workGroupSize = ivec3(1, 1, 1);\nivec3 numWorkGroups = ivec3(1, 1, 1); \nint globalInvocationIndex = int(floor(v_TexCoord.x * u_OutputTextureSize.x))\n + int(floor(v_TexCoord.y * u_OutputTextureSize.y)) * int(u_OutputTextureSize.x);\nint workGroupIDLength = globalInvocationIndex / (workGroupSize.x * workGroupSize.y * workGroupSize.z);\nivec3 workGroupID = ivec3(workGroupIDLength / numWorkGroups.y / numWorkGroups.z, workGroupIDLength / numWorkGroups.x / numWorkGroups.z, workGroupIDLength / numWorkGroups.x / numWorkGroups.y);\nint localInvocationIDZ = globalInvocationIndex / (workGroupSize.x * workGroupSize.y);\nint localInvocationIDY = (globalInvocationIndex - localInvocationIDZ * workGroupSize.x * workGroupSize.y) / workGroupSize.x;\nint localInvocationIDX = globalInvocationIndex - localInvocationIDZ * workGroupSize.x * workGroupSize.y - localInvocationIDY * workGroupSize.x;\nivec3 localInvocationID = ivec3(localInvocationIDX, localInvocationIDY, localInvocationIDZ);\nivec3 globalInvocationID = workGroupID * workGroupSize + localInvocationID;\nint localInvocationIndex = localInvocationID.z * workGroupSize.x * workGroupSize.y\n + localInvocationID.y * workGroupSize.x + localInvocationID.x;\nreturn a + b;}\nvoid main() {\nivec3 workGroupSize = ivec3(1, 1, 1);\nivec3 numWorkGroups = ivec3(1, 1, 1); \nint globalInvocationIndex = int(floor(v_TexCoord.x * u_OutputTextureSize.x))\n + int(floor(v_TexCoord.y * u_OutputTextureSize.y)) * int(u_OutputTextureSize.x);\nint workGroupIDLength = globalInvocationIndex / (workGroupSize.x * workGroupSize.y * workGroupSize.z);\nivec3 workGroupID = ivec3(workGroupIDLength / numWorkGroups.y / numWorkGroups.z, workGroupIDLength / numWorkGroups.x / numWorkGroups.z, workGroupIDLength / numWorkGroups.x / numWorkGroups.y);\nint localInvocationIDZ = globalInvocationIndex / (workGroupSize.x * workGroupSize.y);\nint localInvocationIDY = (globalInvocationIndex - localInvocationIDZ * workGroupSize.x * workGroupSize.y) / workGroupSize.x;\nint localInvocationIDX = globalInvocationIndex - localInvocationIDZ * workGroupSize.x * workGroupSize.y - localInvocationIDY * workGroupSize.x;\nivec3 localInvocationID = ivec3(localInvocationIDX, localInvocationIDY, localInvocationIDZ);\nivec3 globalInvocationID = workGroupID * workGroupSize + localInvocationID;\nint localInvocationIndex = localInvocationID.z * workGroupSize.x * workGroupSize.y\n + localInvocationID.y * workGroupSize.x + localInvocationID.x;\nfloat a = getDatavectorA(globalInvocationID.x);\nfloat b = getDatavectorB(globalInvocationID.x);\ngl_FragColor = vec4(sum(a, b));if (gWebGPUDebug) {\n gl_FragColor = gWebGPUDebugOutput;\n}}\n', - }, - context: { - name: '', - dispatch: [1, 1, 1], - threadGroupSize: [1, 1, 1], - maxIteration: 1, - defines: [], - uniforms: [ - { - name: 'vectorA', - type: 'Float[]', - storageClass: 'StorageBuffer', - readonly: false, - writeonly: false, - size: [1, 1], - }, - { - name: 'vectorB', - type: 'Float[]', - storageClass: 'StorageBuffer', - readonly: true, - writeonly: false, - size: [1, 1], - }, - ], - globalDeclarations: [], - output: { - name: 'vectorA', - size: [1, 1], - length: 1, - }, - needPingpong: true, - }, - }, - }); - - const inputBuffer = device.createBuffer({ - usage: BufferUsage.STORAGE | BufferUsage.COPY_SRC, - viewOrSize: new Int32Array([1, 2, 3, 4]), - }); - const outputBuffer = device.createBuffer({ - usage: BufferUsage.STORAGE | BufferUsage.COPY_SRC, - viewOrSize: new Int32Array([1, 2, 3, 4]), - }); - const readback = device.createReadback(); - - kernel.setBinding(0, inputBuffer); - kernel.setBinding(1, outputBuffer); - - kernel.dispatch(1, 1); - - (async () => { - const output = await readback.readBuffer(outputBuffer); - - console.log(output); - })(); -}); diff --git a/site/examples/gpgpu/basic-algorithm/demo/meta.json b/site/examples/gpgpu/basic-algorithm/demo/meta.json index b8aad8b88..5cc4645bd 100644 --- a/site/examples/gpgpu/basic-algorithm/demo/meta.json +++ b/site/examples/gpgpu/basic-algorithm/demo/meta.json @@ -11,13 +11,6 @@ "en": "Add 2 vectors" } }, - { - "filename": "add-2-vectors-webgl.js", - "title": { - "zh": "向量相加 WebGL", - "en": "Add 2 vectors" - } - }, { "filename": "matrix-multiplication.js", "title": { diff --git a/site/examples/perf/basic/demo/canvas-dirty-rectangle.js b/site/examples/perf/basic/demo/canvas-dirty-rectangle.js index 18ed5c41f..3e831f534 100644 --- a/site/examples/perf/basic/demo/canvas-dirty-rectangle.js +++ b/site/examples/perf/basic/demo/canvas-dirty-rectangle.js @@ -22,7 +22,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/perf/basic/demo/culling.js b/site/examples/perf/basic/demo/culling.js index 349e4b06a..46194b098 100644 --- a/site/examples/perf/basic/demo/culling.js +++ b/site/examples/perf/basic/demo/culling.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/perf/basic/demo/disable-css.js b/site/examples/perf/basic/demo/disable-css.js index 5cb90c63f..3a75546f2 100644 --- a/site/examples/perf/basic/demo/disable-css.js +++ b/site/examples/perf/basic/demo/disable-css.js @@ -34,7 +34,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/perf/basic/demo/images.js b/site/examples/perf/basic/demo/images.js index deff5795f..5f345800e 100644 --- a/site/examples/perf/basic/demo/images.js +++ b/site/examples/perf/basic/demo/images.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/perf/basic/demo/meta.json b/site/examples/perf/basic/demo/meta.json index 99c9dcf2b..46982279c 100644 --- a/site/examples/perf/basic/demo/meta.json +++ b/site/examples/perf/basic/demo/meta.json @@ -14,6 +14,13 @@ "en": "Render Circle & Path with g-webgl" } }, + { + "filename": "webgl-one-command-path.js", + "title": { + "zh": "g-webgl 渲染包含一条命令的 Path", + "en": "Render One-command Path with g-webgl" + } + }, { "filename": "vs-g4.0.js", "title": { diff --git a/site/examples/perf/basic/demo/nodes-5w.js b/site/examples/perf/basic/demo/nodes-5w.js index d6041cc97..49d9b155e 100644 --- a/site/examples/perf/basic/demo/nodes-5w.js +++ b/site/examples/perf/basic/demo/nodes-5w.js @@ -23,7 +23,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/perf/basic/demo/nodes-8k.js b/site/examples/perf/basic/demo/nodes-8k.js index 1fc643a9b..1d5489222 100644 --- a/site/examples/perf/basic/demo/nodes-8k.js +++ b/site/examples/perf/basic/demo/nodes-8k.js @@ -27,7 +27,9 @@ const svgRenderer = new SVGRenderer({ enableCulling: true, }); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/perf/basic/demo/rects.js b/site/examples/perf/basic/demo/rects.js index 8256d9e5e..1a37786b0 100644 --- a/site/examples/perf/basic/demo/rects.js +++ b/site/examples/perf/basic/demo/rects.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/perf/basic/demo/texts.js b/site/examples/perf/basic/demo/texts.js index d07ad3520..c9877dd50 100644 --- a/site/examples/perf/basic/demo/texts.js +++ b/site/examples/perf/basic/demo/texts.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/perf/basic/demo/vs-g4.0.js b/site/examples/perf/basic/demo/vs-g4.0.js index 20c6e9bb6..5e166a3c3 100644 --- a/site/examples/perf/basic/demo/vs-g4.0.js +++ b/site/examples/perf/basic/demo/vs-g4.0.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/perf/basic/demo/webgl-one-command-path.js b/site/examples/perf/basic/demo/webgl-one-command-path.js new file mode 100644 index 000000000..8b39f030d --- /dev/null +++ b/site/examples/perf/basic/demo/webgl-one-command-path.js @@ -0,0 +1,82 @@ +import { Canvas, CanvasEvent, Path } from '@antv/g'; +import { Renderer as WebGLRenderer } from '@antv/g-webgl'; +import * as lil from 'lil-gui'; +import Stats from 'stats.js'; + +// create a renderer +const webglRenderer = new WebGLRenderer(); + +// create a canvas +const canvas = new Canvas({ + container: 'container', + width: 600, + height: 500, + renderer: webglRenderer, +}); + +const path = new Path({ + style: { + lineWidth: 1, + stroke: '#54BECC', + path: 'M 0,40 C 5.5555555555555545,40,22.222222222222218,44.44444444444445,33.33333333333333,40', + }, +}); +path.translate(100, 100); +canvas.appendChild(path); + +const path2 = new Path({ + style: { + lineWidth: 1, + stroke: '#54BECC', + path: 'M 0,40 C 5.5555555555555545,40,22.222222222222218,44.44444444444445,33.33333333333333,40', + }, +}); +path2.translate(200, 200); +canvas.appendChild(path2); + +const path3 = new Path({ + style: { + lineWidth: 1, + stroke: '#54BECC', + path: 'M 0,40 C 5.5555555555555545,40,22.222222222222218,44.44444444444445,33.33333333333333,40', + }, +}); +path3.translate(100, 200); +canvas.appendChild(path3); + +const path4 = new Path({ + style: { + lineWidth: 1, + stroke: '#54BECC', + path: 'M 0,40 C 5.5555555555555545,40,22.222222222222218,44.44444444444445,33.33333333333333,40', + }, +}); +path4.translate(200, 100); +canvas.appendChild(path4); + +// stats +const stats = new Stats(); +stats.showPanel(0); +const $stats = stats.dom; +$stats.style.position = 'absolute'; +$stats.style.left = '0px'; +$stats.style.top = '0px'; +const $wrapper = document.getElementById('container'); +$wrapper.appendChild($stats); + +// GUI +const gui = new lil.GUI({ autoPlace: false }); +$wrapper.appendChild(gui.domElement); + +const transformFolder = gui.addFolder('style'); +const transformConfig = { + lineWidth: 1, +}; +transformFolder + .add(transformConfig, 'lineWidth', 0, 20) + .onChange((lineWidth) => { + path.style.lineWidth = lineWidth; + path2.style.lineWidth = lineWidth; + path3.style.lineWidth = lineWidth; + path4.style.lineWidth = lineWidth; + }); diff --git a/site/examples/plugins/a11y/demo/a11y-keyboard-navigation.js b/site/examples/plugins/a11y/demo/a11y-keyboard-navigation.js index bc224433d..eda107199 100644 --- a/site/examples/plugins/a11y/demo/a11y-keyboard-navigation.js +++ b/site/examples/plugins/a11y/demo/a11y-keyboard-navigation.js @@ -21,7 +21,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/plugins/a11y/demo/a11y-text-extractor.js b/site/examples/plugins/a11y/demo/a11y-text-extractor.js index aeb67a9a9..c990263b5 100644 --- a/site/examples/plugins/a11y/demo/a11y-text-extractor.js +++ b/site/examples/plugins/a11y/demo/a11y-text-extractor.js @@ -21,7 +21,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/plugins/annotation/demo/annotation.js b/site/examples/plugins/annotation/demo/annotation.js index e092c976c..6bbd66bdc 100644 --- a/site/examples/plugins/annotation/demo/annotation.js +++ b/site/examples/plugins/annotation/demo/annotation.js @@ -23,7 +23,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/plugins/annotation/demo/selectable-image.js b/site/examples/plugins/annotation/demo/selectable-image.js index b3f6ec6f8..2bf1cb7fb 100644 --- a/site/examples/plugins/annotation/demo/selectable-image.js +++ b/site/examples/plugins/annotation/demo/selectable-image.js @@ -13,7 +13,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/plugins/physics-engine/demo/physx.js b/site/examples/plugins/physics-engine/demo/physx.js index 16a5fdaad..a4f2f5a8d 100644 --- a/site/examples/plugins/physics-engine/demo/physx.js +++ b/site/examples/plugins/physics-engine/demo/physx.js @@ -25,6 +25,10 @@ const canvas = new Canvas({ renderer, }); +// adjust camera's position +const camera = canvas.getCamera(); +camera.setPerspective(0.1, 5000, 45, 600 / 500); + (async () => { await canvas.ready; const plugin = renderer.getPlugin('device-renderer'); @@ -34,11 +38,13 @@ const canvas = new Canvas({ ); const planeGeometry = new CubeGeometry(device, { - width: 200, - height: 200, - depth: 200, + width: 500, + height: 20, + depth: 500, + }); + const planeMaterial = new MeshBasicMaterial(device, { + wireframe: true, }); - const planeMaterial = new MeshBasicMaterial(device); const plane = new Mesh({ style: { fill: '#1890FF', @@ -47,16 +53,26 @@ const canvas = new Canvas({ rigid: 'static', }, }); + plane.setPosition(300, 400, 0); canvas.appendChild(plane); - plane.setPosition(300, 250, 0); + + const plane2 = new Mesh({ + style: { + fill: '#1890FF', + geometry: planeGeometry, + material: planeMaterial, + rigid: 'static', + }, + }); + plane2.setPosition(300, 100, 0); + canvas.appendChild(plane2); const cubeGeometry = new CubeGeometry(device, { - width: 200, - height: 200, - depth: 200, + width: 100, + height: 100, + depth: 100, }); const basicMaterial = new MeshBasicMaterial(device, { - // wireframe: true, map, }); @@ -68,9 +84,7 @@ const canvas = new Canvas({ rigid: 'dynamic', }, }); - - cube.setPosition(300, 250, 0); - + cube.setPosition(300, -50, 0); canvas.appendChild(cube); // stats diff --git a/site/examples/plugins/yoga/demo/yoga-container.js b/site/examples/plugins/yoga/demo/yoga-container.js index 0a94e64f0..d3026be2a 100644 --- a/site/examples/plugins/yoga/demo/yoga-container.js +++ b/site/examples/plugins/yoga/demo/yoga-container.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const plugin = new PluginYoga(); diff --git a/site/examples/scenegraph/basic/demo/boxmodel.js b/site/examples/scenegraph/basic/demo/boxmodel.js index 30185075d..1eba040dc 100644 --- a/site/examples/scenegraph/basic/demo/boxmodel.js +++ b/site/examples/scenegraph/basic/demo/boxmodel.js @@ -30,7 +30,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/scenegraph/basic/demo/change-z-index.js b/site/examples/scenegraph/basic/demo/change-z-index.js index bd57c9188..91a7db8f3 100644 --- a/site/examples/scenegraph/basic/demo/change-z-index.js +++ b/site/examples/scenegraph/basic/demo/change-z-index.js @@ -11,7 +11,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/scenegraph/basic/demo/hierarchy.js b/site/examples/scenegraph/basic/demo/hierarchy.js index 7325360ec..30d5d2899 100644 --- a/site/examples/scenegraph/basic/demo/hierarchy.js +++ b/site/examples/scenegraph/basic/demo/hierarchy.js @@ -34,7 +34,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/scenegraph/basic/demo/origin.js b/site/examples/scenegraph/basic/demo/origin.js index 4f5a548bb..8e9b7894e 100644 --- a/site/examples/scenegraph/basic/demo/origin.js +++ b/site/examples/scenegraph/basic/demo/origin.js @@ -28,7 +28,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/scenegraph/basic/demo/transform.js b/site/examples/scenegraph/basic/demo/transform.js index 002781920..3536f7b4b 100644 --- a/site/examples/scenegraph/basic/demo/transform.js +++ b/site/examples/scenegraph/basic/demo/transform.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/scenegraph/basic/demo/visibility.js b/site/examples/scenegraph/basic/demo/visibility.js index 252449913..e3660d52c 100644 --- a/site/examples/scenegraph/basic/demo/visibility.js +++ b/site/examples/scenegraph/basic/demo/visibility.js @@ -34,7 +34,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/scenegraph/basic/demo/z-index.js b/site/examples/scenegraph/basic/demo/z-index.js index d875bd905..679ae3d00 100644 --- a/site/examples/scenegraph/basic/demo/z-index.js +++ b/site/examples/scenegraph/basic/demo/z-index.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/circle/demo/circle.js b/site/examples/shape/circle/demo/circle.js index ee7326bc6..aa9998c2a 100644 --- a/site/examples/shape/circle/demo/circle.js +++ b/site/examples/shape/circle/demo/circle.js @@ -11,7 +11,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/shape/circle/demo/filter.js b/site/examples/shape/circle/demo/filter.js index 926e29e5d..cc7b47160 100644 --- a/site/examples/shape/circle/demo/filter.js +++ b/site/examples/shape/circle/demo/filter.js @@ -22,7 +22,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/circle/demo/gradient.js b/site/examples/shape/circle/demo/gradient.js index e2d725152..15678a83d 100644 --- a/site/examples/shape/circle/demo/gradient.js +++ b/site/examples/shape/circle/demo/gradient.js @@ -29,7 +29,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/custom-element/demo/arrow.js b/site/examples/shape/custom-element/demo/arrow.js index ee36492ab..fbbfd077b 100644 --- a/site/examples/shape/custom-element/demo/arrow.js +++ b/site/examples/shape/custom-element/demo/arrow.js @@ -25,7 +25,9 @@ const svgRenderer = new SVGRenderer(); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); canvasRenderer.registerPlugin(new Plugin()); diff --git a/site/examples/shape/custom-element/demo/custom-element.js b/site/examples/shape/custom-element/demo/custom-element.js index 43325e312..4903a98c6 100644 --- a/site/examples/shape/custom-element/demo/custom-element.js +++ b/site/examples/shape/custom-element/demo/custom-element.js @@ -17,7 +17,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/ellipse/demo/ellipse.js b/site/examples/shape/ellipse/demo/ellipse.js index 447393ff4..2d0b98ac8 100644 --- a/site/examples/shape/ellipse/demo/ellipse.js +++ b/site/examples/shape/ellipse/demo/ellipse.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/html/demo/html.js b/site/examples/shape/html/demo/html.js index 3ebb86165..a2edd7a3f 100644 --- a/site/examples/shape/html/demo/html.js +++ b/site/examples/shape/html/demo/html.js @@ -32,7 +32,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/image/demo/image.js b/site/examples/shape/image/demo/image.js index ba4088f70..9c8c8d2b1 100644 --- a/site/examples/shape/image/demo/image.js +++ b/site/examples/shape/image/demo/image.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/line/demo/line.js b/site/examples/shape/line/demo/line.js index be304d6f6..207a02efb 100644 --- a/site/examples/shape/line/demo/line.js +++ b/site/examples/shape/line/demo/line.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/path/demo/a-command.js b/site/examples/shape/path/demo/a-command.js index 471da73b5..68c5b20e2 100644 --- a/site/examples/shape/path/demo/a-command.js +++ b/site/examples/shape/path/demo/a-command.js @@ -13,7 +13,9 @@ const svgRenderer = new SVGRenderer(); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvas = new Canvas({ container: 'container', diff --git a/site/examples/shape/path/demo/get-point.js b/site/examples/shape/path/demo/get-point.js index c91c81774..5cd0d35f7 100644 --- a/site/examples/shape/path/demo/get-point.js +++ b/site/examples/shape/path/demo/get-point.js @@ -13,7 +13,9 @@ const svgRenderer = new SVGRenderer(); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvas = new Canvas({ container: 'container', diff --git a/site/examples/shape/path/demo/group.js b/site/examples/shape/path/demo/group.js index 858a227c7..b8cdd456b 100644 --- a/site/examples/shape/path/demo/group.js +++ b/site/examples/shape/path/demo/group.js @@ -13,7 +13,9 @@ const svgRenderer = new SVGRenderer(); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvas = new Canvas({ container: 'container', diff --git a/site/examples/shape/path/demo/l-command.js b/site/examples/shape/path/demo/l-command.js index 5033261df..083fb59e0 100644 --- a/site/examples/shape/path/demo/l-command.js +++ b/site/examples/shape/path/demo/l-command.js @@ -14,7 +14,9 @@ const svgRenderer = new SVGRenderer(); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvas = new Canvas({ container: 'container', diff --git a/site/examples/shape/path/demo/marker.js b/site/examples/shape/path/demo/marker.js index 83071e23d..c689a5e3c 100644 --- a/site/examples/shape/path/demo/marker.js +++ b/site/examples/shape/path/demo/marker.js @@ -13,7 +13,9 @@ const svgRenderer = new SVGRenderer(); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvas = new Canvas({ container: 'container', diff --git a/site/examples/shape/path/demo/multi-segments.js b/site/examples/shape/path/demo/multi-segments.js index 05b855bdb..5331435c2 100644 --- a/site/examples/shape/path/demo/multi-segments.js +++ b/site/examples/shape/path/demo/multi-segments.js @@ -13,7 +13,9 @@ const svgRenderer = new SVGRenderer(); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvas = new Canvas({ container: 'container', diff --git a/site/examples/shape/path/demo/path.js b/site/examples/shape/path/demo/path.js index 8a8e0072e..2f4ae1176 100644 --- a/site/examples/shape/path/demo/path.js +++ b/site/examples/shape/path/demo/path.js @@ -14,7 +14,9 @@ const svgRenderer = new SVGRenderer(); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvas = new Canvas({ container: 'container', diff --git a/site/examples/shape/path/demo/picking.js b/site/examples/shape/path/demo/picking.js index de4681daa..e1dcbf531 100644 --- a/site/examples/shape/path/demo/picking.js +++ b/site/examples/shape/path/demo/picking.js @@ -13,7 +13,9 @@ const svgRenderer = new SVGRenderer(); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvas = new Canvas({ container: 'container', diff --git a/site/examples/shape/polygon/demo/fillrule.js b/site/examples/shape/polygon/demo/fillrule.js index 1011fb73a..298763156 100644 --- a/site/examples/shape/polygon/demo/fillrule.js +++ b/site/examples/shape/polygon/demo/fillrule.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/polygon/demo/marker.js b/site/examples/shape/polygon/demo/marker.js index 6120d0574..6e7da3bf7 100644 --- a/site/examples/shape/polygon/demo/marker.js +++ b/site/examples/shape/polygon/demo/marker.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/polygon/demo/polygon.js b/site/examples/shape/polygon/demo/polygon.js index c5b620b05..2e581b81d 100644 --- a/site/examples/shape/polygon/demo/polygon.js +++ b/site/examples/shape/polygon/demo/polygon.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/polyline/demo/marker.js b/site/examples/shape/polyline/demo/marker.js index 0eed6ecfa..3fe288a8b 100644 --- a/site/examples/shape/polyline/demo/marker.js +++ b/site/examples/shape/polyline/demo/marker.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/polyline/demo/polyline.js b/site/examples/shape/polyline/demo/polyline.js index 0c80a6c8c..1fc8a8926 100644 --- a/site/examples/shape/polyline/demo/polyline.js +++ b/site/examples/shape/polyline/demo/polyline.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/rect/demo/rect.js b/site/examples/shape/rect/demo/rect.js index f07e5504d..df592f28e 100644 --- a/site/examples/shape/rect/demo/rect.js +++ b/site/examples/shape/rect/demo/rect.js @@ -24,7 +24,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/text/demo/d3-word-cloud.js b/site/examples/shape/text/demo/d3-word-cloud.js index 0bf2e4991..9dc96654d 100644 --- a/site/examples/shape/text/demo/d3-word-cloud.js +++ b/site/examples/shape/text/demo/d3-word-cloud.js @@ -35,7 +35,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/text/demo/text-baseline.js b/site/examples/shape/text/demo/text-baseline.js index 29a6ec073..ad0542778 100644 --- a/site/examples/shape/text/demo/text-baseline.js +++ b/site/examples/shape/text/demo/text-baseline.js @@ -22,7 +22,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/text/demo/text-overflow.js b/site/examples/shape/text/demo/text-overflow.js index 576454fbd..a67bafe5d 100644 --- a/site/examples/shape/text/demo/text-overflow.js +++ b/site/examples/shape/text/demo/text-overflow.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/text/demo/text.js b/site/examples/shape/text/demo/text.js index f9e5103a2..5904dde05 100644 --- a/site/examples/shape/text/demo/text.js +++ b/site/examples/shape/text/demo/text.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/shape/text/demo/web-font-loader.js b/site/examples/shape/text/demo/web-font-loader.js index 0b90339ff..8f8ca096d 100644 --- a/site/examples/shape/text/demo/web-font-loader.js +++ b/site/examples/shape/text/demo/web-font-loader.js @@ -21,7 +21,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/style/basic/demo/color.js b/site/examples/style/basic/demo/color.js index 644d8f938..04c5d6b36 100644 --- a/site/examples/style/basic/demo/color.js +++ b/site/examples/style/basic/demo/color.js @@ -25,7 +25,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/style/basic/demo/custom-property.js b/site/examples/style/basic/demo/custom-property.js index 43325e312..4903a98c6 100644 --- a/site/examples/style/basic/demo/custom-property.js +++ b/site/examples/style/basic/demo/custom-property.js @@ -17,7 +17,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/style/basic/demo/inheritance.js b/site/examples/style/basic/demo/inheritance.js index b6661707f..6bcdba3da 100644 --- a/site/examples/style/basic/demo/inheritance.js +++ b/site/examples/style/basic/demo/inheritance.js @@ -25,7 +25,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/style/basic/demo/length.js b/site/examples/style/basic/demo/length.js index 555bd638f..fd12f3e83 100644 --- a/site/examples/style/basic/demo/length.js +++ b/site/examples/style/basic/demo/length.js @@ -27,7 +27,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/style/basic/demo/paint.js b/site/examples/style/basic/demo/paint.js index bdbb06562..e411038be 100644 --- a/site/examples/style/basic/demo/paint.js +++ b/site/examples/style/basic/demo/paint.js @@ -25,7 +25,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // create a canvas const canvas = new Canvas({ diff --git a/site/examples/style/clip-path/demo/clip.js b/site/examples/style/clip-path/demo/clip.js index 761c9ac7c..9c6d8465e 100644 --- a/site/examples/style/clip-path/demo/clip.js +++ b/site/examples/style/clip-path/demo/clip.js @@ -20,7 +20,9 @@ const canvaskitRenderer = new CanvaskitRenderer({ }, ], }); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); // in user space const clipPathCircle = new Circle({ diff --git a/site/examples/style/gradient/demo/gradient.js b/site/examples/style/gradient/demo/gradient.js index bfc978e7d..32de8d1a1 100644 --- a/site/examples/style/gradient/demo/gradient.js +++ b/site/examples/style/gradient/demo/gradient.js @@ -22,7 +22,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); diff --git a/site/examples/style/gradient/demo/inner-shadow.js b/site/examples/style/gradient/demo/inner-shadow.js index 21af97435..26e3dc56c 100644 --- a/site/examples/style/gradient/demo/inner-shadow.js +++ b/site/examples/style/gradient/demo/inner-shadow.js @@ -11,7 +11,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); diff --git a/site/examples/style/pattern/demo/dots.js b/site/examples/style/pattern/demo/dots.js index 801bf0d5e..cb5aeb384 100644 --- a/site/examples/style/pattern/demo/dots.js +++ b/site/examples/style/pattern/demo/dots.js @@ -15,7 +15,9 @@ import { dots } from '@antv/g-pattern'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/style/pattern/demo/lines.js b/site/examples/style/pattern/demo/lines.js index 0d45ad573..5950772e9 100644 --- a/site/examples/style/pattern/demo/lines.js +++ b/site/examples/style/pattern/demo/lines.js @@ -15,7 +15,9 @@ import { lines } from '@antv/g-pattern'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/examples/style/pattern/demo/pattern.js b/site/examples/style/pattern/demo/pattern.js index c292daf54..406a34c4c 100644 --- a/site/examples/style/pattern/demo/pattern.js +++ b/site/examples/style/pattern/demo/pattern.js @@ -22,7 +22,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); diff --git a/site/examples/style/pattern/demo/piechart.js b/site/examples/style/pattern/demo/piechart.js index 88f59da00..b77121b3e 100644 --- a/site/examples/style/pattern/demo/piechart.js +++ b/site/examples/style/pattern/demo/piechart.js @@ -21,7 +21,9 @@ import { lines } from '@antv/g-pattern'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ @@ -45,7 +47,6 @@ const canvas = new Canvas({ }); const data = [38024.7, 209484.6, 6201.2, 17741.9, 24377.7]; -const total = d3.sum(data); const colors = ['#e8c1a0', '#f47560', '#f1e15b', '#e8a838', '#61cdbb']; const width = 600; const sectorArc = d3 diff --git a/site/examples/style/pattern/demo/rect.js b/site/examples/style/pattern/demo/rect.js index 7503e168c..0c3696689 100644 --- a/site/examples/style/pattern/demo/rect.js +++ b/site/examples/style/pattern/demo/rect.js @@ -11,7 +11,9 @@ import Stats from 'stats.js'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', }); diff --git a/site/examples/style/pattern/demo/squares.js b/site/examples/style/pattern/demo/squares.js index f4583a81e..674f81da0 100644 --- a/site/examples/style/pattern/demo/squares.js +++ b/site/examples/style/pattern/demo/squares.js @@ -15,7 +15,9 @@ import { squares } from '@antv/g-pattern'; const canvasRenderer = new CanvasRenderer(); const svgRenderer = new SVGRenderer(); const webglRenderer = new WebGLRenderer(); -const webgpuRenderer = new WebGPURenderer(); +const webgpuRenderer = new WebGPURenderer({ + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', +}); const canvaskitRenderer = new CanvaskitRenderer({ wasmDir: '/', fonts: [ diff --git a/site/package.json b/site/package.json index 6030c9449..58037bf6f 100644 --- a/site/package.json +++ b/site/package.json @@ -24,9 +24,9 @@ "start": "npm run site:dev" }, "dependencies": { - "@antv/g-components": "^1.9.0", - "@antv/g-plugin-dragndrop": "^1.8.0", - "@antv/g-svg": "^1.10.0", + "@antv/g-components": "^1.9.1", + "@antv/g-mobile-webgl": "^0.9.1", + "@antv/g-plugin-image-loader": "^1.3.1", "@antv/g6": "^4.5.2", "@antv/react-g": "^1.8.79", "@antv/util": "^3.3.1",