ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

deck.gl PointLight 点光源完全指南:参数详解、坐标系统与实战接入

deck.gl PointLight 点光源完全指南:参数详解、坐标系统与实战接入 deck.gl PointLight 点光源完全指南参数详解、坐标系统与实战接入【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl导读PointLight是 deck.gl 核心库中用于模拟从某一点向四面八方均匀发光的光源类是 LightingEffect 支持的三种基础光源环境光 AmbientLight、平行光 DirectionalLight、点光源 PointLight之一。本文以 point-light.md 文档为主线结合 核心源码 与官方示例完整讲解 PointLight 的构造参数、光照衰减模型、地理/非地理坐标投影机制以及如何在 JS、React 与 pydeck 中把它接入渲染管线让读者可以独立为柱状图、热力图、3D 模型等 2.5D/3D 图层配置逼真的点光源照明。PointLight 是什么点光源Point Light是计算机图形学中最基础的光源模型之一它有一个确定的空间位置光线从该点向所有方向均匀辐射因此物体不同朝向的表面会因与光源的方位关系产生明暗差异从而呈现出立体感。在 deck.gl 中PointLight类的定位非常纯粹它只描述光源本身颜色、强度、位置、衰减系数不参与渲染实际的照明计算由LightingEffect统一驱动后者会把所有注册的光源投影到图层坐标系后交给 shader 模块处理光照只作用于支持material属性的 2.5D如挤出的HexagonLayer、PolygonLayer或 3D如PointCloudLayer、SimpleMeshLayer图层参见 using-effects.md 中的 Material Settings 一节。注意原文档注明最多支持 5 个方向光实际该数量限制来自底层 luma.gl 光照 shader 模块对光源总数的约束点光源同样计入总光源预算配置过多光源时需按需取舍。构造 PointLight构造函数签名const pointLight new PointLight({color, intensity, position, attenuation});所有参数均为可选全部省略时使用源码中的默认值见 point-light.ts参数类型默认值说明colornumber[3][255, 255, 255]光源颜色RGB 各通道取值 0–255intensitynumber1.0光源强度数值越大越亮positionnumber[3][0, 0, 1]光源位置坐标系统取决于当前视图详见下文attenuationnumber[3][1, 0, 0]衰减系数[C_constant, C_linear, C_quadratic]默认不随距离衰减原文档给出的最小可用示例const pointLight new PointLight({ color: [128, 128, 0], intensity: 2.0, position: [0, 0, 200] });源码层面的构造细节阅读 point-light.ts 的实现可以发现几个容易被忽视的行为自动生成 id构造函数不要求传入id未指定时自动生成point-${idCount}模块级计数器自增便于在LightingEffect内部区分多个光源类型标记实例上固定type pointLightingEffect正是依据该标记将光源归类到pointLights数组见 lighting-effect.ts投影缓存构造时通过this.projectedLight {...this}复制一份投影后的光源每次渲染时复用该对象、只更新投影后的坐标避免频繁分配内存。光照衰减模型attenuation是 PointLight 最有特色的参数它根据光源到表面的距离D按如下公式削减光照强度Intensity Intensity / (C_constant C_linear * D C_quadratic * D * D)三个系数的物理含义C_constant常数项距离无关的基础衰减通常设为 1C_linear线性项随距离线性衰减适合模拟较近范围的光照C_quadratic二次项随距离平方衰减更接近真实世界光强按距离平方反比衰减的物理规律。文档给出的两条实用建议物理近似需要近似物理正确的衰减时使用attenuation: [1, 0, n]其中n为二次项系数取值越大光照衰减越剧烈默认关闭衰减默认值[1, 0, 0]意味着分母恒为 1光源强度不随距离变化——适合希望光照均匀覆盖整个场景的情况。源码中 getAttenuation 的实现非常直白显式传入attenuation则原样使用否则回退到DEFAULT_ATTENUATION [1, 0, 0]。position 的坐标系统地理视图与非地理视图这是 PointLight 最容易踩坑的地方position的坐标语义取决于当前 deck.gl 视图View的类型原文档明确指向 deck.md#views地理视图geospatial views如MapView、GlobeViewposition 解释为[longitude, latitude, altitude]经度、纬度、海拔高度单位一般为米光源可直接钉在地球表面某一点上空非地理视图non-geospatial views如OrthographicView、OrbitViewposition 解释为普通的世界坐标[x, y, z]。这一转换在源码中由getProjectedLight完成point-light.tsconst position projectPosition(this.position, { viewport, coordinateSystem, coordinateOrigin, fromCoordinateSystem: viewport.isGeospatial ? COORDINATE_SYSTEM.LNGLAT : COORDINATE_SYSTEM.CARTESIAN, fromCoordinateOrigin: [0, 0, 0] });其核心逻辑是判断当前 viewport 是否地理空间viewport.isGeospatial若是则把 position 当作LNGLAT经纬度输入否则当作CARTESIAN笛卡尔输入再通过projectPosition统一投影到图层的公共坐标空间。也就是说光源坐标与图层数据遵循同一套坐标系统LightingEffect文档中的备注Point light position uses the same coordinate system as view statelighting-effect.md正是这个意思。为什么按图层逐个投影注意getProjectedLight的签名是getProjectedLight({layer})原因是 deck.gl 中不同图层可能使用不同的坐标系统与坐标原点coordinateSystem、coordinateOrigin。因此 lighting-effect.ts 的_getLights会逐图层调用pointLight.getProjectedLight({layer})为每个图层生成投影后的光源列表再统一交给光照 shader。测试用例 lighting-effect.spec.ts 验证了这一点在MapView视口下CameraLight的默认位置[0, 0, 1]被投影为[0, 0, 0.018310546875]而手动修改后的PointLight颜色[255, 0, 0]被原样导出到 shader 属性中。在应用中接入 PointLight方式一JS / TypeScriptDeck 实例PointLight本身不直接渲染必须挂在LightingEffect上再通过Deck的effects参数启用。官网 3D 热力图示例3d-heatmap/app.tsx展示了标准组合环境光打底 两个点光源营造局部高光import {Deck, AmbientLight, PointLight, LightingEffect} from deck.gl/core; const ambientLight new AmbientLight({ color: [255, 255, 255], intensity: 1.0 }); const pointLight1 new PointLight({ color: [255, 255, 255], intensity: 0.8, position: [-0.144528, 49.739968, 80000] // 经度、纬度、海拔米 }); const pointLight2 new PointLight({ color: [255, 255, 255], intensity: 0.8, position: [-3.807751, 54.104682, 8000] }); const lightingEffect new LightingEffect({ambientLight, pointLight1, pointLight2}); const deckInstance new Deck({ initialViewState: { longitude: -1.415727, latitude: 52.232395, zoom: 6.6, pitch: 40.5, bearing: -27 }, controller: true, effects: [lightingEffect] // 关键把光照效果加入渲染管线 });方式二ReactDeckGL 组件React 用法几乎一致只是把effects传给DeckGL组件import {DeckGL} from deck.gl/react; import {AmbientLight, PointLight, LightingEffect} from deck.gl/core; const lightingEffect new LightingEffect({ ambientLight: new AmbientLight({color: [255, 255, 255], intensity: 1.0}), pointLight1: new PointLight({color: [255, 255, 255], intensity: 0.8, position: [-0.14, 49.7, 80000]}) }); function App() { return ( DeckGL initialViewState{{longitude: -1.4, latitude: 52.2, zoom: 6.6, pitch: 40.5}} controller effects{[lightingEffect]} {/* 地图底图组件 */} /DeckGL ); }方式三pydeckPython 绑定pydeck 通过pdk.Effect以声明式 JSON 描述光源属性名自动做 snake-case 到 camel-case 转换见 effect.rst。官方示例 point_light.py 完整演示了用点光源照亮多边形底面和柱状图import pydeck as pdk light pdk.Effect( PointLight, color[255, 150, 90], intensity3.0, position[-1.5, -1, 180000], ) lighting pdk.Effect(LightingEffect, gallery_lightlight) deck pdk.Deck( layerslayers, # 包含 materialTrue 的 PolygonLayer / ColumnLayer effects[lighting], initial_view_stateinitial_view_state, map_providerNone, show_errorTrue, ) deck.to_html(point_light.html, css_background_color#111827)注意其中的图层都设置了materialTrue——这与 JS 侧一致只有声明了 material 的图层才会参与光照计算。与 LightingEffect 的协作机制把PointLight接入LightingEffect后其完整工作流程可以归纳为对应 lighting-effect.ts 的setProps分类注册LightingEffect遍历构造时传入的所有光源依据type字段分别归入ambientLight、directionalLights、pointLights三个集合默认光源兜底若用户一个光源都没提供_applyDefaultLights会自动注入一个白色环境光intensity 1.0加两个方向光lighting-effect.ts所以不配置任何 effects 也能看到立体效果逐图层投影getShaderModuleProps阶段调用_getLights为每个图层生成投影后的光源列表并写入lightingshader 模块属性shader 消费图层顶点/片元着色器结合phongMaterial/gouraudMaterial即图层material属性完成 Phong 光照着色计算。与另外两种光源的对比特性AmbientLightDirectionalLightPointLight有无位置无只有方向有位置可衰减光源数量仅 1 个多个多个默认[]距离衰减不适用不适用支持attenuation典型场景打底避免全黑模拟太阳等远距离光模拟灯泡、路灯等局部光源对应测试 lighting-effect.spec.ts 也验证了空构造的LightingEffect会自动创建 1 个环境光和 2 个方向光这正是默认光照的由来。与图层 material 属性配合要让 PointLight 真正在视觉上生效目标图层必须设置material属性。material 是一个普通 JS 对象控制表面如何响应光照默认值见 using-effects.mdambient0–1默认0.35环境光反射系数diffuse0–1默认0.6漫反射系数决定点光源直射面的亮度shininess0默认32高光锐度越大高光越集中specularColornumber[3]RGB 各通道 0–1默认[0.15, 0.15, 0.15]镜面高光颜色。设置为true时全部采用默认值。例如new GeoJsonLayer({ id: geojson-layer, data: /path/to/data.geo.json, extruded: true, // 光照只作用于挤出多边形 getElevation: f f.properties.height, material: { ambient: 0.8, specularColor: [0.3, 0.1, 0.2] } });在 3D 热力图示例中HexagonLayer的 material 被配置为{ambient: 0.64, diffuse: 0.6, shininess: 32, specularColor: [51, 51, 51]}3d-heatmap/app.tsx配合两个位置不同的点光源柱体侧面呈现出从暗到亮的光照渐变立体感显著增强。调试与验证建议确认图层参与光照检查图层是否设置了material且属于 2.5D/3D 图层如挤出的聚合图层、PointCloudLayer、SimpleMeshLayer确认 effects 已挂载effects: [lightingEffect]是必须步骤且注意覆盖默认光照——一旦自定义LightingEffect中没有环境光未受点光源直射的面可能接近全黑建议保留一个低强度AmbientLight地理视图下的位置单位position的第三维altitude通常以米为单位示例中 3D 热力图使用了80000/8000米级别的海拔配合elevationScale才能看到明显效果回归测试仓库测试 lighting-effect.spec.ts 覆盖了光源构造、shader 属性导出、阴影 pass 创建与清理等关键路径修改光照相关代码后应保持这些用例通过。小结PointLight 为 deck.gl 场景提供了基于位置的局部照明能力核心要点可归纳为四条四个构造参数全部可选且均有默认值attenuation支持按距离衰减的物理光照模型position的语义随视图类型地理/非地理自动切换由getProjectedLight结合projectPosition完成投影必须通过LightingEffect挂载并配合图层的material属性才能生效。理解这些机制即可像官方 3D 热力图与 pydeck 示例那样用少量代码为三维场景营造出富有层次的光照氛围。关键参考路径API 文档point-light.md、lighting-effect.md实现源码modules/core/src/effects/lighting/point-light.ts、modules/core/src/effects/lighting/lighting-effect.ts官方示例examples/website/3d-heatmap/app.tsx、bindings/pydeck/examples/lighting/point_light.py开发者指南docs/developer-guide/using-effects.md测试用例test/modules/core/effects/lighting-effect.spec.ts【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表