diff --git a/examples/demos/webgpu/index.ts b/examples/demos/webgpu/index.ts index 320848a31e..20ea93e427 100644 --- a/examples/demos/webgpu/index.ts +++ b/examples/demos/webgpu/index.ts @@ -1,7 +1,11 @@ export { MapRender as boids } from './boids'; export { MapRender as compute_texture } from './compute_texture'; export { MapRender as WebGL_IDW } from './idw'; +// export { MapRender as line_normal } from './line_normal'; export { MapRender as point_column } from './point_column'; export { MapRender as point_fill } from './point_fill'; export { MapRender as point_image } from './point_image'; +export { MapRender as polygon_extrude } from './polygon_extrude'; +export { MapRender as polygon_fill } from './polygon_fill'; +export { MapRender as polygon_texture } from './polygon_texture'; export { MapRender as texture } from './texture'; diff --git a/examples/demos/webgpu/line_normal.ts b/examples/demos/webgpu/line_normal.ts new file mode 100644 index 0000000000..924ea98aea --- /dev/null +++ b/examples/demos/webgpu/line_normal.ts @@ -0,0 +1,82 @@ +// @ts-ignore +import { LineLayer, Scene, Source } from '@antv/l7'; +// @ts-ignore +import * as allMap from '@antv/l7-maps'; + +export function MapRender(option: { map: string; renderer: string }) { + const scene = new Scene({ + id: 'map', + renderer: option.renderer === 'device' ? 'device' : 'regl', + enableWebGPU: true, + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', + map: new allMap[option.map || 'Map']({ + style: 'light', + center: [121.435159, 31.256971], + zoom: 14.89, + minZoom: 10, + }), + }); + const geoData = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: { + offset: 0.3, + }, + geometry: { + type: 'MultiLineString', + coordinates: [ + [ + [99.228515625, 37.43997405227057], + [100.72265625, 27.994401411046148], + [110, 27.994401411046148], + [110, 25], + [100, 25], + ], + [ + [108.544921875, 37.71859032558816], + [112.412109375, 32.84267363195431], + [115, 32.84267363195431], + [115, 35], + ], + ], + }, + }, + { + type: 'Feature', + properties: { + offset: 0.8, + }, + geometry: { + type: 'MultiLineString', + coordinates: [ + [ + [110, 30], + [120, 30], + [120, 40], + ], + ], + }, + }, + ], + }; + const source = new Source(geoData); + const layer = new LineLayer({ blend: 'normal', autoFit: true }) + .source(source) + .size(1) + .shape('line') + .color('#f00') + .style({ + opacity: 0.6, + }); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + + setTimeout(() => { + layer.size(20); + scene.render(); + }, 2000); +} diff --git a/examples/demos/webgpu/polygon_extrude.ts b/examples/demos/webgpu/polygon_extrude.ts new file mode 100644 index 0000000000..597fab2108 --- /dev/null +++ b/examples/demos/webgpu/polygon_extrude.ts @@ -0,0 +1,64 @@ +import { PolygonLayer, Scene } from '@antv/l7'; +import * as allMap from '@antv/l7-maps'; + +export function MapRender(option: { map: string; renderer: string }) { + console.log(option); + const scene = new Scene({ + id: 'map', + renderer: option.renderer === 'device' ? 'device' : 'regl', + enableWebGPU: true, + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', + map: new allMap[option.map || 'Map']({ + style: 'light', + center: [121.434765, 31.256735], + zoom: 14.83, + }), + }); + + const colors = [ + '#87CEFA', + '#00BFFF', + + '#7FFFAA', + '#00FF7F', + '#32CD32', + + '#F0E68C', + '#FFD700', + + '#FF7F50', + '#FF6347', + '#FF0000', + ]; + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/94763191-2816-4c1a-8d0d-8bcf4181056a.json', + ) + .then((res) => res.json()) + .then((data) => { + const filllayer = new PolygonLayer({ + name: 'fill', + zIndex: 3, + autoFit: true, + }) + .source(data) + .shape('extrude') + // .active(true) + .size('unit_price', (unit_price) => unit_price) + .color('count', [ + '#f2f0f7', + '#dadaeb', + '#bcbddc', + '#9e9ac8', + '#756bb1', + '#54278f', + ]) + .style({ + pickLight: true, + + opacity: 1, + }); + scene.addLayer(filllayer); + }); + }); +} diff --git a/examples/demos/webgpu/polygon_fill.ts b/examples/demos/webgpu/polygon_fill.ts new file mode 100644 index 0000000000..85afd31dca --- /dev/null +++ b/examples/demos/webgpu/polygon_fill.ts @@ -0,0 +1,83 @@ +import { PolygonLayer, Scene } from '@antv/l7'; +import * as allMap from '@antv/l7-maps'; + +export function MapRender(option: { map: string; renderer: string }) { + const scene = new Scene({ + id: 'map', + renderer: option.renderer === 'device' ? 'device' : 'regl', + enableWebGPU: true, + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', + map: new allMap[option.map || 'Map']({ + style: 'light', + center: [121.434765, 31.256735], + zoom: 14.83, + }), + }); + + const data = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: { + testOpacity: 0.8, + }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [113.8623046875, 30.031055426540206], + [116.3232421875, 30.031055426540206], + [116.3232421875, 31.090574094954192], + [113.8623046875, 31.090574094954192], + [113.8623046875, 30.031055426540206], + ], + ], + }, + }, + ], + }; + + const data2 = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: { + testOpacity: 0.8, + }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [113.8623046875, 30.031055426540206], + [115.3232421875, 30.031055426540206], + [115.3232421875, 31.090574094954192], + [113.8623046875, 31.090574094954192], + [113.8623046875, 30.031055426540206], + ], + ], + }, + }, + ], + }; + + const layer = new PolygonLayer({ + autoFit: true, + }) + .source(data) + .shape('fill') + .color('red') + // .active(true) + .style({ + opacity: 0.5, + opacityLinear: { + enable: true, + dir: 'in', + }, + }); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); +} diff --git a/examples/demos/webgpu/polygon_texture.ts b/examples/demos/webgpu/polygon_texture.ts new file mode 100644 index 0000000000..f46ed0e090 --- /dev/null +++ b/examples/demos/webgpu/polygon_texture.ts @@ -0,0 +1,46 @@ +import { PolygonLayer, Scene } from '@antv/l7'; +import * as allMap from '@antv/l7-maps'; + +export function MapRender(option: { map: string; renderer: string }) { + const scene = new Scene({ + id: 'map', + renderer: option.renderer === 'device' ? 'device' : 'regl', + enableWebGPU: true, + shaderCompilerPath: '/glsl_wgsl_compiler_bg.wasm', + map: new allMap[option.map || 'Map']({ + style: 'light', + center: [121.434765, 31.256735], + zoom: 14.83, + }), + }); + + scene.on('loaded', () => { + fetch('https://geo.datav.aliyun.com/areas_v3/bound/330000.json') + .then((res) => res.json()) + .then((data) => { + const provincelayerTop = new PolygonLayer({ + autoFit: true, + }) + .source(data) + .size(1000) + .shape('extrude') + .size(10000) + .color('#0DCCFF') + // .active({ + // color: 'rgb(100,230,255)', + // }) + .style({ + heightfixed: true, + // pickLight: true, + mapTexture: + 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*bm0eRKOCcNoAAAAAAAAAAAAADmJ7AQ/original', + // mapTexture:'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*3UcORbAv_zEAAAAAAAAAAAAADmJ7AQ/original', + // raisingHeight: 10000, + opacity: 0.8, + // sidesurface: false, + }); + scene.addLayer(provincelayerTop); + // scene.startAnimate(); + }); + }); +} diff --git a/packages/layers/src/line/models/line.ts b/packages/layers/src/line/models/line.ts index 5d953abda2..8c028a8f74 100644 --- a/packages/layers/src/line/models/line.ts +++ b/packages/layers/src/line/models/line.ts @@ -3,19 +3,13 @@ import type { IEncodeFeature, ILayerConfig, IModel, - ITexture2D} from '@antv/l7-core'; -import { - AttributeType, - gl + ITexture2D, } from '@antv/l7-core'; +import { AttributeType, gl } from '@antv/l7-core'; import { LineTriangulation, rgb2arr } from '@antv/l7-utils'; import BaseModel from '../../core/BaseModel'; -import type { - ILineLayerStyleOptions} from '../../core/interface'; -import { - LinearDir, - TextureBlend, -} from '../../core/interface'; +import type { ILineLayerStyleOptions } from '../../core/interface'; +import { LinearDir, TextureBlend } from '../../core/interface'; // import { LineTriangulation } from '../../core/triangulation'; import { ShaderLocation } from '../../core/CommonStyleAttribute'; @@ -269,7 +263,7 @@ export default class LineModel extends BaseModel { }, }, }); - + this.styleAttributeService.registerStyleAttribute({ name: 'uv', type: AttributeType.Attribute, diff --git a/packages/layers/src/polygon/models/extrude.ts b/packages/layers/src/polygon/models/extrude.ts index e876aced99..66b914b08c 100644 --- a/packages/layers/src/polygon/models/extrude.ts +++ b/packages/layers/src/polygon/models/extrude.ts @@ -1,11 +1,5 @@ -import type { - IEncodeFeature, - IModel, - ITexture2D} from '@antv/l7-core'; -import { - AttributeType, - gl -} from '@antv/l7-core'; +import type { IEncodeFeature, IModel, ITexture2D } from '@antv/l7-core'; +import { AttributeType, gl } from '@antv/l7-core'; import { rgb2arr } from '@antv/l7-utils'; import BaseModel from '../../core/BaseModel'; import type { IPolygonLayerStyleOptions } from '../../core/interface'; @@ -18,9 +12,10 @@ import polygonExtrudeTexFrag from '../shaders/extrude/polygon_extrudetex_frag.gl import polygonExtrudeTexVert from '../shaders/extrude/polygon_extrudetex_vert.glsl'; // extrude picking +import { ShaderLocation } from '../../core/CommonStyleAttribute'; +import { loadImage } from '../../utils/load-image'; import polygonExtrudePickLightFrag from '../shaders/extrude/polygon_extrude_picklight_frag.glsl'; import polygonExtrudePickLightVert from '../shaders/extrude/polygon_extrude_picklight_vert.glsl'; -import { ShaderLocation } from '../../core/CommonStyleAttribute'; export default class ExtrudeModel extends BaseModel { protected texture: ITexture2D; @@ -31,10 +26,15 @@ export default class ExtrudeModel extends BaseModel { return { ...commoninfo.uniformsOption, ...attributeInfo.uniformsOption, - } + }; } - protected getCommonUniformsInfo(): { uniformsArray: number[]; uniformsLength: number; uniformsOption: { [key: string]: any; }; } { + protected getCommonUniformsInfo(): { + uniformsArray: number[]; + uniformsLength: number; + uniformsOption: { [key: string]: any }; + } { const { + mapTexture, heightfixed = false, raisingHeight = 0, topsurface = true, @@ -53,7 +53,6 @@ export default class ExtrudeModel extends BaseModel { useLinearColor = 1; } const commonOptions = { - u_sourceColor: sourceColorArr, u_targetColor: targetColorArr, u_linearColor: useLinearColor, @@ -62,16 +61,14 @@ export default class ExtrudeModel extends BaseModel { u_sidesurface: Number(sidesurface), u_heightfixed: Number(heightfixed), u_raisingHeight: Number(raisingHeight), - - // 渐变色支持参数 - u_texture: this.texture,// 纹理 }; - if(this.texture){ - this.textures =[this.texture] + if (mapTexture && this.texture) { + // @ts-ignore + commonOptions.u_texture = this.texture; + this.textures = [this.texture]; } const commonBufferInfo = this.getUniformsBufferInfo(commonOptions); return commonBufferInfo; - } public async initModels(): Promise { @@ -227,32 +224,19 @@ export default class ExtrudeModel extends BaseModel { const { createTexture2D } = this.rendererService; this.texture = createTexture2D({ - height: 0, - width: 0, + height: 1, + width: 1, }); if (mapTexture) { - return new Promise((resolve, reject) => { - const image = new Image(); - image.crossOrigin = 'anonymous'; - image.src = mapTexture; - - image.onload = () => { - this.texture = createTexture2D({ - data: image, - width: image.width, - height: image.height, - wrapS: gl.CLAMP_TO_EDGE, - wrapT: gl.CLAMP_TO_EDGE, - min: gl.LINEAR, - mag: gl.LINEAR, - }); - return resolve(null); - // this.layerService.reRender(); - }; - - image.onerror = () => { - reject(new Error('image load error')); - }; + const image = await loadImage(mapTexture); + this.texture = createTexture2D({ + data: image, + width: image.width, + height: image.height, + wrapS: gl.CLAMP_TO_EDGE, + wrapT: gl.CLAMP_TO_EDGE, + min: gl.LINEAR, + mag: gl.LINEAR, }); } } diff --git a/packages/layers/src/polygon/shaders/extrude/polygon_extrude_picklight_vert.glsl b/packages/layers/src/polygon/shaders/extrude/polygon_extrude_picklight_vert.glsl index 1dd5cc1369..84ad306a79 100644 --- a/packages/layers/src/polygon/shaders/extrude/polygon_extrude_picklight_vert.glsl +++ b/packages/layers/src/polygon/shaders/extrude/polygon_extrude_picklight_vert.glsl @@ -15,10 +15,9 @@ layout(std140) uniform commonUniforms { float u_raisingHeight; }; -out vec2 v_texture_data; -out vec3 v_uvs; out vec4 v_Color; - +out vec3 v_uvs; +out vec2 v_texture_data; #pragma include "projection" #pragma include "light" diff --git a/packages/layers/src/polygon/shaders/extrude/polygon_extrudetex_frag.glsl b/packages/layers/src/polygon/shaders/extrude/polygon_extrudetex_frag.glsl index 1063e6d219..48874a4f9b 100644 --- a/packages/layers/src/polygon/shaders/extrude/polygon_extrudetex_frag.glsl +++ b/packages/layers/src/polygon/shaders/extrude/polygon_extrudetex_frag.glsl @@ -14,7 +14,6 @@ in vec4 v_Color; in vec3 v_uvs; in vec2 v_texture_data; - #pragma include "picking" out vec4 outputColor; @@ -26,14 +25,16 @@ void main() { float topU = v_uvs[0]; float topV = 1.0 - v_uvs[1]; float sidey = v_uvs[2]; + + outputColor = texture(SAMPLER_2D(u_texture), vec2(topU, topV)); // Tip: 部分机型 GPU 计算精度兼容 - if(isSide < 0.999) {// 是否是边缘 + if (isSide < 0.999) {// 是否是边缘 // side face - if(u_sidesurface < 1.0) { + if (u_sidesurface < 1.0) { discard; } - if(u_linearColor == 1.0) { + if (u_linearColor == 1.0) { vec4 linearColor = mix(u_targetColor, u_sourceColor, sidey); linearColor.rgb *= lightWeight; outputColor = linearColor; @@ -41,16 +42,12 @@ void main() { outputColor = v_Color; } } else { - // top face - if(u_topsurface < 1.0) { + if (u_topsurface < 1.0) { discard; } - - outputColor = texture(SAMPLER_2D(u_texture), vec2(topU, topV)); } - outputColor.a *= opacity; outputColor = filterColor(outputColor); } diff --git a/packages/layers/src/polygon/shaders/extrude/polygon_extrudetex_vert.glsl b/packages/layers/src/polygon/shaders/extrude/polygon_extrudetex_vert.glsl index b148c2fe32..2717736fba 100644 --- a/packages/layers/src/polygon/shaders/extrude/polygon_extrudetex_vert.glsl +++ b/packages/layers/src/polygon/shaders/extrude/polygon_extrudetex_vert.glsl @@ -16,9 +16,8 @@ layout(std140) uniform commonUniforms { }; out vec4 v_Color; - -out vec2 v_texture_data; out vec3 v_uvs; +out vec2 v_texture_data; #pragma include "projection" #pragma include "light" diff --git a/packages/layers/src/polygon/shaders/fill/fill_linear_frag.glsl b/packages/layers/src/polygon/shaders/fill/fill_linear_frag.glsl index 54604e37c4..0a5f2e741d 100644 --- a/packages/layers/src/polygon/shaders/fill/fill_linear_frag.glsl +++ b/packages/layers/src/polygon/shaders/fill/fill_linear_frag.glsl @@ -5,15 +5,15 @@ layout(std140) uniform commonUniforms { float u_dir; }; +in vec4 v_color; in vec3 v_linear; in vec2 v_pos; -in vec4 v_color; out vec4 outputColor; #pragma include "picking" void main() { - outputColor = v_color; - if(u_opacitylinear > 0.0) { + outputColor = v_color; + if (u_opacitylinear > 0.0) { outputColor.a *= u_dir == 1.0 ? 1.0 - length(v_pos - v_linear.xy)/v_linear.z : length(v_pos - v_linear.xy)/v_linear.z; } outputColor = filterColor(outputColor); diff --git a/packages/layers/src/polygon/shaders/fill/fill_linear_vert.glsl b/packages/layers/src/polygon/shaders/fill/fill_linear_vert.glsl index d7cf4bb839..969698a6e0 100644 --- a/packages/layers/src/polygon/shaders/fill/fill_linear_vert.glsl +++ b/packages/layers/src/polygon/shaders/fill/fill_linear_vert.glsl @@ -2,24 +2,21 @@ layout(location = 0) in vec3 a_Position; layout(location = 1) in vec4 a_Color; layout(location = 15) in vec3 a_linear; - layout(std140) uniform commonUniforms { float u_raisingHeight; float u_opacitylinear; float u_dir; }; - out vec4 v_color; +out vec3 v_linear; +out vec2 v_pos; #pragma include "projection" #pragma include "picking" -out vec3 v_linear; -out vec2 v_pos; - void main() { - if(u_opacitylinear > 0.0) { + if (u_opacitylinear > 0.0) { v_linear = a_linear; v_pos = a_Position.xy; } @@ -27,12 +24,12 @@ void main() { vec4 project_pos = project_position(vec4(a_Position, 1.0)); project_pos.z += u_raisingHeight; - if(u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT || u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT_OFFSET) { + if (u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT || u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT_OFFSET) { float mapboxZoomScale = 4.0/pow(2.0, 21.0 - u_Zoom); project_pos.z *= mapboxZoomScale; project_pos.z += u_raisingHeight * mapboxZoomScale; } - gl_Position = project_common_position_to_clipspace_v2(vec4(project_pos.xyz, 1.0)); + gl_Position = project_common_position_to_clipspace_v2(vec4(project_pos.xyz, 1.0)); setPickingColor(a_PickingColor); } \ No newline at end of file diff --git a/packages/layers/src/utils/load-image.ts b/packages/layers/src/utils/load-image.ts new file mode 100644 index 0000000000..a32978ff7e --- /dev/null +++ b/packages/layers/src/utils/load-image.ts @@ -0,0 +1,16 @@ +export async function loadImage( + url: string, +): Promise { + if (!!window.createImageBitmap) { + const response = await fetch(url); + const imageBitmap = await createImageBitmap(await response.blob()); + return imageBitmap; + } else { + const image = new window.Image(); + return new Promise((res) => { + image.onload = () => res(image); + image.src = url; + image.crossOrigin = 'Anonymous'; + }); + } +} diff --git a/packages/renderer/src/device/DeviceTexture2D.ts b/packages/renderer/src/device/DeviceTexture2D.ts index 4fd500f3d4..728c6b4e81 100644 --- a/packages/renderer/src/device/DeviceTexture2D.ts +++ b/packages/renderer/src/device/DeviceTexture2D.ts @@ -75,7 +75,8 @@ export default class DeviceTexture2D implements ITexture2D { unpackFlipY: flipY, packAlignment: alignment, }, - mipLevelCount: usage === TextureUsage.RENDER_TARGET ? 1 : mipmap ? 1 : 0, + // mipLevelCount: usage === TextureUsage.RENDER_TARGET ? 1 : mipmap ? 1 : 0, + mipLevelCount: 1, }); if (data) { // @ts-ignore