Cesium自定义着色器-片元着色器数据来源

书接上文,前面说修改白膜渐变需要知道模型位置PositionMC,那这个是片元着色器内部属性,可以直接访问,还有一种是需要手动传递的,所以下面介绍片元着色器的数据来源:

片元着色器中数据的两种来源

1. 通过 Varying 从顶点着色器传递(需要手动设置)

ini 复制代码
let customShader = new Cesium.CustomShader({
    varyings: {
        v_customPosition: Cesium.VaryingType.VEC3,  // 自定义传递变量
        v_customNormal: Cesium.VaryingType.VEC3
    },
    
    vertexShaderText: `
        void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
            // 手动传递数据到片元着色器
            v_customPosition = vsInput.attributes.positionMC * 2.0; // 自定义计算
            v_customNormal = normalize(vsInput.attributes.normalMC);
        }`,
        
    fragmentShaderText: `
        void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
            // 使用通过varying传递的数据
            vec3 customPos = v_customPosition;
            vec3 customNorm = v_customNormal;
            
            material.diffuse = customNorm * 0.5 + 0.5; // 法线可视化
        }`
});

2. 直接通过 fsInput.attributes 访问(内置可用,无需传递)

ini 复制代码
let customShader = new Cesium.CustomShader({
    // 注意:这里没有定义varyings!
    
    vertexShaderText: `
        void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
            // 顶点着色器可以为空,或者处理其他逻辑
        }`,
        
    fragmentShaderText: `
        void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
            // 直接访问内置属性,无需通过varying传递
            vec3 positionMC = fsInput.attributes.positionMC;
            vec3 normalEC = fsInput.attributes.normalEC;
            vec2 texCoord = fsInput.attributes.texCoord_0;
            
            material.diffuse = vec3(texCoord, 0.0); // UV坐标可视化
        }`
});

内置可用的 fsInput.attributes

Cesium 自动提供以下内置属性:

几何属性:

arduino 复制代码
// 位置相关
vec3 positionMC;      // 模型坐标系位置
vec3 positionEC;      // 眼坐标系位置  
vec3 positionWC;      // 世界坐标系位置

// 法线相关
vec3 normalMC;        // 模型坐标系法线
vec3 normalEC;        // 眼坐标系法线

// 纹理坐标
vec2 texCoord_0;      // 第一套UV坐标
vec2 texCoord_1;      // 第二套UV坐标

其他属性:

arduino 复制代码
// 切线空间
vec3 tangentMC;       // 模型坐标系切线
vec3 bitangentMC;     // 模型坐标系副切线

// 颜色
vec3 color_0;         // 顶点颜色

什么时候需要用 Varying?

需要手动传递的情况:

1. 自定义计算的结果

arduino 复制代码
// 顶点着色器
v_customHeight = positionMC.y * 10.0;  // 自定义高度计算

// 片元着色器  
float height = v_customHeight;         // 使用自定义计算值

2. 修改后的数据

ini 复制代码
// 顶点着色器
v_modifiedNormal = normalMC * 2.0;     // 修改法线

// 片元着色器
vec3 normal = v_modifiedNormal;         // 使用修改后的法线

3. 复杂数据结构

scss 复制代码
// 需要传递多个相关数据时
v_customData = vec4(positionMC, normalMC.x); // 打包数据

实际示例对比

方案A:使用内置属性(推荐,简单)

ini 复制代码
// 直接使用内置的positionMC,不需要varying
fragmentShaderText: `
    void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
        vec3 positionMC = fsInput.attributes.positionMC;
        material.diffuse = vec3(0.0, 1.0 - positionMC.z * 0.005, 1.0);
    }`

方案B:使用Varying传递(复杂,不必要)

ini 复制代码
varyings: {
    v_positionMC: Cesium.VaryingType.VEC3
},

vertexShaderText: `
    void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
        v_positionMC = vsInput.attributes.positionMC; // 只是简单传递
    }`,

fragmentShaderText: `
    void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
        vec3 positionMC = v_positionMC; // 通过varying获取
        material.diffuse = vec3(0.0, 1.0 - positionMC.z * 0.005, 1.0);
    }`

总结

  1. 内置属性 :直接使用 fsInput.attributes.xxx,无需varying
  2. 自定义数据:需要通过varying手动传递
  3. 最佳实践:优先使用内置属性,除非需要传递自定义计算结果
相关推荐
夏幻灵4 小时前
JavaScript this 面试:五种绑定规则、优先级与常见面试陷阱
开发语言·javascript·面试
三天不学习5 小时前
Egg.js 4 突然爆火,原因是否归结于AI 原生落地需求爆发?
前端·javascript·全栈·egg.js
xcs194055 小时前
前端 vue 的前端页面debugger 进不去
前端·javascript·vue.js
小宋102111 小时前
A2UI从零实战:Agent安全生成交互界面与事件回传
javascript·人工智能·安全·交互
大包子11 小时前
structuredClone vs lodash.cloneDeep:核心差异与选型指南
javascript·vue.js
lerhxx11 小时前
AI 应用中的上下文管理 —— 从"上下文窗口"到"分层压缩"的工程实践
前端·javascript
Mahut12 小时前
我在 Mac 上做了个本地剪辑器
javascript·架构·产品
汉堡大王952712 小时前
GPT-6 上线 48 小时,我扒开了 Intelligent UI 的运行机制:DIL、沙箱 Worker 和一个 React 式协调器
前端·javascript·后端
hai_android12 小时前
Chat 聊天模块功能总结
前端·javascript·vue.js
创世虚拟世界13 小时前
我做了一个 3D 虚拟世界基底,基于这个再做 3D 虚拟世界或者元宇宙,会事半功倍
javascript·人工智能·3d·gitee·虚拟现实