唯杰地图 logo唯杰地图
VJMAP
EN

内置材质

vjmap3d/references/builtin/material.md 29.7 KB859 行
原文

WebGPU 引擎

本页全部内置材质在 render: { engine: "webgpu" } 时会自动切换为对应的 TSL 节点材质实现,创建参数与用法不变;运行期改值请统一用 material.uniforms.xxx.value(两种引擎通用)。⚠️ 同名属性存取器(如 mat.uSpeed = 3)在 webgl 下只有 shaderMaterial() 工厂生成的材质才有——FlowMaterial(含 createTextFlowMaterial/createRenderElementFlowMaterial)、AnimatorFrameMaterial、RadarMaterial;HolographicMaterial、FixedSizeMeshMaterial、createFlowGradientMaterial、ShadertoyMaterial、反射材质等在 webgl 下直接写同名属性会被静默忽略。另:webgpu 下 createReflectorShaderMesh 不支持 ignoreObjects/includeObjects(只告警,反射整个场景)。webgpu 引擎下请在 await app.whenReady() 之后再创建材质,详见 WebGPU 渲染引擎。

TextFlowMaterial 文本滚动材质

通过createTextFlowMaterial创建文本滚动材质

用法

垂直文本滚动效果

let geoW = 10, geoH = 10 / 2;
let geom = new THREE.PlaneGeometry(geoW, geoH);
let mat = vjmap3d.createTextFlowMaterial(app, {
    geometryWidth: geoW,
    geometryHeight: geoH,
    flowDirection: "vertical",
    flowSpeed: 0.03,
    text: `春天是一年四季中最美丽的季节之一,也是最富有生机的季节。在这个季节里,大自然给我们带来了很多惊喜和愉悦。在这个季节里,我喜欢去公园里散步,欣赏那里的美景。
走进公园,你会看到一条小路蜿蜒伸向远方。小路两旁种满了各种各样的树木,有高大的梧桐树,还有低矮的桃树和梨树。它们长出了嫩绿的新叶,这些新叶在阳光下闪闪发光,仿佛在向人们报告春天的到来。`,
    fill: "#FF1285",
    font: "30px sans-serif",
    padding: [5, 5, 5, 5],
    backgroundColor: "#FFFE91",
    lineHeight: 50,
    width: 300,
    overflow: "break"
});
let mesh = new THREE.Mesh(geom, mat);
mesh.position.set(0, 0, 0);
mesh.rotateY(Math.PI / 16);
app.scene.add(mesh);

水平文本滚动效果

let geoW2 = 20, geoH2 = 20 / 5;
let geom2 = new THREE.PlaneGeometry(geoW2, geoH2);
let mat2 = vjmap3d.createTextFlowMaterial(app, {
    geometryWidth: geoW2,
    geometryHeight: geoH2,
    flowDirection: "horizon",
    flowSpeed: 0.03,
    text: `春天是一年四季中最美丽的季节之一,也是最富有生机的季节。在这个季节里,大自然给我们带来了很多惊喜和愉悦。在这个季节里,我喜欢去公园里散步,欣赏那里的美景。`,
    fill: "#16417C",
    font: "30px sans-serif",
    padding: [5, 5, 5, 5],
    backgroundColor: "#00ff00",
    lineHeight: 50
});
let mesh2 = new THREE.Mesh(geom2, mat2);
mesh2.position.set(-5, 0, -10);
app.scene.add(mesh2);

示例

::: tabs @tab 三维模式

let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    stat: { show: true, left: "0" },
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
// 垂直文本滚动
let geoW = 10, geoH = 10 / 2;
let geom = new THREE.PlaneGeometry(geoW, geoH);
let mat = vjmap3d.createTextFlowMaterial(app, {
    geometryWidth: geoW,
    geometryHeight: geoH,
    flowDirection: "vertical",
    flowSpeed: 0.03,
    text: `春天是一年四季中最美丽的季节之一,也是最富有生机的季节。在这个季节里,大自然给我们带来了很多惊喜和愉悦。在这个季节里,我喜欢去公园里散步,欣赏那里的美景。
走进公园,你会看到一条小路蜿蜒伸向远方。小路两旁种满了各种各样的树木,有高大的梧桐树,还有低矮的桃树和梨树。它们长出了嫩绿的新叶,这些新叶在阳光下闪闪发光,仿佛在向人们报告春天的到来。
沿着小路往前走,你会看到一片盛开的花海。有各种各样的花朵,比如红色的玫瑰,紫色的薰衣草,黄色的向日葵等等。它们争奇斗艳,各自展示着自己的美丽。在这片花海里,你可以闻到各种各样的香味,让人心旷神怡,烦恼忧虑全都忘了。
在公园里还有一些人工建筑和设施。比如有一个小湖泊,湖里有几只鸭子在戏水,还有一些小鱼在游来游去。湖边有一座小亭子,供游客休息和观赏湖景。还有一些儿童游乐设施,比如秋千、滑梯、沙池等等,让孩子们尽情玩耍和欢笑。
春天是一个充满生机和希望的季节。在这个季节里,我们可以感受到大自然的神奇力量和无限魅力。春天是万物复苏的季节,在这个季节里我们可以看到大自然为我们描绘出一幅美丽画卷。让我们一起欣赏春天的美景吧!`,
    fill: "#FF1285",
    font: "30px sans-serif",
    padding: [5, 5, 5, 5],
    backgroundColor: "#FFFE91",
    lineHeight: 50,
    width: 300,
    overflow: "break"
});
let mesh = new THREE.Mesh(geom, mat);
mesh.position.set(0, 0, 0);
mesh.rotateY(Math.PI / 16);
app.scene.add(mesh);
// 水平滚动文本
let geoW2 = 20, geoH2 = 20 / 5;
let geom2 = new THREE.PlaneGeometry(geoW2, geoH2);
let mat2 = vjmap3d.createTextFlowMaterial(app, {
    geometryWidth: geoW2,
    geometryHeight: geoH2,
    flowDirection: "horizon",
    flowSpeed: 0.03,
    text: `春天是一年四季中最美丽的季节之一,也是最富有生机的季节。在这个季节里,大自然给我们带来了很多惊喜和愉悦。在这个季节里,我喜欢去公园里散步,欣赏那里的美景。`,
    fill: "#16417C",
    font: "30px sans-serif",
    padding: [5, 5, 5, 5],
    backgroundColor: "#00ff00",
    lineHeight: 50
});
let mesh2 = new THREE.Mesh(geom2, mat2);
mesh2.position.set(-5, 0, -10);
app.scene.add(mesh2);

@tab 唯杰地图三维图层模式

let svc = new vjmap.Service(env.serviceUrl, env.accessToken)
// 打开地图
let res = await svc.openMap({
    mapid: env.exampleMapId, // 地图ID
    // @ts-ignore
    mapopenway: vjmap.MapOpenWay.GeomRender, // 以几何数据渲染方式打开
    style: vjmap.openMapLightStyle() // div为深色背景颜色时,这里也传深色背景样式
})
if (res.error) {
    // 如果打开出错
    showError(res.error)
    return;
}
// 获取地图范围
let mapBounds = vjmap.GeoBounds.fromString(res.bounds);
// 根据地图范围建立几何投影坐标系
let prj = new vjmap.GeoProjection(mapBounds);
//
// 地图对象
let map = new vjmap.Map({
    container: 'map', // DIV容器ID
    style: svc.rasterStyle(), // 样式,这里是栅格样式
    center: prj.toLngLat(mapBounds.center()), // 设置地图中心点
    zoom: 2, // 设置地图缩放级别
    pitch: 45,
    antialias: true, // 反锯齿
    renderWorldCopies: false // 不显示多屏地图
});
//
// 关联服务对象和投影对象
map.attach(svc, prj);
await map.onLoad();
//
// 创建3d图层
let mapLayer = new vjmap3d.MapThreeLayer(map, {
    stat: {
        show: true,
        left: "0"
    }
});
map.addLayer(new vjmap.ThreeLayer({ context: mapLayer }))
let app = mapLayer.app;
let mapW = vjmap3d.toDist(mapBounds.width())
// 垂直文本滚动
let geoW = mapW / 10, geoH = mapW / 20;
let geom = new THREE.PlaneGeometry(geoW, geoH);
let mat = vjmap3d.createTextFlowMaterial(app, {
    geometryWidth: geoW,
    geometryHeight: geoH,
    flowDirection: "vertical",
    flowSpeed: 0.03,
    text: `春天是一年四季中最美丽的季节之一,也是最富有生机的季节。在这个季节里,大自然给我们带来了很多惊喜和愉悦。在这个季节里,我喜欢去公园里散步,欣赏那里的美景。
走进公园,你会看到一条小路蜿蜒伸向远方。小路两旁种满了各种各样的树木,有高大的梧桐树,还有低矮的桃树和梨树。它们长出了嫩绿的新叶,这些新叶在阳光下闪闪发光,仿佛在向人们报告春天的到来。
沿着小路往前走,你会看到一片盛开的花海。有各种各样的花朵,比如红色的玫瑰,紫色的薰衣草,黄色的向日葵等等。它们争奇斗艳,各自展示着自己的美丽。在这片花海里,你可以闻到各种各样的香味,让人心旷神怡,烦恼忧虑全都忘了。
在公园里还有一些人工建筑和设施。比如有一个小湖泊,湖里有几只鸭子在戏水,还有一些小鱼在游来游去。湖边有一座小亭子,供游客休息和观赏湖景。还有一些儿童游乐设施,比如秋千、滑梯、沙池等等,让孩子们尽情玩耍和欢笑。
春天是一个充满生机和希望的季节。在这个季节里,我们可以感受到大自然的神奇力量和无限魅力。春天是万物复苏的季节,在这个季节里我们可以看到大自然为我们描绘出一幅美丽画卷。让我们一起欣赏春天的美景吧!`,
    fill: "#FF1285",
    font: "30px sans-serif",
    padding: [5, 5, 5, 5],
    backgroundColor: "#FFFE91",
    lineHeight: 50,
    width: 300,
    overflow: "break"
});
let mesh = new THREE.Mesh(geom, mat);
mesh.position.copy(vjmap3d.toWorld(mapBounds.center().toArray()));
mesh.rotateX( Math.PI / 2)
mesh.rotateY( Math.PI)
app.scene.add(mesh);
// 水平滚动文本
let geoW2 = mapW / 10, geoH2 = mapW / 50;
let geom2 = new THREE.PlaneGeometry(geoW2, geoH2);
let mat2 = vjmap3d.createTextFlowMaterial(app, {
    geometryWidth: geoW2,
    geometryHeight: geoH2,
    flowDirection: "horizon",
    flowSpeed: 0.03,
    text: `春天是一年四季中最美丽的季节之一,也是最富有生机的季节。在这个季节里,大自然给我们带来了很多惊喜和愉悦。在这个季节里,我喜欢去公园里散步,欣赏那里的美景。`,
    fill: "#16417C",
    font: "30px sans-serif",
    padding: [5, 5, 5, 5],
    backgroundColor: "#00ff00",
    lineHeight: 50
});
let mesh2 = new THREE.Mesh(geom2, mat2);
mesh2.position.copy(vjmap3d.toWorld(mapBounds.randomPoint().toArray()));
mesh2.rotateX( Math.PI / 2)
mesh2.rotateY( Math.PI)
app.scene.add(mesh2);
:::

AnimatorFrameMaterial 动画帧纹理材质

动画帧纹理材质AnimatorFrameMaterial根据一张动画帧精灵图组成的图片创建的纹理材质

用法

let texture = await vjmap3d.ResManager.loadTextureSync(env.assetsPath + "sprites/alien.png", true);
let mat = new vjmap3d.AnimatorFrameMaterial(
    {
        imageWidth: texture.source.data.width,
        imageHeight: texture.source.data.height,
        rowCount: 1,
        colCount: 16,
        //spriteCount: 16,
        //spriteWidth: texture.source.data.width / 16,
        //spriteHeight: texture.source.data.height,
        curRunFrameCount: app.time.frameCount,
        map: texture,
        side: THREE.DoubleSide,
        transparent: true
    },
    { time: app.commonUniforms.time }
);
let geoW = 5, geoH = 5;
let geom = new THREE.PlaneGeometry(geoW, geoH);
let mesh = new THREE.Mesh(geom, mat);
mesh.position.set(1, 0, 1);
app.scene.add(mesh);

示例

let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    stat: { show: true, left: "0" },
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
let texture = await vjmap3d.ResManager.loadTextureSync(env.assetsPath + "sprites/alien.png", true);
let mat = new vjmap3d.AnimatorFrameMaterial(
    {
        imageWidth: texture.source.data.width,
        imageHeight: texture.source.data.height,
        rowCount: 1,
        colCount: 16,
        //spriteCount: 16,
        //spriteWidth: texture.source.data.width / 16,
        //spriteHeight: texture.source.data.height,
        curRunFrameCount: app.time.frameCount,
        map: texture,
        side: THREE.DoubleSide,
        transparent: true
    },
    { time: app.commonUniforms.time }
);
let geoW = 5, geoH = 5;
let geom = new THREE.PlaneGeometry(geoW, geoH);
let mesh = new THREE.Mesh(geom, mat);
mesh.position.set(1, 0, 1);
app.scene.add(mesh);

ReflectorMaterial 反射材质

通过 createReflectorShaderMesh 创建反射材质。

用法

const geometry = new THREE.PlaneGeometry(100, 100)
const { mesh, material } = vjmap3d.createReflectorShaderMesh(geometry, {
    reflectorMaterialType: "ReflectorDudvMaterial",
    reflectivity: 0.2
})
mesh.name = "reflectorShaderMesh"
mesh.rotation.x = -Math.PI / 2
mesh.position.y = -0.3
app.scene.add(mesh);

示例

let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    stat: { show: true, left: "0" },
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
let carMesh = await vjmap3d.ResManager.loadModel(env.assetsPath + "models/car.glb", {
    toEntity: true
});
carMesh.scale.set(5, 5, 5)
carMesh.addTo(app);
const geometry = new THREE.PlaneGeometry(100, 100)
const { mesh, material } = vjmap3d.createReflectorShaderMesh(geometry, {
    reflectorMaterialType: "ReflectorDudvMaterial",
    reflectivity: 0.2
})
mesh.name = "reflectorShaderMesh"
mesh.rotation.x = -Math.PI / 2
mesh.position.y = -0.3
app.scene.add(mesh);
const ui = await app.getConfigPane()
ui.appendChild({
    type: "slider",
    label: 'reflectivity',
    property: [material.uniforms.uReflectivity, "value"],
    bounds: [0, 1],
    stepSize: 0.001 // 原始配置对象的步长键名是 stepSize(写 step 会被忽略)
})
ui.appendChild({
    type: "slider",
    label: '位置y',
    property: [mesh.position, "y"],
    bounds: [-10, 0],
    stepSize: 0.01
})

MeshReflectorMaterial 是另一条路径(签名 new MeshReflectorMaterial(app, parent: Mesh, config?)):它不是 Material 子类而是包装类——parent 只用作反射平面(反射相机/渲染目标挂在它上面),构造函数不会替换 parent.material;真正的材质在实例的 .material 字段(MeshReflectorMaterialImpl extends MeshStandardMaterial),必须自己写 parent.material = refl.material。不要把返回值本身当材质赋给 mesh.material。

flowGradientMaterial 流动的渐变材质

通过 createFlowGradientMaterial 创建流动的渐变材质。

用法

let mat = vjmap3d.createFlowGradientMaterial(app, {
    object: mesh, // 或计算出mesh的坐标最小值min和物体坐标最大值max
    lightScale: 0.1, // 动画光带宽度占物体高度的比例(负数表示绝对宽度);没有 borderWidth 这个参数
    circleTime: Math.random() + 0.2,
    lightColor: vjmap3d.randColor(),
    color: vjmap3d.randColor(),
    topColor: vjmap3d.randColor(),
})
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    stat: { show: true, left: "0" },
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
let data = [];
for(let i = 0; i < 10; i++) {
    for(let j = 0; j < 10; j++) {
        const box = new THREE.Mesh(
            new THREE.BoxGeometry(Math.random() * 3 + 0.5, Math.random() * 5 + 3, Math.random() * 3 + 0.5),
            new THREE.MeshStandardMaterial({ color: 0xff0000 })
        );
        box.position.set(i * 10 - 50, 0, j * 10 - 50)
        app.scene.add(box);
        let mat = vjmap3d.createFlowGradientMaterial(app, {
            object: box,
            lightScale: 0.1, // 光带宽度占高度比例
            circleTime: Math.random() + 0.2,
            lightColor: vjmap3d.randColor(),
            color: vjmap3d.randColor(),
            topColor: vjmap3d.randColor(),
        })
        box.material = mat;
    }
}

RadarMaterial 雷达动画材质

通过 RadarMaterial 创建雷达动画材质

用法

let radius = 3;
let mat = new vjmap3d.RadarMaterial(
    {
        uRadius: radius,
        uColor: new THREE.Color("#00ffff"),
        uSpeed: 2,
        uSectorAngle: 200, 
        uEdge: radius / 50,
        opacity: 0.9, // ⚠️ webgl 下雷达着色器不读 opacity(透明度由扇区渐变决定),此项无效
        transparent: true,
        blending: THREE.AdditiveBlending,
        depthWrite: false,
        side: THREE.DoubleSide,
        depthTest: true,
    },
    { uTime: app.commonUniforms.iTime }
);

示例

let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    stat: { show: true, left: "0" },
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
let radius = 3;
let mat = new vjmap3d.RadarMaterial(
    {
        uRadius: radius,
        uColor: new THREE.Color("#00ffff"),
        uSpeed: 2,
        uSectorAngle: 200, 
        uEdge: radius / 50,
        opacity: 0.9, // ⚠️ webgl 下雷达着色器不读 opacity(透明度由扇区渐变决定),此项无效
        transparent: true,
        blending: THREE.AdditiveBlending,
        depthWrite: false,
        side: THREE.DoubleSide,
        depthTest: true,
    },
    { uTime: app.commonUniforms.iTime }
);
let geom = new THREE.CircleGeometry(radius);
let mesh = new THREE.Mesh(geom, mat);
mesh.position.set(0, 0, 0);
mesh.rotateX(- Math.PI / 2)
app.scene.add(mesh);

ShadertoyMaterial Shadertoy材质

shadertoy是一个在浏览器中教学3D图形学的在线社区和通过WebGL创建分享shader程序的工具。网站上shader示例非常丰富。可直接复制shadertoy中的代码,通过 ShadertoyMaterial 创建Shadertoy材质

WebGPU 引擎下的 Shadertoy

webgpu 引擎下,shadertoy 的 GLSL 代码会在运行时自动转译为 TSL 节点再编译到 WGSL,无需修改 shader:支持 iTime / iResolution / iMouse(实时鼠标)/ iChannel0-3 / 自定义 uniforms / #define 与 #ifdef。少数复杂语法可能转译失败,此时自动回退为基础材质并在控制台告警。

用法

// https://www.shadertoy.com/view/4dlfR7
let shader = `
#define NUM_PARTICLES 200.0
#define GLOW 0.5
vec3 Orb(vec2 uv, vec3 color, float radius, float offset)
{        
    vec2 position = vec2(sin(offset * (iTime+30.)),
                         cos(offset * (iTime+30.)));
    position *= sin((iTime ) - offset) * cos(offset);
    //offset = pModPolar(position,2.);
    radius = radius * offset;
    float dist = radius / distance(uv, position);
    return color * pow(dist, 1.0 / GLOW);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv =  vec2(fragCoord.xy - 0.5 * iResolution.xy) / iResolution.y;
    vec3 pixel = vec3(0.0, 0.0, 0.0);
   	vec3 color = vec3(0.0, 0.0, 0.0);
 	color.r = ((sin(((iTime)) * 0.55) + 1.5) * 0.4);
    color.g = ((sin(((iTime)) * 0.34) + 2.0) * 0.4);
    color.b = ((sin(((iTime)) * 0.31) + 4.5) * 0.3);
    float radius = 0.005;
    for	(float i = 0.0; i < NUM_PARTICLES; i++)
        pixel += Orb(uv, color, radius, i / NUM_PARTICLES);
    fragColor = mix(vec4(uv,0.8+0.5*sin(iTime),1.0), vec4(pixel, 1.0), 0.8);
}`
let mat = new vjmap3d.ShadertoyMaterial(app, {
    shader: shader
});

示例

let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    stat: { show: true, left: "0" },
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
// https://www.shadertoy.com/view/4dlfR7
let shader = `
#define NUM_PARTICLES 200.0
#define GLOW 0.5
vec3 Orb(vec2 uv, vec3 color, float radius, float offset)
{        
    vec2 position = vec2(sin(offset * (iTime+30.)),
                         cos(offset * (iTime+30.)));
    position *= sin((iTime ) - offset) * cos(offset);
    //offset = pModPolar(position,2.);
    radius = radius * offset;
    float dist = radius / distance(uv, position);
    return color * pow(dist, 1.0 / GLOW);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv =  vec2(fragCoord.xy - 0.5 * iResolution.xy) / iResolution.y;
    vec3 pixel = vec3(0.0, 0.0, 0.0);
   	vec3 color = vec3(0.0, 0.0, 0.0);
 	color.r = ((sin(((iTime)) * 0.55) + 1.5) * 0.4);
    color.g = ((sin(((iTime)) * 0.34) + 2.0) * 0.4);
    color.b = ((sin(((iTime)) * 0.31) + 4.5) * 0.3);
    float radius = 0.005;
    for	(float i = 0.0; i < NUM_PARTICLES; i++)
        pixel += Orb(uv, color, radius, i / NUM_PARTICLES);
    fragColor = mix(vec4(uv,0.8+0.5*sin(iTime),1.0), vec4(pixel, 1.0), 0.8);
}`
let mat = new vjmap3d.ShadertoyMaterial(app, {
    shader: shader
});
let geoW = 2,
    geoH = 2;
let geom = new THREE.BoxGeometry(geoW, geoH, 2);
let mesh = new THREE.Mesh(geom, mat);
mesh.position.set(0, 2, 0);
app.scene.add(mesh);

FixedSizeMeshMaterial 固定像素大小材质

FixedSizeMeshMaterial 屏幕固定大小的材质(只取网格原点做投影,几何的 xy 坐标按屏幕偏移叠加,大小与相机远近无关)。注意换算:1 个几何单位 ≈ 0.5 个 canvasSize 像素(app.commonUniforms.resolution 是乘过 pixelRatio 的设备像素),并受物体 scale 影响——下例半径 50 的圆在屏幕上约 25 个设备像素半径

用法

let circleGeometry = new THREE.CircleGeometry(50);
let circleMaterial = new vjmap3d.FixedSizeMeshMaterial({
    color: 0x00ffff,
    canvasSize: app.commonUniforms.resolution
});
let circle = new THREE.Mesh(circleGeometry, circleMaterial);
app.scene.add(circle)

示例

let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    stat: { show: true, left: "0" },
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
let circleGeometry = new THREE.CircleGeometry(50);
let circleMaterial = new vjmap3d.FixedSizeMeshMaterial({
    color: 0x00ffff,
    canvasSize: app.commonUniforms.resolution
});
let circle = new THREE.Mesh(circleGeometry, circleMaterial);
app.scene.add(circle)

FlowMaterial 移动的纹理材质

通过 createRenderElementFlowMaterial 创建移动的纹理材质。

用法

let mat = vjmap3d.createRenderElementFlowMaterial(app, {
    geometryWidth: width,
    geometryHeight: height,
    flowDirection: "horizon",
    flowSpeed: -0.1,
    element: [
        new vjmap3d.render2d.Rect({
            shape: {
                x: 0,
                y: 0,
                width: 1000,
                height: 1000 * height / width
            },
            style: {
                fill: "#00023D"
            }
        })
    ]
});
let mesh = new THREE.Mesh(geometry, mat);
app.scene.add(mesh);

示例

let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    stat: { show: true, left: "0" },
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
let width = 10, height = 5;
const geometry = new THREE.PlaneGeometry(width, height)
let ArrowRight = vjmap3d.render2d.Path.extend({
    type: "arrowRight",
    shape: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },
    buildPath(ctx, shape) {
        let x = shape.x;
        let y = shape.y;
        let height = shape.height;
        let width = shape.width;
        // @ts-ignore
        let x1 = parseInt(x + width - 36);
        // @ts-ignore
        let y1 = parseInt(y + height / 5);
        // @ts-ignore
        let y2 = parseInt(y + (height / 5) * 4);
        ctx.moveTo(x, y1);
        ctx.lineTo(x1, y1);
        ctx.lineTo(x1, y);
        ctx.lineTo(x + width, y + height / 2);
        ctx.lineTo(x1, y + height);
        ctx.lineTo(x1, y2);
        ctx.lineTo(x, y2);
        ctx.closePath();
    }
});
let arrows = []
for(let i = 0; i < 5; i++) {
    arrows.push(new ArrowRight({
        // @ts-ignore
        shape: {
            x: 0,
            y: i * 100,
            cx: 250,
            cy: 25,
            width: 50,
            height: 60
        },
        style: {
            fill: "#00ffff"
        }
    }));
}
let mat = vjmap3d.createRenderElementFlowMaterial(app, {
    geometryWidth: width,
    geometryHeight: height,
    flowDirection: "horizon",
    flowSpeed: -0.1,
    element: [
        new vjmap3d.render2d.Rect({
            shape: {
                x: 0,
                y: 0,
                width: 1000,
                height: 1000 * height / width
            },
            style: {
                fill: "#00023D"
            }
        }),
        ...arrows
    ]
});
let mesh = new THREE.Mesh(geometry, mat);
app.scene.add(mesh);

HolographicMaterial 全息投影材质

通过 HolographicMaterial 创建全息投影材质

用法

let mat = new vjmap3d.HolographicMaterial(app, {
    fresnelAmount: 0.45,
    fresnelOpacity: 0.1,
    scanlineSize:  2.0,
    hologramBrightness: 1.2,
    signalSpeed:  0.45,
    hologramColor:  "#51a4de",
    enableBlinking:  true,
    blinkFresnelOnly:  true,
    hologramOpacity:  1.0,
})

示例

let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    stat: { show: true, left: "0" },
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
let size = 3;
let position = new THREE.Vector3(0, 0, 0);
// 创建半球几何体
let radius = size;
let widthSegments = 32;
let heightSegments = 16;
let phiStart = 0;
let phiLength = Math.PI; 
let geom = new THREE.SphereGeometry(radius, widthSegments, heightSegments, phiStart, phiLength);
let mat = new vjmap3d.HolographicMaterial(app, {
    fresnelAmount: 0.45,
    fresnelOpacity: 0.1,
    scanlineSize:  2.0,
    hologramBrightness: 1.2,
    signalSpeed:  0.45,
    hologramColor:  "#51a4de",
    enableBlinking:  true,
    blinkFresnelOnly:  true,
    hologramOpacity:  1.0,
})
let mesh = new THREE.Mesh(geom, mat);
mesh.position.copy(position);
mesh.rotateX(-Math.PI / 2);
app.scene.add(mesh);

MeshTransmissionMaterial 透射材质

通过 MeshTransmissionMaterial 创建透射材质

与 MeshReflectorMaterial 同型:构造 (app, parent: Mesh, config?) 返回包装对象,真材质在 .material(.material 是 ShaderMaterial)——必须写 mesh.material = mat.material,不能把返回值直接当材质用。

用法

const mesh = new THREE.Mesh();
const geo = new THREE.TorusGeometry(3, 1, 32, 100);
const mat = new vjmap3d.MeshTransmissionMaterial(app, mesh);
mesh.geometry = geo;
mesh.material = mat.material;
app.scene.add(mesh);

示例

let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    stat: { show: true, left: "0" },
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
const mesh = new THREE.Mesh();
const geo = new THREE.TorusGeometry(3, 1, 32, 100);
const mat = new vjmap3d.MeshTransmissionMaterial(app, mesh);
mesh.geometry = geo;
mesh.material = mat.material;
app.scene.add(mesh);